]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'exynos/pwm-clocksource' into late/multiplatform
authorArnd Bergmann <arnd@arndb.de>
Mon, 6 May 2013 21:49:09 +0000 (23:49 +0200)
committerArnd Bergmann <arnd@arndb.de>
Mon, 6 May 2013 21:49:09 +0000 (23:49 +0200)
This series from Tomasz Figa restores support for the pwm clocksource
in Exynos, which was broken during the conversion of the platform
to the common clk framework. The clocksource is only used in one
board in the mainline kernel (universal_c210), and this makes it
work for DT based probing as well as restoring the non-DT based
case.

* exynos/pwm-clocksource:
  ARM: dts: exynops4210: really add universal_c210 dts
  ARM: dts: exynos4210: Add basic dts file for universal_c210 board
  ARM: dts: exynos4: Add node for PWM device
  ARM: SAMSUNG: Do not register legacy timer interrupts on Exynos
  clocksource: samsung_pwm_timer: Work around rounding errors in clockevents core
  clocksource: samsung_pwm_timer: Correct programming of clock events
  clocksource: samsung_pwm_timer: Use proper clockevents max_delta
  clocksource: samsung_pwm_timer: Add support for non-DT platforms
  clocksource: samsung_pwm_timer: Drop unused samsung_pwm struct
  clocksource: samsung_pwm_timer: Keep all driver data in a structure
  clocksource: samsung_pwm_timer: Make PWM spinlock global
  clocksource: samsung_pwm_timer: Let platforms select the driver
  Documentation: Add device tree bindings for Samsung PWM timers
  clocksource: add samsung pwm timer driver

Conflicts:
arch/arm/boot/dts/Makefile
arch/arm/mach-exynos/common.c
drivers/clocksource/Kconfig
drivers/clocksource/Makefile

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
1465 files changed:
CREDITS
Documentation/arm/sunxi/clocks.txt [new file with mode: 0644]
Documentation/clk.txt
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-pmc.txt
Documentation/devicetree/bindings/bus/ti-gpmc.txt
Documentation/devicetree/bindings/clock/axi-clkgen.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/exynos4-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/exynos5250-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/exynos5440-clock.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/nvidia,tegra20-car.txt
Documentation/devicetree/bindings/clock/sunxi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/gpio-vt8500.txt [deleted file]
Documentation/devicetree/bindings/interrupt-controller/samsung,s3c24xx-irq.txt [new file with mode: 0644]
Documentation/devicetree/bindings/media/s5p-mfc.txt
Documentation/devicetree/bindings/mfd/ab8500.txt
Documentation/devicetree/bindings/mtd/gpmc-nor.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mtd/gpmc-onenand.txt
Documentation/devicetree/bindings/net/gpmc-eth.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pinctrl/pinctrl-vt8500.txt [new file with mode: 0644]
Documentation/devicetree/bindings/reset/reset.txt [new file with mode: 0644]
Documentation/devicetree/bindings/timer/cadence,ttc-timer.txt [new file with mode: 0644]
Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt [new file with mode: 0644]
Documentation/devicetree/bindings/tty/serial/of-serial.txt
Documentation/devicetree/bindings/usb/exynos-usb.txt [new file with mode: 0644]
Documentation/hwmon/lm75
Documentation/i2c/busses/i2c-diolan-u2c
Documentation/input/alps.txt
Documentation/networking/ipvs-sysctl.txt
Documentation/networking/tuntap.txt
Documentation/sound/alsa/ALSA-Configuration.txt
Documentation/sound/alsa/seq_oss.html
Documentation/trace/ftrace.txt
MAINTAINERS
Makefile
arch/Kconfig
arch/alpha/Kconfig
arch/alpha/Makefile
arch/alpha/include/asm/floppy.h
arch/alpha/kernel/irq.c
arch/alpha/kernel/irq_alpha.c
arch/alpha/kernel/sys_nautilus.c
arch/alpha/kernel/sys_titan.c
arch/arc/include/asm/dma-mapping.h
arch/arc/include/asm/elf.h
arch/arc/include/asm/entry.h
arch/arc/include/asm/kgdb.h
arch/arc/include/asm/ptrace.h
arch/arc/include/asm/syscalls.h
arch/arc/include/uapi/asm/ptrace.h
arch/arc/kernel/entry.S
arch/arc/kernel/kgdb.c
arch/arc/kernel/setup.c
arch/arc/kernel/sys.c
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/boot/Makefile
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/armada-370-mirabox.dts
arch/arm/boot/dts/armada-370-rd.dts
arch/arm/boot/dts/armada-370-xp.dtsi
arch/arm/boot/dts/armada-370.dtsi
arch/arm/boot/dts/armada-xp.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/bcm2835.dtsi
arch/arm/boot/dts/cros5250-common.dtsi
arch/arm/boot/dts/dbx5x0.dtsi
arch/arm/boot/dts/dove.dtsi
arch/arm/boot/dts/exynos4.dtsi
arch/arm/boot/dts/exynos4210-origen.dts
arch/arm/boot/dts/exynos4210-smdkv310.dts
arch/arm/boot/dts/exynos4210-trats.dts
arch/arm/boot/dts/exynos4210.dtsi
arch/arm/boot/dts/exynos4212.dtsi
arch/arm/boot/dts/exynos4412-odroidx.dts [new file with mode: 0644]
arch/arm/boot/dts/exynos4412-origen.dts [new file with mode: 0644]
arch/arm/boot/dts/exynos4412-smdk4412.dts
arch/arm/boot/dts/exynos4412.dtsi
arch/arm/boot/dts/exynos4x12.dtsi
arch/arm/boot/dts/exynos5250-arndale.dts [new file with mode: 0644]
arch/arm/boot/dts/exynos5250-smdk5250.dts
arch/arm/boot/dts/exynos5250-snow.dts
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/exynos5440-ssdk5440.dts
arch/arm/boot/dts/exynos5440.dtsi
arch/arm/boot/dts/href.dtsi
arch/arm/boot/dts/hrefv60plus.dts
arch/arm/boot/dts/imx53-mba53.dts
arch/arm/boot/dts/kirkwood-dns320.dts
arch/arm/boot/dts/kirkwood-dns325.dts
arch/arm/boot/dts/kirkwood-dockstar.dts
arch/arm/boot/dts/kirkwood-dreamplug.dts
arch/arm/boot/dts/kirkwood-goflexnet.dts
arch/arm/boot/dts/kirkwood-ib62x0.dts
arch/arm/boot/dts/kirkwood-iconnect.dts
arch/arm/boot/dts/kirkwood-iomega_ix2_200.dts
arch/arm/boot/dts/kirkwood-km_kirkwood.dts
arch/arm/boot/dts/kirkwood-lschlv2.dts
arch/arm/boot/dts/kirkwood-lsxhl.dts
arch/arm/boot/dts/kirkwood-mplcec4.dts
arch/arm/boot/dts/kirkwood-ns2-common.dtsi
arch/arm/boot/dts/kirkwood-nsa310.dts
arch/arm/boot/dts/kirkwood-openblocks_a6.dts
arch/arm/boot/dts/kirkwood-topkick.dts
arch/arm/boot/dts/kirkwood.dtsi
arch/arm/boot/dts/omap3-beagle.dts
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/orion5x-lacie-ethernet-disk-mini-v2.dts
arch/arm/boot/dts/orion5x.dtsi
arch/arm/boot/dts/r8a7779.dtsi [new file with mode: 0644]
arch/arm/boot/dts/snowball.dts
arch/arm/boot/dts/socfpga.dtsi
arch/arm/boot/dts/tegra114-dalmore.dts
arch/arm/boot/dts/tegra114-pluto.dts
arch/arm/boot/dts/tegra114.dtsi
arch/arm/boot/dts/tegra20-colibri-512.dtsi
arch/arm/boot/dts/tegra20-harmony.dts
arch/arm/boot/dts/tegra20-paz00.dts
arch/arm/boot/dts/tegra20-seaboard.dts
arch/arm/boot/dts/tegra20-tamonten.dtsi
arch/arm/boot/dts/tegra20-trimslice.dts
arch/arm/boot/dts/tegra20-ventana.dts
arch/arm/boot/dts/tegra20-whistler.dts
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/tegra30-beaver.dts
arch/arm/boot/dts/tegra30-cardhu.dtsi
arch/arm/boot/dts/tegra30.dtsi
arch/arm/boot/dts/vt8500.dtsi
arch/arm/boot/dts/wm8505.dtsi
arch/arm/boot/dts/wm8650.dtsi
arch/arm/boot/dts/wm8850.dtsi
arch/arm/boot/dts/zynq-7000.dtsi
arch/arm/boot/dts/zynq-zc702.dts
arch/arm/configs/exynos4_defconfig
arch/arm/configs/mxs_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/include/asm/delay.h
arch/arm/include/asm/highmem.h
arch/arm/include/asm/mmu_context.h
arch/arm/include/asm/tlbflush.h
arch/arm/include/asm/xen/events.h
arch/arm/include/debug/exynos.S [moved from arch/arm/mach-exynos/include/mach/debug-macro.S with 84% similarity]
arch/arm/include/debug/samsung.S [moved from arch/arm/plat-samsung/include/plat/debug-macro.S with 100% similarity]
arch/arm/kernel/entry-armv.S
arch/arm/kernel/entry-common.S
arch/arm/kernel/head.S
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/process.c
arch/arm/kernel/setup.c
arch/arm/kernel/smp.c
arch/arm/kernel/smp_tlb.c
arch/arm/kvm/vgic.c
arch/arm/lib/delay.c
arch/arm/lib/memset.S
arch/arm/mach-at91/at91sam9261.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9g45.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9rl.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/board-foxg20.c
arch/arm/mach-at91/board-stamp9g20.c
arch/arm/mach-at91/include/mach/gpio.h
arch/arm/mach-at91/irq.c
arch/arm/mach-at91/pm.c
arch/arm/mach-cns3xxx/core.c
arch/arm/mach-cns3xxx/include/mach/cns3xxx.h
arch/arm/mach-davinci/dma.c
arch/arm/mach-ep93xx/include/mach/uncompress.h
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/Makefile
arch/arm/mach-exynos/clock-exynos4.c [deleted file]
arch/arm/mach-exynos/clock-exynos4.h [deleted file]
arch/arm/mach-exynos/clock-exynos4210.c [deleted file]
arch/arm/mach-exynos/clock-exynos4212.c [deleted file]
arch/arm/mach-exynos/clock-exynos5.c [deleted file]
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/common.h
arch/arm/mach-exynos/dev-uart.c
arch/arm/mach-exynos/include/mach/irqs.h
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/include/mach/regs-mct.h [deleted file]
arch/arm/mach-exynos/mach-armlex4210.c
arch/arm/mach-exynos/mach-exynos4-dt.c
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-exynos/mach-nuri.c
arch/arm/mach-exynos/mach-origen.c
arch/arm/mach-exynos/mach-smdk4x12.c
arch/arm/mach-exynos/mach-smdkv310.c
arch/arm/mach-exynos/mach-universal_c210.c
arch/arm/mach-exynos/setup-sdhci-gpio.c
arch/arm/mach-footbridge/Kconfig
arch/arm/mach-imx/clk-busy.c
arch/arm/mach-imx/clk-imx35.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/common.h
arch/arm/mach-imx/headsmp.S
arch/arm/mach-imx/hotplug.c
arch/arm/mach-imx/imx25-dt.c
arch/arm/mach-imx/pm-imx6q.c
arch/arm/mach-imx/src.c
arch/arm/mach-integrator/integrator_ap.c
arch/arm/mach-integrator/integrator_cp.c
arch/arm/mach-ixp4xx/vulcan-setup.c
arch/arm/mach-kirkwood/board-dt.c
arch/arm/mach-kirkwood/guruplug-setup.c
arch/arm/mach-kirkwood/openrd-setup.c
arch/arm/mach-kirkwood/rd88f6281-setup.c
arch/arm/mach-mmp/gplugd.c
arch/arm/mach-msm/timer.c
arch/arm/mach-mvebu/irq-armada-370-xp.c
arch/arm/mach-mxs/icoll.c
arch/arm/mach-mxs/mach-mxs.c
arch/arm/mach-mxs/mm.c
arch/arm/mach-mxs/ocotp.c
arch/arm/mach-omap1/Kconfig
arch/arm/mach-omap1/clock_data.c
arch/arm/mach-omap1/common.h
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/board-2430sdp.c
arch/arm/mach-omap2/board-3430sdp.c
arch/arm/mach-omap2/board-3630sdp.c
arch/arm/mach-omap2/board-am3517crane.c
arch/arm/mach-omap2/board-am3517evm.c
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-cm-t3517.c
arch/arm/mach-omap2/board-devkit8000.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/board-igep0020.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-omap3pandora.c
arch/arm/mach-omap2/board-omap3stalker.c
arch/arm/mach-omap2/board-omap3touchbook.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/board-overo.c
arch/arm/mach-omap2/board-rx51.c
arch/arm/mach-omap2/board-zoom.c
arch/arm/mach-omap2/cclock33xx_data.c
arch/arm/mach-omap2/cclock44xx_data.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/dpll3xxx.c
arch/arm/mach-omap2/dsp.c
arch/arm/mach-omap2/gpmc-nand.c
arch/arm/mach-omap2/gpmc-onenand.c
arch/arm/mach-omap2/gpmc-smc91x.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/gpmc.h
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/mux.c
arch/arm/mach-omap2/omap4-common.c
arch/arm/mach-omap2/omap4-sar-layout.h
arch/arm/mach-omap2/omap54xx.h
arch/arm/mach-omap2/omap_device.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod.h
arch/arm/mach-omap2/omap_hwmod_33xx_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/pm-debug.c
arch/arm/mach-omap2/powerdomain.c
arch/arm/mach-omap2/prm44xx.c
arch/arm/mach-omap2/soc.h
arch/arm/mach-omap2/timer.c
arch/arm/mach-omap2/usb-host.c
arch/arm/mach-omap2/usb-tusb6010.c
arch/arm/mach-omap2/usb.h
arch/arm/mach-pxa/raumfeld.c
arch/arm/mach-s3c24xx/Kconfig
arch/arm/mach-s3c24xx/Makefile
arch/arm/mach-s3c24xx/bast-irq.c
arch/arm/mach-s3c24xx/clock-s3c2410.c
arch/arm/mach-s3c24xx/clock-s3c2412.c
arch/arm/mach-s3c24xx/clock-s3c2416.c
arch/arm/mach-s3c24xx/clock-s3c2443.c
arch/arm/mach-s3c24xx/common-smdk.c
arch/arm/mach-s3c24xx/common-smdk.h [moved from arch/arm/plat-samsung/include/plat/common-smdk.h with 86% similarity]
arch/arm/mach-s3c24xx/common.c
arch/arm/mach-s3c24xx/common.h
arch/arm/mach-s3c24xx/dma-s3c2410.c
arch/arm/mach-s3c24xx/dma-s3c2412.c
arch/arm/mach-s3c24xx/dma-s3c2440.c
arch/arm/mach-s3c24xx/dma-s3c2443.c
arch/arm/mach-s3c24xx/include/mach/debug-macro.S
arch/arm/mach-s3c24xx/include/mach/entry-macro.S [deleted file]
arch/arm/mach-s3c24xx/include/mach/irqs.h
arch/arm/mach-s3c24xx/include/mach/regs-sdi.h [deleted file]
arch/arm/mach-s3c24xx/irq-pm.c
arch/arm/mach-s3c24xx/irq-s3c2412.c [deleted file]
arch/arm/mach-s3c24xx/irq-s3c2440.c [deleted file]
arch/arm/mach-s3c24xx/irq-s3c244x.c [deleted file]
arch/arm/mach-s3c24xx/mach-amlm5900.c
arch/arm/mach-s3c24xx/mach-anubis.c
arch/arm/mach-s3c24xx/mach-at2440evb.c
arch/arm/mach-s3c24xx/mach-bast.c
arch/arm/mach-s3c24xx/mach-gta02.c
arch/arm/mach-s3c24xx/mach-h1940.c
arch/arm/mach-s3c24xx/mach-jive.c
arch/arm/mach-s3c24xx/mach-mini2440.c
arch/arm/mach-s3c24xx/mach-n30.c
arch/arm/mach-s3c24xx/mach-nexcoder.c
arch/arm/mach-s3c24xx/mach-osiris.c
arch/arm/mach-s3c24xx/mach-otom.c
arch/arm/mach-s3c24xx/mach-qt2410.c
arch/arm/mach-s3c24xx/mach-rx1950.c
arch/arm/mach-s3c24xx/mach-rx3715.c
arch/arm/mach-s3c24xx/mach-smdk2410.c
arch/arm/mach-s3c24xx/mach-smdk2413.c
arch/arm/mach-s3c24xx/mach-smdk2416.c
arch/arm/mach-s3c24xx/mach-smdk2440.c
arch/arm/mach-s3c24xx/mach-smdk2443.c
arch/arm/mach-s3c24xx/mach-tct_hammer.c
arch/arm/mach-s3c24xx/mach-vr1000.c
arch/arm/mach-s3c24xx/mach-vstms.c
arch/arm/mach-s3c24xx/pm-s3c2412.c
arch/arm/mach-s3c24xx/s3c2410.c
arch/arm/mach-s3c24xx/s3c2412.c
arch/arm/mach-s3c24xx/s3c2416.c
arch/arm/mach-s3c24xx/s3c2440.c
arch/arm/mach-s3c24xx/s3c2442.c
arch/arm/mach-s3c24xx/s3c2443.c
arch/arm/mach-s3c24xx/s3c244x.c
arch/arm/mach-s3c64xx/Kconfig
arch/arm/mach-s3c64xx/include/mach/debug-macro.S
arch/arm/mach-s3c64xx/mach-anw6410.c
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s3c64xx/mach-hmt.c
arch/arm/mach-s3c64xx/mach-mini6410.c
arch/arm/mach-s3c64xx/mach-ncp.c
arch/arm/mach-s3c64xx/mach-real6410.c
arch/arm/mach-s3c64xx/mach-smartq.c
arch/arm/mach-s3c64xx/mach-smartq5.c
arch/arm/mach-s3c64xx/mach-smartq7.c
arch/arm/mach-s3c64xx/mach-smdk6400.c
arch/arm/mach-s3c64xx/mach-smdk6410.c
arch/arm/mach-s5p64x0/Kconfig
arch/arm/mach-s5p64x0/include/mach/debug-macro.S
arch/arm/mach-s5p64x0/mach-smdk6440.c
arch/arm/mach-s5p64x0/mach-smdk6450.c
arch/arm/mach-s5pc100/Kconfig
arch/arm/mach-s5pc100/include/mach/debug-macro.S
arch/arm/mach-s5pc100/mach-smdkc100.c
arch/arm/mach-s5pc100/setup-sdhci-gpio.c
arch/arm/mach-s5pv210/Kconfig
arch/arm/mach-s5pv210/clock.c
arch/arm/mach-s5pv210/include/mach/debug-macro.S
arch/arm/mach-s5pv210/mach-aquila.c
arch/arm/mach-s5pv210/mach-goni.c
arch/arm/mach-s5pv210/mach-smdkc110.c
arch/arm/mach-s5pv210/mach-smdkv210.c
arch/arm/mach-s5pv210/mach-torbreck.c
arch/arm/mach-s5pv210/setup-sdhci-gpio.c
arch/arm/mach-shmobile/Kconfig
arch/arm/mach-shmobile/Makefile
arch/arm/mach-shmobile/board-kzm9g.c
arch/arm/mach-shmobile/board-marzen.c
arch/arm/mach-shmobile/clock-r8a7740.c
arch/arm/mach-shmobile/clock-r8a7779.c
arch/arm/mach-shmobile/clock-sh73a0.c
arch/arm/mach-shmobile/headsmp-scu.S [moved from arch/arm/mach-shmobile/headsmp-sh73a0.S with 85% similarity]
arch/arm/mach-shmobile/hotplug.c [deleted file]
arch/arm/mach-shmobile/include/mach/common.h
arch/arm/mach-shmobile/include/mach/irqs.h
arch/arm/mach-shmobile/intc-r8a7779.c
arch/arm/mach-shmobile/intc-sh73a0.c
arch/arm/mach-shmobile/setup-emev2.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-shmobile/setup-sh73a0.c
arch/arm/mach-shmobile/smp-emev2.c
arch/arm/mach-shmobile/smp-r8a7779.c
arch/arm/mach-shmobile/smp-sh73a0.c
arch/arm/mach-spear3xx/spear3xx.c
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/board-dt-tegra114.c [deleted file]
arch/arm/mach-tegra/board-dt-tegra30.c [deleted file]
arch/arm/mach-tegra/board-harmony-pcie.c
arch/arm/mach-tegra/board.h
arch/arm/mach-tegra/common.c
arch/arm/mach-tegra/cpuidle-tegra20.c
arch/arm/mach-tegra/cpuidle-tegra30.c
arch/arm/mach-tegra/fuse.c
arch/arm/mach-tegra/fuse.h
arch/arm/mach-tegra/headsmp.S
arch/arm/mach-tegra/hotplug.c
arch/arm/mach-tegra/irq.c
arch/arm/mach-tegra/irq.h
arch/arm/mach-tegra/platsmp.c
arch/arm/mach-tegra/pm.c
arch/arm/mach-tegra/pm.h
arch/arm/mach-tegra/pmc.c
arch/arm/mach-tegra/pmc.h
arch/arm/mach-tegra/reset-handler.S
arch/arm/mach-tegra/sleep.h
arch/arm/mach-tegra/tegra.c [moved from arch/arm/mach-tegra/board-dt-tegra20.c with 74% similarity]
arch/arm/mach-tegra/tegra114_speedo.c [new file with mode: 0644]
arch/arm/mach-tegra/tegra2_emc.c
arch/arm/mach-ux500/board-mop500-pins.c
arch/arm/mach-ux500/board-mop500-sdi.c
arch/arm/mach-ux500/board-mop500.c
arch/arm/mach-ux500/board-mop500.h
arch/arm/mach-ux500/cpu-db8500.c
arch/arm/mach-ux500/cpu.c
arch/arm/mach-vt8500/Kconfig
arch/arm/mach-vt8500/Makefile
arch/arm/mach-vt8500/common.h
arch/arm/mach-vt8500/vt8500.c
arch/arm/mach-zynq/Kconfig
arch/arm/mach-zynq/Makefile
arch/arm/mach-zynq/common.c
arch/arm/mach-zynq/common.h
arch/arm/mach-zynq/timer.c [deleted file]
arch/arm/mm/cache-l2x0.c
arch/arm/mm/context.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/mmu.c
arch/arm/mm/proc-v7.S
arch/arm/net/bpf_jit_32.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-orion/addr-map.c
arch/arm/plat-samsung/Kconfig
arch/arm/plat-samsung/Makefile
arch/arm/plat-samsung/devs.c
arch/arm/plat-samsung/include/plat/cpu.h
arch/arm/plat-samsung/include/plat/irq.h [deleted file]
arch/arm/plat-samsung/include/plat/pm.h
arch/arm/plat-samsung/include/plat/s3c2410.h [deleted file]
arch/arm/plat-samsung/include/plat/s3c2412.h [deleted file]
arch/arm/plat-samsung/include/plat/s3c2416.h [deleted file]
arch/arm/plat-samsung/include/plat/s3c2443.h [deleted file]
arch/arm/plat-samsung/include/plat/s3c244x.h [deleted file]
arch/arm/plat-samsung/include/plat/s5p-time.h [deleted file]
arch/arm/plat-samsung/include/plat/samsung-time.h [new file with mode: 0644]
arch/arm/plat-samsung/include/plat/sdhci.h
arch/arm/plat-samsung/irq-vic-timer.c
arch/arm/plat-samsung/pm.c
arch/arm/plat-samsung/s5p-dev-mfc.c
arch/arm/plat-samsung/s5p-irq.c
arch/arm/plat-samsung/samsung-time.c [moved from arch/arm/plat-samsung/s5p-time.c with 68% similarity]
arch/arm/plat-samsung/time.c [deleted file]
arch/arm/plat-spear/Kconfig
arch/arm64/Kconfig
arch/arm64/Kconfig.debug
arch/arm64/configs/defconfig
arch/arm64/include/asm/ucontext.h
arch/arm64/kernel/arm64ksyms.c
arch/arm64/kernel/signal32.c
arch/arm64/mm/mmu.c
arch/avr32/Kconfig
arch/avr32/mach-at32ap/at32ap700x.c
arch/blackfin/Kconfig
arch/cris/Kconfig
arch/frv/Kconfig
arch/h8300/Kconfig
arch/ia64/Kconfig
arch/ia64/kernel/process.c
arch/m32r/Kconfig
arch/m32r/include/uapi/asm/stat.h
arch/m68k/Kconfig
arch/m68k/Kconfig.machine
arch/m68k/include/asm/MC68328.h
arch/m68k/kernel/setup_no.c
arch/m68k/mm/init.c
arch/m68k/platform/coldfire/m528x.c
arch/microblaze/Kconfig
arch/mips/Kconfig
arch/mips/bcm63xx/boards/board_bcm963xx.c
arch/mips/bcm63xx/nvram.c
arch/mips/bcm63xx/setup.c
arch/mips/cavium-octeon/setup.c
arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
arch/mips/include/asm/mach-sead3/cpu-feature-overrides.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/signal.h
arch/mips/include/uapi/asm/signal.h
arch/mips/kernel/Makefile
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/linux32.c
arch/mips/kernel/mcount.S
arch/mips/kernel/proc.c
arch/mips/kernel/traps.c
arch/mips/lib/bitops.c
arch/mips/lib/csum_partial.S
arch/mips/mm/c-r4k.c
arch/mips/mm/sc-mips.c
arch/mips/pci/pci-alchemy.c
arch/mn10300/Kconfig
arch/openrisc/Kconfig
arch/parisc/Kconfig
arch/powerpc/Kconfig
arch/powerpc/include/asm/mmu-hash64.h
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/epapr_paravirt.c
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/prom_init.c
arch/powerpc/kernel/ptrace.c
arch/powerpc/kvm/book3s_64_mmu_host.c
arch/powerpc/mm/hash_utils_64.c
arch/powerpc/mm/mmu_context_hash64.c
arch/powerpc/mm/pgtable_64.c
arch/powerpc/mm/slb_low.S
arch/powerpc/mm/tlb_hash64.c
arch/powerpc/perf/power7-pmu.c
arch/powerpc/platforms/85xx/sgy_cts1000.c
arch/powerpc/platforms/Kconfig.cputype
arch/s390/Kconfig
arch/s390/include/asm/cpu_mf.h
arch/s390/include/asm/eadm.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/tlbflush.h
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/setup.c
arch/s390/lib/uaccess_pt.c
arch/score/Kconfig
arch/sparc/Kconfig
arch/sparc/include/asm/spitfire.h
arch/sparc/kernel/cpu.c
arch/sparc/kernel/head_64.S
arch/sparc/kernel/leon_pci_grpci2.c
arch/tile/Kconfig
arch/tile/configs/tilegx_defconfig
arch/tile/configs/tilepro_defconfig
arch/tile/kernel/setup.c
arch/um/drivers/chan.h
arch/um/drivers/chan_kern.c
arch/um/drivers/chan_user.c
arch/um/drivers/chan_user.h
arch/um/drivers/line.c
arch/um/drivers/net_kern.c
arch/um/drivers/ssl.c
arch/um/drivers/stdio_console.c
arch/um/os-Linux/signal.c
arch/um/os-Linux/start_up.c
arch/unicore32/Kconfig
arch/x86/Kconfig
arch/x86/boot/compressed/Makefile
arch/x86/include/asm/kprobes.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/syscall.h
arch/x86/include/asm/xen/hypercall.h
arch/x86/include/uapi/asm/msr-index.h
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_ds.c
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/microcode_intel_early.c
arch/x86/kvm/lapic.c
arch/x86/kvm/x86.c
arch/x86/lib/usercopy_64.c
arch/x86/power/cpu.c
arch/x86/xen/mmu.c
arch/xtensa/Kconfig
block/blk-flush.c
block/partition-generic.c
drivers/Kconfig
drivers/Makefile
drivers/acpi/Kconfig
drivers/acpi/acpi_i2c.c
drivers/acpi/apei/cper.c
drivers/acpi/pci_root.c
drivers/acpi/processor_idle.c
drivers/acpi/processor_perflib.c
drivers/acpi/sleep.c
drivers/amba/tegra-ahb.c
drivers/ata/Kconfig
drivers/ata/ahci.c
drivers/ata/ata_piix.c
drivers/ata/libata-acpi.c
drivers/ata/pata_samsung_cf.c
drivers/ata/sata_fsl.c
drivers/base/power/qos.c
drivers/base/regmap/regcache-rbtree.c
drivers/base/regmap/regmap.c
drivers/block/Kconfig
drivers/block/aoe/aoecmd.c
drivers/block/cciss.c
drivers/block/loop.c
drivers/block/mg_disk.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/nvme.c
drivers/block/rbd.c
drivers/block/rsxx/Makefile
drivers/block/rsxx/config.c
drivers/block/rsxx/core.c
drivers/block/rsxx/cregs.c
drivers/block/rsxx/dma.c
drivers/block/rsxx/rsxx.h
drivers/block/rsxx/rsxx_cfg.h
drivers/block/rsxx/rsxx_priv.h
drivers/block/xen-blkback/blkback.c
drivers/block/xen-blkback/common.h
drivers/block/xen-blkback/xenbus.c
drivers/block/xen-blkfront.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/char/hw_random/core.c
drivers/char/hw_random/virtio-rng.c
drivers/char/virtio_console.c
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/clk-axi-clkgen.c [new file with mode: 0644]
drivers/clk/clk-composite.c [new file with mode: 0644]
drivers/clk/clk-mux.c
drivers/clk/clk-prima2.c
drivers/clk/clk-vt8500.c
drivers/clk/clk-zynq.c
drivers/clk/clk.c
drivers/clk/mxs/clk.c
drivers/clk/samsung/Makefile [new file with mode: 0644]
drivers/clk/samsung/clk-exynos4.c [new file with mode: 0644]
drivers/clk/samsung/clk-exynos5250.c [new file with mode: 0644]
drivers/clk/samsung/clk-exynos5440.c [new file with mode: 0644]
drivers/clk/samsung/clk-pll.c [new file with mode: 0644]
drivers/clk/samsung/clk-pll.h [new file with mode: 0644]
drivers/clk/samsung/clk.c [new file with mode: 0644]
drivers/clk/samsung/clk.h [new file with mode: 0644]
drivers/clk/spear/spear1340_clock.c
drivers/clk/sunxi/Makefile [new file with mode: 0644]
drivers/clk/sunxi/clk-factors.c [new file with mode: 0644]
drivers/clk/sunxi/clk-factors.h [new file with mode: 0644]
drivers/clk/sunxi/clk-sunxi.c [new file with mode: 0644]
drivers/clk/tegra/Makefile
drivers/clk/tegra/clk-periph-gate.c
drivers/clk/tegra/clk-periph.c
drivers/clk/tegra/clk-pll.c
drivers/clk/tegra/clk-tegra114.c [new file with mode: 0644]
drivers/clk/tegra/clk-tegra20.c
drivers/clk/tegra/clk-tegra30.c
drivers/clk/tegra/clk.c
drivers/clk/tegra/clk.h
drivers/clk/ux500/clk-prcmu.c
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/clocksource/cadence_ttc_timer.c [new file with mode: 0644]
drivers/clocksource/em_sti.c
drivers/clocksource/exynos_mct.c [moved from arch/arm/mach-exynos/mct.c with 65% similarity]
drivers/clocksource/sh_cmt.c
drivers/clocksource/sh_mtu2.c
drivers/clocksource/sh_tmu.c
drivers/clocksource/sunxi_timer.c
drivers/clocksource/tegra20_timer.c
drivers/cpufreq/acpi-cpufreq.c
drivers/cpufreq/cpufreq-cpu0.c
drivers/cpufreq/cpufreq_governor.h
drivers/cpufreq/cpufreq_stats.c
drivers/cpufreq/intel_pstate.c
drivers/crypto/caam/caamalg.c
drivers/crypto/caam/compat.h
drivers/crypto/talitos.c
drivers/dma/Kconfig
drivers/dma/dw_dmac.c
drivers/dma/dw_dmac_regs.h
drivers/edac/amd64_edac.c
drivers/edac/edac_mc.c
drivers/edac/edac_mc_sysfs.c
drivers/eisa/pci_eisa.c
drivers/extcon/extcon-max77693.c
drivers/extcon/extcon-max8997.c
drivers/firmware/Kconfig
drivers/firmware/efivars.c
drivers/gpio/Kconfig
drivers/gpio/Makefile
drivers/gpio/gpio-ich.c
drivers/gpio/gpio-mvebu.c
drivers/gpio/gpio-samsung.c
drivers/gpio/gpio-stmpe.c
drivers/gpio/gpio-tegra.c
drivers/gpio/gpio-vt8500.c [deleted file]
drivers/gpio/gpiolib-of.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_fops.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_gem.c
drivers/gpu/drm/exynos/exynos_drm_gem.h
drivers/gpu/drm/exynos/exynos_drm_vidi.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/i915/i915_debugfs.c
drivers/gpu/drm/i915/i915_drv.c
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem_execbuffer.c
drivers/gpu/drm/i915/intel_crt.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_i2c.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/mgag200/mgag200_mode.c
drivers/gpu/drm/nouveau/core/core/object.c
drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
drivers/gpu/drm/nouveau/core/include/subdev/therm.h
drivers/gpu/drm/nouveau/core/subdev/bios/base.c
drivers/gpu/drm/nouveau/core/subdev/therm/base.c
drivers/gpu/drm/nouveau/core/subdev/therm/ic.c
drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c
drivers/gpu/drm/nouveau/core/subdev/therm/priv.h
drivers/gpu/drm/nouveau/core/subdev/therm/temp.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_bo.c
drivers/gpu/drm/nouveau/nouveau_drm.c
drivers/gpu/drm/nouveau/nouveau_drm.h
drivers/gpu/drm/nouveau/nouveau_pm.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/radeon/ni.c
drivers/gpu/drm/radeon/radeon_benchmark.c
drivers/gpu/drm/radeon/radeon_bios.c
drivers/gpu/drm/radeon/si.c
drivers/hid/hid-core.c
drivers/hid/hid-ids.h
drivers/hid/hid-magicmouse.c
drivers/hid/hid-multitouch.c
drivers/hid/usbhid/hid-quirks.c
drivers/hwmon/lineage-pem.c
drivers/hwmon/lm75.h
drivers/hwmon/pmbus/ltc2978.c
drivers/hwmon/pmbus/pmbus_core.c
drivers/i2c/Kconfig
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-ismt.c
drivers/i2c/busses/i2c-tegra.c
drivers/i2c/muxes/i2c-mux-pca9541.c
drivers/iio/common/st_sensors/st_sensors_core.c
drivers/iio/dac/ad5064.c
drivers/iio/imu/inv_mpu6050/Kconfig
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/cxgb4/qp.c
drivers/infiniband/hw/ipath/ipath_verbs.c
drivers/infiniband/hw/mlx4/cm.c
drivers/infiniband/hw/qib/Kconfig
drivers/infiniband/hw/qib/qib_driver.c
drivers/infiniband/hw/qib/qib_iba6120.c
drivers/infiniband/hw/qib/qib_init.c
drivers/infiniband/hw/qib/qib_sd7220.c
drivers/infiniband/hw/qib/qib_verbs.c
drivers/infiniband/ulp/ipoib/ipoib_cm.c
drivers/input/joystick/analog.c
drivers/input/keyboard/tc3589x-keypad.c
drivers/input/mouse/alps.c
drivers/input/mouse/alps.h
drivers/input/mouse/cypress_ps2.c
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/ads7846.c
drivers/input/touchscreen/mms114.c
drivers/iommu/Kconfig
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_init.c
drivers/iommu/irq_remapping.c
drivers/irqchip/Kconfig
drivers/irqchip/Makefile
drivers/irqchip/exynos-combiner.c
drivers/irqchip/irq-gic.c
drivers/irqchip/irq-renesas-intc-irqpin.c [new file with mode: 0644]
drivers/irqchip/irq-renesas-irqc.c [new file with mode: 0644]
drivers/irqchip/irq-s3c24xx.c [moved from arch/arm/mach-s3c24xx/irq.c with 52% similarity]
drivers/irqchip/irq-vt8500.c [moved from arch/arm/mach-vt8500/irq.c with 97% similarity]
drivers/isdn/hisax/Kconfig
drivers/isdn/i4l/isdn_tty.c
drivers/md/dm-bufio.c
drivers/md/dm-cache-metadata.c
drivers/md/dm-cache-metadata.h
drivers/md/dm-cache-policy-cleaner.c
drivers/md/dm-cache-policy-internal.h
drivers/md/dm-cache-policy-mq.c
drivers/md/dm-cache-policy.c
drivers/md/dm-cache-policy.h
drivers/md/dm-cache-target.c
drivers/md/dm-thin.c
drivers/md/dm-verity.c
drivers/md/md.c
drivers/md/md.h
drivers/md/persistent-data/dm-btree-remove.c
drivers/md/raid5.c
drivers/md/raid5.h
drivers/media/i2c/m5mols/m5mols_core.c
drivers/media/pci/bt8xx/bttv-driver.c
drivers/media/platform/Kconfig
drivers/media/platform/exynos-gsc/gsc-core.c
drivers/media/platform/s5p-fimc/fimc-core.c
drivers/media/platform/s5p-fimc/fimc-lite-reg.c
drivers/media/platform/s5p-fimc/fimc-lite.c
drivers/media/platform/s5p-fimc/fimc-mdevice.c
drivers/media/platform/s5p-mfc/s5p_mfc.c
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
drivers/media/radio/radio-ma901.c
drivers/media/rc/Kconfig
drivers/media/v4l2-core/Makefile
drivers/mfd/Kconfig
drivers/mfd/ab8500-gpadc.c
drivers/mfd/omap-usb-host.c
drivers/mfd/palmas.c
drivers/mfd/tps65912-core.c
drivers/mfd/twl4030-audio.c
drivers/mfd/twl4030-madc.c
drivers/misc/mei/hw-me.c
drivers/misc/mei/init.c
drivers/misc/mei/mei_dev.h
drivers/misc/mei/pci-me.c
drivers/misc/vmw_vmci/vmci_datagram.c
drivers/mmc/host/Kconfig
drivers/mmc/host/s3cmci.c
drivers/mmc/host/sdhci-s3c-regs.h [moved from arch/arm/plat-samsung/include/plat/regs-sdhci.h with 100% similarity]
drivers/mmc/host/sdhci-s3c.c
drivers/mtd/bcm47xxpart.c
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_ids.c
drivers/mtd/onenand/samsung.c
drivers/mtd/onenand/samsung.h [moved from arch/arm/plat-samsung/include/plat/regs-onenand.h with 98% similarity]
drivers/net/bonding/bond_main.c
drivers/net/bonding/bond_sysfs.c
drivers/net/can/sja1000/Kconfig
drivers/net/can/sja1000/plx_pci.c
drivers/net/can/sja1000/sja1000.c
drivers/net/can/sja1000/sja1000.h
drivers/net/ethernet/atheros/atl1e/atl1e.h
drivers/net/ethernet/atheros/atl1e/atl1e_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h
drivers/net/ethernet/broadcom/tg3.c
drivers/net/ethernet/calxeda/xgmac.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/davicom/dm9000.c
drivers/net/ethernet/davicom/dm9000.h
drivers/net/ethernet/dec/tulip/Kconfig
drivers/net/ethernet/emulex/benet/be.h
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_hw.h
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/fec.c
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_ptp.c
drivers/net/ethernet/intel/e1000/e1000_ethtool.c
drivers/net/ethernet/intel/e1000e/ethtool.c
drivers/net/ethernet/intel/e1000e/ich8lan.c
drivers/net/ethernet/intel/e1000e/ich8lan.h
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/intel/e1000e/regs.h
drivers/net/ethernet/intel/igb/e1000_82575.c
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_hwmon.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igb/igb_ptp.c
drivers/net/ethernet/intel/ixgb/ixgb_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/lantiq_etop.c
drivers/net/ethernet/marvell/mv643xx_eth.c
drivers/net/ethernet/marvell/sky2.c
drivers/net/ethernet/marvell/sky2.h
drivers/net/ethernet/mellanox/mlx4/cq.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/eq.c
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/mlx4_en.h
drivers/net/ethernet/mellanox/mlx4/mr.c
drivers/net/ethernet/mellanox/mlx4/pd.c
drivers/net/ethernet/mellanox/mlx4/port.c
drivers/net/ethernet/mellanox/mlx4/qp.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/mellanox/mlx4/srq.c
drivers/net/ethernet/micrel/ks8851.c
drivers/net/ethernet/nxp/lpc_eth.c
drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c
drivers/net/ethernet/realtek/r8169.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/renesas/sh_eth.h
drivers/net/ethernet/sfc/efx.h
drivers/net/ethernet/sfc/nic.c
drivers/net/ethernet/sfc/rx.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/hippi/rrunner.c
drivers/net/macvlan.c
drivers/net/netconsole.c
drivers/net/team/team.c
drivers/net/tun.c
drivers/net/usb/Kconfig
drivers/net/usb/cdc_mbim.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/smsc75xx.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vmxnet3/vmxnet3_ethtool.c
drivers/net/vmxnet3/vmxnet3_int.h
drivers/net/vxlan.c
drivers/net/wireless/ath/ath9k/ar9003_calib.c
drivers/net/wireless/ath/ath9k/link.c
drivers/net/wireless/b43/dma.c
drivers/net/wireless/b43/phy_n.c
drivers/net/wireless/brcm80211/brcmsmac/phy/phy_lcn.c
drivers/net/wireless/brcm80211/brcmsmac/phy/phytbl_lcn.c
drivers/net/wireless/iwlegacy/3945-mac.c
drivers/net/wireless/iwlegacy/4965-rs.c
drivers/net/wireless/iwlwifi/dvm/lib.c
drivers/net/wireless/iwlwifi/dvm/rxon.c
drivers/net/wireless/iwlwifi/dvm/sta.c
drivers/net/wireless/iwlwifi/dvm/tx.c
drivers/net/wireless/iwlwifi/dvm/ucode.c
drivers/net/wireless/iwlwifi/iwl-devtrace.h
drivers/net/wireless/iwlwifi/iwl-drv.c
drivers/net/wireless/iwlwifi/iwl-modparams.h
drivers/net/wireless/iwlwifi/iwl-trans.h
drivers/net/wireless/iwlwifi/mvm/fw-api.h
drivers/net/wireless/iwlwifi/mvm/fw.c
drivers/net/wireless/iwlwifi/mvm/mvm.h
drivers/net/wireless/iwlwifi/mvm/ops.c
drivers/net/wireless/iwlwifi/mvm/rx.c
drivers/net/wireless/iwlwifi/mvm/sta.c
drivers/net/wireless/iwlwifi/mvm/tx.c
drivers/net/wireless/iwlwifi/pcie/internal.h
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/iwlwifi/pcie/tx.c
drivers/net/wireless/mwifiex/cfg80211.c
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/mwifiex/init.c
drivers/net/wireless/mwifiex/join.c
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/pcie.c
drivers/net/wireless/mwifiex/scan.c
drivers/net/wireless/mwifiex/sta_ioctl.c
drivers/net/wireless/rt2x00/Kconfig
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
drivers/net/wireless/rtlwifi/usb.c
drivers/nfc/microread/mei.c
drivers/of/base.c
drivers/pci/pci-acpi.c
drivers/pci/pci-driver.c
drivers/pci/pcie/portdrv_pci.c
drivers/pci/rom.c
drivers/pinctrl/Kconfig
drivers/pinctrl/Makefile
drivers/pinctrl/mvebu/pinctrl-mvebu.c
drivers/pinctrl/pinconf.c
drivers/pinctrl/pinconf.h
drivers/pinctrl/pinctrl-abx500.c
drivers/pinctrl/pinctrl-at91.c
drivers/pinctrl/pinctrl-bcm2835.c
drivers/pinctrl/pinctrl-exynos.c
drivers/pinctrl/pinctrl-samsung.c
drivers/pinctrl/pinctrl-samsung.h
drivers/pinctrl/pinmux.c
drivers/pinctrl/sh-pfc/pfc-sh73a0.c
drivers/pinctrl/vt8500/Kconfig [new file with mode: 0644]
drivers/pinctrl/vt8500/Makefile [new file with mode: 0644]
drivers/pinctrl/vt8500/pinctrl-vt8500.c [new file with mode: 0644]
drivers/pinctrl/vt8500/pinctrl-wm8505.c [new file with mode: 0644]
drivers/pinctrl/vt8500/pinctrl-wm8650.c [new file with mode: 0644]
drivers/pinctrl/vt8500/pinctrl-wm8750.c [new file with mode: 0644]
drivers/pinctrl/vt8500/pinctrl-wm8850.c [new file with mode: 0644]
drivers/pinctrl/vt8500/pinctrl-wmt.c [new file with mode: 0644]
drivers/pinctrl/vt8500/pinctrl-wmt.h [new file with mode: 0644]
drivers/reset/Kconfig [new file with mode: 0644]
drivers/reset/Makefile [new file with mode: 0644]
drivers/reset/core.c [new file with mode: 0644]
drivers/rtc/rtc-da9052.c
drivers/rtc/rtc-mv.c
drivers/rtc/rtc-s3c.c
drivers/rtc/rtc-s3c.h [moved from arch/arm/plat-samsung/include/plat/regs-rtc.h with 97% similarity]
drivers/s390/block/scm_blk.c
drivers/s390/block/scm_blk.h
drivers/s390/block/scm_drv.c
drivers/s390/char/sclp_cmd.c
drivers/s390/char/tty3270.c
drivers/s390/cio/chsc.c
drivers/s390/cio/chsc.h
drivers/s390/cio/scm.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/net/qeth_l3_sys.c
drivers/scsi/bnx2fc/bnx2fc_fcoe.c
drivers/scsi/fcoe/fcoe.c
drivers/scsi/fcoe/fcoe_ctlr.c
drivers/scsi/libfc/fc_disc.c
drivers/spi/Kconfig
drivers/spi/spi-bcm63xx.c
drivers/spi/spi-mpc512x-psc.c
drivers/spi/spi-pxa2xx.c
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-tegra20-slink.c
drivers/spi/spi.c
drivers/staging/comedi/drivers/dt9812.c
drivers/staging/comedi/drivers/s626.c
drivers/staging/comedi/drivers/usbdux.c
drivers/staging/comedi/drivers/usbduxfast.c
drivers/staging/comedi/drivers/usbduxsigma.c
drivers/staging/imx-drm/ipuv3-crtc.c
drivers/staging/tidspbridge/rmgr/drv.c
drivers/staging/vt6656/card.c
drivers/staging/vt6656/main_usb.c
drivers/staging/zcache/Kconfig
drivers/staging/zcache/ramster/tcp.c
drivers/target/iscsi/iscsi_target_auth.c
drivers/target/target_core_file.h
drivers/target/target_core_pscsi.c
drivers/target/target_core_sbc.c
drivers/target/target_core_tpg.c
drivers/target/target_core_transport.c
drivers/thermal/dove_thermal.c
drivers/thermal/exynos_thermal.c
drivers/thermal/kirkwood_thermal.c
drivers/thermal/rcar_thermal.c
drivers/tty/serial/8250/8250_core.c [moved from drivers/tty/serial/8250/8250.c with 98% similarity]
drivers/tty/serial/8250/8250_pci.c
drivers/tty/serial/8250/8250_pnp.c
drivers/tty/serial/8250/Kconfig
drivers/tty/serial/8250/Makefile
drivers/tty/serial/Kconfig
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/bcm63xx_uart.c
drivers/tty/serial/mpc52xx_uart.c
drivers/tty/serial/of_serial.c
drivers/tty/serial/sunsu.c
drivers/tty/serial/vt8500_serial.c
drivers/tty/serial/xilinx_uartps.c
drivers/tty/tty_buffer.c
drivers/tty/vt/vc_screen.c
drivers/usb/Makefile
drivers/usb/c67x00/c67x00-sched.c
drivers/usb/chipidea/udc.c
drivers/usb/class/cdc-acm.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd.c
drivers/usb/core/port.c
drivers/usb/core/usb-acpi.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/dwc3-exynos.c
drivers/usb/dwc3/dwc3-omap.c
drivers/usb/dwc3/dwc3-pci.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/Makefile
drivers/usb/gadget/composite.c
drivers/usb/gadget/f_rndis.c
drivers/usb/gadget/f_uac1.c
drivers/usb/gadget/g_ffs.c
drivers/usb/gadget/imx_udc.c
drivers/usb/gadget/net2272.c
drivers/usb/gadget/net2280.c
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/pxa25x_udc.c
drivers/usb/gadget/pxa27x_udc.c
drivers/usb/gadget/s3c2410_udc.c
drivers/usb/gadget/u_serial.c
drivers/usb/gadget/u_uac1.c
drivers/usb/gadget/udc-core.c
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hub.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci-timer.c
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci-pci.c
drivers/usb/host/xhci-ring.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/musb/Kconfig
drivers/usb/musb/da8xx.c
drivers/usb/musb/musb_core.c
drivers/usb/musb/musb_gadget.c
drivers/usb/musb/omap2430.c
drivers/usb/otg/otg.c
drivers/usb/phy/Kconfig
drivers/usb/phy/omap-control-usb.c
drivers/usb/phy/omap-usb3.c
drivers/usb/phy/samsung-usbphy.c
drivers/usb/serial/ark3116.c
drivers/usb/serial/ch341.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/f81232.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/option.c
drivers/usb/serial/oti6858.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/qcaux.c
drivers/usb/serial/qcserial.c
drivers/usb/serial/quatech2.c
drivers/usb/serial/spcp8x5.c
drivers/usb/serial/ssu100.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c
drivers/usb/storage/initializers.c
drivers/usb/storage/initializers.h
drivers/usb/storage/unusual_devs.h
drivers/vfio/pci/vfio_pci_config.c
drivers/vfio/pci/vfio_pci_intrs.c
drivers/vhost/net.c
drivers/vhost/tcm_vhost.c
drivers/video/atmel_lcdfb.c
drivers/video/ep93xx-fb.c
drivers/video/fbmon.c
drivers/video/mxsfb.c
drivers/video/omap/lcd_ams_delta.c
drivers/video/omap/lcd_osk.c
drivers/video/omap/omapfb_main.c
drivers/video/omap2/displays/panel-tpo-td043mtea1.c
drivers/video/omap2/dss/dss_features.c
drivers/video/sh_mobile_lcdcfb.c
drivers/video/uvesafb.c
drivers/w1/masters/w1-gpio.c
drivers/w1/w1.c
drivers/watchdog/sp5100_tco.c
drivers/watchdog/sp5100_tco.h
drivers/xen/Kconfig
drivers/xen/events.c
drivers/xen/fallback.c
drivers/xen/xen-acpi-processor.c
drivers/xen/xen-pciback/pci_stub.c
drivers/xen/xen-pciback/pciback_ops.c
drivers/xen/xen-stub.c
fs/block_dev.c
fs/btrfs/ctree.c
fs/btrfs/disk-io.c
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/file-item.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/locking.h
fs/btrfs/ordered-data.c
fs/btrfs/qgroup.c
fs/btrfs/scrub.c
fs/btrfs/send.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/cifs/asn1.c
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/netmisc.c
fs/compat.c
fs/dcache.c
fs/ext2/ialloc.c
fs/ext2/inode.c
fs/ext3/super.c
fs/ext4/ext4.h
fs/ext4/extents.c
fs/ext4/extents_status.c
fs/ext4/extents_status.h
fs/ext4/ialloc.c
fs/ext4/indirect.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/move_extent.c
fs/ext4/page-io.c
fs/ext4/resize.c
fs/ext4/super.c
fs/freevxfs/vxfs_super.c
fs/gfs2/file.c
fs/gfs2/incore.h
fs/gfs2/lock_dlm.c
fs/gfs2/rgrp.c
fs/hostfs/hostfs_kern.c
fs/hpfs/super.c
fs/internal.h
fs/isofs/inode.c
fs/jbd2/transaction.c
fs/namespace.c
fs/nfs/blocklayout/blocklayoutdm.c
fs/nfs/idmap.c
fs/nfs/nfs4filelayout.c
fs/nfs/nfs4proc.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/super.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfscache.c
fs/nfsd/vfs.c
fs/pipe.c
fs/pnode.c
fs/pnode.h
fs/proc/inode.c
fs/proc/root.c
fs/quota/dquot.c
fs/read_write.c
fs/reiserfs/super.c
fs/reiserfs/xattr.c
fs/splice.c
fs/squashfs/super.c
fs/sysfs/dir.c
fs/sysfs/mount.c
fs/sysv/super.c
fs/ubifs/super.c
fs/udf/super.c
fs/xfs/xfs_buf.c
fs/xfs/xfs_iomap.c
include/acpi/processor.h
include/asm-generic/atomic.h
include/asm-generic/cmpxchg.h
include/drm/drm_pciids.h
include/linux/clk-private.h
include/linux/clk-provider.h
include/linux/clk/sunxi.h [new file with mode: 0644]
include/linux/clk/tegra.h
include/linux/compat.h
include/linux/debug_locks.h
include/linux/devfreq.h
include/linux/edac.h
include/linux/freezer.h
include/linux/fs_struct.h
include/linux/hash.h
include/linux/idr.h
include/linux/iio/common/st_sensors.h
include/linux/irq_work.h
include/linux/kernel.h
include/linux/kvm_host.h
include/linux/kvm_types.h
include/linux/list.h
include/linux/mfd/max77693-private.h
include/linux/mfd/palmas.h
include/linux/mfd/tps65912.h
include/linux/mfd/wm831x/auxadc.h
include/linux/mfd/wm831x/core.h
include/linux/mm.h
include/linux/mman.h
include/linux/mmzone.h
include/linux/mount.h
include/linux/mtd/nand.h
include/linux/mxsfb.h
include/linux/netdevice.h
include/linux/nvme.h
include/linux/of.h
include/linux/pci.h
include/linux/perf_event.h
include/linux/platform_data/irq-renesas-intc-irqpin.h [new file with mode: 0644]
include/linux/platform_data/irq-renesas-irqc.h [new file with mode: 0644]
include/linux/platform_data/mmc-sdhci-s3c.h [new file with mode: 0644]
include/linux/printk.h
include/linux/res_counter.h
include/linux/reset-controller.h [new file with mode: 0644]
include/linux/reset.h [new file with mode: 0644]
include/linux/signal.h
include/linux/skbuff.h
include/linux/thermal.h
include/linux/udp.h
include/linux/usb/cdc_ncm.h
include/linux/usb/composite.h
include/linux/usb/hcd.h
include/linux/usb/nop-usb-xceiv.h
include/linux/usb/serial.h
include/linux/usb/ulpi.h
include/linux/user_namespace.h
include/net/dst.h
include/net/flow_keys.h
include/net/inet_frag.h
include/net/ip_fib.h
include/net/ip_vs.h
include/net/ipip.h
include/scsi/libfc.h
include/sound/max98090.h [changed mode: 0755->0644]
include/sound/soc-dapm.h
include/uapi/linux/acct.h
include/uapi/linux/aio_abi.h
include/uapi/linux/packet_diag.h
include/uapi/linux/raid/md_p.h
include/uapi/linux/serial_core.h
include/uapi/linux/unix_diag.h
include/video/atmel_lcdc.h
include/xen/interface/io/blkif.h
include/xen/interface/physdev.h
init/Kconfig
ipc/mqueue.c
ipc/msg.c
kernel/events/core.c
kernel/exit.c
kernel/fork.c
kernel/futex.c
kernel/lockdep.c
kernel/pid_namespace.c
kernel/printk.c
kernel/signal.c
kernel/sys.c
kernel/time/tick-broadcast.c
kernel/trace/Kconfig
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_irqsoff.c
kernel/trace/trace_sched_wakeup.c
kernel/user.c
kernel/user_namespace.c
kernel/workqueue.c
lib/bust_spinlocks.c
lib/dma-debug.c
lib/idr.c
lib/xz/Kconfig
mm/Kconfig
mm/fremap.c
mm/hugetlb.c
mm/memory_hotplug.c
mm/mlock.c
mm/mmap.c
mm/nommu.c
mm/process_vm_access.c
net/8021q/vlan.c
net/batman-adv/bat_iv_ogm.c
net/bluetooth/sco.c
net/bridge/br_device.c
net/bridge/br_fdb.c
net/bridge/br_input.c
net/bridge/br_mdb.c
net/bridge/br_multicast.c
net/bridge/br_netlink.c
net/bridge/br_private.h
net/ceph/osdmap.c
net/core/dev.c
net/core/dev_addr_lists.c
net/core/flow.c
net/core/flow_dissector.c
net/core/rtnetlink.c
net/core/scm.c
net/dcb/dcbnl.c
net/ieee802154/6lowpan.h
net/ipv4/af_inet.c
net/ipv4/devinet.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_fragment.c
net/ipv4/ip_fragment.c
net/ipv4/ip_gre.c
net/ipv4/ip_options.c
net/ipv4/ipconfig.c
net/ipv4/netfilter/Kconfig
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv6/addrconf.c
net/ipv6/ip6_input.c
net/ipv6/netfilter/ip6t_NPT.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/reassembly.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/irda/af_irda.c
net/irda/ircomm/ircomm_tty.c
net/key/af_key.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_core.h
net/l2tp/l2tp_debugfs.c
net/l2tp/l2tp_ip.c
net/l2tp/l2tp_ip6.c
net/l2tp/l2tp_netlink.c
net/l2tp/l2tp_ppp.c
net/mac80211/cfg.c
net/mac80211/chan.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/mesh.c
net/mac80211/mlme.c
net/mac80211/offchannel.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/tx.c
net/netfilter/ipvs/ip_vs_core.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/ipvs/ip_vs_proto_sctp.c
net/netfilter/nf_conntrack_helper.c
net/netfilter/nf_conntrack_proto_dccp.c
net/netfilter/nf_conntrack_proto_gre.c
net/netfilter/nf_conntrack_proto_sctp.c
net/netfilter/nf_conntrack_proto_udplite.c
net/netfilter/nf_conntrack_standalone.c
net/netfilter/nfnetlink.c
net/netfilter/nfnetlink_acct.c
net/netfilter/nfnetlink_queue_core.c
net/netfilter/xt_AUDIT.c
net/netlabel/netlabel_unlabeled.c
net/netlink/genetlink.c
net/nfc/llcp/llcp.c
net/nfc/llcp/sock.c
net/openvswitch/actions.c
net/openvswitch/datapath.c
net/openvswitch/flow.c
net/openvswitch/vport-netdev.c
net/openvswitch/vport.c
net/rds/stats.c
net/sched/sch_cbq.c
net/sched/sch_fq_codel.c
net/sched/sch_generic.c
net/sched/sch_qfq.c
net/sctp/associola.c
net/sctp/sm_statefuns.c
net/sunrpc/auth_gss/svcauth_gss.c
net/sunrpc/rpc_pipe.c
net/sunrpc/sched.c
net/sunrpc/xprtsock.c
net/unix/af_unix.c
net/vmw_vsock/af_vsock.c
net/vmw_vsock/vmci_transport.c
net/vmw_vsock/vsock_addr.c
net/vmw_vsock/vsock_addr.h
net/wireless/core.c
net/wireless/core.h
net/wireless/nl80211.c
net/wireless/scan.c
net/wireless/sme.c
net/wireless/trace.h
net/wireless/wext-sme.c
net/xfrm/xfrm_replay.c
scripts/Makefile.headersinst
security/keys/compat.c
security/keys/process_keys.c
security/selinux/xfrm.c
security/yama/yama_lsm.c
sound/core/seq/seq_timer.c
sound/oss/sequencer.c
sound/pci/asihpi/asihpi.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_eld.c
sound/pci/hda/hda_generic.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_ca0132.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_conexant.c
sound/pci/hda/patch_hdmi.c
sound/pci/hda/patch_realtek.c
sound/pci/hda/patch_sigmatel.c
sound/soc/codecs/max98090.c [changed mode: 0755->0644]
sound/soc/codecs/max98090.h [changed mode: 0755->0644]
sound/soc/codecs/si476x.c
sound/soc/codecs/wm_adsp.c
sound/soc/fsl/imx-ssi.c
sound/soc/fsl/pcm030-audio-fabric.c
sound/soc/sh/dma-sh7760.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/spear/spear_pcm.c
sound/usb/card.c
sound/usb/clock.c
sound/usb/mixer.c
tools/lib/traceevent/Makefile
tools/perf/Makefile
tools/perf/bench/bench.h
tools/perf/builtin-record.c
tools/perf/util/hist.h
tools/perf/util/strlist.c
tools/usb/ffs-test.c
virt/kvm/ioapic.c
virt/kvm/kvm_main.c

diff --git a/CREDITS b/CREDITS
index 78163cb3eb6ad9d0b2c3372ef0d6305b48e95981..afaa7cec6ea5126198d5220389f66d9678ed8949 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -1510,6 +1510,14 @@ D: Natsemi ethernet
 D: Cobalt Networks (x86) support
 D: This-and-That
 
+N: Mark M. Hoffman
+E: mhoffman@lightlink.com
+D: asb100, lm93 and smsc47b397 hardware monitoring drivers
+D: hwmon subsystem core
+D: hwmon subsystem maintainer
+D: i2c-sis96x and i2c-stub SMBus drivers
+S: USA
+
 N: Dirk Hohndel
 E: hohndel@suse.de
 D: The XFree86[tm] Project
diff --git a/Documentation/arm/sunxi/clocks.txt b/Documentation/arm/sunxi/clocks.txt
new file mode 100644 (file)
index 0000000..e09a88a
--- /dev/null
@@ -0,0 +1,56 @@
+Frequently asked questions about the sunxi clock system
+=======================================================
+
+This document contains useful bits of information that people tend to ask
+about the sunxi clock system, as well as accompanying ASCII art when adequate.
+
+Q: Why is the main 24MHz oscillator gatable? Wouldn't that break the
+   system?
+
+A: The 24MHz oscillator allows gating to save power. Indeed, if gated
+   carelessly the system would stop functioning, but with the right
+   steps, one can gate it and keep the system running. Consider this
+   simplified suspend example:
+
+   While the system is operational, you would see something like
+
+      24MHz         32kHz
+       |
+      PLL1
+       \
+        \_ CPU Mux
+             |
+           [CPU]
+
+   When you are about to suspend, you switch the CPU Mux to the 32kHz
+   oscillator:
+
+      24Mhz         32kHz
+       |              |
+      PLL1            |
+                     /
+           CPU Mux _/
+             |
+           [CPU]
+
+    Finally you can gate the main oscillator
+
+                    32kHz
+                      |
+                      |
+                     /
+           CPU Mux _/
+             |
+           [CPU]
+
+Q: Were can I learn more about the sunxi clocks?
+
+A: The linux-sunxi wiki contains a page documenting the clock registers,
+   you can find it at
+
+        http://linux-sunxi.org/A10/CCM
+
+   The authoritative source for information at this time is the ccmu driver
+   released by Allwinner, you can find it at
+
+        https://github.com/linux-sunxi/linux-sunxi/tree/sunxi-3.0/arch/arm/mach-sun4i/clock/ccmu
index 1943fae014fd8a7d98a6af898558535556ffaaf3..4274a546eb578a0171a2b033c514f21ea3fc53db 100644 (file)
@@ -174,9 +174,9 @@ int clk_foo_enable(struct clk_hw *hw)
 };
 
 Below is a matrix detailing which clk_ops are mandatory based upon the
-hardware capbilities of that clock.  A cell marked as "y" means
+hardware capabilities of that clock.  A cell marked as "y" means
 mandatory, a cell marked as "n" implies that either including that
-callback is invalid or otherwise uneccesary.  Empty cells are either
+callback is invalid or otherwise unnecessary.  Empty cells are either
 optional or must be evaluated on a case-by-case basis.
 
                            clock hardware characteristics
index b5846e21cc2e53306fdba8304bf9cf12a6595126..1608a54e90e1541e6a1f7ca918f194f9763ed35e 100644 (file)
@@ -1,19 +1,84 @@
 NVIDIA Tegra Power Management Controller (PMC)
 
-Properties:
+The PMC block interacts with an external Power Management Unit. The PMC
+mostly controls the entry and exit of the system from different sleep
+modes. It provides power-gating controllers for SoC and CPU power-islands.
+
+Required properties:
 - name : Should be pmc
 - compatible : Should contain "nvidia,tegra<chip>-pmc".
 - reg : Offset and length of the register set for the device
+- clocks : Must contain an entry for each entry in clock-names.
+- clock-names : Must include the following entries:
+  "pclk" (The Tegra clock of that name),
+  "clk32k_in" (The 32KHz clock input to Tegra).
+
+Optional properties:
 - nvidia,invert-interrupt : If present, inverts the PMU interrupt signal.
   The PMU is an external Power Management Unit, whose interrupt output
   signal is fed into the PMC. This signal is optionally inverted, and then
   fed into the ARM GIC. The PMC is not involved in the detection or
   handling of this interrupt signal, merely its inversion.
+- nvidia,suspend-mode : The suspend mode that the platform should use.
+  Valid values are 0, 1 and 2:
+  0 (LP0): CPU + Core voltage off and DRAM in self-refresh
+  1 (LP1): CPU voltage off and DRAM in self-refresh
+  2 (LP2): CPU voltage off
+- nvidia,core-power-req-active-high : Boolean, core power request active-high
+- nvidia,sys-clock-req-active-high : Boolean, system clock request active-high
+- nvidia,combined-power-req : Boolean, combined power request for CPU & Core
+- nvidia,cpu-pwr-good-en : Boolean, CPU power good signal (from PMIC to PMC)
+                          is enabled.
+
+Required properties when nvidia,suspend-mode is specified:
+- nvidia,cpu-pwr-good-time : CPU power good time in uS.
+- nvidia,cpu-pwr-off-time : CPU power off time in uS.
+- nvidia,core-pwr-good-time : <Oscillator-stable-time Power-stable-time>
+                             Core power good time in uS.
+- nvidia,core-pwr-off-time : Core power off time in uS.
+
+Required properties when nvidia,suspend-mode=<0>:
+- nvidia,lp0-vec : <start length> Starting address and length of LP0 vector
+  The LP0 vector contains the warm boot code that is executed by AVP when
+  resuming from the LP0 state. The AVP (Audio-Video Processor) is an ARM7
+  processor and always being the first boot processor when chip is power on
+  or resume from deep sleep mode. When the system is resumed from the deep
+  sleep mode, the warm boot code will restore some PLLs, clocks and then
+  bring up CPU0 for resuming the system.
 
 Example:
 
+/ SoC dts including file
 pmc@7000f400 {
        compatible = "nvidia,tegra20-pmc";
        reg = <0x7000e400 0x400>;
+       clocks = <&tegra_car 110>, <&clk32k_in>;
+       clock-names = "pclk", "clk32k_in";
        nvidia,invert-interrupt;
+       nvidia,suspend-mode = <1>;
+       nvidia,cpu-pwr-good-time = <2000>;
+       nvidia,cpu-pwr-off-time = <100>;
+       nvidia,core-pwr-good-time = <3845 3845>;
+       nvidia,core-pwr-off-time = <458>;
+       nvidia,core-power-req-active-high;
+       nvidia,sys-clock-req-active-high;
+       nvidia,lp0-vec = <0xbdffd000 0x2000>;
+};
+
+/ Tegra board dts file
+{
+       ...
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock {
+                       compatible = "fixed-clock";
+                       reg=<0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+       ...
 };
index 5ddb2e9efaaacf020a75b1d6b5c6b05908b6cd2a..4b87ea1194e3128e6adba331931cc3616f8e10df 100644 (file)
@@ -35,36 +35,83 @@ Required properties:
 
 Timing properties for child nodes. All are optional and default to 0.
 
- - gpmc,sync-clk:      Minimum clock period for synchronous mode, in picoseconds
-
- Chip-select signal timings corresponding to GPMC_CONFIG2:
- - gpmc,cs-on:         Assertion time
- - gpmc,cs-rd-off:     Read deassertion time
- - gpmc,cs-wr-off:     Write deassertion time
-
- ADV signal timings corresponding to GPMC_CONFIG3:
- - gpmc,adv-on:                Assertion time
- - gpmc,adv-rd-off:    Read deassertion time
- - gpmc,adv-wr-off:    Write deassertion time
-
- WE signals timings corresponding to GPMC_CONFIG4:
- - gpmc,we-on:         Assertion time
- - gpmc,we-off:                Deassertion time
-
- OE signals timings corresponding to GPMC_CONFIG4:
- - gpmc,oe-on:         Assertion time
- - gpmc,oe-off:                Deassertion time
-
- Access time and cycle time timings corresponding to GPMC_CONFIG5:
- - gpmc,page-burst-access: Multiple access word delay
- - gpmc,access:                Start-cycle to first data valid delay
- - gpmc,rd-cycle:      Total read cycle time
- - gpmc,wr-cycle:      Total write cycle time
+ - gpmc,sync-clk-ps:   Minimum clock period for synchronous mode, in picoseconds
+
+ Chip-select signal timings (in nanoseconds) corresponding to GPMC_CONFIG2:
+ - gpmc,cs-on-ns:      Assertion time
+ - gpmc,cs-rd-off-ns:  Read deassertion time
+ - gpmc,cs-wr-off-ns:  Write deassertion time
+
+ ADV signal timings (in nanoseconds) corresponding to GPMC_CONFIG3:
+ - gpmc,adv-on-ns:     Assertion time
+ - gpmc,adv-rd-off-ns: Read deassertion time
+ - gpmc,adv-wr-off-ns: Write deassertion time
+
+ WE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
+ - gpmc,we-on-ns       Assertion time
+ - gpmc,we-off-ns:     Deassertion time
+
+ OE signals timings (in nanoseconds) corresponding to GPMC_CONFIG4:
+ - gpmc,oe-on-ns:      Assertion time
+ - gpmc,oe-off-ns:     Deassertion time
+
+ Access time and cycle time timings (in nanoseconds) corresponding to
+ GPMC_CONFIG5:
+ - gpmc,page-burst-access-ns:  Multiple access word delay
+ - gpmc,access-ns:             Start-cycle to first data valid delay
+ - gpmc,rd-cycle-ns:           Total read cycle time
+ - gpmc,wr-cycle-ns:           Total write cycle time
+ - gpmc,bus-turnaround-ns:     Turn-around time between successive accesses
+ - gpmc,cycle2cycle-delay-ns:  Delay between chip-select pulses
+ - gpmc,clk-activation-ns:     GPMC clock activation time
+ - gpmc,wait-monitoring-ns:    Start of wait monitoring with regard to valid
+                               data
+
+Boolean timing parameters. If property is present parameter enabled and
+disabled if omitted:
+ - gpmc,adv-extra-delay:       ADV signal is delayed by half GPMC clock
+ - gpmc,cs-extra-delay:                CS signal is delayed by half GPMC clock
+ - gpmc,cycle2cycle-diffcsen:  Add "cycle2cycle-delay" between successive
+                               accesses to a different CS
+ - gpmc,cycle2cycle-samecsen:  Add "cycle2cycle-delay" between successive
+                               accesses to the same CS
+ - gpmc,oe-extra-delay:                OE signal is delayed by half GPMC clock
+ - gpmc,we-extra-delay:                WE signal is delayed by half GPMC clock
+ - gpmc,time-para-granularity: Multiply all access times by 2
 
 The following are only applicable to OMAP3+ and AM335x:
- - gpmc,wr-access
- - gpmc,wr-data-mux-bus
-
+ - gpmc,wr-access-ns:          In synchronous write mode, for single or
+                               burst accesses, defines the number of
+                               GPMC_FCLK cycles from start access time
+                               to the GPMC_CLK rising edge used by the
+                               memory device for the first data capture.
+ - gpmc,wr-data-mux-bus-ns:    In address-data multiplex mode, specifies
+                               the time when the first data is driven on
+                               the address-data bus.
+
+GPMC chip-select settings properties for child nodes. All are optional.
+
+- gpmc,burst-length    Page/burst length. Must be 4, 8 or 16.
+- gpmc,burst-wrap      Enables wrap bursting
+- gpmc,burst-read      Enables read page/burst mode
+- gpmc,burst-write     Enables write page/burst mode
+- gpmc,device-nand     Device is NAND
+- gpmc,device-width    Total width of device(s) connected to a GPMC
+                       chip-select in bytes. The GPMC supports 8-bit
+                       and 16-bit devices and so this property must be
+                       1 or 2.
+- gpmc,mux-add-data    Address and data multiplexing configuration.
+                       Valid values are 1 for address-address-data
+                       multiplexing mode and 2 for address-data
+                       multiplexing mode.
+- gpmc,sync-read       Enables synchronous read. Defaults to asynchronous
+                       is this is not set.
+- gpmc,sync-write      Enables synchronous writes. Defaults to asynchronous
+                       is this is not set.
+- gpmc,wait-pin                Wait-pin used by client. Must be less than
+                       "gpmc,num-waitpins".
+- gpmc,wait-on-read    Enables wait monitoring on reads.
+- gpmc,wait-on-write   Enables wait monitoring on writes.
 
 Example for an AM33xx board:
 
diff --git a/Documentation/devicetree/bindings/clock/axi-clkgen.txt b/Documentation/devicetree/bindings/clock/axi-clkgen.txt
new file mode 100644 (file)
index 0000000..028b493
--- /dev/null
@@ -0,0 +1,22 @@
+Binding for the axi-clkgen clock generator
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "adi,axi-clkgen".
+- #clock-cells : from common clock binding; Should always be set to 0.
+- reg : Address and length of the axi-clkgen register set.
+- clocks : Phandle and clock specifier for the parent clock.
+
+Optional properties:
+- clock-output-names : From common clock binding.
+
+Example:
+       clock@0xff000000 {
+               compatible = "adi,axi-clkgen";
+               #clock-cells = <0>;
+               reg = <0xff000000 0x1000>;
+               clocks = <&osc 1>;
+       };
diff --git a/Documentation/devicetree/bindings/clock/exynos4-clock.txt b/Documentation/devicetree/bindings/clock/exynos4-clock.txt
new file mode 100644 (file)
index 0000000..ea5e26f
--- /dev/null
@@ -0,0 +1,288 @@
+* Samsung Exynos4 Clock Controller
+
+The Exynos4 clock controller generates and supplies clock to various controllers
+within the Exynos4 SoC. The clock binding described here is applicable to all
+SoC's in the Exynos4 family.
+
+Required Properties:
+
+- comptible: should be one of the following.
+  - "samsung,exynos4210-clock" - controller compatible with Exynos4210 SoC.
+  - "samsung,exynos4412-clock" - controller compatible with Exynos4412 SoC.
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+The following is the list of clocks generated by the controller. Each clock is
+assigned an identifier and client nodes use this identifier to specify the
+clock which they consume. Some of the clocks are available only on a particular
+Exynos4 SoC and this is specified where applicable.
+
+
+                [Core Clocks]
+
+  Clock               ID      SoC (if specific)
+  -----------------------------------------------
+
+  xxti                1
+  xusbxti             2
+  fin_pll             3
+  fout_apll           4
+  fout_mpll           5
+  fout_epll           6
+  fout_vpll           7
+  sclk_apll           8
+  sclk_mpll           9
+  sclk_epll           10
+  sclk_vpll           11
+  arm_clk             12
+  aclk200             13
+  aclk100             14
+  aclk160             15
+  aclk133             16
+  mout_mpll_user_t    17      Exynos4x12
+  mout_mpll_user_c    18      Exynos4x12
+  mout_core           19
+  mout_apll           20
+
+
+            [Clock Gate for Special Clocks]
+
+  Clock               ID      SoC (if specific)
+  -----------------------------------------------
+
+  sclk_fimc0          128
+  sclk_fimc1          129
+  sclk_fimc2          130
+  sclk_fimc3          131
+  sclk_cam0           132
+  sclk_cam1           133
+  sclk_csis0          134
+  sclk_csis1          135
+  sclk_hdmi           136
+  sclk_mixer          137
+  sclk_dac            138
+  sclk_pixel          139
+  sclk_fimd0          140
+  sclk_mdnie0         141     Exynos4412
+  sclk_mdnie_pwm0 12  142     Exynos4412
+  sclk_mipi0          143
+  sclk_audio0         144
+  sclk_mmc0           145
+  sclk_mmc1           146
+  sclk_mmc2           147
+  sclk_mmc3           148
+  sclk_mmc4           149
+  sclk_sata           150     Exynos4210
+  sclk_uart0          151
+  sclk_uart1          152
+  sclk_uart2          153
+  sclk_uart3          154
+  sclk_uart4          155
+  sclk_audio1         156
+  sclk_audio2         157
+  sclk_spdif          158
+  sclk_spi0           159
+  sclk_spi1           160
+  sclk_spi2           161
+  sclk_slimbus        162
+  sclk_fimd1          163     Exynos4210
+  sclk_mipi1          164     Exynos4210
+  sclk_pcm1           165
+  sclk_pcm2           166
+  sclk_i2s1           167
+  sclk_i2s2           168
+  sclk_mipihsi        169     Exynos4412
+  sclk_mfc            170
+  sclk_pcm0           171
+  sclk_g3d            172
+  sclk_pwm_isp        173     Exynos4x12
+  sclk_spi0_isp       174     Exynos4x12
+  sclk_spi1_isp       175     Exynos4x12
+  sclk_uart_isp       176     Exynos4x12
+
+             [Peripheral Clock Gates]
+
+  Clock               ID      SoC (if specific)
+  -----------------------------------------------
+
+  fimc0               256
+  fimc1               257
+  fimc2               258
+  fimc3               259
+  csis0               260
+  csis1               261
+  jpeg                262
+  smmu_fimc0          263
+  smmu_fimc1          264
+  smmu_fimc2          265
+  smmu_fimc3          266
+  smmu_jpeg           267
+  vp                  268
+  mixer               269
+  tvenc               270     Exynos4210
+  hdmi                271
+  smmu_tv             272
+  mfc                 273
+  smmu_mfcl           274
+  smmu_mfcr           275
+  g3d                 276
+  g2d                 277     Exynos4210
+  rotator             278     Exynos4210
+  mdma                279     Exynos4210
+  smmu_g2d            280     Exynos4210
+  smmu_rotator        281     Exynos4210
+  smmu_mdma           282     Exynos4210
+  fimd0               283
+  mie0                284
+  mdnie0              285     Exynos4412
+  dsim0               286
+  smmu_fimd0          287
+  fimd1               288     Exynos4210
+  mie1                289     Exynos4210
+  dsim1               290     Exynos4210
+  smmu_fimd1          291     Exynos4210
+  pdma0               292
+  pdma1               293
+  pcie_phy            294
+  sata_phy            295     Exynos4210
+  tsi                 296
+  sdmmc0              297
+  sdmmc1              298
+  sdmmc2              299
+  sdmmc3              300
+  sdmmc4              301
+  sata                302     Exynos4210
+  sromc               303
+  usb_host            304
+  usb_device          305
+  pcie                306
+  onenand             307
+  nfcon               308
+  smmu_pcie           309
+  gps                 310
+  smmu_gps            311
+  uart0               312
+  uart1               313
+  uart2               314
+  uart3               315
+  uart4               316
+  i2c0                317
+  i2c1                318
+  i2c2                319
+  i2c3                320
+  i2c4                321
+  i2c5                322
+  i2c6                323
+  i2c7                324
+  i2c_hdmi            325
+  tsadc               326
+  spi0                327
+  spi1                328
+  spi2                329
+  i2s1                330
+  i2s2                331
+  pcm0                332
+  i2s0                333
+  pcm1                334
+  pcm2                335
+  pwm                 336
+  slimbus             337
+  spdif               338
+  ac97                339
+  modemif             340
+  chipid              341
+  sysreg              342
+  hdmi_cec            343
+  mct                 344
+  wdt                 345
+  rtc                 346
+  keyif               347
+  audss               348
+  mipi_hsi            349     Exynos4210
+  mdma2               350     Exynos4210
+  pixelasyncm0        351
+  pixelasyncm1        352
+  fimc_lite0          353     Exynos4x12
+  fimc_lite1          354     Exynos4x12
+  ppmuispx            355     Exynos4x12
+  ppmuispmx           356     Exynos4x12
+  fimc_isp            357     Exynos4x12
+  fimc_drc            358     Exynos4x12
+  fimc_fd             359     Exynos4x12
+  mcuisp              360     Exynos4x12
+  gicisp              361     Exynos4x12
+  smmu_isp            362     Exynos4x12
+  smmu_drc            363     Exynos4x12
+  smmu_fd             364     Exynos4x12
+  smmu_lite0          365     Exynos4x12
+  smmu_lite1          366     Exynos4x12
+  mcuctl_isp          367     Exynos4x12
+  mpwm_isp            368     Exynos4x12
+  i2c0_isp            369     Exynos4x12
+  i2c1_isp            370     Exynos4x12
+  mtcadc_isp          371     Exynos4x12
+  pwm_isp             372     Exynos4x12
+  wdt_isp             373     Exynos4x12
+  uart_isp            374     Exynos4x12
+  asyncaxim           375     Exynos4x12
+  smmu_ispcx          376     Exynos4x12
+  spi0_isp            377     Exynos4x12
+  spi1_isp            378     Exynos4x12
+  pwm_isp_sclk        379     Exynos4x12
+  spi0_isp_sclk       380     Exynos4x12
+  spi1_isp_sclk       381     Exynos4x12
+  uart_isp_sclk       382     Exynos4x12
+
+               [Mux Clocks]
+
+  Clock                        ID      SoC (if specific)
+  -----------------------------------------------
+
+  mout_fimc0           384
+  mout_fimc1           385
+  mout_fimc2           386
+  mout_fimc3           387
+  mout_cam0            388
+  mout_cam1            389
+  mout_csis0           390
+  mout_csis1           391
+  mout_g3d0            392
+  mout_g3d1            393
+  mout_g3d             394
+  aclk400_mcuisp       395     Exynos4x12
+
+               [Div Clocks]
+
+  Clock                        ID      SoC (if specific)
+  -----------------------------------------------
+
+  div_isp0             450     Exynos4x12
+  div_isp1             451     Exynos4x12
+  div_mcuisp0          452     Exynos4x12
+  div_mcuisp1          453     Exynos4x12
+  div_aclk200          454     Exynos4x12
+  div_aclk400_mcuisp   455     Exynos4x12
+
+
+Example 1: An example of a clock controller node is listed below.
+
+       clock: clock-controller@0x10030000 {
+               compatible = "samsung,exynos4210-clock";
+               reg = <0x10030000 0x20000>;
+               #clock-cells = <1>;
+       };
+
+Example 2: UART controller node that consumes the clock generated by the clock
+          controller. Refer to the standard clock bindings for information
+          about 'clocks' and 'clock-names' property.
+
+       serial@13820000 {
+               compatible = "samsung,exynos4210-uart";
+               reg = <0x13820000 0x100>;
+               interrupts = <0 54 0>;
+               clocks = <&clock 314>, <&clock 153>;
+               clock-names = "uart", "clk_uart_baud0";
+       };
diff --git a/Documentation/devicetree/bindings/clock/exynos5250-clock.txt b/Documentation/devicetree/bindings/clock/exynos5250-clock.txt
new file mode 100644 (file)
index 0000000..781a627
--- /dev/null
@@ -0,0 +1,177 @@
+* Samsung Exynos5250 Clock Controller
+
+The Exynos5250 clock controller generates and supplies clock to various
+controllers within the Exynos5250 SoC.
+
+Required Properties:
+
+- comptible: should be one of the following.
+  - "samsung,exynos5250-clock" - controller compatible with Exynos5250 SoC.
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+The following is the list of clocks generated by the controller. Each clock is
+assigned an identifier and client nodes use this identifier to specify the
+clock which they consume.
+
+
+       [Core Clocks]
+
+  Clock                        ID
+  ----------------------------
+
+  fin_pll              1
+
+  [Clock Gate for Special Clocks]
+
+  Clock                        ID
+  ----------------------------
+
+  sclk_cam_bayer       128
+  sclk_cam0            129
+  sclk_cam1            130
+  sclk_gscl_wa         131
+  sclk_gscl_wb         132
+  sclk_fimd1           133
+  sclk_mipi1           134
+  sclk_dp              135
+  sclk_hdmi            136
+  sclk_pixel           137
+  sclk_audio0          138
+  sclk_mmc0            139
+  sclk_mmc1            140
+  sclk_mmc2            141
+  sclk_mmc3            142
+  sclk_sata            143
+  sclk_usb3            144
+  sclk_jpeg            145
+  sclk_uart0           146
+  sclk_uart1           147
+  sclk_uart2           148
+  sclk_uart3           149
+  sclk_pwm             150
+  sclk_audio1          151
+  sclk_audio2          152
+  sclk_spdif           153
+  sclk_spi0            154
+  sclk_spi1            155
+  sclk_spi2            156
+
+
+   [Peripheral Clock Gates]
+
+  Clock                        ID
+  ----------------------------
+
+  gscl0                        256
+  gscl1                        257
+  gscl2                        258
+  gscl3                        259
+  gscl_wa              260
+  gscl_wb              261
+  smmu_gscl0           262
+  smmu_gscl1           263
+  smmu_gscl2           264
+  smmu_gscl3           265
+  mfc                  266
+  smmu_mfcl            267
+  smmu_mfcr            268
+  rotator              269
+  jpeg                 270
+  mdma1                        271
+  smmu_rotator         272
+  smmu_jpeg            273
+  smmu_mdma1           274
+  pdma0                        275
+  pdma1                        276
+  sata                 277
+  usbotg               278
+  mipi_hsi             279
+  sdmmc0               280
+  sdmmc1               281
+  sdmmc2               282
+  sdmmc3               283
+  sromc                        284
+  usb2                 285
+  usb3                 286
+  sata_phyctrl         287
+  sata_phyi2c          288
+  uart0                        289
+  uart1                        290
+  uart2                        291
+  uart3                        292
+  uart4                        293
+  i2c0                 294
+  i2c1                 295
+  i2c2                 296
+  i2c3                 297
+  i2c4                 298
+  i2c5                 299
+  i2c6                 300
+  i2c7                 301
+  i2c_hdmi             302
+  adc                  303
+  spi0                 304
+  spi1                 305
+  spi2                 306
+  i2s1                 307
+  i2s2                 308
+  pcm1                 309
+  pcm2                 310
+  pwm                  311
+  spdif                        312
+  ac97                 313
+  hsi2c0               314
+  hsi2c1               315
+  hs12c2               316
+  hs12c3               317
+  chipid               318
+  sysreg               319
+  pmu                  320
+  cmu_top              321
+  cmu_core             322
+  cmu_mem              323
+  tzpc0                        324
+  tzpc1                        325
+  tzpc2                        326
+  tzpc3                        327
+  tzpc4                        328
+  tzpc5                        329
+  tzpc6                        330
+  tzpc7                        331
+  tzpc8                        332
+  tzpc9                        333
+  hdmi_cec             334
+  mct                  335
+  wdt                  336
+  rtc                  337
+  tmu                  338
+  fimd1                        339
+  mie1                 340
+  dsim0                        341
+  dp                   342
+  mixer                        343
+  hdmi                 345
+
+Example 1: An example of a clock controller node is listed below.
+
+       clock: clock-controller@0x10010000 {
+               compatible = "samsung,exynos5250-clock";
+               reg = <0x10010000 0x30000>;
+               #clock-cells = <1>;
+       };
+
+Example 2: UART controller node that consumes the clock generated by the clock
+          controller. Refer to the standard clock bindings for information
+          about 'clocks' and 'clock-names' property.
+
+       serial@13820000 {
+               compatible = "samsung,exynos4210-uart";
+               reg = <0x13820000 0x100>;
+               interrupts = <0 54 0>;
+               clocks = <&clock 314>, <&clock 153>;
+               clock-names = "uart", "clk_uart_baud0";
+       };
diff --git a/Documentation/devicetree/bindings/clock/exynos5440-clock.txt b/Documentation/devicetree/bindings/clock/exynos5440-clock.txt
new file mode 100644 (file)
index 0000000..4499e99
--- /dev/null
@@ -0,0 +1,61 @@
+* Samsung Exynos5440 Clock Controller
+
+The Exynos5440 clock controller generates and supplies clock to various
+controllers within the Exynos5440 SoC.
+
+Required Properties:
+
+- comptible: should be "samsung,exynos5440-clock".
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- #clock-cells: should be 1.
+
+The following is the list of clocks generated by the controller. Each clock is
+assigned an identifier and client nodes use this identifier to specify the
+clock which they consume.
+
+
+       [Core Clocks]
+
+  Clock                        ID
+  ----------------------------
+
+  xtal                 1
+  arm_clk              2
+
+   [Peripheral Clock Gates]
+
+  Clock                        ID
+  ----------------------------
+
+  spi_baud             16
+  pb0_250              17
+  pr0_250              18
+  pr1_250              19
+  b_250                        20
+  b_125                        21
+  b_200                        22
+  sata                 23
+  usb                  24
+  gmac0                        25
+  cs250                        26
+  pb0_250_o            27
+  pr0_250_o            28
+  pr1_250_o            29
+  b_250_o              30
+  b_125_o              31
+  b_200_o              32
+  sata_o               33
+  usb_o                        34
+  gmac0_o              35
+  cs250_o              36
+
+Example: An example of a clock controller node is listed below.
+
+       clock: clock-controller@0x10010000 {
+               compatible = "samsung,exynos5440-clock";
+               reg = <0x160000 0x10000>;
+               #clock-cells = <1>;
+       };
diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra114-car.txt
new file mode 100644 (file)
index 0000000..d6cb083
--- /dev/null
@@ -0,0 +1,303 @@
+NVIDIA Tegra114 Clock And Reset Controller
+
+This binding uses the common clock binding:
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The CAR (Clock And Reset) Controller on Tegra is the HW module responsible
+for muxing and gating Tegra's clocks, and setting their rates.
+
+Required properties :
+- compatible : Should be "nvidia,tegra114-car"
+- reg : Should contain CAR registers location and length
+- clocks : Should contain phandle and clock specifiers for two clocks:
+  the 32 KHz "32k_in", and the board-specific oscillator "osc".
+- #clock-cells : Should be 1.
+  In clock consumers, this cell represents the clock ID exposed by the CAR.
+
+  The first 160 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
+  registers. These IDs often match those in the CAR's RST_DEVICES registers,
+  but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
+  this case, those clocks are assigned IDs above 160 in order to highlight
+  this issue. Implementations that interpret these clock IDs as bit values
+  within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
+  explicitly handle these special cases.
+
+  The balance of the clocks controlled by the CAR are assigned IDs of 160 and
+  above.
+
+  0    unassigned
+  1    unassigned
+  2    unassigned
+  3    unassigned
+  4    rtc
+  5    timer
+  6    uarta
+  7    unassigned      (register bit affects uartb and vfir)
+  8    unassigned
+  9    sdmmc2
+  10   unassigned      (register bit affects spdif_in and spdif_out)
+  11   i2s1
+  12   i2c1
+  13   ndflash
+  14   sdmmc1
+  15   sdmmc4
+  16   unassigned
+  17   pwm
+  18   i2s2
+  19   epp
+  20   unassigned      (register bit affects vi and vi_sensor)
+  21   2d
+  22   usbd
+  23   isp
+  24   3d
+  25   unassigned
+  26   disp2
+  27   disp1
+  28   host1x
+  29   vcp
+  30   i2s0
+  31   unassigned
+
+  32   unassigned
+  33   unassigned
+  34   apbdma
+  35   unassigned
+  36   kbc
+  37   unassigned
+  38   unassigned
+  39   unassigned      (register bit affects fuse and fuse_burn)
+  40   kfuse
+  41   sbc1
+  42   nor
+  43   unassigned
+  44   sbc2
+  45   unassigned
+  46   sbc3
+  47   i2c5
+  48   dsia
+  49   unassigned
+  50   mipi
+  51   hdmi
+  52   csi
+  53   unassigned
+  54   i2c2
+  55   uartc
+  56   mipi-cal
+  57   emc
+  58   usb2
+  59   usb3
+  60   msenc
+  61   vde
+  62   bsea
+  63   bsev
+
+  64   unassigned
+  65   uartd
+  66   unassigned
+  67   i2c3
+  68   sbc4
+  69   sdmmc3
+  70   unassigned
+  71   owr
+  72   afi
+  73   csite
+  74   unassigned
+  75   unassigned
+  76   la
+  77   trace
+  78   soc_therm
+  79   dtv
+  80   ndspeed
+  81   i2cslow
+  82   dsib
+  83   tsec
+  84   unassigned
+  85   unassigned
+  86   unassigned
+  87   unassigned
+  88   unassigned
+  89   xusb_host
+  90   unassigned
+  91   msenc
+  92   csus
+  93   unassigned
+  94   unassigned
+  95   unassigned      (bit affects xusb_dev and xusb_dev_src)
+
+  96   unassigned
+  97   unassigned
+  98   unassigned
+  99   mselect
+  100  tsensor
+  101  i2s3
+  102  i2s4
+  103  i2c4
+  104  sbc5
+  105  sbc6
+  106  d_audio
+  107  apbif
+  108  dam0
+  109  dam1
+  110  dam2
+  111  hda2codec_2x
+  112  unassigned
+  113  audio0_2x
+  114  audio1_2x
+  115  audio2_2x
+  116  audio3_2x
+  117  audio4_2x
+  118  spdif_2x
+  119  actmon
+  120  extern1
+  121  extern2
+  122  extern3
+  123  unassigned
+  124  unassigned
+  125  hda
+  126  unassigned
+  127  se
+
+  128  hda2hdmi
+  129  unassigned
+  130  unassigned
+  131  unassigned
+  132  unassigned
+  133  unassigned
+  134  unassigned
+  135  unassigned
+  136  unassigned
+  137  unassigned
+  138  unassigned
+  139  unassigned
+  140  unassigned
+  141  unassigned
+  142  unassigned
+  143  unassigned      (bit affects xusb_falcon_src, xusb_fs_src,
+                        xusb_host_src and xusb_ss_src)
+  144  cilab
+  145  cilcd
+  146  cile
+  147  dsialp
+  148  dsiblp
+  149  unassigned
+  150  dds
+  151  unassigned
+  152  dp2
+  153  amx
+  154  adx
+  155  unassigned      (bit affects dfll_ref and dfll_soc)
+  156  xusb_ss
+
+  192  uartb
+  193  vfir
+  194  spdif_in
+  195  spdif_out
+  196  vi
+  197  vi_sensor
+  198  fuse
+  199  fuse_burn
+  200  clk_32k
+  201  clk_m
+  202  clk_m_div2
+  203  clk_m_div4
+  204  pll_ref
+  205  pll_c
+  206  pll_c_out1
+  207  pll_c2
+  208  pll_c3
+  209  pll_m
+  210  pll_m_out1
+  211  pll_p
+  212  pll_p_out1
+  213  pll_p_out2
+  214  pll_p_out3
+  215  pll_p_out4
+  216  pll_a
+  217  pll_a_out0
+  218  pll_d
+  219  pll_d_out0
+  220  pll_d2
+  221  pll_d2_out0
+  222  pll_u
+  223  pll_u_480M
+  224  pll_u_60M
+  225  pll_u_48M
+  226  pll_u_12M
+  227  pll_x
+  228  pll_x_out0
+  229  pll_re_vco
+  230  pll_re_out
+  231  pll_e_out0
+  232  spdif_in_sync
+  233  i2s0_sync
+  234  i2s1_sync
+  235  i2s2_sync
+  236  i2s3_sync
+  237  i2s4_sync
+  238  vimclk_sync
+  239  audio0
+  240  audio1
+  241  audio2
+  242  audio3
+  243  audio4
+  244  spdif
+  245  clk_out_1
+  246  clk_out_2
+  247  clk_out_3
+  248  blink
+  252  xusb_host_src
+  253  xusb_falcon_src
+  254  xusb_fs_src
+  255  xusb_ss_src
+  256  xusb_dev_src
+  257  xusb_dev
+  258  xusb_hs_src
+  259  sclk
+  260  hclk
+  261  pclk
+  262  cclk_g
+  263  cclk_lp
+  264  dfll_ref
+  265  dfll_soc
+
+Example SoC include file:
+
+/ {
+       tegra_car: clock {
+               compatible = "nvidia,tegra114-car";
+               reg = <0x60006000 0x1000>;
+               #clock-cells = <1>;
+       };
+
+       usb@c5004000 {
+               clocks = <&tegra_car 58>; /* usb2 */
+       };
+};
+
+Example board file:
+
+/ {
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               osc: clock@0 {
+                       compatible = "fixed-clock";
+                       reg = <0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <12000000>;
+               };
+
+               clk_32k: clock@1 {
+                       compatible = "fixed-clock";
+                       reg = <1>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+
+       &tegra_car {
+               clocks = <&clk_32k> <&osc>;
+       };
+};
index 0921fac735289ca3e171d918567a2c58163f0f66..e885680f6b4524116d27331f1c44904c9c082e85 100644 (file)
@@ -120,8 +120,8 @@ Required properties :
   90   clk_d
   91   unassigned
   92   sus
-  93   cdev1
-  94   cdev2
+  93   cdev2
+  94   cdev1
   95   unassigned
 
   96   uart2
diff --git a/Documentation/devicetree/bindings/clock/sunxi.txt b/Documentation/devicetree/bindings/clock/sunxi.txt
new file mode 100644 (file)
index 0000000..20b8479
--- /dev/null
@@ -0,0 +1,44 @@
+Device Tree Clock bindings for arch-sunxi
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be one of the following:
+       "allwinner,sun4i-osc-clk" - for a gatable oscillator
+       "allwinner,sun4i-pll1-clk" - for the main PLL clock
+       "allwinner,sun4i-cpu-clk" - for the CPU multiplexer clock
+       "allwinner,sun4i-axi-clk" - for the AXI clock
+       "allwinner,sun4i-ahb-clk" - for the AHB clock
+       "allwinner,sun4i-apb0-clk" - for the APB0 clock
+       "allwinner,sun4i-apb1-clk" - for the APB1 clock
+       "allwinner,sun4i-apb1-mux-clk" - for the APB1 clock muxing
+
+Required properties for all clocks:
+- reg : shall be the control register address for the clock.
+- clocks : shall be the input parent clock(s) phandle for the clock
+- #clock-cells : from common clock binding; shall be set to 0.
+
+For example:
+
+osc24M: osc24M@01c20050 {
+       #clock-cells = <0>;
+       compatible = "allwinner,sun4i-osc-clk";
+       reg = <0x01c20050 0x4>;
+       clocks = <&osc24M_fixed>;
+};
+
+pll1: pll1@01c20000 {
+       #clock-cells = <0>;
+       compatible = "allwinner,sun4i-pll1-clk";
+       reg = <0x01c20000 0x4>;
+       clocks = <&osc24M>;
+};
+
+cpu: cpu@01c20054 {
+       #clock-cells = <0>;
+       compatible = "allwinner,sun4i-cpu-clk";
+       reg = <0x01c20054 0x4>;
+       clocks = <&osc32k>, <&osc24M>, <&pll1>;
+};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-vt8500.txt b/Documentation/devicetree/bindings/gpio/gpio-vt8500.txt
deleted file mode 100644 (file)
index f4dc523..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-VIA/Wondermedia VT8500 GPIO Controller
------------------------------------------------------
-
-Required properties:
-- compatible : "via,vt8500-gpio", "wm,wm8505-gpio"
-       or "wm,wm8650-gpio" depending on your SoC
-- reg : Should contain 1 register range (address and length)
-- #gpio-cells : should be <3>.
-       1) bank
-       2) pin number
-       3) flags - should be 0
-
-Example:
-
-       gpio: gpio-controller@d8110000 {
-               compatible = "via,vt8500-gpio";
-               gpio-controller;
-               reg = <0xd8110000 0x10000>;
-               #gpio-cells = <3>;
-       };
-
-       vibrate {
-               gpios = <&gpio 0 1 0>; /* Bank 0, Pin 1, No flags */
-       };
diff --git a/Documentation/devicetree/bindings/interrupt-controller/samsung,s3c24xx-irq.txt b/Documentation/devicetree/bindings/interrupt-controller/samsung,s3c24xx-irq.txt
new file mode 100644 (file)
index 0000000..c54c5a9
--- /dev/null
@@ -0,0 +1,53 @@
+Samsung S3C24XX Interrupt Controllers
+
+The S3C24XX SoCs contain a custom set of interrupt controllers providing a
+varying number of interrupt sources. The set consists of a main- and sub-
+controller and on newer SoCs even a second main controller.
+
+Required properties:
+- compatible: Compatible property value should be "samsung,s3c2410-irq"
+  for machines before s3c2416 and "samsung,s3c2416-irq" for s3c2416 and later.
+
+- reg: Physical base address of the controller and length of memory mapped
+  region.
+
+- interrupt-controller : Identifies the node as an interrupt controller
+
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The value shall be 4 and interrupt descriptor shall
+  have the following format:
+      <ctrl_num parent_irq ctrl_irq type>
+
+  ctrl_num contains the controller to use:
+      - 0 ... main controller
+      - 1 ... sub controller
+      - 2 ... second main controller on s3c2416 and s3c2450
+  parent_irq contains the parent bit in the main controller and will be
+             ignored in main controllers
+  ctrl_irq contains the interrupt bit of the controller
+  type contains the trigger type to use
+
+Example:
+
+       interrupt-controller@4a000000 {
+               compatible = "samsung,s3c2410-irq";
+               reg = <0x4a000000 0x100>;
+               interrupt-controller;
+               #interrupt-cells=<4>;
+       };
+
+       [...]
+
+       serial@50000000 {
+               compatible = "samsung,s3c2410-uart";
+               reg = <0x50000000 0x4000>;
+               interrupt-parent = <&subintc>;
+               interrupts = <1 28 0 4>, <1 28 1 4>;
+       };
+
+       rtc@57000000 {
+               compatible = "samsung,s3c2410-rtc";
+               reg = <0x57000000 0x100>;
+               interrupt-parent = <&intc>;
+               interrupts = <0 30 0 3>, <0 8 0 3>;
+       };
index 67ec3d4ccc7f5e3ee2b6e2d670a2932936d2ab14..bf0182d8da257d392ce315a6d2b1b749cb740a51 100644 (file)
@@ -21,3 +21,24 @@ Required properties:
 
   - samsung,mfc-l : Base address of the second memory bank used by MFC
                    for DMA contiguous memory allocation and its size.
+
+Optional properties:
+  - samsung,power-domain : power-domain property defined with a phandle
+                          to respective power domain.
+
+Example:
+SoC specific DT entry:
+
+mfc: codec@13400000 {
+       compatible = "samsung,mfc-v5";
+       reg = <0x13400000 0x10000>;
+       interrupts = <0 94 0>;
+       samsung,power-domain = <&pd_mfc>;
+};
+
+Board specific DT entry:
+
+codec@13400000 {
+       samsung,mfc-r = <0x43000000 0x800000>;
+       samsung,mfc-l = <0x51000000 0x800000>;
+};
index 13b707b7355c005e9c877e860c93d4e9ca6baf12..c3a14e0ad0addf57715902618482a5593344f8da 100644 (file)
@@ -13,9 +13,6 @@ Required parent device properties:
                                   4 = active high level-sensitive
                                   8 = active low level-sensitive
 
-Optional parent device properties:
-- reg                    : contains the PRCMU mailbox address for the AB8500 i2c port
-
 The AB8500 consists of a large and varied group of sub-devices:
 
 Device                     IRQ Names              Supply Names   Description
@@ -86,9 +83,8 @@ Non-standard child device properties:
    - stericsson,amic2-bias-vamic1           : Analoge Mic wishes to use a non-standard Vamic
    - stericsson,earpeice-cmv                : Earpeice voltage (only: 950 | 1100 | 1270 | 1580)
 
-ab8500@5 {
+ab8500 {
          compatible = "stericsson,ab8500";
-         reg = <5>; /* mailbox 5 is i2c */
          interrupts = <0 40 0x4>;
          interrupt-controller;
          #interrupt-cells = <2>;
diff --git a/Documentation/devicetree/bindings/mtd/gpmc-nor.txt b/Documentation/devicetree/bindings/mtd/gpmc-nor.txt
new file mode 100644 (file)
index 0000000..420b3ab
--- /dev/null
@@ -0,0 +1,98 @@
+Device tree bindings for NOR flash connect to TI GPMC
+
+NOR flash connected to the TI GPMC (found on OMAP boards) are represented as
+child nodes of the GPMC controller with a name of "nor".
+
+All timing relevant properties as well as generic GPMC child properties are
+explained in a separate documents. Please refer to
+Documentation/devicetree/bindings/bus/ti-gpmc.txt
+
+Required properties:
+- bank-width:          Width of NOR flash in bytes. GPMC supports 8-bit and
+                       16-bit devices and so must be either 1 or 2 bytes.
+- compatible:          Documentation/devicetree/bindings/mtd/mtd-physmap.txt
+- gpmc,cs-on-ns:               Chip-select assertion time
+- gpmc,cs-rd-off-ns:   Chip-select de-assertion time for reads
+- gpmc,cs-wr-off-ns:   Chip-select de-assertion time for writes
+- gpmc,oe-on-ns:       Output-enable assertion time
+- gpmc,oe-off-ns:      Output-enable de-assertion time
+- gpmc,we-on-ns                Write-enable assertion time
+- gpmc,we-off-ns:      Write-enable de-assertion time
+- gpmc,access-ns:      Start cycle to first data capture (read access)
+- gpmc,rd-cycle-ns:    Total read cycle time
+- gpmc,wr-cycle-ns:    Total write cycle time
+- linux,mtd-name:      Documentation/devicetree/bindings/mtd/mtd-physmap.txt
+- reg:                 Chip-select, base address (relative to chip-select)
+                       and size of NOR flash. Note that base address will be
+                       typically 0 as this is the start of the chip-select.
+
+Optional properties:
+- gpmc,XXX             Additional GPMC timings and settings parameters. See
+                       Documentation/devicetree/bindings/bus/ti-gpmc.txt
+
+Optional properties for partiton table parsing:
+- #address-cells: should be set to 1
+- #size-cells: should be set to 1
+
+Example:
+
+gpmc: gpmc@6e000000 {
+       compatible = "ti,omap3430-gpmc", "simple-bus";
+       ti,hwmods = "gpmc";
+       reg = <0x6e000000 0x1000>;
+       interrupts = <20>;
+       gpmc,num-cs = <8>;
+       gpmc,num-waitpins = <4>;
+       #address-cells = <2>;
+       #size-cells = <1>;
+
+       ranges = <0 0 0x10000000 0x08000000>;
+
+       nor@0,0 {
+               compatible = "cfi-flash";
+               linux,mtd-name= "intel,pf48f6000m0y1be";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               reg = <0 0 0x08000000>;
+               bank-width = <2>;
+
+               gpmc,mux-add-data;
+               gpmc,cs-on-ns = <0>;
+               gpmc,cs-rd-off-ns = <186>;
+               gpmc,cs-wr-off-ns = <186>;
+               gpmc,adv-on-ns = <12>;
+               gpmc,adv-rd-off-ns = <48>;
+               gpmc,adv-wr-off-ns = <48>;
+               gpmc,oe-on-ns = <54>;
+               gpmc,oe-off-ns = <168>;
+               gpmc,we-on-ns = <54>;
+               gpmc,we-off-ns = <168>;
+               gpmc,rd-cycle-ns = <186>;
+               gpmc,wr-cycle-ns = <186>;
+               gpmc,access-ns = <114>;
+               gpmc,page-burst-access-ns = <6>;
+               gpmc,bus-turnaround-ns = <12>;
+               gpmc,cycle2cycle-delay-ns = <18>;
+               gpmc,wr-data-mux-bus-ns = <90>;
+               gpmc,wr-access-ns = <186>;
+               gpmc,cycle2cycle-samecsen;
+               gpmc,cycle2cycle-diffcsen;
+
+               partition@0 {
+                       label = "bootloader-nor";
+                       reg = <0 0x40000>;
+               };
+               partition@0x40000 {
+                       label = "params-nor";
+                       reg = <0x40000 0x40000>;
+               };
+               partition@0x80000 {
+                       label = "kernel-nor";
+                       reg = <0x80000 0x200000>;
+               };
+               partition@0x280000 {
+                       label = "filesystem-nor";
+                       reg = <0x240000 0x7d80000>;
+               };
+       };
+};
index deec9da224a2aec46c09a878202599e82d1fbece..b7529424ac88e0a6304aea730ff364be78ec84dd 100644 (file)
@@ -10,6 +10,8 @@ Documentation/devicetree/bindings/bus/ti-gpmc.txt
 Required properties:
 
  - reg:                        The CS line the peripheral is connected to
+ - gpmc,device-width   Width of the ONENAND device connected to the GPMC
+                       in bytes. Must be 1 or 2.
 
 Optional properties:
 
@@ -34,6 +36,7 @@ Example for an OMAP3430 board:
 
                onenand@0 {
                        reg = <0 0 0>; /* CS0, offset 0 */
+                       gpmc,device-width = <2>;
 
                        #address-cells = <1>;
                        #size-cells = <1>;
diff --git a/Documentation/devicetree/bindings/net/gpmc-eth.txt b/Documentation/devicetree/bindings/net/gpmc-eth.txt
new file mode 100644 (file)
index 0000000..24cb4e4
--- /dev/null
@@ -0,0 +1,97 @@
+Device tree bindings for Ethernet chip connected to TI GPMC
+
+Besides being used to interface with external memory devices, the
+General-Purpose Memory Controller can be used to connect Pseudo-SRAM devices
+such as ethernet controllers to processors using the TI GPMC as a data bus.
+
+Ethernet controllers connected to TI GPMC are represented as child nodes of
+the GPMC controller with an "ethernet" name.
+
+All timing relevant properties as well as generic GPMC child properties are
+explained in a separate documents. Please refer to
+Documentation/devicetree/bindings/bus/ti-gpmc.txt
+
+For the properties relevant to the ethernet controller connected to the GPMC
+refer to the binding documentation of the device. For example, the documentation
+for the SMSC 911x is Documentation/devicetree/bindings/net/smsc911x.txt
+
+Child nodes need to specify the GPMC bus address width using the "bank-width"
+property but is possible that an ethernet controller also has a property to
+specify the I/O registers address width. Even when the GPMC has a maximum 16-bit
+address width, it supports devices with 32-bit word registers.
+For example with an SMSC LAN911x/912x controller connected to the TI GPMC on an
+OMAP2+ board, "bank-width = <2>;" and "reg-io-width = <4>;".
+
+Required properties:
+- bank-width:          Address width of the device in bytes. GPMC supports 8-bit
+                       and 16-bit devices and so must be either 1 or 2 bytes.
+- compatible:          Compatible string property for the ethernet child device.
+- gpmc,cs-on:          Chip-select assertion time
+- gpmc,cs-rd-off:      Chip-select de-assertion time for reads
+- gpmc,cs-wr-off:      Chip-select de-assertion time for writes
+- gpmc,oe-on:          Output-enable assertion time
+- gpmc,oe-off          Output-enable de-assertion time
+- gpmc,we-on:          Write-enable assertion time
+- gpmc,we-off:         Write-enable de-assertion time
+- gpmc,access:         Start cycle to first data capture (read access)
+- gpmc,rd-cycle:       Total read cycle time
+- gpmc,wr-cycle:       Total write cycle time
+- reg:                 Chip-select, base address (relative to chip-select)
+                       and size of the memory mapped for the device.
+                       Note that base address will be typically 0 as this
+                       is the start of the chip-select.
+
+Optional properties:
+- gpmc,XXX             Additional GPMC timings and settings parameters. See
+                       Documentation/devicetree/bindings/bus/ti-gpmc.txt
+
+Example:
+
+gpmc: gpmc@6e000000 {
+       compatible = "ti,omap3430-gpmc";
+       ti,hwmods = "gpmc";
+       reg = <0x6e000000 0x1000>;
+       interrupts = <20>;
+       gpmc,num-cs = <8>;
+       gpmc,num-waitpins = <4>;
+       #address-cells = <2>;
+       #size-cells = <1>;
+
+       ranges = <5 0 0x2c000000 0x1000000>;
+
+       ethernet@5,0 {
+               compatible = "smsc,lan9221", "smsc,lan9115";
+               reg = <5 0 0xff>;
+               bank-width = <2>;
+
+               gpmc,mux-add-data;
+               gpmc,cs-on = <0>;
+               gpmc,cs-rd-off = <186>;
+               gpmc,cs-wr-off = <186>;
+               gpmc,adv-on = <12>;
+               gpmc,adv-rd-off = <48>;
+               gpmc,adv-wr-off = <48>;
+               gpmc,oe-on = <54>;
+               gpmc,oe-off = <168>;
+               gpmc,we-on = <54>;
+               gpmc,we-off = <168>;
+               gpmc,rd-cycle = <186>;
+               gpmc,wr-cycle = <186>;
+               gpmc,access = <114>;
+               gpmc,page-burst-access = <6>;
+               gpmc,bus-turnaround = <12>;
+               gpmc,cycle2cycle-delay = <18>;
+               gpmc,wr-data-mux-bus = <90>;
+               gpmc,wr-access = <186>;
+               gpmc,cycle2cycle-samecsen;
+               gpmc,cycle2cycle-diffcsen;
+
+               interrupt-parent = <&gpio6>;
+               interrupts = <16>;
+               vmmc-supply = <&vddvario>;
+               vmmc_aux-supply = <&vdd33a>;
+               reg-io-width = <4>;
+
+               smsc,save-mac-address;
+       };
+};
diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-vt8500.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-vt8500.txt
new file mode 100644 (file)
index 0000000..b3aa90f
--- /dev/null
@@ -0,0 +1,57 @@
+VIA VT8500 and Wondermedia WM8xxx-series pinmux/gpio controller
+
+These SoCs contain a combined Pinmux/GPIO module. Each pin may operate as
+either a GPIO in, GPIO out or as an alternate function (I2C, SPI etc).
+
+Required properties:
+- compatible: "via,vt8500-pinctrl", "wm,wm8505-pinctrl", "wm,wm8650-pinctrl",
+       "wm8750-pinctrl" or "wm,wm8850-pinctrl"
+- reg: Should contain the physical address of the module's registers.
+- interrupt-controller: Marks the device node as an interrupt controller.
+- #interrupt-cells: Should be two.
+- gpio-controller: Marks the device node as a GPIO controller.
+- #gpio-cells : Should be two. The first cell is the pin number and the
+  second cell is used to specify optional parameters.
+       bit 0 - active low
+
+Please refer to ../gpio/gpio.txt for a general description of GPIO bindings.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+Each pin configuration node lists the pin(s) to which it applies, and one or
+more of the mux functions to select on those pin(s), and pull-up/down
+configuration. Each subnode only affects those parameters that are explicitly
+listed. In other words, a subnode that lists only a mux function implies no
+information about any pull configuration. Similarly, a subnode that lists only
+a pull parameter implies no information about the mux function.
+
+Required subnode-properties:
+- wm,pins: An array of cells. Each cell contains the ID of a pin.
+
+Optional subnode-properties:
+- wm,function: Integer, containing the function to mux to the pin(s):
+  0: GPIO in
+  1: GPIO out
+  2: alternate
+
+- wm,pull: Integer, representing the pull-down/up to apply to the pin(s):
+  0: none
+  1: down
+  2: up
+
+Each of wm,function and wm,pull may contain either a single value which
+will be applied to all pins in wm,pins, or one value for each entry in
+wm,pins.
+
+Example:
+
+       pinctrl: pinctrl {
+               compatible = "wm,wm8505-pinctrl";
+               reg = <0xD8110000 0x10000>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
diff --git a/Documentation/devicetree/bindings/reset/reset.txt b/Documentation/devicetree/bindings/reset/reset.txt
new file mode 100644 (file)
index 0000000..31db6ff
--- /dev/null
@@ -0,0 +1,75 @@
+= Reset Signal Device Tree Bindings =
+
+This binding is intended to represent the hardware reset signals present
+internally in most IC (SoC, FPGA, ...) designs. Reset signals for whole
+standalone chips are most likely better represented as GPIOs, although there
+are likely to be exceptions to this rule.
+
+Hardware blocks typically receive a reset signal. This signal is generated by
+a reset provider (e.g. power management or clock module) and received by a
+reset consumer (the module being reset, or a module managing when a sub-
+ordinate module is reset). This binding exists to represent the provider and
+consumer, and provide a way to couple the two together.
+
+A reset signal is represented by the phandle of the provider, plus a reset
+specifier - a list of DT cells that represents the reset signal within the
+provider. The length (number of cells) and semantics of the reset specifier
+are dictated by the binding of the reset provider, although common schemes
+are described below.
+
+A word on where to place reset signal consumers in device tree: It is possible
+in hardware for a reset signal to affect multiple logically separate HW blocks
+at once. In this case, it would be unwise to represent this reset signal in
+the DT node of each affected HW block, since if activated, an unrelated block
+may be reset. Instead, reset signals should be represented in the DT node
+where it makes most sense to control it; this may be a bus node if all
+children of the bus are affected by the reset signal, or an individual HW
+block node for dedicated reset signals. The intent of this binding is to give
+appropriate software access to the reset signals in order to manage the HW,
+rather than to slavishly enumerate the reset signal that affects each HW
+block.
+
+= Reset providers =
+
+Required properties:
+#reset-cells:  Number of cells in a reset specifier; Typically 0 for nodes
+               with a single reset output and 1 for nodes with multiple
+               reset outputs.
+
+For example:
+
+       rst: reset-controller {
+               #reset-cells = <1>;
+       };
+
+= Reset consumers =
+
+Required properties:
+resets:                List of phandle and reset specifier pairs, one pair
+               for each reset signal that affects the device, or that the
+               device manages. Note: if the reset provider specifies '0' for
+               #reset-cells, then only the phandle portion of the pair will
+               appear.
+
+Optional properties:
+reset-names:   List of reset signal name strings sorted in the same order as
+               the resets property. Consumers drivers will use reset-names to
+               match reset signal names with reset specifiers.
+
+For example:
+
+       device {
+               resets = <&rst 20>;
+               reset-names = "reset";
+       };
+
+This represents a device with a single reset signal named "reset".
+
+       bus {
+               resets = <&rst 10> <&rst 11> <&rst 12> <&rst 11>;
+               reset-names = "i2s1", "i2s2", "dma", "mixer";
+       };
+
+This represents a bus that controls the reset signal of each of four sub-
+ordinate devices. Consider for example a bus that fails to operate unless no
+child device has reset asserted.
diff --git a/Documentation/devicetree/bindings/timer/cadence,ttc-timer.txt b/Documentation/devicetree/bindings/timer/cadence,ttc-timer.txt
new file mode 100644 (file)
index 0000000..993695c
--- /dev/null
@@ -0,0 +1,17 @@
+Cadence TTC - Triple Timer Counter
+
+Required properties:
+- compatible : Should be "cdns,ttc".
+- reg : Specifies base physical address and size of the registers.
+- interrupts : A list of 3 interrupts; one per timer channel.
+- clocks: phandle to the source clock
+
+Example:
+
+ttc0: ttc0@f8001000 {
+       interrupt-parent = <&intc>;
+       interrupts = < 0 10 4 0 11 4 0 12 4 >;
+       compatible = "cdns,ttc";
+       reg = <0xF8001000 0x1000>;
+       clocks = <&cpu_clk 3>;
+};
diff --git a/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt b/Documentation/devicetree/bindings/timer/samsung,exynos4210-mct.txt
new file mode 100644 (file)
index 0000000..cb47bfb
--- /dev/null
@@ -0,0 +1,68 @@
+Samsung's Multi Core Timer (MCT)
+
+The Samsung's Multi Core Timer (MCT) module includes two main blocks, the
+global timer and CPU local timers. The global timer is a 64-bit free running
+up-counter and can generate 4 interrupts when the counter reaches one of the
+four preset counter values. The CPU local timers are 32-bit free running
+down-counters and generate an interrupt when the counter expires. There is
+one CPU local timer instantiated in MCT for every CPU in the system.
+
+Required properties:
+
+- compatible: should be "samsung,exynos4210-mct".
+  (a) "samsung,exynos4210-mct", for mct compatible with Exynos4210 mct.
+  (b) "samsung,exynos4412-mct", for mct compatible with Exynos4412 mct.
+
+- reg: base address of the mct controller and length of the address space
+  it occupies.
+
+- interrupts: the list of interrupts generated by the controller. The following
+  should be the order of the interrupts specified. The local timer interrupts
+  should be specified after the four global timer interrupts have been
+  specified.
+
+       0: Global Timer Interrupt 0
+       1: Global Timer Interrupt 1
+       2: Global Timer Interrupt 2
+       3: Global Timer Interrupt 3
+       4: Local Timer Interrupt 0
+       5: Local Timer Interrupt 1
+       6: ..
+       7: ..
+       i: Local Timer Interrupt n
+
+Example 1: In this example, the system uses only the first global timer
+          interrupt generated by MCT and the remaining three global timer
+          interrupts are unused. Two local timer interrupts have been
+          specified.
+
+       mct@10050000 {
+               compatible = "samsung,exynos4210-mct";
+               reg = <0x10050000 0x800>;
+               interrupts = <0 57 0>, <0 0 0>, <0 0 0>, <0 0 0>,
+                            <0 42 0>, <0 48 0>;
+       };
+
+Example 2: In this example, the MCT global and local timer interrupts are
+          connected to two seperate interrupt controllers. Hence, an
+          interrupt-map is created to map the interrupts to the respective
+          interrupt controllers.
+
+       mct@101C0000 {
+               compatible = "samsung,exynos4210-mct";
+               reg = <0x101C0000 0x800>;
+               interrupt-controller;
+               #interrups-cells = <2>;
+               interrupt-parent = <&mct_map>;
+               interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
+                            <4 0>, <5 0>;
+
+               mct_map: mct-map {
+                       #interrupt-cells = <2>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-map = <0x0 0 &combiner 23 3>,
+                                       <0x4 0 &gic 0 120 0>,
+                                       <0x5 0 &gic 0 121 0>;
+               };
+       };
index 1e1145ca4f3c2cb192f7e4bf5ce95f6c73ba0801..8f01cb190f25686747873ab54eaa53652c9b35bc 100644 (file)
@@ -11,6 +11,9 @@ Required properties:
        - "nvidia,tegra20-uart"
        - "nxp,lpc3220-uart"
        - "ibm,qpace-nwp-serial"
+       - "altr,16550-FIFO32"
+       - "altr,16550-FIFO64"
+       - "altr,16550-FIFO128"
        - "serial" if the port type is unknown.
 - reg : offset and length of the register set for the device.
 - interrupts : should contain uart interrupt.
diff --git a/Documentation/devicetree/bindings/usb/exynos-usb.txt b/Documentation/devicetree/bindings/usb/exynos-usb.txt
new file mode 100644 (file)
index 0000000..f66fcdd
--- /dev/null
@@ -0,0 +1,40 @@
+Samsung Exynos SoC USB controller
+
+The USB devices interface with USB controllers on Exynos SOCs.
+The device node has following properties.
+
+EHCI
+Required properties:
+ - compatible: should be "samsung,exynos4210-ehci" for USB 2.0
+   EHCI controller in host mode.
+ - reg: physical base address of the controller and length of memory mapped
+   region.
+ - interrupts: interrupt number to the cpu.
+
+Optional properties:
+ - samsung,vbus-gpio:  if present, specifies the GPIO that
+   needs to be pulled up for the bus to be powered.
+
+Example:
+
+       usb@12110000 {
+               compatible = "samsung,exynos4210-ehci";
+               reg = <0x12110000 0x100>;
+               interrupts = <0 71 0>;
+               samsung,vbus-gpio = <&gpx2 6 1 3 3>;
+       };
+
+OHCI
+Required properties:
+ - compatible: should be "samsung,exynos4210-ohci" for USB 2.0
+   OHCI companion controller in host mode.
+ - reg: physical base address of the controller and length of memory mapped
+   region.
+ - interrupts: interrupt number to the cpu.
+
+Example:
+       usb@12120000 {
+               compatible = "samsung,exynos4210-ohci";
+               reg = <0x12120000 0x100>;
+               interrupts = <0 71 0>;
+       };
index c91a1d15fa28ae62aca3796ab89e15de3fdd0f5a..69af1c7db6b7437ca797c61baaeb74086d264c5c 100644 (file)
@@ -23,7 +23,7 @@ Supported chips:
     Datasheet: Publicly available at the Maxim website
                http://www.maxim-ic.com/
   * Microchip (TelCom) TCN75
-    Prefix: 'lm75'
+    Prefix: 'tcn75'
     Addresses scanned: none
     Datasheet: Publicly available at the Microchip website
                http://www.microchip.com/
index 30fe4bb9a069b13f5979b7debd8a5ec0c0302eab..0d6018c316c741f9cc0cf3b0391457b880b58234 100644 (file)
@@ -5,7 +5,7 @@ Supported adapters:
     Documentation:
        http://www.diolan.com/i2c/u2c12.html
 
-Author: Guenter Roeck <guenter.roeck@ericsson.com>
+Author: Guenter Roeck <linux@roeck-us.net>
 
 Description
 -----------
index 3262b6e4d686ac944f7e767642228f4d4cc2f8f6..e544c7ff8cfa5c6c60697aae738eb4b029e86d23 100644 (file)
@@ -3,10 +3,26 @@ ALPS Touchpad Protocol
 
 Introduction
 ------------
-
-Currently the ALPS touchpad driver supports four protocol versions in use by
-ALPS touchpads, called versions 1, 2, 3, and 4. Information about the various
-protocol versions is contained in the following sections.
+Currently the ALPS touchpad driver supports five protocol versions in use by
+ALPS touchpads, called versions 1, 2, 3, 4 and 5.
+
+Since roughly mid-2010 several new ALPS touchpads have been released and
+integrated into a variety of laptops and netbooks.  These new touchpads
+have enough behavior differences that the alps_model_data definition
+table, describing the properties of the different versions, is no longer
+adequate.  The design choices were to re-define the alps_model_data
+table, with the risk of regression testing existing devices, or isolate
+the new devices outside of the alps_model_data table.  The latter design
+choice was made.  The new touchpad signatures are named: "Rushmore",
+"Pinnacle", and "Dolphin", which you will see in the alps.c code.
+For the purposes of this document, this group of ALPS touchpads will
+generically be called "new ALPS touchpads".
+
+We experimented with probing the ACPI interface _HID (Hardware ID)/_CID
+(Compatibility ID) definition as a way to uniquely identify the
+different ALPS variants but there did not appear to be a 1:1 mapping.
+In fact, it appeared to be an m:n mapping between the _HID and actual
+hardware type.
 
 Detection
 ---------
@@ -20,9 +36,13 @@ If the E6 report is successful, the touchpad model is identified using the "E7
 report" sequence: E8-E7-E7-E7-E9. The response is the model signature and is
 matched against known models in the alps_model_data_array.
 
-With protocol versions 3 and 4, the E7 report model signature is always
-73-02-64. To differentiate between these versions, the response from the
-"Enter Command Mode" sequence must be inspected as described below.
+For older touchpads supporting protocol versions 3 and 4, the E7 report
+model signature is always 73-02-64. To differentiate between these
+versions, the response from the "Enter Command Mode" sequence must be
+inspected as described below.
+
+The new ALPS touchpads have an E7 signature of 73-03-50 or 73-03-0A but
+seem to be better differentiated by the EC Command Mode response.
 
 Command Mode
 ------------
@@ -47,6 +67,14 @@ address of the register being read, and the third contains the value of the
 register. Registers are written by writing the value one nibble at a time
 using the same encoding used for addresses.
 
+For the new ALPS touchpads, the EC command is used to enter command
+mode. The response in the new ALPS touchpads is significantly different,
+and more important in determining the behavior.  This code has been
+separated from the original alps_model_data table and put in the
+alps_identify function.  For example, there seem to be two hardware init
+sequences for the "Dolphin" touchpads as determined by the second byte
+of the EC response.
+
 Packet Format
 -------------
 
@@ -187,3 +215,28 @@ There are several things worth noting here.
     well.
 
 So far no v4 devices with tracksticks have been encountered.
+
+ALPS Absolute Mode - Protocol Version 5
+---------------------------------------
+This is basically Protocol Version 3 but with different logic for packet
+decode.  It uses the same alps_process_touchpad_packet_v3 call with a
+specialized decode_fields function pointer to correctly interpret the
+packets.  This appears to only be used by the Dolphin devices.
+
+For single-touch, the 6-byte packet format is:
+
+ byte 0:    1    1    0    0    1    0    0    0
+ byte 1:    0   x6   x5   x4   x3   x2   x1   x0
+ byte 2:    0   y6   y5   y4   y3   y2   y1   y0
+ byte 3:    0    M    R    L    1    m    r    l
+ byte 4:   y10  y9   y8   y7  x10   x9   x8   x7
+ byte 5:    0   z6   z5   z4   z3   z2   z1   z0
+
+For mt, the format is:
+
+ byte 0:    1    1    1    n3   1   n2   n1   x24
+ byte 1:    1   y7   y6    y5  y4   y3   y2    y1
+ byte 2:    ?   x2   x1   y12 y11  y10   y9    y8
+ byte 3:    0  x23  x22   x21 x20  x19  x18   x17
+ byte 4:    0   x9   x8    x7  x6   x5   x4    x3
+ byte 5:    0  x16  x15   x14 x13  x12  x11   x10
index f2a2488f1bf33d8290384c4823fccee2b39afe36..9573d0c48c6ea882099edd94ed2dcda94e4fe3dd 100644 (file)
@@ -15,6 +15,13 @@ amemthresh - INTEGER
         enabled and the variable is automatically set to 2, otherwise
         the strategy is disabled and the variable is  set  to 1.
 
+backup_only - BOOLEAN
+       0 - disabled (default)
+       not 0 - enabled
+
+       If set, disable the director function while the server is
+       in backup mode to avoid packet loops for DR/TUN methods.
+
 conntrack - BOOLEAN
        0 - disabled (default)
        not 0 - enabled
index c0aab985bad9ac4a159ea9f96e837bee28475291..949d5dcdd9a348fd646f89c62f604d9d29433d2c 100644 (file)
@@ -105,6 +105,83 @@ Copyright (C) 1999-2000 Maxim Krasnyansky <max_mk@yahoo.com>
      Proto [2 bytes]
      Raw protocol(IP, IPv6, etc) frame.
 
+  3.3 Multiqueue tuntap interface:
+
+  From version 3.8, Linux supports multiqueue tuntap which can uses multiple
+  file descriptors (queues) to parallelize packets sending or receiving. The
+  device allocation is the same as before, and if user wants to create multiple
+  queues, TUNSETIFF with the same device name must be called many times with
+  IFF_MULTI_QUEUE flag.
+
+  char *dev should be the name of the device, queues is the number of queues to
+  be created, fds is used to store and return the file descriptors (queues)
+  created to the caller. Each file descriptor were served as the interface of a
+  queue which could be accessed by userspace.
+
+  #include <linux/if.h>
+  #include <linux/if_tun.h>
+
+  int tun_alloc_mq(char *dev, int queues, int *fds)
+  {
+      struct ifreq ifr;
+      int fd, err, i;
+
+      if (!dev)
+          return -1;
+
+      memset(&ifr, 0, sizeof(ifr));
+      /* Flags: IFF_TUN   - TUN device (no Ethernet headers)
+       *        IFF_TAP   - TAP device
+       *
+       *        IFF_NO_PI - Do not provide packet information
+       *        IFF_MULTI_QUEUE - Create a queue of multiqueue device
+       */
+      ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_MULTI_QUEUE;
+      strcpy(ifr.ifr_name, dev);
+
+      for (i = 0; i < queues; i++) {
+          if ((fd = open("/dev/net/tun", O_RDWR)) < 0)
+             goto err;
+          err = ioctl(fd, TUNSETIFF, (void *)&ifr);
+          if (err) {
+             close(fd);
+             goto err;
+          }
+          fds[i] = fd;
+      }
+
+      return 0;
+  err:
+      for (--i; i >= 0; i--)
+          close(fds[i]);
+      return err;
+  }
+
+  A new ioctl(TUNSETQUEUE) were introduced to enable or disable a queue. When
+  calling it with IFF_DETACH_QUEUE flag, the queue were disabled. And when
+  calling it with IFF_ATTACH_QUEUE flag, the queue were enabled. The queue were
+  enabled by default after it was created through TUNSETIFF.
+
+  fd is the file descriptor (queue) that we want to enable or disable, when
+  enable is true we enable it, otherwise we disable it
+
+  #include <linux/if.h>
+  #include <linux/if_tun.h>
+
+  int tun_set_queue(int fd, int enable)
+  {
+      struct ifreq ifr;
+
+      memset(&ifr, 0, sizeof(ifr));
+
+      if (enable)
+         ifr.ifr_flags = IFF_ATTACH_QUEUE;
+      else
+         ifr.ifr_flags = IFF_DETACH_QUEUE;
+
+      return ioctl(fd, TUNSETQUEUE, (void *)&ifr);
+  }
+
 Universal TUN/TAP device driver Frequently Asked Question.
    
 1. What platforms are supported by TUN/TAP driver ?
index ce6581c8ca26915c1a00f31a9b7605c0cb6c3413..95731a08f25787ff77a03a4f542dec5791f120e6 100644 (file)
@@ -890,9 +890,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     enable_msi - Enable Message Signaled Interrupt (MSI) (default = off)
     power_save - Automatic power-saving timeout (in second, 0 =
                disable)
-    power_save_controller - Support runtime D3 of HD-audio controller
-               (-1 = on for supported chip (default), false = off,
-                true = force to on even for unsupported hardware)
+    power_save_controller - Reset HD-audio controller in power-saving mode
+               (default = on)
     align_buffer_size - Force rounding of buffer/period sizes to multiples
                      of 128 bytes. This is more efficient in terms of memory
                      access but isn't required by the HDA spec and prevents
@@ -912,7 +911,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
     models depending on the codec chip.  The list of available models
     is found in HD-Audio-Models.txt
 
-    The model name "genric" is treated as a special case.  When this
+    The model name "generic" is treated as a special case.  When this
     model is given, the driver uses the generic codec parser without
     "codec-patch".  It's sometimes good for testing and debugging.
 
index d9776cf60c07a9b62445174cd6eed64e1e69cb83..9663b45f6fde66ba5d2bb4abdd4b9bf9e651a32b 100644 (file)
@@ -285,7 +285,7 @@ sample data.
 <H4>
 7.2.4 Close Callback</H4>
 The <TT>close</TT> callback is called when this device is closed by the
-applicaion. If any private data was allocated in open callback, it must
+application. If any private data was allocated in open callback, it must
 be released in the close callback. The deletion of ALSA port should be
 done here, too. This callback must not be NULL.
 <H4>
index 53d6a3c51d875771fc2966c9917aec13b17f53c6..a372304aef10a378bc00440053c0fe4028eac566 100644 (file)
@@ -1873,7 +1873,7 @@ feature:
 
        status\input  |     0      |     1      |    else    |
        --------------+------------+------------+------------+
-       not allocated |(do nothing)| alloc+swap |   EINVAL   |
+       not allocated |(do nothing)| alloc+swap |(do nothing)|
        --------------+------------+------------+------------+
        allocated     |    free    |    swap    |   clear    |
        --------------+------------+------------+------------+
index 95616582c728566eaa1e24592f645ece61f6b501..836a6183c37f6f6e2ceec36ea72497136fffde4c 100644 (file)
@@ -1338,12 +1338,6 @@ S:       Maintained
 F:     drivers/platform/x86/asus*.c
 F:     drivers/platform/x86/eeepc*.c
 
-ASUS ASB100 HARDWARE MONITOR DRIVER
-M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
-L:     lm-sensors@lm-sensors.org
-S:     Maintained
-F:     drivers/hwmon/asb100.c
-
 ASYNCHRONOUS TRANSFERS/TRANSFORMS (IOAT) API
 M:     Dan Williams <djbw@fb.com>
 W:     http://sourceforge.net/projects/xscaleiop
@@ -1467,6 +1461,12 @@ F:       drivers/dma/at_hdmac.c
 F:     drivers/dma/at_hdmac_regs.h
 F:     include/linux/platform_data/dma-atmel.h
 
+ATMEL I2C DRIVER
+M:     Ludovic Desroches <ludovic.desroches@atmel.com>
+L:     linux-i2c@vger.kernel.org
+S:     Supported
+F:     drivers/i2c/busses/i2c-at91.c
+
 ATMEL ISI DRIVER
 M:     Josh Wu <josh.wu@atmel.com>
 L:     linux-media@vger.kernel.org
@@ -2629,7 +2629,7 @@ F:        include/uapi/drm/
 
 INTEL DRM DRIVERS (excluding Poulsbo, Moorestown and derivative chipsets)
 M:     Daniel Vetter <daniel.vetter@ffwll.ch>
-L:     intel-gfx@lists.freedesktop.org (subscribers-only)
+L:     intel-gfx@lists.freedesktop.org
 L:     dri-devel@lists.freedesktop.org
 T:     git git://people.freedesktop.org/~danvet/drm-intel
 S:     Supported
@@ -3242,6 +3242,12 @@ F:       Documentation/firmware_class/
 F:     drivers/base/firmware*.c
 F:     include/linux/firmware.h
 
+FLASHSYSTEM DRIVER (IBM FlashSystem 70/80 PCI SSD Flash Card)
+M:     Joshua Morris <josh.h.morris@us.ibm.com>
+M:     Philip Kelleher <pjk1939@linux.vnet.ibm.com>
+S:     Maintained
+F:     drivers/block/rsxx/
+
 FLOPPY DRIVER
 M:     Jiri Kosina <jkosina@suse.cz>
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/jikos/floppy.git
@@ -3851,7 +3857,7 @@ F:        drivers/i2c/busses/i2c-ismt.c
 F:     Documentation/i2c/busses/i2c-ismt
 
 I2C/SMBUS STUB DRIVER
-M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
+M:     Jean Delvare <khali@linux-fr.org>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     drivers/i2c/i2c-stub.c
@@ -4005,6 +4011,22 @@ M:       Stanislaw Gruszka <stf_xl@wp.pl>
 S:     Maintained
 F:     drivers/usb/atm/ueagle-atm.c
 
+INA209 HARDWARE MONITOR DRIVER
+M:     Guenter Roeck <linux@roeck-us.net>
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+F:     Documentation/hwmon/ina209
+F:     Documentation/devicetree/bindings/i2c/ina209.txt
+F:     drivers/hwmon/ina209.c
+
+INA2XX HARDWARE MONITOR DRIVER
+M:     Guenter Roeck <linux@roeck-us.net>
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+F:     Documentation/hwmon/ina2xx
+F:     drivers/hwmon/ina2xx.c
+F:     include/linux/platform_data/ina2xx.h
+
 INDUSTRY PACK SUBSYSTEM (IPACK)
 M:     Samuel Iglesias Gonsalvez <siglesias@igalia.com>
 M:     Jens Taprogge <jens.taprogge@taprogge.org>
@@ -5043,9 +5065,8 @@ S:        Maintained
 F:     drivers/net/ethernet/marvell/sk*
 
 MARVELL LIBERTAS WIRELESS DRIVER
-M:     Dan Williams <dcbw@redhat.com>
 L:     libertas-dev@lists.infradead.org
-S:     Maintained
+S:     Orphan
 F:     drivers/net/wireless/libertas/
 
 MARVELL MV643XX ETHERNET DRIVER
@@ -5098,6 +5119,15 @@ S:       Maintained
 F:     Documentation/hwmon/max6650
 F:     drivers/hwmon/max6650.c
 
+MAX6697 HARDWARE MONITOR DRIVER
+M:     Guenter Roeck <linux@roeck-us.net>
+L:     lm-sensors@lm-sensors.org
+S:     Maintained
+F:     Documentation/hwmon/max6697
+F:     Documentation/devicetree/bindings/i2c/max6697.txt
+F:     drivers/hwmon/max6697.c
+F:     include/linux/platform_data/max6697.h
+
 MAXIRADIO FM RADIO RECEIVER DRIVER
 M:     Hans Verkuil <hverkuil@xs4all.nl>
 L:     linux-media@vger.kernel.org
@@ -5538,6 +5568,7 @@ F:        include/uapi/linux/if_*
 F:     include/uapi/linux/netdevice.h
 
 NETXEN (1/10) GbE SUPPORT
+M:     Manish Chopra <manish.chopra@qlogic.com>
 M:     Sony Chacko <sony.chacko@qlogic.com>
 M:     Rajesh Borundia <rajesh.borundia@qlogic.com>
 L:     netdev@vger.kernel.org
@@ -5622,6 +5653,14 @@ S:       Maintained
 F:     drivers/video/riva/
 F:     drivers/video/nvidia/
 
+NVM EXPRESS DRIVER
+M:     Matthew Wilcox <willy@linux.intel.com>
+L:     linux-nvme@lists.infradead.org
+T:     git git://git.infradead.org/users/willy/linux-nvme.git
+S:     Supported
+F:     drivers/block/nvme.c
+F:     include/linux/nvme.h
+
 OMAP SUPPORT
 M:     Tony Lindgren <tony@atomide.com>
 L:     linux-omap@vger.kernel.org
@@ -5650,7 +5689,7 @@ S:        Maintained
 F:     arch/arm/*omap*/*clock*
 
 OMAP POWER MANAGEMENT SUPPORT
-M:     Kevin Hilman <khilman@ti.com>
+M:     Kevin Hilman <khilman@deeprootsystems.com>
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     arch/arm/*omap*/*pm*
@@ -5744,7 +5783,7 @@ F:        arch/arm/*omap*/usb*
 
 OMAP GPIO DRIVER
 M:     Santosh Shilimkar <santosh.shilimkar@ti.com>
-M:     Kevin Hilman <khilman@ti.com>
+M:     Kevin Hilman <khilman@deeprootsystems.com>
 L:     linux-omap@vger.kernel.org
 S:     Maintained
 F:     drivers/gpio/gpio-omap.c
@@ -6176,7 +6215,7 @@ F:        include/linux/power_supply.h
 F:     drivers/power/
 
 PNP SUPPORT
-M:     Adam Belay <abelay@mit.edu>
+M:     Rafael J. Wysocki <rafael.j.wysocki@intel.com>
 M:     Bjorn Helgaas <bhelgaas@google.com>
 S:     Maintained
 F:     drivers/pnp/
@@ -6412,6 +6451,8 @@ F:        Documentation/networking/LICENSE.qla3xxx
 F:     drivers/net/ethernet/qlogic/qla3xxx.*
 
 QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
+M:     Rajesh Borundia <rajesh.borundia@qlogic.com>
+M:     Shahed Shaikh <shahed.shaikh@qlogic.com>
 M:     Jitendra Kalsaria <jitendra.kalsaria@qlogic.com>
 M:     Sony Chacko <sony.chacko@qlogic.com>
 M:     linux-driver@qlogic.com
@@ -6516,12 +6557,6 @@ S:       Maintained
 F:     Documentation/blockdev/ramdisk.txt
 F:     drivers/block/brd.c
 
-RAMSAM DRIVER (IBM RamSan 70/80 PCI SSD Flash Card)
-M:     Joshua Morris <josh.h.morris@us.ibm.com>
-M:     Philip Kelleher <pjk1939@linux.vnet.ibm.com>
-S:     Maintained
-F:     drivers/block/rsxx/
-
 RANDOM NUMBER DRIVER
 M:     Theodore Ts'o" <tytso@mit.edu>
 S:     Maintained
@@ -7138,7 +7173,7 @@ F:        arch/arm/mach-s3c2410/bast-irq.c
 
 TI DAVINCI MACHINE SUPPORT
 M:     Sekhar Nori <nsekhar@ti.com>
-M:     Kevin Hilman <khilman@ti.com>
+M:     Kevin Hilman <khilman@deeprootsystems.com>
 L:     davinci-linux-open-source@linux.davincidsp.com (moderated for non-subscribers)
 T:     git git://gitorious.org/linux-davinci/linux-davinci.git
 Q:     http://patchwork.kernel.org/project/linux-davinci/list/
@@ -7171,13 +7206,6 @@ L:       netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/sis/sis900.*
 
-SIS 96X I2C/SMBUS DRIVER
-M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
-L:     linux-i2c@vger.kernel.org
-S:     Maintained
-F:     Documentation/i2c/busses/i2c-sis96x
-F:     drivers/i2c/busses/i2c-sis96x.c
-
 SIS FRAMEBUFFER DRIVER
 M:     Thomas Winischhofer <thomas@winischhofer.net>
 W:     http://www.winischhofer.net/linuxsisvga.shtml
@@ -7255,7 +7283,7 @@ F:        Documentation/hwmon/sch5627
 F:     drivers/hwmon/sch5627.c
 
 SMSC47B397 HARDWARE MONITOR DRIVER
-M:     "Mark M. Hoffman" <mhoffman@lightlink.com>
+M:     Jean Delvare <khali@linux-fr.org>
 L:     lm-sensors@lm-sensors.org
 S:     Maintained
 F:     Documentation/hwmon/smsc47b397
@@ -7678,9 +7706,10 @@ F:       include/linux/swiotlb.h
 
 SYNOPSYS ARC ARCHITECTURE
 M:     Vineet Gupta <vgupta@synopsys.com>
-L:     linux-snps-arc@vger.kernel.org
 S:     Supported
 F:     arch/arc/
+F:     Documentation/devicetree/bindings/arc/
+F:     drivers/tty/serial/arc-uart.c
 
 SYSV FILESYSTEM
 M:     Christoph Hellwig <hch@infradead.org>
index a05ea42c5f185d66692be18747e9e90b9633cd20..6db672b15bdaa447cafe1c6413b0fc56f2e9d2fd 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 9
 SUBLEVEL = 0
-EXTRAVERSION = -rc2
+EXTRAVERSION = -rc6
 NAME = Unicycling Gorilla
 
 # *DOCUMENTATION*
index 5a1779c93940153b30ba84a561b75aaec1e109ea..1455579791ec02514a5d616a4b6749cbec3185b0 100644 (file)
@@ -319,13 +319,6 @@ config ARCH_WANT_OLD_COMPAT_IPC
        select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
        bool
 
-config HAVE_VIRT_TO_BUS
-       bool
-       help
-         An architecture should select this if it implements the
-         deprecated interface virt_to_bus().  All new architectures
-         should probably not select this.
-
 config HAVE_ARCH_SECCOMP_FILTER
        bool
        help
index 5833aa4414816526dd23be127ef718a1900d4b7f..8a33ba01301ff5cb4966455699a164c27feb1484 100644 (file)
@@ -9,7 +9,7 @@ config ALPHA
        select HAVE_PERF_EVENTS
        select HAVE_DMA_ATTRS
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select GENERIC_IRQ_PROBE
        select AUTO_IRQ_AFFINITY if SMP
        select GENERIC_IRQ_SHOW
index 4759fe751aa1ba1b21ea99b99ae2c9487627e326..2cc3cc519c549a357052a2279b7f587ed8558c9d 100644 (file)
@@ -12,7 +12,7 @@ NM := $(NM) -B
 
 LDFLAGS_vmlinux        := -static -N #-relax
 CHECKFLAGS     += -D__alpha__ -m64
-cflags-y       := -pipe -mno-fp-regs -ffixed-8 -msmall-data
+cflags-y       := -pipe -mno-fp-regs -ffixed-8
 cflags-y       += $(call cc-option, -fno-jump-tables)
 
 cpuflags-$(CONFIG_ALPHA_EV4)           := -mcpu=ev4
index 46cefbd50e73453abc7d26c08e501c09ce8da5e9..bae97eb19d269dd8cf7b8008ddb9833aab68abfd 100644 (file)
@@ -26,7 +26,7 @@
 #define fd_disable_irq()        disable_irq(FLOPPY_IRQ)
 #define fd_cacheflush(addr,size) /* nothing */
 #define fd_request_irq()        request_irq(FLOPPY_IRQ, floppy_interrupt,\
-                                           IRQF_DISABLED, "floppy", NULL)
+                                           0, "floppy", NULL)
 #define fd_free_irq()           free_irq(FLOPPY_IRQ, NULL)
 
 #ifdef CONFIG_PCI
index 2872accd22156b7ee134f70c84376a7dff48a4c8..7b2be251c30fb92981d4aef8cf4f8951bed24728 100644 (file)
@@ -117,13 +117,6 @@ handle_irq(int irq)
                return;
        }
 
-       /*
-        * From here we must proceed with IPL_MAX. Note that we do not
-        * explicitly enable interrupts afterwards - some MILO PALcode
-        * (namely LX164 one) seems to have severe problems with RTI
-        * at IPL 0.
-        */
-       local_irq_disable();
        irq_enter();
        generic_handle_irq_desc(irq, desc);
        irq_exit();
index 772ddfdb71a8e67af8f20e38ff7f8def9af3b943..f433fc11877a30ae096dd54d263b37b094132fac 100644 (file)
@@ -45,6 +45,14 @@ do_entInt(unsigned long type, unsigned long vector,
          unsigned long la_ptr, struct pt_regs *regs)
 {
        struct pt_regs *old_regs;
+
+       /*
+        * Disable interrupts during IRQ handling.
+        * Note that there is no matching local_irq_enable() due to
+        * severe problems with RTI at IPL0 and some MILO PALcode
+        * (namely LX164).
+        */
+       local_irq_disable();
        switch (type) {
        case 0:
 #ifdef CONFIG_SMP
@@ -62,7 +70,6 @@ do_entInt(unsigned long type, unsigned long vector,
          {
                long cpu;
 
-               local_irq_disable();
                smp_percpu_timer_interrupt(regs);
                cpu = smp_processor_id();
                if (cpu != boot_cpuid) {
@@ -222,7 +229,6 @@ process_mcheck_info(unsigned long vector, unsigned long la_ptr,
 
 struct irqaction timer_irqaction = {
        .handler        = timer_interrupt,
-       .flags          = IRQF_DISABLED,
        .name           = "timer",
 };
 
index 4d4c046f708d6f4691388b64fdd3bd014bb3b3c5..1383f8601a93b7595b290f7ad595f061917c180b 100644 (file)
@@ -188,6 +188,10 @@ nautilus_machine_check(unsigned long vector, unsigned long la_ptr)
 extern void free_reserved_mem(void *, void *);
 extern void pcibios_claim_one_bus(struct pci_bus *);
 
+static struct resource irongate_io = {
+       .name   = "Irongate PCI IO",
+       .flags  = IORESOURCE_IO,
+};
 static struct resource irongate_mem = {
        .name   = "Irongate PCI MEM",
        .flags  = IORESOURCE_MEM,
@@ -209,6 +213,7 @@ nautilus_init_pci(void)
 
        irongate = pci_get_bus_and_slot(0, 0);
        bus->self = irongate;
+       bus->resource[0] = &irongate_io;
        bus->resource[1] = &irongate_mem;
 
        pci_bus_size_bridges(bus);
index 5cf4a481b8c57ea01e0709764f2e4c11ad26b863..a53cf03f49d503cee6e17f043e851d07b847c882 100644 (file)
@@ -280,15 +280,15 @@ titan_late_init(void)
         * all reported to the kernel as machine checks, so the handler
         * is a nop so it can be called to count the individual events.
         */
-       titan_request_irq(63+16, titan_intr_nop, IRQF_DISABLED,
+       titan_request_irq(63+16, titan_intr_nop, 0,
                    "CChip Error", NULL);
-       titan_request_irq(62+16, titan_intr_nop, IRQF_DISABLED,
+       titan_request_irq(62+16, titan_intr_nop, 0,
                    "PChip 0 H_Error", NULL);
-       titan_request_irq(61+16, titan_intr_nop, IRQF_DISABLED,
+       titan_request_irq(61+16, titan_intr_nop, 0,
                    "PChip 1 H_Error", NULL);
-       titan_request_irq(60+16, titan_intr_nop, IRQF_DISABLED,
+       titan_request_irq(60+16, titan_intr_nop, 0,
                    "PChip 0 C_Error", NULL);
-       titan_request_irq(59+16, titan_intr_nop, IRQF_DISABLED,
+       titan_request_irq(59+16, titan_intr_nop, 0,
                    "PChip 1 C_Error", NULL);
 
        /* 
@@ -348,9 +348,9 @@ privateer_init_pci(void)
         * Hook a couple of extra err interrupts that the
         * common titan code won't.
         */
-       titan_request_irq(53+16, titan_intr_nop, IRQF_DISABLED,
+       titan_request_irq(53+16, titan_intr_nop, 0,
                    "NMI", NULL);
-       titan_request_irq(50+16, titan_intr_nop, IRQF_DISABLED,
+       titan_request_irq(50+16, titan_intr_nop, 0,
                    "Temperature Warning", NULL);
 
        /*
index 31f77aec082381e34f5cb7ddb06added7d98d179..45b8e0cea1764d2b9e4a0b0d1f27b787eb845870 100644 (file)
@@ -126,7 +126,7 @@ dma_map_sg(struct device *dev, struct scatterlist *sg,
        int i;
 
        for_each_sg(sg, s, nents, i)
-               sg->dma_address = dma_map_page(dev, sg_page(s), s->offset,
+               s->dma_address = dma_map_page(dev, sg_page(s), s->offset,
                                               s->length, dir);
 
        return nents;
index f4c8d36ebecbd2dcad76db454edc64686cfae292..a262828576839d9d48e5e2be18ae65b9fad815e5 100644 (file)
@@ -72,7 +72,4 @@ extern int elf_check_arch(const struct elf32_hdr *);
  */
 #define ELF_PLATFORM   (NULL)
 
-#define SET_PERSONALITY(ex) \
-       set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
-
 #endif
index 23daa326fc9b4d19c5711af313e730dae2551f27..eb2ae53187d95fe1240885bd7026d1f13c3c98a4 100644 (file)
  *-------------------------------------------------------------*/
 .macro SAVE_ALL_EXCEPTION   marker
 
-       st      \marker, [sp, 8]
+       st      \marker, [sp, 8]        /* orig_r8 */
        st      r0, [sp, 4]    /* orig_r0, needed only for sys calls */
 
        /* Restore r9 used to code the early prologue */
index f3c4934f0ca9462e1876095fa197a90dc2e4fede..4930957ca3d38c4cb312aa60f21ffa9cbb413087 100644 (file)
@@ -13,7 +13,7 @@
 
 #ifdef CONFIG_KGDB
 
-#include <asm/user.h>
+#include <asm/ptrace.h>
 
 /* to ensure compatibility with Linux 2.6.35, we don't implement the get/set
  * register API yet */
@@ -53,9 +53,7 @@ enum arc700_linux_regnums {
 };
 
 #else
-static inline void kgdb_trap(struct pt_regs *regs, int param)
-{
-}
+#define kgdb_trap(regs, param)
 #endif
 
 #endif /* __ARC_KGDB_H__ */
index 8ae783d20a81185dab9ae04e61f5e2a9e47082b0..6179de7e07c21ca4875017adc1107c0e7b0b46c4 100644 (file)
@@ -123,7 +123,7 @@ static inline long regs_return_value(struct pt_regs *regs)
 #define orig_r8_IS_SCALL               0x0001
 #define orig_r8_IS_SCALL_RESTARTED     0x0002
 #define orig_r8_IS_BRKPT               0x0004
-#define orig_r8_IS_EXCPN               0x0004
+#define orig_r8_IS_EXCPN               0x0008
 #define orig_r8_IS_IRQ1                        0x0010
 #define orig_r8_IS_IRQ2                        0x0020
 
index e53a5340ba4f2b91376f76ca7b4f5286567cd302..dd785befe7fd1eaa3b6b7d5df5ee8ef77e849587 100644 (file)
@@ -16,8 +16,6 @@
 #include <linux/types.h>
 
 int sys_clone_wrapper(int, int, int, int, int);
-int sys_fork_wrapper(void);
-int sys_vfork_wrapper(void);
 int sys_cacheflush(uint32_t, uint32_t uint32_t);
 int sys_arc_settls(void *);
 int sys_arc_gettls(void);
index 6afa4f70207529c5d9ae7d0caa69082108d154c9..30333cec0fef274365aeb559084d58a5ee023a9b 100644 (file)
 */
 struct user_regs_struct {
 
-       struct scratch {
+       struct {
                long pad;
                long bta, lp_start, lp_end, lp_count;
                long status32, ret, blink, fp, gp;
                long r12, r11, r10, r9, r8, r7, r6, r5, r4, r3, r2, r1, r0;
                long sp;
        } scratch;
-       struct callee {
+       struct {
                long pad;
                long r25, r24, r23, r22, r21, r20;
                long r19, r18, r17, r16, r15, r14, r13;
index ef6800ba2f03f6cce95a78e1db7b175f66d72e7c..91eeab81f52d3d66a408a215f06b4ff19022d364 100644 (file)
@@ -452,7 +452,7 @@ tracesys:
        ; using ERET won't work since next-PC has already committed
        lr  r12, [efa]
        GET_CURR_TASK_FIELD_PTR   TASK_THREAD, r11
-       st  r12, [r11, THREAD_FAULT_ADDR]
+       st  r12, [r11, THREAD_FAULT_ADDR]       ; thread.fault_address
 
        ; PRE Sys Call Ptrace hook
        mov r0, sp                      ; pt_regs needed
@@ -792,31 +792,6 @@ ARC_EXIT ret_from_fork
 
 ;################### Special Sys Call Wrappers ##########################
 
-; TBD: call do_fork directly from here
-ARC_ENTRY sys_fork_wrapper
-       SAVE_CALLEE_SAVED_USER
-       bl  @sys_fork
-       DISCARD_CALLEE_SAVED_USER
-
-       GET_CURR_THR_INFO_FLAGS   r10
-       btst r10, TIF_SYSCALL_TRACE
-       bnz  tracesys_exit
-
-       b ret_from_system_call
-ARC_EXIT sys_fork_wrapper
-
-ARC_ENTRY sys_vfork_wrapper
-       SAVE_CALLEE_SAVED_USER
-       bl  @sys_vfork
-       DISCARD_CALLEE_SAVED_USER
-
-       GET_CURR_THR_INFO_FLAGS   r10
-       btst r10, TIF_SYSCALL_TRACE
-       bnz  tracesys_exit
-
-       b ret_from_system_call
-ARC_EXIT sys_vfork_wrapper
-
 ARC_ENTRY sys_clone_wrapper
        SAVE_CALLEE_SAVED_USER
        bl  @sys_clone
index 2888ba5be47e4be4e796d0840abb9570253a416a..52bdc83c1495b5bf31a685998f7a5d7b9a1bd15e 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/kgdb.h>
+#include <linux/sched.h>
 #include <asm/disasm.h>
 #include <asm/cacheflush.h>
 
index dc0f968dae0aecfa96db2bc005a99c74bdabb71a..2d95ac07df7bde15169ff5058d7e53afd2f2d73e 100644 (file)
@@ -232,10 +232,8 @@ char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
 
        n += scnprintf(buf + n, len - n, "\n");
 
-#ifdef _ASM_GENERIC_UNISTD_H
        n += scnprintf(buf + n, len - n,
-                      "OS ABI [v2]\t: asm-generic/{unistd,stat,fcntl}\n");
-#endif
+                      "OS ABI [v3]\t: no-legacy-syscalls\n");
 
        return buf;
 }
index f6bdd07583f3a2ed190fdc1de9ceff9e77bf2ba8..9d6c1ca26af6d8bf4c035ae5f6085d8bfb6bc0be 100644 (file)
@@ -6,8 +6,6 @@
 #include <asm/syscalls.h>
 
 #define sys_clone      sys_clone_wrapper
-#define sys_fork       sys_fork_wrapper
-#define sys_vfork      sys_vfork_wrapper
 
 #undef __SYSCALL
 #define __SYSCALL(nr, call) [nr] = (call),
index 5bfd584929c8176988d057cfb54b7f8e88db8020..6a4709b3837ad3c75cafcee16ca492fcd8039ff7 100644 (file)
@@ -49,7 +49,6 @@ config ARM
        select HAVE_REGS_AND_STACK_ACCESS_API
        select HAVE_SYSCALL_TRACEPOINTS
        select HAVE_UID16
-       select HAVE_VIRT_TO_BUS
        select KTIME_SCALAR
        select PERF_USE_VMALLOC
        select RTC_LIB
@@ -556,7 +555,6 @@ config ARCH_IXP4XX
 config ARCH_DOVE
        bool "Marvell Dove"
        select ARCH_REQUIRE_GPIOLIB
-       select COMMON_CLK_DOVE
        select CPU_V7
        select GENERIC_CLOCKEVENTS
        select MIGHT_HAVE_PCI
@@ -675,6 +673,7 @@ config ARCH_TEGRA
        select HAVE_CLK
        select HAVE_SMP
        select MIGHT_HAVE_CACHE_L2X0
+       select SOC_BUS
        select SPARSE_IRQ
        select USE_OF
        help
@@ -744,6 +743,7 @@ config ARCH_RPC
        select NEED_MACH_IO_H
        select NEED_MACH_MEMORY_H
        select NO_IOPORT
+       select VIRT_TO_BUS
        help
          On the Acorn Risc-PC, Linux can support the internal IDE disk and
          CD-ROM interface, serial and parallel port, and the floppy drive.
@@ -770,12 +770,15 @@ config ARCH_SA1100
 config ARCH_S3C24XX
        bool "Samsung S3C24XX SoCs"
        select ARCH_HAS_CPUFREQ
-       select ARCH_USES_GETTIMEOFFSET
+       select ARCH_REQUIRE_GPIOLIB
        select CLKDEV_LOOKUP
+       select CLKSRC_MMIO
+       select GENERIC_CLOCKEVENTS
        select HAVE_CLK
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
        select HAVE_S3C_RTC if RTC_CLASS
+       select MULTI_IRQ_HANDLER
        select NEED_MACH_GPIO_H
        select NEED_MACH_IO_H
        help
@@ -788,10 +791,11 @@ config ARCH_S3C64XX
        bool "Samsung S3C64XX"
        select ARCH_HAS_CPUFREQ
        select ARCH_REQUIRE_GPIOLIB
-       select ARCH_USES_GETTIMEOFFSET
        select ARM_VIC
        select CLKDEV_LOOKUP
+       select CLKSRC_MMIO
        select CPU_V6
+       select GENERIC_CLOCKEVENTS
        select HAVE_CLK
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
@@ -825,9 +829,11 @@ config ARCH_S5P64X0
 
 config ARCH_S5PC100
        bool "Samsung S5PC100"
-       select ARCH_USES_GETTIMEOFFSET
+       select ARCH_REQUIRE_GPIOLIB
        select CLKDEV_LOOKUP
+       select CLKSRC_MMIO
        select CPU_V7
+       select GENERIC_CLOCKEVENTS
        select HAVE_CLK
        select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
@@ -854,18 +860,11 @@ config ARCH_S5PV210
        help
          Samsung S5PV210/S5PC110 series based systems
 
-config ARCH_EXYNOS
+config ARCH_EXYNOS_SINGLE
        bool "Samsung EXYNOS"
-       select ARCH_HAS_CPUFREQ
        select ARCH_HAS_HOLES_MEMORYMODEL
        select ARCH_SPARSEMEM_ENABLE
-       select CLKDEV_LOOKUP
-       select CPU_V7
-       select GENERIC_CLOCKEVENTS
-       select HAVE_CLK
-       select HAVE_S3C2410_I2C if I2C
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
-       select HAVE_S3C_RTC if RTC_CLASS
        select NEED_MACH_GPIO_H
        select NEED_MACH_MEMORY_H
        help
@@ -879,6 +878,7 @@ config ARCH_SHARK
        select ISA_DMA
        select NEED_MACH_MEMORY_H
        select PCI
+       select VIRT_TO_BUS
        select ZONE_DMA
        help
          Support for the StrongARM based Digital DNARD machine, also known
@@ -1006,12 +1006,12 @@ config ARCH_MULTI_V4_V5
        bool
 
 config ARCH_MULTI_V6
-       bool "ARMv6 based platforms (ARM11, Scorpion, ...)"
+       bool "ARMv6 based platforms (ARM11)"
        select ARCH_MULTI_V6_V7
        select CPU_V6
 
 config ARCH_MULTI_V7
-       bool "ARMv7 based platforms (Cortex-A, PJ4, Krait)"
+       bool "ARMv7 based platforms (Cortex-A, PJ4, Scorpion, Krait)"
        default y
        select ARCH_MULTI_V6_V7
        select ARCH_VEXPRESS
@@ -1183,9 +1183,9 @@ config ARM_NR_BANKS
        default 8
 
 config IWMMXT
-       bool "Enable iWMMXt support"
+       bool "Enable iWMMXt support" if !CPU_PJ4
        depends on CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_PJ4
-       default y if PXA27x || PXA3xx || ARCH_MMP
+       default y if PXA27x || PXA3xx || ARCH_MMP || CPU_PJ4
        help
          Enable support for iWMMXt context switching at run time if
          running on a CPU that supports it.
@@ -1439,6 +1439,16 @@ config ARM_ERRATA_775420
         to deadlock. This workaround puts DSB before executing ISB if
         an abort may occur on cache maintenance.
 
+config ARM_ERRATA_798181
+       bool "ARM errata: TLBI/DSB failure on Cortex-A15"
+       depends on CPU_V7 && SMP
+       help
+         On Cortex-A15 (r0p0..r3p2) the TLBI*IS/DSB operations are not
+         adequately shooting down all use of the old entries. This
+         option enables the Linux kernel workaround for this erratum
+         which sends an IPI to the CPUs that are running the same ASID
+         as the one being invalidated.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
@@ -1462,10 +1472,6 @@ config ISA_DMA
        bool
        select ISA_DMA_API
 
-config ARCH_NO_VIRT_TO_BUS
-       def_bool y
-       depends on !ARCH_RPC && !ARCH_NETWINDER && !ARCH_SHARK
-
 # Select ISA DMA interface
 config ISA_DMA_API
        bool
@@ -1651,20 +1657,24 @@ config LOCAL_TIMERS
        bool "Use local timer interrupts"
        depends on SMP
        default y
-       select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT)
+       select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !CLKSRC_EXYNOS_MCT)
        help
          Enable support for local timers on SMP platforms, rather then the
          legacy IPI broadcast method.  Local timers allows the system
          accounting to be spread across the timer interval, preventing a
          "thundering herd" at every timer tick.
 
+# The GPIO number here must be sorted by descending number. In case of
+# a multiplatform kernel, we just want the highest value required by the
+# selected platforms.
 config ARCH_NR_GPIO
        int
        default 1024 if ARCH_SHMOBILE || ARCH_TEGRA
+       default 512 if SOC_OMAP5
        default 355 if ARCH_U8500
+       default 352 if ARCH_VT8500
+       default 288 if ARCH_SUNXI
        default 264 if MACH_H4700
-       default 512 if SOC_OMAP5
-       default 288 if ARCH_VT8500 || ARCH_SUNXI
        default 0
        help
          Maximum number of GPIOs in the system.
@@ -1888,8 +1898,9 @@ config XEN_DOM0
 
 config XEN
        bool "Xen guest support on ARM (EXPERIMENTAL)"
-       depends on ARM && OF
+       depends on ARM && AEABI && OF
        depends on CPU_V7 && !CPU_V6
+       depends on !GENERIC_ATOMIC64
        help
          Say Y if you want to run Linux in a Virtual Machine on Xen on ARM.
 
index acddddac7ee46fb961e8ba1fe86d038276d0a632..59ce26afdcc53087037df2837ea1dd011e527f7a 100644 (file)
@@ -330,6 +330,7 @@ choice
 
        config DEBUG_S3C_UART0
                depends on PLAT_SAMSUNG
+               select DEBUG_EXYNOS_UART if ARCH_EXYNOS
                bool "Use S3C UART 0 for low-level debug"
                help
                  Say Y here if you want the debug print routines to direct
@@ -341,6 +342,7 @@ choice
 
        config DEBUG_S3C_UART1
                depends on PLAT_SAMSUNG
+               select DEBUG_EXYNOS_UART if ARCH_EXYNOS
                bool "Use S3C UART 1 for low-level debug"
                help
                  Say Y here if you want the debug print routines to direct
@@ -352,6 +354,7 @@ choice
 
        config DEBUG_S3C_UART2
                depends on PLAT_SAMSUNG
+               select DEBUG_EXYNOS_UART if ARCH_EXYNOS
                bool "Use S3C UART 2 for low-level debug"
                help
                  Say Y here if you want the debug print routines to direct
@@ -363,6 +366,7 @@ choice
 
        config DEBUG_S3C_UART3
                depends on PLAT_SAMSUNG && ARCH_EXYNOS
+               select DEBUG_EXYNOS_UART
                bool "Use S3C UART 3 for low-level debug"
                help
                  Say Y here if you want the debug print routines to direct
@@ -485,6 +489,9 @@ choice
 
 endchoice
 
+config DEBUG_EXYNOS_UART
+       bool
+
 config DEBUG_IMX_UART_PORT
        int "i.MX Debug UART Port Selection" if DEBUG_IMX1_UART || \
                                                DEBUG_IMX25_UART || \
@@ -492,9 +499,10 @@ config DEBUG_IMX_UART_PORT
                                                DEBUG_IMX31_UART || \
                                                DEBUG_IMX35_UART || \
                                                DEBUG_IMX51_UART || \
-                                               DEBUG_IMX50_IMX53_UART || \
+                                               DEBUG_IMX53_UART || \
                                                DEBUG_IMX6Q_UART
        default 1
+       depends on ARCH_MXC
        help
          Choose UART port on which kernel low-level debug messages
          should be output.
@@ -579,6 +587,7 @@ endchoice
 
 config DEBUG_LL_INCLUDE
        string
+       default "debug/exynos.S" if DEBUG_EXYNOS_UART
        default "debug/icedcc.S" if DEBUG_ICEDCC
        default "debug/imx.S" if DEBUG_IMX1_UART || \
                                 DEBUG_IMX25_UART || \
index 71768b8a1ab91b7d7afe8241b11fc571cc30b516..84aa2caf07ed203fb810220258401a1b51f7cab3 100644 (file)
@@ -115,4 +115,4 @@ i:
        $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
        $(obj)/Image System.map "$(INSTALL_PATH)"
 
-subdir-            := bootp compressed
+subdir-            := bootp compressed dts
index ff48893d621cfe613c113d45b1172010631de1e4..2d870f4e4e2b18164c83ce9d63f518ee9bc86995 100644 (file)
@@ -43,7 +43,10 @@ dtb-$(CONFIG_ARCH_EXYNOS) += exynos4210-origen.dtb \
        exynos4210-smdkv310.dtb \
        exynos4210-trats.dtb \
        exynos4210-universal_c210.dtb \
+       exynos4412-odroidx.dtb \
        exynos4412-smdk4412.dtb \
+       exynos4412-origen.dtb \
+       exynos5250-arndale.dtb \
        exynos5250-smdk5250.dtb \
        exynos5250-snow.dtb \
        exynos5440-ssdk5440.dtb
index dd0c57dd9f3096ae40b35e2b4e43fc3c983f3ea1..3234875824dcc35258bef8909d6bd0a283710765 100644 (file)
@@ -54,7 +54,7 @@
                };
 
                mvsdio@d00d4000 {
-                       pinctrl-0 = <&sdio_pins2>;
+                       pinctrl-0 = <&sdio_pins3>;
                        pinctrl-names = "default";
                        status = "okay";
                        /*
index f8e4855bc9a536b34405dca9a8ff64a268542879..070bba4f25853be236d7b7cd26790283432b5364 100644 (file)
                        status = "okay";
                        /* No CD or WP GPIOs */
                };
+
+               usb@d0050000 {
+                       status = "okay";
+               };
+
+               usb@d0051000 {
+                       status = "okay";
+               };
        };
 };
index 6f1acc75e1559ca109066c7ad68c6e11f50087a0..5b708208b607b4b1eeaf7411040c56784fd93df5 100644 (file)
@@ -31,7 +31,6 @@
        mpic: interrupt-controller@d0020000 {
              compatible = "marvell,mpic";
              #interrupt-cells = <1>;
-             #address-cells = <1>;
              #size-cells = <1>;
              interrupt-controller;
        };
@@ -54,7 +53,7 @@
                                reg = <0xd0012000 0x100>;
                                reg-shift = <2>;
                                interrupts = <41>;
-                               reg-io-width = <4>;
+                               reg-io-width = <1>;
                                status = "disabled";
                };
                serial@d0012100 {
@@ -62,7 +61,7 @@
                                reg = <0xd0012100 0x100>;
                                reg-shift = <2>;
                                interrupts = <42>;
-                               reg-io-width = <4>;
+                               reg-io-width = <1>;
                                status = "disabled";
                };
 
index 8188d138020edc57c88db0cb749b91bdf016a5cf..a195debb67d35297292b43c1a9e7fc45c4908a2c 100644 (file)
                                             "mpp50", "mpp51", "mpp52";
                              marvell,function = "sd0";
                        };
+
+                       sdio_pins3: sdio-pins3 {
+                             marvell,pins = "mpp48", "mpp49", "mpp50",
+                                            "mpp51", "mpp52", "mpp53";
+                             marvell,function = "sd0";
+                       };
                };
 
                gpio0: gpio@d0018100 {
index 1443949c165ea8fa787fe798f687a63a116f2626..ca00d8326c8746cd127e7c35f3c8e7d3da697c15 100644 (file)
@@ -46,7 +46,7 @@
                                reg = <0xd0012200 0x100>;
                                reg-shift = <2>;
                                interrupts = <43>;
-                               reg-io-width = <4>;
+                               reg-io-width = <1>;
                                status = "disabled";
                };
                serial@d0012300 {
@@ -54,7 +54,7 @@
                                reg = <0xd0012300 0x100>;
                                reg-shift = <2>;
                                interrupts = <44>;
-                               reg-io-width = <4>;
+                               reg-io-width = <1>;
                                status = "disabled";
                };
 
index aa98e641931fa21ed76c627229da576289005d12..a98c0d50fbbe1ed80e6c29d5228716155f3399f5 100644 (file)
                                nand {
                                        pinctrl_nand: nand-0 {
                                                atmel,pins =
-                                                       <3 4 0x0 0x1    /* PD5 gpio RDY pin pull_up */
-                                                        3 5 0x0 0x1>;  /* PD4 gpio enable pin pull_up */
+                                                       <3 0 0x1 0x0    /* PD0 periph A Read Enable */
+                                                        3 1 0x1 0x0    /* PD1 periph A Write Enable */
+                                                        3 2 0x1 0x0    /* PD2 periph A Address Latch Enable */
+                                                        3 3 0x1 0x0    /* PD3 periph A Command Latch Enable */
+                                                        3 4 0x0 0x1    /* PD4 gpio Chip Enable pin pull_up */
+                                                        3 5 0x0 0x1    /* PD5 gpio RDY/BUSY pin pull_up */
+                                                        3 6 0x1 0x0    /* PD6 periph A Data bit 0 */
+                                                        3 7 0x1 0x0    /* PD7 periph A Data bit 1 */
+                                                        3 8 0x1 0x0    /* PD8 periph A Data bit 2 */
+                                                        3 9 0x1 0x0    /* PD9 periph A Data bit 3 */
+                                                        3 10 0x1 0x0   /* PD10 periph A Data bit 4 */
+                                                        3 11 0x1 0x0   /* PD11 periph A Data bit 5 */
+                                                        3 12 0x1 0x0   /* PD12 periph A Data bit 6 */
+                                                        3 13 0x1 0x0>; /* PD13 periph A Data bit 7 */
+                                       };
+
+                                       pinctrl_nand_16bits: nand_16bits-0 {
+                                               atmel,pins =
+                                                       <3 14 0x1 0x0   /* PD14 periph A Data bit 8 */
+                                                        3 15 0x1 0x0   /* PD15 periph A Data bit 9 */
+                                                        3 16 0x1 0x0   /* PD16 periph A Data bit 10 */
+                                                        3 17 0x1 0x0   /* PD17 periph A Data bit 11 */
+                                                        3 18 0x1 0x0   /* PD18 periph A Data bit 12 */
+                                                        3 19 0x1 0x0   /* PD19 periph A Data bit 13 */
+                                                        3 20 0x1 0x0   /* PD20 periph A Data bit 14 */
+                                                        3 21 0x1 0x0>; /* PD21 periph A Data bit 15 */
                                        };
                                };
 
index 4bf2a8774aa76ab53889c51208f5fa0cf6841c11..7e0481e2441ac49b96d33ec1491414562a3d9935 100644 (file)
                        compatible = "fixed-clock";
                        reg = <1>;
                        #clock-cells = <0>;
-                       clock-frequency = <150000000>;
+                       clock-frequency = <250000000>;
                };
        };
 };
index 46c09801703655eb0a8fb28b8332cafa674f9b72..62eceb4f0d3fa74fc0fe010e3f4ce5b494dc1738 100644 (file)
                samsung,i2c-max-bus-freq = <378000>;
                gpios = <&gpb3 0 2 3 0>,
                        <&gpb3 1 2 3 0>;
+
+               max77686@09 {
+                       compatible = "maxim,max77686";
+                       reg = <0x09>;
+
+                       voltage-regulators {
+                               ldo1_reg: LDO1 {
+                                       regulator-name = "P1.0V_LDO_OUT1";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo2_reg: LDO2 {
+                                       regulator-name = "P1.8V_LDO_OUT2";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo3_reg: LDO3 {
+                                       regulator-name = "P1.8V_LDO_OUT3";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo7_reg: LDO7 {
+                                       regulator-name = "P1.1V_LDO_OUT7";
+                                       regulator-min-microvolt = <1100000>;
+                                       regulator-max-microvolt = <1100000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo8_reg: LDO8 {
+                                       regulator-name = "P1.0V_LDO_OUT8";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo10_reg: LDO10 {
+                                       regulator-name = "P1.8V_LDO_OUT10";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo12_reg: LDO12 {
+                                       regulator-name = "P3.0V_LDO_OUT12";
+                                       regulator-min-microvolt = <3000000>;
+                                       regulator-max-microvolt = <3000000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo14_reg: LDO14 {
+                                       regulator-name = "P1.8V_LDO_OUT14";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo15_reg: LDO15 {
+                                       regulator-name = "P1.0V_LDO_OUT15";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-always-on;
+                               };
+
+                               ldo16_reg: LDO16 {
+                                       regulator-name = "P1.8V_LDO_OUT16";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                               };
+
+                               buck1_reg: BUCK1 {
+                                       regulator-name = "vdd_mif";
+                                       regulator-min-microvolt = <950000>;
+                                       regulator-max-microvolt = <1300000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               buck2_reg: BUCK2 {
+                                       regulator-name = "vdd_arm";
+                                       regulator-min-microvolt = <850000>;
+                                       regulator-max-microvolt = <1350000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               buck3_reg: BUCK3 {
+                                       regulator-name = "vdd_int";
+                                       regulator-min-microvolt = <900000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               buck4_reg: BUCK4 {
+                                       regulator-name = "vdd_g3d";
+                                       regulator-min-microvolt = <850000>;
+                                       regulator-max-microvolt = <1300000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               buck5_reg: BUCK5 {
+                                       regulator-name = "P1.8V_BUCK_OUT5";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                               };
+
+                               buck6_reg: BUCK6 {
+                                       regulator-name = "P1.35V_BUCK_OUT6";
+                                       regulator-min-microvolt = <1350000>;
+                                       regulator-max-microvolt = <1350000>;
+                                       regulator-always-on;
+                               };
+
+                               buck7_reg: BUCK7 {
+                                       regulator-name = "P2.0V_BUCK_OUT7";
+                                       regulator-min-microvolt = <2000000>;
+                                       regulator-max-microvolt = <2000000>;
+                                       regulator-always-on;
+                               };
+
+                               buck8_reg: BUCK8 {
+                                       regulator-name = "P2.85V_BUCK_OUT8";
+                                       regulator-min-microvolt = <2850000>;
+                                       regulator-max-microvolt = <2850000>;
+                                       regulator-always-on;
+                               };
+                       };
+               };
        };
 
        i2c@12C70000 {
index 69140ba99f465ea357980c84cc232924a69071c0..aaa63d0a80968b20abd4660492fb2af1ed463072 100644 (file)
 
                prcmu: prcmu@80157000 {
                        compatible = "stericsson,db8500-prcmu";
-                       reg = <0x80157000 0x1000>;
-                       reg-names = "prcmu";
+                       reg = <0x80157000 0x1000>, <0x801b0000 0x8000>, <0x801b8000 0x1000>;
+                       reg-names = "prcmu", "prcmu-tcpm", "prcmu-tcdm";
                        interrupts = <0 47 0x4>;
                        #address-cells = <1>;
                        #size-cells = <1>;
                                };
                        };
 
-                       ab8500@5 {
+                       ab8500 {
                                compatible = "stericsson,ab8500";
-                               reg = <5>; /* mailbox 5 is i2c */
                                interrupt-parent = <&intc>;
                                interrupts = <0 40 0x4>;
                                interrupt-controller;
index 67dbe20868a2746638ef2e20c380633a1e6fbcfa..f7509cafc377a14dc38aa5d77232c264a8d8a301 100644 (file)
                        status = "disabled";
                };
 
+               rtc@d8500 {
+                       compatible = "marvell,orion-rtc";
+                       reg = <0xd8500 0x20>;
+               };
+
                crypto: crypto@30000 {
                        compatible = "marvell,orion-crypto";
                        reg = <0x30000 0x10000>,
index 4b866659ae98bb0e78a8bf3e8f158567eabaf9df..b620e34fbd92ae45eea9cbbcfa008231abb43823 100644 (file)
@@ -86,6 +86,8 @@
                compatible = "samsung,s3c2410-wdt";
                reg = <0x10060000 0x100>;
                interrupts = <0 43 0>;
+               clocks = <&clock 345>;
+               clock-names = "watchdog";
                status = "disabled";
        };
 
@@ -93,6 +95,8 @@
                compatible = "samsung,s3c6410-rtc";
                reg = <0x10070000 0x100>;
                interrupts = <0 44 0>, <0 45 0>;
+               clocks = <&clock 346>;
+               clock-names = "rtc";
                status = "disabled";
        };
 
                compatible = "samsung,s5pv210-keypad";
                reg = <0x100A0000 0x100>;
                interrupts = <0 109 0>;
+               clocks = <&clock 347>;
+               clock-names = "keypad";
                status = "disabled";
        };
 
                compatible = "samsung,exynos4210-sdhci";
                reg = <0x12510000 0x100>;
                interrupts = <0 73 0>;
+               clocks = <&clock 297>, <&clock 145>;
+               clock-names = "hsmmc", "mmc_busclk.2";
                status = "disabled";
        };
 
                compatible = "samsung,exynos4210-sdhci";
                reg = <0x12520000 0x100>;
                interrupts = <0 74 0>;
+               clocks = <&clock 298>, <&clock 146>;
+               clock-names = "hsmmc", "mmc_busclk.2";
                status = "disabled";
        };
 
                compatible = "samsung,exynos4210-sdhci";
                reg = <0x12530000 0x100>;
                interrupts = <0 75 0>;
+               clocks = <&clock 299>, <&clock 147>;
+               clock-names = "hsmmc", "mmc_busclk.2";
                status = "disabled";
        };
 
                compatible = "samsung,exynos4210-sdhci";
                reg = <0x12540000 0x100>;
                interrupts = <0 76 0>;
+               clocks = <&clock 300>, <&clock 148>;
+               clock-names = "hsmmc", "mmc_busclk.2";
+               status = "disabled";
+       };
+
+       mfc: codec@13400000 {
+               compatible = "samsung,mfc-v5";
+               reg = <0x13400000 0x10000>;
+               interrupts = <0 94 0>;
+               samsung,power-domain = <&pd_mfc>;
                status = "disabled";
        };
 
                compatible = "samsung,exynos4210-uart";
                reg = <0x13800000 0x100>;
                interrupts = <0 52 0>;
+               clocks = <&clock 312>, <&clock 151>;
+               clock-names = "uart", "clk_uart_baud0";
                status = "disabled";
        };
 
                compatible = "samsung,exynos4210-uart";
                reg = <0x13810000 0x100>;
                interrupts = <0 53 0>;
+               clocks = <&clock 313>, <&clock 152>;
+               clock-names = "uart", "clk_uart_baud0";
                status = "disabled";
        };
 
                compatible = "samsung,exynos4210-uart";
                reg = <0x13820000 0x100>;
                interrupts = <0 54 0>;
+               clocks = <&clock 314>, <&clock 153>;
+               clock-names = "uart", "clk_uart_baud0";
                status = "disabled";
        };
 
                compatible = "samsung,exynos4210-uart";
                reg = <0x13830000 0x100>;
                interrupts = <0 55 0>;
+               clocks = <&clock 315>, <&clock 154>;
+               clock-names = "uart", "clk_uart_baud0";
                status = "disabled";
        };
 
                compatible = "samsung,s3c2440-i2c";
                reg = <0x13860000 0x100>;
                interrupts = <0 58 0>;
+               clocks = <&clock 317>;
+               clock-names = "i2c";
                status = "disabled";
        };
 
                compatible = "samsung,s3c2440-i2c";
                reg = <0x13870000 0x100>;
                interrupts = <0 59 0>;
+               clocks = <&clock 318>;
+               clock-names = "i2c";
                status = "disabled";
        };
 
                compatible = "samsung,s3c2440-i2c";
                reg = <0x13880000 0x100>;
                interrupts = <0 60 0>;
+               clocks = <&clock 319>;
+               clock-names = "i2c";
                status = "disabled";
        };
 
                compatible = "samsung,s3c2440-i2c";
                reg = <0x13890000 0x100>;
                interrupts = <0 61 0>;
+               clocks = <&clock 320>;
+               clock-names = "i2c";
                status = "disabled";
        };
 
                compatible = "samsung,s3c2440-i2c";
                reg = <0x138A0000 0x100>;
                interrupts = <0 62 0>;
+               clocks = <&clock 321>;
+               clock-names = "i2c";
                status = "disabled";
        };
 
                compatible = "samsung,s3c2440-i2c";
                reg = <0x138B0000 0x100>;
                interrupts = <0 63 0>;
+               clocks = <&clock 322>;
+               clock-names = "i2c";
                status = "disabled";
        };
 
                compatible = "samsung,s3c2440-i2c";
                reg = <0x138C0000 0x100>;
                interrupts = <0 64 0>;
+               clocks = <&clock 323>;
+               clock-names = "i2c";
                status = "disabled";
        };
 
                compatible = "samsung,s3c2440-i2c";
                reg = <0x138D0000 0x100>;
                interrupts = <0 65 0>;
+               clocks = <&clock 324>;
+               clock-names = "i2c";
                status = "disabled";
        };
 
                rx-dma-channel = <&pdma0 6>; /* preliminary */
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 327>, <&clock 159>;
+               clock-names = "spi", "spi_busclk0";
                status = "disabled";
        };
 
                rx-dma-channel = <&pdma1 6>; /* preliminary */
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 328>, <&clock 160>;
+               clock-names = "spi", "spi_busclk0";
                status = "disabled";
        };
 
                rx-dma-channel = <&pdma0 8>; /* preliminary */
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 329>, <&clock 161>;
+               clock-names = "spi", "spi_busclk0";
                status = "disabled";
        };
 
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x12680000 0x1000>;
                        interrupts = <0 35 0>;
+                       clocks = <&clock 292>;
+                       clock-names = "apb_pclk";
+                       #dma-cells = <1>;
+                       #dma-channels = <8>;
+                       #dma-requests = <32>;
                };
 
                pdma1: pdma@12690000 {
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x12690000 0x1000>;
                        interrupts = <0 36 0>;
+                       clocks = <&clock 293>;
+                       clock-names = "apb_pclk";
+                       #dma-cells = <1>;
+                       #dma-channels = <8>;
+                       #dma-requests = <32>;
                };
 
                mdma1: mdma@12850000 {
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x12850000 0x1000>;
                        interrupts = <0 34 0>;
+                       clocks = <&clock 279>;
+                       clock-names = "apb_pclk";
+                       #dma-cells = <1>;
+                       #dma-channels = <8>;
+                       #dma-requests = <1>;
                };
        };
 };
index f2710018e84eca2cb758825d84a6f8acde45ea60..1b30bc8e2654f123ff0624b02e095fdb22b70e1d 100644 (file)
                status = "okay";
        };
 
+       codec@13400000 {
+               samsung,mfc-r = <0x43000000 0x800000>;
+               samsung,mfc-l = <0x51000000 0x800000>;
+               status = "okay";
+       };
+
        serial@13800000 {
                status = "okay";
        };
                        linux,default-trigger = "heartbeat";
                };
        };
+
+       fixed-rate-clocks {
+               xxti {
+                       compatible = "samsung,clock-xxti";
+                       clock-frequency = <0>;
+               };
+
+               xusbxti {
+                       compatible = "samsung,clock-xusbxti";
+                       clock-frequency = <24000000>;
+               };
+       };
 };
index f63490707f3a56646c8cc09edd471009d6644b14..f52c86e2d424059b1a391ace03f9d87e7fc2119d 100644 (file)
                status = "okay";
        };
 
+       codec@13400000 {
+               samsung,mfc-r = <0x43000000 0x800000>;
+               samsung,mfc-l = <0x51000000 0x800000>;
+               status = "okay";
+       };
+
        serial@13800000 {
                status = "okay";
        };
                        };
                };
        };
+
+       fixed-rate-clocks {
+               xxti {
+                       compatible = "samsung,clock-xxti";
+                       clock-frequency = <12000000>;
+               };
+
+               xusbxti {
+                       compatible = "samsung,clock-xusbxti";
+                       clock-frequency = <24000000>;
+               };
+       };
 };
index c346b64dff552ef3d13599846130f63be9068e5e..9a14484c7bb11b61d5e1f1ec3c185a3c50710ecc 100644 (file)
                        };
                };
        };
+
+       fixed-rate-clocks {
+               xxti {
+                       compatible = "samsung,clock-xxti";
+                       clock-frequency = <0>;
+               };
+
+               xusbxti {
+                       compatible = "samsung,clock-xusbxti";
+                       clock-frequency = <24000000>;
+               };
+       };
 };
index 2feffc70814cb9223f052528752be9abeb66c07a..5feccffae409ee135436a3401648aacb8ec3699b 100644 (file)
        };
 
        combiner:interrupt-controller@10440000 {
+               samsung,combiner-nr = <16>;
                interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
                             <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
                             <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
                             <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>;
        };
 
+       mct@10050000 {
+               compatible = "samsung,exynos4210-mct";
+               reg = <0x10050000 0x800>;
+               interrupt-controller;
+               #interrups-cells = <2>;
+               interrupt-parent = <&mct_map>;
+               interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
+                            <4 0>, <5 0>;
+               clocks = <&clock 3>, <&clock 344>;
+               clock-names = "fin_pll", "mct";
+
+               mct_map: mct-map {
+                       #interrupt-cells = <2>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-map = <0x0 0 &gic 0 57 0>,
+                                       <0x1 0 &gic 0 69 0>,
+                                       <0x2 0 &combiner 12 6>,
+                                       <0x3 0 &combiner 12 7>,
+                                       <0x4 0 &gic 0 42 0>,
+                                       <0x5 0 &gic 0 48 0>;
+               };
+       };
+
+       clock: clock-controller@0x10030000 {
+               compatible = "samsung,exynos4210-clock";
+               reg = <0x10030000 0x20000>;
+               #clock-cells = <1>;
+       };
+
+       pmu {
+               compatible = "arm,cortex-a9-pmu";
+               interrupt-parent = <&combiner>;
+               interrupts = <2 2>, <3 2>;
+       };
+
        pinctrl_0: pinctrl@11400000 {
                compatible = "samsung,exynos4210-pinctrl";
                reg = <0x11400000 0x1000>;
index c6ae2005961f2f55bc4cb01bf920e15e83cc1244..c0f60f49cea6dff7d0b84096404f70f2703c99bf 100644 (file)
        gic:interrupt-controller@10490000 {
                cpu-offset = <0x8000>;
        };
+
+       interrupt-controller@10440000 {
+               samsung,combiner-nr = <18>;
+               interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
+                            <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
+                            <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
+                            <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
+                            <0 107 0>, <0 108 0>;
+       };
+
+       mct@10050000 {
+               compatible = "samsung,exynos4412-mct";
+               reg = <0x10050000 0x800>;
+               interrupt-controller;
+               #interrups-cells = <2>;
+               interrupt-parent = <&mct_map>;
+               interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
+                            <4 0>, <5 0>;
+
+               mct_map: mct-map {
+                       #interrupt-cells = <2>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-map = <0x0 0 &gic 0 57 0>,
+                                       <0x1 0 &combiner 12 5>,
+                                       <0x2 0 &combiner 12 6>,
+                                       <0x3 0 &combiner 12 7>,
+                                       <0x4 0 &gic 1 12 0>,
+                                       <0x5 0 &gic 1 12 0>;
+               };
+       };
 };
diff --git a/arch/arm/boot/dts/exynos4412-odroidx.dts b/arch/arm/boot/dts/exynos4412-odroidx.dts
new file mode 100644 (file)
index 0000000..53bc8bf
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * Hardkernel's Exynos4412 based ODROID-X board device tree source
+ *
+ * Copyright (c) 2012 Dongjin Kim <tobetter@gmail.com>
+ *
+ * Device tree source file for Hardkernel's ODROID-X board which is based on
+ * Samsung's Exynos4412 SoC.
+ *
+ * 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/ "exynos4412.dtsi"
+
+/ {
+       model = "Hardkernel ODROID-X board based on Exynos4412";
+       compatible = "hardkernel,odroid-x", "samsung,exynos4412";
+
+       memory {
+               reg = <0x40000000 0x40000000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               led1 {
+                       label = "led1:heart";
+                       gpios = <&gpc1 0 1>;
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
+               };
+               led2 {
+                       label = "led2:mmc0";
+                       gpios = <&gpc1 2 1>;
+                       default-state = "on";
+                       linux,default-trigger = "mmc0";
+               };
+       };
+
+       mshc@12550000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
+               pinctrl-names = "default";
+               status = "okay";
+
+               num-slots = <1>;
+               supports-highspeed;
+               broken-cd;
+               fifo-depth = <0x80>;
+               card-detect-delay = <200>;
+               samsung,dw-mshc-ciu-div = <3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
+
+               slot@0 {
+                       reg = <0>;
+                       bus-width = <8>;
+               };
+       };
+
+       regulator_p3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "p3v3_en";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpa1 1 1>;
+               enable-active-high;
+               regulator-boot-on;
+       };
+
+       rtc@10070000 {
+               status = "okay";
+       };
+
+       sdhci@12530000 {
+               bus-width = <4>;
+               pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>;
+               pinctrl-names = "default";
+               status = "okay";
+       };
+
+       serial@13800000 {
+               status = "okay";
+       };
+
+       serial@13810000 {
+               status = "okay";
+       };
+
+       serial@13820000 {
+               status = "okay";
+       };
+
+       serial@13830000 {
+               status = "okay";
+       };
+
+       fixed-rate-clocks {
+               xxti {
+                       compatible = "samsung,clock-xxti";
+                       clock-frequency = <0>;
+               };
+
+               xusbxti {
+                       compatible = "samsung,clock-xusbxti";
+                       clock-frequency = <24000000>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/exynos4412-origen.dts b/arch/arm/boot/dts/exynos4412-origen.dts
new file mode 100644 (file)
index 0000000..1fecf76
--- /dev/null
@@ -0,0 +1,432 @@
+/*
+ * Insignal's Exynos4412 based Origen board device tree source
+ *
+ * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Device tree source file for Insignal's Origen board which is based on
+ * Samsung's Exynos4412 SoC.
+ *
+ * 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/ "exynos4412.dtsi"
+
+/ {
+       model = "Insignal Origen evaluation board based on Exynos4412";
+       compatible = "insignal,origen4412", "samsung,exynos4412";
+
+       memory {
+               reg = <0x40000000 0x40000000>;
+       };
+
+       chosen {
+               bootargs ="console=ttySAC2,115200";
+       };
+
+       mmc_reg: voltage-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "VMEM_VDD_2.8V";
+               regulator-min-microvolt = <2800000>;
+               regulator-max-microvolt = <2800000>;
+               gpio = <&gpx1 1 0>;
+               enable-active-high;
+       };
+
+       sdhci@12530000 {
+               bus-width = <4>;
+               pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &sd2_cd>;
+               pinctrl-names = "default";
+               vmmc-supply = <&mmc_reg>;
+               status = "okay";
+       };
+
+       mshc@12550000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-0 = <&sd4_clk &sd4_cmd &sd4_bus4 &sd4_bus8>;
+               pinctrl-names = "default";
+               status = "okay";
+
+               num-slots = <1>;
+               supports-highspeed;
+               broken-cd;
+               fifo-depth = <0x80>;
+               card-detect-delay = <200>;
+               samsung,dw-mshc-ciu-div = <3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
+
+               slot@0 {
+                       reg = <0>;
+                       bus-width = <8>;
+               };
+       };
+
+       codec@13400000 {
+               samsung,mfc-r = <0x43000000 0x800000>;
+               samsung,mfc-l = <0x51000000 0x800000>;
+               status = "okay";
+       };
+
+       serial@13800000 {
+               status = "okay";
+       };
+
+       serial@13810000 {
+               status = "okay";
+       };
+
+       serial@13820000 {
+               status = "okay";
+       };
+
+       serial@13830000 {
+               status = "okay";
+       };
+
+       i2c@13860000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               samsung,i2c-sda-delay = <100>;
+               samsung,i2c-max-bus-freq = <20000>;
+               pinctrl-0 = <&i2c0_bus>;
+               pinctrl-names = "default";
+               status = "okay";
+
+               s5m8767_pmic@66 {
+                       compatible = "samsung,s5m8767-pmic";
+                       reg = <0x66>;
+
+                       s5m8767,pmic-buck-default-dvs-idx = <3>;
+
+                       s5m8767,pmic-buck-dvs-gpios = <&gpx2 3 0>,
+                                                        <&gpx2 4 0>,
+                                                        <&gpx2 5 0>;
+
+                       s5m8767,pmic-buck-ds-gpios = <&gpm3 5 0>,
+                                                       <&gpm3 6 0>,
+                                                       <&gpm3 7 0>;
+
+                       s5m8767,pmic-buck2-dvs-voltage = <1250000>, <1200000>,
+                                                        <1200000>, <1200000>,
+                                                        <1200000>, <1200000>,
+                                                        <1200000>, <1200000>;
+
+                       s5m8767,pmic-buck3-dvs-voltage = <1100000>, <1100000>,
+                                                        <1100000>, <1100000>,
+                                                        <1100000>, <1100000>,
+                                                        <1100000>, <1100000>;
+
+                       s5m8767,pmic-buck4-dvs-voltage = <1200000>, <1200000>,
+                                                        <1200000>, <1200000>,
+                                                        <1200000>, <1200000>,
+                                                        <1200000>, <1200000>;
+
+                       regulators {
+                               ldo1_reg: LDO1 {
+                                       regulator-name = "VDD_ALIVE";
+                                       regulator-min-microvolt = <1100000>;
+                                       regulator-max-microvolt = <1100000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo2_reg: LDO2 {
+                                       regulator-name = "VDDQ_M12";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo3_reg: LDO3 {
+                                       regulator-name = "VDDIOAP_18";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo4_reg: LDO4 {
+                                       regulator-name = "VDDQ_PRE";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo5_reg: LDO5 {
+                                       regulator-name = "VDD18_2M";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo6_reg: LDO6 {
+                                       regulator-name = "VDD10_MPLL";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo7_reg: LDO7 {
+                                       regulator-name = "VDD10_XPLL";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo8_reg: LDO8 {
+                                       regulator-name = "VDD10_MIPI";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo9_reg: LDO9 {
+                                       regulator-name = "VDD33_LCD";
+                                       regulator-min-microvolt = <3300000>;
+                                       regulator-max-microvolt = <3300000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo10_reg: LDO10 {
+                                       regulator-name = "VDD18_MIPI";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo11_reg: LDO11 {
+                                       regulator-name = "VDD18_ABB1";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo12_reg: LDO12 {
+                                       regulator-name = "VDD33_UOTG";
+                                       regulator-min-microvolt = <3300000>;
+                                       regulator-max-microvolt = <3300000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo13_reg: LDO13 {
+                                       regulator-name = "VDDIOPERI_18";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo14_reg: LDO14 {
+                                       regulator-name = "VDD18_ABB02";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo15_reg: LDO15 {
+                                       regulator-name = "VDD10_USH";
+                                       regulator-min-microvolt = <1000000>;
+                                       regulator-max-microvolt = <1000000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo16_reg: LDO16 {
+                                       regulator-name = "VDD18_HSIC";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo17_reg: LDO17 {
+                                       regulator-name = "VDDIOAP_MMC012_28";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo18_reg: LDO18 {
+                                       regulator-name = "VDDIOPERI_28";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo19_reg: LDO19 {
+                                       regulator-name = "DVDD25";
+                                       regulator-min-microvolt = <2500000>;
+                                       regulator-max-microvolt = <2500000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo20_reg: LDO20 {
+                                       regulator-name = "VDD28_CAM";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo21_reg: LDO21 {
+                                       regulator-name = "VDD28_AF";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo22_reg: LDO22 {
+                                       regulator-name = "VDDA28_2M";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo23_reg: LDO23 {
+                                       regulator-name = "VDD28_TF";
+                                       regulator-min-microvolt = <2800000>;
+                                       regulator-max-microvolt = <2800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo24_reg: LDO24 {
+                                       regulator-name = "VDD33_A31";
+                                       regulator-min-microvolt = <3300000>;
+                                       regulator-max-microvolt = <3300000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo25_reg: LDO25 {
+                                       regulator-name = "VDD18_CAM";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo26_reg: LDO26 {
+                                       regulator-name = "VDD18_A31";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo27_reg: LDO27 {
+                                       regulator-name = "GPS_1V8";
+                                       regulator-min-microvolt = <1800000>;
+                                       regulator-max-microvolt = <1800000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               ldo28_reg: LDO28 {
+                                       regulator-name = "DVDD12";
+                                       regulator-min-microvolt = <1200000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               buck1_reg: BUCK1 {
+                                       regulator-name = "vdd_mif";
+                                       regulator-min-microvolt = <950000>;
+                                       regulator-max-microvolt = <1100000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               buck2_reg: BUCK2 {
+                                       regulator-name = "vdd_arm";
+                                       regulator-min-microvolt = <925000>;
+                                       regulator-max-microvolt = <1300000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               buck3_reg: BUCK3 {
+                                       regulator-name = "vdd_int";
+                                       regulator-min-microvolt = <900000>;
+                                       regulator-max-microvolt = <1200000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               buck4_reg: BUCK4 {
+                                       regulator-name = "vdd_g3d";
+                                       regulator-min-microvolt = <750000>;
+                                       regulator-max-microvolt = <1500000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               buck5_reg: BUCK5 {
+                                       regulator-name = "vdd_m12";
+                                       regulator-min-microvolt = <750000>;
+                                       regulator-max-microvolt = <1500000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               buck6_reg: BUCK6 {
+                                       regulator-name = "vdd12_5m";
+                                       regulator-min-microvolt = <750000>;
+                                       regulator-max-microvolt = <1500000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+
+                               buck9_reg: BUCK9 {
+                                       regulator-name = "vddf28_emmc";
+                                       regulator-min-microvolt = <750000>;
+                                       regulator-max-microvolt = <3000000>;
+                                       regulator-always-on;
+                                       regulator-boot-on;
+                                       op_mode = <1>; /* Normal Mode */
+                               };
+                       };
+               };
+       };
+
+       fixed-rate-clocks {
+               xxti {
+                       compatible = "samsung,clock-xxti";
+                       clock-frequency = <0>;
+               };
+
+               xusbxti {
+                       compatible = "samsung,clock-xusbxti";
+                       clock-frequency = <24000000>;
+               };
+       };
+};
index f05bf575cc456537b5912f606219b4850ef85bed..874beeaef99d802f09e414d447dcb32ab28e88ad 100644 (file)
                bootargs ="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc";
        };
 
+       sdhci@12530000 {
+               bus-width = <4>;
+               pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_bus4 &sd2_cd>;
+               pinctrl-names = "default";
+               status = "okay";
+       };
+
+       codec@13400000 {
+               samsung,mfc-r = <0x43000000 0x800000>;
+               samsung,mfc-l = <0x51000000 0x800000>;
+               status = "okay";
+       };
+
        serial@13800000 {
                status = "okay";
        };
        serial@13830000 {
                status = "okay";
        };
+
+       fixed-rate-clocks {
+               xxti {
+                       compatible = "samsung,clock-xxti";
+                       clock-frequency = <0>;
+               };
+
+               xusbxti {
+                       compatible = "samsung,clock-xusbxti";
+                       clock-frequency = <24000000>;
+               };
+       };
 };
index d7dfe312772a6e5b26a660d2fcf90b7dcdc8badf..f433206bd3c5ef95c4c8993d9a2d5776b8510a03 100644 (file)
        gic:interrupt-controller@10490000 {
                cpu-offset = <0x4000>;
        };
+
+       interrupt-controller@10440000 {
+               samsung,combiner-nr = <20>;
+               interrupts = <0 0 0>, <0 1 0>, <0 2 0>, <0 3 0>,
+                            <0 4 0>, <0 5 0>, <0 6 0>, <0 7 0>,
+                            <0 8 0>, <0 9 0>, <0 10 0>, <0 11 0>,
+                            <0 12 0>, <0 13 0>, <0 14 0>, <0 15 0>,
+                            <0 107 0>, <0 108 0>, <0 48 0>, <0 42 0>;
+       };
+
+       mct@10050000 {
+               compatible = "samsung,exynos4412-mct";
+               reg = <0x10050000 0x800>;
+               interrupt-controller;
+               #interrups-cells = <2>;
+               interrupt-parent = <&mct_map>;
+               interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
+                            <4 0>, <5 0>, <6 0>, <7 0>;
+               clocks = <&clock 3>, <&clock 344>;
+               clock-names = "fin_pll", "mct";
+
+               mct_map: mct-map {
+                       #interrupt-cells = <2>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-map = <0x0 0 &gic 0 57 0>,
+                                       <0x1 0 &combiner 12 5>,
+                                       <0x2 0 &combiner 12 6>,
+                                       <0x3 0 &combiner 12 7>,
+                                       <0x4 0 &gic 1 12 0>,
+                                       <0x5 0 &gic 1 12 0>,
+                                       <0x6 0 &gic 1 12 0>,
+                                       <0x7 0 &gic 1 12 0>;
+               };
+       };
 };
index 9a87806949093e717b1084e1704f14db33767e06..7496b8d633eaa060df987b525b4ed4eb4d12984a 100644 (file)
                             <0 16 0>, <0 17 0>, <0 18 0>, <0 19 0>;
        };
 
+       clock: clock-controller@0x10030000 {
+               compatible = "samsung,exynos4412-clock";
+               reg = <0x10030000 0x20000>;
+               #clock-cells = <1>;
+       };
+
        pinctrl_0: pinctrl@11400000 {
                compatible = "samsung,exynos4x12-pinctrl";
                reg = <0x11400000 0x1000>;
diff --git a/arch/arm/boot/dts/exynos5250-arndale.dts b/arch/arm/boot/dts/exynos5250-arndale.dts
new file mode 100644 (file)
index 0000000..5de019c
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Samsung's Exynos5250 based Arndale board device tree source
+ *
+ * Copyright (c) 2013 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.
+*/
+
+/dts-v1/;
+/include/ "exynos5250.dtsi"
+
+/ {
+       model = "Insignal Arndale evaluation board based on EXYNOS5250";
+       compatible = "insignal,arndale", "samsung,exynos5250";
+
+       memory {
+               reg = <0x40000000 0x80000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttySAC2,115200";
+       };
+
+       i2c@12C60000 {
+               status = "disabled";
+       };
+
+       i2c@12C70000 {
+               status = "disabled";
+       };
+
+       i2c@12C80000 {
+               status = "disabled";
+       };
+
+       i2c@12C90000 {
+               status = "disabled";
+       };
+
+       i2c@12CA0000 {
+               status = "disabled";
+       };
+
+       i2c@12CB0000 {
+               status = "disabled";
+       };
+
+       i2c@12CC0000 {
+               status = "disabled";
+       };
+
+       i2c@12CD0000 {
+               status = "disabled";
+       };
+
+       i2c@121D0000 {
+               status = "disabled";
+       };
+
+       dwmmc_0: dwmmc0@12200000 {
+               num-slots = <1>;
+               supports-highspeed;
+               broken-cd;
+               fifo-depth = <0x80>;
+               card-detect-delay = <200>;
+               samsung,dw-mshc-ciu-div = <3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
+
+               slot@0 {
+                       reg = <0>;
+                       bus-width = <8>;
+                       gpios = <&gpc0 0 2 0 3>, <&gpc0 1 2 0 3>,
+                               <&gpc0 3 2 3 3>, <&gpc0 4 2 3 3>,
+                               <&gpc0 5 2 3 3>, <&gpc0 6 2 3 3>,
+                               <&gpc1 0 2 3 3>, <&gpc1 1 2 3 3>,
+                               <&gpc1 2 2 3 3>, <&gpc1 3 2 3 3>;
+               };
+       };
+
+       dwmmc_1: dwmmc1@12210000 {
+               status = "disabled";
+       };
+
+       dwmmc_2: dwmmc2@12220000 {
+               num-slots = <1>;
+               supports-highspeed;
+               fifo-depth = <0x80>;
+               card-detect-delay = <200>;
+               samsung,dw-mshc-ciu-div = <3>;
+               samsung,dw-mshc-sdr-timing = <2 3>;
+               samsung,dw-mshc-ddr-timing = <1 2>;
+
+               slot@0 {
+                       reg = <0>;
+                       bus-width = <4>;
+                       samsung,cd-pinmux-gpio = <&gpc3 2 2 3 3>;
+                       gpios = <&gpc3 0 2 0 3>, <&gpc3 1 2 0 3>,
+                               <&gpc3 3 2 3 3>, <&gpc3 4 2 3 3>,
+                               <&gpc3 5 2 3 3>, <&gpc3 6 2 3 3>;
+               };
+       };
+
+       dwmmc_3: dwmmc3@12230000 {
+               status = "disabled";
+       };
+
+       spi_0: spi@12d20000 {
+               status = "disabled";
+       };
+
+       spi_1: spi@12d30000 {
+               status = "disabled";
+       };
+
+       spi_2: spi@12d40000 {
+               status = "disabled";
+       };
+
+       fixed-rate-clocks {
+               xxti {
+                       compatible = "samsung,clock-xxti";
+                       clock-frequency = <24000000>;
+               };
+       };
+};
index 1b8d4106d33859c5f8e61ce94fc6d1c1f543f829..872ae1f93c75288823d52118bce7e716967c859f 100644 (file)
                samsung,i2s-controller = <&i2s0>;
                samsung,audio-codec = <&wm8994>;
        };
+
+       usb@12110000 {
+               samsung,vbus-gpio = <&gpx2 6 1 3 3>;
+       };
+
+       dp-controller {
+               samsung,color-space = <0>;
+               samsung,dynamic-range = <0>;
+               samsung,ycbcr-coeff = <0>;
+               samsung,color-depth = <1>;
+               samsung,link-rate = <0x0a>;
+               samsung,lane-count = <4>;
+       };
+
+       fixed-rate-clocks {
+               xxti {
+                       compatible = "samsung,clock-xxti";
+                       clock-frequency = <24000000>;
+               };
+       };
 };
index 17dd951c1cd2a38787b76aacf09384a9a1bdfcb8..babd9f9b1bf9fdc955303b6c0f758ba0a35337d8 100644 (file)
                                <&gpc4 5 2 3 0>, <&gpc4 6 2 3 0>;
                };
        };
+
+       usb@12110000 {
+               samsung,vbus-gpio = <&gpx1 1 1 3 3>;
+       };
+
+       fixed-rate-clocks {
+               xxti {
+                       compatible = "samsung,clock-xxti";
+                       clock-frequency = <24000000>;
+               };
+       };
 };
index b1ac73e21c80da0de48e6e9d70a585c62c243706..24c52e681b58ee91541ad29e41b27257ea95d7dd 100644 (file)
                i2c8 = &i2c_8;
        };
 
+       pd_gsc: gsc-power-domain@0x10044000 {
+               compatible = "samsung,exynos4210-pd";
+               reg = <0x10044000 0x20>;
+       };
+
+       pd_mfc: mfc-power-domain@0x10044040 {
+               compatible = "samsung,exynos4210-pd";
+               reg = <0x10044040 0x20>;
+       };
+
+       clock: clock-controller@0x10010000 {
+               compatible = "samsung,exynos5250-clock";
+               reg = <0x10010000 0x30000>;
+               #clock-cells = <1>;
+       };
+
        gic:interrupt-controller@10481000 {
                compatible = "arm,cortex-a9-gic";
                #interrupt-cells = <3>;
                             <0 28 0>, <0 29 0>, <0 30 0>, <0 31 0>;
        };
 
+       mct@101C0000 {
+               compatible = "samsung,exynos4210-mct";
+               reg = <0x101C0000 0x800>;
+               interrupt-controller;
+               #interrups-cells = <2>;
+               interrupt-parent = <&mct_map>;
+               interrupts = <0 0>, <1 0>, <2 0>, <3 0>,
+                            <4 0>, <5 0>;
+               clocks = <&clock 1>, <&clock 335>;
+               clock-names = "fin_pll", "mct";
+
+               mct_map: mct-map {
+                       #interrupt-cells = <2>;
+                       #address-cells = <0>;
+                       #size-cells = <0>;
+                       interrupt-map = <0x0 0 &combiner 23 3>,
+                                       <0x1 0 &combiner 23 4>,
+                                       <0x2 0 &combiner 25 2>,
+                                       <0x3 0 &combiner 25 3>,
+                                       <0x4 0 &gic 0 120 0>,
+                                       <0x5 0 &gic 0 121 0>;
+               };
+       };
+
+       pmu {
+               compatible = "arm,cortex-a15-pmu";
+               interrupt-parent = <&combiner>;
+               interrupts = <1 2>, <22 4>;
+       };
+
        watchdog {
                compatible = "samsung,s3c2410-wdt";
                reg = <0x101D0000 0x100>;
                interrupts = <0 42 0>;
+               clocks = <&clock 336>;
+               clock-names = "watchdog";
        };
 
        codec@11000000 {
                compatible = "samsung,mfc-v6";
                reg = <0x11000000 0x10000>;
                interrupts = <0 96 0>;
+               samsung,power-domain = <&pd_mfc>;
        };
 
        rtc {
                compatible = "samsung,s3c6410-rtc";
                reg = <0x101E0000 0x100>;
                interrupts = <0 43 0>, <0 44 0>;
+               clocks = <&clock 337>;
+               clock-names = "rtc";
        };
 
        tmu@10060000 {
                compatible = "samsung,exynos5250-tmu";
                reg = <0x10060000 0x100>;
                interrupts = <0 65 0>;
+               clocks = <&clock 338>;
+               clock-names = "tmu_apbif";
        };
 
        serial@12C00000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0x12C00000 0x100>;
                interrupts = <0 51 0>;
+               clocks = <&clock 289>, <&clock 146>;
+               clock-names = "uart", "clk_uart_baud0";
        };
 
        serial@12C10000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0x12C10000 0x100>;
                interrupts = <0 52 0>;
+               clocks = <&clock 290>, <&clock 147>;
+               clock-names = "uart", "clk_uart_baud0";
        };
 
        serial@12C20000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0x12C20000 0x100>;
                interrupts = <0 53 0>;
+               clocks = <&clock 291>, <&clock 148>;
+               clock-names = "uart", "clk_uart_baud0";
        };
 
        serial@12C30000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0x12C30000 0x100>;
                interrupts = <0 54 0>;
+               clocks = <&clock 292>, <&clock 149>;
+               clock-names = "uart", "clk_uart_baud0";
        };
 
        sata@122F0000 {
                compatible = "samsung,exynos5-sata-ahci";
                reg = <0x122F0000 0x1ff>;
                interrupts = <0 115 0>;
+               clocks = <&clock 277>, <&clock 143>;
+               clock-names = "sata", "sclk_sata";
        };
 
        sata-phy@12170000 {
                interrupts = <0 56 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 294>;
+               clock-names = "i2c";
        };
 
        i2c_1: i2c@12C70000 {
                interrupts = <0 57 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 295>;
+               clock-names = "i2c";
        };
 
        i2c_2: i2c@12C80000 {
                interrupts = <0 58 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 296>;
+               clock-names = "i2c";
        };
 
        i2c_3: i2c@12C90000 {
                interrupts = <0 59 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 297>;
+               clock-names = "i2c";
        };
 
        i2c_4: i2c@12CA0000 {
                interrupts = <0 60 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 298>;
+               clock-names = "i2c";
        };
 
        i2c_5: i2c@12CB0000 {
                interrupts = <0 61 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 299>;
+               clock-names = "i2c";
        };
 
        i2c_6: i2c@12CC0000 {
                interrupts = <0 62 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 300>;
+               clock-names = "i2c";
        };
 
        i2c_7: i2c@12CD0000 {
                interrupts = <0 63 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 301>;
+               clock-names = "i2c";
        };
 
        i2c_8: i2c@12CE0000 {
                interrupts = <0 64 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 302>;
+               clock-names = "i2c";
        };
 
        i2c@121D0000 {
                 reg = <0x121D0000 0x100>;
                 #address-cells = <1>;
                 #size-cells = <0>;
+               clocks = <&clock 288>;
+               clock-names = "i2c";
        };
 
        spi_0: spi@12d20000 {
                dma-names = "tx", "rx";
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 304>, <&clock 154>;
+               clock-names = "spi", "spi_busclk0";
        };
 
        spi_1: spi@12d30000 {
                dma-names = "tx", "rx";
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 305>, <&clock 155>;
+               clock-names = "spi", "spi_busclk0";
        };
 
        spi_2: spi@12d40000 {
                dma-names = "tx", "rx";
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 306>, <&clock 156>;
+               clock-names = "spi", "spi_busclk0";
        };
 
        dwmmc_0: dwmmc0@12200000 {
                interrupts = <0 75 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 280>, <&clock 139>;
+               clock-names = "biu", "ciu";
        };
 
        dwmmc_1: dwmmc1@12210000 {
                interrupts = <0 76 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 281>, <&clock 140>;
+               clock-names = "biu", "ciu";
        };
 
        dwmmc_2: dwmmc2@12220000 {
                interrupts = <0 77 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 282>, <&clock 141>;
+               clock-names = "biu", "ciu";
        };
 
        dwmmc_3: dwmmc3@12230000 {
                interrupts = <0 78 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 283>, <&clock 142>;
+               clock-names = "biu", "ciu";
        };
 
        i2s0: i2s@03830000 {
                dma-names = "tx", "rx";
        };
 
+       usb@12110000 {
+               compatible = "samsung,exynos4210-ehci";
+               reg = <0x12110000 0x100>;
+               interrupts = <0 71 0>;
+       };
+
+       usb@12120000 {
+               compatible = "samsung,exynos4210-ohci";
+               reg = <0x12120000 0x100>;
+               interrupts = <0 71 0>;
+       };
+
        amba {
                #address-cells = <1>;
                #size-cells = <1>;
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x121A0000 0x1000>;
                        interrupts = <0 34 0>;
+                       clocks = <&clock 275>;
+                       clock-names = "apb_pclk";
                        #dma-cells = <1>;
                        #dma-channels = <8>;
                        #dma-requests = <32>;
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x121B0000 0x1000>;
                        interrupts = <0 35 0>;
+                       clocks = <&clock 276>;
+                       clock-names = "apb_pclk";
                        #dma-cells = <1>;
                        #dma-channels = <8>;
                        #dma-requests = <32>;
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x10800000 0x1000>;
                        interrupts = <0 33 0>;
+                       clocks = <&clock 271>;
+                       clock-names = "apb_pclk";
                        #dma-cells = <1>;
                        #dma-channels = <8>;
                        #dma-requests = <1>;
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x11C10000 0x1000>;
                        interrupts = <0 124 0>;
+                       clocks = <&clock 271>;
+                       clock-names = "apb_pclk";
                        #dma-cells = <1>;
                        #dma-channels = <8>;
                        #dma-requests = <1>;
                };
        };
 
+
        gsc_0:  gsc@0x13e00000 {
                compatible = "samsung,exynos5-gsc";
                reg = <0x13e00000 0x1000>;
                interrupts = <0 85 0>;
+               samsung,power-domain = <&pd_gsc>;
+               clocks = <&clock 256>;
+               clock-names = "gscl";
        };
 
        gsc_1:  gsc@0x13e10000 {
                compatible = "samsung,exynos5-gsc";
                reg = <0x13e10000 0x1000>;
                interrupts = <0 86 0>;
+               samsung,power-domain = <&pd_gsc>;
+               clocks = <&clock 257>;
+               clock-names = "gscl";
        };
 
        gsc_2:  gsc@0x13e20000 {
                compatible = "samsung,exynos5-gsc";
                reg = <0x13e20000 0x1000>;
                interrupts = <0 87 0>;
+               samsung,power-domain = <&pd_gsc>;
+               clocks = <&clock 258>;
+               clock-names = "gscl";
        };
 
        gsc_3:  gsc@0x13e30000 {
                compatible = "samsung,exynos5-gsc";
                reg = <0x13e30000 0x1000>;
                interrupts = <0 88 0>;
+               samsung,power-domain = <&pd_gsc>;
+               clocks = <&clock 259>;
+               clock-names = "gscl";
        };
 
        hdmi {
                compatible = "samsung,exynos5-hdmi";
                reg = <0x14530000 0x70000>;
                interrupts = <0 95 0>;
+               clocks = <&clock 333>, <&clock 136>, <&clock 137>,
+                               <&clock 333>, <&clock 333>;
+               clock-names = "hdmi", "sclk_hdmi", "sclk_pixel",
+                               "sclk_hdmiphy", "hdmiphy";
        };
 
        mixer {
                reg = <0x14450000 0x10000>;
                interrupts = <0 94 0>;
        };
+
+       dp-controller {
+               compatible = "samsung,exynos5-dp";
+               reg = <0x145b0000 0x1000>;
+               interrupts = <10 3>;
+               interrupt-parent = <&combiner>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               dptx-phy {
+                       reg = <0x10040720>;
+                       samsung,enable-mask = <1>;
+               };
+       };
 };
index 81e2c964a900f8a74d5efbac4aca73491bcc719a..a21eb4cbe893e11a7eccfe4ae440e00a92a6542a 100644 (file)
                status = "disabled";
        };
 
-       i2c@F0000 {
-               status = "disabled";
-       };
-
-       i2c@100000 {
-               status = "disabled";
-       };
-
-       watchdog {
-               status = "disabled";
-       };
-
-       rtc {
-               status = "disabled";
+       fixed-rate-clocks {
+               xtal {
+                       compatible = "samsung,clock-xtal";
+                       clock-frequency = <50000000>;
+               };
        };
 };
index 5f3562ad67463a89a2bac80a81b1ac01c46907af..c374a31e9c3d59b86dcd79491e655c45499937fb 100644 (file)
 
        interrupt-parent = <&gic>;
 
+       clock: clock-controller@0x160000 {
+               compatible = "samsung,exynos5440-clock";
+               reg = <0x160000 0x1000>;
+               #clock-cells = <1>;
+       };
+
        gic:interrupt-controller@2E0000 {
                compatible = "arm,cortex-a15-gic";
                #interrupt-cells = <3>;
        };
 
        cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
                cpu@0 {
                        compatible = "arm,cortex-a15";
-                       timer {
-                               compatible = "arm,armv7-timer";
-                               interrupts = <1 13 0xf08>;
-                               clock-frequency = <1000000>;
-                       };
+                       reg = <0>;
                };
                cpu@1 {
                        compatible = "arm,cortex-a15";
-                       timer {
-                               compatible = "arm,armv7-timer";
-                               interrupts = <1 14 0xf08>;
-                               clock-frequency = <1000000>;
-                       };
+                       reg = <1>;
                };
                cpu@2 {
                        compatible = "arm,cortex-a15";
-                       timer {
-                               compatible = "arm,armv7-timer";
-                               interrupts = <1 14 0xf08>;
-                               clock-frequency = <1000000>;
-                       };
+                       reg = <2>;
                };
                cpu@3 {
                        compatible = "arm,cortex-a15";
-                       timer {
-                               compatible = "arm,armv7-timer";
-                               interrupts = <1 14 0xf08>;
-                               clock-frequency = <1000000>;
-                       };
+                       reg = <3>;
                };
        };
 
-       common {
-               compatible = "samsung,exynos5440";
-
+       timer {
+               compatible = "arm,cortex-a15-timer",
+                            "arm,armv7-timer";
+               interrupts = <1 13 0xf08>,
+                            <1 14 0xf08>,
+                            <1 11 0xf08>,
+                            <1 10 0xf08>;
+               clock-frequency = <50000000>;
        };
 
        serial@B0000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0xB0000 0x1000>;
                interrupts = <0 2 0>;
+               clocks = <&clock 21>, <&clock 21>;
+               clock-names = "uart", "clk_uart_baud0";
        };
 
        serial@C0000 {
                compatible = "samsung,exynos4210-uart";
                reg = <0xC0000 0x1000>;
                interrupts = <0 3 0>;
+               clocks = <&clock 21>, <&clock 21>;
+               clock-names = "uart", "clk_uart_baud0";
        };
 
        spi {
@@ -83,6 +85,8 @@
                rx-dma-channel = <&pdma0 4>; /* preliminary */
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 21>, <&clock 16>;
+               clock-names = "spi", "spi_busclk0";
        };
 
        pinctrl {
        };
 
        i2c@F0000 {
-               compatible = "samsung,s3c2440-i2c";
+               compatible = "samsung,exynos5440-i2c";
                reg = <0xF0000 0x1000>;
                interrupts = <0 5 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 21>;
+               clock-names = "i2c";
        };
 
        i2c@100000 {
-               compatible = "samsung,s3c2440-i2c";
+               compatible = "samsung,exynos5440-i2c";
                reg = <0x100000 0x1000>;
                interrupts = <0 6 0>;
                #address-cells = <1>;
                #size-cells = <0>;
+               clocks = <&clock 21>;
+               clock-names = "i2c";
        };
 
        watchdog {
                compatible = "samsung,s3c2410-wdt";
                reg = <0x110000 0x1000>;
                interrupts = <0 1 0>;
+               clocks = <&clock 21>;
+               clock-names = "watchdog";
        };
 
        amba {
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x120000 0x1000>;
                        interrupts = <0 34 0>;
+                       clocks = <&clock 21>;
+                       clock-names = "apb_pclk";
+                       #dma-cells = <1>;
+                       #dma-channels = <8>;
+                       #dma-requests = <32>;
                };
 
                pdma1: pdma@121B0000 {
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x121000 0x1000>;
                        interrupts = <0 35 0>;
+                       clocks = <&clock 21>;
+                       clock-names = "apb_pclk";
+                       #dma-cells = <1>;
+                       #dma-channels = <8>;
+                       #dma-requests = <32>;
                };
        };
 
                compatible = "samsung,s3c6410-rtc";
                reg = <0x130000 0x1000>;
                interrupts = <0 17 0>, <0 16 0>;
+               clocks = <&clock 21>;
+               clock-names = "rtc";
        };
 };
index 592fb9dc35bdcd355293e923b5a07bb79d11b1b9..379128eb9d981fc8f38b69cd8420652f48d1f91a 100644 (file)
                                };
                        };
 
-                       ab8500@5 {
+                       ab8500 {
                                ab8500-regulators {
                                        ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
                                                regulator-name = "V-DISPLAY";
index 55f4191a626ede9b0f74d27752ede38d7a547b2b..2b587a74b8136f9d396deedffd9bd43c9bd28f54 100644 (file)
                                };
                        };
 
-                       ab8500@5 {
+                       ab8500 {
                                ab8500-regulators {
                                        ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
                                                regulator-name = "V-DISPLAY";
index e54fffd483690300c2a89e6719a2621b03aa75bb..468c0a1d48d93a0804737cc78494a21234887f3b 100644 (file)
                        fsl,pins = <689 0x10000         /* DISP1_DRDY   */
                                    482 0x10000         /* DISP1_HSYNC  */
                                    489 0x10000         /* DISP1_VSYNC  */
-                                   684 0x10000         /* DISP1_DAT_0  */
                                    515 0x10000         /* DISP1_DAT_22 */
                                    523 0x10000         /* DISP1_DAT_23 */
-                                   543 0x10000         /* DISP1_DAT_21 */
+                                   545 0x10000         /* DISP1_DAT_21 */
                                    553 0x10000         /* DISP1_DAT_20 */
                                    558 0x10000         /* DISP1_DAT_19 */
                                    564 0x10000         /* DISP1_DAT_18 */
index 5bb0bf39d3b88483ffd16828b57fdd8aceca7612..c9c44b2f62d7b6a4248a7f2d84125e14ce4b1284 100644 (file)
 
        ocp@f1000000 {
                serial@12000 {
-                       clock-frequency = <166666667>;
                        status = "okay";
                };
 
                serial@12100 {
-                       clock-frequency = <166666667>;
                        status = "okay";
                };
        };
index d430713ea9b93c3fd746df1e3f4a92cf31796026..e4e4930dc5cf78b9318e9f7015980ab5bd5b90da 100644 (file)
@@ -50,7 +50,6 @@
                        };
                };
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "okay";
                };
        };
index 2e3dd34e21a554298a029dc1bdf563c26f19ea59..0196cf6b0ef29c302e2628767d3284893cc851b9 100644 (file)
@@ -37,7 +37,6 @@
                        };
                };
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index ef2d8c7057093b8ef609488fe56ae45d9991c7b3..289e51d86372895ff6428892fe199cbefa255520 100644 (file)
@@ -38,7 +38,6 @@
                        };
                };
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index 1b133e0c566e80b4c4e47ab1cd2531772065489d..c3573be7b92c18d1bb0b577f200c8d0bcc170351 100644 (file)
                        };
                };
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
                nand@3000000 {
+                       chip-delay = <40>;
                        status = "okay";
 
                        partition@0 {
index 71902da33d6383583659adf35b16d7b3a1684c85..5335b1aa8601309f1ce9dc1a75a21243be1364f0 100644 (file)
@@ -51,7 +51,6 @@
                        };
                };
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "okay";
                };
 
index 504f16be8b54bf682a4c45413a354a48fd27c35e..12ccf74ac3c417e6de31fa5c33a2ab731f136220 100644 (file)
@@ -78,7 +78,6 @@
                        };
                };
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index 6cae4599c4b3e620974dbfa318119db952a56136..93c3afbef9eeecc4b0b3741c2bc2360717da81b9 100644 (file)
                };
 
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index 8db3123ac80f49d0bef30aa4c6c79dcf68690a51..5bbd0542cdd3b97848515a64fd55b49adfd0eaec 100644 (file)
@@ -34,7 +34,6 @@
                };
 
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index 9510c9ea666cc15dad8b512ac6c84d2b2cd8a0d5..9f55d95f35f5806ca126cb23120abbcf0d692a94 100644 (file)
@@ -13,7 +13,6 @@
 
        ocp@f1000000 {
                serial@12000 {
-                       clock-frequency = <166666667>;
                        status = "okay";
                };
        };
index 739019c4cba9c0806ca09da9b2c8cb2fffca2762..5c84c118ed8d6f81e490c9b7924c3aecd2fb845d 100644 (file)
@@ -13,7 +13,6 @@
 
        ocp@f1000000 {
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "okay";
                };
        };
index 662dfd81b1cee275358db30328259529928d99f1..758824118a9a8e22041817183449839f1c9c072e 100644 (file)
@@ -90,7 +90,6 @@
                 };
 
                 serial@12000 {
-                        clock-frequency = <200000000>;
                         status = "ok";
                 };
 
index e8e7ecef1650e3bb9ad6b73d43382a0946a4abff..6affd924fe11c48df75653970cb92cbac7954591 100644 (file)
@@ -23,7 +23,6 @@
                };
 
                serial@12000 {
-                       clock-frequency = <166666667>;
                        status = "okay";
                };
 
index 3a178cf708d729885c78d81926349e9c15fc4f56..a7412b937a8add0c3f0ccfbc165c0a5c3325f50d 100644 (file)
                };
 
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index ede7fe0d7a87d872f9a108f25c479d6fc0c1349d..d27f7245f8e71a07539b041121b66cb06e2402a7 100644 (file)
 
        ocp@f1000000 {
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
                serial@12100 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index 842ff95d60df1f392347abb9b5a1d44981a309be..66eb45b00b25218476c372a5bb1dfc20f3046fb0 100644 (file)
                };
 
                serial@12000 {
-                       clock-frequency = <200000000>;
                        status = "ok";
                };
 
index 2c738d9dc82a17143b1578c3867dbf87e304cef0..fada7e6d24d8543fd956ef18d7981aa12b9b9ee6 100644 (file)
@@ -38,6 +38,7 @@
                        interrupt-controller;
                        #interrupt-cells = <2>;
                        interrupts = <35>, <36>, <37>, <38>;
+                       clocks = <&gate_clk 7>;
                };
 
                gpio1: gpio@10140 {
@@ -49,6 +50,7 @@
                        interrupt-controller;
                        #interrupt-cells = <2>;
                        interrupts = <39>, <40>, <41>;
+                       clocks = <&gate_clk 7>;
                };
 
                serial@12000 {
@@ -57,7 +59,6 @@
                        reg-shift = <2>;
                        interrupts = <33>;
                        clocks = <&gate_clk 7>;
-                       /* set clock-frequency in board dts */
                        status = "disabled";
                };
 
@@ -67,7 +68,6 @@
                        reg-shift = <2>;
                        interrupts = <34>;
                        clocks = <&gate_clk 7>;
-                       /* set clock-frequency in board dts */
                        status = "disabled";
                };
 
@@ -75,6 +75,7 @@
                        compatible = "marvell,kirkwood-rtc", "marvell,orion-rtc";
                        reg = <0x10300 0x20>;
                        interrupts = <53>;
+                       clocks = <&gate_clk 7>;
                };
 
                spi@10600 {
index f624dc85d441e5000b8fa0a13abfa78a3e5ce7d2..02d23f15fd867fafe2172a1eb75e60beab51a5c7 100644 (file)
                };
        };
 
+       /* HS USB Port 2 RESET */
+       hsusb2_reset: hsusb2_reset_reg {
+               compatible = "regulator-fixed";
+               regulator-name = "hsusb2_reset";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio5 19 0>;   /* gpio_147 */
+               startup-delay-us = <70000>;
+               enable-active-high;
+       };
+
+       /* HS USB Port 2 Power */
+       hsusb2_power: hsusb2_power_reg {
+               compatible = "regulator-fixed";
+               regulator-name = "hsusb2_vbus";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&twl_gpio 18 0>;        /* GPIO LEDA */
+               startup-delay-us = <70000>;
+       };
+
+       /* HS USB Host PHY on PORT 2 */
+       hsusb2_phy: hsusb2_phy {
+               compatible = "usb-nop-xceiv";
+               reset-supply = <&hsusb2_reset>;
+               vcc-supply = <&hsusb2_power>;
+       };
+};
+
+&omap3_pmx_core {
+       pinctrl-names = "default";
+       pinctrl-0 = <
+                       &hsusbb2_pins
+       >;
+
+       hsusbb2_pins: pinmux_hsusbb2_pins {
+               pinctrl-single,pins = <
+                       0x5c0 0x3  /* USBB2_ULPITLL_CLK_MUXMODE.usbb1_ulpiphy_clk OUTPUT */
+                       0x5c2 0x3  /* USBB2_ULPITLL_CLK_MUXMODE.usbb1_ulpiphy_stp OUTPUT */
+                       0x5c4 0x10b  /* USBB2_ULPITLL_CLK_MUXMODE.usbb1_ulpiphy_dir INPUT | PULLDOWN */
+                       0x5c6 0x10b  /* USBB2_ULPITLL_CLK_MUXMODE.usbb1_ulpiphy_nxt INPUT | PULLDOWN */
+                       0x5c8 0x10b  /* USBB2_ULPITLL_CLK_MUXMODE.usbb1_ulpiphy_dat0 INPUT | PULLDOWN */
+                       0x5cA 0x10b  /* USBB2_ULPITLL_CLK_MUXMODE.usbb1_ulpiphy_dat1 INPUT | PULLDOWN */
+                       0x1a4 0x10b  /* USBB2_ULPITLL_CLK_MUXMODE.usbb1_ulpiphy_dat2 INPUT | PULLDOWN */
+                       0x1a6 0x10b  /* USBB2_ULPITLL_CLK_MUXMODE.usbb1_ulpiphy_dat3 INPUT | PULLDOWN */
+                       0x1a8 0x10b  /* USBB2_ULPITLL_CLK_MUXMODE.usbb1_ulpiphy_dat4 INPUT | PULLDOWN */
+                       0x1aa 0x10b  /* USBB2_ULPITLL_CLK_MUXMODE.usbb1_ulpiphy_dat5 INPUT | PULLDOWN */
+                       0x1ac 0x10b  /* USBB2_ULPITLL_CLK_MUXMODE.usbb1_ulpiphy_dat6 INPUT | PULLDOWN */
+                       0x1ae 0x10b  /* USBB2_ULPITLL_CLK_MUXMODE.usbb1_ulpiphy_dat7 INPUT | PULLDOWN */
+               >;
+       };
 };
 
 &i2c1 {
 &mmc3 {
        status = "disabled";
 };
+
+&usbhshost {
+       port2-mode = "ehci-phy";
+};
+
+&usbhsehci {
+       phys = <0 &hsusb2_phy>;
+};
+
+&twl_gpio {
+       ti,use-leds;
+       /* pullups: BIT(1) */
+       ti,pullups = <0x000002>;
+       /*
+        * pulldowns:
+        * BIT(2), BIT(6), BIT(7), BIT(8), BIT(13)
+        * BIT(15), BIT(16), BIT(17)
+        */
+       ti,pulldowns = <0x03a1c4>;
+};
index 1acc26148ffcf94c1ee605d1db58c531f9b01e26..a14f74bbce7c0079238486899ba3037dcf926c62 100644 (file)
                        ti,timer-alwon;
                        ti,timer-secure;
                };
+
+               usbhstll: usbhstll@48062000 {
+                       compatible = "ti,usbhs-tll";
+                       reg = <0x48062000 0x1000>;
+                       interrupts = <78>;
+                       ti,hwmods = "usb_tll_hs";
+               };
+
+               usbhshost: usbhshost@48064000 {
+                       compatible = "ti,usbhs-host";
+                       reg = <0x48064000 0x400>;
+                       ti,hwmods = "usb_host_hs";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       usbhsohci: ohci@48064400 {
+                               compatible = "ti,ohci-omap3", "usb-ohci";
+                               reg = <0x48064400 0x400>;
+                               interrupt-parent = <&intc>;
+                               interrupts = <76>;
+                       };
+
+                       usbhsehci: ehci@48064800 {
+                               compatible = "ti,ehci-omap", "usb-ehci";
+                               reg = <0x48064800 0x400>;
+                               interrupt-parent = <&intc>;
+                               interrupts = <77>;
+                       };
+               };
+
        };
 };
index 739bb79e410e5bb5f558afdc85d227d9e5056885..b7db1a2b6ca7a9a3200a1087372d9c988dcab5a7 100644 (file)
                        ti,hwmods = "timer11";
                        ti,timer-pwm;
                };
+
+               usbhstll: usbhstll@4a062000 {
+                       compatible = "ti,usbhs-tll";
+                       reg = <0x4a062000 0x1000>;
+                       interrupts = <0 78 0x4>;
+                       ti,hwmods = "usb_tll_hs";
+               };
+
+               usbhshost: usbhshost@4a064000 {
+                       compatible = "ti,usbhs-host";
+                       reg = <0x4a064000 0x800>;
+                       ti,hwmods = "usb_host_hs";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       usbhsohci: ohci@4a064800 {
+                               compatible = "ti,ohci-omap3", "usb-ohci";
+                               reg = <0x4a064800 0x400>;
+                               interrupt-parent = <&gic>;
+                               interrupts = <0 76 0x4>;
+                       };
+
+                       usbhsehci: ehci@4a064c00 {
+                               compatible = "ti,ehci-omap", "usb-ehci";
+                               reg = <0x4a064c00 0x400>;
+                               interrupt-parent = <&gic>;
+                               interrupts = <0 77 0x4>;
+                       };
+               };
        };
 };
index 5a3a58b7e18fa134d71094ea27b5138b5ca5abc3..0077fc8510b78d5b92b03a5f3a7951ee5e9d5753 100644 (file)
@@ -11,7 +11,7 @@
 
 / {
        model = "LaCie Ethernet Disk mini V2";
-       compatible = "lacie,ethernet-disk-mini-v2", "marvell-orion5x-88f5182", "marvell,orion5x";
+       compatible = "lacie,ethernet-disk-mini-v2", "marvell,orion5x-88f5182", "marvell,orion5x";
 
        memory {
                reg = <0x00000000 0x4000000>; /* 64 MB */
index 8aad00f81ed9393118e64b38bfe96dc9aab56d28..f7bec3b1ba323538c7ef26d3f9b2aa5cd68b00cc 100644 (file)
@@ -13,6 +13,9 @@
        compatible = "marvell,orion5x";
        interrupt-parent = <&intc>;
 
+       aliases {
+               gpio0 = &gpio0;
+       };
        intc: interrupt-controller {
                compatible = "marvell,orion-intc", "marvell,intc";
                interrupt-controller;
@@ -32,7 +35,9 @@
                        #gpio-cells = <2>;
                        gpio-controller;
                        reg = <0x10100 0x40>;
-                       ngpio = <32>;
+                       ngpios = <32>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
                        interrupts = <6>, <7>, <8>, <9>;
                };
 
@@ -91,7 +96,7 @@
                        reg = <0x90000 0x10000>,
                              <0xf2200000 0x800>;
                        reg-names = "regs", "sram";
-                       interrupts = <22>;
+                       interrupts = <28>;
                        status = "okay";
                };
        };
diff --git a/arch/arm/boot/dts/r8a7779.dtsi b/arch/arm/boot/dts/r8a7779.dtsi
new file mode 100644 (file)
index 0000000..fe5c6f2
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Device Tree Source for Renesas r8a7779
+ *
+ * Copyright (C) 2013 Renesas Solutions Corp.
+ * Copyright (C) 2013 Simon Horman
+ *
+ * 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 = "renesas,r8a7779";
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <0>;
+               };
+               cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <1>;
+               };
+               cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <2>;
+               };
+               cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a9";
+                       reg = <3>;
+               };
+       };
+
+        gic: interrupt-controller@f0001000 {
+                compatible = "arm,cortex-a9-gic";
+                #interrupt-cells = <3>;
+                interrupt-controller;
+                reg = <0xf0001000 0x1000>,
+                      <0xf0000100 0x100>;
+        };
+
+       i2c0: i2c@0xffc70000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,rmobile-iic";
+               reg = <0xffc70000 0x1000>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 79 0x4>;
+       };
+
+       i2c1: i2c@0xffc71000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,rmobile-iic";
+               reg = <0xffc71000 0x1000>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 82 0x4>;
+       };
+
+       i2c2: i2c@0xffc72000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,rmobile-iic";
+               reg = <0xffc72000 0x1000>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 80 0x4>;
+       };
+
+       i2c3: i2c@0xffc73000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "renesas,rmobile-iic";
+               reg = <0xffc73000 0x1000>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 81 0x4>;
+       };
+
+       thermal@ffc48000 {
+               compatible = "renesas,rcar-thermal";
+               reg = <0xffc48000 0x38>;
+       };
+
+       sata: sata@fc600000 {
+               compatible = "renesas,rcar-sata";
+               reg = <0xfc600000 0x2000>;
+               interrupt-parent = <&gic>;
+               interrupts = <0 100 0x4>;
+       };
+};
index 27f31a5fa4947aa530d74cfa4c0260fc406ace7e..d3ec32f6b79073fc7171f966f47257cac86aabfb 100644 (file)
                                };
                        };
 
-                       ab8500@5 {
+                       ab8500 {
                                ab8500-regulators {
                                        ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
                                                regulator-name = "V-DISPLAY";
index 936d2306e7e12e9e46fd09294b6af54e41f0ccb3..7e8769bd59774334ce330c27b91e96d5783ee93e 100644 (file)
@@ -75,6 +75,9 @@
                                compatible = "arm,pl330", "arm,primecell";
                                reg = <0xffe01000 0x1000>;
                                interrupts = <0 180 4>;
+                               #dma-cells = <1>;
+                               #dma-channels = <8>;
+                               #dma-requests = <32>;
                        };
                };
 
index a30aca62658ad192691dc81800f9a1f27fe6cb1e..616990dc92dba2a6ee1f5aec7177a22d21018e45 100644 (file)
 
        serial@70006300 {
                status = "okay";
-               clock-frequency = <408000000>;
        };
 
        pmc {
                nvidia,invert-interrupt;
        };
+
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock {
+                       compatible = "fixed-clock";
+                       reg=<0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
 };
index 9bea8f57aa47f6010441066dee01367df3887153..6bbc8efae9c0e88018c35bb4465db3f7c19801e5 100644 (file)
 
        serial@70006300 {
                status = "okay";
-               clock-frequency = <408000000>;
        };
 
        pmc {
                nvidia,invert-interrupt;
        };
+
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock {
+                       compatible = "fixed-clock";
+                       reg=<0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
 };
index 1dfaf2874c57261a2c108073ed47d2131c3188eb..c1110a9b2a9122f319c81cdff5ceae681caf06ff 100644 (file)
                              0 42 0x04
                              0 121 0x04
                              0 122 0x04>;
+               clocks = <&tegra_car 5>;
        };
 
        tegra_car: clock {
-               compatible = "nvidia,tegra114-car, nvidia,tegra30-car";
+               compatible = "nvidia,tegra114-car";
                reg = <0x60006000 0x1000>;
                #clock-cells = <1>;
        };
@@ -66,6 +67,7 @@
                reg-shift = <2>;
                interrupts = <0 36 0x04>;
                status = "disabled";
+               clocks = <&tegra_car 6>;
        };
 
        serial@70006040 {
@@ -74,6 +76,7 @@
                reg-shift = <2>;
                interrupts = <0 37 0x04>;
                status = "disabled";
+               clocks = <&tegra_car 192>;
        };
 
        serial@70006200 {
@@ -82,6 +85,7 @@
                reg-shift = <2>;
                interrupts = <0 46 0x04>;
                status = "disabled";
+               clocks = <&tegra_car 55>;
        };
 
        serial@70006300 {
                reg-shift = <2>;
                interrupts = <0 90 0x04>;
                status = "disabled";
+               clocks = <&tegra_car 65>;
        };
 
        rtc {
                compatible = "nvidia,tegra114-rtc", "nvidia,tegra20-rtc";
                reg = <0x7000e000 0x100>;
                interrupts = <0 2 0x04>;
+               clocks = <&tegra_car 4>;
        };
 
        pmc {
-               compatible = "nvidia,tegra114-pmc", "nvidia,tegra30-pmc";
+               compatible = "nvidia,tegra114-pmc";
                reg = <0x7000e400 0x400>;
+               clocks = <&tegra_car 261>, <&clk32k_in>;
+               clock-names = "pclk", "clk32k_in";
        };
 
        iommu {
index 444162090042cf4f59f6961b1cd839ac14764c0c..4e3afdef28a87e4fc9b8fb97a0bc5105a0a53f1f 100644 (file)
        };
 
        sdhci@c8000600 {
-               cd-gpios = <&gpio 23 0>; /* gpio PC7 */
+               cd-gpios = <&gpio 23 1>; /* gpio PC7 */
+       };
+
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock {
+                       compatible = "fixed-clock";
+                       reg=<0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
        };
 
        sound {
index 61d027f03617d36a2ef87cdc2978e5a34320f95c..ae9d5a20834e542c364bd146474f803148f41d2d 100644 (file)
 
        sdhci@c8000200 {
                status = "okay";
-               cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+               cd-gpios = <&gpio 69 1>; /* gpio PI5 */
                wp-gpios = <&gpio 57 0>; /* gpio PH1 */
                power-gpios = <&gpio 155 0>; /* gpio PT3 */
                bus-width = <4>;
 
        sdhci@c8000600 {
                status = "okay";
-               cd-gpios = <&gpio 58 0>; /* gpio PH2 */
+               cd-gpios = <&gpio 58 1>; /* gpio PH2 */
                wp-gpios = <&gpio 59 0>; /* gpio PH3 */
                power-gpios = <&gpio 70 0>; /* gpio PI6 */
                bus-width = <8>;
        };
 
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock {
+                       compatible = "fixed-clock";
+                       reg=<0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+
        kbc {
                status = "okay";
                nvidia,debounce-delay-ms = <2>;
index 54d6fce00a59e4cfa4296d5715c50d00f8543eb7..fd60940e40636949aba4aa23e5ca5acd7efdf7ea 100644 (file)
 
        sdhci@c8000000 {
                status = "okay";
-               cd-gpios = <&gpio 173 0>; /* gpio PV5 */
+               cd-gpios = <&gpio 173 1>; /* gpio PV5 */
                wp-gpios = <&gpio 57 0>;  /* gpio PH1 */
                power-gpios = <&gpio 169 0>; /* gpio PV1 */
                bus-width = <4>;
                bus-width = <8>;
        };
 
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock {
+                       compatible = "fixed-clock";
+                       reg=<0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+
        gpio-keys {
                compatible = "gpio-keys";
 
index 37b3a57ec0f15ad4b330251fbc1a20526cbdb788..4ee700a33ca55e4fbf00c0202cc85217d02ee10f 100644 (file)
 
        sdhci@c8000400 {
                status = "okay";
-               cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+               cd-gpios = <&gpio 69 1>; /* gpio PI5 */
                wp-gpios = <&gpio 57 0>; /* gpio PH1 */
                power-gpios = <&gpio 70 0>; /* gpio PI6 */
                bus-width = <4>;
                bus-width = <8>;
        };
 
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock {
+                       compatible = "fixed-clock";
+                       reg=<0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+
        gpio-keys {
                compatible = "gpio-keys";
 
index 4766abae7a72bb20a984e2914e1dd3c76d60356e..c190257259182b6668c156b46ea8259957435e9b 100644 (file)
        };
 
        sdhci@c8000600 {
-               cd-gpios = <&gpio 58 0>; /* gpio PH2 */
+               cd-gpios = <&gpio 58 1>; /* gpio PH2 */
                wp-gpios = <&gpio 59 0>; /* gpio PH3 */
                bus-width = <4>;
                status = "okay";
        };
 
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock {
+                       compatible = "fixed-clock";
+                       reg=<0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+
        regulators {
                compatible = "simple-bus";
 
index 5d79e4fc49a63577a599f428533b185552897281..a9f3f06580f5fc9c82a7b5e4c9f281bcbb9b2eb2 100644 (file)
 
        sdhci@c8000600 {
                status = "okay";
-               cd-gpios = <&gpio 121 0>; /* gpio PP1 */
+               cd-gpios = <&gpio 121 1>; /* gpio PP1 */
                wp-gpios = <&gpio 122 0>; /* gpio PP2 */
                bus-width = <4>;
        };
 
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock {
+                       compatible = "fixed-clock";
+                       reg=<0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+
        poweroff {
                compatible = "gpio-poweroff";
                gpios = <&gpio 191 1>; /* gpio PX7, active low */
index 425c89000c20ebd6cd55ff353bb45253fc7fa79f..f544806e9618d6aa8cdf70dc4ef59078fc992aa4 100644 (file)
 
        sdhci@c8000400 {
                status = "okay";
-               cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+               cd-gpios = <&gpio 69 1>; /* gpio PI5 */
                wp-gpios = <&gpio 57 0>; /* gpio PH1 */
                power-gpios = <&gpio 70 0>; /* gpio PI6 */
                bus-width = <4>;
                bus-width = <8>;
        };
 
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock {
+                       compatible = "fixed-clock";
+                       reg=<0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+
        regulators {
                compatible = "simple-bus";
                #address-cells = <1>;
index ea57c0f6dccea46b98d4f06d40eb3446df8e5d10..258cf945f515265b02dafbb419170519259a1bd0 100644 (file)
 
        sdhci@c8000400 {
                status = "okay";
+               cd-gpios = <&gpio 69 1>; /* gpio PI5 */
                wp-gpios = <&gpio 173 0>; /* gpio PV5 */
                bus-width = <8>;
        };
                bus-width = <8>;
        };
 
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock {
+                       compatible = "fixed-clock";
+                       reg=<0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+
        kbc {
                status = "okay";
                nvidia,debounce-delay-ms = <20>;
index 9a428931d0429d2befef3d6d3084b7499eeb3a02..fc7febc2b386ade8311ff18b11a6e938ebacd885 100644 (file)
                compatible = "arm,cortex-a9-twd-timer";
                reg = <0x50040600 0x20>;
                interrupts = <1 13 0x304>;
+               clocks = <&tegra_car 132>;
        };
 
        intc: interrupt-controller {
                              0 1 0x04
                              0 41 0x04
                              0 42 0x04>;
+               clocks = <&tegra_car 5>;
        };
 
        tegra_car: clock {
                compatible = "nvidia,tegra20-rtc";
                reg = <0x7000e000 0x100>;
                interrupts = <0 2 0x04>;
+               clocks = <&tegra_car 4>;
        };
 
        i2c@7000c000 {
 
        spi@7000d800 {
                compatible = "nvidia,tegra20-slink";
-               reg = <0x7000d480 0x200>;
+               reg = <0x7000d800 0x200>;
                interrupts = <0 83 0x04>;
                nvidia,dma-request-selector = <&apbdma 17>;
                #address-cells = <1>;
        pmc {
                compatible = "nvidia,tegra20-pmc";
                reg = <0x7000e400 0x400>;
+               clocks = <&tegra_car 110>, <&clk32k_in>;
+               clock-names = "pclk", "clk32k_in";
        };
 
        memory-controller@7000f000 {
index 8ff2ff20e4a34a3799be59fc6f3b5dff5e621329..6248b2445b32e3df61b0344b3a436f69edef1f62 100644 (file)
 
        sdhci@78000000 {
                status = "okay";
-               cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+               cd-gpios = <&gpio 69 1>; /* gpio PI5 */
                wp-gpios = <&gpio 155 0>; /* gpio PT3 */
                power-gpios = <&gpio 31 0>; /* gpio PD7 */
                bus-width = <4>;
                bus-width = <8>;
        };
 
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock {
+                       compatible = "fixed-clock";
+                       reg=<0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+
        regulators {
                compatible = "simple-bus";
                #address-cells = <1>;
index 17499272a4ef97e2df09fc8ced7f07bf13255aaa..65bf2b63174e772c2c8856f91d4fed51b182bdca 100644 (file)
 
        sdhci@78000000 {
                status = "okay";
-               cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+               cd-gpios = <&gpio 69 1>; /* gpio PI5 */
                wp-gpios = <&gpio 155 0>; /* gpio PT3 */
                power-gpios = <&gpio 31 0>; /* gpio PD7 */
                bus-width = <4>;
                bus-width = <8>;
        };
 
+       clocks {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               clk32k_in: clock {
+                       compatible = "fixed-clock";
+                       reg=<0>;
+                       #clock-cells = <0>;
+                       clock-frequency = <32768>;
+               };
+       };
+
        regulators {
                compatible = "simple-bus";
                #address-cells = <1>;
index 767803e1fd55f2d6e75053527e47a26d536e4f77..9fe7a92b4c8508e4925abf76205b08202d02e07f 100644 (file)
                compatible = "arm,cortex-a9-twd-timer";
                reg = <0x50040600 0x20>;
                interrupts = <1 13 0xf04>;
+               clocks = <&tegra_car 214>;
        };
 
        intc: interrupt-controller {
                              0 42 0x04
                              0 121 0x04
                              0 122 0x04>;
+               clocks = <&tegra_car 5>;
        };
 
        tegra_car: clock {
                compatible = "nvidia,tegra30-rtc", "nvidia,tegra20-rtc";
                reg = <0x7000e000 0x100>;
                interrupts = <0 2 0x04>;
+               clocks = <&tegra_car 4>;
        };
 
        i2c@7000c000 {
 
        spi@7000d800 {
                compatible = "nvidia,tegra30-slink", "nvidia,tegra20-slink";
-               reg = <0x7000d480 0x200>;
+               reg = <0x7000d800 0x200>;
                interrupts = <0 83 0x04>;
                nvidia,dma-request-selector = <&apbdma 17>;
                #address-cells = <1>;
        };
 
        pmc {
-               compatible = "nvidia,tegra20-pmc", "nvidia,tegra30-pmc";
+               compatible = "nvidia,tegra30-pmc";
                reg = <0x7000e400 0x400>;
+               clocks = <&tegra_car 218>, <&clk32k_in>;
+               clock-names = "pclk", "clk32k_in";
        };
 
        memory-controller {
index cf31ced46602e1ef8c24bf8a1fed2634488e8845..e1c3926aca52bec4dfa70be136831c5889b63552 100644 (file)
                        #interrupt-cells = <1>;
                };
 
-               gpio: gpio-controller@d8110000 {
-                       compatible = "via,vt8500-gpio";
-                       gpio-controller;
+               pinctrl: pinctrl@d8110000 {
+                       compatible = "via,vt8500-pinctrl";
                        reg = <0xd8110000 0x10000>;
-                       #gpio-cells = <3>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
                };
 
                pmc@d8130000 {
index e74a1c0fb9a2998ef91dbf58019850644711465f..bb92ef8ce66517c51689b2ed61d45198ca60bd73 100644 (file)
                        interrupts = <56 57 58 59 60 61 62 63>;
                };
 
-               gpio: gpio-controller@d8110000 {
-                       compatible = "wm,wm8505-gpio";
-                       gpio-controller;
+               pinctrl: pinctrl@d8110000 {
+                       compatible = "wm,wm8505-pinctrl";
                        reg = <0xd8110000 0x10000>;
-                       #gpio-cells = <3>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
                };
 
                pmc@d8130000 {
index db3c0a12e052782641bd23731bf58aa4f4d4cc62..bb4af580f40bccf64aad0e787581e8fac73d312b 100644 (file)
                        interrupts = <56 57 58 59 60 61 62 63>;
                };
 
-               gpio: gpio-controller@d8110000 {
-                       compatible = "wm,wm8650-gpio";
-                       gpio-controller;
+               pinctrl: pinctrl@d8110000 {
+                       compatible = "wm,wm8650-pinctrl";
                        reg = <0xd8110000 0x10000>;
-                       #gpio-cells = <3>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
                };
 
                pmc@d8130000 {
index e8cbfdc87bba4bcfaa64089377727b02db13b0a3..11cd180c58d3ae67979d0ab325246591903f969b 100644 (file)
                        interrupts = <56 57 58 59 60 61 62 63>;
                };
 
-               gpio: gpio-controller@d8110000 {
-                       compatible = "wm,wm8650-gpio";
-                       gpio-controller;
+               pinctrl: pinctrl@d8110000 {
+                       compatible = "wm,wm8850-pinctrl";
                        reg = <0xd8110000 0x10000>;
-                       #gpio-cells = <3>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
                };
 
                pmc@d8130000 {
index 5914b5654591083f9a14e8d8cab15bd1fc47a3ef..51243db2e9e4cd812ce435b8f534e7c26028cd4a 100644 (file)
                };
 
                ttc0: ttc0@f8001000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       compatible = "xlnx,ttc";
+                       interrupt-parent = <&intc>;
+                       interrupts = < 0 10 4 0 11 4 0 12 4 >;
+                       compatible = "cdns,ttc";
                        reg = <0xF8001000 0x1000>;
                        clocks = <&cpu_clk 3>;
                        clock-names = "cpu_1x";
                        clock-ranges;
-
-                       ttc0_0: ttc0.0 {
-                               status = "disabled";
-                               reg = <0>;
-                               interrupts = <0 10 4>;
-                       };
-                       ttc0_1: ttc0.1 {
-                               status = "disabled";
-                               reg = <1>;
-                               interrupts = <0 11 4>;
-                       };
-                       ttc0_2: ttc0.2 {
-                               status = "disabled";
-                               reg = <2>;
-                               interrupts = <0 12 4>;
-                       };
                };
 
                ttc1: ttc1@f8002000 {
-                       #interrupt-parent = <&intc>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       compatible = "xlnx,ttc";
+                       interrupt-parent = <&intc>;
+                       interrupts = < 0 37 4 0 38 4 0 39 4 >;
+                       compatible = "cdns,ttc";
                        reg = <0xF8002000 0x1000>;
                        clocks = <&cpu_clk 3>;
                        clock-names = "cpu_1x";
                        clock-ranges;
-
-                       ttc1_0: ttc1.0 {
-                               status = "disabled";
-                               reg = <0>;
-                               interrupts = <0 37 4>;
-                       };
-                       ttc1_1: ttc1.1 {
-                               status = "disabled";
-                               reg = <1>;
-                               interrupts = <0 38 4>;
-                       };
-                       ttc1_2: ttc1.2 {
-                               status = "disabled";
-                               reg = <2>;
-                               interrupts = <0 39 4>;
-                       };
                };
        };
 };
index c772942a399af0bf6d6682baea61a195c5ba4c3b..86f44d5b0265bf8fe3b7c6da4370d409e7f9b7d0 100644 (file)
 &ps_clk {
        clock-frequency = <33333330>;
 };
-
-&ttc0_0 {
-       status = "ok";
-       compatible = "xlnx,ttc-counter-clocksource";
-};
-
-&ttc0_1 {
-       status = "ok";
-       compatible = "xlnx,ttc-counter-clockevent";
-};
index bffe68e190a3d93157886557e1958bde59798648..ae90a0f7d53cab9e9ce5a0aabacb3135cd8fe8ca 100644 (file)
@@ -4,7 +4,7 @@ CONFIG_KALLSYMS_ALL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
-CONFIG_ARCH_EXYNOS=y
+CONFIG_ARCH_EXYNOS_SINGLE=y
 CONFIG_S3C_LOWLEVEL_UART_PORT=1
 CONFIG_MACH_SMDKC210=y
 CONFIG_MACH_ARMLEX4210=y
index fbbc5bb022d56ad6f6244405cc0e0911eccfdfe0..6a99e30f81d2ac992da503ba5338571c2d2731ba 100644 (file)
@@ -116,6 +116,7 @@ CONFIG_SND_SOC=y
 CONFIG_SND_MXS_SOC=y
 CONFIG_SND_SOC_MXS_SGTL5000=y
 CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA_HOST=y
 CONFIG_USB_STORAGE=y
index b16bae2c9a600f504c442c1c9f5513179e8d710a..bd07864f14a00b0fd9608139cb607ae9f021a154 100644 (file)
@@ -126,6 +126,8 @@ CONFIG_INPUT_MISC=y
 CONFIG_INPUT_TWL4030_PWRBUTTON=y
 CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=32
 CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
index 720799fd3a81195f02563ed5540d649adea14e05..dff714d886d58dbdce93a468e6a098cf45db98f6 100644 (file)
@@ -24,7 +24,7 @@ extern struct arm_delay_ops {
        void (*delay)(unsigned long);
        void (*const_udelay)(unsigned long);
        void (*udelay)(unsigned long);
-       bool const_clock;
+       unsigned long ticks_per_jiffy;
 } arm_delay_ops;
 
 #define __delay(n)             arm_delay_ops.delay(n)
index 8c5e828f484dd7a039a2c5c9d060d6bba008c0ef..91b99abe7a95c114be0d3b628fb8b8d09f781c74 100644 (file)
@@ -41,6 +41,13 @@ extern void kunmap_high(struct page *page);
 #endif
 #endif
 
+/*
+ * Needed to be able to broadcast the TLB invalidation for kmap.
+ */
+#ifdef CONFIG_ARM_ERRATA_798181
+#undef ARCH_NEEDS_KMAP_HIGH_GET
+#endif
+
 #ifdef ARCH_NEEDS_KMAP_HIGH_GET
 extern void *kmap_high_get(struct page *page);
 #else
index 863a6611323c70077a9428b198a10d59758ff919..a7b85e0d0cc154a90a2efadca763cc60d95e82d8 100644 (file)
@@ -27,6 +27,8 @@ void __check_vmalloc_seq(struct mm_struct *mm);
 void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk);
 #define init_new_context(tsk,mm)       ({ atomic64_set(&mm->context.id, 0); 0; })
 
+DECLARE_PER_CPU(atomic64_t, active_asids);
+
 #else  /* !CONFIG_CPU_HAS_ASID */
 
 #ifdef CONFIG_MMU
index 4db8c8820f0d1c832bf9efd5e81a69d32b4fc7d7..9e9c041358ca8789e4a6798aaf871007795e8fb9 100644 (file)
@@ -450,6 +450,21 @@ static inline void local_flush_bp_all(void)
                isb();
 }
 
+#ifdef CONFIG_ARM_ERRATA_798181
+static inline void dummy_flush_tlb_a15_erratum(void)
+{
+       /*
+        * Dummy TLBIMVAIS. Using the unmapped address 0 and ASID 0.
+        */
+       asm("mcr p15, 0, %0, c8, c3, 1" : : "r" (0));
+       dsb();
+}
+#else
+static inline void dummy_flush_tlb_a15_erratum(void)
+{
+}
+#endif
+
 /*
  *     flush_pmd_entry
  *
index 5c27696de14fda11bf6866138387f1149128e485..8b1f37bfeeecf3c2d8af09ed15bcbc4cc8fa991f 100644 (file)
@@ -2,6 +2,7 @@
 #define _ASM_ARM_XEN_EVENTS_H
 
 #include <asm/ptrace.h>
+#include <asm/atomic.h>
 
 enum ipi_vector {
        XEN_PLACEHOLDER_VECTOR,
@@ -15,26 +16,8 @@ static inline int xen_irqs_disabled(struct pt_regs *regs)
        return raw_irqs_disabled_flags(regs->ARM_cpsr);
 }
 
-/*
- * We cannot use xchg because it does not support 8-byte
- * values. However it is safe to use {ldr,dtd}exd directly because all
- * platforms which Xen can run on support those instructions.
- */
-static inline xen_ulong_t xchg_xen_ulong(xen_ulong_t *ptr, xen_ulong_t val)
-{
-       xen_ulong_t oldval;
-       unsigned int tmp;
-
-       wmb();
-       asm volatile("@ xchg_xen_ulong\n"
-               "1:     ldrexd  %0, %H0, [%3]\n"
-               "       strexd  %1, %2, %H2, [%3]\n"
-               "       teq     %1, #0\n"
-               "       bne     1b"
-               : "=&r" (oldval), "=&r" (tmp)
-               : "r" (val), "r" (ptr)
-               : "memory", "cc");
-       return oldval;
-}
+#define xchg_xen_ulong(ptr, val) atomic64_xchg(container_of((ptr),     \
+                                                           atomic64_t, \
+                                                           counter), (val))
 
 #endif /* _ASM_ARM_XEN_EVENTS_H */
similarity index 84%
rename from arch/arm/mach-exynos/include/mach/debug-macro.S
rename to arch/arm/include/debug/exynos.S
index e0c86ea475e7bccd6f1e7b598fe6da69b78abc0f..b17fdb7fbd3472d85b30dabf529a9df23e9ff643 100644 (file)
@@ -1,10 +1,7 @@
-/* linux/arch/arm/mach-exynos4/include/mach/debug-macro.S
- *
+/*
  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
  *
- * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S
- *
  * 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.
@@ -12,7 +9,10 @@
 
 /* pull in the relevant register and map files. */
 
-#include <mach/map.h>
+#define S3C_ADDR_BASE   0xF6000000
+#define S3C_VA_UART    S3C_ADDR_BASE + 0x01000000
+#define EXYNOS4_PA_UART        0x13800000
+#define EXYNOS5_PA_UART        0x12C00000
 
        /* note, for the boot process to work we have to keep the UART
         * virtual address aligned to an 1MiB boundary for the L1
@@ -36,4 +36,4 @@
 #define fifo_full fifo_full_s5pv210
 #define fifo_level fifo_level_s5pv210
 
-#include <plat/debug-macro.S>
+#include <debug/samsung.S>
index 0f82098c9bfe3618115dcc4e8b2d74d95c7ddcf6..cd22d821bf74cb1d73acc0fcc44e229dd60a505f 100644 (file)
@@ -562,21 +562,21 @@ ENDPROC(__und_usr)
        @ Fall-through from Thumb-2 __und_usr
        @
 #ifdef CONFIG_NEON
+       get_thread_info r10                     @ get current thread
        adr     r6, .LCneon_thumb_opcodes
        b       2f
 #endif
 call_fpe:
+       get_thread_info r10                     @ get current thread
 #ifdef CONFIG_NEON
        adr     r6, .LCneon_arm_opcodes
-2:
-       ldr     r7, [r6], #4                    @ mask value
-       cmp     r7, #0                          @ end mask?
-       beq     1f
-       and     r8, r0, r7
+2:     ldr     r5, [r6], #4                    @ mask value
        ldr     r7, [r6], #4                    @ opcode bits matching in mask
+       cmp     r5, #0                          @ end mask?
+       beq     1f
+       and     r8, r0, r5
        cmp     r8, r7                          @ NEON instruction?
        bne     2b
-       get_thread_info r10
        mov     r7, #1
        strb    r7, [r10, #TI_USED_CP + 10]     @ mark CP#10 as used
        strb    r7, [r10, #TI_USED_CP + 11]     @ mark CP#11 as used
@@ -586,7 +586,6 @@ call_fpe:
        tst     r0, #0x08000000                 @ only CDP/CPRT/LDC/STC have bit 27
        tstne   r0, #0x04000000                 @ bit 26 set on both ARM and Thumb-2
        moveq   pc, lr
-       get_thread_info r10                     @ get current thread
        and     r8, r0, #0x00000f00             @ mask out CP number
  THUMB(        lsr     r8, r8, #8              )
        mov     r7, #1
index 3248cde504ed9e3995d2f14357e9e1875b3f8129..fefd7f971437a084bedb5d4281fd6e78bac59d04 100644 (file)
@@ -276,7 +276,13 @@ ENDPROC(ftrace_graph_caller_old)
  */
 
 .macro mcount_enter
+/*
+ * This pad compensates for the push {lr} at the call site.  Note that we are
+ * unable to unwind through a function which does not otherwise save its lr.
+ */
+ UNWIND(.pad   #4)
        stmdb   sp!, {r0-r3, lr}
+ UNWIND(.save  {r0-r3, lr})
 .endm
 
 .macro mcount_get_lr reg
@@ -289,6 +295,7 @@ ENDPROC(ftrace_graph_caller_old)
 .endm
 
 ENTRY(__gnu_mcount_nc)
+UNWIND(.fnstart)
 #ifdef CONFIG_DYNAMIC_FTRACE
        mov     ip, lr
        ldmia   sp!, {lr}
@@ -296,17 +303,22 @@ ENTRY(__gnu_mcount_nc)
 #else
        __mcount
 #endif
+UNWIND(.fnend)
 ENDPROC(__gnu_mcount_nc)
 
 #ifdef CONFIG_DYNAMIC_FTRACE
 ENTRY(ftrace_caller)
+UNWIND(.fnstart)
        __ftrace_caller
+UNWIND(.fnend)
 ENDPROC(ftrace_caller)
 #endif
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 ENTRY(ftrace_graph_caller)
+UNWIND(.fnstart)
        __ftrace_graph_caller
+UNWIND(.fnend)
 ENDPROC(ftrace_graph_caller)
 #endif
 
index e0eb9a1cae774fc714548c3e11ad5141cc82190e..8bac553fe213def562dec9e30cad88c827d6239c 100644 (file)
@@ -267,7 +267,7 @@ __create_page_tables:
        addne   r6, r6, #1 << SECTION_SHIFT
        strne   r6, [r3]
 
-#if defined(CONFIG_LPAE) && defined(CONFIG_CPU_ENDIAN_BE8)
+#if defined(CONFIG_ARM_LPAE) && defined(CONFIG_CPU_ENDIAN_BE8)
        sub     r4, r4, #4                      @ Fixup page table pointer
                                                @ for 64-bit descriptors
 #endif
index 96093b75ab90dc134d7232e3f6a1e3c5f41e7902..5dc1aa6f0f7d75e9339094a1da1b61eb018f32f3 100644 (file)
@@ -966,7 +966,7 @@ static void reset_ctrl_regs(void *unused)
        }
 
        if (err) {
-               pr_warning("CPU %d debug is powered down!\n", cpu);
+               pr_warn_once("CPU %d debug is powered down!\n", cpu);
                cpumask_or(&debug_err_mask, &debug_err_mask, cpumask_of(cpu));
                return;
        }
@@ -987,7 +987,7 @@ clear_vcr:
        isb();
 
        if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) {
-               pr_warning("CPU %d failed to disable vector catch\n", cpu);
+               pr_warn_once("CPU %d failed to disable vector catch\n", cpu);
                return;
        }
 
@@ -1007,7 +1007,7 @@ clear_vcr:
        }
 
        if (cpumask_intersects(&debug_err_mask, cpumask_of(cpu))) {
-               pr_warning("CPU %d failed to clear debug register pairs\n", cpu);
+               pr_warn_once("CPU %d failed to clear debug register pairs\n", cpu);
                return;
        }
 
index 047d3e40e47062d4946d7f7c11e8330132340654..cbd0f51937cc68e63a8dc4c1d62ec3ff4f7b20ad 100644 (file)
@@ -459,15 +459,16 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
  * atomic helpers and the signal restart code. Insert it into the
  * gate_vma so that it is visible through ptrace and /proc/<pid>/mem.
  */
-static struct vm_area_struct gate_vma;
+static struct vm_area_struct gate_vma = {
+       .vm_start       = 0xffff0000,
+       .vm_end         = 0xffff0000 + PAGE_SIZE,
+       .vm_flags       = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC,
+       .vm_mm          = &init_mm,
+};
 
 static int __init gate_vma_init(void)
 {
-       gate_vma.vm_start       = 0xffff0000;
-       gate_vma.vm_end         = 0xffff0000 + PAGE_SIZE;
-       gate_vma.vm_page_prot   = PAGE_READONLY_EXEC;
-       gate_vma.vm_flags       = VM_READ | VM_EXEC |
-                                 VM_MAYREAD | VM_MAYEXEC;
+       gate_vma.vm_page_prot = PAGE_READONLY_EXEC;
        return 0;
 }
 arch_initcall(gate_vma_init);
index 3f6cbb2e3edae392f2b73520b89b6ee3b19e8437..d343a6c3a6d1f26ec10ca55f914785b65b4fa473 100644 (file)
@@ -353,6 +353,23 @@ void __init early_print(const char *str, ...)
        printk("%s", buf);
 }
 
+static void __init cpuid_init_hwcaps(void)
+{
+       unsigned int divide_instrs;
+
+       if (cpu_architecture() < CPU_ARCH_ARMv7)
+               return;
+
+       divide_instrs = (read_cpuid_ext(CPUID_EXT_ISAR0) & 0x0f000000) >> 24;
+
+       switch (divide_instrs) {
+       case 2:
+               elf_hwcap |= HWCAP_IDIVA;
+       case 1:
+               elf_hwcap |= HWCAP_IDIVT;
+       }
+}
+
 static void __init feat_v6_fixup(void)
 {
        int id = read_cpuid_id();
@@ -483,8 +500,11 @@ static void __init setup_processor(void)
        snprintf(elf_platform, ELF_PLATFORM_SIZE, "%s%c",
                 list->elf_name, ENDIANNESS);
        elf_hwcap = list->elf_hwcap;
+
+       cpuid_init_hwcaps();
+
 #ifndef CONFIG_ARM_THUMB
-       elf_hwcap &= ~HWCAP_THUMB;
+       elf_hwcap &= ~(HWCAP_THUMB | HWCAP_IDIVT);
 #endif
 
        feat_v6_fixup();
@@ -524,7 +544,7 @@ int __init arm_add_memory(phys_addr_t start, phys_addr_t size)
        size -= start & ~PAGE_MASK;
        bank->start = PAGE_ALIGN(start);
 
-#ifndef CONFIG_LPAE
+#ifndef CONFIG_ARM_LPAE
        if (bank->start + size < bank->start) {
                printk(KERN_CRIT "Truncating memory at 0x%08llx to fit in "
                        "32-bit physical address space\n", (long long)start);
index 31644f1978d56d8e6fad053804ed8d730bff9003..1f2ccccaf009751a0ed830c6a91bfa4ea60278e3 100644 (file)
@@ -480,7 +480,7 @@ static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt)
        evt->features   = CLOCK_EVT_FEAT_ONESHOT |
                          CLOCK_EVT_FEAT_PERIODIC |
                          CLOCK_EVT_FEAT_DUMMY;
-       evt->rating     = 400;
+       evt->rating     = 100;
        evt->mult       = 1;
        evt->set_mode   = broadcast_timer_set_mode;
 
@@ -673,9 +673,6 @@ static int cpufreq_callback(struct notifier_block *nb,
        if (freq->flags & CPUFREQ_CONST_LOOPS)
                return NOTIFY_OK;
 
-       if (arm_delay_ops.const_clock)
-               return NOTIFY_OK;
-
        if (!per_cpu(l_p_j_ref, cpu)) {
                per_cpu(l_p_j_ref, cpu) =
                        per_cpu(cpu_data, cpu).loops_per_jiffy;
index bd0300531399e5eeb066a45f3c29b0d897c23b42..e82e1d24877227ba65ab716dc6c87e110617bd79 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <asm/smp_plat.h>
 #include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
 
 /**********************************************************************/
 
@@ -69,12 +70,72 @@ static inline void ipi_flush_bp_all(void *ignored)
        local_flush_bp_all();
 }
 
+#ifdef CONFIG_ARM_ERRATA_798181
+static int erratum_a15_798181(void)
+{
+       unsigned int midr = read_cpuid_id();
+
+       /* Cortex-A15 r0p0..r3p2 affected */
+       if ((midr & 0xff0ffff0) != 0x410fc0f0 || midr > 0x413fc0f2)
+               return 0;
+       return 1;
+}
+#else
+static int erratum_a15_798181(void)
+{
+       return 0;
+}
+#endif
+
+static void ipi_flush_tlb_a15_erratum(void *arg)
+{
+       dmb();
+}
+
+static void broadcast_tlb_a15_erratum(void)
+{
+       if (!erratum_a15_798181())
+               return;
+
+       dummy_flush_tlb_a15_erratum();
+       smp_call_function_many(cpu_online_mask, ipi_flush_tlb_a15_erratum,
+                              NULL, 1);
+}
+
+static void broadcast_tlb_mm_a15_erratum(struct mm_struct *mm)
+{
+       int cpu;
+       cpumask_t mask = { CPU_BITS_NONE };
+
+       if (!erratum_a15_798181())
+               return;
+
+       dummy_flush_tlb_a15_erratum();
+       for_each_online_cpu(cpu) {
+               if (cpu == smp_processor_id())
+                       continue;
+               /*
+                * We only need to send an IPI if the other CPUs are running
+                * the same ASID as the one being invalidated. There is no
+                * need for locking around the active_asids check since the
+                * switch_mm() function has at least one dmb() (as required by
+                * this workaround) in case a context switch happens on
+                * another CPU after the condition below.
+                */
+               if (atomic64_read(&mm->context.id) ==
+                   atomic64_read(&per_cpu(active_asids, cpu)))
+                       cpumask_set_cpu(cpu, &mask);
+       }
+       smp_call_function_many(&mask, ipi_flush_tlb_a15_erratum, NULL, 1);
+}
+
 void flush_tlb_all(void)
 {
        if (tlb_ops_need_broadcast())
                on_each_cpu(ipi_flush_tlb_all, NULL, 1);
        else
                local_flush_tlb_all();
+       broadcast_tlb_a15_erratum();
 }
 
 void flush_tlb_mm(struct mm_struct *mm)
@@ -83,6 +144,7 @@ void flush_tlb_mm(struct mm_struct *mm)
                on_each_cpu_mask(mm_cpumask(mm), ipi_flush_tlb_mm, mm, 1);
        else
                local_flush_tlb_mm(mm);
+       broadcast_tlb_mm_a15_erratum(mm);
 }
 
 void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
@@ -95,6 +157,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
                                        &ta, 1);
        } else
                local_flush_tlb_page(vma, uaddr);
+       broadcast_tlb_mm_a15_erratum(vma->vm_mm);
 }
 
 void flush_tlb_kernel_page(unsigned long kaddr)
@@ -105,6 +168,7 @@ void flush_tlb_kernel_page(unsigned long kaddr)
                on_each_cpu(ipi_flush_tlb_kernel_page, &ta, 1);
        } else
                local_flush_tlb_kernel_page(kaddr);
+       broadcast_tlb_a15_erratum();
 }
 
 void flush_tlb_range(struct vm_area_struct *vma,
@@ -119,6 +183,7 @@ void flush_tlb_range(struct vm_area_struct *vma,
                                        &ta, 1);
        } else
                local_flush_tlb_range(vma, start, end);
+       broadcast_tlb_mm_a15_erratum(vma->vm_mm);
 }
 
 void flush_tlb_kernel_range(unsigned long start, unsigned long end)
@@ -130,6 +195,7 @@ void flush_tlb_kernel_range(unsigned long start, unsigned long end)
                on_each_cpu(ipi_flush_tlb_kernel_range, &ta, 1);
        } else
                local_flush_tlb_kernel_range(start, end);
+       broadcast_tlb_a15_erratum();
 }
 
 void flush_bp_all(void)
index c9a17316e9fe75f2a8dec4fe3893816d3d0730c9..0e4cfe123b385339629499ae5dacb4f6f5e08ff6 100644 (file)
@@ -883,8 +883,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
                          lr, irq, vgic_cpu->vgic_lr[lr]);
                BUG_ON(!test_bit(lr, vgic_cpu->lr_used));
                vgic_cpu->vgic_lr[lr] |= GICH_LR_PENDING_BIT;
-
-               goto out;
+               return true;
        }
 
        /* Try to use another LR for this interrupt */
@@ -898,7 +897,6 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
        vgic_cpu->vgic_irq_lr_map[irq] = lr;
        set_bit(lr, vgic_cpu->lr_used);
 
-out:
        if (!vgic_irq_is_edge(vcpu, irq))
                vgic_cpu->vgic_lr[lr] |= GICH_LR_EOI;
 
@@ -1018,21 +1016,6 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
 
        kvm_debug("MISR = %08x\n", vgic_cpu->vgic_misr);
 
-       /*
-        * We do not need to take the distributor lock here, since the only
-        * action we perform is clearing the irq_active_bit for an EOIed
-        * level interrupt.  There is a potential race with
-        * the queuing of an interrupt in __kvm_vgic_flush_hwstate(), where we
-        * check if the interrupt is already active. Two possibilities:
-        *
-        * - The queuing is occurring on the same vcpu: cannot happen,
-        *   as we're already in the context of this vcpu, and
-        *   executing the handler
-        * - The interrupt has been migrated to another vcpu, and we
-        *   ignore this interrupt for this run. Big deal. It is still
-        *   pending though, and will get considered when this vcpu
-        *   exits.
-        */
        if (vgic_cpu->vgic_misr & GICH_MISR_EOI) {
                /*
                 * Some level interrupts have been EOIed. Clear their
@@ -1054,6 +1037,13 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
                        } else {
                                vgic_cpu_irq_clear(vcpu, irq);
                        }
+
+                       /*
+                        * Despite being EOIed, the LR may not have
+                        * been marked as empty.
+                        */
+                       set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr);
+                       vgic_cpu->vgic_lr[lr] &= ~GICH_LR_ACTIVE_BIT;
                }
        }
 
@@ -1064,9 +1054,8 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
 }
 
 /*
- * Sync back the VGIC state after a guest run. We do not really touch
- * the distributor here (the irq_pending_on_cpu bit is safe to set),
- * so there is no need for taking its lock.
+ * Sync back the VGIC state after a guest run. The distributor lock is
+ * needed so we don't get preempted in the middle of the state processing.
  */
 static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
 {
@@ -1112,10 +1101,14 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 
 void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
 {
+       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+
        if (!irqchip_in_kernel(vcpu->kvm))
                return;
 
+       spin_lock(&dist->lock);
        __kvm_vgic_sync_hwstate(vcpu);
+       spin_unlock(&dist->lock);
 }
 
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
index 6b93f6a1a3c7413982d455e674c0a12ba5f70186..64dbfa57204ae9c3fde48c6efaec7f60e3c6af89 100644 (file)
@@ -58,7 +58,7 @@ static void __timer_delay(unsigned long cycles)
 static void __timer_const_udelay(unsigned long xloops)
 {
        unsigned long long loops = xloops;
-       loops *= loops_per_jiffy;
+       loops *= arm_delay_ops.ticks_per_jiffy;
        __timer_delay(loops >> UDELAY_SHIFT);
 }
 
@@ -73,11 +73,13 @@ void __init register_current_timer_delay(const struct delay_timer *timer)
                pr_info("Switching to timer-based delay loop\n");
                delay_timer                     = timer;
                lpj_fine                        = timer->freq / HZ;
-               loops_per_jiffy                 = lpj_fine;
+
+               /* cpufreq may scale loops_per_jiffy, so keep a private copy */
+               arm_delay_ops.ticks_per_jiffy   = lpj_fine;
                arm_delay_ops.delay             = __timer_delay;
                arm_delay_ops.const_udelay      = __timer_const_udelay;
                arm_delay_ops.udelay            = __timer_udelay;
-               arm_delay_ops.const_clock       = true;
+
                delay_calibrated                = true;
        } else {
                pr_info("Ignoring duplicate/late registration of read_current_timer delay\n");
index d912e7397ecc94a190a132b649f667b94774c1b9..94b0650ea98fd42492c280d20c7610382a2f4a81 100644 (file)
 
        .text
        .align  5
-       .word   0
-
-1:     subs    r2, r2, #4              @ 1 do we have enough
-       blt     5f                      @ 1 bytes to align with?
-       cmp     r3, #2                  @ 1
-       strltb  r1, [ip], #1            @ 1
-       strleb  r1, [ip], #1            @ 1
-       strb    r1, [ip], #1            @ 1
-       add     r2, r2, r3              @ 1 (r2 = r2 - (4 - r3))
-/*
- * The pointer is now aligned and the length is adjusted.  Try doing the
- * memset again.
- */
 
 ENTRY(memset)
-/*
- * Preserve the contents of r0 for the return value.
- */
-       mov     ip, r0
-       ands    r3, ip, #3              @ 1 unaligned?
-       bne     1b                      @ 1
+       ands    r3, r0, #3              @ 1 unaligned?
+       mov     ip, r0                  @ preserve r0 as return value
+       bne     6f                      @ 1
 /*
  * we know that the pointer in ip is aligned to a word boundary.
  */
-       orr     r1, r1, r1, lsl #8
+1:     orr     r1, r1, r1, lsl #8
        orr     r1, r1, r1, lsl #16
        mov     r3, r1
        cmp     r2, #16
@@ -127,4 +111,13 @@ ENTRY(memset)
        tst     r2, #1
        strneb  r1, [ip], #1
        mov     pc, lr
+
+6:     subs    r2, r2, #4              @ 1 do we have enough
+       blt     5b                      @ 1 bytes to align with?
+       cmp     r3, #2                  @ 1
+       strltb  r1, [ip], #1            @ 1
+       strleb  r1, [ip], #1            @ 1
+       strb    r1, [ip], #1            @ 1
+       add     r2, r2, r3              @ 1 (r2 = r2 - (4 - r3))
+       b       1b
 ENDPROC(memset)
index 2998a08afc2d91a020700807ff9fcd0ca813b68c..0204f4cc9ebf714321f731d3d26f97c9131517a3 100644 (file)
@@ -169,6 +169,8 @@ static struct clk *periph_clocks[] __initdata = {
 };
 
 static struct clk_lookup periph_clocks_lookups[] = {
+       CLKDEV_CON_DEV_ID("hclk", "at91sam9261-lcdfb.0", &hck1),
+       CLKDEV_CON_DEV_ID("hclk", "at91sam9g10-lcdfb.0", &hck1),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.1", &spi1_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
index 92e0f861084aad210fab02837401eb5185255c98..629ea5fc95cf74e2cf72a145d3ea80c4d98aa4b3 100644 (file)
@@ -488,7 +488,6 @@ static struct resource lcdc_resources[] = {
 };
 
 static struct platform_device at91_lcdc_device = {
-       .name           = "atmel_lcdfb",
        .id             = 0,
        .dev            = {
                                .dma_mask               = &lcdc_dmamask,
@@ -505,6 +504,11 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
                return;
        }
 
+       if (cpu_is_at91sam9g10())
+               at91_lcdc_device.name = "at91sam9g10-lcdfb";
+       else
+               at91_lcdc_device.name = "at91sam9261-lcdfb";
+
 #if defined(CONFIG_FB_ATMEL_STN)
        at91_set_A_periph(AT91_PIN_PB0, 0);     /* LCDVSYNC */
        at91_set_A_periph(AT91_PIN_PB1, 0);     /* LCDHSYNC */
index b9fc60d1b33a2f2e6f0e4feef4f44fb82dda38e9..2282fd7ad3e3c1d8218bbe2958452774cea7676a 100644 (file)
@@ -190,6 +190,7 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_DEV_ID("pclk", "at91rm9200_ssc.1", &ssc1_clk),
        CLKDEV_CON_DEV_ID("pclk", "fff98000.ssc", &ssc0_clk),
        CLKDEV_CON_DEV_ID("pclk", "fff9c000.ssc", &ssc1_clk),
+       CLKDEV_CON_DEV_ID("hclk", "at91sam9263-lcdfb.0", &lcdc_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.0", &mmc0_clk),
        CLKDEV_CON_DEV_ID("mci_clk", "atmel_mci.1", &mmc1_clk),
        CLKDEV_CON_DEV_ID("spi_clk", "atmel_spi.0", &spi0_clk),
index ed666f5cb01d577ffb219f2a7857ba84e913e619..858c8aac2daf06328ed99de3b56987647f81b33d 100644 (file)
@@ -848,7 +848,7 @@ static struct resource lcdc_resources[] = {
 };
 
 static struct platform_device at91_lcdc_device = {
-       .name           = "atmel_lcdfb",
+       .name           = "at91sam9263-lcdfb",
        .id             = 0,
        .dev            = {
                                .dma_mask               = &lcdc_dmamask,
index d3addee43d8dac22689c5e3b3970564dbc0d2aca..c68960d82247f3cdb6918632565f5ac8acf90d45 100644 (file)
@@ -228,6 +228,8 @@ static struct clk_lookup periph_clocks_lookups[] = {
        CLKDEV_CON_ID("hclk", &macb_clk),
        /* One additional fake clock for ohci */
        CLKDEV_CON_ID("ohci_clk", &uhphs_clk),
+       CLKDEV_CON_DEV_ID("hclk", "at91sam9g45-lcdfb.0", &lcdc_clk),
+       CLKDEV_CON_DEV_ID("hclk", "at91sam9g45es-lcdfb.0", &lcdc_clk),
        CLKDEV_CON_DEV_ID("ehci_clk", "atmel-ehci", &uhphs_clk),
        CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
        CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
index 827c9f2a70fb9a3f36c40570694bd2ed6960e652..fe626d431b692477be5225e0081baeab80d25584 100644 (file)
@@ -981,7 +981,6 @@ static struct resource lcdc_resources[] = {
 };
 
 static struct platform_device at91_lcdc_device = {
-       .name           = "atmel_lcdfb",
        .id             = 0,
        .dev            = {
                                .dma_mask               = &lcdc_dmamask,
@@ -997,6 +996,11 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data)
        if (!data)
                return;
 
+       if (cpu_is_at91sam9g45es())
+               at91_lcdc_device.name = "at91sam9g45es-lcdfb";
+       else
+               at91_lcdc_device.name = "at91sam9g45-lcdfb";
+
        at91_set_A_periph(AT91_PIN_PE0, 0);     /* LCDDPWR */
 
        at91_set_A_periph(AT91_PIN_PE2, 0);     /* LCDCC */
index eb98704db2d92a4b24835b226cedcf7814260529..3de3e04d0f81905db6e499f46562a1e2f11e7210 100644 (file)
@@ -179,6 +179,7 @@ static struct clk *periph_clocks[] __initdata = {
 };
 
 static struct clk_lookup periph_clocks_lookups[] = {
+       CLKDEV_CON_DEV_ID("hclk", "at91sam9rl-lcdfb.0", &lcdc_clk),
        CLKDEV_CON_DEV_ID("hclk", "atmel_usba_udc", &utmi_clk),
        CLKDEV_CON_DEV_ID("pclk", "atmel_usba_udc", &udphs_clk),
        CLKDEV_CON_DEV_ID("t0_clk", "atmel_tcb.0", &tc0_clk),
index ddf223ff35c41ba21999cc1a829975843bab51f3..352468f265a9616bb411fecc503a13a933e926b2 100644 (file)
@@ -514,7 +514,7 @@ static struct resource lcdc_resources[] = {
 };
 
 static struct platform_device at91_lcdc_device = {
-       .name           = "atmel_lcdfb",
+       .name           = "at91sam9rl-lcdfb",
        .id             = 0,
        .dev            = {
                                .dma_mask               = &lcdc_dmamask,
index 2ea7059b840bfedc5a156d009c943ee4246340ac..c20a870ea9c9295e01eda9842650a3aa593533fd 100644 (file)
@@ -176,6 +176,7 @@ static struct w1_gpio_platform_data w1_gpio_pdata = {
        /* If you choose to use a pin other than PB16 it needs to be 3.3V */
        .pin            = AT91_PIN_PB16,
        .is_open_drain  = 1,
+       .ext_pullup_enable_pin  = -EINVAL,
 };
 
 static struct platform_device w1_device = {
index a033b8df9fb2b147965c95a7393958c832180983..869cbecf00b7eee51c78b4621019ac40ea2edacf 100644 (file)
@@ -188,6 +188,7 @@ static struct spi_board_info portuxg20_spi_devices[] = {
 static struct w1_gpio_platform_data w1_gpio_pdata = {
        .pin            = AT91_PIN_PA29,
        .is_open_drain  = 1,
+       .ext_pullup_enable_pin  = -EINVAL,
 };
 
 static struct platform_device w1_device = {
index eed465ab0dd7d14c589880f4a242ce74138e7030..5fc23771c15455a4874211ba49ae2b012ffe6566 100644 (file)
@@ -209,6 +209,14 @@ extern int at91_get_gpio_value(unsigned pin);
 extern void at91_gpio_suspend(void);
 extern void at91_gpio_resume(void);
 
+#ifdef CONFIG_PINCTRL_AT91
+extern void at91_pinctrl_gpio_suspend(void);
+extern void at91_pinctrl_gpio_resume(void);
+#else
+static inline void at91_pinctrl_gpio_suspend(void) {}
+static inline void at91_pinctrl_gpio_resume(void) {}
+#endif
+
 #endif /* __ASSEMBLY__ */
 
 #endif
index 8e210262aeee59c3aef9ea13ab2a8d4e5d0af120..e0ca59171022fb8f2cee7a488cc2ee622c238384 100644 (file)
@@ -92,23 +92,21 @@ static int at91_aic_set_wake(struct irq_data *d, unsigned value)
 
 void at91_irq_suspend(void)
 {
-       int i = 0, bit;
+       int bit = -1;
 
        if (has_aic5()) {
                /* disable enabled irqs */
-               while ((bit = find_next_bit(backups, n_irqs, i)) < n_irqs) {
+               while ((bit = find_next_bit(backups, n_irqs, bit + 1)) < n_irqs) {
                        at91_aic_write(AT91_AIC5_SSR,
                                       bit & AT91_AIC5_INTSEL_MSK);
                        at91_aic_write(AT91_AIC5_IDCR, 1);
-                       i = bit;
                }
                /* enable wakeup irqs */
-               i = 0;
-               while ((bit = find_next_bit(wakeups, n_irqs, i)) < n_irqs) {
+               bit = -1;
+               while ((bit = find_next_bit(wakeups, n_irqs, bit + 1)) < n_irqs) {
                        at91_aic_write(AT91_AIC5_SSR,
                                       bit & AT91_AIC5_INTSEL_MSK);
                        at91_aic_write(AT91_AIC5_IECR, 1);
-                       i = bit;
                }
        } else {
                at91_aic_write(AT91_AIC_IDCR, *backups);
@@ -118,23 +116,21 @@ void at91_irq_suspend(void)
 
 void at91_irq_resume(void)
 {
-       int i = 0, bit;
+       int bit = -1;
 
        if (has_aic5()) {
                /* disable wakeup irqs */
-               while ((bit = find_next_bit(wakeups, n_irqs, i)) < n_irqs) {
+               while ((bit = find_next_bit(wakeups, n_irqs, bit + 1)) < n_irqs) {
                        at91_aic_write(AT91_AIC5_SSR,
                                       bit & AT91_AIC5_INTSEL_MSK);
                        at91_aic_write(AT91_AIC5_IDCR, 1);
-                       i = bit;
                }
                /* enable irqs disabled for suspend */
-               i = 0;
-               while ((bit = find_next_bit(backups, n_irqs, i)) < n_irqs) {
+               bit = -1;
+               while ((bit = find_next_bit(backups, n_irqs, bit + 1)) < n_irqs) {
                        at91_aic_write(AT91_AIC5_SSR,
                                       bit & AT91_AIC5_INTSEL_MSK);
                        at91_aic_write(AT91_AIC5_IECR, 1);
-                       i = bit;
                }
        } else {
                at91_aic_write(AT91_AIC_IDCR, *wakeups);
index adb6db888a1f1ebda8a088e9ae1e5780ba4b4555..73f1f250403a68575b78e02a8e8d72078ca42375 100644 (file)
@@ -201,7 +201,10 @@ extern u32 at91_slow_clock_sz;
 
 static int at91_pm_enter(suspend_state_t state)
 {
-       at91_gpio_suspend();
+       if (of_have_populated_dt())
+               at91_pinctrl_gpio_suspend();
+       else
+               at91_gpio_suspend();
        at91_irq_suspend();
 
        pr_debug("AT91: PM - wake mask %08x, pm state %d\n",
@@ -286,7 +289,10 @@ static int at91_pm_enter(suspend_state_t state)
 error:
        target_state = PM_SUSPEND_ON;
        at91_irq_resume();
-       at91_gpio_resume();
+       if (of_have_populated_dt())
+               at91_pinctrl_gpio_resume();
+       else
+               at91_gpio_resume();
        return 0;
 }
 
index e698f26cc0cb5ed6bd3a62b7effb39b70d619376..52e4bb5cf12df3d58295c5120ee7fbb0c2e57fd9 100644 (file)
 
 static struct map_desc cns3xxx_io_desc[] __initdata = {
        {
-               .virtual        = CNS3XXX_TC11MP_TWD_BASE_VIRT,
-               .pfn            = __phys_to_pfn(CNS3XXX_TC11MP_TWD_BASE),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT,
-               .pfn            = __phys_to_pfn(CNS3XXX_TC11MP_GIC_CPU_BASE),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT,
-               .pfn            = __phys_to_pfn(CNS3XXX_TC11MP_GIC_DIST_BASE),
-               .length         = SZ_4K,
+               .virtual        = CNS3XXX_TC11MP_SCU_BASE_VIRT,
+               .pfn            = __phys_to_pfn(CNS3XXX_TC11MP_SCU_BASE),
+               .length         = SZ_8K,
                .type           = MT_DEVICE,
        }, {
                .virtual        = CNS3XXX_TIMER1_2_3_BASE_VIRT,
index 191c8e57f2890f09c30610bce584194bc1c3d7f1..b1021aafa4810663a202dc2d1837fcae98c3c2de 100644 (file)
 #define RTC_INTR_STS_OFFSET                    0x34
 
 #define CNS3XXX_MISC_BASE                      0x76000000      /* Misc Control */
-#define CNS3XXX_MISC_BASE_VIRT                 0xFFF07000      /* Misc Control */
+#define CNS3XXX_MISC_BASE_VIRT                 0xFB000000      /* Misc Control */
 
 #define CNS3XXX_PM_BASE                                0x77000000      /* Power Management Control */
-#define CNS3XXX_PM_BASE_VIRT                   0xFFF08000
+#define CNS3XXX_PM_BASE_VIRT                   0xFB001000
 
 #define PM_CLK_GATE_OFFSET                     0x00
 #define PM_SOFT_RST_OFFSET                     0x04
 #define PM_PLL_HM_PD_OFFSET                    0x1C
 
 #define CNS3XXX_UART0_BASE                     0x78000000      /* UART 0 */
-#define CNS3XXX_UART0_BASE_VIRT                        0xFFF09000
+#define CNS3XXX_UART0_BASE_VIRT                        0xFB002000
 
 #define CNS3XXX_UART1_BASE                     0x78400000      /* UART 1 */
 #define CNS3XXX_UART1_BASE_VIRT                        0xFFF0A000
 #define CNS3XXX_I2S_BASE_VIRT                  0xFFF10000
 
 #define CNS3XXX_TIMER1_2_3_BASE                        0x7C800000      /* Timer */
-#define CNS3XXX_TIMER1_2_3_BASE_VIRT           0xFFF10800
+#define CNS3XXX_TIMER1_2_3_BASE_VIRT           0xFB003000
 
 #define TIMER1_COUNTER_OFFSET                  0x00
 #define TIMER1_AUTO_RELOAD_OFFSET              0x04
  * Testchip peripheral and fpga gic regions
  */
 #define CNS3XXX_TC11MP_SCU_BASE                        0x90000000      /* IRQ, Test chip */
-#define CNS3XXX_TC11MP_SCU_BASE_VIRT           0xFF000000
+#define CNS3XXX_TC11MP_SCU_BASE_VIRT           0xFB004000
 
 #define CNS3XXX_TC11MP_GIC_CPU_BASE            0x90000100      /* Test chip interrupt controller CPU interface */
-#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT       0xFF000100
+#define CNS3XXX_TC11MP_GIC_CPU_BASE_VIRT       (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x100)
 
 #define CNS3XXX_TC11MP_TWD_BASE                        0x90000600
-#define CNS3XXX_TC11MP_TWD_BASE_VIRT           0xFF000600
+#define CNS3XXX_TC11MP_TWD_BASE_VIRT           (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x600)
 
 #define CNS3XXX_TC11MP_GIC_DIST_BASE           0x90001000      /* Test chip interrupt controller distributor */
-#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT      0xFF001000
+#define CNS3XXX_TC11MP_GIC_DIST_BASE_VIRT      (CNS3XXX_TC11MP_SCU_BASE_VIRT + 0x1000)
 
 #define CNS3XXX_TC11MP_L220_BASE               0x92002000      /* L220 registers */
 #define CNS3XXX_TC11MP_L220_BASE_VIRT          0xFF002000
index a685e9706b7ba305b462b103899398b3521f2917..45b7c71d9cc1966bb514862364b5180cdd307060 100644 (file)
@@ -743,6 +743,9 @@ EXPORT_SYMBOL(edma_free_channel);
  */
 int edma_alloc_slot(unsigned ctlr, int slot)
 {
+       if (!edma_cc[ctlr])
+               return -EINVAL;
+
        if (slot >= 0)
                slot = EDMA_CHAN_SLOT(slot);
 
index d2afb4dd82aba7902049e24e72215e432eed6bd2..b5cc77d2380bd59c24c2da80a9995d45c2277f85 100644 (file)
@@ -47,9 +47,13 @@ static void __raw_writel(unsigned int value, unsigned int ptr)
 
 static inline void putc(int c)
 {
-       /* Transmit fifo not full?  */
-       while (__raw_readb(PHYS_UART_FLAG) & UART_FLAG_TXFF)
-               ;
+       int i;
+
+       for (i = 0; i < 10000; i++) {
+               /* Transmit fifo not full? */
+               if (!(__raw_readb(PHYS_UART_FLAG) & UART_FLAG_TXFF))
+                       break;
+       }
 
        __raw_writeb(c, PHYS_UART_DATA);
 }
index 70f94c87479df7d4dc2ab8aa25356461a3066b14..a77db362a8888034d42e3d5429cdd28069a84c60 100644 (file)
@@ -7,6 +7,21 @@
 
 # Configuration options for the EXYNOS4
 
+config ARCH_EXYNOS
+       # TODO: make this visible after all drivers are converted
+       bool "Samsung EXYNOS" if ARCH_MULTI_V7 && BROKEN
+       default ARCH_EXYNOS_SINGLE
+       select ARCH_HAS_CPUFREQ
+       select CLKDEV_LOOKUP
+       select COMMON_CLK
+       select CPU_V7
+       select GENERIC_CLOCKEVENTS
+       select HAVE_CLK
+       select HAVE_S3C2410_I2C if I2C
+       select HAVE_S3C_RTC if RTC_CLASS
+       help
+         Support for SAMSUNG's EXYNOS SoCs (EXYNOS4/5)
+
 if ARCH_EXYNOS
 
 menu "SAMSUNG EXYNOS SoCs Support"
@@ -19,6 +34,9 @@ config ARCH_EXYNOS4
        help
          Samsung EXYNOS4 SoCs based systems
 
+config ARCH_EXYNOS4_SINGLE
+       def_bool ARCH_EXYNOS4 && ARCH_EXYNOS_SINGLE
+
 config ARCH_EXYNOS5
        bool "SAMSUNG EXYNOS5"
        select HAVE_SMP
@@ -35,7 +53,7 @@ config CPU_EXYNOS4210
        select PM_GENERIC_DOMAINS
        select S5P_PM if PM
        select S5P_SLEEP if PM
-       select SAMSUNG_DMADEV
+       select SAMSUNG_DMADEV if ARCH_EXYNOS_SINGLE
        help
          Enable EXYNOS4210 CPU support
 
@@ -45,7 +63,7 @@ config SOC_EXYNOS4212
        depends on ARCH_EXYNOS4
        select S5P_PM if PM
        select S5P_SLEEP if PM
-       select SAMSUNG_DMADEV
+       select SAMSUNG_DMADEV if ARCH_EXYNOS_SINGLE
        help
          Enable EXYNOS4212 SoC support
 
@@ -53,7 +71,7 @@ config SOC_EXYNOS4412
        bool "SAMSUNG EXYNOS4412"
        default y
        depends on ARCH_EXYNOS4
-       select SAMSUNG_DMADEV
+       select SAMSUNG_DMADEV if ARCH_EXYNOS_SINGLE
        help
          Enable EXYNOS4412 SoC support
 
@@ -61,10 +79,11 @@ config SOC_EXYNOS5250
        bool "SAMSUNG EXYNOS5250"
        default y
        depends on ARCH_EXYNOS5
+       select PM_GENERIC_DOMAINS if PM
        select S5P_PM if PM
        select S5P_SLEEP if PM
        select S5P_DEV_MFC
-       select SAMSUNG_DMADEV
+       select SAMSUNG_DMADEV if ARCH_EXYNOS_SINGLE
        help
          Enable EXYNOS5250 SoC support
 
@@ -79,11 +98,18 @@ config SOC_EXYNOS5440
        help
          Enable EXYNOS5440 SoC support
 
-config EXYNOS4_MCT
-       bool
+config EXYNOS_ATAGS
+       bool "ATAGS based boot for EXYNOS (deprecated)"
+       depends on !ARCH_MULTIPLATFORM
+       depends on ATAGS
        default y
        help
-         Use MCT (Multi Core Timer) as kernel timers
+         The EXYNOS platform is moving towards being completely probed
+         through device tree. This enables support for board files using
+         the traditional ATAGS boot format.
+         Note that this option is not available for multiplatform builds.
+
+if EXYNOS_ATAGS
 
 config EXYNOS_DEV_DMA
        bool
@@ -276,8 +302,8 @@ config MACH_UNIVERSAL_C210
        select S5P_DEV_ONENAND
        select S5P_DEV_TV
        select S5P_GPIO_INT
-       select S5P_HRT
        select S5P_SETUP_MIPIPHY
+       select SAMSUNG_HRT
        help
          Machine support for Samsung Mobile Universal S5PC210 Reference
          Board.
@@ -400,16 +426,20 @@ config MACH_SMDK4412
          Machine support for Samsung SMDK4412
 endif
 
+endif
+
 comment "Flattened Device Tree based board for EXYNOS SoCs"
 
 config MACH_EXYNOS4_DT
        bool "Samsung Exynos4 Machine using device tree"
        depends on ARCH_EXYNOS4
        select ARM_AMBA
+       select CLKSRC_OF
        select CPU_EXYNOS4210
        select HAVE_SAMSUNG_KEYPAD if INPUT_KEYBOARD
        select PINCTRL
        select PINCTRL_EXYNOS
+       select S5P_DEV_MFC
        select USE_OF
        help
          Machine support for Samsung Exynos4 machine with device tree enabled.
@@ -422,6 +452,7 @@ config MACH_EXYNOS5_DT
        default y
        depends on ARCH_EXYNOS5
        select ARM_AMBA
+       select CLKSRC_OF
        select USE_OF
        help
          Machine support for Samsung EXYNOS5 machine with device tree enabled.
index 435757e57bb47d8f2b784352150dcb182aa6eb43..e26d05c5249f285ced44a29f49f5ffc9f93b188c 100644 (file)
@@ -4,6 +4,7 @@
 #              http://www.samsung.com/
 #
 # Licensed under GPLv2
+ccflags-$(CONFIG_ARCH_MULTIPLATFORM) += -I$(srctree)/$(src)/include -I$(srctree)/arch/arm/plat-samsung/include
 
 obj-y                          :=
 obj-m                          :=
@@ -13,10 +14,6 @@ obj-                         :=
 # Core
 
 obj-$(CONFIG_ARCH_EXYNOS)      += common.o
-obj-$(CONFIG_ARCH_EXYNOS4)     += clock-exynos4.o
-obj-$(CONFIG_CPU_EXYNOS4210)   += clock-exynos4210.o
-obj-$(CONFIG_SOC_EXYNOS4212)   += clock-exynos4212.o
-obj-$(CONFIG_SOC_EXYNOS5250)   += clock-exynos5.o
 
 obj-$(CONFIG_PM)               += pm.o
 obj-$(CONFIG_PM_GENERIC_DOMAINS) += pm_domains.o
@@ -26,8 +23,6 @@ obj-$(CONFIG_ARCH_EXYNOS)     += pmu.o
 
 obj-$(CONFIG_SMP)              += platsmp.o headsmp.o
 
-obj-$(CONFIG_EXYNOS4_MCT)      += mct.o
-
 obj-$(CONFIG_HOTPLUG_CPU)      += hotplug.o
 
 # machine support
@@ -48,12 +43,12 @@ obj-$(CONFIG_MACH_EXYNOS5_DT)               += mach-exynos5-dt.o
 # device support
 
 obj-y                                  += dev-uart.o
-obj-$(CONFIG_ARCH_EXYNOS4)             += dev-audio.o
+obj-$(CONFIG_ARCH_EXYNOS4_SINGLE)      += dev-audio.o
 obj-$(CONFIG_EXYNOS4_DEV_AHCI)         += dev-ahci.o
 obj-$(CONFIG_EXYNOS_DEV_DMA)           += dma.o
 obj-$(CONFIG_EXYNOS4_DEV_USB_OHCI)     += dev-ohci.o
 
-obj-$(CONFIG_ARCH_EXYNOS)              += setup-i2c0.o
+obj-$(CONFIG_ARCH_EXYNOS_SINGLE)       += setup-i2c0.o
 obj-$(CONFIG_EXYNOS4_SETUP_FIMC)       += setup-fimc.o
 obj-$(CONFIG_EXYNOS4_SETUP_FIMD0)      += setup-fimd0.o
 obj-$(CONFIG_EXYNOS4_SETUP_I2C1)       += setup-i2c1.o
diff --git a/arch/arm/mach-exynos/clock-exynos4.c b/arch/arm/mach-exynos/clock-exynos4.c
deleted file mode 100644 (file)
index 8a8468d..0000000
+++ /dev/null
@@ -1,1601 +0,0 @@
-/*
- * Copyright (c) 2010-2012 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/pm.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4_clock_save[] = {
-       SAVE_ITEM(EXYNOS4_CLKDIV_LEFTBUS),
-       SAVE_ITEM(EXYNOS4_CLKGATE_IP_LEFTBUS),
-       SAVE_ITEM(EXYNOS4_CLKDIV_RIGHTBUS),
-       SAVE_ITEM(EXYNOS4_CLKGATE_IP_RIGHTBUS),
-       SAVE_ITEM(EXYNOS4_CLKSRC_TOP0),
-       SAVE_ITEM(EXYNOS4_CLKSRC_TOP1),
-       SAVE_ITEM(EXYNOS4_CLKSRC_CAM),
-       SAVE_ITEM(EXYNOS4_CLKSRC_TV),
-       SAVE_ITEM(EXYNOS4_CLKSRC_MFC),
-       SAVE_ITEM(EXYNOS4_CLKSRC_G3D),
-       SAVE_ITEM(EXYNOS4_CLKSRC_LCD0),
-       SAVE_ITEM(EXYNOS4_CLKSRC_MAUDIO),
-       SAVE_ITEM(EXYNOS4_CLKSRC_FSYS),
-       SAVE_ITEM(EXYNOS4_CLKSRC_PERIL0),
-       SAVE_ITEM(EXYNOS4_CLKSRC_PERIL1),
-       SAVE_ITEM(EXYNOS4_CLKDIV_CAM),
-       SAVE_ITEM(EXYNOS4_CLKDIV_TV),
-       SAVE_ITEM(EXYNOS4_CLKDIV_MFC),
-       SAVE_ITEM(EXYNOS4_CLKDIV_G3D),
-       SAVE_ITEM(EXYNOS4_CLKDIV_LCD0),
-       SAVE_ITEM(EXYNOS4_CLKDIV_MAUDIO),
-       SAVE_ITEM(EXYNOS4_CLKDIV_FSYS0),
-       SAVE_ITEM(EXYNOS4_CLKDIV_FSYS1),
-       SAVE_ITEM(EXYNOS4_CLKDIV_FSYS2),
-       SAVE_ITEM(EXYNOS4_CLKDIV_FSYS3),
-       SAVE_ITEM(EXYNOS4_CLKDIV_PERIL0),
-       SAVE_ITEM(EXYNOS4_CLKDIV_PERIL1),
-       SAVE_ITEM(EXYNOS4_CLKDIV_PERIL2),
-       SAVE_ITEM(EXYNOS4_CLKDIV_PERIL3),
-       SAVE_ITEM(EXYNOS4_CLKDIV_PERIL4),
-       SAVE_ITEM(EXYNOS4_CLKDIV_PERIL5),
-       SAVE_ITEM(EXYNOS4_CLKDIV_TOP),
-       SAVE_ITEM(EXYNOS4_CLKSRC_MASK_TOP),
-       SAVE_ITEM(EXYNOS4_CLKSRC_MASK_CAM),
-       SAVE_ITEM(EXYNOS4_CLKSRC_MASK_TV),
-       SAVE_ITEM(EXYNOS4_CLKSRC_MASK_LCD0),
-       SAVE_ITEM(EXYNOS4_CLKSRC_MASK_MAUDIO),
-       SAVE_ITEM(EXYNOS4_CLKSRC_MASK_FSYS),
-       SAVE_ITEM(EXYNOS4_CLKSRC_MASK_PERIL0),
-       SAVE_ITEM(EXYNOS4_CLKSRC_MASK_PERIL1),
-       SAVE_ITEM(EXYNOS4_CLKDIV2_RATIO),
-       SAVE_ITEM(EXYNOS4_CLKGATE_SCLKCAM),
-       SAVE_ITEM(EXYNOS4_CLKGATE_IP_CAM),
-       SAVE_ITEM(EXYNOS4_CLKGATE_IP_TV),
-       SAVE_ITEM(EXYNOS4_CLKGATE_IP_MFC),
-       SAVE_ITEM(EXYNOS4_CLKGATE_IP_G3D),
-       SAVE_ITEM(EXYNOS4_CLKGATE_IP_LCD0),
-       SAVE_ITEM(EXYNOS4_CLKGATE_IP_FSYS),
-       SAVE_ITEM(EXYNOS4_CLKGATE_IP_GPS),
-       SAVE_ITEM(EXYNOS4_CLKGATE_IP_PERIL),
-       SAVE_ITEM(EXYNOS4_CLKGATE_BLOCK),
-       SAVE_ITEM(EXYNOS4_CLKSRC_MASK_DMC),
-       SAVE_ITEM(EXYNOS4_CLKSRC_DMC),
-       SAVE_ITEM(EXYNOS4_CLKDIV_DMC0),
-       SAVE_ITEM(EXYNOS4_CLKDIV_DMC1),
-       SAVE_ITEM(EXYNOS4_CLKGATE_IP_DMC),
-       SAVE_ITEM(EXYNOS4_CLKSRC_CPU),
-       SAVE_ITEM(EXYNOS4_CLKDIV_CPU),
-       SAVE_ITEM(EXYNOS4_CLKDIV_CPU + 0x4),
-       SAVE_ITEM(EXYNOS4_CLKGATE_SCLKCPU),
-       SAVE_ITEM(EXYNOS4_CLKGATE_IP_CPU),
-};
-#endif
-
-static struct clk exynos4_clk_sclk_hdmi27m = {
-       .name           = "sclk_hdmi27m",
-       .rate           = 27000000,
-};
-
-static struct clk exynos4_clk_sclk_hdmiphy = {
-       .name           = "sclk_hdmiphy",
-};
-
-static struct clk exynos4_clk_sclk_usbphy0 = {
-       .name           = "sclk_usbphy0",
-       .rate           = 27000000,
-};
-
-static struct clk exynos4_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(EXYNOS4_CLKSRC_MASK_TOP, clk, enable);
-}
-
-static int exynos4_clksrc_mask_cam_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_CAM, clk, enable);
-}
-
-static int exynos4_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_LCD0, clk, enable);
-}
-
-int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_FSYS, clk, enable);
-}
-
-static int exynos4_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_PERIL0, clk, enable);
-}
-
-static int exynos4_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_PERIL1, clk, enable);
-}
-
-static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKGATE_IP_MFC, clk, enable);
-}
-
-static int exynos4_clksrc_mask_tv_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKSRC_MASK_TV, clk, enable);
-}
-
-static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKGATE_IP_CAM, clk, enable);
-}
-
-static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKGATE_IP_TV, clk, enable);
-}
-
-int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKGATE_IP_IMAGE, clk, enable);
-}
-
-static int exynos4_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKGATE_IP_LCD0, clk, enable);
-}
-
-int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4210_CLKGATE_IP_LCD1, clk, enable);
-}
-
-int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKGATE_IP_FSYS, clk, enable);
-}
-
-static int exynos4_clk_ip_peril_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIL, clk, enable);
-}
-
-static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKGATE_IP_PERIR, clk, enable);
-}
-
-int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKGATE_IP_DMC, 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 exynos4_clk_mout_apll = {
-       .clk    = {
-               .name           = "mout_apll",
-       },
-       .sources = &clk_src_apll,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_apll = {
-       .clk    = {
-               .name           = "sclk_apll",
-               .parent         = &exynos4_clk_mout_apll.clk,
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 24, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_mout_epll = {
-       .clk    = {
-               .name           = "mout_epll",
-       },
-       .sources = &clk_src_epll,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 4, .size = 1 },
-};
-
-struct clksrc_clk exynos4_clk_mout_mpll = {
-       .clk    = {
-               .name           = "mout_mpll",
-       },
-       .sources = &clk_src_mpll,
-
-       /* reg_src will be added in each SoCs' clock */
-};
-
-static struct clk *exynos4_clkset_moutcore_list[] = {
-       [0] = &exynos4_clk_mout_apll.clk,
-       [1] = &exynos4_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_moutcore = {
-       .sources        = exynos4_clkset_moutcore_list,
-       .nr_sources     = ARRAY_SIZE(exynos4_clkset_moutcore_list),
-};
-
-static struct clksrc_clk exynos4_clk_moutcore = {
-       .clk    = {
-               .name           = "moutcore",
-       },
-       .sources = &exynos4_clkset_moutcore,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_coreclk = {
-       .clk    = {
-               .name           = "core_clk",
-               .parent         = &exynos4_clk_moutcore.clk,
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_armclk = {
-       .clk    = {
-               .name           = "armclk",
-               .parent         = &exynos4_clk_coreclk.clk,
-       },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corem0 = {
-       .clk    = {
-               .name           = "aclk_corem0",
-               .parent         = &exynos4_clk_coreclk.clk,
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_cores = {
-       .clk    = {
-               .name           = "aclk_cores",
-               .parent         = &exynos4_clk_coreclk.clk,
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corem1 = {
-       .clk    = {
-               .name           = "aclk_corem1",
-               .parent         = &exynos4_clk_coreclk.clk,
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_periphclk = {
-       .clk    = {
-               .name           = "periphclk",
-               .parent         = &exynos4_clk_coreclk.clk,
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_CPU, .shift = 12, .size = 3 },
-};
-
-/* Core list of CMU_CORE side */
-
-static struct clk *exynos4_clkset_corebus_list[] = {
-       [0] = &exynos4_clk_mout_mpll.clk,
-       [1] = &exynos4_clk_sclk_apll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_corebus = {
-       .sources        = exynos4_clkset_corebus_list,
-       .nr_sources     = ARRAY_SIZE(exynos4_clkset_corebus_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_corebus = {
-       .clk    = {
-               .name           = "mout_corebus",
-       },
-       .sources = &exynos4_clkset_mout_corebus,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_dmc = {
-       .clk    = {
-               .name           = "sclk_dmc",
-               .parent         = &exynos4_clk_mout_corebus.clk,
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_cored = {
-       .clk    = {
-               .name           = "aclk_cored",
-               .parent         = &exynos4_clk_sclk_dmc.clk,
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_corep = {
-       .clk    = {
-               .name           = "aclk_corep",
-               .parent         = &exynos4_clk_aclk_cored.clk,
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 20, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_acp = {
-       .clk    = {
-               .name           = "aclk_acp",
-               .parent         = &exynos4_clk_mout_corebus.clk,
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_pclk_acp = {
-       .clk    = {
-               .name           = "pclk_acp",
-               .parent         = &exynos4_clk_aclk_acp.clk,
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_DMC0, .shift = 4, .size = 3 },
-};
-
-/* Core list of CMU_TOP side */
-
-struct clk *exynos4_clkset_aclk_top_list[] = {
-       [0] = &exynos4_clk_mout_mpll.clk,
-       [1] = &exynos4_clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_aclk = {
-       .sources        = exynos4_clkset_aclk_top_list,
-       .nr_sources     = ARRAY_SIZE(exynos4_clkset_aclk_top_list),
-};
-
-static struct clksrc_clk exynos4_clk_aclk_200 = {
-       .clk    = {
-               .name           = "aclk_200",
-       },
-       .sources = &exynos4_clkset_aclk,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 12, .size = 1 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_100 = {
-       .clk    = {
-               .name           = "aclk_100",
-       },
-       .sources = &exynos4_clkset_aclk,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 16, .size = 1 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_aclk_160 = {
-       .clk    = {
-               .name           = "aclk_160",
-       },
-       .sources = &exynos4_clkset_aclk,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 20, .size = 1 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 8, .size = 3 },
-};
-
-struct clksrc_clk exynos4_clk_aclk_133 = {
-       .clk    = {
-               .name           = "aclk_133",
-       },
-       .sources = &exynos4_clkset_aclk,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 24, .size = 1 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_TOP, .shift = 12, .size = 3 },
-};
-
-static struct clk *exynos4_clkset_vpllsrc_list[] = {
-       [0] = &clk_fin_vpll,
-       [1] = &exynos4_clk_sclk_hdmi27m,
-};
-
-static struct clksrc_sources exynos4_clkset_vpllsrc = {
-       .sources        = exynos4_clkset_vpllsrc_list,
-       .nr_sources     = ARRAY_SIZE(exynos4_clkset_vpllsrc_list),
-};
-
-static struct clksrc_clk exynos4_clk_vpllsrc = {
-       .clk    = {
-               .name           = "vpll_src",
-               .enable         = exynos4_clksrc_mask_top_ctrl,
-               .ctrlbit        = (1 << 0),
-       },
-       .sources = &exynos4_clkset_vpllsrc,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_TOP1, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_sclk_vpll_list[] = {
-       [0] = &exynos4_clk_vpllsrc.clk,
-       [1] = &clk_fout_vpll,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_vpll = {
-       .sources        = exynos4_clkset_sclk_vpll_list,
-       .nr_sources     = ARRAY_SIZE(exynos4_clkset_sclk_vpll_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_vpll = {
-       .clk    = {
-               .name           = "sclk_vpll",
-       },
-       .sources = &exynos4_clkset_sclk_vpll,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_TOP0, .shift = 8, .size = 1 },
-};
-
-static struct clk exynos4_init_clocks_off[] = {
-       {
-               .name           = "timers",
-               .parent         = &exynos4_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           = "jpeg",
-               .id             = 0,
-               .enable         = exynos4_clk_ip_cam_ctrl,
-               .ctrlbit        = (1 << 6),
-       }, {
-               .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           = "tsi",
-               .enable         = exynos4_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 4),
-       }, {
-               .name           = "hsmmc",
-               .devname        = "exynos4-sdhci.0",
-               .parent         = &exynos4_clk_aclk_133.clk,
-               .enable         = exynos4_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 5),
-       }, {
-               .name           = "hsmmc",
-               .devname        = "exynos4-sdhci.1",
-               .parent         = &exynos4_clk_aclk_133.clk,
-               .enable         = exynos4_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 6),
-       }, {
-               .name           = "hsmmc",
-               .devname        = "exynos4-sdhci.2",
-               .parent         = &exynos4_clk_aclk_133.clk,
-               .enable         = exynos4_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 7),
-       }, {
-               .name           = "hsmmc",
-               .devname        = "exynos4-sdhci.3",
-               .parent         = &exynos4_clk_aclk_133.clk,
-               .enable         = exynos4_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 8),
-       }, {
-               .name           = "biu",
-               .parent         = &exynos4_clk_aclk_133.clk,
-               .enable         = exynos4_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 9),
-       }, {
-               .name           = "onenand",
-               .enable         = exynos4_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 15),
-       }, {
-               .name           = "nfcon",
-               .enable         = exynos4_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 16),
-       }, {
-               .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           = "adc",
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 15),
-       }, {
-               .name           = "tmu_apbif",
-               .enable         = exynos4_clk_ip_perir_ctrl,
-               .ctrlbit        = (1 << 17),
-       }, {
-               .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         = &exynos4_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        = "exynos4210-spi.0",
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 16),
-       }, {
-               .name           = "spi",
-               .devname        = "exynos4210-spi.1",
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 17),
-       }, {
-               .name           = "spi",
-               .devname        = "exynos4210-spi.2",
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 18),
-       }, {
-               .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           = "pcm",
-               .devname        = "samsung-pcm.1",
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 22),
-       }, {
-               .name           = "pcm",
-               .devname        = "samsung-pcm.2",
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 23),
-       }, {
-               .name           = "slimbus",
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 25),
-       }, {
-               .name           = "spdif",
-               .devname        = "samsung-spdif",
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 26),
-       }, {
-               .name           = "ac97",
-               .devname        = "samsung-ac97",
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 27),
-       }, {
-               .name           = "mfc",
-               .devname        = "s5p-mfc",
-               .enable         = exynos4_clk_ip_mfc_ctrl,
-               .ctrlbit        = (1 << 0),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.0",
-               .parent         = &exynos4_clk_aclk_100.clk,
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 6),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.1",
-               .parent         = &exynos4_clk_aclk_100.clk,
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 7),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.2",
-               .parent         = &exynos4_clk_aclk_100.clk,
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 8),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.3",
-               .parent         = &exynos4_clk_aclk_100.clk,
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 9),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.4",
-               .parent         = &exynos4_clk_aclk_100.clk,
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 10),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.5",
-               .parent         = &exynos4_clk_aclk_100.clk,
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 11),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.6",
-               .parent         = &exynos4_clk_aclk_100.clk,
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 12),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.7",
-               .parent         = &exynos4_clk_aclk_100.clk,
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 13),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-hdmiphy-i2c",
-               .parent         = &exynos4_clk_aclk_100.clk,
-               .enable         = exynos4_clk_ip_peril_ctrl,
-               .ctrlbit        = (1 << 14),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.0",
-               .enable         = exynos4_clk_ip_mfc_ctrl,
-               .ctrlbit        = (1 << 1),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.1",
-               .enable         = exynos4_clk_ip_mfc_ctrl,
-               .ctrlbit        = (1 << 2),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.2",
-               .enable         = exynos4_clk_ip_tv_ctrl,
-               .ctrlbit        = (1 << 4),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.3",
-               .enable         = exynos4_clk_ip_cam_ctrl,
-               .ctrlbit        = (1 << 11),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.4",
-               .enable         = exynos4_clk_ip_image_ctrl,
-               .ctrlbit        = (1 << 4),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.5",
-               .enable         = exynos4_clk_ip_cam_ctrl,
-               .ctrlbit        = (1 << 7),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.6",
-               .enable         = exynos4_clk_ip_cam_ctrl,
-               .ctrlbit        = (1 << 8),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.7",
-               .enable         = exynos4_clk_ip_cam_ctrl,
-               .ctrlbit        = (1 << 9),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.8",
-               .enable         = exynos4_clk_ip_cam_ctrl,
-               .ctrlbit        = (1 << 10),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.10",
-               .enable         = exynos4_clk_ip_lcd0_ctrl,
-               .ctrlbit        = (1 << 4),
-       }
-};
-
-static struct clk exynos4_init_clocks_on[] = {
-       {
-               .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),
-       }
-};
-
-static struct clk exynos4_clk_pdma0 = {
-       .name           = "dma",
-       .devname        = "dma-pl330.0",
-       .enable         = exynos4_clk_ip_fsys_ctrl,
-       .ctrlbit        = (1 << 0),
-};
-
-static struct clk exynos4_clk_pdma1 = {
-       .name           = "dma",
-       .devname        = "dma-pl330.1",
-       .enable         = exynos4_clk_ip_fsys_ctrl,
-       .ctrlbit        = (1 << 1),
-};
-
-static struct clk exynos4_clk_mdma1 = {
-       .name           = "dma",
-       .devname        = "dma-pl330.2",
-       .enable         = exynos4_clk_ip_image_ctrl,
-       .ctrlbit        = ((1 << 8) | (1 << 5) | (1 << 2)),
-};
-
-static struct clk exynos4_clk_fimd0 = {
-       .name           = "fimd",
-       .devname        = "exynos4-fb.0",
-       .enable         = exynos4_clk_ip_lcd0_ctrl,
-       .ctrlbit        = (1 << 0),
-};
-
-struct clk *exynos4_clkset_group_list[] = {
-       [0] = &clk_ext_xtal_mux,
-       [1] = &clk_xusbxti,
-       [2] = &exynos4_clk_sclk_hdmi27m,
-       [3] = &exynos4_clk_sclk_usbphy0,
-       [4] = &exynos4_clk_sclk_usbphy1,
-       [5] = &exynos4_clk_sclk_hdmiphy,
-       [6] = &exynos4_clk_mout_mpll.clk,
-       [7] = &exynos4_clk_mout_epll.clk,
-       [8] = &exynos4_clk_sclk_vpll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_group = {
-       .sources        = exynos4_clkset_group_list,
-       .nr_sources     = ARRAY_SIZE(exynos4_clkset_group_list),
-};
-
-static struct clk *exynos4_clkset_mout_g2d0_list[] = {
-       [0] = &exynos4_clk_mout_mpll.clk,
-       [1] = &exynos4_clk_sclk_apll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_g2d0 = {
-       .sources        = exynos4_clkset_mout_g2d0_list,
-       .nr_sources     = ARRAY_SIZE(exynos4_clkset_mout_g2d0_list),
-};
-
-static struct clk *exynos4_clkset_mout_g2d1_list[] = {
-       [0] = &exynos4_clk_mout_epll.clk,
-       [1] = &exynos4_clk_sclk_vpll.clk,
-};
-
-struct clksrc_sources exynos4_clkset_mout_g2d1 = {
-       .sources        = exynos4_clkset_mout_g2d1_list,
-       .nr_sources     = ARRAY_SIZE(exynos4_clkset_mout_g2d1_list),
-};
-
-static struct clk *exynos4_clkset_mout_mfc0_list[] = {
-       [0] = &exynos4_clk_mout_mpll.clk,
-       [1] = &exynos4_clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc0 = {
-       .sources        = exynos4_clkset_mout_mfc0_list,
-       .nr_sources     = ARRAY_SIZE(exynos4_clkset_mout_mfc0_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_mfc0 = {
-       .clk    = {
-               .name           = "mout_mfc0",
-       },
-       .sources = &exynos4_clkset_mout_mfc0,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_mout_mfc1_list[] = {
-       [0] = &exynos4_clk_mout_epll.clk,
-       [1] = &exynos4_clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc1 = {
-       .sources        = exynos4_clkset_mout_mfc1_list,
-       .nr_sources     = ARRAY_SIZE(exynos4_clkset_mout_mfc1_list),
-};
-
-static struct clksrc_clk exynos4_clk_mout_mfc1 = {
-       .clk    = {
-               .name           = "mout_mfc1",
-       },
-       .sources = &exynos4_clkset_mout_mfc1,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 4, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_mout_mfc_list[] = {
-       [0] = &exynos4_clk_mout_mfc0.clk,
-       [1] = &exynos4_clk_mout_mfc1.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_mout_mfc = {
-       .sources        = exynos4_clkset_mout_mfc_list,
-       .nr_sources     = ARRAY_SIZE(exynos4_clkset_mout_mfc_list),
-};
-
-static struct clk *exynos4_clkset_sclk_dac_list[] = {
-       [0] = &exynos4_clk_sclk_vpll.clk,
-       [1] = &exynos4_clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_dac = {
-       .sources        = exynos4_clkset_sclk_dac_list,
-       .nr_sources     = ARRAY_SIZE(exynos4_clkset_sclk_dac_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_dac = {
-       .clk            = {
-               .name           = "sclk_dac",
-               .enable         = exynos4_clksrc_mask_tv_ctrl,
-               .ctrlbit        = (1 << 8),
-       },
-       .sources = &exynos4_clkset_sclk_dac,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 8, .size = 1 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_pixel = {
-       .clk            = {
-               .name           = "sclk_pixel",
-               .parent         = &exynos4_clk_sclk_vpll.clk,
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_TV, .shift = 0, .size = 4 },
-};
-
-static struct clk *exynos4_clkset_sclk_hdmi_list[] = {
-       [0] = &exynos4_clk_sclk_pixel.clk,
-       [1] = &exynos4_clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_hdmi = {
-       .sources        = exynos4_clkset_sclk_hdmi_list,
-       .nr_sources     = ARRAY_SIZE(exynos4_clkset_sclk_hdmi_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_hdmi = {
-       .clk            = {
-               .name           = "sclk_hdmi",
-               .enable         = exynos4_clksrc_mask_tv_ctrl,
-               .ctrlbit        = (1 << 0),
-       },
-       .sources = &exynos4_clkset_sclk_hdmi,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos4_clkset_sclk_mixer_list[] = {
-       [0] = &exynos4_clk_sclk_dac.clk,
-       [1] = &exynos4_clk_sclk_hdmi.clk,
-};
-
-static struct clksrc_sources exynos4_clkset_sclk_mixer = {
-       .sources        = exynos4_clkset_sclk_mixer_list,
-       .nr_sources     = ARRAY_SIZE(exynos4_clkset_sclk_mixer_list),
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mixer = {
-       .clk    = {
-               .name           = "sclk_mixer",
-               .enable         = exynos4_clksrc_mask_tv_ctrl,
-               .ctrlbit        = (1 << 4),
-       },
-       .sources = &exynos4_clkset_sclk_mixer,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_TV, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk *exynos4_sclk_tv[] = {
-       &exynos4_clk_sclk_dac,
-       &exynos4_clk_sclk_pixel,
-       &exynos4_clk_sclk_hdmi,
-       &exynos4_clk_sclk_mixer,
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc0 = {
-       .clk    = {
-               .name           = "dout_mmc0",
-       },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 0, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc1 = {
-       .clk    = {
-               .name           = "dout_mmc1",
-       },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 4, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc2 = {
-       .clk    = {
-               .name           = "dout_mmc2",
-       },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 8, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc3 = {
-       .clk    = {
-               .name           = "dout_mmc3",
-       },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 12, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_dout_mmc4 = {
-       .clk            = {
-               .name           = "dout_mmc4",
-       },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 16, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS3, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clksrcs[] = {
-       {
-               .clk    = {
-                       .name           = "sclk_pwm",
-                       .enable         = exynos4_clksrc_mask_peril0_ctrl,
-                       .ctrlbit        = (1 << 24),
-               },
-               .sources = &exynos4_clkset_group,
-               .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 24, .size = 4 },
-               .reg_div = { .reg = EXYNOS4_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 = &exynos4_clkset_group,
-               .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 24, .size = 4 },
-               .reg_div = { .reg = EXYNOS4_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 = &exynos4_clkset_group,
-               .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 28, .size = 4 },
-               .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 28, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_cam0",
-                       .enable         = exynos4_clksrc_mask_cam_ctrl,
-                       .ctrlbit        = (1 << 16),
-               },
-               .sources = &exynos4_clkset_group,
-               .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 16, .size = 4 },
-               .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 16, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_cam1",
-                       .enable         = exynos4_clksrc_mask_cam_ctrl,
-                       .ctrlbit        = (1 << 20),
-               },
-               .sources = &exynos4_clkset_group,
-               .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 20, .size = 4 },
-               .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 20, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_fimc",
-                       .devname        = "exynos4-fimc.0",
-                       .enable         = exynos4_clksrc_mask_cam_ctrl,
-                       .ctrlbit        = (1 << 0),
-               },
-               .sources = &exynos4_clkset_group,
-               .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 0, .size = 4 },
-               .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 0, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_fimc",
-                       .devname        = "exynos4-fimc.1",
-                       .enable         = exynos4_clksrc_mask_cam_ctrl,
-                       .ctrlbit        = (1 << 4),
-               },
-               .sources = &exynos4_clkset_group,
-               .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 4, .size = 4 },
-               .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 4, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_fimc",
-                       .devname        = "exynos4-fimc.2",
-                       .enable         = exynos4_clksrc_mask_cam_ctrl,
-                       .ctrlbit        = (1 << 8),
-               },
-               .sources = &exynos4_clkset_group,
-               .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 8, .size = 4 },
-               .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 8, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_fimc",
-                       .devname        = "exynos4-fimc.3",
-                       .enable         = exynos4_clksrc_mask_cam_ctrl,
-                       .ctrlbit        = (1 << 12),
-               },
-               .sources = &exynos4_clkset_group,
-               .reg_src = { .reg = EXYNOS4_CLKSRC_CAM, .shift = 12, .size = 4 },
-               .reg_div = { .reg = EXYNOS4_CLKDIV_CAM, .shift = 12, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_fimd",
-                       .devname        = "exynos4-fb.0",
-                       .enable         = exynos4_clksrc_mask_lcd0_ctrl,
-                       .ctrlbit        = (1 << 0),
-               },
-               .sources = &exynos4_clkset_group,
-               .reg_src = { .reg = EXYNOS4_CLKSRC_LCD0, .shift = 0, .size = 4 },
-               .reg_div = { .reg = EXYNOS4_CLKDIV_LCD0, .shift = 0, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_mfc",
-                       .devname        = "s5p-mfc",
-               },
-               .sources = &exynos4_clkset_mout_mfc,
-               .reg_src = { .reg = EXYNOS4_CLKSRC_MFC, .shift = 8, .size = 1 },
-               .reg_div = { .reg = EXYNOS4_CLKDIV_MFC, .shift = 0, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "ciu",
-                       .parent         = &exynos4_clk_dout_mmc4.clk,
-                       .enable         = exynos4_clksrc_mask_fsys_ctrl,
-                       .ctrlbit        = (1 << 16),
-               },
-               .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS3, .shift = 8, .size = 8 },
-       }
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart0 = {
-       .clk    = {
-               .name           = "uclk1",
-               .devname        = "exynos4210-uart.0",
-               .enable         = exynos4_clksrc_mask_peril0_ctrl,
-               .ctrlbit        = (1 << 0),
-       },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 0, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart1 = {
-       .clk    = {
-               .name           = "uclk1",
-               .devname        = "exynos4210-uart.1",
-               .enable         = exynos4_clksrc_mask_peril0_ctrl,
-               .ctrlbit        = (1 << 4),
-       },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 4, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart2 = {
-       .clk    = {
-               .name           = "uclk1",
-               .devname        = "exynos4210-uart.2",
-               .enable         = exynos4_clksrc_mask_peril0_ctrl,
-               .ctrlbit        = (1 << 8),
-       },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 8, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_uart3 = {
-       .clk    = {
-               .name           = "uclk1",
-               .devname        = "exynos4210-uart.3",
-               .enable         = exynos4_clksrc_mask_peril0_ctrl,
-               .ctrlbit        = (1 << 12),
-       },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL0, .shift = 12, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL0, .shift = 12, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc0 = {
-       .clk    = {
-               .name           = "sclk_mmc",
-               .devname        = "exynos4-sdhci.0",
-               .parent         = &exynos4_clk_dout_mmc0.clk,
-               .enable         = exynos4_clksrc_mask_fsys_ctrl,
-               .ctrlbit        = (1 << 0),
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc1 = {
-       .clk    = {
-               .name           = "sclk_mmc",
-               .devname        = "exynos4-sdhci.1",
-               .parent         = &exynos4_clk_dout_mmc1.clk,
-               .enable         = exynos4_clksrc_mask_fsys_ctrl,
-               .ctrlbit        = (1 << 4),
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc2 = {
-       .clk    = {
-               .name           = "sclk_mmc",
-               .devname        = "exynos4-sdhci.2",
-               .parent         = &exynos4_clk_dout_mmc2.clk,
-               .enable         = exynos4_clksrc_mask_fsys_ctrl,
-               .ctrlbit        = (1 << 8),
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_mmc3 = {
-       .clk    = {
-               .name           = "sclk_mmc",
-               .devname        = "exynos4-sdhci.3",
-               .parent         = &exynos4_clk_dout_mmc3.clk,
-               .enable         = exynos4_clksrc_mask_fsys_ctrl,
-               .ctrlbit        = (1 << 12),
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS2, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi0 = {
-       .clk    = {
-               .name           = "mdout_spi",
-               .devname        = "exynos4210-spi.0",
-       },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 16, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi1 = {
-       .clk    = {
-               .name           = "mdout_spi",
-               .devname        = "exynos4210-spi.1",
-       },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 20, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_mdout_spi2 = {
-       .clk    = {
-               .name           = "mdout_spi",
-               .devname        = "exynos4210-spi.2",
-       },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 24, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi0 = {
-       .clk    = {
-               .name           = "sclk_spi",
-               .devname        = "exynos4210-spi.0",
-               .parent         = &exynos4_clk_mdout_spi0.clk,
-               .enable         = exynos4_clksrc_mask_peril1_ctrl,
-               .ctrlbit        = (1 << 16),
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi1 = {
-       .clk    = {
-               .name           = "sclk_spi",
-               .devname        = "exynos4210-spi.1",
-               .parent         = &exynos4_clk_mdout_spi1.clk,
-               .enable         = exynos4_clksrc_mask_peril1_ctrl,
-               .ctrlbit        = (1 << 20),
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos4_clk_sclk_spi2 = {
-       .clk    = {
-               .name           = "sclk_spi",
-               .devname        = "exynos4210-spi.2",
-               .parent         = &exynos4_clk_mdout_spi2.clk,
-               .enable         = exynos4_clksrc_mask_peril1_ctrl,
-               .ctrlbit        = (1 << 24),
-       },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 8, .size = 8 },
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *exynos4_sysclks[] = {
-       &exynos4_clk_mout_apll,
-       &exynos4_clk_sclk_apll,
-       &exynos4_clk_mout_epll,
-       &exynos4_clk_mout_mpll,
-       &exynos4_clk_moutcore,
-       &exynos4_clk_coreclk,
-       &exynos4_clk_armclk,
-       &exynos4_clk_aclk_corem0,
-       &exynos4_clk_aclk_cores,
-       &exynos4_clk_aclk_corem1,
-       &exynos4_clk_periphclk,
-       &exynos4_clk_mout_corebus,
-       &exynos4_clk_sclk_dmc,
-       &exynos4_clk_aclk_cored,
-       &exynos4_clk_aclk_corep,
-       &exynos4_clk_aclk_acp,
-       &exynos4_clk_pclk_acp,
-       &exynos4_clk_vpllsrc,
-       &exynos4_clk_sclk_vpll,
-       &exynos4_clk_aclk_200,
-       &exynos4_clk_aclk_100,
-       &exynos4_clk_aclk_160,
-       &exynos4_clk_aclk_133,
-       &exynos4_clk_dout_mmc0,
-       &exynos4_clk_dout_mmc1,
-       &exynos4_clk_dout_mmc2,
-       &exynos4_clk_dout_mmc3,
-       &exynos4_clk_dout_mmc4,
-       &exynos4_clk_mout_mfc0,
-       &exynos4_clk_mout_mfc1,
-};
-
-static struct clk *exynos4_clk_cdev[] = {
-       &exynos4_clk_pdma0,
-       &exynos4_clk_pdma1,
-       &exynos4_clk_mdma1,
-       &exynos4_clk_fimd0,
-};
-
-static struct clksrc_clk *exynos4_clksrc_cdev[] = {
-       &exynos4_clk_sclk_uart0,
-       &exynos4_clk_sclk_uart1,
-       &exynos4_clk_sclk_uart2,
-       &exynos4_clk_sclk_uart3,
-       &exynos4_clk_sclk_mmc0,
-       &exynos4_clk_sclk_mmc1,
-       &exynos4_clk_sclk_mmc2,
-       &exynos4_clk_sclk_mmc3,
-       &exynos4_clk_sclk_spi0,
-       &exynos4_clk_sclk_spi1,
-       &exynos4_clk_sclk_spi2,
-       &exynos4_clk_mdout_spi0,
-       &exynos4_clk_mdout_spi1,
-       &exynos4_clk_mdout_spi2,
-};
-
-static struct clk_lookup exynos4_clk_lookup[] = {
-       CLKDEV_INIT("exynos4210-uart.0", "clk_uart_baud0", &exynos4_clk_sclk_uart0.clk),
-       CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos4_clk_sclk_uart1.clk),
-       CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos4_clk_sclk_uart2.clk),
-       CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos4_clk_sclk_uart3.clk),
-       CLKDEV_INIT("exynos4-sdhci.0", "mmc_busclk.2", &exynos4_clk_sclk_mmc0.clk),
-       CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos4_clk_sclk_mmc1.clk),
-       CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos4_clk_sclk_mmc2.clk),
-       CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos4_clk_sclk_mmc3.clk),
-       CLKDEV_INIT("exynos4-fb.0", "lcd", &exynos4_clk_fimd0),
-       CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos4_clk_pdma0),
-       CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos4_clk_pdma1),
-       CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos4_clk_mdma1),
-       CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk),
-       CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk),
-       CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk),
-};
-
-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(EXYNOS4_APLL_CON0),
-                                       pll_4508);
-       else if (soc_is_exynos4212() || soc_is_exynos4412())
-               return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS4_APLL_CON0));
-       else
-               return 0;
-}
-
-static struct clk_ops exynos4_fout_apll_ops = {
-       .get_rate = exynos4_fout_apll_get_rate,
-};
-
-static u32 exynos4_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(EXYNOS4_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(EXYNOS4_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(exynos4_vpll_div); i++) {
-               if (exynos4_vpll_div[i][0] == rate) {
-                       vpll_con0 |= exynos4_vpll_div[i][1] << PLL46XX_PDIV_SHIFT;
-                       vpll_con0 |= exynos4_vpll_div[i][2] << PLL46XX_MDIV_SHIFT;
-                       vpll_con0 |= exynos4_vpll_div[i][3] << PLL46XX_SDIV_SHIFT;
-                       vpll_con1 |= exynos4_vpll_div[i][4] << PLL46XX_KDIV_SHIFT;
-                       vpll_con1 |= exynos4_vpll_div[i][5] << PLL46XX_MFR_SHIFT;
-                       vpll_con1 |= exynos4_vpll_div[i][6] << PLL46XX_MRR_SHIFT;
-                       vpll_con0 |= exynos4_vpll_div[i][7] << 27;
-                       break;
-               }
-       }
-
-       if (i == ARRAY_SIZE(exynos4_vpll_div)) {
-               printk(KERN_ERR "%s: Invalid Clock VPLL Frequency\n",
-                               __func__);
-               return -EINVAL;
-       }
-
-       __raw_writel(vpll_con0, EXYNOS4_VPLL_CON0);
-       __raw_writel(vpll_con1, EXYNOS4_VPLL_CON1);
-
-       /* Wait for VPLL lock */
-       while (!(__raw_readl(EXYNOS4_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(EXYNOS4_APLL_CON0),
-                                       pll_4508);
-               mpll = s5p_get_pll45xx(xtal, __raw_readl(EXYNOS4_MPLL_CON0),
-                                       pll_4508);
-               epll = s5p_get_pll46xx(xtal, __raw_readl(EXYNOS4_EPLL_CON0),
-                                       __raw_readl(EXYNOS4_EPLL_CON1), pll_4600);
-
-               vpllsrc = clk_get_rate(&exynos4_clk_vpllsrc.clk);
-               vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(EXYNOS4_VPLL_CON0),
-                                       __raw_readl(EXYNOS4_VPLL_CON1), pll_4650c);
-       } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
-               apll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS4_APLL_CON0));
-               mpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS4_MPLL_CON0));
-               epll = s5p_get_pll36xx(xtal, __raw_readl(EXYNOS4_EPLL_CON0),
-                                       __raw_readl(EXYNOS4_EPLL_CON1));
-
-               vpllsrc = clk_get_rate(&exynos4_clk_vpllsrc.clk);
-               vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(EXYNOS4_VPLL_CON0),
-                                       __raw_readl(EXYNOS4_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(&exynos4_clk_armclk.clk);
-       sclk_dmc = clk_get_rate(&exynos4_clk_sclk_dmc.clk);
-
-       aclk_200 = clk_get_rate(&exynos4_clk_aclk_200.clk);
-       aclk_100 = clk_get_rate(&exynos4_clk_aclk_100.clk);
-       aclk_160 = clk_get_rate(&exynos4_clk_aclk_160.clk);
-       aclk_133 = clk_get_rate(&exynos4_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(exynos4_clksrcs); ptr++)
-               s3c_set_clksrc(&exynos4_clksrcs[ptr], true);
-}
-
-static struct clk *exynos4_clks[] __initdata = {
-       &exynos4_clk_sclk_hdmi27m,
-       &exynos4_clk_sclk_hdmiphy,
-       &exynos4_clk_sclk_usbphy0,
-       &exynos4_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
-
-static 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(exynos4_clks, ARRAY_SIZE(exynos4_clks));
-
-       for (ptr = 0; ptr < ARRAY_SIZE(exynos4_sysclks); ptr++)
-               s3c_register_clksrc(exynos4_sysclks[ptr], 1);
-
-       for (ptr = 0; ptr < ARRAY_SIZE(exynos4_sclk_tv); ptr++)
-               s3c_register_clksrc(exynos4_sclk_tv[ptr], 1);
-
-       for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clksrc_cdev); ptr++)
-               s3c_register_clksrc(exynos4_clksrc_cdev[ptr], 1);
-
-       s3c_register_clksrc(exynos4_clksrcs, ARRAY_SIZE(exynos4_clksrcs));
-       s3c_register_clocks(exynos4_init_clocks_on, ARRAY_SIZE(exynos4_init_clocks_on));
-
-       s3c24xx_register_clocks(exynos4_clk_cdev, ARRAY_SIZE(exynos4_clk_cdev));
-       for (ptr = 0; ptr < ARRAY_SIZE(exynos4_clk_cdev); ptr++)
-               s3c_disable_clocks(exynos4_clk_cdev[ptr], 1);
-
-       s3c_register_clocks(exynos4_init_clocks_off, ARRAY_SIZE(exynos4_init_clocks_off));
-       s3c_disable_clocks(exynos4_init_clocks_off, ARRAY_SIZE(exynos4_init_clocks_off));
-       clkdev_add_table(exynos4_clk_lookup, ARRAY_SIZE(exynos4_clk_lookup));
-
-       register_syscore_ops(&exynos4_clock_syscore_ops);
-       s3c24xx_register_clock(&dummy_apb_pclk);
-
-       s3c_pwmclk_init();
-}
diff --git a/arch/arm/mach-exynos/clock-exynos4.h b/arch/arm/mach-exynos/clock-exynos4.h
deleted file mode 100644 (file)
index bd12d5f..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2011-2012 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 clksrc_clk exynos4_clk_aclk_133;
-extern struct clksrc_clk exynos4_clk_mout_mpll;
-
-extern struct clksrc_sources exynos4_clkset_mout_corebus;
-extern struct clksrc_sources exynos4_clkset_group;
-
-extern struct clk *exynos4_clkset_aclk_top_list[];
-extern struct clk *exynos4_clkset_group_list[];
-
-extern struct clksrc_sources exynos4_clkset_mout_g2d0;
-extern struct clksrc_sources exynos4_clkset_mout_g2d1;
-
-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);
-extern int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable);
-extern int exynos4_clk_ip_dmc_ctrl(struct clk *clk, int enable);
-
-#endif /* __ASM_ARCH_CLOCK_H */
diff --git a/arch/arm/mach-exynos/clock-exynos4210.c b/arch/arm/mach-exynos/clock-exynos4210.c
deleted file mode 100644 (file)
index 19af9f7..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * EXYNOS4210 - 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/clk.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/pm.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4210_clock_save[] = {
-       SAVE_ITEM(EXYNOS4_CLKSRC_IMAGE),
-       SAVE_ITEM(EXYNOS4_CLKDIV_IMAGE),
-       SAVE_ITEM(EXYNOS4210_CLKSRC_LCD1),
-       SAVE_ITEM(EXYNOS4210_CLKDIV_LCD1),
-       SAVE_ITEM(EXYNOS4210_CLKSRC_MASK_LCD1),
-       SAVE_ITEM(EXYNOS4210_CLKGATE_IP_IMAGE),
-       SAVE_ITEM(EXYNOS4210_CLKGATE_IP_LCD1),
-       SAVE_ITEM(EXYNOS4210_CLKGATE_IP_PERIR),
-};
-#endif
-
-static struct clksrc_clk *sysclks[] = {
-       /* nothing here yet */
-};
-
-static struct clksrc_clk exynos4210_clk_mout_g2d0 = {
-       .clk    = {
-               .name           = "mout_g2d0",
-       },
-       .sources = &exynos4_clkset_mout_g2d0,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk exynos4210_clk_mout_g2d1 = {
-       .clk    = {
-               .name           = "mout_g2d1",
-       },
-       .sources = &exynos4_clkset_mout_g2d1,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 4, .size = 1 },
-};
-
-static struct clk *exynos4210_clkset_mout_g2d_list[] = {
-       [0] = &exynos4210_clk_mout_g2d0.clk,
-       [1] = &exynos4210_clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources exynos4210_clkset_mout_g2d = {
-       .sources        = exynos4210_clkset_mout_g2d_list,
-       .nr_sources     = ARRAY_SIZE(exynos4210_clkset_mout_g2d_list),
-};
-
-static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4210_CLKSRC_MASK_LCD1, clk, enable);
-}
-
-static struct clksrc_clk clksrcs[] = {
-       {
-               .clk            = {
-                       .name           = "sclk_sata",
-                       .id             = -1,
-                       .enable         = exynos4_clksrc_mask_fsys_ctrl,
-                       .ctrlbit        = (1 << 24),
-               },
-               .sources = &exynos4_clkset_mout_corebus,
-               .reg_src = { .reg = EXYNOS4_CLKSRC_FSYS, .shift = 24, .size = 1 },
-               .reg_div = { .reg = EXYNOS4_CLKDIV_FSYS0, .shift = 20, .size = 4 },
-       }, {
-               .clk            = {
-                       .name           = "sclk_fimd",
-                       .devname        = "exynos4-fb.1",
-                       .enable         = exynos4_clksrc_mask_lcd1_ctrl,
-                       .ctrlbit        = (1 << 0),
-               },
-               .sources = &exynos4_clkset_group,
-               .reg_src = { .reg = EXYNOS4210_CLKSRC_LCD1, .shift = 0, .size = 4 },
-               .reg_div = { .reg = EXYNOS4210_CLKDIV_LCD1, .shift = 0, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_fimg2d",
-               },
-               .sources = &exynos4210_clkset_mout_g2d,
-               .reg_src = { .reg = EXYNOS4_CLKSRC_IMAGE, .shift = 8, .size = 1 },
-               .reg_div = { .reg = EXYNOS4_CLKDIV_IMAGE, .shift = 0, .size = 4 },
-       },
-};
-
-static struct clk init_clocks_off[] = {
-       {
-               .name           = "sataphy",
-               .id             = -1,
-               .parent         = &exynos4_clk_aclk_133.clk,
-               .enable         = exynos4_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 3),
-       }, {
-               .name           = "sata",
-               .id             = -1,
-               .parent         = &exynos4_clk_aclk_133.clk,
-               .enable         = exynos4_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 10),
-       }, {
-               .name           = "fimd",
-               .devname        = "exynos4-fb.1",
-               .enable         = exynos4_clk_ip_lcd1_ctrl,
-               .ctrlbit        = (1 << 0),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.9",
-               .enable         = exynos4_clk_ip_image_ctrl,
-               .ctrlbit        = (1 << 3),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.11",
-               .enable         = exynos4_clk_ip_lcd1_ctrl,
-               .ctrlbit        = (1 << 4),
-       }, {
-               .name           = "fimg2d",
-               .enable         = exynos4_clk_ip_image_ctrl,
-               .ctrlbit        = (1 << 0),
-       },
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4210_clock_suspend(void)
-{
-       s3c_pm_do_save(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
-
-       return 0;
-}
-
-static void exynos4210_clock_resume(void)
-{
-       s3c_pm_do_restore_core(exynos4210_clock_save, ARRAY_SIZE(exynos4210_clock_save));
-}
-
-#else
-#define exynos4210_clock_suspend NULL
-#define exynos4210_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4210_clock_syscore_ops = {
-       .suspend        = exynos4210_clock_suspend,
-       .resume         = exynos4210_clock_resume,
-};
-
-void __init exynos4210_register_clocks(void)
-{
-       int ptr;
-
-       exynos4_clk_mout_mpll.reg_src.reg = EXYNOS4_CLKSRC_CPU;
-       exynos4_clk_mout_mpll.reg_src.shift = 8;
-       exynos4_clk_mout_mpll.reg_src.size = 1;
-
-       for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-               s3c_register_clksrc(sysclks[ptr], 1);
-
-       s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-
-       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(&exynos4210_clock_syscore_ops);
-}
diff --git a/arch/arm/mach-exynos/clock-exynos4212.c b/arch/arm/mach-exynos/clock-exynos4212.c
deleted file mode 100644 (file)
index 529476f..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- * Copyright (c) 2011-2012 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * EXYNOS4212 - 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/clk.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/pm.h>
-
-#include <mach/hardware.h>
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include "common.h"
-#include "clock-exynos4.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos4212_clock_save[] = {
-       SAVE_ITEM(EXYNOS4_CLKSRC_IMAGE),
-       SAVE_ITEM(EXYNOS4_CLKDIV_IMAGE),
-       SAVE_ITEM(EXYNOS4212_CLKGATE_IP_IMAGE),
-       SAVE_ITEM(EXYNOS4212_CLKGATE_IP_PERIR),
-};
-#endif
-
-static int exynos4212_clk_ip_isp0_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP0, clk, enable);
-}
-
-static int exynos4212_clk_ip_isp1_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS4_CLKGATE_IP_ISP1, clk, enable);
-}
-
-static struct clk *clk_src_mpll_user_list[] = {
-       [0] = &clk_fin_mpll,
-       [1] = &exynos4_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clk_src_mpll_user = {
-       .sources        = clk_src_mpll_user_list,
-       .nr_sources     = ARRAY_SIZE(clk_src_mpll_user_list),
-};
-
-static struct clksrc_clk clk_mout_mpll_user = {
-       .clk = {
-               .name           = "mout_mpll_user",
-       },
-       .sources        = &clk_src_mpll_user,
-       .reg_src        = { .reg = EXYNOS4_CLKSRC_CPU, .shift = 24, .size = 1 },
-};
-
-static struct clksrc_clk exynos4x12_clk_mout_g2d0 = {
-       .clk    = {
-               .name           = "mout_g2d0",
-       },
-       .sources = &exynos4_clkset_mout_g2d0,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 20, .size = 1 },
-};
-
-static struct clksrc_clk exynos4x12_clk_mout_g2d1 = {
-       .clk    = {
-               .name           = "mout_g2d1",
-       },
-       .sources = &exynos4_clkset_mout_g2d1,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 24, .size = 1 },
-};
-
-static struct clk *exynos4x12_clkset_mout_g2d_list[] = {
-       [0] = &exynos4x12_clk_mout_g2d0.clk,
-       [1] = &exynos4x12_clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources exynos4x12_clkset_mout_g2d = {
-       .sources        = exynos4x12_clkset_mout_g2d_list,
-       .nr_sources     = ARRAY_SIZE(exynos4x12_clkset_mout_g2d_list),
-};
-
-static struct clksrc_clk *sysclks[] = {
-       &clk_mout_mpll_user,
-};
-
-static struct clksrc_clk clksrcs[] = {
-       {
-               .clk    = {
-                       .name           = "sclk_fimg2d",
-               },
-               .sources = &exynos4x12_clkset_mout_g2d,
-               .reg_src = { .reg = EXYNOS4_CLKSRC_DMC, .shift = 28, .size = 1 },
-               .reg_div = { .reg = EXYNOS4_CLKDIV_DMC1, .shift = 0, .size = 4 },
-       },
-};
-
-static struct clk init_clocks_off[] = {
-       {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.9",
-               .enable         = exynos4_clk_ip_dmc_ctrl,
-               .ctrlbit        = (1 << 24),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.12",
-               .enable         = exynos4212_clk_ip_isp0_ctrl,
-               .ctrlbit        = (7 << 8),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.13",
-               .enable         = exynos4212_clk_ip_isp1_ctrl,
-               .ctrlbit        = (1 << 4),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.14",
-               .enable         = exynos4212_clk_ip_isp0_ctrl,
-               .ctrlbit        = (1 << 11),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.15",
-               .enable         = exynos4212_clk_ip_isp0_ctrl,
-               .ctrlbit        = (1 << 12),
-       }, {
-               .name           = "flite",
-               .devname        = "exynos-fimc-lite.0",
-               .enable         = exynos4212_clk_ip_isp0_ctrl,
-               .ctrlbit        = (1 << 4),
-       }, {
-               .name           = "flite",
-               .devname        = "exynos-fimc-lite.1",
-               .enable         = exynos4212_clk_ip_isp0_ctrl,
-               .ctrlbit        = (1 << 3),
-       }, {
-               .name           = "fimg2d",
-               .enable         = exynos4_clk_ip_dmc_ctrl,
-               .ctrlbit        = (1 << 23),
-       },
-};
-
-#ifdef CONFIG_PM_SLEEP
-static int exynos4212_clock_suspend(void)
-{
-       s3c_pm_do_save(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
-
-       return 0;
-}
-
-static void exynos4212_clock_resume(void)
-{
-       s3c_pm_do_restore_core(exynos4212_clock_save, ARRAY_SIZE(exynos4212_clock_save));
-}
-
-#else
-#define exynos4212_clock_suspend NULL
-#define exynos4212_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos4212_clock_syscore_ops = {
-       .suspend        = exynos4212_clock_suspend,
-       .resume         = exynos4212_clock_resume,
-};
-
-void __init exynos4212_register_clocks(void)
-{
-       int ptr;
-
-       /* usbphy1 is removed */
-       exynos4_clkset_group_list[4] = NULL;
-
-       /* mout_mpll_user is used */
-       exynos4_clkset_group_list[6] = &clk_mout_mpll_user.clk;
-       exynos4_clkset_aclk_top_list[0] = &clk_mout_mpll_user.clk;
-
-       exynos4_clk_mout_mpll.reg_src.reg = EXYNOS4_CLKSRC_DMC;
-       exynos4_clk_mout_mpll.reg_src.shift = 12;
-       exynos4_clk_mout_mpll.reg_src.size = 1;
-
-       for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-               s3c_register_clksrc(sysclks[ptr], 1);
-
-       s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-
-       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(&exynos4212_clock_syscore_ops);
-}
diff --git a/arch/arm/mach-exynos/clock-exynos5.c b/arch/arm/mach-exynos/clock-exynos5.c
deleted file mode 100644 (file)
index b0ea31f..0000000
+++ /dev/null
@@ -1,1645 +0,0 @@
-/*
- * Copyright (c) 2012 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Clock support for EXYNOS5 SoCs
- *
- * 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/pm.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-#include "common.h"
-
-#ifdef CONFIG_PM_SLEEP
-static struct sleep_save exynos5_clock_save[] = {
-       SAVE_ITEM(EXYNOS5_CLKSRC_MASK_TOP),
-       SAVE_ITEM(EXYNOS5_CLKSRC_MASK_GSCL),
-       SAVE_ITEM(EXYNOS5_CLKSRC_MASK_DISP1_0),
-       SAVE_ITEM(EXYNOS5_CLKSRC_MASK_FSYS),
-       SAVE_ITEM(EXYNOS5_CLKSRC_MASK_MAUDIO),
-       SAVE_ITEM(EXYNOS5_CLKSRC_MASK_PERIC0),
-       SAVE_ITEM(EXYNOS5_CLKSRC_MASK_PERIC1),
-       SAVE_ITEM(EXYNOS5_CLKGATE_IP_GSCL),
-       SAVE_ITEM(EXYNOS5_CLKGATE_IP_DISP1),
-       SAVE_ITEM(EXYNOS5_CLKGATE_IP_MFC),
-       SAVE_ITEM(EXYNOS5_CLKGATE_IP_G3D),
-       SAVE_ITEM(EXYNOS5_CLKGATE_IP_GEN),
-       SAVE_ITEM(EXYNOS5_CLKGATE_IP_FSYS),
-       SAVE_ITEM(EXYNOS5_CLKGATE_IP_PERIC),
-       SAVE_ITEM(EXYNOS5_CLKGATE_IP_PERIS),
-       SAVE_ITEM(EXYNOS5_CLKGATE_BLOCK),
-       SAVE_ITEM(EXYNOS5_CLKDIV_TOP0),
-       SAVE_ITEM(EXYNOS5_CLKDIV_TOP1),
-       SAVE_ITEM(EXYNOS5_CLKDIV_GSCL),
-       SAVE_ITEM(EXYNOS5_CLKDIV_DISP1_0),
-       SAVE_ITEM(EXYNOS5_CLKDIV_GEN),
-       SAVE_ITEM(EXYNOS5_CLKDIV_MAUDIO),
-       SAVE_ITEM(EXYNOS5_CLKDIV_FSYS0),
-       SAVE_ITEM(EXYNOS5_CLKDIV_FSYS1),
-       SAVE_ITEM(EXYNOS5_CLKDIV_FSYS2),
-       SAVE_ITEM(EXYNOS5_CLKDIV_FSYS3),
-       SAVE_ITEM(EXYNOS5_CLKDIV_PERIC0),
-       SAVE_ITEM(EXYNOS5_CLKDIV_PERIC1),
-       SAVE_ITEM(EXYNOS5_CLKDIV_PERIC2),
-       SAVE_ITEM(EXYNOS5_CLKDIV_PERIC3),
-       SAVE_ITEM(EXYNOS5_CLKDIV_PERIC4),
-       SAVE_ITEM(EXYNOS5_CLKDIV_PERIC5),
-       SAVE_ITEM(EXYNOS5_SCLK_DIV_ISP),
-       SAVE_ITEM(EXYNOS5_CLKSRC_TOP0),
-       SAVE_ITEM(EXYNOS5_CLKSRC_TOP1),
-       SAVE_ITEM(EXYNOS5_CLKSRC_TOP2),
-       SAVE_ITEM(EXYNOS5_CLKSRC_TOP3),
-       SAVE_ITEM(EXYNOS5_CLKSRC_GSCL),
-       SAVE_ITEM(EXYNOS5_CLKSRC_DISP1_0),
-       SAVE_ITEM(EXYNOS5_CLKSRC_MAUDIO),
-       SAVE_ITEM(EXYNOS5_CLKSRC_FSYS),
-       SAVE_ITEM(EXYNOS5_CLKSRC_PERIC0),
-       SAVE_ITEM(EXYNOS5_CLKSRC_PERIC1),
-       SAVE_ITEM(EXYNOS5_SCLK_SRC_ISP),
-       SAVE_ITEM(EXYNOS5_EPLL_CON0),
-       SAVE_ITEM(EXYNOS5_EPLL_CON1),
-       SAVE_ITEM(EXYNOS5_EPLL_CON2),
-       SAVE_ITEM(EXYNOS5_VPLL_CON0),
-       SAVE_ITEM(EXYNOS5_VPLL_CON1),
-       SAVE_ITEM(EXYNOS5_VPLL_CON2),
-       SAVE_ITEM(EXYNOS5_PWR_CTRL1),
-       SAVE_ITEM(EXYNOS5_PWR_CTRL2),
-};
-#endif
-
-static struct clk exynos5_clk_sclk_dptxphy = {
-       .name           = "sclk_dptx",
-};
-
-static struct clk exynos5_clk_sclk_hdmi24m = {
-       .name           = "sclk_hdmi24m",
-       .rate           = 24000000,
-};
-
-static struct clk exynos5_clk_sclk_hdmi27m = {
-       .name           = "sclk_hdmi27m",
-       .rate           = 27000000,
-};
-
-static struct clk exynos5_clk_sclk_hdmiphy = {
-       .name           = "sclk_hdmiphy",
-};
-
-static struct clk exynos5_clk_sclk_usbphy = {
-       .name           = "sclk_usbphy",
-       .rate           = 48000000,
-};
-
-static int exynos5_clksrc_mask_top_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_TOP, clk, enable);
-}
-
-static int exynos5_clksrc_mask_disp1_0_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_DISP1_0, clk, enable);
-}
-
-static int exynos5_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_FSYS, clk, enable);
-}
-
-static int exynos5_clksrc_mask_gscl_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_GSCL, clk, enable);
-}
-
-static int exynos5_clksrc_mask_peric0_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC0, clk, enable);
-}
-
-static int exynos5_clksrc_mask_peric1_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKSRC_MASK_PERIC1, clk, enable);
-}
-
-static int exynos5_clk_ip_acp_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ACP, clk, enable);
-}
-
-static int exynos5_clk_ip_core_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_CORE, clk, enable);
-}
-
-static int exynos5_clk_ip_disp1_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_DISP1, clk, enable);
-}
-
-static int exynos5_clk_ip_fsys_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_FSYS, clk, enable);
-}
-
-static int exynos5_clk_block_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKGATE_BLOCK, clk, enable);
-}
-
-static int exynos5_clk_ip_gen_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GEN, clk, enable);
-}
-
-static int exynos5_clk_ip_mfc_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_MFC, clk, enable);
-}
-
-static int exynos5_clk_ip_peric_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIC, clk, enable);
-}
-
-static int exynos5_clk_ip_peris_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_PERIS, clk, enable);
-}
-
-static int exynos5_clk_ip_gscl_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_GSCL, clk, enable);
-}
-
-static int exynos5_clk_ip_isp0_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ISP0, clk, enable);
-}
-
-static int exynos5_clk_ip_isp1_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(EXYNOS5_CLKGATE_IP_ISP1, clk, enable);
-}
-
-static int exynos5_clk_hdmiphy_ctrl(struct clk *clk, int enable)
-{
-       return s5p_gatectrl(S5P_HDMI_PHY_CONTROL, clk, enable);
-}
-
-/* Core list of CMU_CPU side */
-
-static struct clksrc_clk exynos5_clk_mout_apll = {
-       .clk    = {
-               .name           = "mout_apll",
-       },
-       .sources = &clk_src_apll,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_CPU, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_apll = {
-       .clk    = {
-               .name           = "sclk_apll",
-               .parent         = &exynos5_clk_mout_apll.clk,
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 24, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_mout_bpll_fout = {
-       .clk    = {
-               .name           = "mout_bpll_fout",
-       },
-       .sources = &clk_src_bpll_fout,
-       .reg_src = { .reg = EXYNOS5_PLL_DIV2_SEL, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos5_clk_src_bpll_list[] = {
-       [0] = &clk_fin_bpll,
-       [1] = &exynos5_clk_mout_bpll_fout.clk,
-};
-
-static struct clksrc_sources exynos5_clk_src_bpll = {
-       .sources        = exynos5_clk_src_bpll_list,
-       .nr_sources     = ARRAY_SIZE(exynos5_clk_src_bpll_list),
-};
-
-static struct clksrc_clk exynos5_clk_mout_bpll = {
-       .clk    = {
-               .name           = "mout_bpll",
-       },
-       .sources = &exynos5_clk_src_bpll,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_CDREX, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos5_clk_src_bpll_user_list[] = {
-       [0] = &clk_fin_mpll,
-       [1] = &exynos5_clk_mout_bpll.clk,
-};
-
-static struct clksrc_sources exynos5_clk_src_bpll_user = {
-       .sources        = exynos5_clk_src_bpll_user_list,
-       .nr_sources     = ARRAY_SIZE(exynos5_clk_src_bpll_user_list),
-};
-
-static struct clksrc_clk exynos5_clk_mout_bpll_user = {
-       .clk    = {
-               .name           = "mout_bpll_user",
-       },
-       .sources = &exynos5_clk_src_bpll_user,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 24, .size = 1 },
-};
-
-static struct clksrc_clk exynos5_clk_mout_cpll = {
-       .clk    = {
-               .name           = "mout_cpll",
-       },
-       .sources = &clk_src_cpll,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 8, .size = 1 },
-};
-
-static struct clksrc_clk exynos5_clk_mout_epll = {
-       .clk    = {
-               .name           = "mout_epll",
-       },
-       .sources = &clk_src_epll,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 12, .size = 1 },
-};
-
-static struct clksrc_clk exynos5_clk_mout_mpll_fout = {
-       .clk    = {
-               .name           = "mout_mpll_fout",
-       },
-       .sources = &clk_src_mpll_fout,
-       .reg_src = { .reg = EXYNOS5_PLL_DIV2_SEL, .shift = 4, .size = 1 },
-};
-
-static struct clk *exynos5_clk_src_mpll_list[] = {
-       [0] = &clk_fin_mpll,
-       [1] = &exynos5_clk_mout_mpll_fout.clk,
-};
-
-static struct clksrc_sources exynos5_clk_src_mpll = {
-       .sources        = exynos5_clk_src_mpll_list,
-       .nr_sources     = ARRAY_SIZE(exynos5_clk_src_mpll_list),
-};
-
-static struct clksrc_clk exynos5_clk_mout_mpll = {
-       .clk = {
-               .name           = "mout_mpll",
-       },
-       .sources = &exynos5_clk_src_mpll,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_CORE1, .shift = 8, .size = 1 },
-};
-
-static struct clk *exynos_clkset_vpllsrc_list[] = {
-       [0] = &clk_fin_vpll,
-       [1] = &exynos5_clk_sclk_hdmi27m,
-};
-
-static struct clksrc_sources exynos5_clkset_vpllsrc = {
-       .sources        = exynos_clkset_vpllsrc_list,
-       .nr_sources     = ARRAY_SIZE(exynos_clkset_vpllsrc_list),
-};
-
-static struct clksrc_clk exynos5_clk_vpllsrc = {
-       .clk    = {
-               .name           = "vpll_src",
-               .enable         = exynos5_clksrc_mask_top_ctrl,
-               .ctrlbit        = (1 << 0),
-       },
-       .sources = &exynos5_clkset_vpllsrc,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 0, .size = 1 },
-};
-
-static struct clk *exynos5_clkset_sclk_vpll_list[] = {
-       [0] = &exynos5_clk_vpllsrc.clk,
-       [1] = &clk_fout_vpll,
-};
-
-static struct clksrc_sources exynos5_clkset_sclk_vpll = {
-       .sources        = exynos5_clkset_sclk_vpll_list,
-       .nr_sources     = ARRAY_SIZE(exynos5_clkset_sclk_vpll_list),
-};
-
-static struct clksrc_clk exynos5_clk_sclk_vpll = {
-       .clk    = {
-               .name           = "sclk_vpll",
-       },
-       .sources = &exynos5_clkset_sclk_vpll,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_pixel = {
-       .clk    = {
-               .name           = "sclk_pixel",
-               .parent         = &exynos5_clk_sclk_vpll.clk,
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_DISP1_0, .shift = 28, .size = 4 },
-};
-
-static struct clk *exynos5_clkset_sclk_hdmi_list[] = {
-       [0] = &exynos5_clk_sclk_pixel.clk,
-       [1] = &exynos5_clk_sclk_hdmiphy,
-};
-
-static struct clksrc_sources exynos5_clkset_sclk_hdmi = {
-       .sources        = exynos5_clkset_sclk_hdmi_list,
-       .nr_sources     = ARRAY_SIZE(exynos5_clkset_sclk_hdmi_list),
-};
-
-static struct clksrc_clk exynos5_clk_sclk_hdmi = {
-       .clk    = {
-               .name           = "sclk_hdmi",
-               .enable         = exynos5_clksrc_mask_disp1_0_ctrl,
-               .ctrlbit        = (1 << 20),
-       },
-       .sources = &exynos5_clkset_sclk_hdmi,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_DISP1_0, .shift = 20, .size = 1 },
-};
-
-static struct clksrc_clk *exynos5_sclk_tv[] = {
-       &exynos5_clk_sclk_pixel,
-       &exynos5_clk_sclk_hdmi,
-};
-
-static struct clk *exynos5_clk_src_mpll_user_list[] = {
-       [0] = &clk_fin_mpll,
-       [1] = &exynos5_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources exynos5_clk_src_mpll_user = {
-       .sources        = exynos5_clk_src_mpll_user_list,
-       .nr_sources     = ARRAY_SIZE(exynos5_clk_src_mpll_user_list),
-};
-
-static struct clksrc_clk exynos5_clk_mout_mpll_user = {
-       .clk    = {
-               .name           = "mout_mpll_user",
-       },
-       .sources = &exynos5_clk_src_mpll_user,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP2, .shift = 20, .size = 1 },
-};
-
-static struct clk *exynos5_clkset_mout_cpu_list[] = {
-       [0] = &exynos5_clk_mout_apll.clk,
-       [1] = &exynos5_clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources exynos5_clkset_mout_cpu = {
-       .sources        = exynos5_clkset_mout_cpu_list,
-       .nr_sources     = ARRAY_SIZE(exynos5_clkset_mout_cpu_list),
-};
-
-static struct clksrc_clk exynos5_clk_mout_cpu = {
-       .clk    = {
-               .name           = "mout_cpu",
-       },
-       .sources = &exynos5_clkset_mout_cpu,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_CPU, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk exynos5_clk_dout_armclk = {
-       .clk    = {
-               .name           = "dout_armclk",
-               .parent         = &exynos5_clk_mout_cpu.clk,
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_dout_arm2clk = {
-       .clk    = {
-               .name           = "dout_arm2clk",
-               .parent         = &exynos5_clk_dout_armclk.clk,
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_CPU0, .shift = 28, .size = 3 },
-};
-
-static struct clk exynos5_clk_armclk = {
-       .name           = "armclk",
-       .parent         = &exynos5_clk_dout_arm2clk.clk,
-};
-
-/* Core list of CMU_CDREX side */
-
-static struct clk *exynos5_clkset_cdrex_list[] = {
-       [0] = &exynos5_clk_mout_mpll.clk,
-       [1] = &exynos5_clk_mout_bpll.clk,
-};
-
-static struct clksrc_sources exynos5_clkset_cdrex = {
-       .sources        = exynos5_clkset_cdrex_list,
-       .nr_sources     = ARRAY_SIZE(exynos5_clkset_cdrex_list),
-};
-
-static struct clksrc_clk exynos5_clk_cdrex = {
-       .clk    = {
-               .name           = "clk_cdrex",
-       },
-       .sources = &exynos5_clkset_cdrex,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_CDREX, .shift = 4, .size = 1 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_CDREX, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_aclk_acp = {
-       .clk    = {
-               .name           = "aclk_acp",
-               .parent         = &exynos5_clk_mout_mpll.clk,
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_ACP, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_pclk_acp = {
-       .clk    = {
-               .name           = "pclk_acp",
-               .parent         = &exynos5_clk_aclk_acp.clk,
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_ACP, .shift = 4, .size = 3 },
-};
-
-/* Core list of CMU_TOP side */
-
-static struct clk *exynos5_clkset_aclk_top_list[] = {
-       [0] = &exynos5_clk_mout_mpll_user.clk,
-       [1] = &exynos5_clk_mout_bpll_user.clk,
-};
-
-static struct clksrc_sources exynos5_clkset_aclk = {
-       .sources        = exynos5_clkset_aclk_top_list,
-       .nr_sources     = ARRAY_SIZE(exynos5_clkset_aclk_top_list),
-};
-
-static struct clksrc_clk exynos5_clk_aclk_400 = {
-       .clk    = {
-               .name           = "aclk_400",
-       },
-       .sources = &exynos5_clkset_aclk,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 20, .size = 1 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 },
-};
-
-static struct clk *exynos5_clkset_aclk_333_166_list[] = {
-       [0] = &exynos5_clk_mout_cpll.clk,
-       [1] = &exynos5_clk_mout_mpll_user.clk,
-};
-
-static struct clksrc_sources exynos5_clkset_aclk_333_166 = {
-       .sources        = exynos5_clkset_aclk_333_166_list,
-       .nr_sources     = ARRAY_SIZE(exynos5_clkset_aclk_333_166_list),
-};
-
-static struct clksrc_clk exynos5_clk_aclk_333 = {
-       .clk    = {
-               .name           = "aclk_333",
-       },
-       .sources = &exynos5_clkset_aclk_333_166,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 16, .size = 1 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 20, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_aclk_166 = {
-       .clk    = {
-               .name           = "aclk_166",
-       },
-       .sources = &exynos5_clkset_aclk_333_166,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 8, .size = 1 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_aclk_266 = {
-       .clk    = {
-               .name           = "aclk_266",
-               .parent         = &exynos5_clk_mout_mpll_user.clk,
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_aclk_200 = {
-       .clk    = {
-               .name           = "aclk_200",
-       },
-       .sources = &exynos5_clkset_aclk,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 12, .size = 1 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_aclk_66_pre = {
-       .clk    = {
-               .name           = "aclk_66_pre",
-               .parent         = &exynos5_clk_mout_mpll_user.clk,
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_TOP1, .shift = 24, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_aclk_66 = {
-       .clk    = {
-               .name           = "aclk_66",
-               .parent         = &exynos5_clk_aclk_66_pre.clk,
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk exynos5_clk_mout_aclk_300_gscl_mid = {
-       .clk    = {
-               .name           = "mout_aclk_300_gscl_mid",
-       },
-       .sources = &exynos5_clkset_aclk,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 24, .size = 1 },
-};
-
-static struct clk *exynos5_clkset_aclk_300_mid1_list[] = {
-       [0] = &exynos5_clk_sclk_vpll.clk,
-       [1] = &exynos5_clk_mout_cpll.clk,
-};
-
-static struct clksrc_sources exynos5_clkset_aclk_300_gscl_mid1 = {
-       .sources        = exynos5_clkset_aclk_300_mid1_list,
-       .nr_sources     = ARRAY_SIZE(exynos5_clkset_aclk_300_mid1_list),
-};
-
-static struct clksrc_clk exynos5_clk_mout_aclk_300_gscl_mid1 = {
-       .clk    = {
-               .name           = "mout_aclk_300_gscl_mid1",
-       },
-       .sources = &exynos5_clkset_aclk_300_gscl_mid1,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP1, .shift = 12, .size = 1 },
-};
-
-static struct clk *exynos5_clkset_aclk_300_gscl_list[] = {
-       [0] = &exynos5_clk_mout_aclk_300_gscl_mid.clk,
-       [1] = &exynos5_clk_mout_aclk_300_gscl_mid1.clk,
-};
-
-static struct clksrc_sources exynos5_clkset_aclk_300_gscl = {
-       .sources        = exynos5_clkset_aclk_300_gscl_list,
-       .nr_sources     = ARRAY_SIZE(exynos5_clkset_aclk_300_gscl_list),
-};
-
-static struct clksrc_clk exynos5_clk_mout_aclk_300_gscl = {
-       .clk    = {
-               .name           = "mout_aclk_300_gscl",
-       },
-       .sources = &exynos5_clkset_aclk_300_gscl,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 25, .size = 1 },
-};
-
-static struct clk *exynos5_clk_src_gscl_300_list[] = {
-       [0] = &clk_ext_xtal_mux,
-       [1] = &exynos5_clk_mout_aclk_300_gscl.clk,
-};
-
-static struct clksrc_sources exynos5_clk_src_gscl_300 = {
-       .sources        = exynos5_clk_src_gscl_300_list,
-       .nr_sources     = ARRAY_SIZE(exynos5_clk_src_gscl_300_list),
-};
-
-static struct clksrc_clk exynos5_clk_aclk_300_gscl = {
-       .clk    = {
-               .name           = "aclk_300_gscl",
-       },
-       .sources = &exynos5_clk_src_gscl_300,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_TOP3, .shift = 10, .size = 1 },
-};
-
-static struct clk exynos5_init_clocks_off[] = {
-       {
-               .name           = "timers",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 24),
-       }, {
-               .name           = "tmu_apbif",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peris_ctrl,
-               .ctrlbit        = (1 << 21),
-       }, {
-               .name           = "rtc",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peris_ctrl,
-               .ctrlbit        = (1 << 20),
-       }, {
-               .name           = "watchdog",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peris_ctrl,
-               .ctrlbit        = (1 << 19),
-       }, {
-               .name           = "biu",        /* bus interface unit clock */
-               .devname        = "dw_mmc.0",
-               .parent         = &exynos5_clk_aclk_200.clk,
-               .enable         = exynos5_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 12),
-       }, {
-               .name           = "biu",
-               .devname        = "dw_mmc.1",
-               .parent         = &exynos5_clk_aclk_200.clk,
-               .enable         = exynos5_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 13),
-       }, {
-               .name           = "biu",
-               .devname        = "dw_mmc.2",
-               .parent         = &exynos5_clk_aclk_200.clk,
-               .enable         = exynos5_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 14),
-       }, {
-               .name           = "biu",
-               .devname        = "dw_mmc.3",
-               .parent         = &exynos5_clk_aclk_200.clk,
-               .enable         = exynos5_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 15),
-       }, {
-               .name           = "sata",
-               .devname        = "exynos5-sata",
-               .parent         = &exynos5_clk_aclk_200.clk,
-               .enable         = exynos5_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 6),
-       }, {
-               .name           = "sata-phy",
-               .devname        = "exynos5-sata-phy",
-               .parent         = &exynos5_clk_aclk_200.clk,
-               .enable         = exynos5_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 24),
-       }, {
-               .name           = "i2c",
-               .devname        = "exynos5-sata-phy-i2c",
-               .parent         = &exynos5_clk_aclk_200.clk,
-               .enable         = exynos5_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 25),
-       }, {
-               .name           = "mfc",
-               .devname        = "s5p-mfc-v6",
-               .enable         = exynos5_clk_ip_mfc_ctrl,
-               .ctrlbit        = (1 << 0),
-       }, {
-               .name           = "hdmi",
-               .devname        = "exynos5-hdmi",
-               .enable         = exynos5_clk_ip_disp1_ctrl,
-               .ctrlbit        = (1 << 6),
-       }, {
-               .name           = "hdmiphy",
-               .devname        = "exynos5-hdmi",
-               .enable         = exynos5_clk_hdmiphy_ctrl,
-               .ctrlbit        = (1 << 0),
-       }, {
-               .name           = "mixer",
-               .devname        = "exynos5-mixer",
-               .enable         = exynos5_clk_ip_disp1_ctrl,
-               .ctrlbit        = (1 << 5),
-       }, {
-               .name           = "dp",
-               .devname        = "exynos-dp",
-               .enable         = exynos5_clk_ip_disp1_ctrl,
-               .ctrlbit        = (1 << 4),
-       }, {
-               .name           = "jpeg",
-               .enable         = exynos5_clk_ip_gen_ctrl,
-               .ctrlbit        = (1 << 2),
-       }, {
-               .name           = "dsim0",
-               .enable         = exynos5_clk_ip_disp1_ctrl,
-               .ctrlbit        = (1 << 3),
-       }, {
-               .name           = "iis",
-               .devname        = "samsung-i2s.1",
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 20),
-       }, {
-               .name           = "iis",
-               .devname        = "samsung-i2s.2",
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 21),
-       }, {
-               .name           = "pcm",
-               .devname        = "samsung-pcm.1",
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 22),
-       }, {
-               .name           = "pcm",
-               .devname        = "samsung-pcm.2",
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 23),
-       }, {
-               .name           = "spdif",
-               .devname        = "samsung-spdif",
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 26),
-       }, {
-               .name           = "ac97",
-               .devname        = "samsung-ac97",
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 27),
-       }, {
-               .name           = "usbhost",
-               .enable         = exynos5_clk_ip_fsys_ctrl ,
-               .ctrlbit        = (1 << 18),
-       }, {
-               .name           = "usbotg",
-               .enable         = exynos5_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 7),
-       }, {
-               .name           = "nfcon",
-               .enable         = exynos5_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 22),
-       }, {
-               .name           = "iop",
-               .enable         = exynos5_clk_ip_fsys_ctrl,
-               .ctrlbit        = ((1 << 30) | (1 << 26) | (1 << 23)),
-       }, {
-               .name           = "core_iop",
-               .enable         = exynos5_clk_ip_core_ctrl,
-               .ctrlbit        = ((1 << 21) | (1 << 3)),
-       }, {
-               .name           = "mcu_iop",
-               .enable         = exynos5_clk_ip_fsys_ctrl,
-               .ctrlbit        = (1 << 0),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.0",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 6),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.1",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 7),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.2",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 8),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.3",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 9),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.4",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 10),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.5",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 11),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.6",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 12),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-i2c.7",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 13),
-       }, {
-               .name           = "i2c",
-               .devname        = "s3c2440-hdmiphy-i2c",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 14),
-       }, {
-               .name           = "spi",
-               .devname        = "exynos4210-spi.0",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 16),
-       }, {
-               .name           = "spi",
-               .devname        = "exynos4210-spi.1",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 17),
-       }, {
-               .name           = "spi",
-               .devname        = "exynos4210-spi.2",
-               .parent         = &exynos5_clk_aclk_66.clk,
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 18),
-       }, {
-               .name           = "gscl",
-               .devname        = "exynos-gsc.0",
-               .enable         = exynos5_clk_ip_gscl_ctrl,
-               .ctrlbit        = (1 << 0),
-       }, {
-               .name           = "gscl",
-               .devname        = "exynos-gsc.1",
-               .enable         = exynos5_clk_ip_gscl_ctrl,
-               .ctrlbit        = (1 << 1),
-       }, {
-               .name           = "gscl",
-               .devname        = "exynos-gsc.2",
-               .enable         = exynos5_clk_ip_gscl_ctrl,
-               .ctrlbit        = (1 << 2),
-       }, {
-               .name           = "gscl",
-               .devname        = "exynos-gsc.3",
-               .enable         = exynos5_clk_ip_gscl_ctrl,
-               .ctrlbit        = (1 << 3),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.1",
-               .enable         = &exynos5_clk_ip_mfc_ctrl,
-               .ctrlbit        = (1 << 1),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.0",
-               .enable         = &exynos5_clk_ip_mfc_ctrl,
-               .ctrlbit        = (1 << 2),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.2",
-               .enable         = &exynos5_clk_ip_disp1_ctrl,
-               .ctrlbit        = (1 << 9)
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.3",
-               .enable         = &exynos5_clk_ip_gen_ctrl,
-               .ctrlbit        = (1 << 7),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.4",
-               .enable         = &exynos5_clk_ip_gen_ctrl,
-               .ctrlbit        = (1 << 6)
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.5",
-               .enable         = &exynos5_clk_ip_gscl_ctrl,
-               .ctrlbit        = (1 << 7),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.6",
-               .enable         = &exynos5_clk_ip_gscl_ctrl,
-               .ctrlbit        = (1 << 8),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.7",
-               .enable         = &exynos5_clk_ip_gscl_ctrl,
-               .ctrlbit        = (1 << 9),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.8",
-               .enable         = &exynos5_clk_ip_gscl_ctrl,
-               .ctrlbit        = (1 << 10),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.9",
-               .enable         = &exynos5_clk_ip_isp0_ctrl,
-               .ctrlbit        = (0x3F << 8),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.10",
-               .enable         = &exynos5_clk_ip_isp1_ctrl,
-               .ctrlbit        = (0xF << 4),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.11",
-               .enable         = &exynos5_clk_ip_disp1_ctrl,
-               .ctrlbit        = (1 << 8)
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.12",
-               .enable         = &exynos5_clk_ip_gscl_ctrl,
-               .ctrlbit        = (1 << 11),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.13",
-               .enable         = &exynos5_clk_ip_gscl_ctrl,
-               .ctrlbit        = (1 << 12),
-       }, {
-               .name           = "sysmmu",
-               .devname        = "exynos-sysmmu.14",
-               .enable         = &exynos5_clk_ip_acp_ctrl,
-               .ctrlbit        = (1 << 7)
-       }
-};
-
-static struct clk exynos5_init_clocks_on[] = {
-       {
-               .name           = "uart",
-               .devname        = "s5pv210-uart.0",
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 0),
-       }, {
-               .name           = "uart",
-               .devname        = "s5pv210-uart.1",
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 1),
-       }, {
-               .name           = "uart",
-               .devname        = "s5pv210-uart.2",
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 2),
-       }, {
-               .name           = "uart",
-               .devname        = "s5pv210-uart.3",
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 3),
-       }, {
-               .name           = "uart",
-               .devname        = "s5pv210-uart.4",
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 4),
-       }, {
-               .name           = "uart",
-               .devname        = "s5pv210-uart.5",
-               .enable         = exynos5_clk_ip_peric_ctrl,
-               .ctrlbit        = (1 << 5),
-       }
-};
-
-static struct clk exynos5_clk_pdma0 = {
-       .name           = "dma",
-       .devname        = "dma-pl330.0",
-       .enable         = exynos5_clk_ip_fsys_ctrl,
-       .ctrlbit        = (1 << 1),
-};
-
-static struct clk exynos5_clk_pdma1 = {
-       .name           = "dma",
-       .devname        = "dma-pl330.1",
-       .enable         = exynos5_clk_ip_fsys_ctrl,
-       .ctrlbit        = (1 << 2),
-};
-
-static struct clk exynos5_clk_mdma1 = {
-       .name           = "dma",
-       .devname        = "dma-pl330.2",
-       .enable         = exynos5_clk_ip_gen_ctrl,
-       .ctrlbit        = (1 << 4),
-};
-
-static struct clk exynos5_clk_fimd1 = {
-       .name           = "fimd",
-       .devname        = "exynos5-fb.1",
-       .enable         = exynos5_clk_ip_disp1_ctrl,
-       .ctrlbit        = (1 << 0),
-};
-
-static struct clk *exynos5_clkset_group_list[] = {
-       [0] = &clk_ext_xtal_mux,
-       [1] = NULL,
-       [2] = &exynos5_clk_sclk_hdmi24m,
-       [3] = &exynos5_clk_sclk_dptxphy,
-       [4] = &exynos5_clk_sclk_usbphy,
-       [5] = &exynos5_clk_sclk_hdmiphy,
-       [6] = &exynos5_clk_mout_mpll_user.clk,
-       [7] = &exynos5_clk_mout_epll.clk,
-       [8] = &exynos5_clk_sclk_vpll.clk,
-       [9] = &exynos5_clk_mout_cpll.clk,
-};
-
-static struct clksrc_sources exynos5_clkset_group = {
-       .sources        = exynos5_clkset_group_list,
-       .nr_sources     = ARRAY_SIZE(exynos5_clkset_group_list),
-};
-
-/* Possible clock sources for aclk_266_gscl_sub Mux */
-static struct clk *clk_src_gscl_266_list[] = {
-       [0] = &clk_ext_xtal_mux,
-       [1] = &exynos5_clk_aclk_266.clk,
-};
-
-static struct clksrc_sources clk_src_gscl_266 = {
-       .sources        = clk_src_gscl_266_list,
-       .nr_sources     = ARRAY_SIZE(clk_src_gscl_266_list),
-};
-
-static struct clksrc_clk exynos5_clk_dout_mmc0 = {
-       .clk            = {
-               .name           = "dout_mmc0",
-       },
-       .sources = &exynos5_clkset_group,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 0, .size = 4 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_dout_mmc1 = {
-       .clk            = {
-               .name           = "dout_mmc1",
-       },
-       .sources = &exynos5_clkset_group,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 4, .size = 4 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_dout_mmc2 = {
-       .clk            = {
-               .name           = "dout_mmc2",
-       },
-       .sources = &exynos5_clkset_group,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 8, .size = 4 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_dout_mmc3 = {
-       .clk            = {
-               .name           = "dout_mmc3",
-       },
-       .sources = &exynos5_clkset_group,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 12, .size = 4 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_dout_mmc4 = {
-       .clk            = {
-               .name           = "dout_mmc4",
-       },
-       .sources = &exynos5_clkset_group,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 16, .size = 4 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS3, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_uart0 = {
-       .clk    = {
-               .name           = "uclk1",
-               .devname        = "exynos4210-uart.0",
-               .enable         = exynos5_clksrc_mask_peric0_ctrl,
-               .ctrlbit        = (1 << 0),
-       },
-       .sources = &exynos5_clkset_group,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 0, .size = 4 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_uart1 = {
-       .clk    = {
-               .name           = "uclk1",
-               .devname        = "exynos4210-uart.1",
-               .enable         = exynos5_clksrc_mask_peric0_ctrl,
-               .ctrlbit        = (1 << 4),
-       },
-       .sources = &exynos5_clkset_group,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 4, .size = 4 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_uart2 = {
-       .clk    = {
-               .name           = "uclk1",
-               .devname        = "exynos4210-uart.2",
-               .enable         = exynos5_clksrc_mask_peric0_ctrl,
-               .ctrlbit        = (1 << 8),
-       },
-       .sources = &exynos5_clkset_group,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 8, .size = 4 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 8, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_uart3 = {
-       .clk    = {
-               .name           = "uclk1",
-               .devname        = "exynos4210-uart.3",
-               .enable         = exynos5_clksrc_mask_peric0_ctrl,
-               .ctrlbit        = (1 << 12),
-       },
-       .sources = &exynos5_clkset_group,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC0, .shift = 12, .size = 4 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC0, .shift = 12, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_mmc0 = {
-       .clk    = {
-               .name           = "ciu",        /* card interface unit clock */
-               .devname        = "dw_mmc.0",
-               .parent         = &exynos5_clk_dout_mmc0.clk,
-               .enable         = exynos5_clksrc_mask_fsys_ctrl,
-               .ctrlbit        = (1 << 0),
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_mmc1 = {
-       .clk    = {
-               .name           = "ciu",
-               .devname        = "dw_mmc.1",
-               .parent         = &exynos5_clk_dout_mmc1.clk,
-               .enable         = exynos5_clksrc_mask_fsys_ctrl,
-               .ctrlbit        = (1 << 4),
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_mmc2 = {
-       .clk    = {
-               .name           = "ciu",
-               .devname        = "dw_mmc.2",
-               .parent         = &exynos5_clk_dout_mmc2.clk,
-               .enable         = exynos5_clksrc_mask_fsys_ctrl,
-               .ctrlbit        = (1 << 8),
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_mmc3 = {
-       .clk    = {
-               .name           = "ciu",
-               .devname        = "dw_mmc.3",
-               .parent         = &exynos5_clk_dout_mmc3.clk,
-               .enable         = exynos5_clksrc_mask_fsys_ctrl,
-               .ctrlbit        = (1 << 12),
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS2, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos5_clk_mdout_spi0 = {
-       .clk    = {
-               .name           = "mdout_spi",
-               .devname        = "exynos4210-spi.0",
-       },
-       .sources = &exynos5_clkset_group,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC1, .shift = 16, .size = 4 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_mdout_spi1 = {
-       .clk    = {
-               .name           = "mdout_spi",
-               .devname        = "exynos4210-spi.1",
-       },
-       .sources = &exynos5_clkset_group,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC1, .shift = 20, .size = 4 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_mdout_spi2 = {
-       .clk    = {
-               .name           = "mdout_spi",
-               .devname        = "exynos4210-spi.2",
-       },
-       .sources = &exynos5_clkset_group,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_PERIC1, .shift = 24, .size = 4 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_spi0 = {
-       .clk    = {
-               .name           = "sclk_spi",
-               .devname        = "exynos4210-spi.0",
-               .parent         = &exynos5_clk_mdout_spi0.clk,
-               .enable         = exynos5_clksrc_mask_peric1_ctrl,
-               .ctrlbit        = (1 << 16),
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_spi1 = {
-       .clk    = {
-               .name           = "sclk_spi",
-               .devname        = "exynos4210-spi.1",
-               .parent         = &exynos5_clk_mdout_spi1.clk,
-               .enable         = exynos5_clksrc_mask_peric1_ctrl,
-               .ctrlbit        = (1 << 20),
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC1, .shift = 24, .size = 8 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_spi2 = {
-       .clk    = {
-               .name           = "sclk_spi",
-               .devname        = "exynos4210-spi.2",
-               .parent         = &exynos5_clk_mdout_spi2.clk,
-               .enable         = exynos5_clksrc_mask_peric1_ctrl,
-               .ctrlbit        = (1 << 24),
-       },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_PERIC2, .shift = 8, .size = 8 },
-};
-
-static struct clksrc_clk exynos5_clk_sclk_fimd1 = {
-       .clk    = {
-               .name           = "sclk_fimd",
-               .devname        = "exynos5-fb.1",
-               .enable         = exynos5_clksrc_mask_disp1_0_ctrl,
-               .ctrlbit        = (1 << 0),
-       },
-       .sources = &exynos5_clkset_group,
-       .reg_src = { .reg = EXYNOS5_CLKSRC_DISP1_0, .shift = 0, .size = 4 },
-       .reg_div = { .reg = EXYNOS5_CLKDIV_DISP1_0, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk exynos5_clksrcs[] = {
-       {
-               .clk    = {
-                       .name           = "aclk_266_gscl",
-               },
-               .sources = &clk_src_gscl_266,
-               .reg_src = { .reg = EXYNOS5_CLKSRC_TOP3, .shift = 8, .size = 1 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_g3d",
-                       .devname        = "mali-t604.0",
-                       .enable         = exynos5_clk_block_ctrl,
-                       .ctrlbit        = (1 << 1),
-               },
-               .sources = &exynos5_clkset_aclk,
-               .reg_src = { .reg = EXYNOS5_CLKSRC_TOP0, .shift = 20, .size = 1 },
-               .reg_div = { .reg = EXYNOS5_CLKDIV_TOP0, .shift = 24, .size = 3 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_sata",
-                       .devname        = "exynos5-sata",
-                       .enable         = exynos5_clksrc_mask_fsys_ctrl,
-                       .ctrlbit        = (1 << 24),
-               },
-               .sources = &exynos5_clkset_aclk,
-               .reg_src = { .reg = EXYNOS5_CLKSRC_FSYS, .shift = 24, .size = 1 },
-               .reg_div = { .reg = EXYNOS5_CLKDIV_FSYS0, .shift = 20, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_gscl_wrap",
-                       .devname        = "s5p-mipi-csis.0",
-                       .enable         = exynos5_clksrc_mask_gscl_ctrl,
-                       .ctrlbit        = (1 << 24),
-               },
-               .sources = &exynos5_clkset_group,
-               .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 24, .size = 4 },
-               .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 24, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_gscl_wrap",
-                       .devname        = "s5p-mipi-csis.1",
-                       .enable         = exynos5_clksrc_mask_gscl_ctrl,
-                       .ctrlbit        = (1 << 28),
-               },
-               .sources = &exynos5_clkset_group,
-               .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 28, .size = 4 },
-               .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 28, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_cam0",
-                       .enable         = exynos5_clksrc_mask_gscl_ctrl,
-                       .ctrlbit        = (1 << 16),
-               },
-               .sources = &exynos5_clkset_group,
-               .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 16, .size = 4 },
-               .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 16, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_cam1",
-                       .enable         = exynos5_clksrc_mask_gscl_ctrl,
-                       .ctrlbit        = (1 << 20),
-               },
-               .sources = &exynos5_clkset_group,
-               .reg_src = { .reg = EXYNOS5_CLKSRC_GSCL, .shift = 20, .size = 4 },
-               .reg_div = { .reg = EXYNOS5_CLKDIV_GSCL, .shift = 20, .size = 4 },
-       }, {
-               .clk    = {
-                       .name           = "sclk_jpeg",
-                       .parent         = &exynos5_clk_mout_cpll.clk,
-               },
-               .reg_div = { .reg = EXYNOS5_CLKDIV_GEN, .shift = 4, .size = 3 },
-       },
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *exynos5_sysclks[] = {
-       &exynos5_clk_mout_apll,
-       &exynos5_clk_sclk_apll,
-       &exynos5_clk_mout_bpll,
-       &exynos5_clk_mout_bpll_fout,
-       &exynos5_clk_mout_bpll_user,
-       &exynos5_clk_mout_cpll,
-       &exynos5_clk_mout_epll,
-       &exynos5_clk_mout_mpll,
-       &exynos5_clk_mout_mpll_fout,
-       &exynos5_clk_mout_mpll_user,
-       &exynos5_clk_vpllsrc,
-       &exynos5_clk_sclk_vpll,
-       &exynos5_clk_mout_cpu,
-       &exynos5_clk_dout_armclk,
-       &exynos5_clk_dout_arm2clk,
-       &exynos5_clk_cdrex,
-       &exynos5_clk_aclk_400,
-       &exynos5_clk_aclk_333,
-       &exynos5_clk_aclk_266,
-       &exynos5_clk_aclk_200,
-       &exynos5_clk_aclk_166,
-       &exynos5_clk_aclk_300_gscl,
-       &exynos5_clk_mout_aclk_300_gscl,
-       &exynos5_clk_mout_aclk_300_gscl_mid,
-       &exynos5_clk_mout_aclk_300_gscl_mid1,
-       &exynos5_clk_aclk_66_pre,
-       &exynos5_clk_aclk_66,
-       &exynos5_clk_dout_mmc0,
-       &exynos5_clk_dout_mmc1,
-       &exynos5_clk_dout_mmc2,
-       &exynos5_clk_dout_mmc3,
-       &exynos5_clk_dout_mmc4,
-       &exynos5_clk_aclk_acp,
-       &exynos5_clk_pclk_acp,
-       &exynos5_clk_sclk_spi0,
-       &exynos5_clk_sclk_spi1,
-       &exynos5_clk_sclk_spi2,
-       &exynos5_clk_mdout_spi0,
-       &exynos5_clk_mdout_spi1,
-       &exynos5_clk_mdout_spi2,
-       &exynos5_clk_sclk_fimd1,
-};
-
-static struct clk *exynos5_clk_cdev[] = {
-       &exynos5_clk_pdma0,
-       &exynos5_clk_pdma1,
-       &exynos5_clk_mdma1,
-       &exynos5_clk_fimd1,
-};
-
-static struct clksrc_clk *exynos5_clksrc_cdev[] = {
-       &exynos5_clk_sclk_uart0,
-       &exynos5_clk_sclk_uart1,
-       &exynos5_clk_sclk_uart2,
-       &exynos5_clk_sclk_uart3,
-       &exynos5_clk_sclk_mmc0,
-       &exynos5_clk_sclk_mmc1,
-       &exynos5_clk_sclk_mmc2,
-       &exynos5_clk_sclk_mmc3,
-};
-
-static struct clk_lookup exynos5_clk_lookup[] = {
-       CLKDEV_INIT("exynos4210-uart.0", "clk_uart_baud0", &exynos5_clk_sclk_uart0.clk),
-       CLKDEV_INIT("exynos4210-uart.1", "clk_uart_baud0", &exynos5_clk_sclk_uart1.clk),
-       CLKDEV_INIT("exynos4210-uart.2", "clk_uart_baud0", &exynos5_clk_sclk_uart2.clk),
-       CLKDEV_INIT("exynos4210-uart.3", "clk_uart_baud0", &exynos5_clk_sclk_uart3.clk),
-       CLKDEV_INIT("exynos4-sdhci.0", "mmc_busclk.2", &exynos5_clk_sclk_mmc0.clk),
-       CLKDEV_INIT("exynos4-sdhci.1", "mmc_busclk.2", &exynos5_clk_sclk_mmc1.clk),
-       CLKDEV_INIT("exynos4-sdhci.2", "mmc_busclk.2", &exynos5_clk_sclk_mmc2.clk),
-       CLKDEV_INIT("exynos4-sdhci.3", "mmc_busclk.2", &exynos5_clk_sclk_mmc3.clk),
-       CLKDEV_INIT("exynos4210-spi.0", "spi_busclk0", &exynos5_clk_sclk_spi0.clk),
-       CLKDEV_INIT("exynos4210-spi.1", "spi_busclk0", &exynos5_clk_sclk_spi1.clk),
-       CLKDEV_INIT("exynos4210-spi.2", "spi_busclk0", &exynos5_clk_sclk_spi2.clk),
-       CLKDEV_INIT("dma-pl330.0", "apb_pclk", &exynos5_clk_pdma0),
-       CLKDEV_INIT("dma-pl330.1", "apb_pclk", &exynos5_clk_pdma1),
-       CLKDEV_INIT("dma-pl330.2", "apb_pclk", &exynos5_clk_mdma1),
-       CLKDEV_INIT("exynos5-fb.1", "lcd", &exynos5_clk_fimd1),
-};
-
-static unsigned long exynos5_epll_get_rate(struct clk *clk)
-{
-       return clk->rate;
-}
-
-static struct clk *exynos5_clks[] __initdata = {
-       &exynos5_clk_sclk_hdmi27m,
-       &exynos5_clk_sclk_hdmiphy,
-       &clk_fout_bpll,
-       &clk_fout_bpll_div2,
-       &clk_fout_cpll,
-       &clk_fout_mpll_div2,
-       &exynos5_clk_armclk,
-};
-
-static u32 epll_div[][6] = {
-       { 192000000, 0, 48, 3, 1, 0 },
-       { 180000000, 0, 45, 3, 1, 0 },
-       {  73728000, 1, 73, 3, 3, 47710 },
-       {  67737600, 1, 90, 4, 3, 20762 },
-       {  49152000, 0, 49, 3, 3, 9961 },
-       {  45158400, 0, 45, 3, 3, 10381 },
-       { 180633600, 0, 45, 3, 1, 10381 },
-};
-
-static int exynos5_epll_set_rate(struct clk *clk, unsigned long rate)
-{
-       unsigned int epll_con, epll_con_k;
-       unsigned int i;
-       unsigned int tmp;
-       unsigned int epll_rate;
-       unsigned int locktime;
-       unsigned int lockcnt;
-
-       /* Return if nothing changed */
-       if (clk->rate == rate)
-               return 0;
-
-       if (clk->parent)
-               epll_rate = clk_get_rate(clk->parent);
-       else
-               epll_rate = clk_ext_xtal_mux.rate;
-
-       if (epll_rate != 24000000) {
-               pr_err("Invalid Clock : recommended clock is 24MHz.\n");
-               return -EINVAL;
-       }
-
-       epll_con = __raw_readl(EXYNOS5_EPLL_CON0);
-       epll_con &= ~(0x1 << 27 | \
-                       PLL46XX_MDIV_MASK << PLL46XX_MDIV_SHIFT |   \
-                       PLL46XX_PDIV_MASK << PLL46XX_PDIV_SHIFT | \
-                       PLL46XX_SDIV_MASK << PLL46XX_SDIV_SHIFT);
-
-       for (i = 0; i < ARRAY_SIZE(epll_div); i++) {
-               if (epll_div[i][0] == rate) {
-                       epll_con_k = epll_div[i][5] << 0;
-                       epll_con |= epll_div[i][1] << 27;
-                       epll_con |= epll_div[i][2] << PLL46XX_MDIV_SHIFT;
-                       epll_con |= epll_div[i][3] << PLL46XX_PDIV_SHIFT;
-                       epll_con |= epll_div[i][4] << PLL46XX_SDIV_SHIFT;
-                       break;
-               }
-       }
-
-       if (i == ARRAY_SIZE(epll_div)) {
-               printk(KERN_ERR "%s: Invalid Clock EPLL Frequency\n",
-                               __func__);
-               return -EINVAL;
-       }
-
-       epll_rate /= 1000000;
-
-       /* 3000 max_cycls : specification data */
-       locktime = 3000 / epll_rate * epll_div[i][3];
-       lockcnt = locktime * 10000 / (10000 / epll_rate);
-
-       __raw_writel(lockcnt, EXYNOS5_EPLL_LOCK);
-
-       __raw_writel(epll_con, EXYNOS5_EPLL_CON0);
-       __raw_writel(epll_con_k, EXYNOS5_EPLL_CON1);
-
-       do {
-               tmp = __raw_readl(EXYNOS5_EPLL_CON0);
-       } while (!(tmp & 0x1 << EXYNOS5_EPLLCON0_LOCKED_SHIFT));
-
-       clk->rate = rate;
-
-       return 0;
-}
-
-static struct clk_ops exynos5_epll_ops = {
-       .get_rate = exynos5_epll_get_rate,
-       .set_rate = exynos5_epll_set_rate,
-};
-
-static int xtal_rate;
-
-static unsigned long exynos5_fout_apll_get_rate(struct clk *clk)
-{
-       return s5p_get_pll35xx(xtal_rate, __raw_readl(EXYNOS5_APLL_CON0));
-}
-
-static struct clk_ops exynos5_fout_apll_ops = {
-       .get_rate = exynos5_fout_apll_get_rate,
-};
-
-#ifdef CONFIG_PM
-static int exynos5_clock_suspend(void)
-{
-       s3c_pm_do_save(exynos5_clock_save, ARRAY_SIZE(exynos5_clock_save));
-
-       return 0;
-}
-
-static void exynos5_clock_resume(void)
-{
-       s3c_pm_do_restore_core(exynos5_clock_save, ARRAY_SIZE(exynos5_clock_save));
-}
-#else
-#define exynos5_clock_suspend NULL
-#define exynos5_clock_resume NULL
-#endif
-
-static struct syscore_ops exynos5_clock_syscore_ops = {
-       .suspend        = exynos5_clock_suspend,
-       .resume         = exynos5_clock_resume,
-};
-
-void __init_or_cpufreq exynos5_setup_clocks(void)
-{
-       struct clk *xtal_clk;
-       unsigned long apll;
-       unsigned long bpll;
-       unsigned long cpll;
-       unsigned long mpll;
-       unsigned long epll;
-       unsigned long vpll;
-       unsigned long vpllsrc;
-       unsigned long xtal;
-       unsigned long armclk;
-       unsigned long mout_cdrex;
-       unsigned long aclk_400;
-       unsigned long aclk_333;
-       unsigned long aclk_266;
-       unsigned long aclk_200;
-       unsigned long aclk_166;
-       unsigned long aclk_66;
-       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);
-
-       apll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_APLL_CON0));
-       bpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_BPLL_CON0));
-       cpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_CPLL_CON0));
-       mpll = s5p_get_pll35xx(xtal, __raw_readl(EXYNOS5_MPLL_CON0));
-       epll = s5p_get_pll36xx(xtal, __raw_readl(EXYNOS5_EPLL_CON0),
-                       __raw_readl(EXYNOS5_EPLL_CON1));
-
-       vpllsrc = clk_get_rate(&exynos5_clk_vpllsrc.clk);
-       vpll = s5p_get_pll36xx(vpllsrc, __raw_readl(EXYNOS5_VPLL_CON0),
-                       __raw_readl(EXYNOS5_VPLL_CON1));
-
-       clk_fout_apll.ops = &exynos5_fout_apll_ops;
-       clk_fout_bpll.rate = bpll;
-       clk_fout_bpll_div2.rate = bpll >> 1;
-       clk_fout_cpll.rate = cpll;
-       clk_fout_mpll.rate = mpll;
-       clk_fout_mpll_div2.rate = mpll >> 1;
-       clk_fout_epll.rate = epll;
-       clk_fout_vpll.rate = vpll;
-
-       printk(KERN_INFO "EXYNOS5: PLL settings, A=%ld, B=%ld, C=%ld\n"
-                       "M=%ld, E=%ld V=%ld",
-                       apll, bpll, cpll, mpll, epll, vpll);
-
-       armclk = clk_get_rate(&exynos5_clk_armclk);
-       mout_cdrex = clk_get_rate(&exynos5_clk_cdrex.clk);
-
-       aclk_400 = clk_get_rate(&exynos5_clk_aclk_400.clk);
-       aclk_333 = clk_get_rate(&exynos5_clk_aclk_333.clk);
-       aclk_266 = clk_get_rate(&exynos5_clk_aclk_266.clk);
-       aclk_200 = clk_get_rate(&exynos5_clk_aclk_200.clk);
-       aclk_166 = clk_get_rate(&exynos5_clk_aclk_166.clk);
-       aclk_66 = clk_get_rate(&exynos5_clk_aclk_66.clk);
-
-       printk(KERN_INFO "EXYNOS5: ARMCLK=%ld, CDREX=%ld, ACLK400=%ld\n"
-                       "ACLK333=%ld, ACLK266=%ld, ACLK200=%ld\n"
-                       "ACLK166=%ld, ACLK66=%ld\n",
-                       armclk, mout_cdrex, aclk_400,
-                       aclk_333, aclk_266, aclk_200,
-                       aclk_166, aclk_66);
-
-
-       clk_fout_epll.ops = &exynos5_epll_ops;
-
-       if (clk_set_parent(&exynos5_clk_mout_epll.clk, &clk_fout_epll))
-               printk(KERN_ERR "Unable to set parent %s of clock %s.\n",
-                               clk_fout_epll.name, exynos5_clk_mout_epll.clk.name);
-
-       clk_set_rate(&exynos5_clk_sclk_apll.clk, 100000000);
-       clk_set_rate(&exynos5_clk_aclk_266.clk, 300000000);
-
-       clk_set_rate(&exynos5_clk_aclk_acp.clk, 267000000);
-       clk_set_rate(&exynos5_clk_pclk_acp.clk, 134000000);
-
-       for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clksrcs); ptr++)
-               s3c_set_clksrc(&exynos5_clksrcs[ptr], true);
-}
-
-void __init exynos5_register_clocks(void)
-{
-       int ptr;
-
-       s3c24xx_register_clocks(exynos5_clks, ARRAY_SIZE(exynos5_clks));
-
-       for (ptr = 0; ptr < ARRAY_SIZE(exynos5_sysclks); ptr++)
-               s3c_register_clksrc(exynos5_sysclks[ptr], 1);
-
-       for (ptr = 0; ptr < ARRAY_SIZE(exynos5_sclk_tv); ptr++)
-               s3c_register_clksrc(exynos5_sclk_tv[ptr], 1);
-
-       for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clksrc_cdev); ptr++)
-               s3c_register_clksrc(exynos5_clksrc_cdev[ptr], 1);
-
-       s3c_register_clksrc(exynos5_clksrcs, ARRAY_SIZE(exynos5_clksrcs));
-       s3c_register_clocks(exynos5_init_clocks_on, ARRAY_SIZE(exynos5_init_clocks_on));
-
-       s3c24xx_register_clocks(exynos5_clk_cdev, ARRAY_SIZE(exynos5_clk_cdev));
-       for (ptr = 0; ptr < ARRAY_SIZE(exynos5_clk_cdev); ptr++)
-               s3c_disable_clocks(exynos5_clk_cdev[ptr], 1);
-
-       s3c_register_clocks(exynos5_init_clocks_off, ARRAY_SIZE(exynos5_init_clocks_off));
-       s3c_disable_clocks(exynos5_init_clocks_off, ARRAY_SIZE(exynos5_init_clocks_off));
-       clkdev_add_table(exynos5_clk_lookup, ARRAY_SIZE(exynos5_clk_lookup));
-
-       register_syscore_ops(&exynos5_clock_syscore_ops);
-       s3c_pwmclk_init();
-}
index 8abf2b6b98c6268ac8756ff962717bc0b0f25117..4bc1c49c69f1c70b171eb82c2f87139402cddc47 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/irqdomain.h>
 #include <linux/irqchip.h>
 #include <linux/of_address.h>
+#include <linux/clocksource.h>
+#include <linux/clk-provider.h>
 #include <linux/irqchip/arm-gic.h>
 
 #include <asm/proc-fns.h>
@@ -37,9 +39,9 @@
 #include <mach/regs-irq.h>
 #include <mach/regs-pmu.h>
 #include <mach/regs-gpio.h>
+#include <mach/irqs.h>
 
 #include <plat/cpu.h>
-#include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/pm.h>
 #include <plat/sdhci.h>
@@ -65,17 +67,16 @@ static const char name_exynos5440[] = "EXYNOS5440";
 static void exynos4_map_io(void);
 static void exynos5_map_io(void);
 static void exynos5440_map_io(void);
-static void exynos4_init_clocks(int xtal);
-static void exynos5_init_clocks(int xtal);
 static void exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no);
 static int exynos_init(void);
 
+unsigned long xxti_f = 0, xusbxti_f = 0;
+
 static struct cpu_table cpu_ids[] __initdata = {
        {
                .idcode         = EXYNOS4210_CPU_ID,
                .idmask         = EXYNOS4_CPU_MASK,
                .map_io         = exynos4_map_io,
-               .init_clocks    = exynos4_init_clocks,
                .init_uarts     = exynos4_init_uarts,
                .init           = exynos_init,
                .name           = name_exynos4210,
@@ -83,7 +84,6 @@ static struct cpu_table cpu_ids[] __initdata = {
                .idcode         = EXYNOS4212_CPU_ID,
                .idmask         = EXYNOS4_CPU_MASK,
                .map_io         = exynos4_map_io,
-               .init_clocks    = exynos4_init_clocks,
                .init_uarts     = exynos4_init_uarts,
                .init           = exynos_init,
                .name           = name_exynos4212,
@@ -91,7 +91,6 @@ static struct cpu_table cpu_ids[] __initdata = {
                .idcode         = EXYNOS4412_CPU_ID,
                .idmask         = EXYNOS4_CPU_MASK,
                .map_io         = exynos4_map_io,
-               .init_clocks    = exynos4_init_clocks,
                .init_uarts     = exynos4_init_uarts,
                .init           = exynos_init,
                .name           = name_exynos4412,
@@ -99,7 +98,6 @@ static struct cpu_table cpu_ids[] __initdata = {
                .idcode         = EXYNOS5250_SOC_ID,
                .idmask         = EXYNOS5_SOC_MASK,
                .map_io         = exynos5_map_io,
-               .init_clocks    = exynos5_init_clocks,
                .init           = exynos_init,
                .name           = name_exynos5250,
        }, {
@@ -256,11 +254,6 @@ static struct map_desc exynos5_iodesc[] __initdata = {
                .pfn            = __phys_to_pfn(EXYNOS5_PA_SROMC),
                .length         = SZ_4K,
                .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)S5P_VA_SYSTIMER,
-               .pfn            = __phys_to_pfn(EXYNOS5_PA_SYSTIMER),
-               .length         = SZ_4K,
-               .type           = MT_DEVICE,
        }, {
                .virtual        = (unsigned long)S5P_VA_SYSRAM,
                .pfn            = __phys_to_pfn(EXYNOS5_PA_SYSRAM),
@@ -368,6 +361,9 @@ static void __init exynos4_map_io(void)
        else
                iotable_init(exynos4_iodesc1, ARRAY_SIZE(exynos4_iodesc1));
 
+       if (!IS_ENABLED(CONFIG_EXYNOS_ATAGS))
+               return
+
        /* initialize device information early */
        exynos4_default_sdhci0();
        exynos4_default_sdhci1();
@@ -402,45 +398,41 @@ static void __init exynos5_map_io(void)
        iotable_init(exynos5_iodesc, ARRAY_SIZE(exynos5_iodesc));
 }
 
-static 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 __init exynos5440_map_io(void)
 {
        iotable_init(exynos5440_iodesc0, ARRAY_SIZE(exynos5440_iodesc0));
 }
 
-static void __init exynos5_init_clocks(int xtal)
+void __init exynos_init_time(void)
 {
-       printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-       /* EXYNOS5440 can support only common clock framework */
-
-       if (soc_is_exynos5440())
-               return;
-
-#ifdef CONFIG_SOC_EXYNOS5250
-       s3c24xx_register_baseclocks(xtal);
-       s5p_register_clocks(xtal);
-
-       exynos5_register_clocks();
-       exynos5_setup_clocks();
+       if (of_have_populated_dt()) {
+#ifdef CONFIG_OF
+               of_clk_init(NULL);
+               clocksource_of_init();
+#endif
+       } else {
+               /* todo: remove after migrating legacy E4 platforms to dt */
+#ifdef CONFIG_ARCH_EXYNOS4
+               exynos4_clk_init(NULL, !soc_is_exynos4210(), S5P_VA_CMU, readl(S5P_VA_CHIPID + 8) & 1);
+               exynos4_clk_register_fixed_ext(xxti_f, xusbxti_f);
 #endif
+               mct_init(S5P_VA_SYSTIMER, EXYNOS4_IRQ_MCT_G0, EXYNOS4_IRQ_MCT_L0, EXYNOS4_IRQ_MCT_L1);
+       }
+}
+
+static unsigned int max_combiner_nr(void)
+{
+       if (soc_is_exynos5250())
+               return EXYNOS5_MAX_COMBINER_NR;
+       else if (soc_is_exynos4412())
+               return EXYNOS4412_MAX_COMBINER_NR;
+       else if (soc_is_exynos4212())
+               return EXYNOS4212_MAX_COMBINER_NR;
+       else
+               return EXYNOS4210_MAX_COMBINER_NR;
 }
 
+
 void __init exynos4_init_irq(void)
 {
        unsigned int gic_bank_offset;
@@ -455,7 +447,8 @@ void __init exynos4_init_irq(void)
 #endif
 
        if (!of_have_populated_dt())
-               combiner_init(S5P_VA_COMBINER_BASE, NULL);
+               combiner_init(S5P_VA_COMBINER_BASE, NULL,
+                             max_combiner_nr(), COMBINER_IRQ(0, 0));
 }
 
 void __init exynos5_init_irq(void)
@@ -555,6 +548,8 @@ static void __init exynos4_init_uarts(struct s3c2410_uartcfg *cfg, int no)
        s3c24xx_init_uartdevs("exynos4210-uart", exynos4_uart_resources, cfg, no);
 }
 
+
+#ifdef CONFIG_EXYNOS_ATAGS
 static void __iomem *exynos_eint_base;
 
 static DEFINE_SPINLOCK(eint_lock);
@@ -807,6 +802,7 @@ static int __init exynos_init_irq_eint(void)
        static const struct of_device_id exynos_pinctrl_ids[] = {
                { .compatible = "samsung,exynos4210-pinctrl", },
                { .compatible = "samsung,exynos4x12-pinctrl", },
+               { .compatible = "samsung,exynos5250-pinctrl", },
        };
        struct device_node *pctrl_np, *wkup_np;
        const char *wkup_compat = "samsung,exynos4210-wakeup-eint";
@@ -860,3 +856,31 @@ static int __init exynos_init_irq_eint(void)
        return 0;
 }
 arch_initcall(exynos_init_irq_eint);
+#endif
+
+static struct resource exynos4_pmu_resource[] = {
+       DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU),
+       DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU1),
+#if defined(CONFIG_SOC_EXYNOS4412)
+       DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU2),
+       DEFINE_RES_IRQ(EXYNOS4_IRQ_PMU_CPU3),
+#endif
+};
+
+static struct platform_device exynos4_device_pmu = {
+       .name           = "arm-pmu",
+       .num_resources  = ARRAY_SIZE(exynos4_pmu_resource),
+       .resource       = exynos4_pmu_resource,
+};
+
+static int __init exynos_armpmu_init(void)
+{
+       if (!of_have_populated_dt()) {
+               if (soc_is_exynos4210() || soc_is_exynos4212())
+                       exynos4_device_pmu.num_resources = 2;
+               platform_device_register(&exynos4_device_pmu);
+       }
+
+       return 0;
+}
+arch_initcall(exynos_armpmu_init);
index 9339bb8954be9e8bc3f8787dbdfd630eaf7c7909..3e72d03a385e7a11f7b59c5ff7d16d1ee972ef13 100644 (file)
 #ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H
 #define __ARCH_ARM_MACH_EXYNOS_COMMON_H
 
-extern void exynos4_timer_init(void);
+#include <linux/of.h>
+
+void mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1);
+void exynos_init_time(void);
+extern unsigned long xxti_f, xusbxti_f;
 
 struct map_desc;
 void exynos_init_io(struct map_desc *mach_desc, int size);
@@ -22,6 +26,10 @@ void exynos4_restart(char mode, const char *cmd);
 void exynos5_restart(char mode, const char *cmd);
 void exynos_init_late(void);
 
+/* ToDo: remove these after migrating legacy exynos4 platforms to dt */
+void exynos4_clk_init(struct device_node *np, int is_exynos4210, void __iomem *reg_base, unsigned long xom);
+void exynos4_clk_register_fixed_ext(unsigned long, unsigned long);
+
 #ifdef CONFIG_PM_GENERIC_DOMAINS
 int exynos_pm_late_initcall(void);
 #else
@@ -61,7 +69,8 @@ void exynos4212_register_clocks(void);
 #endif
 
 struct device_node;
-void combiner_init(void __iomem *combiner_base, struct device_node *np);
+void combiner_init(void __iomem *combiner_base, struct device_node *np,
+                       unsigned int max_nr, int irq_base);
 
 extern struct smp_operations exynos_smp_ops;
 
index 7c42f4b7c8be0c167c8996745b69a4065f44483d..c48aff02c786d46706a4159003082c148a5f0776 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/mach/irq.h>
 #include <mach/hardware.h>
 #include <mach/map.h>
+#include <mach/irqs.h>
 
 #include <plat/devs.h>
 
index 1f4dc35cd4b9b88479e4b16496a7f62a05c58a46..c72f59d91fcebcfc89a2857b050a653c5db660bc 100644 (file)
@@ -30,8 +30,6 @@
 
 /* For EXYNOS4 and EXYNOS5 */
 
-#define EXYNOS_IRQ_MCT_LOCALTIMER      IRQ_PPI(12)
-
 #define EXYNOS_IRQ_EINT16_31           IRQ_SPI(32)
 
 /* For EXYNOS4 SoCs */
 #define EXYNOS4_IRQ_ADC1               IRQ_SPI(107)
 #define EXYNOS4_IRQ_PEN1               IRQ_SPI(108)
 #define EXYNOS4_IRQ_KEYPAD             IRQ_SPI(109)
-#define EXYNOS4_IRQ_PMU                        IRQ_SPI(110)
+#define EXYNOS4_IRQ_POWER_PMU          IRQ_SPI(110)
 #define EXYNOS4_IRQ_GPS                        IRQ_SPI(111)
 #define EXYNOS4_IRQ_INTFEEDCTRL_SSS    IRQ_SPI(112)
 #define EXYNOS4_IRQ_SLIMBUS            IRQ_SPI(113)
 #define EXYNOS4_IRQ_TSI                        IRQ_SPI(115)
 #define EXYNOS4_IRQ_SATA               IRQ_SPI(116)
 
+#define EXYNOS4_IRQ_PMU                        COMBINER_IRQ(2, 2)
+#define EXYNOS4_IRQ_PMU_CPU1           COMBINER_IRQ(3, 2)
+#define EXYNOS4_IRQ_PMU_CPU2           COMBINER_IRQ(18, 2)
+#define EXYNOS4_IRQ_PMU_CPU3           COMBINER_IRQ(19, 2)
+
 #define EXYNOS4_IRQ_TMU_TRIG0          COMBINER_IRQ(2, 4)
 #define EXYNOS4_IRQ_TMU_TRIG1          COMBINER_IRQ(3, 4)
 
 #define EXYNOS4_IRQ_FIMD0_VSYNC                COMBINER_IRQ(11, 1)
 #define EXYNOS4_IRQ_FIMD0_SYSTEM       COMBINER_IRQ(11, 2)
 
-#define EXYNOS4_MAX_COMBINER_NR                16
+#define EXYNOS4210_MAX_COMBINER_NR     16
+#define EXYNOS4212_MAX_COMBINER_NR     18
+#define EXYNOS4412_MAX_COMBINER_NR     20
+#define EXYNOS4_MAX_COMBINER_NR                EXYNOS4412_MAX_COMBINER_NR
 
 #define EXYNOS4_IRQ_GPIO1_NR_GROUPS    16
 #define EXYNOS4_IRQ_GPIO2_NR_GROUPS    9
 #define IRQ_TC                         EXYNOS4_IRQ_PEN0
 
 #define IRQ_KEYPAD                     EXYNOS4_IRQ_KEYPAD
-#define IRQ_PMU                                EXYNOS4_IRQ_PMU
 
 #define IRQ_FIMD0_FIFO                 EXYNOS4_IRQ_FIMD0_FIFO
 #define IRQ_FIMD0_VSYNC                        EXYNOS4_IRQ_FIMD0_VSYNC
 #define EXYNOS5_IRQ_CEC                        IRQ_SPI(114)
 #define EXYNOS5_IRQ_SATA               IRQ_SPI(115)
 
-#define EXYNOS5_IRQ_MCT_L0             IRQ_SPI(120)
-#define EXYNOS5_IRQ_MCT_L1             IRQ_SPI(121)
 #define EXYNOS5_IRQ_MMC44              IRQ_SPI(123)
 #define EXYNOS5_IRQ_MDMA1              IRQ_SPI(124)
 #define EXYNOS5_IRQ_FIMC_LITE0         IRQ_SPI(125)
 #define EXYNOS5_IRQ_PMU_CPU1           COMBINER_IRQ(22, 4)
 
 #define EXYNOS5_IRQ_EINT0              COMBINER_IRQ(23, 0)
-#define EXYNOS5_IRQ_MCT_G0             COMBINER_IRQ(23, 3)
-#define EXYNOS5_IRQ_MCT_G1             COMBINER_IRQ(23, 4)
 
 #define EXYNOS5_IRQ_EINT1              COMBINER_IRQ(24, 0)
 #define EXYNOS5_IRQ_SYSMMU_LITE1_0     COMBINER_IRQ(24, 1)
 #define IRQ_TIMER_BASE                 (IRQ_GPIO_END + 64)
 
 /* Set the default NR_IRQS */
+#define EXYNOS_NR_IRQS                 (IRQ_TIMER_BASE + IRQ_TIMER_COUNT)
 
-#define NR_IRQS                                (IRQ_TIMER_BASE + IRQ_TIMER_COUNT)
+#ifndef CONFIG_SPARSE_IRQ
+#define NR_IRQS                                EXYNOS_NR_IRQS
+#endif
 
 #endif /* __ASM_ARCH_IRQS_H */
index 1df6abbf53b8cb4364884f4ee5c7018b83968bac..7f99b7b187d66e6e247ee534b15000a392cb63ee 100644 (file)
@@ -65,7 +65,6 @@
 #define EXYNOS5_PA_CMU                 0x10010000
 
 #define EXYNOS4_PA_SYSTIMER            0x10050000
-#define EXYNOS5_PA_SYSTIMER            0x101C0000
 
 #define EXYNOS4_PA_WATCHDOG            0x10060000
 #define EXYNOS5_PA_WATCHDOG            0x101D0000
diff --git a/arch/arm/mach-exynos/include/mach/regs-mct.h b/arch/arm/mach-exynos/include/mach/regs-mct.h
deleted file mode 100644 (file)
index 80dd02a..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/* arch/arm/mach-exynos4/include/mach/regs-mct.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * EXYNOS4 MCT configutation
- *
- * 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_REGS_MCT_H
-#define __ASM_ARCH_REGS_MCT_H __FILE__
-
-#include <mach/map.h>
-
-#define EXYNOS4_MCTREG(x)              (S5P_VA_SYSTIMER + (x))
-
-#define EXYNOS4_MCT_G_CNT_L            EXYNOS4_MCTREG(0x100)
-#define EXYNOS4_MCT_G_CNT_U            EXYNOS4_MCTREG(0x104)
-#define EXYNOS4_MCT_G_CNT_WSTAT                EXYNOS4_MCTREG(0x110)
-
-#define EXYNOS4_MCT_G_COMP0_L          EXYNOS4_MCTREG(0x200)
-#define EXYNOS4_MCT_G_COMP0_U          EXYNOS4_MCTREG(0x204)
-#define EXYNOS4_MCT_G_COMP0_ADD_INCR   EXYNOS4_MCTREG(0x208)
-
-#define EXYNOS4_MCT_G_TCON             EXYNOS4_MCTREG(0x240)
-
-#define EXYNOS4_MCT_G_INT_CSTAT                EXYNOS4_MCTREG(0x244)
-#define EXYNOS4_MCT_G_INT_ENB          EXYNOS4_MCTREG(0x248)
-#define EXYNOS4_MCT_G_WSTAT            EXYNOS4_MCTREG(0x24C)
-
-#define _EXYNOS4_MCT_L_BASE            EXYNOS4_MCTREG(0x300)
-#define EXYNOS4_MCT_L_BASE(x)          (_EXYNOS4_MCT_L_BASE + (0x100 * x))
-#define EXYNOS4_MCT_L_MASK             (0xffffff00)
-
-#define MCT_L_TCNTB_OFFSET             (0x00)
-#define MCT_L_ICNTB_OFFSET             (0x08)
-#define MCT_L_TCON_OFFSET              (0x20)
-#define MCT_L_INT_CSTAT_OFFSET         (0x30)
-#define MCT_L_INT_ENB_OFFSET           (0x34)
-#define MCT_L_WSTAT_OFFSET             (0x40)
-
-#define MCT_G_TCON_START               (1 << 8)
-#define MCT_G_TCON_COMP0_AUTO_INC      (1 << 1)
-#define MCT_G_TCON_COMP0_ENABLE                (1 << 0)
-
-#define MCT_L_TCON_INTERVAL_MODE       (1 << 2)
-#define MCT_L_TCON_INT_START           (1 << 1)
-#define MCT_L_TCON_TIMER_START         (1 << 0)
-
-#endif /* __ASM_ARCH_REGS_MCT_H */
index 685f29173afa8295313ab2e6320a2d029fb90ff2..5f0f557013740b25a9da8f541ce412fa6e08c39b 100644 (file)
@@ -25,6 +25,7 @@
 #include <plat/regs-srom.h>
 #include <plat/sdhci.h>
 
+#include <mach/irqs.h>
 #include <mach/map.h>
 
 #include "common.h"
@@ -177,7 +178,6 @@ static void __init armlex4210_smsc911x_init(void)
 static void __init armlex4210_map_io(void)
 {
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(24000000);
        s3c24xx_init_uarts(armlex4210_uartcfgs,
                           ARRAY_SIZE(armlex4210_uartcfgs));
 }
@@ -202,6 +202,6 @@ MACHINE_START(ARMLEX4210, "ARMLEX4210")
        .map_io         = armlex4210_map_io,
        .init_machine   = armlex4210_machine_init,
        .init_late      = exynos_init_late,
-       .init_time      = exynos4_timer_init,
+       .init_time      = exynos_init_time,
        .restart        = exynos4_restart,
 MACHINE_END
index 3358088c822a3015721b206f1671363df3db67c6..ac27f3cd121f7b98da9b4ca1caa0e746c8470fb3 100644 (file)
  * published by the Free Software Foundation.
 */
 
+#include <linux/kernel.h>
 #include <linux/of_platform.h>
+#include <linux/of_fdt.h>
 #include <linux/serial_core.h>
+#include <linux/memblock.h>
+#include <linux/clocksource.h>
 
 #include <asm/mach/arch.h>
-#include <mach/map.h>
-
-#include <plat/cpu.h>
-#include <plat/regs-serial.h>
+#include <plat/mfc.h>
 
 #include "common.h"
 
-/*
- * The following lookup table is used to override device names when devices
- * are registered from device tree. This is temporarily added to enable
- * device tree support addition for the Exynos4 architecture.
- *
- * For drivers that require platform data to be provided from the machine
- * file, a platform data pointer can also be supplied along with the
- * devices names. Usually, the platform data elements that cannot be parsed
- * from the device tree by the drivers (example: function pointers) are
- * supplied. But it should be noted that this is a temporary mechanism and
- * at some point, the drivers should be capable of parsing all the platform
- * data from the device tree.
- */
-static const struct of_dev_auxdata exynos4_auxdata_lookup[] __initconst = {
-       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART0,
-                               "exynos4210-uart.0", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART1,
-                               "exynos4210-uart.1", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART2,
-                               "exynos4210-uart.2", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS4_PA_UART3,
-                               "exynos4210-uart.3", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(0),
-                               "exynos4-sdhci.0", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(1),
-                               "exynos4-sdhci.1", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(2),
-                               "exynos4-sdhci.2", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-sdhci", EXYNOS4_PA_HSMMC(3),
-                               "exynos4-sdhci.3", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(0),
-                               "s3c2440-i2c.0", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(1),
-                               "s3c2440-i2c.1", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(2),
-                               "s3c2440-i2c.2", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(3),
-                               "s3c2440-i2c.3", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(4),
-                               "s3c2440-i2c.4", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(5),
-                               "s3c2440-i2c.5", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(6),
-                               "s3c2440-i2c.6", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(7),
-                               "s3c2440-i2c.7", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI0,
-                               "exynos4210-spi.0", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI1,
-                               "exynos4210-spi.1", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS4_PA_SPI2,
-                               "exynos4210-spi.2", NULL),
-       OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA0, "dma-pl330.0", NULL),
-       OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_PDMA1, "dma-pl330.1", NULL),
-       OF_DEV_AUXDATA("arm,pl330", EXYNOS4_PA_MDMA1, "dma-pl330.2", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-tmu", EXYNOS4_PA_TMU,
-                               "exynos-tmu", NULL),
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13620000,
-                       "exynos-sysmmu.0", NULL), /* MFC_L */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13630000,
-                       "exynos-sysmmu.1", NULL), /* MFC_R */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13E20000,
-                       "exynos-sysmmu.2", NULL), /* TV */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A60000,
-                       "exynos-sysmmu.3", NULL), /* JPEG */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x12A30000,
-                       "exynos-sysmmu.4", NULL), /* ROTATOR */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A20000,
-                       "exynos-sysmmu.5", NULL), /* FIMC0 */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A30000,
-                       "exynos-sysmmu.6", NULL), /* FIMC1 */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A40000,
-                       "exynos-sysmmu.7", NULL), /* FIMC2 */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11A50000,
-                       "exynos-sysmmu.8", NULL), /* FIMC3 */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x12A20000,
-                       "exynos-sysmmu.9", NULL), /* G2D(4210) */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x10A40000,
-                       "exynos-sysmmu.9", NULL), /* G2D(4x12) */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11E20000,
-                       "exynos-sysmmu.10", NULL), /* FIMD0 */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x12220000,
-                       "exynos-sysmmu.11", NULL), /* FIMD1(4210) */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x12260000,
-                       "exynos-sysmmu.12", NULL), /* IS0(4x12) */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x122B0000,
-                       "exynos-sysmmu.13", NULL), /* IS1(4x12) */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x123B0000,
-                       "exynos-sysmmu.14", NULL), /* FIMC-LITE0(4x12) */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x123C0000,
-                       "exynos-sysmmu.15", NULL), /* FIMC-LITE1(4x12) */
-       {},
-};
-
 static void __init exynos4_dt_map_io(void)
 {
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(24000000);
 }
 
 static void __init exynos4_dt_machine_init(void)
 {
-       of_platform_populate(NULL, of_default_bus_match_table,
-                               exynos4_auxdata_lookup, NULL);
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static char const *exynos4_dt_compat[] __initdata = {
@@ -135,6 +40,18 @@ static char const *exynos4_dt_compat[] __initdata = {
        NULL
 };
 
+static void __init exynos4_reserve(void)
+{
+#ifdef CONFIG_S5P_DEV_MFC
+       struct s5p_mfc_dt_meminfo mfc_mem;
+
+       /* Reserve memory for MFC only if it's available */
+       mfc_mem.compatible = "samsung,mfc-v5";
+       if (of_scan_flat_dt(s5p_fdt_find_mfc_mem, &mfc_mem))
+               s5p_mfc_reserve_mem(mfc_mem.roff, mfc_mem.rsize, mfc_mem.loff,
+                               mfc_mem.lsize);
+#endif
+}
 DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
        /* Maintainer: Thomas Abraham <thomas.abraham@linaro.org> */
        .smp            = smp_ops(exynos_smp_ops),
@@ -142,7 +59,8 @@ DT_MACHINE_START(EXYNOS4210_DT, "Samsung Exynos4 (Flattened Device Tree)")
        .map_io         = exynos4_dt_map_io,
        .init_machine   = exynos4_dt_machine_init,
        .init_late      = exynos_init_late,
-       .init_time      = exynos4_timer_init,
+       .init_time      = exynos_init_time,
        .dt_compat      = exynos4_dt_compat,
        .restart        = exynos4_restart,
+       .reserve        = exynos4_reserve,
 MACHINE_END
index acaeb14db54b933f0c658a0ded6fdb7608abe011..753b94f3fca7e3ba4c3895582f638e6c395e60fd 100644 (file)
 
 #include <linux/of_platform.h>
 #include <linux/of_fdt.h>
-#include <linux/serial_core.h>
 #include <linux/memblock.h>
 #include <linux/io.h>
+#include <linux/clocksource.h>
 
 #include <asm/mach/arch.h>
-#include <mach/map.h>
 #include <mach/regs-pmu.h>
 
 #include <plat/cpu.h>
-#include <plat/regs-serial.h>
 #include <plat/mfc.h>
 
 #include "common.h"
 
-/*
- * The following lookup table is used to override device names when devices
- * are registered from device tree. This is temporarily added to enable
- * device tree support addition for the EXYNOS5 architecture.
- *
- * For drivers that require platform data to be provided from the machine
- * file, a platform data pointer can also be supplied along with the
- * devices names. Usually, the platform data elements that cannot be parsed
- * from the device tree by the drivers (example: function pointers) are
- * supplied. But it should be noted that this is a temporary mechanism and
- * at some point, the drivers should be capable of parsing all the platform
- * data from the device tree.
- */
-static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
-       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART0,
-                               "exynos4210-uart.0", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART1,
-                               "exynos4210-uart.1", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART2,
-                               "exynos4210-uart.2", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5_PA_UART3,
-                               "exynos4210-uart.3", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(0),
-                               "s3c2440-i2c.0", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(1),
-                               "s3c2440-i2c.1", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(2),
-                               "s3c2440-i2c.2", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(3),
-                               "s3c2440-i2c.3", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(4),
-                               "s3c2440-i2c.4", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(5),
-                               "s3c2440-i2c.5", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(6),
-                               "s3c2440-i2c.6", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(7),
-                               "s3c2440-i2c.7", NULL),
-       OF_DEV_AUXDATA("samsung,s3c2440-hdmiphy-i2c", EXYNOS5_PA_IIC(8),
-                               "s3c2440-hdmiphy-i2c", NULL),
-       OF_DEV_AUXDATA("samsung,exynos5250-dw-mshc", EXYNOS5_PA_DWMCI0,
-                               "dw_mmc.0", NULL),
-       OF_DEV_AUXDATA("samsung,exynos5250-dw-mshc", EXYNOS5_PA_DWMCI1,
-                               "dw_mmc.1", NULL),
-       OF_DEV_AUXDATA("samsung,exynos5250-dw-mshc", EXYNOS5_PA_DWMCI2,
-                               "dw_mmc.2", NULL),
-       OF_DEV_AUXDATA("samsung,exynos5250-dw-mshc", EXYNOS5_PA_DWMCI3,
-                               "dw_mmc.3", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI0,
-                               "exynos4210-spi.0", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI1,
-                               "exynos4210-spi.1", NULL),
-       OF_DEV_AUXDATA("samsung,exynos4210-spi", EXYNOS5_PA_SPI2,
-                               "exynos4210-spi.2", NULL),
-       OF_DEV_AUXDATA("samsung,exynos5-sata-ahci", 0x122F0000,
-                               "exynos5-sata", NULL),
-       OF_DEV_AUXDATA("samsung,exynos5-sata-phy", 0x12170000,
-                               "exynos5-sata-phy", NULL),
-       OF_DEV_AUXDATA("samsung,exynos5-sata-phy-i2c", 0x121D0000,
-                               "exynos5-sata-phy-i2c", NULL),
-       OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA0, "dma-pl330.0", NULL),
-       OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_PDMA1, "dma-pl330.1", NULL),
-       OF_DEV_AUXDATA("arm,pl330", EXYNOS5_PA_MDMA1, "dma-pl330.2", NULL),
-       OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC0,
-                               "exynos-gsc.0", NULL),
-       OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC1,
-                               "exynos-gsc.1", NULL),
-       OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC2,
-                               "exynos-gsc.2", NULL),
-       OF_DEV_AUXDATA("samsung,exynos5-gsc", EXYNOS5_PA_GSC3,
-                               "exynos-gsc.3", NULL),
-       OF_DEV_AUXDATA("samsung,exynos5-hdmi", 0x14530000,
-                               "exynos5-hdmi", NULL),
-       OF_DEV_AUXDATA("samsung,exynos5-mixer", 0x14450000,
-                               "exynos5-mixer", NULL),
-       OF_DEV_AUXDATA("samsung,mfc-v6", 0x11000000, "s5p-mfc-v6", NULL),
-       OF_DEV_AUXDATA("samsung,exynos5250-tmu", 0x10060000,
-                               "exynos-tmu", NULL),
-       OF_DEV_AUXDATA("samsung,i2s-v5", 0x03830000,
-                               "samsung-i2s.0", NULL),
-       OF_DEV_AUXDATA("samsung,i2s-v5", 0x12D60000,
-                               "samsung-i2s.1", NULL),
-       OF_DEV_AUXDATA("samsung,i2s-v5", 0x12D70000,
-                               "samsung-i2s.2", NULL),
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11210000,
-                       "exynos-sysmmu.0", "mfc"), /* MFC_L */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11200000,
-                       "exynos-sysmmu.1", "mfc"), /* MFC_R */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x14650000,
-                       "exynos-sysmmu.2", NULL), /* TV */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11F20000,
-                       "exynos-sysmmu.3", "jpeg"), /* JPEG */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x11D40000,
-                       "exynos-sysmmu.4", NULL), /* ROTATOR */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13E80000,
-                       "exynos-sysmmu.5", "gscl"), /* GSCL0 */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13E90000,
-                       "exynos-sysmmu.6", "gscl"), /* GSCL1 */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13EA0000,
-                       "exynos-sysmmu.7", "gscl"), /* GSCL2 */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13EB0000,
-                       "exynos-sysmmu.8", "gscl"), /* GSCL3 */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13260000,
-                       "exynos-sysmmu.9", NULL), /* FIMC-IS0 */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x132C0000,
-                       "exynos-sysmmu.10", NULL), /* FIMC-IS1 */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x14640000,
-                       "exynos-sysmmu.11", NULL), /* FIMD1 */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13C40000,
-                       "exynos-sysmmu.12", NULL), /* FIMC-LITE0 */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x13C50000,
-                       "exynos-sysmmu.13", NULL), /* FIMC-LITE1 */
-       OF_DEV_AUXDATA("samsung,exynos-sysmmu", 0x10A60000,
-                       "exynos-sysmmu.14", NULL), /* G2D */
-       {},
-};
-
-static const struct of_dev_auxdata exynos5440_auxdata_lookup[] __initconst = {
-       OF_DEV_AUXDATA("samsung,exynos4210-uart", EXYNOS5440_PA_UART0,
-                               "exynos4210-uart.0", NULL),
-       {},
-};
-
 static void __init exynos5_dt_map_io(void)
 {
-       unsigned long root = of_get_flat_dt_root();
-
        exynos_init_io(NULL, 0);
-
-       if (of_flat_dt_is_compatible(root, "samsung,exynos5250"))
-               s3c24xx_init_clocks(24000000);
 }
 
 static void __init exynos5_dt_machine_init(void)
@@ -182,12 +52,7 @@ static void __init exynos5_dt_machine_init(void)
                }
        }
 
-       if (of_machine_is_compatible("samsung,exynos5250"))
-               of_platform_populate(NULL, of_default_bus_match_table,
-                                    exynos5250_auxdata_lookup, NULL);
-       else if (of_machine_is_compatible("samsung,exynos5440"))
-               of_platform_populate(NULL, of_default_bus_match_table,
-                                    exynos5440_auxdata_lookup, NULL);
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static char const *exynos5_dt_compat[] __initdata = {
@@ -216,7 +81,7 @@ DT_MACHINE_START(EXYNOS5_DT, "SAMSUNG EXYNOS5 (Flattened Device Tree)")
        .map_io         = exynos5_dt_map_io,
        .init_machine   = exynos5_dt_machine_init,
        .init_late      = exynos_init_late,
-       .init_time      = exynos4_timer_init,
+       .init_time      = exynos_init_time,
        .dt_compat      = exynos5_dt_compat,
        .restart        = exynos5_restart,
        .reserve        = exynos5_reserve,
index 1ea79730187f9e3e1297a717a5a4a66650bf9d6a..081a5baadd8b437d1935f1c90673da267d84edad 100644 (file)
@@ -53,6 +53,7 @@
 #include <plat/fimc-core.h>
 #include <plat/camport.h>
 
+#include <mach/irqs.h>
 #include <mach/map.h>
 
 #include "common.h"
@@ -1330,8 +1331,9 @@ static struct platform_device *nuri_devices[] __initdata = {
 static void __init nuri_map_io(void)
 {
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
+       xxti_f = 0;
+       xusbxti_f = 24000000;
 }
 
 static void __init nuri_reserve(void)
@@ -1380,7 +1382,7 @@ MACHINE_START(NURI, "NURI")
        .map_io         = nuri_map_io,
        .init_machine   = nuri_machine_init,
        .init_late      = exynos_init_late,
-       .init_time      = exynos4_timer_init,
+       .init_time      = exynos_init_time,
        .reserve        = &nuri_reserve,
        .restart        = exynos4_restart,
 MACHINE_END
index 579d2d171daa6e4ea21f56611dda80f536d41133..27ebe44785f0bdcd550620e4a006feb0d70ba520 100644 (file)
@@ -46,6 +46,7 @@
 #include <plat/hdmi.h>
 
 #include <mach/map.h>
+#include <mach/irqs.h>
 
 #include <drm/exynos_drm.h>
 #include "common.h"
@@ -754,8 +755,9 @@ static void s5p_tv_setup(void)
 static void __init origen_map_io(void)
 {
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
+       xxti_f = 0;
+       xusbxti_f = 24000000;
 }
 
 static void __init origen_power_init(void)
@@ -815,7 +817,7 @@ MACHINE_START(ORIGEN, "ORIGEN")
        .map_io         = origen_map_io,
        .init_machine   = origen_machine_init,
        .init_late      = exynos_init_late,
-       .init_time      = exynos4_timer_init,
+       .init_time      = exynos_init_time,
        .reserve        = &origen_reserve,
        .restart        = exynos4_restart,
 MACHINE_END
index fe6149624b849aa2dd624115711e1eb1e9fcbee6..2c8af96179202bdce6b2a521731e5dd6c3d74f3e 100644 (file)
@@ -39,6 +39,7 @@
 #include <plat/regs-serial.h>
 #include <plat/sdhci.h>
 
+#include <mach/irqs.h>
 #include <mach/map.h>
 
 #include <drm/exynos_drm.h>
@@ -322,7 +323,6 @@ static struct platform_device *smdk4x12_devices[] __initdata = {
 static void __init smdk4x12_map_io(void)
 {
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(smdk4x12_uartcfgs, ARRAY_SIZE(smdk4x12_uartcfgs));
 }
 
@@ -376,7 +376,7 @@ MACHINE_START(SMDK4212, "SMDK4212")
        .init_irq       = exynos4_init_irq,
        .map_io         = smdk4x12_map_io,
        .init_machine   = smdk4x12_machine_init,
-       .init_time      = exynos4_timer_init,
+       .init_time      = exynos_init_time,
        .restart        = exynos4_restart,
        .reserve        = &smdk4x12_reserve,
 MACHINE_END
@@ -390,7 +390,7 @@ MACHINE_START(SMDK4412, "SMDK4412")
        .map_io         = smdk4x12_map_io,
        .init_machine   = smdk4x12_machine_init,
        .init_late      = exynos_init_late,
-       .init_time      = exynos4_timer_init,
+       .init_time      = exynos_init_time,
        .restart        = exynos4_restart,
        .reserve        = &smdk4x12_reserve,
 MACHINE_END
index d71672922b191c7270a1dfa3fcdb28718e1bbf66..ee312b676772e2fe47b168337a31911760879b27 100644 (file)
@@ -43,6 +43,7 @@
 #include <plat/clock.h>
 #include <plat/hdmi.h>
 
+#include <mach/irqs.h>
 #include <mach/map.h>
 
 #include <drm/exynos_drm.h>
@@ -371,8 +372,9 @@ static void s5p_tv_setup(void)
 static void __init smdkv310_map_io(void)
 {
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
+       xxti_f = 12000000;
+       xusbxti_f = 24000000;
 }
 
 static void __init smdkv310_reserve(void)
@@ -423,7 +425,7 @@ MACHINE_START(SMDKV310, "SMDKV310")
        .init_irq       = exynos4_init_irq,
        .map_io         = smdkv310_map_io,
        .init_machine   = smdkv310_machine_init,
-       .init_time      = exynos4_timer_init,
+       .init_time      = exynos_init_time,
        .reserve        = &smdkv310_reserve,
        .restart        = exynos4_restart,
 MACHINE_END
@@ -436,7 +438,7 @@ MACHINE_START(SMDKC210, "SMDKC210")
        .map_io         = smdkv310_map_io,
        .init_machine   = smdkv310_machine_init,
        .init_late      = exynos_init_late,
-       .init_time      = exynos4_timer_init,
+       .init_time      = exynos_init_time,
        .reserve        = &smdkv310_reserve,
        .restart        = exynos4_restart,
 MACHINE_END
index 497fcb793dc150a39b02fa9c4b49cf33b70a18b1..72f08fd7cfa94f657b020c246036eaa6b4b722d5 100644 (file)
@@ -41,7 +41,7 @@
 #include <plat/mfc.h>
 #include <plat/sdhci.h>
 #include <plat/fimc-core.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 #include <plat/camport.h>
 
 #include <mach/map.h>
@@ -1092,9 +1092,10 @@ static struct platform_device *universal_devices[] __initdata = {
 static void __init universal_map_io(void)
 {
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
-       s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
+       samsung_set_timer_source(SAMSUNG_PWM2, SAMSUNG_PWM4);
+       xxti_f = 0;
+       xusbxti_f = 24000000;
 }
 
 static void s5p_tv_setup(void)
@@ -1152,7 +1153,7 @@ MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
        .map_io         = universal_map_io,
        .init_machine   = universal_machine_init,
        .init_late      = exynos_init_late,
-       .init_time      = s5p_timer_init,
+       .init_time      = samsung_timer_init,
        .reserve        = &universal_reserve,
        .restart        = exynos4_restart,
 MACHINE_END
index e8d08bf8965aa7bdff8935173fcb1549dcbab815..d5b98c8667385cbab7ed4f371dec7a9106d07dea 100644 (file)
@@ -19,8 +19,8 @@
 #include <linux/mmc/host.h>
 #include <linux/mmc/card.h>
 
+#include <mach/gpio.h>
 #include <plat/gpio-cfg.h>
-#include <plat/regs-sdhci.h>
 #include <plat/sdhci.h>
 
 void exynos4_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
index abda5a18a664734a5d29a015cfabfbe7d0a5c26a..0f2111a11315853a046284b71b290890f3ae8fdd 100644 (file)
@@ -67,6 +67,7 @@ config ARCH_NETWINDER
        select ISA
        select ISA_DMA
        select PCI
+       select VIRT_TO_BUS
        help
          Say Y here if you intend to run this kernel on the Rebel.COM
          NetWinder.  Information about this machine can be found at:
index 1ab91b5209e6503e7742450c4dc424a15b2e651c..85b728cc27abc4db782328f9a0524cb08abc759a 100644 (file)
@@ -169,7 +169,7 @@ struct clk *imx_clk_busy_mux(const char *name, void __iomem *reg, u8 shift,
 
        busy->mux.reg = reg;
        busy->mux.shift = shift;
-       busy->mux.width = width;
+       busy->mux.mask = BIT(width) - 1;
        busy->mux.lock = &imx_ccm_lock;
        busy->mux_ops = &clk_mux_ops;
 
index 74e3a34d78b80a25be2edeb9afcc2f027f610368..e13a8fa5e62c5aa4f04b0aba66f4e77df0ac24ce 100644 (file)
@@ -264,6 +264,7 @@ int __init mx35_clocks_init(void)
        clk_prepare_enable(clk[gpio3_gate]);
        clk_prepare_enable(clk[iim_gate]);
        clk_prepare_enable(clk[emi_gate]);
+       clk_prepare_enable(clk[max_gate]);
 
        /*
         * SCC is needed to boot via mmc after a watchdog reset. The clock code
index 7b025ee528a517bdb7d584e90cebefc40fb56a48..2f9ff93a4e6134773befacb68c4dd4ec5c14bb90 100644 (file)
@@ -172,7 +172,7 @@ static struct clk *clk[clk_max];
 static struct clk_onecell_data clk_data;
 
 static enum mx6q_clks const clks_init_on[] __initconst = {
-       mmdc_ch0_axi, rom,
+       mmdc_ch0_axi, rom, pll1_sys,
 };
 
 static struct clk_div_table clk_enet_ref_table[] = {
index 5a800bfcec5b9e67bbf20b6b7001a70867c28482..5bf4a97ab2413c3a7234a092a74350423cba359b 100644 (file)
@@ -110,6 +110,8 @@ void tzic_handle_irq(struct pt_regs *);
 
 extern void imx_enable_cpu(int cpu, bool enable);
 extern void imx_set_cpu_jump(int cpu, void *jump_addr);
+extern u32 imx_get_cpu_arg(int cpu);
+extern void imx_set_cpu_arg(int cpu, u32 arg);
 extern void v7_cpu_resume(void);
 extern u32 *pl310_get_save_ptr(void);
 #ifdef CONFIG_SMP
index 921fc15558549093f0ff0bbcc9b9de946d520152..a58c8b0527ccb3aad1f542b83a159c868a61655d 100644 (file)
@@ -26,16 +26,16 @@ ENDPROC(v7_secondary_startup)
 
 #ifdef CONFIG_PM
 /*
- * 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.
+ * The following code must assume it is running from physical address
+ * where absolute virtual addresses to the data section have to be
+ * turned into relative ones.
  */
-       .data
-       .align
 
 #ifdef CONFIG_CACHE_L2X0
        .macro  pl310_resume
-       ldr     r2, phys_l2x0_saved_regs
+       adr     r0, l2x0_saved_regs_offset
+       ldr     r2, [r0]
+       add     r2, r2, r0
        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
@@ -43,9 +43,9 @@ ENDPROC(v7_secondary_startup)
        str     r1, [r0, #L2X0_CTRL]            @ re-enable L2
        .endm
 
-       .globl  phys_l2x0_saved_regs
-phys_l2x0_saved_regs:
-        .long   0
+l2x0_saved_regs_offset:
+       .word   l2x0_saved_regs - .
+
 #else
        .macro  pl310_resume
        .endm
index 7bc5fe15dda2a3cbc5eb43bd1c93d69830c4af70..361a253e2b63c1abbce953df6745c1fdac8812d7 100644 (file)
@@ -46,11 +46,23 @@ static inline void cpu_enter_lowpower(void)
 void imx_cpu_die(unsigned int cpu)
 {
        cpu_enter_lowpower();
+       /*
+        * We use the cpu jumping argument register to sync with
+        * imx_cpu_kill() which is running on cpu0 and waiting for
+        * the register being cleared to kill the cpu.
+        */
+       imx_set_cpu_arg(cpu, ~0);
        cpu_do_idle();
 }
 
 int imx_cpu_kill(unsigned int cpu)
 {
+       unsigned long timeout = jiffies + msecs_to_jiffies(50);
+
+       while (imx_get_cpu_arg(cpu) == 0)
+               if (time_after(jiffies, timeout))
+                       return 0;
        imx_enable_cpu(cpu, false);
+       imx_set_cpu_arg(cpu, 0);
        return 1;
 }
index 03b65e5ea541613a062ea5719b32ab045b9e723f..82348391582a0944108a8d3ab06a4abb81771e20 100644 (file)
@@ -27,6 +27,11 @@ static const char * const imx25_dt_board_compat[] __initconst = {
        NULL
 };
 
+static void __init imx25_timer_init(void)
+{
+       mx25_clocks_init_dt();
+}
+
 DT_MACHINE_START(IMX25_DT, "Freescale i.MX25 (Device Tree Support)")
        .map_io         = mx25_map_io,
        .init_early     = imx25_init_early,
index ee42d20cba19f022d4a9ece8616e27b443d7e82e..5faba7a3c95f6e74393699045aa0635331459d46 100644 (file)
@@ -22,8 +22,6 @@
 #include "common.h"
 #include "hardware.h"
 
-extern unsigned long phys_l2x0_saved_regs;
-
 static int imx6q_suspend_finish(unsigned long val)
 {
        cpu_do_idle();
@@ -57,18 +55,5 @@ static const struct platform_suspend_ops imx6q_pm_ops = {
 
 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.
-        */
-#ifdef CONFIG_CACHE_L2X0
-       phys_l2x0_saved_regs = __pa(&l2x0_saved_regs);
-#endif
-
        suspend_set_ops(&imx6q_pm_ops);
 }
index e15f1555c59b1ebd2712ba8b8c31772c340b06ef..09a742f8c7aba31be0155076699eb192f4aa251e 100644 (file)
@@ -43,6 +43,18 @@ void imx_set_cpu_jump(int cpu, void *jump_addr)
                       src_base + SRC_GPR1 + cpu * 8);
 }
 
+u32 imx_get_cpu_arg(int cpu)
+{
+       cpu = cpu_logical_map(cpu);
+       return readl_relaxed(src_base + SRC_GPR1 + cpu * 8 + 4);
+}
+
+void imx_set_cpu_arg(int cpu, u32 arg)
+{
+       cpu = cpu_logical_map(cpu);
+       writel_relaxed(arg, src_base + SRC_GPR1 + cpu * 8 + 4);
+}
+
 void imx_src_prepare_restart(void)
 {
        u32 val;
index ea961445e0e993a6f244b8bc70cd5a79c59108c4..b23c8e4f28e859180b90d04fb1a7c8b79e619b69 100644 (file)
@@ -536,16 +536,14 @@ static void __init ap_init_of(void)
                                           'A' + (ap_sc_id & 0x0f));
 
        soc_dev = soc_device_register(soc_dev_attr);
-       if (IS_ERR_OR_NULL(soc_dev)) {
+       if (IS_ERR(soc_dev)) {
                kfree(soc_dev_attr->revision);
                kfree(soc_dev_attr);
                return;
        }
 
        parent = soc_device_to_device(soc_dev);
-
-       if (!IS_ERR_OR_NULL(parent))
-               integrator_init_sysfs(parent, ap_sc_id);
+       integrator_init_sysfs(parent, ap_sc_id);
 
        of_platform_populate(root, of_default_bus_match_table,
                        ap_auxdata_lookup, parent);
index 2b0db82a53819e58d98b89131fd05f07317515e6..da1091be0887bd1344a9ba33daf743d1d0a05b3a 100644 (file)
@@ -360,17 +360,14 @@ static void __init intcp_init_of(void)
                                           'A' + (intcp_sc_id & 0x0f));
 
        soc_dev = soc_device_register(soc_dev_attr);
-       if (IS_ERR_OR_NULL(soc_dev)) {
+       if (IS_ERR(soc_dev)) {
                kfree(soc_dev_attr->revision);
                kfree(soc_dev_attr);
                return;
        }
 
        parent = soc_device_to_device(soc_dev);
-
-       if (!IS_ERR_OR_NULL(parent))
-               integrator_init_sysfs(parent, intcp_sc_id);
-
+       integrator_init_sysfs(parent, intcp_sc_id);
        of_platform_populate(root, of_default_bus_match_table,
                        intcp_auxdata_lookup, parent);
 }
index d42730a1d4abf5b85ccb193c6e9c297a140485c0..d599e354ca57fd6511db36fb8660636e6d152c81 100644 (file)
@@ -163,6 +163,7 @@ static struct platform_device vulcan_max6369 = {
 
 static struct w1_gpio_platform_data vulcan_w1_gpio_pdata = {
        .pin                    = 14,
+       .ext_pullup_enable_pin  = -EINVAL,
 };
 
 static struct platform_device vulcan_w1_gpio = {
index 2e73e9d53f705775246a057bb7cfbdf8219f44a2..d367aa6b47bbf8a11df36fd856e620e81b65d0c1 100644 (file)
@@ -41,16 +41,12 @@ static void __init kirkwood_legacy_clk_init(void)
 
        struct device_node *np = of_find_compatible_node(
                NULL, NULL, "marvell,kirkwood-gating-clock");
-
        struct of_phandle_args clkspec;
+       struct clk *clk;
 
        clkspec.np = np;
        clkspec.args_count = 1;
 
-       clkspec.args[0] = CGC_BIT_GE0;
-       orion_clkdev_add(NULL, "mv643xx_eth_port.0",
-                        of_clk_get_from_provider(&clkspec));
-
        clkspec.args[0] = CGC_BIT_PEX0;
        orion_clkdev_add("0", "pcie",
                         of_clk_get_from_provider(&clkspec));
@@ -59,9 +55,24 @@ static void __init kirkwood_legacy_clk_init(void)
        orion_clkdev_add("1", "pcie",
                         of_clk_get_from_provider(&clkspec));
 
-       clkspec.args[0] = CGC_BIT_GE1;
-       orion_clkdev_add(NULL, "mv643xx_eth_port.1",
+       clkspec.args[0] = CGC_BIT_SDIO;
+       orion_clkdev_add(NULL, "mvsdio",
                         of_clk_get_from_provider(&clkspec));
+
+       /*
+        * The ethernet interfaces forget the MAC address assigned by
+        * u-boot if the clocks are turned off. Until proper DT support
+        * is available we always enable them for now.
+        */
+       clkspec.args[0] = CGC_BIT_GE0;
+       clk = of_clk_get_from_provider(&clkspec);
+       orion_clkdev_add(NULL, "mv643xx_eth_port.0", clk);
+       clk_prepare_enable(clk);
+
+       clkspec.args[0] = CGC_BIT_GE1;
+       clk = of_clk_get_from_provider(&clkspec);
+       orion_clkdev_add(NULL, "mv643xx_eth_port.1", clk);
+       clk_prepare_enable(clk);
 }
 
 static void __init kirkwood_of_clk_init(void)
index 1c6e736cbbf8b64e580f511c4a3f0e6f3a239d0a..08dd739aa70918fe9fdf1c06aeca7eda265ca07f 100644 (file)
@@ -53,6 +53,8 @@ static struct mv_sata_platform_data guruplug_sata_data = {
 
 static struct mvsdio_platform_data guruplug_mvsdio_data = {
        /* unfortunately the CD signal has not been connected */
+       .gpio_card_detect = -1,
+       .gpio_write_protect = -1,
 };
 
 static struct gpio_led guruplug_led_pins[] = {
index 8ddd69fdc9374ebe20c8ab7b1842593164410c05..6a6eb548307d10762b0f56307b81938842d180aa 100644 (file)
@@ -55,6 +55,7 @@ static struct mv_sata_platform_data openrd_sata_data = {
 
 static struct mvsdio_platform_data openrd_mvsdio_data = {
        .gpio_card_detect = 29, /* MPP29 used as SD card detect */
+       .gpio_write_protect = -1,
 };
 
 static unsigned int openrd_mpp_config[] __initdata = {
index c7d93b48926bbae7d7013190e00ae401e552549b..d24223166e06c60e5d9631d6f8818f44bfb0fc5b 100644 (file)
@@ -69,6 +69,7 @@ static struct mv_sata_platform_data rd88f6281_sata_data = {
 
 static struct mvsdio_platform_data rd88f6281_mvsdio_data = {
        .gpio_card_detect = 28,
+       .gpio_write_protect = -1,
 };
 
 static unsigned int rd88f6281_mpp_config[] __initdata = {
index d1e2d595e79cafd44b737d49904b07b65042d3fa..f62b68d926f4237bf70911ba43487d27c98d4e97 100644 (file)
@@ -9,6 +9,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <linux/gpio.h>
 
 #include <asm/mach/arch.h>
index 2969027f02fa57045ec7bb3d65d7a98927cfde3c..f9fd77e8f1f5a998af7b8f15e12af3afd5bcc299 100644 (file)
@@ -62,7 +62,10 @@ static int msm_timer_set_next_event(unsigned long cycles,
 {
        u32 ctrl = readl_relaxed(event_base + TIMER_ENABLE);
 
-       writel_relaxed(0, event_base + TIMER_CLEAR);
+       ctrl &= ~TIMER_ENABLE_EN;
+       writel_relaxed(ctrl, event_base + TIMER_ENABLE);
+
+       writel_relaxed(ctrl, event_base + TIMER_CLEAR);
        writel_relaxed(cycles, event_base + TIMER_MATCH_VAL);
        writel_relaxed(ctrl | TIMER_ENABLE_EN, event_base + TIMER_ENABLE);
        return 0;
index 274ff58271de149f168a1a901ccc435ea131f690..6a9195e10579a8263b3446ccc443bd1d1381f784 100644 (file)
@@ -44,6 +44,8 @@
 
 #define ARMADA_370_XP_MAX_PER_CPU_IRQS         (28)
 
+#define ARMADA_370_XP_TIMER0_PER_CPU_IRQ       (5)
+
 #define ACTIVE_DOORBELLS                       (8)
 
 static DEFINE_RAW_SPINLOCK(irq_controller_lock);
@@ -62,7 +64,7 @@ static void armada_370_xp_irq_mask(struct irq_data *d)
 #ifdef CONFIG_SMP
        irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
-       if (hwirq > ARMADA_370_XP_MAX_PER_CPU_IRQS)
+       if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
                writel(hwirq, main_int_base +
                                ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS);
        else
@@ -79,7 +81,7 @@ static void armada_370_xp_irq_unmask(struct irq_data *d)
 #ifdef CONFIG_SMP
        irq_hw_number_t hwirq = irqd_to_hwirq(d);
 
-       if (hwirq > ARMADA_370_XP_MAX_PER_CPU_IRQS)
+       if (hwirq != ARMADA_370_XP_TIMER0_PER_CPU_IRQ)
                writel(hwirq, main_int_base +
                                ARMADA_370_XP_INT_SET_ENABLE_OFFS);
        else
@@ -147,7 +149,7 @@ static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
        writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS);
        irq_set_status_flags(virq, IRQ_LEVEL);
 
-       if (hw < ARMADA_370_XP_MAX_PER_CPU_IRQS) {
+       if (hw == ARMADA_370_XP_TIMER0_PER_CPU_IRQ) {
                irq_set_percpu_devid(virq);
                irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
                                        handle_percpu_devid_irq);
index 8fb23af154b391957da0c03b16ed1d046fca6d2e..e26eeba46598356be29a31fc1e1caeac1c07a9c3 100644 (file)
@@ -100,7 +100,7 @@ static struct irq_domain_ops icoll_irq_domain_ops = {
        .xlate = irq_domain_xlate_onecell,
 };
 
-void __init icoll_of_init(struct device_node *np,
+static void __init icoll_of_init(struct device_node *np,
                          struct device_node *interrupt_parent)
 {
        /*
index 052186713347c5b4ed1a17c503825f4b9894f316..e7b781d3788f2c9a9e896ef75b502f789fd15d64 100644 (file)
@@ -41,8 +41,6 @@ static struct fb_videomode mx23evk_video_modes[] = {
                .lower_margin   = 4,
                .hsync_len      = 1,
                .vsync_len      = 1,
-               .sync           = FB_SYNC_DATA_ENABLE_HIGH_ACT |
-                                 FB_SYNC_DOTCLK_FAILING_ACT,
        },
 };
 
@@ -59,8 +57,6 @@ static struct fb_videomode mx28evk_video_modes[] = {
                .lower_margin   = 10,
                .hsync_len      = 10,
                .vsync_len      = 10,
-               .sync           = FB_SYNC_DATA_ENABLE_HIGH_ACT |
-                                 FB_SYNC_DOTCLK_FAILING_ACT,
        },
 };
 
@@ -77,7 +73,6 @@ static struct fb_videomode m28evk_video_modes[] = {
                .lower_margin   = 45,
                .hsync_len      = 1,
                .vsync_len      = 1,
-               .sync           = FB_SYNC_DATA_ENABLE_HIGH_ACT,
        },
 };
 
@@ -94,9 +89,7 @@ static struct fb_videomode apx4devkit_video_modes[] = {
                .lower_margin   = 13,
                .hsync_len      = 48,
                .vsync_len      = 3,
-               .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT |
-                                 FB_SYNC_DATA_ENABLE_HIGH_ACT |
-                                 FB_SYNC_DOTCLK_FAILING_ACT,
+               .sync           = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
        },
 };
 
@@ -113,9 +106,7 @@ static struct fb_videomode apf28dev_video_modes[] = {
                .lower_margin = 0x15,
                .hsync_len = 64,
                .vsync_len = 4,
-               .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT |
-                               FB_SYNC_DATA_ENABLE_HIGH_ACT |
-                               FB_SYNC_DOTCLK_FAILING_ACT,
+               .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
        },
 };
 
@@ -132,7 +123,6 @@ static struct fb_videomode cfa10049_video_modes[] = {
                .lower_margin   = 2,
                .hsync_len      = 15,
                .vsync_len      = 15,
-               .sync           = FB_SYNC_DATA_ENABLE_HIGH_ACT
        },
 };
 
@@ -259,6 +249,8 @@ static void __init imx23_evk_init(void)
        mxsfb_pdata.mode_count = ARRAY_SIZE(mx23evk_video_modes);
        mxsfb_pdata.default_bpp = 32;
        mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT;
+       mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT |
+                               MXSFB_SYNC_DOTCLK_FAILING_ACT;
 }
 
 static inline void enable_clk_enet_out(void)
@@ -278,6 +270,8 @@ static void __init imx28_evk_init(void)
        mxsfb_pdata.mode_count = ARRAY_SIZE(mx28evk_video_modes);
        mxsfb_pdata.default_bpp = 32;
        mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT;
+       mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT |
+                               MXSFB_SYNC_DOTCLK_FAILING_ACT;
 
        mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
 }
@@ -297,6 +291,7 @@ static void __init m28evk_init(void)
        mxsfb_pdata.mode_count = ARRAY_SIZE(m28evk_video_modes);
        mxsfb_pdata.default_bpp = 16;
        mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT;
+       mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT;
 }
 
 static void __init sc_sps1_init(void)
@@ -322,6 +317,8 @@ static void __init apx4devkit_init(void)
        mxsfb_pdata.mode_count = ARRAY_SIZE(apx4devkit_video_modes);
        mxsfb_pdata.default_bpp = 32;
        mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT;
+       mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT |
+                               MXSFB_SYNC_DOTCLK_FAILING_ACT;
 }
 
 #define ENET0_MDC__GPIO_4_0    MXS_GPIO_NR(4, 0)
@@ -402,17 +399,18 @@ static void __init cfa10049_init(void)
 {
        enable_clk_enet_out();
        update_fec_mac_prop(OUI_CRYSTALFONTZ);
+
+       mxsfb_pdata.mode_list = cfa10049_video_modes;
+       mxsfb_pdata.mode_count = ARRAY_SIZE(cfa10049_video_modes);
+       mxsfb_pdata.default_bpp = 32;
+       mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT;
+       mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT;
 }
 
 static void __init cfa10037_init(void)
 {
        enable_clk_enet_out();
        update_fec_mac_prop(OUI_CRYSTALFONTZ);
-
-       mxsfb_pdata.mode_list = cfa10049_video_modes;
-       mxsfb_pdata.mode_count = ARRAY_SIZE(cfa10049_video_modes);
-       mxsfb_pdata.default_bpp = 32;
-       mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT;
 }
 
 static void __init apf28_init(void)
@@ -423,6 +421,8 @@ static void __init apf28_init(void)
        mxsfb_pdata.mode_count = ARRAY_SIZE(apf28dev_video_modes);
        mxsfb_pdata.default_bpp = 16;
        mxsfb_pdata.ld_intf_width = STMLCDIF_16BIT;
+       mxsfb_pdata.sync = MXSFB_SYNC_DATA_ENABLE_HIGH_ACT |
+                               MXSFB_SYNC_DOTCLK_FAILING_ACT;
 }
 
 static void __init mxs_machine_init(void)
index a4294aa9f301f93c6166c1902fe8577753bc3961..e63b7d87acbda14b1c422113e8198e58c245c999 100644 (file)
@@ -18,6 +18,7 @@
 
 #include <mach/mx23.h>
 #include <mach/mx28.h>
+#include <mach/common.h>
 
 /*
  * Define the MX23 memory map.
index 54add60f94c98c5d8d15c119e996395a13b6fc86..1dff46703753f67e96a3efd2a62a29966aba8b71 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/processor.h>     /* for cpu_relax() */
 
 #include <mach/mxs.h>
+#include <mach/common.h>
 
 #define OCOTP_WORD_OFFSET              0x20
 #define OCOTP_WORD_COUNT               0x20
index 903da8eb886c8ebc6abe1a79dab58b0d79a98730..cdd05f2e67ee87148a023bd2af8025fbfb5b5bff 100644 (file)
@@ -55,12 +55,6 @@ config MACH_OMAP_H3
          TI OMAP 1710 H3 board support. Say Y here if you have such
          a board.
 
-config MACH_OMAP_HTCWIZARD
-       bool "HTC Wizard"
-       depends on ARCH_OMAP850
-       help
-         HTC Wizard smartphone support (AKA QTEK 9100, ...)
-
 config MACH_HERALD
        bool "HTC Herald"
        depends on ARCH_OMAP850
index cb7c6ae2e3fc66f4a0744bf7930e7e1cd635ee87..6c4f766365a2e31d9b0364ef6460dca7e79c756c 100644 (file)
@@ -538,15 +538,6 @@ static struct clk usb_hhc_ck16xx = {
 };
 
 static struct clk usb_dc_ck = {
-       .name           = "usb_dc_ck",
-       .ops            = &clkops_generic,
-       /* Direct from ULPD, no parent */
-       .rate           = 48000000,
-       .enable_reg     = OMAP1_IO_ADDRESS(SOFT_REQ_REG),
-       .enable_bit     = USB_REQ_EN_SHIFT,
-};
-
-static struct clk usb_dc_ck7xx = {
        .name           = "usb_dc_ck",
        .ops            = &clkops_generic,
        /* Direct from ULPD, no parent */
@@ -727,8 +718,7 @@ static struct omap_clk omap_clks[] = {
        CLK(NULL,       "usb_clko",     &usb_clko,      CK_16XX | CK_1510 | CK_310),
        CLK(NULL,       "usb_hhc_ck",   &usb_hhc_ck1510, CK_1510 | CK_310),
        CLK(NULL,       "usb_hhc_ck",   &usb_hhc_ck16xx, CK_16XX),
-       CLK(NULL,       "usb_dc_ck",    &usb_dc_ck,     CK_16XX),
-       CLK(NULL,       "usb_dc_ck",    &usb_dc_ck7xx,  CK_7XX),
+       CLK(NULL,       "usb_dc_ck",    &usb_dc_ck,     CK_16XX | CK_7XX),
        CLK(NULL,       "mclk",         &mclk_1510,     CK_1510 | CK_310),
        CLK(NULL,       "mclk",         &mclk_16xx,     CK_16XX),
        CLK(NULL,       "bclk",         &bclk_1510,     CK_1510 | CK_310),
index fb18831e88aa5009fd8d1b546bba39d9397697d3..14f7e99204798dc5cfff4fc14be33c683751a405 100644 (file)
@@ -31,6 +31,8 @@
 
 #include <plat/i2c.h>
 
+#include <mach/irqs.h>
+
 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
 void omap7xx_map_io(void);
 #else
index 49ac3dfebef90b15d7d1da6e15f06e2807bc9cc1..b9c0ed3f648c8415f432a5f4b8f079c163beb013 100644 (file)
@@ -311,9 +311,6 @@ config MACH_OMAP_ZOOM2
        default y
        select OMAP_PACKAGE_CBB
        select REGULATOR_FIXED_VOLTAGE if REGULATOR
-       select SERIAL_8250
-       select SERIAL_8250_CONSOLE
-       select SERIAL_CORE_CONSOLE
 
 config MACH_OMAP_ZOOM3
        bool "OMAP3630 Zoom3 board"
@@ -321,9 +318,6 @@ config MACH_OMAP_ZOOM3
        default y
        select OMAP_PACKAGE_CBP
        select REGULATOR_FIXED_VOLTAGE if REGULATOR
-       select SERIAL_8250
-       select SERIAL_8250_CONSOLE
-       select SERIAL_CORE_CONSOLE
 
 config MACH_CM_T35
        bool "CompuLab CM-T35/CM-T3730 modules"
@@ -414,7 +408,7 @@ config OMAP3_SDRC_AC_TIMING
 
 config OMAP4_ERRATA_I688
        bool "OMAP4 errata: Async Bridge Corruption"
-       depends on ARCH_OMAP4 && !ARCH_MULTIPLATFORM
+       depends on (ARCH_OMAP4 || SOC_OMAP5) && !ARCH_MULTIPLATFORM
        select ARCH_HAS_BARRIERS
        help
          If a data is stalled inside asynchronous bridge because of back
index a3e0aaa4886b9c4954160d585115a219d1ba3a95..cb0596b631cff4feef830b27f0904be930416b47 100644 (file)
@@ -166,7 +166,7 @@ static void __init sdp2430_display_init(void)
        omap_display_init(&sdp2430_dss_data);
 }
 
-#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE)
+#if IS_ENABLED(CONFIG_SMC91X)
 
 static struct omap_smc91x_platform_data board_smc91x_data = {
        .cs             = 5,
index ce812decfacad108eecdb20174f7c030ffcf5cc5..7eb9651dd0f7e02d7e19c52c3d81d0bfa5cfc8dc 100644 (file)
@@ -445,16 +445,23 @@ static void enable_board_wakeup_source(void)
                OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP);
 }
 
+static struct usbhs_phy_data phy_data[] __initdata = {
+       {
+               .port = 1,
+               .reset_gpio = 57,
+               .vcc_gpio = -EINVAL,
+       },
+       {
+               .port = 2,
+               .reset_gpio = 61,
+               .vcc_gpio = -EINVAL,
+       },
+};
+
 static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 
        .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
-       .phy_reset  = true,
-       .reset_gpio_port[0]  = 57,
-       .reset_gpio_port[1]  = 61,
-       .reset_gpio_port[2]  = -EINVAL
 };
 
 #ifdef CONFIG_OMAP_MUX
@@ -606,6 +613,8 @@ static void __init omap_3430sdp_init(void)
        board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
        sdp3430_display_init();
        enable_board_wakeup_source();
+
+       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
        usbhs_init(&usbhs_bdata);
 }
 
index 67447bd4564fbd05c5956ebed41a5de3e10ac3f6..20d6d8189240d3343798833578093d4ae9933f36 100644 (file)
@@ -53,16 +53,23 @@ static void enable_board_wakeup_source(void)
                OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP);
 }
 
+static struct usbhs_phy_data phy_data[] __initdata = {
+       {
+               .port = 1,
+               .reset_gpio = 126,
+               .vcc_gpio = -EINVAL,
+       },
+       {
+               .port = 2,
+               .reset_gpio = 61,
+               .vcc_gpio = -EINVAL,
+       },
+};
+
 static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 
        .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
-       .phy_reset  = true,
-       .reset_gpio_port[0]  = 126,
-       .reset_gpio_port[1]  = 61,
-       .reset_gpio_port[2]  = -EINVAL
 };
 
 #ifdef CONFIG_OMAP_MUX
@@ -199,6 +206,8 @@ static void __init omap_sdp_init(void)
        board_smc91x_init();
        board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16);
        enable_board_wakeup_source();
+
+       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
        usbhs_init(&usbhs_bdata);
 }
 
index 7d3358b2e59369083cd02cbf31d38abb0e3bb282..fc53911d0d13b9842a7efcf28ba4431159df0bc4 100644 (file)
@@ -47,15 +47,17 @@ static struct omap_board_mux board_mux[] __initdata = {
 };
 #endif
 
+static struct usbhs_phy_data phy_data[] __initdata = {
+       {
+               .port = 1,
+               .reset_gpio = GPIO_USB_NRESET,
+               .vcc_gpio = GPIO_USB_POWER,
+               .vcc_polarity = 1,
+       },
+};
+
 static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
        .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
-       .phy_reset  = true,
-       .reset_gpio_port[0]  = GPIO_USB_NRESET,
-       .reset_gpio_port[1]  = -EINVAL,
-       .reset_gpio_port[2]  = -EINVAL
 };
 
 static struct mtd_partition crane_nand_partitions[] = {
@@ -131,13 +133,7 @@ static void __init am3517_crane_init(void)
                return;
        }
 
-       ret = gpio_request_one(GPIO_USB_POWER, GPIOF_OUT_INIT_HIGH,
-                              "usb_ehci_enable");
-       if (ret < 0) {
-               pr_err("Can not request GPIO %d\n", GPIO_USB_POWER);
-               return;
-       }
-
+       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
        usbhs_init(&usbhs_bdata);
        am35xx_emac_init(AM35XX_DEFAULT_MDIO_FREQUENCY, 1);
 }
index 9fb85908a61e498a7ae7ec27f18fe2f7b45756db..191f9762ba63c4eb4368b95a862b17228ac5049c 100644 (file)
@@ -274,6 +274,14 @@ static __init void am3517_evm_mcbsp1_init(void)
        omap_ctrl_writel(devconf0, OMAP2_CONTROL_DEVCONF0);
 }
 
+static struct usbhs_phy_data phy_data[] __initdata = {
+       {
+               .port = 1,
+               .reset_gpio = 57,
+               .vcc_gpio = -EINVAL,
+       },
+};
+
 static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
        .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 #if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \
@@ -282,12 +290,6 @@ static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
 #else
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
 #endif
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
-       .phy_reset  = true,
-       .reset_gpio_port[0]  = 57,
-       .reset_gpio_port[1]  = -EINVAL,
-       .reset_gpio_port[2]  = -EINVAL
 };
 
 #ifdef CONFIG_OMAP_MUX
@@ -349,7 +351,6 @@ static struct omap2_hsmmc_info mmc[] = {
        {}      /* Terminator */
 };
 
-
 static void __init am3517_evm_init(void)
 {
        omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
@@ -361,6 +362,8 @@ static void __init am3517_evm_init(void)
 
        /* Configure GPIO for EHCI port */
        omap_mux_init_gpio(57, OMAP_PIN_OUTPUT);
+
+       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
        usbhs_init(&usbhs_bdata);
        am3517_evm_hecc_init(&am3517_evm_hecc_pdata);
        /* DSS */
index af2bb219e2147d922c95f829e833804f421184b3..7fda3f5f8a7fdf8ce0de057241342333729a8fc8 100644 (file)
@@ -419,15 +419,22 @@ static struct omap2_hsmmc_info mmc[] = {
        {}      /* Terminator */
 };
 
+static struct usbhs_phy_data phy_data[] __initdata = {
+       {
+               .port = 1,
+               .reset_gpio = OMAP_MAX_GPIO_LINES + 6,
+               .vcc_gpio = -EINVAL,
+       },
+       {
+               .port = 2,
+               .reset_gpio = OMAP_MAX_GPIO_LINES + 7,
+               .vcc_gpio = -EINVAL,
+       },
+};
+
 static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
        .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
-       .phy_reset  = true,
-       .reset_gpio_port[0]  = OMAP_MAX_GPIO_LINES + 6,
-       .reset_gpio_port[1]  = OMAP_MAX_GPIO_LINES + 7,
-       .reset_gpio_port[2]  = -EINVAL
 };
 
 static void  __init cm_t35_init_usbh(void)
@@ -444,6 +451,7 @@ static void  __init cm_t35_init_usbh(void)
                msleep(1);
        }
 
+       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
        usbhs_init(&usbhs_bdata);
 }
 
index a66da808cc4ab011d7d97f449bd33f6a51272b4c..4eb5e6f2f7f5c7e164797069c4f84a03d1995ad1 100644 (file)
@@ -188,15 +188,22 @@ static inline void cm_t3517_init_rtc(void) {}
 #define HSUSB2_RESET_GPIO      (147)
 #define USB_HUB_RESET_GPIO     (152)
 
+static struct usbhs_phy_data phy_data[] __initdata = {
+       {
+               .port = 1,
+               .reset_gpio = HSUSB1_RESET_GPIO,
+               .vcc_gpio = -EINVAL,
+       },
+       {
+               .port = 2,
+               .reset_gpio = HSUSB2_RESET_GPIO,
+               .vcc_gpio = -EINVAL,
+       },
+};
+
 static struct usbhs_omap_platform_data cm_t3517_ehci_pdata __initdata = {
        .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
-       .phy_reset  = true,
-       .reset_gpio_port[0]  = HSUSB1_RESET_GPIO,
-       .reset_gpio_port[1]  = HSUSB2_RESET_GPIO,
-       .reset_gpio_port[2]  = -EINVAL,
 };
 
 static int __init cm_t3517_init_usbh(void)
@@ -213,6 +220,7 @@ static int __init cm_t3517_init_usbh(void)
                msleep(1);
        }
 
+       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
        usbhs_init(&cm_t3517_ehci_pdata);
 
        return 0;
@@ -324,6 +332,6 @@ MACHINE_START(CM_T3517, "Compulab CM-T3517")
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = cm_t3517_init,
        .init_late      = am35xx_init_late,
-       .init_time      = omap3_gp_gptimer_timer_init,
+       .init_time      = omap3_gptimer_timer_init,
        .restart        = omap3xxx_restart,
 MACHINE_END
index 53056c3b08362ea6a4c40f8a044f2b146018a1d8..42fbf1ef12a949778107b7a5e8aa76b18638e986 100644 (file)
@@ -437,15 +437,7 @@ static struct platform_device *devkit8000_devices[] __initdata = {
 };
 
 static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
-
        .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
-       .phy_reset  = true,
-       .reset_gpio_port[0]  = -EINVAL,
-       .reset_gpio_port[1]  = -EINVAL,
-       .reset_gpio_port[2]  = -EINVAL
 };
 
 #ifdef CONFIG_OMAP_MUX
index 0274ff7a2a2b1c33dcdcf5e6aaac541f15a86c84..78813b3972098faf7860be9a90ce4fd94b1ac1dc 100644 (file)
@@ -102,6 +102,7 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
        .init_irq       = omap_intc_of_init,
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_generic_init,
+       .init_late      = omap3_init_late,
        .init_time      = omap3_sync32k_timer_init,
        .dt_compat      = omap3_boards_compat,
        .restart        = omap3xxx_restart,
@@ -119,6 +120,7 @@ DT_MACHINE_START(OMAP3_GP_DT, "Generic OMAP3-GP (Flattened Device Tree)")
        .init_irq       = omap_intc_of_init,
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_generic_init,
+       .init_late      = omap3_init_late,
        .init_time      = omap3_secure_sync32k_timer_init,
        .dt_compat      = omap3_gp_boards_compat,
        .restart        = omap3xxx_restart,
@@ -138,7 +140,7 @@ DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
        .init_irq       = omap_intc_of_init,
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_generic_init,
-       .init_time      = omap3_am33xx_gptimer_timer_init,
+       .init_time      = omap3_gptimer_timer_init,
        .dt_compat      = am33xx_boards_compat,
        .restart        = am33xx_restart,
 MACHINE_END
index 812c829fa46f60a3af0aeec99bcb45555500bb05..5b4ec51c385f06ecdaf0b3f0b231e0f281bee3c2 100644 (file)
@@ -246,7 +246,7 @@ static u32 is_gpmc_muxed(void)
                return 0;
 }
 
-#if defined(CONFIG_SMC91X) || defined(CONFIG_SMC91x_MODULE)
+#if IS_ENABLED(CONFIG_SMC91X)
 
 static struct omap_smc91x_platform_data board_smc91x_data = {
        .cs             = 1,
index bf92678a01d061dabd0d857dfb00d83504ce034a..95ccec0eeab919f33101e657147955056c818ca2 100644 (file)
@@ -527,26 +527,28 @@ static void __init igep_i2c_init(void)
        omap3_pmic_init("twl4030", &igep_twldata);
 }
 
+static struct usbhs_phy_data igep2_phy_data[] __initdata = {
+       {
+               .port = 1,
+               .reset_gpio = IGEP2_GPIO_USBH_NRESET,
+               .vcc_gpio = -EINVAL,
+       },
+};
+
+static struct usbhs_phy_data igep3_phy_data[] __initdata = {
+       {
+               .port = 2,
+               .reset_gpio = IGEP3_GPIO_USBH_NRESET,
+               .vcc_gpio = -EINVAL,
+       },
+};
+
 static struct usbhs_omap_platform_data igep2_usbhs_bdata __initdata = {
        .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
-       .phy_reset = true,
-       .reset_gpio_port[0] = IGEP2_GPIO_USBH_NRESET,
-       .reset_gpio_port[1] = -EINVAL,
-       .reset_gpio_port[2] = -EINVAL,
 };
 
 static struct usbhs_omap_platform_data igep3_usbhs_bdata __initdata = {
-       .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
-       .phy_reset = true,
-       .reset_gpio_port[0] = -EINVAL,
-       .reset_gpio_port[1] = IGEP3_GPIO_USBH_NRESET,
-       .reset_gpio_port[2] = -EINVAL,
 };
 
 #ifdef CONFIG_OMAP_MUX
@@ -642,8 +644,10 @@ static void __init igep_init(void)
        if (machine_is_igep0020()) {
                omap_display_init(&igep2_dss_data);
                igep2_init_smsc911x();
+               usbhs_init_phys(igep2_phy_data, ARRAY_SIZE(igep2_phy_data));
                usbhs_init(&igep2_usbhs_bdata);
        } else {
+               usbhs_init_phys(igep3_phy_data, ARRAY_SIZE(igep3_phy_data));
                usbhs_init(&igep3_usbhs_bdata);
        }
 }
index c3558f93d42c4a3d52f705573be61e156ff59669..6955a428f534321e94c8ca4301e1bbcc3363a900 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/mmc/host.h>
 #include <linux/usb/phy.h>
+#include <linux/usb/nop-usb-xceiv.h>
 
 #include <linux/regulator/machine.h>
 #include <linux/i2c/twl.h>
@@ -277,6 +278,21 @@ static struct regulator_consumer_supply beagle_vsim_supply[] = {
 
 static struct gpio_led gpio_leds[];
 
+/* PHY's VCC regulator might be added later, so flag that we need it */
+static struct nop_usb_xceiv_platform_data hsusb2_phy_data = {
+       .needs_vcc = true,
+};
+
+static struct usbhs_phy_data phy_data[] = {
+       {
+               .port = 2,
+               .reset_gpio = 147,
+               .vcc_gpio = -1,         /* updated in beagle_twl_gpio_setup */
+               .vcc_polarity = 1,      /* updated in beagle_twl_gpio_setup */
+               .platform_data = &hsusb2_phy_data,
+       },
+};
+
 static int beagle_twl_gpio_setup(struct device *dev,
                unsigned gpio, unsigned ngpio)
 {
@@ -318,9 +334,11 @@ static int beagle_twl_gpio_setup(struct device *dev,
        }
        dvi_panel.power_down_gpio = beagle_config.dvi_pd_gpio;
 
-       gpio_request_one(gpio + TWL4030_GPIO_MAX, beagle_config.usb_pwr_level,
-                       "nEN_USB_PWR");
+       /* TWL4030_GPIO_MAX i.e. LED_GPO controls HS USB Port 2 power */
+       phy_data[0].vcc_gpio = gpio + TWL4030_GPIO_MAX;
+       phy_data[0].vcc_polarity = beagle_config.usb_pwr_level;
 
+       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
        return 0;
 }
 
@@ -453,15 +471,7 @@ static struct platform_device *omap3_beagle_devices[] __initdata = {
 };
 
 static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
-
-       .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
-       .phy_reset  = true,
-       .reset_gpio_port[0]  = -EINVAL,
-       .reset_gpio_port[1]  = 147,
-       .reset_gpio_port[2]  = -EINVAL
 };
 
 #ifdef CONFIG_OMAP_MUX
@@ -479,7 +489,7 @@ static int __init beagle_opp_init(void)
 
        /* Initialize the omap3 opp table if not already created. */
        r = omap3_opp_init();
-       if (IS_ERR_VALUE(r) && (r != -EEXIST)) {
+       if (r < 0 && (r != -EEXIST)) {
                pr_err("%s: opp default init failed\n", __func__);
                return r;
        }
@@ -543,7 +553,9 @@ static void __init omap3_beagle_init(void)
 
        usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
        usb_musb_init(NULL);
+
        usbhs_init(&usbhs_bdata);
+
        board_nand_init(omap3beagle_nand_partitions,
                        ARRAY_SIZE(omap3beagle_nand_partitions), NAND_CS,
                        NAND_BUSWIDTH_16, NULL);
index 48789e0bb915059ff8b9fb26d5a2712ff095020b..2de92facc8a38234bacec820218fe4143b8b137f 100644 (file)
@@ -496,7 +496,7 @@ struct wl12xx_platform_data omap3evm_wlan_data __initdata = {
 static struct regulator_consumer_supply omap3evm_vaux2_supplies[] = {
        REGULATOR_SUPPLY("VDD_CSIPHY1", "omap3isp"),    /* OMAP ISP */
        REGULATOR_SUPPLY("VDD_CSIPHY2", "omap3isp"),    /* OMAP ISP */
-       REGULATOR_SUPPLY("hsusb1", "ehci-omap.0"),
+       REGULATOR_SUPPLY("vcc", "nop_usb_xceiv.2"),     /* hsusb port 2 */
        REGULATOR_SUPPLY("vaux2", NULL),
 };
 
@@ -539,17 +539,16 @@ static int __init omap3_evm_i2c_init(void)
        return 0;
 }
 
-static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
+static struct usbhs_phy_data phy_data[] __initdata = {
+       {
+               .port = 2,
+               .reset_gpio = -1,       /* set at runtime */
+               .vcc_gpio = -EINVAL,
+       },
+};
 
-       .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
+static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
-       .phy_reset  = true,
-       /* PHY reset GPIO will be runtime programmed based on EVM version */
-       .reset_gpio_port[0]  = -EINVAL,
-       .reset_gpio_port[1]  = -EINVAL,
-       .reset_gpio_port[2]  = -EINVAL
 };
 
 #ifdef CONFIG_OMAP_MUX
@@ -725,7 +724,7 @@ static void __init omap3_evm_init(void)
 
                /* setup EHCI phy reset config */
                omap_mux_init_gpio(21, OMAP_PIN_INPUT_PULLUP);
-               usbhs_bdata.reset_gpio_port[1] = 21;
+               phy_data[0].reset_gpio = 21;
 
                /* EVM REV >= E can supply 500mA with EXTVBUS programming */
                musb_board_data.power = 500;
@@ -733,10 +732,12 @@ static void __init omap3_evm_init(void)
        } else {
                /* setup EHCI phy reset on MDC */
                omap_mux_init_gpio(135, OMAP_PIN_OUTPUT);
-               usbhs_bdata.reset_gpio_port[1] = 135;
+               phy_data[0].reset_gpio = 135;
        }
        usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
        usb_musb_init(&musb_board_data);
+
+       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
        usbhs_init(&usbhs_bdata);
        board_nand_init(omap3evm_nand_partitions,
                        ARRAY_SIZE(omap3evm_nand_partitions), NAND_CS,
index 2bba362148a0c87d12a53d86d5dd5ef2ddbeb4c1..1004d2aaa68f5e29847eeb1691f7e3d909a162d7 100644 (file)
@@ -346,7 +346,7 @@ static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = {
 };
 
 static struct regulator_consumer_supply pandora_usb_phy_supply[] = {
-       REGULATOR_SUPPLY("hsusb1", "ehci-omap.0"),
+       REGULATOR_SUPPLY("vcc", "nop_usb_xceiv.2"),     /* hsusb port 2 */
 };
 
 /* ads7846 on SPI and 2 nub controllers on I2C */
@@ -561,6 +561,14 @@ fail:
        printk(KERN_ERR "wl1251 board initialisation failed\n");
 }
 
+static struct usbhs_phy_data phy_data[] __initdata = {
+       {
+               .port = 2,
+               .reset_gpio = 16,
+               .vcc_gpio = -EINVAL,
+       },
+};
+
 static struct platform_device *omap3pandora_devices[] __initdata = {
        &pandora_leds_gpio,
        &pandora_keys_gpio,
@@ -569,15 +577,7 @@ static struct platform_device *omap3pandora_devices[] __initdata = {
 };
 
 static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
-
-       .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
-       .phy_reset  = true,
-       .reset_gpio_port[0]  = -EINVAL,
-       .reset_gpio_port[1]  = 16,
-       .reset_gpio_port[2]  = -EINVAL
 };
 
 #ifdef CONFIG_OMAP_MUX
@@ -601,7 +601,10 @@ static void __init omap3pandora_init(void)
        spi_register_board_info(omap3pandora_spi_board_info,
                        ARRAY_SIZE(omap3pandora_spi_board_info));
        omap_ads7846_init(1, OMAP3_PANDORA_TS_GPIO, 0, NULL);
+
+       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
        usbhs_init(&usbhs_bdata);
+
        usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
        usb_musb_init(NULL);
        gpmc_nand_init(&pandora_nand_data, NULL);
index 95c10b3aa678a5321be115c91a353a8296405168..bf095648989933ca0c0171ff661fc998a704a96b 100644 (file)
@@ -358,19 +358,20 @@ static int __init omap3_stalker_i2c_init(void)
 
 #define OMAP3_STALKER_TS_GPIO  175
 
+static struct usbhs_phy_data phy_data[] __initdata = {
+       {
+               .port = 2,
+               .reset_gpio = 21,
+               .vcc_gpio = -EINVAL,
+       },
+};
+
 static struct platform_device *omap3_stalker_devices[] __initdata = {
        &keys_gpio,
 };
 
 static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
-       .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
-       .phy_reset = true,
-       .reset_gpio_port[0] = -EINVAL,
-       .reset_gpio_port[1] = 21,
-       .reset_gpio_port[2] = -EINVAL,
 };
 
 #ifdef CONFIG_OMAP_MUX
@@ -407,6 +408,8 @@ static void __init omap3_stalker_init(void)
        omap_sdrc_init(mt46h32m32lf6_sdrc_params, NULL);
        usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
        usb_musb_init(NULL);
+
+       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
        usbhs_init(&usbhs_bdata);
        omap_ads7846_init(1, OMAP3_STALKER_TS_GPIO, 310, NULL);
 
index bcd44fbcd87785f4332f881d4b23bbb4da7f5d5f..7da48bc42bbfbb2007ac244a594c54299a2eb13d 100644 (file)
@@ -305,21 +305,22 @@ static struct omap_board_mux board_mux[] __initdata = {
 };
 #endif
 
+static struct usbhs_phy_data phy_data[] __initdata = {
+       {
+               .port = 2,
+               .reset_gpio = 147,
+               .vcc_gpio = -EINVAL,
+       },
+};
+
 static struct platform_device *omap3_touchbook_devices[] __initdata = {
        &leds_gpio,
        &keys_gpio,
 };
 
 static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
-
        .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-
-       .phy_reset  = true,
-       .reset_gpio_port[0]  = -EINVAL,
-       .reset_gpio_port[1]  = 147,
-       .reset_gpio_port[2]  = -EINVAL
 };
 
 static void omap3_touchbook_poweroff(void)
@@ -368,6 +369,8 @@ static void __init omap3_touchbook_init(void)
        omap_ads7846_init(4, OMAP3_TS_GPIO, 310, &ads7846_pdata);
        usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
        usb_musb_init(NULL);
+
+       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
        usbhs_init(&usbhs_bdata);
        board_nand_init(omap3touchbook_nand_partitions,
                        ARRAY_SIZE(omap3touchbook_nand_partitions), NAND_CS,
index b02c2f00609b275ad50ae9cb91e9c15ad0ca6975..a71ad345f20d8129788244dcfebd0864e396bd88 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/ti_wilink_st.h>
 #include <linux/usb/musb.h>
 #include <linux/usb/phy.h>
+#include <linux/usb/nop-usb-xceiv.h>
 #include <linux/wl12xx.h>
 #include <linux/irqchip/arm-gic.h>
 #include <linux/platform_data/omap-abe-twl6040.h>
@@ -132,6 +133,22 @@ static struct platform_device btwilink_device = {
        .id     = -1,
 };
 
+/* PHY device on HS USB Port 1 i.e. nop_usb_xceiv.1 */
+static struct nop_usb_xceiv_platform_data hsusb1_phy_data = {
+       /* FREF_CLK3 provides the 19.2 MHz reference clock to the PHY */
+       .clk_rate = 19200000,
+};
+
+static struct usbhs_phy_data phy_data[] __initdata = {
+       {
+               .port = 1,
+               .reset_gpio = GPIO_HUB_NRESET,
+               .vcc_gpio = GPIO_HUB_POWER,
+               .vcc_polarity = 1,
+               .platform_data = &hsusb1_phy_data,
+       },
+};
+
 static struct platform_device *panda_devices[] __initdata = {
        &leds_gpio,
        &wl1271_device,
@@ -142,49 +159,19 @@ static struct platform_device *panda_devices[] __initdata = {
 
 static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
        .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-       .phy_reset  = false,
-       .reset_gpio_port[0]  = -EINVAL,
-       .reset_gpio_port[1]  = -EINVAL,
-       .reset_gpio_port[2]  = -EINVAL
-};
-
-static struct gpio panda_ehci_gpios[] __initdata = {
-       { GPIO_HUB_POWER,       GPIOF_OUT_INIT_LOW,  "hub_power"  },
-       { GPIO_HUB_NRESET,      GPIOF_OUT_INIT_LOW,  "hub_nreset" },
 };
 
 static void __init omap4_ehci_init(void)
 {
        int ret;
-       struct clk *phy_ref_clk;
 
        /* FREF_CLK3 provides the 19.2 MHz reference clock to the PHY */
-       phy_ref_clk = clk_get(NULL, "auxclk3_ck");
-       if (IS_ERR(phy_ref_clk)) {
-               pr_err("Cannot request auxclk3\n");
-               return;
-       }
-       clk_set_rate(phy_ref_clk, 19200000);
-       clk_prepare_enable(phy_ref_clk);
-
-       /* disable the power to the usb hub prior to init and reset phy+hub */
-       ret = gpio_request_array(panda_ehci_gpios,
-                                ARRAY_SIZE(panda_ehci_gpios));
-       if (ret) {
-               pr_err("Unable to initialize EHCI power/reset\n");
-               return;
-       }
-
-       gpio_export(GPIO_HUB_POWER, 0);
-       gpio_export(GPIO_HUB_NRESET, 0);
-       gpio_set_value(GPIO_HUB_NRESET, 1);
+       ret = clk_add_alias("main_clk", "nop_usb_xceiv.1", "auxclk3_ck", NULL);
+       if (ret)
+               pr_err("Failed to add main_clk alias to auxclk3_ck\n");
 
+       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
        usbhs_init(&usbhs_bdata);
-
-       /* enable power to hub */
-       gpio_set_value(GPIO_HUB_POWER, 1);
 }
 
 static struct omap_musb_board_data musb_board_data = {
index 86bab51154eefe66ba1808f38fa85cef0ceb41e6..ab79a4422bcc6301e63a2d10b5b835cb85ad306f 100644 (file)
@@ -458,14 +458,16 @@ static int __init overo_spi_init(void)
        return 0;
 }
 
+static struct usbhs_phy_data phy_data[] __initdata = {
+       {
+               .port = 2,
+               .reset_gpio = OVERO_GPIO_USBH_NRESET,
+               .vcc_gpio = -EINVAL,
+       },
+};
+
 static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
-       .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
-       .phy_reset  = true,
-       .reset_gpio_port[0]  = -EINVAL,
-       .reset_gpio_port[1]  = OVERO_GPIO_USBH_NRESET,
-       .reset_gpio_port[2]  = -EINVAL
 };
 
 #ifdef CONFIG_OMAP_MUX
@@ -502,6 +504,8 @@ static void __init overo_init(void)
                        ARRAY_SIZE(overo_nand_partitions), NAND_CS, 0, NULL);
        usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
        usb_musb_init(NULL);
+
+       usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
        usbhs_init(&usbhs_bdata);
        overo_spi_init();
        overo_init_smsc911x();
index f7c4616cbb60a7e90f45e1fdc8a686e3cd47857f..d2ea68ea678af901715aa609b4c5f41175641ddf 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/leds.h>
+#include <linux/usb/phy.h>
 #include <linux/usb/musb.h>
 #include <linux/platform_data/spi-omap2-mcspi.h>
 
@@ -98,6 +99,7 @@ static void __init rx51_init(void)
        sdrc_params = nokia_get_sdram_timings();
        omap_sdrc_init(sdrc_params, sdrc_params);
 
+       usb_bind_phy("musb-hdrc.0.auto", 0, "twl4030_usb");
        usb_musb_init(&musb_board_data);
        rx51_peripherals_init();
 
index 5e4d4c9fe61a4fd6c036e4447bb67d268ff82c8a..1a3dd865d8ebac8aca30ce309f2893eee5bb6462 100644 (file)
@@ -92,14 +92,16 @@ static struct mtd_partition zoom_nand_partitions[] = {
        },
 };
 
+static struct usbhs_phy_data phy_data[] __initdata = {
+       {
+               .port = 2,
+               .reset_gpio = ZOOM3_EHCI_RESET_GPIO,
+               .vcc_gpio = -EINVAL,
+       },
+};
+
 static struct usbhs_omap_platform_data usbhs_bdata __initdata = {
-       .port_mode[0]           = OMAP_USBHS_PORT_MODE_UNUSED,
        .port_mode[1]           = OMAP_EHCI_PORT_MODE_PHY,
-       .port_mode[2]           = OMAP_USBHS_PORT_MODE_UNUSED,
-       .phy_reset              = true,
-       .reset_gpio_port[0]     = -EINVAL,
-       .reset_gpio_port[1]     = ZOOM3_EHCI_RESET_GPIO,
-       .reset_gpio_port[2]     = -EINVAL,
 };
 
 static void __init omap_zoom_init(void)
@@ -109,6 +111,8 @@ static void __init omap_zoom_init(void)
        } else if (machine_is_omap_zoom3()) {
                omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
                omap_mux_init_gpio(ZOOM3_EHCI_RESET_GPIO, OMAP_PIN_OUTPUT);
+
+               usbhs_init_phys(phy_data, ARRAY_SIZE(phy_data));
                usbhs_init(&usbhs_bdata);
        }
 
index 476b82066cb6b27368e18155998ad85cff910240..7f091c85384e241f76bcd9ba585382cf29ba0824 100644 (file)
@@ -958,6 +958,14 @@ int __init am33xx_clk_init(void)
 
        clk_set_parent(&timer3_fck, &sys_clkin_ck);
        clk_set_parent(&timer6_fck, &sys_clkin_ck);
+       /*
+        * The On-Chip 32K RC Osc clock is not an accurate clock-source as per
+        * the design/spec, so as a result, for example, timer which supposed
+        * to get expired @60Sec, but will expire somewhere ~@40Sec, which is
+        * not expected by any use-case, so change WDT1 clock source to PRCM
+        * 32KHz clock.
+        */
+       clk_set_parent(&wdt1_fck, &clkdiv32k_ick);
 
        return 0;
 }
index 3d58f335f173fe4c3a9542590d43a98dbebedefb..0c6834ae1fc43a8ab20409dccd1bb24d7eeb20fd 100644 (file)
  */
 #define OMAP4_DPLL_ABE_DEFFREQ                         98304000
 
+/*
+ * OMAP4 USB DPLL default frequency. In OMAP4430 TRM version V, section
+ * "3.6.3.9.5 DPLL_USB Preferred Settings" shows that the preferred
+ * locked frequency for the USB DPLL is 960MHz.
+ */
+#define OMAP4_DPLL_USB_DEFFREQ                         960000000
+
 /* Root clocks */
 
 DEFINE_CLK_FIXED_RATE(extalt_clkin_ck, CLK_IS_ROOT, 59000000, 0x0);
@@ -1011,6 +1018,10 @@ DEFINE_CLK_OMAP_MUX(hsmmc2_fclk, "l3_init_clkdm", hsmmc1_fclk_sel,
                    OMAP4430_CM_L3INIT_MMC2_CLKCTRL, OMAP4430_CLKSEL_MASK,
                    hsmmc1_fclk_parents, func_dmic_abe_gfclk_ops);
 
+DEFINE_CLK_GATE(ocp2scp_usb_phy_phy_48m, "func_48m_fclk", &func_48m_fclk, 0x0,
+               OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
+               OMAP4430_OPTFCLKEN_PHY_48M_SHIFT, 0x0, NULL);
+
 DEFINE_CLK_GATE(sha2md5_fck, "l3_div_ck", &l3_div_ck, 0x0,
                OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL,
                OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
@@ -1538,6 +1549,7 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "per_mcbsp4_gfclk",                     &per_mcbsp4_gfclk,      CK_443X),
        CLK(NULL,       "hsmmc1_fclk",                  &hsmmc1_fclk,   CK_443X),
        CLK(NULL,       "hsmmc2_fclk",                  &hsmmc2_fclk,   CK_443X),
+       CLK(NULL,       "ocp2scp_usb_phy_phy_48m",      &ocp2scp_usb_phy_phy_48m,       CK_443X),
        CLK(NULL,       "sha2md5_fck",                  &sha2md5_fck,   CK_443X),
        CLK(NULL,       "slimbus1_fclk_1",              &slimbus1_fclk_1,       CK_443X),
        CLK(NULL,       "slimbus1_fclk_0",              &slimbus1_fclk_0,       CK_443X),
@@ -1705,5 +1717,13 @@ int __init omap4xxx_clk_init(void)
        if (rc)
                pr_err("%s: failed to configure ABE DPLL!\n", __func__);
 
+       /*
+        * Lock USB DPLL on OMAP4 devices so that the L3INIT power
+        * domain can transition to retention state when not in use.
+        */
+       rc = clk_set_rate(&dpll_usb_ck, OMAP4_DPLL_USB_DEFFREQ);
+       if (rc)
+               pr_err("%s: failed to configure USB DPLL!\n", __func__);
+
        return 0;
 }
index e4ec3a69ee2e749b1d40b80065956f23b4424070..2191f25ad21b6f18153034e9de15aad273d2174b 100644 (file)
@@ -596,7 +596,7 @@ int __init omap2_clk_switch_mpurate_at_boot(const char *mpurate_ck_name)
                return -ENOENT;
 
        r = clk_set_rate(mpurate_ck, mpurate);
-       if (IS_ERR_VALUE(r)) {
+       if (r < 0) {
                WARN(1, "clock: %s: unable to set MPU rate to %d: %d\n",
                     mpurate_ck_name, mpurate, r);
                clk_put(mpurate_ck);
index 0a6b9c7a63da494f6596f702cc3763fe1a25a3d2..272490e72ee01708b28685b382f42f6c75870d01 100644 (file)
@@ -82,8 +82,7 @@ extern void omap2_init_common_infrastructure(void);
 extern void omap2_sync32k_timer_init(void);
 extern void omap3_sync32k_timer_init(void);
 extern void omap3_secure_sync32k_timer_init(void);
-extern void omap3_gp_gptimer_timer_init(void);
-extern void omap3_am33xx_gptimer_timer_init(void);
+extern void omap3_gptimer_timer_init(void);
 extern void omap4_local_timer_init(void);
 extern void omap5_realtime_timer_init(void);
 
@@ -108,7 +107,6 @@ void omap35xx_init_late(void);
 void omap3630_init_late(void);
 void am35xx_init_late(void);
 void ti81xx_init_late(void);
-void omap4430_init_late(void);
 int omap2_common_pm_late_init(void);
 
 #if defined(CONFIG_SOC_OMAP2420) || defined(CONFIG_SOC_OMAP2430)
@@ -294,5 +292,8 @@ extern void omap_reserve(void);
 struct omap_hwmod;
 extern int omap_dss_reset(struct omap_hwmod *);
 
+/* SoC specific clock initializer */
+extern int (*omap_clk_init)(void);
+
 #endif /* __ASSEMBLER__ */
 #endif /* __ARCH_ARM_MACH_OMAP2PLUS_COMMON_H */
index 3aed4b0b95632dbdf244b7e6a8d6349840872d1e..3a0296cfcace879a322a6c414b4b9de9bb0cce62 100644 (file)
@@ -307,10 +307,10 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
        _omap3_noncore_dpll_bypass(clk);
 
        /*
-        * Set jitter correction. No jitter correction for OMAP4 and 3630
-        * since freqsel field is no longer present
+        * Set jitter correction. Jitter correction applicable for OMAP343X
+        * only since freqsel field is no longer present on other devices.
         */
-       if (!soc_is_am33xx() && !cpu_is_omap44xx() && !cpu_is_omap3630()) {
+       if (cpu_is_omap343x()) {
                v = __raw_readl(dd->control_reg);
                v &= ~dd->freqsel_mask;
                v |= freqsel << __ffs(dd->freqsel_mask);
@@ -480,29 +480,30 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
        if (!dd)
                return -EINVAL;
 
-       __clk_prepare(dd->clk_bypass);
-       clk_enable(dd->clk_bypass);
-       __clk_prepare(dd->clk_ref);
-       clk_enable(dd->clk_ref);
-
        if (__clk_get_rate(dd->clk_bypass) == rate &&
            (dd->modes & (1 << DPLL_LOW_POWER_BYPASS))) {
                pr_debug("%s: %s: set rate: entering bypass.\n",
                         __func__, __clk_get_name(hw->clk));
 
+               __clk_prepare(dd->clk_bypass);
+               clk_enable(dd->clk_bypass);
                ret = _omap3_noncore_dpll_bypass(clk);
                if (!ret)
                        new_parent = dd->clk_bypass;
+               clk_disable(dd->clk_bypass);
+               __clk_unprepare(dd->clk_bypass);
        } else {
+               __clk_prepare(dd->clk_ref);
+               clk_enable(dd->clk_ref);
+
                if (dd->last_rounded_rate != rate)
                        rate = __clk_round_rate(hw->clk, rate);
 
                if (dd->last_rounded_rate == 0)
                        return -EINVAL;
 
-               /* No freqsel on AM335x, OMAP4 and OMAP3630 */
-               if (!soc_is_am33xx() && !cpu_is_omap44xx() &&
-                   !cpu_is_omap3630()) {
+               /* Freqsel is available only on OMAP343X devices */
+               if (cpu_is_omap343x()) {
                        freqsel = _omap3_dpll_compute_freqsel(clk,
                                                dd->last_rounded_n);
                        WARN_ON(!freqsel);
@@ -514,6 +515,8 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
                ret = omap3_noncore_dpll_program(clk, freqsel);
                if (!ret)
                        new_parent = dd->clk_ref;
+               clk_disable(dd->clk_ref);
+               __clk_unprepare(dd->clk_ref);
        }
        /*
        * FIXME - this is all wrong.  common code handles reparenting and
@@ -525,11 +528,6 @@ int omap3_noncore_dpll_set_rate(struct clk_hw *hw, unsigned long rate,
        if (!ret)
                __clk_reparent(hw->clk, new_parent);
 
-       clk_disable(dd->clk_ref);
-       __clk_unprepare(dd->clk_ref);
-       clk_disable(dd->clk_bypass);
-       __clk_unprepare(dd->clk_bypass);
-
        return 0;
 }
 
index b155500e84a8e12dc5eeb6b6d3844d7b2fe6b122..b8208b4b1bd99882b178a095f02b1c64e4f3fa87 100644 (file)
@@ -26,7 +26,7 @@
 #include "control.h"
 #include "cm2xxx_3xxx.h"
 #include "prm2xxx_3xxx.h"
-#ifdef CONFIG_BRIDGE_DVFS
+#ifdef CONFIG_TIDSPBRIDGE_DVFS
 #include "omap-pm.h"
 #endif
 
@@ -35,7 +35,7 @@
 static struct platform_device *omap_dsp_pdev;
 
 static struct omap_dsp_platform_data omap_dsp_pdata __initdata = {
-#ifdef CONFIG_BRIDGE_DVFS
+#ifdef CONFIG_TIDSPBRIDGE_DVFS
        .dsp_set_min_opp = omap_pm_dsp_set_min_opp,
        .dsp_get_opp = omap_pm_dsp_get_opp,
        .cpu_set_freq = omap_pm_cpu_set_freq,
index afc1e8c32d6ccf8ced2372f6131300a8407ed1d7..d9c27195caf0ffa2d9ee38b17cc23067954d6a21 100644 (file)
@@ -74,14 +74,6 @@ static int omap2_nand_gpmc_retime(
        t.cs_wr_off = gpmc_t->cs_wr_off;
        t.wr_cycle = gpmc_t->wr_cycle;
 
-       /* Configure GPMC */
-       if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
-               gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
-       else
-               gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0);
-       gpmc_cs_configure(gpmc_nand_data->cs,
-                       GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND);
-       gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_WP, 0);
        err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
        if (err)
                return err;
@@ -115,14 +107,18 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
                   struct gpmc_timings *gpmc_t)
 {
        int err = 0;
+       struct gpmc_settings s;
        struct device *dev = &gpmc_nand_device.dev;
 
+       memset(&s, 0, sizeof(struct gpmc_settings));
+
        gpmc_nand_device.dev.platform_data = gpmc_nand_data;
 
        err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE,
                                (unsigned long *)&gpmc_nand_resource[0].start);
        if (err < 0) {
-               dev_err(dev, "Cannot request GPMC CS\n");
+               dev_err(dev, "Cannot request GPMC CS %d, error %d\n",
+                       gpmc_nand_data->cs, err);
                return err;
        }
 
@@ -140,11 +136,31 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
                        dev_err(dev, "Unable to set gpmc timings: %d\n", err);
                        return err;
                }
-       }
 
-       /* Enable RD PIN Monitoring Reg */
-       if (gpmc_nand_data->dev_ready) {
-               gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_RDY_BSY, 1);
+               if (gpmc_nand_data->of_node) {
+                       gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
+               } else {
+                       s.device_nand = true;
+
+                       /* Enable RD PIN Monitoring Reg */
+                       if (gpmc_nand_data->dev_ready) {
+                               s.wait_on_read = true;
+                               s.wait_on_write = true;
+                       }
+               }
+
+               if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
+                       s.device_width = GPMC_DEVWIDTH_16BIT;
+               else
+                       s.device_width = GPMC_DEVWIDTH_8BIT;
+
+               err = gpmc_cs_program_settings(gpmc_nand_data->cs, &s);
+               if (err < 0)
+                       goto out_free_cs;
+
+               err = gpmc_configure(GPMC_CONFIG_WP, 0);
+               if (err < 0)
+                       goto out_free_cs;
        }
 
        gpmc_update_nand_reg(&gpmc_nand_data->reg, gpmc_nand_data->cs);
index fadd87435cd02e8396ef7fea8ed16a5eabf8e116..64b5a83469822ad53693c2ae8ffdd3b227fa2a7b 100644 (file)
@@ -47,11 +47,23 @@ static struct platform_device gpmc_onenand_device = {
        .resource       = &gpmc_onenand_resource,
 };
 
-static struct gpmc_timings omap2_onenand_calc_async_timings(void)
+static struct gpmc_settings onenand_async = {
+       .device_width   = GPMC_DEVWIDTH_16BIT,
+       .mux_add_data   = GPMC_MUX_AD,
+};
+
+static struct gpmc_settings onenand_sync = {
+       .burst_read     = true,
+       .burst_wrap     = true,
+       .burst_len      = GPMC_BURST_16,
+       .device_width   = GPMC_DEVWIDTH_16BIT,
+       .mux_add_data   = GPMC_MUX_AD,
+       .wait_pin       = 0,
+};
+
+static void omap2_onenand_calc_async_timings(struct gpmc_timings *t)
 {
        struct gpmc_device_timings dev_t;
-       struct gpmc_timings t;
-
        const int t_cer = 15;
        const int t_avdp = 12;
        const int t_aavdh = 7;
@@ -64,7 +76,6 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void)
 
        memset(&dev_t, 0, sizeof(dev_t));
 
-       dev_t.mux = true;
        dev_t.t_avdp_r = max_t(int, t_avdp, t_cer) * 1000;
        dev_t.t_avdp_w = dev_t.t_avdp_r;
        dev_t.t_aavdh = t_aavdh * 1000;
@@ -76,19 +87,7 @@ static struct gpmc_timings omap2_onenand_calc_async_timings(void)
        dev_t.t_wpl = t_wpl * 1000;
        dev_t.t_wph = t_wph * 1000;
 
-       gpmc_calc_timings(&t, &dev_t);
-
-       return t;
-}
-
-static int gpmc_set_async_mode(int cs, struct gpmc_timings *t)
-{
-       /* Configure GPMC for asynchronous read */
-       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
-                         GPMC_CONFIG1_DEVICESIZE_16 |
-                         GPMC_CONFIG1_MUXADDDATA);
-
-       return gpmc_cs_set_timings(cs, t);
+       gpmc_calc_timings(t, &onenand_async, &dev_t);
 }
 
 static void omap2_onenand_set_async_mode(void __iomem *onenand_base)
@@ -158,12 +157,11 @@ static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
        return freq;
 }
 
-static struct gpmc_timings
-omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
-                               int freq)
+static void omap2_onenand_calc_sync_timings(struct gpmc_timings *t,
+                                           unsigned int flags,
+                                           int freq)
 {
        struct gpmc_device_timings dev_t;
-       struct gpmc_timings t;
        const int t_cer  = 15;
        const int t_avdp = 12;
        const int t_cez  = 20; /* max of t_cez, t_oez */
@@ -172,9 +170,9 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
        int min_gpmc_clk_period, t_ces, t_avds, t_avdh, t_ach, t_aavdh, t_rdyo;
        int div, gpmc_clk_ns;
 
-       if (cfg->flags & ONENAND_SYNC_READ)
+       if (flags & ONENAND_SYNC_READ)
                onenand_flags = ONENAND_FLAG_SYNCREAD;
-       else if (cfg->flags & ONENAND_SYNC_READWRITE)
+       else if (flags & ONENAND_SYNC_READWRITE)
                onenand_flags = ONENAND_FLAG_SYNCREAD | ONENAND_FLAG_SYNCWRITE;
 
        switch (freq) {
@@ -239,10 +237,11 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
        /* Set synchronous read timings */
        memset(&dev_t, 0, sizeof(dev_t));
 
-       dev_t.mux = true;
-       dev_t.sync_read = true;
+       if (onenand_flags & ONENAND_FLAG_SYNCREAD)
+               onenand_sync.sync_read = true;
        if (onenand_flags & ONENAND_FLAG_SYNCWRITE) {
-               dev_t.sync_write = true;
+               onenand_sync.sync_write = true;
+               onenand_sync.burst_write = true;
        } else {
                dev_t.t_avdp_w = max(t_avdp, t_cer) * 1000;
                dev_t.t_wpl = t_wpl * 1000;
@@ -265,32 +264,7 @@ omap2_onenand_calc_sync_timings(struct omap_onenand_platform_data *cfg,
        dev_t.cyc_aavdh_oe = 1;
        dev_t.t_rdyo = t_rdyo * 1000 + min_gpmc_clk_period;
 
-       gpmc_calc_timings(&t, &dev_t);
-
-       return t;
-}
-
-static int gpmc_set_sync_mode(int cs, struct gpmc_timings *t)
-{
-       unsigned sync_read = onenand_flags & ONENAND_FLAG_SYNCREAD;
-       unsigned sync_write = onenand_flags & ONENAND_FLAG_SYNCWRITE;
-
-       /* Configure GPMC for synchronous read */
-       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1,
-                         GPMC_CONFIG1_WRAPBURST_SUPP |
-                         GPMC_CONFIG1_READMULTIPLE_SUPP |
-                         (sync_read ? GPMC_CONFIG1_READTYPE_SYNC : 0) |
-                         (sync_write ? GPMC_CONFIG1_WRITEMULTIPLE_SUPP : 0) |
-                         (sync_write ? GPMC_CONFIG1_WRITETYPE_SYNC : 0) |
-                         GPMC_CONFIG1_PAGE_LEN(2) |
-                         (cpu_is_omap34xx() ? 0 :
-                               (GPMC_CONFIG1_WAIT_READ_MON |
-                                GPMC_CONFIG1_WAIT_PIN_SEL(0))) |
-                         GPMC_CONFIG1_DEVICESIZE_16 |
-                         GPMC_CONFIG1_DEVICETYPE_NOR |
-                         GPMC_CONFIG1_MUXADDDATA);
-
-       return gpmc_cs_set_timings(cs, t);
+       gpmc_calc_timings(t, &onenand_sync, &dev_t);
 }
 
 static int omap2_onenand_setup_async(void __iomem *onenand_base)
@@ -298,12 +272,20 @@ static int omap2_onenand_setup_async(void __iomem *onenand_base)
        struct gpmc_timings t;
        int ret;
 
+       if (gpmc_onenand_data->of_node)
+               gpmc_read_settings_dt(gpmc_onenand_data->of_node,
+                                     &onenand_async);
+
        omap2_onenand_set_async_mode(onenand_base);
 
-       t = omap2_onenand_calc_async_timings();
+       omap2_onenand_calc_async_timings(&t);
+
+       ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_async);
+       if (ret < 0)
+               return ret;
 
-       ret = gpmc_set_async_mode(gpmc_onenand_data->cs, &t);
-       if (IS_ERR_VALUE(ret))
+       ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
+       if (ret < 0)
                return ret;
 
        omap2_onenand_set_async_mode(onenand_base);
@@ -322,10 +304,26 @@ static int omap2_onenand_setup_sync(void __iomem *onenand_base, int *freq_ptr)
                set_onenand_cfg(onenand_base);
        }
 
-       t = omap2_onenand_calc_sync_timings(gpmc_onenand_data, freq);
+       if (gpmc_onenand_data->of_node) {
+               gpmc_read_settings_dt(gpmc_onenand_data->of_node,
+                                     &onenand_sync);
+       } else {
+               /*
+                * FIXME: Appears to be legacy code from initial ONENAND commit.
+                * Unclear what boards this is for and if this can be removed.
+                */
+               if (!cpu_is_omap34xx())
+                       onenand_sync.wait_on_read = true;
+       }
+
+       omap2_onenand_calc_sync_timings(&t, gpmc_onenand_data->flags, freq);
 
-       ret = gpmc_set_sync_mode(gpmc_onenand_data->cs, &t);
-       if (IS_ERR_VALUE(ret))
+       ret = gpmc_cs_program_settings(gpmc_onenand_data->cs, &onenand_sync);
+       if (ret < 0)
+               return ret;
+
+       ret = gpmc_cs_set_timings(gpmc_onenand_data->cs, &t);
+       if (ret < 0)
                return ret;
 
        set_onenand_cfg(onenand_base);
@@ -359,6 +357,7 @@ static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
 void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 {
        int err;
+       struct device *dev = &gpmc_onenand_device.dev;
 
        gpmc_onenand_data = _onenand_data;
        gpmc_onenand_data->onenand_setup = gpmc_onenand_setup;
@@ -366,7 +365,7 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
 
        if (cpu_is_omap24xx() &&
                        (gpmc_onenand_data->flags & ONENAND_SYNC_READWRITE)) {
-               printk(KERN_ERR "Onenand using only SYNC_READ on 24xx\n");
+               dev_warn(dev, "OneNAND using only SYNC_READ on 24xx\n");
                gpmc_onenand_data->flags &= ~ONENAND_SYNC_READWRITE;
                gpmc_onenand_data->flags |= ONENAND_SYNC_READ;
        }
@@ -379,7 +378,8 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
        err = gpmc_cs_request(gpmc_onenand_data->cs, ONENAND_IO_SIZE,
                                (unsigned long *)&gpmc_onenand_resource.start);
        if (err < 0) {
-               pr_err("%s: Cannot request GPMC CS\n", __func__);
+               dev_err(dev, "Cannot request GPMC CS %d, error %d\n",
+                       gpmc_onenand_data->cs, err);
                return;
        }
 
@@ -387,7 +387,7 @@ void gpmc_onenand_init(struct omap_onenand_platform_data *_onenand_data)
                                                        ONENAND_IO_SIZE - 1;
 
        if (platform_device_register(&gpmc_onenand_device) < 0) {
-               pr_err("%s: Unable to register OneNAND device\n", __func__);
+               dev_err(dev, "Unable to register OneNAND device\n");
                gpmc_cs_free(gpmc_onenand_data->cs);
                return;
        }
index 11d0b756f09897be435075302392131a35aa686b..61a063595e66fb1c2d01bca46c561873aa2fd643 100644 (file)
@@ -49,6 +49,10 @@ static struct platform_device gpmc_smc91x_device = {
        .resource       = gpmc_smc91x_resources,
 };
 
+static struct gpmc_settings smc91x_settings = {
+       .device_width = GPMC_DEVWIDTH_16BIT,
+};
+
 /*
  * Set the gpmc timings for smc91c96. The timings are taken
  * from the data sheet available at:
@@ -67,18 +71,6 @@ static int smc91c96_gpmc_retime(void)
        const int t7 = 5;       /* Figure 12.4 write */
        const int t8 = 5;       /* Figure 12.4 write */
        const int t20 = 185;    /* Figure 12.2 read and 12.4 write */
-       u32 l;
-
-       l = GPMC_CONFIG1_DEVICESIZE_16;
-       if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
-               l |= GPMC_CONFIG1_MUXADDDATA;
-       if (gpmc_cfg->flags & GPMC_READ_MON)
-               l |= GPMC_CONFIG1_WAIT_READ_MON;
-       if (gpmc_cfg->flags & GPMC_WRITE_MON)
-               l |= GPMC_CONFIG1_WAIT_WRITE_MON;
-       if (gpmc_cfg->wait_pin)
-               l |= GPMC_CONFIG1_WAIT_PIN_SEL(gpmc_cfg->wait_pin);
-       gpmc_cs_write_reg(gpmc_cfg->cs, GPMC_CS_CONFIG1, l);
 
        /*
         * FIXME: Calculate the address and data bus muxed timings.
@@ -104,7 +96,7 @@ static int smc91c96_gpmc_retime(void)
        dev_t.t_cez_w = t4_w * 1000;
        dev_t.t_wr_cycle = (t20 - t3) * 1000;
 
-       gpmc_calc_timings(&t, &dev_t);
+       gpmc_calc_timings(&t, &smc91x_settings, &dev_t);
 
        return gpmc_cs_set_timings(gpmc_cfg->cs, &t);
 }
@@ -133,6 +125,18 @@ void __init gpmc_smc91x_init(struct omap_smc91x_platform_data *board_data)
        gpmc_smc91x_resources[0].end = cs_mem_base + 0x30f;
        gpmc_smc91x_resources[1].flags |= (gpmc_cfg->flags & IRQF_TRIGGER_MASK);
 
+       if (gpmc_cfg->flags & GPMC_MUX_ADD_DATA)
+               smc91x_settings.mux_add_data = GPMC_MUX_AD;
+       if (gpmc_cfg->flags & GPMC_READ_MON)
+               smc91x_settings.wait_on_read = true;
+       if (gpmc_cfg->flags & GPMC_WRITE_MON)
+               smc91x_settings.wait_on_write = true;
+       if (gpmc_cfg->wait_pin)
+               smc91x_settings.wait_pin = gpmc_cfg->wait_pin;
+       ret = gpmc_cs_program_settings(gpmc_cfg->cs, &smc91x_settings);
+       if (ret < 0)
+               goto free1;
+
        if (gpmc_cfg->retime) {
                ret = gpmc_cfg->retime();
                if (ret != 0)
index e4b16c8efe8b05d8296f6431f253f1dd5e0e49be..ed946df5ad8a6acd75bb9010843eac90b3d4480c 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 #include <linux/of_mtd.h>
 #include <linux/of_device.h>
 #include <linux/mtd/nand.h>
@@ -91,9 +92,7 @@
 #define GPMC_CS_SIZE           0x30
 #define        GPMC_BCH_SIZE           0x10
 
-#define GPMC_MEM_START         0x00000000
 #define GPMC_MEM_END           0x3FFFFFFF
-#define BOOT_ROM_SPACE         0x100000        /* 1MB */
 
 #define GPMC_CHUNK_SHIFT       24              /* 16 MB */
 #define GPMC_SECTION_SHIFT     28              /* 128 MB */
 
 #define        GPMC_HAS_WR_ACCESS              0x1
 #define        GPMC_HAS_WR_DATA_MUX_BUS        0x2
+#define        GPMC_HAS_MUX_AAD                0x4
+
+#define GPMC_NR_WAITPINS               4
 
 /* XXX: Only NAND irq has been considered,currently these are the only ones used
  */
@@ -153,6 +155,7 @@ static struct resource      gpmc_cs_mem[GPMC_CS_NUM];
 static DEFINE_SPINLOCK(gpmc_mem_lock);
 /* Define chip-selects as reserved by default until probe completes */
 static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1);
+static unsigned int gpmc_nr_waitpins;
 static struct device *gpmc_dev;
 static int gpmc_irq;
 static resource_size_t phys_base, mem_size;
@@ -181,7 +184,7 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val)
        __raw_writel(val, reg_addr);
 }
 
-u32 gpmc_cs_read_reg(int cs, int idx)
+static u32 gpmc_cs_read_reg(int cs, int idx)
 {
        void __iomem *reg_addr;
 
@@ -190,7 +193,7 @@ u32 gpmc_cs_read_reg(int cs, int idx)
 }
 
 /* TODO: Add support for gpmc_fck to clock framework and use it */
-unsigned long gpmc_get_fclk_period(void)
+static unsigned long gpmc_get_fclk_period(void)
 {
        unsigned long rate = clk_get_rate(gpmc_l3_clk);
 
@@ -205,7 +208,7 @@ unsigned long gpmc_get_fclk_period(void)
        return rate;
 }
 
-unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
+static unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
 {
        unsigned long tick_ps;
 
@@ -215,7 +218,7 @@ unsigned int gpmc_ns_to_ticks(unsigned int time_ns)
        return (time_ns * 1000 + tick_ps - 1) / tick_ps;
 }
 
-unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
+static unsigned int gpmc_ps_to_ticks(unsigned int time_ps)
 {
        unsigned long tick_ps;
 
@@ -230,13 +233,6 @@ unsigned int gpmc_ticks_to_ns(unsigned int ticks)
        return ticks * gpmc_get_fclk_period() / 1000;
 }
 
-unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns)
-{
-       unsigned long ticks = gpmc_ns_to_ticks(time_ns);
-
-       return ticks * gpmc_get_fclk_period() / 1000;
-}
-
 static unsigned int gpmc_ticks_to_ps(unsigned int ticks)
 {
        return ticks * gpmc_get_fclk_period();
@@ -405,11 +401,18 @@ int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t)
        return 0;
 }
 
-static void gpmc_cs_enable_mem(int cs, u32 base, u32 size)
+static int gpmc_cs_enable_mem(int cs, u32 base, u32 size)
 {
        u32 l;
        u32 mask;
 
+       /*
+        * Ensure that base address is aligned on a
+        * boundary equal to or greater than size.
+        */
+       if (base & (size - 1))
+               return -EINVAL;
+
        mask = (1 << GPMC_SECTION_SHIFT) - size;
        l = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG7);
        l &= ~0x3f;
@@ -418,6 +421,8 @@ static void gpmc_cs_enable_mem(int cs, u32 base, u32 size)
        l |= ((mask >> GPMC_CHUNK_SHIFT) & 0x0f) << 8;
        l |= GPMC_CONFIG7_CSVALID;
        gpmc_cs_write_reg(cs, GPMC_CS_CONFIG7, l);
+
+       return 0;
 }
 
 static void gpmc_cs_disable_mem(int cs)
@@ -448,22 +453,14 @@ static int gpmc_cs_mem_enabled(int cs)
        return l & GPMC_CONFIG7_CSVALID;
 }
 
-int gpmc_cs_set_reserved(int cs, int reserved)
+static void gpmc_cs_set_reserved(int cs, int reserved)
 {
-       if (cs > GPMC_CS_NUM)
-               return -ENODEV;
-
        gpmc_cs_map &= ~(1 << cs);
        gpmc_cs_map |= (reserved ? 1 : 0) << cs;
-
-       return 0;
 }
 
-int gpmc_cs_reserved(int cs)
+static bool gpmc_cs_reserved(int cs)
 {
-       if (cs > GPMC_CS_NUM)
-               return -ENODEV;
-
        return gpmc_cs_map & (1 << cs);
 }
 
@@ -510,6 +507,39 @@ static int gpmc_cs_delete_mem(int cs)
        return r;
 }
 
+/**
+ * gpmc_cs_remap - remaps a chip-select physical base address
+ * @cs:                chip-select to remap
+ * @base:      physical base address to re-map chip-select to
+ *
+ * Re-maps a chip-select to a new physical base address specified by
+ * "base". Returns 0 on success and appropriate negative error code
+ * on failure.
+ */
+static int gpmc_cs_remap(int cs, u32 base)
+{
+       int ret;
+       u32 old_base, size;
+
+       if (cs > GPMC_CS_NUM)
+               return -ENODEV;
+       gpmc_cs_get_memconf(cs, &old_base, &size);
+       if (base == old_base)
+               return 0;
+       gpmc_cs_disable_mem(cs);
+       ret = gpmc_cs_delete_mem(cs);
+       if (ret < 0)
+               return ret;
+       ret = gpmc_cs_insert_mem(cs, base, size);
+       if (ret < 0)
+               return ret;
+       ret = gpmc_cs_enable_mem(cs, base, size);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
 int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
 {
        struct resource *res = &gpmc_cs_mem[cs];
@@ -535,7 +565,12 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
        if (r < 0)
                goto out;
 
-       gpmc_cs_enable_mem(cs, res->start, resource_size(res));
+       r = gpmc_cs_enable_mem(cs, res->start, resource_size(res));
+       if (r < 0) {
+               release_resource(res);
+               goto out;
+       }
+
        *base = res->start;
        gpmc_cs_set_reserved(cs, 1);
 out:
@@ -561,16 +596,14 @@ void gpmc_cs_free(int cs)
 EXPORT_SYMBOL(gpmc_cs_free);
 
 /**
- * gpmc_cs_configure - write request to configure gpmc
- * @cs: chip select number
+ * gpmc_configure - write request to configure gpmc
  * @cmd: command type
  * @wval: value to write
  * @return status of the operation
  */
-int gpmc_cs_configure(int cs, int cmd, int wval)
+int gpmc_configure(int cmd, int wval)
 {
-       int err = 0;
-       u32 regval = 0;
+       u32 regval;
 
        switch (cmd) {
        case GPMC_ENABLE_IRQ:
@@ -590,43 +623,14 @@ int gpmc_cs_configure(int cs, int cmd, int wval)
                gpmc_write_reg(GPMC_CONFIG, regval);
                break;
 
-       case GPMC_CONFIG_RDY_BSY:
-               regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-               if (wval)
-                       regval |= WR_RD_PIN_MONITORING;
-               else
-                       regval &= ~WR_RD_PIN_MONITORING;
-               gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
-               break;
-
-       case GPMC_CONFIG_DEV_SIZE:
-               regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-
-               /* clear 2 target bits */
-               regval &= ~GPMC_CONFIG1_DEVICESIZE(3);
-
-               /* set the proper value */
-               regval |= GPMC_CONFIG1_DEVICESIZE(wval);
-
-               gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
-               break;
-
-       case GPMC_CONFIG_DEV_TYPE:
-               regval  = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1);
-               regval |= GPMC_CONFIG1_DEVICETYPE(wval);
-               if (wval == GPMC_DEVICETYPE_NOR)
-                       regval |= GPMC_CONFIG1_MUXADDDATA;
-               gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval);
-               break;
-
        default:
-               printk(KERN_ERR "gpmc_configure_cs: Not supported\n");
-               err = -EINVAL;
+               pr_err("%s: command not supported\n", __func__);
+               return -EINVAL;
        }
 
-       return err;
+       return 0;
 }
-EXPORT_SYMBOL(gpmc_cs_configure);
+EXPORT_SYMBOL(gpmc_configure);
 
 void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs)
 {
@@ -716,7 +720,7 @@ static int gpmc_setup_irq(void)
                return -EINVAL;
 
        gpmc_irq_start = irq_alloc_descs(-1, 0, GPMC_NR_IRQ, 0);
-       if (IS_ERR_VALUE(gpmc_irq_start)) {
+       if (gpmc_irq_start < 0) {
                pr_err("irq_alloc_descs failed\n");
                return gpmc_irq_start;
        }
@@ -781,16 +785,16 @@ static void gpmc_mem_exit(void)
 
 }
 
-static int gpmc_mem_init(void)
+static void gpmc_mem_init(void)
 {
-       int cs, rc;
-       unsigned long boot_rom_space = 0;
+       int cs;
 
-       /* never allocate the first page, to facilitate bug detection;
-        * even if we didn't boot from ROM.
+       /*
+        * The first 1MB of GPMC address space is typically mapped to
+        * the internal ROM. Never allocate the first page, to
+        * facilitate bug detection; even if we didn't boot from ROM.
         */
-       boot_rom_space = BOOT_ROM_SPACE;
-       gpmc_mem_root.start = GPMC_MEM_START + boot_rom_space;
+       gpmc_mem_root.start = SZ_1M;
        gpmc_mem_root.end = GPMC_MEM_END;
 
        /* Reserve all regions that has been set up by bootloader */
@@ -800,16 +804,12 @@ static int gpmc_mem_init(void)
                if (!gpmc_cs_mem_enabled(cs))
                        continue;
                gpmc_cs_get_memconf(cs, &base, &size);
-               rc = gpmc_cs_insert_mem(cs, base, size);
-               if (IS_ERR_VALUE(rc)) {
-                       while (--cs >= 0)
-                               if (gpmc_cs_mem_enabled(cs))
-                                       gpmc_cs_delete_mem(cs);
-                       return rc;
+               if (gpmc_cs_insert_mem(cs, base, size)) {
+                       pr_warn("%s: disabling cs %d mapped at 0x%x-0x%x\n",
+                               __func__, cs, base, base + size);
+                       gpmc_cs_disable_mem(cs);
                }
        }
-
-       return 0;
 }
 
 static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk)
@@ -825,9 +825,9 @@ static u32 gpmc_round_ps_to_sync_clk(u32 time_ps, u32 sync_clk)
 
 /* XXX: can the cycles be avoided ? */
 static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
-                               struct gpmc_device_timings *dev_t)
+                                      struct gpmc_device_timings *dev_t,
+                                      bool mux)
 {
-       bool mux = dev_t->mux;
        u32 temp;
 
        /* adv_rd_off */
@@ -880,9 +880,9 @@ static int gpmc_calc_sync_read_timings(struct gpmc_timings *gpmc_t,
 }
 
 static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
-                               struct gpmc_device_timings *dev_t)
+                                       struct gpmc_device_timings *dev_t,
+                                       bool mux)
 {
-       bool mux = dev_t->mux;
        u32 temp;
 
        /* adv_wr_off */
@@ -942,9 +942,9 @@ static int gpmc_calc_sync_write_timings(struct gpmc_timings *gpmc_t,
 }
 
 static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
-                               struct gpmc_device_timings *dev_t)
+                                       struct gpmc_device_timings *dev_t,
+                                       bool mux)
 {
-       bool mux = dev_t->mux;
        u32 temp;
 
        /* adv_rd_off */
@@ -982,9 +982,9 @@ static int gpmc_calc_async_read_timings(struct gpmc_timings *gpmc_t,
 }
 
 static int gpmc_calc_async_write_timings(struct gpmc_timings *gpmc_t,
-                               struct gpmc_device_timings *dev_t)
+                                        struct gpmc_device_timings *dev_t,
+                                        bool mux)
 {
-       bool mux = dev_t->mux;
        u32 temp;
 
        /* adv_wr_off */
@@ -1054,7 +1054,8 @@ static int gpmc_calc_sync_common_timings(struct gpmc_timings *gpmc_t,
 }
 
 static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
-                       struct gpmc_device_timings *dev_t)
+                                   struct gpmc_device_timings *dev_t,
+                                   bool sync)
 {
        u32 temp;
 
@@ -1068,7 +1069,7 @@ static int gpmc_calc_common_timings(struct gpmc_timings *gpmc_t,
                                gpmc_t->cs_on + dev_t->t_ce_avd);
        gpmc_t->adv_on = gpmc_round_ps_to_ticks(temp);
 
-       if (dev_t->sync_write || dev_t->sync_read)
+       if (sync)
                gpmc_calc_sync_common_timings(gpmc_t, dev_t);
 
        return 0;
@@ -1103,27 +1104,116 @@ static void gpmc_convert_ps_to_ns(struct gpmc_timings *t)
 }
 
 int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
-                       struct gpmc_device_timings *dev_t)
+                     struct gpmc_settings *gpmc_s,
+                     struct gpmc_device_timings *dev_t)
 {
+       bool mux = false, sync = false;
+
+       if (gpmc_s) {
+               mux = gpmc_s->mux_add_data ? true : false;
+               sync = (gpmc_s->sync_read || gpmc_s->sync_write);
+       }
+
        memset(gpmc_t, 0, sizeof(*gpmc_t));
 
-       gpmc_calc_common_timings(gpmc_t, dev_t);
+       gpmc_calc_common_timings(gpmc_t, dev_t, sync);
 
-       if (dev_t->sync_read)
-               gpmc_calc_sync_read_timings(gpmc_t, dev_t);
+       if (gpmc_s && gpmc_s->sync_read)
+               gpmc_calc_sync_read_timings(gpmc_t, dev_t, mux);
        else
-               gpmc_calc_async_read_timings(gpmc_t, dev_t);
+               gpmc_calc_async_read_timings(gpmc_t, dev_t, mux);
 
-       if (dev_t->sync_write)
-               gpmc_calc_sync_write_timings(gpmc_t, dev_t);
+       if (gpmc_s && gpmc_s->sync_write)
+               gpmc_calc_sync_write_timings(gpmc_t, dev_t, mux);
        else
-               gpmc_calc_async_write_timings(gpmc_t, dev_t);
+               gpmc_calc_async_write_timings(gpmc_t, dev_t, mux);
 
        /* TODO: remove, see function definition */
        gpmc_convert_ps_to_ns(gpmc_t);
 
-       /* Now the GPMC is initialised, unreserve the chip-selects */
-       gpmc_cs_map = 0;
+       return 0;
+}
+
+/**
+ * gpmc_cs_program_settings - programs non-timing related settings
+ * @cs:                GPMC chip-select to program
+ * @p:         pointer to GPMC settings structure
+ *
+ * Programs non-timing related settings for a GPMC chip-select, such as
+ * bus-width, burst configuration, etc. Function should be called once
+ * for each chip-select that is being used and must be called before
+ * calling gpmc_cs_set_timings() as timing parameters in the CONFIG1
+ * register will be initialised to zero by this function. Returns 0 on
+ * success and appropriate negative error code on failure.
+ */
+int gpmc_cs_program_settings(int cs, struct gpmc_settings *p)
+{
+       u32 config1;
+
+       if ((!p->device_width) || (p->device_width > GPMC_DEVWIDTH_16BIT)) {
+               pr_err("%s: invalid width %d!", __func__, p->device_width);
+               return -EINVAL;
+       }
+
+       /* Address-data multiplexing not supported for NAND devices */
+       if (p->device_nand && p->mux_add_data) {
+               pr_err("%s: invalid configuration!\n", __func__);
+               return -EINVAL;
+       }
+
+       if ((p->mux_add_data > GPMC_MUX_AD) ||
+           ((p->mux_add_data == GPMC_MUX_AAD) &&
+            !(gpmc_capability & GPMC_HAS_MUX_AAD))) {
+               pr_err("%s: invalid multiplex configuration!\n", __func__);
+               return -EINVAL;
+       }
+
+       /* Page/burst mode supports lengths of 4, 8 and 16 bytes */
+       if (p->burst_read || p->burst_write) {
+               switch (p->burst_len) {
+               case GPMC_BURST_4:
+               case GPMC_BURST_8:
+               case GPMC_BURST_16:
+                       break;
+               default:
+                       pr_err("%s: invalid page/burst-length (%d)\n",
+                              __func__, p->burst_len);
+                       return -EINVAL;
+               }
+       }
+
+       if ((p->wait_on_read || p->wait_on_write) &&
+           (p->wait_pin > gpmc_nr_waitpins)) {
+               pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
+               return -EINVAL;
+       }
+
+       config1 = GPMC_CONFIG1_DEVICESIZE((p->device_width - 1));
+
+       if (p->sync_read)
+               config1 |= GPMC_CONFIG1_READTYPE_SYNC;
+       if (p->sync_write)
+               config1 |= GPMC_CONFIG1_WRITETYPE_SYNC;
+       if (p->wait_on_read)
+               config1 |= GPMC_CONFIG1_WAIT_READ_MON;
+       if (p->wait_on_write)
+               config1 |= GPMC_CONFIG1_WAIT_WRITE_MON;
+       if (p->wait_on_read || p->wait_on_write)
+               config1 |= GPMC_CONFIG1_WAIT_PIN_SEL(p->wait_pin);
+       if (p->device_nand)
+               config1 |= GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NAND);
+       if (p->mux_add_data)
+               config1 |= GPMC_CONFIG1_MUXTYPE(p->mux_add_data);
+       if (p->burst_read)
+               config1 |= GPMC_CONFIG1_READMULTIPLE_SUPP;
+       if (p->burst_write)
+               config1 |= GPMC_CONFIG1_WRITEMULTIPLE_SUPP;
+       if (p->burst_read || p->burst_write) {
+               config1 |= GPMC_CONFIG1_PAGE_LEN(p->burst_len >> 3);
+               config1 |= p->burst_wrap ? GPMC_CONFIG1_WRAPBURST_SUPP : 0;
+       }
+
+       gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, config1);
 
        return 0;
 }
@@ -1139,70 +1229,110 @@ static struct of_device_id gpmc_dt_ids[] = {
 };
 MODULE_DEVICE_TABLE(of, gpmc_dt_ids);
 
+/**
+ * gpmc_read_settings_dt - read gpmc settings from device-tree
+ * @np:                pointer to device-tree node for a gpmc child device
+ * @p:         pointer to gpmc settings structure
+ *
+ * Reads the GPMC settings for a GPMC child device from device-tree and
+ * stores them in the GPMC settings structure passed. The GPMC settings
+ * structure is initialised to zero by this function and so any
+ * previously stored settings will be cleared.
+ */
+void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p)
+{
+       memset(p, 0, sizeof(struct gpmc_settings));
+
+       p->sync_read = of_property_read_bool(np, "gpmc,sync-read");
+       p->sync_write = of_property_read_bool(np, "gpmc,sync-write");
+       p->device_nand = of_property_read_bool(np, "gpmc,device-nand");
+       of_property_read_u32(np, "gpmc,device-width", &p->device_width);
+       of_property_read_u32(np, "gpmc,mux-add-data", &p->mux_add_data);
+
+       if (!of_property_read_u32(np, "gpmc,burst-length", &p->burst_len)) {
+               p->burst_wrap = of_property_read_bool(np, "gpmc,burst-wrap");
+               p->burst_read = of_property_read_bool(np, "gpmc,burst-read");
+               p->burst_write = of_property_read_bool(np, "gpmc,burst-write");
+               if (!p->burst_read && !p->burst_write)
+                       pr_warn("%s: page/burst-length set but not used!\n",
+                               __func__);
+       }
+
+       if (!of_property_read_u32(np, "gpmc,wait-pin", &p->wait_pin)) {
+               p->wait_on_read = of_property_read_bool(np,
+                                                       "gpmc,wait-on-read");
+               p->wait_on_write = of_property_read_bool(np,
+                                                        "gpmc,wait-on-write");
+               if (!p->wait_on_read && !p->wait_on_write)
+                       pr_warn("%s: read/write wait monitoring not enabled!\n",
+                               __func__);
+       }
+}
+
 static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
                                                struct gpmc_timings *gpmc_t)
 {
-       u32 val;
+       struct gpmc_bool_timings *p;
+
+       if (!np || !gpmc_t)
+               return;
 
        memset(gpmc_t, 0, sizeof(*gpmc_t));
 
        /* minimum clock period for syncronous mode */
-       if (!of_property_read_u32(np, "gpmc,sync-clk", &val))
-               gpmc_t->sync_clk = val;
+       of_property_read_u32(np, "gpmc,sync-clk-ps", &gpmc_t->sync_clk);
 
        /* chip select timtings */
-       if (!of_property_read_u32(np, "gpmc,cs-on", &val))
-               gpmc_t->cs_on = val;
-
-       if (!of_property_read_u32(np, "gpmc,cs-rd-off", &val))
-               gpmc_t->cs_rd_off = val;
-
-       if (!of_property_read_u32(np, "gpmc,cs-wr-off", &val))
-               gpmc_t->cs_wr_off = val;
+       of_property_read_u32(np, "gpmc,cs-on-ns", &gpmc_t->cs_on);
+       of_property_read_u32(np, "gpmc,cs-rd-off-ns", &gpmc_t->cs_rd_off);
+       of_property_read_u32(np, "gpmc,cs-wr-off-ns", &gpmc_t->cs_wr_off);
 
        /* ADV signal timings */
-       if (!of_property_read_u32(np, "gpmc,adv-on", &val))
-               gpmc_t->adv_on = val;
-
-       if (!of_property_read_u32(np, "gpmc,adv-rd-off", &val))
-               gpmc_t->adv_rd_off = val;
-
-       if (!of_property_read_u32(np, "gpmc,adv-wr-off", &val))
-               gpmc_t->adv_wr_off = val;
+       of_property_read_u32(np, "gpmc,adv-on-ns", &gpmc_t->adv_on);
+       of_property_read_u32(np, "gpmc,adv-rd-off-ns", &gpmc_t->adv_rd_off);
+       of_property_read_u32(np, "gpmc,adv-wr-off-ns", &gpmc_t->adv_wr_off);
 
        /* WE signal timings */
-       if (!of_property_read_u32(np, "gpmc,we-on", &val))
-               gpmc_t->we_on = val;
-
-       if (!of_property_read_u32(np, "gpmc,we-off", &val))
-               gpmc_t->we_off = val;
+       of_property_read_u32(np, "gpmc,we-on-ns", &gpmc_t->we_on);
+       of_property_read_u32(np, "gpmc,we-off-ns", &gpmc_t->we_off);
 
        /* OE signal timings */
-       if (!of_property_read_u32(np, "gpmc,oe-on", &val))
-               gpmc_t->oe_on = val;
-
-       if (!of_property_read_u32(np, "gpmc,oe-off", &val))
-               gpmc_t->oe_off = val;
+       of_property_read_u32(np, "gpmc,oe-on-ns", &gpmc_t->oe_on);
+       of_property_read_u32(np, "gpmc,oe-off-ns", &gpmc_t->oe_off);
 
        /* access and cycle timings */
-       if (!of_property_read_u32(np, "gpmc,page-burst-access", &val))
-               gpmc_t->page_burst_access = val;
-
-       if (!of_property_read_u32(np, "gpmc,access", &val))
-               gpmc_t->access = val;
-
-       if (!of_property_read_u32(np, "gpmc,rd-cycle", &val))
-               gpmc_t->rd_cycle = val;
-
-       if (!of_property_read_u32(np, "gpmc,wr-cycle", &val))
-               gpmc_t->wr_cycle = val;
-
-       /* only for OMAP3430 */
-       if (!of_property_read_u32(np, "gpmc,wr-access", &val))
-               gpmc_t->wr_access = val;
-
-       if (!of_property_read_u32(np, "gpmc,wr-data-mux-bus", &val))
-               gpmc_t->wr_data_mux_bus = val;
+       of_property_read_u32(np, "gpmc,page-burst-access-ns",
+                            &gpmc_t->page_burst_access);
+       of_property_read_u32(np, "gpmc,access-ns", &gpmc_t->access);
+       of_property_read_u32(np, "gpmc,rd-cycle-ns", &gpmc_t->rd_cycle);
+       of_property_read_u32(np, "gpmc,wr-cycle-ns", &gpmc_t->wr_cycle);
+       of_property_read_u32(np, "gpmc,bus-turnaround-ns",
+                            &gpmc_t->bus_turnaround);
+       of_property_read_u32(np, "gpmc,cycle2cycle-delay-ns",
+                            &gpmc_t->cycle2cycle_delay);
+       of_property_read_u32(np, "gpmc,wait-monitoring-ns",
+                            &gpmc_t->wait_monitoring);
+       of_property_read_u32(np, "gpmc,clk-activation-ns",
+                            &gpmc_t->clk_activation);
+
+       /* only applicable to OMAP3+ */
+       of_property_read_u32(np, "gpmc,wr-access-ns", &gpmc_t->wr_access);
+       of_property_read_u32(np, "gpmc,wr-data-mux-bus-ns",
+                            &gpmc_t->wr_data_mux_bus);
+
+       /* bool timing parameters */
+       p = &gpmc_t->bool_timings;
+
+       p->cycle2cyclediffcsen =
+               of_property_read_bool(np, "gpmc,cycle2cycle-diffcsen");
+       p->cycle2cyclesamecsen =
+               of_property_read_bool(np, "gpmc,cycle2cycle-samecsen");
+       p->we_extra_delay = of_property_read_bool(np, "gpmc,we-extra-delay");
+       p->oe_extra_delay = of_property_read_bool(np, "gpmc,oe-extra-delay");
+       p->adv_extra_delay = of_property_read_bool(np, "gpmc,adv-extra-delay");
+       p->cs_extra_delay = of_property_read_bool(np, "gpmc,cs-extra-delay");
+       p->time_para_granularity =
+               of_property_read_bool(np, "gpmc,time-para-granularity");
 }
 
 #ifdef CONFIG_MTD_NAND
@@ -1298,6 +1428,81 @@ static int gpmc_probe_onenand_child(struct platform_device *pdev,
 }
 #endif
 
+/**
+ * gpmc_probe_generic_child - configures the gpmc for a child device
+ * @pdev:      pointer to gpmc platform device
+ * @child:     pointer to device-tree node for child device
+ *
+ * Allocates and configures a GPMC chip-select for a child device.
+ * Returns 0 on success and appropriate negative error code on failure.
+ */
+static int gpmc_probe_generic_child(struct platform_device *pdev,
+                               struct device_node *child)
+{
+       struct gpmc_settings gpmc_s;
+       struct gpmc_timings gpmc_t;
+       struct resource res;
+       unsigned long base;
+       int ret, cs;
+
+       if (of_property_read_u32(child, "reg", &cs) < 0) {
+               dev_err(&pdev->dev, "%s has no 'reg' property\n",
+                       child->full_name);
+               return -ENODEV;
+       }
+
+       if (of_address_to_resource(child, 0, &res) < 0) {
+               dev_err(&pdev->dev, "%s has malformed 'reg' property\n",
+                       child->full_name);
+               return -ENODEV;
+       }
+
+       ret = gpmc_cs_request(cs, resource_size(&res), &base);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "cannot request GPMC CS %d\n", cs);
+               return ret;
+       }
+
+       /*
+        * FIXME: gpmc_cs_request() will map the CS to an arbitary
+        * location in the gpmc address space. When booting with
+        * device-tree we want the NOR flash to be mapped to the
+        * location specified in the device-tree blob. So remap the
+        * CS to this location. Once DT migration is complete should
+        * just make gpmc_cs_request() map a specific address.
+        */
+       ret = gpmc_cs_remap(cs, res.start);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "cannot remap GPMC CS %d to 0x%x\n",
+                       cs, res.start);
+               goto err;
+       }
+
+       gpmc_read_settings_dt(child, &gpmc_s);
+
+       ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width);
+       if (ret < 0)
+               goto err;
+
+       ret = gpmc_cs_program_settings(cs, &gpmc_s);
+       if (ret < 0)
+               goto err;
+
+       gpmc_read_timings_dt(child, &gpmc_t);
+       gpmc_cs_set_timings(cs, &gpmc_t);
+
+       if (of_platform_device_create(child, NULL, &pdev->dev))
+               return 0;
+
+       dev_err(&pdev->dev, "failed to create gpmc child %s\n", child->name);
+       ret = -ENODEV;
+
+err:
+       gpmc_cs_free(cs);
+
+       return ret;
+}
+
 static int gpmc_probe_dt(struct platform_device *pdev)
 {
        int ret;
@@ -1308,6 +1513,13 @@ static int gpmc_probe_dt(struct platform_device *pdev)
        if (!of_id)
                return 0;
 
+       ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-waitpins",
+                                  &gpmc_nr_waitpins);
+       if (ret < 0) {
+               pr_err("%s: number of wait pins not found!\n", __func__);
+               return ret;
+       }
+
        for_each_node_by_name(child, "nand") {
                ret = gpmc_probe_nand_child(pdev, child);
                if (ret < 0) {
@@ -1323,6 +1535,23 @@ static int gpmc_probe_dt(struct platform_device *pdev)
                        return ret;
                }
        }
+
+       for_each_node_by_name(child, "nor") {
+               ret = gpmc_probe_generic_child(pdev, child);
+               if (ret < 0) {
+                       of_node_put(child);
+                       return ret;
+               }
+       }
+
+       for_each_node_by_name(child, "ethernet") {
+               ret = gpmc_probe_generic_child(pdev, child);
+               if (ret < 0) {
+                       of_node_put(child);
+                       return ret;
+               }
+       }
+
        return 0;
 }
 #else
@@ -1367,22 +1596,37 @@ static int gpmc_probe(struct platform_device *pdev)
        gpmc_dev = &pdev->dev;
 
        l = gpmc_read_reg(GPMC_REVISION);
+
+       /*
+        * FIXME: Once device-tree migration is complete the below flags
+        * should be populated based upon the device-tree compatible
+        * string. For now just use the IP revision. OMAP3+ devices have
+        * the wr_access and wr_data_mux_bus register fields. OMAP4+
+        * devices support the addr-addr-data multiplex protocol.
+        *
+        * GPMC IP revisions:
+        * - OMAP24xx                   = 2.0
+        * - OMAP3xxx                   = 5.0
+        * - OMAP44xx/54xx/AM335x       = 6.0
+        */
        if (GPMC_REVISION_MAJOR(l) > 0x4)
                gpmc_capability = GPMC_HAS_WR_ACCESS | GPMC_HAS_WR_DATA_MUX_BUS;
+       if (GPMC_REVISION_MAJOR(l) > 0x5)
+               gpmc_capability |= GPMC_HAS_MUX_AAD;
        dev_info(gpmc_dev, "GPMC revision %d.%d\n", GPMC_REVISION_MAJOR(l),
                 GPMC_REVISION_MINOR(l));
 
-       rc = gpmc_mem_init();
-       if (IS_ERR_VALUE(rc)) {
-               clk_disable_unprepare(gpmc_l3_clk);
-               clk_put(gpmc_l3_clk);
-               dev_err(gpmc_dev, "failed to reserve memory\n");
-               return rc;
-       }
+       gpmc_mem_init();
 
-       if (IS_ERR_VALUE(gpmc_setup_irq()))
+       if (gpmc_setup_irq() < 0)
                dev_warn(gpmc_dev, "gpmc_setup_irq failed\n");
 
+       /* Now the GPMC is initialised, unreserve the chip-selects */
+       gpmc_cs_map = 0;
+
+       if (!pdev->dev.of_node)
+               gpmc_nr_waitpins = GPMC_NR_WAITPINS;
+
        rc = gpmc_probe_dt(pdev);
        if (rc < 0) {
                clk_disable_unprepare(gpmc_l3_clk);
index fe0a844d5007a7775cadf78e357b541bbb80b153..707f6d58edd53d300a1b266cc229b3f9c1edd8f3 100644 (file)
@@ -58,7 +58,7 @@
 #define GPMC_CONFIG1_DEVICESIZE_16      GPMC_CONFIG1_DEVICESIZE(1)
 #define GPMC_CONFIG1_DEVICETYPE(val)    ((val & 3) << 10)
 #define GPMC_CONFIG1_DEVICETYPE_NOR     GPMC_CONFIG1_DEVICETYPE(0)
-#define GPMC_CONFIG1_MUXADDDATA         (1 << 9)
+#define GPMC_CONFIG1_MUXTYPE(val)       ((val & 3) << 8)
 #define GPMC_CONFIG1_TIME_PARA_GRAN     (1 << 4)
 #define GPMC_CONFIG1_FCLK_DIV(val)      (val & 3)
 #define GPMC_CONFIG1_FCLK_DIV2          (GPMC_CONFIG1_FCLK_DIV(1))
 #define GPMC_IRQ_FIFOEVENTENABLE       0x01
 #define GPMC_IRQ_COUNT_EVENT           0x02
 
+#define GPMC_BURST_4                   4       /* 4 word burst */
+#define GPMC_BURST_8                   8       /* 8 word burst */
+#define GPMC_BURST_16                  16      /* 16 word burst */
+#define GPMC_DEVWIDTH_8BIT             1       /* 8-bit device width */
+#define GPMC_DEVWIDTH_16BIT            2       /* 16-bit device width */
+#define GPMC_MUX_AAD                   1       /* Addr-Addr-Data multiplex */
+#define GPMC_MUX_AD                    2       /* Addr-Data multiplex */
 
 /* bool type time settings */
 struct gpmc_bool_timings {
@@ -178,10 +185,6 @@ struct gpmc_device_timings {
        u8 cyc_wpl;     /* write deassertion time in cycles */
        u32 cyc_iaa;    /* initial access time in cycles */
 
-       bool mux;       /* address & data muxed */
-       bool sync_write;/* synchronous write */
-       bool sync_read; /* synchronous read */
-
        /* extra delays */
        bool ce_xdelay;
        bool avd_xdelay;
@@ -189,28 +192,40 @@ struct gpmc_device_timings {
        bool we_xdelay;
 };
 
+struct gpmc_settings {
+       bool burst_wrap;        /* enables wrap bursting */
+       bool burst_read;        /* enables read page/burst mode */
+       bool burst_write;       /* enables write page/burst mode */
+       bool device_nand;       /* device is NAND */
+       bool sync_read;         /* enables synchronous reads */
+       bool sync_write;        /* enables synchronous writes */
+       bool wait_on_read;      /* monitor wait on reads */
+       bool wait_on_write;     /* monitor wait on writes */
+       u32 burst_len;          /* page/burst length */
+       u32 device_width;       /* device bus width (8 or 16 bit) */
+       u32 mux_add_data;       /* multiplex address & data */
+       u32 wait_pin;           /* wait-pin to be used */
+};
+
 extern int gpmc_calc_timings(struct gpmc_timings *gpmc_t,
-                               struct gpmc_device_timings *dev_t);
+                            struct gpmc_settings *gpmc_s,
+                            struct gpmc_device_timings *dev_t);
 
 extern void gpmc_update_nand_reg(struct gpmc_nand_regs *reg, int cs);
 extern int gpmc_get_client_irq(unsigned irq_config);
 
-extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns);
-extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps);
 extern unsigned int gpmc_ticks_to_ns(unsigned int ticks);
-extern unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns);
-extern unsigned long gpmc_get_fclk_period(void);
 
 extern void gpmc_cs_write_reg(int cs, int idx, u32 val);
-extern u32 gpmc_cs_read_reg(int cs, int idx);
 extern int gpmc_calc_divider(unsigned int sync_clk);
 extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t);
+extern int gpmc_cs_program_settings(int cs, struct gpmc_settings *p);
 extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base);
 extern void gpmc_cs_free(int cs);
-extern int gpmc_cs_set_reserved(int cs, int reserved);
-extern int gpmc_cs_reserved(int cs);
 extern void omap3_gpmc_save_context(void);
 extern void omap3_gpmc_restore_context(void);
-extern int gpmc_cs_configure(int cs, int cmd, int wval);
+extern int gpmc_configure(int cmd, int wval);
+extern void gpmc_read_settings_dt(struct device_node *np,
+                                 struct gpmc_settings *p);
 
 #endif
index 8a68f1ec66b9ac07dd9e20cf7c6239e794972407..ff0bc9e51aa777ad42a9d7661fc575624c21960c 100644 (file)
@@ -529,22 +529,28 @@ void __init omap5xxx_check_revision(void)
        case 0xb942:
                switch (rev) {
                case 0:
-               default:
                        omap_revision = OMAP5430_REV_ES1_0;
+                       break;
+               case 1:
+               default:
+                       omap_revision = OMAP5430_REV_ES2_0;
                }
                break;
 
        case 0xb998:
                switch (rev) {
                case 0:
-               default:
                        omap_revision = OMAP5432_REV_ES1_0;
+                       break;
+               case 1:
+               default:
+                       omap_revision = OMAP5432_REV_ES2_0;
                }
                break;
 
        default:
                /* Unknown default to latest silicon rev as default*/
-               omap_revision = OMAP5430_REV_ES1_0;
+               omap_revision = OMAP5430_REV_ES2_0;
        }
 
        pr_info("OMAP%04x ES%d.0\n",
index 2c3fdd65387b56c542d6d97cbc093fcf69a51b9a..e210fa830f8d7d076fdec7a23202bdab8b1a2089 100644 (file)
 #include "prm3xxx.h"
 #include "prm44xx.h"
 
+/*
+ * omap_clk_init: points to a function that does the SoC-specific
+ * clock initializations
+ */
+int (*omap_clk_init)(void);
+
 /*
  * The machine specific code may provide the extra mapping besides the
  * default mapping provided here.
@@ -271,6 +277,14 @@ static struct map_desc omap54xx_io_desc[] __initdata = {
                .length         = L4_PER_54XX_SIZE,
                .type           = MT_DEVICE,
        },
+#ifdef CONFIG_OMAP4_ERRATA_I688
+       {
+               .virtual        = OMAP4_SRAM_VA,
+               .pfn            = __phys_to_pfn(OMAP4_SRAM_PA),
+               .length         = PAGE_SIZE,
+               .type           = MT_MEMORY_SO,
+       },
+#endif
 };
 #endif
 
@@ -323,6 +337,7 @@ void __init omap4_map_io(void)
 void __init omap5_map_io(void)
 {
        iotable_init(omap54xx_io_desc, ARRAY_SIZE(omap54xx_io_desc));
+       omap_barriers_init();
 }
 #endif
 /*
@@ -397,7 +412,7 @@ void __init omap2420_init_early(void)
        omap242x_clockdomains_init();
        omap2420_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap2420_clk_init();
+       omap_clk_init = omap2420_clk_init;
 }
 
 void __init omap2420_init_late(void)
@@ -427,7 +442,7 @@ void __init omap2430_init_early(void)
        omap243x_clockdomains_init();
        omap2430_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap2430_clk_init();
+       omap_clk_init = omap2430_clk_init;
 }
 
 void __init omap2430_init_late(void)
@@ -462,7 +477,7 @@ void __init omap3_init_early(void)
        omap3xxx_clockdomains_init();
        omap3xxx_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap3xxx_clk_init();
+       omap_clk_init = omap3xxx_clk_init;
 }
 
 void __init omap3430_init_early(void)
@@ -500,7 +515,7 @@ void __init ti81xx_init_early(void)
        omap3xxx_clockdomains_init();
        omap3xxx_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap3xxx_clk_init();
+       omap_clk_init = omap3xxx_clk_init;
 }
 
 void __init omap3_init_late(void)
@@ -568,7 +583,7 @@ void __init am33xx_init_early(void)
        am33xx_clockdomains_init();
        am33xx_hwmod_init();
        omap_hwmod_init_postsetup();
-       am33xx_clk_init();
+       omap_clk_init = am33xx_clk_init;
 }
 #endif
 
@@ -593,7 +608,7 @@ void __init omap4430_init_early(void)
        omap44xx_clockdomains_init();
        omap44xx_hwmod_init();
        omap_hwmod_init_postsetup();
-       omap4xxx_clk_init();
+       omap_clk_init = omap4xxx_clk_init;
 }
 
 void __init omap4430_init_late(void)
index 6a217c98db5484a2560d08ff343219557ee75fb9..f82cf878d6af41da87b8bb444acd609105af72a9 100644 (file)
@@ -211,8 +211,6 @@ static int __init _omap_mux_get_by_name(struct omap_mux_partition *partition,
                return -EINVAL;
        }
 
-       pr_err("%s: Could not find signal %s\n", __func__, muxname);
-
        return -ENODEV;
 }
 
@@ -234,6 +232,8 @@ int __init omap_mux_get_by_name(const char *muxname,
                return mux_mode;
        }
 
+       pr_err("%s: Could not find signal %s\n", __func__, muxname);
+
        return -ENODEV;
 }
 
@@ -739,8 +739,9 @@ static void __init omap_mux_dbg_create_entry(
        list_for_each_entry(e, &partition->muxmodes, node) {
                struct omap_mux *m = &e->mux;
 
-               (void)debugfs_create_file(m->muxnames[0], S_IWUSR, mux_dbg_dir,
-                                         m, &omap_mux_dbg_signal_fops);
+               (void)debugfs_create_file(m->muxnames[0], S_IWUSR | S_IRUGO,
+                                         mux_dbg_dir, m,
+                                         &omap_mux_dbg_signal_fops);
        }
 }
 
index 708bb115a27ff8e54f0e760eaebaf2c10c9f4af1..2aeb928efdfdbcd1f291497f436acf6fdfea1867 100644 (file)
@@ -240,15 +240,21 @@ void __iomem *omap4_get_sar_ram_base(void)
  */
 static int __init omap4_sar_ram_init(void)
 {
+       unsigned long sar_base;
+
        /*
         * To avoid code running on other OMAPs in
         * multi-omap builds
         */
-       if (!cpu_is_omap44xx())
+       if (cpu_is_omap44xx())
+               sar_base = OMAP44XX_SAR_RAM_BASE;
+       else if (soc_is_omap54xx())
+               sar_base = OMAP54XX_SAR_RAM_BASE;
+       else
                return -ENOMEM;
 
        /* Static mapping, never released */
-       sar_ram_base = ioremap(OMAP44XX_SAR_RAM_BASE, SZ_16K);
+       sar_ram_base = ioremap(sar_base, SZ_16K);
        if (WARN_ON(!sar_ram_base))
                return -ENOMEM;
 
index e170fe803b046b2e0ff624e1b502960e902ac2a7..937417523b8eca71235eb4d5c22f479a1126af59 100644 (file)
 #define SAR_BACKUP_STATUS_WAKEUPGEN            0x10
 
 /* WakeUpGen save restore offset from OMAP54XX_SAR_RAM_BASE */
-#define OMAP5_WAKEUPGENENB_OFFSET_CPU0         (SAR_BANK3_OFFSET + 0x8d4)
-#define OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU0  (SAR_BANK3_OFFSET + 0x8e8)
-#define OMAP5_WAKEUPGENENB_OFFSET_CPU1         (SAR_BANK3_OFFSET + 0x8fc)
-#define OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU1  (SAR_BANK3_OFFSET + 0x910)
-#define OMAP5_AUXCOREBOOT0_OFFSET              (SAR_BANK3_OFFSET + 0x924)
-#define OMAP5_AUXCOREBOOT1_OFFSET              (SAR_BANK3_OFFSET + 0x928)
-#define OMAP5_AMBA_IF_MODE_OFFSET              (SAR_BANK3_OFFSET + 0x92c)
+#define OMAP5_WAKEUPGENENB_OFFSET_CPU0         (SAR_BANK3_OFFSET + 0x9dc)
+#define OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU0  (SAR_BANK3_OFFSET + 0x9f0)
+#define OMAP5_WAKEUPGENENB_OFFSET_CPU1         (SAR_BANK3_OFFSET + 0xa04)
+#define OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU1  (SAR_BANK3_OFFSET + 0xa18)
+#define OMAP5_AUXCOREBOOT0_OFFSET              (SAR_BANK3_OFFSET + 0xa2c)
+#define OMAP5_AUXCOREBOOT1_OFFSET              (SAR_BANK3_OFFSET + 0x930)
+#define OMAP5_AMBA_IF_MODE_OFFSET              (SAR_BANK3_OFFSET + 0xa34)
 #define OMAP5_SAR_BACKUP_STATUS_OFFSET         (SAR_BANK3_OFFSET + 0x800)
 
 #endif
index a2582bb3cab3d4b7dc5293e61bf757e0dba3a2b0..a086ba15868b2c4a32ea24de917e5cbd6d734675 100644 (file)
@@ -28,5 +28,6 @@
 #define OMAP54XX_PRCM_MPU_BASE         0x48243000
 #define OMAP54XX_SCM_BASE              0x4a002000
 #define OMAP54XX_CTRL_BASE             0x4a002800
+#define OMAP54XX_SAR_RAM_BASE          0x4ae26000
 
 #endif /* __ASM_SOC_OMAP555554XX_H */
index 381be7ac0c17923d8330ad6bfc983347c1695417..eeea4fa28fbcced9e8e8908d1749493ea4057a8b 100644 (file)
@@ -131,7 +131,7 @@ static int omap_device_build_from_dt(struct platform_device *pdev)
        int oh_cnt, i, ret = 0;
 
        oh_cnt = of_property_count_strings(node, "ti,hwmods");
-       if (!oh_cnt || IS_ERR_VALUE(oh_cnt)) {
+       if (oh_cnt <= 0) {
                dev_dbg(&pdev->dev, "No 'hwmods' to build omap_device\n");
                return -ENODEV;
        }
@@ -815,20 +815,17 @@ struct device *omap_device_get_by_hwmod_name(const char *oh_name)
        }
 
        oh = omap_hwmod_lookup(oh_name);
-       if (IS_ERR_OR_NULL(oh)) {
+       if (!oh) {
                WARN(1, "%s: no hwmod for %s\n", __func__,
                        oh_name);
-               return ERR_PTR(oh ? PTR_ERR(oh) : -ENODEV);
+               return ERR_PTR(-ENODEV);
        }
-       if (IS_ERR_OR_NULL(oh->od)) {
+       if (!oh->od) {
                WARN(1, "%s: no omap_device for %s\n", __func__,
                        oh_name);
-               return ERR_PTR(oh->od ? PTR_ERR(oh->od) : -ENODEV);
+               return ERR_PTR(-ENODEV);
        }
 
-       if (IS_ERR_OR_NULL(oh->od->pdev))
-               return ERR_PTR(oh->od->pdev ? PTR_ERR(oh->od->pdev) : -ENODEV);
-
        return &oh->od->pdev->dev;
 }
 
index c2c798c08c2b9f63a55bc11be5f654f80006431c..3f50f680372eed38c535885768a1f7205171bd5e 100644 (file)
@@ -610,8 +610,6 @@ static int _enable_wakeup(struct omap_hwmod *oh, u32 *v)
 
        /* XXX test pwrdm_get_wken for this hwmod's subsystem */
 
-       oh->_int_flags |= _HWMOD_WAKEUP_ENABLED;
-
        return 0;
 }
 
@@ -645,8 +643,6 @@ static int _disable_wakeup(struct omap_hwmod *oh, u32 *v)
 
        /* XXX test pwrdm_get_wken for this hwmod's subsystem */
 
-       oh->_int_flags &= ~_HWMOD_WAKEUP_ENABLED;
-
        return 0;
 }
 
@@ -1368,7 +1364,9 @@ static void _enable_sysc(struct omap_hwmod *oh)
        }
 
        if (sf & SYSC_HAS_MIDLEMODE) {
-               if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
+               if (oh->flags & HWMOD_FORCE_MSTANDBY) {
+                       idlemode = HWMOD_IDLEMODE_FORCE;
+               } else if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
                        idlemode = HWMOD_IDLEMODE_NO;
                } else {
                        if (sf & SYSC_HAS_ENAWAKEUP)
@@ -1440,7 +1438,8 @@ static void _idle_sysc(struct omap_hwmod *oh)
        }
 
        if (sf & SYSC_HAS_MIDLEMODE) {
-               if (oh->flags & HWMOD_SWSUP_MSTANDBY) {
+               if ((oh->flags & HWMOD_SWSUP_MSTANDBY) ||
+                   (oh->flags & HWMOD_FORCE_MSTANDBY)) {
                        idlemode = HWMOD_IDLEMODE_FORCE;
                } else {
                        if (sf & SYSC_HAS_ENAWAKEUP)
@@ -1663,7 +1662,7 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
                return -ENOSYS;
 
        ret = _lookup_hardreset(oh, name, &ohri);
-       if (IS_ERR_VALUE(ret))
+       if (ret < 0)
                return ret;
 
        if (oh->clkdm) {
@@ -2413,7 +2412,7 @@ static int __init _init(struct omap_hwmod *oh, void *data)
        _init_mpu_rt_base(oh, NULL);
 
        r = _init_clocks(oh, NULL);
-       if (IS_ERR_VALUE(r)) {
+       if (r < 0) {
                WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh->name);
                return -EINVAL;
        }
index d43d9b608edab3c1b7e69c96e711ec1eefc2d7c8..fe5962921f07244e602429b758f0d5ccecb7398c 100644 (file)
@@ -427,8 +427,8 @@ struct omap_hwmod_omap4_prcm {
  *
  * HWMOD_SWSUP_SIDLE: omap_hwmod code should manually bring module in and out
  *     of idle, rather than relying on module smart-idle
- * HWMOD_SWSUP_MSTDBY: omap_hwmod code should manually bring module in and out
- *     of standby, rather than relying on module smart-standby
+ * HWMOD_SWSUP_MSTANDBY: omap_hwmod code should manually bring module in and
+ *     out of standby, rather than relying on module smart-standby
  * HWMOD_INIT_NO_RESET: don't reset this module at boot - important for
  *     SDRAM controller, etc. XXX probably belongs outside the main hwmod file
  *     XXX Should be HWMOD_SETUP_NO_RESET
@@ -459,6 +459,10 @@ struct omap_hwmod_omap4_prcm {
  *     correctly, or this is being abused to deal with some PM latency
  *     issues -- but we're currently suffering from a shortage of
  *     folks who are able to track these issues down properly.
+ * HWMOD_FORCE_MSTANDBY: Always keep MIDLEMODE bits cleared so that device
+ *     is kept in force-standby mode. Failing to do so causes PM problems
+ *     with musb on OMAP3630 at least. Note that musb has a dedicated register
+ *     to control MSTANDBY signal when MIDLEMODE is set to force-standby.
  */
 #define HWMOD_SWSUP_SIDLE                      (1 << 0)
 #define HWMOD_SWSUP_MSTANDBY                   (1 << 1)
@@ -471,21 +475,20 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_16BIT_REG                                (1 << 8)
 #define HWMOD_EXT_OPT_MAIN_CLK                 (1 << 9)
 #define HWMOD_BLOCK_WFI                                (1 << 10)
+#define HWMOD_FORCE_MSTANDBY                   (1 << 11)
 
 /*
  * omap_hwmod._int_flags definitions
  * These are for internal use only and are managed by the omap_hwmod code.
  *
  * _HWMOD_NO_MPU_PORT: no path exists for the MPU to write to this module
- * _HWMOD_WAKEUP_ENABLED: set when the omap_hwmod code has enabled ENAWAKEUP
  * _HWMOD_SYSCONFIG_LOADED: set when the OCP_SYSCONFIG value has been cached
  * _HWMOD_SKIP_ENABLE: set if hwmod enabled during init (HWMOD_INIT_NO_IDLE) -
  *     causes the first call to _enable() to only update the pinmux
  */
 #define _HWMOD_NO_MPU_PORT                     (1 << 0)
-#define _HWMOD_WAKEUP_ENABLED                  (1 << 1)
-#define _HWMOD_SYSCONFIG_LOADED                        (1 << 2)
-#define _HWMOD_SKIP_ENABLE                     (1 << 3)
+#define _HWMOD_SYSCONFIG_LOADED                        (1 << 1)
+#define _HWMOD_SKIP_ENABLE                     (1 << 2)
 
 /*
  * omap_hwmod._state definitions
index 26eee4a556ad13a82f27a09d1820eb48f6d3ebac..31bea1ce3de10a7049d49b917b616c1f52701401 100644 (file)
@@ -28,6 +28,7 @@
 #include "prm-regbits-33xx.h"
 #include "i2c.h"
 #include "mmc.h"
+#include "wd_timer.h"
 
 /*
  * IP blocks
@@ -2087,8 +2088,21 @@ static struct omap_hwmod am33xx_uart6_hwmod = {
 };
 
 /* 'wd_timer' class */
+static struct omap_hwmod_class_sysconfig wdt_sysc = {
+       .rev_offs       = 0x0,
+       .sysc_offs      = 0x10,
+       .syss_offs      = 0x14,
+       .sysc_flags     = (SYSC_HAS_EMUFREE | SYSC_HAS_SIDLEMODE |
+                       SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+       .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+                       SIDLE_SMART_WKUP),
+       .sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
 static struct omap_hwmod_class am33xx_wd_timer_hwmod_class = {
        .name           = "wd_timer",
+       .sysc           = &wdt_sysc,
+       .pre_shutdown   = &omap2_wd_timer_disable,
 };
 
 /*
@@ -2099,6 +2113,7 @@ static struct omap_hwmod am33xx_wd_timer1_hwmod = {
        .name           = "wd_timer2",
        .class          = &am33xx_wd_timer_hwmod_class,
        .clkdm_name     = "l4_wkup_clkdm",
+       .flags          = HWMOD_SWSUP_SIDLE,
        .main_clk       = "wdt1_fck",
        .prcm           = {
                .omap4  = {
index ac7e03ec952f22f7c856084c15e2de3e767e4273..5112d04e7b79bd928a3d332f2ec846352e0e5b1b 100644 (file)
@@ -1707,9 +1707,14 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
         * Erratum ID: i479  idle_req / idle_ack mechanism potentially
         * broken when autoidle is enabled
         * workaround is to disable the autoidle bit at module level.
+        *
+        * Enabling the device in any other MIDLEMODE setting but force-idle
+        * causes core_pwrdm not enter idle states at least on OMAP3630.
+        * Note that musb has OTG_FORCESTDBY register that controls MSTANDBY
+        * signal when MIDLEMODE is set to force-idle.
         */
        .flags          = HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
-                               | HWMOD_SWSUP_MSTANDBY,
+                               | HWMOD_FORCE_MSTANDBY,
 };
 
 /* usb_otg_hs */
index 0e47d2e1687c76004ea7449b8e496340617b09d1..9e0576569e07ae2e19492b5877de7aafe3ef567c 100644 (file)
@@ -2714,6 +2714,10 @@ static struct omap_ocp2scp_dev ocp2scp_dev_attr[] = {
        { }
 };
 
+static struct omap_hwmod_opt_clk ocp2scp_usb_phy_opt_clks[] = {
+       { .role = "48mhz", .clk = "ocp2scp_usb_phy_phy_48m" },
+};
+
 /* ocp2scp_usb_phy */
 static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
        .name           = "ocp2scp_usb_phy",
@@ -2728,6 +2732,8 @@ static struct omap_hwmod omap44xx_ocp2scp_usb_phy_hwmod = {
                },
        },
        .dev_attr       = ocp2scp_dev_attr,
+       .opt_clks       = ocp2scp_usb_phy_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(ocp2scp_usb_phy_opt_clks),
 };
 
 /*
index 1edd000a81439eb6e7648dcefeeb69ec5ab01b42..0b339861d751004a4c3f8607e329922eeb008334 100644 (file)
@@ -217,7 +217,7 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *dir)
                return 0;
 
        d = debugfs_create_dir(pwrdm->name, (struct dentry *)dir);
-       if (!(IS_ERR_OR_NULL(d)))
+       if (d)
                (void) debugfs_create_file("suspend", S_IRUGO|S_IWUSR, d,
                        (void *)pwrdm, &pwrdm_suspend_fops);
 
@@ -261,8 +261,8 @@ static int __init pm_dbg_init(void)
                return 0;
 
        d = debugfs_create_dir("pm_debug", NULL);
-       if (IS_ERR_OR_NULL(d))
-               return PTR_ERR(d);
+       if (!d)
+               return -EINVAL;
 
        (void) debugfs_create_file("count", S_IRUGO,
                d, (void *)DEBUG_FILE_COUNTERS, &debug_fops);
index 8e61d80bf6b3442e658747f7a42cb4f822f973ac..86babd740d410d42cbe3cf6502cdcaa971313558 100644 (file)
@@ -52,7 +52,6 @@ enum {
 #define ALREADYACTIVE_SWITCH           0
 #define FORCEWAKEUP_SWITCH             1
 #define LOWPOWERSTATE_SWITCH           2
-#define ERROR_SWITCH                   3
 
 /* pwrdm_list contains all registered struct powerdomains */
 static LIST_HEAD(pwrdm_list);
@@ -233,10 +232,7 @@ static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm,
 {
        u8 sleep_switch;
 
-       if (curr_pwrst < 0) {
-               WARN_ON(1);
-               sleep_switch = ERROR_SWITCH;
-       } else if (curr_pwrst < PWRDM_POWER_ON) {
+       if (curr_pwrst < PWRDM_POWER_ON) {
                if (curr_pwrst > pwrst &&
                    pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
                    arch_pwrdm->pwrdm_set_lowpwrstchange) {
@@ -1091,7 +1087,8 @@ int pwrdm_post_transition(struct powerdomain *pwrdm)
  */
 int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 pwrst)
 {
-       u8 curr_pwrst, next_pwrst, sleep_switch;
+       u8 next_pwrst, sleep_switch;
+       int curr_pwrst;
        int ret = 0;
        bool hwsup = false;
 
@@ -1107,16 +1104,17 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 pwrst)
        pwrdm_lock(pwrdm);
 
        curr_pwrst = pwrdm_read_pwrst(pwrdm);
+       if (curr_pwrst < 0) {
+               ret = -EINVAL;
+               goto osps_out;
+       }
+
        next_pwrst = pwrdm_read_next_pwrst(pwrdm);
        if (curr_pwrst == pwrst && next_pwrst == pwrst)
                goto osps_out;
 
        sleep_switch = _pwrdm_save_clkdm_state_and_activate(pwrdm, curr_pwrst,
                                                            pwrst, &hwsup);
-       if (sleep_switch == ERROR_SWITCH) {
-               ret = -EINVAL;
-               goto osps_out;
-       }
 
        ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
        if (ret)
@@ -1182,7 +1180,7 @@ bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm)
 {
        int i;
 
-       if (IS_ERR_OR_NULL(pwrdm)) {
+       if (!pwrdm) {
                pr_debug("powerdomain: %s: invalid powerdomain pointer\n",
                         __func__);
                return 1;
index d35f98aabf7a206c1b781511dd1ac3059eca9eeb..415c7e0c9393ad3e85f45591a3fbf68a93a1df12 100644 (file)
@@ -81,13 +81,13 @@ static struct prm_reset_src_map omap44xx_prm_reset_src_map[] = {
 /* Read a register in a CM/PRM instance in the PRM module */
 u32 omap4_prm_read_inst_reg(s16 inst, u16 reg)
 {
-       return __raw_readl(OMAP44XX_PRM_REGADDR(inst, reg));
+       return __raw_readl(prm_base + inst + reg);
 }
 
 /* Write into a register in a CM/PRM instance in the PRM module */
 void omap4_prm_write_inst_reg(u32 val, s16 inst, u16 reg)
 {
-       __raw_writel(val, OMAP44XX_PRM_REGADDR(inst, reg));
+       __raw_writel(val, prm_base + inst + reg);
 }
 
 /* Read-modify-write a register in a PRM module. Caller must lock */
@@ -650,7 +650,7 @@ static struct prm_ll_data omap44xx_prm_ll_data = {
 
 int __init omap44xx_prm_init(void)
 {
-       if (!cpu_is_omap44xx())
+       if (!cpu_is_omap44xx() && !soc_is_omap54xx())
                return 0;
 
        return prm_register(&omap44xx_prm_ll_data);
index c62116bbc760d3a1245f722ecc3b19be5ba09955..18fdeeb3a44a494096ae7b246a02a9604a4fdb89 100644 (file)
@@ -413,7 +413,9 @@ IS_OMAP_TYPE(3430, 0x3430)
 
 #define OMAP54XX_CLASS         0x54000054
 #define OMAP5430_REV_ES1_0     (OMAP54XX_CLASS | (0x30 << 16) | (0x10 << 8))
+#define OMAP5430_REV_ES2_0     (OMAP54XX_CLASS | (0x30 << 16) | (0x20 << 8))
 #define OMAP5432_REV_ES1_0     (OMAP54XX_CLASS | (0x32 << 16) | (0x10 << 8))
+#define OMAP5432_REV_ES2_0     (OMAP54XX_CLASS | (0x32 << 16) | (0x20 << 8))
 
 void omap2xxx_check_revision(void);
 void omap3xxx_check_revision(void);
index 4fd80257c73ebe768fbfef51c492bbde4dd9423c..31ae764817376502b65eb285be147ee639176ad1 100644 (file)
 #include "common.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"
-
 #define REALTIME_COUNTER_BASE                          0x48243200
 #define INCREMENTER_NUMERATOR_OFFSET                   0x10
 #define INCREMENTER_DENUMERATOR_RELOAD_OFFSET          0x14
@@ -129,7 +120,6 @@ static void omap2_gp_timer_set_mode(enum clock_event_mode mode,
 }
 
 static struct clock_event_device clockevent_gpt = {
-       .name           = "gp_timer",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .rating         = 300,
        .set_next_event = omap2_gp_timer_set_next_event,
@@ -170,6 +160,12 @@ static struct device_node * __init omap_get_timer_dt(struct of_device_id *match,
                if (property && !of_get_property(np, property, NULL))
                        continue;
 
+               if (!property && (of_get_property(np, "ti,timer-alwon", NULL) ||
+                                 of_get_property(np, "ti,timer-dsp", NULL) ||
+                                 of_get_property(np, "ti,timer-pwm", NULL) ||
+                                 of_get_property(np, "ti,timer-secure", NULL)))
+                       continue;
+
                of_add_property(np, &device_disabled);
                return np;
        }
@@ -214,16 +210,17 @@ static u32 __init omap_dm_timer_get_errata(void)
 }
 
 static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
-                                               int gptimer_id,
-                                               const char *fck_source,
-                                               const char *property,
-                                               int posted)
+                                        const char *fck_source,
+                                        const char *property,
+                                        const char **timer_name,
+                                        int posted)
 {
        char name[10]; /* 10 = sizeof("gptXX_Xck0") */
        const char *oh_name;
        struct device_node *np;
        struct omap_hwmod *oh;
        struct resource irq, mem;
+       struct clk *src;
        int r = 0;
 
        if (of_have_populated_dt()) {
@@ -243,10 +240,10 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
 
                of_node_put(np);
        } else {
-               if (omap_dm_timer_reserve_systimer(gptimer_id))
+               if (omap_dm_timer_reserve_systimer(timer->id))
                        return -ENODEV;
 
-               sprintf(name, "timer%d", gptimer_id);
+               sprintf(name, "timer%d", timer->id);
                oh_name = name;
        }
 
@@ -254,6 +251,8 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
        if (!oh)
                return -ENODEV;
 
+       *timer_name = oh->name;
+
        if (!of_have_populated_dt()) {
                r = omap_hwmod_get_resource_byname(oh, IORESOURCE_IRQ, NULL,
                                                   &irq);
@@ -276,24 +275,24 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
        /* After the dmtimer is using hwmod these clocks won't be needed */
        timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh));
        if (IS_ERR(timer->fclk))
-               return -ENODEV;
+               return PTR_ERR(timer->fclk);
 
-       /* FIXME: Need to remove hard-coded test on timer ID */
-       if (gptimer_id != 12) {
-               struct clk *src;
-
-               src = clk_get(NULL, fck_source);
-               if (IS_ERR(src)) {
-                       r = -EINVAL;
-               } else {
-                       r = clk_set_parent(timer->fclk, src);
-                       if (IS_ERR_VALUE(r))
-                               pr_warn("%s: %s cannot set source\n",
-                                       __func__, oh->name);
+       src = clk_get(NULL, fck_source);
+       if (IS_ERR(src))
+               return PTR_ERR(src);
+
+       if (clk_get_parent(timer->fclk) != src) {
+               r = clk_set_parent(timer->fclk, src);
+               if (r < 0) {
+                       pr_warn("%s: %s cannot set source\n", __func__,
+                               oh->name);
                        clk_put(src);
+                       return r;
                }
        }
 
+       clk_put(src);
+
        omap_hwmod_setup_one(oh_name);
        omap_hwmod_enable(oh);
        __omap_dm_timer_init_regs(timer);
@@ -317,6 +316,7 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
 {
        int res;
 
+       clkev.id = gptimer_id;
        clkev.errata = omap_dm_timer_get_errata();
 
        /*
@@ -326,8 +326,8 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
         */
        __omap_dm_timer_override_errata(&clkev, OMAP_TIMER_ERRATA_I103_I767);
 
-       res = omap_dm_timer_init_one(&clkev, gptimer_id, fck_source, property,
-                                    OMAP_TIMER_POSTED);
+       res = omap_dm_timer_init_one(&clkev, fck_source, property,
+                                    &clockevent_gpt.name, OMAP_TIMER_POSTED);
        BUG_ON(res);
 
        omap2_gp_timer_irq.dev_id = &clkev;
@@ -341,8 +341,8 @@ static void __init omap2_gp_clockevent_init(int gptimer_id,
                                        3, /* Timer internal resynch latency */
                                        0xffffffff);
 
-       pr_info("OMAP clockevent source: GPTIMER%d at %lu Hz\n",
-               gptimer_id, clkev.rate);
+       pr_info("OMAP clockevent source: %s at %lu Hz\n", clockevent_gpt.name,
+               clkev.rate);
 }
 
 /* Clocksource code */
@@ -359,7 +359,6 @@ static cycle_t clocksource_read_cycles(struct clocksource *cs)
 }
 
 static struct clocksource clocksource_gpt = {
-       .name           = "gp_timer",
        .rating         = 300,
        .read           = clocksource_read_cycles,
        .mask           = CLOCKSOURCE_MASK(32),
@@ -442,13 +441,16 @@ static int __init __maybe_unused omap2_sync32k_clocksource_init(void)
 }
 
 static void __init omap2_gptimer_clocksource_init(int gptimer_id,
-                                               const char *fck_source)
+                                                 const char *fck_source,
+                                                 const char *property)
 {
        int res;
 
+       clksrc.id = gptimer_id;
        clksrc.errata = omap_dm_timer_get_errata();
 
-       res = omap_dm_timer_init_one(&clksrc, gptimer_id, fck_source, NULL,
+       res = omap_dm_timer_init_one(&clksrc, fck_source, property,
+                                    &clocksource_gpt.name,
                                     OMAP_TIMER_NONPOSTED);
        BUG_ON(res);
 
@@ -461,8 +463,8 @@ static void __init omap2_gptimer_clocksource_init(int gptimer_id,
                pr_err("Could not register clocksource %s\n",
                        clocksource_gpt.name);
        else
-               pr_info("OMAP clocksource: GPTIMER%d at %lu Hz\n",
-                       gptimer_id, clksrc.rate);
+               pr_info("OMAP clocksource: %s at %lu Hz\n",
+                       clocksource_gpt.name, clksrc.rate);
 }
 
 #ifdef CONFIG_SOC_HAS_REALTIME_COUNTER
@@ -487,7 +489,7 @@ static void __init realtime_counter_init(void)
                pr_err("%s: ioremap failed\n", __func__);
                return;
        }
-       sys_clk = clk_get(NULL, "sys_clkin_ck");
+       sys_clk = clk_get(NULL, "sys_clkin");
        if (IS_ERR(sys_clk)) {
                pr_err("%s: failed to get system clock handle\n", __func__);
                iounmap(base);
@@ -544,49 +546,56 @@ static inline void __init realtime_counter_init(void)
 #endif
 
 #define OMAP_SYS_GP_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop,  \
-                              clksrc_nr, clksrc_src)                   \
+                              clksrc_nr, clksrc_src, clksrc_prop)      \
 void __init omap##name##_gptimer_timer_init(void)                      \
 {                                                                      \
+       if (omap_clk_init)                                              \
+               omap_clk_init();                                        \
        omap_dmtimer_init();                                            \
        omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);    \
-       omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src);        \
+       omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src,         \
+                                       clksrc_prop);                   \
 }
 
 #define OMAP_SYS_32K_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop, \
-                               clksrc_nr, clksrc_src)                  \
+                               clksrc_nr, clksrc_src, clksrc_prop)     \
 void __init omap##name##_sync32k_timer_init(void)              \
 {                                                                      \
+       if (omap_clk_init)                                              \
+               omap_clk_init();                                        \
        omap_dmtimer_init();                                            \
        omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);    \
        /* Enable the use of clocksource="gp_timer" kernel parameter */ \
        if (use_gptimer_clksrc)                                         \
-               omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src);\
+               omap2_gptimer_clocksource_init((clksrc_nr), clksrc_src, \
+                                               clksrc_prop);           \
        else                                                            \
                omap2_sync32k_clocksource_init();                       \
 }
 
 #ifdef CONFIG_ARCH_OMAP2
-OMAP_SYS_32K_TIMER_INIT(2, 1, OMAP2_32K_SOURCE, "ti,timer-alwon",
-                       2, OMAP2_MPU_SOURCE);
+OMAP_SYS_32K_TIMER_INIT(2, 1, "timer_32k_ck", "ti,timer-alwon",
+                       2, "timer_sys_ck", NULL);
 #endif /* CONFIG_ARCH_OMAP2 */
 
 #ifdef CONFIG_ARCH_OMAP3
-OMAP_SYS_32K_TIMER_INIT(3, 1, OMAP3_32K_SOURCE, "ti,timer-alwon",
-                       2, OMAP3_MPU_SOURCE);
-OMAP_SYS_32K_TIMER_INIT(3_secure, 12, OMAP3_32K_SOURCE, "ti,timer-secure",
-                       2, OMAP3_MPU_SOURCE);
-OMAP_SYS_GP_TIMER_INIT(3_gp, 1, OMAP3_MPU_SOURCE, "ti,timer-alwon",
-                      2, OMAP3_MPU_SOURCE);
+OMAP_SYS_32K_TIMER_INIT(3, 1, "timer_32k_ck", "ti,timer-alwon",
+                       2, "timer_sys_ck", NULL);
+OMAP_SYS_32K_TIMER_INIT(3_secure, 12, "secure_32k_fck", "ti,timer-secure",
+                       2, "timer_sys_ck", NULL);
 #endif /* CONFIG_ARCH_OMAP3 */
 
-#ifdef CONFIG_SOC_AM33XX
-OMAP_SYS_GP_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, "ti,timer-alwon",
-                      2, OMAP4_MPU_SOURCE);
-#endif /* CONFIG_SOC_AM33XX */
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX)
+OMAP_SYS_GP_TIMER_INIT(3, 2, "timer_sys_ck", NULL,
+                      1, "timer_sys_ck", "ti,timer-alwon");
+#endif
+
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
+static OMAP_SYS_32K_TIMER_INIT(4, 1, "timer_32k_ck", "ti,timer-alwon",
+                              2, "sys_clkin_ck", NULL);
+#endif
 
 #ifdef CONFIG_ARCH_OMAP4
-OMAP_SYS_32K_TIMER_INIT(4, 1, OMAP4_32K_SOURCE, "ti,timer-alwon",
-                       2, OMAP4_MPU_SOURCE);
 #ifdef CONFIG_LOCAL_TIMERS
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29);
 void __init omap4_local_timer_init(void)
@@ -615,13 +624,11 @@ void __init omap4_local_timer_init(void)
 #endif /* CONFIG_ARCH_OMAP4 */
 
 #ifdef CONFIG_SOC_OMAP5
-OMAP_SYS_32K_TIMER_INIT(5, 1, OMAP4_32K_SOURCE, "ti,timer-alwon",
-                       2, OMAP4_MPU_SOURCE);
 void __init omap5_realtime_timer_init(void)
 {
        int err;
 
-       omap5_sync32k_timer_init();
+       omap4_sync32k_timer_init();
        realtime_counter_init();
 
        err = arch_timer_of_register();
index 5706bdccf45ee34b643141337b38222fbaf5f63a..aa27d7f5cbb7a760596337903fd0e61ac22e647b 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dma-mapping.h>
-
-#include <asm/io.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/string.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/usb/phy.h>
 
 #include "soc.h"
 #include "omap_device.h"
@@ -526,3 +530,155 @@ void __init usbhs_init(struct usbhs_omap_platform_data *pdata)
 }
 
 #endif
+
+/* Template for PHY regulators */
+static struct fixed_voltage_config hsusb_reg_config = {
+       /* .supply_name filled later */
+       .microvolts = 3300000,
+       .gpio = -1,             /* updated later */
+       .startup_delay = 70000, /* 70msec */
+       .enable_high = 1,       /* updated later */
+       .enabled_at_boot = 0,   /* keep in RESET */
+       /* .init_data filled later */
+};
+
+static const char *nop_name = "nop_usb_xceiv"; /* NOP PHY driver */
+static const char *reg_name = "reg-fixed-voltage"; /* Regulator driver */
+
+/**
+ * usbhs_add_regulator - Add a gpio based fixed voltage regulator device
+ * @name: name for the regulator
+ * @dev_id: device id of the device this regulator supplies power to
+ * @dev_supply: supply name that the device expects
+ * @gpio: GPIO number
+ * @polarity: 1 - Active high, 0 - Active low
+ */
+static int usbhs_add_regulator(char *name, char *dev_id, char *dev_supply,
+                                               int gpio, int polarity)
+{
+       struct regulator_consumer_supply *supplies;
+       struct regulator_init_data *reg_data;
+       struct fixed_voltage_config *config;
+       struct platform_device *pdev;
+       int ret;
+
+       supplies = kzalloc(sizeof(*supplies), GFP_KERNEL);
+       if (!supplies)
+               return -ENOMEM;
+
+       supplies->supply = dev_supply;
+       supplies->dev_name = dev_id;
+
+       reg_data = kzalloc(sizeof(*reg_data), GFP_KERNEL);
+       if (!reg_data)
+               return -ENOMEM;
+
+       reg_data->constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS;
+       reg_data->consumer_supplies = supplies;
+       reg_data->num_consumer_supplies = 1;
+
+       config = kmemdup(&hsusb_reg_config, sizeof(hsusb_reg_config),
+                       GFP_KERNEL);
+       if (!config)
+               return -ENOMEM;
+
+       config->supply_name = name;
+       config->gpio = gpio;
+       config->enable_high = polarity;
+       config->init_data = reg_data;
+
+       /* create a regulator device */
+       pdev = kzalloc(sizeof(*pdev), GFP_KERNEL);
+       if (!pdev)
+               return -ENOMEM;
+
+       pdev->id = PLATFORM_DEVID_AUTO;
+       pdev->name = reg_name;
+       pdev->dev.platform_data = config;
+
+       ret = platform_device_register(pdev);
+       if (ret)
+               pr_err("%s: Failed registering regulator %s for %s\n",
+                               __func__, name, dev_id);
+
+       return ret;
+}
+
+int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys)
+{
+       char *rail_name;
+       int i, len;
+       struct platform_device *pdev;
+       char *phy_id;
+
+       /* the phy_id will be something like "nop_usb_xceiv.1" */
+       len = strlen(nop_name) + 3; /* 3 -> ".1" and NULL terminator */
+
+       for (i = 0; i < num_phys; i++) {
+
+               if (!phy->port) {
+                       pr_err("%s: Invalid port 0. Must start from 1\n",
+                                               __func__);
+                       continue;
+               }
+
+               /* do we need a NOP PHY device ? */
+               if (!gpio_is_valid(phy->reset_gpio) &&
+                       !gpio_is_valid(phy->vcc_gpio))
+                       continue;
+
+               /* create a NOP PHY device */
+               pdev = kzalloc(sizeof(*pdev), GFP_KERNEL);
+               if (!pdev)
+                       return -ENOMEM;
+
+               pdev->id = phy->port;
+               pdev->name = nop_name;
+               pdev->dev.platform_data = phy->platform_data;
+
+               phy_id = kmalloc(len, GFP_KERNEL);
+               if (!phy_id)
+                       return -ENOMEM;
+
+               scnprintf(phy_id, len, "nop_usb_xceiv.%d\n",
+                                       pdev->id);
+
+               if (platform_device_register(pdev)) {
+                       pr_err("%s: Failed to register device %s\n",
+                               __func__,  phy_id);
+                       continue;
+               }
+
+               usb_bind_phy("ehci-omap.0", phy->port - 1, phy_id);
+
+               /* Do we need RESET regulator ? */
+               if (gpio_is_valid(phy->reset_gpio)) {
+
+                       rail_name = kmalloc(13, GFP_KERNEL);
+                       if (!rail_name)
+                               return -ENOMEM;
+
+                       scnprintf(rail_name, 13, "hsusb%d_reset", phy->port);
+
+                       usbhs_add_regulator(rail_name, phy_id, "reset",
+                                               phy->reset_gpio, 1);
+               }
+
+               /* Do we need VCC regulator ? */
+               if (gpio_is_valid(phy->vcc_gpio)) {
+
+                       rail_name = kmalloc(13, GFP_KERNEL);
+                       if (!rail_name)
+                               return -ENOMEM;
+
+                       scnprintf(rail_name, 13, "hsusb%d_vcc", phy->port);
+
+                       usbhs_add_regulator(rail_name, phy_id, "vcc",
+                                       phy->vcc_gpio, phy->vcc_polarity);
+               }
+
+               phy++;
+       }
+
+       return 0;
+}
index c5a3c6f9504e79c8085e12e0aac10904a5177ab3..e832bc7b8e2dd77042ef323d68185d8f9a7dd135 100644 (file)
@@ -8,6 +8,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/err.h>
 #include <linux/string.h>
 #include <linux/types.h>
 #include <linux/errno.h>
 static u8              async_cs, sync_cs;
 static unsigned                refclk_psec;
 
+static struct gpmc_settings tusb_async = {
+       .wait_on_read   = true,
+       .wait_on_write  = true,
+       .device_width   = GPMC_DEVWIDTH_16BIT,
+       .mux_add_data   = GPMC_MUX_AD,
+};
+
+static struct gpmc_settings tusb_sync = {
+       .burst_read     = true,
+       .burst_write    = true,
+       .sync_read      = true,
+       .sync_write     = true,
+       .wait_on_read   = true,
+       .wait_on_write  = true,
+       .burst_len      = GPMC_BURST_16,
+       .device_width   = GPMC_DEVWIDTH_16BIT,
+       .mux_add_data   = GPMC_MUX_AD,
+};
 
 /* NOTE:  timings are from tusb 6010 datasheet Rev 1.8, 12-Sept 2006 */
 
@@ -37,8 +56,6 @@ static int tusb_set_async_mode(unsigned sysclk_ps)
 
        memset(&dev_t, 0, sizeof(dev_t));
 
-       dev_t.mux = true;
-
        dev_t.t_ceasu = 8 * 1000;
        dev_t.t_avdasu = t_acsnh_advnh - 7000;
        dev_t.t_ce_avd = 1000;
@@ -52,7 +69,7 @@ static int tusb_set_async_mode(unsigned sysclk_ps)
        dev_t.t_wpl = 300;
        dev_t.cyc_aavdh_we = 1;
 
-       gpmc_calc_timings(&t, &dev_t);
+       gpmc_calc_timings(&t, &tusb_async, &dev_t);
 
        return gpmc_cs_set_timings(async_cs, &t);
 }
@@ -65,10 +82,6 @@ static int tusb_set_sync_mode(unsigned sysclk_ps)
 
        memset(&dev_t, 0, sizeof(dev_t));
 
-       dev_t.mux = true;
-       dev_t.sync_read = true;
-       dev_t.sync_write = true;
-
        dev_t.clk = 11100;
        dev_t.t_bacc = 1000;
        dev_t.t_ces = 1000;
@@ -84,7 +97,7 @@ static int tusb_set_sync_mode(unsigned sysclk_ps)
        dev_t.cyc_wpl = 6;
        dev_t.t_ce_rdyz = 7000;
 
-       gpmc_calc_timings(&t, &dev_t);
+       gpmc_calc_timings(&t, &tusb_sync, &dev_t);
 
        return gpmc_cs_set_timings(sync_cs, &t);
 }
@@ -165,18 +178,12 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
                return status;
        }
        tusb_resources[0].end = tusb_resources[0].start + 0x9ff;
+       tusb_async.wait_pin = waitpin;
        async_cs = async;
-       gpmc_cs_write_reg(async, GPMC_CS_CONFIG1,
-                         GPMC_CONFIG1_PAGE_LEN(2)
-                       | GPMC_CONFIG1_WAIT_READ_MON
-                       | GPMC_CONFIG1_WAIT_WRITE_MON
-                       | GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
-                       | GPMC_CONFIG1_READTYPE_ASYNC
-                       | GPMC_CONFIG1_WRITETYPE_ASYNC
-                       | GPMC_CONFIG1_DEVICESIZE_16
-                       | GPMC_CONFIG1_DEVICETYPE_NOR
-                       | GPMC_CONFIG1_MUXADDDATA);
 
+       status = gpmc_cs_program_settings(async_cs, &tusb_async);
+       if (status < 0)
+               return status;
 
        /* SYNC region, primarily for DMA */
        status = gpmc_cs_request(sync, SZ_16M, (unsigned long *)
@@ -186,21 +193,12 @@ tusb6010_setup_interface(struct musb_hdrc_platform_data *data,
                return status;
        }
        tusb_resources[1].end = tusb_resources[1].start + 0x9ff;
+       tusb_sync.wait_pin = waitpin;
        sync_cs = sync;
-       gpmc_cs_write_reg(sync, GPMC_CS_CONFIG1,
-                         GPMC_CONFIG1_READMULTIPLE_SUPP
-                       | GPMC_CONFIG1_READTYPE_SYNC
-                       | GPMC_CONFIG1_WRITEMULTIPLE_SUPP
-                       | GPMC_CONFIG1_WRITETYPE_SYNC
-                       | GPMC_CONFIG1_PAGE_LEN(2)
-                       | GPMC_CONFIG1_WAIT_READ_MON
-                       | GPMC_CONFIG1_WAIT_WRITE_MON
-                       | GPMC_CONFIG1_WAIT_PIN_SEL(waitpin)
-                       | GPMC_CONFIG1_DEVICESIZE_16
-                       | GPMC_CONFIG1_DEVICETYPE_NOR
-                       | GPMC_CONFIG1_MUXADDDATA
-                       /* fclk divider gets set later */
-                       );
+
+       status = gpmc_cs_program_settings(sync_cs, &tusb_sync);
+       if (status < 0)
+               return status;
 
        /* IRQ */
        status = gpio_request_one(irq, GPIOF_IN, "TUSB6010 irq");
index 3319f5cf47a3aade4bdf79ba9605e3cdc183ee6f..e7261ebcf7b02ba83c4e4fe672d132636aeb841e 100644 (file)
 #define USBPHY_OTGSESSEND_EN   (1 << 20)
 #define USBPHY_DATA_POLARITY   (1 << 23)
 
+struct usbhs_phy_data {
+       int port;               /* 1 indexed port number */
+       int reset_gpio;
+       int vcc_gpio;
+       bool vcc_polarity;      /* 1 active high, 0 active low */
+       void *platform_data;
+};
+
 extern void usb_musb_init(struct omap_musb_board_data *board_data);
 extern void usbhs_init(struct usbhs_omap_platform_data *pdata);
+extern int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys);
 
 extern void am35x_musb_reset(void);
 extern void am35x_musb_phy_power(u8 on);
index af41888acbd674db746f194475b4ad077150b070..969b0ba7fa703a688a7078250c2118a3e19fe4b3 100644 (file)
@@ -505,6 +505,7 @@ static struct w1_gpio_platform_data w1_gpio_platform_data = {
        .pin                    = GPIO_ONE_WIRE,
        .is_open_drain          = 0,
        .enable_external_pullup = w1_enable_external_pullup,
+       .ext_pullup_enable_pin  = -EINVAL,
 };
 
 struct platform_device raumfeld_w1_gpio_device = {
index 37f513d1588ece1db569d02bdeda76980b6a65e1..0a8663c5f2ba4e064db16b02a5bfc6f6ed6be29c 100644 (file)
@@ -30,6 +30,7 @@ config CPU_S3C2410
        select S3C2410_CLOCK
        select S3C2410_CPUFREQ if CPU_FREQ_S3C24XX
        select S3C2410_PM if PM
+       select SAMSUNG_HRT
        help
          Support for S3C2410 and S3C2410A family from the S3C24XX line
          of Samsung Mobile CPUs.
@@ -41,6 +42,7 @@ config CPU_S3C2412
        select CPU_LLSERIAL_S3C2440
        select S3C2412_DMA if S3C24XX_DMA
        select S3C2412_PM if PM
+       select SAMSUNG_HRT
        help
          Support for the S3C2412 and S3C2413 SoCs from the S3C24XX line
 
@@ -53,6 +55,7 @@ config CPU_S3C2416
        select S3C2443_COMMON
        select S3C2443_DMA if S3C24XX_DMA
        select SAMSUNG_CLKSRC
+       select SAMSUNG_HRT
        help
          Support for the S3C2416 SoC from the S3C24XX line
 
@@ -63,6 +66,7 @@ config CPU_S3C2440
        select S3C2410_CLOCK
        select S3C2410_PM if PM
        select S3C2440_DMA if S3C24XX_DMA
+       select SAMSUNG_HRT
        help
          Support for S3C2440 Samsung Mobile CPU based systems.
 
@@ -72,6 +76,7 @@ config CPU_S3C2442
        select CPU_LLSERIAL_S3C2440
        select S3C2410_CLOCK
        select S3C2410_PM if PM
+       select SAMSUNG_HRT
        help
          Support for S3C2442 Samsung Mobile CPU based systems.
 
@@ -87,6 +92,7 @@ config CPU_S3C2443
        select S3C2443_COMMON
        select S3C2443_DMA if S3C24XX_DMA
        select SAMSUNG_CLKSRC
+       select SAMSUNG_HRT
        help
          Support for the S3C2443 SoC from the S3C24XX line
 
@@ -401,6 +407,7 @@ config S3C2412_DMA
 config S3C2412_PM
        bool
        select S3C2412_PM_SLEEP
+       select SAMSUNG_WAKEMASK
        help
          Internal config node to apply S3C2412 power management
 
index af53d27d5c3651200da19fc24b61c111c23f041d..6f46ecfc83967ce893ad63a01d23ca8ac498e908 100644 (file)
@@ -14,7 +14,7 @@ obj-                          :=
 
 # core
 
-obj-y                          += common.o irq.o
+obj-y                          += common.o
 
 obj-$(CONFIG_CPU_S3C2410)      += s3c2410.o
 obj-$(CONFIG_S3C2410_CPUFREQ)  += cpufreq-s3c2410.o
@@ -22,7 +22,7 @@ obj-$(CONFIG_S3C2410_DMA)     += dma-s3c2410.o
 obj-$(CONFIG_S3C2410_PLL)      += pll-s3c2410.o
 obj-$(CONFIG_S3C2410_PM)       += pm-s3c2410.o sleep-s3c2410.o
 
-obj-$(CONFIG_CPU_S3C2412)      += s3c2412.o irq-s3c2412.o clock-s3c2412.o
+obj-$(CONFIG_CPU_S3C2412)      += s3c2412.o clock-s3c2412.o
 obj-$(CONFIG_S3C2412_CPUFREQ)  += cpufreq-s3c2412.o
 obj-$(CONFIG_S3C2412_DMA)      += dma-s3c2412.o
 obj-$(CONFIG_S3C2412_PM)       += pm-s3c2412.o
@@ -31,9 +31,9 @@ obj-$(CONFIG_S3C2412_PM_SLEEP)        += sleep-s3c2412.o
 obj-$(CONFIG_CPU_S3C2416)      += s3c2416.o clock-s3c2416.o
 obj-$(CONFIG_S3C2416_PM)       += pm-s3c2416.o
 
-obj-$(CONFIG_CPU_S3C2440)      += s3c2440.o irq-s3c2440.o clock-s3c2440.o
+obj-$(CONFIG_CPU_S3C2440)      += s3c2440.o clock-s3c2440.o
 obj-$(CONFIG_CPU_S3C2442)      += s3c2442.o
-obj-$(CONFIG_CPU_S3C244X)      += s3c244x.o irq-s3c244x.o clock-s3c244x.o
+obj-$(CONFIG_CPU_S3C244X)      += s3c244x.o clock-s3c244x.o
 obj-$(CONFIG_S3C2440_CPUFREQ)  += cpufreq-s3c2440.o
 obj-$(CONFIG_S3C2440_DMA)      += dma-s3c2440.o
 obj-$(CONFIG_S3C2440_PLL_12000000) += pll-s3c2440-12000000.o
index c0daa9590b4c15635ed90723797881d77338e80b..cb1b791954dea7d9a31eb202af4416353be04737 100644 (file)
@@ -34,8 +34,6 @@
 #include <mach/hardware.h>
 #include <mach/regs-irq.h>
 
-#include <plat/irq.h>
-
 #include "bast.h"
 
 #define irqdbf(x...)
index 641266f3d152011d35530d9194c2c219af977217..34fffdf6fc1dc4b7f699418976e0b3d943c512a6 100644 (file)
@@ -40,7 +40,6 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
-#include <plat/s3c2410.h>
 #include <plat/clock.h>
 #include <plat/cpu.h>
 
index d10b695a9066a760fe98d965383847e52be8f9bd..2cc017da88fe234874863a23920b9c78acb850d1 100644 (file)
@@ -41,7 +41,6 @@
 #include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
-#include <plat/s3c2412.h>
 #include <plat/clock.h>
 #include <plat/cpu.h>
 
index 14a81c2317a417eb14b3fc413678a5541e9b09a5..036056cea57c63bd5a4ddf07f5ec3a5326ed35b6 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 
-#include <plat/s3c2416.h>
 #include <plat/clock.h>
 #include <plat/clock-clksrc.h>
 #include <plat/cpu.h>
index bdaba59b42dce799b7fca73e98856c539e78a946..0a53051b078721ea6635677e6b36381e98b182c2 100644 (file)
@@ -41,7 +41,6 @@
 
 #include <plat/cpu-freq.h>
 
-#include <plat/s3c2443.h>
 #include <plat/clock.h>
 #include <plat/clock-clksrc.h>
 #include <plat/cpu.h>
index 3b2cf6db36349d23df16392d4bbcf8d73391cead..404444dd3840e0559996ddf0175a7d8ead07838d 100644 (file)
 
 #include <linux/platform_data/mtd-nand-s3c2410.h>
 
-#include <plat/common-smdk.h>
 #include <plat/gpio-cfg.h>
 #include <plat/devs.h>
 #include <plat/pm.h>
 
+#include "common-smdk.h"
+
 /* LED devices */
 
 static struct s3c24xx_led_platdata smdk_pdata_led4 = {
similarity index 86%
rename from arch/arm/plat-samsung/include/plat/common-smdk.h
rename to arch/arm/mach-s3c24xx/common-smdk.h
index ba028f1ed30babe907bd30d58252e134e55304aa..98f733e1cb42f78ca697f83aeb389f132ab60b73 100644 (file)
@@ -1,5 +1,4 @@
-/* linux/arch/arm/plat-samsung/include/plat/common-smdk.h
- *
+/*
  * Copyright (c) 2006 Simtec Electronics
  *     Ben Dooks <ben@simtec.co.uk>
  *
index 6bcf87f65f9e41c7cb86dfd064495eb3a76820af..d97533d21ac4c34dcf976ef2e43d3047d98cd75c 100644 (file)
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/clock.h>
-#include <plat/s3c2410.h>
-#include <plat/s3c2412.h>
-#include <plat/s3c2416.h>
-#include <plat/s3c244x.h>
-#include <plat/s3c2443.h>
 #include <plat/cpu-freq.h>
 #include <plat/pll.h>
 
+#include "common.h"
+
 /* table of supported CPUs */
 
 static const char name_s3c2410[]  = "S3C2410";
index ed6276fcaa3b10089969189f67340ce1351f1dc9..307c3714be55d43de2b8e4b65f92fbf3a7ea2e22 100644 (file)
 #ifndef __ARCH_ARM_MACH_S3C24XX_COMMON_H
 #define __ARCH_ARM_MACH_S3C24XX_COMMON_H __FILE__
 
-void s3c2410_restart(char mode, const char *cmd);
-void s3c244x_restart(char mode, const char *cmd);
+struct s3c2410_uartcfg;
+
+#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);
+extern void s3c2410_restart(char mode, const char *cmd);
+extern void s3c2410_init_irq(void);
+#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
+
+#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);
+extern void s3c2412_restart(char mode, const char *cmd);
+extern void s3c2412_init_irq(void);
+#else
+#define s3c2412_init_clocks NULL
+#define s3c2412_init_uarts NULL
+#define s3c2412_map_io NULL
+#define s3c2412_init NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2416
+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);
+extern void s3c2416_restart(char mode, const char *cmd);
+extern void s3c2416_init_irq(void);
+
+extern struct syscore_ops s3c2416_irq_syscore_ops;
+#else
+#define s3c2416_init_clocks NULL
+#define s3c2416_init_uarts NULL
+#define s3c2416_map_io NULL
+#define s3c2416_init NULL
+#endif
+
+#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);
+extern void s3c244x_restart(char mode, const char *cmd);
+#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);
+extern void s3c2440_init_irq(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);
+extern void s3c2442_init_irq(void);
+#else
+#define s3c2442_init NULL
+#define s3c2442_map_io NULL
+#endif
+
+#ifdef CONFIG_CPU_S3C2443
+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);
+extern void s3c2443_restart(char mode, const char *cmd);
+extern void s3c2443_init_irq(void);
+#else
+#define s3c2443_init_clocks NULL
+#define s3c2443_init_uarts NULL
+#define s3c2443_map_io NULL
+#define s3c2443_init NULL
+#endif
 
 extern struct syscore_ops s3c24xx_irq_syscore_ops;
 
index 25d085adc93cd416e5751ab4a066a33485d6058a..a6c94b820954a55f016cb4e388c9889d97d4fbf8 100644 (file)
@@ -28,7 +28,6 @@
 #include <plat/regs-ac97.h>
 #include <plat/regs-dma.h>
 #include <mach/regs-lcd.h>
-#include <mach/regs-sdi.h>
 #include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 
index d2408ba372cb966975b9b12d6af1f1ef23fd0a09..c0e8c3f5057ef98ce0bfb1557a5a2f200894380e 100644 (file)
@@ -28,7 +28,6 @@
 #include <plat/regs-ac97.h>
 #include <plat/regs-dma.h>
 #include <mach/regs-lcd.h>
-#include <mach/regs-sdi.h>
 #include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 
index 0b86e74d104f6823a9eb6a8a3ac05ec7297e05a2..1c08eccd9425c12007a2c0a7db4ba8a9e48b65e6 100644 (file)
@@ -28,7 +28,6 @@
 #include <plat/regs-ac97.h>
 #include <plat/regs-dma.h>
 #include <mach/regs-lcd.h>
-#include <mach/regs-sdi.h>
 #include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 
index 05536254a3f87023c7d89efc2f05f9cb7cf89842..000e4c69fce9ad3f92b8adc414e1299abbda1cca 100644 (file)
@@ -28,7 +28,6 @@
 #include <plat/regs-ac97.h>
 #include <plat/regs-dma.h>
 #include <mach/regs-lcd.h>
-#include <mach/regs-sdi.h>
 #include <plat/regs-iis.h>
 #include <plat/regs-spi.h>
 
index 13ed33c69113a3c6a5f70af6b9739d30d6f0b53b..2558952e3147ee281ecf2a2e2c7fc4df20900925 100644 (file)
@@ -98,4 +98,4 @@
 
 /* include the reset of the code which will do the work */
 
-#include <plat/debug-macro.S>
+#include <debug/samsung.S>
diff --git a/arch/arm/mach-s3c24xx/include/mach/entry-macro.S b/arch/arm/mach-s3c24xx/include/mach/entry-macro.S
deleted file mode 100644 (file)
index 6a21bee..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * arch/arm/mach-s3c2410/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for S3C2410-based 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.
-*/
-
-/* We have a problem that the INTOFFSET register does not always
- * show one interrupt. Occasionally we get two interrupts through
- * the prioritiser, and this causes the INTOFFSET register to show
- * what looks like the logical-or of the two interrupt numbers.
- *
- * Thanks to Klaus, Shannon, et al for helping to debug this problem
-*/
-
-#define INTPND         (0x10)
-#define INTOFFSET      (0x14)
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-       .macro  get_irqnr_preamble, base, tmp
-       .endm
-
-       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-
-               mov     \base, #S3C24XX_VA_IRQ
-
-               @@ try the interrupt offset register, since it is there
-
-               ldr     \irqstat, [\base, #INTPND ]
-               teq     \irqstat, #0
-               beq     1002f
-               ldr     \irqnr, [\base, #INTOFFSET ]
-               mov     \tmp, #1
-               tst     \irqstat, \tmp, lsl \irqnr
-               bne     1001f
-
-               @@ the number specified is not a valid irq, so try
-               @@ and work it out for ourselves
-
-               mov     \irqnr, #0              @@ start here
-
-               @@ work out which irq (if any) we got
-
-               movs    \tmp, \irqstat, lsl#16
-               addeq   \irqnr, \irqnr, #16
-               moveq   \irqstat, \irqstat, lsr#16
-               tst     \irqstat, #0xff
-               addeq   \irqnr, \irqnr, #8
-               moveq   \irqstat, \irqstat, lsr#8
-               tst     \irqstat, #0xf
-               addeq   \irqnr, \irqnr, #4
-               moveq   \irqstat, \irqstat, lsr#4
-               tst     \irqstat, #0x3
-               addeq   \irqnr, \irqnr, #2
-               moveq   \irqstat, \irqstat, lsr#2
-               tst     \irqstat, #0x1
-               addeq   \irqnr, \irqnr, #1
-
-               @@ we have the value
-1001:
-               adds    \irqnr, \irqnr, #IRQ_EINT0
-1002:
-               @@ exit here, Z flag unset if IRQ
-
-       .endm
index b7a9f4d469e816bf6ca1f389f31d9280d06ecc46..43cada8019b449e46b98d7aca57d89f5bfcf9520 100644 (file)
 #define IRQ_ADCPARENT  S3C2410_IRQ(31)
 
 /* interrupts generated from the external interrupts sources */
-#define IRQ_EINT4      S3C2410_IRQ(32)    /* 48 */
-#define IRQ_EINT5      S3C2410_IRQ(33)
-#define IRQ_EINT6      S3C2410_IRQ(34)
-#define IRQ_EINT7      S3C2410_IRQ(35)
-#define IRQ_EINT8      S3C2410_IRQ(36)
-#define IRQ_EINT9      S3C2410_IRQ(37)
-#define IRQ_EINT10     S3C2410_IRQ(38)
-#define IRQ_EINT11     S3C2410_IRQ(39)
-#define IRQ_EINT12     S3C2410_IRQ(40)
-#define IRQ_EINT13     S3C2410_IRQ(41)
-#define IRQ_EINT14     S3C2410_IRQ(42)
-#define IRQ_EINT15     S3C2410_IRQ(43)
-#define IRQ_EINT16     S3C2410_IRQ(44)
-#define IRQ_EINT17     S3C2410_IRQ(45)
-#define IRQ_EINT18     S3C2410_IRQ(46)
-#define IRQ_EINT19     S3C2410_IRQ(47)
-#define IRQ_EINT20     S3C2410_IRQ(48)    /* 64 */
-#define IRQ_EINT21     S3C2410_IRQ(49)
-#define IRQ_EINT22     S3C2410_IRQ(50)
-#define IRQ_EINT23     S3C2410_IRQ(51)
+#define IRQ_EINT0_2412 S3C2410_IRQ(32)
+#define IRQ_EINT1_2412 S3C2410_IRQ(33)
+#define IRQ_EINT2_2412 S3C2410_IRQ(34)
+#define IRQ_EINT3_2412 S3C2410_IRQ(35)
+#define IRQ_EINT4      S3C2410_IRQ(36)    /* 52 */
+#define IRQ_EINT5      S3C2410_IRQ(37)
+#define IRQ_EINT6      S3C2410_IRQ(38)
+#define IRQ_EINT7      S3C2410_IRQ(39)
+#define IRQ_EINT8      S3C2410_IRQ(40)
+#define IRQ_EINT9      S3C2410_IRQ(41)
+#define IRQ_EINT10     S3C2410_IRQ(42)
+#define IRQ_EINT11     S3C2410_IRQ(43)
+#define IRQ_EINT12     S3C2410_IRQ(44)
+#define IRQ_EINT13     S3C2410_IRQ(45)
+#define IRQ_EINT14     S3C2410_IRQ(46)
+#define IRQ_EINT15     S3C2410_IRQ(47)
+#define IRQ_EINT16     S3C2410_IRQ(48)
+#define IRQ_EINT17     S3C2410_IRQ(49)
+#define IRQ_EINT18     S3C2410_IRQ(50)
+#define IRQ_EINT19     S3C2410_IRQ(51)
+#define IRQ_EINT20     S3C2410_IRQ(52)    /* 68 */
+#define IRQ_EINT21     S3C2410_IRQ(53)
+#define IRQ_EINT22     S3C2410_IRQ(54)
+#define IRQ_EINT23     S3C2410_IRQ(55)
 
 #define IRQ_EINT_BIT(x)        ((x) - IRQ_EINT4 + 4)
 #define IRQ_EINT(x)    (((x) >= 4) ? (IRQ_EINT4 + (x) - 4) : (IRQ_EINT0 + (x)))
 
-#define IRQ_LCD_FIFO   S3C2410_IRQ(52)
-#define IRQ_LCD_FRAME  S3C2410_IRQ(53)
+#define IRQ_LCD_FIFO   S3C2410_IRQ(56)
+#define IRQ_LCD_FRAME  S3C2410_IRQ(57)
 
 /* IRQs for the interal UARTs, and ADC
  * these need to be ordered in number of appearance in the
  * SUBSRC mask register
 */
 
-#define S3C2410_IRQSUB(x)      S3C2410_IRQ((x)+54)
+#define S3C2410_IRQSUB(x)      S3C2410_IRQ((x)+58)
 
-#define IRQ_S3CUART_RX0                S3C2410_IRQSUB(0)       /* 70 */
+#define IRQ_S3CUART_RX0                S3C2410_IRQSUB(0)       /* 74 */
 #define IRQ_S3CUART_TX0                S3C2410_IRQSUB(1)
 #define IRQ_S3CUART_ERR0       S3C2410_IRQSUB(2)
 
-#define IRQ_S3CUART_RX1                S3C2410_IRQSUB(3)       /* 73 */
+#define IRQ_S3CUART_RX1                S3C2410_IRQSUB(3)       /* 77 */
 #define IRQ_S3CUART_TX1                S3C2410_IRQSUB(4)
 #define IRQ_S3CUART_ERR1       S3C2410_IRQSUB(5)
 
-#define IRQ_S3CUART_RX2                S3C2410_IRQSUB(6)       /* 76 */
+#define IRQ_S3CUART_RX2                S3C2410_IRQSUB(6)       /* 80 */
 #define IRQ_S3CUART_TX2                S3C2410_IRQSUB(7)
 #define IRQ_S3CUART_ERR2       S3C2410_IRQSUB(8)
 
 
 /* second interrupt-register of s3c2416/s3c2450 */
 
-#define S3C2416_IRQ(x)         S3C2410_IRQ((x) + 54 + 29)
+#define S3C2416_IRQ(x)         S3C2410_IRQ((x) + 58 + 29)
 #define IRQ_S3C2416_2D         S3C2416_IRQ(0)
 #define IRQ_S3C2416_IIC1       S3C2416_IRQ(1)
 #define IRQ_S3C2416_RESERVED2  S3C2416_IRQ(2)
diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-sdi.h b/arch/arm/mach-s3c24xx/include/mach/regs-sdi.h
deleted file mode 100644 (file)
index cbf2d88..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-sdi.h
- *
- * Copyright (c) 2004 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 MMC/SDIO register definitions
-*/
-
-#ifndef __ASM_ARM_REGS_SDI
-#define __ASM_ARM_REGS_SDI "regs-sdi.h"
-
-#define S3C2410_SDICON                (0x00)
-#define S3C2410_SDIPRE                (0x04)
-#define S3C2410_SDICMDARG             (0x08)
-#define S3C2410_SDICMDCON             (0x0C)
-#define S3C2410_SDICMDSTAT            (0x10)
-#define S3C2410_SDIRSP0               (0x14)
-#define S3C2410_SDIRSP1               (0x18)
-#define S3C2410_SDIRSP2               (0x1C)
-#define S3C2410_SDIRSP3               (0x20)
-#define S3C2410_SDITIMER              (0x24)
-#define S3C2410_SDIBSIZE              (0x28)
-#define S3C2410_SDIDCON               (0x2C)
-#define S3C2410_SDIDCNT               (0x30)
-#define S3C2410_SDIDSTA               (0x34)
-#define S3C2410_SDIFSTA               (0x38)
-
-#define S3C2410_SDIDATA               (0x3C)
-#define S3C2410_SDIIMSK               (0x40)
-
-#define S3C2440_SDIDATA               (0x40)
-#define S3C2440_SDIIMSK               (0x3C)
-
-#define S3C2440_SDICON_SDRESET        (1<<8)
-#define S3C2440_SDICON_MMCCLOCK       (1<<5)
-#define S3C2410_SDICON_BYTEORDER      (1<<4)
-#define S3C2410_SDICON_SDIOIRQ        (1<<3)
-#define S3C2410_SDICON_RWAITEN        (1<<2)
-#define S3C2410_SDICON_FIFORESET      (1<<1)
-#define S3C2410_SDICON_CLOCKTYPE      (1<<0)
-
-#define S3C2410_SDICMDCON_ABORT       (1<<12)
-#define S3C2410_SDICMDCON_WITHDATA    (1<<11)
-#define S3C2410_SDICMDCON_LONGRSP     (1<<10)
-#define S3C2410_SDICMDCON_WAITRSP     (1<<9)
-#define S3C2410_SDICMDCON_CMDSTART    (1<<8)
-#define S3C2410_SDICMDCON_SENDERHOST  (1<<6)
-#define S3C2410_SDICMDCON_INDEX       (0x3f)
-
-#define S3C2410_SDICMDSTAT_CRCFAIL    (1<<12)
-#define S3C2410_SDICMDSTAT_CMDSENT    (1<<11)
-#define S3C2410_SDICMDSTAT_CMDTIMEOUT (1<<10)
-#define S3C2410_SDICMDSTAT_RSPFIN     (1<<9)
-#define S3C2410_SDICMDSTAT_XFERING    (1<<8)
-#define S3C2410_SDICMDSTAT_INDEX      (0xff)
-
-#define S3C2440_SDIDCON_DS_BYTE       (0<<22)
-#define S3C2440_SDIDCON_DS_HALFWORD   (1<<22)
-#define S3C2440_SDIDCON_DS_WORD       (2<<22)
-#define S3C2410_SDIDCON_IRQPERIOD     (1<<21)
-#define S3C2410_SDIDCON_TXAFTERRESP   (1<<20)
-#define S3C2410_SDIDCON_RXAFTERCMD    (1<<19)
-#define S3C2410_SDIDCON_BUSYAFTERCMD  (1<<18)
-#define S3C2410_SDIDCON_BLOCKMODE     (1<<17)
-#define S3C2410_SDIDCON_WIDEBUS       (1<<16)
-#define S3C2410_SDIDCON_DMAEN         (1<<15)
-#define S3C2410_SDIDCON_STOP          (1<<14)
-#define S3C2440_SDIDCON_DATSTART      (1<<14)
-#define S3C2410_SDIDCON_DATMODE              (3<<12)
-#define S3C2410_SDIDCON_BLKNUM        (0x7ff)
-
-/* constants for S3C2410_SDIDCON_DATMODE */
-#define S3C2410_SDIDCON_XFER_READY    (0<<12)
-#define S3C2410_SDIDCON_XFER_CHKSTART (1<<12)
-#define S3C2410_SDIDCON_XFER_RXSTART  (2<<12)
-#define S3C2410_SDIDCON_XFER_TXSTART  (3<<12)
-
-#define S3C2410_SDIDCON_BLKNUM_MASK   (0xFFF)
-#define S3C2410_SDIDCNT_BLKNUM_SHIFT  (12)
-
-#define S3C2410_SDIDSTA_RDYWAITREQ    (1<<10)
-#define S3C2410_SDIDSTA_SDIOIRQDETECT (1<<9)
-#define S3C2410_SDIDSTA_FIFOFAIL      (1<<8)   /* reserved on 2440 */
-#define S3C2410_SDIDSTA_CRCFAIL       (1<<7)
-#define S3C2410_SDIDSTA_RXCRCFAIL     (1<<6)
-#define S3C2410_SDIDSTA_DATATIMEOUT   (1<<5)
-#define S3C2410_SDIDSTA_XFERFINISH    (1<<4)
-#define S3C2410_SDIDSTA_BUSYFINISH    (1<<3)
-#define S3C2410_SDIDSTA_SBITERR       (1<<2)   /* reserved on 2410a/2440 */
-#define S3C2410_SDIDSTA_TXDATAON      (1<<1)
-#define S3C2410_SDIDSTA_RXDATAON      (1<<0)
-
-#define S3C2440_SDIFSTA_FIFORESET      (1<<16)
-#define S3C2440_SDIFSTA_FIFOFAIL       (3<<14)  /* 3 is correct (2 bits) */
-#define S3C2410_SDIFSTA_TFDET          (1<<13)
-#define S3C2410_SDIFSTA_RFDET          (1<<12)
-#define S3C2410_SDIFSTA_TFHALF         (1<<11)
-#define S3C2410_SDIFSTA_TFEMPTY        (1<<10)
-#define S3C2410_SDIFSTA_RFLAST         (1<<9)
-#define S3C2410_SDIFSTA_RFFULL         (1<<8)
-#define S3C2410_SDIFSTA_RFHALF         (1<<7)
-#define S3C2410_SDIFSTA_COUNTMASK      (0x7f)
-
-#define S3C2410_SDIIMSK_RESPONSECRC    (1<<17)
-#define S3C2410_SDIIMSK_CMDSENT        (1<<16)
-#define S3C2410_SDIIMSK_CMDTIMEOUT     (1<<15)
-#define S3C2410_SDIIMSK_RESPONSEND     (1<<14)
-#define S3C2410_SDIIMSK_READWAIT       (1<<13)
-#define S3C2410_SDIIMSK_SDIOIRQ        (1<<12)
-#define S3C2410_SDIIMSK_FIFOFAIL       (1<<11)
-#define S3C2410_SDIIMSK_CRCSTATUS      (1<<10)
-#define S3C2410_SDIIMSK_DATACRC        (1<<9)
-#define S3C2410_SDIIMSK_DATATIMEOUT    (1<<8)
-#define S3C2410_SDIIMSK_DATAFINISH     (1<<7)
-#define S3C2410_SDIIMSK_BUSYFINISH     (1<<6)
-#define S3C2410_SDIIMSK_SBITERR        (1<<5)  /* reserved 2440/2410a */
-#define S3C2410_SDIIMSK_TXFIFOHALF     (1<<4)
-#define S3C2410_SDIIMSK_TXFIFOEMPTY    (1<<3)
-#define S3C2410_SDIIMSK_RXFIFOLAST     (1<<2)
-#define S3C2410_SDIIMSK_RXFIFOFULL     (1<<1)
-#define S3C2410_SDIIMSK_RXFIFOHALF     (1<<0)
-
-#endif /* __ASM_ARM_REGS_SDI */
index e1199599873e0691ed432be5208d7461e1629af4..b91341ef2b2e72b7b39738e55728c0757d551410 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/syscore_ops.h>
+#include <linux/io.h>
 
 #include <plat/cpu.h>
 #include <plat/pm.h>
-#include <plat/irq.h>
+#include <plat/map-base.h>
+#include <plat/map-s3c.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
 
 #include <asm/irq.h>
 
diff --git a/arch/arm/mach-s3c24xx/irq-s3c2412.c b/arch/arm/mach-s3c24xx/irq-s3c2412.c
deleted file mode 100644 (file)
index 67d7631..0000000
+++ /dev/null
@@ -1,215 +0,0 @@
-/* linux/arch/arm/mach-s3c2412/irq.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 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/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/cpu.h>
-#include <plat/irq.h>
-#include <plat/pm.h>
-
-#include "s3c2412-power.h"
-
-#define INTMSK(start, end) ((1 << ((end) + 1 - (start))) - 1)
-#define INTMSK_SUB(start, end) (INTMSK(start, end) << ((start - S3C2410_IRQSUB(0))))
-
-/* the s3c2412 changes the behaviour of IRQ_EINT0 through IRQ_EINT3 by
- * having them turn up in both the INT* and the EINT* registers. Whilst
- * both show the status, they both now need to be acked when the IRQs
- * go off.
-*/
-
-static void
-s3c2412_irq_mask(struct irq_data *data)
-{
-       unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
-       unsigned long mask;
-
-       mask = __raw_readl(S3C2410_INTMSK);
-       __raw_writel(mask | bitval, S3C2410_INTMSK);
-
-       mask = __raw_readl(S3C2412_EINTMASK);
-       __raw_writel(mask | bitval, S3C2412_EINTMASK);
-}
-
-static inline void
-s3c2412_irq_ack(struct irq_data *data)
-{
-       unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
-
-       __raw_writel(bitval, S3C2412_EINTPEND);
-       __raw_writel(bitval, S3C2410_SRCPND);
-       __raw_writel(bitval, S3C2410_INTPND);
-}
-
-static inline void
-s3c2412_irq_maskack(struct irq_data *data)
-{
-       unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
-       unsigned long mask;
-
-       mask = __raw_readl(S3C2410_INTMSK);
-       __raw_writel(mask|bitval, S3C2410_INTMSK);
-
-       mask = __raw_readl(S3C2412_EINTMASK);
-       __raw_writel(mask | bitval, S3C2412_EINTMASK);
-
-       __raw_writel(bitval, S3C2412_EINTPEND);
-       __raw_writel(bitval, S3C2410_SRCPND);
-       __raw_writel(bitval, S3C2410_INTPND);
-}
-
-static void
-s3c2412_irq_unmask(struct irq_data *data)
-{
-       unsigned long bitval = 1UL << (data->irq - IRQ_EINT0);
-       unsigned long mask;
-
-       mask = __raw_readl(S3C2412_EINTMASK);
-       __raw_writel(mask & ~bitval, S3C2412_EINTMASK);
-
-       mask = __raw_readl(S3C2410_INTMSK);
-       __raw_writel(mask & ~bitval, S3C2410_INTMSK);
-}
-
-static struct irq_chip s3c2412_irq_eint0t4 = {
-       .irq_ack        = s3c2412_irq_ack,
-       .irq_mask       = s3c2412_irq_mask,
-       .irq_unmask     = s3c2412_irq_unmask,
-       .irq_set_wake   = s3c_irq_wake,
-       .irq_set_type   = s3c_irqext_type,
-};
-
-#define INTBIT(x)      (1 << ((x) - S3C2410_IRQSUB(0)))
-
-/* CF and SDI sub interrupts */
-
-static void s3c2412_irq_demux_cfsdi(unsigned int irq, struct irq_desc *desc)
-{
-       unsigned int subsrc, submsk;
-
-       subsrc = __raw_readl(S3C2410_SUBSRCPND);
-       submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-       subsrc  &= ~submsk;
-
-       if (subsrc & INTBIT(IRQ_S3C2412_SDI))
-               generic_handle_irq(IRQ_S3C2412_SDI);
-
-       if (subsrc & INTBIT(IRQ_S3C2412_CF))
-               generic_handle_irq(IRQ_S3C2412_CF);
-}
-
-#define INTMSK_CFSDI   (1UL << (IRQ_S3C2412_CFSDI - IRQ_EINT0))
-#define SUBMSK_CFSDI   INTMSK_SUB(IRQ_S3C2412_SDI, IRQ_S3C2412_CF)
-
-static void s3c2412_irq_cfsdi_mask(struct irq_data *data)
-{
-       s3c_irqsub_mask(data->irq, INTMSK_CFSDI, SUBMSK_CFSDI);
-}
-
-static void s3c2412_irq_cfsdi_unmask(struct irq_data *data)
-{
-       s3c_irqsub_unmask(data->irq, INTMSK_CFSDI);
-}
-
-static void s3c2412_irq_cfsdi_ack(struct irq_data *data)
-{
-       s3c_irqsub_maskack(data->irq, INTMSK_CFSDI, SUBMSK_CFSDI);
-}
-
-static struct irq_chip s3c2412_irq_cfsdi = {
-       .name           = "s3c2412-cfsdi",
-       .irq_ack        = s3c2412_irq_cfsdi_ack,
-       .irq_mask       = s3c2412_irq_cfsdi_mask,
-       .irq_unmask     = s3c2412_irq_cfsdi_unmask,
-};
-
-static int s3c2412_irq_rtc_wake(struct irq_data *data, unsigned int state)
-{
-       unsigned long pwrcfg;
-
-       pwrcfg = __raw_readl(S3C2412_PWRCFG);
-       if (state)
-               pwrcfg &= ~S3C2412_PWRCFG_RTC_MASKIRQ;
-       else
-               pwrcfg |= S3C2412_PWRCFG_RTC_MASKIRQ;
-       __raw_writel(pwrcfg, S3C2412_PWRCFG);
-
-       return s3c_irq_chip.irq_set_wake(data, state);
-}
-
-static struct irq_chip s3c2412_irq_rtc_chip;
-
-static int s3c2412_irq_add(struct device *dev, struct subsys_interface *sif)
-{
-       unsigned int irqno;
-
-       for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
-               irq_set_chip_and_handler(irqno, &s3c2412_irq_eint0t4,
-                                        handle_edge_irq);
-               set_irq_flags(irqno, IRQF_VALID);
-       }
-
-       /* add demux support for CF/SDI */
-
-       irq_set_chained_handler(IRQ_S3C2412_CFSDI, s3c2412_irq_demux_cfsdi);
-
-       for (irqno = IRQ_S3C2412_SDI; irqno <= IRQ_S3C2412_CF; irqno++) {
-               irq_set_chip_and_handler(irqno, &s3c2412_irq_cfsdi,
-                                        handle_level_irq);
-               set_irq_flags(irqno, IRQF_VALID);
-       }
-
-       /* change RTC IRQ's set wake method */
-
-       s3c2412_irq_rtc_chip = s3c_irq_chip;
-       s3c2412_irq_rtc_chip.irq_set_wake = s3c2412_irq_rtc_wake;
-
-       irq_set_chip(IRQ_RTC, &s3c2412_irq_rtc_chip);
-
-       return 0;
-}
-
-static struct subsys_interface s3c2412_irq_interface = {
-       .name           = "s3c2412_irq",
-       .subsys         = &s3c2412_subsys,
-       .add_dev        = s3c2412_irq_add,
-};
-
-static int s3c2412_irq_init(void)
-{
-       return subsys_interface_register(&s3c2412_irq_interface);
-}
-
-arch_initcall(s3c2412_irq_init);
diff --git a/arch/arm/mach-s3c24xx/irq-s3c2440.c b/arch/arm/mach-s3c24xx/irq-s3c2440.c
deleted file mode 100644 (file)
index 4a18cde..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-/* linux/arch/arm/mach-s3c2440/irq.c
- *
- * Copyright (c) 2003-2004 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 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/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/cpu.h>
-#include <plat/pm.h>
-#include <plat/irq.h>
-
-/* WDT/AC97 */
-
-static void s3c_irq_demux_wdtac97(unsigned int irq,
-                                 struct irq_desc *desc)
-{
-       unsigned int subsrc, submsk;
-
-       /* read the current pending interrupts, and the mask
-        * for what it is available */
-
-       subsrc = __raw_readl(S3C2410_SUBSRCPND);
-       submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-       subsrc &= ~submsk;
-       subsrc >>= 13;
-       subsrc &= 3;
-
-       if (subsrc != 0) {
-               if (subsrc & 1) {
-                       generic_handle_irq(IRQ_S3C2440_WDT);
-               }
-               if (subsrc & 2) {
-                       generic_handle_irq(IRQ_S3C2440_AC97);
-               }
-       }
-}
-
-
-#define INTMSK_WDT      (1UL << (IRQ_WDT - IRQ_EINT0))
-
-static void
-s3c_irq_wdtac97_mask(struct irq_data *data)
-{
-       s3c_irqsub_mask(data->irq, INTMSK_WDT, 3 << 13);
-}
-
-static void
-s3c_irq_wdtac97_unmask(struct irq_data *data)
-{
-       s3c_irqsub_unmask(data->irq, INTMSK_WDT);
-}
-
-static void
-s3c_irq_wdtac97_ack(struct irq_data *data)
-{
-       s3c_irqsub_maskack(data->irq, INTMSK_WDT, 3 << 13);
-}
-
-static struct irq_chip s3c_irq_wdtac97 = {
-       .irq_mask       = s3c_irq_wdtac97_mask,
-       .irq_unmask     = s3c_irq_wdtac97_unmask,
-       .irq_ack        = s3c_irq_wdtac97_ack,
-};
-
-static int s3c2440_irq_add(struct device *dev, struct subsys_interface *sif)
-{
-       unsigned int irqno;
-
-       printk("S3C2440: IRQ Support\n");
-
-       /* add new chained handler for wdt, ac7 */
-
-       irq_set_chip_and_handler(IRQ_WDT, &s3c_irq_level_chip,
-                                handle_level_irq);
-       irq_set_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
-
-       for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
-               irq_set_chip_and_handler(irqno, &s3c_irq_wdtac97,
-                                        handle_level_irq);
-               set_irq_flags(irqno, IRQF_VALID);
-       }
-
-       return 0;
-}
-
-static struct subsys_interface s3c2440_irq_interface = {
-       .name           = "s3c2440_irq",
-       .subsys         = &s3c2440_subsys,
-       .add_dev        = s3c2440_irq_add,
-};
-
-static int s3c2440_irq_init(void)
-{
-       return subsys_interface_register(&s3c2440_irq_interface);
-}
-
-arch_initcall(s3c2440_irq_init);
-
diff --git a/arch/arm/mach-s3c24xx/irq-s3c244x.c b/arch/arm/mach-s3c24xx/irq-s3c244x.c
deleted file mode 100644 (file)
index 5fe8e58..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/* linux/arch/arm/plat-s3c24xx/s3c244x-irq.c
- *
- * Copyright (c) 2003-2004 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 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/module.h>
-#include <linux/interrupt.h>
-#include <linux/ioport.h>
-#include <linux/device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <asm/mach/irq.h>
-
-#include <mach/regs-irq.h>
-#include <mach/regs-gpio.h>
-
-#include <plat/cpu.h>
-#include <plat/pm.h>
-#include <plat/irq.h>
-
-/* camera irq */
-
-static void s3c_irq_demux_cam(unsigned int irq,
-                             struct irq_desc *desc)
-{
-       unsigned int subsrc, submsk;
-
-       /* read the current pending interrupts, and the mask
-        * for what it is available */
-
-       subsrc = __raw_readl(S3C2410_SUBSRCPND);
-       submsk = __raw_readl(S3C2410_INTSUBMSK);
-
-       subsrc &= ~submsk;
-       subsrc >>= 11;
-       subsrc &= 3;
-
-       if (subsrc != 0) {
-               if (subsrc & 1) {
-                       generic_handle_irq(IRQ_S3C2440_CAM_C);
-               }
-               if (subsrc & 2) {
-                       generic_handle_irq(IRQ_S3C2440_CAM_P);
-               }
-       }
-}
-
-#define INTMSK_CAM (1UL << (IRQ_CAM - IRQ_EINT0))
-
-static void
-s3c_irq_cam_mask(struct irq_data *data)
-{
-       s3c_irqsub_mask(data->irq, INTMSK_CAM, 3 << 11);
-}
-
-static void
-s3c_irq_cam_unmask(struct irq_data *data)
-{
-       s3c_irqsub_unmask(data->irq, INTMSK_CAM);
-}
-
-static void
-s3c_irq_cam_ack(struct irq_data *data)
-{
-       s3c_irqsub_maskack(data->irq, INTMSK_CAM, 3 << 11);
-}
-
-static struct irq_chip s3c_irq_cam = {
-       .irq_mask       = s3c_irq_cam_mask,
-       .irq_unmask     = s3c_irq_cam_unmask,
-       .irq_ack        = s3c_irq_cam_ack,
-};
-
-static int s3c244x_irq_add(struct device *dev, struct subsys_interface *sif)
-{
-       unsigned int irqno;
-
-       irq_set_chip_and_handler(IRQ_NFCON, &s3c_irq_level_chip,
-                                handle_level_irq);
-       set_irq_flags(IRQ_NFCON, IRQF_VALID);
-
-       /* add chained handler for camera */
-
-       irq_set_chip_and_handler(IRQ_CAM, &s3c_irq_level_chip,
-                                handle_level_irq);
-       irq_set_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
-
-       for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
-               irq_set_chip_and_handler(irqno, &s3c_irq_cam,
-                                        handle_level_irq);
-               set_irq_flags(irqno, IRQF_VALID);
-       }
-
-       return 0;
-}
-
-static struct subsys_interface s3c2440_irq_interface = {
-       .name           = "s3c2440_irq",
-       .subsys         = &s3c2440_subsys,
-       .add_dev        = s3c244x_irq_add,
-};
-
-static int s3c2440_irq_init(void)
-{
-       return subsys_interface_register(&s3c2440_irq_interface);
-}
-
-arch_initcall(s3c2440_irq_init);
-
-static struct subsys_interface s3c2442_irq_interface = {
-       .name           = "s3c2442_irq",
-       .subsys         = &s3c2442_subsys,
-       .add_dev        = s3c244x_irq_add,
-};
-
-
-static int s3c2442_irq_init(void)
-{
-       return subsys_interface_register(&s3c2442_irq_interface);
-}
-
-arch_initcall(s3c2442_irq_init);
index 0e0279e79150e781ae82f3c4c048921445abf5aa..e27b5c91b3db230b0cc6126ebf20e6c1f73ea104 100644 (file)
@@ -63,6 +63,8 @@
 #include <linux/mtd/map.h>
 #include <linux/mtd/physmap.h>
 
+#include <plat/samsung-time.h>
+
 #include "common.h"
 
 static struct resource amlm5900_nor_resource =
@@ -160,6 +162,7 @@ static void __init amlm5900_map_io(void)
        s3c24xx_init_io(amlm5900_iodesc, ARRAY_SIZE(amlm5900_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(amlm5900_uartcfgs, ARRAY_SIZE(amlm5900_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 #ifdef CONFIG_FB_S3C2410
@@ -235,8 +238,8 @@ static void __init amlm5900_init(void)
 MACHINE_START(AML_M5900, "AML_M5900")
        .atag_offset    = 0x100,
        .map_io         = amlm5900_map_io,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .init_machine   = amlm5900_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index bb595f15ce36c8f2788621462eec2aa010b8f565..c1fb6c37867f2ad54af7da5f379acd031d55784e 100644 (file)
@@ -49,6 +49,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <linux/platform_data/asoc-s3c24xx_simtec.h>
+#include <plat/samsung-time.h>
 
 #include "anubis.h"
 #include "common.h"
@@ -410,6 +411,7 @@ static void __init anubis_map_io(void)
        s3c24xx_init_io(anubis_iodesc, ARRAY_SIZE(anubis_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(anubis_uartcfgs, ARRAY_SIZE(anubis_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
        /* check for the newer revision boards with large page nand */
 
@@ -443,7 +445,7 @@ MACHINE_START(ANUBIS, "Simtec-Anubis")
        .atag_offset    = 0x100,
        .map_io         = anubis_map_io,
        .init_machine   = anubis_init,
-       .init_irq       = s3c24xx_init_irq,
-       .init_time      = s3c24xx_timer_init,
+       .init_irq       = s3c2440_init_irq,
+       .init_time      = samsung_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index b4bc60c78ebb89f06bb4af29066b71638b031608..6dfeeb7ef4693a8fd8f86a06c770c7d66175580a 100644 (file)
@@ -48,6 +48,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <linux/platform_data/mmc-s3cmci.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -192,6 +193,7 @@ static void __init at2440evb_map_io(void)
        s3c24xx_init_io(at2440evb_iodesc, ARRAY_SIZE(at2440evb_iodesc));
        s3c24xx_init_clocks(16934400);
        s3c24xx_init_uarts(at2440evb_uartcfgs, ARRAY_SIZE(at2440evb_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init at2440evb_init(void)
@@ -209,7 +211,7 @@ MACHINE_START(AT2440EVB, "AT2440EVB")
        .atag_offset    = 0x100,
        .map_io         = at2440evb_map_io,
        .init_machine   = at2440evb_init,
-       .init_irq       = s3c24xx_init_irq,
-       .init_time      = s3c24xx_timer_init,
+       .init_irq       = s3c2440_init_irq,
+       .init_time      = samsung_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index ca661808104171a6ec13683868aa71bc69ecacf8..22d6ae926d91c996ac7bc98425a1a5aa65d872d0 100644 (file)
@@ -55,6 +55,7 @@
 #include <plat/devs.h>
 #include <plat/gpio-cfg.h>
 #include <plat/regs-serial.h>
+#include <plat/samsung-time.h>
 
 #include "bast.h"
 #include "common.h"
@@ -576,6 +577,7 @@ static void __init bast_map_io(void)
        s3c24xx_init_io(bast_iodesc, ARRAY_SIZE(bast_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(bast_uartcfgs, ARRAY_SIZE(bast_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init bast_init(void)
@@ -603,8 +605,8 @@ MACHINE_START(BAST, "Simtec-BAST")
        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
        .atag_offset    = 0x100,
        .map_io         = bast_map_io,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .init_machine   = bast_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index a25e8c5a7b4c9a3fe236af761e08814c97234267..13d8d073675a577d7b5de70b709cbd1c8a848743 100644 (file)
@@ -81,6 +81,7 @@
 #include <plat/gpio-cfg.h>
 #include <plat/pm.h>
 #include <plat/regs-serial.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "gta02.h"
@@ -501,6 +502,7 @@ static void __init gta02_map_io(void)
        s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 
@@ -587,8 +589,8 @@ MACHINE_START(NEO1973_GTA02, "GTA02")
        /* Maintainer: Nelson Castillo <arhuaco@freaks-unidos.net> */
        .atag_offset    = 0x100,
        .map_io         = gta02_map_io,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2442_init_irq,
        .init_machine   = gta02_machine_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index 79bc0830d740658986ed6cb1739310f71252020d..af4334d6b4d532c60937154019a7816e4276f36c 100644 (file)
@@ -62,7 +62,7 @@
 #include <plat/pll.h>
 #include <plat/pm.h>
 #include <plat/regs-serial.h>
-
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "h1940.h"
@@ -646,6 +646,7 @@ static void __init h1940_map_io(void)
        s3c24xx_init_io(h1940_iodesc, ARRAY_SIZE(h1940_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(h1940_uartcfgs, ARRAY_SIZE(h1940_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
        /* setup PM */
 
@@ -666,11 +667,6 @@ static void __init h1940_reserve(void)
        memblock_reserve(0x30081000, 0x1000);
 }
 
-static void __init h1940_init_irq(void)
-{
-       s3c24xx_init_irq();
-}
-
 static void __init h1940_init(void)
 {
        u32 tmp;
@@ -739,8 +735,8 @@ MACHINE_START(H1940, "IPAQ-H1940")
        .atag_offset    = 0x100,
        .map_io         = h1940_map_io,
        .reserve        = h1940_reserve,
-       .init_irq       = h1940_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .init_machine   = h1940_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index 54e83c1f780c569358c820046afccea0f41f62de..a45fcd8ccf796016c9007d0d7a44e089f30a9497 100644 (file)
 #include <linux/mtd/nand_ecc.h>
 #include <linux/mtd/partitions.h>
 
-#include <plat/s3c2412.h>
 #include <plat/gpio-cfg.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/pm.h>
 #include <linux/platform_data/usb-s3c2410_udc.h>
+#include <plat/samsung-time.h>
 
+#include "common.h"
 #include "s3c2412-power.h"
 
 static struct map_desc jive_iodesc[] __initdata = {
@@ -506,6 +507,7 @@ static void __init jive_map_io(void)
        s3c24xx_init_io(jive_iodesc, ARRAY_SIZE(jive_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(jive_uartcfgs, ARRAY_SIZE(jive_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void jive_power_off(void)
@@ -658,9 +660,9 @@ MACHINE_START(JIVE, "JIVE")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
        .atag_offset    = 0x100,
 
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2412_init_irq,
        .map_io         = jive_map_io,
        .init_machine   = jive_machine_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2412_restart,
 MACHINE_END
index 2865e5919f2cb8a176a54d9d463afdeda4c8731f..a83db46320bc6d1e8345ebee8aefd3845f9b347f 100644 (file)
@@ -56,6 +56,7 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/samsung-time.h>
 
 #include <sound/s3c24xx_uda134x.h>
 
@@ -525,6 +526,7 @@ static void __init mini2440_map_io(void)
        s3c24xx_init_io(mini2440_iodesc, ARRAY_SIZE(mini2440_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 /*
@@ -686,7 +688,7 @@ MACHINE_START(MINI2440, "MINI2440")
        .atag_offset    = 0x100,
        .map_io         = mini2440_map_io,
        .init_machine   = mini2440_init,
-       .init_irq       = s3c24xx_init_irq,
-       .init_time      = s3c24xx_timer_init,
+       .init_irq       = s3c2440_init_irq,
+       .init_time      = samsung_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index d9d04b2402959eee8a6fd5c32c0718f15435161b..2cb46c37c92058450e7bb9ec575ec14779ff9ba7 100644 (file)
@@ -48,8 +48,8 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <linux/platform_data/mmc-s3cmci.h>
-#include <plat/s3c2410.h>
 #include <linux/platform_data/usb-s3c2410_udc.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -536,6 +536,7 @@ static void __init n30_map_io(void)
        n30_hwinit();
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(n30_uartcfgs, ARRAY_SIZE(n30_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 /* GPB3 is the line that controls the pull-up for the USB D+ line */
@@ -589,9 +590,9 @@ MACHINE_START(N30, "Acer-N30")
                                Ben Dooks <ben-linux@fluff.org>
        */
        .atag_offset    = 0x100,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .init_machine   = n30_init,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .map_io         = n30_map_io,
        .restart        = s3c2410_restart,
 MACHINE_END
@@ -600,9 +601,9 @@ MACHINE_START(N35, "Acer-N35")
        /* Maintainer: Christer Weinigel <christer@weinigel.se>
        */
        .atag_offset    = 0x100,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .init_machine   = n30_init,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .map_io         = n30_map_io,
        .restart        = s3c2410_restart,
 MACHINE_END
index a454e246186063694508f59f957e87f5f5142f00..01f4354206f99e9f423d2bc31f3c8d0fa37712ef 100644 (file)
 #include <linux/platform_data/i2c-s3c2410.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/s3c2410.h>
-#include <plat/s3c244x.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -137,6 +136,7 @@ static void __init nexcoder_map_io(void)
        s3c24xx_init_io(nexcoder_iodesc, ARRAY_SIZE(nexcoder_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(nexcoder_uartcfgs, ARRAY_SIZE(nexcoder_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
        nexcoder_sensorboard_init();
 }
@@ -152,7 +152,7 @@ MACHINE_START(NEXCODER_2440, "NexVision - Nexcoder 2440")
        .atag_offset    = 0x100,
        .map_io         = nexcoder_map_io,
        .init_machine   = nexcoder_init,
-       .init_irq       = s3c24xx_init_irq,
-       .init_time      = s3c24xx_timer_init,
+       .init_irq       = s3c2440_init_irq,
+       .init_time      = samsung_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index ae2cbdf3e3ca536e9a184342979ee3829b963bb6..58d6fbe5bf1fc7b59cde5de87eb99cbf573dbdde 100644 (file)
@@ -45,6 +45,7 @@
 #include <plat/devs.h>
 #include <plat/gpio-cfg.h>
 #include <plat/regs-serial.h>
+#include <plat/samsung-time.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-gpio.h>
@@ -384,6 +385,7 @@ static void __init osiris_map_io(void)
        s3c24xx_init_io(osiris_iodesc, ARRAY_SIZE(osiris_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(osiris_uartcfgs, ARRAY_SIZE(osiris_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
        /* check for the newer revision boards with large page nand */
 
@@ -424,8 +426,8 @@ MACHINE_START(OSIRIS, "Simtec-OSIRIS")
        /* Maintainer: Ben Dooks <ben@simtec.co.uk> */
        .atag_offset    = 0x100,
        .map_io         = osiris_map_io,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2440_init_irq,
        .init_machine   = osiris_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index 40a47d6c6a851e0a658f583a5af8fc20cb84d71e..7e16b0740ec1eb02208aba8a0f4dc72f13e300fc 100644 (file)
@@ -33,7 +33,7 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/regs-serial.h>
-#include <plat/s3c2410.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "otom.h"
@@ -102,6 +102,7 @@ static void __init otom11_map_io(void)
        s3c24xx_init_io(otom11_iodesc, ARRAY_SIZE(otom11_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(otom11_uartcfgs, ARRAY_SIZE(otom11_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init otom11_init(void)
@@ -115,7 +116,7 @@ MACHINE_START(OTOM, "Nex Vision - Otom 1.1")
        .atag_offset    = 0x100,
        .map_io         = otom11_map_io,
        .init_machine   = otom11_init,
-       .init_irq       = s3c24xx_init_irq,
-       .init_time      = s3c24xx_timer_init,
+       .init_irq       = s3c2410_init_irq,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index 56175f0941b101def5aae288abf011698441b69e..f8feaeadb55a43402912bccefbcb7313881f5422 100644 (file)
 #include <linux/platform_data/usb-s3c2410_udc.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 
-#include <plat/common-smdk.h>
 #include <plat/gpio-cfg.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/pm.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
+#include "common-smdk.h"
 
 static struct map_desc qt2410_iodesc[] __initdata = {
        { 0xe0000000, __phys_to_pfn(S3C2410_CS3+0x01000000), SZ_1M, MT_DEVICE }
@@ -304,6 +305,7 @@ static void __init qt2410_map_io(void)
        s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
        s3c24xx_init_clocks(12*1000*1000);
        s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init qt2410_machine_init(void)
@@ -341,8 +343,8 @@ static void __init qt2410_machine_init(void)
 MACHINE_START(QT2410, "QT2410")
        .atag_offset    = 0x100,
        .map_io         = qt2410_map_io,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .init_machine   = qt2410_machine_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index 1f9ba2ae5288ee83aa9d83300eb68181ba263612..e4d67a33ebee77d9d2dc5bb2de28d680a216c1c6 100644 (file)
@@ -58,6 +58,7 @@
 #include <plat/pm.h>
 #include <plat/regs-iic.h>
 #include <plat/regs-serial.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "h1940.h"
@@ -741,6 +742,7 @@ static void __init rx1950_map_io(void)
        s3c24xx_init_io(rx1950_iodesc, ARRAY_SIZE(rx1950_iodesc));
        s3c24xx_init_clocks(16934000);
        s3c24xx_init_uarts(rx1950_uartcfgs, ARRAY_SIZE(rx1950_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
        /* setup PM */
 
@@ -811,8 +813,8 @@ MACHINE_START(RX1950, "HP iPAQ RX1950")
        .atag_offset = 0x100,
        .map_io = rx1950_map_io,
        .reserve        = rx1950_reserve,
-       .init_irq = s3c24xx_init_irq,
+       .init_irq       = s3c2442_init_irq,
        .init_machine = rx1950_init_machine,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index f20418a2fb1b62e2bf882dd768da1fae52c4e288..3bc6231d0a1fc1becb922de1ccab7c4b08581d86 100644 (file)
@@ -49,6 +49,7 @@
 #include <plat/devs.h>
 #include <plat/pm.h>
 #include <plat/regs-serial.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "h1940.h"
@@ -179,6 +180,7 @@ static void __init rx3715_map_io(void)
        s3c24xx_init_io(rx3715_iodesc, ARRAY_SIZE(rx3715_iodesc));
        s3c24xx_init_clocks(16934000);
        s3c24xx_init_uarts(rx3715_uartcfgs, ARRAY_SIZE(rx3715_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 /* H1940 and RX3715 need to reserve this for suspend */
@@ -188,11 +190,6 @@ static void __init rx3715_reserve(void)
        memblock_reserve(0x30081000, 0x1000);
 }
 
-static void __init rx3715_init_irq(void)
-{
-       s3c24xx_init_irq();
-}
-
 static void __init rx3715_init_machine(void)
 {
 #ifdef CONFIG_PM_H1940
@@ -210,8 +207,8 @@ MACHINE_START(RX3715, "IPAQ-RX3715")
        .atag_offset    = 0x100,
        .map_io         = rx3715_map_io,
        .reserve        = rx3715_reserve,
-       .init_irq       = rx3715_init_irq,
+       .init_irq       = s3c2440_init_irq,
        .init_machine   = rx3715_init_machine,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index e184bfa9613aea23dc19a83d08eb88c0175667d6..a773789e4f38ec8cd87a8b8fd80aa2afbd696fbb 100644 (file)
 
 #include <plat/devs.h>
 #include <plat/cpu.h>
-
-#include <plat/common-smdk.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
+#include "common-smdk.h"
 
 static struct map_desc smdk2410_iodesc[] __initdata = {
   /* nothing here yet */
@@ -101,6 +101,7 @@ static void __init smdk2410_map_io(void)
        s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init smdk2410_init(void)
@@ -115,8 +116,8 @@ MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switc
        /* Maintainer: Jonas Dietsche */
        .atag_offset    = 0x100,
        .map_io         = smdk2410_map_io,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .init_machine   = smdk2410_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index 86d7847c9d4502820bd3754d2c589c1fec023ce4..8146e920f10d67313bbae45ddc81f47735eb67d1 100644 (file)
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <mach/fb.h>
 
-#include <plat/s3c2410.h>
-#include <plat/s3c2412.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/samsung-time.h>
 
-#include <plat/common-smdk.h>
+#include "common.h"
+#include "common-smdk.h"
 
 static struct map_desc smdk2413_iodesc[] __initdata = {
 };
@@ -106,6 +106,7 @@ static void __init smdk2413_map_io(void)
        s3c24xx_init_io(smdk2413_iodesc, ARRAY_SIZE(smdk2413_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(smdk2413_uartcfgs, ARRAY_SIZE(smdk2413_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init smdk2413_machine_init(void)
@@ -129,10 +130,10 @@ MACHINE_START(S3C2413, "S3C2413")
        .atag_offset    = 0x100,
 
        .fixup          = smdk2413_fixup,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2412_init_irq,
        .map_io         = smdk2413_map_io,
        .init_machine   = smdk2413_machine_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2412_restart,
 MACHINE_END
 
@@ -141,10 +142,10 @@ MACHINE_START(SMDK2412, "SMDK2412")
        .atag_offset    = 0x100,
 
        .fixup          = smdk2413_fixup,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2412_init_irq,
        .map_io         = smdk2413_map_io,
        .init_machine   = smdk2413_machine_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2412_restart,
 MACHINE_END
 
@@ -153,9 +154,9 @@ MACHINE_START(SMDK2413, "SMDK2413")
        .atag_offset    = 0x100,
 
        .fixup          = smdk2413_fixup,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2412_init_irq,
        .map_io         = smdk2413_map_io,
        .init_machine   = smdk2413_machine_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2412_restart,
 MACHINE_END
index ebb2e61f3d079c4503b6285cade566eddaa26af4..cb46847c66b4a71c50272a4d847ca49356266742 100644 (file)
@@ -42,7 +42,6 @@
 #include <linux/platform_data/leds-s3c24xx.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 
-#include <plat/s3c2416.h>
 #include <plat/gpio-cfg.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/sdhci.h>
 #include <linux/platform_data/usb-s3c2410_udc.h>
 #include <linux/platform_data/s3c-hsudc.h>
+#include <plat/samsung-time.h>
 
 #include <plat/fb.h>
 
-#include <plat/common-smdk.h>
+#include "common.h"
+#include "common-smdk.h"
 
 static struct map_desc smdk2416_iodesc[] __initdata = {
        /* ISA IO Space map (memory space selected by A24) */
@@ -221,6 +222,7 @@ static void __init smdk2416_map_io(void)
        s3c24xx_init_io(smdk2416_iodesc, ARRAY_SIZE(smdk2416_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(smdk2416_uartcfgs, ARRAY_SIZE(smdk2416_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init smdk2416_machine_init(void)
@@ -253,6 +255,6 @@ MACHINE_START(SMDK2416, "SMDK2416")
        .init_irq       = s3c2416_init_irq,
        .map_io         = smdk2416_map_io,
        .init_machine   = smdk2416_machine_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2416_restart,
 MACHINE_END
index 08cc38c8a4aee6d2e8142a5d05d6599c59c46176..de2e5d39a8471b490a90be86ea966c6b835ba02a 100644 (file)
 #include <mach/fb.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 
-#include <plat/s3c2410.h>
-#include <plat/s3c244x.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
-
-#include <plat/common-smdk.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
+#include "common-smdk.h"
 
 static struct map_desc smdk2440_iodesc[] __initdata = {
        /* ISA IO Space map (memory space selected by A24) */
@@ -163,6 +161,7 @@ static void __init smdk2440_map_io(void)
        s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
        s3c24xx_init_clocks(16934400);
        s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init smdk2440_machine_init(void)
@@ -178,9 +177,9 @@ MACHINE_START(S3C2440, "SMDK2440")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
        .atag_offset    = 0x100,
 
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2440_init_irq,
        .map_io         = smdk2440_map_io,
        .init_machine   = smdk2440_machine_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c244x_restart,
 MACHINE_END
index fc65d74d3c73f7567caa9cd2eebd17d0f165f020..9435c3bef18a91c53da53dcc29e68498bc834946 100644 (file)
 #include <mach/fb.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 
-#include <plat/s3c2410.h>
-#include <plat/s3c2443.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/samsung-time.h>
 
-#include <plat/common-smdk.h>
+#include "common.h"
+#include "common-smdk.h"
 
 static struct map_desc smdk2443_iodesc[] __initdata = {
        /* ISA IO Space map (memory space selected by A24) */
@@ -122,6 +122,7 @@ static void __init smdk2443_map_io(void)
        s3c24xx_init_io(smdk2443_iodesc, ARRAY_SIZE(smdk2443_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(smdk2443_uartcfgs, ARRAY_SIZE(smdk2443_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init smdk2443_machine_init(void)
@@ -143,6 +144,6 @@ MACHINE_START(SMDK2443, "SMDK2443")
        .init_irq       = s3c2443_init_irq,
        .map_io         = smdk2443_map_io,
        .init_machine   = smdk2443_machine_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2443_restart,
 MACHINE_END
index 24b3d79e7b2c65174dd5aa84cd5d6c6af2abfd6b..7fad8f055cabc050b5aba9e1ecaf82c2fc1998f9 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/map.h>
 #include <linux/mtd/physmap.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -136,6 +137,7 @@ static void __init tct_hammer_map_io(void)
        s3c24xx_init_io(tct_hammer_iodesc, ARRAY_SIZE(tct_hammer_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(tct_hammer_uartcfgs, ARRAY_SIZE(tct_hammer_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init tct_hammer_init(void)
@@ -147,8 +149,8 @@ static void __init tct_hammer_init(void)
 MACHINE_START(TCT_HAMMER, "TCT_HAMMER")
        .atag_offset    = 0x100,
        .map_io         = tct_hammer_map_io,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2410_init_irq,
        .init_machine   = tct_hammer_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index ec42d1e4e465b5ef6b61d9089924b41de501b6ca..42e7187fed6090fbef193901984cbd9e5cc0582c 100644 (file)
@@ -45,6 +45,7 @@
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/regs-serial.h>
+#include <plat/samsung-time.h>
 
 #include "bast.h"
 #include "common.h"
@@ -332,6 +333,7 @@ static void __init vr1000_map_io(void)
        s3c24xx_init_io(vr1000_iodesc, ARRAY_SIZE(vr1000_iodesc));
        s3c24xx_init_clocks(0);
        s3c24xx_init_uarts(vr1000_uartcfgs, ARRAY_SIZE(vr1000_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init vr1000_init(void)
@@ -353,7 +355,7 @@ MACHINE_START(VR1000, "Thorcom-VR1000")
        .atag_offset    = 0x100,
        .map_io         = vr1000_map_io,
        .init_machine   = vr1000_init,
-       .init_irq       = s3c24xx_init_irq,
-       .init_time      = s3c24xx_timer_init,
+       .init_irq       = s3c2410_init_irq,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2410_restart,
 MACHINE_END
index 3e2bfddc9df126469b4778141449e9a8f9dd3df5..b66588428ec90e7b0d4c056f60e8ddc2e5dc36be 100644 (file)
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <linux/platform_data/mtd-nand-s3c2410.h>
 
-#include <plat/s3c2410.h>
-#include <plat/s3c2412.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/samsung-time.h>
 
+#include "common.h"
 
 static struct map_desc vstms_iodesc[] __initdata = {
 };
@@ -143,6 +143,7 @@ static void __init vstms_map_io(void)
        s3c24xx_init_io(vstms_iodesc, ARRAY_SIZE(vstms_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(vstms_uartcfgs, ARRAY_SIZE(vstms_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init vstms_init(void)
@@ -157,9 +158,9 @@ MACHINE_START(VSTMS, "VSTMS")
        .atag_offset    = 0x100,
 
        .fixup          = vstms_fixup,
-       .init_irq       = s3c24xx_init_irq,
+       .init_irq       = s3c2412_init_irq,
        .init_machine   = vstms_init,
        .map_io         = vstms_map_io,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c2412_restart,
 MACHINE_END
index 668a78a8b19518a07dff82f4e6cc8e702d6e8be5..d75f95e487ee6414eb7d02908bbdf5320475950a 100644 (file)
@@ -29,7 +29,7 @@
 
 #include <plat/cpu.h>
 #include <plat/pm.h>
-#include <plat/s3c2412.h>
+#include <plat/wakeup-mask.h>
 
 #include "regs-dsc.h"
 #include "s3c2412-power.h"
@@ -52,8 +52,15 @@ static int s3c2412_cpu_suspend(unsigned long arg)
        return 1; /* Aborting suspend */
 }
 
+/* mapping of interrupts to parts of the wakeup mask */
+static struct samsung_wakeup_mask wake_irqs[] = {
+       { .irq = IRQ_RTC,       .bit = S3C2412_PWRCFG_RTC_MASKIRQ, },
+};
+
 static void s3c2412_pm_prepare(void)
 {
+       samsung_sync_wakemask(S3C2412_PWRCFG,
+                             wake_irqs, ARRAY_SIZE(wake_irqs));
 }
 
 static int s3c2412_pm_add(struct device *dev, struct subsys_interface *sif)
index 9ebef95da721d4fcd81650a04127609d170fb2cd..d850ea5adac26f142beb8beb8b1c03c2637ffc58 100644 (file)
@@ -37,7 +37,6 @@
 #include <mach/regs-clock.h>
 #include <plat/regs-serial.h>
 
-#include <plat/s3c2410.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
 #include <plat/clock.h>
index 0d592159a5c33492012aec32e59443aed2557862..0f864d4c97deae90cb0a3cd8dac24ede99af4904 100644 (file)
@@ -44,7 +44,6 @@
 #include <plat/pm.h>
 #include <plat/regs-serial.h>
 #include <plat/regs-spi.h>
-#include <plat/s3c2412.h>
 
 #include "common.h"
 #include "regs-dsc.h"
index e30476db0295b848630ddd616c990ca084c13e9b..b9c5d382dafb973b8258ae2cdbb9241436726a0b 100644 (file)
@@ -50,7 +50,6 @@
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
 #include <plat/gpio-cfg-helpers.h>
-#include <plat/s3c2416.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/sdhci.h>
index 559e394e89895a79f68809621c1458112f4abd9b..5f9d6569475d713cacf7be730d4c4fff6c9369ee 100644 (file)
@@ -33,7 +33,6 @@
 
 #include <plat/devs.h>
 #include <plat/cpu.h>
-#include <plat/s3c244x.h>
 #include <plat/pm.h>
 
 #include <plat/gpio-core.h>
index f732826c23593ef80d0b4f4d5f68e9cee9a6715e..6819961f6b19c0f6cfc7d41b3bb28e386f2869d2 100644 (file)
@@ -44,7 +44,6 @@
 
 #include <plat/clock.h>
 #include <plat/cpu.h>
-#include <plat/s3c244x.h>
 #include <plat/pm.h>
 
 #include <plat/gpio-core.h>
index 165b6a6b3daaa9450201db7b0c721f76c62574f2..8328cd65bf3d44c4255f3c5eb66382473e4ffdef 100644 (file)
@@ -36,7 +36,6 @@
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
 #include <plat/gpio-cfg-helpers.h>
-#include <plat/s3c2443.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/fb-core.h>
index ad2671baa910dbc1a1ad43000df6730e00e3ff64..2a35edb6735499b9f78c8fb01e3d2fba07548522 100644 (file)
@@ -37,8 +37,6 @@
 #include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
 
-#include <plat/s3c2410.h>
-#include <plat/s3c244x.h>
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
index 131c86284711daa565ab89a350a79ba72d687422..283cb77d47211a2e4a840b8b772a3b82dff1d32d 100644 (file)
@@ -17,11 +17,13 @@ config PLAT_S3C64XX
 # Configuration options for the S3C6410 CPU
 
 config CPU_S3C6400
+       select SAMSUNG_HRT
        bool
        help
          Enable S3C6400 CPU support
 
 config CPU_S3C6410
+       select SAMSUNG_HRT
        bool
        help
          Enable S3C6410 CPU support
index c0c076a90f27ad4ea1f3f2715d836f52ccebc618..dd9ccca5de1f3eb2a50ededc605fb5a36f2924e2 100644 (file)
@@ -35,4 +35,4 @@
  * will be fine with us.
  */
 
-#include <plat/debug-macro.S>
+#include <debug/samsung.S>
index 728eef3296b2d19c5a878cdc49d1685c18b44313..35e3f54574eff6773f5c2eca10b69d0d1e02cccc 100644 (file)
@@ -49,6 +49,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <mach/regs-gpio.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "regs-modem.h"
@@ -208,6 +209,7 @@ static void __init anw6410_map_io(void)
        s3c64xx_init_io(anw6410_iodesc, ARRAY_SIZE(anw6410_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(anw6410_uartcfgs, ARRAY_SIZE(anw6410_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
        anw6410_lcd_mode_set();
 }
@@ -232,6 +234,6 @@ MACHINE_START(ANW6410, "A&W6410")
        .map_io         = anw6410_map_io,
        .init_machine   = anw6410_machine_init,
        .init_late      = s3c64xx_init_late,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index 1acf02bace57074429bfec20ee7b362f4dbdf938..8ad88ace795a41cc617a1cdba91aa08e46856e04 100644 (file)
@@ -64,6 +64,7 @@
 #include <plat/adc.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/pm.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "crag6410.h"
@@ -744,6 +745,7 @@ 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));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
        /* LCD type and Bypass set by bootloader */
 }
@@ -868,6 +870,6 @@ MACHINE_START(WLF_CRAGG_6410, "Wolfson Cragganmore 6410")
        .map_io         = crag6410_map_io,
        .init_machine   = crag6410_machine_init,
        .init_late      = s3c64xx_init_late,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index 7212eb9cfeb9f255f5581b485a2f34eb4afd0261..5b7f357d8c22c1de54a8e62a8b8225cf48af63e6 100644 (file)
@@ -41,6 +41,7 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -248,6 +249,7 @@ static void __init hmt_map_io(void)
        s3c64xx_init_io(hmt_iodesc, ARRAY_SIZE(hmt_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(hmt_uartcfgs, ARRAY_SIZE(hmt_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init hmt_machine_init(void)
@@ -275,6 +277,6 @@ MACHINE_START(HMT, "Airgoo-HMT")
        .map_io         = hmt_map_io,
        .init_machine   = hmt_machine_init,
        .init_late      = s3c64xx_init_late,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index 4b41fcdaa7b663465f4a3d00c1f66e668ea478ef..fc043e3ecdf8a869ea77e27af42dad5c24222356 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <video/platform_lcd.h>
 #include <video/samsung_fimd.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "regs-modem.h"
@@ -232,6 +233,7 @@ static void __init mini6410_map_io(void)
        s3c64xx_init_io(NULL, 0);
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(mini6410_uartcfgs, ARRAY_SIZE(mini6410_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
        /* set the LCD type */
        tmp = __raw_readl(S3C64XX_SPCON);
@@ -354,6 +356,6 @@ MACHINE_START(MINI6410, "MINI6410")
        .map_io         = mini6410_map_io,
        .init_machine   = mini6410_machine_init,
        .init_late      = s3c64xx_init_late,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index 8d3cedd995ffd43a88c1398cff7ce5ddaa33bbb9..7e2c3908f1f87a2db546867d9ff8417e2051049e 100644 (file)
@@ -43,6 +43,7 @@
 #include <plat/clock.h>
 #include <plat/devs.h>
 #include <plat/cpu.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -87,6 +88,7 @@ static void __init ncp_map_io(void)
        s3c64xx_init_io(ncp_iodesc, ARRAY_SIZE(ncp_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(ncp_uartcfgs, ARRAY_SIZE(ncp_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init ncp_machine_init(void)
@@ -103,6 +105,6 @@ MACHINE_START(NCP, "NCP")
        .map_io         = ncp_map_io,
        .init_machine   = ncp_machine_init,
        .init_late      = s3c64xx_init_late,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index fa12bd21ad82058f51934f6a5e063e260bfadbfc..8bed37b3d5ac8897eaa49912f67edacdbed238fe 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <video/platform_lcd.h>
 #include <video/samsung_fimd.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "regs-modem.h"
@@ -211,6 +212,7 @@ static void __init real6410_map_io(void)
        s3c64xx_init_io(NULL, 0);
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(real6410_uartcfgs, ARRAY_SIZE(real6410_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
        /* set the LCD type */
        tmp = __raw_readl(S3C64XX_SPCON);
@@ -333,6 +335,6 @@ MACHINE_START(REAL6410, "REAL6410")
        .map_io         = real6410_map_io,
        .init_machine   = real6410_machine_init,
        .init_late      = s3c64xx_init_late,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index fc3e9b32e26fb235a38e226b4659cc1bca21ca5d..58ac99041274e86b187826f8349bcf8c93d53d9b 100644 (file)
@@ -38,6 +38,7 @@
 #include <linux/platform_data/touchscreen-s3c2410.h>
 
 #include <video/platform_lcd.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "regs-modem.h"
@@ -378,6 +379,7 @@ void __init smartq_map_io(void)
        s3c64xx_init_io(smartq_iodesc, ARRAY_SIZE(smartq_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(smartq_uartcfgs, ARRAY_SIZE(smartq_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
        smartq_lcd_mode_set();
 }
index ca2afcfce57391f29721325229246895002823ed..8aca5daf3d05a10b62184969109c1a59c9744438 100644 (file)
@@ -28,6 +28,7 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "mach-smartq.h"
@@ -155,6 +156,6 @@ MACHINE_START(SMARTQ5, "SmartQ 5")
        .map_io         = smartq_map_io,
        .init_machine   = smartq5_machine_init,
        .init_late      = s3c64xx_init_late,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index 37bb0c632a5efe1043b2473d053be656b0d38d73..a052e107c0b402a3ac7cab606da610e573ef7618 100644 (file)
@@ -28,6 +28,7 @@
 #include <plat/devs.h>
 #include <plat/fb.h>
 #include <plat/gpio-cfg.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "mach-smartq.h"
@@ -171,6 +172,6 @@ MACHINE_START(SMARTQ7, "SmartQ 7")
        .map_io         = smartq_map_io,
        .init_machine   = smartq7_machine_init,
        .init_late      = s3c64xx_init_late,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index a392869c834262360ec0ce5a51abffca27977bc4..d70c0843aea2d8bca384cc814d0270e778def128 100644 (file)
@@ -35,6 +35,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <linux/platform_data/i2c-s3c2410.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -66,6 +67,7 @@ static void __init smdk6400_map_io(void)
        s3c64xx_init_io(smdk6400_iodesc, ARRAY_SIZE(smdk6400_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(smdk6400_uartcfgs, ARRAY_SIZE(smdk6400_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static struct platform_device *smdk6400_devices[] __initdata = {
@@ -92,6 +94,6 @@ MACHINE_START(SMDK6400, "SMDK6400")
        .map_io         = smdk6400_map_io,
        .init_machine   = smdk6400_machine_init,
        .init_late      = s3c64xx_init_late,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index ba7544e2d04d6fcec91205350601b042d5d247b8..bd3295a19ad7dc02f18f3e38c335d4ca2deda8f7 100644 (file)
@@ -69,6 +69,7 @@
 #include <linux/platform_data/touchscreen-s3c2410.h>
 #include <plat/keypad.h>
 #include <plat/backlight.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 #include "regs-modem.h"
@@ -634,6 +635,7 @@ static void __init smdk6410_map_io(void)
        s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc));
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 
        /* set the LCD type */
 
@@ -702,6 +704,6 @@ MACHINE_START(SMDK6410, "SMDK6410")
        .map_io         = smdk6410_map_io,
        .init_machine   = smdk6410_machine_init,
        .init_late      = s3c64xx_init_late,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s3c64xx_restart,
 MACHINE_END
index e8742cb7ddd955726d6c62637eae424c2a6924f5..5a707bdb9ea032172f5eef696d17593ffce3825f 100644 (file)
@@ -9,16 +9,16 @@ if ARCH_S5P64X0
 
 config CPU_S5P6440
        bool
-       select S5P_HRT
        select S5P_SLEEP if PM
        select SAMSUNG_DMADEV
+       select SAMSUNG_HRT
        select SAMSUNG_WAKEMASK if PM
        help
          Enable S5P6440 CPU support
 
 config CPU_S5P6450
        bool
-       select S5P_HRT
+       select SAMSUNG_HRT
        select S5P_SLEEP if PM
        select SAMSUNG_DMADEV
        select SAMSUNG_WAKEMASK if PM
index e80ba3c698143227ec9a6a505982e7c6a880d6fa..5e2916fb19a9f2f4f6f9c95b222cd7af86b09a28 100644 (file)
@@ -30,4 +30,4 @@
 #endif
        .endm
 
-#include <plat/debug-macro.S>
+#include <debug/samsung.S>
index e23723a5a21480d16c202cec050ea967eca1d41a..73f71a698a3434b26cca9a26128ae746dc719363 100644 (file)
@@ -48,7 +48,7 @@
 #include <plat/pll.h>
 #include <plat/adc.h>
 #include <linux/platform_data/touchscreen-s3c2410.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 #include <plat/backlight.h>
 #include <plat/fb.h>
 #include <plat/sdhci.h>
@@ -229,7 +229,7 @@ static void __init smdk6440_map_io(void)
        s5p64x0_init_io(NULL, 0);
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(smdk6440_uartcfgs, ARRAY_SIZE(smdk6440_uartcfgs));
-       s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void s5p6440_set_lcd_interface(void)
@@ -273,6 +273,6 @@ MACHINE_START(SMDK6440, "SMDK6440")
        .init_irq       = s5p6440_init_irq,
        .map_io         = smdk6440_map_io,
        .init_machine   = smdk6440_machine_init,
-       .init_time      = s5p_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s5p64x0_restart,
 MACHINE_END
index ca10963a959efdb3bf7ea9737e0fad5f79ca108a..18303e12019f3bffe1784950870f532b663f0ab0 100644 (file)
@@ -48,7 +48,7 @@
 #include <plat/pll.h>
 #include <plat/adc.h>
 #include <linux/platform_data/touchscreen-s3c2410.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 #include <plat/backlight.h>
 #include <plat/fb.h>
 #include <plat/sdhci.h>
@@ -248,7 +248,7 @@ static void __init smdk6450_map_io(void)
        s5p64x0_init_io(NULL, 0);
        s3c24xx_init_clocks(19200000);
        s3c24xx_init_uarts(smdk6450_uartcfgs, ARRAY_SIZE(smdk6450_uartcfgs));
-       s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void s5p6450_set_lcd_interface(void)
@@ -292,6 +292,6 @@ MACHINE_START(SMDK6450, "SMDK6450")
        .init_irq       = s5p6450_init_irq,
        .map_io         = smdk6450_map_io,
        .init_machine   = smdk6450_machine_init,
-       .init_time      = s5p_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s5p64x0_restart,
 MACHINE_END
index 15170be97a74c0ecc69dd481d087205912095837..2f456a4533bafaa332dfaf548f469aec7cf64b7e 100644 (file)
@@ -11,6 +11,7 @@ config CPU_S5PC100
        bool
        select S5P_EXT_INT
        select SAMSUNG_DMADEV
+       select SAMSUNG_HRT
        help
          Enable S5PC100 CPU support
 
index 694f759370008e1678c9b0a06c1ed21c0cf92411..66cb7f16bf2aa37f9ebfdab4a5ebd38bbf18d821 100644 (file)
@@ -36,4 +36,4 @@
  * will be fine with us.
  */
 
-#include <plat/debug-macro.S>
+#include <debug/samsung.S>
index 185a19583898dc3221d0fa69122a96a21a9d0a6b..8c880f76f27436302d739bc9f877c6769b67724b 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/platform_data/touchscreen-s3c2410.h>
 #include <linux/platform_data/asoc-s3c.h>
 #include <plat/backlight.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -221,6 +222,7 @@ static void __init smdkc100_map_io(void)
        s5pc100_init_io(NULL, 0);
        s3c24xx_init_clocks(12000000);
        s3c24xx_init_uarts(smdkc100_uartcfgs, ARRAY_SIZE(smdkc100_uartcfgs));
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init smdkc100_machine_init(void)
@@ -255,6 +257,6 @@ MACHINE_START(SMDKC100, "SMDKC100")
        .init_irq       = s5pc100_init_irq,
        .map_io         = smdkc100_map_io,
        .init_machine   = smdkc100_machine_init,
-       .init_time      = s3c24xx_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s5pc100_restart,
 MACHINE_END
index 03c02d04c68cd6e6cf0424bf559833a37881a01f..6010c0310cb5203b9d76861ea69c2db656110f64 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/mmc/card.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/regs-sdhci.h>
 #include <plat/sdhci.h>
 
 void s5pc100_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
index 92ad72f0ef980ea836c2a38ca7ffde7262b358c8..0963283a7c5dc886ccb5e8746c66752cefa1cf2a 100644 (file)
@@ -12,10 +12,10 @@ if ARCH_S5PV210
 config CPU_S5PV210
        bool
        select S5P_EXT_INT
-       select S5P_HRT
        select S5P_PM if PM
        select S5P_SLEEP if PM
        select SAMSUNG_DMADEV
+       select SAMSUNG_HRT
        help
          Enable S5PV210 CPU support
 
index fcdf52dbcc49f9bb8525790bc77953db7f452b73..f051f53e35b7bcb3d2ec85af45d2e4d8071fa821 100644 (file)
@@ -214,11 +214,6 @@ static struct clk clk_pcmcdclk2 = {
        .name           = "pcmcdclk",
 };
 
-static struct clk dummy_apb_pclk = {
-       .name           = "apb_pclk",
-       .id             = -1,
-};
-
 static struct clk *clkset_vpllsrc_list[] = {
        [0] = &clk_fin_vpll,
        [1] = &clk_sclk_hdmi27m,
@@ -305,18 +300,6 @@ static struct clk_ops clk_fout_apll_ops = {
 
 static struct clk init_clocks_off[] = {
        {
-               .name           = "dma",
-               .devname        = "dma-pl330.0",
-               .parent         = &clk_hclk_psys.clk,
-               .enable         = s5pv210_clk_ip0_ctrl,
-               .ctrlbit        = (1 << 3),
-       }, {
-               .name           = "dma",
-               .devname        = "dma-pl330.1",
-               .parent         = &clk_hclk_psys.clk,
-               .enable         = s5pv210_clk_ip0_ctrl,
-               .ctrlbit        = (1 << 4),
-       }, {
                .name           = "rot",
                .parent         = &clk_hclk_dsys.clk,
                .enable         = s5pv210_clk_ip0_ctrl,
@@ -573,6 +556,20 @@ static struct clk clk_hsmmc3 = {
        .ctrlbit        = (1<<19),
 };
 
+static struct clk clk_pdma0 = {
+       .name           = "pdma0",
+       .parent         = &clk_hclk_psys.clk,
+       .enable         = s5pv210_clk_ip0_ctrl,
+       .ctrlbit        = (1 << 3),
+};
+
+static struct clk clk_pdma1 = {
+       .name           = "pdma1",
+       .parent         = &clk_hclk_psys.clk,
+       .enable         = s5pv210_clk_ip0_ctrl,
+       .ctrlbit        = (1 << 4),
+};
+
 static struct clk *clkset_uart_list[] = {
        [6] = &clk_mout_mpll.clk,
        [7] = &clk_mout_epll.clk,
@@ -1075,6 +1072,8 @@ static struct clk *clk_cdev[] = {
        &clk_hsmmc1,
        &clk_hsmmc2,
        &clk_hsmmc3,
+       &clk_pdma0,
+       &clk_pdma1,
 };
 
 /* Clock initialisation code */
@@ -1333,6 +1332,8 @@ static struct clk_lookup s5pv210_clk_lookup[] = {
        CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
        CLKDEV_INIT("s5pv210-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
        CLKDEV_INIT("s5pv210-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
+       CLKDEV_INIT("dma-pl330.0", "apb_pclk", &clk_pdma0),
+       CLKDEV_INIT("dma-pl330.1", "apb_pclk", &clk_pdma1),
 };
 
 void __init s5pv210_register_clocks(void)
@@ -1361,6 +1362,5 @@ void __init s5pv210_register_clocks(void)
        for (ptr = 0; ptr < ARRAY_SIZE(clk_cdev); ptr++)
                s3c_disable_clocks(clk_cdev[ptr], 1);
 
-       s3c24xx_register_clock(&dummy_apb_pclk);
        s3c_pwmclk_init();
 }
index 79e55597ab633cb0f653fec915fa6b47f6766239..80c21996c9434c02453d98570f5160278d1796ed 100644 (file)
@@ -38,4 +38,4 @@
  * will be fine with us.
  */
 
-#include <plat/debug-macro.S>
+#include <debug/samsung.S>
index 11900a8e88a3369daba6dd5a5e64f94a9adb7319..ed2b85485b9d95301ff228e2e209911807090922 100644 (file)
@@ -38,7 +38,7 @@
 #include <plat/fb.h>
 #include <plat/fimc-core.h>
 #include <plat/sdhci.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -651,7 +651,7 @@ static void __init aquila_map_io(void)
        s5pv210_init_io(NULL, 0);
        s3c24xx_init_clocks(24000000);
        s3c24xx_init_uarts(aquila_uartcfgs, ARRAY_SIZE(aquila_uartcfgs));
-       s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init aquila_machine_init(void)
@@ -686,6 +686,6 @@ MACHINE_START(AQUILA, "Aquila")
        .init_irq       = s5pv210_init_irq,
        .map_io         = aquila_map_io,
        .init_machine   = aquila_machine_init,
-       .init_time      = s5p_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s5pv210_restart,
 MACHINE_END
index 3a38f7b34b9400e52293456729a0b51c8cd29051..30b24ad84f496d383a2f71d0983926b51a239d1b 100644 (file)
@@ -47,7 +47,7 @@
 #include <plat/keypad.h>
 #include <plat/sdhci.h>
 #include <plat/clock.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 #include <plat/mfc.h>
 #include <plat/camport.h>
 
@@ -845,7 +845,7 @@ static struct fimc_source_info goni_camera_sensors[] = {
                .mux_id         = 0,
                .flags          = V4L2_MBUS_PCLK_SAMPLE_FALLING |
                                  V4L2_MBUS_VSYNC_ACTIVE_LOW,
-               .bus_type       = FIMC_BUS_TYPE_ITU_601,
+               .fimc_bus_type  = FIMC_BUS_TYPE_ITU_601,
                .board_info     = &noon010pc30_board_info,
                .i2c_bus_num    = 0,
                .clk_frequency  = 16000000UL,
@@ -908,7 +908,7 @@ static void __init goni_map_io(void)
        s5pv210_init_io(NULL, 0);
        s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(goni_uartcfgs, ARRAY_SIZE(goni_uartcfgs));
-       s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init goni_reserve(void)
@@ -973,7 +973,7 @@ MACHINE_START(GONI, "GONI")
        .init_irq       = s5pv210_init_irq,
        .map_io         = goni_map_io,
        .init_machine   = goni_machine_init,
-       .init_time      = s5p_timer_init,
+       .init_time      = samsung_timer_init,
        .reserve        = &goni_reserve,
        .restart        = s5pv210_restart,
 MACHINE_END
index 28bd0248a3e2ec57be4499bfa517d0fd5271e0b4..7c0ed07a78a3bf9bdb7944e609d1d65a19a1a921 100644 (file)
@@ -29,7 +29,7 @@
 #include <linux/platform_data/ata-samsung_cf.h>
 #include <linux/platform_data/i2c-s3c2410.h>
 #include <plat/pm.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 #include <plat/mfc.h>
 
 #include "common.h"
@@ -120,7 +120,7 @@ static void __init smdkc110_map_io(void)
        s5pv210_init_io(NULL, 0);
        s3c24xx_init_clocks(24000000);
        s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
-       s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init smdkc110_reserve(void)
@@ -153,7 +153,7 @@ MACHINE_START(SMDKC110, "SMDKC110")
        .init_irq       = s5pv210_init_irq,
        .map_io         = smdkc110_map_io,
        .init_machine   = smdkc110_machine_init,
-       .init_time      = s5p_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s5pv210_restart,
        .reserve        = &smdkc110_reserve,
 MACHINE_END
index 3c73f36869bbab37d49134882f3f1cb8f9758f08..d50b6f124465e2cac96e524ba16639b64f57e3ed 100644 (file)
@@ -44,7 +44,7 @@
 #include <plat/keypad.h>
 #include <plat/pm.h>
 #include <plat/fb.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 #include <plat/backlight.h>
 #include <plat/mfc.h>
 #include <plat/clock.h>
@@ -285,7 +285,7 @@ static void __init smdkv210_map_io(void)
        s5pv210_init_io(NULL, 0);
        s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
-       s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
+       samsung_set_timer_source(SAMSUNG_PWM2, SAMSUNG_PWM4);
 }
 
 static void __init smdkv210_reserve(void)
@@ -329,7 +329,7 @@ MACHINE_START(SMDKV210, "SMDKV210")
        .init_irq       = s5pv210_init_irq,
        .map_io         = smdkv210_map_io,
        .init_machine   = smdkv210_machine_init,
-       .init_time      = s5p_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s5pv210_restart,
        .reserve        = &smdkv210_reserve,
 MACHINE_END
index 2d4c5531819c06d7038149f0e872fa1b3a16a79d..579afe89842a3b169c9532e46096cfef7c998b9e 100644 (file)
@@ -26,7 +26,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <linux/platform_data/i2c-s3c2410.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 
 #include "common.h"
 
@@ -106,7 +106,7 @@ static void __init torbreck_map_io(void)
        s5pv210_init_io(NULL, 0);
        s3c24xx_init_clocks(24000000);
        s3c24xx_init_uarts(torbreck_uartcfgs, ARRAY_SIZE(torbreck_uartcfgs));
-       s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
+       samsung_set_timer_source(SAMSUNG_PWM3, SAMSUNG_PWM4);
 }
 
 static void __init torbreck_machine_init(void)
@@ -130,6 +130,6 @@ MACHINE_START(TORBRECK, "TORBRECK")
        .init_irq       = s5pv210_init_irq,
        .map_io         = torbreck_map_io,
        .init_machine   = torbreck_machine_init,
-       .init_time      = s5p_timer_init,
+       .init_time      = samsung_timer_init,
        .restart        = s5pv210_restart,
 MACHINE_END
index 3e3ac05bb7b15d5f61dee876d4804dfb1a65391d..0512ada00522f73155b4918a0a8645b364ee6f39 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/mmc/card.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/regs-sdhci.h>
 #include <plat/sdhci.h>
 
 void s5pv210_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
index 9255546e7bf64fb98fce8bbfb3bb7830ce51f2cd..75d413c004b6f35f3f330e3f07c9bf3538d2ead5 100644 (file)
@@ -16,6 +16,7 @@ config ARCH_SH73A0
        select CPU_V7
        select I2C
        select SH_CLK_CPG
+       select RENESAS_INTC_IRQPIN
 
 config ARCH_R8A7740
        bool "R-Mobile A1 (R8A77400)"
@@ -31,6 +32,7 @@ config ARCH_R8A7779
        select SH_CLK_CPG
        select USB_ARCH_HAS_EHCI
        select USB_ARCH_HAS_OHCI
+       select RENESAS_INTC_IRQPIN
 
 config ARCH_EMEV2
        bool "Emma Mobile EV2"
index e1fac57514b93ea55f36f336c4617c429bd13985..b646ff4d742ab103100f1d7e43ed45fcd476dbac 100644 (file)
@@ -14,10 +14,9 @@ obj-$(CONFIG_ARCH_EMEV2)     += setup-emev2.o clock-emev2.o
 
 # SMP objects
 smp-y                          := platsmp.o headsmp.o
-smp-$(CONFIG_HOTPLUG_CPU)      += hotplug.o
-smp-$(CONFIG_ARCH_SH73A0)      += smp-sh73a0.o headsmp-sh73a0.o
-smp-$(CONFIG_ARCH_R8A7779)     += smp-r8a7779.o
-smp-$(CONFIG_ARCH_EMEV2)       += smp-emev2.o
+smp-$(CONFIG_ARCH_SH73A0)      += smp-sh73a0.o headsmp-scu.o
+smp-$(CONFIG_ARCH_R8A7779)     += smp-r8a7779.o headsmp-scu.o
+smp-$(CONFIG_ARCH_EMEV2)       += smp-emev2.o headsmp-scu.o
 
 # IRQ objects
 obj-$(CONFIG_ARCH_SH7372)      += entry-intc.o
index 7f3a6b7e7b7cfdfd1697560d2e3ecb6b3a6c6f38..d34d12ae496b34144c1a2398071f06df31b41313 100644 (file)
@@ -81,7 +81,7 @@ static struct resource smsc9221_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = intcs_evt2irq(0x260), /* IRQ3 */
+               .start  = irq_pin(3), /* IRQ3 */
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -115,7 +115,7 @@ static struct resource usb_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = intcs_evt2irq(0x220), /* IRQ1 */
+               .start  = irq_pin(1), /* IRQ1 */
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -138,7 +138,7 @@ struct usbhs_private {
        struct renesas_usbhs_platform_info info;
 };
 
-#define IRQ15                  intcs_evt2irq(0x03e0)
+#define IRQ15                  irq_pin(15)
 #define USB_PHY_MODE           (1 << 4)
 #define USB_PHY_INT_EN         ((1 << 3) | (1 << 2))
 #define USB_PHY_ON             (1 << 1)
@@ -563,25 +563,25 @@ static struct i2c_board_info i2c0_devices[] = {
        },
        {
                I2C_BOARD_INFO("ak8975", 0x0c),
-               .irq = intcs_evt2irq(0x3380), /* IRQ28 */
+               .irq = irq_pin(28), /* IRQ28 */
        },
        {
                I2C_BOARD_INFO("adxl34x", 0x1d),
-               .irq = intcs_evt2irq(0x3340), /* IRQ26 */
+               .irq = irq_pin(26), /* IRQ26 */
        },
 };
 
 static struct i2c_board_info i2c1_devices[] = {
        {
                I2C_BOARD_INFO("st1232-ts", 0x55),
-               .irq = intcs_evt2irq(0x300), /* IRQ8 */
+               .irq = irq_pin(8), /* IRQ8 */
        },
 };
 
 static struct i2c_board_info i2c3_devices[] = {
        {
                I2C_BOARD_INFO("pcf8575", 0x20),
-               .irq            = intcs_evt2irq(0x3260), /* IRQ19 */
+               .irq = irq_pin(19), /* IRQ19 */
                .platform_data = &pcf8575_pdata,
        },
 };
index cdcb799e802f0e2e5bcdaeaf42e50107a18b0197..fec49ebc359a56497b1aa7cf819177edd0293728 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/smsc911x.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/sh_hspi.h>
+#include <linux/mmc/host.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <linux/usb/otg.h>
index 19ce885a3b4372af27579b3eeb68446c9b8cfcb7..1feb9a2286a83105572b7611401185c0086bb349 100644 (file)
@@ -593,29 +593,42 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("sh_mobile_ceu.1",        &mstp_clks[MSTP128]),
 
        CLKDEV_DEV_ID("sh-sci.4",               &mstp_clks[MSTP200]),
+       CLKDEV_DEV_ID("e6c80000.sci",           &mstp_clks[MSTP200]),
        CLKDEV_DEV_ID("sh-sci.3",               &mstp_clks[MSTP201]),
+       CLKDEV_DEV_ID("e6c70000.sci",           &mstp_clks[MSTP201]),
        CLKDEV_DEV_ID("sh-sci.2",               &mstp_clks[MSTP202]),
+       CLKDEV_DEV_ID("e6c60000.sci",           &mstp_clks[MSTP202]),
        CLKDEV_DEV_ID("sh-sci.1",               &mstp_clks[MSTP203]),
+       CLKDEV_DEV_ID("e6c50000.sci",           &mstp_clks[MSTP203]),
        CLKDEV_DEV_ID("sh-sci.0",               &mstp_clks[MSTP204]),
+       CLKDEV_DEV_ID("e6c40000.sci",           &mstp_clks[MSTP204]),
        CLKDEV_DEV_ID("sh-sci.8",               &mstp_clks[MSTP206]),
+       CLKDEV_DEV_ID("e6c30000.sci",           &mstp_clks[MSTP206]),
        CLKDEV_DEV_ID("sh-sci.5",               &mstp_clks[MSTP207]),
+       CLKDEV_DEV_ID("e6cb0000.sci",           &mstp_clks[MSTP207]),
        CLKDEV_DEV_ID("sh-dma-engine.3",        &mstp_clks[MSTP214]),
        CLKDEV_DEV_ID("sh-dma-engine.2",        &mstp_clks[MSTP216]),
        CLKDEV_DEV_ID("sh-dma-engine.1",        &mstp_clks[MSTP217]),
        CLKDEV_DEV_ID("sh-dma-engine.0",        &mstp_clks[MSTP218]),
        CLKDEV_DEV_ID("sh-sci.7",               &mstp_clks[MSTP222]),
+       CLKDEV_DEV_ID("e6cd0000.sci",           &mstp_clks[MSTP222]),
        CLKDEV_DEV_ID("sh-sci.6",               &mstp_clks[MSTP230]),
+       CLKDEV_DEV_ID("e6cc0000.sci",           &mstp_clks[MSTP230]),
 
        CLKDEV_DEV_ID("sh_cmt.10",              &mstp_clks[MSTP329]),
        CLKDEV_DEV_ID("sh_fsi2",                &mstp_clks[MSTP328]),
        CLKDEV_DEV_ID("i2c-sh_mobile.1",        &mstp_clks[MSTP323]),
        CLKDEV_DEV_ID("renesas_usbhs",          &mstp_clks[MSTP320]),
        CLKDEV_DEV_ID("sh_mobile_sdhi.0",       &mstp_clks[MSTP314]),
+       CLKDEV_DEV_ID("e6850000.sdhi",          &mstp_clks[MSTP314]),
        CLKDEV_DEV_ID("sh_mobile_sdhi.1",       &mstp_clks[MSTP313]),
+       CLKDEV_DEV_ID("e6860000.sdhi",          &mstp_clks[MSTP313]),
        CLKDEV_DEV_ID("sh_mmcif",               &mstp_clks[MSTP312]),
+       CLKDEV_DEV_ID("e6bd0000.mmcif",         &mstp_clks[MSTP312]),
        CLKDEV_DEV_ID("sh-eth",                 &mstp_clks[MSTP309]),
 
        CLKDEV_DEV_ID("sh_mobile_sdhi.2",       &mstp_clks[MSTP415]),
+       CLKDEV_DEV_ID("e6870000.sdhi",          &mstp_clks[MSTP415]),
 
        /* ICK */
        CLKDEV_ICK_ID("host",   "renesas_usbhs",        &mstp_clks[MSTP416]),
index 1db36537255c250a834e373e5a56e3de7f23dc70..d9edeaf6600706a875cf5cf156010059dcf4eb49 100644 (file)
@@ -87,7 +87,8 @@ static struct clk div4_clks[DIV4_NR] = {
 };
 
 enum { MSTP323, MSTP322, MSTP321, MSTP320,
-       MSTP101, MSTP100,
+       MSTP115,
+       MSTP103, MSTP101, MSTP100,
        MSTP030,
        MSTP029, MSTP028, MSTP027, MSTP026, MSTP025, MSTP024, MSTP023, MSTP022, MSTP021,
        MSTP016, MSTP015, MSTP014,
@@ -99,6 +100,8 @@ static struct clk mstp_clks[MSTP_NR] = {
        [MSTP322] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 22, 0), /* SDHI1 */
        [MSTP321] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 21, 0), /* SDHI2 */
        [MSTP320] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR3, 20, 0), /* SDHI3 */
+       [MSTP115] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 15, 0), /* SATA */
+       [MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_S], MSTPCR1,  3, 0), /* DU */
        [MSTP101] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1,  1, 0), /* USB2 */
        [MSTP100] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1,  0, 0), /* USB0/1 */
        [MSTP030] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR0, 30, 0), /* I2C0 */
@@ -156,6 +159,8 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("peripheral_clk", &div4_clks[DIV4_P]),
 
        /* MSTP32 clocks */
+       CLKDEV_DEV_ID("sata_rcar", &mstp_clks[MSTP115]), /* SATA */
+       CLKDEV_DEV_ID("fc600000.sata", &mstp_clks[MSTP115]), /* SATA w/DT */
        CLKDEV_DEV_ID("ehci-platform.1", &mstp_clks[MSTP101]), /* USB EHCI port2 */
        CLKDEV_DEV_ID("ohci-platform.1", &mstp_clks[MSTP101]), /* USB OHCI port2 */
        CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
@@ -180,6 +185,7 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP322]), /* SDHI1 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP321]), /* SDHI2 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.3", &mstp_clks[MSTP320]), /* SDHI3 */
+       CLKDEV_DEV_ID("rcar-du.0", &mstp_clks[MSTP103]), /* DU */
 };
 
 void __init r8a7779_clock_init(void)
index afa5423a0f93871351669830a07dddbaf808b616..71843dd39e16adb0593dd5f377a6baefb857116b 100644 (file)
@@ -265,12 +265,12 @@ enum { DIV4_I, DIV4_ZG, DIV4_M3, DIV4_B, DIV4_M1, DIV4_M2,
 
 static struct clk div4_clks[DIV4_NR] = {
        [DIV4_I] = DIV4(FRQCRA, 20, 0xdff, CLK_ENABLE_ON_INIT),
-       [DIV4_ZG] = DIV4(FRQCRA, 16, 0xd7f, CLK_ENABLE_ON_INIT),
+       [DIV4_ZG] = SH_CLK_DIV4(&pll0_clk, FRQCRA, 16, 0xd7f, CLK_ENABLE_ON_INIT),
        [DIV4_M3] = DIV4(FRQCRA, 12, 0x1dff, CLK_ENABLE_ON_INIT),
        [DIV4_B] = DIV4(FRQCRA, 8, 0xdff, CLK_ENABLE_ON_INIT),
        [DIV4_M1] = DIV4(FRQCRA, 4, 0x1dff, 0),
        [DIV4_M2] = DIV4(FRQCRA, 0, 0x1dff, 0),
-       [DIV4_Z] = DIV4(FRQCRB, 24, 0x97f, 0),
+       [DIV4_Z] = SH_CLK_DIV4(&pll0_clk, FRQCRB, 24, 0x97f, 0),
        [DIV4_ZTR] = DIV4(FRQCRB, 20, 0xdff, 0),
        [DIV4_ZT] = DIV4(FRQCRB, 16, 0xdff, 0),
        [DIV4_ZX] = DIV4(FRQCRB, 12, 0xdff, 0),
@@ -581,10 +581,13 @@ static struct clk_lookup lookups[] = {
        CLKDEV_DEV_ID("e6822000.i2c", &mstp_clks[MSTP323]), /* I2C1 */
        CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP322]), /* USB */
        CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
+       CLKDEV_DEV_ID("ee100000.sdhi", &mstp_clks[MSTP314]), /* SDHI0 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
+       CLKDEV_DEV_ID("ee120000.sdhi", &mstp_clks[MSTP313]), /* SDHI1 */
        CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */
        CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), /* MMCIF0 */
        CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */
+       CLKDEV_DEV_ID("ee140000.sdhi", &mstp_clks[MSTP311]), /* SDHI2 */
        CLKDEV_DEV_ID("leds-renesas-tpu.12", &mstp_clks[MSTP303]), /* TPU1 */
        CLKDEV_DEV_ID("leds-renesas-tpu.21", &mstp_clks[MSTP302]), /* TPU2 */
        CLKDEV_DEV_ID("leds-renesas-tpu.30", &mstp_clks[MSTP301]), /* TPU3 */
similarity index 85%
rename from arch/arm/mach-shmobile/headsmp-sh73a0.S
rename to arch/arm/mach-shmobile/headsmp-scu.S
index bec4c0d9b713979593e75c7c4c60ed9770fb3e7f..7d113f898e7f62b57440348d6ce201d5c2441643 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * SMP support for SoC sh73a0
+ * Shared SCU setup for mach-shmobile
  *
  * Copyright (C) 2012 Bastian Hecht
  *
  * the physical address as the MMU is still turned off.
  */
        .align  12
-ENTRY(sh73a0_secondary_vector)
+ENTRY(shmobile_secondary_vector_scu)
        mrc     p15, 0, r0, c0, c0, 5   @ read MIPDR
        and     r0, r0, #3              @ mask out cpu ID
        lsl     r0, r0, #3              @ we will shift by cpu_id * 8 bits
-       mov     r1, #0xf0000000         @ SCU base address
+       ldr     r1, 2f
+       ldr     r1, [r1]                @ SCU base address
        ldr     r2, [r1, #8]            @ SCU Power Status Register
        mov     r3, #3
        bic     r2, r2, r3, lsl r0      @ Clear bits of our CPU (Run Mode)
@@ -47,4 +48,10 @@ ENTRY(sh73a0_secondary_vector)
 
        ldr     pc, 1f
 1:     .long shmobile_invalidate_start - PAGE_OFFSET + PLAT_PHYS_OFFSET
-ENDPROC(sh73a0_secondary_vector)
+2:     .long shmobile_scu_base - PAGE_OFFSET + PLAT_PHYS_OFFSET
+ENDPROC(shmobile_secondary_vector_scu)
+
+       .text
+       .globl  shmobile_scu_base
+shmobile_scu_base:
+       .space  4
diff --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c
deleted file mode 100644 (file)
index a1524e3..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * SMP support for R-Mobile / SH-Mobile
- *
- * Copyright (C) 2010  Magnus Damm
- *
- * Based on realview, Copyright (C) 2002 ARM Ltd, 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/kernel.h>
-#include <linux/errno.h>
-#include <linux/smp.h>
-#include <linux/cpumask.h>
-#include <linux/delay.h>
-#include <linux/of.h>
-#include <mach/common.h>
-#include <mach/r8a7779.h>
-#include <mach/emev2.h>
-#include <asm/cacheflush.h>
-#include <asm/mach-types.h>
-
-static cpumask_t dead_cpus;
-
-void shmobile_cpu_die(unsigned int cpu)
-{
-       /* hardware shutdown code running on the CPU that is being offlined */
-       flush_cache_all();
-       dsb();
-
-       /* notify platform_cpu_kill() that hardware shutdown is finished */
-       cpumask_set_cpu(cpu, &dead_cpus);
-
-       /* wait for SoC code in platform_cpu_kill() to shut off CPU core
-        * power. CPU bring up starts from the reset vector.
-        */
-       while (1) {
-               /*
-                * here's the WFI
-                */
-               asm(".word      0xe320f003\n"
-                   :
-                   :
-                   : "memory", "cc");
-       }
-}
-
-int shmobile_cpu_disable(unsigned int cpu)
-{
-       cpumask_clear_cpu(cpu, &dead_cpus);
-       /*
-        * we don't allow CPU 0 to be shutdown (it is still too special
-        * e.g. clock tick interrupts)
-        */
-       return cpu == 0 ? -EPERM : 0;
-}
-
-int shmobile_cpu_disable_any(unsigned int cpu)
-{
-       cpumask_clear_cpu(cpu, &dead_cpus);
-       return 0;
-}
-
-int shmobile_cpu_is_dead(unsigned int cpu)
-{
-       return cpumask_test_cpu(cpu, &dead_cpus);
-}
index e48606d8a2be31214168c0616ae6bc9d81ddc458..03f73def2fc6046a9a820d4267314252fbe5379c 100644 (file)
@@ -8,6 +8,7 @@ extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
 struct twd_local_timer;
 extern void shmobile_setup_console(void);
 extern void shmobile_secondary_vector(void);
+extern void shmobile_secondary_vector_scu(void);
 struct clk;
 extern int shmobile_clk_init(void);
 extern void shmobile_handle_irq_intc(struct pt_regs *);
@@ -33,23 +34,23 @@ extern int sh7372_do_idle_sysc(unsigned long sleep_mode);
 extern struct clk sh7372_extal1_clk;
 extern struct clk sh7372_extal2_clk;
 
+extern void sh73a0_init_delay(void);
 extern void sh73a0_init_irq(void);
 extern void sh73a0_init_irq_dt(void);
 extern void sh73a0_map_io(void);
 extern void sh73a0_earlytimer_init(void);
 extern void sh73a0_add_early_devices(void);
-extern void sh73a0_add_early_devices_dt(void);
 extern void sh73a0_add_standard_devices(void);
 extern void sh73a0_add_standard_devices_dt(void);
 extern void sh73a0_clock_init(void);
 extern void sh73a0_pinmux_init(void);
 extern void sh73a0_pm_init(void);
-extern void sh73a0_secondary_vector(void);
 extern struct clk sh73a0_extal1_clk;
 extern struct clk sh73a0_extal2_clk;
 extern struct clk sh73a0_extcki_clk;
 extern struct clk sh73a0_extalr_clk;
 
+extern void r8a7740_meram_workaround(void);
 extern void r8a7740_init_irq(void);
 extern void r8a7740_map_io(void);
 extern void r8a7740_add_early_devices(void);
@@ -58,16 +59,18 @@ extern void r8a7740_clock_init(u8 md_ck);
 extern void r8a7740_pinmux_init(void);
 extern void r8a7740_pm_init(void);
 
+extern void r8a7779_init_delay(void);
 extern void r8a7779_init_irq(void);
+extern void r8a7779_init_irq_extpin(int irlm);
+extern void r8a7779_init_irq_dt(void);
 extern void r8a7779_map_io(void);
 extern void r8a7779_earlytimer_init(void);
 extern void r8a7779_add_early_devices(void);
 extern void r8a7779_add_standard_devices(void);
+extern void r8a7779_add_standard_devices_dt(void);
 extern void r8a7779_clock_init(void);
 extern void r8a7779_pinmux_init(void);
 extern void r8a7779_pm_init(void);
-extern void r8a7740_meram_workaround(void);
-
 extern void r8a7779_register_twd(void);
 
 #ifdef CONFIG_SUSPEND
@@ -82,16 +85,7 @@ int shmobile_cpuidle_init(void);
 static inline int shmobile_cpuidle_init(void) { return 0; }
 #endif
 
-extern void shmobile_cpu_die(unsigned int cpu);
-extern int shmobile_cpu_disable(unsigned int cpu);
-extern int shmobile_cpu_disable_any(unsigned int cpu);
-
-#ifdef CONFIG_HOTPLUG_CPU
-extern int shmobile_cpu_is_dead(unsigned int cpu);
-#else
-static inline int shmobile_cpu_is_dead(unsigned int cpu) { return 1; }
-#endif
-
+extern void __iomem *shmobile_scu_base;
 extern void shmobile_smp_init_cpus(unsigned int ncores);
 
 static inline void __init shmobile_init_late(void)
index 06a5da3c305090e0176373d2576f6de68feb2922..b2074e2acb15f2641f5b92fc65fad9ff619c54cb 100644 (file)
@@ -5,10 +5,15 @@
 
 /* GIC */
 #define gic_spi(nr)            ((nr) + 32)
+#define gic_iid(nr)            (nr) /* ICCIAR / interrupt ID */
 
 /* INTCS */
 #define INTCS_VECT_BASE                0x3400
 #define INTCS_VECT(n, vect)    INTC_VECT((n), INTCS_VECT_BASE + (vect))
 #define intcs_evt2irq(evt)     evt2irq(INTCS_VECT_BASE + (evt))
 
+/* External IRQ pins */
+#define IRQPIN_BASE            2000
+#define irq_pin(nr)            ((nr) + IRQPIN_BASE)
+
 #endif /* __ASM_MACH_IRQS_H */
index 8807c27f71f968c15721af91f099b3ee4771cad7..b86dc8908724f3cb38a651897623b021aeb37c28 100644 (file)
  */
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/irqchip/arm-gic.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
+#include <linux/irqchip.h>
 #include <mach/common.h>
 #include <mach/intc.h>
+#include <mach/irqs.h>
 #include <mach/r8a7779.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #define INT2NTSR0 IOMEM(0xfe700060)
 #define INT2NTSR1 IOMEM(0xfe700064)
 
+static struct renesas_intc_irqpin_config irqpin0_platform_data = {
+       .irq_base = irq_pin(0), /* IRQ0 -> IRQ3 */
+       .sense_bitfield_width = 2,
+};
+
+static struct resource irqpin0_resources[] = {
+       DEFINE_RES_MEM(0xfe78001c, 4), /* ICR1 */
+       DEFINE_RES_MEM(0xfe780010, 4), /* INTPRI */
+       DEFINE_RES_MEM(0xfe780024, 4), /* INTREQ */
+       DEFINE_RES_MEM(0xfe780044, 4), /* INTMSK0 */
+       DEFINE_RES_MEM(0xfe780064, 4), /* INTMSKCLR0 */
+       DEFINE_RES_IRQ(gic_spi(27)), /* IRQ0 */
+       DEFINE_RES_IRQ(gic_spi(28)), /* IRQ1 */
+       DEFINE_RES_IRQ(gic_spi(29)), /* IRQ2 */
+       DEFINE_RES_IRQ(gic_spi(30)), /* IRQ3 */
+};
+
+static struct platform_device irqpin0_device = {
+       .name           = "renesas_intc_irqpin",
+       .id             = 0,
+       .resource       = irqpin0_resources,
+       .num_resources  = ARRAY_SIZE(irqpin0_resources),
+       .dev            = {
+               .platform_data  = &irqpin0_platform_data,
+       },
+};
+
+void __init r8a7779_init_irq_extpin(int irlm)
+{
+       void __iomem *icr0 = ioremap_nocache(0xfe780000, PAGE_SIZE);
+       unsigned long tmp;
+
+       if (icr0) {
+               tmp = ioread32(icr0);
+               if (irlm)
+                       tmp |= 1 << 23; /* IRQ0 -> IRQ3 as individual pins */
+               else
+                       tmp &= ~(1 << 23); /* IRL mode - not supported */
+               tmp |= (1 << 21); /* LVLMODE = 1 */
+               iowrite32(tmp, icr0);
+               iounmap(icr0);
+
+               if (irlm)
+                       platform_device_register(&irqpin0_device);
+       } else
+               pr_warn("r8a7779: unable to setup external irq pin mode\n");
+}
+
 static int r8a7779_set_wake(struct irq_data *data, unsigned int on)
 {
        return 0; /* always allow wakeup */
 }
 
-void __init r8a7779_init_irq(void)
+static void __init r8a7779_init_irq_common(void)
 {
-       void __iomem *gic_dist_base = IOMEM(0xf0001000);
-       void __iomem *gic_cpu_base = IOMEM(0xf0000100);
-
-       /* use GIC to handle interrupts */
-       gic_init(0, 29, gic_dist_base, gic_cpu_base);
        gic_arch_extn.irq_set_wake = r8a7779_set_wake;
 
        /* route all interrupts to ARM */
@@ -63,3 +110,22 @@ void __init r8a7779_init_irq(void)
        __raw_writel(0xbffffffc, INT2SMSKCR3);
        __raw_writel(0x003fee3f, INT2SMSKCR4);
 }
+
+void __init r8a7779_init_irq(void)
+{
+       void __iomem *gic_dist_base = IOMEM(0xf0001000);
+       void __iomem *gic_cpu_base = IOMEM(0xf0000100);
+
+       /* use GIC to handle interrupts */
+       gic_init(0, 29, gic_dist_base, gic_cpu_base);
+
+       r8a7779_init_irq_common();
+}
+
+#ifdef CONFIG_OF
+void __init r8a7779_init_irq_dt(void)
+{
+       irqchip_init();
+       r8a7779_init_irq_common();
+}
+#endif
index 91faba666d462916ec37822450b127674e8446db..19a26f4579b31e47b2437b2fe4128c7dc7dd6a3d 100644 (file)
@@ -260,108 +260,6 @@ static int sh73a0_set_wake(struct irq_data *data, unsigned int on)
        return 0; /* always allow wakeup */
 }
 
-#define RELOC_BASE 0x1200
-
-/* INTCA IRQ pins at INTCS + RELOC_BASE to make space for GIC+INTC handling */
-#define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE)
-
-INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
-                INTCS_VECT_RELOC, "sh73a0-intca-irq-pins");
-
-static int to_gic_irq(struct irq_data *data)
-{
-       unsigned int vect = irq2evt(data->irq) - INTCS_VECT_BASE;
-
-       if (vect >= 0x3200)
-               vect -= 0x3000;
-       else
-               vect -= 0x0200;
-
-       return gic_spi((vect >> 5) + 1);
-}
-
-static int to_intca_reloc_irq(struct irq_data *data)
-{
-       return data->irq + (RELOC_BASE >> 5);
-}
-
-#define irq_cb(cb, irq) irq_get_chip(irq)->cb(irq_get_irq_data(irq))
-#define irq_cbp(cb, irq, p...) irq_get_chip(irq)->cb(irq_get_irq_data(irq), p)
-
-static void intca_gic_enable(struct irq_data *data)
-{
-       irq_cb(irq_unmask, to_intca_reloc_irq(data));
-       irq_cb(irq_unmask, to_gic_irq(data));
-}
-
-static void intca_gic_disable(struct irq_data *data)
-{
-       irq_cb(irq_mask, to_gic_irq(data));
-       irq_cb(irq_mask, to_intca_reloc_irq(data));
-}
-
-static void intca_gic_mask_ack(struct irq_data *data)
-{
-       irq_cb(irq_mask, to_gic_irq(data));
-       irq_cb(irq_mask_ack, to_intca_reloc_irq(data));
-}
-
-static void intca_gic_eoi(struct irq_data *data)
-{
-       irq_cb(irq_eoi, to_gic_irq(data));
-}
-
-static int intca_gic_set_type(struct irq_data *data, unsigned int type)
-{
-       return irq_cbp(irq_set_type, to_intca_reloc_irq(data), type);
-}
-
-#ifdef CONFIG_SMP
-static int intca_gic_set_affinity(struct irq_data *data,
-                                 const struct cpumask *cpumask,
-                                 bool force)
-{
-       return irq_cbp(irq_set_affinity, to_gic_irq(data), cpumask, force);
-}
-#endif
-
-struct irq_chip intca_gic_irq_chip = {
-       .name                   = "INTCA-GIC",
-       .irq_mask               = intca_gic_disable,
-       .irq_unmask             = intca_gic_enable,
-       .irq_mask_ack           = intca_gic_mask_ack,
-       .irq_eoi                = intca_gic_eoi,
-       .irq_enable             = intca_gic_enable,
-       .irq_disable            = intca_gic_disable,
-       .irq_shutdown           = intca_gic_disable,
-       .irq_set_type           = intca_gic_set_type,
-       .irq_set_wake           = sh73a0_set_wake,
-#ifdef CONFIG_SMP
-       .irq_set_affinity       = intca_gic_set_affinity,
-#endif
-};
-
-static int to_intc_vect(int irq)
-{
-       unsigned int irq_pin = irq - gic_spi(1);
-       unsigned int offs;
-
-       if (irq_pin < 16)
-               offs = 0x0200;
-       else
-               offs = 0x3000;
-
-       return offs + (irq_pin << 5);
-}
-
-static irqreturn_t sh73a0_irq_pin_demux(int irq, void *dev_id)
-{
-       generic_handle_irq(intcs_evt2irq(to_intc_vect(irq)));
-       return IRQ_HANDLED;
-}
-
-static struct irqaction sh73a0_irq_pin_cascade[32];
-
 #define PINTER0_PHYS 0xe69000a0
 #define PINTER1_PHYS 0xe69000a4
 #define PINTER0_VIRT IOMEM(0xe69000a0)
@@ -422,13 +320,11 @@ void __init sh73a0_init_irq(void)
        void __iomem *gic_dist_base = IOMEM(0xf0001000);
        void __iomem *gic_cpu_base = IOMEM(0xf0000100);
        void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE);
-       int k, n;
 
        gic_init(0, 29, gic_dist_base, gic_cpu_base);
        gic_arch_extn.irq_set_wake = sh73a0_set_wake;
 
        register_intc_controller(&intcs_desc);
-       register_intc_controller(&intca_irq_pins_desc);
        register_intc_controller(&intc_pint0_desc);
        register_intc_controller(&intc_pint1_desc);
 
@@ -438,19 +334,6 @@ void __init sh73a0_init_irq(void)
        sh73a0_intcs_cascade.dev_id = intevtsa;
        setup_irq(gic_spi(50), &sh73a0_intcs_cascade);
 
-       /* IRQ pins require special handling through INTCA and GIC */
-       for (k = 0; k < 32; k++) {
-               sh73a0_irq_pin_cascade[k].name = "INTCA-GIC cascade";
-               sh73a0_irq_pin_cascade[k].handler = sh73a0_irq_pin_demux;
-               setup_irq(gic_spi(1 + k), &sh73a0_irq_pin_cascade[k]);
-
-               n = intcs_evt2irq(to_intc_vect(gic_spi(1 + k)));
-               WARN_ON(irq_alloc_desc_at(n, numa_node_id()) != n);
-               irq_set_chip_and_handler_name(n, &intca_gic_irq_chip,
-                                             handle_level_irq, "level");
-               set_irq_flags(n, IRQF_VALID); /* yuck */
-       }
-
        /* PINT pins are sanely tied to the GIC as SPI */
        sh73a0_pint0_cascade.name = "PINT0 cascade";
        sh73a0_pint0_cascade.handler = sh73a0_pint0_demux;
@@ -460,11 +343,3 @@ void __init sh73a0_init_irq(void)
        sh73a0_pint1_cascade.handler = sh73a0_pint1_demux;
        setup_irq(gic_spi(34), &sh73a0_pint1_cascade);
 }
-
-#ifdef CONFIG_OF
-void __init sh73a0_init_irq_dt(void)
-{
-       irqchip_init();
-       gic_arch_extn.irq_set_wake = sh73a0_set_wake;
-}
-#endif
index 47662a581c0a59d172529f06970b4e2ecb271e3d..e4545c152722e3361fd273fefb90c54f26753dea 100644 (file)
@@ -404,7 +404,7 @@ void __init emev2_add_standard_devices(void)
                             ARRAY_SIZE(emev2_late_devices));
 }
 
-void __init emev2_init_delay(void)
+static void __init emev2_init_delay(void)
 {
        shmobile_setup_delay(533, 1, 3); /* Cortex-A9 @ 533MHz */
 }
@@ -439,7 +439,7 @@ static const struct of_dev_auxdata emev2_auxdata_lookup[] __initconst = {
        { }
 };
 
-void __init emev2_add_standard_devices_dt(void)
+static void __init emev2_add_standard_devices_dt(void)
 {
        of_platform_populate(NULL, of_default_bus_match_table,
                             emev2_auxdata_lookup, NULL);
index c54ff9b29fe541aaa211f792bc9c3978a41f9724..042df35e71a0714a89c2f4a1a73d44d4535859ee 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/of_platform.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/input.h>
@@ -28,6 +29,7 @@
 #include <linux/serial_sci.h>
 #include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
+#include <linux/dma-mapping.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/r8a7779.h>
@@ -91,7 +93,7 @@ static struct plat_sci_port scif0_platform_data = {
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
-       .irqs           = SCIx_IRQ_MUXED(gic_spi(88)),
+       .irqs           = SCIx_IRQ_MUXED(gic_iid(0x78)),
 };
 
 static struct platform_device scif0_device = {
@@ -108,7 +110,7 @@ static struct plat_sci_port scif1_platform_data = {
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
-       .irqs           = SCIx_IRQ_MUXED(gic_spi(89)),
+       .irqs           = SCIx_IRQ_MUXED(gic_iid(0x79)),
 };
 
 static struct platform_device scif1_device = {
@@ -125,7 +127,7 @@ static struct plat_sci_port scif2_platform_data = {
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
-       .irqs           = SCIx_IRQ_MUXED(gic_spi(90)),
+       .irqs           = SCIx_IRQ_MUXED(gic_iid(0x7a)),
 };
 
 static struct platform_device scif2_device = {
@@ -142,7 +144,7 @@ static struct plat_sci_port scif3_platform_data = {
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
-       .irqs           = SCIx_IRQ_MUXED(gic_spi(91)),
+       .irqs           = SCIx_IRQ_MUXED(gic_iid(0x7b)),
 };
 
 static struct platform_device scif3_device = {
@@ -159,7 +161,7 @@ static struct plat_sci_port scif4_platform_data = {
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
-       .irqs           = SCIx_IRQ_MUXED(gic_spi(92)),
+       .irqs           = SCIx_IRQ_MUXED(gic_iid(0x7c)),
 };
 
 static struct platform_device scif4_device = {
@@ -176,7 +178,7 @@ static struct plat_sci_port scif5_platform_data = {
        .scscr          = SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
        .scbrr_algo_id  = SCBRR_ALGO_2,
        .type           = PORT_SCIF,
-       .irqs           = SCIx_IRQ_MUXED(gic_spi(93)),
+       .irqs           = SCIx_IRQ_MUXED(gic_iid(0x7d)),
 };
 
 static struct platform_device scif5_device = {
@@ -203,7 +205,7 @@ static struct resource tmu00_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = gic_spi(32),
+               .start  = gic_iid(0x40),
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -233,7 +235,7 @@ static struct resource tmu01_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = gic_spi(33),
+               .start  = gic_iid(0x41),
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -255,7 +257,7 @@ static struct resource rcar_i2c0_res[] = {
                .end    = 0xffc70fff,
                .flags  = IORESOURCE_MEM,
        }, {
-               .start  = gic_spi(79),
+               .start  = gic_iid(0x6f),
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -273,7 +275,7 @@ static struct resource rcar_i2c1_res[] = {
                .end    = 0xffc71fff,
                .flags  = IORESOURCE_MEM,
        }, {
-               .start  = gic_spi(82),
+               .start  = gic_iid(0x72),
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -291,7 +293,7 @@ static struct resource rcar_i2c2_res[] = {
                .end    = 0xffc72fff,
                .flags  = IORESOURCE_MEM,
        }, {
-               .start  = gic_spi(80),
+               .start  = gic_iid(0x70),
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -309,7 +311,7 @@ static struct resource rcar_i2c3_res[] = {
                .end    = 0xffc73fff,
                .flags  = IORESOURCE_MEM,
        }, {
-               .start  = gic_spi(81),
+               .start  = gic_iid(0x71),
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -321,7 +323,31 @@ static struct platform_device i2c3_device = {
        .num_resources  = ARRAY_SIZE(rcar_i2c3_res),
 };
 
-static struct platform_device *r8a7779_early_devices[] __initdata = {
+static struct resource sata_resources[] = {
+       [0] = {
+               .name   = "rcar-sata",
+               .start  = 0xfc600000,
+               .end    = 0xfc601fff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = gic_iid(0x84),
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device sata_device = {
+       .name           = "sata_rcar",
+       .id             = -1,
+       .resource       = sata_resources,
+       .num_resources  = ARRAY_SIZE(sata_resources),
+       .dev            = {
+               .dma_mask               = &sata_device.dev.coherent_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+
+static struct platform_device *r8a7779_devices_dt[] __initdata = {
        &scif0_device,
        &scif1_device,
        &scif2_device,
@@ -330,13 +356,14 @@ static struct platform_device *r8a7779_early_devices[] __initdata = {
        &scif5_device,
        &tmu00_device,
        &tmu01_device,
+};
+
+static struct platform_device *r8a7779_late_devices[] __initdata = {
        &i2c0_device,
        &i2c1_device,
        &i2c2_device,
        &i2c3_device,
-};
-
-static struct platform_device *r8a7779_late_devices[] __initdata = {
+       &sata_device,
 };
 
 void __init r8a7779_add_standard_devices(void)
@@ -349,8 +376,8 @@ void __init r8a7779_add_standard_devices(void)
 
        r8a7779_init_pm_domains();
 
-       platform_add_devices(r8a7779_early_devices,
-                           ARRAY_SIZE(r8a7779_early_devices));
+       platform_add_devices(r8a7779_devices_dt,
+                           ARRAY_SIZE(r8a7779_devices_dt));
        platform_add_devices(r8a7779_late_devices,
                            ARRAY_SIZE(r8a7779_late_devices));
 }
@@ -367,8 +394,8 @@ void __init r8a7779_earlytimer_init(void)
 
 void __init r8a7779_add_early_devices(void)
 {
-       early_platform_add_devices(r8a7779_early_devices,
-                                  ARRAY_SIZE(r8a7779_early_devices));
+       early_platform_add_devices(r8a7779_devices_dt,
+                                  ARRAY_SIZE(r8a7779_devices_dt));
 
        /* Early serial console setup is not included here due to
         * memory map collisions. The SCIF serial ports in r8a7779
@@ -386,3 +413,40 @@ void __init r8a7779_add_early_devices(void)
         * command line in case of the marzen board.
         */
 }
+
+#ifdef CONFIG_USE_OF
+void __init r8a7779_init_delay(void)
+{
+       shmobile_setup_delay(1000, 2, 4); /* Cortex-A9 @ 1000MHz */
+}
+
+static const struct of_dev_auxdata r8a7779_auxdata_lookup[] __initconst = {
+       {},
+};
+
+void __init r8a7779_add_standard_devices_dt(void)
+{
+       /* clocks are setup late during boot in the case of DT */
+       r8a7779_clock_init();
+
+       platform_add_devices(r8a7779_devices_dt,
+                            ARRAY_SIZE(r8a7779_devices_dt));
+       of_platform_populate(NULL, of_default_bus_match_table,
+                            r8a7779_auxdata_lookup, NULL);
+}
+
+static const char *r8a7779_compat_dt[] __initdata = {
+       "renesas,r8a7779",
+       NULL,
+};
+
+DT_MACHINE_START(R8A7779_DT, "Generic R8A7779 (Flattened Device Tree)")
+       .map_io         = r8a7779_map_io,
+       .init_early     = r8a7779_init_delay,
+       .nr_irqs        = NR_IRQS_LEGACY,
+       .init_irq       = r8a7779_init_irq_dt,
+       .init_machine   = r8a7779_add_standard_devices_dt,
+       .init_time      = shmobile_timer_init,
+       .dt_compat      = r8a7779_compat_dt,
+MACHINE_END
+#endif /* CONFIG_USE_OF */
index bdab575f88bcf0bc57fe267d8369a6603c9fcc26..e8cd93a5c5503cdbd86342f0e3742fedcdca531b 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/platform_device.h>
 #include <linux/of_platform.h>
 #include <linux/delay.h>
@@ -32,6 +33,7 @@
 #include <linux/sh_intc.h>
 #include <linux/sh_timer.h>
 #include <linux/platform_data/sh_ipmmu.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
 #include <mach/dma-register.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
@@ -810,7 +812,128 @@ static struct platform_device ipmmu_device = {
        .num_resources  = ARRAY_SIZE(ipmmu_resources),
 };
 
-static struct platform_device *sh73a0_early_devices_dt[] __initdata = {
+static struct renesas_intc_irqpin_config irqpin0_platform_data = {
+       .irq_base = irq_pin(0), /* IRQ0 -> IRQ7 */
+};
+
+static struct resource irqpin0_resources[] = {
+       DEFINE_RES_MEM(0xe6900000, 4), /* ICR1A */
+       DEFINE_RES_MEM(0xe6900010, 4), /* INTPRI00A */
+       DEFINE_RES_MEM(0xe6900020, 1), /* INTREQ00A */
+       DEFINE_RES_MEM(0xe6900040, 1), /* INTMSK00A */
+       DEFINE_RES_MEM(0xe6900060, 1), /* INTMSKCLR00A */
+       DEFINE_RES_IRQ(gic_spi(1)), /* IRQ0 */
+       DEFINE_RES_IRQ(gic_spi(2)), /* IRQ1 */
+       DEFINE_RES_IRQ(gic_spi(3)), /* IRQ2 */
+       DEFINE_RES_IRQ(gic_spi(4)), /* IRQ3 */
+       DEFINE_RES_IRQ(gic_spi(5)), /* IRQ4 */
+       DEFINE_RES_IRQ(gic_spi(6)), /* IRQ5 */
+       DEFINE_RES_IRQ(gic_spi(7)), /* IRQ6 */
+       DEFINE_RES_IRQ(gic_spi(8)), /* IRQ7 */
+};
+
+static struct platform_device irqpin0_device = {
+       .name           = "renesas_intc_irqpin",
+       .id             = 0,
+       .resource       = irqpin0_resources,
+       .num_resources  = ARRAY_SIZE(irqpin0_resources),
+       .dev            = {
+               .platform_data  = &irqpin0_platform_data,
+       },
+};
+
+static struct renesas_intc_irqpin_config irqpin1_platform_data = {
+       .irq_base = irq_pin(8), /* IRQ8 -> IRQ15 */
+       .control_parent = true, /* Disable spurious IRQ10 */
+};
+
+static struct resource irqpin1_resources[] = {
+       DEFINE_RES_MEM(0xe6900004, 4), /* ICR2A */
+       DEFINE_RES_MEM(0xe6900014, 4), /* INTPRI10A */
+       DEFINE_RES_MEM(0xe6900024, 1), /* INTREQ10A */
+       DEFINE_RES_MEM(0xe6900044, 1), /* INTMSK10A */
+       DEFINE_RES_MEM(0xe6900064, 1), /* INTMSKCLR10A */
+       DEFINE_RES_IRQ(gic_spi(9)), /* IRQ8 */
+       DEFINE_RES_IRQ(gic_spi(10)), /* IRQ9 */
+       DEFINE_RES_IRQ(gic_spi(11)), /* IRQ10 */
+       DEFINE_RES_IRQ(gic_spi(12)), /* IRQ11 */
+       DEFINE_RES_IRQ(gic_spi(13)), /* IRQ12 */
+       DEFINE_RES_IRQ(gic_spi(14)), /* IRQ13 */
+       DEFINE_RES_IRQ(gic_spi(15)), /* IRQ14 */
+       DEFINE_RES_IRQ(gic_spi(16)), /* IRQ15 */
+};
+
+static struct platform_device irqpin1_device = {
+       .name           = "renesas_intc_irqpin",
+       .id             = 1,
+       .resource       = irqpin1_resources,
+       .num_resources  = ARRAY_SIZE(irqpin1_resources),
+       .dev            = {
+               .platform_data  = &irqpin1_platform_data,
+       },
+};
+
+static struct renesas_intc_irqpin_config irqpin2_platform_data = {
+       .irq_base = irq_pin(16), /* IRQ16 -> IRQ23 */
+};
+
+static struct resource irqpin2_resources[] = {
+       DEFINE_RES_MEM(0xe6900008, 4), /* ICR3A */
+       DEFINE_RES_MEM(0xe6900018, 4), /* INTPRI20A */
+       DEFINE_RES_MEM(0xe6900028, 1), /* INTREQ20A */
+       DEFINE_RES_MEM(0xe6900048, 1), /* INTMSK20A */
+       DEFINE_RES_MEM(0xe6900068, 1), /* INTMSKCLR20A */
+       DEFINE_RES_IRQ(gic_spi(17)), /* IRQ16 */
+       DEFINE_RES_IRQ(gic_spi(18)), /* IRQ17 */
+       DEFINE_RES_IRQ(gic_spi(19)), /* IRQ18 */
+       DEFINE_RES_IRQ(gic_spi(20)), /* IRQ19 */
+       DEFINE_RES_IRQ(gic_spi(21)), /* IRQ20 */
+       DEFINE_RES_IRQ(gic_spi(22)), /* IRQ21 */
+       DEFINE_RES_IRQ(gic_spi(23)), /* IRQ22 */
+       DEFINE_RES_IRQ(gic_spi(24)), /* IRQ23 */
+};
+
+static struct platform_device irqpin2_device = {
+       .name           = "renesas_intc_irqpin",
+       .id             = 2,
+       .resource       = irqpin2_resources,
+       .num_resources  = ARRAY_SIZE(irqpin2_resources),
+       .dev            = {
+               .platform_data  = &irqpin2_platform_data,
+       },
+};
+
+static struct renesas_intc_irqpin_config irqpin3_platform_data = {
+       .irq_base = irq_pin(24), /* IRQ24 -> IRQ31 */
+};
+
+static struct resource irqpin3_resources[] = {
+       DEFINE_RES_MEM(0xe690000c, 4), /* ICR4A */
+       DEFINE_RES_MEM(0xe690001c, 4), /* INTPRI30A */
+       DEFINE_RES_MEM(0xe690002c, 1), /* INTREQ30A */
+       DEFINE_RES_MEM(0xe690004c, 1), /* INTMSK30A */
+       DEFINE_RES_MEM(0xe690006c, 1), /* INTMSKCLR30A */
+       DEFINE_RES_IRQ(gic_spi(25)), /* IRQ24 */
+       DEFINE_RES_IRQ(gic_spi(26)), /* IRQ25 */
+       DEFINE_RES_IRQ(gic_spi(27)), /* IRQ26 */
+       DEFINE_RES_IRQ(gic_spi(28)), /* IRQ27 */
+       DEFINE_RES_IRQ(gic_spi(29)), /* IRQ28 */
+       DEFINE_RES_IRQ(gic_spi(30)), /* IRQ29 */
+       DEFINE_RES_IRQ(gic_spi(31)), /* IRQ30 */
+       DEFINE_RES_IRQ(gic_spi(32)), /* IRQ31 */
+};
+
+static struct platform_device irqpin3_device = {
+       .name           = "renesas_intc_irqpin",
+       .id             = 3,
+       .resource       = irqpin3_resources,
+       .num_resources  = ARRAY_SIZE(irqpin3_resources),
+       .dev            = {
+               .platform_data  = &irqpin3_platform_data,
+       },
+};
+
+static struct platform_device *sh73a0_devices_dt[] __initdata = {
        &scif0_device,
        &scif1_device,
        &scif2_device,
@@ -838,6 +961,10 @@ static struct platform_device *sh73a0_late_devices[] __initdata = {
        &dma0_device,
        &mpdma0_device,
        &pmu_device,
+       &irqpin0_device,
+       &irqpin1_device,
+       &irqpin2_device,
+       &irqpin3_device,
 };
 
 #define SRCR2          IOMEM(0xe61580b0)
@@ -847,8 +974,8 @@ void __init sh73a0_add_standard_devices(void)
        /* Clear software reset bit on SY-DMAC module */
        __raw_writel(__raw_readl(SRCR2) & ~(1 << 18), SRCR2);
 
-       platform_add_devices(sh73a0_early_devices_dt,
-                           ARRAY_SIZE(sh73a0_early_devices_dt));
+       platform_add_devices(sh73a0_devices_dt,
+                           ARRAY_SIZE(sh73a0_devices_dt));
        platform_add_devices(sh73a0_early_devices,
                            ARRAY_SIZE(sh73a0_early_devices));
        platform_add_devices(sh73a0_late_devices,
@@ -867,8 +994,8 @@ void __init sh73a0_earlytimer_init(void)
 
 void __init sh73a0_add_early_devices(void)
 {
-       early_platform_add_devices(sh73a0_early_devices_dt,
-                                  ARRAY_SIZE(sh73a0_early_devices_dt));
+       early_platform_add_devices(sh73a0_devices_dt,
+                                  ARRAY_SIZE(sh73a0_devices_dt));
        early_platform_add_devices(sh73a0_early_devices,
                                   ARRAY_SIZE(sh73a0_early_devices));
 
@@ -878,23 +1005,9 @@ void __init sh73a0_add_early_devices(void)
 
 #ifdef CONFIG_USE_OF
 
-/* Please note that the clock initialisation shcheme used in
- * sh73a0_add_early_devices_dt() and sh73a0_add_standard_devices_dt()
- * does not work with SMP as there is a yet to be resolved lock-up in
- * workqueue initialisation.
- *
- * CONFIG_SMP should be disabled when using this code.
- */
-
-void __init sh73a0_add_early_devices_dt(void)
+void __init sh73a0_init_delay(void)
 {
        shmobile_setup_delay(1196, 44, 46); /* Cortex-A9 @ 1196MHz */
-
-       early_platform_add_devices(sh73a0_early_devices_dt,
-                                  ARRAY_SIZE(sh73a0_early_devices_dt));
-
-       /* setup early console here as well */
-       shmobile_setup_console();
 }
 
 static const struct of_dev_auxdata sh73a0_auxdata_lookup[] __initconst = {
@@ -906,8 +1019,8 @@ void __init sh73a0_add_standard_devices_dt(void)
        /* clocks are setup late during boot in the case of DT */
        sh73a0_clock_init();
 
-       platform_add_devices(sh73a0_early_devices_dt,
-                            ARRAY_SIZE(sh73a0_early_devices_dt));
+       platform_add_devices(sh73a0_devices_dt,
+                            ARRAY_SIZE(sh73a0_devices_dt));
        of_platform_populate(NULL, of_default_bus_match_table,
                             sh73a0_auxdata_lookup, NULL);
 }
@@ -918,10 +1031,11 @@ static const char *sh73a0_boards_compat_dt[] __initdata = {
 };
 
 DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)")
+       .smp            = smp_ops(sh73a0_smp_ops),
        .map_io         = sh73a0_map_io,
-       .init_early     = sh73a0_add_early_devices_dt,
+       .init_early     = sh73a0_init_delay,
        .nr_irqs        = NR_IRQS_LEGACY,
-       .init_irq       = sh73a0_init_irq_dt,
+       .init_irq       = irqchip_init,
        .init_machine   = sh73a0_add_standard_devices_dt,
        .init_time      = shmobile_timer_init,
        .dt_compat      = sh73a0_boards_compat_dt,
index 953eb1f9388d672bd763d0287ea32f214438e840..8225c16b371b47fb549b8dd6a9397b5059229b62 100644 (file)
 #include <mach/emev2.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
-#include <asm/cacheflush.h>
 
 #define EMEV2_SCU_BASE 0x1e000000
 
-static DEFINE_SPINLOCK(scu_lock);
-static void __iomem *scu_base;
-
-static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
-{
-       unsigned long tmp;
-
-       /* we assume this code is running on a different cpu
-        * than the one that is changing coherency setting */
-       spin_lock(&scu_lock);
-       tmp = readl(scu_base + 8);
-       tmp &= ~clr;
-       tmp |= set;
-       writel(tmp, scu_base + 8);
-       spin_unlock(&scu_lock);
-
-}
-
-static unsigned int __init emev2_get_core_count(void)
-{
-       if (!scu_base) {
-               scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
-               emev2_clock_init(); /* need ioremapped SMU */
-       }
-
-       WARN_ON_ONCE(!scu_base);
-
-       return scu_base ? scu_get_core_count(scu_base) : 1;
-}
-
-static int emev2_platform_cpu_kill(unsigned int cpu)
-{
-       return 0; /* not supported yet */
-}
-
-static int __maybe_unused emev2_cpu_kill(unsigned int cpu)
-{
-       int k;
-
-       /* this function is running on another CPU than the offline target,
-        * here we need wait for shutdown code in platform_cpu_die() to
-        * finish before asking SoC-specific code to power off the CPU core.
-        */
-       for (k = 0; k < 1000; k++) {
-               if (shmobile_cpu_is_dead(cpu))
-                       return emev2_platform_cpu_kill(cpu);
-               mdelay(1);
-       }
-
-       return 0;
-}
-
-
 static void __cpuinit emev2_secondary_init(unsigned int cpu)
 {
        gic_secondary_init(0);
@@ -92,31 +38,30 @@ static void __cpuinit emev2_secondary_init(unsigned int cpu)
 
 static int __cpuinit emev2_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-       cpu = cpu_logical_map(cpu);
-
-       /* enable cache coherency */
-       modify_scu_cpu_psr(0, 3 << (cpu * 8));
-
-       /* Tell ROM loader about our vector (in headsmp.S) */
-       emev2_set_boot_vector(__pa(shmobile_secondary_vector));
-
-       arch_send_wakeup_ipi_mask(cpumask_of(cpu));
+       arch_send_wakeup_ipi_mask(cpumask_of(cpu_logical_map(cpu)));
        return 0;
 }
 
 static void __init emev2_smp_prepare_cpus(unsigned int max_cpus)
 {
-       int cpu = cpu_logical_map(0);
+       scu_enable(shmobile_scu_base);
 
-       scu_enable(scu_base);
+       /* Tell ROM loader about our vector (in headsmp-scu.S) */
+       emev2_set_boot_vector(__pa(shmobile_secondary_vector_scu));
 
-       /* enable cache coherency on CPU0 */
-       modify_scu_cpu_psr(0, 3 << (cpu * 8));
+       /* enable cache coherency on booting CPU */
+       scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
 }
 
 static void __init emev2_smp_init_cpus(void)
 {
-       unsigned int ncores = emev2_get_core_count();
+       unsigned int ncores;
+
+       /* setup EMEV2 specific SCU base */
+       shmobile_scu_base = ioremap(EMEV2_SCU_BASE, PAGE_SIZE);
+       emev2_clock_init(); /* need ioremapped SMU */
+
+       ncores = shmobile_scu_base ? scu_get_core_count(shmobile_scu_base) : 1;
 
        shmobile_smp_init_cpus(ncores);
 }
@@ -126,9 +71,4 @@ struct smp_operations emev2_smp_ops __initdata = {
        .smp_prepare_cpus       = emev2_smp_prepare_cpus,
        .smp_secondary_init     = emev2_secondary_init,
        .smp_boot_secondary     = emev2_boot_secondary,
-#ifdef CONFIG_HOTPLUG_CPU
-       .cpu_kill               = emev2_cpu_kill,
-       .cpu_die                = shmobile_cpu_die,
-       .cpu_disable            = shmobile_cpu_disable,
-#endif
 };
index 3a4acf23edcf5c920ba1c4e9a665d676d704ab47..ea4535a5c4e23e8014dc84207bb2d6c043c5d73a 100644 (file)
 #include <linux/irqchip/arm-gic.h>
 #include <mach/common.h>
 #include <mach/r8a7779.h>
+#include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
 
 #define AVECR IOMEM(0xfe700040)
+#define R8A7779_SCU_BASE 0xf0000000
 
 static struct r8a7779_pm_ch r8a7779_ch_cpu1 = {
        .chan_offs = 0x40, /* PWRSR0 .. PWRER0 */
@@ -56,44 +58,14 @@ static struct r8a7779_pm_ch *r8a7779_ch_cpu[4] = {
        [3] = &r8a7779_ch_cpu3,
 };
 
-static void __iomem *scu_base_addr(void)
-{
-       return (void __iomem *)0xf0000000;
-}
-
-static DEFINE_SPINLOCK(scu_lock);
-static unsigned long tmp;
-
 #ifdef CONFIG_HAVE_ARM_TWD
-static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
-
+static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, R8A7779_SCU_BASE + 0x600, 29);
 void __init r8a7779_register_twd(void)
 {
        twd_local_timer_register(&twd_local_timer);
 }
 #endif
 
-static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
-{
-       void __iomem *scu_base = scu_base_addr();
-
-       spin_lock(&scu_lock);
-       tmp = __raw_readl(scu_base + 8);
-       tmp &= ~clr;
-       tmp |= set;
-       spin_unlock(&scu_lock);
-
-       /* disable cache coherency after releasing the lock */
-       __raw_writel(tmp, scu_base + 8);
-}
-
-static unsigned int __init r8a7779_get_core_count(void)
-{
-       void __iomem *scu_base = scu_base_addr();
-
-       return scu_get_core_count(scu_base);
-}
-
 static int r8a7779_platform_cpu_kill(unsigned int cpu)
 {
        struct r8a7779_pm_ch *ch = NULL;
@@ -101,9 +73,6 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu)
 
        cpu = cpu_logical_map(cpu);
 
-       /* disable cache coherency */
-       modify_scu_cpu_psr(3 << (cpu * 8), 0);
-
        if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
                ch = r8a7779_ch_cpu[cpu];
 
@@ -113,25 +82,6 @@ static int r8a7779_platform_cpu_kill(unsigned int cpu)
        return ret ? ret : 1;
 }
 
-static int __maybe_unused r8a7779_cpu_kill(unsigned int cpu)
-{
-       int k;
-
-       /* this function is running on another CPU than the offline target,
-        * here we need wait for shutdown code in platform_cpu_die() to
-        * finish before asking SoC-specific code to power off the CPU core.
-        */
-       for (k = 0; k < 1000; k++) {
-               if (shmobile_cpu_is_dead(cpu))
-                       return r8a7779_platform_cpu_kill(cpu);
-
-               mdelay(1);
-       }
-
-       return 0;
-}
-
-
 static void __cpuinit r8a7779_secondary_init(unsigned int cpu)
 {
        gic_secondary_init(0);
@@ -144,9 +94,6 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct
 
        cpu = cpu_logical_map(cpu);
 
-       /* enable cache coherency */
-       modify_scu_cpu_psr(0, 3 << (cpu * 8));
-
        if (cpu < ARRAY_SIZE(r8a7779_ch_cpu))
                ch = r8a7779_ch_cpu[cpu];
 
@@ -158,15 +105,13 @@ static int __cpuinit r8a7779_boot_secondary(unsigned int cpu, struct task_struct
 
 static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
 {
-       int cpu = cpu_logical_map(0);
+       scu_enable(shmobile_scu_base);
 
-       scu_enable(scu_base_addr());
+       /* Map the reset vector (in headsmp-scu.S) */
+       __raw_writel(__pa(shmobile_secondary_vector_scu), AVECR);
 
-       /* Map the reset vector (in headsmp.S) */
-       __raw_writel(__pa(shmobile_secondary_vector), AVECR);
-
-       /* enable cache coherency on CPU0 */
-       modify_scu_cpu_psr(0, 3 << (cpu * 8));
+       /* enable cache coherency on booting CPU */
+       scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
 
        r8a7779_pm_init();
 
@@ -178,10 +123,60 @@ static void __init r8a7779_smp_prepare_cpus(unsigned int max_cpus)
 
 static void __init r8a7779_smp_init_cpus(void)
 {
-       unsigned int ncores = r8a7779_get_core_count();
+       /* setup r8a7779 specific SCU base */
+       shmobile_scu_base = IOMEM(R8A7779_SCU_BASE);
+
+       shmobile_smp_init_cpus(scu_get_core_count(shmobile_scu_base));
+}
 
-       shmobile_smp_init_cpus(ncores);
+#ifdef CONFIG_HOTPLUG_CPU
+static int r8a7779_scu_psr_core_disabled(int cpu)
+{
+       unsigned long mask = 3 << (cpu * 8);
+
+       if ((__raw_readl(shmobile_scu_base + 8) & mask) == mask)
+               return 1;
+
+       return 0;
+}
+
+static int r8a7779_cpu_kill(unsigned int cpu)
+{
+       int k;
+
+       /* this function is running on another CPU than the offline target,
+        * here we need wait for shutdown code in platform_cpu_die() to
+        * finish before asking SoC-specific code to power off the CPU core.
+        */
+       for (k = 0; k < 1000; k++) {
+               if (r8a7779_scu_psr_core_disabled(cpu))
+                       return r8a7779_platform_cpu_kill(cpu);
+
+               mdelay(1);
+       }
+
+       return 0;
+}
+
+static void r8a7779_cpu_die(unsigned int cpu)
+{
+       dsb();
+       flush_cache_all();
+
+       /* disable cache coherency */
+       scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF);
+
+       /* Endless loop until power off from r8a7779_cpu_kill() */
+       while (1)
+               cpu_do_idle();
+}
+
+static int r8a7779_cpu_disable(unsigned int cpu)
+{
+       /* only CPU1->3 have power domains, do not allow hotplug of CPU0 */
+       return cpu == 0 ? -EPERM : 0;
 }
+#endif /* CONFIG_HOTPLUG_CPU */
 
 struct smp_operations r8a7779_smp_ops  __initdata = {
        .smp_init_cpus          = r8a7779_smp_init_cpus,
@@ -190,7 +185,7 @@ struct smp_operations r8a7779_smp_ops  __initdata = {
        .smp_boot_secondary     = r8a7779_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
        .cpu_kill               = r8a7779_cpu_kill,
-       .cpu_die                = shmobile_cpu_die,
-       .cpu_disable            = shmobile_cpu_disable,
+       .cpu_die                = r8a7779_cpu_die,
+       .cpu_disable            = r8a7779_cpu_disable,
 #endif
 };
index acb46a94ccdfb8ec967ed5e52e5a9593f531c414..5ae502b16437c53dec44317f63c8f53e14edf273 100644 (file)
 
 #define PSTR_SHUTDOWN_MODE     3
 
-static void __iomem *scu_base_addr(void)
-{
-       return (void __iomem *)0xf0000000;
-}
+#define SH73A0_SCU_BASE 0xf0000000
 
 #ifdef CONFIG_HAVE_ARM_TWD
-static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
+static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, SH73A0_SCU_BASE + 0x600, 29);
 void __init sh73a0_register_twd(void)
 {
        twd_local_timer_register(&twd_local_timer);
 }
 #endif
 
-static unsigned int __init sh73a0_get_core_count(void)
-{
-       void __iomem *scu_base = scu_base_addr();
-
-       return scu_get_core_count(scu_base);
-}
-
 static void __cpuinit sh73a0_secondary_init(unsigned int cpu)
 {
        gic_secondary_init(0);
@@ -78,21 +68,22 @@ static int __cpuinit sh73a0_boot_secondary(unsigned int cpu, struct task_struct
 
 static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
 {
-       scu_enable(scu_base_addr());
+       scu_enable(shmobile_scu_base);
 
-       /* Map the reset vector (in headsmp-sh73a0.S) */
+       /* Map the reset vector (in headsmp-scu.S) */
        __raw_writel(0, APARMBAREA);      /* 4k */
-       __raw_writel(__pa(sh73a0_secondary_vector), SBAR);
+       __raw_writel(__pa(shmobile_secondary_vector_scu), SBAR);
 
        /* enable cache coherency on booting CPU */
-       scu_power_mode(scu_base_addr(), SCU_PM_NORMAL);
+       scu_power_mode(shmobile_scu_base, SCU_PM_NORMAL);
 }
 
 static void __init sh73a0_smp_init_cpus(void)
 {
-       unsigned int ncores = sh73a0_get_core_count();
+       /* setup sh73a0 specific SCU base */
+       shmobile_scu_base = IOMEM(SH73A0_SCU_BASE);
 
-       shmobile_smp_init_cpus(ncores);
+       shmobile_smp_init_cpus(scu_get_core_count(shmobile_scu_base));
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -128,11 +119,16 @@ static void sh73a0_cpu_die(unsigned int cpu)
        flush_cache_all();
 
        /* Set power off mode. This takes the CPU out of the MP cluster */
-       scu_power_mode(scu_base_addr(), SCU_PM_POWEROFF);
+       scu_power_mode(shmobile_scu_base, SCU_PM_POWEROFF);
 
        /* Enter shutdown mode */
        cpu_do_idle();
 }
+
+static int sh73a0_cpu_disable(unsigned int cpu)
+{
+       return 0; /* CPU0 and CPU1 supported */
+}
 #endif /* CONFIG_HOTPLUG_CPU */
 
 struct smp_operations sh73a0_smp_ops __initdata = {
@@ -143,6 +139,6 @@ struct smp_operations sh73a0_smp_ops __initdata = {
 #ifdef CONFIG_HOTPLUG_CPU
        .cpu_kill               = sh73a0_cpu_kill,
        .cpu_die                = sh73a0_cpu_die,
-       .cpu_disable            = shmobile_cpu_disable_any,
+       .cpu_disable            = sh73a0_cpu_disable,
 #endif
 };
index f9d754f90c5991e6bce11371fa5702f9a8d81c16..d2b3937c4014c1cc737d737d1800f0fb58de36ea 100644 (file)
@@ -14,7 +14,7 @@
 #define pr_fmt(fmt) "SPEAr3xx: " fmt
 
 #include <linux/amba/pl022.h>
-#include <linux/amba/pl08x.h>
+#include <linux/amba/pl080.h>
 #include <linux/io.h>
 #include <plat/pl080.h>
 #include <mach/generic.h>
index f6b46ae2b7f868829310fa22295d251eda20b95b..e40326d0e29fa8fb6dff8e694f8539ca09e8e31f 100644 (file)
@@ -10,6 +10,7 @@ obj-y                                 += pm.o
 obj-y                                  += reset.o
 obj-y                                  += reset-handler.o
 obj-y                                  += sleep.o
+obj-y                                  += tegra.o
 obj-$(CONFIG_CPU_IDLE)                 += cpuidle.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += tegra20_speedo.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += tegra2_emc.o
@@ -27,9 +28,7 @@ obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
 obj-$(CONFIG_CPU_FREQ)                  += cpu-tegra.o
 obj-$(CONFIG_TEGRA_PCI)                        += pcie.o
 
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += board-dt-tegra20.o
-obj-$(CONFIG_ARCH_TEGRA_3x_SOC)                += board-dt-tegra30.o
-obj-$(CONFIG_ARCH_TEGRA_114_SOC)       += board-dt-tegra114.o
+obj-$(CONFIG_ARCH_TEGRA_114_SOC)       += tegra114_speedo.o
 ifeq ($(CONFIG_CPU_IDLE),y)
 obj-$(CONFIG_ARCH_TEGRA_114_SOC)       += cpuidle-tegra114.o
 endif
diff --git a/arch/arm/mach-tegra/board-dt-tegra114.c b/arch/arm/mach-tegra/board-dt-tegra114.c
deleted file mode 100644 (file)
index 085d636..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * NVIDIA Tegra114 device tree board support
- *
- * Copyright (C) 2013 NVIDIA Corporation
- *
- * 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/of.h>
-#include <linux/of_platform.h>
-#include <linux/clocksource.h>
-
-#include <asm/mach/arch.h>
-
-#include "board.h"
-#include "common.h"
-
-static void __init tegra114_dt_init(void)
-{
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
-static const char * const tegra114_dt_board_compat[] = {
-       "nvidia,tegra114",
-       NULL,
-};
-
-DT_MACHINE_START(TEGRA114_DT, "NVIDIA Tegra114 (Flattened Device Tree)")
-       .smp            = smp_ops(tegra_smp_ops),
-       .map_io         = tegra_map_common_io,
-       .init_early     = tegra114_init_early,
-       .init_irq       = tegra_dt_init_irq,
-       .init_time      = clocksource_of_init,
-       .init_machine   = tegra114_dt_init,
-       .init_late      = tegra_init_late,
-       .restart        = tegra_assert_system_reset,
-       .dt_compat      = tegra114_dt_board_compat,
-MACHINE_END
diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
deleted file mode 100644 (file)
index bf68567..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * arch/arm/mach-tegra/board-dt-tegra30.c
- *
- * NVIDIA Tegra30 device tree board support
- *
- * Copyright (C) 2011 NVIDIA Corporation
- *
- * Derived from:
- *
- * arch/arm/mach-tegra/board-dt-tegra20.c
- *
- * 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/clocksource.h>
-#include <linux/kernel.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 <asm/mach/arch.h>
-
-#include "board.h"
-#include "common.h"
-#include "iomap.h"
-
-static void __init tegra30_dt_init(void)
-{
-       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
-}
-
-static const char *tegra30_dt_board_compat[] = {
-       "nvidia,tegra30",
-       NULL
-};
-
-DT_MACHINE_START(TEGRA30_DT, "NVIDIA Tegra30 (Flattened Device Tree)")
-       .smp            = smp_ops(tegra_smp_ops),
-       .map_io         = tegra_map_common_io,
-       .init_early     = tegra30_init_early,
-       .init_irq       = tegra_dt_init_irq,
-       .init_time      = clocksource_of_init,
-       .init_machine   = tegra30_dt_init,
-       .init_late      = tegra_init_late,
-       .restart        = tegra_assert_system_reset,
-       .dt_compat      = tegra30_dt_board_compat,
-MACHINE_END
index 3cdc1bb8254c6764c453fb978f748aae6d8f526a..035b240b9e1502dba8b6c88240c00359bb7aa605 100644 (file)
@@ -56,13 +56,17 @@ int __init harmony_pcie_init(void)
        gpio_direction_output(en_vdd_1v05, 1);
 
        regulator = regulator_get(NULL, "vdd_ldo0,vddio_pex_clk");
-       if (IS_ERR_OR_NULL(regulator)) {
-               pr_err("%s: regulator_get failed: %d\n", __func__,
-                      (int)PTR_ERR(regulator));
+       if (IS_ERR(regulator)) {
+               err = PTR_ERR(regulator);
+               pr_err("%s: regulator_get failed: %d\n", __func__, err);
                goto err_reg;
        }
 
-       regulator_enable(regulator);
+       err = regulator_enable(regulator);
+       if (err) {
+               pr_err("%s: regulator_enable failed: %d\n", __func__, err);
+               goto err_en;
+       }
 
        err = tegra_pcie_init(true, true);
        if (err) {
@@ -74,6 +78,7 @@ int __init harmony_pcie_init(void)
 
 err_pcie:
        regulator_disable(regulator);
+err_en:
        regulator_put(regulator);
 err_reg:
        gpio_free(en_vdd_1v05);
index 86851c81a35093a44df58a52472be5d9ed2d7229..60431de585ca71c5a42c3646227cf80338ec4aec 100644 (file)
@@ -26,9 +26,7 @@
 
 void tegra_assert_system_reset(char mode, const char *cmd);
 
-void __init tegra20_init_early(void);
-void __init tegra30_init_early(void);
-void __init tegra114_init_early(void);
+void __init tegra_init_early(void);
 void __init tegra_map_common_io(void);
 void __init tegra_init_irq(void);
 void __init tegra_dt_init_irq(void);
index 5449a3f2977bc5d642891e00ce93087947ed17d8..eb1f3c8c74ccf0ac99839b97bec66551649584a9 100644 (file)
@@ -33,6 +33,7 @@
 #include "common.h"
 #include "fuse.h"
 #include "iomap.h"
+#include "irq.h"
 #include "pmc.h"
 #include "apbio.h"
 #include "sleep.h"
@@ -61,8 +62,10 @@ u32 tegra_uart_config[4] = {
 void __init tegra_dt_init_irq(void)
 {
        tegra_clocks_init();
+       tegra_pmc_init();
        tegra_init_irq();
        irqchip_init();
+       tegra_legacy_irq_syscore_init();
 }
 #endif
 
@@ -94,40 +97,18 @@ static void __init tegra_init_cache(void)
 
 }
 
-static void __init tegra_init_early(void)
+void __init tegra_init_early(void)
 {
        tegra_cpu_reset_handler_init();
        tegra_apb_io_init();
        tegra_init_fuse();
        tegra_init_cache();
-       tegra_pmc_init();
        tegra_powergate_init();
+       tegra_hotplug_init();
 }
 
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-void __init tegra20_init_early(void)
-{
-       tegra_init_early();
-       tegra20_hotplug_init();
-}
-#endif
-
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
-void __init tegra30_init_early(void)
-{
-       tegra_init_early();
-       tegra30_hotplug_init();
-}
-#endif
-
-#ifdef CONFIG_ARCH_TEGRA_114_SOC
-void __init tegra114_init_early(void)
-{
-       tegra_init_early();
-}
-#endif
-
 void __init tegra_init_late(void)
 {
+       tegra_init_suspend();
        tegra_powergate_debugfs_init();
 }
index 825ced4f7a404a48adc8861e35930a024aff30b2..8bbbdebed882fb7a49e8de19fb30b363858af8b6 100644 (file)
@@ -130,10 +130,6 @@ static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
                                           struct cpuidle_driver *drv,
                                           int index)
 {
-       struct cpuidle_state *state = &drv->states[index];
-       u32 cpu_on_time = state->exit_latency;
-       u32 cpu_off_time = state->target_residency - state->exit_latency;
-
        while (tegra20_cpu_is_resettable_soon())
                cpu_relax();
 
@@ -142,7 +138,7 @@ static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
 
        clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
 
-       tegra_idle_lp2_last(cpu_on_time, cpu_off_time);
+       tegra_idle_lp2_last();
 
        clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 
index 8b50cf4ddd6f04819e0c8a69bf4bf7eb9d28ddc5..c0931c8bb3e5f12c65aebef545c01e9305cb963d 100644 (file)
@@ -72,10 +72,6 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
                                           struct cpuidle_driver *drv,
                                           int index)
 {
-       struct cpuidle_state *state = &drv->states[index];
-       u32 cpu_on_time = state->exit_latency;
-       u32 cpu_off_time = state->target_residency - state->exit_latency;
-
        /* All CPUs entering LP2 is not working.
         * Don't let CPU0 enter LP2 when any secondary CPU is online.
         */
@@ -86,7 +82,7 @@ static bool tegra30_cpu_cluster_power_down(struct cpuidle_device *dev,
 
        clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
 
-       tegra_idle_lp2_last(cpu_on_time, cpu_off_time);
+       tegra_idle_lp2_last();
 
        clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 
@@ -102,12 +98,8 @@ static bool tegra30_cpu_core_power_down(struct cpuidle_device *dev,
 
        smp_wmb();
 
-       save_cpu_arch_register();
-
        cpu_suspend(0, tegra30_sleep_cpu_secondary_finish);
 
-       restore_cpu_arch_register();
-
        clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
 
        return true;
index f7db0782a6b6bdbcc256a06936831ee0d38f49e7..e035cd284a6eb5e3bf1268acb00da3c5784e5ced 100644 (file)
@@ -2,6 +2,7 @@
  * arch/arm/mach-tegra/fuse.c
  *
  * Copyright (C) 2010 Google, Inc.
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * Author:
  *     Colin Cross <ccross@android.com>
@@ -137,6 +138,9 @@ void tegra_init_fuse(void)
                tegra_fuse_spare_bit = TEGRA30_FUSE_SPARE_BIT;
                tegra_init_speedo_data = &tegra30_init_speedo_data;
                break;
+       case TEGRA114:
+               tegra_init_speedo_data = &tegra114_init_speedo_data;
+               break;
        default:
                pr_warn("Tegra: unknown chip id %d\n", tegra_chip_id);
                tegra_fuse_spare_bit = TEGRA20_FUSE_SPARE_BIT;
index da78434678c76029707c6df2d4f2b51a2f31a0bd..aacc00d059801bbfef78faa9251c276f9e4bf8da 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2010 Google, Inc.
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * Author:
  *     Colin Cross <ccross@android.com>
@@ -66,4 +67,10 @@ void tegra30_init_speedo_data(void);
 static inline void tegra30_init_speedo_data(void) {}
 #endif
 
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+void tegra114_init_speedo_data(void);
+#else
+static inline void tegra114_init_speedo_data(void) {}
+#endif
+
 #endif
index fd473f2b4c3d981e391a3fd8560c51f0b3ddedce..045c16f2dd51fae9d86551d91cb883f6e5d03aba 100644 (file)
@@ -7,8 +7,5 @@
 
 ENTRY(tegra_secondary_startup)
         bl      v7_invalidate_l1
-       /* Enable coresight */
-       mov32   r0, 0xC5ACCE55
-       mcr     p14, 0, r0, c7, c12, 6
         b       secondary_startup
 ENDPROC(tegra_secondary_startup)
index a599f6e36dea49768c6eb18d9550b3d04fb9c1db..8da9f78475da21f81ef314bbd7e9e04939398378 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *
  *  Copyright (C) 2002 ARM Ltd.
  *  All Rights Reserved
- *  Copyright (c) 2010, 2012 NVIDIA Corporation. All rights reserved.
+ *  Copyright (c) 2010, 2012-2013, NVIDIA Corporation. 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
@@ -15,6 +14,7 @@
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 
+#include "fuse.h"
 #include "sleep.h"
 
 static void (*tegra_hotplug_shutdown)(void);
@@ -56,18 +56,13 @@ int tegra_cpu_disable(unsigned int cpu)
        return cpu == 0 ? -EPERM : 0;
 }
 
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-extern void tegra20_hotplug_shutdown(void);
-void __init tegra20_hotplug_init(void)
+void __init tegra_hotplug_init(void)
 {
-       tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
-}
-#endif
+       if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
+               return;
 
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
-extern void tegra30_hotplug_shutdown(void);
-void __init tegra30_hotplug_init(void)
-{
-       tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
+       if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
+               tegra_hotplug_shutdown = tegra20_hotplug_shutdown;
+       if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
+               tegra_hotplug_shutdown = tegra30_hotplug_shutdown;
 }
-#endif
index 1952e82797ccd3f45eecb88e8be523dd0a3d8104..0de4eed1493dca411af5b91bbee8e2b0b6f87ed9 100644 (file)
@@ -4,7 +4,7 @@
  * Author:
  *     Colin Cross <ccross@android.com>
  *
- * Copyright (C) 2010, NVIDIA Corporation
+ * Copyright (C) 2010,2013, NVIDIA Corporation
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -23,6 +23,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/irqchip/arm-gic.h>
+#include <linux/syscore_ops.h>
 
 #include "board.h"
 #include "iomap.h"
@@ -43,6 +44,7 @@
 #define ICTLR_COP_IEP_CLASS    0x3c
 
 #define FIRST_LEGACY_IRQ 32
+#define TEGRA_MAX_NUM_ICTLRS   5
 
 #define SGI_MASK 0xFFFF
 
@@ -56,6 +58,15 @@ static void __iomem *ictlr_reg_base[] = {
        IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE),
 };
 
+#ifdef CONFIG_PM_SLEEP
+static u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
+static u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
+static u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
+static u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
+
+static u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
+#endif
+
 bool tegra_pending_sgi(void)
 {
        u32 pending_set;
@@ -125,6 +136,87 @@ static int tegra_retrigger(struct irq_data *d)
        return 1;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int tegra_set_wake(struct irq_data *d, unsigned int enable)
+{
+       u32 irq = d->irq;
+       u32 index, mask;
+
+       if (irq < FIRST_LEGACY_IRQ ||
+               irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32)
+               return -EINVAL;
+
+       index = ((irq - FIRST_LEGACY_IRQ) / 32);
+       mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);
+       if (enable)
+               ictlr_wake_mask[index] |= mask;
+       else
+               ictlr_wake_mask[index] &= ~mask;
+
+       return 0;
+}
+
+static int tegra_legacy_irq_suspend(void)
+{
+       unsigned long flags;
+       int i;
+
+       local_irq_save(flags);
+       for (i = 0; i < num_ictlrs; i++) {
+               void __iomem *ictlr = ictlr_reg_base[i];
+               /* Save interrupt state */
+               cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
+               cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
+               cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
+               cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
+
+               /* Disable COP interrupts */
+               writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
+
+               /* Disable CPU interrupts */
+               writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+
+               /* Enable the wakeup sources of ictlr */
+               writel_relaxed(ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
+       }
+       local_irq_restore(flags);
+
+       return 0;
+}
+
+static void tegra_legacy_irq_resume(void)
+{
+       unsigned long flags;
+       int i;
+
+       local_irq_save(flags);
+       for (i = 0; i < num_ictlrs; i++) {
+               void __iomem *ictlr = ictlr_reg_base[i];
+               writel_relaxed(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
+               writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+               writel_relaxed(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
+               writel_relaxed(cop_iep[i], ictlr + ICTLR_COP_IEP_CLASS);
+               writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
+               writel_relaxed(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
+       }
+       local_irq_restore(flags);
+}
+
+static struct syscore_ops tegra_legacy_irq_syscore_ops = {
+       .suspend = tegra_legacy_irq_suspend,
+       .resume = tegra_legacy_irq_resume,
+};
+
+int tegra_legacy_irq_syscore_init(void)
+{
+       register_syscore_ops(&tegra_legacy_irq_syscore_ops);
+
+       return 0;
+}
+#else
+#define tegra_set_wake NULL
+#endif
+
 void __init tegra_init_irq(void)
 {
        int i;
@@ -150,6 +242,8 @@ void __init tegra_init_irq(void)
        gic_arch_extn.irq_mask = tegra_mask;
        gic_arch_extn.irq_unmask = tegra_unmask;
        gic_arch_extn.irq_retrigger = tegra_retrigger;
+       gic_arch_extn.irq_set_wake = tegra_set_wake;
+       gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
 
        /*
         * Check if there is a devicetree present, since the GIC will be
index 5142649bba05513b46ead7a336b3082141ac41da..bc05ce5613fbf79195159f8eef03324992a5c73d 100644 (file)
 
 bool tegra_pending_sgi(void);
 
+#ifdef CONFIG_PM_SLEEP
+int tegra_legacy_irq_syscore_init(void);
+#else
+static inline int tegra_legacy_irq_syscore_init(void) { return 0; }
+#endif
+
 #endif
index 2c6b3d55213b49f16ee256548279b1742111bd20..516aab28fe34217a8f99576df6b89b99a82f39f9 100644 (file)
 #include <asm/smp_scu.h>
 #include <asm/smp_plat.h>
 
-#include <mach/powergate.h>
-
 #include "fuse.h"
 #include "flowctrl.h"
 #include "reset.h"
+#include "pmc.h"
 
 #include "common.h"
 #include "iomap.h"
 
-extern void tegra_secondary_startup(void);
-
 static cpumask_t tegra_cpu_init_mask;
 
-#define EVP_CPU_RESET_VECTOR \
-       (IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
-
 static void __cpuinit tegra_secondary_init(unsigned int cpu)
 {
        /*
@@ -54,25 +48,43 @@ static void __cpuinit tegra_secondary_init(unsigned int cpu)
        cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
 }
 
-static int tegra20_power_up_cpu(unsigned int cpu)
+
+static int tegra20_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-       /* Enable the CPU clock. */
-       tegra_enable_cpu_clock(cpu);
+       cpu = cpu_logical_map(cpu);
+
+       /*
+        * Force the CPU into reset. The CPU must remain in reset when
+        * the flow controller state is cleared (which will cause the
+        * flow controller to stop driving reset if the CPU has been
+        * power-gated via the flow controller). This will have no
+        * effect on first boot of the CPU since it should already be
+        * in reset.
+        */
+       tegra_put_cpu_in_reset(cpu);
 
-       /* Clear flow controller CSR. */
-       flowctrl_write_cpu_csr(cpu, 0);
+       /*
+        * Unhalt the CPU. If the flow controller was used to
+        * power-gate the CPU this will cause the flow controller to
+        * stop driving reset. The CPU will remain in reset because the
+        * clock and reset block is now driving reset.
+        */
+       flowctrl_write_cpu_halt(cpu, 0);
 
+       tegra_enable_cpu_clock(cpu);
+       flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
+       tegra_cpu_out_of_reset(cpu);
        return 0;
 }
 
-static int tegra30_power_up_cpu(unsigned int cpu)
+static int tegra30_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-       int ret, pwrgateid;
+       int ret;
        unsigned long timeout;
 
-       pwrgateid = tegra_cpu_powergate_id(cpu);
-       if (pwrgateid < 0)
-               return pwrgateid;
+       cpu = cpu_logical_map(cpu);
+       tegra_put_cpu_in_reset(cpu);
+       flowctrl_write_cpu_halt(cpu, 0);
 
        /*
         * The power up sequence of cold boot CPU and warm boot CPU
@@ -85,13 +97,13 @@ static int tegra30_power_up_cpu(unsigned int cpu)
         * the IO clamps.
         * For cold boot CPU, do not wait. After the cold boot CPU be
         * booted, it will run to tegra_secondary_init() and set
-        * tegra_cpu_init_mask which influences what tegra30_power_up_cpu()
+        * tegra_cpu_init_mask which influences what tegra30_boot_secondary()
         * next time around.
         */
        if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
                timeout = jiffies + msecs_to_jiffies(50);
                do {
-                       if (!tegra_powergate_is_powered(pwrgateid))
+                       if (tegra_pmc_cpu_is_powered(cpu))
                                goto remove_clamps;
                        udelay(10);
                } while (time_before(jiffies, timeout));
@@ -103,14 +115,14 @@ static int tegra30_power_up_cpu(unsigned int cpu)
         * be un-gated by un-toggling the power gate register
         * manually.
         */
-       if (!tegra_powergate_is_powered(pwrgateid)) {
-               ret = tegra_powergate_power_on(pwrgateid);
+       if (!tegra_pmc_cpu_is_powered(cpu)) {
+               ret = tegra_pmc_cpu_power_on(cpu);
                if (ret)
                        return ret;
 
                /* Wait for the power to come up. */
                timeout = jiffies + msecs_to_jiffies(100);
-               while (tegra_powergate_is_powered(pwrgateid)) {
+               while (tegra_pmc_cpu_is_powered(cpu)) {
                        if (time_after(jiffies, timeout))
                                return -ETIMEDOUT;
                        udelay(10);
@@ -123,57 +135,34 @@ remove_clamps:
        udelay(10);
 
        /* Remove I/O clamps. */
-       ret = tegra_powergate_remove_clamping(pwrgateid);
-       udelay(10);
+       ret = tegra_pmc_cpu_remove_clamping(cpu);
+       if (ret)
+               return ret;
 
-       /* Clear flow controller CSR. */
-       flowctrl_write_cpu_csr(cpu, 0);
+       udelay(10);
 
+       flowctrl_write_cpu_csr(cpu, 0); /* Clear flow controller CSR. */
+       tegra_cpu_out_of_reset(cpu);
        return 0;
 }
 
-static int __cpuinit tegra_boot_secondary(unsigned int cpu, struct task_struct *idle)
+static int tegra114_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-       int status;
-
        cpu = cpu_logical_map(cpu);
+       return tegra_pmc_cpu_power_on(cpu);
+}
 
-       /*
-        * Force the CPU into reset. The CPU must remain in reset when the
-        * flow controller state is cleared (which will cause the flow
-        * controller to stop driving reset if the CPU has been power-gated
-        * via the flow controller). This will have no effect on first boot
-        * of the CPU since it should already be in reset.
-        */
-       tegra_put_cpu_in_reset(cpu);
-
-       /*
-        * Unhalt the CPU. If the flow controller was used to power-gate the
-        * CPU this will cause the flow controller to stop driving reset.
-        * The CPU will remain in reset because the clock and reset block
-        * is now driving reset.
-        */
-       flowctrl_write_cpu_halt(cpu, 0);
-
-       switch (tegra_chip_id) {
-       case TEGRA20:
-               status = tegra20_power_up_cpu(cpu);
-               break;
-       case TEGRA30:
-               status = tegra30_power_up_cpu(cpu);
-               break;
-       default:
-               status = -EINVAL;
-               break;
-       }
-
-       if (status)
-               goto done;
-
-       /* Take the CPU out of reset. */
-       tegra_cpu_out_of_reset(cpu);
-done:
-       return status;
+static int __cpuinit tegra_boot_secondary(unsigned int cpu,
+                                         struct task_struct *idle)
+{
+       if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC) && tegra_chip_id == TEGRA20)
+               return tegra20_boot_secondary(cpu, idle);
+       if (IS_ENABLED(CONFIG_ARCH_TEGRA_3x_SOC) && tegra_chip_id == TEGRA30)
+               return tegra30_boot_secondary(cpu, idle);
+       if (IS_ENABLED(CONFIG_ARCH_TEGRA_114_SOC) && tegra_chip_id == TEGRA114)
+               return tegra114_boot_secondary(cpu, idle);
+
+       return -EINVAL;
 }
 
 static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
index 523604de666f6f6369330fabadbedb2b05750cf9..d0b7400e46065b4ba5ae19a7f1be974118b6e6a9 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/cpumask.h>
 #include <linux/delay.h>
 #include <linux/cpu_pm.h>
-#include <linux/clk.h>
+#include <linux/suspend.h>
 #include <linux/err.h>
 #include <linux/clk/tegra.h>
 
 #include "reset.h"
 #include "flowctrl.h"
 #include "fuse.h"
+#include "pmc.h"
 #include "sleep.h"
 
-#define TEGRA_POWER_CPU_PWRREQ_OE      (1 << 16)  /* CPU pwr req enable */
-
-#define PMC_CTRL               0x0
-#define PMC_CPUPWRGOOD_TIMER   0xc8
-#define PMC_CPUPWROFF_TIMER    0xcc
-
 #ifdef CONFIG_PM_SLEEP
-static unsigned int g_diag_reg;
 static DEFINE_SPINLOCK(tegra_lp2_lock);
-static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
-static struct clk *tegra_pclk;
 void (*tegra_tear_down_cpu)(void);
 
-void save_cpu_arch_register(void)
-{
-       /* read diagnostic register */
-       asm("mrc p15, 0, %0, c15, c0, 1" : "=r"(g_diag_reg) : : "cc");
-       return;
-}
-
-void restore_cpu_arch_register(void)
-{
-       /* write diagnostic register */
-       asm("mcr p15, 0, %0, c15, c0, 1" : : "r"(g_diag_reg) : "cc");
-       return;
-}
-
-static void set_power_timers(unsigned long us_on, unsigned long us_off)
-{
-       unsigned long long ticks;
-       unsigned long long pclk;
-       unsigned long rate;
-       static unsigned long tegra_last_pclk;
-
-       if (tegra_pclk == NULL) {
-               tegra_pclk = clk_get_sys(NULL, "pclk");
-               WARN_ON(IS_ERR(tegra_pclk));
-       }
-
-       rate = clk_get_rate(tegra_pclk);
-
-       if (WARN_ON_ONCE(rate <= 0))
-               pclk = 100000000;
-       else
-               pclk = rate;
-
-       if ((rate != tegra_last_pclk)) {
-               ticks = (us_on * pclk) + 999999ull;
-               do_div(ticks, 1000000);
-               writel((unsigned long)ticks, pmc + PMC_CPUPWRGOOD_TIMER);
-
-               ticks = (us_off * pclk) + 999999ull;
-               do_div(ticks, 1000000);
-               writel((unsigned long)ticks, pmc + PMC_CPUPWROFF_TIMER);
-               wmb();
-       }
-       tegra_last_pclk = pclk;
-}
-
 /*
  * restore_cpu_complex
  *
@@ -119,8 +65,6 @@ static void restore_cpu_complex(void)
        tegra_cpu_clock_resume();
 
        flowctrl_cpu_suspend_exit(cpu);
-
-       restore_cpu_arch_register();
 }
 
 /*
@@ -145,8 +89,6 @@ static void suspend_cpu_complex(void)
        tegra_cpu_clock_suspend();
 
        flowctrl_cpu_suspend_enter(cpu);
-
-       save_cpu_arch_register();
 }
 
 void tegra_clear_cpu_in_lp2(int phy_cpu_id)
@@ -197,16 +139,9 @@ static int tegra_sleep_cpu(unsigned long v2p)
        return 0;
 }
 
-void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time)
+void tegra_idle_lp2_last(void)
 {
-       u32 mode;
-
-       /* Only the last cpu down does the final suspend steps */
-       mode = readl(pmc + PMC_CTRL);
-       mode |= TEGRA_POWER_CPU_PWRREQ_OE;
-       writel(mode, pmc + PMC_CTRL);
-
-       set_power_timers(cpu_on_time, cpu_off_time);
+       tegra_pmc_pm_set(TEGRA_SUSPEND_LP2);
 
        cpu_cluster_pm_enter();
        suspend_cpu_complex();
@@ -216,4 +151,81 @@ void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time)
        restore_cpu_complex();
        cpu_cluster_pm_exit();
 }
+
+enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
+                               enum tegra_suspend_mode mode)
+{
+       /* Tegra114 didn't support any suspending mode yet. */
+       if (tegra_chip_id == TEGRA114)
+               return TEGRA_SUSPEND_NONE;
+
+       /*
+        * The Tegra devices only support suspending to LP2 currently.
+        */
+       if (mode > TEGRA_SUSPEND_LP2)
+               return TEGRA_SUSPEND_LP2;
+
+       return mode;
+}
+
+static const char *lp_state[TEGRA_MAX_SUSPEND_MODE] = {
+       [TEGRA_SUSPEND_NONE] = "none",
+       [TEGRA_SUSPEND_LP2] = "LP2",
+       [TEGRA_SUSPEND_LP1] = "LP1",
+       [TEGRA_SUSPEND_LP0] = "LP0",
+};
+
+static int __cpuinit tegra_suspend_enter(suspend_state_t state)
+{
+       enum tegra_suspend_mode mode = tegra_pmc_get_suspend_mode();
+
+       if (WARN_ON(mode < TEGRA_SUSPEND_NONE ||
+                   mode >= TEGRA_MAX_SUSPEND_MODE))
+               return -EINVAL;
+
+       pr_info("Entering suspend state %s\n", lp_state[mode]);
+
+       tegra_pmc_pm_set(mode);
+
+       local_fiq_disable();
+
+       suspend_cpu_complex();
+       switch (mode) {
+       case TEGRA_SUSPEND_LP2:
+               tegra_set_cpu_in_lp2(0);
+               break;
+       default:
+               break;
+       }
+
+       cpu_suspend(PHYS_OFFSET - PAGE_OFFSET, &tegra_sleep_cpu);
+
+       switch (mode) {
+       case TEGRA_SUSPEND_LP2:
+               tegra_clear_cpu_in_lp2(0);
+               break;
+       default:
+               break;
+       }
+       restore_cpu_complex();
+
+       local_fiq_enable();
+
+       return 0;
+}
+
+static const struct platform_suspend_ops tegra_suspend_ops = {
+       .valid          = suspend_valid_only_mem,
+       .enter          = tegra_suspend_enter,
+};
+
+void __init tegra_init_suspend(void)
+{
+       if (tegra_pmc_get_suspend_mode() == TEGRA_SUSPEND_NONE)
+               return;
+
+       tegra_pmc_suspend_init();
+
+       suspend_set_ops(&tegra_suspend_ops);
+}
 #endif
index 787335cc964cfb38d96f12fa059b3a50331982b0..9d2d038bf12e06bdee8f9ee2e2450e58bacbc063 100644 (file)
@@ -21,6 +21,8 @@
 #ifndef _MACH_TEGRA_PM_H_
 #define _MACH_TEGRA_PM_H_
 
+#include "pmc.h"
+
 extern unsigned long l2x0_saved_regs_addr;
 
 void save_cpu_arch_register(void);
@@ -29,7 +31,20 @@ void restore_cpu_arch_register(void);
 void tegra_clear_cpu_in_lp2(int phy_cpu_id);
 bool tegra_set_cpu_in_lp2(int phy_cpu_id);
 
-void tegra_idle_lp2_last(u32 cpu_on_time, u32 cpu_off_time);
+void tegra_idle_lp2_last(void);
 extern void (*tegra_tear_down_cpu)(void);
 
+#ifdef CONFIG_PM_SLEEP
+enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
+                               enum tegra_suspend_mode mode);
+void tegra_init_suspend(void);
+#else
+enum tegra_suspend_mode tegra_pm_validate_suspend_mode(
+                               enum tegra_suspend_mode mode)
+{
+       return TEGRA_SUSPEND_NONE;
+}
+static inline void tegra_init_suspend(void) {}
+#endif
+
 #endif /* _MACH_TEGRA_PM_H_ */
index d4fdb5fcec20955c95a4f0199efb1ae180f72409..32360e540ce6a8536c41d94577ab21b6d2674693 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 NVIDIA CORPORATION. All rights reserved.
+ * Copyright (C) 2012,2013 NVIDIA CORPORATION. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
  */
 
 #include <linux/kernel.h>
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/of.h>
+#include <linux/of_address.h>
 
-#include "iomap.h"
+#include "fuse.h"
+#include "pm.h"
+#include "pmc.h"
+#include "sleep.h"
 
-#define PMC_CTRL               0x0
-#define PMC_CTRL_INTR_LOW      (1 << 17)
+#define TEGRA_POWER_EFFECT_LP0         (1 << 14)  /* LP0 when CPU pwr gated */
+#define TEGRA_POWER_CPU_PWRREQ_POLARITY        (1 << 15)  /* CPU pwr req polarity */
+#define TEGRA_POWER_CPU_PWRREQ_OE      (1 << 16)  /* CPU pwr req enable */
+
+#define PMC_CTRL                       0x0
+#define PMC_CTRL_INTR_LOW              (1 << 17)
+#define PMC_PWRGATE_TOGGLE             0x30
+#define PMC_PWRGATE_TOGGLE_START       (1 << 8)
+#define PMC_REMOVE_CLAMPING            0x34
+#define PMC_PWRGATE_STATUS             0x38
+
+#define PMC_CPUPWRGOOD_TIMER   0xc8
+#define PMC_CPUPWROFF_TIMER    0xcc
+
+#define TEGRA_POWERGATE_PCIE   3
+#define TEGRA_POWERGATE_VDEC   4
+#define TEGRA_POWERGATE_CPU1   9
+#define TEGRA_POWERGATE_CPU2   10
+#define TEGRA_POWERGATE_CPU3   11
+
+static u8 tegra_cpu_domains[] = {
+       0xFF,                   /* not available for CPU0 */
+       TEGRA_POWERGATE_CPU1,
+       TEGRA_POWERGATE_CPU2,
+       TEGRA_POWERGATE_CPU3,
+};
+static DEFINE_SPINLOCK(tegra_powergate_lock);
+
+static void __iomem *tegra_pmc_base;
+static bool tegra_pmc_invert_interrupt;
+static struct clk *tegra_pclk;
+
+struct pmc_pm_data {
+       u32 cpu_good_time;      /* CPU power good time in uS */
+       u32 cpu_off_time;       /* CPU power off time in uS */
+       u32 core_osc_time;      /* Core power good osc time in uS */
+       u32 core_pmu_time;      /* Core power good pmu time in uS */
+       u32 core_off_time;      /* Core power off time in uS */
+       bool corereq_high;      /* Core power request active-high */
+       bool sysclkreq_high;    /* System clock request active-high */
+       bool combined_req;      /* Combined pwr req for CPU & Core */
+       bool cpu_pwr_good_en;   /* CPU power good signal is enabled */
+       u32 lp0_vec_phy_addr;   /* The phy addr of LP0 warm boot code */
+       u32 lp0_vec_size;       /* The size of LP0 warm boot code */
+       enum tegra_suspend_mode suspend_mode;
+};
+static struct pmc_pm_data pmc_pm_data;
 
 static inline u32 tegra_pmc_readl(u32 reg)
 {
-       return readl(IO_ADDRESS(TEGRA_PMC_BASE + reg));
+       return readl(tegra_pmc_base + reg);
 }
 
 static inline void tegra_pmc_writel(u32 val, u32 reg)
 {
-       writel(val, IO_ADDRESS(TEGRA_PMC_BASE + reg));
+       writel(val, tegra_pmc_base + reg);
+}
+
+static int tegra_pmc_get_cpu_powerdomain_id(int cpuid)
+{
+       if (cpuid <= 0 || cpuid >= num_possible_cpus())
+               return -EINVAL;
+       return tegra_cpu_domains[cpuid];
+}
+
+static bool tegra_pmc_powergate_is_powered(int id)
+{
+       return (tegra_pmc_readl(PMC_PWRGATE_STATUS) >> id) & 1;
+}
+
+static int tegra_pmc_powergate_set(int id, bool new_state)
+{
+       bool old_state;
+       unsigned long flags;
+
+       spin_lock_irqsave(&tegra_powergate_lock, flags);
+
+       old_state = tegra_pmc_powergate_is_powered(id);
+       WARN_ON(old_state == new_state);
+
+       tegra_pmc_writel(PMC_PWRGATE_TOGGLE_START | id, PMC_PWRGATE_TOGGLE);
+
+       spin_unlock_irqrestore(&tegra_powergate_lock, flags);
+
+       return 0;
+}
+
+static int tegra_pmc_powergate_remove_clamping(int id)
+{
+       u32 mask;
+
+       /*
+        * Tegra has a bug where PCIE and VDE clamping masks are
+        * swapped relatively to the partition ids.
+        */
+       if (id ==  TEGRA_POWERGATE_VDEC)
+               mask = (1 << TEGRA_POWERGATE_PCIE);
+       else if (id == TEGRA_POWERGATE_PCIE)
+               mask = (1 << TEGRA_POWERGATE_VDEC);
+       else
+               mask = (1 << id);
+
+       tegra_pmc_writel(mask, PMC_REMOVE_CLAMPING);
+
+       return 0;
+}
+
+bool tegra_pmc_cpu_is_powered(int cpuid)
+{
+       int id;
+
+       id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
+       if (id < 0)
+               return false;
+       return tegra_pmc_powergate_is_powered(id);
 }
 
-#ifdef CONFIG_OF
+int tegra_pmc_cpu_power_on(int cpuid)
+{
+       int id;
+
+       id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
+       if (id < 0)
+               return id;
+       return tegra_pmc_powergate_set(id, true);
+}
+
+int tegra_pmc_cpu_remove_clamping(int cpuid)
+{
+       int id;
+
+       id = tegra_pmc_get_cpu_powerdomain_id(cpuid);
+       if (id < 0)
+               return id;
+       return tegra_pmc_powergate_remove_clamping(id);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static void set_power_timers(u32 us_on, u32 us_off, unsigned long rate)
+{
+       unsigned long long ticks;
+       unsigned long long pclk;
+       static unsigned long tegra_last_pclk;
+
+       if (WARN_ON_ONCE(rate <= 0))
+               pclk = 100000000;
+       else
+               pclk = rate;
+
+       if ((rate != tegra_last_pclk)) {
+               ticks = (us_on * pclk) + 999999ull;
+               do_div(ticks, 1000000);
+               tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWRGOOD_TIMER);
+
+               ticks = (us_off * pclk) + 999999ull;
+               do_div(ticks, 1000000);
+               tegra_pmc_writel((unsigned long)ticks, PMC_CPUPWROFF_TIMER);
+               wmb();
+       }
+       tegra_last_pclk = pclk;
+}
+
+enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
+{
+       return pmc_pm_data.suspend_mode;
+}
+
+void tegra_pmc_pm_set(enum tegra_suspend_mode mode)
+{
+       u32 reg;
+       unsigned long rate = 0;
+
+       reg = tegra_pmc_readl(PMC_CTRL);
+       reg |= TEGRA_POWER_CPU_PWRREQ_OE;
+       reg &= ~TEGRA_POWER_EFFECT_LP0;
+
+       switch (mode) {
+       case TEGRA_SUSPEND_LP2:
+               rate = clk_get_rate(tegra_pclk);
+               break;
+       default:
+               break;
+       }
+
+       set_power_timers(pmc_pm_data.cpu_good_time, pmc_pm_data.cpu_off_time,
+                        rate);
+
+       tegra_pmc_writel(reg, PMC_CTRL);
+}
+
+void tegra_pmc_suspend_init(void)
+{
+       u32 reg;
+
+       /* Always enable CPU power request */
+       reg = tegra_pmc_readl(PMC_CTRL);
+       reg |= TEGRA_POWER_CPU_PWRREQ_OE;
+       tegra_pmc_writel(reg, PMC_CTRL);
+}
+#endif
+
 static const struct of_device_id matches[] __initconst = {
+       { .compatible = "nvidia,tegra114-pmc" },
+       { .compatible = "nvidia,tegra30-pmc" },
        { .compatible = "nvidia,tegra20-pmc" },
        { }
 };
-#endif
 
-void __init tegra_pmc_init(void)
+static void tegra_pmc_parse_dt(void)
 {
-       /*
-        * For now, Harmony is the only board that uses the PMC, and it wants
-        * the signal inverted. Seaboard would too if it used the PMC.
-        * Hopefully by the time other boards want to use the PMC, everything
-        * will be device-tree, or they also want it inverted.
-        */
-       bool invert_interrupt = true;
-       u32 val;
+       struct device_node *np;
+       u32 prop;
+       enum tegra_suspend_mode suspend_mode;
+       u32 core_good_time[2] = {0, 0};
+       u32 lp0_vec[2] = {0, 0};
 
-#ifdef CONFIG_OF
-       if (of_have_populated_dt()) {
-               struct device_node *np;
+       np = of_find_matching_node(NULL, matches);
+       BUG_ON(!np);
 
-               invert_interrupt = false;
+       tegra_pmc_base = of_iomap(np, 0);
 
-               np = of_find_matching_node(NULL, matches);
-               if (np) {
-                       if (of_find_property(np, "nvidia,invert-interrupt",
-                                               NULL))
-                               invert_interrupt = true;
+       tegra_pmc_invert_interrupt = of_property_read_bool(np,
+                                    "nvidia,invert-interrupt");
+       tegra_pclk = of_clk_get_by_name(np, "pclk");
+       WARN_ON(IS_ERR(tegra_pclk));
+
+       /* Grabbing the power management configurations */
+       if (of_property_read_u32(np, "nvidia,suspend-mode", &prop)) {
+               suspend_mode = TEGRA_SUSPEND_NONE;
+       } else {
+               switch (prop) {
+               case 0:
+                       suspend_mode = TEGRA_SUSPEND_LP0;
+                       break;
+               case 1:
+                       suspend_mode = TEGRA_SUSPEND_LP1;
+                       break;
+               case 2:
+                       suspend_mode = TEGRA_SUSPEND_LP2;
+                       break;
+               default:
+                       suspend_mode = TEGRA_SUSPEND_NONE;
+                       break;
                }
        }
-#endif
+       suspend_mode = tegra_pm_validate_suspend_mode(suspend_mode);
+
+       if (of_property_read_u32(np, "nvidia,cpu-pwr-good-time", &prop))
+               suspend_mode = TEGRA_SUSPEND_NONE;
+       pmc_pm_data.cpu_good_time = prop;
+
+       if (of_property_read_u32(np, "nvidia,cpu-pwr-off-time", &prop))
+               suspend_mode = TEGRA_SUSPEND_NONE;
+       pmc_pm_data.cpu_off_time = prop;
+
+       if (of_property_read_u32_array(np, "nvidia,core-pwr-good-time",
+                       core_good_time, ARRAY_SIZE(core_good_time)))
+               suspend_mode = TEGRA_SUSPEND_NONE;
+       pmc_pm_data.core_osc_time = core_good_time[0];
+       pmc_pm_data.core_pmu_time = core_good_time[1];
+
+       if (of_property_read_u32(np, "nvidia,core-pwr-off-time",
+                                &prop))
+               suspend_mode = TEGRA_SUSPEND_NONE;
+       pmc_pm_data.core_off_time = prop;
+
+       pmc_pm_data.corereq_high = of_property_read_bool(np,
+                               "nvidia,core-power-req-active-high");
+
+       pmc_pm_data.sysclkreq_high = of_property_read_bool(np,
+                               "nvidia,sys-clock-req-active-high");
+
+       pmc_pm_data.combined_req = of_property_read_bool(np,
+                               "nvidia,combined-power-req");
+
+       pmc_pm_data.cpu_pwr_good_en = of_property_read_bool(np,
+                               "nvidia,cpu-pwr-good-en");
+
+       if (of_property_read_u32_array(np, "nvidia,lp0-vec", lp0_vec,
+                                      ARRAY_SIZE(lp0_vec)))
+               if (suspend_mode == TEGRA_SUSPEND_LP0)
+                       suspend_mode = TEGRA_SUSPEND_LP1;
+
+       pmc_pm_data.lp0_vec_phy_addr = lp0_vec[0];
+       pmc_pm_data.lp0_vec_size = lp0_vec[1];
+
+       pmc_pm_data.suspend_mode = suspend_mode;
+}
+
+void __init tegra_pmc_init(void)
+{
+       u32 val;
+
+       tegra_pmc_parse_dt();
 
        val = tegra_pmc_readl(PMC_CTRL);
-       if (invert_interrupt)
+       if (tegra_pmc_invert_interrupt)
                val |= PMC_CTRL_INTR_LOW;
        else
                val &= ~PMC_CTRL_INTR_LOW;
index 8995ee4a87681dd80a63c990b05c324955261f24..e1c2df272f7dc6e723ea4765731fa05cb9baf0e7 100644 (file)
 #ifndef __MACH_TEGRA_PMC_H
 #define __MACH_TEGRA_PMC_H
 
+enum tegra_suspend_mode {
+       TEGRA_SUSPEND_NONE = 0,
+       TEGRA_SUSPEND_LP2,      /* CPU voltage off */
+       TEGRA_SUSPEND_LP1,      /* CPU voltage off, DRAM self-refresh */
+       TEGRA_SUSPEND_LP0,      /* CPU + core voltage off, DRAM self-refresh */
+       TEGRA_MAX_SUSPEND_MODE,
+};
+
+#ifdef CONFIG_PM_SLEEP
+enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
+void tegra_pmc_pm_set(enum tegra_suspend_mode mode);
+void tegra_pmc_suspend_init(void);
+#endif
+
+bool tegra_pmc_cpu_is_powered(int cpuid);
+int tegra_pmc_cpu_power_on(int cpuid);
+int tegra_pmc_cpu_remove_clamping(int cpuid);
+
 void tegra_pmc_init(void);
 
 #endif
index 54382ceade4a516b0389626a511a7358af95a4d9..1676aba5e7b84ecf97c577b2ccc8d5ff565308dd 100644 (file)
@@ -41,9 +41,6 @@
  */
 ENTRY(tegra_resume)
        bl      v7_invalidate_l1
-       /* Enable coresight */
-       mov32   r0, 0xC5ACCE55
-       mcr     p14, 0, r0, c7, c12, 6
 
        cpu_id  r0
        cmp     r0, #0                          @ CPU0?
@@ -99,6 +96,8 @@ ENTRY(__tegra_cpu_reset_handler_start)
  *
  * Register usage within the reset handler:
  *
+ *      Others: scratch
+ *      R6  = SoC ID << 8
  *      R7  = CPU present (to the OS) mask
  *      R8  = CPU in LP1 state mask
  *      R9  = CPU in LP2 state mask
@@ -114,6 +113,40 @@ ENTRY(__tegra_cpu_reset_handler_start)
 ENTRY(__tegra_cpu_reset_handler)
 
        cpsid   aif, 0x13                       @ SVC mode, interrupts disabled
+
+       mov32   r6, TEGRA_APB_MISC_BASE
+       ldr     r6, [r6, #APB_MISC_GP_HIDREV]
+       and     r6, r6, #0xff00
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+t20_check:
+       cmp     r6, #(0x20 << 8)
+       bne     after_t20_check
+t20_errata:
+       # Tegra20 is a Cortex-A9 r1p1
+       mrc     p15, 0, r0, c1, c0, 0   @ read system control register
+       orr     r0, r0, #1 << 14        @ erratum 716044
+       mcr     p15, 0, r0, c1, c0, 0   @ write system control register
+       mrc     p15, 0, r0, c15, c0, 1  @ read diagnostic register
+       orr     r0, r0, #1 << 4         @ erratum 742230
+       orr     r0, r0, #1 << 11        @ erratum 751472
+       mcr     p15, 0, r0, c15, c0, 1  @ write diagnostic register
+       b       after_errata
+after_t20_check:
+#endif
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+t30_check:
+       cmp     r6, #(0x30 << 8)
+       bne     after_t30_check
+t30_errata:
+       # Tegra30 is a Cortex-A9 r2p9
+       mrc     p15, 0, r0, c15, c0, 1  @ read diagnostic register
+       orr     r0, r0, #1 << 6         @ erratum 743622
+       orr     r0, r0, #1 << 11        @ erratum 751472
+       mcr     p15, 0, r0, c15, c0, 1  @ write diagnostic register
+       b       after_errata
+after_t30_check:
+#endif
+after_errata:
        mrc     p15, 0, r10, c0, c0, 5          @ MPIDR
        and     r10, r10, #0x3                  @ R10 = CPU number
        mov     r11, #1
@@ -129,16 +162,13 @@ ENTRY(__tegra_cpu_reset_handler)
 
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
        /* Are we on Tegra20? */
-       mov32   r6, TEGRA_APB_MISC_BASE
-       ldr     r0, [r6, #APB_MISC_GP_HIDREV]
-       and     r0, r0, #0xff00
-       cmp     r0, #(0x20 << 8)
+       cmp     r6, #(0x20 << 8)
        bne     1f
        /* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
-       mov32   r6, TEGRA_PMC_BASE
+       mov32   r5, TEGRA_PMC_BASE
        mov     r0, #0
        cmp     r10, #0
-       strne   r0, [r6, #PMC_SCRATCH41]
+       strne   r0, [r5, #PMC_SCRATCH41]
 1:
 #endif
 
index 4ffae541726e1d258502007482e37585e33ad4ee..970ebd5138b99bf0a6d9cf682cee836b1f5cd5e7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
+ * Copyright (c) 2010-2013, NVIDIA Corporation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -124,11 +124,11 @@ int tegra_sleep_cpu_finish(unsigned long);
 void tegra_disable_clean_inv_dcache(void);
 
 #ifdef CONFIG_HOTPLUG_CPU
-void tegra20_hotplug_init(void);
-void tegra30_hotplug_init(void);
+void tegra20_hotplug_shutdown(void);
+void tegra30_hotplug_shutdown(void);
+void tegra_hotplug_init(void);
 #else
-static inline void tegra20_hotplug_init(void) {}
-static inline void tegra30_hotplug_init(void) {}
+static inline void tegra_hotplug_init(void) {}
 #endif
 
 void tegra20_cpu_shutdown(int cpu);
similarity index 74%
rename from arch/arm/mach-tegra/board-dt-tegra20.c
rename to arch/arm/mach-tegra/tegra.c
index a0edf2510280b60e559c50dce3731927a11de635..61749e2d811112d67642db8d9eeecb151e0b127b 100644 (file)
@@ -1,6 +1,7 @@
 /*
- * nVidia Tegra device tree board support
+ * NVIDIA Tegra SoC device tree board support
  *
+ * Copyright (C) 2011, 2013, NVIDIA Corporation
  * Copyright (C) 2010 Secret Lab Technologies, Ltd.
  * Copyright (C) 2010 Google, Inc.
  *
 #include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/i2c-tegra.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
 #include <linux/usb/tegra_usb_phy.h>
+#include <linux/clk/tegra.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -41,6 +45,7 @@
 
 #include "board.h"
 #include "common.h"
+#include "fuse.h"
 #include "iomap.h"
 
 static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
@@ -79,12 +84,38 @@ static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
 
 static void __init tegra_dt_init(void)
 {
+       struct soc_device_attribute *soc_dev_attr;
+       struct soc_device *soc_dev;
+       struct device *parent = NULL;
+
+       tegra_clocks_apply_init_table();
+
+       soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+       if (!soc_dev_attr)
+               goto out;
+
+       soc_dev_attr->family = kasprintf(GFP_KERNEL, "Tegra");
+       soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%d", tegra_revision);
+       soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "%d", tegra_chip_id);
+
+       soc_dev = soc_device_register(soc_dev_attr);
+       if (IS_ERR(soc_dev)) {
+               kfree(soc_dev_attr->family);
+               kfree(soc_dev_attr->revision);
+               kfree(soc_dev_attr->soc_id);
+               kfree(soc_dev_attr);
+               goto out;
+       }
+
+       parent = soc_device_to_device(soc_dev);
+
        /*
         * Finished with the static registrations now; fill in the missing
         * devices
         */
+out:
        of_platform_populate(NULL, of_default_bus_match_table,
-                               tegra20_auxdata_lookup, NULL);
+                               tegra20_auxdata_lookup, parent);
 }
 
 static void __init trimslice_init(void)
@@ -111,7 +142,8 @@ static void __init harmony_init(void)
 
 static void __init paz00_init(void)
 {
-       tegra_paz00_wifikill_init();
+       if (IS_ENABLED(CONFIG_ARCH_TEGRA_2x_SOC))
+               tegra_paz00_wifikill_init();
 }
 
 static struct {
@@ -137,19 +169,21 @@ static void __init tegra_dt_init_late(void)
        }
 }
 
-static const char *tegra20_dt_board_compat[] = {
+static const char * const tegra_dt_board_compat[] = {
+       "nvidia,tegra114",
+       "nvidia,tegra30",
        "nvidia,tegra20",
        NULL
 };
 
-DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)")
+DT_MACHINE_START(TEGRA_DT, "NVIDIA Tegra SoC (Flattened Device Tree)")
        .map_io         = tegra_map_common_io,
        .smp            = smp_ops(tegra_smp_ops),
-       .init_early     = tegra20_init_early,
+       .init_early     = tegra_init_early,
        .init_irq       = tegra_dt_init_irq,
        .init_time      = clocksource_of_init,
        .init_machine   = tegra_dt_init,
        .init_late      = tegra_dt_init_late,
        .restart        = tegra_assert_system_reset,
-       .dt_compat      = tegra20_dt_board_compat,
+       .dt_compat      = tegra_dt_board_compat,
 MACHINE_END
diff --git a/arch/arm/mach-tegra/tegra114_speedo.c b/arch/arm/mach-tegra/tegra114_speedo.c
new file mode 100644 (file)
index 0000000..5218d48
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * 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/bug.h>
+
+#include "fuse.h"
+
+#define CORE_PROCESS_CORNERS_NUM       2
+#define CPU_PROCESS_CORNERS_NUM                2
+
+enum {
+       THRESHOLD_INDEX_0,
+       THRESHOLD_INDEX_1,
+       THRESHOLD_INDEX_COUNT,
+};
+
+static const u32 core_process_speedos[][CORE_PROCESS_CORNERS_NUM] = {
+       {1123,     UINT_MAX},
+       {0,        UINT_MAX},
+};
+
+static const u32 cpu_process_speedos[][CPU_PROCESS_CORNERS_NUM] = {
+       {1695,     UINT_MAX},
+       {0,        UINT_MAX},
+};
+
+static void rev_sku_to_speedo_ids(int rev, int sku, int *threshold)
+{
+       u32 tmp;
+
+       switch (sku) {
+       case 0x00:
+       case 0x10:
+       case 0x05:
+       case 0x06:
+               tegra_cpu_speedo_id = 1;
+               tegra_soc_speedo_id = 0;
+               *threshold = THRESHOLD_INDEX_0;
+               break;
+
+       case 0x03:
+       case 0x04:
+               tegra_cpu_speedo_id = 2;
+               tegra_soc_speedo_id = 1;
+               *threshold = THRESHOLD_INDEX_1;
+               break;
+
+       default:
+               pr_err("Tegra114 Unknown SKU %d\n", sku);
+               tegra_cpu_speedo_id = 0;
+               tegra_soc_speedo_id = 0;
+               *threshold = THRESHOLD_INDEX_0;
+               break;
+       }
+
+       if (rev == TEGRA_REVISION_A01) {
+               tmp = tegra_fuse_readl(0x270) << 1;
+               tmp |= tegra_fuse_readl(0x26c);
+               if (!tmp)
+                       tegra_cpu_speedo_id = 0;
+       }
+}
+
+void tegra114_init_speedo_data(void)
+{
+       u32 cpu_speedo_val;
+       u32 core_speedo_val;
+       int threshold;
+       int i;
+
+       BUILD_BUG_ON(ARRAY_SIZE(cpu_process_speedos) !=
+                       THRESHOLD_INDEX_COUNT);
+       BUILD_BUG_ON(ARRAY_SIZE(core_process_speedos) !=
+                       THRESHOLD_INDEX_COUNT);
+
+       rev_sku_to_speedo_ids(tegra_revision, tegra_sku_id, &threshold);
+
+       cpu_speedo_val = tegra_fuse_readl(0x12c) + 1024;
+       core_speedo_val = tegra_fuse_readl(0x134);
+
+       for (i = 0; i < CPU_PROCESS_CORNERS_NUM; i++)
+               if (cpu_speedo_val < cpu_process_speedos[threshold][i])
+                       break;
+       tegra_cpu_process_id = i;
+
+       for (i = 0; i < CORE_PROCESS_CORNERS_NUM; i++)
+               if (core_speedo_val < core_process_speedos[threshold][i])
+                       break;
+       tegra_core_process_id = i;
+}
index ce7ce42a1ac97b5ec8724181c0a03436e9377c45..9e8bdfa2b36915e4db7a8352753626e7f41b682e 100644 (file)
@@ -276,7 +276,7 @@ static struct tegra_emc_pdata *tegra_emc_fill_pdata(struct platform_device *pdev
        int i;
 
        WARN_ON(pdev->dev.platform_data);
-       BUG_ON(IS_ERR_OR_NULL(c));
+       BUG_ON(IS_ERR(c));
 
        pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
        pdata->tables = devm_kzalloc(&pdev->dev, sizeof(*pdata->tables),
index 0a3f30df1eb8cb9c45d375b465fe2a94ef8df6aa..152ae38cd18c24dbce5c3442f3b9f14d72ed11ec 100644 (file)
@@ -48,8 +48,12 @@ BIAS(slpm_in_nopull_wkup, PIN_SLEEPMODE_ENABLED|
        PIN_SLPM_DIR_INPUT|PIN_SLPM_PULL_NONE|PIN_SLPM_WAKEUP_ENABLE);
 BIAS(slpm_in_wkup_pdis, PIN_SLEEPMODE_ENABLED|
        PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_in_wkup_pdis_en, PIN_SLEEPMODE_ENABLED|
+       PIN_SLPM_DIR_INPUT|PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_ENABLED);
 BIAS(slpm_wkup_pdis, PIN_SLEEPMODE_ENABLED|
        PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_DISABLED);
+BIAS(slpm_wkup_pdis_en, PIN_SLEEPMODE_ENABLED|
+       PIN_SLPM_WAKEUP_ENABLE|PIN_SLPM_PDIS_ENABLED);
 BIAS(slpm_out_lo_pdis, PIN_SLEEPMODE_ENABLED|
        PIN_SLPM_OUTPUT_LOW|PIN_SLPM_WAKEUP_DISABLE|PIN_SLPM_PDIS_DISABLED);
 BIAS(slpm_out_lo_wkup, PIN_SLEEPMODE_ENABLED|
@@ -78,9 +82,6 @@ BIAS(out_wkup_pdis, PIN_SLPM_DIR_OUTPUT|PIN_SLPM_WAKEUP_ENABLE|
        PIN_MAP_MUX_GROUP_HOG_DEFAULT("pinctrl-db8500", group, func)
 #define DB8500_PIN_HOG(pin,conf) \
        PIN_MAP_CONFIGS_PIN_HOG_DEFAULT("pinctrl-db8500", pin, conf)
-#define DB8500_PIN_SLEEP(pin, conf, dev) \
-       PIN_MAP_CONFIGS_PIN(dev, PINCTRL_STATE_SLEEP, "pinctrl-db8500", \
-                           pin, conf)
 
 /* These are default states associated with device and changed runtime */
 #define DB8500_MUX(group,func,dev) \
@@ -309,8 +310,23 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
        DB8500_PIN_SLEEP("GPIO207_AJ23", slpm_in_wkup_pdis, "sdi4"), /* DAT4 */
 
        /* Mux in USB pins, drive STP high */
-       DB8500_MUX("usb_a_1", "usb", "musb-ux500.0"),
-       DB8500_PIN("GPIO257_AE29", out_hi, "musb-ux500.0"), /* STP */
+       /* USB default state */
+       DB8500_MUX("usb_a_1", "usb", "ab8500-usb.0"),
+       DB8500_PIN("GPIO257_AE29", out_hi, "ab8500-usb.0"), /* STP */
+       /* USB sleep state */
+       DB8500_PIN_SLEEP("GPIO256_AF28", slpm_wkup_pdis_en, "ab8500-usb.0"), /* NXT */
+       DB8500_PIN_SLEEP("GPIO257_AE29", slpm_out_hi_wkup_pdis, "ab8500-usb.0"), /* STP */
+       DB8500_PIN_SLEEP("GPIO258_AD29", slpm_wkup_pdis_en, "ab8500-usb.0"), /* XCLK */
+       DB8500_PIN_SLEEP("GPIO259_AC29", slpm_wkup_pdis_en, "ab8500-usb.0"), /* DIR */
+       DB8500_PIN_SLEEP("GPIO260_AD28", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT7 */
+       DB8500_PIN_SLEEP("GPIO261_AD26", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT6 */
+       DB8500_PIN_SLEEP("GPIO262_AE26", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT5 */
+       DB8500_PIN_SLEEP("GPIO263_AG29", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT4 */
+       DB8500_PIN_SLEEP("GPIO264_AE27", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT3 */
+       DB8500_PIN_SLEEP("GPIO265_AD27", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT2 */
+       DB8500_PIN_SLEEP("GPIO266_AC28", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT1 */
+       DB8500_PIN_SLEEP("GPIO267_AC27", slpm_in_wkup_pdis_en, "ab8500-usb.0"), /* DAT0 */
+
        /* Mux in SPI2 pins on the "other C1" altfunction */
        DB8500_MUX("spi2_oc1_2", "spi2", "spi2"),
        DB8500_PIN("GPIO216_AG12", gpio_out_hi, "spi2"), /* FRM */
@@ -318,9 +334,9 @@ static struct pinctrl_map __initdata mop500_family_pinmap[] = {
        DB8500_PIN("GPIO215_AH13", out_lo, "spi2"), /* TXD */
        DB8500_PIN("GPIO217_AH12", out_lo, "spi2"), /* CLK */
        /* SPI2 idle state */
-       DB8500_PIN_SLEEP("GPIO218_AH11", slpm_in_wkup_pdis, "spi2"), /* RXD */
-       DB8500_PIN_SLEEP("GPIO215_AH13", slpm_out_lo_wkup_pdis, "spi2"), /* TXD */
-       DB8500_PIN_SLEEP("GPIO217_AH12", slpm_wkup_pdis, "spi2"), /* CLK */
+       DB8500_PIN_IDLE("GPIO218_AH11", slpm_in_wkup_pdis, "spi2"), /* RXD */
+       DB8500_PIN_IDLE("GPIO215_AH13", slpm_out_lo_wkup_pdis, "spi2"), /* TXD */
+       DB8500_PIN_IDLE("GPIO217_AH12", slpm_wkup_pdis, "spi2"), /* CLK */
        /* SPI2 sleep state */
        DB8500_PIN_SLEEP("GPIO216_AG12", slpm_in_wkup_pdis, "spi2"), /* FRM */
        DB8500_PIN_SLEEP("GPIO218_AH11", slpm_in_wkup_pdis, "spi2"), /* RXD */
@@ -747,6 +763,8 @@ static struct pinctrl_map __initdata snowball_pinmap[] = {
        DB8500_PIN_HOG("GPIO21_AB3", out_hi),
        /* Mux in "SM" which is used for the SMSC911x Ethernet adapter */
        DB8500_MUX_HOG("sm_b_1", "sm"),
+       /* User LED */
+       DB8500_PIN_HOG("GPIO142_C11", gpio_out_hi),
        /* Drive RSTn_LAN high */
        DB8500_PIN_HOG("GPIO141_C12", gpio_out_hi),
        /*  Accelerometer/Magnetometer */
index 051b62c2710208537a3442a0ec03af57c11cc530..7f2cb6c5e2c10de3b6479e8a23ced9c523329b55 100644 (file)
@@ -81,7 +81,6 @@ static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
 #endif
 
 struct mmci_platform_data mop500_sdi0_data = {
-       .ios_handler    = mop500_sdi0_ios_handler,
        .ocr_mask       = MMC_VDD_29_30,
        .f_max          = 50000000,
        .capabilities   = MMC_CAP_4_BIT_DATA |
index b03457881c4b5aed70daee7ded2c182cc238d3b7..87d2d7b38ce90742a0a1b9d3ccda2e0271c1f5fb 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
+#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/platform_data/i2c-nomadik.h>
@@ -439,6 +440,15 @@ static void mop500_prox_deactivate(struct device *dev)
        regulator_put(prox_regulator);
 }
 
+void mop500_snowball_ethernet_clock_enable(void)
+{
+       struct clk *clk;
+
+       clk = clk_get_sys("fsmc", NULL);
+       if (!IS_ERR(clk))
+               clk_prepare_enable(clk);
+}
+
 static struct cryp_platform_data u8500_cryp1_platform_data = {
                .mem_to_engine = {
                                .dir = STEDMA40_MEM_TO_PERIPH,
@@ -683,6 +693,8 @@ static void __init snowball_init_machine(void)
        mop500_audio_init(parent);
        mop500_uart_init(parent);
 
+       mop500_snowball_ethernet_clock_enable();
+
        /* This board has full regulator constraints */
        regulator_has_full_constraints();
 }
index eaa605f5d90dc463ac62079e01d5db92e50473ca..d38951be70df01304745bcc1a62584b5c89522f3 100644 (file)
@@ -104,6 +104,7 @@ void __init mop500_pinmaps_init(void);
 void __init snowball_pinmaps_init(void);
 void __init hrefv60_pinmaps_init(void);
 void mop500_audio_init(struct device *parent);
+void mop500_snowball_ethernet_clock_enable(void);
 
 int __init mop500_uib_init(void);
 void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
index 19235cf7bbe3f33c4fe4d63eee73d779624dbb69..f1a581844372881e7e0d54aac4b3465495a5941d 100644 (file)
@@ -312,9 +312,10 @@ static void __init u8500_init_machine(void)
        /* Pinmaps must be in place before devices register */
        if (of_machine_is_compatible("st-ericsson,mop500"))
                mop500_pinmaps_init();
-       else if (of_machine_is_compatible("calaosystems,snowball-a9500"))
+       else if (of_machine_is_compatible("calaosystems,snowball-a9500")) {
                snowball_pinmaps_init();
-       else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
+               mop500_snowball_ethernet_clock_enable();
+       } else if (of_machine_is_compatible("st-ericsson,hrefv60+"))
                hrefv60_pinmaps_init();
        else if (of_machine_is_compatible("st-ericsson,ccu9540")) {}
                /* TODO: Add pinmaps for ccu9540 board. */
index 537870d3fea87a5df90eb733969ce81dcac8a538..002da9a369d5fe170bd2ca10658a5fa2b9a8725d 100644 (file)
@@ -140,14 +140,13 @@ struct device * __init ux500_soc_device_init(const char *soc_id)
        soc_info_populate(soc_dev_attr, soc_id);
 
        soc_dev = soc_device_register(soc_dev_attr);
-       if (IS_ERR_OR_NULL(soc_dev)) {
+       if (IS_ERR(soc_dev)) {
                kfree(soc_dev_attr);
                return NULL;
        }
 
        parent = soc_device_to_device(soc_dev);
-       if (!IS_ERR_OR_NULL(parent))
-               device_create_file(parent, &ux500_soc_attr);
+       device_create_file(parent, &ux500_soc_attr);
 
        return parent;
 }
index e3e94b2fa145b011c250076e506cb325370456a6..9b252934b2065f60f21888f5bc76ffd7c609326e 100644 (file)
@@ -7,6 +7,7 @@ config ARCH_VT8500
        select GENERIC_CLOCKEVENTS
        select HAVE_CLK
        select VT8500_TIMER
+       select PINCTRL
        help
          Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
 
index 92ceb2436b60151c4c729ab0d6554c21bdf494f9..4c8a846375944a940fc67b91f02fa2dccc814c53 100644 (file)
@@ -1 +1 @@
-obj-$(CONFIG_ARCH_VT8500) += irq.o vt8500.o
+obj-$(CONFIG_ARCH_VT8500) += vt8500.o
index 77611a6968d6c7d519214ef998e6df316f9c574e..087787af62f151d3171759c9d66727a2f1d01d34 100644 (file)
 
 #include <linux/of.h>
 
-int __init vt8500_irq_init(struct device_node *node,
-                               struct device_node *parent);
-
 /* defined in drivers/clk/clk-vt8500.c */
 void __init vtwm_clk_init(void __iomem *pmc_base);
 
-/* defined in irq.c */
-asmlinkage void vt8500_handle_irq(struct pt_regs *regs);
-
 #endif
index 49e80053d828c51e6d3ffd4d819b08d62af3cf17..1dd281efc02035dac37cc971a0db4c69c98c8a11 100644 (file)
@@ -20,6 +20,7 @@
 
 #include <linux/clocksource.h>
 #include <linux/io.h>
+#include <linux/irqchip.h>
 #include <linux/pm.h>
 
 #include <asm/mach-types.h>
@@ -166,16 +167,6 @@ void __init vt8500_init(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static const struct of_device_id vt8500_irq_match[] __initconst = {
-       { .compatible = "via,vt8500-intc", .data = vt8500_irq_init, },
-       { /* sentinel */ },
-};
-
-static void __init vt8500_init_irq(void)
-{
-       of_irq_init(vt8500_irq_match);
-};
-
 static const char * const vt8500_dt_compat[] = {
        "via,vt8500",
        "wm,wm8650",
@@ -187,10 +178,9 @@ static const char * const vt8500_dt_compat[] = {
 DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)")
        .dt_compat      = vt8500_dt_compat,
        .map_io         = vt8500_map_io,
-       .init_irq       = vt8500_init_irq,
+       .init_irq       = irqchip_init,
        .init_machine   = vt8500_init,
        .init_time      = clocksource_of_init,
        .restart        = vt8500_restart,
-       .handle_irq     = vt8500_handle_irq,
 MACHINE_END
 
index adb6c0ea0e533b36b7f23f996c5ee4329d6aacbc..d70651e8b7057f0585d195c926c2aac2636cf6c2 100644 (file)
@@ -9,5 +9,6 @@ config ARCH_ZYNQ
        select MIGHT_HAVE_CACHE_L2X0
        select USE_OF
        select SPARSE_IRQ
+       select CADENCE_TTC_TIMER
        help
          Support for Xilinx Zynq ARM Cortex A9 Platform
index 397268c1b2501ac0291d8344ef3098735468f0fa..320faedeb48482968fae80fe2fd36f1fa97312c3 100644 (file)
@@ -3,4 +3,4 @@
 #
 
 # Common support
-obj-y                          := common.o timer.o
+obj-y                          := common.o
index 5c8983218183c11e774cd31395c98d31edfc536f..68e0907de5d002fc162c0247845f27c284d057e2 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/clk/zynq.h>
+#include <linux/clocksource.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
@@ -77,7 +78,7 @@ static void __init xilinx_zynq_timer_init(void)
 
        xilinx_zynq_clocks_init(slcr);
 
-       xttcps_timer_init();
+       clocksource_of_init();
 }
 
 /**
index 8b4dbbaa01cf4b078b1e4b6e50413bb4316de385..5050bb10bb12a16646d71b0a74ca202ec9af9e7d 100644 (file)
@@ -17,6 +17,4 @@
 #ifndef __MACH_ZYNQ_COMMON_H__
 #define __MACH_ZYNQ_COMMON_H__
 
-void __init xttcps_timer_init(void);
-
 #endif
diff --git a/arch/arm/mach-zynq/timer.c b/arch/arm/mach-zynq/timer.c
deleted file mode 100644 (file)
index f9fbc9c..0000000
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * 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/interrupt.h>
-#include <linux/clockchips.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/slab.h>
-#include <linux/clk-provider.h>
-#include "common.h"
-
-/*
- * Timer Register Offset Definitions of Timer 1, Increment base address by 4
- * and use same offsets for Timer 2
- */
-#define XTTCPS_CLK_CNTRL_OFFSET                0x00 /* Clock Control Reg, RW */
-#define XTTCPS_CNT_CNTRL_OFFSET                0x0C /* Counter Control Reg, RW */
-#define XTTCPS_COUNT_VAL_OFFSET                0x18 /* Counter Value Reg, RO */
-#define XTTCPS_INTR_VAL_OFFSET         0x24 /* Interval Count Reg, RW */
-#define XTTCPS_ISR_OFFSET              0x54 /* Interrupt Status Reg, RO */
-#define XTTCPS_IER_OFFSET              0x60 /* Interrupt Enable Reg, RW */
-
-#define XTTCPS_CNT_CNTRL_DISABLE_MASK  0x1
-
-/*
- * Setup the timers to use pre-scaling, using a fixed value for now that will
- * work across most input frequency, but it may need to be more dynamic
- */
-#define PRESCALE_EXPONENT      11      /* 2 ^ PRESCALE_EXPONENT = PRESCALE */
-#define PRESCALE               2048    /* The exponent must match this */
-#define CLK_CNTRL_PRESCALE     ((PRESCALE_EXPONENT - 1) << 1)
-#define CLK_CNTRL_PRESCALE_EN  1
-#define CNT_CNTRL_RESET                (1<<4)
-
-/**
- * struct xttcps_timer - This definition defines local timer structure
- *
- * @base_addr: Base address of timer
- **/
-struct xttcps_timer {
-       void __iomem    *base_addr;
-};
-
-struct xttcps_timer_clocksource {
-       struct xttcps_timer     xttc;
-       struct clocksource      cs;
-};
-
-#define to_xttcps_timer_clksrc(x) \
-               container_of(x, struct xttcps_timer_clocksource, cs)
-
-struct xttcps_timer_clockevent {
-       struct xttcps_timer             xttc;
-       struct clock_event_device       ce;
-       struct clk                      *clk;
-};
-
-#define to_xttcps_timer_clkevent(x) \
-               container_of(x, struct xttcps_timer_clockevent, ce)
-
-/**
- * xttcps_set_interval - Set the timer interval value
- *
- * @timer:     Pointer to the timer instance
- * @cycles:    Timer interval ticks
- **/
-static void xttcps_set_interval(struct xttcps_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 + XTTCPS_CNT_CNTRL_OFFSET);
-       ctrl_reg |= XTTCPS_CNT_CNTRL_DISABLE_MASK;
-       __raw_writel(ctrl_reg, timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET);
-
-       __raw_writel(cycles, timer->base_addr + XTTCPS_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 |= CNT_CNTRL_RESET;
-       ctrl_reg &= ~XTTCPS_CNT_CNTRL_DISABLE_MASK;
-       __raw_writel(ctrl_reg, timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET);
-}
-
-/**
- * xttcps_clock_event_interrupt - Clock event timer interrupt handler
- *
- * @irq:       IRQ number of the Timer
- * @dev_id:    void pointer to the xttcps_timer instance
- *
- * returns: Always IRQ_HANDLED - success
- **/
-static irqreturn_t xttcps_clock_event_interrupt(int irq, void *dev_id)
-{
-       struct xttcps_timer_clockevent *xttce = dev_id;
-       struct xttcps_timer *timer = &xttce->xttc;
-
-       /* Acknowledge the interrupt and call event handler */
-       __raw_readl(timer->base_addr + XTTCPS_ISR_OFFSET);
-
-       xttce->ce.event_handler(&xttce->ce);
-
-       return IRQ_HANDLED;
-}
-
-/**
- * __xttc_clocksource_read - Reads the timer counter register
- *
- * returns: Current timer counter register value
- **/
-static cycle_t __xttc_clocksource_read(struct clocksource *cs)
-{
-       struct xttcps_timer *timer = &to_xttcps_timer_clksrc(cs)->xttc;
-
-       return (cycle_t)__raw_readl(timer->base_addr +
-                               XTTCPS_COUNT_VAL_OFFSET);
-}
-
-/**
- * xttcps_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 xttcps_set_next_event(unsigned long cycles,
-                                       struct clock_event_device *evt)
-{
-       struct xttcps_timer_clockevent *xttce = to_xttcps_timer_clkevent(evt);
-       struct xttcps_timer *timer = &xttce->xttc;
-
-       xttcps_set_interval(timer, cycles);
-       return 0;
-}
-
-/**
- * xttcps_set_mode - Sets the mode of timer
- *
- * @mode:      Mode to be set
- * @evt:       Address of clock event instance
- **/
-static void xttcps_set_mode(enum clock_event_mode mode,
-                                       struct clock_event_device *evt)
-{
-       struct xttcps_timer_clockevent *xttce = to_xttcps_timer_clkevent(evt);
-       struct xttcps_timer *timer = &xttce->xttc;
-       u32 ctrl_reg;
-
-       switch (mode) {
-       case CLOCK_EVT_MODE_PERIODIC:
-               xttcps_set_interval(timer,
-                                    DIV_ROUND_CLOSEST(clk_get_rate(xttce->clk),
-                                                      PRESCALE * HZ));
-               break;
-       case CLOCK_EVT_MODE_ONESHOT:
-       case CLOCK_EVT_MODE_UNUSED:
-       case CLOCK_EVT_MODE_SHUTDOWN:
-               ctrl_reg = __raw_readl(timer->base_addr +
-                                       XTTCPS_CNT_CNTRL_OFFSET);
-               ctrl_reg |= XTTCPS_CNT_CNTRL_DISABLE_MASK;
-               __raw_writel(ctrl_reg,
-                               timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET);
-               break;
-       case CLOCK_EVT_MODE_RESUME:
-               ctrl_reg = __raw_readl(timer->base_addr +
-                                       XTTCPS_CNT_CNTRL_OFFSET);
-               ctrl_reg &= ~XTTCPS_CNT_CNTRL_DISABLE_MASK;
-               __raw_writel(ctrl_reg,
-                               timer->base_addr + XTTCPS_CNT_CNTRL_OFFSET);
-               break;
-       }
-}
-
-static void __init zynq_ttc_setup_clocksource(struct device_node *np,
-                                            void __iomem *base)
-{
-       struct xttcps_timer_clocksource *ttccs;
-       struct clk *clk;
-       int err;
-       u32 reg;
-
-       ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL);
-       if (WARN_ON(!ttccs))
-               return;
-
-       err = of_property_read_u32(np, "reg", &reg);
-       if (WARN_ON(err))
-               return;
-
-       clk = of_clk_get_by_name(np, "cpu_1x");
-       if (WARN_ON(IS_ERR(clk)))
-               return;
-
-       err = clk_prepare_enable(clk);
-       if (WARN_ON(err))
-               return;
-
-       ttccs->xttc.base_addr = base + reg * 4;
-
-       ttccs->cs.name = np->name;
-       ttccs->cs.rating = 200;
-       ttccs->cs.read = __xttc_clocksource_read;
-       ttccs->cs.mask = CLOCKSOURCE_MASK(16);
-       ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
-
-       __raw_writel(0x0,  ttccs->xttc.base_addr + XTTCPS_IER_OFFSET);
-       __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
-                    ttccs->xttc.base_addr + XTTCPS_CLK_CNTRL_OFFSET);
-       __raw_writel(CNT_CNTRL_RESET,
-                    ttccs->xttc.base_addr + XTTCPS_CNT_CNTRL_OFFSET);
-
-       err = clocksource_register_hz(&ttccs->cs, clk_get_rate(clk) / PRESCALE);
-       if (WARN_ON(err))
-               return;
-}
-
-static void __init zynq_ttc_setup_clockevent(struct device_node *np,
-                                           void __iomem *base)
-{
-       struct xttcps_timer_clockevent *ttcce;
-       int err, irq;
-       u32 reg;
-
-       ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL);
-       if (WARN_ON(!ttcce))
-               return;
-
-       err = of_property_read_u32(np, "reg", &reg);
-       if (WARN_ON(err))
-               return;
-
-       ttcce->xttc.base_addr = base + reg * 4;
-
-       ttcce->clk = of_clk_get_by_name(np, "cpu_1x");
-       if (WARN_ON(IS_ERR(ttcce->clk)))
-               return;
-
-       err = clk_prepare_enable(ttcce->clk);
-       if (WARN_ON(err))
-               return;
-
-       irq = irq_of_parse_and_map(np, 0);
-       if (WARN_ON(!irq))
-               return;
-
-       ttcce->ce.name = np->name;
-       ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
-       ttcce->ce.set_next_event = xttcps_set_next_event;
-       ttcce->ce.set_mode = xttcps_set_mode;
-       ttcce->ce.rating = 200;
-       ttcce->ce.irq = irq;
-       ttcce->ce.cpumask = cpu_possible_mask;
-
-       __raw_writel(0x23, ttcce->xttc.base_addr + XTTCPS_CNT_CNTRL_OFFSET);
-       __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
-                    ttcce->xttc.base_addr + XTTCPS_CLK_CNTRL_OFFSET);
-       __raw_writel(0x1,  ttcce->xttc.base_addr + XTTCPS_IER_OFFSET);
-
-       err = request_irq(irq, xttcps_clock_event_interrupt, IRQF_TIMER,
-                         np->name, ttcce);
-       if (WARN_ON(err))
-               return;
-
-       clockevents_config_and_register(&ttcce->ce,
-                                       clk_get_rate(ttcce->clk) / PRESCALE,
-                                       1, 0xfffe);
-}
-
-static const __initconst struct of_device_id zynq_ttc_match[] = {
-       { .compatible = "xlnx,ttc-counter-clocksource",
-               .data = zynq_ttc_setup_clocksource, },
-       { .compatible = "xlnx,ttc-counter-clockevent",
-               .data = zynq_ttc_setup_clockevent, },
-       {}
-};
-
-/**
- * xttcps_timer_init - Initialize the timer
- *
- * Initializes the timer hardware and register the clock source and clock event
- * timers with Linux kernal timer framework
- **/
-void __init xttcps_timer_init(void)
-{
-       struct device_node *np;
-
-       for_each_compatible_node(np, NULL, "xlnx,ttc") {
-               struct device_node *np_chld;
-               void __iomem *base;
-
-               base = of_iomap(np, 0);
-               if (WARN_ON(!base))
-                       return;
-
-               for_each_available_child_of_node(np, np_chld) {
-                       int (*cb)(struct device_node *np, void __iomem *base);
-                       const struct of_device_id *match;
-
-                       match = of_match_node(zynq_ttc_match, np_chld);
-                       if (match) {
-                               cb = match->data;
-                               cb(np_chld, base);
-                       }
-               }
-       }
-}
index c2f37390308a20b835d653dfbb0f64f28cc8ce40..c465faca51b06b05ed50c27962b8b169198ea909 100644 (file)
@@ -299,7 +299,7 @@ static void l2x0_unlock(u32 cache_id)
        int lockregs;
        int i;
 
-       switch (cache_id) {
+       switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
        case L2X0_CACHE_ID_PART_L310:
                lockregs = 8;
                break;
@@ -333,15 +333,14 @@ void __init l2x0_init(void __iomem *base, u32 aux_val, u32 aux_mask)
        if (cache_id_part_number_from_dt)
                cache_id = cache_id_part_number_from_dt;
        else
-               cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID)
-                       & L2X0_CACHE_ID_PART_MASK;
+               cache_id = readl_relaxed(l2x0_base + L2X0_CACHE_ID);
        aux = readl_relaxed(l2x0_base + L2X0_AUX_CTRL);
 
        aux &= aux_mask;
        aux |= aux_val;
 
        /* Determine the number of ways */
-       switch (cache_id) {
+       switch (cache_id & L2X0_CACHE_ID_PART_MASK) {
        case L2X0_CACHE_ID_PART_L310:
                if (aux & (1 << 16))
                        ways = 16;
@@ -725,7 +724,6 @@ static const struct l2x0_of_data pl310_data = {
                .flush_all   = l2x0_flush_all,
                .inv_all     = l2x0_inv_all,
                .disable     = l2x0_disable,
-               .set_debug   = pl310_set_debug,
        },
 };
 
@@ -814,9 +812,8 @@ int __init l2x0_of_init(u32 aux_val, u32 aux_mask)
                data->save();
 
        of_init = true;
-       l2x0_init(l2x0_base, aux_val, aux_mask);
-
        memcpy(&outer_cache, &data->outer_cache, sizeof(outer_cache));
+       l2x0_init(l2x0_base, aux_val, aux_mask);
 
        return 0;
 }
index a5a4b2bc42ba353e7e0ae94461cf4d8691b2b68a..2ac37372ef52f4ba4db642d39bef349798f1785a 100644 (file)
@@ -48,7 +48,7 @@ static DEFINE_RAW_SPINLOCK(cpu_asid_lock);
 static atomic64_t asid_generation = ATOMIC64_INIT(ASID_FIRST_VERSION);
 static DECLARE_BITMAP(asid_map, NUM_USER_ASIDS);
 
-static DEFINE_PER_CPU(atomic64_t, active_asids);
+DEFINE_PER_CPU(atomic64_t, active_asids);
 static DEFINE_PER_CPU(u64, reserved_asids);
 static cpumask_t tlb_flush_pending;
 
@@ -215,6 +215,7 @@ void check_and_switch_context(struct mm_struct *mm, struct task_struct *tsk)
        if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending)) {
                local_flush_bp_all();
                local_flush_tlb_all();
+               dummy_flush_tlb_a15_erratum();
        }
 
        atomic64_set(&per_cpu(active_asids, cpu), asid);
index c7e3759f16d303c8c989af0a903f768f358c0e4f..e9db6b4bf65a158adf54bd4a799dbc7fee754c36 100644 (file)
@@ -342,6 +342,7 @@ static int __init atomic_pool_init(void)
 {
        struct dma_pool *pool = &atomic_pool;
        pgprot_t prot = pgprot_dmacoherent(pgprot_kernel);
+       gfp_t gfp = GFP_KERNEL | GFP_DMA;
        unsigned long nr_pages = pool->size >> PAGE_SHIFT;
        unsigned long *bitmap;
        struct page *page;
@@ -361,8 +362,8 @@ static int __init atomic_pool_init(void)
                ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page,
                                              atomic_pool_init);
        else
-               ptr = __alloc_remap_buffer(NULL, pool->size, GFP_KERNEL, prot,
-                                          &page, atomic_pool_init);
+               ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
+                                          atomic_pool_init);
        if (ptr) {
                int i;
 
index e95a996ab78f6c7d995d859f6010ef5d8df471ed..78978945492a2a105f1a9a2d18e81cd76dc1e7b6 100644 (file)
@@ -598,39 +598,60 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
        } while (pte++, addr += PAGE_SIZE, addr != end);
 }
 
-static void __init alloc_init_section(pud_t *pud, unsigned long addr,
-                                     unsigned long end, phys_addr_t phys,
-                                     const struct mem_type *type)
+static void __init map_init_section(pmd_t *pmd, unsigned long addr,
+                       unsigned long end, phys_addr_t phys,
+                       const struct mem_type *type)
 {
-       pmd_t *pmd = pmd_offset(pud, addr);
-
+#ifndef CONFIG_ARM_LPAE
        /*
-        * Try a section mapping - end, addr and phys must all be aligned
-        * to a section boundary.  Note that PMDs refer to the individual
-        * L1 entries, whereas PGDs refer to a group of L1 entries making
-        * up one logical pointer to an L2 table.
+        * In classic MMU format, puds and pmds are folded in to
+        * the pgds. pmd_offset gives the PGD entry. PGDs refer to a
+        * group of L1 entries making up one logical pointer to
+        * an L2 table (2MB), where as PMDs refer to the individual
+        * L1 entries (1MB). Hence increment to get the correct
+        * offset for odd 1MB sections.
+        * (See arch/arm/include/asm/pgtable-2level.h)
         */
-       if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) {
-               pmd_t *p = pmd;
-
-#ifndef CONFIG_ARM_LPAE
-               if (addr & SECTION_SIZE)
-                       pmd++;
+       if (addr & SECTION_SIZE)
+               pmd++;
 #endif
+       do {
+               *pmd = __pmd(phys | type->prot_sect);
+               phys += SECTION_SIZE;
+       } while (pmd++, addr += SECTION_SIZE, addr != end);
 
-               do {
-                       *pmd = __pmd(phys | type->prot_sect);
-                       phys += SECTION_SIZE;
-               } while (pmd++, addr += SECTION_SIZE, addr != end);
+       flush_pmd_entry(pmd);
+}
 
-               flush_pmd_entry(p);
-       } else {
+static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
+                                     unsigned long end, phys_addr_t phys,
+                                     const struct mem_type *type)
+{
+       pmd_t *pmd = pmd_offset(pud, addr);
+       unsigned long next;
+
+       do {
                /*
-                * No need to loop; pte's aren't interested in the
-                * individual L1 entries.
+                * With LPAE, we must loop over to map
+                * all the pmds for the given range.
                 */
-               alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
-       }
+               next = pmd_addr_end(addr, end);
+
+               /*
+                * Try a section mapping - addr, next and phys must all be
+                * aligned to a section boundary.
+                */
+               if (type->prot_sect &&
+                               ((addr | next | phys) & ~SECTION_MASK) == 0) {
+                       map_init_section(pmd, addr, next, phys, type);
+               } else {
+                       alloc_init_pte(pmd, addr, next,
+                                               __phys_to_pfn(phys), type);
+               }
+
+               phys += next - addr;
+
+       } while (pmd++, addr = next, addr != end);
 }
 
 static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
@@ -641,7 +662,7 @@ static void __init alloc_init_pud(pgd_t *pgd, unsigned long addr,
 
        do {
                next = pud_addr_end(addr, end);
-               alloc_init_section(pud, addr, next, phys, type);
+               alloc_init_pmd(pud, addr, next, phys, type);
                phys += next - addr;
        } while (pud++, addr = next, addr != end);
 }
index 3a3c015f8d5c33cb99357995b6d35790037e7f94..f584d3f5b37c5855782a0259c327bc6347bba89a 100644 (file)
@@ -420,7 +420,7 @@ __v7_pj4b_proc_info:
 __v7_ca7mp_proc_info:
        .long   0x410fc070
        .long   0xff0ffff0
-       __v7_proc __v7_ca7mp_setup, hwcaps = HWCAP_IDIV
+       __v7_proc __v7_ca7mp_setup
        .size   __v7_ca7mp_proc_info, . - __v7_ca7mp_proc_info
 
        /*
@@ -430,9 +430,24 @@ __v7_ca7mp_proc_info:
 __v7_ca15mp_proc_info:
        .long   0x410fc0f0
        .long   0xff0ffff0
-       __v7_proc __v7_ca15mp_setup, hwcaps = HWCAP_IDIV
+       __v7_proc __v7_ca15mp_setup
        .size   __v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
 
+       /*
+        * Qualcomm Inc. Krait processors.
+        */
+       .type   __krait_proc_info, #object
+__krait_proc_info:
+       .long   0x510f0400              @ Required ID value
+       .long   0xff0ffc00              @ Mask for ID
+       /*
+        * Some Krait processors don't indicate support for SDIV and UDIV
+        * instructions in the ARM instruction set, even though they actually
+        * do support them.
+        */
+       __v7_proc __v7_setup, hwcaps = HWCAP_IDIV
+       .size   __krait_proc_info, . - __krait_proc_info
+
        /*
         * Match any ARMv7 processor core.
         */
index 6828ef6ce80e69c5ce360190917abd75a3028041..a0bd8a755bdfc9616c0515116d37dc41bc16e812 100644 (file)
@@ -576,7 +576,7 @@ load_ind:
                        /* x = ((*(frame + k)) & 0xf) << 2; */
                        ctx->seen |= SEEN_X | SEEN_DATA | SEEN_CALL;
                        /* the interpreter should deal with the negative K */
-                       if (k < 0)
+                       if ((int)k < 0)
                                return -1;
                        /* offset in r1: we might have to take the slow path */
                        emit_mov_i(r_off, k, ctx);
index a0daa2fb5de667d4410a87e81fb53cba254dc664..e6dbc8dbe6a68457acf5515a238551f61fc65e78 100644 (file)
@@ -140,8 +140,7 @@ static int omap_dm_timer_prepare(struct omap_dm_timer *timer)
         */
        if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
                timer->fclk = clk_get(&timer->pdev->dev, "fck");
-               if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
-                       timer->fclk = NULL;
+               if (WARN_ON_ONCE(IS_ERR(timer->fclk))) {
                        dev_err(&timer->pdev->dev, ": No fclk handle.\n");
                        return -EINVAL;
                }
@@ -373,7 +372,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_modify_idlect_mask);
 
 struct clk *omap_dm_timer_get_fclk(struct omap_dm_timer *timer)
 {
-       if (timer)
+       if (timer && !IS_ERR(timer->fclk))
                return timer->fclk;
        return NULL;
 }
@@ -482,7 +481,7 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
        if (pdata && pdata->set_timer_src)
                return pdata->set_timer_src(timer->pdev, source);
 
-       if (!timer->fclk)
+       if (IS_ERR(timer->fclk))
                return -EINVAL;
 
        switch (source) {
@@ -500,13 +499,13 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
        }
 
        parent = clk_get(&timer->pdev->dev, parent_name);
-       if (IS_ERR_OR_NULL(parent)) {
+       if (IS_ERR(parent)) {
                pr_err("%s: %s not found\n", __func__, parent_name);
                return -EINVAL;
        }
 
        ret = clk_set_parent(timer->fclk, parent);
-       if (IS_ERR_VALUE(ret))
+       if (ret < 0)
                pr_err("%s: failed to set %s as parent\n", __func__,
                        parent_name);
 
@@ -808,6 +807,7 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
                return  -ENOMEM;
        }
 
+       timer->fclk = ERR_PTR(-ENODEV);
        timer->io_base = devm_ioremap_resource(dev, mem);
        if (IS_ERR(timer->io_base))
                return PTR_ERR(timer->io_base);
index febe3862873ca2238aaaccf3265991c97fe5384c..807ac8e5cbc062ed7e5dbb17869a163e58b15ce7 100644 (file)
@@ -157,9 +157,12 @@ void __init orion_setup_cpu_mbus_target(const struct orion_addr_map_cfg *cfg,
                u32 size = readl(ddr_window_cpu_base + DDR_SIZE_CS_OFF(i));
 
                /*
-                * Chip select enabled?
+                * We only take care of entries for which the chip
+                * select is enabled, and that don't have high base
+                * address bits set (devices can only access the first
+                * 32 bits of the memory).
                 */
-               if (size & 1) {
+               if ((size & 1) && !(base & 0xF)) {
                        struct mbus_dram_window *w;
 
                        w = &orion_mbus_dram_info.cs[cs++];
index 2e1b1905ac3a26e183f88564ec0602d41418325c..53b2d59ca252f6d52683a9d8c9d433f36a5328ac 100644 (file)
@@ -13,6 +13,10 @@ config PLAT_SAMSUNG
        help
          Base platform code for all Samsung SoC based systems
 
+config PLAT_SAMSUNG_SINGLE
+       def_bool PLAT_SAMSUNG && !ARCH_MULTIPLATFORM
+       
+
 config PLAT_S5P
        bool
        depends on (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
@@ -23,9 +27,9 @@ config PLAT_S5P
        select GIC_NON_BANKED if ARCH_EXYNOS4
        select NO_IOPORT
        select PLAT_SAMSUNG
-       select S3C_GPIO_TRACK
+       select S3C_GPIO_TRACK if PLAT_SAMSUNG_SINGLE
        select S5P_GPIO_DRVSTR
-       select SAMSUNG_CLKSRC
+       select SAMSUNG_CLKSRC if !COMMON_CLK
        select SAMSUNG_GPIOLIB_4BIT
        select SAMSUNG_IRQ_VIC_TIMER
        help
@@ -70,7 +74,7 @@ config S3C_LOWLEVEL_UART_PORT
 
 # timer options
 
-config S5P_HRT
+config SAMSUNG_HRT
        bool
        select SAMSUNG_DEV_PWM
        help
@@ -89,7 +93,7 @@ config SAMSUNG_CLKSRC
          used by newer systems such as the S3C64XX.
 
 config S5P_CLOCK
-       def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS)
+       def_bool (ARCH_S5P64X0 || ARCH_S5PC100 || ARCH_S5PV210)
        help
          Support common clock part for ARCH_S5P and ARCH_EXYNOS SoCs
 
@@ -178,6 +182,7 @@ config S5P_DEV_UART
 
 config S3C_ADC
        bool "ADC common driver support"
+       depends on PLAT_SAMSUNG_SINGLE
        help
          Core support for the ADC block found in the Samsung SoC systems
          for drivers such as the touchscreen and hwmon to use to share
index 3a7c64d1814a2edb92a01fcbe390189e005c1eb3..f38ce8489dfde1fd014c7ba7af918caf2ad1304b 100644 (file)
@@ -4,6 +4,9 @@
 #
 # Licensed under GPLv2
 
+ccflags-$(CONFIG_ARCH_MULTI_V7) += -I$(srctree)/$(src)/include
+ccflags-$(CONFIG_ARCH_EXYNOS)  += -I$(srctree)/arch/arm/mach-exynos/include
+
 obj-y                          :=
 obj-m                          :=
 obj-n                          := dummy.o
@@ -12,8 +15,7 @@ obj-                          :=
 # Objects we always build independent of SoC choice
 
 obj-y                          += init.o cpu.o
-obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET)   += time.o
-obj-$(CONFIG_S5P_HRT)          += s5p-time.o
+obj-$(CONFIG_SAMSUNG_HRT)      += samsung-time.o
 
 obj-$(CONFIG_SAMSUNG_CLOCK)    += clock.o
 obj-$(CONFIG_SAMSUNG_CLOCK)    += pwm-clock.o
@@ -34,7 +36,7 @@ obj-$(CONFIG_S3C_ADC) += adc.o
 
 obj-y                          += platformdata.o
 
-obj-y                          += devs.o
+obj-$(CONFIG_PLAT_SAMSUNG_SINGLE)      += devs.o
 obj-y                          += dev-uart.o
 obj-$(CONFIG_S5P_DEV_MFC)      += s5p-dev-mfc.o
 obj-$(CONFIG_S5P_DEV_UART)     += s5p-dev-uart.o
@@ -51,9 +53,10 @@ obj-$(CONFIG_S3C_DMA)                += dma.o s3c-dma-ops.o
 obj-$(CONFIG_SAMSUNG_DMADEV)   += dma-ops.o
 
 # PM support
-
 obj-$(CONFIG_PM)               += pm.o
+ifdef CONFIG_PLAT_SAMSUNG_SINGLE
 obj-$(CONFIG_PM)               += pm-gpio.o
+endif
 obj-$(CONFIG_SAMSUNG_PM_CHECK) += pm-check.o
 
 obj-$(CONFIG_SAMSUNG_WAKEMASK) += wakeup-mask.o
index 51afedda9ab61fd761114d79422fb2e34d6e138b..4cf660e381826a4dd49e9605762533da667b370b 100644 (file)
@@ -878,51 +878,6 @@ void __init s3c24xx_fb_set_platdata(struct s3c2410fb_mach_info *pd)
 }
 #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
@@ -1113,7 +1068,7 @@ struct platform_device s5p_device_onenand = {
 
 /* PMU */
 
-#ifdef CONFIG_PLAT_S5P
+#if defined(CONFIG_PLAT_S5P) && !defined(CONFIG_ARCH_EXYNOS)
 static struct resource s5p_pmu_resource[] = {
        DEFINE_RES_IRQ(IRQ_PMU)
 };
index 37703ef6dfc76ff28b70543b55311f7abc52269b..989fefe18be6b77bee4216be31948f49582a475b 100644 (file)
@@ -23,6 +23,9 @@ extern unsigned long samsung_cpu_id;
 #define S3C24XX_CPU_ID         0x32400000
 #define S3C24XX_CPU_MASK       0xFFF00000
 
+#define S3C2412_CPU_ID         0x32412000
+#define S3C2412_CPU_MASK       0xFFFFF000
+
 #define S3C6400_CPU_ID         0x36400000
 #define S3C6410_CPU_ID         0x36410000
 #define S3C64XX_CPU_MASK       0xFFFFF000
@@ -53,6 +56,7 @@ static inline int is_samsung_##name(void)     \
 }
 
 IS_SAMSUNG_CPU(s3c24xx, S3C24XX_CPU_ID, S3C24XX_CPU_MASK)
+IS_SAMSUNG_CPU(s3c2412, S3C2412_CPU_ID, S3C2412_CPU_MASK)
 IS_SAMSUNG_CPU(s3c6400, S3C6400_CPU_ID, S3C64XX_CPU_MASK)
 IS_SAMSUNG_CPU(s3c6410, S3C6410_CPU_ID, S3C64XX_CPU_MASK)
 IS_SAMSUNG_CPU(s5p6440, S5P6440_CPU_ID, S5P64XX_CPU_MASK)
@@ -74,6 +78,12 @@ IS_SAMSUNG_CPU(exynos5440, EXYNOS5440_SOC_ID, EXYNOS5_SOC_MASK)
 # define soc_is_s3c24xx()      0
 #endif
 
+#if defined(CONFIG_CPU_S3C2412)
+# define soc_is_s3c2412()      is_samsung_s3c2412()
+#else
+# define soc_is_s3c2412()      0
+#endif
+
 #if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
 # define soc_is_s3c64xx()      (is_samsung_s3c6400() || is_samsung_s3c6410())
 #else
@@ -173,7 +183,6 @@ extern void s3c_init_cpu(unsigned long idcode,
 
 /* core initialisation functions */
 
-extern void s3c24xx_init_irq(void);
 extern void s5p_init_irq(u32 *vic, u32 num_vic);
 
 extern void s3c24xx_init_io(struct map_desc *mach_desc, int size);
@@ -192,10 +201,6 @@ extern void s3c24xx_init_uartdevs(char *name,
                                  struct s3c24xx_uart_resources *res,
                                  struct s3c2410_uartcfg *cfg, int no);
 
-/* timer for 2410/2440 */
-
-extern void s3c24xx_timer_init(void);
-
 extern struct syscore_ops s3c2410_pm_syscore_ops;
 extern struct syscore_ops s3c2412_pm_syscore_ops;
 extern struct syscore_ops s3c2416_pm_syscore_ops;
diff --git a/arch/arm/plat-samsung/include/plat/irq.h b/arch/arm/plat-samsung/include/plat/irq.h
deleted file mode 100644 (file)
index e21a89b..0000000
+++ /dev/null
@@ -1,116 +0,0 @@
-/* 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);
index f6fcadeee969f323197e0a84d4b89f58ceef3d8c..266a4e3e24586383d79bb4336a48807184e7c97e 100644 (file)
@@ -166,6 +166,7 @@ extern void s3c_pm_check_store(void);
  */
 extern void s3c_pm_configure_extint(void);
 
+#ifdef CONFIG_PLAT_SAMSUNG_SINGLE
 /**
  * samsung_pm_restore_gpios() - restore the state of the gpios after sleep.
  *
@@ -181,6 +182,10 @@ extern void samsung_pm_restore_gpios(void);
  * Save the GPIO states for resotration on resume. See samsung_pm_restore_gpios().
  */
 extern void samsung_pm_save_gpios(void);
+#else
+#define samsung_pm_restore_gpios()     do { } while(0)
+#define samsung_pm_save_gpios()                do { } while(0)
+#endif
 
 extern void s3c_pm_save_core(void);
 extern void s3c_pm_restore_core(void);
diff --git a/arch/arm/plat-samsung/include/plat/s3c2410.h b/arch/arm/plat-samsung/include/plat/s3c2410.h
deleted file mode 100644 (file)
index 55b0e5f..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/* 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
diff --git a/arch/arm/plat-samsung/include/plat/s3c2412.h b/arch/arm/plat-samsung/include/plat/s3c2412.h
deleted file mode 100644 (file)
index cbae50d..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/* 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);
-
-extern void s3c2412_restart(char mode, const char *cmd);
-#else
-#define s3c2412_init_clocks NULL
-#define s3c2412_init_uarts NULL
-#define s3c2412_map_io NULL
-#define s3c2412_init NULL
-#define s3c2412_restart NULL
-#endif
diff --git a/arch/arm/plat-samsung/include/plat/s3c2416.h b/arch/arm/plat-samsung/include/plat/s3c2416.h
deleted file mode 100644 (file)
index f27399a..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/* 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);
-
-extern void s3c2416_restart(char mode, const char *cmd);
-
-extern void s3c2416_init_irq(void);
-extern struct syscore_ops s3c2416_irq_syscore_ops;
-
-#else
-#define s3c2416_init_clocks NULL
-#define s3c2416_init_uarts NULL
-#define s3c2416_map_io NULL
-#define s3c2416_init NULL
-#define s3c2416_restart NULL
-#endif
diff --git a/arch/arm/plat-samsung/include/plat/s3c2443.h b/arch/arm/plat-samsung/include/plat/s3c2443.h
deleted file mode 100644 (file)
index 71b88ec..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* 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);
-
-extern void s3c2443_restart(char mode, const char *cmd);
-
-extern void s3c2443_init_irq(void);
-#else
-#define s3c2443_init_clocks NULL
-#define s3c2443_init_uarts NULL
-#define s3c2443_map_io NULL
-#define s3c2443_init NULL
-#define s3c2443_restart NULL
-#endif
diff --git a/arch/arm/plat-samsung/include/plat/s3c244x.h b/arch/arm/plat-samsung/include/plat/s3c244x.h
deleted file mode 100644 (file)
index ea0c961..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/* 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/s5p-time.h b/arch/arm/plat-samsung/include/plat/s5p-time.h
deleted file mode 100644 (file)
index 9c96f35..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* 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 void s5p_timer_init(void);
-#endif /* __ASM_PLAT_S5P_TIME_H */
diff --git a/arch/arm/plat-samsung/include/plat/samsung-time.h b/arch/arm/plat-samsung/include/plat/samsung-time.h
new file mode 100644 (file)
index 0000000..4cc99bb
--- /dev/null
@@ -0,0 +1,53 @@
+/* linux/arch/arm/plat-samsung/include/plat/samsung-time.h
+ *
+ * Copyright 2011 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com/
+ *
+ * Header file for samsung s3c and 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_SAMSUNG_TIME_H
+#define __ASM_PLAT_SAMSUNG_TIME_H __FILE__
+
+/* SAMSUNG HR-Timer Clock mode */
+enum samsung_timer_mode {
+       SAMSUNG_PWM0,
+       SAMSUNG_PWM1,
+       SAMSUNG_PWM2,
+       SAMSUNG_PWM3,
+       SAMSUNG_PWM4,
+};
+
+struct samsung_timer_source {
+       unsigned int event_id;
+       unsigned int source_id;
+};
+
+/* Be able to sleep for atleast 4 seconds (usually more) */
+#define SAMSUNG_TIMER_MIN_RANGE        4
+
+#if defined(CONFIG_ARCH_S3C24XX) || defined(CONFIG_ARCH_S5PC100)
+#define TCNT_MAX               0xffff
+#define TSCALER_DIV            25
+#define TDIV                   50
+#define TSIZE                  16
+#else
+#define TCNT_MAX               0xffffffff
+#define TSCALER_DIV            2
+#define TDIV                   2
+#define TSIZE                  32
+#endif
+
+#define NON_PERIODIC           0
+#define PERIODIC               1
+
+extern void __init samsung_set_timer_source(enum samsung_timer_mode event,
+                                       enum samsung_timer_mode source);
+
+extern void __init samsung_timer_init(void);
+
+#endif /* __ASM_PLAT_SAMSUNG_TIME_H */
index 9b87f38fc4f400e24332d00bffabe08e6cfb56cd..1e0aab08c13f36a05f16f54b5be7a1781dda6a5c 100644 (file)
 #ifndef __PLAT_S3C_SDHCI_H
 #define __PLAT_S3C_SDHCI_H __FILE__
 
+#include <linux/platform_data/mmc-sdhci-s3c.h>
 #include <plat/devs.h>
 
-struct platform_device;
-struct mmc_host;
-struct mmc_card;
-struct mmc_ios;
-
-enum cd_types {
-       S3C_SDHCI_CD_INTERNAL,  /* use mmc internal CD line */
-       S3C_SDHCI_CD_EXTERNAL,  /* use external callback */
-       S3C_SDHCI_CD_GPIO,      /* use external gpio pin for CD line */
-       S3C_SDHCI_CD_NONE,      /* no CD line, use polling to detect card */
-       S3C_SDHCI_CD_PERMANENT, /* no CD line, card permanently wired to host */
-};
-
-/**
- * struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI
- * @max_width: The maximum number of data bits supported.
- * @host_caps: Standard MMC host capabilities bit field.
- * @host_caps2: The second standard MMC host capabilities bit field.
- * @cd_type: Type of Card Detection method (see cd_types enum above)
- * @ext_cd_init: Initialize external card detect subsystem. Called on
- *              sdhci-s3c driver probe when cd_type == S3C_SDHCI_CD_EXTERNAL.
- *              notify_func argument is a callback to the sdhci-s3c driver
- *              that triggers the card detection event. Callback arguments:
- *              dev is pointer to platform device of the host controller,
- *              state is new state of the card (0 - removed, 1 - inserted).
- * @ext_cd_cleanup: Cleanup external card detect subsystem. Called on
- *              sdhci-s3c driver remove when cd_type == S3C_SDHCI_CD_EXTERNAL.
- *              notify_func argument is the same callback as for ext_cd_init.
- * @ext_cd_gpio: gpio pin used for external CD line, valid only if
- *              cd_type == S3C_SDHCI_CD_GPIO
- * @ext_cd_gpio_invert: invert values for external CD gpio line
- * @cfg_gpio: Configure the GPIO for a specific card bit-width
- *
- * Initialisation data specific to either the machine or the platform
- * for the device driver to use or call-back when configuring gpio or
- * card speed information.
-*/
-struct s3c_sdhci_platdata {
-       unsigned int    max_width;
-       unsigned int    host_caps;
-       unsigned int    host_caps2;
-       unsigned int    pm_caps;
-       enum cd_types   cd_type;
-
-       int             ext_cd_gpio;
-       bool            ext_cd_gpio_invert;
-       int     (*ext_cd_init)(void (*notify_func)(struct platform_device *,
-                                                  int state));
-       int     (*ext_cd_cleanup)(void (*notify_func)(struct platform_device *,
-                                                     int state));
-
-       void    (*cfg_gpio)(struct platform_device *dev, int width);
-};
-
 /* s3c_sdhci_set_platdata() - common helper for setting SDHCI platform data
  * @pd: The default platform data for this device.
  * @set: Pointer to the platform data to fill in.
@@ -378,5 +325,4 @@ static inline void s3c_sdhci_setname(int id, char *name)
                break;
        }
 }
-
 #endif /* __PLAT_S3C_SDHCI_H */
index f980cf3d2baa6166fa82eb420c2b1f6d7a025716..1113066240cf5eeef7dd25159881872a7aa2a1e5 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/io.h>
 
 #include <mach/map.h>
+#include <mach/irqs.h>
 #include <plat/cpu.h>
 #include <plat/irq-vic-timer.h>
 #include <plat/regs-timer.h>
index 002b1472293b4e34459e7563dd3edd8af0ecf93b..53210ec4e8ece7fdbe2f1eb7893692fd15569f38 100644 (file)
@@ -27,6 +27,7 @@
 #include <plat/regs-serial.h>
 #include <mach/regs-clock.h>
 #include <mach/regs-irq.h>
+#include <mach/irqs.h>
 #include <asm/irq.h>
 
 #include <plat/pm.h>
index 5ec104b5408b37d58e25efa202439110150a21c2..a93fb6fb66062db6580ff327acadf3982a44de65 100644 (file)
 #include <linux/of.h>
 
 #include <mach/map.h>
+#include <mach/irqs.h>
 #include <plat/devs.h>
-#include <plat/irqs.h>
 #include <plat/mfc.h>
 
+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               = &s5p_device_mfc_l.dev.coherent_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               = &s5p_device_mfc_r.dev.coherent_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+};
+
 struct s5p_mfc_reserved_mem {
        phys_addr_t     base;
        unsigned long   size;
index 103e371f5e35b2a4277144cf0f45a769a1408cfa..ff1a76011b1ed2a2e2e547399fd230decc63d956 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/io.h>
 #include <linux/irqchip/arm-vic.h>
 
+#include <mach/irqs.h>
 #include <mach/map.h>
 #include <plat/regs-timer.h>
 #include <plat/cpu.h>
similarity index 68%
rename from arch/arm/plat-samsung/s5p-time.c
rename to arch/arm/plat-samsung/samsung-time.c
index e92510cf82ee6318b533624bd765e5fd082b9eb6..f899cbc9b28832cfdba7d4740713728b25562947 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
  *
- * S5P - Common hr-timer support
+ * samsung - Common hr-timer support (s3c and s5p)
  *
  * 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
 #include <mach/map.h>
 #include <plat/devs.h>
 #include <plat/regs-timer.h>
-#include <plat/s5p-time.h>
+#include <plat/samsung-time.h>
 
 static struct clk *tin_event;
 static struct clk *tin_source;
 static struct clk *tdiv_event;
 static struct clk *tdiv_source;
 static struct clk *timerclk;
-static struct s5p_timer_source timer_source;
+static struct samsung_timer_source timer_source;
 static unsigned long clock_count_per_tick;
-static void s5p_timer_resume(void);
+static void samsung_timer_resume(void);
 
-static void s5p_time_stop(enum s5p_timer_mode mode)
+static void samsung_time_stop(enum samsung_timer_mode mode)
 {
        unsigned long tcon;
 
        tcon = __raw_readl(S3C2410_TCON);
 
        switch (mode) {
-       case S5P_PWM0:
+       case SAMSUNG_PWM0:
                tcon &= ~S3C2410_TCON_T0START;
                break;
 
-       case S5P_PWM1:
+       case SAMSUNG_PWM1:
                tcon &= ~S3C2410_TCON_T1START;
                break;
 
-       case S5P_PWM2:
+       case SAMSUNG_PWM2:
                tcon &= ~S3C2410_TCON_T2START;
                break;
 
-       case S5P_PWM3:
+       case SAMSUNG_PWM3:
                tcon &= ~S3C2410_TCON_T3START;
                break;
 
-       case S5P_PWM4:
+       case SAMSUNG_PWM4:
                tcon &= ~S3C2410_TCON_T4START;
                break;
 
@@ -70,7 +70,7 @@ static void s5p_time_stop(enum s5p_timer_mode mode)
        __raw_writel(tcon, S3C2410_TCON);
 }
 
-static void s5p_time_setup(enum s5p_timer_mode mode, unsigned long tcnt)
+static void samsung_time_setup(enum samsung_timer_mode mode, unsigned long tcnt)
 {
        unsigned long tcon;
 
@@ -79,27 +79,27 @@ static void s5p_time_setup(enum s5p_timer_mode mode, unsigned long tcnt)
        tcnt--;
 
        switch (mode) {
-       case S5P_PWM0:
+       case SAMSUNG_PWM0:
                tcon &= ~(0x0f << 0);
                tcon |= S3C2410_TCON_T0MANUALUPD;
                break;
 
-       case S5P_PWM1:
+       case SAMSUNG_PWM1:
                tcon &= ~(0x0f << 8);
                tcon |= S3C2410_TCON_T1MANUALUPD;
                break;
 
-       case S5P_PWM2:
+       case SAMSUNG_PWM2:
                tcon &= ~(0x0f << 12);
                tcon |= S3C2410_TCON_T2MANUALUPD;
                break;
 
-       case S5P_PWM3:
+       case SAMSUNG_PWM3:
                tcon &= ~(0x0f << 16);
                tcon |= S3C2410_TCON_T3MANUALUPD;
                break;
 
-       case S5P_PWM4:
+       case SAMSUNG_PWM4:
                tcon &= ~(0x07 << 20);
                tcon |= S3C2410_TCON_T4MANUALUPD;
                break;
@@ -114,14 +114,14 @@ static void s5p_time_setup(enum s5p_timer_mode mode, unsigned long tcnt)
        __raw_writel(tcon, S3C2410_TCON);
 }
 
-static void s5p_time_start(enum s5p_timer_mode mode, bool periodic)
+static void samsung_time_start(enum samsung_timer_mode mode, bool periodic)
 {
        unsigned long tcon;
 
        tcon  = __raw_readl(S3C2410_TCON);
 
        switch (mode) {
-       case S5P_PWM0:
+       case SAMSUNG_PWM0:
                tcon |= S3C2410_TCON_T0START;
                tcon &= ~S3C2410_TCON_T0MANUALUPD;
 
@@ -131,7 +131,7 @@ static void s5p_time_start(enum s5p_timer_mode mode, bool periodic)
                        tcon &= ~S3C2410_TCON_T0RELOAD;
                break;
 
-       case S5P_PWM1:
+       case SAMSUNG_PWM1:
                tcon |= S3C2410_TCON_T1START;
                tcon &= ~S3C2410_TCON_T1MANUALUPD;
 
@@ -141,7 +141,7 @@ static void s5p_time_start(enum s5p_timer_mode mode, bool periodic)
                        tcon &= ~S3C2410_TCON_T1RELOAD;
                break;
 
-       case S5P_PWM2:
+       case SAMSUNG_PWM2:
                tcon |= S3C2410_TCON_T2START;
                tcon &= ~S3C2410_TCON_T2MANUALUPD;
 
@@ -151,7 +151,7 @@ static void s5p_time_start(enum s5p_timer_mode mode, bool periodic)
                        tcon &= ~S3C2410_TCON_T2RELOAD;
                break;
 
-       case S5P_PWM3:
+       case SAMSUNG_PWM3:
                tcon |= S3C2410_TCON_T3START;
                tcon &= ~S3C2410_TCON_T3MANUALUPD;
 
@@ -161,7 +161,7 @@ static void s5p_time_start(enum s5p_timer_mode mode, bool periodic)
                        tcon &= ~S3C2410_TCON_T3RELOAD;
                break;
 
-       case S5P_PWM4:
+       case SAMSUNG_PWM4:
                tcon |= S3C2410_TCON_T4START;
                tcon &= ~S3C2410_TCON_T4MANUALUPD;
 
@@ -178,24 +178,24 @@ static void s5p_time_start(enum s5p_timer_mode mode, bool periodic)
        __raw_writel(tcon, S3C2410_TCON);
 }
 
-static int s5p_set_next_event(unsigned long cycles,
+static int samsung_set_next_event(unsigned long cycles,
                                struct clock_event_device *evt)
 {
-       s5p_time_setup(timer_source.event_id, cycles);
-       s5p_time_start(timer_source.event_id, NON_PERIODIC);
+       samsung_time_setup(timer_source.event_id, cycles);
+       samsung_time_start(timer_source.event_id, NON_PERIODIC);
 
        return 0;
 }
 
-static void s5p_set_mode(enum clock_event_mode mode,
+static void samsung_set_mode(enum clock_event_mode mode,
                                struct clock_event_device *evt)
 {
-       s5p_time_stop(timer_source.event_id);
+       samsung_time_stop(timer_source.event_id);
 
        switch (mode) {
        case CLOCK_EVT_MODE_PERIODIC:
-               s5p_time_setup(timer_source.event_id, clock_count_per_tick);
-               s5p_time_start(timer_source.event_id, PERIODIC);
+               samsung_time_setup(timer_source.event_id, clock_count_per_tick);
+               samsung_time_start(timer_source.event_id, PERIODIC);
                break;
 
        case CLOCK_EVT_MODE_ONESHOT:
@@ -206,24 +206,24 @@ static void s5p_set_mode(enum clock_event_mode mode,
                break;
 
        case CLOCK_EVT_MODE_RESUME:
-               s5p_timer_resume();
+               samsung_timer_resume();
                break;
        }
 }
 
-static void s5p_timer_resume(void)
+static void samsung_timer_resume(void)
 {
        /* event timer restart */
-       s5p_time_setup(timer_source.event_id, clock_count_per_tick);
-       s5p_time_start(timer_source.event_id, PERIODIC);
+       samsung_time_setup(timer_source.event_id, clock_count_per_tick);
+       samsung_time_start(timer_source.event_id, PERIODIC);
 
        /* source timer restart */
-       s5p_time_setup(timer_source.source_id, TCNT_MAX);
-       s5p_time_start(timer_source.source_id, PERIODIC);
+       samsung_time_setup(timer_source.source_id, TCNT_MAX);
+       samsung_time_start(timer_source.source_id, PERIODIC);
 }
 
-void __init s5p_set_timer_source(enum s5p_timer_mode event,
-                                enum s5p_timer_mode source)
+void __init samsung_set_timer_source(enum samsung_timer_mode event,
+                                enum samsung_timer_mode source)
 {
        s3c_device_timer[event].dev.bus = &platform_bus_type;
        s3c_device_timer[source].dev.bus = &platform_bus_type;
@@ -233,14 +233,14 @@ void __init s5p_set_timer_source(enum s5p_timer_mode event,
 }
 
 static struct clock_event_device time_event_device = {
-       .name           = "s5p_event_timer",
+       .name           = "samsung_event_timer",
        .features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
        .rating         = 200,
-       .set_next_event = s5p_set_next_event,
-       .set_mode       = s5p_set_mode,
+       .set_next_event = samsung_set_next_event,
+       .set_mode       = samsung_set_mode,
 };
 
-static irqreturn_t s5p_clock_event_isr(int irq, void *dev_id)
+static irqreturn_t samsung_clock_event_isr(int irq, void *dev_id)
 {
        struct clock_event_device *evt = dev_id;
 
@@ -249,14 +249,14 @@ static irqreturn_t s5p_clock_event_isr(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-static struct irqaction s5p_clock_event_irq = {
-       .name           = "s5p_time_irq",
+static struct irqaction samsung_clock_event_irq = {
+       .name           = "samsung_time_irq",
        .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-       .handler        = s5p_clock_event_isr,
+       .handler        = samsung_clock_event_isr,
        .dev_id         = &time_event_device,
 };
 
-static void __init s5p_clockevent_init(void)
+static void __init samsung_clockevent_init(void)
 {
        unsigned long pclk;
        unsigned long clock_rate;
@@ -267,8 +267,8 @@ static void __init s5p_clockevent_init(void)
 
        tscaler = clk_get_parent(tdiv_event);
 
-       clk_set_rate(tscaler, pclk / 2);
-       clk_set_rate(tdiv_event, pclk / 2);
+       clk_set_rate(tscaler, pclk / TSCALER_DIV);
+       clk_set_rate(tdiv_event, pclk / TDIV);
        clk_set_parent(tin_event, tdiv_event);
 
        clock_rate = clk_get_rate(tin_event);
@@ -278,22 +278,22 @@ static void __init s5p_clockevent_init(void)
        clockevents_config_and_register(&time_event_device, clock_rate, 1, -1);
 
        irq_number = timer_source.event_id + IRQ_TIMER0;
-       setup_irq(irq_number, &s5p_clock_event_irq);
+       setup_irq(irq_number, &samsung_clock_event_irq);
 }
 
-static void __iomem *s5p_timer_reg(void)
+static void __iomem *samsung_timer_reg(void)
 {
        unsigned long offset = 0;
 
        switch (timer_source.source_id) {
-       case S5P_PWM0:
-       case S5P_PWM1:
-       case S5P_PWM2:
-       case S5P_PWM3:
+       case SAMSUNG_PWM0:
+       case SAMSUNG_PWM1:
+       case SAMSUNG_PWM2:
+       case SAMSUNG_PWM3:
                offset = (timer_source.source_id * 0x0c) + 0x14;
                break;
 
-       case S5P_PWM4:
+       case SAMSUNG_PWM4:
                offset = 0x40;
                break;
 
@@ -312,9 +312,9 @@ static void __iomem *s5p_timer_reg(void)
  * this wraps around for now, since it is just a relative time
  * stamp. (Inspired by U300 implementation.)
  */
-static u32 notrace s5p_read_sched_clock(void)
+static u32 notrace samsung_read_sched_clock(void)
 {
-       void __iomem *reg = s5p_timer_reg();
+       void __iomem *reg = samsung_timer_reg();
 
        if (!reg)
                return 0;
@@ -322,29 +322,29 @@ static u32 notrace s5p_read_sched_clock(void)
        return ~__raw_readl(reg);
 }
 
-static void __init s5p_clocksource_init(void)
+static void __init samsung_clocksource_init(void)
 {
        unsigned long pclk;
        unsigned long clock_rate;
 
        pclk = clk_get_rate(timerclk);
 
-       clk_set_rate(tdiv_source, pclk / 2);
+       clk_set_rate(tdiv_source, pclk / TDIV);
        clk_set_parent(tin_source, tdiv_source);
 
        clock_rate = clk_get_rate(tin_source);
 
-       s5p_time_setup(timer_source.source_id, TCNT_MAX);
-       s5p_time_start(timer_source.source_id, PERIODIC);
+       samsung_time_setup(timer_source.source_id, TCNT_MAX);
+       samsung_time_start(timer_source.source_id, PERIODIC);
 
-       setup_sched_clock(s5p_read_sched_clock, 32, clock_rate);
+       setup_sched_clock(samsung_read_sched_clock, TSIZE, clock_rate);
 
-       if (clocksource_mmio_init(s5p_timer_reg(), "s5p_clocksource_timer",
-                       clock_rate, 250, 32, clocksource_mmio_readl_down))
-               panic("s5p_clocksource_timer: can't register clocksource\n");
+       if (clocksource_mmio_init(samsung_timer_reg(), "samsung_clocksource_timer",
+                       clock_rate, 250, TSIZE, clocksource_mmio_readl_down))
+               panic("samsung_clocksource_timer: can't register clocksource\n");
 }
 
-static void __init s5p_timer_resources(void)
+static void __init samsung_timer_resources(void)
 {
 
        unsigned long event_id = timer_source.event_id;
@@ -386,9 +386,9 @@ static void __init s5p_timer_resources(void)
        clk_enable(tin_source);
 }
 
-void __init s5p_timer_init(void)
+void __init samsung_timer_init(void)
 {
-       s5p_timer_resources();
-       s5p_clockevent_init();
-       s5p_clocksource_init();
+       samsung_timer_resources();
+       samsung_clockevent_init();
+       samsung_clocksource_init();
 }
diff --git a/arch/arm/plat-samsung/time.c b/arch/arm/plat-samsung/time.c
deleted file mode 100644 (file)
index 73defd0..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/* linux/arch/arm/plat-samsung/time.c
- *
- * Copyright (C) 2003-2005 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 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/kernel.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/syscore_ops.h>
-
-#include <asm/mach-types.h>
-
-#include <asm/irq.h>
-#include <mach/map.h>
-#include <plat/regs-timer.h>
-#include <mach/regs-irq.h>
-#include <asm/mach/time.h>
-#include <mach/tick.h>
-
-#include <plat/clock.h>
-#include <plat/cpu.h>
-
-static unsigned long timer_startval;
-static unsigned long timer_usec_ticks;
-
-#ifndef TICK_MAX
-#define TICK_MAX (0xffff)
-#endif
-
-#define TIMER_USEC_SHIFT 16
-
-/* we use the shifted arithmetic to work out the ratio of timer ticks
- * to usecs, as often the peripheral clock is not a nice even multiple
- * of 1MHz.
- *
- * shift of 14 and 15 are too low for the 12MHz, 16 seems to be ok
- * for the current HZ value of 200 without producing overflows.
- *
- * Original patch by Dimitry Andric, updated by Ben Dooks
-*/
-
-
-/* timer_mask_usec_ticks
- *
- * given a clock and divisor, make the value to pass into timer_ticks_to_usec
- * to scale the ticks into usecs
-*/
-
-static inline unsigned long
-timer_mask_usec_ticks(unsigned long scaler, unsigned long pclk)
-{
-       unsigned long den = pclk / 1000;
-
-       return ((1000 << TIMER_USEC_SHIFT) * scaler + (den >> 1)) / den;
-}
-
-/* timer_ticks_to_usec
- *
- * convert timer ticks to usec.
-*/
-
-static inline unsigned long timer_ticks_to_usec(unsigned long ticks)
-{
-       unsigned long res;
-
-       res = ticks * timer_usec_ticks;
-       res += 1 << (TIMER_USEC_SHIFT - 4);     /* round up slightly */
-
-       return res >> TIMER_USEC_SHIFT;
-}
-
-/***
- * Returns microsecond  since last clock interrupt.  Note that interrupts
- * will have been disabled by do_gettimeoffset()
- * IRQs are disabled before entering here from do_gettimeofday()
- */
-
-static u32 s3c2410_gettimeoffset(void)
-{
-       unsigned long tdone;
-       unsigned long tval;
-
-       /* work out how many ticks have gone since last timer interrupt */
-
-       tval =  __raw_readl(S3C2410_TCNTO(4));
-       tdone = timer_startval - tval;
-
-       /* check to see if there is an interrupt pending */
-
-       if (s3c24xx_ostimer_pending()) {
-               /* re-read the timer, and try and fix up for the missed
-                * interrupt. Note, the interrupt may go off before the
-                * timer has re-loaded from wrapping.
-                */
-
-               tval =  __raw_readl(S3C2410_TCNTO(4));
-               tdone = timer_startval - tval;
-
-               if (tval != 0)
-                       tdone += timer_startval;
-       }
-
-       return timer_ticks_to_usec(tdone) * 1000;
-}
-
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t
-s3c2410_timer_interrupt(int irq, void *dev_id)
-{
-       timer_tick();
-       return IRQ_HANDLED;
-}
-
-static struct irqaction s3c2410_timer_irq = {
-       .name           = "S3C2410 Timer Tick",
-       .flags          = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-       .handler        = s3c2410_timer_interrupt,
-};
-
-#define use_tclk1_12() ( \
-       machine_is_bast()       || \
-       machine_is_vr1000()     || \
-       machine_is_anubis()     || \
-       machine_is_osiris())
-
-static struct clk *tin;
-static struct clk *tdiv;
-static struct clk *timerclk;
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- *
- * Currently we only use timer4, as it is the only timer which has no
- * other function that can be exploited externally
- */
-static void s3c2410_timer_setup (void)
-{
-       unsigned long tcon;
-       unsigned long tcnt;
-       unsigned long tcfg1;
-       unsigned long tcfg0;
-
-       tcnt = TICK_MAX;  /* default value for tcnt */
-
-       /* configure the system for whichever machine is in use */
-
-       if (use_tclk1_12()) {
-               /* timer is at 12MHz, scaler is 1 */
-               timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
-               tcnt = 12000000 / HZ;
-
-               tcfg1 = __raw_readl(S3C2410_TCFG1);
-               tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
-               tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
-               __raw_writel(tcfg1, S3C2410_TCFG1);
-       } else {
-               unsigned long pclk;
-               struct clk *tscaler;
-
-               /* for the h1940 (and others), we use the pclk from the core
-                * to generate the timer values. since values around 50 to
-                * 70MHz are not values we can directly generate the timer
-                * value from, we need to pre-scale and divide before using it.
-                *
-                * for instance, using 50.7MHz and dividing by 6 gives 8.45MHz
-                * (8.45 ticks per usec)
-                */
-
-               pclk = clk_get_rate(timerclk);
-
-               /* configure clock tick */
-
-               timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
-
-               tscaler = clk_get_parent(tdiv);
-
-               clk_set_rate(tscaler, pclk / 3);
-               clk_set_rate(tdiv, pclk / 6);
-               clk_set_parent(tin, tdiv);
-
-               tcnt = clk_get_rate(tin) / HZ;
-       }
-
-       tcon = __raw_readl(S3C2410_TCON);
-       tcfg0 = __raw_readl(S3C2410_TCFG0);
-       tcfg1 = __raw_readl(S3C2410_TCFG1);
-
-       /* timers reload after counting zero, so reduce the count by 1 */
-
-       tcnt--;
-
-       printk(KERN_DEBUG "timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n",
-              tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks);
-
-       /* check to see if timer is within 16bit range... */
-       if (tcnt > TICK_MAX) {
-               panic("setup_timer: HZ is too small, cannot configure timer!");
-               return;
-       }
-
-       __raw_writel(tcfg1, S3C2410_TCFG1);
-       __raw_writel(tcfg0, S3C2410_TCFG0);
-
-       timer_startval = tcnt;
-       __raw_writel(tcnt, S3C2410_TCNTB(4));
-
-       /* ensure timer is stopped... */
-
-       tcon &= ~(7<<20);
-       tcon |= S3C2410_TCON_T4RELOAD;
-       tcon |= S3C2410_TCON_T4MANUALUPD;
-
-       __raw_writel(tcon, S3C2410_TCON);
-       __raw_writel(tcnt, S3C2410_TCNTB(4));
-       __raw_writel(tcnt, S3C2410_TCMPB(4));
-
-       /* start the timer running */
-       tcon |= S3C2410_TCON_T4START;
-       tcon &= ~S3C2410_TCON_T4MANUALUPD;
-       __raw_writel(tcon, S3C2410_TCON);
-}
-
-static void __init s3c2410_timer_resources(void)
-{
-       struct platform_device tmpdev;
-
-       tmpdev.dev.bus = &platform_bus_type;
-       tmpdev.id = 4;
-
-       timerclk = clk_get(NULL, "timers");
-       if (IS_ERR(timerclk))
-               panic("failed to get clock for system timer");
-
-       clk_enable(timerclk);
-
-       if (!use_tclk1_12()) {
-               tmpdev.id = 4;
-               tmpdev.dev.init_name = "s3c24xx-pwm.4";
-               tin = clk_get(&tmpdev.dev, "pwm-tin");
-               if (IS_ERR(tin))
-                       panic("failed to get pwm-tin clock for system timer");
-
-               tdiv = clk_get(&tmpdev.dev, "pwm-tdiv");
-               if (IS_ERR(tdiv))
-                       panic("failed to get pwm-tdiv clock for system timer");
-       }
-
-       clk_enable(tin);
-}
-
-static struct syscore_ops s3c24xx_syscore_ops = {
-       .resume         = s3c2410_timer_setup,
-};
-
-void __init s3c24xx_timer_init(void)
-{
-       arch_gettimeoffset = s3c2410_gettimeoffset;
-
-       s3c2410_timer_resources();
-       s3c2410_timer_setup();
-       setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
-       register_syscore_ops(&s3c24xx_syscore_ops);
-}
index 739d016eb273faf8a22859856767901ce7e8beef..8a08c31b5e20a950052901f6549dccc09f1d871a 100644 (file)
@@ -10,7 +10,7 @@ choice
 
 config ARCH_SPEAR13XX
        bool "ST SPEAr13xx with Device Tree"
-       select ARCH_HAVE_CPUFREQ
+       select ARCH_HAS_CPUFREQ
        select ARM_GIC
        select CPU_V7
        select GPIO_SPEAR_SPICS
index fd70a68387ebe5d3baeec3b18adf93f5523e4661..9b6d19f74078e0a2118e6fbd1c517e5f4f82203c 100644 (file)
@@ -9,7 +9,6 @@ config ARM64
        select CLONE_BACKWARDS
        select COMMON_CLK
        select GENERIC_CLOCKEVENTS
-       select GENERIC_HARDIRQS_NO_DEPRECATED
        select GENERIC_IOMAP
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
index 51493430f142d8c1cce428826bb8371d98250916..1a6bfe954d4926de3a8dcee10fdbe0b0698279b3 100644 (file)
@@ -6,17 +6,6 @@ config FRAME_POINTER
        bool
        default y
 
-config DEBUG_ERRORS
-       bool "Verbose kernel error messages"
-       depends on DEBUG_KERNEL
-       help
-         This option controls verbose debugging information which can be
-         printed when the kernel detects an internal error. This debugging
-         information is useful to kernel hackers when tracking down problems,
-         but mostly meaningless to other people. It's safe to say Y unless
-         you are concerned with the code size or don't want to see these
-         messages.
-
 config DEBUG_STACK_USAGE
        bool "Enable stack utilization instrumentation"
        depends on DEBUG_KERNEL
index 9212c7880da742e54e0bebbe3709ef941aa6282d..09bef29f3a09aa02a9441df34773670649cd19c2 100644 (file)
@@ -82,4 +82,3 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_INFO=y
 # CONFIG_FTRACE is not set
 CONFIG_ATOMIC64_SELFTEST=y
-CONFIG_DEBUG_ERRORS=y
index bde960720892a694bda151a3288c9ecd30c8954d..42e04c87742837e1e204492a3a675dfae29fea4f 100644 (file)
@@ -22,7 +22,7 @@ struct ucontext {
        stack_t           uc_stack;
        sigset_t          uc_sigmask;
        /* glibc uses a 1024-bit sigset_t */
-       __u8              __unused[(1024 - sizeof(sigset_t)) / 8];
+       __u8              __unused[1024 / 8 - sizeof(sigset_t)];
        /* last for future expansion */
        struct sigcontext uc_mcontext;
 };
index cef3925eaf60d3367c610df3db9769d87dfe918d..aa3e948f78857bb1e64278c79e57916abbb2e5a4 100644 (file)
@@ -40,7 +40,9 @@ EXPORT_SYMBOL(__copy_to_user);
 EXPORT_SYMBOL(__clear_user);
 
        /* bitops */
+#ifdef CONFIG_SMP
 EXPORT_SYMBOL(__atomic_hash);
+#endif
 
        /* physical memory */
 EXPORT_SYMBOL(memstart_addr);
index 7f4f3673f2bc0e1ad4f1d0dd5f978cbb1b7f4255..e393174fe859721e7f6538bc377577cb69bb68aa 100644 (file)
@@ -549,7 +549,6 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
                          sigset_t *set, struct pt_regs *regs)
 {
        struct compat_rt_sigframe __user *frame;
-       compat_stack_t stack;
        int err = 0;
 
        frame = compat_get_sigframe(ka, regs, sizeof(*frame));
index 224b44ab534ee4682ffb004e50c3d92b86a39a85..70b8cd4021c46cb800cbf76bd21a001e2e73e86c 100644 (file)
@@ -261,7 +261,7 @@ static void __init create_mapping(phys_addr_t phys, unsigned long virt,
 void __iomem * __init early_io_map(phys_addr_t phys, unsigned long virt)
 {
        unsigned long size, mask;
-       bool page64k = IS_ENABLED(ARM64_64K_PAGES);
+       bool page64k = IS_ENABLED(CONFIG_ARM64_64K_PAGES);
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
index 9b89257b2cfdc348746e0145ea428afdfc97c273..c1a868d398bd284f6c7552d31279e24215792f51 100644 (file)
@@ -7,7 +7,7 @@ config AVR32
        select HAVE_OPROFILE
        select HAVE_KPROBES
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select GENERIC_IRQ_PROBE
        select GENERIC_ATOMIC64
        select HARDIRQS_SW_RESEND
index b323d8d3185b35b91a21da1857bcd340d935449c..7c2f6685bf434d06afa68bfc4f2f86b34db3d4c8 100644 (file)
@@ -1453,7 +1453,7 @@ static struct resource atmel_lcdfb0_resource[] = {
        },
 };
 DEFINE_DEV_DATA(atmel_lcdfb, 0);
-DEV_CLK(hck1, atmel_lcdfb0, hsb, 7);
+DEV_CLK(hclk, atmel_lcdfb0, hsb, 7);
 static struct clk atmel_lcdfb0_pixclk = {
        .name           = "lcdc_clk",
        .dev            = &atmel_lcdfb0_device.dev,
@@ -1530,6 +1530,8 @@ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data,
        memcpy(info, data, sizeof(struct atmel_lcdfb_info));
        info->default_monspecs = monspecs;
 
+       pdev->name = "at32ap-lcdfb";
+
        platform_device_register(pdev);
        return pdev;
 
@@ -2246,7 +2248,7 @@ static __initdata struct clk *init_clocks[] = {
        &atmel_twi0_pclk,
        &atmel_mci0_pclk,
 #if defined(CONFIG_CPU_AT32AP7000) || defined(CONFIG_CPU_AT32AP7002)
-       &atmel_lcdfb0_hck1,
+       &atmel_lcdfb0_hclk,
        &atmel_lcdfb0_pixclk,
 #endif
        &ssc0_pclk,
index 600494c70e96e2d26728cc2967a31053a470f667..c3f2e0bc644aed0b64e86b7a801424d5cb239b9a 100644 (file)
@@ -33,7 +33,7 @@ config BLACKFIN
        select ARCH_HAVE_CUSTOM_GPIO_H
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select HAVE_UID16
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select ARCH_WANT_IPC_PARSE_VERSION
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_ATOMIC64
index bb0ac66cf5336aab4e240e32ad44d6fd8ea10679..06dd026533e3b758b68091bc0a8c754b3084f0da 100644 (file)
@@ -43,7 +43,7 @@ config CRIS
        select GENERIC_ATOMIC64
        select HAVE_GENERIC_HARDIRQS
        select HAVE_UID16
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select ARCH_WANT_IPC_PARSE_VERSION
        select GENERIC_IRQ_SHOW
        select GENERIC_IOMAP
index 12369b194c7b2e98a9fa00b688882809f3000c36..2ce731f9aa4d522abfc7d2fbcfff33483a2b2154 100644 (file)
@@ -6,7 +6,7 @@ config FRV
        select HAVE_PERF_EVENTS
        select HAVE_UID16
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select GENERIC_IRQ_SHOW
        select HAVE_DEBUG_BUGVERBOSE
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
index ae8551eb3736ae201bd2decbf1fc34feb23f9c75..79250de1b12a434f7b0d945cb6b4b42559a9d101 100644 (file)
@@ -5,7 +5,7 @@ config H8300
        select HAVE_GENERIC_HARDIRQS
        select GENERIC_ATOMIC64
        select HAVE_UID16
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select ARCH_WANT_IPC_PARSE_VERSION
        select GENERIC_IRQ_SHOW
        select GENERIC_CPU_DEVICES
index 33f3fdc0b214e93350b95d8ec8fcc935df2b56d9..9a02f71c6b1f7cb5e8339e55f77bb82ad9b8d8d3 100644 (file)
@@ -26,7 +26,7 @@ config IA64
        select HAVE_MEMBLOCK
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_VIRT_CPU_ACCOUNTING
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select ARCH_DISCARD_MEMBLOCK
        select GENERIC_IRQ_PROBE
        select GENERIC_PENDING_IRQ if SMP
index e34f565f595ae2d54613309af8013b2e735e9881..6f7dc8b7b35ccc8ba435caa08ed1a8ab8e7863a5 100644 (file)
@@ -291,7 +291,6 @@ cpu_idle (void)
                }
 
                if (!need_resched()) {
-                       void (*idle)(void);
 #ifdef CONFIG_SMP
                        min_xtp();
 #endif
@@ -299,9 +298,7 @@ cpu_idle (void)
                        if (mark_idle)
                                (*mark_idle)(1);
 
-                       if (!idle)
-                               idle = default_idle;
-                       (*idle)();
+                       default_idle();
                        if (mark_idle)
                                (*mark_idle)(0);
 #ifdef CONFIG_SMP
index 92623818a1fe0ecb6147ceed0ebeb900a79df49e..bcd17b20657128ef42c2f68f0dd07880467f1c2c 100644 (file)
@@ -10,7 +10,7 @@ config M32R
        select ARCH_WANT_IPC_PARSE_VERSION
        select HAVE_DEBUG_BUGVERBOSE
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
        select GENERIC_ATOMIC64
index da4518f82d6d31d71609d7a670924cbe79c88c2a..98470fe483b67861b952f7c35bb946111016c9db 100644 (file)
@@ -63,10 +63,10 @@ struct stat64 {
        long long       st_size;
        unsigned long   st_blksize;
 
-#if defined(__BIG_ENDIAN)
+#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __BIG_ENDIAN : defined(__BIG_ENDIAN)
        unsigned long   __pad4;         /* future possible st_blocks high bits */
        unsigned long   st_blocks;      /* Number 512-byte blocks allocated. */
-#elif defined(__LITTLE_ENDIAN)
+#elif defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
        unsigned long   st_blocks;      /* Number 512-byte blocks allocated. */
        unsigned long   __pad4;         /* future possible st_blocks high bits */
 #else
index 0e708c78e01c6f82cdc87af1c9cd60eef285173e..6de813370b8c7d01e8b98d78634baef15da6fe3b 100644 (file)
@@ -8,7 +8,7 @@ config M68K
        select GENERIC_IRQ_SHOW
        select GENERIC_ATOMIC64
        select HAVE_UID16
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select ARCH_HAVE_NMI_SAFE_CMPXCHG if RMW_INSNS
        select GENERIC_CPU_DEVICES
        select GENERIC_STRNCPY_FROM_USER if MMU
index 7cdf6b010381f8ae31332012c18d93345232514a..7240584d343974847fbaab832bcf50388d8d2ba3 100644 (file)
@@ -310,7 +310,6 @@ config COBRA5282
 config SOM5282EM
        bool "EMAC.Inc SOM5282EM board support"
        depends on M528x
-       select EMAC_INC
        help
          Support for the EMAC.Inc SOM5282EM module.
 
index a337e56d09bf9118eea7004ee9ba21921b02faca..4ebf098b8a1fd58c9a222d864b9f4cea6f6c2171 100644 (file)
 /*
  * Here go the bitmasks themselves
  */
-#define IMR_MSPIM      (1 << SPIM _IRQ_NUM)    /* Mask SPI Master interrupt */
+#define IMR_MSPIM      (1 << SPIM_IRQ_NUM)     /* Mask SPI Master interrupt */
 #define        IMR_MTMR2       (1 << TMR2_IRQ_NUM)     /* Mask Timer 2 interrupt */
 #define IMR_MUART      (1 << UART_IRQ_NUM)     /* Mask UART interrupt */       
 #define        IMR_MWDT        (1 << WDT_IRQ_NUM)      /* Mask Watchdog Timer interrupt */
 #define IWR_ADDR       0xfffff308
 #define IWR            LONG_REF(IWR_ADDR)
 
-#define IWR_SPIM       (1 << SPIM _IRQ_NUM)    /* SPI Master interrupt */
+#define IWR_SPIM       (1 << SPIM_IRQ_NUM)     /* SPI Master interrupt */
 #define        IWR_TMR2        (1 << TMR2_IRQ_NUM)     /* Timer 2 interrupt */
 #define IWR_UART       (1 << UART_IRQ_NUM)     /* UART interrupt */    
 #define        IWR_WDT         (1 << WDT_IRQ_NUM)      /* Watchdog Timer interrupt */
 #define ISR_ADDR       0xfffff30c
 #define ISR            LONG_REF(ISR_ADDR)
 
-#define ISR_SPIM       (1 << SPIM _IRQ_NUM)    /* SPI Master interrupt */
+#define ISR_SPIM       (1 << SPIM_IRQ_NUM)     /* SPI Master interrupt */
 #define        ISR_TMR2        (1 << TMR2_IRQ_NUM)     /* Timer 2 interrupt */
 #define ISR_UART       (1 << UART_IRQ_NUM)     /* UART interrupt */    
 #define        ISR_WDT         (1 << WDT_IRQ_NUM)      /* Watchdog Timer interrupt */
 #define IPR_ADDR       0xfffff310
 #define IPR            LONG_REF(IPR_ADDR)
 
-#define IPR_SPIM       (1 << SPIM _IRQ_NUM)    /* SPI Master interrupt */
+#define IPR_SPIM       (1 << SPIM_IRQ_NUM)     /* SPI Master interrupt */
 #define        IPR_TMR2        (1 << TMR2_IRQ_NUM)     /* Timer 2 interrupt */
 #define IPR_UART       (1 << UART_IRQ_NUM)     /* UART interrupt */    
 #define        IPR_WDT         (1 << WDT_IRQ_NUM)      /* Watchdog Timer interrupt */
 
 /* 'EZ328-compatible definitions */
 #define TCN_ADDR       TCN1_ADDR
-#define TCN            TCN
+#define TCN            TCN1
 
 /*
  * Timer Unit 1 and 2 Status Registers
index 71fb29938dba260b6e5895c3d7eb5f10f2afbb16..911ba472e6c4abbd83dac862a561d98eb22526aa 100644 (file)
@@ -57,6 +57,9 @@ void (*mach_reset)(void);
 void (*mach_halt)(void);
 void (*mach_power_off)(void);
 
+#ifdef CONFIG_M68000
+#define CPU_NAME       "MC68000"
+#endif
 #ifdef CONFIG_M68328
 #define CPU_NAME       "MC68328"
 #endif
index afd8106fd83b10c2b1d51b956b178effd9a6b096..519aad8fa812ca6ac7ce07f82abb06ae080139bf 100644 (file)
@@ -188,7 +188,7 @@ void __init mem_init(void)
                }
        }
 
-#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
+#if defined(CONFIG_MMU) && !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
        /* insert pointer tables allocated so far into the tablelist */
        init_pointer_table((unsigned long)kernel_pg_dir);
        for (i = 0; i < PTRS_PER_PGD; i++) {
index 83b7dad7a84e7a1928d105fa6b08acfe3bc8c546..b03a9d271837a8efa46245eb7dc90b7a9a322b12 100644 (file)
@@ -69,7 +69,7 @@ static void __init m528x_uarts_init(void)
        u8 port;
 
        /* make sure PUAPAR is set for UART0 and UART1 */
-       port = readb(MCF5282_GPIO_PUAPAR);
+       port = readb(MCFGPIO_PUAPAR);
        port |= 0x03 | (0x03 << 2);
        writeb(port, MCFGPIO_PUAPAR);
 }
index 7843d11156e60a36d20a5f499b2ff6623e8aa275..1323fa2530eb7c144abe5da9ab1318e410d1c643 100644 (file)
@@ -19,7 +19,7 @@ config MICROBLAZE
        select HAVE_DEBUG_KMEMLEAK
        select IRQ_DOMAIN
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
        select GENERIC_PCI_IOMAP
index ae9c716c46bbf5d93849f5ad9dcb5e3c9a47fd88..51244bf972718a54876e7ba2ab78ae1790c98e59 100644 (file)
@@ -18,7 +18,7 @@ config MIPS
        select HAVE_KRETPROBES
        select HAVE_DEBUG_KMEMLEAK
        select ARCH_BINFMT_ELF_RANDOMIZE_PIE
-       select HAVE_ARCH_TRANSPARENT_HUGEPAGE
+       select HAVE_ARCH_TRANSPARENT_HUGEPAGE if CPU_SUPPORTS_HUGEPAGES && 64BIT
        select RTC_LIB if !MACH_LOONGSON
        select GENERIC_ATOMIC64 if !64BIT
        select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
@@ -38,7 +38,7 @@ config MIPS
        select GENERIC_CLOCKEVENTS
        select GENERIC_CMOS_UPDATE
        select HAVE_MOD_ARCH_SPECIFIC
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select MODULES_USE_ELF_REL if MODULES
        select MODULES_USE_ELF_RELA if MODULES && 64BIT
        select CLONE_BACKWARDS
@@ -657,7 +657,7 @@ config SNI_RM
        bool "SNI RM200/300/400"
        select FW_ARC if CPU_LITTLE_ENDIAN
        select FW_ARC32 if CPU_LITTLE_ENDIAN
-       select SNIPROM if CPU_BIG_ENDIAN
+       select FW_SNIPROM if CPU_BIG_ENDIAN
        select ARCH_MAY_HAVE_PC_FDC
        select BOOT_ELF32
        select CEVT_R4K
@@ -1144,7 +1144,7 @@ config DEFAULT_SGI_PARTITION
 config FW_ARC32
        bool
 
-config SNIPROM
+config FW_SNIPROM
        bool
 
 config BOOT_ELF32
@@ -1493,7 +1493,6 @@ config CPU_XLP
        select CPU_SUPPORTS_32BIT_KERNEL
        select CPU_SUPPORTS_64BIT_KERNEL
        select CPU_SUPPORTS_HIGHMEM
-       select CPU_HAS_LLSC
        select WEAK_ORDERING
        select WEAK_REORDERING_BEYOND_LLSC
        select CPU_HAS_PREFETCH
index ed1949c295087bf81ef951539c08400507e9d603..9aa7d44898ed11cff9c70112e0e142923e27f2f4 100644 (file)
@@ -745,10 +745,7 @@ void __init board_prom_init(void)
                strcpy(cfe_version, "unknown");
        printk(KERN_INFO PFX "CFE version: %s\n", cfe_version);
 
-       if (bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET)) {
-               printk(KERN_ERR PFX "invalid nvram checksum\n");
-               return;
-       }
+       bcm63xx_nvram_init(boot_addr + BCM963XX_NVRAM_OFFSET);
 
        board_name = bcm63xx_nvram_get_name();
        /* find board by name */
index 620611680839e42d1aa16741aca00526f352e39f..a4b8864f93072d8e305d6a7bcca4953b2cbcc4a5 100644 (file)
@@ -38,7 +38,7 @@ struct bcm963xx_nvram {
 static struct bcm963xx_nvram nvram;
 static int mac_addr_used;
 
-int __init bcm63xx_nvram_init(void *addr)
+void __init bcm63xx_nvram_init(void *addr)
 {
        unsigned int check_len;
        u32 crc, expected_crc;
@@ -60,9 +60,8 @@ int __init bcm63xx_nvram_init(void *addr)
        crc = crc32_le(~0, (u8 *)&nvram, check_len);
 
        if (crc != expected_crc)
-               return -EINVAL;
-
-       return 0;
+               pr_warn("nvram checksum failed, contents may be invalid (expected %08x, got %08x)\n",
+                       expected_crc, crc);
 }
 
 u8 *bcm63xx_nvram_get_name(void)
index 314231be788cd7365c55e3501187600296932c38..35e18e98beb96b04151999aac8bf037129efc324 100644 (file)
@@ -157,4 +157,4 @@ int __init bcm63xx_register_devices(void)
        return board_register_devices();
 }
 
-device_initcall(bcm63xx_register_devices);
+arch_initcall(bcm63xx_register_devices);
index c594a3d4f743be31d2933e5ed5589f423d8a3743..b0baa299f899b3c2322c0a4346cc4947dcfc2457 100644 (file)
@@ -174,7 +174,10 @@ static int octeon_kexec_prepare(struct kimage *image)
 
 static void octeon_generic_shutdown(void)
 {
-       int cpu, i;
+       int i;
+#ifdef CONFIG_SMP
+       int cpu;
+#endif
        struct cvmx_bootmem_desc *bootmem_desc;
        void *named_block_array_ptr;
 
index 62d6a3b4d3b7b512550e558001934f3e55a7917f..4e0b6bc1165edcbae2f44663390daa2c63c017d9 100644 (file)
@@ -9,10 +9,8 @@
  *
  * Initialized the local nvram copy from the target address and checks
  * its checksum.
- *
- * Returns 0 on success.
  */
-int __init bcm63xx_nvram_init(void *nvram);
+void bcm63xx_nvram_init(void *nvram);
 
 /**
  * bcm63xx_nvram_get_name() - returns the board name according to nvram
index d9c82841903775734d6a462de251deaba1058715..193c0912d38e651519b8fb8b7bbc9fa31d7893e8 100644 (file)
 /* #define cpu_has_prefetch    ? */
 #define cpu_has_mcheck         1
 /* #define cpu_has_ejtag       ? */
-#ifdef CONFIG_CPU_HAS_LLSC
 #define cpu_has_llsc           1
-#else
-#define cpu_has_llsc           0
-#endif
 /* #define cpu_has_vtag_icache ? */
 /* #define cpu_has_dc_aliases  ? */
 /* #define cpu_has_ic_fills_f_dc ? */
index 12b70c25906a0d3a32d095b52d3766bc2285e115..0da44d422f5b0242380bfc0dde4973b547c1900e 100644 (file)
@@ -1166,7 +1166,10 @@ do {                                                                     \
        unsigned int __dspctl;                                          \
                                                                        \
        __asm__ __volatile__(                                           \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
        "       rddsp   %0, %x1                                 \n"     \
+       "       .set pop                                        \n"     \
        : "=r" (__dspctl)                                               \
        : "i" (mask));                                                  \
        __dspctl;                                                       \
@@ -1175,30 +1178,198 @@ do {                                                                   \
 #define wrdsp(val, mask)                                               \
 do {                                                                   \
        __asm__ __volatile__(                                           \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
        "       wrdsp   %0, %x1                                 \n"     \
+       "       .set pop                                        \n"     \
        :                                                               \
        : "r" (val), "i" (mask));                                       \
 } while (0)
 
-#define mflo0() ({ long mflo0; __asm__("mflo %0, $ac0" : "=r" (mflo0)); mflo0;})
-#define mflo1() ({ long mflo1; __asm__("mflo %0, $ac1" : "=r" (mflo1)); mflo1;})
-#define mflo2() ({ long mflo2; __asm__("mflo %0, $ac2" : "=r" (mflo2)); mflo2;})
-#define mflo3() ({ long mflo3; __asm__("mflo %0, $ac3" : "=r" (mflo3)); mflo3;})
-
-#define mfhi0() ({ long mfhi0; __asm__("mfhi %0, $ac0" : "=r" (mfhi0)); mfhi0;})
-#define mfhi1() ({ long mfhi1; __asm__("mfhi %0, $ac1" : "=r" (mfhi1)); mfhi1;})
-#define mfhi2() ({ long mfhi2; __asm__("mfhi %0, $ac2" : "=r" (mfhi2)); mfhi2;})
-#define mfhi3() ({ long mfhi3; __asm__("mfhi %0, $ac3" : "=r" (mfhi3)); mfhi3;})
-
-#define mtlo0(x) __asm__("mtlo %0, $ac0" ::"r" (x))
-#define mtlo1(x) __asm__("mtlo %0, $ac1" ::"r" (x))
-#define mtlo2(x) __asm__("mtlo %0, $ac2" ::"r" (x))
-#define mtlo3(x) __asm__("mtlo %0, $ac3" ::"r" (x))
-
-#define mthi0(x) __asm__("mthi %0, $ac0" ::"r" (x))
-#define mthi1(x) __asm__("mthi %0, $ac1" ::"r" (x))
-#define mthi2(x) __asm__("mthi %0, $ac2" ::"r" (x))
-#define mthi3(x) __asm__("mthi %0, $ac3" ::"r" (x))
+#define mflo0()                                                                \
+({                                                                     \
+       long mflo0;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mflo %0, $ac0                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mflo0));                                                \
+       mflo0;                                                          \
+})
+
+#define mflo1()                                                                \
+({                                                                     \
+       long mflo1;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mflo %0, $ac1                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mflo1));                                                \
+       mflo1;                                                          \
+})
+
+#define mflo2()                                                                \
+({                                                                     \
+       long mflo2;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mflo %0, $ac2                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mflo2));                                                \
+       mflo2;                                                          \
+})
+
+#define mflo3()                                                                \
+({                                                                     \
+       long mflo3;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mflo %0, $ac3                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mflo3));                                                \
+       mflo3;                                                          \
+})
+
+#define mfhi0()                                                                \
+({                                                                     \
+       long mfhi0;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mfhi %0, $ac0                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mfhi0));                                                \
+       mfhi0;                                                          \
+})
+
+#define mfhi1()                                                                \
+({                                                                     \
+       long mfhi1;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mfhi %0, $ac1                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mfhi1));                                                \
+       mfhi1;                                                          \
+})
+
+#define mfhi2()                                                                \
+({                                                                     \
+       long mfhi2;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mfhi %0, $ac2                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mfhi2));                                                \
+       mfhi2;                                                          \
+})
+
+#define mfhi3()                                                                \
+({                                                                     \
+       long mfhi3;                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mfhi %0, $ac3                                   \n"     \
+       "       .set pop                                        \n"     \
+       : "=r" (mfhi3));                                                \
+       mfhi3;                                                          \
+})
+
+
+#define mtlo0(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mtlo %0, $ac0                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
+
+#define mtlo1(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mtlo %0, $ac1                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
+
+#define mtlo2(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mtlo %0, $ac2                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
+
+#define mtlo3(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mtlo %0, $ac3                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
+
+#define mthi0(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mthi %0, $ac0                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
+
+#define mthi1(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mthi %0, $ac1                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
+
+#define mthi2(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mthi %0, $ac2                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
+
+#define mthi3(x)                                                       \
+({                                                                     \
+       __asm__(                                                        \
+       "       .set push                                       \n"     \
+       "       .set dsp                                        \n"     \
+       "       mthi %0, $ac3                                   \n"     \
+       "       .set pop                                        \n"     \
+       :                                                               \
+       : "r" (x));                                                     \
+})
 
 #else
 
index 197f6367c201c122171b7e81cbcebc328a683a7f..8efe5a9e2c3e68a1ab5cffe718fe58bbd815abb4 100644 (file)
@@ -21,6 +21,6 @@
 #include <asm/sigcontext.h>
 #include <asm/siginfo.h>
 
-#define __ARCH_HAS_ODD_SIGACTION
+#define __ARCH_HAS_IRIX_SIGACTION
 
 #endif /* _ASM_SIGNAL_H */
index d6b18b4d0f3a99c7c96f58a27d77c1fd62777f61..addb9f556b71836de758580005a0a603fc040f64 100644 (file)
@@ -72,6 +72,12 @@ typedef unsigned long old_sigset_t;          /* at least 32 bits */
  *
  * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
  * Unix names RESETHAND and NODEFER respectively.
+ *
+ * SA_RESTORER used to be defined as 0x04000000 but only the O32 ABI ever
+ * supported its use and no libc was using it, so the entire sa-restorer
+ * functionality was removed with lmo commit 39bffc12c3580ab for 2.5.48
+ * retaining only the SA_RESTORER definition as a reminder to avoid
+ * accidental reuse of the mask bit.
  */
 #define SA_ONSTACK     0x08000000
 #define SA_RESETHAND   0x80000000
@@ -84,8 +90,6 @@ typedef unsigned long old_sigset_t;           /* at least 32 bits */
 #define SA_NOMASK      SA_NODEFER
 #define SA_ONESHOT     SA_RESETHAND
 
-#define SA_RESTORER    0x04000000      /* Only for o32 */
-
 #define MINSIGSTKSZ    2048
 #define SIGSTKSZ       8192
 
index f81d98f6184c2f89ff7f69530247a2b6181245fd..de75fb50562bfec163b876e312e9b6a0d72a7c23 100644 (file)
@@ -100,29 +100,16 @@ obj-$(CONFIG_HW_PERF_EVENTS)      += perf_event_mipsxx.o
 obj-$(CONFIG_JUMP_LABEL)       += jump_label.o
 
 #
-# DSP ASE supported for MIPS32 or MIPS64 Release 2 cores only. It is safe
-# to enable DSP assembler support here even if the MIPS Release 2 CPU we
-# are targetting does not support DSP because all code-paths making use of
-# it properly check that the running CPU *actually does* support these
-# instructions.
+# DSP ASE supported for MIPS32 or MIPS64 Release 2 cores only. It is not
+# safe to unconditionnaly use the assembler -mdsp / -mdspr2 switches
+# here because the compiler may use DSP ASE instructions (such as lwx) in
+# code paths where we cannot check that the CPU we are running on supports it.
+# Proper abstraction using HAVE_AS_DSP and macros is done in
+# arch/mips/include/asm/mipsregs.h.
 #
 ifeq ($(CONFIG_CPU_MIPSR2), y)
 CFLAGS_DSP                     = -DHAVE_AS_DSP
 
-#
-# Check if assembler supports DSP ASE
-#
-ifeq ($(call cc-option-yn,-mdsp), y)
-CFLAGS_DSP                     += -mdsp
-endif
-
-#
-# Check if assembler supports DSP ASE Rev2
-#
-ifeq ($(call cc-option-yn,-mdspr2), y)
-CFLAGS_DSP                     += -mdspr2
-endif
-
 CFLAGS_signal.o                        = $(CFLAGS_DSP)
 CFLAGS_signal32.o              = $(CFLAGS_DSP)
 CFLAGS_process.o               = $(CFLAGS_DSP)
index 6bfccc227a95f850d31c64ce1b6e6c863f62ba77..5fe66a0c32245366bc56079eca0a160a7b9bc0cb 100644 (file)
@@ -580,6 +580,9 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                c->tlbsize = 48;
                break;
        case PRID_IMP_VR41XX:
+               set_isa(c, MIPS_CPU_ISA_III);
+               c->options = R4K_OPTS;
+               c->tlbsize = 32;
                switch (c->processor_id & 0xf0) {
                case PRID_REV_VR4111:
                        c->cputype = CPU_VR4111;
@@ -604,6 +607,7 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                                __cpu_name[cpu] = "NEC VR4131";
                        } else {
                                c->cputype = CPU_VR4133;
+                               c->options |= MIPS_CPU_LLSC;
                                __cpu_name[cpu] = "NEC VR4133";
                        }
                        break;
@@ -613,9 +617,6 @@ static inline void cpu_probe_legacy(struct cpuinfo_mips *c, unsigned int cpu)
                        __cpu_name[cpu] = "NEC Vr41xx";
                        break;
                }
-               set_isa(c, MIPS_CPU_ISA_III);
-               c->options = R4K_OPTS;
-               c->tlbsize = 32;
                break;
        case PRID_IMP_R4300:
                c->cputype = CPU_R4300;
@@ -1226,10 +1227,8 @@ __cpuinit void cpu_probe(void)
        if (c->options & MIPS_CPU_FPU) {
                c->fpu_id = cpu_get_fpu_id();
 
-               if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
-                   c->isa_level == MIPS_CPU_ISA_M32R2 ||
-                   c->isa_level == MIPS_CPU_ISA_M64R1 ||
-                   c->isa_level == MIPS_CPU_ISA_M64R2) {
+               if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
+                                   MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) {
                        if (c->fpu_id & MIPS_FPIR_3D)
                                c->ases |= MIPS_ASE_MIPS3D;
                }
index 8eeee1c860c08cd5ea0228e8387668cc2aaa0cc5..db9655f08892d73738664e45a48e088f941b263a 100644 (file)
@@ -171,7 +171,7 @@ SYSCALL_DEFINE6(32_ipc, u32, call, long, first, long, second, long, third,
                err = compat_sys_shmctl(first, second, compat_ptr(ptr));
                break;
        default:
-               err = -EINVAL;
+               err = -ENOSYS;
                break;
        }
 
index 1658676733576e74867347f0f7d122df0c5a023e..33d067148e61ba6d1526529ef735b24f2c3017c3 100644 (file)
        PTR_L   a5, PT_R9(sp)
        PTR_L   a6, PT_R10(sp)
        PTR_L   a7, PT_R11(sp)
-#else
-       PTR_ADDIU       sp, PT_SIZE
 #endif
-.endm
+       PTR_ADDIU       sp, PT_SIZE
+       .endm
 
        .macro RETURN_BACK
        jr ra
@@ -68,7 +67,11 @@ NESTED(ftrace_caller, PT_SIZE, ra)
        .globl _mcount
 _mcount:
        b       ftrace_stub
-       addiu sp,sp,8
+#ifdef CONFIG_32BIT
+        addiu sp,sp,8
+#else
+        nop
+#endif
 
        /* When tracing is activated, it calls ftrace_caller+8 (aka here) */
        lw      t1, function_trace_stop
index 135c4aadccbe35d9a49415170dce3d2b9e05a697..7a54f74b7818ad402a70221eb2090dc91f5643f8 100644 (file)
@@ -67,7 +67,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        if (cpu_has_mips_r) {
                seq_printf(m, "isa\t\t\t:");
                if (cpu_has_mips_1)
-                       seq_printf(m, "%s", "mips1");
+                       seq_printf(m, "%s", " mips1");
                if (cpu_has_mips_2)
                        seq_printf(m, "%s", " mips2");
                if (cpu_has_mips_3)
index a200b5bdbb870c0d5b7121503f9c1032f62c956a..c3abb88170fc01a6a4cfeeda10bd7c3f144707ec 100644 (file)
@@ -1571,7 +1571,7 @@ void __cpuinit per_cpu_trap_init(bool is_boot_cpu)
 #ifdef CONFIG_64BIT
        status_set |= ST0_FR|ST0_KX|ST0_SX|ST0_UX;
 #endif
-       if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
+       if (current_cpu_data.isa_level & MIPS_CPU_ISA_IV)
                status_set |= ST0_XX;
        if (cpu_has_dsp)
                status_set |= ST0_MX;
index 81f1dcfdcab8c212ebbac6c5159291dc8b8e1162..a64daee740ee0414ee6a8db474b32893ae51ab1d 100644 (file)
@@ -90,12 +90,12 @@ int __mips_test_and_set_bit(unsigned long nr,
        unsigned bit = nr & SZLONG_MASK;
        unsigned long mask;
        unsigned long flags;
-       unsigned long res;
+       int res;
 
        a += nr >> SZLONG_LOG;
        mask = 1UL << bit;
        raw_local_irq_save(flags);
-       res = (mask & *a);
+       res = (mask & *a) != 0;
        *a |= mask;
        raw_local_irq_restore(flags);
        return res;
@@ -116,12 +116,12 @@ int __mips_test_and_set_bit_lock(unsigned long nr,
        unsigned bit = nr & SZLONG_MASK;
        unsigned long mask;
        unsigned long flags;
-       unsigned long res;
+       int res;
 
        a += nr >> SZLONG_LOG;
        mask = 1UL << bit;
        raw_local_irq_save(flags);
-       res = (mask & *a);
+       res = (mask & *a) != 0;
        *a |= mask;
        raw_local_irq_restore(flags);
        return res;
@@ -141,12 +141,12 @@ int __mips_test_and_clear_bit(unsigned long nr, volatile unsigned long *addr)
        unsigned bit = nr & SZLONG_MASK;
        unsigned long mask;
        unsigned long flags;
-       unsigned long res;
+       int res;
 
        a += nr >> SZLONG_LOG;
        mask = 1UL << bit;
        raw_local_irq_save(flags);
-       res = (mask & *a);
+       res = (mask & *a) != 0;
        *a &= ~mask;
        raw_local_irq_restore(flags);
        return res;
@@ -166,12 +166,12 @@ int __mips_test_and_change_bit(unsigned long nr, volatile unsigned long *addr)
        unsigned bit = nr & SZLONG_MASK;
        unsigned long mask;
        unsigned long flags;
-       unsigned long res;
+       int res;
 
        a += nr >> SZLONG_LOG;
        mask = 1UL << bit;
        raw_local_irq_save(flags);
-       res = (mask & *a);
+       res = (mask & *a) != 0;
        *a ^= mask;
        raw_local_irq_restore(flags);
        return res;
index 507147aebd417d612633e1104b83fd8bff08cbce..a6adffbb4e5f0a5ccc5ec268c18c718b69c5a8da 100644 (file)
@@ -270,7 +270,7 @@ LEAF(csum_partial)
 #endif
 
        /* odd buffer alignment? */
-#ifdef CPU_MIPSR2
+#ifdef CONFIG_CPU_MIPSR2
        wsbh    v1, sum
        movn    sum, v1, t7
 #else
@@ -670,7 +670,7 @@ EXC(        sb      t0, NBYTES-2(dst), .Ls_exc)
        addu    sum, v1
 #endif
 
-#ifdef CPU_MIPSR2
+#ifdef CONFIG_CPU_MIPSR2
        wsbh    v1, sum
        movn    sum, v1, odd
 #else
index ecca559b8d7b4313431e120b82dc88edf5b7e807..2078915eacb9c9ff740ec2daa1a65274ad1de7a9 100644 (file)
@@ -1247,10 +1247,8 @@ static void __cpuinit setup_scache(void)
                return;
 
        default:
-               if (c->isa_level == MIPS_CPU_ISA_M32R1 ||
-                   c->isa_level == MIPS_CPU_ISA_M32R2 ||
-                   c->isa_level == MIPS_CPU_ISA_M64R1 ||
-                   c->isa_level == MIPS_CPU_ISA_M64R2) {
+               if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
+                                   MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)) {
 #ifdef CONFIG_MIPS_CPU_SCACHE
                        if (mips_sc_init ()) {
                                scache_size = c->scache.ways * c->scache.sets * c->scache.linesz;
index 93d937b4b1ba6fdc01460b2b55e586fbd10dda10..df96da7e939b540f9b1b9c73dae3f73162845d8e 100644 (file)
@@ -98,10 +98,8 @@ static inline int __init mips_sc_probe(void)
        c->scache.flags |= MIPS_CACHE_NOT_PRESENT;
 
        /* Ignore anything but MIPSxx processors */
-       if (c->isa_level != MIPS_CPU_ISA_M32R1 &&
-           c->isa_level != MIPS_CPU_ISA_M32R2 &&
-           c->isa_level != MIPS_CPU_ISA_M64R1 &&
-           c->isa_level != MIPS_CPU_ISA_M64R2)
+       if (!(c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 |
+                             MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)))
                return 0;
 
        /* Does this MIPS32/MIPS64 CPU have a config2 register? */
index 38a80c83fd6743c1a2e025d83b7f02d02c2f6bd5..d1faece21b6a78f4c79e20e3cfbaec448d281fad 100644 (file)
@@ -19,7 +19,7 @@
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/tlbmisc.h>
 
-#ifdef CONFIG_DEBUG_PCI
+#ifdef CONFIG_PCI_DEBUG
 #define DBG(x...) printk(KERN_DEBUG x)
 #else
 #define DBG(x...) do {} while (0)
@@ -162,7 +162,7 @@ static int config_access(unsigned char access_type, struct pci_bus *bus,
        if (status & (1 << 29)) {
                *data = 0xffffffff;
                error = -1;
-               DBG("alchemy-pci: master abort on cfg access %d bus %d dev %d",
+               DBG("alchemy-pci: master abort on cfg access %d bus %d dev %d\n",
                    access_type, bus->number, device);
        } else if ((status >> 28) & 0xf) {
                DBG("alchemy-pci: PCI ERR detected: dev %d, status %lx\n",
index b06c7360b1c6fafd6ba5ea9faba8d7dd0c9abbca..428da175d0734abab132fbbbad57154b05530b1d 100644 (file)
@@ -8,7 +8,7 @@ config MN10300
        select HAVE_ARCH_KGDB
        select GENERIC_ATOMIC64
        select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select GENERIC_CLOCKEVENTS
        select MODULES_USE_ELF_RELA
        select OLD_SIGSUSPEND3
index 014a6482ed4ce3c38c44d4bef68c758f9e684a31..9ab3bf2eca8d2efeef9f0adbadc8b94c356cb857 100644 (file)
@@ -9,10 +9,9 @@ config OPENRISC
        select OF_EARLY_FLATTREE
        select IRQ_DOMAIN
        select HAVE_MEMBLOCK
-       select ARCH_WANT_OPTIONAL_GPIOLIB
+       select ARCH_REQUIRE_GPIOLIB
         select HAVE_ARCH_TRACEHOOK
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_VIRT_TO_BUS
        select GENERIC_IRQ_CHIP
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
index a9ff712a28643e235892c8ec426ed9b596ce77d6..0339181bf3ac3d377db760ef93a7e74933288eee 100644 (file)
@@ -21,7 +21,7 @@ config PARISC
        select GENERIC_STRNCPY_FROM_USER
        select SYSCTL_ARCH_UNALIGN_ALLOW
        select HAVE_MOD_ARCH_SPECIFIC
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select MODULES_USE_ELF_RELA
        select CLONE_BACKWARDS
        select TTY # Needed for pdc_cons.c
index b89d7eb730a25360129d0d4b7f83136e130a227d..ea5bb045983a19070958b003a8408841bce35a7c 100644 (file)
@@ -90,6 +90,7 @@ config GENERIC_GPIO
 config PPC
        bool
        default y
+       select BINFMT_ELF
        select OF
        select OF_EARLY_FLATTREE
        select HAVE_FTRACE_MCOUNT_RECORD
@@ -98,7 +99,7 @@ config PPC
        select HAVE_FUNCTION_GRAPH_TRACER
        select SYSCTL_EXCEPTION_TRACE
        select ARCH_WANT_OPTIONAL_GPIOLIB
-       select HAVE_VIRT_TO_BUS if !PPC64
+       select VIRT_TO_BUS if !PPC64
        select HAVE_IDE
        select HAVE_IOREMAP_PROT
        select HAVE_EFFICIENT_UNALIGNED_ACCESS
index 2fdb47a19efda298b8ddc3749f174be75e1e7a63..b59e06f507ea6c3f3af39688752e20a23096b666 100644 (file)
@@ -343,17 +343,16 @@ extern void slb_set_size(u16 size);
 /*
  * VSID allocation (256MB segment)
  *
- * We first generate a 38-bit "proto-VSID".  For kernel addresses this
- * is equal to the ESID | 1 << 37, for user addresses it is:
- *     (context << USER_ESID_BITS) | (esid & ((1U << USER_ESID_BITS) - 1)
+ * We first generate a 37-bit "proto-VSID". Proto-VSIDs are generated
+ * from mmu context id and effective segment id of the address.
  *
- * This splits the proto-VSID into the below range
- *  0 - (2^(CONTEXT_BITS + USER_ESID_BITS) - 1) : User proto-VSID range
- *  2^(CONTEXT_BITS + USER_ESID_BITS) - 2^(VSID_BITS) : Kernel proto-VSID range
- *
- * We also have CONTEXT_BITS + USER_ESID_BITS = VSID_BITS - 1
- * That is, we assign half of the space to user processes and half
- * to the kernel.
+ * For user processes max context id is limited to ((1ul << 19) - 5)
+ * for kernel space, we use the top 4 context ids to map address as below
+ * NOTE: each context only support 64TB now.
+ * 0x7fffc -  [ 0xc000000000000000 - 0xc0003fffffffffff ]
+ * 0x7fffd -  [ 0xd000000000000000 - 0xd0003fffffffffff ]
+ * 0x7fffe -  [ 0xe000000000000000 - 0xe0003fffffffffff ]
+ * 0x7ffff -  [ 0xf000000000000000 - 0xf0003fffffffffff ]
  *
  * The proto-VSIDs are then scrambled into real VSIDs with the
  * multiplicative hash:
@@ -363,41 +362,49 @@ extern void slb_set_size(u16 size);
  * VSID_MULTIPLIER is prime, so in particular it is
  * co-prime to VSID_MODULUS, making this a 1:1 scrambling function.
  * Because the modulus is 2^n-1 we can compute it efficiently without
- * a divide or extra multiply (see below).
- *
- * This scheme has several advantages over older methods:
- *
- *     - We have VSIDs allocated for every kernel address
- * (i.e. everything above 0xC000000000000000), except the very top
- * segment, which simplifies several things.
+ * a divide or extra multiply (see below). The scramble function gives
+ * robust scattering in the hash table (at least based on some initial
+ * results).
  *
- *     - We allow for USER_ESID_BITS significant bits of ESID and
- * CONTEXT_BITS  bits of context for user addresses.
- *  i.e. 64T (46 bits) of address space for up to half a million contexts.
+ * We also consider VSID 0 special. We use VSID 0 for slb entries mapping
+ * bad address. This enables us to consolidate bad address handling in
+ * hash_page.
  *
- *     - The scramble function gives robust scattering in the hash
- * table (at least based on some initial results).  The previous
- * method was more susceptible to pathological cases giving excessive
- * hash collisions.
+ * We also need to avoid the last segment of the last context, because that
+ * would give a protovsid of 0x1fffffffff. That will result in a VSID 0
+ * because of the modulo operation in vsid scramble. But the vmemmap
+ * (which is what uses region 0xf) will never be close to 64TB in size
+ * (it's 56 bytes per page of system memory).
  */
 
+#define CONTEXT_BITS           19
+#define ESID_BITS              18
+#define ESID_BITS_1T           6
+
+/*
+ * 256MB segment
+ * The proto-VSID space has 2^(CONTEX_BITS + ESID_BITS) - 1 segments
+ * available for user + kernel mapping. The top 4 contexts are used for
+ * kernel mapping. Each segment contains 2^28 bytes. Each
+ * context maps 2^46 bytes (64TB) so we can support 2^19-1 contexts
+ * (19 == 37 + 28 - 46).
+ */
+#define MAX_USER_CONTEXT       ((ASM_CONST(1) << CONTEXT_BITS) - 5)
+
 /*
  * This should be computed such that protovosid * vsid_mulitplier
  * doesn't overflow 64 bits. It should also be co-prime to vsid_modulus
  */
 #define VSID_MULTIPLIER_256M   ASM_CONST(12538073)     /* 24-bit prime */
-#define VSID_BITS_256M         38
+#define VSID_BITS_256M         (CONTEXT_BITS + ESID_BITS)
 #define VSID_MODULUS_256M      ((1UL<<VSID_BITS_256M)-1)
 
 #define VSID_MULTIPLIER_1T     ASM_CONST(12538073)     /* 24-bit prime */
-#define VSID_BITS_1T           26
+#define VSID_BITS_1T           (CONTEXT_BITS + ESID_BITS_1T)
 #define VSID_MODULUS_1T                ((1UL<<VSID_BITS_1T)-1)
 
-#define CONTEXT_BITS           19
-#define USER_ESID_BITS         18
-#define USER_ESID_BITS_1T      6
 
-#define USER_VSID_RANGE        (1UL << (USER_ESID_BITS + SID_SHIFT))
+#define USER_VSID_RANGE        (1UL << (ESID_BITS + SID_SHIFT))
 
 /*
  * This macro generates asm code to compute the VSID scramble
@@ -421,7 +428,8 @@ extern void slb_set_size(u16 size);
        srdi    rx,rt,VSID_BITS_##size;                                 \
        clrldi  rt,rt,(64-VSID_BITS_##size);                            \
        add     rt,rt,rx;               /* add high and low bits */     \
-       /* Now, r3 == VSID (mod 2^36-1), and lies between 0 and         \
+       /* NOTE: explanation based on VSID_BITS_##size = 36             \
+        * Now, r3 == VSID (mod 2^36-1), and lies between 0 and         \
         * 2^36-1+2^28-1.  That in particular means that if r3 >=       \
         * 2^36-1, then r3+1 has the 2^36 bit set.  So, if r3+1 has     \
         * the bit clear, r3 already has the answer we want, if it      \
@@ -513,34 +521,6 @@ typedef struct {
        })
 #endif /* 1 */
 
-/*
- * This is only valid for addresses >= PAGE_OFFSET
- * The proto-VSID space is divided into two class
- * User:   0 to 2^(CONTEXT_BITS + USER_ESID_BITS) -1
- * kernel: 2^(CONTEXT_BITS + USER_ESID_BITS) to 2^(VSID_BITS) - 1
- *
- * With KERNEL_START at 0xc000000000000000, the proto vsid for
- * the kernel ends up with 0xc00000000 (36 bits). With 64TB
- * support we need to have kernel proto-VSID in the
- * [2^37 to 2^38 - 1] range due to the increased USER_ESID_BITS.
- */
-static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
-{
-       unsigned long proto_vsid;
-       /*
-        * We need to make sure proto_vsid for the kernel is
-        * >= 2^(CONTEXT_BITS + USER_ESID_BITS[_1T])
-        */
-       if (ssize == MMU_SEGSIZE_256M) {
-               proto_vsid = ea >> SID_SHIFT;
-               proto_vsid |= (1UL << (CONTEXT_BITS + USER_ESID_BITS));
-               return vsid_scramble(proto_vsid, 256M);
-       }
-       proto_vsid = ea >> SID_SHIFT_1T;
-       proto_vsid |= (1UL << (CONTEXT_BITS + USER_ESID_BITS_1T));
-       return vsid_scramble(proto_vsid, 1T);
-}
-
 /* Returns the segment size indicator for a user address */
 static inline int user_segment_size(unsigned long addr)
 {
@@ -550,17 +530,41 @@ static inline int user_segment_size(unsigned long addr)
        return MMU_SEGSIZE_256M;
 }
 
-/* This is only valid for user addresses (which are below 2^44) */
 static inline unsigned long get_vsid(unsigned long context, unsigned long ea,
                                     int ssize)
 {
+       /*
+        * Bad address. We return VSID 0 for that
+        */
+       if ((ea & ~REGION_MASK) >= PGTABLE_RANGE)
+               return 0;
+
        if (ssize == MMU_SEGSIZE_256M)
-               return vsid_scramble((context << USER_ESID_BITS)
+               return vsid_scramble((context << ESID_BITS)
                                     | (ea >> SID_SHIFT), 256M);
-       return vsid_scramble((context << USER_ESID_BITS_1T)
+       return vsid_scramble((context << ESID_BITS_1T)
                             | (ea >> SID_SHIFT_1T), 1T);
 }
 
+/*
+ * This is only valid for addresses >= PAGE_OFFSET
+ *
+ * For kernel space, we use the top 4 context ids to map address as below
+ * 0x7fffc -  [ 0xc000000000000000 - 0xc0003fffffffffff ]
+ * 0x7fffd -  [ 0xd000000000000000 - 0xd0003fffffffffff ]
+ * 0x7fffe -  [ 0xe000000000000000 - 0xe0003fffffffffff ]
+ * 0x7ffff -  [ 0xf000000000000000 - 0xf0003fffffffffff ]
+ */
+static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
+{
+       unsigned long context;
+
+       /*
+        * kernel take the top 4 context from the available range
+        */
+       context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1;
+       return get_vsid(context, ea, ssize);
+}
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_POWERPC_MMU_HASH64_H_ */
index 75a3d71b895d985e20307bdd90dda88e4449ed9c..19599ef352bc89ddb8039a65cf22419d82c25c9f 100644 (file)
@@ -275,7 +275,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                .cpu_features           = CPU_FTRS_PPC970,
                .cpu_user_features      = COMMON_USER_POWER4 |
                        PPC_FEATURE_HAS_ALTIVEC_COMP,
-               .mmu_features           = MMU_FTR_HPTE_TABLE,
+               .mmu_features           = MMU_FTRS_PPC970,
                .icache_bsize           = 128,
                .dcache_bsize           = 128,
                .num_pmcs               = 8,
index f3eab8594d9f873432deb94c770db354f20ffc76..d44a571e45a79dae9b7976c7e281c93021b2847e 100644 (file)
 #include <asm/code-patching.h>
 #include <asm/machdep.h>
 
+#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
 extern void epapr_ev_idle(void);
 extern u32 epapr_ev_idle_start[];
+#endif
 
 bool epapr_paravirt_enabled;
 
@@ -47,11 +49,15 @@ static int __init epapr_paravirt_init(void)
 
        for (i = 0; i < (len / 4); i++) {
                patch_instruction(epapr_hypercall_start + i, insts[i]);
+#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
                patch_instruction(epapr_ev_idle_start + i, insts[i]);
+#endif
        }
 
+#if !defined(CONFIG_64BIT) || defined(CONFIG_PPC_BOOK3E_64)
        if (of_get_property(hyper_node, "has-idle", NULL))
                ppc_md.power_save = epapr_ev_idle;
+#endif
 
        epapr_paravirt_enabled = true;
 
index 87ef8f5ee5bc52242af82aec893b274a6a8ec47d..56bd92362ce131e8742f33d56ff8613e05bcced0 100644 (file)
@@ -1066,78 +1066,6 @@ unrecov_user_slb:
 #endif /* __DISABLED__ */
 
 
-/*
- * r13 points to the PACA, r9 contains the saved CR,
- * r12 contain the saved SRR1, SRR0 is still ready for return
- * r3 has the faulting address
- * r9 - r13 are saved in paca->exslb.
- * r3 is saved in paca->slb_r3
- * We assume we aren't going to take any exceptions during this procedure.
- */
-_GLOBAL(slb_miss_realmode)
-       mflr    r10
-#ifdef CONFIG_RELOCATABLE
-       mtctr   r11
-#endif
-
-       stw     r9,PACA_EXSLB+EX_CCR(r13)       /* save CR in exc. frame */
-       std     r10,PACA_EXSLB+EX_LR(r13)       /* save LR */
-
-       bl      .slb_allocate_realmode
-
-       /* All done -- return from exception. */
-
-       ld      r10,PACA_EXSLB+EX_LR(r13)
-       ld      r3,PACA_EXSLB+EX_R3(r13)
-       lwz     r9,PACA_EXSLB+EX_CCR(r13)       /* get saved CR */
-
-       mtlr    r10
-
-       andi.   r10,r12,MSR_RI  /* check for unrecoverable exception */
-       beq-    2f
-
-.machine       push
-.machine       "power4"
-       mtcrf   0x80,r9
-       mtcrf   0x01,r9         /* slb_allocate uses cr0 and cr7 */
-.machine       pop
-
-       RESTORE_PPR_PACA(PACA_EXSLB, r9)
-       ld      r9,PACA_EXSLB+EX_R9(r13)
-       ld      r10,PACA_EXSLB+EX_R10(r13)
-       ld      r11,PACA_EXSLB+EX_R11(r13)
-       ld      r12,PACA_EXSLB+EX_R12(r13)
-       ld      r13,PACA_EXSLB+EX_R13(r13)
-       rfid
-       b       .       /* prevent speculative execution */
-
-2:     mfspr   r11,SPRN_SRR0
-       ld      r10,PACAKBASE(r13)
-       LOAD_HANDLER(r10,unrecov_slb)
-       mtspr   SPRN_SRR0,r10
-       ld      r10,PACAKMSR(r13)
-       mtspr   SPRN_SRR1,r10
-       rfid
-       b       .
-
-unrecov_slb:
-       EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
-       DISABLE_INTS
-       bl      .save_nvgprs
-1:     addi    r3,r1,STACK_FRAME_OVERHEAD
-       bl      .unrecoverable_exception
-       b       1b
-
-
-#ifdef CONFIG_PPC_970_NAP
-power4_fixup_nap:
-       andc    r9,r9,r10
-       std     r9,TI_LOCAL_FLAGS(r11)
-       ld      r10,_LINK(r1)           /* make idle task do the */
-       std     r10,_NIP(r1)            /* equivalent of a blr */
-       blr
-#endif
-
        .align  7
        .globl alignment_common
 alignment_common:
@@ -1335,6 +1263,78 @@ _GLOBAL(opal_mc_secondary_handler)
 #endif /* CONFIG_PPC_POWERNV */
 
 
+/*
+ * r13 points to the PACA, r9 contains the saved CR,
+ * r12 contain the saved SRR1, SRR0 is still ready for return
+ * r3 has the faulting address
+ * r9 - r13 are saved in paca->exslb.
+ * r3 is saved in paca->slb_r3
+ * We assume we aren't going to take any exceptions during this procedure.
+ */
+_GLOBAL(slb_miss_realmode)
+       mflr    r10
+#ifdef CONFIG_RELOCATABLE
+       mtctr   r11
+#endif
+
+       stw     r9,PACA_EXSLB+EX_CCR(r13)       /* save CR in exc. frame */
+       std     r10,PACA_EXSLB+EX_LR(r13)       /* save LR */
+
+       bl      .slb_allocate_realmode
+
+       /* All done -- return from exception. */
+
+       ld      r10,PACA_EXSLB+EX_LR(r13)
+       ld      r3,PACA_EXSLB+EX_R3(r13)
+       lwz     r9,PACA_EXSLB+EX_CCR(r13)       /* get saved CR */
+
+       mtlr    r10
+
+       andi.   r10,r12,MSR_RI  /* check for unrecoverable exception */
+       beq-    2f
+
+.machine       push
+.machine       "power4"
+       mtcrf   0x80,r9
+       mtcrf   0x01,r9         /* slb_allocate uses cr0 and cr7 */
+.machine       pop
+
+       RESTORE_PPR_PACA(PACA_EXSLB, r9)
+       ld      r9,PACA_EXSLB+EX_R9(r13)
+       ld      r10,PACA_EXSLB+EX_R10(r13)
+       ld      r11,PACA_EXSLB+EX_R11(r13)
+       ld      r12,PACA_EXSLB+EX_R12(r13)
+       ld      r13,PACA_EXSLB+EX_R13(r13)
+       rfid
+       b       .       /* prevent speculative execution */
+
+2:     mfspr   r11,SPRN_SRR0
+       ld      r10,PACAKBASE(r13)
+       LOAD_HANDLER(r10,unrecov_slb)
+       mtspr   SPRN_SRR0,r10
+       ld      r10,PACAKMSR(r13)
+       mtspr   SPRN_SRR1,r10
+       rfid
+       b       .
+
+unrecov_slb:
+       EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB)
+       DISABLE_INTS
+       bl      .save_nvgprs
+1:     addi    r3,r1,STACK_FRAME_OVERHEAD
+       bl      .unrecoverable_exception
+       b       1b
+
+
+#ifdef CONFIG_PPC_970_NAP
+power4_fixup_nap:
+       andc    r9,r9,r10
+       std     r9,TI_LOCAL_FLAGS(r11)
+       ld      r10,_LINK(r1)           /* make idle task do the */
+       std     r10,_NIP(r1)            /* equivalent of a blr */
+       blr
+#endif
+
 /*
  * Hash table stuff
  */
@@ -1452,20 +1452,36 @@ do_ste_alloc:
 _GLOBAL(do_stab_bolted)
        stw     r9,PACA_EXSLB+EX_CCR(r13)       /* save CR in exc. frame */
        std     r11,PACA_EXSLB+EX_SRR0(r13)     /* save SRR0 in exc. frame */
+       mfspr   r11,SPRN_DAR                    /* ea */
 
+       /*
+        * check for bad kernel/user address
+        * (ea & ~REGION_MASK) >= PGTABLE_RANGE
+        */
+       rldicr. r9,r11,4,(63 - 46 - 4)
+       li      r9,0    /* VSID = 0 for bad address */
+       bne-    0f
+
+       /*
+        * Calculate VSID:
+        * This is the kernel vsid, we take the top for context from
+        * the range. context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1
+        * Here we know that (ea >> 60) == 0xc
+        */
+       lis     r9,(MAX_USER_CONTEXT + 1)@ha
+       addi    r9,r9,(MAX_USER_CONTEXT + 1)@l
+
+       srdi    r10,r11,SID_SHIFT
+       rldimi  r10,r9,ESID_BITS,0 /* proto vsid */
+       ASM_VSID_SCRAMBLE(r10, r9, 256M)
+       rldic   r9,r10,12,16    /* r9 = vsid << 12 */
+
+0:
        /* Hash to the primary group */
        ld      r10,PACASTABVIRT(r13)
-       mfspr   r11,SPRN_DAR
-       srdi    r11,r11,28
+       srdi    r11,r11,SID_SHIFT
        rldimi  r10,r11,7,52    /* r10 = first ste of the group */
 
-       /* Calculate VSID */
-       /* This is a kernel address, so protovsid = ESID | 1 << 37 */
-       li      r9,0x1
-       rldimi  r11,r9,(CONTEXT_BITS + USER_ESID_BITS),0
-       ASM_VSID_SCRAMBLE(r11, r9, 256M)
-       rldic   r9,r11,12,16    /* r9 = vsid << 12 */
-
        /* Search the primary group for a free entry */
 1:     ld      r11,0(r10)      /* Test valid bit of the current ste    */
        andi.   r11,r11,0x80
index 7f7fb7fd991bd4e6185937faf1864499433b0eb6..13f8d168b3f1e467599248c92457c442b456b7ee 100644 (file)
@@ -2832,11 +2832,13 @@ static void unreloc_toc(void)
 {
 }
 #else
-static void __reloc_toc(void *tocstart, unsigned long offset,
-                       unsigned long nr_entries)
+static void __reloc_toc(unsigned long offset, unsigned long nr_entries)
 {
        unsigned long i;
-       unsigned long *toc_entry = (unsigned long *)tocstart;
+       unsigned long *toc_entry;
+
+       /* Get the start of the TOC by using r2 directly. */
+       asm volatile("addi %0,2,-0x8000" : "=b" (toc_entry));
 
        for (i = 0; i < nr_entries; i++) {
                *toc_entry = *toc_entry + offset;
@@ -2850,8 +2852,7 @@ static void reloc_toc(void)
        unsigned long nr_entries =
                (__prom_init_toc_end - __prom_init_toc_start) / sizeof(long);
 
-       /* Need to add offset to get at __prom_init_toc_start */
-       __reloc_toc(__prom_init_toc_start + offset, offset, nr_entries);
+       __reloc_toc(offset, nr_entries);
 
        mb();
 }
@@ -2864,8 +2865,7 @@ static void unreloc_toc(void)
 
        mb();
 
-       /* __prom_init_toc_start has been relocated, no need to add offset */
-       __reloc_toc(__prom_init_toc_start, -offset, nr_entries);
+       __reloc_toc(-offset, nr_entries);
 }
 #endif
 #endif
index 245c1b6a08589d216d3389308c565668b720b597..f9b30c68ba473a7f51607936da0e124507f40362 100644 (file)
@@ -1428,6 +1428,7 @@ static long ppc_set_hwdebug(struct task_struct *child,
 
        brk.address = bp_info->addr & ~7UL;
        brk.type = HW_BRK_TYPE_TRANSLATE;
+       brk.len = 8;
        if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ)
                brk.type |= HW_BRK_TYPE_READ;
        if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
index ead58e3172945d81e863ba937cc1d88b93922558..5d7d29a313eb99d8581f7bf2e515421020628fbe 100644 (file)
@@ -326,8 +326,8 @@ int kvmppc_mmu_init(struct kvm_vcpu *vcpu)
        vcpu3s->context_id[0] = err;
 
        vcpu3s->proto_vsid_max = ((vcpu3s->context_id[0] + 1)
-                                 << USER_ESID_BITS) - 1;
-       vcpu3s->proto_vsid_first = vcpu3s->context_id[0] << USER_ESID_BITS;
+                                 << ESID_BITS) - 1;
+       vcpu3s->proto_vsid_first = vcpu3s->context_id[0] << ESID_BITS;
        vcpu3s->proto_vsid_next = vcpu3s->proto_vsid_first;
 
        kvmppc_mmu_hpte_init(vcpu);
index 1b6e1271719f994e1d16b21621851733658bffa5..f410c3e12c1e78c0a6c5e24ad9f41d86fdf01337 100644 (file)
@@ -195,6 +195,11 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
                unsigned long vpn  = hpt_vpn(vaddr, vsid, ssize);
                unsigned long tprot = prot;
 
+               /*
+                * If we hit a bad address return error.
+                */
+               if (!vsid)
+                       return -1;
                /* Make kernel text executable */
                if (overlaps_kernel_text(vaddr, vaddr + step))
                        tprot &= ~HPTE_R_N;
@@ -759,6 +764,8 @@ void __init early_init_mmu(void)
        /* Initialize stab / SLB management */
        if (mmu_has_feature(MMU_FTR_SLB))
                slb_initialize();
+       else
+               stab_initialize(get_paca()->stab_real);
 }
 
 #ifdef CONFIG_SMP
@@ -922,11 +929,6 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
        DBG_LOW("hash_page(ea=%016lx, access=%lx, trap=%lx\n",
                ea, access, trap);
 
-       if ((ea & ~REGION_MASK) >= PGTABLE_RANGE) {
-               DBG_LOW(" out of pgtable range !\n");
-               return 1;
-       }
-
        /* Get region & vsid */
        switch (REGION_ID(ea)) {
        case USER_REGION_ID:
@@ -957,6 +959,11 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
        }
        DBG_LOW(" mm=%p, mm->pgdir=%p, vsid=%016lx\n", mm, mm->pgd, vsid);
 
+       /* Bad address. */
+       if (!vsid) {
+               DBG_LOW("Bad address!\n");
+               return 1;
+       }
        /* Get pgdir */
        pgdir = mm->pgd;
        if (pgdir == NULL)
@@ -1126,6 +1133,8 @@ void hash_preload(struct mm_struct *mm, unsigned long ea,
        /* Get VSID */
        ssize = user_segment_size(ea);
        vsid = get_vsid(mm->context.id, ea, ssize);
+       if (!vsid)
+               return;
 
        /* Hash doesn't like irqs */
        local_irq_save(flags);
@@ -1233,6 +1242,9 @@ static void kernel_map_linear_page(unsigned long vaddr, unsigned long lmi)
        hash = hpt_hash(vpn, PAGE_SHIFT, mmu_kernel_ssize);
        hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
+       /* Don't create HPTE entries for bad address */
+       if (!vsid)
+               return;
        ret = ppc_md.hpte_insert(hpteg, vpn, __pa(vaddr),
                                 mode, HPTE_V_BOLTED,
                                 mmu_linear_psize, mmu_kernel_ssize);
index 40bc5b0ace54354aea6944d77b6ef07e6f7f7b3d..d1d1b92c5b9964c3363f84a1719f0759507ba41d 100644 (file)
 static DEFINE_SPINLOCK(mmu_context_lock);
 static DEFINE_IDA(mmu_context_ida);
 
-/*
- * 256MB segment
- * The proto-VSID space has 2^(CONTEX_BITS + USER_ESID_BITS) - 1 segments
- * available for user mappings. Each segment contains 2^28 bytes. Each
- * context maps 2^46 bytes (64TB) so we can support 2^19-1 contexts
- * (19 == 37 + 28 - 46).
- */
-#define MAX_CONTEXT    ((1UL << CONTEXT_BITS) - 1)
-
 int __init_new_context(void)
 {
        int index;
@@ -56,7 +47,7 @@ again:
        else if (err)
                return err;
 
-       if (index > MAX_CONTEXT) {
+       if (index > MAX_USER_CONTEXT) {
                spin_lock(&mmu_context_lock);
                ida_remove(&mmu_context_ida, index);
                spin_unlock(&mmu_context_lock);
index e212a271c7a4bdadac512efd24da89de6c9ddd77..654258f165aeb9496ae96131c0f9b383927e8d20 100644 (file)
@@ -61,7 +61,7 @@
 #endif
 
 #ifdef CONFIG_PPC_STD_MMU_64
-#if TASK_SIZE_USER64 > (1UL << (USER_ESID_BITS + SID_SHIFT))
+#if TASK_SIZE_USER64 > (1UL << (ESID_BITS + SID_SHIFT))
 #error TASK_SIZE_USER64 exceeds user VSID range
 #endif
 #endif
index 1a16ca2277575fef9c0614df84f6e4f93df376f1..17aa6dfceb3498cbb0a09302485bdf1ab8049cbf 100644 (file)
  * No other registers are examined or changed.
  */
 _GLOBAL(slb_allocate_realmode)
-       /* r3 = faulting address */
+       /*
+        * check for bad kernel/user address
+        * (ea & ~REGION_MASK) >= PGTABLE_RANGE
+        */
+       rldicr. r9,r3,4,(63 - 46 - 4)
+       bne-    8f
 
        srdi    r9,r3,60                /* get region */
-       srdi    r10,r3,28               /* get esid */
+       srdi    r10,r3,SID_SHIFT        /* get esid */
        cmpldi  cr7,r9,0xc              /* cmp PAGE_OFFSET for later use */
 
        /* r3 = address, r10 = esid, cr7 = <> PAGE_OFFSET */
@@ -56,12 +61,14 @@ _GLOBAL(slb_allocate_realmode)
         */
 _GLOBAL(slb_miss_kernel_load_linear)
        li      r11,0
-       li      r9,0x1
        /*
-        * for 1T we shift 12 bits more.  slb_finish_load_1T will do
-        * the necessary adjustment
+        * context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1
+        * r9 = region id.
         */
-       rldimi  r10,r9,(CONTEXT_BITS + USER_ESID_BITS),0
+       addis   r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@ha
+       addi    r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@l
+
+
 BEGIN_FTR_SECTION
        b       slb_finish_load
 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
@@ -91,24 +98,19 @@ _GLOBAL(slb_miss_kernel_load_vmemmap)
        _GLOBAL(slb_miss_kernel_load_io)
        li      r11,0
 6:
-       li      r9,0x1
        /*
-        * for 1T we shift 12 bits more.  slb_finish_load_1T will do
-        * the necessary adjustment
+        * context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1
+        * r9 = region id.
         */
-       rldimi  r10,r9,(CONTEXT_BITS + USER_ESID_BITS),0
+       addis   r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@ha
+       addi    r9,r9,(MAX_USER_CONTEXT - 0xc + 1)@l
+
 BEGIN_FTR_SECTION
        b       slb_finish_load
 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
        b       slb_finish_load_1T
 
-0:     /* user address: proto-VSID = context << 15 | ESID. First check
-        * if the address is within the boundaries of the user region
-        */
-       srdi.   r9,r10,USER_ESID_BITS
-       bne-    8f                      /* invalid ea bits set */
-
-
+0:
        /* when using slices, we extract the psize off the slice bitmaps
         * and then we need to get the sllp encoding off the mmu_psize_defs
         * array.
@@ -164,15 +166,13 @@ END_MMU_FTR_SECTION_IFCLR(MMU_FTR_1T_SEGMENT)
        ld      r9,PACACONTEXTID(r13)
 BEGIN_FTR_SECTION
        cmpldi  r10,0x1000
-END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
-       rldimi  r10,r9,USER_ESID_BITS,0
-BEGIN_FTR_SECTION
        bge     slb_finish_load_1T
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        b       slb_finish_load
 
 8:     /* invalid EA */
        li      r10,0                   /* BAD_VSID */
+       li      r9,0                    /* BAD_VSID */
        li      r11,SLB_VSID_USER       /* flags don't much matter */
        b       slb_finish_load
 
@@ -221,8 +221,6 @@ _GLOBAL(slb_allocate_user)
 
        /* get context to calculate proto-VSID */
        ld      r9,PACACONTEXTID(r13)
-       rldimi  r10,r9,USER_ESID_BITS,0
-
        /* fall through slb_finish_load */
 
 #endif /* __DISABLED__ */
@@ -231,9 +229,10 @@ _GLOBAL(slb_allocate_user)
 /*
  * Finish loading of an SLB entry and return
  *
- * r3 = EA, r10 = proto-VSID, r11 = flags, clobbers r9, cr7 = <> PAGE_OFFSET
+ * r3 = EA, r9 = context, r10 = ESID, r11 = flags, clobbers r9, cr7 = <> PAGE_OFFSET
  */
 slb_finish_load:
+       rldimi  r10,r9,ESID_BITS,0
        ASM_VSID_SCRAMBLE(r10,r9,256M)
        /*
         * bits above VSID_BITS_256M need to be ignored from r10
@@ -298,10 +297,11 @@ _GLOBAL(slb_compare_rr_to_size)
 /*
  * Finish loading of a 1T SLB entry (for the kernel linear mapping) and return.
  *
- * r3 = EA, r10 = proto-VSID, r11 = flags, clobbers r9
+ * r3 = EA, r9 = context, r10 = ESID(256MB), r11 = flags, clobbers r9
  */
 slb_finish_load_1T:
-       srdi    r10,r10,40-28           /* get 1T ESID */
+       srdi    r10,r10,(SID_SHIFT_1T - SID_SHIFT)      /* get 1T ESID */
+       rldimi  r10,r9,ESID_BITS_1T,0
        ASM_VSID_SCRAMBLE(r10,r9,1T)
        /*
         * bits above VSID_BITS_1T need to be ignored from r10
index 0d82ef50dc3faf9269042bb09001320fbdacdaad..023ec8a13f38eed82e45fe37fc0f6e4be9518b83 100644 (file)
@@ -82,11 +82,11 @@ void hpte_need_flush(struct mm_struct *mm, unsigned long addr,
        if (!is_kernel_addr(addr)) {
                ssize = user_segment_size(addr);
                vsid = get_vsid(mm->context.id, addr, ssize);
-               WARN_ON(vsid == 0);
        } else {
                vsid = get_kernel_vsid(addr, mmu_kernel_ssize);
                ssize = mmu_kernel_ssize;
        }
+       WARN_ON(vsid == 0);
        vpn = hpt_vpn(addr, vsid, ssize);
        rpte = __real_pte(__pte(pte), ptep);
 
index b554879bd31e4c48cc6769092695c7f32a899af4..3c475d6267c75b0db98584b0f4c7cd0379fd19d1 100644 (file)
@@ -420,7 +420,20 @@ static struct attribute_group power7_pmu_events_group = {
        .attrs = power7_events_attr,
 };
 
+PMU_FORMAT_ATTR(event, "config:0-19");
+
+static struct attribute *power7_pmu_format_attr[] = {
+       &format_attr_event.attr,
+       NULL,
+};
+
+struct attribute_group power7_pmu_format_group = {
+       .name = "format",
+       .attrs = power7_pmu_format_attr,
+};
+
 static const struct attribute_group *power7_pmu_attr_groups[] = {
+       &power7_pmu_format_group,
        &power7_pmu_events_group,
        NULL,
 };
index 611e92f291c428765378140dbf5dc06890c44973..7179726ba5c5fdb521afa9a78509eefca7695131 100644 (file)
@@ -69,7 +69,7 @@ static irqreturn_t gpio_halt_irq(int irq, void *__data)
         return IRQ_HANDLED;
 };
 
-static int __devinit gpio_halt_probe(struct platform_device *pdev)
+static int gpio_halt_probe(struct platform_device *pdev)
 {
        enum of_gpio_flags flags;
        struct device_node *node = pdev->dev.of_node;
@@ -128,7 +128,7 @@ static int __devinit gpio_halt_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit gpio_halt_remove(struct platform_device *pdev)
+static int gpio_halt_remove(struct platform_device *pdev)
 {
        if (halt_node) {
                int gpio = of_get_gpio(halt_node, 0);
@@ -165,7 +165,7 @@ static struct platform_driver gpio_halt_driver = {
                .of_match_table = gpio_halt_match,
        },
        .probe          = gpio_halt_probe,
-       .remove         = __devexit_p(gpio_halt_remove),
+       .remove         = gpio_halt_remove,
 };
 
 module_platform_driver(gpio_halt_driver);
index cea2f09c42418d101c78b445b18c9286a714b53b..18e3b76c78d7ca3d8372ccda9808a5b122deb78d 100644 (file)
@@ -124,9 +124,8 @@ config 6xx
        select PPC_HAVE_PMU_SUPPORT
 
 config POWER3
-       bool
        depends on PPC64 && PPC_BOOK3S
-       default y if !POWER4_ONLY
+       def_bool y
 
 config POWER4
        depends on PPC64 && PPC_BOOK3S
@@ -145,8 +144,7 @@ config TUNE_CELL
          but somewhat slower on other machines. This option only changes
          the scheduling of instructions, not the selection of instructions
          itself, so the resulting kernel will keep running on all other
-         machines. When building a kernel that is supposed to run only
-         on Cell, you should also select the POWER4_ONLY option.
+         machines.
 
 # this is temp to handle compat with arch=ppc
 config 8xx
index 4b505370a1d59430b0bc519c47b926b0ed29adab..eb8fb629f00bba774b195a475471d630d6bd8bd0 100644 (file)
@@ -134,7 +134,7 @@ config S390
        select HAVE_SYSCALL_WRAPPERS
        select HAVE_UID16 if 32BIT
        select HAVE_VIRT_CPU_ACCOUNTING
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select INIT_ALL_POSSIBLE
        select KTIME_SCALAR if 32BIT
        select MODULES_USE_ELF_RELA
index f1eddd150dd7e782876ed8faff25a6d004b3f841..c879fad404c8d36d73aff75ea1174df65374061b 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef _ASM_S390_CPU_MF_H
 #define _ASM_S390_CPU_MF_H
 
+#include <linux/errno.h>
 #include <asm/facility.h>
 
 #define CPU_MF_INT_SF_IAE      (1 << 31)       /* invalid entry address */
index 8d4847191ecc52121cbe2afaa04fff7e2c6d2ad8..dc9200ca32eda4d3e5a819025b176f7af5a06d60 100644 (file)
@@ -34,6 +34,8 @@ struct arsb {
        u32 reserved[4];
 } __packed;
 
+#define EQC_WR_PROHIBIT 22
+
 struct msb {
        u8 fmt:4;
        u8 oc:4;
@@ -96,11 +98,13 @@ struct scm_device {
 #define OP_STATE_TEMP_ERR      2
 #define OP_STATE_PERM_ERR      3
 
+enum scm_event {SCM_CHANGE, SCM_AVAIL};
+
 struct scm_driver {
        struct device_driver drv;
        int (*probe) (struct scm_device *scmdev);
        int (*remove) (struct scm_device *scmdev);
-       void (*notify) (struct scm_device *scmdev);
+       void (*notify) (struct scm_device *scmdev, enum scm_event event);
        void (*handler) (struct scm_device *scmdev, void *data, int error);
 };
 
index 4a2930844d43a078492732cf156d392ac10fc29e..4a5443118cfb039d4b5e53f63b7470c292c4a431 100644 (file)
@@ -344,6 +344,7 @@ extern unsigned long MODULES_END;
 #define _REGION3_ENTRY_CO      0x100   /* change-recording override        */
 
 /* Bits in the segment table entry */
+#define _SEGMENT_ENTRY_ORIGIN_LARGE ~0xfffffUL /* large page address       */
 #define _SEGMENT_ENTRY_ORIGIN  ~0x7ffUL/* segment table origin             */
 #define _SEGMENT_ENTRY_RO      0x200   /* page protection bit              */
 #define _SEGMENT_ENTRY_INV     0x20    /* invalid segment table entry      */
@@ -1531,7 +1532,8 @@ extern int s390_enable_sie(void);
 /*
  * No page table caches to initialise
  */
-#define pgtable_cache_init()   do { } while (0)
+static inline void pgtable_cache_init(void) { }
+static inline void check_pgt_cache(void) { }
 
 #include <asm-generic/pgtable.h>
 
index 1d8fe2b17ef6f1d0069c0e3cc8ff70c7d9cc402a..6b32af30878cc6276c57079aeefcda38ea6ea685 100644 (file)
@@ -74,8 +74,6 @@ static inline void __tlb_flush_idte(unsigned long asce)
 
 static inline void __tlb_flush_mm(struct mm_struct * mm)
 {
-       if (unlikely(cpumask_empty(mm_cpumask(mm))))
-               return;
        /*
         * If the machine has IDTE we prefer to do a per mm flush
         * on all cpus instead of doing a local flush if the mm
index 55022852326748599c4a8f4a74e77468e3d1f5a3..94feff7d613233dca1ad45702181f161bb425caf 100644 (file)
@@ -636,7 +636,8 @@ ENTRY(mcck_int_handler)
        UPDATE_VTIME %r14,%r15,__LC_MCCK_ENTER_TIMER
 mcck_skip:
        SWITCH_ASYNC __LC_GPREGS_SAVE_AREA+32,__LC_PANIC_STACK,PAGE_SHIFT
-       mvc     __PT_R0(64,%r11),__LC_GPREGS_SAVE_AREA
+       stm     %r0,%r7,__PT_R0(%r11)
+       mvc     __PT_R8(32,%r11),__LC_GPREGS_SAVE_AREA+32
        stm     %r8,%r9,__PT_PSW(%r11)
        xc      __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)
        l       %r1,BASED(.Ldo_machine_check)
index 9c837c101297a52536c726d2e6b2e2c2e9c79ce9..2e6d60c55f909259803a1b52d7fdc6d04277fd0b 100644 (file)
@@ -678,8 +678,9 @@ ENTRY(mcck_int_handler)
        UPDATE_VTIME %r14,__LC_MCCK_ENTER_TIMER
        LAST_BREAK %r14
 mcck_skip:
-       lghi    %r14,__LC_GPREGS_SAVE_AREA
-       mvc     __PT_R0(128,%r11),0(%r14)
+       lghi    %r14,__LC_GPREGS_SAVE_AREA+64
+       stmg    %r0,%r7,__PT_R0(%r11)
+       mvc     __PT_R8(64,%r11),0(%r14)
        stmg    %r8,%r9,__PT_PSW(%r11)
        xc      __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)
        lgr     %r2,%r11                # pass pointer to pt_regs
index a5360de85ec7e7eb190f64de6028d08ea2e2c68e..29268859d8eebc405bc013fee0a2d05ee86d71b8 100644 (file)
@@ -571,6 +571,8 @@ static void __init setup_memory_end(void)
 
        /* Split remaining virtual space between 1:1 mapping & vmemmap array */
        tmp = VMALLOC_START / (PAGE_SIZE + sizeof(struct page));
+       /* vmemmap contains a multiple of PAGES_PER_SECTION struct pages */
+       tmp = SECTION_ALIGN_UP(tmp);
        tmp = VMALLOC_START - tmp * sizeof(struct page);
        tmp &= ~((vmax >> 11) - 1);     /* align to page table level */
        tmp = min(tmp, 1UL << MAX_PHYSMEM_BITS);
index dff631d34b45b2630551813454ede86ba94dca84..466fb3383960442b7624e51990536d2cf0b8c65d 100644 (file)
@@ -77,42 +77,69 @@ static size_t copy_in_kernel(size_t count, void __user *to,
  * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occured and the address
  * contains the (negative) exception code.
  */
-static __always_inline unsigned long follow_table(struct mm_struct *mm,
-                                                 unsigned long addr, int write)
+#ifdef CONFIG_64BIT
+static unsigned long follow_table(struct mm_struct *mm,
+                                 unsigned long address, int write)
 {
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *ptep;
+       unsigned long *table = (unsigned long *)__pa(mm->pgd);
+
+       switch (mm->context.asce_bits & _ASCE_TYPE_MASK) {
+       case _ASCE_TYPE_REGION1:
+               table = table + ((address >> 53) & 0x7ff);
+               if (unlikely(*table & _REGION_ENTRY_INV))
+                       return -0x39UL;
+               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+       case _ASCE_TYPE_REGION2:
+               table = table + ((address >> 42) & 0x7ff);
+               if (unlikely(*table & _REGION_ENTRY_INV))
+                       return -0x3aUL;
+               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+       case _ASCE_TYPE_REGION3:
+               table = table + ((address >> 31) & 0x7ff);
+               if (unlikely(*table & _REGION_ENTRY_INV))
+                       return -0x3bUL;
+               table = (unsigned long *)(*table & _REGION_ENTRY_ORIGIN);
+       case _ASCE_TYPE_SEGMENT:
+               table = table + ((address >> 20) & 0x7ff);
+               if (unlikely(*table & _SEGMENT_ENTRY_INV))
+                       return -0x10UL;
+               if (unlikely(*table & _SEGMENT_ENTRY_LARGE)) {
+                       if (write && (*table & _SEGMENT_ENTRY_RO))
+                               return -0x04UL;
+                       return (*table & _SEGMENT_ENTRY_ORIGIN_LARGE) +
+                               (address & ~_SEGMENT_ENTRY_ORIGIN_LARGE);
+               }
+               table = (unsigned long *)(*table & _SEGMENT_ENTRY_ORIGIN);
+       }
+       table = table + ((address >> 12) & 0xff);
+       if (unlikely(*table & _PAGE_INVALID))
+               return -0x11UL;
+       if (write && (*table & _PAGE_RO))
+               return -0x04UL;
+       return (*table & PAGE_MASK) + (address & ~PAGE_MASK);
+}
 
-       pgd = pgd_offset(mm, addr);
-       if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
-               return -0x3aUL;
+#else /* CONFIG_64BIT */
 
-       pud = pud_offset(pgd, addr);
-       if (pud_none(*pud) || unlikely(pud_bad(*pud)))
-               return -0x3bUL;
+static unsigned long follow_table(struct mm_struct *mm,
+                                 unsigned long address, int write)
+{
+       unsigned long *table = (unsigned long *)__pa(mm->pgd);
 
-       pmd = pmd_offset(pud, addr);
-       if (pmd_none(*pmd))
+       table = table + ((address >> 20) & 0x7ff);
+       if (unlikely(*table & _SEGMENT_ENTRY_INV))
                return -0x10UL;
-       if (pmd_large(*pmd)) {
-               if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO))
-                       return -0x04UL;
-               return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK);
-       }
-       if (unlikely(pmd_bad(*pmd)))
-               return -0x10UL;
-
-       ptep = pte_offset_map(pmd, addr);
-       if (!pte_present(*ptep))
+       table = (unsigned long *)(*table & _SEGMENT_ENTRY_ORIGIN);
+       table = table + ((address >> 12) & 0xff);
+       if (unlikely(*table & _PAGE_INVALID))
                return -0x11UL;
-       if (write && (!pte_write(*ptep) || !pte_dirty(*ptep)))
+       if (write && (*table & _PAGE_RO))
                return -0x04UL;
-
-       return (pte_val(*ptep) & PAGE_MASK) + (addr & ~PAGE_MASK);
+       return (*table & PAGE_MASK) + (address & ~PAGE_MASK);
 }
 
+#endif /* CONFIG_64BIT */
+
 static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
                                             size_t n, int write_user)
 {
@@ -197,7 +224,7 @@ size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
 
 static size_t clear_user_pt(size_t n, void __user *to)
 {
-       void *zpage = &empty_zero_page;
+       void *zpage = (void *) empty_zero_page;
        long done, size, ret;
 
        done = 0;
index e569aa1fd2ba7a5c68d6dfb95564e98c2397f9d7..c8def8bc90209578a5a6d5cfaf8f9f258c4ec7fb 100644 (file)
@@ -12,7 +12,7 @@ config SCORE
        select GENERIC_CPU_DEVICES
        select GENERIC_CLOCKEVENTS
        select HAVE_MOD_ARCH_SPECIFIC
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select MODULES_USE_ELF_REL
        select CLONE_BACKWARDS
 
index 289127d5241ce7a2ee646e8b8211849ae1cc2eda..3d361f236308c13cde14286379ec418af3e52990 100644 (file)
@@ -84,12 +84,6 @@ config ARCH_DEFCONFIG
        default "arch/sparc/configs/sparc32_defconfig" if SPARC32
        default "arch/sparc/configs/sparc64_defconfig" if SPARC64
 
-# CONFIG_BITS can be used at source level to get 32/64 bits
-config BITS
-       int
-       default 32 if SPARC32
-       default 64 if SPARC64
-
 config IOMMU_HELPER
        bool
        default y if SPARC64
@@ -197,7 +191,7 @@ config RWSEM_XCHGADD_ALGORITHM
 
 config GENERIC_HWEIGHT
        bool
-       default y if !ULTRA_HAS_POPULATION_COUNT
+       default y
 
 config GENERIC_CALIBRATE_DELAY
        bool
index d06a266017534f406b41d0488e0c00eb296d0156..6b67e50fb9b4cf934dade73c9d10dfeec6afe364 100644 (file)
@@ -45,6 +45,7 @@
 #define SUN4V_CHIP_NIAGARA3    0x03
 #define SUN4V_CHIP_NIAGARA4    0x04
 #define SUN4V_CHIP_NIAGARA5    0x05
+#define SUN4V_CHIP_SPARC64X    0x8a
 #define SUN4V_CHIP_UNKNOWN     0xff
 
 #ifndef __ASSEMBLY__
index a6c94a2bf9d4b1150e41b63d3e71a81138fc1f63..5c5125895db86e4dacd9de9dee91b508628b30c2 100644 (file)
@@ -493,6 +493,12 @@ static void __init sun4v_cpu_probe(void)
                sparc_pmu_type = "niagara5";
                break;
 
+       case SUN4V_CHIP_SPARC64X:
+               sparc_cpu_type = "SPARC64-X";
+               sparc_fpu_type = "SPARC64-X integrated FPU";
+               sparc_pmu_type = "sparc64-x";
+               break;
+
        default:
                printk(KERN_WARNING "CPU: Unknown sun4v cpu type [%s]\n",
                       prom_cpu_compatible);
index 2feb15c35d9e1bb0154d1f023accccca3a8ee460..26b706a1867dc6b9976b52e1e61ef8e54ce0df91 100644 (file)
@@ -134,6 +134,8 @@ prom_niagara_prefix:
        .asciz  "SUNW,UltraSPARC-T"
 prom_sparc_prefix:
        .asciz  "SPARC-"
+prom_sparc64x_prefix:
+       .asciz  "SPARC64-X"
        .align  4
 prom_root_compatible:
        .skip   64
@@ -412,7 +414,7 @@ sun4v_chip_type:
        cmp     %g2, 'T'
        be,pt   %xcc, 70f
         cmp    %g2, 'M'
-       bne,pn  %xcc, 4f
+       bne,pn  %xcc, 49f
         nop
 
 70:    ldub    [%g1 + 7], %g2
@@ -425,7 +427,7 @@ sun4v_chip_type:
        cmp     %g2, '5'
        be,pt   %xcc, 5f
         mov    SUN4V_CHIP_NIAGARA5, %g4
-       ba,pt   %xcc, 4f
+       ba,pt   %xcc, 49f
         nop
 
 91:    sethi   %hi(prom_cpu_compatible), %g1
@@ -439,6 +441,25 @@ sun4v_chip_type:
         mov    SUN4V_CHIP_NIAGARA2, %g4
        
 4:
+       /* Athena */
+       sethi   %hi(prom_cpu_compatible), %g1
+       or      %g1, %lo(prom_cpu_compatible), %g1
+       sethi   %hi(prom_sparc64x_prefix), %g7
+       or      %g7, %lo(prom_sparc64x_prefix), %g7
+       mov     9, %g3
+41:    ldub    [%g7], %g2
+       ldub    [%g1], %g4
+       cmp     %g2, %g4
+       bne,pn  %icc, 49f
+       add     %g7, 1, %g7
+       subcc   %g3, 1, %g3
+       bne,pt  %xcc, 41b
+       add     %g1, 1, %g1
+       mov     SUN4V_CHIP_SPARC64X, %g4
+       ba,pt   %xcc, 5f
+       nop
+
+49:
        mov     SUN4V_CHIP_UNKNOWN, %g4
 5:     sethi   %hi(sun4v_chip_type), %g2
        or      %g2, %lo(sun4v_chip_type), %g2
index fc4320886a3aa5d15f817075cfca261487d21438..4d1487138d260553005af8036734ef519395dd22 100644 (file)
@@ -186,6 +186,8 @@ struct grpci2_cap_first {
 #define CAP9_IOMAP_OFS 0x20
 #define CAP9_BARSIZE_OFS 0x24
 
+#define TGT 256
+
 struct grpci2_priv {
        struct leon_pci_info    info; /* must be on top of this structure */
        struct grpci2_regs      *regs;
@@ -237,8 +239,12 @@ static int grpci2_cfg_r32(struct grpci2_priv *priv, unsigned int bus,
        if (where & 0x3)
                return -EINVAL;
 
-       if (bus == 0 && PCI_SLOT(devfn) != 0)
-               devfn += (0x8 * 6);
+       if (bus == 0) {
+               devfn += (0x8 * 6); /* start at AD16=Device0 */
+       } else if (bus == TGT) {
+               bus = 0;
+               devfn = 0; /* special case: bridge controller itself */
+       }
 
        /* Select bus */
        spin_lock_irqsave(&grpci2_dev_lock, flags);
@@ -303,8 +309,12 @@ static int grpci2_cfg_w32(struct grpci2_priv *priv, unsigned int bus,
        if (where & 0x3)
                return -EINVAL;
 
-       if (bus == 0 && PCI_SLOT(devfn) != 0)
-               devfn += (0x8 * 6);
+       if (bus == 0) {
+               devfn += (0x8 * 6); /* start at AD16=Device0 */
+       } else if (bus == TGT) {
+               bus = 0;
+               devfn = 0; /* special case: bridge controller itself */
+       }
 
        /* Select bus */
        spin_lock_irqsave(&grpci2_dev_lock, flags);
@@ -368,7 +378,7 @@ static int grpci2_read_config(struct pci_bus *bus, unsigned int devfn,
        unsigned int busno = bus->number;
        int ret;
 
-       if (PCI_SLOT(devfn) > 15 || (PCI_SLOT(devfn) == 0 && busno == 0)) {
+       if (PCI_SLOT(devfn) > 15 || busno > 255) {
                *val = ~0;
                return 0;
        }
@@ -406,7 +416,7 @@ static int grpci2_write_config(struct pci_bus *bus, unsigned int devfn,
        struct grpci2_priv *priv = grpci2priv;
        unsigned int busno = bus->number;
 
-       if (PCI_SLOT(devfn) > 15 || (PCI_SLOT(devfn) == 0 && busno == 0))
+       if (PCI_SLOT(devfn) > 15 || busno > 255)
                return 0;
 
 #ifdef GRPCI2_DEBUG_CFGACCESS
@@ -578,15 +588,15 @@ void grpci2_hw_init(struct grpci2_priv *priv)
                REGSTORE(regs->ahbmst_map[i], priv->pci_area);
 
        /* Get the GRPCI2 Host PCI ID */
-       grpci2_cfg_r32(priv, 0, 0, PCI_VENDOR_ID, &priv->pciid);
+       grpci2_cfg_r32(priv, TGT, 0, PCI_VENDOR_ID, &priv->pciid);
 
        /* Get address to first (always defined) capability structure */
-       grpci2_cfg_r8(priv, 0, 0, PCI_CAPABILITY_LIST, &capptr);
+       grpci2_cfg_r8(priv, TGT, 0, PCI_CAPABILITY_LIST, &capptr);
 
        /* Enable/Disable Byte twisting */
-       grpci2_cfg_r32(priv, 0, 0, capptr+CAP9_IOMAP_OFS, &io_map);
+       grpci2_cfg_r32(priv, TGT, 0, capptr+CAP9_IOMAP_OFS, &io_map);
        io_map = (io_map & ~0x1) | (priv->bt_enabled ? 1 : 0);
-       grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_IOMAP_OFS, io_map);
+       grpci2_cfg_w32(priv, TGT, 0, capptr+CAP9_IOMAP_OFS, io_map);
 
        /* Setup the Host's PCI Target BARs for other peripherals to access,
         * and do DMA to the host's memory. The target BARs can be sized and
@@ -617,17 +627,18 @@ void grpci2_hw_init(struct grpci2_priv *priv)
                                pciadr = 0;
                        }
                }
-               grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_BARSIZE_OFS+i*4, bar_sz);
-               grpci2_cfg_w32(priv, 0, 0, PCI_BASE_ADDRESS_0+i*4, pciadr);
-               grpci2_cfg_w32(priv, 0, 0, capptr+CAP9_BAR_OFS+i*4, ahbadr);
+               grpci2_cfg_w32(priv, TGT, 0, capptr+CAP9_BARSIZE_OFS+i*4,
+                               bar_sz);
+               grpci2_cfg_w32(priv, TGT, 0, PCI_BASE_ADDRESS_0+i*4, pciadr);
+               grpci2_cfg_w32(priv, TGT, 0, capptr+CAP9_BAR_OFS+i*4, ahbadr);
                printk(KERN_INFO "        TGT BAR[%d]: 0x%08x (PCI)-> 0x%08x\n",
                        i, pciadr, ahbadr);
        }
 
        /* set as bus master and enable pci memory responses */
-       grpci2_cfg_r32(priv, 0, 0, PCI_COMMAND, &data);
+       grpci2_cfg_r32(priv, TGT, 0, PCI_COMMAND, &data);
        data |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
-       grpci2_cfg_w32(priv, 0, 0, PCI_COMMAND, data);
+       grpci2_cfg_w32(priv, TGT, 0, PCI_COMMAND, data);
 
        /* Enable Error respone (CPU-TRAP) on illegal memory access. */
        REGSTORE(regs->ctrl, CTRL_ER | CTRL_PE);
index ff496ab1e79445472aabd261ef133e2565c2a513..25877aebc685fcde958145add51e09e7fcbcc341 100644 (file)
@@ -17,7 +17,7 @@ config TILE
        select GENERIC_IRQ_SHOW
        select HAVE_DEBUG_BUGVERBOSE
        select HAVE_SYSCALL_WRAPPERS if TILEGX
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select SYS_HYPERVISOR
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select GENERIC_CLOCKEVENTS
index 8c5eff6d6df5577ea987d01cbf79cde62cab3506..47684815e5c8a27bf51fd8854ca11ae7cb2a07f8 100644 (file)
@@ -330,7 +330,6 @@ CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID456=m
-CONFIG_MULTICORE_RAID456=y
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_DEBUG=y
index e7a3dfcbcda7094ef4c7fa818c650716d2103397..dd2b8f0c631fc4a1ffb047d322753d3b4cef95b4 100644 (file)
@@ -324,7 +324,6 @@ CONFIG_MD_RAID0=m
 CONFIG_MD_RAID1=m
 CONFIG_MD_RAID10=m
 CONFIG_MD_RAID456=m
-CONFIG_MULTICORE_RAID456=y
 CONFIG_MD_FAULTY=m
 CONFIG_BLK_DEV_DM=m
 CONFIG_DM_DEBUG=y
index d1e15f7b59c68ab54ee62a137443270287f59f34..7a5aa1a7864e2371900e5ccba2d2a0f507fa834e 100644 (file)
@@ -1004,15 +1004,8 @@ void __cpuinit setup_cpu(int boot)
 
 #ifdef CONFIG_BLK_DEV_INITRD
 
-/*
- * Note that the kernel can potentially support other compression
- * techniques than gz, though we don't do so by default.  If we ever
- * decide to do so we can either look for other filename extensions,
- * or just allow a file with this name to be compressed with an
- * arbitrary compressor (somewhat counterintuitively).
- */
 static int __initdata set_initramfs_file;
-static char __initdata initramfs_file[128] = "initramfs.cpio.gz";
+static char __initdata initramfs_file[128] = "initramfs";
 
 static int __init setup_initramfs_file(char *str)
 {
@@ -1026,9 +1019,9 @@ static int __init setup_initramfs_file(char *str)
 early_param("initramfs_file", setup_initramfs_file);
 
 /*
- * We look for an "initramfs.cpio.gz" file in the hvfs.
- * If there is one, we allocate some memory for it and it will be
- * unpacked to the initramfs.
+ * We look for a file called "initramfs" in the hvfs.  If there is one, we
+ * allocate some memory for it and it will be unpacked to the initramfs.
+ * If it's compressed, the initd code will uncompress it first.
  */
 static void __init load_hv_initrd(void)
 {
@@ -1038,10 +1031,16 @@ static void __init load_hv_initrd(void)
 
        fd = hv_fs_findfile((HV_VirtAddr) initramfs_file);
        if (fd == HV_ENOENT) {
-               if (set_initramfs_file)
+               if (set_initramfs_file) {
                        pr_warning("No such hvfs initramfs file '%s'\n",
                                   initramfs_file);
-               return;
+                       return;
+               } else {
+                       /* Try old backwards-compatible name. */
+                       fd = hv_fs_findfile((HV_VirtAddr)"initramfs.cpio.gz");
+                       if (fd == HV_ENOENT)
+                               return;
+               }
        }
        BUG_ON(fd < 0);
        stat = hv_fs_fstat(fd);
index 78f1b899996446e9e769ff703938dbb7bedc6fe6..c512b0306dd41beff8039787d1eca7b90546ed40 100644 (file)
@@ -37,7 +37,7 @@ extern int console_write_chan(struct chan *chan, const char *buf,
 extern int console_open_chan(struct line *line, struct console *co);
 extern void deactivate_chan(struct chan *chan, int irq);
 extern void reactivate_chan(struct chan *chan, int irq);
-extern void chan_enable_winch(struct chan *chan, struct tty_struct *tty);
+extern void chan_enable_winch(struct chan *chan, struct tty_port *port);
 extern int enable_chan(struct line *line);
 extern void close_chan(struct line *line);
 extern int chan_window_size(struct line *line, 
index 15c553c239a119259f2f948f8381e5a9a26f4ccb..80b47cb71e0a85e7ea1a10626f7a1e0efe8e5225 100644 (file)
@@ -122,10 +122,10 @@ static int open_chan(struct list_head *chans)
        return err;
 }
 
-void chan_enable_winch(struct chan *chan, struct tty_struct *tty)
+void chan_enable_winch(struct chan *chan, struct tty_port *port)
 {
        if (chan && chan->primary && chan->ops->winch)
-               register_winch(chan->fd, tty);
+               register_winch(chan->fd, port);
 }
 
 static void line_timer_cb(struct work_struct *work)
index 9be670ad23b5fa6c94bb6b361bb9db59a0924a2d..3fd7c3efdb18df6b0f8f1dfd68e3883052b329c1 100644 (file)
@@ -216,7 +216,7 @@ static int winch_thread(void *arg)
        }
 }
 
-static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out,
+static int winch_tramp(int fd, struct tty_port *port, int *fd_out,
                       unsigned long *stack_out)
 {
        struct winch_data data;
@@ -271,7 +271,7 @@ static int winch_tramp(int fd, struct tty_struct *tty, int *fd_out,
        return err;
 }
 
-void register_winch(int fd, struct tty_struct *tty)
+void register_winch(int fd, struct tty_port *port)
 {
        unsigned long stack;
        int pid, thread, count, thread_fd = -1;
@@ -281,17 +281,17 @@ void register_winch(int fd, struct tty_struct *tty)
                return;
 
        pid = tcgetpgrp(fd);
-       if (is_skas_winch(pid, fd, tty)) {
-               register_winch_irq(-1, fd, -1, tty, 0);
+       if (is_skas_winch(pid, fd, port)) {
+               register_winch_irq(-1, fd, -1, port, 0);
                return;
        }
 
        if (pid == -1) {
-               thread = winch_tramp(fd, tty, &thread_fd, &stack);
+               thread = winch_tramp(fd, port, &thread_fd, &stack);
                if (thread < 0)
                        return;
 
-               register_winch_irq(thread_fd, fd, thread, tty, stack);
+               register_winch_irq(thread_fd, fd, thread, port, stack);
 
                count = write(thread_fd, &c, sizeof(c));
                if (count != sizeof(c))
index dc693298eb8fc0a73719d98521f8a4ae9f911dfa..03f1b565c5f9ac9028ed7b91444b89c1dde963f1 100644 (file)
@@ -38,10 +38,10 @@ extern int generic_window_size(int fd, void *unused, unsigned short *rows_out,
                               unsigned short *cols_out);
 extern void generic_free(void *data);
 
-struct tty_struct;
-extern void register_winch(int fd,  struct tty_struct *tty);
+struct tty_port;
+extern void register_winch(int fd,  struct tty_port *port);
 extern void register_winch_irq(int fd, int tty_fd, int pid,
-                              struct tty_struct *tty, unsigned long stack);
+                              struct tty_port *port, unsigned long stack);
 
 #define __channel_help(fn, prefix) \
 __uml_help(fn, prefix "[0-9]*=<channel description>\n" \
index f1b38571f94e7996d1c83712945583e3d1e75a06..be541cf69fd282cea191a3580e851549f25c39e0 100644 (file)
@@ -305,7 +305,7 @@ static int line_activate(struct tty_port *port, struct tty_struct *tty)
                return ret;
 
        if (!line->sigio) {
-               chan_enable_winch(line->chan_out, tty);
+               chan_enable_winch(line->chan_out, port);
                line->sigio = 1;
        }
 
@@ -315,8 +315,22 @@ static int line_activate(struct tty_port *port, struct tty_struct *tty)
        return 0;
 }
 
+static void unregister_winch(struct tty_struct *tty);
+
+static void line_destruct(struct tty_port *port)
+{
+       struct tty_struct *tty = tty_port_tty_get(port);
+       struct line *line = tty->driver_data;
+
+       if (line->sigio) {
+               unregister_winch(tty);
+               line->sigio = 0;
+       }
+}
+
 static const struct tty_port_operations line_port_ops = {
        .activate = line_activate,
+       .destruct = line_destruct,
 };
 
 int line_open(struct tty_struct *tty, struct file *filp)
@@ -340,18 +354,6 @@ int line_install(struct tty_driver *driver, struct tty_struct *tty,
        return 0;
 }
 
-static void unregister_winch(struct tty_struct *tty);
-
-void line_cleanup(struct tty_struct *tty)
-{
-       struct line *line = tty->driver_data;
-
-       if (line->sigio) {
-               unregister_winch(tty);
-               line->sigio = 0;
-       }
-}
-
 void line_close(struct tty_struct *tty, struct file * filp)
 {
        struct line *line = tty->driver_data;
@@ -601,7 +603,7 @@ struct winch {
        int fd;
        int tty_fd;
        int pid;
-       struct tty_struct *tty;
+       struct tty_port *port;
        unsigned long stack;
        struct work_struct work;
 };
@@ -655,7 +657,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
                        goto out;
                }
        }
-       tty = winch->tty;
+       tty = tty_port_tty_get(winch->port);
        if (tty != NULL) {
                line = tty->driver_data;
                if (line != NULL) {
@@ -663,6 +665,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
                                         &tty->winsize.ws_col);
                        kill_pgrp(tty->pgrp, SIGWINCH, 1);
                }
+               tty_kref_put(tty);
        }
  out:
        if (winch->fd != -1)
@@ -670,7 +673,7 @@ static irqreturn_t winch_interrupt(int irq, void *data)
        return IRQ_HANDLED;
 }
 
-void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
+void register_winch_irq(int fd, int tty_fd, int pid, struct tty_port *port,
                        unsigned long stack)
 {
        struct winch *winch;
@@ -685,7 +688,7 @@ void register_winch_irq(int fd, int tty_fd, int pid, struct tty_struct *tty,
                                   .fd          = fd,
                                   .tty_fd      = tty_fd,
                                   .pid         = pid,
-                                  .tty         = tty,
+                                  .port        = port,
                                   .stack       = stack });
 
        if (um_request_irq(WINCH_IRQ, fd, IRQ_READ, winch_interrupt,
@@ -714,15 +717,18 @@ static void unregister_winch(struct tty_struct *tty)
 {
        struct list_head *ele, *next;
        struct winch *winch;
+       struct tty_struct *wtty;
 
        spin_lock(&winch_handler_lock);
 
        list_for_each_safe(ele, next, &winch_handlers) {
                winch = list_entry(ele, struct winch, list);
-               if (winch->tty == tty) {
+               wtty = tty_port_tty_get(winch->port);
+               if (wtty == tty) {
                        free_winch(winch);
                        break;
                }
+               tty_kref_put(wtty);
        }
        spin_unlock(&winch_handler_lock);
 }
index d8926c30362946475822ff21ca6a4d5dc9f20cbf..39f186252e02521ccc33eb0fad6b450ccfb19d73 100644 (file)
@@ -218,6 +218,7 @@ static int uml_net_start_xmit(struct sk_buff *skb, struct net_device *dev)
        spin_lock_irqsave(&lp->lock, flags);
 
        len = (*lp->write)(lp->fd, skb, lp);
+       skb_tx_timestamp(skb);
 
        if (len == skb->len) {
                dev->stats.tx_packets++;
@@ -281,6 +282,7 @@ static void uml_net_get_drvinfo(struct net_device *dev,
 static const struct ethtool_ops uml_net_ethtool_ops = {
        .get_drvinfo    = uml_net_get_drvinfo,
        .get_link       = ethtool_op_get_link,
+       .get_ts_info    = ethtool_op_get_ts_info,
 };
 
 static void uml_net_user_timer_expire(unsigned long _conn)
index 16fdd0a0f9d617c67b7d99f0aa4317f2fcdfc7aa..b8d14fa5205901b0955b33735d4026d2ee49f8d2 100644 (file)
@@ -105,7 +105,6 @@ static const struct tty_operations ssl_ops = {
        .throttle               = line_throttle,
        .unthrottle             = line_unthrottle,
        .install                = ssl_install,
-       .cleanup                = line_cleanup,
        .hangup                 = line_hangup,
 };
 
index 827777af3f6d673bcb26570e4e28ccc370cfcd5e..7b361f36ca965f7b9ce202133f752e0347290c04 100644 (file)
@@ -110,7 +110,6 @@ static const struct tty_operations console_ops = {
        .set_termios            = line_set_termios,
        .throttle               = line_throttle,
        .unthrottle             = line_unthrottle,
-       .cleanup                = line_cleanup,
        .hangup                 = line_hangup,
 };
 
index b1469fe9329564dac95f1fc5b6320f0ed56ea31b..9d9f1b4bf8269d89af35a08b5e24064337a410e4 100644 (file)
@@ -15,7 +15,7 @@
 #include <sysdep/mcontext.h>
 #include "internal.h"
 
-void (*sig_info[NSIG])(int, siginfo_t *, struct uml_pt_regs *) = {
+void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
        [SIGTRAP]       = relay_signal,
        [SIGFPE]        = relay_signal,
        [SIGILL]        = relay_signal,
index da4b9e9999fd2640764c8a4afe0c11ca2f43bc3b..337518c5042a5cb4895e389202e6a4c5bc9654b2 100644 (file)
@@ -15,6 +15,8 @@
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 #include <asm/unistd.h>
 #include <init.h>
 #include <os.h>
index dc50b157fc83385b815768fb69ca2351fac83271..2943e3acdf0cba611bcd0fc222fbc59fb3f6602a 100644 (file)
@@ -9,7 +9,7 @@ config UNICORE32
        select GENERIC_ATOMIC64
        select HAVE_KERNEL_LZO
        select HAVE_KERNEL_LZMA
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select ARCH_HAVE_CUSTOM_GPIO_H
        select GENERIC_FIND_FIRST_BIT
        select GENERIC_IRQ_PROBE
index a4f24f5b1218520074eacc4918bcf5fd04d139a4..70c0f3da0476a35ba93546689bb4b06b5f576bba 100644 (file)
@@ -112,7 +112,7 @@ config X86
        select GENERIC_STRNLEN_USER
        select HAVE_CONTEXT_TRACKING if X86_64
        select HAVE_IRQ_TIME_ACCOUNTING
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select MODULES_USE_ELF_REL if X86_32
        select MODULES_USE_ELF_RELA if X86_64
        select CLONE_BACKWARDS if X86_32
index 8a84501acb1b965f2dbfe1d18b91799667af4fb3..5ef205c5f37b094a2e0358052775f01a8fe292b0 100644 (file)
@@ -4,7 +4,7 @@
 # create a compressed vmlinux image from the original vmlinux
 #
 
-targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.xz vmlinux.bin.lzo head_$(BITS).o misc.o string.o cmdline.o early_serial_console.o piggy.o
+targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.xz vmlinux.bin.lzo
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
 KBUILD_CFLAGS += -fno-strict-aliasing -fPIC
@@ -29,7 +29,6 @@ VMLINUX_OBJS = $(obj)/vmlinux.lds $(obj)/head_$(BITS).o $(obj)/misc.o \
        $(obj)/piggy.o
 
 $(obj)/eboot.o: KBUILD_CFLAGS += -fshort-wchar -mno-red-zone
-$(obj)/efi_stub_$(BITS).o: KBUILD_CLFAGS += -fshort-wchar -mno-red-zone
 
 ifeq ($(CONFIG_EFI_STUB), y)
        VMLINUX_OBJS += $(obj)/eboot.o $(obj)/efi_stub_$(BITS).o
@@ -43,7 +42,7 @@ OBJCOPYFLAGS_vmlinux.bin :=  -R .comment -S
 $(obj)/vmlinux.bin: vmlinux FORCE
        $(call if_changed,objcopy)
 
-targets += vmlinux.bin.all vmlinux.relocs
+targets += $(patsubst $(obj)/%,%,$(VMLINUX_OBJS)) vmlinux.bin.all vmlinux.relocs
 
 CMD_RELOCS = arch/x86/tools/relocs
 quiet_cmd_relocs = RELOCS  $@
index d3ddd17405d07b1e288828a949ac9ecb363c3c2e..5a6d2873f80eb61e878ded58ff289cf59adc0341 100644 (file)
@@ -77,6 +77,7 @@ struct arch_specific_insn {
         * a post_handler or break_handler).
         */
        int boostable;
+       bool if_modifier;
 };
 
 struct arch_optimized_insn {
index 635a74d224098523c2fcdee0f26a71618f96bdd8..4979778cc7fb51a14f5fa5960eb02b36d5c235f9 100644 (file)
@@ -414,8 +414,8 @@ struct kvm_vcpu_arch {
        gpa_t time;
        struct pvclock_vcpu_time_info hv_clock;
        unsigned int hw_tsc_khz;
-       unsigned int time_offset;
-       struct page *time_page;
+       struct gfn_to_hva_cache pv_time;
+       bool pv_time_enabled;
        /* set guest stopped flag in pvclock flags field */
        bool pvclock_set_guest_stopped_request;
 
index 1ace47b62592adabd69c568d1f842ffa33f057e2..2e188d68397c82930bdba80c52a87260546fcbd3 100644 (file)
@@ -29,13 +29,13 @@ extern const unsigned long sys_call_table[];
  */
 static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
 {
-       return regs->orig_ax & __SYSCALL_MASK;
+       return regs->orig_ax;
 }
 
 static inline void syscall_rollback(struct task_struct *task,
                                    struct pt_regs *regs)
 {
-       regs->ax = regs->orig_ax & __SYSCALL_MASK;
+       regs->ax = regs->orig_ax;
 }
 
 static inline long syscall_get_error(struct task_struct *task,
index c20d1ce62dc6a0a236280ab51b7ac8386fb1c32b..e709884d0ef9edbdd0b7228f180814bef1c0b174 100644 (file)
@@ -382,14 +382,14 @@ HYPERVISOR_console_io(int cmd, int count, char *str)
        return _hypercall3(int, console_io, cmd, count, str);
 }
 
-extern int __must_check HYPERVISOR_physdev_op_compat(int, void *);
+extern int __must_check xen_physdev_op_compat(int, void *);
 
 static inline int
 HYPERVISOR_physdev_op(int cmd, void *arg)
 {
        int rc = _hypercall2(int, physdev_op, cmd, arg);
        if (unlikely(rc == -ENOSYS))
-               rc = HYPERVISOR_physdev_op_compat(cmd, arg);
+               rc = xen_physdev_op_compat(cmd, arg);
        return rc;
 }
 
index 892ce40a7470515543e09d80115efae395717b0b..7a060f4b411f753ed065c389b705e7b2a010ab7b 100644 (file)
@@ -44,6 +44,7 @@
 #define SNB_C1_AUTO_UNDEMOTE           (1UL << 27)
 #define SNB_C3_AUTO_UNDEMOTE           (1UL << 28)
 
+#define MSR_PLATFORM_INFO              0x000000ce
 #define MSR_MTRRcap                    0x000000fe
 #define MSR_IA32_BBL_CR_CTL            0x00000119
 #define MSR_IA32_BBL_CR_CTL3           0x0000011e
index 529c8931fc029faffb4f4437ef74dd4fedb538f3..dab7580c47aee2e71e501afbfa94c17e2790777d 100644 (file)
@@ -101,6 +101,10 @@ static struct event_constraint intel_snb_event_constraints[] __read_mostly =
        FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
        FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
        FIXED_EVENT_CONSTRAINT(0x0300, 2), /* CPU_CLK_UNHALTED.REF */
+       INTEL_UEVENT_CONSTRAINT(0x04a3, 0xf), /* CYCLE_ACTIVITY.CYCLES_NO_DISPATCH */
+       INTEL_UEVENT_CONSTRAINT(0x05a3, 0xf), /* CYCLE_ACTIVITY.STALLS_L2_PENDING */
+       INTEL_UEVENT_CONSTRAINT(0x02a3, 0x4), /* CYCLE_ACTIVITY.CYCLES_L1D_PENDING */
+       INTEL_UEVENT_CONSTRAINT(0x06a3, 0x4), /* CYCLE_ACTIVITY.STALLS_L1D_PENDING */
        INTEL_EVENT_CONSTRAINT(0x48, 0x4), /* L1D_PEND_MISS.PENDING */
        INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
        INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
index 826054a4f2ee4c54ea4cfb9d29ab117db35e7fc5..b05a575d56f42f4543504b999a3b4875de110772 100644 (file)
@@ -729,3 +729,13 @@ void intel_ds_init(void)
                }
        }
 }
+
+void perf_restore_debug_store(void)
+{
+       struct debug_store *ds = __this_cpu_read(cpu_hw_events.ds);
+
+       if (!x86_pmu.bts && !x86_pmu.pebs)
+               return;
+
+       wrmsrl(MSR_IA32_DS_AREA, (unsigned long)ds);
+}
index 3f06e61499814ee368ddcf6ec41a690cdfbea3c5..7bfe318d3d8a4a50b07bd8c02865c9f4af3496d7 100644 (file)
@@ -375,6 +375,9 @@ static void __kprobes arch_copy_kprobe(struct kprobe *p)
        else
                p->ainsn.boostable = -1;
 
+       /* Check whether the instruction modifies Interrupt Flag or not */
+       p->ainsn.if_modifier = is_IF_modifier(p->ainsn.insn);
+
        /* Also, displacement change doesn't affect the first byte */
        p->opcode = p->ainsn.insn[0];
 }
@@ -434,7 +437,7 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
        __this_cpu_write(current_kprobe, p);
        kcb->kprobe_saved_flags = kcb->kprobe_old_flags
                = (regs->flags & (X86_EFLAGS_TF | X86_EFLAGS_IF));
-       if (is_IF_modifier(p->ainsn.insn))
+       if (p->ainsn.if_modifier)
                kcb->kprobe_saved_flags &= ~X86_EFLAGS_IF;
 }
 
index 7890bc8389524d4a1e934e23b041ab1010abf4f7..d893e8ed8ac96559b2175b00c3d68d71658a4105 100644 (file)
@@ -90,13 +90,13 @@ microcode_phys(struct microcode_intel **mc_saved_tmp,
        struct microcode_intel ***mc_saved;
 
        mc_saved = (struct microcode_intel ***)
-                  __pa_symbol(&mc_saved_data->mc_saved);
+                  __pa_nodebug(&mc_saved_data->mc_saved);
        for (i = 0; i < mc_saved_data->mc_saved_count; i++) {
                struct microcode_intel *p;
 
                p = *(struct microcode_intel **)
-                       __pa(mc_saved_data->mc_saved + i);
-               mc_saved_tmp[i] = (struct microcode_intel *)__pa(p);
+                       __pa_nodebug(mc_saved_data->mc_saved + i);
+               mc_saved_tmp[i] = (struct microcode_intel *)__pa_nodebug(p);
        }
 }
 #endif
@@ -562,7 +562,7 @@ scan_microcode(unsigned long start, unsigned long end,
        struct cpio_data cd;
        long offset = 0;
 #ifdef CONFIG_X86_32
-       char *p = (char *)__pa_symbol(ucode_name);
+       char *p = (char *)__pa_nodebug(ucode_name);
 #else
        char *p = ucode_name;
 #endif
@@ -630,8 +630,8 @@ static void __cpuinit print_ucode(struct ucode_cpu_info *uci)
        if (mc_intel == NULL)
                return;
 
-       delay_ucode_info_p = (int *)__pa_symbol(&delay_ucode_info);
-       current_mc_date_p = (int *)__pa_symbol(&current_mc_date);
+       delay_ucode_info_p = (int *)__pa_nodebug(&delay_ucode_info);
+       current_mc_date_p = (int *)__pa_nodebug(&current_mc_date);
 
        *delay_ucode_info_p = 1;
        *current_mc_date_p = mc_intel->hdr.date;
@@ -659,8 +659,8 @@ static inline void __cpuinit print_ucode(struct ucode_cpu_info *uci)
 }
 #endif
 
-static int apply_microcode_early(struct mc_saved_data *mc_saved_data,
-                                struct ucode_cpu_info *uci)
+static int __cpuinit apply_microcode_early(struct mc_saved_data *mc_saved_data,
+                                          struct ucode_cpu_info *uci)
 {
        struct microcode_intel *mc_intel;
        unsigned int val[2];
@@ -741,15 +741,15 @@ load_ucode_intel_bsp(void)
 #ifdef CONFIG_X86_32
        struct boot_params *boot_params_p;
 
-       boot_params_p = (struct boot_params *)__pa_symbol(&boot_params);
+       boot_params_p = (struct boot_params *)__pa_nodebug(&boot_params);
        ramdisk_image = boot_params_p->hdr.ramdisk_image;
        ramdisk_size  = boot_params_p->hdr.ramdisk_size;
        initrd_start_early = ramdisk_image;
        initrd_end_early = initrd_start_early + ramdisk_size;
 
        _load_ucode_intel_bsp(
-               (struct mc_saved_data *)__pa_symbol(&mc_saved_data),
-               (unsigned long *)__pa_symbol(&mc_saved_in_initrd),
+               (struct mc_saved_data *)__pa_nodebug(&mc_saved_data),
+               (unsigned long *)__pa_nodebug(&mc_saved_in_initrd),
                initrd_start_early, initrd_end_early, &uci);
 #else
        ramdisk_image = boot_params.hdr.ramdisk_image;
@@ -772,10 +772,10 @@ void __cpuinit load_ucode_intel_ap(void)
        unsigned long *initrd_start_p;
 
        mc_saved_in_initrd_p =
-               (unsigned long *)__pa_symbol(mc_saved_in_initrd);
-       mc_saved_data_p = (struct mc_saved_data *)__pa_symbol(&mc_saved_data);
-       initrd_start_p = (unsigned long *)__pa_symbol(&initrd_start);
-       initrd_start_addr = (unsigned long)__pa_symbol(*initrd_start_p);
+               (unsigned long *)__pa_nodebug(mc_saved_in_initrd);
+       mc_saved_data_p = (struct mc_saved_data *)__pa_nodebug(&mc_saved_data);
+       initrd_start_p = (unsigned long *)__pa_nodebug(&initrd_start);
+       initrd_start_addr = (unsigned long)__pa_nodebug(*initrd_start_p);
 #else
        mc_saved_data_p = &mc_saved_data;
        mc_saved_in_initrd_p = mc_saved_in_initrd;
index 02b51dd4e4ad37e4852efa0b40d110121ebbad83..f77df1c5de6eeb4ac341b9a9ac7f6afdb054b658 100644 (file)
@@ -1857,7 +1857,7 @@ int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data)
        if (!pv_eoi_enabled(vcpu))
                return 0;
        return kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.pv_eoi.data,
-                                        addr);
+                                        addr, sizeof(u8));
 }
 
 void kvm_lapic_init(void)
index f71500af1f813245bb12092665ac7dea3ba5f24f..e1721324c271e18430f43ee226a367c4495d18ab 100644 (file)
@@ -1406,25 +1406,15 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
        unsigned long flags, this_tsc_khz;
        struct kvm_vcpu_arch *vcpu = &v->arch;
        struct kvm_arch *ka = &v->kvm->arch;
-       void *shared_kaddr;
        s64 kernel_ns, max_kernel_ns;
        u64 tsc_timestamp, host_tsc;
-       struct pvclock_vcpu_time_info *guest_hv_clock;
+       struct pvclock_vcpu_time_info guest_hv_clock;
        u8 pvclock_flags;
        bool use_master_clock;
 
        kernel_ns = 0;
        host_tsc = 0;
 
-       /* Keep irq disabled to prevent changes to the clock */
-       local_irq_save(flags);
-       this_tsc_khz = __get_cpu_var(cpu_tsc_khz);
-       if (unlikely(this_tsc_khz == 0)) {
-               local_irq_restore(flags);
-               kvm_make_request(KVM_REQ_CLOCK_UPDATE, v);
-               return 1;
-       }
-
        /*
         * If the host uses TSC clock, then passthrough TSC as stable
         * to the guest.
@@ -1436,6 +1426,15 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
                kernel_ns = ka->master_kernel_ns;
        }
        spin_unlock(&ka->pvclock_gtod_sync_lock);
+
+       /* Keep irq disabled to prevent changes to the clock */
+       local_irq_save(flags);
+       this_tsc_khz = __get_cpu_var(cpu_tsc_khz);
+       if (unlikely(this_tsc_khz == 0)) {
+               local_irq_restore(flags);
+               kvm_make_request(KVM_REQ_CLOCK_UPDATE, v);
+               return 1;
+       }
        if (!use_master_clock) {
                host_tsc = native_read_tsc();
                kernel_ns = get_kernel_ns();
@@ -1463,7 +1462,7 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
 
        local_irq_restore(flags);
 
-       if (!vcpu->time_page)
+       if (!vcpu->pv_time_enabled)
                return 0;
 
        /*
@@ -1525,12 +1524,12 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
         */
        vcpu->hv_clock.version += 2;
 
-       shared_kaddr = kmap_atomic(vcpu->time_page);
-
-       guest_hv_clock = shared_kaddr + vcpu->time_offset;
+       if (unlikely(kvm_read_guest_cached(v->kvm, &vcpu->pv_time,
+               &guest_hv_clock, sizeof(guest_hv_clock))))
+               return 0;
 
        /* retain PVCLOCK_GUEST_STOPPED if set in guest copy */
-       pvclock_flags = (guest_hv_clock->flags & PVCLOCK_GUEST_STOPPED);
+       pvclock_flags = (guest_hv_clock.flags & PVCLOCK_GUEST_STOPPED);
 
        if (vcpu->pvclock_set_guest_stopped_request) {
                pvclock_flags |= PVCLOCK_GUEST_STOPPED;
@@ -1543,12 +1542,9 @@ static int kvm_guest_time_update(struct kvm_vcpu *v)
 
        vcpu->hv_clock.flags = pvclock_flags;
 
-       memcpy(shared_kaddr + vcpu->time_offset, &vcpu->hv_clock,
-              sizeof(vcpu->hv_clock));
-
-       kunmap_atomic(shared_kaddr);
-
-       mark_page_dirty(v->kvm, vcpu->time >> PAGE_SHIFT);
+       kvm_write_guest_cached(v->kvm, &vcpu->pv_time,
+                               &vcpu->hv_clock,
+                               sizeof(vcpu->hv_clock));
        return 0;
 }
 
@@ -1827,7 +1823,8 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
                return 0;
        }
 
-       if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa))
+       if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.apf.data, gpa,
+                                       sizeof(u32)))
                return 1;
 
        vcpu->arch.apf.send_user_only = !(data & KVM_ASYNC_PF_SEND_ALWAYS);
@@ -1837,10 +1834,7 @@ static int kvm_pv_enable_async_pf(struct kvm_vcpu *vcpu, u64 data)
 
 static void kvmclock_reset(struct kvm_vcpu *vcpu)
 {
-       if (vcpu->arch.time_page) {
-               kvm_release_page_dirty(vcpu->arch.time_page);
-               vcpu->arch.time_page = NULL;
-       }
+       vcpu->arch.pv_time_enabled = false;
 }
 
 static void accumulate_steal_time(struct kvm_vcpu *vcpu)
@@ -1947,6 +1941,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                break;
        case MSR_KVM_SYSTEM_TIME_NEW:
        case MSR_KVM_SYSTEM_TIME: {
+               u64 gpa_offset;
                kvmclock_reset(vcpu);
 
                vcpu->arch.time = data;
@@ -1956,14 +1951,14 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                if (!(data & 1))
                        break;
 
-               /* ...but clean it before doing the actual write */
-               vcpu->arch.time_offset = data & ~(PAGE_MASK | 1);
-
-               vcpu->arch.time_page =
-                               gfn_to_page(vcpu->kvm, data >> PAGE_SHIFT);
+               gpa_offset = data & ~(PAGE_MASK | 1);
 
-               if (is_error_page(vcpu->arch.time_page))
-                       vcpu->arch.time_page = NULL;
+               if (kvm_gfn_to_hva_cache_init(vcpu->kvm,
+                    &vcpu->arch.pv_time, data & ~1ULL,
+                    sizeof(struct pvclock_vcpu_time_info)))
+                       vcpu->arch.pv_time_enabled = false;
+               else
+                       vcpu->arch.pv_time_enabled = true;
 
                break;
        }
@@ -1980,7 +1975,8 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                        return 1;
 
                if (kvm_gfn_to_hva_cache_init(vcpu->kvm, &vcpu->arch.st.stime,
-                                                       data & KVM_STEAL_VALID_BITS))
+                                               data & KVM_STEAL_VALID_BITS,
+                                               sizeof(struct kvm_steal_time)))
                        return 1;
 
                vcpu->arch.st.msr_val = data;
@@ -2967,7 +2963,7 @@ static int kvm_vcpu_ioctl_x86_set_xcrs(struct kvm_vcpu *vcpu,
  */
 static int kvm_set_guest_paused(struct kvm_vcpu *vcpu)
 {
-       if (!vcpu->arch.time_page)
+       if (!vcpu->arch.pv_time_enabled)
                return -EINVAL;
        vcpu->arch.pvclock_set_guest_stopped_request = true;
        kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
@@ -6718,6 +6714,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
                goto fail_free_wbinvd_dirty_mask;
 
        vcpu->arch.ia32_tsc_adjust_msr = 0x0;
+       vcpu->arch.pv_time_enabled = false;
        kvm_async_pf_hash_reset(vcpu);
        kvm_pmu_init(vcpu);
 
index 05928aae911e0addaaaf1bd0fce5002ba3c9f96e..906fea3157919dcffabfe2bc4b23a1becb98aa7c 100644 (file)
@@ -74,10 +74,10 @@ copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest)
        char c;
        unsigned zero_len;
 
-       for (; len; --len) {
+       for (; len; --len, to++) {
                if (__get_user_nocheck(c, from++, sizeof(char)))
                        break;
-               if (__put_user_nocheck(c, to++, sizeof(char)))
+               if (__put_user_nocheck(c, to, sizeof(char)))
                        break;
        }
 
index 120cee1c3f8d6ab8d3873c537d063e3d45553778..3c68768d7a75963d8825f65b3ac28fff2f257361 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/suspend.h>
 #include <linux/export.h>
 #include <linux/smp.h>
+#include <linux/perf_event.h>
 
 #include <asm/pgtable.h>
 #include <asm/proto.h>
@@ -228,6 +229,7 @@ static void __restore_processor_state(struct saved_context *ctxt)
        do_fpu_end();
        x86_platform.restore_sched_clock_state();
        mtrr_bp_restore();
+       perf_restore_debug_store();
 }
 
 /* Needed by apm.c */
index e8e34938c57d86be6ba133abb033fbd7616d8f9a..6afbb2ca9a0ac450f79c6628b7cd9cd7c2ceeccf 100644 (file)
@@ -1467,8 +1467,6 @@ static void __init xen_write_cr3_init(unsigned long cr3)
        __xen_write_cr3(true, cr3);
 
        xen_mc_issue(PARAVIRT_LAZY_CPU);  /* interrupts restored */
-
-       pv_mmu_ops.write_cr3 = &xen_write_cr3;
 }
 #endif
 
@@ -2122,6 +2120,7 @@ static void __init xen_post_allocator_init(void)
 #endif
 
 #ifdef CONFIG_X86_64
+       pv_mmu_ops.write_cr3 = &xen_write_cr3;
        SetPagePinned(virt_to_page(level3_user_vsyscall));
 #endif
        xen_mark_init_mm_pinned();
index 35876ffac11d19875b15828a2d8bee3c51081baa..b09de49dbec5cf0a7d65590afc7c2a97158399bf 100644 (file)
@@ -9,7 +9,7 @@ config XTENSA
        select HAVE_IDE
        select GENERIC_ATOMIC64
        select HAVE_GENERIC_HARDIRQS
-       select HAVE_VIRT_TO_BUS
+       select VIRT_TO_BUS
        select GENERIC_IRQ_SHOW
        select GENERIC_CPU_DEVICES
        select MODULES_USE_ELF_RELA
index db8f1b5078570fe98afb8dd748636060511ba683..cc2b827a853cdea378f1c54edeadd65546b33651 100644 (file)
@@ -444,7 +444,7 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask,
         * copied from blk_rq_pos(rq).
         */
        if (error_sector)
-               *error_sector = bio->bi_sector;
+               *error_sector = bio->bi_sector;
 
        if (!bio_flagged(bio, BIO_UPTODATE))
                ret = -EIO;
index 789cdea05893bb8e3420ede5d1aa65e7af408e1b..ae95ee6a58aad6d005affa10bb270bdf1008e986 100644 (file)
@@ -257,6 +257,7 @@ void delete_partition(struct gendisk *disk, int partno)
 
        hd_struct_put(part);
 }
+EXPORT_SYMBOL(delete_partition);
 
 static ssize_t whole_disk_show(struct device *dev,
                               struct device_attribute *attr, char *buf)
index 202fa6d051b97b24d084aa0962d9135eea5cd798..847f8e31f3dd8e5c475d8f8b8ef26ca181ceb596 100644 (file)
@@ -162,4 +162,6 @@ source "drivers/irqchip/Kconfig"
 
 source "drivers/ipack/Kconfig"
 
+source "drivers/reset/Kconfig"
+
 endmenu
index dce39a95fa71ee028285ebaa6d3a105eca1b4b97..1a64c4cd9094b8f1df1c79dd5793ca723a54cce8 100644 (file)
@@ -37,6 +37,9 @@ obj-$(CONFIG_XEN)             += xen/
 # regulators early, since some subsystems rely on them to initialize
 obj-$(CONFIG_REGULATOR)                += regulator/
 
+# reset controllers early, since gpu drivers might rely on them to initialize
+obj-$(CONFIG_RESET_CONTROLLER) += reset/
+
 # tty/ comes before char/ so that the VT console is the boot-time
 # default.
 obj-y                          += tty/
index 92ed9692c47e8f63e4f5bae061f2ed29e62b4e76..4bf68c8d479733b71d33332e41afaa90654511ff 100644 (file)
@@ -396,7 +396,7 @@ config ACPI_CUSTOM_METHOD
 
 config ACPI_BGRT
        bool "Boottime Graphics Resource Table support"
-       depends on EFI
+       depends on EFI && X86
         help
          This driver adds support for exposing the ACPI Boottime Graphics
          Resource Table, which allows the operating system to obtain
index 82045e3f5caca124fd4f12c7605314e1f572580e..a82c7626aa9bc684ea96e92460cdfd7f8b2b83a3 100644 (file)
@@ -90,7 +90,7 @@ void acpi_i2c_register_devices(struct i2c_adapter *adapter)
        acpi_handle handle;
        acpi_status status;
 
-       handle = ACPI_HANDLE(&adapter->dev);
+       handle = ACPI_HANDLE(adapter->dev.parent);
        if (!handle)
                return;
 
index 1e5d8a40101e274f5d6ce2bfe1a24a486a671af7..fefc2ca7cc3e0199b5f98b707107d424dd40b8eb 100644 (file)
@@ -405,7 +405,7 @@ int apei_estatus_check(const struct acpi_hest_generic_status *estatus)
                return rc;
        data_len = estatus->data_length;
        gdata = (struct acpi_hest_generic_data *)(estatus + 1);
-       while (data_len > sizeof(*gdata)) {
+       while (data_len >= sizeof(*gdata)) {
                gedata_len = gdata->error_data_length;
                if (gedata_len > data_len - sizeof(*gdata))
                        return -EINVAL;
index 0ac546d5e53f5b0f079792c71419dd07001fe892..6ae5e440436ef46a9ca518303575fa31963cb23f 100644 (file)
@@ -415,7 +415,6 @@ static int acpi_pci_root_add(struct acpi_device *device,
        struct acpi_pci_root *root;
        struct acpi_pci_driver *driver;
        u32 flags, base_flags;
-       bool is_osc_granted = false;
 
        root = kzalloc(sizeof(struct acpi_pci_root), GFP_KERNEL);
        if (!root)
@@ -476,6 +475,30 @@ static int acpi_pci_root_add(struct acpi_device *device,
        flags = base_flags = OSC_PCI_SEGMENT_GROUPS_SUPPORT;
        acpi_pci_osc_support(root, flags);
 
+       /*
+        * TBD: Need PCI interface for enumeration/configuration of roots.
+        */
+
+       mutex_lock(&acpi_pci_root_lock);
+       list_add_tail(&root->node, &acpi_pci_roots);
+       mutex_unlock(&acpi_pci_root_lock);
+
+       /*
+        * Scan the Root Bridge
+        * --------------------
+        * Must do this prior to any attempt to bind the root device, as the
+        * PCI namespace does not get created until this call is made (and
+        * thus the root bridge's pci_dev does not exist).
+        */
+       root->bus = pci_acpi_scan_root(root);
+       if (!root->bus) {
+               printk(KERN_ERR PREFIX
+                           "Bus %04x:%02x not present in PCI namespace\n",
+                           root->segment, (unsigned int)root->secondary.start);
+               result = -ENODEV;
+               goto out_del_root;
+       }
+
        /* Indicate support for various _OSC capabilities. */
        if (pci_ext_cfg_avail())
                flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
@@ -494,6 +517,7 @@ static int acpi_pci_root_add(struct acpi_device *device,
                        flags = base_flags;
                }
        }
+
        if (!pcie_ports_disabled
            && (flags & ACPI_PCIE_REQ_SUPPORT) == ACPI_PCIE_REQ_SUPPORT) {
                flags = OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL
@@ -514,54 +538,28 @@ static int acpi_pci_root_add(struct acpi_device *device,
                status = acpi_pci_osc_control_set(device->handle, &flags,
                                       OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
                if (ACPI_SUCCESS(status)) {
-                       is_osc_granted = true;
                        dev_info(&device->dev,
                                "ACPI _OSC control (0x%02x) granted\n", flags);
+                       if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM) {
+                               /*
+                                * We have ASPM control, but the FADT indicates
+                                * that it's unsupported. Clear it.
+                                */
+                               pcie_clear_aspm(root->bus);
+                       }
                } else {
-                       is_osc_granted = false;
                        dev_info(&device->dev,
                                "ACPI _OSC request failed (%s), "
                                "returned control mask: 0x%02x\n",
                                acpi_format_exception(status), flags);
+                       pr_info("ACPI _OSC control for PCIe not granted, "
+                               "disabling ASPM\n");
+                       pcie_no_aspm();
                }
        } else {
                dev_info(&device->dev,
-                       "Unable to request _OSC control "
-                       "(_OSC support mask: 0x%02x)\n", flags);
-       }
-
-       /*
-        * TBD: Need PCI interface for enumeration/configuration of roots.
-        */
-
-       mutex_lock(&acpi_pci_root_lock);
-       list_add_tail(&root->node, &acpi_pci_roots);
-       mutex_unlock(&acpi_pci_root_lock);
-
-       /*
-        * Scan the Root Bridge
-        * --------------------
-        * Must do this prior to any attempt to bind the root device, as the
-        * PCI namespace does not get created until this call is made (and 
-        * thus the root bridge's pci_dev does not exist).
-        */
-       root->bus = pci_acpi_scan_root(root);
-       if (!root->bus) {
-               printk(KERN_ERR PREFIX
-                           "Bus %04x:%02x not present in PCI namespace\n",
-                           root->segment, (unsigned int)root->secondary.start);
-               result = -ENODEV;
-               goto out_del_root;
-       }
-
-       /* ASPM setting */
-       if (is_osc_granted) {
-               if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_ASPM)
-                       pcie_clear_aspm(root->bus);
-       } else {
-               pr_info("ACPI _OSC control for PCIe not granted, "
-                       "disabling ASPM\n");
-               pcie_no_aspm();
+                        "Unable to request _OSC control "
+                        "(_OSC support mask: 0x%02x)\n", flags);
        }
 
        pci_acpi_add_bus_pm_notifier(device, root->bus);
@@ -646,6 +644,7 @@ static void handle_root_bridge_insertion(acpi_handle handle)
 
 static void handle_root_bridge_removal(struct acpi_device *device)
 {
+       acpi_status status;
        struct acpi_eject_event *ej_event;
 
        ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL);
@@ -661,7 +660,9 @@ static void handle_root_bridge_removal(struct acpi_device *device)
        ej_event->device = device;
        ej_event->event = ACPI_NOTIFY_EJECT_REQUEST;
 
-       acpi_bus_hot_remove_device(ej_event);
+       status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event);
+       if (ACPI_FAILURE(status))
+               kfree(ej_event);
 }
 
 static void _handle_hotplug_event_root(struct work_struct *work)
@@ -676,8 +677,9 @@ static void _handle_hotplug_event_root(struct work_struct *work)
        handle = hp_work->handle;
        type = hp_work->type;
 
-       root = acpi_pci_find_root(handle);
+       acpi_scan_lock_acquire();
 
+       root = acpi_pci_find_root(handle);
        acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer);
 
        switch (type) {
@@ -711,6 +713,7 @@ static void _handle_hotplug_event_root(struct work_struct *work)
                break;
        }
 
+       acpi_scan_lock_release();
        kfree(hp_work); /* allocated in handle_hotplug_event_bridge */
        kfree(buffer.pointer);
 }
index fc95308e9a114896289922869ff068f486fdf788..ee255c60bdacc5a53849d23a5f0c1332e5f64b22 100644 (file)
@@ -66,7 +66,8 @@ module_param(latency_factor, uint, 0644);
 
 static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device);
 
-static struct acpi_processor_cx *acpi_cstate[CPUIDLE_STATE_MAX];
+static DEFINE_PER_CPU(struct acpi_processor_cx * [CPUIDLE_STATE_MAX],
+                                                               acpi_cstate);
 
 static int disabled_by_idle_boot_param(void)
 {
@@ -722,7 +723,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
                struct cpuidle_driver *drv, int index)
 {
        struct acpi_processor *pr;
-       struct acpi_processor_cx *cx = acpi_cstate[index];
+       struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
 
        pr = __this_cpu_read(processors);
 
@@ -745,7 +746,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
  */
 static int acpi_idle_play_dead(struct cpuidle_device *dev, int index)
 {
-       struct acpi_processor_cx *cx = acpi_cstate[index];
+       struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
 
        ACPI_FLUSH_CPU_CACHE();
 
@@ -775,7 +776,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
                struct cpuidle_driver *drv, int index)
 {
        struct acpi_processor *pr;
-       struct acpi_processor_cx *cx = acpi_cstate[index];
+       struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
 
        pr = __this_cpu_read(processors);
 
@@ -833,7 +834,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
                struct cpuidle_driver *drv, int index)
 {
        struct acpi_processor *pr;
-       struct acpi_processor_cx *cx = acpi_cstate[index];
+       struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu);
 
        pr = __this_cpu_read(processors);
 
@@ -960,7 +961,7 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr,
                    !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED))
                        continue;
 #endif
-               acpi_cstate[count] = cx;
+               per_cpu(acpi_cstate[count], dev->cpu) = cx;
 
                count++;
                if (count == CPUIDLE_STATE_MAX)
index 53e7ac9403a7dc21502e90a698ef1b27ad668a37..e854582f29a672a5920500333e26a0b77b310e58 100644 (file)
@@ -465,7 +465,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr)
        return result;
 }
 
-static int acpi_processor_get_performance_info(struct acpi_processor *pr)
+int acpi_processor_get_performance_info(struct acpi_processor *pr)
 {
        int result = 0;
        acpi_status status = AE_OK;
@@ -509,7 +509,7 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr)
 #endif
        return result;
 }
-
+EXPORT_SYMBOL_GPL(acpi_processor_get_performance_info);
 int acpi_processor_notify_smm(struct module *calling_module)
 {
        acpi_status status;
index 24213033fbae2aee5f033c2a776d2b37084fc88e..9c1a435d10e69c8228516346832a8d2d2d242890 100644 (file)
@@ -193,6 +193,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = {
        },
        {
        .callback = init_nvs_nosave,
+       .ident = "Sony Vaio VGN-FW21M",
+       .matches = {
+               DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+               DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21M"),
+               },
+       },
+       {
+       .callback = init_nvs_nosave,
        .ident = "Sony Vaio VPCEB17FX",
        .matches = {
                DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
index 093c435549631db21748b17827a433d8428ad862..1f44e56cc65d3c0262f4217c0040bd7c82c47569 100644 (file)
@@ -158,7 +158,7 @@ int tegra_ahb_enable_smmu(struct device_node *dn)
 EXPORT_SYMBOL(tegra_ahb_enable_smmu);
 #endif
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
 static int tegra_ahb_suspend(struct device *dev)
 {
        int i;
index 3e751b74615eac73bbf1835aa404337cd0cd6431..a5a3ebcbdd2cf6295028f62d0fe1d3bb21397633 100644 (file)
@@ -59,15 +59,16 @@ config ATA_ACPI
          option libata.noacpi=1
 
 config SATA_ZPODD
-       bool "SATA Zero Power ODD Support"
+       bool "SATA Zero Power Optical Disc Drive (ZPODD) support"
        depends on ATA_ACPI
        default n
        help
-         This option adds support for SATA ZPODD. It requires both
-         ODD and the platform support, and if enabled, will automatically
-         power on/off the ODD when certain condition is satisfied. This
-         does not impact user's experience of the ODD, only power is saved
-         when ODD is not in use(i.e. no disc inside).
+         This option adds support for SATA Zero Power Optical Disc
+         Drive (ZPODD). It requires both the ODD and the platform
+         support, and if enabled, will automatically power on/off the
+         ODD when certain condition is satisfied. This does not impact
+         end user's experience of the ODD, only power is saved when
+         the ODD is not in use (i.e. no disc inside).
 
          If unsure, say N.
 
index a99112cfd8b1e8524558ce659754d5c501e7c0fe..6a67b07de49439a1bbe3da827ef4750bd74269a8 100644 (file)
@@ -281,6 +281,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */
        { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */
        { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */
+       { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */
+       { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */
        { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */
        { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */
        { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */
index d2ba439cfe54f33f3dd6ad040b8ea1e909602a9f..ffdd32d22602296875ff395a1fdc08e32509c393 100644 (file)
@@ -1547,6 +1547,10 @@ static bool piix_broken_system_poweroff(struct pci_dev *pdev)
 
 static int prefer_ms_hyperv = 1;
 module_param(prefer_ms_hyperv, int, 0);
+MODULE_PARM_DESC(prefer_ms_hyperv,
+       "Prefer Hyper-V paravirtualization drivers instead of ATA, "
+       "0 - Use ATA drivers, "
+       "1 (Default) - Use the paravirtualization drivers.");
 
 static void piix_ignore_devices_quirk(struct ata_host *host)
 {
index beea3115577e31a687532cbc1cd3319d900e34a6..8a52dab412e2a8013f36bd547460924c79c996aa 100644 (file)
@@ -1027,7 +1027,7 @@ static void ata_acpi_register_power_resource(struct ata_device *dev)
 
        handle = ata_dev_acpi_handle(dev);
        if (handle)
-               acpi_dev_pm_remove_dependent(handle, &sdev->sdev_gendev);
+               acpi_dev_pm_add_dependent(handle, &sdev->sdev_gendev);
 }
 
 static void ata_acpi_unregister_power_resource(struct ata_device *dev)
index 70b0e01372b3da34564f53352aa075fa1ab39bf1..6ef27e98c50894190e74f396e19e13a44713157c 100644 (file)
@@ -661,18 +661,7 @@ static struct platform_driver pata_s3c_driver = {
        },
 };
 
-static int __init pata_s3c_init(void)
-{
-       return platform_driver_probe(&pata_s3c_driver, pata_s3c_probe);
-}
-
-static void __exit pata_s3c_exit(void)
-{
-       platform_driver_unregister(&pata_s3c_driver);
-}
-
-module_init(pata_s3c_init);
-module_exit(pata_s3c_exit);
+module_platform_driver_probe(pata_s3c_driver, pata_s3c_probe);
 
 MODULE_AUTHOR("Abhilash Kesavan, <a.kesavan@samsung.com>");
 MODULE_DESCRIPTION("low-level driver for Samsung PATA controller");
index 124b2c1d9c0b020255870dec161d41626562fcca..608f82fed632be1738c019f6fcfac6117b657a8d 100644 (file)
@@ -1511,8 +1511,7 @@ error_exit_with_cleanup:
 
        if (hcr_base)
                iounmap(hcr_base);
-       if (host_priv)
-               kfree(host_priv);
+       kfree(host_priv);
 
        return retval;
 }
index 5f74587ef258f4598e16c37bf9284d108c475ead..71671c42ef457e3486f13b770114a0c09459a708 100644 (file)
@@ -46,6 +46,7 @@
 #include "power.h"
 
 static DEFINE_MUTEX(dev_pm_qos_mtx);
+static DEFINE_MUTEX(dev_pm_qos_sysfs_mtx);
 
 static BLOCKING_NOTIFIER_HEAD(dev_pm_notifiers);
 
@@ -216,12 +217,17 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
        struct pm_qos_constraints *c;
        struct pm_qos_flags *f;
 
-       mutex_lock(&dev_pm_qos_mtx);
+       mutex_lock(&dev_pm_qos_sysfs_mtx);
 
        /*
         * If the device's PM QoS resume latency limit or PM QoS flags have been
         * exposed to user space, they have to be hidden at this point.
         */
+       pm_qos_sysfs_remove_latency(dev);
+       pm_qos_sysfs_remove_flags(dev);
+
+       mutex_lock(&dev_pm_qos_mtx);
+
        __dev_pm_qos_hide_latency_limit(dev);
        __dev_pm_qos_hide_flags(dev);
 
@@ -254,6 +260,8 @@ void dev_pm_qos_constraints_destroy(struct device *dev)
 
  out:
        mutex_unlock(&dev_pm_qos_mtx);
+
+       mutex_unlock(&dev_pm_qos_sysfs_mtx);
 }
 
 /**
@@ -558,6 +566,14 @@ static void __dev_pm_qos_drop_user_request(struct device *dev,
        kfree(req);
 }
 
+static void dev_pm_qos_drop_user_request(struct device *dev,
+                                        enum dev_pm_qos_req_type type)
+{
+       mutex_lock(&dev_pm_qos_mtx);
+       __dev_pm_qos_drop_user_request(dev, type);
+       mutex_unlock(&dev_pm_qos_mtx);
+}
+
 /**
  * dev_pm_qos_expose_latency_limit - Expose PM QoS latency limit to user space.
  * @dev: Device whose PM QoS latency limit is to be exposed to user space.
@@ -581,6 +597,8 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
                return ret;
        }
 
+       mutex_lock(&dev_pm_qos_sysfs_mtx);
+
        mutex_lock(&dev_pm_qos_mtx);
 
        if (IS_ERR_OR_NULL(dev->power.qos))
@@ -591,26 +609,27 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value)
        if (ret < 0) {
                __dev_pm_qos_remove_request(req);
                kfree(req);
+               mutex_unlock(&dev_pm_qos_mtx);
                goto out;
        }
-
        dev->power.qos->latency_req = req;
+
+       mutex_unlock(&dev_pm_qos_mtx);
+
        ret = pm_qos_sysfs_add_latency(dev);
        if (ret)
-               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
+               dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
 
  out:
-       mutex_unlock(&dev_pm_qos_mtx);
+       mutex_unlock(&dev_pm_qos_sysfs_mtx);
        return ret;
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit);
 
 static void __dev_pm_qos_hide_latency_limit(struct device *dev)
 {
-       if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req) {
-               pm_qos_sysfs_remove_latency(dev);
+       if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req)
                __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY);
-       }
 }
 
 /**
@@ -619,9 +638,15 @@ static void __dev_pm_qos_hide_latency_limit(struct device *dev)
  */
 void dev_pm_qos_hide_latency_limit(struct device *dev)
 {
+       mutex_lock(&dev_pm_qos_sysfs_mtx);
+
+       pm_qos_sysfs_remove_latency(dev);
+
        mutex_lock(&dev_pm_qos_mtx);
        __dev_pm_qos_hide_latency_limit(dev);
        mutex_unlock(&dev_pm_qos_mtx);
+
+       mutex_unlock(&dev_pm_qos_sysfs_mtx);
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit);
 
@@ -649,6 +674,8 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val)
        }
 
        pm_runtime_get_sync(dev);
+       mutex_lock(&dev_pm_qos_sysfs_mtx);
+
        mutex_lock(&dev_pm_qos_mtx);
 
        if (IS_ERR_OR_NULL(dev->power.qos))
@@ -659,16 +686,19 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val)
        if (ret < 0) {
                __dev_pm_qos_remove_request(req);
                kfree(req);
+               mutex_unlock(&dev_pm_qos_mtx);
                goto out;
        }
-
        dev->power.qos->flags_req = req;
+
+       mutex_unlock(&dev_pm_qos_mtx);
+
        ret = pm_qos_sysfs_add_flags(dev);
        if (ret)
-               __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
+               dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
 
  out:
-       mutex_unlock(&dev_pm_qos_mtx);
+       mutex_unlock(&dev_pm_qos_sysfs_mtx);
        pm_runtime_put(dev);
        return ret;
 }
@@ -676,10 +706,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags);
 
 static void __dev_pm_qos_hide_flags(struct device *dev)
 {
-       if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req) {
-               pm_qos_sysfs_remove_flags(dev);
+       if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req)
                __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS);
-       }
 }
 
 /**
@@ -689,9 +717,15 @@ static void __dev_pm_qos_hide_flags(struct device *dev)
 void dev_pm_qos_hide_flags(struct device *dev)
 {
        pm_runtime_get_sync(dev);
+       mutex_lock(&dev_pm_qos_sysfs_mtx);
+
+       pm_qos_sysfs_remove_flags(dev);
+
        mutex_lock(&dev_pm_qos_mtx);
        __dev_pm_qos_hide_flags(dev);
        mutex_unlock(&dev_pm_qos_mtx);
+
+       mutex_unlock(&dev_pm_qos_sysfs_mtx);
        pm_runtime_put(dev);
 }
 EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags);
index e6732cf7c06eea7aedf62e383a390ef3e61c3fe2..79f4fca9877a579cd3b5c787fa7de4c1ed75612f 100644 (file)
@@ -398,7 +398,7 @@ static int regcache_rbtree_sync(struct regmap *map, unsigned int min,
                        base = 0;
 
                if (max < rbnode->base_reg + rbnode->blklen)
-                       end = rbnode->base_reg + rbnode->blklen - max;
+                       end = max - rbnode->base_reg + 1;
                else
                        end = rbnode->blklen;
 
index 3d2367501fd0521ee4e472df6126b6ea25ee09a3..d34adef1e63e2bee55aa3cd5a9e7f2d98912103b 100644 (file)
@@ -710,12 +710,12 @@ skip_format_initialization:
                }
        }
 
+       regmap_debugfs_init(map, config->name);
+
        ret = regcache_init(map, config);
        if (ret != 0)
                goto err_range;
 
-       regmap_debugfs_init(map, config->name);
-
        /* Add a devres resource for dev_get_regmap() */
        m = devres_alloc(dev_get_regmap_release, sizeof(*m), GFP_KERNEL);
        if (!m) {
@@ -943,8 +943,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
                unsigned int ival;
                int val_bytes = map->format.val_bytes;
                for (i = 0; i < val_len / val_bytes; i++) {
-                       memcpy(map->work_buf, val + (i * val_bytes), val_bytes);
-                       ival = map->format.parse_val(map->work_buf);
+                       ival = map->format.parse_val(val + (i * val_bytes));
                        ret = regcache_write(map, reg + (i * map->reg_stride),
                                             ival);
                        if (ret) {
@@ -1036,6 +1035,8 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
                        kfree(async->work_buf);
                        kfree(async);
                }
+
+               return ret;
        }
 
        trace_regmap_hw_write_start(map->dev, reg,
index 5dc0daed8fac523f5d631c3cd4a022f6fb4c5aca..b81ddfea1da075ad3c1d0cbeb9ab7bf854593436 100644 (file)
@@ -532,11 +532,11 @@ config BLK_DEV_RBD
          If unsure, say N.
 
 config BLK_DEV_RSXX
-       tristate "RamSam PCIe Flash SSD Device Driver"
+       tristate "IBM FlashSystem 70/80 PCIe SSD Device Driver"
        depends on PCI
        help
          Device driver for IBM's high speed PCIe SSD
-         storage devices: RamSan-70 and RamSan-80.
+         storage devices: FlashSystem-70 and FlashSystem-80.
 
          To compile this driver as a module, choose M here: the
          module will be called rsxx.
index 25ef5c014fcaa4255e0e3009991b6a9ac1ff18c7..92b6d7c51e39590b3780f17c88737009b7becbbf 100644 (file)
@@ -51,8 +51,9 @@ new_skb(ulong len)
 {
        struct sk_buff *skb;
 
-       skb = alloc_skb(len, GFP_ATOMIC);
+       skb = alloc_skb(len + MAX_HEADER, GFP_ATOMIC);
        if (skb) {
+               skb_reserve(skb, MAX_HEADER);
                skb_reset_mac_header(skb);
                skb_reset_network_header(skb);
                skb->protocol = __constant_htons(ETH_P_AOE);
index ade58bc8f3c4dee67f69edde4ce20b1ef18d7cc8..1c1b8e544aa250d38710b47c19353c9ef5773c6c 100644 (file)
@@ -4206,7 +4206,7 @@ static int cciss_find_cfgtables(ctlr_info_t *h)
        if (rc)
                return rc;
        h->cfgtable = remap_pci_mem(pci_resource_start(h->pdev,
-               cfg_base_addr_index) + cfg_offset, sizeof(h->cfgtable));
+               cfg_base_addr_index) + cfg_offset, sizeof(*h->cfgtable));
        if (!h->cfgtable)
                return -ENOMEM;
        rc = write_driver_ver_to_cfgtable(h->cfgtable);
index 747bb2af69dcc55fec530466a9f55d06914ba8f7..2c127f9c3f3bf9e5966172e5255efa3a0d35b595 100644 (file)
@@ -922,6 +922,11 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode,
                lo->lo_flags |= LO_FLAGS_PARTSCAN;
        if (lo->lo_flags & LO_FLAGS_PARTSCAN)
                ioctl_by_bdev(bdev, BLKRRPART, 0);
+
+       /* Grab the block_device to prevent its destruction after we
+        * put /dev/loopXX inode. Later in loop_clr_fd() we bdput(bdev).
+        */
+       bdgrab(bdev);
        return 0;
 
 out_clr:
@@ -1031,8 +1036,10 @@ static int loop_clr_fd(struct loop_device *lo)
        memset(lo->lo_encrypt_key, 0, LO_KEY_SIZE);
        memset(lo->lo_crypt_name, 0, LO_NAME_SIZE);
        memset(lo->lo_file_name, 0, LO_NAME_SIZE);
-       if (bdev)
+       if (bdev) {
+               bdput(bdev);
                invalidate_bdev(bdev);
+       }
        set_capacity(lo->lo_disk, 0);
        loop_sysfs_exit(lo);
        if (bdev) {
@@ -1044,12 +1051,29 @@ static int loop_clr_fd(struct loop_device *lo)
        lo->lo_state = Lo_unbound;
        /* This is safe: open() is still holding a reference. */
        module_put(THIS_MODULE);
-       if (lo->lo_flags & LO_FLAGS_PARTSCAN && bdev)
-               ioctl_by_bdev(bdev, BLKRRPART, 0);
        lo->lo_flags = 0;
        if (!part_shift)
                lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN;
        mutex_unlock(&lo->lo_ctl_mutex);
+
+       /*
+        * Remove all partitions, since BLKRRPART won't remove user
+        * added partitions when max_part=0
+        */
+       if (bdev) {
+               struct disk_part_iter piter;
+               struct hd_struct *part;
+
+               mutex_lock_nested(&bdev->bd_mutex, 1);
+               invalidate_partition(bdev->bd_disk, 0);
+               disk_part_iter_init(&piter, bdev->bd_disk,
+                                       DISK_PITER_INCL_EMPTY);
+               while ((part = disk_part_iter_next(&piter)))
+                       delete_partition(bdev->bd_disk, part->partno);
+               disk_part_iter_exit(&piter);
+               mutex_unlock(&bdev->bd_mutex);
+       }
+
        /*
         * Need not hold lo_ctl_mutex to fput backing file.
         * Calling fput holding lo_ctl_mutex triggers a circular
@@ -1623,6 +1647,7 @@ static int loop_add(struct loop_device **l, int i)
                goto out_free_dev;
        i = err;
 
+       err = -ENOMEM;
        lo->lo_queue = blk_alloc_queue(GFP_KERNEL);
        if (!lo->lo_queue)
                goto out_free_dev;
index 1788f491e0fb50e13cefb2f81c286d41721e75ef..076ae7f1b781e0b1586631b2708471ce98f978c1 100644 (file)
@@ -890,8 +890,10 @@ static int mg_probe(struct platform_device *plat_dev)
        gpio_direction_output(host->rst, 1);
 
        /* reset out pin */
-       if (!(prv_data->dev_attr & MG_DEV_MASK))
+       if (!(prv_data->dev_attr & MG_DEV_MASK)) {
+               err = -EINVAL;
                goto probe_err_3a;
+       }
 
        if (prv_data->dev_attr != MG_BOOT_DEV) {
                rsc = platform_get_resource_byname(plat_dev, IORESOURCE_IO,
index 11cc9522cdd439ff3db29825037c4f866bc28abb..92250af84e7d151a8da57ed2cf6d22d8e3313e9d 100644 (file)
@@ -4224,6 +4224,7 @@ static int mtip_pci_probe(struct pci_dev *pdev,
        dd->isr_workq = create_workqueue(dd->workq_name);
        if (!dd->isr_workq) {
                dev_warn(&pdev->dev, "Can't create wq %d\n", dd->instance);
+               rv = -ENOMEM;
                goto block_initialize_err;
        }
 
@@ -4282,7 +4283,8 @@ static int mtip_pci_probe(struct pci_dev *pdev,
        INIT_WORK(&dd->work[7].work, mtip_workq_sdbf7);
 
        pci_set_master(pdev);
-       if (pci_enable_msi(pdev)) {
+       rv = pci_enable_msi(pdev);
+       if (rv) {
                dev_warn(&pdev->dev,
                        "Unable to enable MSI interrupt.\n");
                goto block_initialize_err;
index 07fb2dfaae13f02588128ea0d73372a8859b63ba..9dcefe40380bf23ca7c1675b4286c5f97a480d79 100644 (file)
@@ -135,6 +135,7 @@ static inline void _nvme_check_size(void)
        BUILD_BUG_ON(sizeof(struct nvme_id_ctrl) != 4096);
        BUILD_BUG_ON(sizeof(struct nvme_id_ns) != 4096);
        BUILD_BUG_ON(sizeof(struct nvme_lba_range_type) != 64);
+       BUILD_BUG_ON(sizeof(struct nvme_smart_log) != 512);
 }
 
 typedef void (*nvme_completion_fn)(struct nvme_dev *, void *,
@@ -237,7 +238,8 @@ static void *free_cmdid(struct nvme_queue *nvmeq, int cmdid,
                *fn = special_completion;
                return CMD_CTX_INVALID;
        }
-       *fn = info[cmdid].fn;
+       if (fn)
+               *fn = info[cmdid].fn;
        ctx = info[cmdid].ctx;
        info[cmdid].fn = special_completion;
        info[cmdid].ctx = CMD_CTX_COMPLETED;
@@ -335,6 +337,7 @@ nvme_alloc_iod(unsigned nseg, unsigned nbytes, gfp_t gfp)
                iod->offset = offsetof(struct nvme_iod, sg[nseg]);
                iod->npages = -1;
                iod->length = nbytes;
+               iod->nents = 0;
        }
 
        return iod;
@@ -375,7 +378,8 @@ static void bio_completion(struct nvme_dev *dev, void *ctx,
        struct bio *bio = iod->private;
        u16 status = le16_to_cpup(&cqe->status) >> 1;
 
-       dma_unmap_sg(&dev->pci_dev->dev, iod->sg, iod->nents,
+       if (iod->nents)
+               dma_unmap_sg(&dev->pci_dev->dev, iod->sg, iod->nents,
                        bio_data_dir(bio) ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
        nvme_free_iod(dev, iod);
        if (status) {
@@ -589,7 +593,7 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns,
 
        result = nvme_map_bio(nvmeq->q_dmadev, iod, bio, dma_dir, psegs);
        if (result < 0)
-               goto free_iod;
+               goto free_cmdid;
        length = result;
 
        cmnd->rw.command_id = cmdid;
@@ -609,6 +613,8 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns,
 
        return 0;
 
+ free_cmdid:
+       free_cmdid(nvmeq, cmdid, NULL);
  free_iod:
        nvme_free_iod(nvmeq->dev, iod);
  nomem:
@@ -835,8 +841,8 @@ static int nvme_identify(struct nvme_dev *dev, unsigned nsid, unsigned cns,
        return nvme_submit_admin_cmd(dev, &c, NULL);
 }
 
-static int nvme_get_features(struct nvme_dev *dev, unsigned fid,
-                               unsigned nsid, dma_addr_t dma_addr)
+static int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid,
+                                       dma_addr_t dma_addr, u32 *result)
 {
        struct nvme_command c;
 
@@ -846,7 +852,7 @@ static int nvme_get_features(struct nvme_dev *dev, unsigned fid,
        c.features.prp1 = cpu_to_le64(dma_addr);
        c.features.fid = cpu_to_le32(fid);
 
-       return nvme_submit_admin_cmd(dev, &c, NULL);
+       return nvme_submit_admin_cmd(dev, &c, result);
 }
 
 static int nvme_set_features(struct nvme_dev *dev, unsigned fid,
@@ -906,6 +912,10 @@ static void nvme_free_queue(struct nvme_dev *dev, int qid)
 
        spin_lock_irq(&nvmeq->q_lock);
        nvme_cancel_ios(nvmeq, false);
+       while (bio_list_peek(&nvmeq->sq_cong)) {
+               struct bio *bio = bio_list_pop(&nvmeq->sq_cong);
+               bio_endio(bio, -EIO);
+       }
        spin_unlock_irq(&nvmeq->q_lock);
 
        irq_set_affinity_hint(vector, NULL);
@@ -1230,12 +1240,17 @@ static int nvme_user_admin_cmd(struct nvme_dev *dev,
        if (length != cmd.data_len)
                status = -ENOMEM;
        else
-               status = nvme_submit_admin_cmd(dev, &c, NULL);
+               status = nvme_submit_admin_cmd(dev, &c, &cmd.result);
 
        if (cmd.data_len) {
                nvme_unmap_user_pages(dev, cmd.opcode & 1, iod);
                nvme_free_iod(dev, iod);
        }
+
+       if (!status && copy_to_user(&ucmd->result, &cmd.result,
+                                                       sizeof(cmd.result)))
+               status = -EFAULT;
+
        return status;
 }
 
@@ -1523,9 +1538,9 @@ static int nvme_dev_add(struct nvme_dev *dev)
                        continue;
 
                res = nvme_get_features(dev, NVME_FEAT_LBA_RANGE, i,
-                                                       dma_addr + 4096);
+                                                       dma_addr + 4096, NULL);
                if (res)
-                       continue;
+                       memset(mem + 4096, 0, 4096);
 
                ns = nvme_alloc_ns(dev, i, mem, mem + 4096);
                if (ns)
index 6c81a4c040b987e75d4a8b0bb5e4ff65e2108dba..f556f8a8b3f9b476949c6133f39778c49502e380 100644 (file)
@@ -1264,6 +1264,32 @@ static bool obj_request_done_test(struct rbd_obj_request *obj_request)
        return atomic_read(&obj_request->done) != 0;
 }
 
+static void
+rbd_img_obj_request_read_callback(struct rbd_obj_request *obj_request)
+{
+       dout("%s: obj %p img %p result %d %llu/%llu\n", __func__,
+               obj_request, obj_request->img_request, obj_request->result,
+               obj_request->xferred, obj_request->length);
+       /*
+        * ENOENT means a hole in the image.  We zero-fill the
+        * entire length of the request.  A short read also implies
+        * zero-fill to the end of the request.  Either way we
+        * update the xferred count to indicate the whole request
+        * was satisfied.
+        */
+       BUG_ON(obj_request->type != OBJ_REQUEST_BIO);
+       if (obj_request->result == -ENOENT) {
+               zero_bio_chain(obj_request->bio_list, 0);
+               obj_request->result = 0;
+               obj_request->xferred = obj_request->length;
+       } else if (obj_request->xferred < obj_request->length &&
+                       !obj_request->result) {
+               zero_bio_chain(obj_request->bio_list, obj_request->xferred);
+               obj_request->xferred = obj_request->length;
+       }
+       obj_request_done_set(obj_request);
+}
+
 static void rbd_obj_request_complete(struct rbd_obj_request *obj_request)
 {
        dout("%s: obj %p cb %p\n", __func__, obj_request,
@@ -1284,23 +1310,10 @@ static void rbd_osd_read_callback(struct rbd_obj_request *obj_request)
 {
        dout("%s: obj %p result %d %llu/%llu\n", __func__, obj_request,
                obj_request->result, obj_request->xferred, obj_request->length);
-       /*
-        * ENOENT means a hole in the object.  We zero-fill the
-        * entire length of the request.  A short read also implies
-        * zero-fill to the end of the request.  Either way we
-        * update the xferred count to indicate the whole request
-        * was satisfied.
-        */
-       if (obj_request->result == -ENOENT) {
-               zero_bio_chain(obj_request->bio_list, 0);
-               obj_request->result = 0;
-               obj_request->xferred = obj_request->length;
-       } else if (obj_request->xferred < obj_request->length &&
-                       !obj_request->result) {
-               zero_bio_chain(obj_request->bio_list, obj_request->xferred);
-               obj_request->xferred = obj_request->length;
-       }
-       obj_request_done_set(obj_request);
+       if (obj_request->img_request)
+               rbd_img_obj_request_read_callback(obj_request);
+       else
+               obj_request_done_set(obj_request);
 }
 
 static void rbd_osd_write_callback(struct rbd_obj_request *obj_request)
index f35cd0b71f7b5802ae521d046c8b582386e6c6f3..b1c53c0aa450c47ddd38bf2138bb0505f341fc61 100644 (file)
@@ -1,2 +1,2 @@
 obj-$(CONFIG_BLK_DEV_RSXX) += rsxx.o
-rsxx-y := config.o core.o cregs.o dev.o dma.o
+rsxx-objs := config.o core.o cregs.o dev.o dma.o
index a295e7e9ee41c98613ded6756ff725a615b5bafb..10cd530d3e1026fcb270e1b402a3a900363a7765 100644 (file)
 #include "rsxx_priv.h"
 #include "rsxx_cfg.h"
 
-static void initialize_config(void *config)
+static void initialize_config(struct rsxx_card_cfg *cfg)
 {
-       struct rsxx_card_cfg *cfg = config;
-
        cfg->hdr.version = RSXX_CFG_VERSION;
 
        cfg->data.block_size        = RSXX_HW_BLK_SIZE;
        cfg->data.stripe_size       = RSXX_HW_BLK_SIZE;
-       cfg->data.vendor_id         = RSXX_VENDOR_ID_TMS_IBM;
+       cfg->data.vendor_id         = RSXX_VENDOR_ID_IBM;
        cfg->data.cache_order       = (-1);
        cfg->data.intr_coal.mode    = RSXX_INTR_COAL_DISABLED;
        cfg->data.intr_coal.count   = 0;
@@ -181,7 +179,7 @@ int rsxx_load_config(struct rsxx_cardinfo *card)
        } else {
                dev_info(CARD_TO_DEV(card),
                        "Initializing card configuration.\n");
-               initialize_config(card);
+               initialize_config(&card->config);
                st = rsxx_save_config(card);
                if (st)
                        return st;
index e5162487686aef6f429b86655e22e27c9a14cddd..5af21f2db29cd1246397e3b4eed8627ba314adf2 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/reboot.h>
 #include <linux/slab.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 
 #include <linux/genhd.h>
 #include <linux/idr.h>
@@ -39,8 +40,8 @@
 
 #define NO_LEGACY 0
 
-MODULE_DESCRIPTION("IBM RamSan PCIe Flash SSD Device Driver");
-MODULE_AUTHOR("IBM <support@ramsan.com>");
+MODULE_DESCRIPTION("IBM FlashSystem 70/80 PCIe SSD Device Driver");
+MODULE_AUTHOR("Joshua Morris/Philip Kelleher, IBM");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRIVER_VERSION);
 
@@ -52,6 +53,13 @@ static DEFINE_IDA(rsxx_disk_ida);
 static DEFINE_SPINLOCK(rsxx_ida_lock);
 
 /*----------------- Interrupt Control & Handling -------------------*/
+
+static void rsxx_mask_interrupts(struct rsxx_cardinfo *card)
+{
+       card->isr_mask = 0;
+       card->ier_mask = 0;
+}
+
 static void __enable_intr(unsigned int *mask, unsigned int intr)
 {
        *mask |= intr;
@@ -71,7 +79,8 @@ static void __disable_intr(unsigned int *mask, unsigned int intr)
  */
 void rsxx_enable_ier(struct rsxx_cardinfo *card, unsigned int intr)
 {
-       if (unlikely(card->halt))
+       if (unlikely(card->halt) ||
+           unlikely(card->eeh_state))
                return;
 
        __enable_intr(&card->ier_mask, intr);
@@ -80,6 +89,9 @@ void rsxx_enable_ier(struct rsxx_cardinfo *card, unsigned int intr)
 
 void rsxx_disable_ier(struct rsxx_cardinfo *card, unsigned int intr)
 {
+       if (unlikely(card->eeh_state))
+               return;
+
        __disable_intr(&card->ier_mask, intr);
        iowrite32(card->ier_mask, card->regmap + IER);
 }
@@ -87,7 +99,8 @@ void rsxx_disable_ier(struct rsxx_cardinfo *card, unsigned int intr)
 void rsxx_enable_ier_and_isr(struct rsxx_cardinfo *card,
                                 unsigned int intr)
 {
-       if (unlikely(card->halt))
+       if (unlikely(card->halt) ||
+           unlikely(card->eeh_state))
                return;
 
        __enable_intr(&card->isr_mask, intr);
@@ -97,6 +110,9 @@ void rsxx_enable_ier_and_isr(struct rsxx_cardinfo *card,
 void rsxx_disable_ier_and_isr(struct rsxx_cardinfo *card,
                                  unsigned int intr)
 {
+       if (unlikely(card->eeh_state))
+               return;
+
        __disable_intr(&card->isr_mask, intr);
        __disable_intr(&card->ier_mask, intr);
        iowrite32(card->ier_mask, card->regmap + IER);
@@ -115,6 +131,9 @@ static irqreturn_t rsxx_isr(int irq, void *pdata)
        do {
                reread_isr = 0;
 
+               if (unlikely(card->eeh_state))
+                       break;
+
                isr = ioread32(card->regmap + ISR);
                if (isr == 0xffffffff) {
                        /*
@@ -161,9 +180,9 @@ static irqreturn_t rsxx_isr(int irq, void *pdata)
 }
 
 /*----------------- Card Event Handler -------------------*/
-static char *rsxx_card_state_to_str(unsigned int state)
+static const char * const rsxx_card_state_to_str(unsigned int state)
 {
-       static char *state_strings[] = {
+       static const char * const state_strings[] = {
                "Unknown", "Shutdown", "Starting", "Formatting",
                "Uninitialized", "Good", "Shutting Down",
                "Fault", "Read Only Fault", "dStroying"
@@ -304,6 +323,192 @@ static int card_shutdown(struct rsxx_cardinfo *card)
        return 0;
 }
 
+static int rsxx_eeh_frozen(struct pci_dev *dev)
+{
+       struct rsxx_cardinfo *card = pci_get_drvdata(dev);
+       int i;
+       int st;
+
+       dev_warn(&dev->dev, "IBM FlashSystem PCI: preparing for slot reset.\n");
+
+       card->eeh_state = 1;
+       rsxx_mask_interrupts(card);
+
+       /*
+        * We need to guarantee that the write for eeh_state and masking
+        * interrupts does not become reordered. This will prevent a possible
+        * race condition with the EEH code.
+        */
+       wmb();
+
+       pci_disable_device(dev);
+
+       st = rsxx_eeh_save_issued_dmas(card);
+       if (st)
+               return st;
+
+       rsxx_eeh_save_issued_creg(card);
+
+       for (i = 0; i < card->n_targets; i++) {
+               if (card->ctrl[i].status.buf)
+                       pci_free_consistent(card->dev, STATUS_BUFFER_SIZE8,
+                                           card->ctrl[i].status.buf,
+                                           card->ctrl[i].status.dma_addr);
+               if (card->ctrl[i].cmd.buf)
+                       pci_free_consistent(card->dev, COMMAND_BUFFER_SIZE8,
+                                           card->ctrl[i].cmd.buf,
+                                           card->ctrl[i].cmd.dma_addr);
+       }
+
+       return 0;
+}
+
+static void rsxx_eeh_failure(struct pci_dev *dev)
+{
+       struct rsxx_cardinfo *card = pci_get_drvdata(dev);
+       int i;
+
+       dev_err(&dev->dev, "IBM FlashSystem PCI: disabling failed card.\n");
+
+       card->eeh_state = 1;
+
+       for (i = 0; i < card->n_targets; i++)
+               del_timer_sync(&card->ctrl[i].activity_timer);
+
+       rsxx_eeh_cancel_dmas(card);
+}
+
+static int rsxx_eeh_fifo_flush_poll(struct rsxx_cardinfo *card)
+{
+       unsigned int status;
+       int iter = 0;
+
+       /* We need to wait for the hardware to reset */
+       while (iter++ < 10) {
+               status = ioread32(card->regmap + PCI_RECONFIG);
+
+               if (status & RSXX_FLUSH_BUSY) {
+                       ssleep(1);
+                       continue;
+               }
+
+               if (status & RSXX_FLUSH_TIMEOUT)
+                       dev_warn(CARD_TO_DEV(card), "HW: flash controller timeout\n");
+               return 0;
+       }
+
+       /* Hardware failed resetting itself. */
+       return -1;
+}
+
+static pci_ers_result_t rsxx_error_detected(struct pci_dev *dev,
+                                           enum pci_channel_state error)
+{
+       int st;
+
+       if (dev->revision < RSXX_EEH_SUPPORT)
+               return PCI_ERS_RESULT_NONE;
+
+       if (error == pci_channel_io_perm_failure) {
+               rsxx_eeh_failure(dev);
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+
+       st = rsxx_eeh_frozen(dev);
+       if (st) {
+               dev_err(&dev->dev, "Slot reset setup failed\n");
+               rsxx_eeh_failure(dev);
+               return PCI_ERS_RESULT_DISCONNECT;
+       }
+
+       return PCI_ERS_RESULT_NEED_RESET;
+}
+
+static pci_ers_result_t rsxx_slot_reset(struct pci_dev *dev)
+{
+       struct rsxx_cardinfo *card = pci_get_drvdata(dev);
+       unsigned long flags;
+       int i;
+       int st;
+
+       dev_warn(&dev->dev,
+               "IBM FlashSystem PCI: recovering from slot reset.\n");
+
+       st = pci_enable_device(dev);
+       if (st)
+               goto failed_hw_setup;
+
+       pci_set_master(dev);
+
+       st = rsxx_eeh_fifo_flush_poll(card);
+       if (st)
+               goto failed_hw_setup;
+
+       rsxx_dma_queue_reset(card);
+
+       for (i = 0; i < card->n_targets; i++) {
+               st = rsxx_hw_buffers_init(dev, &card->ctrl[i]);
+               if (st)
+                       goto failed_hw_buffers_init;
+       }
+
+       if (card->config_valid)
+               rsxx_dma_configure(card);
+
+       /* Clears the ISR register from spurious interrupts */
+       st = ioread32(card->regmap + ISR);
+
+       card->eeh_state = 0;
+
+       st = rsxx_eeh_remap_dmas(card);
+       if (st)
+               goto failed_remap_dmas;
+
+       spin_lock_irqsave(&card->irq_lock, flags);
+       if (card->n_targets & RSXX_MAX_TARGETS)
+               rsxx_enable_ier_and_isr(card, CR_INTR_ALL_G);
+       else
+               rsxx_enable_ier_and_isr(card, CR_INTR_ALL_C);
+       spin_unlock_irqrestore(&card->irq_lock, flags);
+
+       rsxx_kick_creg_queue(card);
+
+       for (i = 0; i < card->n_targets; i++) {
+               spin_lock(&card->ctrl[i].queue_lock);
+               if (list_empty(&card->ctrl[i].queue)) {
+                       spin_unlock(&card->ctrl[i].queue_lock);
+                       continue;
+               }
+               spin_unlock(&card->ctrl[i].queue_lock);
+
+               queue_work(card->ctrl[i].issue_wq,
+                               &card->ctrl[i].issue_dma_work);
+       }
+
+       dev_info(&dev->dev, "IBM FlashSystem PCI: recovery complete.\n");
+
+       return PCI_ERS_RESULT_RECOVERED;
+
+failed_hw_buffers_init:
+failed_remap_dmas:
+       for (i = 0; i < card->n_targets; i++) {
+               if (card->ctrl[i].status.buf)
+                       pci_free_consistent(card->dev,
+                                       STATUS_BUFFER_SIZE8,
+                                       card->ctrl[i].status.buf,
+                                       card->ctrl[i].status.dma_addr);
+               if (card->ctrl[i].cmd.buf)
+                       pci_free_consistent(card->dev,
+                                       COMMAND_BUFFER_SIZE8,
+                                       card->ctrl[i].cmd.buf,
+                                       card->ctrl[i].cmd.dma_addr);
+       }
+failed_hw_setup:
+       rsxx_eeh_failure(dev);
+       return PCI_ERS_RESULT_DISCONNECT;
+
+}
+
 /*----------------- Driver Initialization & Setup -------------------*/
 /* Returns:   0 if the driver is compatible with the device
             -1 if the driver is NOT compatible with the device */
@@ -383,6 +588,7 @@ static int rsxx_pci_probe(struct pci_dev *dev,
 
        spin_lock_init(&card->irq_lock);
        card->halt = 0;
+       card->eeh_state = 0;
 
        spin_lock_irq(&card->irq_lock);
        rsxx_disable_ier_and_isr(card, CR_INTR_ALL);
@@ -538,9 +744,6 @@ static void rsxx_pci_remove(struct pci_dev *dev)
        rsxx_disable_ier_and_isr(card, CR_INTR_EVENT);
        spin_unlock_irqrestore(&card->irq_lock, flags);
 
-       /* Prevent work_structs from re-queuing themselves. */
-       card->halt = 1;
-
        cancel_work_sync(&card->event_work);
 
        rsxx_destroy_dev(card);
@@ -549,6 +752,10 @@ static void rsxx_pci_remove(struct pci_dev *dev)
        spin_lock_irqsave(&card->irq_lock, flags);
        rsxx_disable_ier_and_isr(card, CR_INTR_ALL);
        spin_unlock_irqrestore(&card->irq_lock, flags);
+
+       /* Prevent work_structs from re-queuing themselves. */
+       card->halt = 1;
+
        free_irq(dev->irq, card);
 
        if (!force_legacy)
@@ -592,11 +799,14 @@ static void rsxx_pci_shutdown(struct pci_dev *dev)
        card_shutdown(card);
 }
 
+static const struct pci_error_handlers rsxx_err_handler = {
+       .error_detected = rsxx_error_detected,
+       .slot_reset     = rsxx_slot_reset,
+};
+
 static DEFINE_PCI_DEVICE_TABLE(rsxx_pci_ids) = {
-       {PCI_DEVICE(PCI_VENDOR_ID_TMS_IBM, PCI_DEVICE_ID_RS70_FLASH)},
-       {PCI_DEVICE(PCI_VENDOR_ID_TMS_IBM, PCI_DEVICE_ID_RS70D_FLASH)},
-       {PCI_DEVICE(PCI_VENDOR_ID_TMS_IBM, PCI_DEVICE_ID_RS80_FLASH)},
-       {PCI_DEVICE(PCI_VENDOR_ID_TMS_IBM, PCI_DEVICE_ID_RS81_FLASH)},
+       {PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_FS70_FLASH)},
+       {PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_FS80_FLASH)},
        {0,},
 };
 
@@ -609,6 +819,7 @@ static struct pci_driver rsxx_pci_driver = {
        .remove         = rsxx_pci_remove,
        .suspend        = rsxx_pci_suspend,
        .shutdown       = rsxx_pci_shutdown,
+       .err_handler    = &rsxx_err_handler,
 };
 
 static int __init rsxx_core_init(void)
index 80bbe639fccd72d002d269f6486e58ace210aab9..4b5c020a0a65ad8831d75bf3407dd81b2d82b306 100644 (file)
@@ -58,7 +58,7 @@ static struct kmem_cache *creg_cmd_pool;
 #error Unknown endianess!!! Aborting...
 #endif
 
-static void copy_to_creg_data(struct rsxx_cardinfo *card,
+static int copy_to_creg_data(struct rsxx_cardinfo *card,
                              int cnt8,
                              void *buf,
                              unsigned int stream)
@@ -66,6 +66,9 @@ static void copy_to_creg_data(struct rsxx_cardinfo *card,
        int i = 0;
        u32 *data = buf;
 
+       if (unlikely(card->eeh_state))
+               return -EIO;
+
        for (i = 0; cnt8 > 0; i++, cnt8 -= 4) {
                /*
                 * Firmware implementation makes it necessary to byte swap on
@@ -76,10 +79,12 @@ static void copy_to_creg_data(struct rsxx_cardinfo *card,
                else
                        iowrite32(data[i], card->regmap + CREG_DATA(i));
        }
+
+       return 0;
 }
 
 
-static void copy_from_creg_data(struct rsxx_cardinfo *card,
+static int copy_from_creg_data(struct rsxx_cardinfo *card,
                                int cnt8,
                                void *buf,
                                unsigned int stream)
@@ -87,6 +92,9 @@ static void copy_from_creg_data(struct rsxx_cardinfo *card,
        int i = 0;
        u32 *data = buf;
 
+       if (unlikely(card->eeh_state))
+               return -EIO;
+
        for (i = 0; cnt8 > 0; i++, cnt8 -= 4) {
                /*
                 * Firmware implementation makes it necessary to byte swap on
@@ -97,41 +105,31 @@ static void copy_from_creg_data(struct rsxx_cardinfo *card,
                else
                        data[i] = ioread32(card->regmap + CREG_DATA(i));
        }
-}
-
-static struct creg_cmd *pop_active_cmd(struct rsxx_cardinfo *card)
-{
-       struct creg_cmd *cmd;
 
-       /*
-        * Spin lock is needed because this can be called in atomic/interrupt
-        * context.
-        */
-       spin_lock_bh(&card->creg_ctrl.lock);
-       cmd = card->creg_ctrl.active_cmd;
-       card->creg_ctrl.active_cmd = NULL;
-       spin_unlock_bh(&card->creg_ctrl.lock);
-
-       return cmd;
+       return 0;
 }
 
 static void creg_issue_cmd(struct rsxx_cardinfo *card, struct creg_cmd *cmd)
 {
+       int st;
+
+       if (unlikely(card->eeh_state))
+               return;
+
        iowrite32(cmd->addr, card->regmap + CREG_ADD);
        iowrite32(cmd->cnt8, card->regmap + CREG_CNT);
 
        if (cmd->op == CREG_OP_WRITE) {
-               if (cmd->buf)
-                       copy_to_creg_data(card, cmd->cnt8,
-                                         cmd->buf, cmd->stream);
+               if (cmd->buf) {
+                       st = copy_to_creg_data(card, cmd->cnt8,
+                                              cmd->buf, cmd->stream);
+                       if (st)
+                               return;
+               }
        }
 
-       /*
-        * Data copy must complete before initiating the command. This is
-        * needed for weakly ordered processors (i.e. PowerPC), so that all
-        * neccessary registers are written before we kick the hardware.
-        */
-       wmb();
+       if (unlikely(card->eeh_state))
+               return;
 
        /* Setting the valid bit will kick off the command. */
        iowrite32(cmd->op, card->regmap + CREG_CMD);
@@ -196,11 +194,11 @@ static int creg_queue_cmd(struct rsxx_cardinfo *card,
        cmd->cb_private = cb_private;
        cmd->status     = 0;
 
-       spin_lock(&card->creg_ctrl.lock);
+       spin_lock_bh(&card->creg_ctrl.lock);
        list_add_tail(&cmd->list, &card->creg_ctrl.queue);
        card->creg_ctrl.q_depth++;
        creg_kick_queue(card);
-       spin_unlock(&card->creg_ctrl.lock);
+       spin_unlock_bh(&card->creg_ctrl.lock);
 
        return 0;
 }
@@ -210,7 +208,11 @@ static void creg_cmd_timed_out(unsigned long data)
        struct rsxx_cardinfo *card = (struct rsxx_cardinfo *) data;
        struct creg_cmd *cmd;
 
-       cmd = pop_active_cmd(card);
+       spin_lock(&card->creg_ctrl.lock);
+       cmd = card->creg_ctrl.active_cmd;
+       card->creg_ctrl.active_cmd = NULL;
+       spin_unlock(&card->creg_ctrl.lock);
+
        if (cmd == NULL) {
                card->creg_ctrl.creg_stats.creg_timeout++;
                dev_warn(CARD_TO_DEV(card),
@@ -247,7 +249,11 @@ static void creg_cmd_done(struct work_struct *work)
        if (del_timer_sync(&card->creg_ctrl.cmd_timer) == 0)
                card->creg_ctrl.creg_stats.failed_cancel_timer++;
 
-       cmd = pop_active_cmd(card);
+       spin_lock_bh(&card->creg_ctrl.lock);
+       cmd = card->creg_ctrl.active_cmd;
+       card->creg_ctrl.active_cmd = NULL;
+       spin_unlock_bh(&card->creg_ctrl.lock);
+
        if (cmd == NULL) {
                dev_err(CARD_TO_DEV(card),
                        "Spurious creg interrupt!\n");
@@ -287,7 +293,7 @@ static void creg_cmd_done(struct work_struct *work)
                        goto creg_done;
                }
 
-               copy_from_creg_data(card, cnt8, cmd->buf, cmd->stream);
+               st = copy_from_creg_data(card, cnt8, cmd->buf, cmd->stream);
        }
 
 creg_done:
@@ -296,10 +302,10 @@ creg_done:
 
        kmem_cache_free(creg_cmd_pool, cmd);
 
-       spin_lock(&card->creg_ctrl.lock);
+       spin_lock_bh(&card->creg_ctrl.lock);
        card->creg_ctrl.active = 0;
        creg_kick_queue(card);
-       spin_unlock(&card->creg_ctrl.lock);
+       spin_unlock_bh(&card->creg_ctrl.lock);
 }
 
 static void creg_reset(struct rsxx_cardinfo *card)
@@ -324,7 +330,7 @@ static void creg_reset(struct rsxx_cardinfo *card)
                "Resetting creg interface for recovery\n");
 
        /* Cancel outstanding commands */
-       spin_lock(&card->creg_ctrl.lock);
+       spin_lock_bh(&card->creg_ctrl.lock);
        list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) {
                list_del(&cmd->list);
                card->creg_ctrl.q_depth--;
@@ -345,7 +351,7 @@ static void creg_reset(struct rsxx_cardinfo *card)
 
                card->creg_ctrl.active = 0;
        }
-       spin_unlock(&card->creg_ctrl.lock);
+       spin_unlock_bh(&card->creg_ctrl.lock);
 
        card->creg_ctrl.reset = 0;
        spin_lock_irqsave(&card->irq_lock, flags);
@@ -399,12 +405,12 @@ static int __issue_creg_rw(struct rsxx_cardinfo *card,
                return st;
 
        /*
-        * This timeout is neccessary for unresponsive hardware. The additional
+        * This timeout is necessary for unresponsive hardware. The additional
         * 20 seconds to used to guarantee that each cregs requests has time to
         * complete.
         */
-       timeout = msecs_to_jiffies((CREG_TIMEOUT_MSEC *
-                               card->creg_ctrl.q_depth) + 20000);
+       timeout = msecs_to_jiffies(CREG_TIMEOUT_MSEC *
+                                  card->creg_ctrl.q_depth + 20000);
 
        /*
         * The creg interface is guaranteed to complete. It has a timeout
@@ -690,6 +696,32 @@ int rsxx_reg_access(struct rsxx_cardinfo *card,
        return 0;
 }
 
+void rsxx_eeh_save_issued_creg(struct rsxx_cardinfo *card)
+{
+       struct creg_cmd *cmd = NULL;
+
+       cmd = card->creg_ctrl.active_cmd;
+       card->creg_ctrl.active_cmd = NULL;
+
+       if (cmd) {
+               del_timer_sync(&card->creg_ctrl.cmd_timer);
+
+               spin_lock_bh(&card->creg_ctrl.lock);
+               list_add(&cmd->list, &card->creg_ctrl.queue);
+               card->creg_ctrl.q_depth++;
+               card->creg_ctrl.active = 0;
+               spin_unlock_bh(&card->creg_ctrl.lock);
+       }
+}
+
+void rsxx_kick_creg_queue(struct rsxx_cardinfo *card)
+{
+       spin_lock_bh(&card->creg_ctrl.lock);
+       if (!list_empty(&card->creg_ctrl.queue))
+               creg_kick_queue(card);
+       spin_unlock_bh(&card->creg_ctrl.lock);
+}
+
 /*------------ Initialization & Setup --------------*/
 int rsxx_creg_setup(struct rsxx_cardinfo *card)
 {
@@ -712,7 +744,7 @@ void rsxx_creg_destroy(struct rsxx_cardinfo *card)
        int cnt = 0;
 
        /* Cancel outstanding commands */
-       spin_lock(&card->creg_ctrl.lock);
+       spin_lock_bh(&card->creg_ctrl.lock);
        list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) {
                list_del(&cmd->list);
                if (cmd->cb)
@@ -737,7 +769,7 @@ void rsxx_creg_destroy(struct rsxx_cardinfo *card)
                        "Canceled active creg command\n");
                kmem_cache_free(creg_cmd_pool, cmd);
        }
-       spin_unlock(&card->creg_ctrl.lock);
+       spin_unlock_bh(&card->creg_ctrl.lock);
 
        cancel_work_sync(&card->creg_ctrl.done_work);
 }
index 63176e67662f5f48d2b358c39d93d86735c21c72..0607513cfb41fa4b2ff88bac32be0665c645a2bb 100644 (file)
@@ -28,7 +28,7 @@
 struct rsxx_dma {
        struct list_head         list;
        u8                       cmd;
-       unsigned int             laddr;     /* Logical address on the ramsan */
+       unsigned int             laddr;     /* Logical address */
        struct {
                u32              off;
                u32              cnt;
@@ -81,9 +81,6 @@ enum rsxx_hw_status {
        HW_STATUS_FAULT         = 0x08,
 };
 
-#define STATUS_BUFFER_SIZE8     4096
-#define COMMAND_BUFFER_SIZE8    4096
-
 static struct kmem_cache *rsxx_dma_pool;
 
 struct dma_tracker {
@@ -122,7 +119,7 @@ static unsigned int rsxx_get_dma_tgt(struct rsxx_cardinfo *card, u64 addr8)
        return tgt;
 }
 
-static void rsxx_dma_queue_reset(struct rsxx_cardinfo *card)
+void rsxx_dma_queue_reset(struct rsxx_cardinfo *card)
 {
        /* Reset all DMA Command/Status Queues */
        iowrite32(DMA_QUEUE_RESET, card->regmap + RESET);
@@ -210,7 +207,8 @@ static void dma_intr_coal_auto_tune(struct rsxx_cardinfo *card)
        u32 q_depth = 0;
        u32 intr_coal;
 
-       if (card->config.data.intr_coal.mode != RSXX_INTR_COAL_AUTO_TUNE)
+       if (card->config.data.intr_coal.mode != RSXX_INTR_COAL_AUTO_TUNE ||
+           unlikely(card->eeh_state))
                return;
 
        for (i = 0; i < card->n_targets; i++)
@@ -223,31 +221,26 @@ static void dma_intr_coal_auto_tune(struct rsxx_cardinfo *card)
 }
 
 /*----------------- RSXX DMA Handling -------------------*/
-static void rsxx_complete_dma(struct rsxx_cardinfo *card,
+static void rsxx_complete_dma(struct rsxx_dma_ctrl *ctrl,
                                  struct rsxx_dma *dma,
                                  unsigned int status)
 {
        if (status & DMA_SW_ERR)
-               printk_ratelimited(KERN_ERR
-                                  "SW Error in DMA(cmd x%02x, laddr x%08x)\n",
-                                  dma->cmd, dma->laddr);
+               ctrl->stats.dma_sw_err++;
        if (status & DMA_HW_FAULT)
-               printk_ratelimited(KERN_ERR
-                                  "HW Fault in DMA(cmd x%02x, laddr x%08x)\n",
-                                  dma->cmd, dma->laddr);
+               ctrl->stats.dma_hw_fault++;
        if (status & DMA_CANCELLED)
-               printk_ratelimited(KERN_ERR
-                                  "DMA Cancelled(cmd x%02x, laddr x%08x)\n",
-                                  dma->cmd, dma->laddr);
+               ctrl->stats.dma_cancelled++;
 
        if (dma->dma_addr)
-               pci_unmap_page(card->dev, dma->dma_addr, get_dma_size(dma),
+               pci_unmap_page(ctrl->card->dev, dma->dma_addr,
+                              get_dma_size(dma),
                               dma->cmd == HW_CMD_BLK_WRITE ?
                                           PCI_DMA_TODEVICE :
                                           PCI_DMA_FROMDEVICE);
 
        if (dma->cb)
-               dma->cb(card, dma->cb_data, status ? 1 : 0);
+               dma->cb(ctrl->card, dma->cb_data, status ? 1 : 0);
 
        kmem_cache_free(rsxx_dma_pool, dma);
 }
@@ -330,14 +323,15 @@ static void rsxx_handle_dma_error(struct rsxx_dma_ctrl *ctrl,
        if (requeue_cmd)
                rsxx_requeue_dma(ctrl, dma);
        else
-               rsxx_complete_dma(ctrl->card, dma, status);
+               rsxx_complete_dma(ctrl, dma, status);
 }
 
 static void dma_engine_stalled(unsigned long data)
 {
        struct rsxx_dma_ctrl *ctrl = (struct rsxx_dma_ctrl *)data;
 
-       if (atomic_read(&ctrl->stats.hw_q_depth) == 0)
+       if (atomic_read(&ctrl->stats.hw_q_depth) == 0 ||
+           unlikely(ctrl->card->eeh_state))
                return;
 
        if (ctrl->cmd.idx != ioread32(ctrl->regmap + SW_CMD_IDX)) {
@@ -369,7 +363,8 @@ static void rsxx_issue_dmas(struct work_struct *work)
        ctrl = container_of(work, struct rsxx_dma_ctrl, issue_dma_work);
        hw_cmd_buf = ctrl->cmd.buf;
 
-       if (unlikely(ctrl->card->halt))
+       if (unlikely(ctrl->card->halt) ||
+           unlikely(ctrl->card->eeh_state))
                return;
 
        while (1) {
@@ -397,7 +392,7 @@ static void rsxx_issue_dmas(struct work_struct *work)
                 */
                if (unlikely(ctrl->card->dma_fault)) {
                        push_tracker(ctrl->trackers, tag);
-                       rsxx_complete_dma(ctrl->card, dma, DMA_CANCELLED);
+                       rsxx_complete_dma(ctrl, dma, DMA_CANCELLED);
                        continue;
                }
 
@@ -432,19 +427,15 @@ static void rsxx_issue_dmas(struct work_struct *work)
 
        /* Let HW know we've queued commands. */
        if (cmds_pending) {
-               /*
-                * We must guarantee that the CPU writes to 'ctrl->cmd.buf'
-                * (which is in PCI-consistent system-memory) from the loop
-                * above make it into the coherency domain before the
-                * following PIO "trigger" updating the cmd.idx.  A WMB is
-                * sufficient. We need not explicitly CPU cache-flush since
-                * the memory is a PCI-consistent (ie; coherent) mapping.
-                */
-               wmb();
-
                atomic_add(cmds_pending, &ctrl->stats.hw_q_depth);
                mod_timer(&ctrl->activity_timer,
                          jiffies + DMA_ACTIVITY_TIMEOUT);
+
+               if (unlikely(ctrl->card->eeh_state)) {
+                       del_timer_sync(&ctrl->activity_timer);
+                       return;
+               }
+
                iowrite32(ctrl->cmd.idx, ctrl->regmap + SW_CMD_IDX);
        }
 }
@@ -463,7 +454,8 @@ static void rsxx_dma_done(struct work_struct *work)
        hw_st_buf = ctrl->status.buf;
 
        if (unlikely(ctrl->card->halt) ||
-           unlikely(ctrl->card->dma_fault))
+           unlikely(ctrl->card->dma_fault) ||
+           unlikely(ctrl->card->eeh_state))
                return;
 
        count = le16_to_cpu(hw_st_buf[ctrl->status.idx].count);
@@ -508,7 +500,7 @@ static void rsxx_dma_done(struct work_struct *work)
                if (status)
                        rsxx_handle_dma_error(ctrl, dma, status);
                else
-                       rsxx_complete_dma(ctrl->card, dma, 0);
+                       rsxx_complete_dma(ctrl, dma, 0);
 
                push_tracker(ctrl->trackers, tag);
 
@@ -727,20 +719,54 @@ bvec_err:
 
 
 /*----------------- DMA Engine Initialization & Setup -------------------*/
+int rsxx_hw_buffers_init(struct pci_dev *dev, struct rsxx_dma_ctrl *ctrl)
+{
+       ctrl->status.buf = pci_alloc_consistent(dev, STATUS_BUFFER_SIZE8,
+                               &ctrl->status.dma_addr);
+       ctrl->cmd.buf = pci_alloc_consistent(dev, COMMAND_BUFFER_SIZE8,
+                               &ctrl->cmd.dma_addr);
+       if (ctrl->status.buf == NULL || ctrl->cmd.buf == NULL)
+               return -ENOMEM;
+
+       memset(ctrl->status.buf, 0xac, STATUS_BUFFER_SIZE8);
+       iowrite32(lower_32_bits(ctrl->status.dma_addr),
+               ctrl->regmap + SB_ADD_LO);
+       iowrite32(upper_32_bits(ctrl->status.dma_addr),
+               ctrl->regmap + SB_ADD_HI);
+
+       memset(ctrl->cmd.buf, 0x83, COMMAND_BUFFER_SIZE8);
+       iowrite32(lower_32_bits(ctrl->cmd.dma_addr), ctrl->regmap + CB_ADD_LO);
+       iowrite32(upper_32_bits(ctrl->cmd.dma_addr), ctrl->regmap + CB_ADD_HI);
+
+       ctrl->status.idx = ioread32(ctrl->regmap + HW_STATUS_CNT);
+       if (ctrl->status.idx > RSXX_MAX_OUTSTANDING_CMDS) {
+               dev_crit(&dev->dev, "Failed reading status cnt x%x\n",
+                       ctrl->status.idx);
+               return -EINVAL;
+       }
+       iowrite32(ctrl->status.idx, ctrl->regmap + HW_STATUS_CNT);
+       iowrite32(ctrl->status.idx, ctrl->regmap + SW_STATUS_CNT);
+
+       ctrl->cmd.idx = ioread32(ctrl->regmap + HW_CMD_IDX);
+       if (ctrl->cmd.idx > RSXX_MAX_OUTSTANDING_CMDS) {
+               dev_crit(&dev->dev, "Failed reading cmd cnt x%x\n",
+                       ctrl->status.idx);
+               return -EINVAL;
+       }
+       iowrite32(ctrl->cmd.idx, ctrl->regmap + HW_CMD_IDX);
+       iowrite32(ctrl->cmd.idx, ctrl->regmap + SW_CMD_IDX);
+
+       return 0;
+}
+
 static int rsxx_dma_ctrl_init(struct pci_dev *dev,
                                  struct rsxx_dma_ctrl *ctrl)
 {
        int i;
+       int st;
 
        memset(&ctrl->stats, 0, sizeof(ctrl->stats));
 
-       ctrl->status.buf = pci_alloc_consistent(dev, STATUS_BUFFER_SIZE8,
-                                               &ctrl->status.dma_addr);
-       ctrl->cmd.buf = pci_alloc_consistent(dev, COMMAND_BUFFER_SIZE8,
-                                            &ctrl->cmd.dma_addr);
-       if (ctrl->status.buf == NULL || ctrl->cmd.buf == NULL)
-               return -ENOMEM;
-
        ctrl->trackers = vmalloc(DMA_TRACKER_LIST_SIZE8);
        if (!ctrl->trackers)
                return -ENOMEM;
@@ -770,35 +796,9 @@ static int rsxx_dma_ctrl_init(struct pci_dev *dev,
        INIT_WORK(&ctrl->issue_dma_work, rsxx_issue_dmas);
        INIT_WORK(&ctrl->dma_done_work, rsxx_dma_done);
 
-       memset(ctrl->status.buf, 0xac, STATUS_BUFFER_SIZE8);
-       iowrite32(lower_32_bits(ctrl->status.dma_addr),
-                 ctrl->regmap + SB_ADD_LO);
-       iowrite32(upper_32_bits(ctrl->status.dma_addr),
-                 ctrl->regmap + SB_ADD_HI);
-
-       memset(ctrl->cmd.buf, 0x83, COMMAND_BUFFER_SIZE8);
-       iowrite32(lower_32_bits(ctrl->cmd.dma_addr), ctrl->regmap + CB_ADD_LO);
-       iowrite32(upper_32_bits(ctrl->cmd.dma_addr), ctrl->regmap + CB_ADD_HI);
-
-       ctrl->status.idx = ioread32(ctrl->regmap + HW_STATUS_CNT);
-       if (ctrl->status.idx > RSXX_MAX_OUTSTANDING_CMDS) {
-               dev_crit(&dev->dev, "Failed reading status cnt x%x\n",
-                        ctrl->status.idx);
-               return -EINVAL;
-       }
-       iowrite32(ctrl->status.idx, ctrl->regmap + HW_STATUS_CNT);
-       iowrite32(ctrl->status.idx, ctrl->regmap + SW_STATUS_CNT);
-
-       ctrl->cmd.idx = ioread32(ctrl->regmap + HW_CMD_IDX);
-       if (ctrl->cmd.idx > RSXX_MAX_OUTSTANDING_CMDS) {
-               dev_crit(&dev->dev, "Failed reading cmd cnt x%x\n",
-                        ctrl->status.idx);
-               return -EINVAL;
-       }
-       iowrite32(ctrl->cmd.idx, ctrl->regmap + HW_CMD_IDX);
-       iowrite32(ctrl->cmd.idx, ctrl->regmap + SW_CMD_IDX);
-
-       wmb();
+       st = rsxx_hw_buffers_init(dev, ctrl);
+       if (st)
+               return st;
 
        return 0;
 }
@@ -834,7 +834,7 @@ static int rsxx_dma_stripe_setup(struct rsxx_cardinfo *card,
        return 0;
 }
 
-static int rsxx_dma_configure(struct rsxx_cardinfo *card)
+int rsxx_dma_configure(struct rsxx_cardinfo *card)
 {
        u32 intr_coal;
 
@@ -980,6 +980,103 @@ void rsxx_dma_destroy(struct rsxx_cardinfo *card)
        }
 }
 
+int rsxx_eeh_save_issued_dmas(struct rsxx_cardinfo *card)
+{
+       int i;
+       int j;
+       int cnt;
+       struct rsxx_dma *dma;
+       struct list_head *issued_dmas;
+
+       issued_dmas = kzalloc(sizeof(*issued_dmas) * card->n_targets,
+                             GFP_KERNEL);
+       if (!issued_dmas)
+               return -ENOMEM;
+
+       for (i = 0; i < card->n_targets; i++) {
+               INIT_LIST_HEAD(&issued_dmas[i]);
+               cnt = 0;
+               for (j = 0; j < RSXX_MAX_OUTSTANDING_CMDS; j++) {
+                       dma = get_tracker_dma(card->ctrl[i].trackers, j);
+                       if (dma == NULL)
+                               continue;
+
+                       if (dma->cmd == HW_CMD_BLK_WRITE)
+                               card->ctrl[i].stats.writes_issued--;
+                       else if (dma->cmd == HW_CMD_BLK_DISCARD)
+                               card->ctrl[i].stats.discards_issued--;
+                       else
+                               card->ctrl[i].stats.reads_issued--;
+
+                       list_add_tail(&dma->list, &issued_dmas[i]);
+                       push_tracker(card->ctrl[i].trackers, j);
+                       cnt++;
+               }
+
+               spin_lock(&card->ctrl[i].queue_lock);
+               list_splice(&issued_dmas[i], &card->ctrl[i].queue);
+
+               atomic_sub(cnt, &card->ctrl[i].stats.hw_q_depth);
+               card->ctrl[i].stats.sw_q_depth += cnt;
+               card->ctrl[i].e_cnt = 0;
+
+               list_for_each_entry(dma, &card->ctrl[i].queue, list) {
+                       if (dma->dma_addr)
+                               pci_unmap_page(card->dev, dma->dma_addr,
+                                              get_dma_size(dma),
+                                              dma->cmd == HW_CMD_BLK_WRITE ?
+                                              PCI_DMA_TODEVICE :
+                                              PCI_DMA_FROMDEVICE);
+               }
+               spin_unlock(&card->ctrl[i].queue_lock);
+       }
+
+       kfree(issued_dmas);
+
+       return 0;
+}
+
+void rsxx_eeh_cancel_dmas(struct rsxx_cardinfo *card)
+{
+       struct rsxx_dma *dma;
+       struct rsxx_dma *tmp;
+       int i;
+
+       for (i = 0; i < card->n_targets; i++) {
+               spin_lock(&card->ctrl[i].queue_lock);
+               list_for_each_entry_safe(dma, tmp, &card->ctrl[i].queue, list) {
+                       list_del(&dma->list);
+
+                       rsxx_complete_dma(&card->ctrl[i], dma, DMA_CANCELLED);
+               }
+               spin_unlock(&card->ctrl[i].queue_lock);
+       }
+}
+
+int rsxx_eeh_remap_dmas(struct rsxx_cardinfo *card)
+{
+       struct rsxx_dma *dma;
+       int i;
+
+       for (i = 0; i < card->n_targets; i++) {
+               spin_lock(&card->ctrl[i].queue_lock);
+               list_for_each_entry(dma, &card->ctrl[i].queue, list) {
+                       dma->dma_addr = pci_map_page(card->dev, dma->page,
+                                       dma->pg_off, get_dma_size(dma),
+                                       dma->cmd == HW_CMD_BLK_WRITE ?
+                                       PCI_DMA_TODEVICE :
+                                       PCI_DMA_FROMDEVICE);
+                       if (!dma->dma_addr) {
+                               spin_unlock(&card->ctrl[i].queue_lock);
+                               kmem_cache_free(rsxx_dma_pool, dma);
+                               return -ENOMEM;
+                       }
+               }
+               spin_unlock(&card->ctrl[i].queue_lock);
+       }
+
+       return 0;
+}
 
 int rsxx_dma_init(void)
 {
index 2e50b65902b71e564f9a25cba8a22cc09d893805..24ba3642bd89aeaabc113407eb2de6d92f13602a 100644 (file)
 
 /*----------------- IOCTL Definitions -------------------*/
 
+#define RSXX_MAX_DATA 8
+
 struct rsxx_reg_access {
        __u32 addr;
        __u32 cnt;
        __u32 stat;
        __u32 stream;
-       __u32 data[8];
+       __u32 data[RSXX_MAX_DATA];
 };
 
-#define RSXX_MAX_REG_CNT       (8 * (sizeof(__u32)))
+#define RSXX_MAX_REG_CNT       (RSXX_MAX_DATA * (sizeof(__u32)))
 
 #define RSXX_IOC_MAGIC 'r'
 
index c025fe5fdb703af4d1a94ed491814cded627a17d..f384c943846de35a2dab6d5f173df7b15c4bd5f2 100644 (file)
@@ -58,7 +58,7 @@ struct rsxx_card_cfg {
 };
 
 /* Vendor ID Values */
-#define RSXX_VENDOR_ID_TMS_IBM         0
+#define RSXX_VENDOR_ID_IBM             0
 #define RSXX_VENDOR_ID_DSI             1
 #define RSXX_VENDOR_COUNT              2
 
index a1ac907d8f4c3ee60aabb11bdfb439ea3418183c..382e8bf5c03b73dae35fd1ae8865110cc1a85168 100644 (file)
 
 struct proc_cmd;
 
-#define PCI_VENDOR_ID_TMS_IBM          0x15B6
-#define PCI_DEVICE_ID_RS70_FLASH       0x0019
-#define PCI_DEVICE_ID_RS70D_FLASH      0x001A
-#define PCI_DEVICE_ID_RS80_FLASH       0x001C
-#define PCI_DEVICE_ID_RS81_FLASH       0x001E
+#define PCI_DEVICE_ID_FS70_FLASH       0x04A9
+#define PCI_DEVICE_ID_FS80_FLASH       0x04AA
 
 #define RS70_PCI_REV_SUPPORTED 4
 
 #define DRIVER_NAME "rsxx"
-#define DRIVER_VERSION "3.7"
+#define DRIVER_VERSION "4.0"
 
 /* Block size is 4096 */
 #define RSXX_HW_BLK_SHIFT              12
@@ -67,6 +64,9 @@ struct proc_cmd;
 #define RSXX_MAX_OUTSTANDING_CMDS      255
 #define RSXX_CS_IDX_MASK               0xff
 
+#define STATUS_BUFFER_SIZE8     4096
+#define COMMAND_BUFFER_SIZE8    4096
+
 #define RSXX_MAX_TARGETS       8
 
 struct dma_tracker_list;
@@ -91,6 +91,9 @@ struct rsxx_dma_stats {
        u32 discards_failed;
        u32 done_rescheduled;
        u32 issue_rescheduled;
+       u32 dma_sw_err;
+       u32 dma_hw_fault;
+       u32 dma_cancelled;
        u32 sw_q_depth;         /* Number of DMAs on the SW queue. */
        atomic_t hw_q_depth;    /* Number of DMAs queued to HW. */
 };
@@ -116,6 +119,7 @@ struct rsxx_dma_ctrl {
 struct rsxx_cardinfo {
        struct pci_dev          *dev;
        unsigned int            halt;
+       unsigned int            eeh_state;
 
        void                    __iomem *regmap;
        spinlock_t              irq_lock;
@@ -224,6 +228,7 @@ enum rsxx_pci_regmap {
        PERF_RD512_HI   = 0xac,
        PERF_WR512_LO   = 0xb0,
        PERF_WR512_HI   = 0xb4,
+       PCI_RECONFIG    = 0xb8,
 };
 
 enum rsxx_intr {
@@ -237,6 +242,8 @@ enum rsxx_intr {
        CR_INTR_DMA5    = 0x00000080,
        CR_INTR_DMA6    = 0x00000100,
        CR_INTR_DMA7    = 0x00000200,
+       CR_INTR_ALL_C   = 0x0000003f,
+       CR_INTR_ALL_G   = 0x000003ff,
        CR_INTR_DMA_ALL = 0x000003f5,
        CR_INTR_ALL     = 0xffffffff,
 };
@@ -253,8 +260,14 @@ enum rsxx_pci_reset {
        DMA_QUEUE_RESET         = 0x00000001,
 };
 
+enum rsxx_hw_fifo_flush {
+       RSXX_FLUSH_BUSY         = 0x00000002,
+       RSXX_FLUSH_TIMEOUT      = 0x00000004,
+};
+
 enum rsxx_pci_revision {
        RSXX_DISCARD_SUPPORT = 2,
+       RSXX_EEH_SUPPORT     = 3,
 };
 
 enum rsxx_creg_cmd {
@@ -360,11 +373,17 @@ int rsxx_dma_setup(struct rsxx_cardinfo *card);
 void rsxx_dma_destroy(struct rsxx_cardinfo *card);
 int rsxx_dma_init(void);
 void rsxx_dma_cleanup(void);
+void rsxx_dma_queue_reset(struct rsxx_cardinfo *card);
+int rsxx_dma_configure(struct rsxx_cardinfo *card);
 int rsxx_dma_queue_bio(struct rsxx_cardinfo *card,
                           struct bio *bio,
                           atomic_t *n_dmas,
                           rsxx_dma_cb cb,
                           void *cb_data);
+int rsxx_hw_buffers_init(struct pci_dev *dev, struct rsxx_dma_ctrl *ctrl);
+int rsxx_eeh_save_issued_dmas(struct rsxx_cardinfo *card);
+void rsxx_eeh_cancel_dmas(struct rsxx_cardinfo *card);
+int rsxx_eeh_remap_dmas(struct rsxx_cardinfo *card);
 
 /***** cregs.c *****/
 int rsxx_creg_write(struct rsxx_cardinfo *card, u32 addr,
@@ -389,10 +408,11 @@ int rsxx_creg_setup(struct rsxx_cardinfo *card);
 void rsxx_creg_destroy(struct rsxx_cardinfo *card);
 int rsxx_creg_init(void);
 void rsxx_creg_cleanup(void);
-
 int rsxx_reg_access(struct rsxx_cardinfo *card,
                        struct rsxx_reg_access __user *ucmd,
                        int read);
+void rsxx_eeh_save_issued_creg(struct rsxx_cardinfo *card);
+void rsxx_kick_creg_queue(struct rsxx_cardinfo *card);
 
 
 
index de1f319f7bd7e0118a960b5bd23fd286a6ba343e..dd5b2fed97e9ae2b7665f13ec3c42db6ee6fb462 100644 (file)
@@ -164,7 +164,7 @@ static void make_response(struct xen_blkif *blkif, u64 id,
 
 #define foreach_grant_safe(pos, n, rbtree, node) \
        for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node), \
-            (n) = rb_next(&(pos)->node); \
+            (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL; \
             &(pos)->node != NULL; \
             (pos) = container_of(n, typeof(*(pos)), node), \
             (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL)
@@ -381,8 +381,8 @@ irqreturn_t xen_blkif_be_int(int irq, void *dev_id)
 
 static void print_stats(struct xen_blkif *blkif)
 {
-       pr_info("xen-blkback (%s): oo %3d  |  rd %4d  |  wr %4d  |  f %4d"
-                "  |  ds %4d\n",
+       pr_info("xen-blkback (%s): oo %3llu  |  rd %4llu  |  wr %4llu  |  f %4llu"
+                "  |  ds %4llu\n",
                 current->comm, blkif->st_oo_req,
                 blkif->st_rd_req, blkif->st_wr_req,
                 blkif->st_f_req, blkif->st_ds_req);
@@ -442,7 +442,7 @@ int xen_blkif_schedule(void *arg)
 }
 
 struct seg_buf {
-       unsigned long buf;
+       unsigned int offset;
        unsigned int nsec;
 };
 /*
@@ -621,30 +621,21 @@ static int xen_blkbk_map(struct blkif_request *req,
                                 * If this is a new persistent grant
                                 * save the handler
                                 */
-                               persistent_gnts[i]->handle = map[j].handle;
-                               persistent_gnts[i]->dev_bus_addr =
-                                       map[j++].dev_bus_addr;
+                               persistent_gnts[i]->handle = map[j++].handle;
                        }
                        pending_handle(pending_req, i) =
                                persistent_gnts[i]->handle;
 
                        if (ret)
                                continue;
-
-                       seg[i].buf = persistent_gnts[i]->dev_bus_addr |
-                               (req->u.rw.seg[i].first_sect << 9);
                } else {
-                       pending_handle(pending_req, i) = map[j].handle;
+                       pending_handle(pending_req, i) = map[j++].handle;
                        bitmap_set(pending_req->unmap_seg, i, 1);
 
-                       if (ret) {
-                               j++;
+                       if (ret)
                                continue;
-                       }
-
-                       seg[i].buf = map[j++].dev_bus_addr |
-                               (req->u.rw.seg[i].first_sect << 9);
                }
+               seg[i].offset = (req->u.rw.seg[i].first_sect << 9);
        }
        return ret;
 }
@@ -679,6 +670,16 @@ static int dispatch_discard_io(struct xen_blkif *blkif,
        return err;
 }
 
+static int dispatch_other_io(struct xen_blkif *blkif,
+                            struct blkif_request *req,
+                            struct pending_req *pending_req)
+{
+       free_req(pending_req);
+       make_response(blkif, req->u.other.id, req->operation,
+                     BLKIF_RSP_EOPNOTSUPP);
+       return -EIO;
+}
+
 static void xen_blk_drain_io(struct xen_blkif *blkif)
 {
        atomic_set(&blkif->drain, 1);
@@ -800,17 +801,30 @@ __do_block_io_op(struct xen_blkif *blkif)
 
                /* Apply all sanity checks to /private copy/ of request. */
                barrier();
-               if (unlikely(req.operation == BLKIF_OP_DISCARD)) {
+
+               switch (req.operation) {
+               case BLKIF_OP_READ:
+               case BLKIF_OP_WRITE:
+               case BLKIF_OP_WRITE_BARRIER:
+               case BLKIF_OP_FLUSH_DISKCACHE:
+                       if (dispatch_rw_block_io(blkif, &req, pending_req))
+                               goto done;
+                       break;
+               case BLKIF_OP_DISCARD:
                        free_req(pending_req);
                        if (dispatch_discard_io(blkif, &req))
-                               break;
-               } else if (dispatch_rw_block_io(blkif, &req, pending_req))
+                               goto done;
                        break;
+               default:
+                       if (dispatch_other_io(blkif, &req, pending_req))
+                               goto done;
+                       break;
+               }
 
                /* Yield point for this unbounded loop. */
                cond_resched();
        }
-
+done:
        return more_to_do;
 }
 
@@ -904,7 +918,8 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
                pr_debug(DRV_PFX "access denied: %s of [%llu,%llu] on dev=%04x\n",
                         operation == READ ? "read" : "write",
                         preq.sector_number,
-                        preq.sector_number + preq.nr_sects, preq.dev);
+                        preq.sector_number + preq.nr_sects,
+                        blkif->vbd.pdevice);
                goto fail_response;
        }
 
@@ -947,7 +962,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
                       (bio_add_page(bio,
                                     pages[i],
                                     seg[i].nsec << 9,
-                                    seg[i].buf & ~PAGE_MASK) == 0)) {
+                                    seg[i].offset) == 0)) {
 
                        bio = bio_alloc(GFP_KERNEL, nseg-i);
                        if (unlikely(bio == NULL))
@@ -977,13 +992,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
                bio->bi_end_io  = end_block_io_op;
        }
 
-       /*
-        * We set it one so that the last submit_bio does not have to call
-        * atomic_inc.
-        */
        atomic_set(&pending_req->pendcnt, nbio);
-
-       /* Get a reference count for the disk queue and start sending I/O */
        blk_start_plug(&plug);
 
        for (i = 0; i < nbio; i++)
@@ -1011,6 +1020,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif,
  fail_put_bio:
        for (i = 0; i < nbio; i++)
                bio_put(biolist[i]);
+       atomic_set(&pending_req->pendcnt, 1);
        __end_block_io_op(pending_req, -EINVAL);
        msleep(1); /* back off a bit */
        return -EIO;
index 6072390c7f57ef724bee4476502eb78d63941c7c..60103e2517ba28ac5c946f32e1bd9e0e6eb7f668 100644 (file)
@@ -77,11 +77,18 @@ struct blkif_x86_32_request_discard {
        uint64_t       nr_sectors;
 } __attribute__((__packed__));
 
+struct blkif_x86_32_request_other {
+       uint8_t        _pad1;
+       blkif_vdev_t   _pad2;
+       uint64_t       id;           /* private guest value, echoed in resp  */
+} __attribute__((__packed__));
+
 struct blkif_x86_32_request {
        uint8_t        operation;    /* BLKIF_OP_???                         */
        union {
                struct blkif_x86_32_request_rw rw;
                struct blkif_x86_32_request_discard discard;
+               struct blkif_x86_32_request_other other;
        } u;
 } __attribute__((__packed__));
 
@@ -113,11 +120,19 @@ struct blkif_x86_64_request_discard {
        uint64_t       nr_sectors;
 } __attribute__((__packed__));
 
+struct blkif_x86_64_request_other {
+       uint8_t        _pad1;
+       blkif_vdev_t   _pad2;
+       uint32_t       _pad3;        /* offsetof(blkif_..,u.discard.id)==8   */
+       uint64_t       id;           /* private guest value, echoed in resp  */
+} __attribute__((__packed__));
+
 struct blkif_x86_64_request {
        uint8_t        operation;    /* BLKIF_OP_???                         */
        union {
                struct blkif_x86_64_request_rw rw;
                struct blkif_x86_64_request_discard discard;
+               struct blkif_x86_64_request_other other;
        } u;
 } __attribute__((__packed__));
 
@@ -172,7 +187,6 @@ struct persistent_gnt {
        struct page *page;
        grant_ref_t gnt;
        grant_handle_t handle;
-       uint64_t dev_bus_addr;
        struct rb_node node;
 };
 
@@ -208,13 +222,13 @@ struct xen_blkif {
 
        /* statistics */
        unsigned long           st_print;
-       int                     st_rd_req;
-       int                     st_wr_req;
-       int                     st_oo_req;
-       int                     st_f_req;
-       int                     st_ds_req;
-       int                     st_rd_sect;
-       int                     st_wr_sect;
+       unsigned long long                      st_rd_req;
+       unsigned long long                      st_wr_req;
+       unsigned long long                      st_oo_req;
+       unsigned long long                      st_f_req;
+       unsigned long long                      st_ds_req;
+       unsigned long long                      st_rd_sect;
+       unsigned long long                      st_wr_sect;
 
        wait_queue_head_t       waiting_to_free;
 };
@@ -278,6 +292,11 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst,
                dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
                break;
        default:
+               /*
+                * Don't know how to translate this op. Only get the
+                * ID so failure can be reported to the frontend.
+                */
+               dst->u.other.id = src->u.other.id;
                break;
        }
 }
@@ -309,6 +328,11 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst,
                dst->u.discard.nr_sectors = src->u.discard.nr_sectors;
                break;
        default:
+               /*
+                * Don't know how to translate this op. Only get the
+                * ID so failure can be reported to the frontend.
+                */
+               dst->u.other.id = src->u.other.id;
                break;
        }
 }
index 5e237f630c47f2b2299749e067744dc89adba1a8..8bfd1bcf95ec0c168f565ac769479cb3be6098d3 100644 (file)
@@ -230,13 +230,13 @@ int __init xen_blkif_interface_init(void)
        }                                                               \
        static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
 
-VBD_SHOW(oo_req,  "%d\n", be->blkif->st_oo_req);
-VBD_SHOW(rd_req,  "%d\n", be->blkif->st_rd_req);
-VBD_SHOW(wr_req,  "%d\n", be->blkif->st_wr_req);
-VBD_SHOW(f_req,  "%d\n", be->blkif->st_f_req);
-VBD_SHOW(ds_req,  "%d\n", be->blkif->st_ds_req);
-VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect);
-VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect);
+VBD_SHOW(oo_req,  "%llu\n", be->blkif->st_oo_req);
+VBD_SHOW(rd_req,  "%llu\n", be->blkif->st_rd_req);
+VBD_SHOW(wr_req,  "%llu\n", be->blkif->st_wr_req);
+VBD_SHOW(f_req,  "%llu\n", be->blkif->st_f_req);
+VBD_SHOW(ds_req,  "%llu\n", be->blkif->st_ds_req);
+VBD_SHOW(rd_sect, "%llu\n", be->blkif->st_rd_sect);
+VBD_SHOW(wr_sect, "%llu\n", be->blkif->st_wr_sect);
 
 static struct attribute *xen_vbdstat_attrs[] = {
        &dev_attr_oo_req.attr,
index c3dae2e0f290e8ad64b4f3e6c869c2fca14cd1a1..a894f88762d8d3a1f72315e805f9494cdad8294d 100644 (file)
@@ -44,7 +44,7 @@
 #include <linux/mutex.h>
 #include <linux/scatterlist.h>
 #include <linux/bitmap.h>
-#include <linux/llist.h>
+#include <linux/list.h>
 
 #include <xen/xen.h>
 #include <xen/xenbus.h>
@@ -68,13 +68,12 @@ enum blkif_state {
 struct grant {
        grant_ref_t gref;
        unsigned long pfn;
-       struct llist_node node;
+       struct list_head node;
 };
 
 struct blk_shadow {
        struct blkif_request req;
        struct request *request;
-       unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST];
        struct grant *grants_used[BLKIF_MAX_SEGMENTS_PER_REQUEST];
 };
 
@@ -105,7 +104,7 @@ struct blkfront_info
        struct work_struct work;
        struct gnttab_free_callback callback;
        struct blk_shadow shadow[BLK_RING_SIZE];
-       struct llist_head persistent_gnts;
+       struct list_head persistent_gnts;
        unsigned int persistent_gnts_c;
        unsigned long shadow_free;
        unsigned int feature_flush;
@@ -165,6 +164,69 @@ static int add_id_to_freelist(struct blkfront_info *info,
        return 0;
 }
 
+static int fill_grant_buffer(struct blkfront_info *info, int num)
+{
+       struct page *granted_page;
+       struct grant *gnt_list_entry, *n;
+       int i = 0;
+
+       while(i < num) {
+               gnt_list_entry = kzalloc(sizeof(struct grant), GFP_NOIO);
+               if (!gnt_list_entry)
+                       goto out_of_memory;
+
+               granted_page = alloc_page(GFP_NOIO);
+               if (!granted_page) {
+                       kfree(gnt_list_entry);
+                       goto out_of_memory;
+               }
+
+               gnt_list_entry->pfn = page_to_pfn(granted_page);
+               gnt_list_entry->gref = GRANT_INVALID_REF;
+               list_add(&gnt_list_entry->node, &info->persistent_gnts);
+               i++;
+       }
+
+       return 0;
+
+out_of_memory:
+       list_for_each_entry_safe(gnt_list_entry, n,
+                                &info->persistent_gnts, node) {
+               list_del(&gnt_list_entry->node);
+               __free_page(pfn_to_page(gnt_list_entry->pfn));
+               kfree(gnt_list_entry);
+               i--;
+       }
+       BUG_ON(i != 0);
+       return -ENOMEM;
+}
+
+static struct grant *get_grant(grant_ref_t *gref_head,
+                               struct blkfront_info *info)
+{
+       struct grant *gnt_list_entry;
+       unsigned long buffer_mfn;
+
+       BUG_ON(list_empty(&info->persistent_gnts));
+       gnt_list_entry = list_first_entry(&info->persistent_gnts, struct grant,
+                                         node);
+       list_del(&gnt_list_entry->node);
+
+       if (gnt_list_entry->gref != GRANT_INVALID_REF) {
+               info->persistent_gnts_c--;
+               return gnt_list_entry;
+       }
+
+       /* Assign a gref to this page */
+       gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head);
+       BUG_ON(gnt_list_entry->gref == -ENOSPC);
+       buffer_mfn = pfn_to_mfn(gnt_list_entry->pfn);
+       gnttab_grant_foreign_access_ref(gnt_list_entry->gref,
+                                       info->xbdev->otherend_id,
+                                       buffer_mfn, 0);
+       return gnt_list_entry;
+}
+
 static const char *op_name(int op)
 {
        static const char *const names[] = {
@@ -293,7 +355,6 @@ static int blkif_ioctl(struct block_device *bdev, fmode_t mode,
 static int blkif_queue_request(struct request *req)
 {
        struct blkfront_info *info = req->rq_disk->private_data;
-       unsigned long buffer_mfn;
        struct blkif_request *ring_req;
        unsigned long id;
        unsigned int fsect, lsect;
@@ -306,7 +367,6 @@ static int blkif_queue_request(struct request *req)
         */
        bool new_persistent_gnts;
        grant_ref_t gref_head;
-       struct page *granted_page;
        struct grant *gnt_list_entry = NULL;
        struct scatterlist *sg;
 
@@ -370,41 +430,8 @@ static int blkif_queue_request(struct request *req)
                        fsect = sg->offset >> 9;
                        lsect = fsect + (sg->length >> 9) - 1;
 
-                       if (info->persistent_gnts_c) {
-                               BUG_ON(llist_empty(&info->persistent_gnts));
-                               gnt_list_entry = llist_entry(
-                                       llist_del_first(&info->persistent_gnts),
-                                       struct grant, node);
-
-                               ref = gnt_list_entry->gref;
-                               buffer_mfn = pfn_to_mfn(gnt_list_entry->pfn);
-                               info->persistent_gnts_c--;
-                       } else {
-                               ref = gnttab_claim_grant_reference(&gref_head);
-                               BUG_ON(ref == -ENOSPC);
-
-                               gnt_list_entry =
-                                       kmalloc(sizeof(struct grant),
-                                                        GFP_ATOMIC);
-                               if (!gnt_list_entry)
-                                       return -ENOMEM;
-
-                               granted_page = alloc_page(GFP_ATOMIC);
-                               if (!granted_page) {
-                                       kfree(gnt_list_entry);
-                                       return -ENOMEM;
-                               }
-
-                               gnt_list_entry->pfn =
-                                       page_to_pfn(granted_page);
-                               gnt_list_entry->gref = ref;
-
-                               buffer_mfn = pfn_to_mfn(page_to_pfn(
-                                                               granted_page));
-                               gnttab_grant_foreign_access_ref(ref,
-                                       info->xbdev->otherend_id,
-                                       buffer_mfn, 0);
-                       }
+                       gnt_list_entry = get_grant(&gref_head, info);
+                       ref = gnt_list_entry->gref;
 
                        info->shadow[id].grants_used[i] = gnt_list_entry;
 
@@ -435,7 +462,6 @@ static int blkif_queue_request(struct request *req)
                                kunmap_atomic(shared_data);
                        }
 
-                       info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
                        ring_req->u.rw.seg[i] =
                                        (struct blkif_request_segment) {
                                                .gref       = ref,
@@ -790,9 +816,8 @@ static void blkif_restart_queue(struct work_struct *work)
 
 static void blkif_free(struct blkfront_info *info, int suspend)
 {
-       struct llist_node *all_gnts;
-       struct grant *persistent_gnt, *tmp;
-       struct llist_node *n;
+       struct grant *persistent_gnt;
+       struct grant *n;
 
        /* Prevent new requests being issued until we fix things up. */
        spin_lock_irq(&info->io_lock);
@@ -803,22 +828,20 @@ static void blkif_free(struct blkfront_info *info, int suspend)
                blk_stop_queue(info->rq);
 
        /* Remove all persistent grants */
-       if (info->persistent_gnts_c) {
-               all_gnts = llist_del_all(&info->persistent_gnts);
-               persistent_gnt = llist_entry(all_gnts, typeof(*(persistent_gnt)), node);
-               while (persistent_gnt) {
-                       gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL);
+       if (!list_empty(&info->persistent_gnts)) {
+               list_for_each_entry_safe(persistent_gnt, n,
+                                        &info->persistent_gnts, node) {
+                       list_del(&persistent_gnt->node);
+                       if (persistent_gnt->gref != GRANT_INVALID_REF) {
+                               gnttab_end_foreign_access(persistent_gnt->gref,
+                                                         0, 0UL);
+                               info->persistent_gnts_c--;
+                       }
                        __free_page(pfn_to_page(persistent_gnt->pfn));
-                       tmp = persistent_gnt;
-                       n = persistent_gnt->node.next;
-                       if (n)
-                               persistent_gnt = llist_entry(n, typeof(*(persistent_gnt)), node);
-                       else
-                               persistent_gnt = NULL;
-                       kfree(tmp);
+                       kfree(persistent_gnt);
                }
-               info->persistent_gnts_c = 0;
        }
+       BUG_ON(info->persistent_gnts_c != 0);
 
        /* No more gnttab callback work. */
        gnttab_cancel_free_callback(&info->callback);
@@ -875,7 +898,7 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info,
        }
        /* Add the persistent grant into the list of free grants */
        for (i = 0; i < s->req.u.rw.nr_segments; i++) {
-               llist_add(&s->grants_used[i]->node, &info->persistent_gnts);
+               list_add(&s->grants_used[i]->node, &info->persistent_gnts);
                info->persistent_gnts_c++;
        }
 }
@@ -1013,6 +1036,12 @@ static int setup_blkring(struct xenbus_device *dev,
 
        sg_init_table(info->sg, BLKIF_MAX_SEGMENTS_PER_REQUEST);
 
+       /* Allocate memory for grants */
+       err = fill_grant_buffer(info, BLK_RING_SIZE *
+                                     BLKIF_MAX_SEGMENTS_PER_REQUEST);
+       if (err)
+               goto fail;
+
        err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring));
        if (err < 0) {
                free_page((unsigned long)sring);
@@ -1171,7 +1200,7 @@ static int blkfront_probe(struct xenbus_device *dev,
        spin_lock_init(&info->io_lock);
        info->xbdev = dev;
        info->vdevice = vdevice;
-       init_llist_head(&info->persistent_gnts);
+       INIT_LIST_HEAD(&info->persistent_gnts);
        info->persistent_gnts_c = 0;
        info->connected = BLKIF_STATE_DISCONNECTED;
        INIT_WORK(&info->work, blkif_restart_queue);
@@ -1203,11 +1232,10 @@ static int blkif_recover(struct blkfront_info *info)
        int j;
 
        /* Stage 1: Make a safe copy of the shadow state. */
-       copy = kmalloc(sizeof(info->shadow),
+       copy = kmemdup(info->shadow, sizeof(info->shadow),
                       GFP_NOIO | __GFP_REPEAT | __GFP_HIGH);
        if (!copy)
                return -ENOMEM;
-       memcpy(copy, info->shadow, sizeof(info->shadow));
 
        /* Stage 2: Set up free list. */
        memset(&info->shadow, 0, sizeof(info->shadow));
@@ -1236,7 +1264,7 @@ static int blkif_recover(struct blkfront_info *info)
                                gnttab_grant_foreign_access_ref(
                                        req->u.rw.seg[j].gref,
                                        info->xbdev->otherend_id,
-                                       pfn_to_mfn(info->shadow[req->u.rw.id].frame[j]),
+                                       pfn_to_mfn(copy[i].grants_used[j]->pfn),
                                        0);
                }
                info->shadow[req->u.rw.id].req = *req;
index a8a41e07a221695684fd78770980749b25ff2b5a..6aab00ef4379a5b9e4dfeb290461d3c177726f07 100644 (file)
@@ -73,9 +73,13 @@ static struct usb_device_id ath3k_table[] = {
        { USB_DEVICE(0x03F0, 0x311D) },
 
        /* Atheros AR3012 with sflash firmware*/
+       { USB_DEVICE(0x0CF3, 0x0036) },
        { USB_DEVICE(0x0CF3, 0x3004) },
+       { USB_DEVICE(0x0CF3, 0x3008) },
        { USB_DEVICE(0x0CF3, 0x311D) },
+       { USB_DEVICE(0x0CF3, 0x817a) },
        { USB_DEVICE(0x13d3, 0x3375) },
+       { USB_DEVICE(0x04CA, 0x3004) },
        { USB_DEVICE(0x04CA, 0x3005) },
        { USB_DEVICE(0x04CA, 0x3006) },
        { USB_DEVICE(0x04CA, 0x3008) },
@@ -105,9 +109,13 @@ MODULE_DEVICE_TABLE(usb, ath3k_table);
 static struct usb_device_id ath3k_blist_tbl[] = {
 
        /* Atheros AR3012 with sflash firmware*/
+       { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
index 7e351e345476c1bcc2141f95e41fe43a3e65e612..2cc5f774a29c47140739361420564b3f7c15b095 100644 (file)
@@ -131,9 +131,13 @@ static struct usb_device_id blacklist_table[] = {
        { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
 
        /* Atheros 3012 with sflash firmware */
+       { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
        { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
index 69ae5972713cf814e968c3c9d9ad8743d3dd240d..a0f7724852eb84d2ccb20eebc8e4309ea48a085c 100644 (file)
@@ -380,6 +380,15 @@ void hwrng_unregister(struct hwrng *rng)
 }
 EXPORT_SYMBOL_GPL(hwrng_unregister);
 
+static void __exit hwrng_exit(void)
+{
+       mutex_lock(&rng_mutex);
+       BUG_ON(current_rng);
+       kfree(rng_buffer);
+       mutex_unlock(&rng_mutex);
+}
+
+module_exit(hwrng_exit);
 
 MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
 MODULE_LICENSE("GPL");
index 10fd71ccf587789858582b09f37e646b7119e937..6bf4d47324eb884e7f462678acf493fec4c518b1 100644 (file)
@@ -92,14 +92,22 @@ static int probe_common(struct virtio_device *vdev)
 {
        int err;
 
+       if (vq) {
+               /* We only support one device for now */
+               return -EBUSY;
+       }
        /* We expect a single virtqueue. */
        vq = virtio_find_single_vq(vdev, random_recv_done, "input");
-       if (IS_ERR(vq))
-               return PTR_ERR(vq);
+       if (IS_ERR(vq)) {
+               err = PTR_ERR(vq);
+               vq = NULL;
+               return err;
+       }
 
        err = hwrng_register(&virtio_hwrng);
        if (err) {
                vdev->config->del_vqs(vdev);
+               vq = NULL;
                return err;
        }
 
@@ -112,6 +120,7 @@ static void remove_common(struct virtio_device *vdev)
        busy = false;
        hwrng_unregister(&virtio_hwrng);
        vdev->config->del_vqs(vdev);
+       vq = NULL;
 }
 
 static int virtrng_probe(struct virtio_device *vdev)
index e905d5f5305180cd7cc77a8690e51ae53bed3fec..ce5f3fc25d6dbf1f7c45ff4cad6d2349da202d1a 100644 (file)
@@ -149,7 +149,8 @@ struct ports_device {
        spinlock_t ports_lock;
 
        /* To protect the vq operations for the control channel */
-       spinlock_t cvq_lock;
+       spinlock_t c_ivq_lock;
+       spinlock_t c_ovq_lock;
 
        /* The current config space is stored here */
        struct virtio_console_config config;
@@ -569,11 +570,14 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
        vq = portdev->c_ovq;
 
        sg_init_one(sg, &cpkt, sizeof(cpkt));
+
+       spin_lock(&portdev->c_ovq_lock);
        if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) == 0) {
                virtqueue_kick(vq);
                while (!virtqueue_get_buf(vq, &len))
                        cpu_relax();
        }
+       spin_unlock(&portdev->c_ovq_lock);
        return 0;
 }
 
@@ -1436,7 +1440,7 @@ static int add_port(struct ports_device *portdev, u32 id)
                 * rproc_serial does not want the console port, only
                 * the generic port implementation.
                 */
-               port->host_connected = port->guest_connected = true;
+               port->host_connected = true;
        else if (!use_multiport(port->portdev)) {
                /*
                 * If we're not using multiport support,
@@ -1709,23 +1713,23 @@ static void control_work_handler(struct work_struct *work)
        portdev = container_of(work, struct ports_device, control_work);
        vq = portdev->c_ivq;
 
-       spin_lock(&portdev->cvq_lock);
+       spin_lock(&portdev->c_ivq_lock);
        while ((buf = virtqueue_get_buf(vq, &len))) {
-               spin_unlock(&portdev->cvq_lock);
+               spin_unlock(&portdev->c_ivq_lock);
 
                buf->len = len;
                buf->offset = 0;
 
                handle_control_message(portdev, buf);
 
-               spin_lock(&portdev->cvq_lock);
+               spin_lock(&portdev->c_ivq_lock);
                if (add_inbuf(portdev->c_ivq, buf) < 0) {
                        dev_warn(&portdev->vdev->dev,
                                 "Error adding buffer to queue\n");
                        free_buf(buf, false);
                }
        }
-       spin_unlock(&portdev->cvq_lock);
+       spin_unlock(&portdev->c_ivq_lock);
 }
 
 static void out_intr(struct virtqueue *vq)
@@ -1752,13 +1756,23 @@ static void in_intr(struct virtqueue *vq)
        port->inbuf = get_inbuf(port);
 
        /*
-        * Don't queue up data when port is closed.  This condition
+        * Normally the port should not accept data when the port is
+        * closed. For generic serial ports, the host won't (shouldn't)
+        * send data till the guest is connected. But this condition
         * can be reached when a console port is not yet connected (no
-        * tty is spawned) and the host sends out data to console
-        * ports.  For generic serial ports, the host won't
-        * (shouldn't) send data till the guest is connected.
+        * tty is spawned) and the other side sends out data over the
+        * vring, or when a remote devices start sending data before
+        * the ports are opened.
+        *
+        * A generic serial port will discard data if not connected,
+        * while console ports and rproc-serial ports accepts data at
+        * any time. rproc-serial is initiated with guest_connected to
+        * false because port_fops_open expects this. Console ports are
+        * hooked up with an HVC console and is initialized with
+        * guest_connected to true.
         */
-       if (!port->guest_connected)
+
+       if (!port->guest_connected && !is_rproc_serial(port->portdev->vdev))
                discard_port_data(port);
 
        spin_unlock_irqrestore(&port->inbuf_lock, flags);
@@ -1986,10 +2000,12 @@ static int virtcons_probe(struct virtio_device *vdev)
        if (multiport) {
                unsigned int nr_added_bufs;
 
-               spin_lock_init(&portdev->cvq_lock);
+               spin_lock_init(&portdev->c_ivq_lock);
+               spin_lock_init(&portdev->c_ovq_lock);
                INIT_WORK(&portdev->control_work, &control_work_handler);
 
-               nr_added_bufs = fill_queue(portdev->c_ivq, &portdev->cvq_lock);
+               nr_added_bufs = fill_queue(portdev->c_ivq,
+                                          &portdev->c_ivq_lock);
                if (!nr_added_bufs) {
                        dev_err(&vdev->dev,
                                "Error allocating buffers for control queue\n");
@@ -2140,7 +2156,7 @@ static int virtcons_restore(struct virtio_device *vdev)
                return ret;
 
        if (use_multiport(portdev))
-               fill_queue(portdev->c_ivq, &portdev->cvq_lock);
+               fill_queue(portdev->c_ivq, &portdev->c_ivq_lock);
 
        list_for_each_entry(port, &portdev->ports, list) {
                port->in_vq = portdev->in_vqs[port->id];
index a47e6ee98b8c9798da8ffad462dbc052ef875053..a64caefdba1228a242f1177422aad485b40c2dc5 100644 (file)
@@ -63,6 +63,14 @@ config CLK_TWL6040
          McPDM. McPDM module is using the external bit clock on the McPDM bus
          as functional clock.
 
+config COMMON_CLK_AXI_CLKGEN
+       tristate "AXI clkgen driver"
+       depends on ARCH_ZYNQ || MICROBLAZE
+       help
+       ---help---
+         Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx
+         FPGAs. It is commonly used in Analog Devices' reference designs.
+
 endmenu
 
 source "drivers/clk/mvebu/Kconfig"
index 300d4775d9268334d30aeb1b6d8d7d8070de634b..17e8dc4e417cfdfa397a83649a1628f02fa382c3 100644 (file)
@@ -7,6 +7,7 @@ obj-$(CONFIG_COMMON_CLK)        += clk-fixed-factor.o
 obj-$(CONFIG_COMMON_CLK)       += clk-fixed-rate.o
 obj-$(CONFIG_COMMON_CLK)       += clk-gate.o
 obj-$(CONFIG_COMMON_CLK)       += clk-mux.o
+obj-$(CONFIG_COMMON_CLK)       += clk-composite.o
 
 # SoCs specific
 obj-$(CONFIG_ARCH_BCM2835)     += clk-bcm2835.o
@@ -23,14 +24,17 @@ ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)         += mmp/
 endif
 obj-$(CONFIG_MACH_LOONGSON1)   += clk-ls1x.o
+obj-$(CONFIG_ARCH_SUNXI)       += sunxi/
 obj-$(CONFIG_ARCH_U8500)       += ux500/
 obj-$(CONFIG_ARCH_VT8500)      += clk-vt8500.o
 obj-$(CONFIG_ARCH_ZYNQ)                += clk-zynq.o
 obj-$(CONFIG_ARCH_TEGRA)       += tegra/
+obj-$(CONFIG_PLAT_SAMSUNG)     += samsung/
 
 obj-$(CONFIG_X86)              += x86/
 
 # Chip specific
+obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
 obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o
 obj-$(CONFIG_CLK_TWL6040)      += clk-twl6040.o
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c
new file mode 100644 (file)
index 0000000..8137327
--- /dev/null
@@ -0,0 +1,331 @@
+/*
+ * AXI clkgen driver
+ *
+ * Copyright 2012-2013 Analog Devices Inc.
+ *  Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2.
+ *
+ */
+
+#include <linux/platform_device.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+#define AXI_CLKGEN_REG_UPDATE_ENABLE   0x04
+#define AXI_CLKGEN_REG_CLK_OUT1                0x08
+#define AXI_CLKGEN_REG_CLK_OUT2                0x0c
+#define AXI_CLKGEN_REG_CLK_DIV         0x10
+#define AXI_CLKGEN_REG_CLK_FB1         0x14
+#define AXI_CLKGEN_REG_CLK_FB2         0x18
+#define AXI_CLKGEN_REG_LOCK1           0x1c
+#define AXI_CLKGEN_REG_LOCK2           0x20
+#define AXI_CLKGEN_REG_LOCK3           0x24
+#define AXI_CLKGEN_REG_FILTER1         0x28
+#define AXI_CLKGEN_REG_FILTER2         0x2c
+
+struct axi_clkgen {
+       void __iomem *base;
+       struct clk_hw clk_hw;
+};
+
+static uint32_t axi_clkgen_lookup_filter(unsigned int m)
+{
+       switch (m) {
+       case 0:
+               return 0x01001990;
+       case 1:
+               return 0x01001190;
+       case 2:
+               return 0x01009890;
+       case 3:
+               return 0x01001890;
+       case 4:
+               return 0x01008890;
+       case 5 ... 8:
+               return 0x01009090;
+       case 9 ... 11:
+               return 0x01000890;
+       case 12:
+               return 0x08009090;
+       case 13 ... 22:
+               return 0x01001090;
+       case 23 ... 36:
+               return 0x01008090;
+       case 37 ... 46:
+               return 0x08001090;
+       default:
+               return 0x08008090;
+       }
+}
+
+static const uint32_t axi_clkgen_lock_table[] = {
+       0x060603e8, 0x060603e8, 0x080803e8, 0x0b0b03e8,
+       0x0e0e03e8, 0x111103e8, 0x131303e8, 0x161603e8,
+       0x191903e8, 0x1c1c03e8, 0x1f1f0384, 0x1f1f0339,
+       0x1f1f02ee, 0x1f1f02bc, 0x1f1f028a, 0x1f1f0271,
+       0x1f1f023f, 0x1f1f0226, 0x1f1f020d, 0x1f1f01f4,
+       0x1f1f01db, 0x1f1f01c2, 0x1f1f01a9, 0x1f1f0190,
+       0x1f1f0190, 0x1f1f0177, 0x1f1f015e, 0x1f1f015e,
+       0x1f1f0145, 0x1f1f0145, 0x1f1f012c, 0x1f1f012c,
+       0x1f1f012c, 0x1f1f0113, 0x1f1f0113, 0x1f1f0113,
+};
+
+static uint32_t axi_clkgen_lookup_lock(unsigned int m)
+{
+       if (m < ARRAY_SIZE(axi_clkgen_lock_table))
+               return axi_clkgen_lock_table[m];
+       return 0x1f1f00fa;
+}
+
+static const unsigned int fpfd_min = 10000;
+static const unsigned int fpfd_max = 300000;
+static const unsigned int fvco_min = 600000;
+static const unsigned int fvco_max = 1200000;
+
+static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout,
+       unsigned int *best_d, unsigned int *best_m, unsigned int *best_dout)
+{
+       unsigned long d, d_min, d_max, _d_min, _d_max;
+       unsigned long m, m_min, m_max;
+       unsigned long f, dout, best_f, fvco;
+
+       fin /= 1000;
+       fout /= 1000;
+
+       best_f = ULONG_MAX;
+       *best_d = 0;
+       *best_m = 0;
+       *best_dout = 0;
+
+       d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1);
+       d_max = min_t(unsigned long, fin / fpfd_min, 80);
+
+       m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min, fin) * d_min, 1);
+       m_max = min_t(unsigned long, fvco_max * d_max / fin, 64);
+
+       for (m = m_min; m <= m_max; m++) {
+               _d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max));
+               _d_max = min(d_max, fin * m / fvco_min);
+
+               for (d = _d_min; d <= _d_max; d++) {
+                       fvco = fin * m / d;
+
+                       dout = DIV_ROUND_CLOSEST(fvco, fout);
+                       dout = clamp_t(unsigned long, dout, 1, 128);
+                       f = fvco / dout;
+                       if (abs(f - fout) < abs(best_f - fout)) {
+                               best_f = f;
+                               *best_d = d;
+                               *best_m = m;
+                               *best_dout = dout;
+                               if (best_f == fout)
+                                       return;
+                       }
+               }
+       }
+}
+
+static void axi_clkgen_calc_clk_params(unsigned int divider, unsigned int *low,
+       unsigned int *high, unsigned int *edge, unsigned int *nocount)
+{
+       if (divider == 1)
+               *nocount = 1;
+       else
+               *nocount = 0;
+
+       *high = divider / 2;
+       *edge = divider % 2;
+       *low = divider - *high;
+}
+
+static void axi_clkgen_write(struct axi_clkgen *axi_clkgen,
+       unsigned int reg, unsigned int val)
+{
+       writel(val, axi_clkgen->base + reg);
+}
+
+static void axi_clkgen_read(struct axi_clkgen *axi_clkgen,
+       unsigned int reg, unsigned int *val)
+{
+       *val = readl(axi_clkgen->base + reg);
+}
+
+static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw)
+{
+       return container_of(clk_hw, struct axi_clkgen, clk_hw);
+}
+
+static int axi_clkgen_set_rate(struct clk_hw *clk_hw,
+       unsigned long rate, unsigned long parent_rate)
+{
+       struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
+       unsigned int d, m, dout;
+       unsigned int nocount;
+       unsigned int high;
+       unsigned int edge;
+       unsigned int low;
+       uint32_t filter;
+       uint32_t lock;
+
+       if (parent_rate == 0 || rate == 0)
+               return -EINVAL;
+
+       axi_clkgen_calc_params(parent_rate, rate, &d, &m, &dout);
+
+       if (d == 0 || dout == 0 || m == 0)
+               return -EINVAL;
+
+       filter = axi_clkgen_lookup_filter(m - 1);
+       lock = axi_clkgen_lookup_lock(m - 1);
+
+       axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 0);
+
+       axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount);
+       axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1,
+               (high << 6) | low);
+       axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT2,
+               (edge << 7) | (nocount << 6));
+
+       axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount);
+       axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV,
+               (edge << 13) | (nocount << 12) | (high << 6) | low);
+
+       axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount);
+       axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1,
+               (high << 6) | low);
+       axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB2,
+               (edge << 7) | (nocount << 6));
+
+       axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK1, lock & 0x3ff);
+       axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK2,
+               (((lock >> 16) & 0x1f) << 10) | 0x1);
+       axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK3,
+               (((lock >> 24) & 0x1f) << 10) | 0x3e9);
+       axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER1, filter >> 16);
+       axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER2, filter);
+
+       axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 1);
+
+       return 0;
+}
+
+static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate,
+       unsigned long *parent_rate)
+{
+       unsigned int d, m, dout;
+
+       axi_clkgen_calc_params(*parent_rate, rate, &d, &m, &dout);
+
+       if (d == 0 || dout == 0 || m == 0)
+               return -EINVAL;
+
+       return *parent_rate / d * m / dout;
+}
+
+static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw,
+       unsigned long parent_rate)
+{
+       struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw);
+       unsigned int d, m, dout;
+       unsigned int reg;
+       unsigned long long tmp;
+
+       axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, &reg);
+       dout = (reg & 0x3f) + ((reg >> 6) & 0x3f);
+       axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, &reg);
+       d = (reg & 0x3f) + ((reg >> 6) & 0x3f);
+       axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, &reg);
+       m = (reg & 0x3f) + ((reg >> 6) & 0x3f);
+
+       if (d == 0 || dout == 0)
+               return 0;
+
+       tmp = (unsigned long long)(parent_rate / d) * m;
+       do_div(tmp, dout);
+
+       if (tmp > ULONG_MAX)
+               return ULONG_MAX;
+
+       return tmp;
+}
+
+static const struct clk_ops axi_clkgen_ops = {
+       .recalc_rate = axi_clkgen_recalc_rate,
+       .round_rate = axi_clkgen_round_rate,
+       .set_rate = axi_clkgen_set_rate,
+};
+
+static int axi_clkgen_probe(struct platform_device *pdev)
+{
+       struct axi_clkgen *axi_clkgen;
+       struct clk_init_data init;
+       const char *parent_name;
+       const char *clk_name;
+       struct resource *mem;
+       struct clk *clk;
+
+       axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL);
+       if (!axi_clkgen)
+               return -ENOMEM;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem);
+       if (IS_ERR(axi_clkgen->base))
+               return PTR_ERR(axi_clkgen->base);
+
+       parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0);
+       if (!parent_name)
+               return -EINVAL;
+
+       clk_name = pdev->dev.of_node->name;
+       of_property_read_string(pdev->dev.of_node, "clock-output-names",
+               &clk_name);
+
+       init.name = clk_name;
+       init.ops = &axi_clkgen_ops;
+       init.flags = 0;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       axi_clkgen->clk_hw.init = &init;
+       clk = devm_clk_register(&pdev->dev, &axi_clkgen->clk_hw);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       return of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get,
+                                   clk);
+}
+
+static int axi_clkgen_remove(struct platform_device *pdev)
+{
+       of_clk_del_provider(pdev->dev.of_node);
+
+       return 0;
+}
+
+static const struct of_device_id axi_clkgen_ids[] = {
+       { .compatible = "adi,axi-clkgen-1.00.a" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, axi_clkgen_ids);
+
+static struct platform_driver axi_clkgen_driver = {
+       .driver = {
+               .name = "adi-axi-clkgen",
+               .owner = THIS_MODULE,
+               .of_match_table = axi_clkgen_ids,
+       },
+       .probe = axi_clkgen_probe,
+       .remove = axi_clkgen_remove,
+};
+module_platform_driver(axi_clkgen_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("Driver for the Analog Devices' AXI clkgen pcore clock generator");
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c
new file mode 100644 (file)
index 0000000..097dee4
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2013 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * 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/clk-provider.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw)
+
+static u8 clk_composite_get_parent(struct clk_hw *hw)
+{
+       struct clk_composite *composite = to_clk_composite(hw);
+       const struct clk_ops *mux_ops = composite->mux_ops;
+       struct clk_hw *mux_hw = composite->mux_hw;
+
+       mux_hw->clk = hw->clk;
+
+       return mux_ops->get_parent(mux_hw);
+}
+
+static int clk_composite_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct clk_composite *composite = to_clk_composite(hw);
+       const struct clk_ops *mux_ops = composite->mux_ops;
+       struct clk_hw *mux_hw = composite->mux_hw;
+
+       mux_hw->clk = hw->clk;
+
+       return mux_ops->set_parent(mux_hw, index);
+}
+
+static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
+                                           unsigned long parent_rate)
+{
+       struct clk_composite *composite = to_clk_composite(hw);
+       const struct clk_ops *div_ops = composite->div_ops;
+       struct clk_hw *div_hw = composite->div_hw;
+
+       div_hw->clk = hw->clk;
+
+       return div_ops->recalc_rate(div_hw, parent_rate);
+}
+
+static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate,
+                                 unsigned long *prate)
+{
+       struct clk_composite *composite = to_clk_composite(hw);
+       const struct clk_ops *div_ops = composite->div_ops;
+       struct clk_hw *div_hw = composite->div_hw;
+
+       div_hw->clk = hw->clk;
+
+       return div_ops->round_rate(div_hw, rate, prate);
+}
+
+static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate,
+                              unsigned long parent_rate)
+{
+       struct clk_composite *composite = to_clk_composite(hw);
+       const struct clk_ops *div_ops = composite->div_ops;
+       struct clk_hw *div_hw = composite->div_hw;
+
+       div_hw->clk = hw->clk;
+
+       return div_ops->set_rate(div_hw, rate, parent_rate);
+}
+
+static int clk_composite_is_enabled(struct clk_hw *hw)
+{
+       struct clk_composite *composite = to_clk_composite(hw);
+       const struct clk_ops *gate_ops = composite->gate_ops;
+       struct clk_hw *gate_hw = composite->gate_hw;
+
+       gate_hw->clk = hw->clk;
+
+       return gate_ops->is_enabled(gate_hw);
+}
+
+static int clk_composite_enable(struct clk_hw *hw)
+{
+       struct clk_composite *composite = to_clk_composite(hw);
+       const struct clk_ops *gate_ops = composite->gate_ops;
+       struct clk_hw *gate_hw = composite->gate_hw;
+
+       gate_hw->clk = hw->clk;
+
+       return gate_ops->enable(gate_hw);
+}
+
+static void clk_composite_disable(struct clk_hw *hw)
+{
+       struct clk_composite *composite = to_clk_composite(hw);
+       const struct clk_ops *gate_ops = composite->gate_ops;
+       struct clk_hw *gate_hw = composite->gate_hw;
+
+       gate_hw->clk = hw->clk;
+
+       gate_ops->disable(gate_hw);
+}
+
+struct clk *clk_register_composite(struct device *dev, const char *name,
+                       const char **parent_names, int num_parents,
+                       struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
+                       struct clk_hw *div_hw, const struct clk_ops *div_ops,
+                       struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+                       unsigned long flags)
+{
+       struct clk *clk;
+       struct clk_init_data init;
+       struct clk_composite *composite;
+       struct clk_ops *clk_composite_ops;
+
+       composite = kzalloc(sizeof(*composite), GFP_KERNEL);
+       if (!composite) {
+               pr_err("%s: could not allocate composite clk\n", __func__);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       init.name = name;
+       init.flags = flags | CLK_IS_BASIC;
+       init.parent_names = parent_names;
+       init.num_parents = num_parents;
+
+       clk_composite_ops = &composite->ops;
+
+       if (mux_hw && mux_ops) {
+               if (!mux_ops->get_parent || !mux_ops->set_parent) {
+                       clk = ERR_PTR(-EINVAL);
+                       goto err;
+               }
+
+               composite->mux_hw = mux_hw;
+               composite->mux_ops = mux_ops;
+               clk_composite_ops->get_parent = clk_composite_get_parent;
+               clk_composite_ops->set_parent = clk_composite_set_parent;
+       }
+
+       if (div_hw && div_ops) {
+               if (!div_ops->recalc_rate || !div_ops->round_rate ||
+                   !div_ops->set_rate) {
+                       clk = ERR_PTR(-EINVAL);
+                       goto err;
+               }
+
+               composite->div_hw = div_hw;
+               composite->div_ops = div_ops;
+               clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
+               clk_composite_ops->round_rate = clk_composite_round_rate;
+               clk_composite_ops->set_rate = clk_composite_set_rate;
+       }
+
+       if (gate_hw && gate_ops) {
+               if (!gate_ops->is_enabled || !gate_ops->enable ||
+                   !gate_ops->disable) {
+                       clk = ERR_PTR(-EINVAL);
+                       goto err;
+               }
+
+               composite->gate_hw = gate_hw;
+               composite->gate_ops = gate_ops;
+               clk_composite_ops->is_enabled = clk_composite_is_enabled;
+               clk_composite_ops->enable = clk_composite_enable;
+               clk_composite_ops->disable = clk_composite_disable;
+       }
+
+       init.ops = clk_composite_ops;
+       composite->hw.init = &init;
+
+       clk = clk_register(dev, &composite->hw);
+       if (IS_ERR(clk))
+               goto err;
+
+       if (composite->mux_hw)
+               composite->mux_hw->clk = clk;
+
+       if (composite->div_hw)
+               composite->div_hw->clk = clk;
+
+       if (composite->gate_hw)
+               composite->gate_hw->clk = clk;
+
+       return clk;
+
+err:
+       kfree(composite);
+       return clk;
+}
index 508c032edce43e43259ca88ecfd9b77dc5704ce8..25b1734560d0c99bbae8455c78d22d613ccb99c0 100644 (file)
@@ -32,6 +32,7 @@
 static u8 clk_mux_get_parent(struct clk_hw *hw)
 {
        struct clk_mux *mux = to_clk_mux(hw);
+       int num_parents = __clk_get_num_parents(hw->clk);
        u32 val;
 
        /*
@@ -42,7 +43,16 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
         * val = 0x4 really means "bit 2, index starts at bit 0"
         */
        val = readl(mux->reg) >> mux->shift;
-       val &= (1 << mux->width) - 1;
+       val &= mux->mask;
+
+       if (mux->table) {
+               int i;
+
+               for (i = 0; i < num_parents; i++)
+                       if (mux->table[i] == val)
+                               return i;
+               return -EINVAL;
+       }
 
        if (val && (mux->flags & CLK_MUX_INDEX_BIT))
                val = ffs(val) - 1;
@@ -50,7 +60,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
        if (val && (mux->flags & CLK_MUX_INDEX_ONE))
                val--;
 
-       if (val >= __clk_get_num_parents(hw->clk))
+       if (val >= num_parents)
                return -EINVAL;
 
        return val;
@@ -62,17 +72,22 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
        u32 val;
        unsigned long flags = 0;
 
-       if (mux->flags & CLK_MUX_INDEX_BIT)
-               index = (1 << ffs(index));
+       if (mux->table)
+               index = mux->table[index];
 
-       if (mux->flags & CLK_MUX_INDEX_ONE)
-               index++;
+       else {
+               if (mux->flags & CLK_MUX_INDEX_BIT)
+                       index = (1 << ffs(index));
+
+               if (mux->flags & CLK_MUX_INDEX_ONE)
+                       index++;
+       }
 
        if (mux->lock)
                spin_lock_irqsave(mux->lock, flags);
 
        val = readl(mux->reg);
-       val &= ~(((1 << mux->width) - 1) << mux->shift);
+       val &= ~(mux->mask << mux->shift);
        val |= index << mux->shift;
        writel(val, mux->reg);
 
@@ -88,10 +103,10 @@ const struct clk_ops clk_mux_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_mux_ops);
 
-struct clk *clk_register_mux(struct device *dev, const char *name,
+struct clk *clk_register_mux_table(struct device *dev, const char *name,
                const char **parent_names, u8 num_parents, unsigned long flags,
-               void __iomem *reg, u8 shift, u8 width,
-               u8 clk_mux_flags, spinlock_t *lock)
+               void __iomem *reg, u8 shift, u32 mask,
+               u8 clk_mux_flags, u32 *table, spinlock_t *lock)
 {
        struct clk_mux *mux;
        struct clk *clk;
@@ -113,9 +128,10 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
        /* struct clk_mux assignments */
        mux->reg = reg;
        mux->shift = shift;
-       mux->width = width;
+       mux->mask = mask;
        mux->flags = clk_mux_flags;
        mux->lock = lock;
+       mux->table = table;
        mux->hw.init = &init;
 
        clk = clk_register(dev, &mux->hw);
@@ -125,3 +141,15 @@ struct clk *clk_register_mux(struct device *dev, const char *name,
 
        return clk;
 }
+
+struct clk *clk_register_mux(struct device *dev, const char *name,
+               const char **parent_names, u8 num_parents, unsigned long flags,
+               void __iomem *reg, u8 shift, u8 width,
+               u8 clk_mux_flags, spinlock_t *lock)
+{
+       u32 mask = BIT(width) - 1;
+
+       return clk_register_mux_table(dev, name, parent_names, num_parents,
+                                     flags, reg, shift, mask, clk_mux_flags,
+                                     NULL, lock);
+}
index f8e9d0c27be27252f53aeb0ecec904c9caabc99a..643ca653fef026b2de60235a1ef401e67c88148a 100644 (file)
@@ -1113,7 +1113,7 @@ void __init sirfsoc_of_clk_init(void)
 
        for (i = pll1; i < maxclk; i++) {
                prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]);
-               BUG_ON(!prima2_clks[i]);
+               BUG_ON(IS_ERR(prima2_clks[i]));
        }
        clk_register_clkdev(prima2_clks[cpu], NULL, "cpu");
        clk_register_clkdev(prima2_clks[io],  NULL, "io");
index b5538bba7a10b84581c70d51357a8e360fc81545..09c63315e57979f8d726f627279f0e5e88e94c3f 100644 (file)
@@ -157,7 +157,7 @@ static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate,
        divisor =  parent_rate / rate;
 
        /* If prate / rate would be decimal, incr the divisor */
-       if (rate * divisor < *prate)
+       if (rate * divisor < parent_rate)
                divisor++;
 
        if (divisor == cdev->div_mask + 1)
index b14a25f3925514ac09ee75953fa07e4104291b5b..32062977f45368d9561410193238362d29a332f4 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/clk-provider.h>
+#include <linux/clk/zynq.h>
 
 static void __iomem *slcr_base;
 
index ed87b2405806f6a80f24b607be5d23ccc922ce26..0230c9d959752a954d36192ba4f24b59f9fa3541 100644 (file)
 #include <linux/of.h>
 #include <linux/device.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 
 static DEFINE_SPINLOCK(enable_lock);
 static DEFINE_MUTEX(prepare_lock);
 
+static struct task_struct *prepare_owner;
+static struct task_struct *enable_owner;
+
+static int prepare_refcnt;
+static int enable_refcnt;
+
 static HLIST_HEAD(clk_root_list);
 static HLIST_HEAD(clk_orphan_list);
 static LIST_HEAD(clk_notifier_list);
 
+/***           locking             ***/
+static void clk_prepare_lock(void)
+{
+       if (!mutex_trylock(&prepare_lock)) {
+               if (prepare_owner == current) {
+                       prepare_refcnt++;
+                       return;
+               }
+               mutex_lock(&prepare_lock);
+       }
+       WARN_ON_ONCE(prepare_owner != NULL);
+       WARN_ON_ONCE(prepare_refcnt != 0);
+       prepare_owner = current;
+       prepare_refcnt = 1;
+}
+
+static void clk_prepare_unlock(void)
+{
+       WARN_ON_ONCE(prepare_owner != current);
+       WARN_ON_ONCE(prepare_refcnt == 0);
+
+       if (--prepare_refcnt)
+               return;
+       prepare_owner = NULL;
+       mutex_unlock(&prepare_lock);
+}
+
+static unsigned long clk_enable_lock(void)
+{
+       unsigned long flags;
+
+       if (!spin_trylock_irqsave(&enable_lock, flags)) {
+               if (enable_owner == current) {
+                       enable_refcnt++;
+                       return flags;
+               }
+               spin_lock_irqsave(&enable_lock, flags);
+       }
+       WARN_ON_ONCE(enable_owner != NULL);
+       WARN_ON_ONCE(enable_refcnt != 0);
+       enable_owner = current;
+       enable_refcnt = 1;
+       return flags;
+}
+
+static void clk_enable_unlock(unsigned long flags)
+{
+       WARN_ON_ONCE(enable_owner != current);
+       WARN_ON_ONCE(enable_refcnt == 0);
+
+       if (--enable_refcnt)
+               return;
+       enable_owner = NULL;
+       spin_unlock_irqrestore(&enable_lock, flags);
+}
+
 /***        debugfs support        ***/
 
 #ifdef CONFIG_COMMON_CLK_DEBUG
@@ -69,7 +132,7 @@ static int clk_summary_show(struct seq_file *s, void *data)
        seq_printf(s, "   clock                        enable_cnt  prepare_cnt  rate\n");
        seq_printf(s, "---------------------------------------------------------------------\n");
 
-       mutex_lock(&prepare_lock);
+       clk_prepare_lock();
 
        hlist_for_each_entry(c, &clk_root_list, child_node)
                clk_summary_show_subtree(s, c, 0);
@@ -77,7 +140,7 @@ static int clk_summary_show(struct seq_file *s, void *data)
        hlist_for_each_entry(c, &clk_orphan_list, child_node)
                clk_summary_show_subtree(s, c, 0);
 
-       mutex_unlock(&prepare_lock);
+       clk_prepare_unlock();
 
        return 0;
 }
@@ -130,7 +193,7 @@ static int clk_dump(struct seq_file *s, void *data)
 
        seq_printf(s, "{");
 
-       mutex_lock(&prepare_lock);
+       clk_prepare_lock();
 
        hlist_for_each_entry(c, &clk_root_list, child_node) {
                if (!first_node)
@@ -144,7 +207,7 @@ static int clk_dump(struct seq_file *s, void *data)
                clk_dump_subtree(s, c, 0);
        }
 
-       mutex_unlock(&prepare_lock);
+       clk_prepare_unlock();
 
        seq_printf(s, "}");
        return 0;
@@ -316,7 +379,7 @@ static int __init clk_debug_init(void)
        if (!orphandir)
                return -ENOMEM;
 
-       mutex_lock(&prepare_lock);
+       clk_prepare_lock();
 
        hlist_for_each_entry(clk, &clk_root_list, child_node)
                clk_debug_create_subtree(clk, rootdir);
@@ -326,7 +389,7 @@ static int __init clk_debug_init(void)
 
        inited = 1;
 
-       mutex_unlock(&prepare_lock);
+       clk_prepare_unlock();
 
        return 0;
 }
@@ -335,6 +398,31 @@ late_initcall(clk_debug_init);
 static inline int clk_debug_register(struct clk *clk) { return 0; }
 #endif
 
+/* caller must hold prepare_lock */
+static void clk_unprepare_unused_subtree(struct clk *clk)
+{
+       struct clk *child;
+
+       if (!clk)
+               return;
+
+       hlist_for_each_entry(child, &clk->children, child_node)
+               clk_unprepare_unused_subtree(child);
+
+       if (clk->prepare_count)
+               return;
+
+       if (clk->flags & CLK_IGNORE_UNUSED)
+               return;
+
+       if (__clk_is_prepared(clk)) {
+               if (clk->ops->unprepare_unused)
+                       clk->ops->unprepare_unused(clk->hw);
+               else if (clk->ops->unprepare)
+                       clk->ops->unprepare(clk->hw);
+       }
+}
+
 /* caller must hold prepare_lock */
 static void clk_disable_unused_subtree(struct clk *clk)
 {
@@ -347,7 +435,7 @@ static void clk_disable_unused_subtree(struct clk *clk)
        hlist_for_each_entry(child, &clk->children, child_node)
                clk_disable_unused_subtree(child);
 
-       spin_lock_irqsave(&enable_lock, flags);
+       flags = clk_enable_lock();
 
        if (clk->enable_count)
                goto unlock_out;
@@ -368,7 +456,7 @@ static void clk_disable_unused_subtree(struct clk *clk)
        }
 
 unlock_out:
-       spin_unlock_irqrestore(&enable_lock, flags);
+       clk_enable_unlock(flags);
 
 out:
        return;
@@ -378,7 +466,7 @@ static int clk_disable_unused(void)
 {
        struct clk *clk;
 
-       mutex_lock(&prepare_lock);
+       clk_prepare_lock();
 
        hlist_for_each_entry(clk, &clk_root_list, child_node)
                clk_disable_unused_subtree(clk);
@@ -386,7 +474,13 @@ static int clk_disable_unused(void)
        hlist_for_each_entry(clk, &clk_orphan_list, child_node)
                clk_disable_unused_subtree(clk);
 
-       mutex_unlock(&prepare_lock);
+       hlist_for_each_entry(clk, &clk_root_list, child_node)
+               clk_unprepare_unused_subtree(clk);
+
+       hlist_for_each_entry(clk, &clk_orphan_list, child_node)
+               clk_unprepare_unused_subtree(clk);
+
+       clk_prepare_unlock();
 
        return 0;
 }
@@ -451,6 +545,27 @@ unsigned long __clk_get_flags(struct clk *clk)
        return !clk ? 0 : clk->flags;
 }
 
+bool __clk_is_prepared(struct clk *clk)
+{
+       int ret;
+
+       if (!clk)
+               return false;
+
+       /*
+        * .is_prepared is optional for clocks that can prepare
+        * fall back to software usage counter if it is missing
+        */
+       if (!clk->ops->is_prepared) {
+               ret = clk->prepare_count ? 1 : 0;
+               goto out;
+       }
+
+       ret = clk->ops->is_prepared(clk->hw);
+out:
+       return !!ret;
+}
+
 bool __clk_is_enabled(struct clk *clk)
 {
        int ret;
@@ -548,9 +663,9 @@ void __clk_unprepare(struct clk *clk)
  */
 void clk_unprepare(struct clk *clk)
 {
-       mutex_lock(&prepare_lock);
+       clk_prepare_lock();
        __clk_unprepare(clk);
-       mutex_unlock(&prepare_lock);
+       clk_prepare_unlock();
 }
 EXPORT_SYMBOL_GPL(clk_unprepare);
 
@@ -596,9 +711,9 @@ int clk_prepare(struct clk *clk)
 {
        int ret;
 
-       mutex_lock(&prepare_lock);
+       clk_prepare_lock();
        ret = __clk_prepare(clk);
-       mutex_unlock(&prepare_lock);
+       clk_prepare_unlock();
 
        return ret;
 }
@@ -640,9 +755,9 @@ void clk_disable(struct clk *clk)
 {
        unsigned long flags;
 
-       spin_lock_irqsave(&enable_lock, flags);
+       flags = clk_enable_lock();
        __clk_disable(clk);
-       spin_unlock_irqrestore(&enable_lock, flags);
+       clk_enable_unlock(flags);
 }
 EXPORT_SYMBOL_GPL(clk_disable);
 
@@ -693,9 +808,9 @@ int clk_enable(struct clk *clk)
        unsigned long flags;
        int ret;
 
-       spin_lock_irqsave(&enable_lock, flags);
+       flags = clk_enable_lock();
        ret = __clk_enable(clk);
-       spin_unlock_irqrestore(&enable_lock, flags);
+       clk_enable_unlock(flags);
 
        return ret;
 }
@@ -740,9 +855,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
 {
        unsigned long ret;
 
-       mutex_lock(&prepare_lock);
+       clk_prepare_lock();
        ret = __clk_round_rate(clk, rate);
-       mutex_unlock(&prepare_lock);
+       clk_prepare_unlock();
 
        return ret;
 }
@@ -837,13 +952,13 @@ unsigned long clk_get_rate(struct clk *clk)
 {
        unsigned long rate;
 
-       mutex_lock(&prepare_lock);
+       clk_prepare_lock();
 
        if (clk && (clk->flags & CLK_GET_RATE_NOCACHE))
                __clk_recalc_rates(clk, 0);
 
        rate = __clk_get_rate(clk);
-       mutex_unlock(&prepare_lock);
+       clk_prepare_unlock();
 
        return rate;
 }
@@ -974,7 +1089,7 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even
        int ret = NOTIFY_DONE;
 
        if (clk->rate == clk->new_rate)
-               return 0;
+               return NULL;
 
        if (clk->notifier_count) {
                ret = __clk_notify(clk, event, clk->rate, clk->new_rate);
@@ -1048,7 +1163,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
        int ret = 0;
 
        /* prevent racing with updates to the clock topology */
-       mutex_lock(&prepare_lock);
+       clk_prepare_lock();
 
        /* bail early if nothing to do */
        if (rate == clk->rate)
@@ -1080,7 +1195,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
        clk_change_rate(top);
 
 out:
-       mutex_unlock(&prepare_lock);
+       clk_prepare_unlock();
 
        return ret;
 }
@@ -1096,9 +1211,9 @@ struct clk *clk_get_parent(struct clk *clk)
 {
        struct clk *parent;
 
-       mutex_lock(&prepare_lock);
+       clk_prepare_lock();
        parent = __clk_get_parent(clk);
-       mutex_unlock(&prepare_lock);
+       clk_prepare_unlock();
 
        return parent;
 }
@@ -1242,19 +1357,19 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent)
                __clk_prepare(parent);
 
        /* FIXME replace with clk_is_enabled(clk) someday */
-       spin_lock_irqsave(&enable_lock, flags);
+       flags = clk_enable_lock();
        if (clk->enable_count)
                __clk_enable(parent);
-       spin_unlock_irqrestore(&enable_lock, flags);
+       clk_enable_unlock(flags);
 
        /* change clock input source */
        ret = clk->ops->set_parent(clk->hw, i);
 
        /* clean up old prepare and enable */
-       spin_lock_irqsave(&enable_lock, flags);
+       flags = clk_enable_lock();
        if (clk->enable_count)
                __clk_disable(old_parent);
-       spin_unlock_irqrestore(&enable_lock, flags);
+       clk_enable_unlock(flags);
 
        if (clk->prepare_count)
                __clk_unprepare(old_parent);
@@ -1286,7 +1401,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
                return -ENOSYS;
 
        /* prevent racing with updates to the clock topology */
-       mutex_lock(&prepare_lock);
+       clk_prepare_lock();
 
        if (clk->parent == parent)
                goto out;
@@ -1315,7 +1430,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent)
        __clk_reparent(clk, parent);
 
 out:
-       mutex_unlock(&prepare_lock);
+       clk_prepare_unlock();
 
        return ret;
 }
@@ -1338,7 +1453,7 @@ int __clk_init(struct device *dev, struct clk *clk)
        if (!clk)
                return -EINVAL;
 
-       mutex_lock(&prepare_lock);
+       clk_prepare_lock();
 
        /* check to see if a clock with this name is already registered */
        if (__clk_lookup(clk->name)) {
@@ -1462,7 +1577,7 @@ int __clk_init(struct device *dev, struct clk *clk)
        clk_debug_register(clk);
 
 out:
-       mutex_unlock(&prepare_lock);
+       clk_prepare_unlock();
 
        return ret;
 }
@@ -1696,7 +1811,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
        if (!clk || !nb)
                return -EINVAL;
 
-       mutex_lock(&prepare_lock);
+       clk_prepare_lock();
 
        /* search the list of notifiers for this clk */
        list_for_each_entry(cn, &clk_notifier_list, node)
@@ -1720,7 +1835,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
        clk->notifier_count++;
 
 out:
-       mutex_unlock(&prepare_lock);
+       clk_prepare_unlock();
 
        return ret;
 }
@@ -1745,7 +1860,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
        if (!clk || !nb)
                return -EINVAL;
 
-       mutex_lock(&prepare_lock);
+       clk_prepare_lock();
 
        list_for_each_entry(cn, &clk_notifier_list, node)
                if (cn->clk == clk)
@@ -1766,7 +1881,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb)
                ret = -ENOENT;
        }
 
-       mutex_unlock(&prepare_lock);
+       clk_prepare_unlock();
 
        return ret;
 }
index b24d56067c800a987b13746bc780a8d0e9ca4486..5301bce8957b92e9cb5a40f692d26180e767737e 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 #include <linux/jiffies.h>
 #include <linux/spinlock.h>
+#include "clk.h"
 
 DEFINE_SPINLOCK(mxs_lock);
 
diff --git a/drivers/clk/samsung/Makefile b/drivers/clk/samsung/Makefile
new file mode 100644 (file)
index 0000000..b7c232e
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Samsung Clock specific Makefile
+#
+
+obj-$(CONFIG_COMMON_CLK)       += clk.o clk-pll.o
+obj-$(CONFIG_ARCH_EXYNOS4)     += clk-exynos4.o
+obj-$(CONFIG_SOC_EXYNOS5250)   += clk-exynos5250.o
+obj-$(CONFIG_SOC_EXYNOS5440)   += clk-exynos5440.o
diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c
new file mode 100644 (file)
index 0000000..d0940e6
--- /dev/null
@@ -0,0 +1,1082 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@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.
+ *
+ * Common Clock Framework support for all Exynos4 SoCs.
+*/
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk.h"
+#include "clk-pll.h"
+
+/* Exynos4 clock controller register offsets */
+#define SRC_LEFTBUS            0x4200
+#define DIV_LEFTBUS            0x4500
+#define GATE_IP_LEFTBUS                0x4800
+#define E4X12_GATE_IP_IMAGE    0x4930
+#define SRC_RIGHTBUS           0x8200
+#define DIV_RIGHTBUS           0x8500
+#define GATE_IP_RIGHTBUS       0x8800
+#define E4X12_GATE_IP_PERIR    0x8960
+#define EPLL_LOCK              0xc010
+#define VPLL_LOCK              0xc020
+#define EPLL_CON0              0xc110
+#define EPLL_CON1              0xc114
+#define EPLL_CON2              0xc118
+#define VPLL_CON0              0xc120
+#define VPLL_CON1              0xc124
+#define VPLL_CON2              0xc128
+#define SRC_TOP0               0xc210
+#define SRC_TOP1               0xc214
+#define SRC_CAM                        0xc220
+#define SRC_TV                 0xc224
+#define SRC_MFC                        0xcc28
+#define SRC_G3D                        0xc22c
+#define E4210_SRC_IMAGE                0xc230
+#define SRC_LCD0               0xc234
+#define E4210_SRC_LCD1         0xc238
+#define E4X12_SRC_ISP          0xc238
+#define SRC_MAUDIO             0xc23c
+#define SRC_FSYS               0xc240
+#define SRC_PERIL0             0xc250
+#define SRC_PERIL1             0xc254
+#define E4X12_SRC_CAM1         0xc258
+#define SRC_MASK_TOP           0xc310
+#define SRC_MASK_CAM           0xc320
+#define SRC_MASK_TV            0xc324
+#define SRC_MASK_LCD0          0xc334
+#define E4210_SRC_MASK_LCD1    0xc338
+#define E4X12_SRC_MASK_ISP     0xc338
+#define SRC_MASK_MAUDIO                0xc33c
+#define SRC_MASK_FSYS          0xc340
+#define SRC_MASK_PERIL0                0xc350
+#define SRC_MASK_PERIL1                0xc354
+#define DIV_TOP                        0xc510
+#define DIV_CAM                        0xc520
+#define DIV_TV                 0xc524
+#define DIV_MFC                        0xc528
+#define DIV_G3D                        0xc52c
+#define DIV_IMAGE              0xc530
+#define DIV_LCD0               0xc534
+#define E4210_DIV_LCD1         0xc538
+#define E4X12_DIV_ISP          0xc538
+#define DIV_MAUDIO             0xc53c
+#define DIV_FSYS0              0xc540
+#define DIV_FSYS1              0xc544
+#define DIV_FSYS2              0xc548
+#define DIV_FSYS3              0xc54c
+#define DIV_PERIL0             0xc550
+#define DIV_PERIL1             0xc554
+#define DIV_PERIL2             0xc558
+#define DIV_PERIL3             0xc55c
+#define DIV_PERIL4             0xc560
+#define DIV_PERIL5             0xc564
+#define E4X12_DIV_CAM1         0xc568
+#define GATE_SCLK_CAM          0xc820
+#define GATE_IP_CAM            0xc920
+#define GATE_IP_TV             0xc924
+#define GATE_IP_MFC            0xc928
+#define GATE_IP_G3D            0xc92c
+#define E4210_GATE_IP_IMAGE    0xc930
+#define GATE_IP_LCD0           0xc934
+#define E4210_GATE_IP_LCD1     0xc938
+#define E4X12_GATE_IP_ISP      0xc938
+#define E4X12_GATE_IP_MAUDIO   0xc93c
+#define GATE_IP_FSYS           0xc940
+#define GATE_IP_GPS            0xc94c
+#define GATE_IP_PERIL          0xc950
+#define E4210_GATE_IP_PERIR    0xc960
+#define GATE_BLOCK             0xc970
+#define E4X12_MPLL_CON0                0x10108
+#define SRC_DMC                        0x10200
+#define SRC_MASK_DMC           0x10300
+#define DIV_DMC0               0x10500
+#define DIV_DMC1               0x10504
+#define GATE_IP_DMC            0x10900
+#define APLL_CON0              0x14100
+#define E4210_MPLL_CON0                0x14108
+#define SRC_CPU                        0x14200
+#define DIV_CPU0               0x14500
+#define DIV_CPU1               0x14504
+#define GATE_SCLK_CPU          0x14800
+#define GATE_IP_CPU            0x14900
+#define E4X12_DIV_ISP0         0x18300
+#define E4X12_DIV_ISP1         0x18304
+#define E4X12_GATE_ISP0                0x18800
+#define E4X12_GATE_ISP1                0x18804
+
+/* the exynos4 soc type */
+enum exynos4_soc {
+       EXYNOS4210,
+       EXYNOS4X12,
+};
+
+/*
+ * Let each supported clock get a unique id. This id is used to lookup the clock
+ * for device tree based platforms. The clocks are categorized into three
+ * sections: core, sclk gate and bus interface gate clocks.
+ *
+ * When adding a new clock to this list, it is advised to choose a clock
+ * category and add it to the end of that category. That is because the the
+ * device tree source file is referring to these ids and any change in the
+ * sequence number of existing clocks will require corresponding change in the
+ * device tree files. This limitation would go away when pre-processor support
+ * for dtc would be available.
+ */
+enum exynos4_clks {
+       none,
+
+       /* core clocks */
+       xxti, xusbxti, fin_pll, fout_apll, fout_mpll, fout_epll, fout_vpll,
+       sclk_apll, sclk_mpll, sclk_epll, sclk_vpll, arm_clk, aclk200, aclk100,
+       aclk160, aclk133, mout_mpll_user_t, mout_mpll_user_c, mout_core,
+       mout_apll, /* 20 */
+
+       /* gate for special clocks (sclk) */
+       sclk_fimc0 = 128, sclk_fimc1, sclk_fimc2, sclk_fimc3, sclk_cam0,
+       sclk_cam1, sclk_csis0, sclk_csis1, sclk_hdmi, sclk_mixer, sclk_dac,
+       sclk_pixel, sclk_fimd0, sclk_mdnie0, sclk_mdnie_pwm0, sclk_mipi0,
+       sclk_audio0, sclk_mmc0, sclk_mmc1, sclk_mmc2, sclk_mmc3, sclk_mmc4,
+       sclk_sata, sclk_uart0, sclk_uart1, sclk_uart2, sclk_uart3, sclk_uart4,
+       sclk_audio1, sclk_audio2, sclk_spdif, sclk_spi0, sclk_spi1, sclk_spi2,
+       sclk_slimbus, sclk_fimd1, sclk_mipi1, sclk_pcm1, sclk_pcm2, sclk_i2s1,
+       sclk_i2s2, sclk_mipihsi, sclk_mfc, sclk_pcm0, sclk_g3d, sclk_pwm_isp,
+       sclk_spi0_isp, sclk_spi1_isp, sclk_uart_isp,
+
+       /* gate clocks */
+       fimc0 = 256, fimc1, fimc2, fimc3, csis0, csis1, jpeg, smmu_fimc0,
+       smmu_fimc1, smmu_fimc2, smmu_fimc3, smmu_jpeg, vp, mixer, tvenc, hdmi,
+       smmu_tv, mfc, smmu_mfcl, smmu_mfcr, g3d, g2d, rotator, mdma, smmu_g2d,
+       smmu_rotator, smmu_mdma, fimd0, mie0, mdnie0, dsim0, smmu_fimd0, fimd1,
+       mie1, dsim1, smmu_fimd1, pdma0, pdma1, pcie_phy, sata_phy, tsi, sdmmc0,
+       sdmmc1, sdmmc2, sdmmc3, sdmmc4, sata, sromc, usb_host, usb_device, pcie,
+       onenand, nfcon, smmu_pcie, gps, smmu_gps, uart0, uart1, uart2, uart3,
+       uart4, i2c0, i2c1, i2c2, i2c3, i2c4, i2c5, i2c6, i2c7, i2c_hdmi, tsadc,
+       spi0, spi1, spi2, i2s1, i2s2, pcm0, i2s0, pcm1, pcm2, pwm, slimbus,
+       spdif, ac97, modemif, chipid, sysreg, hdmi_cec, mct, wdt, rtc, keyif,
+       audss, mipi_hsi, mdma2, pixelasyncm0, pixelasyncm1, fimc_lite0,
+       fimc_lite1, ppmuispx, ppmuispmx, fimc_isp, fimc_drc, fimc_fd, mcuisp,
+       gicisp, smmu_isp, smmu_drc, smmu_fd, smmu_lite0, smmu_lite1, mcuctl_isp,
+       mpwm_isp, i2c0_isp, i2c1_isp, mtcadc_isp, pwm_isp, wdt_isp, uart_isp,
+       asyncaxim, smmu_ispcx, spi0_isp, spi1_isp, pwm_isp_sclk, spi0_isp_sclk,
+       spi1_isp_sclk, uart_isp_sclk,
+
+       /* mux clocks */
+       mout_fimc0 = 384, mout_fimc1, mout_fimc2, mout_fimc3, mout_cam0,
+       mout_cam1, mout_csis0, mout_csis1, mout_g3d0, mout_g3d1, mout_g3d,
+       aclk400_mcuisp,
+
+       /* div clocks */
+       div_isp0 = 450, div_isp1, div_mcuisp0, div_mcuisp1, div_aclk200,
+       div_aclk400_mcuisp,
+
+       nr_clks,
+};
+
+/*
+ * list of controller registers to be saved and restored during a
+ * suspend/resume cycle.
+ */
+static __initdata unsigned long exynos4210_clk_save[] = {
+       E4210_SRC_IMAGE,
+       E4210_SRC_LCD1,
+       E4210_SRC_MASK_LCD1,
+       E4210_DIV_LCD1,
+       E4210_GATE_IP_IMAGE,
+       E4210_GATE_IP_LCD1,
+       E4210_GATE_IP_PERIR,
+       E4210_MPLL_CON0,
+};
+
+static __initdata unsigned long exynos4x12_clk_save[] = {
+       E4X12_GATE_IP_IMAGE,
+       E4X12_GATE_IP_PERIR,
+       E4X12_SRC_CAM1,
+       E4X12_DIV_ISP,
+       E4X12_DIV_CAM1,
+       E4X12_MPLL_CON0,
+};
+
+static __initdata unsigned long exynos4_clk_regs[] = {
+       SRC_LEFTBUS,
+       DIV_LEFTBUS,
+       GATE_IP_LEFTBUS,
+       SRC_RIGHTBUS,
+       DIV_RIGHTBUS,
+       GATE_IP_RIGHTBUS,
+       EPLL_CON0,
+       EPLL_CON1,
+       EPLL_CON2,
+       VPLL_CON0,
+       VPLL_CON1,
+       VPLL_CON2,
+       SRC_TOP0,
+       SRC_TOP1,
+       SRC_CAM,
+       SRC_TV,
+       SRC_MFC,
+       SRC_G3D,
+       SRC_LCD0,
+       SRC_MAUDIO,
+       SRC_FSYS,
+       SRC_PERIL0,
+       SRC_PERIL1,
+       SRC_MASK_TOP,
+       SRC_MASK_CAM,
+       SRC_MASK_TV,
+       SRC_MASK_LCD0,
+       SRC_MASK_MAUDIO,
+       SRC_MASK_FSYS,
+       SRC_MASK_PERIL0,
+       SRC_MASK_PERIL1,
+       DIV_TOP,
+       DIV_CAM,
+       DIV_TV,
+       DIV_MFC,
+       DIV_G3D,
+       DIV_IMAGE,
+       DIV_LCD0,
+       DIV_MAUDIO,
+       DIV_FSYS0,
+       DIV_FSYS1,
+       DIV_FSYS2,
+       DIV_FSYS3,
+       DIV_PERIL0,
+       DIV_PERIL1,
+       DIV_PERIL2,
+       DIV_PERIL3,
+       DIV_PERIL4,
+       DIV_PERIL5,
+       GATE_SCLK_CAM,
+       GATE_IP_CAM,
+       GATE_IP_TV,
+       GATE_IP_MFC,
+       GATE_IP_G3D,
+       GATE_IP_LCD0,
+       GATE_IP_FSYS,
+       GATE_IP_GPS,
+       GATE_IP_PERIL,
+       GATE_BLOCK,
+       SRC_MASK_DMC,
+       SRC_DMC,
+       DIV_DMC0,
+       DIV_DMC1,
+       GATE_IP_DMC,
+       APLL_CON0,
+       SRC_CPU,
+       DIV_CPU0,
+       DIV_CPU1,
+       GATE_SCLK_CPU,
+       GATE_IP_CPU,
+};
+
+/* list of all parent clock list */
+PNAME(mout_apll_p)     = { "fin_pll", "fout_apll", };
+PNAME(mout_mpll_p)     = { "fin_pll", "fout_mpll", };
+PNAME(mout_epll_p)     = { "fin_pll", "fout_epll", };
+PNAME(mout_vpllsrc_p)  = { "fin_pll", "sclk_hdmi24m", };
+PNAME(mout_vpll_p)     = { "fin_pll", "fout_vpll", };
+PNAME(sclk_evpll_p)    = { "sclk_epll", "sclk_vpll", };
+PNAME(mout_mfc_p)      = { "mout_mfc0", "mout_mfc1", };
+PNAME(mout_g3d_p)      = { "mout_g3d0", "mout_g3d1", };
+PNAME(mout_g2d_p)      = { "mout_g2d0", "mout_g2d1", };
+PNAME(mout_hdmi_p)     = { "sclk_pixel", "sclk_hdmiphy", };
+PNAME(mout_jpeg_p)     = { "mout_jpeg0", "mout_jpeg1", };
+PNAME(mout_spdif_p)    = { "sclk_audio0", "sclk_audio1", "sclk_audio2",
+                               "spdif_extclk", };
+PNAME(mout_onenand_p)  = {"aclk133", "aclk160", };
+PNAME(mout_onenand1_p) = {"mout_onenand", "sclk_vpll", };
+
+/* Exynos 4210-specific parent groups */
+PNAME(sclk_vpll_p4210) = { "mout_vpllsrc", "fout_vpll", };
+PNAME(mout_core_p4210) = { "mout_apll", "sclk_mpll", };
+PNAME(sclk_ampll_p4210)        = { "sclk_mpll", "sclk_apll", };
+PNAME(group1_p4210)    = { "xxti", "xusbxti", "sclk_hdmi24m",
+                               "sclk_usbphy0", "none", "sclk_hdmiphy",
+                               "sclk_mpll", "sclk_epll", "sclk_vpll", };
+PNAME(mout_audio0_p4210) = { "cdclk0", "none", "sclk_hdmi24m",
+                               "sclk_usbphy0", "xxti", "xusbxti", "sclk_mpll",
+                               "sclk_epll", "sclk_vpll" };
+PNAME(mout_audio1_p4210) = { "cdclk1", "none", "sclk_hdmi24m",
+                               "sclk_usbphy0", "xxti", "xusbxti", "sclk_mpll",
+                               "sclk_epll", "sclk_vpll", };
+PNAME(mout_audio2_p4210) = { "cdclk2", "none", "sclk_hdmi24m",
+                               "sclk_usbphy0", "xxti", "xusbxti", "sclk_mpll",
+                               "sclk_epll", "sclk_vpll", };
+PNAME(mout_mixer_p4210)        = { "sclk_dac", "sclk_hdmi", };
+PNAME(mout_dac_p4210)  = { "sclk_vpll", "sclk_hdmiphy", };
+
+/* Exynos 4x12-specific parent groups */
+PNAME(mout_mpll_user_p4x12) = { "fin_pll", "sclk_mpll", };
+PNAME(mout_core_p4x12) = { "mout_apll", "mout_mpll_user_c", };
+PNAME(sclk_ampll_p4x12)        = { "mout_mpll_user_t", "sclk_apll", };
+PNAME(group1_p4x12)    = { "xxti", "xusbxti", "sclk_hdmi24m", "sclk_usbphy0",
+                               "none", "sclk_hdmiphy", "mout_mpll_user_t",
+                               "sclk_epll", "sclk_vpll", };
+PNAME(mout_audio0_p4x12) = { "cdclk0", "none", "sclk_hdmi24m",
+                               "sclk_usbphy0", "xxti", "xusbxti",
+                               "mout_mpll_user_t", "sclk_epll", "sclk_vpll" };
+PNAME(mout_audio1_p4x12) = { "cdclk1", "none", "sclk_hdmi24m",
+                               "sclk_usbphy0", "xxti", "xusbxti",
+                               "mout_mpll_user_t", "sclk_epll", "sclk_vpll", };
+PNAME(mout_audio2_p4x12) = { "cdclk2", "none", "sclk_hdmi24m",
+                               "sclk_usbphy0", "xxti", "xusbxti",
+                               "mout_mpll_user_t", "sclk_epll", "sclk_vpll", };
+PNAME(aclk_p4412)      = { "mout_mpll_user_t", "sclk_apll", };
+PNAME(mout_user_aclk400_mcuisp_p4x12) = {"fin_pll", "div_aclk400_mcuisp", };
+PNAME(mout_user_aclk200_p4x12) = {"fin_pll", "div_aclk200", };
+PNAME(mout_user_aclk266_gps_p4x12) = {"fin_pll", "div_aclk266_gps", };
+
+/* fixed rate clocks generated outside the soc */
+struct samsung_fixed_rate_clock exynos4_fixed_rate_ext_clks[] __initdata = {
+       FRATE(xxti, "xxti", NULL, CLK_IS_ROOT, 0),
+       FRATE(xusbxti, "xusbxti", NULL, CLK_IS_ROOT, 0),
+};
+
+/* fixed rate clocks generated inside the soc */
+struct samsung_fixed_rate_clock exynos4_fixed_rate_clks[] __initdata = {
+       FRATE(none, "sclk_hdmi24m", NULL, CLK_IS_ROOT, 24000000),
+       FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 27000000),
+       FRATE(none, "sclk_usbphy0", NULL, CLK_IS_ROOT, 48000000),
+};
+
+struct samsung_fixed_rate_clock exynos4210_fixed_rate_clks[] __initdata = {
+       FRATE(none, "sclk_usbphy1", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* list of mux clocks supported in all exynos4 soc's */
+struct samsung_mux_clock exynos4_mux_clks[] __initdata = {
+       MUX_F(mout_apll, "mout_apll", mout_apll_p, SRC_CPU, 0, 1,
+                       CLK_SET_RATE_PARENT, 0),
+       MUX(none, "mout_hdmi", mout_hdmi_p, SRC_TV, 0, 1),
+       MUX(none, "mout_mfc1", sclk_evpll_p, SRC_MFC, 4, 1),
+       MUX(none, "mout_mfc", mout_mfc_p, SRC_MFC, 8, 1),
+       MUX_F(mout_g3d1, "mout_g3d1", sclk_evpll_p, SRC_G3D, 4, 1,
+                       CLK_SET_RATE_PARENT, 0),
+       MUX_F(mout_g3d, "mout_g3d", mout_g3d_p, SRC_G3D, 8, 1,
+                       CLK_SET_RATE_PARENT, 0),
+       MUX(none, "mout_spdif", mout_spdif_p, SRC_PERIL1, 8, 2),
+       MUX(none, "mout_onenand1", mout_onenand1_p, SRC_TOP0, 0, 1),
+       MUX_A(sclk_epll, "sclk_epll", mout_epll_p, SRC_TOP0, 4, 1, "sclk_epll"),
+       MUX(none, "mout_onenand", mout_onenand_p, SRC_TOP0, 28, 1),
+};
+
+/* list of mux clocks supported in exynos4210 soc */
+struct samsung_mux_clock exynos4210_mux_clks[] __initdata = {
+       MUX(none, "mout_aclk200", sclk_ampll_p4210, SRC_TOP0, 12, 1),
+       MUX(none, "mout_aclk100", sclk_ampll_p4210, SRC_TOP0, 16, 1),
+       MUX(none, "mout_aclk160", sclk_ampll_p4210, SRC_TOP0, 20, 1),
+       MUX(none, "mout_aclk133", sclk_ampll_p4210, SRC_TOP0, 24, 1),
+       MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP1, 0, 1),
+       MUX(none, "mout_mixer", mout_mixer_p4210, SRC_TV, 4, 1),
+       MUX(none, "mout_dac", mout_dac_p4210, SRC_TV, 8, 1),
+       MUX(none, "mout_g2d0", sclk_ampll_p4210, E4210_SRC_IMAGE, 0, 1),
+       MUX(none, "mout_g2d1", sclk_evpll_p, E4210_SRC_IMAGE, 4, 1),
+       MUX(none, "mout_g2d", mout_g2d_p, E4210_SRC_IMAGE, 8, 1),
+       MUX(none, "mout_fimd1", group1_p4210, E4210_SRC_LCD1, 0, 4),
+       MUX(none, "mout_mipi1", group1_p4210, E4210_SRC_LCD1, 12, 4),
+       MUX_A(sclk_mpll, "sclk_mpll", mout_mpll_p, SRC_CPU, 8, 1, "sclk_mpll"),
+       MUX_A(mout_core, "mout_core", mout_core_p4210,
+                       SRC_CPU, 16, 1, "mout_core"),
+       MUX_A(sclk_vpll, "sclk_vpll", sclk_vpll_p4210,
+                       SRC_TOP0, 8, 1, "sclk_vpll"),
+       MUX(mout_fimc0, "mout_fimc0", group1_p4210, SRC_CAM, 0, 4),
+       MUX(mout_fimc1, "mout_fimc1", group1_p4210, SRC_CAM, 4, 4),
+       MUX(mout_fimc2, "mout_fimc2", group1_p4210, SRC_CAM, 8, 4),
+       MUX(mout_fimc3, "mout_fimc3", group1_p4210, SRC_CAM, 12, 4),
+       MUX(mout_cam0, "mout_cam0", group1_p4210, SRC_CAM, 16, 4),
+       MUX(mout_cam1, "mout_cam1", group1_p4210, SRC_CAM, 20, 4),
+       MUX(mout_csis0, "mout_csis0", group1_p4210, SRC_CAM, 24, 4),
+       MUX(mout_csis1, "mout_csis1", group1_p4210, SRC_CAM, 28, 4),
+       MUX(none, "mout_mfc0", sclk_ampll_p4210, SRC_MFC, 0, 1),
+       MUX_F(mout_g3d0, "mout_g3d0", sclk_ampll_p4210, SRC_G3D, 0, 1,
+                       CLK_SET_RATE_PARENT, 0),
+       MUX(none, "mout_fimd0", group1_p4210, SRC_LCD0, 0, 4),
+       MUX(none, "mout_mipi0", group1_p4210, SRC_LCD0, 12, 4),
+       MUX(none, "mout_audio0", mout_audio0_p4210, SRC_MAUDIO, 0, 4),
+       MUX(none, "mout_mmc0", group1_p4210, SRC_FSYS, 0, 4),
+       MUX(none, "mout_mmc1", group1_p4210, SRC_FSYS, 4, 4),
+       MUX(none, "mout_mmc2", group1_p4210, SRC_FSYS, 8, 4),
+       MUX(none, "mout_mmc3", group1_p4210, SRC_FSYS, 12, 4),
+       MUX(none, "mout_mmc4", group1_p4210, SRC_FSYS, 16, 4),
+       MUX(none, "mout_sata", sclk_ampll_p4210, SRC_FSYS, 24, 1),
+       MUX(none, "mout_uart0", group1_p4210, SRC_PERIL0, 0, 4),
+       MUX(none, "mout_uart1", group1_p4210, SRC_PERIL0, 4, 4),
+       MUX(none, "mout_uart2", group1_p4210, SRC_PERIL0, 8, 4),
+       MUX(none, "mout_uart3", group1_p4210, SRC_PERIL0, 12, 4),
+       MUX(none, "mout_uart4", group1_p4210, SRC_PERIL0, 16, 4),
+       MUX(none, "mout_audio1", mout_audio1_p4210, SRC_PERIL1, 0, 4),
+       MUX(none, "mout_audio2", mout_audio2_p4210, SRC_PERIL1, 4, 4),
+       MUX(none, "mout_spi0", group1_p4210, SRC_PERIL1, 16, 4),
+       MUX(none, "mout_spi1", group1_p4210, SRC_PERIL1, 20, 4),
+       MUX(none, "mout_spi2", group1_p4210, SRC_PERIL1, 24, 4),
+};
+
+/* list of mux clocks supported in exynos4x12 soc */
+struct samsung_mux_clock exynos4x12_mux_clks[] __initdata = {
+       MUX(mout_mpll_user_c, "mout_mpll_user_c", mout_mpll_user_p4x12,
+                       SRC_CPU, 24, 1),
+       MUX(none, "mout_aclk266_gps", aclk_p4412, SRC_TOP1, 4, 1),
+       MUX(none, "mout_aclk400_mcuisp", aclk_p4412, SRC_TOP1, 8, 1),
+       MUX(mout_mpll_user_t, "mout_mpll_user_t", mout_mpll_user_p4x12,
+                       SRC_TOP1, 12, 1),
+       MUX(none, "mout_user_aclk266_gps", mout_user_aclk266_gps_p4x12,
+                       SRC_TOP1, 16, 1),
+       MUX(aclk200, "aclk200", mout_user_aclk200_p4x12, SRC_TOP1, 20, 1),
+       MUX(aclk400_mcuisp, "aclk400_mcuisp", mout_user_aclk400_mcuisp_p4x12,
+                       SRC_TOP1, 24, 1),
+       MUX(none, "mout_aclk200", aclk_p4412, SRC_TOP0, 12, 1),
+       MUX(none, "mout_aclk100", aclk_p4412, SRC_TOP0, 16, 1),
+       MUX(none, "mout_aclk160", aclk_p4412, SRC_TOP0, 20, 1),
+       MUX(none, "mout_aclk133", aclk_p4412, SRC_TOP0, 24, 1),
+       MUX(none, "mout_mdnie0", group1_p4x12, SRC_LCD0, 4, 4),
+       MUX(none, "mout_mdnie_pwm0", group1_p4x12, SRC_LCD0, 8, 4),
+       MUX(none, "mout_sata", sclk_ampll_p4x12, SRC_FSYS, 24, 1),
+       MUX(none, "mout_jpeg0", sclk_ampll_p4x12, E4X12_SRC_CAM1, 0, 1),
+       MUX(none, "mout_jpeg1", sclk_evpll_p, E4X12_SRC_CAM1, 4, 1),
+       MUX(none, "mout_jpeg", mout_jpeg_p, E4X12_SRC_CAM1, 8, 1),
+       MUX_A(sclk_mpll, "sclk_mpll", mout_mpll_p,
+                       SRC_DMC, 12, 1, "sclk_mpll"),
+       MUX_A(sclk_vpll, "sclk_vpll", mout_vpll_p,
+                       SRC_TOP0, 8, 1, "sclk_vpll"),
+       MUX(mout_core, "mout_core", mout_core_p4x12, SRC_CPU, 16, 1),
+       MUX(mout_fimc0, "mout_fimc0", group1_p4x12, SRC_CAM, 0, 4),
+       MUX(mout_fimc1, "mout_fimc1", group1_p4x12, SRC_CAM, 4, 4),
+       MUX(mout_fimc2, "mout_fimc2", group1_p4x12, SRC_CAM, 8, 4),
+       MUX(mout_fimc3, "mout_fimc3", group1_p4x12, SRC_CAM, 12, 4),
+       MUX(mout_cam0, "mout_cam0", group1_p4x12, SRC_CAM, 16, 4),
+       MUX(mout_cam1, "mout_cam1", group1_p4x12, SRC_CAM, 20, 4),
+       MUX(mout_csis0, "mout_csis0", group1_p4x12, SRC_CAM, 24, 4),
+       MUX(mout_csis1, "mout_csis1", group1_p4x12, SRC_CAM, 28, 4),
+       MUX(none, "mout_mfc0", sclk_ampll_p4x12, SRC_MFC, 0, 1),
+       MUX_F(mout_g3d0, "mout_g3d0", sclk_ampll_p4x12, SRC_G3D, 0, 1,
+                       CLK_SET_RATE_PARENT, 0),
+       MUX(none, "mout_fimd0", group1_p4x12, SRC_LCD0, 0, 4),
+       MUX(none, "mout_mipi0", group1_p4x12, SRC_LCD0, 12, 4),
+       MUX(none, "mout_audio0", mout_audio0_p4x12, SRC_MAUDIO, 0, 4),
+       MUX(none, "mout_mmc0", group1_p4x12, SRC_FSYS, 0, 4),
+       MUX(none, "mout_mmc1", group1_p4x12, SRC_FSYS, 4, 4),
+       MUX(none, "mout_mmc2", group1_p4x12, SRC_FSYS, 8, 4),
+       MUX(none, "mout_mmc3", group1_p4x12, SRC_FSYS, 12, 4),
+       MUX(none, "mout_mmc4", group1_p4x12, SRC_FSYS, 16, 4),
+       MUX(none, "mout_mipihsi", aclk_p4412, SRC_FSYS, 24, 1),
+       MUX(none, "mout_uart0", group1_p4x12, SRC_PERIL0, 0, 4),
+       MUX(none, "mout_uart1", group1_p4x12, SRC_PERIL0, 4, 4),
+       MUX(none, "mout_uart2", group1_p4x12, SRC_PERIL0, 8, 4),
+       MUX(none, "mout_uart3", group1_p4x12, SRC_PERIL0, 12, 4),
+       MUX(none, "mout_uart4", group1_p4x12, SRC_PERIL0, 16, 4),
+       MUX(none, "mout_audio1", mout_audio1_p4x12, SRC_PERIL1, 0, 4),
+       MUX(none, "mout_audio2", mout_audio2_p4x12, SRC_PERIL1, 4, 4),
+       MUX(none, "mout_spi0", group1_p4x12, SRC_PERIL1, 16, 4),
+       MUX(none, "mout_spi1", group1_p4x12, SRC_PERIL1, 20, 4),
+       MUX(none, "mout_spi2", group1_p4x12, SRC_PERIL1, 24, 4),
+       MUX(none, "mout_pwm_isp", group1_p4x12, E4X12_SRC_ISP, 0, 4),
+       MUX(none, "mout_spi0_isp", group1_p4x12, E4X12_SRC_ISP, 4, 4),
+       MUX(none, "mout_spi1_isp", group1_p4x12, E4X12_SRC_ISP, 8, 4),
+       MUX(none, "mout_uart_isp", group1_p4x12, E4X12_SRC_ISP, 12, 4),
+};
+
+/* list of divider clocks supported in all exynos4 soc's */
+struct samsung_div_clock exynos4_div_clks[] __initdata = {
+       DIV(none, "div_core", "mout_core", DIV_CPU0, 0, 3),
+       DIV(none, "div_core2", "div_core", DIV_CPU0, 28, 3),
+       DIV(none, "div_fimc0", "mout_fimc0", DIV_CAM, 0, 4),
+       DIV(none, "div_fimc1", "mout_fimc1", DIV_CAM, 4, 4),
+       DIV(none, "div_fimc2", "mout_fimc2", DIV_CAM, 8, 4),
+       DIV(none, "div_fimc3", "mout_fimc3", DIV_CAM, 12, 4),
+       DIV(none, "div_cam0", "mout_cam0", DIV_CAM, 16, 4),
+       DIV(none, "div_cam1", "mout_cam1", DIV_CAM, 20, 4),
+       DIV(none, "div_csis0", "mout_csis0", DIV_CAM, 24, 4),
+       DIV(none, "div_csis1", "mout_csis1", DIV_CAM, 28, 4),
+       DIV(sclk_mfc, "sclk_mfc", "mout_mfc", DIV_MFC, 0, 4),
+       DIV_F(none, "div_g3d", "mout_g3d", DIV_G3D, 0, 4,
+                       CLK_SET_RATE_PARENT, 0),
+       DIV(none, "div_fimd0", "mout_fimd0", DIV_LCD0, 0, 4),
+       DIV(none, "div_mipi0", "mout_mipi0", DIV_LCD0, 16, 4),
+       DIV(none, "div_audio0", "mout_audio0", DIV_MAUDIO, 0, 4),
+       DIV(sclk_pcm0, "sclk_pcm0", "sclk_audio0", DIV_MAUDIO, 4, 8),
+       DIV(none, "div_mmc0", "mout_mmc0", DIV_FSYS1, 0, 4),
+       DIV(none, "div_mmc1", "mout_mmc1", DIV_FSYS1, 16, 4),
+       DIV(none, "div_mmc2", "mout_mmc2", DIV_FSYS2, 0, 4),
+       DIV(none, "div_mmc3", "mout_mmc3", DIV_FSYS2, 16, 4),
+       DIV(sclk_pixel, "sclk_pixel", "sclk_vpll", DIV_TV, 0, 4),
+       DIV(aclk100, "aclk100", "mout_aclk100", DIV_TOP, 4, 4),
+       DIV(aclk160, "aclk160", "mout_aclk160", DIV_TOP, 8, 3),
+       DIV(aclk133, "aclk133", "mout_aclk133", DIV_TOP, 12, 3),
+       DIV(none, "div_onenand", "mout_onenand1", DIV_TOP, 16, 3),
+       DIV(sclk_slimbus, "sclk_slimbus", "sclk_epll", DIV_PERIL3, 4, 4),
+       DIV(sclk_pcm1, "sclk_pcm1", "sclk_audio1", DIV_PERIL4, 4, 8),
+       DIV(sclk_pcm2, "sclk_pcm2", "sclk_audio2", DIV_PERIL4, 20, 8),
+       DIV(sclk_i2s1, "sclk_i2s1", "sclk_audio1", DIV_PERIL5, 0, 6),
+       DIV(sclk_i2s2, "sclk_i2s2", "sclk_audio2", DIV_PERIL5, 8, 6),
+       DIV(none, "div_mmc4", "mout_mmc4", DIV_FSYS3, 0, 4),
+       DIV(none, "div_mmc_pre4", "div_mmc4", DIV_FSYS3, 8, 8),
+       DIV(none, "div_uart0", "mout_uart0", DIV_PERIL0, 0, 4),
+       DIV(none, "div_uart1", "mout_uart1", DIV_PERIL0, 4, 4),
+       DIV(none, "div_uart2", "mout_uart2", DIV_PERIL0, 8, 4),
+       DIV(none, "div_uart3", "mout_uart3", DIV_PERIL0, 12, 4),
+       DIV(none, "div_uart4", "mout_uart4", DIV_PERIL0, 16, 4),
+       DIV(none, "div_spi0", "mout_spi0", DIV_PERIL1, 0, 4),
+       DIV(none, "div_spi_pre0", "div_spi0", DIV_PERIL1, 8, 8),
+       DIV(none, "div_spi1", "mout_spi1", DIV_PERIL1, 16, 4),
+       DIV(none, "div_spi_pre1", "div_spi1", DIV_PERIL1, 24, 8),
+       DIV(none, "div_spi2", "mout_spi2", DIV_PERIL2, 0, 4),
+       DIV(none, "div_spi_pre2", "div_spi2", DIV_PERIL2, 8, 8),
+       DIV(none, "div_audio1", "mout_audio1", DIV_PERIL4, 0, 4),
+       DIV(none, "div_audio2", "mout_audio2", DIV_PERIL4, 16, 4),
+       DIV_A(arm_clk, "arm_clk", "div_core2", DIV_CPU0, 28, 3, "arm_clk"),
+       DIV_A(sclk_apll, "sclk_apll", "mout_apll",
+                       DIV_CPU0, 24, 3, "sclk_apll"),
+       DIV_F(none, "div_mipi_pre0", "div_mipi0", DIV_LCD0, 20, 4,
+                       CLK_SET_RATE_PARENT, 0),
+       DIV_F(none, "div_mmc_pre0", "div_mmc0", DIV_FSYS1, 8, 8,
+                       CLK_SET_RATE_PARENT, 0),
+       DIV_F(none, "div_mmc_pre1", "div_mmc1", DIV_FSYS1, 24, 8,
+                       CLK_SET_RATE_PARENT, 0),
+       DIV_F(none, "div_mmc_pre2", "div_mmc2", DIV_FSYS2, 8, 8,
+                       CLK_SET_RATE_PARENT, 0),
+       DIV_F(none, "div_mmc_pre3", "div_mmc3", DIV_FSYS2, 24, 8,
+                       CLK_SET_RATE_PARENT, 0),
+};
+
+/* list of divider clocks supported in exynos4210 soc */
+struct samsung_div_clock exynos4210_div_clks[] __initdata = {
+       DIV(aclk200, "aclk200", "mout_aclk200", DIV_TOP, 0, 3),
+       DIV(none, "div_g2d", "mout_g2d", DIV_IMAGE, 0, 4),
+       DIV(none, "div_fimd1", "mout_fimd1", E4210_DIV_LCD1, 0, 4),
+       DIV(none, "div_mipi1", "mout_mipi1", E4210_DIV_LCD1, 16, 4),
+       DIV(none, "div_sata", "mout_sata", DIV_FSYS0, 20, 4),
+       DIV_F(none, "div_mipi_pre1", "div_mipi1", E4210_DIV_LCD1, 20, 4,
+                       CLK_SET_RATE_PARENT, 0),
+};
+
+/* list of divider clocks supported in exynos4x12 soc */
+struct samsung_div_clock exynos4x12_div_clks[] __initdata = {
+       DIV(none, "div_mdnie0", "mout_mdnie0", DIV_LCD0, 4, 4),
+       DIV(none, "div_mdnie_pwm0", "mout_mdnie_pwm0", DIV_LCD0, 8, 4),
+       DIV(none, "div_mdnie_pwm_pre0", "div_mdnie_pwm0", DIV_LCD0, 12, 4),
+       DIV(none, "div_mipihsi", "mout_mipihsi", DIV_FSYS0, 20, 4),
+       DIV(none, "div_jpeg", "mout_jpeg", E4X12_DIV_CAM1, 0, 4),
+       DIV(div_aclk200, "div_aclk200", "mout_aclk200", DIV_TOP, 0, 3),
+       DIV(none, "div_aclk266_gps", "mout_aclk266_gps", DIV_TOP, 20, 3),
+       DIV(div_aclk400_mcuisp, "div_aclk400_mcuisp", "mout_aclk400_mcuisp",
+                                               DIV_TOP, 24, 3),
+       DIV(none, "div_pwm_isp", "mout_pwm_isp", E4X12_DIV_ISP, 0, 4),
+       DIV(none, "div_spi0_isp", "mout_spi0_isp", E4X12_DIV_ISP, 4, 4),
+       DIV(none, "div_spi0_isp_pre", "div_spi0_isp", E4X12_DIV_ISP, 8, 8),
+       DIV(none, "div_spi1_isp", "mout_spi1_isp", E4X12_DIV_ISP, 16, 4),
+       DIV(none, "div_spi1_isp_pre", "div_spi1_isp", E4X12_DIV_ISP, 20, 8),
+       DIV(none, "div_uart_isp", "mout_uart_isp", E4X12_DIV_ISP, 28, 4),
+       DIV(div_isp0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3),
+       DIV(div_isp1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3),
+       DIV(none, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3),
+       DIV(div_mcuisp0, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1, 4, 3),
+       DIV(div_mcuisp1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1, 8, 3),
+};
+
+/* list of gate clocks supported in all exynos4 soc's */
+struct samsung_gate_clock exynos4_gate_clks[] __initdata = {
+       /*
+        * After all Exynos4 based platforms are migrated to use device tree,
+        * the device name and clock alias names specified below for some
+        * of the clocks can be removed.
+        */
+       GATE(sclk_hdmi, "sclk_hdmi", "mout_hdmi", SRC_MASK_TV, 0, 0, 0),
+       GATE(sclk_spdif, "sclk_spdif", "mout_spdif", SRC_MASK_PERIL1, 8, 0, 0),
+       GATE(jpeg, "jpeg", "aclk160", GATE_IP_CAM, 6, 0, 0),
+       GATE(mie0, "mie0", "aclk160", GATE_IP_LCD0, 1, 0, 0),
+       GATE(dsim0, "dsim0", "aclk160", GATE_IP_LCD0, 3, 0, 0),
+       GATE(fimd1, "fimd1", "aclk160", E4210_GATE_IP_LCD1, 0, 0, 0),
+       GATE(mie1, "mie1", "aclk160", E4210_GATE_IP_LCD1, 1, 0, 0),
+       GATE(dsim1, "dsim1", "aclk160", E4210_GATE_IP_LCD1, 3, 0, 0),
+       GATE(smmu_fimd1, "smmu_fimd1", "aclk160", E4210_GATE_IP_LCD1, 4, 0, 0),
+       GATE(tsi, "tsi", "aclk133", GATE_IP_FSYS, 4, 0, 0),
+       GATE(sromc, "sromc", "aclk133", GATE_IP_FSYS, 11, 0, 0),
+       GATE(sclk_g3d, "sclk_g3d", "div_g3d", GATE_IP_G3D, 0,
+                       CLK_SET_RATE_PARENT, 0),
+       GATE(usb_device, "usb_device", "aclk133", GATE_IP_FSYS, 13, 0, 0),
+       GATE(onenand, "onenand", "aclk133", GATE_IP_FSYS, 15, 0, 0),
+       GATE(nfcon, "nfcon", "aclk133", GATE_IP_FSYS, 16, 0, 0),
+       GATE(gps, "gps", "aclk133", GATE_IP_GPS, 0, 0, 0),
+       GATE(smmu_gps, "smmu_gps", "aclk133", GATE_IP_GPS, 1, 0, 0),
+       GATE(slimbus, "slimbus", "aclk100", GATE_IP_PERIL, 25, 0, 0),
+       GATE(sclk_cam0, "sclk_cam0", "div_cam0", GATE_SCLK_CAM, 4,
+                       CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_cam1, "sclk_cam1", "div_cam1", GATE_SCLK_CAM, 5,
+                       CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_mipi0, "sclk_mipi0", "div_mipi_pre0",
+                       SRC_MASK_LCD0, 12, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_audio0, "sclk_audio0", "div_audio0", SRC_MASK_MAUDIO, 0,
+                       CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_audio1, "sclk_audio1", "div_audio1", SRC_MASK_PERIL1, 0,
+                       CLK_SET_RATE_PARENT, 0),
+       GATE_D(vp, "s5p-mixer", "vp", "aclk160", GATE_IP_TV, 0, 0, 0),
+       GATE_D(mixer, "s5p-mixer", "mixer", "aclk160", GATE_IP_TV, 1, 0, 0),
+       GATE_D(hdmi, "exynos4-hdmi", "hdmi", "aclk160", GATE_IP_TV, 3, 0, 0),
+       GATE_A(pwm, "pwm", "aclk100", GATE_IP_PERIL, 24, 0, 0, "timers"),
+       GATE_A(sdmmc4, "sdmmc4", "aclk133", GATE_IP_FSYS, 9, 0, 0, "biu"),
+       GATE_A(usb_host, "usb_host", "aclk133",
+                       GATE_IP_FSYS, 12, 0, 0, "usbhost"),
+       GATE_DA(sclk_fimc0, "exynos4-fimc.0", "sclk_fimc0", "div_fimc0",
+                       SRC_MASK_CAM, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
+       GATE_DA(sclk_fimc1, "exynos4-fimc.1", "sclk_fimc1", "div_fimc1",
+                       SRC_MASK_CAM, 4, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
+       GATE_DA(sclk_fimc2, "exynos4-fimc.2", "sclk_fimc2", "div_fimc2",
+                       SRC_MASK_CAM, 8, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
+       GATE_DA(sclk_fimc3, "exynos4-fimc.3", "sclk_fimc3", "div_fimc3",
+                       SRC_MASK_CAM, 12, CLK_SET_RATE_PARENT, 0, "sclk_fimc"),
+       GATE_DA(sclk_csis0, "s5p-mipi-csis.0", "sclk_csis0", "div_csis0",
+                       SRC_MASK_CAM, 24, CLK_SET_RATE_PARENT, 0, "sclk_csis"),
+       GATE_DA(sclk_csis1, "s5p-mipi-csis.1", "sclk_csis1", "div_csis1",
+                       SRC_MASK_CAM, 28, CLK_SET_RATE_PARENT, 0, "sclk_csis"),
+       GATE_DA(sclk_fimd0, "exynos4-fb.0", "sclk_fimd0", "div_fimd0",
+                       SRC_MASK_LCD0, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimd"),
+       GATE_DA(sclk_mmc0, "exynos4-sdhci.0", "sclk_mmc0", "div_mmc_pre0",
+                       SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0,
+                       "mmc_busclk.2"),
+       GATE_DA(sclk_mmc1, "exynos4-sdhci.1", "sclk_mmc1", "div_mmc_pre1",
+                       SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0,
+                       "mmc_busclk.2"),
+       GATE_DA(sclk_mmc2, "exynos4-sdhci.2", "sclk_mmc2", "div_mmc_pre2",
+                       SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0,
+                       "mmc_busclk.2"),
+       GATE_DA(sclk_mmc3, "exynos4-sdhci.3", "sclk_mmc3", "div_mmc_pre3",
+                       SRC_MASK_FSYS, 12, CLK_SET_RATE_PARENT, 0,
+                       "mmc_busclk.2"),
+       GATE_DA(sclk_mmc4, NULL, "sclk_mmc4", "div_mmc_pre4",
+                       SRC_MASK_FSYS, 16, CLK_SET_RATE_PARENT, 0, "ciu"),
+       GATE_DA(sclk_uart0, "exynos4210-uart.0", "uclk0", "div_uart0",
+                       SRC_MASK_PERIL0, 0, CLK_SET_RATE_PARENT,
+                       0, "clk_uart_baud0"),
+       GATE_DA(sclk_uart1, "exynos4210-uart.1", "uclk1", "div_uart1",
+                       SRC_MASK_PERIL0, 4, CLK_SET_RATE_PARENT,
+                       0, "clk_uart_baud0"),
+       GATE_DA(sclk_uart2, "exynos4210-uart.2", "uclk2", "div_uart2",
+                       SRC_MASK_PERIL0, 8, CLK_SET_RATE_PARENT,
+                       0, "clk_uart_baud0"),
+       GATE_DA(sclk_uart3, "exynos4210-uart.3", "uclk3", "div_uart3",
+                       SRC_MASK_PERIL0, 12, CLK_SET_RATE_PARENT,
+                       0, "clk_uart_baud0"),
+       GATE_DA(sclk_uart4, "exynos4210-uart.4", "uclk4", "div_uart4",
+                       SRC_MASK_PERIL0, 16, CLK_SET_RATE_PARENT,
+                       0, "clk_uart_baud0"),
+       GATE(sclk_audio2, "sclk_audio2", "div_audio2", SRC_MASK_PERIL1, 4,
+                       CLK_SET_RATE_PARENT, 0),
+       GATE_DA(sclk_spi0, "exynos4210-spi.0", "sclk_spi0", "div_spi_pre0",
+                       SRC_MASK_PERIL1, 16, CLK_SET_RATE_PARENT,
+                       0, "spi_busclk0"),
+       GATE_DA(sclk_spi1, "exynos4210-spi.1", "sclk_spi1", "div_spi_pre1",
+                       SRC_MASK_PERIL1, 20, CLK_SET_RATE_PARENT,
+                       0, "spi_busclk0"),
+       GATE_DA(sclk_spi2, "exynos4210-spi.2", "sclk_spi2", "div_spi_pre2",
+                       SRC_MASK_PERIL1, 24, CLK_SET_RATE_PARENT,
+                       0, "spi_busclk0"),
+       GATE_DA(fimc0, "exynos4-fimc.0", "fimc0", "aclk160",
+                       GATE_IP_CAM, 0, 0, 0, "fimc"),
+       GATE_DA(fimc1, "exynos4-fimc.1", "fimc1", "aclk160",
+                       GATE_IP_CAM, 1, 0, 0, "fimc"),
+       GATE_DA(fimc2, "exynos4-fimc.2", "fimc2", "aclk160",
+                       GATE_IP_CAM, 2, 0, 0, "fimc"),
+       GATE_DA(fimc3, "exynos4-fimc.3", "fimc3", "aclk160",
+                       GATE_IP_CAM, 3, 0, 0, "fimc"),
+       GATE_DA(csis0, "s5p-mipi-csis.0", "csis0", "aclk160",
+                       GATE_IP_CAM, 4, 0, 0, "fimc"),
+       GATE_DA(csis1, "s5p-mipi-csis.1", "csis1", "aclk160",
+                       GATE_IP_CAM, 5, 0, 0, "fimc"),
+       GATE_DA(smmu_fimc0, "exynos-sysmmu.5", "smmu_fimc0", "aclk160",
+                       GATE_IP_CAM, 7, 0, 0, "sysmmu"),
+       GATE_DA(smmu_fimc1, "exynos-sysmmu.6", "smmu_fimc1", "aclk160",
+                       GATE_IP_CAM, 8, 0, 0, "sysmmu"),
+       GATE_DA(smmu_fimc2, "exynos-sysmmu.7", "smmu_fimc2", "aclk160",
+                       GATE_IP_CAM, 9, 0, 0, "sysmmu"),
+       GATE_DA(smmu_fimc3, "exynos-sysmmu.8", "smmu_fimc3", "aclk160",
+                       GATE_IP_CAM, 10, 0, 0, "sysmmu"),
+       GATE_DA(smmu_jpeg, "exynos-sysmmu.3", "smmu_jpeg", "aclk160",
+                       GATE_IP_CAM, 11, 0, 0, "sysmmu"),
+       GATE(pixelasyncm0, "pxl_async0", "aclk160", GATE_IP_CAM, 17, 0, 0),
+       GATE(pixelasyncm1, "pxl_async1", "aclk160", GATE_IP_CAM, 18, 0, 0),
+       GATE_DA(smmu_tv, "exynos-sysmmu.2", "smmu_tv", "aclk160",
+                       GATE_IP_TV, 4, 0, 0, "sysmmu"),
+       GATE_DA(mfc, "s5p-mfc", "mfc", "aclk100", GATE_IP_MFC, 0, 0, 0, "mfc"),
+       GATE_DA(smmu_mfcl, "exynos-sysmmu.0", "smmu_mfcl", "aclk100",
+                       GATE_IP_MFC, 1, 0, 0, "sysmmu"),
+       GATE_DA(smmu_mfcr, "exynos-sysmmu.1", "smmu_mfcr", "aclk100",
+                       GATE_IP_MFC, 2, 0, 0, "sysmmu"),
+       GATE_DA(fimd0, "exynos4-fb.0", "fimd0", "aclk160",
+                       GATE_IP_LCD0, 0, 0, 0, "fimd"),
+       GATE_DA(smmu_fimd0, "exynos-sysmmu.10", "smmu_fimd0", "aclk160",
+                       GATE_IP_LCD0, 4, 0, 0, "sysmmu"),
+       GATE_DA(pdma0, "dma-pl330.0", "pdma0", "aclk133",
+                       GATE_IP_FSYS, 0, 0, 0, "dma"),
+       GATE_DA(pdma1, "dma-pl330.1", "pdma1", "aclk133",
+                       GATE_IP_FSYS, 1, 0, 0, "dma"),
+       GATE_DA(sdmmc0, "exynos4-sdhci.0", "sdmmc0", "aclk133",
+                       GATE_IP_FSYS, 5, 0, 0, "hsmmc"),
+       GATE_DA(sdmmc1, "exynos4-sdhci.1", "sdmmc1", "aclk133",
+                       GATE_IP_FSYS, 6, 0, 0, "hsmmc"),
+       GATE_DA(sdmmc2, "exynos4-sdhci.2", "sdmmc2", "aclk133",
+                       GATE_IP_FSYS, 7, 0, 0, "hsmmc"),
+       GATE_DA(sdmmc3, "exynos4-sdhci.3", "sdmmc3", "aclk133",
+                       GATE_IP_FSYS, 8, 0, 0, "hsmmc"),
+       GATE_DA(uart0, "exynos4210-uart.0", "uart0", "aclk100",
+                       GATE_IP_PERIL, 0, 0, 0, "uart"),
+       GATE_DA(uart1, "exynos4210-uart.1", "uart1", "aclk100",
+                       GATE_IP_PERIL, 1, 0, 0, "uart"),
+       GATE_DA(uart2, "exynos4210-uart.2", "uart2", "aclk100",
+                       GATE_IP_PERIL, 2, 0, 0, "uart"),
+       GATE_DA(uart3, "exynos4210-uart.3", "uart3", "aclk100",
+                       GATE_IP_PERIL, 3, 0, 0, "uart"),
+       GATE_DA(uart4, "exynos4210-uart.4", "uart4", "aclk100",
+                       GATE_IP_PERIL, 4, 0, 0, "uart"),
+       GATE_DA(i2c0, "s3c2440-i2c.0", "i2c0", "aclk100",
+                       GATE_IP_PERIL, 6, 0, 0, "i2c"),
+       GATE_DA(i2c1, "s3c2440-i2c.1", "i2c1", "aclk100",
+                       GATE_IP_PERIL, 7, 0, 0, "i2c"),
+       GATE_DA(i2c2, "s3c2440-i2c.2", "i2c2", "aclk100",
+                       GATE_IP_PERIL, 8, 0, 0, "i2c"),
+       GATE_DA(i2c3, "s3c2440-i2c.3", "i2c3", "aclk100",
+                       GATE_IP_PERIL, 9, 0, 0, "i2c"),
+       GATE_DA(i2c4, "s3c2440-i2c.4", "i2c4", "aclk100",
+                       GATE_IP_PERIL, 10, 0, 0, "i2c"),
+       GATE_DA(i2c5, "s3c2440-i2c.5", "i2c5", "aclk100",
+                       GATE_IP_PERIL, 11, 0, 0, "i2c"),
+       GATE_DA(i2c6, "s3c2440-i2c.6", "i2c6", "aclk100",
+                       GATE_IP_PERIL, 12, 0, 0, "i2c"),
+       GATE_DA(i2c7, "s3c2440-i2c.7", "i2c7", "aclk100",
+                       GATE_IP_PERIL, 13, 0, 0, "i2c"),
+       GATE_DA(i2c_hdmi, "s3c2440-hdmiphy-i2c", "i2c-hdmi", "aclk100",
+                       GATE_IP_PERIL, 14, 0, 0, "i2c"),
+       GATE_DA(spi0, "exynos4210-spi.0", "spi0", "aclk100",
+                       GATE_IP_PERIL, 16, 0, 0, "spi"),
+       GATE_DA(spi1, "exynos4210-spi.1", "spi1", "aclk100",
+                       GATE_IP_PERIL, 17, 0, 0, "spi"),
+       GATE_DA(spi2, "exynos4210-spi.2", "spi2", "aclk100",
+                       GATE_IP_PERIL, 18, 0, 0, "spi"),
+       GATE_DA(i2s1, "samsung-i2s.1", "i2s1", "aclk100",
+                       GATE_IP_PERIL, 20, 0, 0, "iis"),
+       GATE_DA(i2s2, "samsung-i2s.2", "i2s2", "aclk100",
+                       GATE_IP_PERIL, 21, 0, 0, "iis"),
+       GATE_DA(pcm1, "samsung-pcm.1", "pcm1", "aclk100",
+                       GATE_IP_PERIL, 22, 0, 0, "pcm"),
+       GATE_DA(pcm2, "samsung-pcm.2", "pcm2", "aclk100",
+                       GATE_IP_PERIL, 23, 0, 0, "pcm"),
+       GATE_DA(spdif, "samsung-spdif", "spdif", "aclk100",
+                       GATE_IP_PERIL, 26, 0, 0, "spdif"),
+       GATE_DA(ac97, "samsung-ac97", "ac97", "aclk100",
+                       GATE_IP_PERIL, 27, 0, 0, "ac97"),
+};
+
+/* list of gate clocks supported in exynos4210 soc */
+struct samsung_gate_clock exynos4210_gate_clks[] __initdata = {
+       GATE(tvenc, "tvenc", "aclk160", GATE_IP_TV, 2, 0, 0),
+       GATE(g2d, "g2d", "aclk200", E4210_GATE_IP_IMAGE, 0, 0, 0),
+       GATE(rotator, "rotator", "aclk200", E4210_GATE_IP_IMAGE, 1, 0, 0),
+       GATE(mdma, "mdma", "aclk200", E4210_GATE_IP_IMAGE, 2, 0, 0),
+       GATE(smmu_g2d, "smmu_g2d", "aclk200", E4210_GATE_IP_IMAGE, 3, 0, 0),
+       GATE(smmu_mdma, "smmu_mdma", "aclk200", E4210_GATE_IP_IMAGE, 5, 0, 0),
+       GATE(pcie_phy, "pcie_phy", "aclk133", GATE_IP_FSYS, 2, 0, 0),
+       GATE(sata_phy, "sata_phy", "aclk133", GATE_IP_FSYS, 3, 0, 0),
+       GATE(sata, "sata", "aclk133", GATE_IP_FSYS, 10, 0, 0),
+       GATE(pcie, "pcie", "aclk133", GATE_IP_FSYS, 14, 0, 0),
+       GATE(smmu_pcie, "smmu_pcie", "aclk133", GATE_IP_FSYS, 18, 0, 0),
+       GATE(modemif, "modemif", "aclk100", GATE_IP_PERIL, 28, 0, 0),
+       GATE(chipid, "chipid", "aclk100", E4210_GATE_IP_PERIR, 0, 0, 0),
+       GATE(sysreg, "sysreg", "aclk100", E4210_GATE_IP_PERIR, 0, 0, 0),
+       GATE(hdmi_cec, "hdmi_cec", "aclk100", E4210_GATE_IP_PERIR, 11, 0, 0),
+       GATE(smmu_rotator, "smmu_rotator", "aclk200",
+                       E4210_GATE_IP_IMAGE, 4, 0, 0),
+       GATE(sclk_mipi1, "sclk_mipi1", "div_mipi_pre1",
+                       E4210_SRC_MASK_LCD1, 12, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_sata, "sclk_sata", "div_sata",
+                       SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_mixer, "sclk_mixer", "mout_mixer", SRC_MASK_TV, 4, 0, 0),
+       GATE(sclk_dac, "sclk_dac", "mout_dac", SRC_MASK_TV, 8, 0, 0),
+       GATE_A(tsadc, "tsadc", "aclk100", GATE_IP_PERIL, 15, 0, 0, "adc"),
+       GATE_A(mct, "mct", "aclk100", E4210_GATE_IP_PERIR, 13, 0, 0, "mct"),
+       GATE_A(wdt, "watchdog", "aclk100", E4210_GATE_IP_PERIR, 14, 0, 0, "watchdog"),
+       GATE_A(rtc, "rtc", "aclk100", E4210_GATE_IP_PERIR, 15, 0, 0, "rtc"),
+       GATE_A(keyif, "keyif", "aclk100", E4210_GATE_IP_PERIR, 16, 0, 0, "keypad"),
+       GATE_DA(sclk_fimd1, "exynos4-fb.1", "sclk_fimd1", "div_fimd1",
+                       E4210_SRC_MASK_LCD1, 0, CLK_SET_RATE_PARENT, 0, "sclk_fimd"),
+};
+
+/* list of gate clocks supported in exynos4x12 soc */
+struct samsung_gate_clock exynos4x12_gate_clks[] __initdata = {
+       GATE(audss, "audss", "sclk_epll", E4X12_GATE_IP_MAUDIO, 0, 0, 0),
+       GATE(mdnie0, "mdnie0", "aclk160", GATE_IP_LCD0, 2, 0, 0),
+       GATE(rotator, "rotator", "aclk200", E4X12_GATE_IP_IMAGE, 1, 0, 0),
+       GATE(mdma2, "mdma2", "aclk200", E4X12_GATE_IP_IMAGE, 2, 0, 0),
+       GATE(smmu_mdma, "smmu_mdma", "aclk200", E4X12_GATE_IP_IMAGE, 5, 0, 0),
+       GATE(mipi_hsi, "mipi_hsi", "aclk133", GATE_IP_FSYS, 10, 0, 0),
+       GATE(chipid, "chipid", "aclk100", E4X12_GATE_IP_PERIR, 0, 0, 0),
+       GATE(sysreg, "sysreg", "aclk100", E4X12_GATE_IP_PERIR, 1, 0, 0),
+       GATE(hdmi_cec, "hdmi_cec", "aclk100", E4X12_GATE_IP_PERIR, 11, 0, 0),
+       GATE(sclk_mdnie0, "sclk_mdnie0", "div_mdnie0",
+                       SRC_MASK_LCD0, 4, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_mdnie_pwm0, "sclk_mdnie_pwm0", "div_mdnie_pwm_pre0",
+                       SRC_MASK_LCD0, 8, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_mipihsi, "sclk_mipihsi", "div_mipihsi",
+                       SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
+       GATE(smmu_rotator, "smmu_rotator", "aclk200",
+                       E4X12_GATE_IP_IMAGE, 4, 0, 0),
+       GATE_A(mct, "mct", "aclk100", E4X12_GATE_IP_PERIR, 13, 0, 0, "mct"),
+       GATE_A(rtc, "rtc", "aclk100", E4X12_GATE_IP_PERIR, 15, 0, 0, "rtc"),
+       GATE_A(keyif, "keyif", "aclk100",
+                       E4X12_GATE_IP_PERIR, 16, 0, 0, "keypad"),
+       GATE(sclk_pwm_isp, "sclk_pwm_isp", "div_pwm_isp",
+                       E4X12_SRC_MASK_ISP, 0, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_spi0_isp, "sclk_spi0_isp", "div_spi0_isp_pre",
+                       E4X12_SRC_MASK_ISP, 4, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_spi1_isp, "sclk_spi1_isp", "div_spi1_isp_pre",
+                       E4X12_SRC_MASK_ISP, 8, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_uart_isp, "sclk_uart_isp", "div_uart_isp",
+                       E4X12_SRC_MASK_ISP, 12, CLK_SET_RATE_PARENT, 0),
+       GATE(pwm_isp_sclk, "pwm_isp_sclk", "sclk_pwm_isp",
+                       E4X12_GATE_IP_ISP, 0, 0, 0),
+       GATE(spi0_isp_sclk, "spi0_isp_sclk", "sclk_spi0_isp",
+                       E4X12_GATE_IP_ISP, 1, 0, 0),
+       GATE(spi1_isp_sclk, "spi1_isp_sclk", "sclk_spi1_isp",
+                       E4X12_GATE_IP_ISP, 2, 0, 0),
+       GATE(uart_isp_sclk, "uart_isp_sclk", "sclk_uart_isp",
+                       E4X12_GATE_IP_ISP, 3, 0, 0),
+       GATE_A(wdt, "watchdog", "aclk100",
+                       E4X12_GATE_IP_PERIR, 14, 0, 0, "watchdog"),
+       GATE_DA(pcm0, "samsung-pcm.0", "pcm0", "aclk100",
+                       E4X12_GATE_IP_MAUDIO, 2, 0, 0, "pcm"),
+       GATE_DA(i2s0, "samsung-i2s.0", "i2s0", "aclk100",
+                       E4X12_GATE_IP_MAUDIO, 3, 0, 0, "iis"),
+       GATE(fimc_isp, "isp", "aclk200", E4X12_GATE_ISP0, 0,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(fimc_drc, "drc", "aclk200", E4X12_GATE_ISP0, 1,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(fimc_fd, "fd", "aclk200", E4X12_GATE_ISP0, 2,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(fimc_lite0, "lite0", "aclk200", E4X12_GATE_ISP0, 3,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(fimc_lite1, "lite1", "aclk200", E4X12_GATE_ISP0, 4,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(mcuisp, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(gicisp, "gicisp", "aclk200", E4X12_GATE_ISP0, 7,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(smmu_isp, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(smmu_drc, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(smmu_fd, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(smmu_lite0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(smmu_lite1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(ppmuispmx, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(ppmuispx, "ppmuispx", "aclk200", E4X12_GATE_ISP0, 21,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(mcuctl_isp, "mcuctl_isp", "aclk200", E4X12_GATE_ISP0, 23,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(mpwm_isp, "mpwm_isp", "aclk200", E4X12_GATE_ISP0, 24,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(i2c0_isp, "i2c0_isp", "aclk200", E4X12_GATE_ISP0, 25,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(i2c1_isp, "i2c1_isp", "aclk200", E4X12_GATE_ISP0, 26,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(mtcadc_isp, "mtcadc_isp", "aclk200", E4X12_GATE_ISP0, 27,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(pwm_isp, "pwm_isp", "aclk200", E4X12_GATE_ISP0, 28,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(wdt_isp, "wdt_isp", "aclk200", E4X12_GATE_ISP0, 30,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(uart_isp, "uart_isp", "aclk200", E4X12_GATE_ISP0, 31,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(asyncaxim, "asyncaxim", "aclk200", E4X12_GATE_ISP1, 0,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(smmu_ispcx, "smmu_ispcx", "aclk200", E4X12_GATE_ISP1, 4,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(spi0_isp, "spi0_isp", "aclk200", E4X12_GATE_ISP1, 12,
+                       CLK_IGNORE_UNUSED, 0),
+       GATE(spi1_isp, "spi1_isp", "aclk200", E4X12_GATE_ISP1, 13,
+                       CLK_IGNORE_UNUSED, 0),
+};
+
+/*
+ * The parent of the fin_pll clock is selected by the XOM[0] bit. This bit
+ * resides in chipid register space, outside of the clock controller memory
+ * mapped space. So to determine the parent of fin_pll clock, the chipid
+ * controller is first remapped and the value of XOM[0] bit is read to
+ * determine the parent clock.
+ */
+static unsigned long exynos4_get_xom(void)
+{
+       unsigned long xom = 0;
+       void __iomem *chipid_base;
+       struct device_node *np;
+
+       np = of_find_compatible_node(NULL, NULL, "samsung,exynos4210-chipid");
+       if (np) {
+               chipid_base = of_iomap(np, 0);
+
+               if (chipid_base)
+                       xom = readl(chipid_base + 8);
+
+               iounmap(chipid_base);
+       }
+
+       return xom;
+}
+
+static void __init exynos4_clk_register_finpll(unsigned long xom)
+{
+       struct samsung_fixed_rate_clock fclk;
+       struct clk *clk;
+       unsigned long finpll_f = 24000000;
+       char *parent_name;
+
+       parent_name = xom & 1 ? "xusbxti" : "xxti";
+       clk = clk_get(NULL, parent_name);
+       if (IS_ERR(clk)) {
+               pr_err("%s: failed to lookup parent clock %s, assuming "
+                       "fin_pll clock frequency is 24MHz\n", __func__,
+                       parent_name);
+       } else {
+               finpll_f = clk_get_rate(clk);
+       }
+
+       fclk.id = fin_pll;
+       fclk.name = "fin_pll";
+       fclk.parent_name = NULL;
+       fclk.flags = CLK_IS_ROOT;
+       fclk.fixed_rate = finpll_f;
+       samsung_clk_register_fixed_rate(&fclk, 1);
+
+}
+
+/*
+ * This function allows non-dt platforms to specify the clock speed of the
+ * xxti and xusbxti clocks. These clocks are then registered with the specified
+ * clock speed.
+ */
+void __init exynos4_clk_register_fixed_ext(unsigned long xxti_f,
+                                               unsigned long xusbxti_f)
+{
+       exynos4_fixed_rate_ext_clks[0].fixed_rate = xxti_f;
+       exynos4_fixed_rate_ext_clks[1].fixed_rate = xusbxti_f;
+       samsung_clk_register_fixed_rate(exynos4_fixed_rate_ext_clks,
+                       ARRAY_SIZE(exynos4_fixed_rate_ext_clks));
+}
+
+static __initdata struct of_device_id ext_clk_match[] = {
+       { .compatible = "samsung,clock-xxti", .data = (void *)0, },
+       { .compatible = "samsung,clock-xusbxti", .data = (void *)1, },
+       {},
+};
+
+/* register exynos4 clocks */
+void __init exynos4_clk_init(struct device_node *np, enum exynos4_soc exynos4_soc, void __iomem *reg_base, unsigned long xom)
+{
+       struct clk *apll, *mpll, *epll, *vpll;
+
+       if (np) {
+               reg_base = of_iomap(np, 0);
+               if (!reg_base)
+                       panic("%s: failed to map registers\n", __func__);
+       }
+
+       if (exynos4_soc == EXYNOS4210)
+               samsung_clk_init(np, reg_base, nr_clks,
+                       exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs),
+                       exynos4210_clk_save, ARRAY_SIZE(exynos4210_clk_save));
+       else
+               samsung_clk_init(np, reg_base, nr_clks,
+                       exynos4_clk_regs, ARRAY_SIZE(exynos4_clk_regs),
+                       exynos4x12_clk_save, ARRAY_SIZE(exynos4x12_clk_save));
+
+       if (np)
+               samsung_clk_of_register_fixed_ext(exynos4_fixed_rate_ext_clks,
+                       ARRAY_SIZE(exynos4_fixed_rate_ext_clks),
+                       ext_clk_match);
+
+       exynos4_clk_register_finpll(xom);
+
+       if (exynos4_soc == EXYNOS4210) {
+               apll = samsung_clk_register_pll45xx("fout_apll", "fin_pll",
+                                       reg_base + APLL_CON0, pll_4508);
+               mpll = samsung_clk_register_pll45xx("fout_mpll", "fin_pll",
+                                       reg_base + E4210_MPLL_CON0, pll_4508);
+               epll = samsung_clk_register_pll46xx("fout_epll", "fin_pll",
+                                       reg_base + EPLL_CON0, pll_4600);
+               vpll = samsung_clk_register_pll46xx("fout_vpll", "mout_vpllsrc",
+                                       reg_base + VPLL_CON0, pll_4650c);
+       } else {
+               apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
+                                       reg_base + APLL_CON0);
+               mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
+                                       reg_base + E4X12_MPLL_CON0);
+               epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
+                                       reg_base + EPLL_CON0);
+               vpll = samsung_clk_register_pll36xx("fout_vpll", "fin_pll",
+                                       reg_base + VPLL_CON0);
+       }
+
+       samsung_clk_add_lookup(apll, fout_apll);
+       samsung_clk_add_lookup(mpll, fout_mpll);
+       samsung_clk_add_lookup(epll, fout_epll);
+       samsung_clk_add_lookup(vpll, fout_vpll);
+
+       samsung_clk_register_fixed_rate(exynos4_fixed_rate_clks,
+                       ARRAY_SIZE(exynos4_fixed_rate_clks));
+       samsung_clk_register_mux(exynos4_mux_clks,
+                       ARRAY_SIZE(exynos4_mux_clks));
+       samsung_clk_register_div(exynos4_div_clks,
+                       ARRAY_SIZE(exynos4_div_clks));
+       samsung_clk_register_gate(exynos4_gate_clks,
+                       ARRAY_SIZE(exynos4_gate_clks));
+
+       if (exynos4_soc == EXYNOS4210) {
+               samsung_clk_register_fixed_rate(exynos4210_fixed_rate_clks,
+                       ARRAY_SIZE(exynos4210_fixed_rate_clks));
+               samsung_clk_register_mux(exynos4210_mux_clks,
+                       ARRAY_SIZE(exynos4210_mux_clks));
+               samsung_clk_register_div(exynos4210_div_clks,
+                       ARRAY_SIZE(exynos4210_div_clks));
+               samsung_clk_register_gate(exynos4210_gate_clks,
+                       ARRAY_SIZE(exynos4210_gate_clks));
+       } else {
+               samsung_clk_register_mux(exynos4x12_mux_clks,
+                       ARRAY_SIZE(exynos4x12_mux_clks));
+               samsung_clk_register_div(exynos4x12_div_clks,
+                       ARRAY_SIZE(exynos4x12_div_clks));
+               samsung_clk_register_gate(exynos4x12_gate_clks,
+                       ARRAY_SIZE(exynos4x12_gate_clks));
+       }
+
+       pr_info("%s clocks: sclk_apll = %ld, sclk_mpll = %ld\n"
+               "\tsclk_epll = %ld, sclk_vpll = %ld, arm_clk = %ld\n",
+               exynos4_soc == EXYNOS4210 ? "Exynos4210" : "Exynos4x12",
+               _get_rate("sclk_apll"), _get_rate("sclk_mpll"),
+               _get_rate("sclk_epll"), _get_rate("sclk_vpll"),
+               _get_rate("arm_clk"));
+}
+
+
+static void __init exynos4210_clk_init(struct device_node *np)
+{
+       exynos4_clk_init(np, EXYNOS4210, NULL, exynos4_get_xom());
+}
+CLK_OF_DECLARE(exynos4210_clk, "samsung,exynos4210-clock", exynos4210_clk_init);
+
+static void __init exynos4412_clk_init(struct device_node *np)
+{
+       exynos4_clk_init(np, EXYNOS4X12, NULL, exynos4_get_xom());
+}
+CLK_OF_DECLARE(exynos4412_clk, "samsung,exynos4412-clock", exynos4412_clk_init);
diff --git a/drivers/clk/samsung/clk-exynos5250.c b/drivers/clk/samsung/clk-exynos5250.c
new file mode 100644 (file)
index 0000000..61068cd
--- /dev/null
@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@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.
+ *
+ * Common Clock Framework support for Exynos5250 SoC.
+*/
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk.h"
+#include "clk-pll.h"
+
+#define SRC_CPU                        0x200
+#define DIV_CPU0               0x500
+#define SRC_CORE1              0x4204
+#define SRC_TOP0               0x10210
+#define SRC_TOP2               0x10218
+#define SRC_GSCL               0x10220
+#define SRC_DISP1_0            0x1022c
+#define SRC_MAU                        0x10240
+#define SRC_FSYS               0x10244
+#define SRC_GEN                        0x10248
+#define SRC_PERIC0             0x10250
+#define SRC_PERIC1             0x10254
+#define SRC_MASK_GSCL          0x10320
+#define SRC_MASK_DISP1_0       0x1032c
+#define SRC_MASK_MAU           0x10334
+#define SRC_MASK_FSYS          0x10340
+#define SRC_MASK_GEN           0x10344
+#define SRC_MASK_PERIC0                0x10350
+#define SRC_MASK_PERIC1                0x10354
+#define DIV_TOP0               0x10510
+#define DIV_TOP1               0x10514
+#define DIV_GSCL               0x10520
+#define DIV_DISP1_0            0x1052c
+#define DIV_GEN                        0x1053c
+#define DIV_MAU                        0x10544
+#define DIV_FSYS0              0x10548
+#define DIV_FSYS1              0x1054c
+#define DIV_FSYS2              0x10550
+#define DIV_PERIC0             0x10558
+#define DIV_PERIC1             0x1055c
+#define DIV_PERIC2             0x10560
+#define DIV_PERIC3             0x10564
+#define DIV_PERIC4             0x10568
+#define DIV_PERIC5             0x1056c
+#define GATE_IP_GSCL           0x10920
+#define GATE_IP_MFC            0x1092c
+#define GATE_IP_GEN            0x10934
+#define GATE_IP_FSYS           0x10944
+#define GATE_IP_PERIC          0x10950
+#define GATE_IP_PERIS          0x10960
+#define SRC_CDREX              0x20200
+#define PLL_DIV2_SEL           0x20a24
+#define GATE_IP_DISP1          0x10928
+
+/*
+ * Let each supported clock get a unique id. This id is used to lookup the clock
+ * for device tree based platforms. The clocks are categorized into three
+ * sections: core, sclk gate and bus interface gate clocks.
+ *
+ * When adding a new clock to this list, it is advised to choose a clock
+ * category and add it to the end of that category. That is because the the
+ * device tree source file is referring to these ids and any change in the
+ * sequence number of existing clocks will require corresponding change in the
+ * device tree files. This limitation would go away when pre-processor support
+ * for dtc would be available.
+ */
+enum exynos5250_clks {
+       none,
+
+       /* core clocks */
+       fin_pll,
+
+       /* gate for special clocks (sclk) */
+       sclk_cam_bayer = 128, sclk_cam0, sclk_cam1, sclk_gscl_wa, sclk_gscl_wb,
+       sclk_fimd1, sclk_mipi1, sclk_dp, sclk_hdmi, sclk_pixel, sclk_audio0,
+       sclk_mmc0, sclk_mmc1, sclk_mmc2, sclk_mmc3, sclk_sata, sclk_usb3,
+       sclk_jpeg, sclk_uart0, sclk_uart1, sclk_uart2, sclk_uart3, sclk_pwm,
+       sclk_audio1, sclk_audio2, sclk_spdif, sclk_spi0, sclk_spi1, sclk_spi2,
+
+       /* gate clocks */
+       gscl0 = 256, gscl1, gscl2, gscl3, gscl_wa, gscl_wb, smmu_gscl0,
+       smmu_gscl1, smmu_gscl2, smmu_gscl3, mfc, smmu_mfcl, smmu_mfcr, rotator,
+       jpeg, mdma1, smmu_rotator, smmu_jpeg, smmu_mdma1, pdma0, pdma1, sata,
+       usbotg, mipi_hsi, sdmmc0, sdmmc1, sdmmc2, sdmmc3, sromc, usb2, usb3,
+       sata_phyctrl, sata_phyi2c, uart0, uart1, uart2, uart3, uart4, i2c0,
+       i2c1, i2c2, i2c3, i2c4, i2c5, i2c6, i2c7, i2c_hdmi, adc, spi0, spi1,
+       spi2, i2s1, i2s2, pcm1, pcm2, pwm, spdif, ac97, hsi2c0, hsi2c1, hsi2c2,
+       hsi2c3, chipid, sysreg, pmu, cmu_top, cmu_core, cmu_mem, tzpc0, tzpc1,
+       tzpc2, tzpc3, tzpc4, tzpc5, tzpc6, tzpc7, tzpc8, tzpc9, hdmi_cec, mct,
+       wdt, rtc, tmu, fimd1, mie1, dsim0, dp, mixer, hdmi,
+
+       nr_clks,
+};
+
+/*
+ * list of controller registers to be saved and restored during a
+ * suspend/resume cycle.
+ */
+static __initdata unsigned long exynos5250_clk_regs[] = {
+       SRC_CPU,
+       DIV_CPU0,
+       SRC_CORE1,
+       SRC_TOP0,
+       SRC_TOP2,
+       SRC_GSCL,
+       SRC_DISP1_0,
+       SRC_MAU,
+       SRC_FSYS,
+       SRC_GEN,
+       SRC_PERIC0,
+       SRC_PERIC1,
+       SRC_MASK_GSCL,
+       SRC_MASK_DISP1_0,
+       SRC_MASK_MAU,
+       SRC_MASK_FSYS,
+       SRC_MASK_GEN,
+       SRC_MASK_PERIC0,
+       SRC_MASK_PERIC1,
+       DIV_TOP0,
+       DIV_TOP1,
+       DIV_GSCL,
+       DIV_DISP1_0,
+       DIV_GEN,
+       DIV_MAU,
+       DIV_FSYS0,
+       DIV_FSYS1,
+       DIV_FSYS2,
+       DIV_PERIC0,
+       DIV_PERIC1,
+       DIV_PERIC2,
+       DIV_PERIC3,
+       DIV_PERIC4,
+       DIV_PERIC5,
+       GATE_IP_GSCL,
+       GATE_IP_MFC,
+       GATE_IP_GEN,
+       GATE_IP_FSYS,
+       GATE_IP_PERIC,
+       GATE_IP_PERIS,
+       SRC_CDREX,
+       PLL_DIV2_SEL,
+       GATE_IP_DISP1,
+};
+
+/* list of all parent clock list */
+PNAME(mout_apll_p)     = { "fin_pll", "fout_apll", };
+PNAME(mout_cpu_p)      = { "mout_apll", "mout_mpll", };
+PNAME(mout_mpll_fout_p)        = { "fout_mplldiv2", "fout_mpll" };
+PNAME(mout_mpll_p)     = { "fin_pll", "mout_mpll_fout" };
+PNAME(mout_bpll_fout_p)        = { "fout_bplldiv2", "fout_bpll" };
+PNAME(mout_bpll_p)     = { "fin_pll", "mout_bpll_fout" };
+PNAME(mout_vpllsrc_p)  = { "fin_pll", "sclk_hdmi27m" };
+PNAME(mout_vpll_p)     = { "mout_vpllsrc", "fout_vpll" };
+PNAME(mout_cpll_p)     = { "fin_pll", "fout_cpll" };
+PNAME(mout_epll_p)     = { "fin_pll", "fout_epll" };
+PNAME(mout_mpll_user_p)        = { "fin_pll", "sclk_mpll" };
+PNAME(mout_bpll_user_p)        = { "fin_pll", "sclk_bpll" };
+PNAME(mout_aclk166_p)  = { "sclk_cpll", "sclk_mpll_user" };
+PNAME(mout_aclk200_p)  = { "sclk_mpll_user", "sclk_bpll_user" };
+PNAME(mout_hdmi_p)     = { "div_hdmi_pixel", "sclk_hdmiphy" };
+PNAME(mout_usb3_p)     = { "sclk_mpll_user", "sclk_cpll" };
+PNAME(mout_group1_p)   = { "fin_pll", "fin_pll", "sclk_hdmi27m",
+                               "sclk_dptxphy", "sclk_uhostphy", "sclk_hdmiphy",
+                               "sclk_mpll_user", "sclk_epll", "sclk_vpll",
+                               "sclk_cpll" };
+PNAME(mout_audio0_p)   = { "cdclk0", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
+                               "sclk_uhostphy", "sclk_hdmiphy",
+                               "sclk_mpll_user", "sclk_epll", "sclk_vpll",
+                               "sclk_cpll" };
+PNAME(mout_audio1_p)   = { "cdclk1", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
+                               "sclk_uhostphy", "sclk_hdmiphy",
+                               "sclk_mpll_user", "sclk_epll", "sclk_vpll",
+                               "sclk_cpll" };
+PNAME(mout_audio2_p)   = { "cdclk2", "fin_pll", "sclk_hdmi27m", "sclk_dptxphy",
+                               "sclk_uhostphy", "sclk_hdmiphy",
+                               "sclk_mpll_user", "sclk_epll", "sclk_vpll",
+                               "sclk_cpll" };
+PNAME(mout_spdif_p)    = { "sclk_audio0", "sclk_audio1", "sclk_audio2",
+                               "spdif_extclk" };
+
+/* fixed rate clocks generated outside the soc */
+struct samsung_fixed_rate_clock exynos5250_fixed_rate_ext_clks[] __initdata = {
+       FRATE(fin_pll, "fin_pll", NULL, CLK_IS_ROOT, 0),
+};
+
+/* fixed rate clocks generated inside the soc */
+struct samsung_fixed_rate_clock exynos5250_fixed_rate_clks[] __initdata = {
+       FRATE(none, "sclk_hdmiphy", NULL, CLK_IS_ROOT, 24000000),
+       FRATE(none, "sclk_hdmi27m", NULL, CLK_IS_ROOT, 27000000),
+       FRATE(none, "sclk_dptxphy", NULL, CLK_IS_ROOT, 24000000),
+       FRATE(none, "sclk_uhostphy", NULL, CLK_IS_ROOT, 48000000),
+};
+
+struct samsung_fixed_factor_clock exynos5250_fixed_factor_clks[] __initdata = {
+       FFACTOR(none, "fout_mplldiv2", "fout_mpll", 1, 2, 0),
+       FFACTOR(none, "fout_bplldiv2", "fout_bpll", 1, 2, 0),
+};
+
+struct samsung_mux_clock exynos5250_mux_clks[] __initdata = {
+       MUX(none, "mout_apll", mout_apll_p, SRC_CPU, 0, 1),
+       MUX(none, "mout_cpu", mout_cpu_p, SRC_CPU, 16, 1),
+       MUX(none, "mout_mpll_fout", mout_mpll_fout_p, PLL_DIV2_SEL, 4, 1),
+       MUX(none, "sclk_mpll", mout_mpll_p, SRC_CORE1, 8, 1),
+       MUX(none, "mout_bpll_fout", mout_bpll_fout_p, PLL_DIV2_SEL, 0, 1),
+       MUX(none, "sclk_bpll", mout_bpll_p, SRC_CDREX, 0, 1),
+       MUX(none, "mout_vpllsrc", mout_vpllsrc_p, SRC_TOP2, 0, 1),
+       MUX(none, "sclk_vpll", mout_vpll_p, SRC_TOP2, 16, 1),
+       MUX(none, "sclk_epll", mout_epll_p, SRC_TOP2, 12, 1),
+       MUX(none, "sclk_cpll", mout_cpll_p, SRC_TOP2, 8, 1),
+       MUX(none, "sclk_mpll_user", mout_mpll_user_p, SRC_TOP2, 20, 1),
+       MUX(none, "sclk_bpll_user", mout_bpll_user_p, SRC_TOP2, 24, 1),
+       MUX(none, "mout_aclk166", mout_aclk166_p, SRC_TOP0, 8, 1),
+       MUX(none, "mout_aclk333", mout_aclk166_p, SRC_TOP0, 16, 1),
+       MUX(none, "mout_aclk200", mout_aclk200_p, SRC_TOP0, 12, 1),
+       MUX(none, "mout_cam_bayer", mout_group1_p, SRC_GSCL, 12, 4),
+       MUX(none, "mout_cam0", mout_group1_p, SRC_GSCL, 16, 4),
+       MUX(none, "mout_cam1", mout_group1_p, SRC_GSCL, 20, 4),
+       MUX(none, "mout_gscl_wa", mout_group1_p, SRC_GSCL, 24, 4),
+       MUX(none, "mout_gscl_wb", mout_group1_p, SRC_GSCL, 28, 4),
+       MUX(none, "mout_fimd1", mout_group1_p, SRC_DISP1_0, 0, 4),
+       MUX(none, "mout_mipi1", mout_group1_p, SRC_DISP1_0, 12, 4),
+       MUX(none, "mout_dp", mout_group1_p, SRC_DISP1_0, 16, 4),
+       MUX(none, "mout_hdmi", mout_hdmi_p, SRC_DISP1_0, 20, 1),
+       MUX(none, "mout_audio0", mout_audio0_p, SRC_MAU, 0, 4),
+       MUX(none, "mout_mmc0", mout_group1_p, SRC_FSYS, 0, 4),
+       MUX(none, "mout_mmc1", mout_group1_p, SRC_FSYS, 4, 4),
+       MUX(none, "mout_mmc2", mout_group1_p, SRC_FSYS, 8, 4),
+       MUX(none, "mout_mmc3", mout_group1_p, SRC_FSYS, 12, 4),
+       MUX(none, "mout_sata", mout_aclk200_p, SRC_FSYS, 24, 1),
+       MUX(none, "mout_usb3", mout_usb3_p, SRC_FSYS, 28, 1),
+       MUX(none, "mout_jpeg", mout_group1_p, SRC_GEN, 0, 4),
+       MUX(none, "mout_uart0", mout_group1_p, SRC_PERIC0, 0, 4),
+       MUX(none, "mout_uart1", mout_group1_p, SRC_PERIC0, 4, 4),
+       MUX(none, "mout_uart2", mout_group1_p, SRC_PERIC0, 8, 4),
+       MUX(none, "mout_uart3", mout_group1_p, SRC_PERIC0, 12, 4),
+       MUX(none, "mout_pwm", mout_group1_p, SRC_PERIC0, 24, 4),
+       MUX(none, "mout_audio1", mout_audio1_p, SRC_PERIC1, 0, 4),
+       MUX(none, "mout_audio2", mout_audio2_p, SRC_PERIC1, 4, 4),
+       MUX(none, "mout_spdif", mout_spdif_p, SRC_PERIC1, 8, 2),
+       MUX(none, "mout_spi0", mout_group1_p, SRC_PERIC1, 16, 4),
+       MUX(none, "mout_spi1", mout_group1_p, SRC_PERIC1, 20, 4),
+       MUX(none, "mout_spi2", mout_group1_p, SRC_PERIC1, 24, 4),
+};
+
+struct samsung_div_clock exynos5250_div_clks[] __initdata = {
+       DIV(none, "div_arm", "mout_cpu", DIV_CPU0, 0, 3),
+       DIV(none, "sclk_apll", "mout_apll", DIV_CPU0, 24, 3),
+       DIV(none, "aclk66_pre", "sclk_mpll_user", DIV_TOP1, 24, 3),
+       DIV(none, "aclk66", "aclk66_pre", DIV_TOP0, 0, 3),
+       DIV(none, "aclk266", "sclk_mpll_user", DIV_TOP0, 16, 3),
+       DIV(none, "aclk166", "mout_aclk166", DIV_TOP0, 8, 3),
+       DIV(none, "aclk333", "mout_aclk333", DIV_TOP0, 20, 3),
+       DIV(none, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3),
+       DIV(none, "div_cam_bayer", "mout_cam_bayer", DIV_GSCL, 12, 4),
+       DIV(none, "div_cam0", "mout_cam0", DIV_GSCL, 16, 4),
+       DIV(none, "div_cam1", "mout_cam1", DIV_GSCL, 20, 4),
+       DIV(none, "div_gscl_wa", "mout_gscl_wa", DIV_GSCL, 24, 4),
+       DIV(none, "div_gscl_wb", "mout_gscl_wb", DIV_GSCL, 28, 4),
+       DIV(none, "div_fimd1", "mout_fimd1", DIV_DISP1_0, 0, 4),
+       DIV(none, "div_mipi1", "mout_mipi1", DIV_DISP1_0, 16, 4),
+       DIV(none, "div_dp", "mout_dp", DIV_DISP1_0, 24, 4),
+       DIV(none, "div_jpeg", "mout_jpeg", DIV_GEN, 4, 4),
+       DIV(none, "div_audio0", "mout_audio0", DIV_MAU, 0, 4),
+       DIV(none, "div_pcm0", "sclk_audio0", DIV_MAU, 4, 8),
+       DIV(none, "div_sata", "mout_sata", DIV_FSYS0, 20, 4),
+       DIV(none, "div_usb3", "mout_usb3", DIV_FSYS0, 24, 4),
+       DIV(none, "div_mmc0", "mout_mmc0", DIV_FSYS1, 8, 8),
+       DIV(none, "div_mmc1", "mout_mmc1", DIV_FSYS1, 24, 8),
+       DIV(none, "div_mmc2", "mout_mmc2", DIV_FSYS2, 8, 8),
+       DIV(none, "div_mmc3", "mout_mmc3", DIV_FSYS2, 24, 8),
+       DIV(none, "div_uart0", "mout_uart0", DIV_PERIC0, 0, 4),
+       DIV(none, "div_uart1", "mout_uart1", DIV_PERIC0, 4, 4),
+       DIV(none, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4),
+       DIV(none, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4),
+       DIV(none, "div_spi0", "mout_spi0", DIV_PERIC1, 0, 4),
+       DIV(none, "div_spi1", "mout_spi1", DIV_PERIC1, 16, 4),
+       DIV(none, "div_spi2", "mout_spi2", DIV_PERIC2, 0, 4),
+       DIV(none, "div_pwm", "mout_pwm", DIV_PERIC3, 0, 4),
+       DIV(none, "div_audio1", "mout_audio1", DIV_PERIC4, 0, 4),
+       DIV(none, "div_pcm1", "sclk_audio1", DIV_PERIC4, 4, 8),
+       DIV(none, "div_audio2", "mout_audio2", DIV_PERIC4, 16, 4),
+       DIV(none, "div_pcm2", "sclk_audio2", DIV_PERIC4, 20, 8),
+       DIV(none, "div_i2s1", "sclk_audio1", DIV_PERIC5, 0, 6),
+       DIV(none, "div_i2s2", "sclk_audio2", DIV_PERIC5, 8, 6),
+       DIV(sclk_pixel, "div_hdmi_pixel", "sclk_vpll", DIV_DISP1_0, 28, 4),
+       DIV_A(none, "armclk", "div_arm", DIV_CPU0, 28, 3, "armclk"),
+       DIV_F(none, "div_mipi1_pre", "div_mipi1",
+                       DIV_DISP1_0, 20, 4, CLK_SET_RATE_PARENT, 0),
+       DIV_F(none, "div_mmc_pre0", "div_mmc0",
+                       DIV_FSYS1, 8, 8, CLK_SET_RATE_PARENT, 0),
+       DIV_F(none, "div_mmc_pre1", "div_mmc1",
+                       DIV_FSYS1, 24, 8, CLK_SET_RATE_PARENT, 0),
+       DIV_F(none, "div_mmc_pre2", "div_mmc2",
+                       DIV_FSYS2, 8, 8, CLK_SET_RATE_PARENT, 0),
+       DIV_F(none, "div_mmc_pre3", "div_mmc3",
+                       DIV_FSYS2, 24, 8, CLK_SET_RATE_PARENT, 0),
+       DIV_F(none, "div_spi_pre0", "div_spi0",
+                       DIV_PERIC1, 8, 8, CLK_SET_RATE_PARENT, 0),
+       DIV_F(none, "div_spi_pre1", "div_spi1",
+                       DIV_PERIC1, 24, 8, CLK_SET_RATE_PARENT, 0),
+       DIV_F(none, "div_spi_pre2", "div_spi2",
+                       DIV_PERIC2, 8, 8, CLK_SET_RATE_PARENT, 0),
+};
+
+struct samsung_gate_clock exynos5250_gate_clks[] __initdata = {
+       GATE(gscl0, "gscl0", "none", GATE_IP_GSCL, 0, 0, 0),
+       GATE(gscl1, "gscl1", "none", GATE_IP_GSCL, 1, 0, 0),
+       GATE(gscl2, "gscl2", "aclk266", GATE_IP_GSCL, 2, 0, 0),
+       GATE(gscl3, "gscl3", "aclk266", GATE_IP_GSCL, 3, 0, 0),
+       GATE(gscl_wa, "gscl_wa", "div_gscl_wa", GATE_IP_GSCL, 5, 0, 0),
+       GATE(gscl_wb, "gscl_wb", "div_gscl_wb", GATE_IP_GSCL, 6, 0, 0),
+       GATE(smmu_gscl0, "smmu_gscl0", "aclk266", GATE_IP_GSCL, 7, 0, 0),
+       GATE(smmu_gscl1, "smmu_gscl1", "aclk266", GATE_IP_GSCL, 8, 0, 0),
+       GATE(smmu_gscl2, "smmu_gscl2", "aclk266", GATE_IP_GSCL, 9, 0, 0),
+       GATE(smmu_gscl3, "smmu_gscl3", "aclk266", GATE_IP_GSCL, 10, 0, 0),
+       GATE(mfc, "mfc", "aclk333", GATE_IP_MFC, 0, 0, 0),
+       GATE(smmu_mfcl, "smmu_mfcl", "aclk333", GATE_IP_MFC, 1, 0, 0),
+       GATE(smmu_mfcr, "smmu_mfcr", "aclk333", GATE_IP_MFC, 2, 0, 0),
+       GATE(rotator, "rotator", "aclk266", GATE_IP_GEN, 1, 0, 0),
+       GATE(jpeg, "jpeg", "aclk166", GATE_IP_GEN, 2, 0, 0),
+       GATE(mdma1, "mdma1", "aclk266", GATE_IP_GEN, 4, 0, 0),
+       GATE(smmu_rotator, "smmu_rotator", "aclk266", GATE_IP_GEN, 6, 0, 0),
+       GATE(smmu_jpeg, "smmu_jpeg", "aclk166", GATE_IP_GEN, 7, 0, 0),
+       GATE(smmu_mdma1, "smmu_mdma1", "aclk266", GATE_IP_GEN, 9, 0, 0),
+       GATE(pdma0, "pdma0", "aclk200", GATE_IP_FSYS, 1, 0, 0),
+       GATE(pdma1, "pdma1", "aclk200", GATE_IP_FSYS, 2, 0, 0),
+       GATE(sata, "sata", "aclk200", GATE_IP_FSYS, 6, 0, 0),
+       GATE(usbotg, "usbotg", "aclk200", GATE_IP_FSYS, 7, 0, 0),
+       GATE(mipi_hsi, "mipi_hsi", "aclk200", GATE_IP_FSYS, 8, 0, 0),
+       GATE(sdmmc0, "sdmmc0", "aclk200", GATE_IP_FSYS, 12, 0, 0),
+       GATE(sdmmc1, "sdmmc1", "aclk200", GATE_IP_FSYS, 13, 0, 0),
+       GATE(sdmmc2, "sdmmc2", "aclk200", GATE_IP_FSYS, 14, 0, 0),
+       GATE(sdmmc3, "sdmmc3", "aclk200", GATE_IP_FSYS, 15, 0, 0),
+       GATE(sromc, "sromc", "aclk200", GATE_IP_FSYS, 17, 0, 0),
+       GATE(usb2, "usb2", "aclk200", GATE_IP_FSYS, 18, 0, 0),
+       GATE(usb3, "usb3", "aclk200", GATE_IP_FSYS, 19, 0, 0),
+       GATE(sata_phyctrl, "sata_phyctrl", "aclk200", GATE_IP_FSYS, 24, 0, 0),
+       GATE(sata_phyi2c, "sata_phyi2c", "aclk200", GATE_IP_FSYS, 25, 0, 0),
+       GATE(uart0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0),
+       GATE(uart1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0),
+       GATE(uart2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
+       GATE(uart3, "uart3", "aclk66", GATE_IP_PERIC, 3, 0, 0),
+       GATE(uart4, "uart4", "aclk66", GATE_IP_PERIC, 4, 0, 0),
+       GATE(i2c0, "i2c0", "aclk66", GATE_IP_PERIC, 6, 0, 0),
+       GATE(i2c1, "i2c1", "aclk66", GATE_IP_PERIC, 7, 0, 0),
+       GATE(i2c2, "i2c2", "aclk66", GATE_IP_PERIC, 8, 0, 0),
+       GATE(i2c3, "i2c3", "aclk66", GATE_IP_PERIC, 9, 0, 0),
+       GATE(i2c4, "i2c4", "aclk66", GATE_IP_PERIC, 10, 0, 0),
+       GATE(i2c5, "i2c5", "aclk66", GATE_IP_PERIC, 11, 0, 0),
+       GATE(i2c6, "i2c6", "aclk66", GATE_IP_PERIC, 12, 0, 0),
+       GATE(i2c7, "i2c7", "aclk66", GATE_IP_PERIC, 13, 0, 0),
+       GATE(i2c_hdmi, "i2c_hdmi", "aclk66", GATE_IP_PERIC, 14, 0, 0),
+       GATE(adc, "adc", "aclk66", GATE_IP_PERIC, 15, 0, 0),
+       GATE(spi0, "spi0", "aclk66", GATE_IP_PERIC, 16, 0, 0),
+       GATE(spi1, "spi1", "aclk66", GATE_IP_PERIC, 17, 0, 0),
+       GATE(spi2, "spi2", "aclk66", GATE_IP_PERIC, 18, 0, 0),
+       GATE(i2s1, "i2s1", "aclk66", GATE_IP_PERIC, 20, 0, 0),
+       GATE(i2s2, "i2s2", "aclk66", GATE_IP_PERIC, 21, 0, 0),
+       GATE(pcm1, "pcm1", "aclk66", GATE_IP_PERIC, 22, 0, 0),
+       GATE(pcm2, "pcm2", "aclk66", GATE_IP_PERIC, 23, 0, 0),
+       GATE(pwm, "pwm", "aclk66", GATE_IP_PERIC, 24, 0, 0),
+       GATE(spdif, "spdif", "aclk66", GATE_IP_PERIC, 26, 0, 0),
+       GATE(ac97, "ac97", "aclk66", GATE_IP_PERIC, 27, 0, 0),
+       GATE(hsi2c0, "hsi2c0", "aclk66", GATE_IP_PERIC, 28, 0, 0),
+       GATE(hsi2c1, "hsi2c1", "aclk66", GATE_IP_PERIC, 29, 0, 0),
+       GATE(hsi2c2, "hsi2c2", "aclk66", GATE_IP_PERIC, 30, 0, 0),
+       GATE(hsi2c3, "hsi2c3", "aclk66", GATE_IP_PERIC, 31, 0, 0),
+       GATE(chipid, "chipid", "aclk66", GATE_IP_PERIS, 0, 0, 0),
+       GATE(sysreg, "sysreg", "aclk66", GATE_IP_PERIS, 1, 0, 0),
+       GATE(pmu, "pmu", "aclk66", GATE_IP_PERIS, 2, 0, 0),
+       GATE(tzpc0, "tzpc0", "aclk66", GATE_IP_PERIS, 6, 0, 0),
+       GATE(tzpc1, "tzpc1", "aclk66", GATE_IP_PERIS, 7, 0, 0),
+       GATE(tzpc2, "tzpc2", "aclk66", GATE_IP_PERIS, 8, 0, 0),
+       GATE(tzpc3, "tzpc3", "aclk66", GATE_IP_PERIS, 9, 0, 0),
+       GATE(tzpc4, "tzpc4", "aclk66", GATE_IP_PERIS, 10, 0, 0),
+       GATE(tzpc5, "tzpc5", "aclk66", GATE_IP_PERIS, 11, 0, 0),
+       GATE(tzpc6, "tzpc6", "aclk66", GATE_IP_PERIS, 12, 0, 0),
+       GATE(tzpc7, "tzpc7", "aclk66", GATE_IP_PERIS, 13, 0, 0),
+       GATE(tzpc8, "tzpc8", "aclk66", GATE_IP_PERIS, 14, 0, 0),
+       GATE(tzpc9, "tzpc9", "aclk66", GATE_IP_PERIS, 15, 0, 0),
+       GATE(hdmi_cec, "hdmi_cec", "aclk66", GATE_IP_PERIS, 16, 0, 0),
+       GATE(mct, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0),
+       GATE(wdt, "wdt", "aclk66", GATE_IP_PERIS, 19, 0, 0),
+       GATE(rtc, "rtc", "aclk66", GATE_IP_PERIS, 20, 0, 0),
+       GATE(tmu, "tmu", "aclk66", GATE_IP_PERIS, 21, 0, 0),
+       GATE(cmu_top, "cmu_top", "aclk66",
+                       GATE_IP_PERIS, 3, CLK_IGNORE_UNUSED, 0),
+       GATE(cmu_core, "cmu_core", "aclk66",
+                       GATE_IP_PERIS, 4, CLK_IGNORE_UNUSED, 0),
+       GATE(cmu_mem, "cmu_mem", "aclk66",
+                       GATE_IP_PERIS, 5, CLK_IGNORE_UNUSED, 0),
+       GATE(sclk_cam_bayer, "sclk_cam_bayer", "div_cam_bayer",
+                       SRC_MASK_GSCL, 12, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_cam0, "sclk_cam0", "div_cam0",
+                       SRC_MASK_GSCL, 16, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_cam1, "sclk_cam1", "div_cam1",
+                       SRC_MASK_GSCL, 20, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_gscl_wa, "sclk_gscl_wa", "div_gscl_wa",
+                       SRC_MASK_GSCL, 24, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_gscl_wb, "sclk_gscl_wb", "div_gscl_wb",
+                       SRC_MASK_GSCL, 28, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_fimd1, "sclk_fimd1", "div_fimd1",
+                       SRC_MASK_DISP1_0, 0, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_mipi1, "sclk_mipi1", "div_mipi1",
+                       SRC_MASK_DISP1_0, 12, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_dp, "sclk_dp", "div_dp",
+                       SRC_MASK_DISP1_0, 16, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_hdmi, "sclk_hdmi", "mout_hdmi",
+                       SRC_MASK_DISP1_0, 20, 0, 0),
+       GATE(sclk_audio0, "sclk_audio0", "div_audio0",
+                       SRC_MASK_MAU, 0, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_mmc0, "sclk_mmc0", "div_mmc0",
+                       SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_mmc1, "sclk_mmc1", "div_mmc1",
+                       SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_mmc2, "sclk_mmc2", "div_mmc2",
+                       SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_mmc3, "sclk_mmc3", "div_mmc3",
+                       SRC_MASK_FSYS, 12, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_sata, "sclk_sata", "div_sata",
+                       SRC_MASK_FSYS, 24, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_usb3, "sclk_usb3", "div_usb3",
+                       SRC_MASK_FSYS, 28, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_jpeg, "sclk_jpeg", "div_jpeg",
+                       SRC_MASK_GEN, 0, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_uart0, "sclk_uart0", "div_uart0",
+                       SRC_MASK_PERIC0, 0, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_uart1, "sclk_uart1", "div_uart1",
+                       SRC_MASK_PERIC0, 4, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_uart2, "sclk_uart2", "div_uart2",
+                       SRC_MASK_PERIC0, 8, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_uart3, "sclk_uart3", "div_uart3",
+                       SRC_MASK_PERIC0, 12, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_pwm, "sclk_pwm", "div_pwm",
+                       SRC_MASK_PERIC0, 24, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_audio1, "sclk_audio1", "div_audio1",
+                       SRC_MASK_PERIC1, 0, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_audio2, "sclk_audio2", "div_audio2",
+                       SRC_MASK_PERIC1, 4, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_spdif, "sclk_spdif", "mout_spdif",
+                       SRC_MASK_PERIC1, 4, 0, 0),
+       GATE(sclk_spi0, "sclk_spi0", "div_spi_pre0",
+                       SRC_MASK_PERIC1, 16, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_spi1, "sclk_spi1", "div_spi_pre1",
+                       SRC_MASK_PERIC1, 20, CLK_SET_RATE_PARENT, 0),
+       GATE(sclk_spi2, "sclk_spi2", "div_spi_pre2",
+                       SRC_MASK_PERIC1, 24, CLK_SET_RATE_PARENT, 0),
+       GATE(fimd1, "fimd1", "aclk200", GATE_IP_DISP1, 0, 0, 0),
+       GATE(mie1, "mie1", "aclk200", GATE_IP_DISP1, 1, 0, 0),
+       GATE(dsim0, "dsim0", "aclk200", GATE_IP_DISP1, 3, 0, 0),
+       GATE(dp, "dp", "aclk200", GATE_IP_DISP1, 4, 0, 0),
+       GATE(mixer, "mixer", "aclk200", GATE_IP_DISP1, 5, 0, 0),
+       GATE(hdmi, "hdmi", "aclk200", GATE_IP_DISP1, 6, 0, 0),
+};
+
+static __initdata struct of_device_id ext_clk_match[] = {
+       { .compatible = "samsung,clock-xxti", .data = (void *)0, },
+       { },
+};
+
+/* register exynox5250 clocks */
+void __init exynos5250_clk_init(struct device_node *np)
+{
+       void __iomem *reg_base;
+       struct clk *apll, *mpll, *epll, *vpll, *bpll, *gpll, *cpll;
+
+       if (np) {
+               reg_base = of_iomap(np, 0);
+               if (!reg_base)
+                       panic("%s: failed to map registers\n", __func__);
+       } else {
+               panic("%s: unable to determine soc\n", __func__);
+       }
+
+       samsung_clk_init(np, reg_base, nr_clks,
+                       exynos5250_clk_regs, ARRAY_SIZE(exynos5250_clk_regs),
+                       NULL, 0);
+       samsung_clk_of_register_fixed_ext(exynos5250_fixed_rate_ext_clks,
+                       ARRAY_SIZE(exynos5250_fixed_rate_ext_clks),
+                       ext_clk_match);
+
+       apll = samsung_clk_register_pll35xx("fout_apll", "fin_pll",
+                       reg_base + 0x100);
+       mpll = samsung_clk_register_pll35xx("fout_mpll", "fin_pll",
+                       reg_base + 0x4100);
+       bpll = samsung_clk_register_pll35xx("fout_bpll", "fin_pll",
+                       reg_base + 0x20110);
+       gpll = samsung_clk_register_pll35xx("fout_gpll", "fin_pll",
+                       reg_base + 0x10150);
+       cpll = samsung_clk_register_pll35xx("fout_cpll", "fin_pll",
+                       reg_base + 0x10120);
+       epll = samsung_clk_register_pll36xx("fout_epll", "fin_pll",
+                       reg_base + 0x10130);
+       vpll = samsung_clk_register_pll36xx("fout_vpll", "mout_vpllsrc",
+                       reg_base + 0x10140);
+
+       samsung_clk_register_fixed_rate(exynos5250_fixed_rate_clks,
+                       ARRAY_SIZE(exynos5250_fixed_rate_clks));
+       samsung_clk_register_fixed_factor(exynos5250_fixed_factor_clks,
+                       ARRAY_SIZE(exynos5250_fixed_factor_clks));
+       samsung_clk_register_mux(exynos5250_mux_clks,
+                       ARRAY_SIZE(exynos5250_mux_clks));
+       samsung_clk_register_div(exynos5250_div_clks,
+                       ARRAY_SIZE(exynos5250_div_clks));
+       samsung_clk_register_gate(exynos5250_gate_clks,
+                       ARRAY_SIZE(exynos5250_gate_clks));
+
+       pr_info("Exynos5250: clock setup completed, armclk=%ld\n",
+                       _get_rate("armclk"));
+}
+CLK_OF_DECLARE(exynos5250_clk, "samsung,exynos5250-clock", exynos5250_clk_init);
diff --git a/drivers/clk/samsung/clk-exynos5440.c b/drivers/clk/samsung/clk-exynos5440.c
new file mode 100644 (file)
index 0000000..7d54341
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Author: Thomas Abraham <thomas.ab@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.
+ *
+ * Common Clock Framework support for Exynos5440 SoC.
+*/
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk.h"
+#include "clk-pll.h"
+
+#define CLKEN_OV_VAL           0xf8
+#define CPU_CLK_STATUS         0xfc
+#define MISC_DOUT1             0x558
+
+/*
+ * Let each supported clock get a unique id. This id is used to lookup the clock
+ * for device tree based platforms.
+ */
+enum exynos5440_clks {
+       none, xtal, arm_clk,
+
+       spi_baud = 16, pb0_250, pr0_250, pr1_250, b_250, b_125, b_200, sata,
+       usb, gmac0, cs250, pb0_250_o, pr0_250_o, pr1_250_o, b_250_o, b_125_o,
+       b_200_o, sata_o, usb_o, gmac0_o, cs250_o,
+
+       nr_clks,
+};
+
+/* parent clock name list */
+PNAME(mout_armclk_p)   = { "cplla", "cpllb" };
+PNAME(mout_spi_p)      = { "div125", "div200" };
+
+/* fixed rate clocks generated outside the soc */
+struct samsung_fixed_rate_clock exynos5440_fixed_rate_ext_clks[] __initdata = {
+       FRATE(none, "xtal", NULL, CLK_IS_ROOT, 0),
+};
+
+/* fixed rate clocks */
+struct samsung_fixed_rate_clock exynos5440_fixed_rate_clks[] __initdata = {
+       FRATE(none, "ppll", NULL, CLK_IS_ROOT, 1000000000),
+       FRATE(none, "usb_phy0", NULL, CLK_IS_ROOT, 60000000),
+       FRATE(none, "usb_phy1", NULL, CLK_IS_ROOT, 60000000),
+       FRATE(none, "usb_ohci12", NULL, CLK_IS_ROOT, 12000000),
+       FRATE(none, "usb_ohci48", NULL, CLK_IS_ROOT, 48000000),
+};
+
+/* fixed factor clocks */
+struct samsung_fixed_factor_clock exynos5440_fixed_factor_clks[] __initdata = {
+       FFACTOR(none, "div250", "ppll", 1, 4, 0),
+       FFACTOR(none, "div200", "ppll", 1, 5, 0),
+       FFACTOR(none, "div125", "div250", 1, 2, 0),
+};
+
+/* mux clocks */
+struct samsung_mux_clock exynos5440_mux_clks[] __initdata = {
+       MUX(none, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1),
+       MUX_A(arm_clk, "arm_clk", mout_armclk_p,
+                       CPU_CLK_STATUS, 0, 1, "armclk"),
+};
+
+/* divider clocks */
+struct samsung_div_clock exynos5440_div_clks[] __initdata = {
+       DIV(spi_baud, "div_spi", "mout_spi", MISC_DOUT1, 3, 2),
+};
+
+/* gate clocks */
+struct samsung_gate_clock exynos5440_gate_clks[] __initdata = {
+       GATE(pb0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0),
+       GATE(pr0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0),
+       GATE(pr1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0),
+       GATE(b_250, "b_250", "div250", CLKEN_OV_VAL, 9, 0, 0),
+       GATE(b_125, "b_125", "div125", CLKEN_OV_VAL, 10, 0, 0),
+       GATE(b_200, "b_200", "div200", CLKEN_OV_VAL, 11, 0, 0),
+       GATE(sata, "sata", "div200", CLKEN_OV_VAL, 12, 0, 0),
+       GATE(usb, "usb", "div200", CLKEN_OV_VAL, 13, 0, 0),
+       GATE(gmac0, "gmac0", "div200", CLKEN_OV_VAL, 14, 0, 0),
+       GATE(cs250, "cs250", "div250", CLKEN_OV_VAL, 19, 0, 0),
+       GATE(pb0_250_o, "pb0_250_o", "pb0_250", CLKEN_OV_VAL, 3, 0, 0),
+       GATE(pr0_250_o, "pr0_250_o", "pr0_250", CLKEN_OV_VAL, 4, 0, 0),
+       GATE(pr1_250_o, "pr1_250_o", "pr1_250", CLKEN_OV_VAL, 5, 0, 0),
+       GATE(b_250_o, "b_250_o", "b_250", CLKEN_OV_VAL, 9, 0, 0),
+       GATE(b_125_o, "b_125_o", "b_125", CLKEN_OV_VAL, 10, 0, 0),
+       GATE(b_200_o, "b_200_o", "b_200", CLKEN_OV_VAL, 11, 0, 0),
+       GATE(sata_o, "sata_o", "sata", CLKEN_OV_VAL, 12, 0, 0),
+       GATE(usb_o, "usb_o", "usb", CLKEN_OV_VAL, 13, 0, 0),
+       GATE(gmac0_o, "gmac0_o", "gmac", CLKEN_OV_VAL, 14, 0, 0),
+       GATE(cs250_o, "cs250_o", "cs250", CLKEN_OV_VAL, 19, 0, 0),
+};
+
+static __initdata struct of_device_id ext_clk_match[] = {
+       { .compatible = "samsung,clock-xtal", .data = (void *)0, },
+       {},
+};
+
+/* register exynos5440 clocks */
+void __init exynos5440_clk_init(struct device_node *np)
+{
+       void __iomem *reg_base;
+
+       reg_base = of_iomap(np, 0);
+       if (!reg_base) {
+               pr_err("%s: failed to map clock controller registers,"
+                       " aborting clock initialization\n", __func__);
+               return;
+       }
+
+       samsung_clk_init(np, reg_base, nr_clks, NULL, 0, NULL, 0);
+       samsung_clk_of_register_fixed_ext(exynos5440_fixed_rate_ext_clks,
+               ARRAY_SIZE(exynos5440_fixed_rate_ext_clks), ext_clk_match);
+
+       samsung_clk_register_pll2550x("cplla", "xtal", reg_base + 0x1c, 0x10);
+       samsung_clk_register_pll2550x("cpllb", "xtal", reg_base + 0x20, 0x10);
+
+       samsung_clk_register_fixed_rate(exynos5440_fixed_rate_clks,
+                       ARRAY_SIZE(exynos5440_fixed_rate_clks));
+       samsung_clk_register_fixed_factor(exynos5440_fixed_factor_clks,
+                       ARRAY_SIZE(exynos5440_fixed_factor_clks));
+       samsung_clk_register_mux(exynos5440_mux_clks,
+                       ARRAY_SIZE(exynos5440_mux_clks));
+       samsung_clk_register_div(exynos5440_div_clks,
+                       ARRAY_SIZE(exynos5440_div_clks));
+       samsung_clk_register_gate(exynos5440_gate_clks,
+                       ARRAY_SIZE(exynos5440_gate_clks));
+
+       pr_info("Exynos5440: arm_clk = %ldHz\n", _get_rate("armclk"));
+       pr_info("exynos5440 clock initialization complete\n");
+}
+CLK_OF_DECLARE(exynos5440_clk, "samsung,exynos5440-clock", exynos5440_clk_init);
diff --git a/drivers/clk/samsung/clk-pll.c b/drivers/clk/samsung/clk-pll.c
new file mode 100644 (file)
index 0000000..89135f6
--- /dev/null
@@ -0,0 +1,419 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ *
+ * 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 the utility functions to register the pll clocks.
+*/
+
+#include <linux/errno.h>
+#include "clk.h"
+#include "clk-pll.h"
+
+/*
+ * PLL35xx Clock Type
+ */
+
+#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)
+
+struct samsung_clk_pll35xx {
+       struct clk_hw           hw;
+       const void __iomem      *con_reg;
+};
+
+#define to_clk_pll35xx(_hw) container_of(_hw, struct samsung_clk_pll35xx, hw)
+
+static unsigned long samsung_pll35xx_recalc_rate(struct clk_hw *hw,
+                               unsigned long parent_rate)
+{
+       struct samsung_clk_pll35xx *pll = to_clk_pll35xx(hw);
+       u32 mdiv, pdiv, sdiv, pll_con;
+       u64 fvco = parent_rate;
+
+       pll_con = __raw_readl(pll->con_reg);
+       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;
+}
+
+static const struct clk_ops samsung_pll35xx_clk_ops = {
+       .recalc_rate = samsung_pll35xx_recalc_rate,
+};
+
+struct clk * __init samsung_clk_register_pll35xx(const char *name,
+                       const char *pname, const void __iomem *con_reg)
+{
+       struct samsung_clk_pll35xx *pll;
+       struct clk *clk;
+       struct clk_init_data init;
+
+       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+       if (!pll) {
+               pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+               return NULL;
+       }
+
+       init.name = name;
+       init.ops = &samsung_pll35xx_clk_ops;
+       init.flags = CLK_GET_RATE_NOCACHE;
+       init.parent_names = &pname;
+       init.num_parents = 1;
+
+       pll->hw.init = &init;
+       pll->con_reg = con_reg;
+
+       clk = clk_register(NULL, &pll->hw);
+       if (IS_ERR(clk)) {
+               pr_err("%s: failed to register pll clock %s\n", __func__,
+                               name);
+               kfree(pll);
+       }
+
+       if (clk_register_clkdev(clk, name, NULL))
+               pr_err("%s: failed to register lookup for %s", __func__, name);
+
+       return clk;
+}
+
+/*
+ * PLL36xx Clock Type
+ */
+
+#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)
+
+struct samsung_clk_pll36xx {
+       struct clk_hw           hw;
+       const void __iomem      *con_reg;
+};
+
+#define to_clk_pll36xx(_hw) container_of(_hw, struct samsung_clk_pll36xx, hw)
+
+static unsigned long samsung_pll36xx_recalc_rate(struct clk_hw *hw,
+                               unsigned long parent_rate)
+{
+       struct samsung_clk_pll36xx *pll = to_clk_pll36xx(hw);
+       u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1;
+       u64 fvco = parent_rate;
+
+       pll_con0 = __raw_readl(pll->con_reg);
+       pll_con1 = __raw_readl(pll->con_reg + 4);
+       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;
+
+       fvco *= (mdiv << 16) + kdiv;
+       do_div(fvco, (pdiv << sdiv));
+       fvco >>= 16;
+
+       return (unsigned long)fvco;
+}
+
+static const struct clk_ops samsung_pll36xx_clk_ops = {
+       .recalc_rate = samsung_pll36xx_recalc_rate,
+};
+
+struct clk * __init samsung_clk_register_pll36xx(const char *name,
+                       const char *pname, const void __iomem *con_reg)
+{
+       struct samsung_clk_pll36xx *pll;
+       struct clk *clk;
+       struct clk_init_data init;
+
+       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+       if (!pll) {
+               pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+               return NULL;
+       }
+
+       init.name = name;
+       init.ops = &samsung_pll36xx_clk_ops;
+       init.flags = CLK_GET_RATE_NOCACHE;
+       init.parent_names = &pname;
+       init.num_parents = 1;
+
+       pll->hw.init = &init;
+       pll->con_reg = con_reg;
+
+       clk = clk_register(NULL, &pll->hw);
+       if (IS_ERR(clk)) {
+               pr_err("%s: failed to register pll clock %s\n", __func__,
+                               name);
+               kfree(pll);
+       }
+
+       if (clk_register_clkdev(clk, name, NULL))
+               pr_err("%s: failed to register lookup for %s", __func__, name);
+
+       return clk;
+}
+
+/*
+ * PLL45xx Clock Type
+ */
+
+#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)
+
+struct samsung_clk_pll45xx {
+       struct clk_hw           hw;
+       enum pll45xx_type       type;
+       const void __iomem      *con_reg;
+};
+
+#define to_clk_pll45xx(_hw) container_of(_hw, struct samsung_clk_pll45xx, hw)
+
+static unsigned long samsung_pll45xx_recalc_rate(struct clk_hw *hw,
+                               unsigned long parent_rate)
+{
+       struct samsung_clk_pll45xx *pll = to_clk_pll45xx(hw);
+       u32 mdiv, pdiv, sdiv, pll_con;
+       u64 fvco = parent_rate;
+
+       pll_con = __raw_readl(pll->con_reg);
+       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;
+}
+
+static const struct clk_ops samsung_pll45xx_clk_ops = {
+       .recalc_rate = samsung_pll45xx_recalc_rate,
+};
+
+struct clk * __init samsung_clk_register_pll45xx(const char *name,
+                       const char *pname, const void __iomem *con_reg,
+                       enum pll45xx_type type)
+{
+       struct samsung_clk_pll45xx *pll;
+       struct clk *clk;
+       struct clk_init_data init;
+
+       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+       if (!pll) {
+               pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+               return NULL;
+       }
+
+       init.name = name;
+       init.ops = &samsung_pll45xx_clk_ops;
+       init.flags = CLK_GET_RATE_NOCACHE;
+       init.parent_names = &pname;
+       init.num_parents = 1;
+
+       pll->hw.init = &init;
+       pll->con_reg = con_reg;
+       pll->type = type;
+
+       clk = clk_register(NULL, &pll->hw);
+       if (IS_ERR(clk)) {
+               pr_err("%s: failed to register pll clock %s\n", __func__,
+                               name);
+               kfree(pll);
+       }
+
+       if (clk_register_clkdev(clk, name, NULL))
+               pr_err("%s: failed to register lookup for %s", __func__, name);
+
+       return clk;
+}
+
+/*
+ * PLL46xx Clock Type
+ */
+
+#define PLL46XX_MDIV_MASK      (0x1FF)
+#define PLL46XX_PDIV_MASK      (0x3F)
+#define PLL46XX_SDIV_MASK      (0x7)
+#define PLL46XX_MDIV_SHIFT     (16)
+#define PLL46XX_PDIV_SHIFT     (8)
+#define PLL46XX_SDIV_SHIFT     (0)
+
+#define PLL46XX_KDIV_MASK      (0xFFFF)
+#define PLL4650C_KDIV_MASK     (0xFFF)
+#define PLL46XX_KDIV_SHIFT     (0)
+
+struct samsung_clk_pll46xx {
+       struct clk_hw           hw;
+       enum pll46xx_type       type;
+       const void __iomem      *con_reg;
+};
+
+#define to_clk_pll46xx(_hw) container_of(_hw, struct samsung_clk_pll46xx, hw)
+
+static unsigned long samsung_pll46xx_recalc_rate(struct clk_hw *hw,
+                               unsigned long parent_rate)
+{
+       struct samsung_clk_pll46xx *pll = to_clk_pll46xx(hw);
+       u32 mdiv, pdiv, sdiv, kdiv, pll_con0, pll_con1, shift;
+       u64 fvco = parent_rate;
+
+       pll_con0 = __raw_readl(pll->con_reg);
+       pll_con1 = __raw_readl(pll->con_reg + 4);
+       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->type == pll_4650c ? pll_con1 & PLL4650C_KDIV_MASK :
+                                       pll_con1 & PLL46XX_KDIV_MASK;
+
+       shift = pll->type == pll_4600 ? 16 : 10;
+       fvco *= (mdiv << shift) + kdiv;
+       do_div(fvco, (pdiv << sdiv));
+       fvco >>= shift;
+
+       return (unsigned long)fvco;
+}
+
+static const struct clk_ops samsung_pll46xx_clk_ops = {
+       .recalc_rate = samsung_pll46xx_recalc_rate,
+};
+
+struct clk * __init samsung_clk_register_pll46xx(const char *name,
+                       const char *pname, const void __iomem *con_reg,
+                       enum pll46xx_type type)
+{
+       struct samsung_clk_pll46xx *pll;
+       struct clk *clk;
+       struct clk_init_data init;
+
+       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+       if (!pll) {
+               pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+               return NULL;
+       }
+
+       init.name = name;
+       init.ops = &samsung_pll46xx_clk_ops;
+       init.flags = CLK_GET_RATE_NOCACHE;
+       init.parent_names = &pname;
+       init.num_parents = 1;
+
+       pll->hw.init = &init;
+       pll->con_reg = con_reg;
+       pll->type = type;
+
+       clk = clk_register(NULL, &pll->hw);
+       if (IS_ERR(clk)) {
+               pr_err("%s: failed to register pll clock %s\n", __func__,
+                               name);
+               kfree(pll);
+       }
+
+       if (clk_register_clkdev(clk, name, NULL))
+               pr_err("%s: failed to register lookup for %s", __func__, name);
+
+       return clk;
+}
+
+/*
+ * PLL2550x Clock Type
+ */
+
+#define PLL2550X_R_MASK       (0x1)
+#define PLL2550X_P_MASK       (0x3F)
+#define PLL2550X_M_MASK       (0x3FF)
+#define PLL2550X_S_MASK       (0x7)
+#define PLL2550X_R_SHIFT      (20)
+#define PLL2550X_P_SHIFT      (14)
+#define PLL2550X_M_SHIFT      (4)
+#define PLL2550X_S_SHIFT      (0)
+
+struct samsung_clk_pll2550x {
+       struct clk_hw           hw;
+       const void __iomem      *reg_base;
+       unsigned long           offset;
+};
+
+#define to_clk_pll2550x(_hw) container_of(_hw, struct samsung_clk_pll2550x, hw)
+
+static unsigned long samsung_pll2550x_recalc_rate(struct clk_hw *hw,
+                               unsigned long parent_rate)
+{
+       struct samsung_clk_pll2550x *pll = to_clk_pll2550x(hw);
+       u32 r, p, m, s, pll_stat;
+       u64 fvco = parent_rate;
+
+       pll_stat = __raw_readl(pll->reg_base + pll->offset * 3);
+       r = (pll_stat >> PLL2550X_R_SHIFT) & PLL2550X_R_MASK;
+       if (!r)
+               return 0;
+       p = (pll_stat >> PLL2550X_P_SHIFT) & PLL2550X_P_MASK;
+       m = (pll_stat >> PLL2550X_M_SHIFT) & PLL2550X_M_MASK;
+       s = (pll_stat >> PLL2550X_S_SHIFT) & PLL2550X_S_MASK;
+
+       fvco *= m;
+       do_div(fvco, (p << s));
+
+       return (unsigned long)fvco;
+}
+
+static const struct clk_ops samsung_pll2550x_clk_ops = {
+       .recalc_rate = samsung_pll2550x_recalc_rate,
+};
+
+struct clk * __init samsung_clk_register_pll2550x(const char *name,
+                       const char *pname, const void __iomem *reg_base,
+                       const unsigned long offset)
+{
+       struct samsung_clk_pll2550x *pll;
+       struct clk *clk;
+       struct clk_init_data init;
+
+       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+       if (!pll) {
+               pr_err("%s: could not allocate pll clk %s\n", __func__, name);
+               return NULL;
+       }
+
+       init.name = name;
+       init.ops = &samsung_pll2550x_clk_ops;
+       init.flags = CLK_GET_RATE_NOCACHE;
+       init.parent_names = &pname;
+       init.num_parents = 1;
+
+       pll->hw.init = &init;
+       pll->reg_base = reg_base;
+       pll->offset = offset;
+
+       clk = clk_register(NULL, &pll->hw);
+       if (IS_ERR(clk)) {
+               pr_err("%s: failed to register pll clock %s\n", __func__,
+                               name);
+               kfree(pll);
+       }
+
+       if (clk_register_clkdev(clk, name, NULL))
+               pr_err("%s: failed to register lookup for %s", __func__, name);
+
+       return clk;
+}
diff --git a/drivers/clk/samsung/clk-pll.h b/drivers/clk/samsung/clk-pll.h
new file mode 100644 (file)
index 0000000..f33786e
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ *
+ * 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 Clock Framework support for all PLL's in Samsung platforms
+*/
+
+#ifndef __SAMSUNG_CLK_PLL_H
+#define __SAMSUNG_CLK_PLL_H
+
+enum pll45xx_type {
+       pll_4500,
+       pll_4502,
+       pll_4508
+};
+
+enum pll46xx_type {
+       pll_4600,
+       pll_4650,
+       pll_4650c,
+};
+
+extern struct clk * __init samsung_clk_register_pll35xx(const char *name,
+                       const char *pname, const void __iomem *con_reg);
+extern struct clk * __init samsung_clk_register_pll36xx(const char *name,
+                       const char *pname, const void __iomem *con_reg);
+extern struct clk * __init samsung_clk_register_pll45xx(const char *name,
+                       const char *pname, const void __iomem *con_reg,
+                       enum pll45xx_type type);
+extern struct clk * __init samsung_clk_register_pll46xx(const char *name,
+                       const char *pname, const void __iomem *con_reg,
+                       enum pll46xx_type type);
+extern struct clk * __init samsung_clk_register_pll2550x(const char *name,
+                       const char *pname, const void __iomem *reg_base,
+                       const unsigned long offset);
+
+#endif /* __SAMSUNG_CLK_PLL_H */
diff --git a/drivers/clk/samsung/clk.c b/drivers/clk/samsung/clk.c
new file mode 100644 (file)
index 0000000..cd3c40a
--- /dev/null
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@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.
+ *
+ * This file includes utility functions to register clocks to common
+ * clock framework for Samsung platforms.
+*/
+
+#include <linux/syscore_ops.h>
+#include "clk.h"
+
+static DEFINE_SPINLOCK(lock);
+static struct clk **clk_table;
+static void __iomem *reg_base;
+#ifdef CONFIG_OF
+static struct clk_onecell_data clk_data;
+#endif
+
+#ifdef CONFIG_PM_SLEEP
+static struct samsung_clk_reg_dump *reg_dump;
+static unsigned long nr_reg_dump;
+
+static int samsung_clk_suspend(void)
+{
+       struct samsung_clk_reg_dump *rd = reg_dump;
+       unsigned long i;
+
+       for (i = 0; i < nr_reg_dump; i++, rd++)
+               rd->value = __raw_readl(reg_base + rd->offset);
+
+       return 0;
+}
+
+static void samsung_clk_resume(void)
+{
+       struct samsung_clk_reg_dump *rd = reg_dump;
+       unsigned long i;
+
+       for (i = 0; i < nr_reg_dump; i++, rd++)
+               __raw_writel(rd->value, reg_base + rd->offset);
+}
+
+static struct syscore_ops samsung_clk_syscore_ops = {
+       .suspend        = samsung_clk_suspend,
+       .resume         = samsung_clk_resume,
+};
+#endif /* CONFIG_PM_SLEEP */
+
+/* setup the essentials required to support clock lookup using ccf */
+void __init samsung_clk_init(struct device_node *np, void __iomem *base,
+               unsigned long nr_clks, unsigned long *rdump,
+               unsigned long nr_rdump, unsigned long *soc_rdump,
+               unsigned long nr_soc_rdump)
+{
+       reg_base = base;
+
+#ifdef CONFIG_PM_SLEEP
+       if (rdump && nr_rdump) {
+               unsigned int idx;
+               reg_dump = kzalloc(sizeof(struct samsung_clk_reg_dump)
+                               * (nr_rdump + nr_soc_rdump), GFP_KERNEL);
+               if (!reg_dump) {
+                       pr_err("%s: memory alloc for register dump failed\n",
+                                       __func__);
+                       return;
+               }
+
+               for (idx = 0; idx < nr_rdump; idx++)
+                       reg_dump[idx].offset = rdump[idx];
+               for (idx = 0; idx < nr_soc_rdump; idx++)
+                       reg_dump[nr_rdump + idx].offset = soc_rdump[idx];
+               nr_reg_dump = nr_rdump + nr_soc_rdump;
+               register_syscore_ops(&samsung_clk_syscore_ops);
+       }
+#endif
+
+       clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL);
+       if (!clk_table)
+               panic("could not allocate clock lookup table\n");
+
+       if (!np)
+               return;
+
+#ifdef CONFIG_OF
+       clk_data.clks = clk_table;
+       clk_data.clk_num = nr_clks;
+       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+#endif
+}
+
+/* add a clock instance to the clock lookup table used for dt based lookup */
+void samsung_clk_add_lookup(struct clk *clk, unsigned int id)
+{
+       if (clk_table && id)
+               clk_table[id] = clk;
+}
+
+/* register a list of aliases */
+void __init samsung_clk_register_alias(struct samsung_clock_alias *list,
+                                       unsigned int nr_clk)
+{
+       struct clk *clk;
+       unsigned int idx, ret;
+
+       if (!clk_table) {
+               pr_err("%s: clock table missing\n", __func__);
+               return;
+       }
+
+       for (idx = 0; idx < nr_clk; idx++, list++) {
+               if (!list->id) {
+                       pr_err("%s: clock id missing for index %d\n", __func__,
+                               idx);
+                       continue;
+               }
+
+               clk = clk_table[list->id];
+               if (!clk) {
+                       pr_err("%s: failed to find clock %d\n", __func__,
+                               list->id);
+                       continue;
+               }
+
+               ret = clk_register_clkdev(clk, list->alias, list->dev_name);
+               if (ret)
+                       pr_err("%s: failed to register lookup %s\n",
+                                       __func__, list->alias);
+       }
+}
+
+/* register a list of fixed clocks */
+void __init samsung_clk_register_fixed_rate(
+               struct samsung_fixed_rate_clock *list, unsigned int nr_clk)
+{
+       struct clk *clk;
+       unsigned int idx, ret;
+
+       for (idx = 0; idx < nr_clk; idx++, list++) {
+               clk = clk_register_fixed_rate(NULL, list->name,
+                       list->parent_name, list->flags, list->fixed_rate);
+               if (IS_ERR(clk)) {
+                       pr_err("%s: failed to register clock %s\n", __func__,
+                               list->name);
+                       continue;
+               }
+
+               samsung_clk_add_lookup(clk, list->id);
+
+               /*
+                * Unconditionally add a clock lookup for the fixed rate clocks.
+                * There are not many of these on any of Samsung platforms.
+                */
+               ret = clk_register_clkdev(clk, list->name, NULL);
+               if (ret)
+                       pr_err("%s: failed to register clock lookup for %s",
+                               __func__, list->name);
+       }
+}
+
+/* register a list of fixed factor clocks */
+void __init samsung_clk_register_fixed_factor(
+               struct samsung_fixed_factor_clock *list, unsigned int nr_clk)
+{
+       struct clk *clk;
+       unsigned int idx;
+
+       for (idx = 0; idx < nr_clk; idx++, list++) {
+               clk = clk_register_fixed_factor(NULL, list->name,
+                       list->parent_name, list->flags, list->mult, list->div);
+               if (IS_ERR(clk)) {
+                       pr_err("%s: failed to register clock %s\n", __func__,
+                               list->name);
+                       continue;
+               }
+
+               samsung_clk_add_lookup(clk, list->id);
+       }
+}
+
+/* register a list of mux clocks */
+void __init samsung_clk_register_mux(struct samsung_mux_clock *list,
+                                       unsigned int nr_clk)
+{
+       struct clk *clk;
+       unsigned int idx, ret;
+
+       for (idx = 0; idx < nr_clk; idx++, list++) {
+               clk = clk_register_mux(NULL, list->name, list->parent_names,
+                       list->num_parents, list->flags, reg_base + list->offset,
+                       list->shift, list->width, list->mux_flags, &lock);
+               if (IS_ERR(clk)) {
+                       pr_err("%s: failed to register clock %s\n", __func__,
+                               list->name);
+                       continue;
+               }
+
+               samsung_clk_add_lookup(clk, list->id);
+
+               /* register a clock lookup only if a clock alias is specified */
+               if (list->alias) {
+                       ret = clk_register_clkdev(clk, list->alias,
+                                               list->dev_name);
+                       if (ret)
+                               pr_err("%s: failed to register lookup %s\n",
+                                               __func__, list->alias);
+               }
+       }
+}
+
+/* register a list of div clocks */
+void __init samsung_clk_register_div(struct samsung_div_clock *list,
+                                       unsigned int nr_clk)
+{
+       struct clk *clk;
+       unsigned int idx, ret;
+
+       for (idx = 0; idx < nr_clk; idx++, list++) {
+               if (list->table)
+                       clk = clk_register_divider_table(NULL, list->name,
+                                       list->parent_name, list->flags,
+                                       reg_base + list->offset, list->shift,
+                                       list->width, list->div_flags,
+                                       list->table, &lock);
+               else
+                       clk = clk_register_divider(NULL, list->name,
+                                       list->parent_name, list->flags,
+                                       reg_base + list->offset, list->shift,
+                                       list->width, list->div_flags, &lock);
+               if (IS_ERR(clk)) {
+                       pr_err("%s: failed to register clock %s\n", __func__,
+                               list->name);
+                       continue;
+               }
+
+               samsung_clk_add_lookup(clk, list->id);
+
+               /* register a clock lookup only if a clock alias is specified */
+               if (list->alias) {
+                       ret = clk_register_clkdev(clk, list->alias,
+                                               list->dev_name);
+                       if (ret)
+                               pr_err("%s: failed to register lookup %s\n",
+                                               __func__, list->alias);
+               }
+       }
+}
+
+/* register a list of gate clocks */
+void __init samsung_clk_register_gate(struct samsung_gate_clock *list,
+                                               unsigned int nr_clk)
+{
+       struct clk *clk;
+       unsigned int idx, ret;
+
+       for (idx = 0; idx < nr_clk; idx++, list++) {
+               clk = clk_register_gate(NULL, list->name, list->parent_name,
+                               list->flags, reg_base + list->offset,
+                               list->bit_idx, list->gate_flags, &lock);
+               if (IS_ERR(clk)) {
+                       pr_err("%s: failed to register clock %s\n", __func__,
+                               list->name);
+                       continue;
+               }
+
+               /* register a clock lookup only if a clock alias is specified */
+               if (list->alias) {
+                       ret = clk_register_clkdev(clk, list->alias,
+                                                       list->dev_name);
+                       if (ret)
+                               pr_err("%s: failed to register lookup %s\n",
+                                       __func__, list->alias);
+               }
+
+               samsung_clk_add_lookup(clk, list->id);
+       }
+}
+
+/*
+ * obtain the clock speed of all external fixed clock sources from device
+ * tree and register it
+ */
+#ifdef CONFIG_OF
+void __init samsung_clk_of_register_fixed_ext(
+                       struct samsung_fixed_rate_clock *fixed_rate_clk,
+                       unsigned int nr_fixed_rate_clk,
+                       struct of_device_id *clk_matches)
+{
+       const struct of_device_id *match;
+       struct device_node *np;
+       u32 freq;
+
+       for_each_matching_node_and_match(np, clk_matches, &match) {
+               if (of_property_read_u32(np, "clock-frequency", &freq))
+                       continue;
+               fixed_rate_clk[(u32)match->data].fixed_rate = freq;
+       }
+       samsung_clk_register_fixed_rate(fixed_rate_clk, nr_fixed_rate_clk);
+}
+#endif
+
+/* utility function to get the rate of a specified clock */
+unsigned long _get_rate(const char *clk_name)
+{
+       struct clk *clk;
+       unsigned long rate;
+
+       clk = clk_get(NULL, clk_name);
+       if (IS_ERR(clk)) {
+               pr_err("%s: could not find clock %s\n", __func__, clk_name);
+               return 0;
+       }
+       rate = clk_get_rate(clk);
+       clk_put(clk);
+       return rate;
+}
diff --git a/drivers/clk/samsung/clk.h b/drivers/clk/samsung/clk.h
new file mode 100644 (file)
index 0000000..e4ad6ea
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2013 Linaro Ltd.
+ * Author: Thomas Abraham <thomas.ab@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.
+ *
+ * Common Clock Framework support for all Samsung platforms
+*/
+
+#ifndef __SAMSUNG_CLK_H
+#define __SAMSUNG_CLK_H
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+/**
+ * struct samsung_clock_alias: information about mux clock
+ * @id: platform specific id of the clock.
+ * @dev_name: name of the device to which this clock belongs.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_clock_alias {
+       unsigned int            id;
+       const char              *dev_name;
+       const char              *alias;
+};
+
+#define ALIAS(_id, dname, a)   \
+       {                                                       \
+               .id             = _id,                          \
+               .dev_name       = dname,                        \
+               .alias          = a,                            \
+       }
+
+/**
+ * struct samsung_fixed_rate_clock: information about fixed-rate clock
+ * @id: platform specific id of the clock.
+ * @name: name of this fixed-rate clock.
+ * @parent_name: optional parent clock name.
+ * @flags: optional fixed-rate clock flags.
+ * @fixed-rate: fixed clock rate of this clock.
+ */
+struct samsung_fixed_rate_clock {
+       unsigned int            id;
+       char                    *name;
+       const char              *parent_name;
+       unsigned long           flags;
+       unsigned long           fixed_rate;
+};
+
+#define FRATE(_id, cname, pname, f, frate)             \
+       {                                               \
+               .id             = _id,                  \
+               .name           = cname,                \
+               .parent_name    = pname,                \
+               .flags          = f,                    \
+               .fixed_rate     = frate,                \
+       }
+
+/*
+ * struct samsung_fixed_factor_clock: information about fixed-factor clock
+ * @id: platform specific id of the clock.
+ * @name: name of this fixed-factor clock.
+ * @parent_name: parent clock name.
+ * @mult: fixed multiplication factor.
+ * @div: fixed division factor.
+ * @flags: optional fixed-factor clock flags.
+ */
+struct samsung_fixed_factor_clock {
+       unsigned int            id;
+       char                    *name;
+       const char              *parent_name;
+       unsigned long           mult;
+       unsigned long           div;
+       unsigned long           flags;
+};
+
+#define FFACTOR(_id, cname, pname, m, d, f)            \
+       {                                               \
+               .id             = _id,                  \
+               .name           = cname,                \
+               .parent_name    = pname,                \
+               .mult           = m,                    \
+               .div            = d,                    \
+               .flags          = f,                    \
+       }
+
+/**
+ * struct samsung_mux_clock: information about mux clock
+ * @id: platform specific id of the clock.
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this mux clock.
+ * @parent_names: array of pointer to parent clock names.
+ * @num_parents: number of parents listed in @parent_names.
+ * @flags: optional flags for basic clock.
+ * @offset: offset of the register for configuring the mux.
+ * @shift: starting bit location of the mux control bit-field in @reg.
+ * @width: width of the mux control bit-field in @reg.
+ * @mux_flags: flags for mux-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_mux_clock {
+       unsigned int            id;
+       const char              *dev_name;
+       const char              *name;
+       const char              **parent_names;
+       u8                      num_parents;
+       unsigned long           flags;
+       unsigned long           offset;
+       u8                      shift;
+       u8                      width;
+       u8                      mux_flags;
+       const char              *alias;
+};
+
+#define __MUX(_id, dname, cname, pnames, o, s, w, f, mf, a)    \
+       {                                                       \
+               .id             = _id,                          \
+               .dev_name       = dname,                        \
+               .name           = cname,                        \
+               .parent_names   = pnames,                       \
+               .num_parents    = ARRAY_SIZE(pnames),           \
+               .flags          = f,                            \
+               .offset         = o,                            \
+               .shift          = s,                            \
+               .width          = w,                            \
+               .mux_flags      = mf,                           \
+               .alias          = a,                            \
+       }
+
+#define MUX(_id, cname, pnames, o, s, w)                       \
+       __MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, NULL)
+
+#define MUX_A(_id, cname, pnames, o, s, w, a)                  \
+       __MUX(_id, NULL, cname, pnames, o, s, w, 0, 0, a)
+
+#define MUX_F(_id, cname, pnames, o, s, w, f, mf)              \
+       __MUX(_id, NULL, cname, pnames, o, s, w, f, mf, NULL)
+
+/**
+ * @id: platform specific id of the clock.
+ * struct samsung_div_clock: information about div clock
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this div clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @offset: offset of the register for configuring the div.
+ * @shift: starting bit location of the div control bit-field in @reg.
+ * @div_flags: flags for div-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_div_clock {
+       unsigned int            id;
+       const char              *dev_name;
+       const char              *name;
+       const char              *parent_name;
+       unsigned long           flags;
+       unsigned long           offset;
+       u8                      shift;
+       u8                      width;
+       u8                      div_flags;
+       const char              *alias;
+       struct clk_div_table    *table;
+};
+
+#define __DIV(_id, dname, cname, pname, o, s, w, f, df, a, t)  \
+       {                                                       \
+               .id             = _id,                          \
+               .dev_name       = dname,                        \
+               .name           = cname,                        \
+               .parent_name    = pname,                        \
+               .flags          = f,                            \
+               .offset         = o,                            \
+               .shift          = s,                            \
+               .width          = w,                            \
+               .div_flags      = df,                           \
+               .alias          = a,                            \
+               .table          = t,                            \
+       }
+
+#define DIV(_id, cname, pname, o, s, w)                                \
+       __DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, NULL)
+
+#define DIV_A(_id, cname, pname, o, s, w, a)                   \
+       __DIV(_id, NULL, cname, pname, o, s, w, 0, 0, a, NULL)
+
+#define DIV_F(_id, cname, pname, o, s, w, f, df)               \
+       __DIV(_id, NULL, cname, pname, o, s, w, f, df, NULL, NULL)
+
+#define DIV_T(_id, cname, pname, o, s, w, t)                   \
+       __DIV(_id, NULL, cname, pname, o, s, w, 0, 0, NULL, t)
+
+/**
+ * struct samsung_gate_clock: information about gate clock
+ * @id: platform specific id of the clock.
+ * @dev_name: name of the device to which this clock belongs.
+ * @name: name of this gate clock.
+ * @parent_name: name of the parent clock.
+ * @flags: optional flags for basic clock.
+ * @offset: offset of the register for configuring the gate.
+ * @bit_idx: bit index of the gate control bit-field in @reg.
+ * @gate_flags: flags for gate-type clock.
+ * @alias: optional clock alias name to be assigned to this clock.
+ */
+struct samsung_gate_clock {
+       unsigned int            id;
+       const char              *dev_name;
+       const char              *name;
+       const char              *parent_name;
+       unsigned long           flags;
+       unsigned long           offset;
+       u8                      bit_idx;
+       u8                      gate_flags;
+       const char              *alias;
+};
+
+#define __GATE(_id, dname, cname, pname, o, b, f, gf, a)       \
+       {                                                       \
+               .id             = _id,                          \
+               .dev_name       = dname,                        \
+               .name           = cname,                        \
+               .parent_name    = pname,                        \
+               .flags          = f,                            \
+               .offset         = o,                            \
+               .bit_idx        = b,                            \
+               .gate_flags     = gf,                           \
+               .alias          = a,                            \
+       }
+
+#define GATE(_id, cname, pname, o, b, f, gf)                   \
+       __GATE(_id, NULL, cname, pname, o, b, f, gf, NULL)
+
+#define GATE_A(_id, cname, pname, o, b, f, gf, a)              \
+       __GATE(_id, NULL, cname, pname, o, b, f, gf, a)
+
+#define GATE_D(_id, dname, cname, pname, o, b, f, gf)          \
+       __GATE(_id, dname, cname, pname, o, b, f, gf, NULL)
+
+#define GATE_DA(_id, dname, cname, pname, o, b, f, gf, a)      \
+       __GATE(_id, dname, cname, pname, o, b, f, gf, a)
+
+#define PNAME(x) static const char *x[] __initdata
+
+/**
+ * struct samsung_clk_reg_dump: register dump of clock controller registers.
+ * @offset: clock register offset from the controller base address.
+ * @value: the value to be register at offset.
+ */
+struct samsung_clk_reg_dump {
+       u32     offset;
+       u32     value;
+};
+
+extern void __init samsung_clk_init(struct device_node *np, void __iomem *base,
+               unsigned long nr_clks, unsigned long *rdump,
+               unsigned long nr_rdump, unsigned long *soc_rdump,
+               unsigned long nr_soc_rdump);
+extern void __init samsung_clk_of_register_fixed_ext(
+               struct samsung_fixed_rate_clock *fixed_rate_clk,
+               unsigned int nr_fixed_rate_clk,
+               struct of_device_id *clk_matches);
+
+extern void samsung_clk_add_lookup(struct clk *clk, unsigned int id);
+
+extern void samsung_clk_register_alias(struct samsung_clock_alias *list,
+               unsigned int nr_clk);
+extern void __init samsung_clk_register_fixed_rate(
+               struct samsung_fixed_rate_clock *clk_list, unsigned int nr_clk);
+extern void __init samsung_clk_register_fixed_factor(
+               struct samsung_fixed_factor_clock *list, unsigned int nr_clk);
+extern void __init samsung_clk_register_mux(struct samsung_mux_clock *clk_list,
+               unsigned int nr_clk);
+extern void __init samsung_clk_register_div(struct samsung_div_clock *clk_list,
+               unsigned int nr_clk);
+extern void __init samsung_clk_register_gate(
+               struct samsung_gate_clock *clk_list, unsigned int nr_clk);
+
+extern unsigned long _get_rate(const char *clk_name);
+
+#endif /* __SAMSUNG_CLK_H */
index 82abea366b785d15f9d138885e240822d29762fb..35e7e2698e100fad879337e1b44823edfddb7a18 100644 (file)
@@ -960,47 +960,47 @@ void __init spear1340_clk_init(void)
                        SPEAR1340_SPDIF_IN_CLK_ENB, 0, &_lock);
        clk_register_clkdev(clk, NULL, "d0100000.spdif-in");
 
-       clk = clk_register_gate(NULL, "acp_clk", "acp_mclk", 0,
+       clk = clk_register_gate(NULL, "acp_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_ACP_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "acp_clk");
 
-       clk = clk_register_gate(NULL, "plgpio_clk", "plgpio_mclk", 0,
+       clk = clk_register_gate(NULL, "plgpio_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PLGPIO_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "e2800000.gpio");
 
-       clk = clk_register_gate(NULL, "video_dec_clk", "video_dec_mclk", 0,
+       clk = clk_register_gate(NULL, "video_dec_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_DEC_CLK_ENB,
                        0, &_lock);
        clk_register_clkdev(clk, NULL, "video_dec");
 
-       clk = clk_register_gate(NULL, "video_enc_clk", "video_enc_mclk", 0,
+       clk = clk_register_gate(NULL, "video_enc_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_ENC_CLK_ENB,
                        0, &_lock);
        clk_register_clkdev(clk, NULL, "video_enc");
 
-       clk = clk_register_gate(NULL, "video_in_clk", "video_in_mclk", 0,
+       clk = clk_register_gate(NULL, "video_in_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_IN_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "spear_vip");
 
-       clk = clk_register_gate(NULL, "cam0_clk", "cam0_mclk", 0,
+       clk = clk_register_gate(NULL, "cam0_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM0_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "d0200000.cam0");
 
-       clk = clk_register_gate(NULL, "cam1_clk", "cam1_mclk", 0,
+       clk = clk_register_gate(NULL, "cam1_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM1_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "d0300000.cam1");
 
-       clk = clk_register_gate(NULL, "cam2_clk", "cam2_mclk", 0,
+       clk = clk_register_gate(NULL, "cam2_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM2_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "d0400000.cam2");
 
-       clk = clk_register_gate(NULL, "cam3_clk", "cam3_mclk", 0,
+       clk = clk_register_gate(NULL, "cam3_clk", "ahb_clk", 0,
                        SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM3_CLK_ENB, 0,
                        &_lock);
        clk_register_clkdev(clk, NULL, "d0500000.cam3");
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
new file mode 100644 (file)
index 0000000..b5bac91
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for sunxi specific clk
+#
+
+obj-y += clk-sunxi.o clk-factors.o
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c
new file mode 100644 (file)
index 0000000..88523f9
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2013 Emilio López <emilio@elopez.com.ar>
+ *
+ * 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.
+ *
+ * Adjustable factor-based clock implementation
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/string.h>
+
+#include <linux/delay.h>
+
+#include "clk-factors.h"
+
+/*
+ * DOC: basic adjustable factor-based clock that cannot gate
+ *
+ * Traits of this clock:
+ * prepare - clk_prepare only ensures that parents are prepared
+ * enable - clk_enable only ensures that parents are enabled
+ * rate - rate is adjustable.
+ *        clk->rate = (parent->rate * N * (K + 1) >> P) / (M + 1)
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+struct clk_factors {
+       struct clk_hw hw;
+       void __iomem *reg;
+       struct clk_factors_config *config;
+       void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p);
+       spinlock_t *lock;
+};
+
+#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
+
+#define SETMASK(len, pos)              (((-1U) >> (31-len))  << (pos))
+#define CLRMASK(len, pos)              (~(SETMASK(len, pos)))
+#define FACTOR_GET(bit, len, reg)      (((reg) & SETMASK(len, bit)) >> (bit))
+
+#define FACTOR_SET(bit, len, reg, val) \
+       (((reg) & CLRMASK(len, bit)) | (val << (bit)))
+
+static unsigned long clk_factors_recalc_rate(struct clk_hw *hw,
+                                            unsigned long parent_rate)
+{
+       u8 n = 1, k = 0, p = 0, m = 0;
+       u32 reg;
+       unsigned long rate;
+       struct clk_factors *factors = to_clk_factors(hw);
+       struct clk_factors_config *config = factors->config;
+
+       /* Fetch the register value */
+       reg = readl(factors->reg);
+
+       /* Get each individual factor if applicable */
+       if (config->nwidth != SUNXI_FACTORS_NOT_APPLICABLE)
+               n = FACTOR_GET(config->nshift, config->nwidth, reg);
+       if (config->kwidth != SUNXI_FACTORS_NOT_APPLICABLE)
+               k = FACTOR_GET(config->kshift, config->kwidth, reg);
+       if (config->mwidth != SUNXI_FACTORS_NOT_APPLICABLE)
+               m = FACTOR_GET(config->mshift, config->mwidth, reg);
+       if (config->pwidth != SUNXI_FACTORS_NOT_APPLICABLE)
+               p = FACTOR_GET(config->pshift, config->pwidth, reg);
+
+       /* Calculate the rate */
+       rate = (parent_rate * n * (k + 1) >> p) / (m + 1);
+
+       return rate;
+}
+
+static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate,
+                                  unsigned long *parent_rate)
+{
+       struct clk_factors *factors = to_clk_factors(hw);
+       factors->get_factors((u32 *)&rate, (u32)*parent_rate,
+                            NULL, NULL, NULL, NULL);
+
+       return rate;
+}
+
+static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate)
+{
+       u8 n, k, m, p;
+       u32 reg;
+       struct clk_factors *factors = to_clk_factors(hw);
+       struct clk_factors_config *config = factors->config;
+       unsigned long flags = 0;
+
+       factors->get_factors((u32 *)&rate, (u32)parent_rate, &n, &k, &m, &p);
+
+       if (factors->lock)
+               spin_lock_irqsave(factors->lock, flags);
+
+       /* Fetch the register value */
+       reg = readl(factors->reg);
+
+       /* Set up the new factors - macros do not do anything if width is 0 */
+       reg = FACTOR_SET(config->nshift, config->nwidth, reg, n);
+       reg = FACTOR_SET(config->kshift, config->kwidth, reg, k);
+       reg = FACTOR_SET(config->mshift, config->mwidth, reg, m);
+       reg = FACTOR_SET(config->pshift, config->pwidth, reg, p);
+
+       /* Apply them now */
+       writel(reg, factors->reg);
+
+       /* delay 500us so pll stabilizes */
+       __delay((rate >> 20) * 500 / 2);
+
+       if (factors->lock)
+               spin_unlock_irqrestore(factors->lock, flags);
+
+       return 0;
+}
+
+static const struct clk_ops clk_factors_ops = {
+       .recalc_rate = clk_factors_recalc_rate,
+       .round_rate = clk_factors_round_rate,
+       .set_rate = clk_factors_set_rate,
+};
+
+/**
+ * clk_register_factors - register a factors clock with
+ * the clock framework
+ * @dev: device registering this clock
+ * @name: name of this clock
+ * @parent_name: name of clock's parent
+ * @flags: framework-specific flags
+ * @reg: register address to adjust factors
+ * @config: shift and width of factors n, k, m and p
+ * @get_factors: function to calculate the factors for a given frequency
+ * @lock: shared register lock for this clock
+ */
+struct clk *clk_register_factors(struct device *dev, const char *name,
+                                const char *parent_name,
+                                unsigned long flags, void __iomem *reg,
+                                struct clk_factors_config *config,
+                                void (*get_factors)(u32 *rate, u32 parent,
+                                                    u8 *n, u8 *k, u8 *m, u8 *p),
+                                spinlock_t *lock)
+{
+       struct clk_factors *factors;
+       struct clk *clk;
+       struct clk_init_data init;
+
+       /* allocate the factors */
+       factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL);
+       if (!factors) {
+               pr_err("%s: could not allocate factors clk\n", __func__);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       init.name = name;
+       init.ops = &clk_factors_ops;
+       init.flags = flags;
+       init.parent_names = (parent_name ? &parent_name : NULL);
+       init.num_parents = (parent_name ? 1 : 0);
+
+       /* struct clk_factors assignments */
+       factors->reg = reg;
+       factors->config = config;
+       factors->lock = lock;
+       factors->hw.init = &init;
+       factors->get_factors = get_factors;
+
+       /* register the clock */
+       clk = clk_register(dev, &factors->hw);
+
+       if (IS_ERR(clk))
+               kfree(factors);
+
+       return clk;
+}
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h
new file mode 100644 (file)
index 0000000..f49851c
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef __MACH_SUNXI_CLK_FACTORS_H
+#define __MACH_SUNXI_CLK_FACTORS_H
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+
+#define SUNXI_FACTORS_NOT_APPLICABLE   (0)
+
+struct clk_factors_config {
+       u8 nshift;
+       u8 nwidth;
+       u8 kshift;
+       u8 kwidth;
+       u8 mshift;
+       u8 mwidth;
+       u8 pshift;
+       u8 pwidth;
+};
+
+struct clk *clk_register_factors(struct device *dev, const char *name,
+                                const char *parent_name,
+                                unsigned long flags, void __iomem *reg,
+                                struct clk_factors_config *config,
+                                void (*get_factors) (u32 *rate, u32 parent_rate,
+                                                     u8 *n, u8 *k, u8 *m, u8 *p),
+                                spinlock_t *lock);
+#endif
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c
new file mode 100644 (file)
index 0000000..d528a24
--- /dev/null
@@ -0,0 +1,362 @@
+/*
+ * Copyright 2013 Emilio López
+ *
+ * Emilio López <emilio@elopez.com.ar>
+ *
+ * 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/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/clk/sunxi.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#include "clk-factors.h"
+
+static DEFINE_SPINLOCK(clk_lock);
+
+/**
+ * sunxi_osc_clk_setup() - Setup function for gatable oscillator
+ */
+
+#define SUNXI_OSC24M_GATE      0
+
+static void __init sunxi_osc_clk_setup(struct device_node *node)
+{
+       struct clk *clk;
+       const char *clk_name = node->name;
+       const char *parent;
+       void *reg;
+
+       reg = of_iomap(node, 0);
+
+       parent = of_clk_get_parent_name(node, 0);
+
+       clk = clk_register_gate(NULL, clk_name, parent, CLK_IGNORE_UNUSED,
+                               reg, SUNXI_OSC24M_GATE, 0, &clk_lock);
+
+       if (clk) {
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+               clk_register_clkdev(clk, clk_name, NULL);
+       }
+}
+
+
+
+/**
+ * sunxi_get_pll1_factors() - calculates n, k, m, p factors for PLL1
+ * PLL1 rate is calculated as follows
+ * rate = (parent_rate * n * (k + 1) >> p) / (m + 1);
+ * parent_rate is always 24Mhz
+ */
+
+static void sunxi_get_pll1_factors(u32 *freq, u32 parent_rate,
+                                  u8 *n, u8 *k, u8 *m, u8 *p)
+{
+       u8 div;
+
+       /* Normalize value to a 6M multiple */
+       div = *freq / 6000000;
+       *freq = 6000000 * div;
+
+       /* we were called to round the frequency, we can now return */
+       if (n == NULL)
+               return;
+
+       /* m is always zero for pll1 */
+       *m = 0;
+
+       /* k is 1 only on these cases */
+       if (*freq >= 768000000 || *freq == 42000000 || *freq == 54000000)
+               *k = 1;
+       else
+               *k = 0;
+
+       /* p will be 3 for divs under 10 */
+       if (div < 10)
+               *p = 3;
+
+       /* p will be 2 for divs between 10 - 20 and odd divs under 32 */
+       else if (div < 20 || (div < 32 && (div & 1)))
+               *p = 2;
+
+       /* p will be 1 for even divs under 32, divs under 40 and odd pairs
+        * of divs between 40-62 */
+       else if (div < 40 || (div < 64 && (div & 2)))
+               *p = 1;
+
+       /* any other entries have p = 0 */
+       else
+               *p = 0;
+
+       /* calculate a suitable n based on k and p */
+       div <<= *p;
+       div /= (*k + 1);
+       *n = div / 4;
+}
+
+
+
+/**
+ * sunxi_get_apb1_factors() - calculates m, p factors for APB1
+ * APB1 rate is calculated as follows
+ * rate = (parent_rate >> p) / (m + 1);
+ */
+
+static void sunxi_get_apb1_factors(u32 *freq, u32 parent_rate,
+                                  u8 *n, u8 *k, u8 *m, u8 *p)
+{
+       u8 calcm, calcp;
+
+       if (parent_rate < *freq)
+               *freq = parent_rate;
+
+       parent_rate = (parent_rate + (*freq - 1)) / *freq;
+
+       /* Invalid rate! */
+       if (parent_rate > 32)
+               return;
+
+       if (parent_rate <= 4)
+               calcp = 0;
+       else if (parent_rate <= 8)
+               calcp = 1;
+       else if (parent_rate <= 16)
+               calcp = 2;
+       else
+               calcp = 3;
+
+       calcm = (parent_rate >> calcp) - 1;
+
+       *freq = (parent_rate >> calcp) / (calcm + 1);
+
+       /* we were called to round the frequency, we can now return */
+       if (n == NULL)
+               return;
+
+       *m = calcm;
+       *p = calcp;
+}
+
+
+
+/**
+ * sunxi_factors_clk_setup() - Setup function for factor clocks
+ */
+
+struct factors_data {
+       struct clk_factors_config *table;
+       void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p);
+};
+
+static struct clk_factors_config pll1_config = {
+       .nshift = 8,
+       .nwidth = 5,
+       .kshift = 4,
+       .kwidth = 2,
+       .mshift = 0,
+       .mwidth = 2,
+       .pshift = 16,
+       .pwidth = 2,
+};
+
+static struct clk_factors_config apb1_config = {
+       .mshift = 0,
+       .mwidth = 5,
+       .pshift = 16,
+       .pwidth = 2,
+};
+
+static const __initconst struct factors_data pll1_data = {
+       .table = &pll1_config,
+       .getter = sunxi_get_pll1_factors,
+};
+
+static const __initconst struct factors_data apb1_data = {
+       .table = &apb1_config,
+       .getter = sunxi_get_apb1_factors,
+};
+
+static void __init sunxi_factors_clk_setup(struct device_node *node,
+                                          struct factors_data *data)
+{
+       struct clk *clk;
+       const char *clk_name = node->name;
+       const char *parent;
+       void *reg;
+
+       reg = of_iomap(node, 0);
+
+       parent = of_clk_get_parent_name(node, 0);
+
+       clk = clk_register_factors(NULL, clk_name, parent, CLK_IGNORE_UNUSED,
+                                  reg, data->table, data->getter, &clk_lock);
+
+       if (clk) {
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+               clk_register_clkdev(clk, clk_name, NULL);
+       }
+}
+
+
+
+/**
+ * sunxi_mux_clk_setup() - Setup function for muxes
+ */
+
+#define SUNXI_MUX_GATE_WIDTH   2
+
+struct mux_data {
+       u8 shift;
+};
+
+static const __initconst struct mux_data cpu_data = {
+       .shift = 16,
+};
+
+static const __initconst struct mux_data apb1_mux_data = {
+       .shift = 24,
+};
+
+static void __init sunxi_mux_clk_setup(struct device_node *node,
+                                      struct mux_data *data)
+{
+       struct clk *clk;
+       const char *clk_name = node->name;
+       const char **parents = kmalloc(sizeof(char *) * 5, GFP_KERNEL);
+       void *reg;
+       int i = 0;
+
+       reg = of_iomap(node, 0);
+
+       while (i < 5 && (parents[i] = of_clk_get_parent_name(node, i)) != NULL)
+               i++;
+
+       clk = clk_register_mux(NULL, clk_name, parents, i, 0, reg,
+                              data->shift, SUNXI_MUX_GATE_WIDTH,
+                              0, &clk_lock);
+
+       if (clk) {
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+               clk_register_clkdev(clk, clk_name, NULL);
+       }
+}
+
+
+
+/**
+ * sunxi_divider_clk_setup() - Setup function for simple divider clocks
+ */
+
+#define SUNXI_DIVISOR_WIDTH    2
+
+struct div_data {
+       u8 shift;
+       u8 pow;
+};
+
+static const __initconst struct div_data axi_data = {
+       .shift = 0,
+       .pow = 0,
+};
+
+static const __initconst struct div_data ahb_data = {
+       .shift = 4,
+       .pow = 1,
+};
+
+static const __initconst struct div_data apb0_data = {
+       .shift = 8,
+       .pow = 1,
+};
+
+static void __init sunxi_divider_clk_setup(struct device_node *node,
+                                          struct div_data *data)
+{
+       struct clk *clk;
+       const char *clk_name = node->name;
+       const char *clk_parent;
+       void *reg;
+
+       reg = of_iomap(node, 0);
+
+       clk_parent = of_clk_get_parent_name(node, 0);
+
+       clk = clk_register_divider(NULL, clk_name, clk_parent, 0,
+                                  reg, data->shift, SUNXI_DIVISOR_WIDTH,
+                                  data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0,
+                                  &clk_lock);
+       if (clk) {
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+               clk_register_clkdev(clk, clk_name, NULL);
+       }
+}
+
+
+/* Matches for of_clk_init */
+static const __initconst struct of_device_id clk_match[] = {
+       {.compatible = "fixed-clock", .data = of_fixed_clk_setup,},
+       {.compatible = "allwinner,sun4i-osc-clk", .data = sunxi_osc_clk_setup,},
+       {}
+};
+
+/* Matches for factors clocks */
+static const __initconst struct of_device_id clk_factors_match[] = {
+       {.compatible = "allwinner,sun4i-pll1-clk", .data = &pll1_data,},
+       {.compatible = "allwinner,sun4i-apb1-clk", .data = &apb1_data,},
+       {}
+};
+
+/* Matches for divider clocks */
+static const __initconst struct of_device_id clk_div_match[] = {
+       {.compatible = "allwinner,sun4i-axi-clk", .data = &axi_data,},
+       {.compatible = "allwinner,sun4i-ahb-clk", .data = &ahb_data,},
+       {.compatible = "allwinner,sun4i-apb0-clk", .data = &apb0_data,},
+       {}
+};
+
+/* Matches for mux clocks */
+static const __initconst struct of_device_id clk_mux_match[] = {
+       {.compatible = "allwinner,sun4i-cpu-clk", .data = &cpu_data,},
+       {.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &apb1_mux_data,},
+       {}
+};
+
+static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_match,
+                                             void *function)
+{
+       struct device_node *np;
+       const struct div_data *data;
+       const struct of_device_id *match;
+       void (*setup_function)(struct device_node *, const void *) = function;
+
+       for_each_matching_node(np, clk_match) {
+               match = of_match_node(clk_match, np);
+               data = match->data;
+               setup_function(np, data);
+       }
+}
+
+void __init sunxi_init_clocks(void)
+{
+       /* Register all the simple sunxi clocks on DT */
+       of_clk_init(clk_match);
+
+       /* Register factor clocks */
+       of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup);
+
+       /* Register divider clocks */
+       of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup);
+
+       /* Register mux clocks */
+       of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup);
+}
index 2b41b0f4f731b577df9bac3b147865a06657bd2c..f49fac2d193acf662856fc74e5acd1d668b2cc84 100644 (file)
@@ -9,3 +9,4 @@ obj-y                                   += clk-super.o
 
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clk-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)         += clk-tegra30.o
+obj-$(CONFIG_ARCH_TEGRA_114_SOC)       += clk-tegra114.o
index 6dd533251e7b103255e8edb2bb0cc87cfa60ca97..bafee9895a247905d56ebe94c6a972eb7527c1c8 100644 (file)
@@ -41,7 +41,9 @@ static DEFINE_SPINLOCK(periph_ref_lock);
 #define write_rst_clr(val, gate) \
        writel_relaxed(val, gate->clk_base + (gate->regs->rst_clr_reg))
 
-#define periph_clk_to_bit(periph) (1 << (gate->clk_num % 32))
+#define periph_clk_to_bit(gate) (1 << (gate->clk_num % 32))
+
+#define LVL2_CLK_GATE_OVRE 0x554
 
 /* Peripheral gate clock ops */
 static int clk_periph_is_enabled(struct clk_hw *hw)
@@ -83,6 +85,13 @@ static int clk_periph_enable(struct clk_hw *hw)
                }
        }
 
+       if (gate->flags & TEGRA_PERIPH_WAR_1005168) {
+               writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
+               writel_relaxed(BIT(22), gate->clk_base + LVL2_CLK_GATE_OVRE);
+               udelay(1);
+               writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE);
+       }
+
        spin_unlock_irqrestore(&periph_ref_lock, flags);
 
        return 0;
index 788486e6331a0f10fa99984f8f1b0581dfb90635..b2309d37a9637b70cfc823ea3ada7dc32d99c88a 100644 (file)
@@ -16,6 +16,7 @@
 
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/export.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 
@@ -128,6 +129,7 @@ void tegra_periph_reset_deassert(struct clk *c)
 
        tegra_periph_reset(gate, 0);
 }
+EXPORT_SYMBOL(tegra_periph_reset_deassert);
 
 void tegra_periph_reset_assert(struct clk *c)
 {
@@ -147,6 +149,7 @@ void tegra_periph_reset_assert(struct clk *c)
 
        tegra_periph_reset(gate, 1);
 }
+EXPORT_SYMBOL(tegra_periph_reset_assert);
 
 const struct clk_ops tegra_clk_periph_ops = {
        .get_parent = clk_periph_get_parent,
@@ -170,14 +173,15 @@ const struct clk_ops tegra_clk_periph_nodiv_ops = {
 static struct clk *_tegra_clk_register_periph(const char *name,
                        const char **parent_names, int num_parents,
                        struct tegra_clk_periph *periph,
-                       void __iomem *clk_base, u32 offset, bool div)
+                       void __iomem *clk_base, u32 offset, bool div,
+                       unsigned long flags)
 {
        struct clk *clk;
        struct clk_init_data init;
 
        init.name = name;
        init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops;
-       init.flags = div ? 0 : CLK_SET_RATE_PARENT;
+       init.flags = flags;
        init.parent_names = parent_names;
        init.num_parents = num_parents;
 
@@ -202,10 +206,10 @@ static struct clk *_tegra_clk_register_periph(const char *name,
 struct clk *tegra_clk_register_periph(const char *name,
                const char **parent_names, int num_parents,
                struct tegra_clk_periph *periph, void __iomem *clk_base,
-               u32 offset)
+               u32 offset, unsigned long flags)
 {
        return _tegra_clk_register_periph(name, parent_names, num_parents,
-                       periph, clk_base, offset, true);
+                       periph, clk_base, offset, true, flags);
 }
 
 struct clk *tegra_clk_register_periph_nodiv(const char *name,
@@ -214,5 +218,5 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name,
                u32 offset)
 {
        return _tegra_clk_register_periph(name, parent_names, num_parents,
-                       periph, clk_base, offset, false);
+                       periph, clk_base, offset, false, CLK_SET_RATE_PARENT);
 }
index 165f24734c1b7342a41e705a3505d520958bb345..17c2cc086eb4e997034d6f2348956cf6f856582b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2012, 2013, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
 #define PLLE_SS_CTRL 0x68
 #define PLLE_SS_DISABLE (7 << 10)
 
+#define PLLE_AUX_PLLP_SEL      BIT(2)
+#define PLLE_AUX_ENABLE_SWCTL  BIT(4)
+#define PLLE_AUX_SEQ_ENABLE    BIT(24)
+#define PLLE_AUX_PLLRE_SEL     BIT(28)
+
+#define PLLE_MISC_PLLE_PTS     BIT(8)
+#define PLLE_MISC_IDDQ_SW_VALUE        BIT(13)
+#define PLLE_MISC_IDDQ_SW_CTRL BIT(14)
+#define PLLE_MISC_VREG_BG_CTRL_SHIFT   4
+#define PLLE_MISC_VREG_BG_CTRL_MASK    (3 << PLLE_MISC_VREG_BG_CTRL_SHIFT)
+#define PLLE_MISC_VREG_CTRL_SHIFT      2
+#define PLLE_MISC_VREG_CTRL_MASK       (2 << PLLE_MISC_VREG_CTRL_SHIFT)
+
+#define PLLCX_MISC_STROBE      BIT(31)
+#define PLLCX_MISC_RESET       BIT(30)
+#define PLLCX_MISC_SDM_DIV_SHIFT 28
+#define PLLCX_MISC_SDM_DIV_MASK (0x3 << PLLCX_MISC_SDM_DIV_SHIFT)
+#define PLLCX_MISC_FILT_DIV_SHIFT 26
+#define PLLCX_MISC_FILT_DIV_MASK (0x3 << PLLCX_MISC_FILT_DIV_SHIFT)
+#define PLLCX_MISC_ALPHA_SHIFT 18
+#define PLLCX_MISC_DIV_LOW_RANGE \
+               ((0x1 << PLLCX_MISC_SDM_DIV_SHIFT) | \
+               (0x1 << PLLCX_MISC_FILT_DIV_SHIFT))
+#define PLLCX_MISC_DIV_HIGH_RANGE \
+               ((0x2 << PLLCX_MISC_SDM_DIV_SHIFT) | \
+               (0x2 << PLLCX_MISC_FILT_DIV_SHIFT))
+#define PLLCX_MISC_COEF_LOW_RANGE \
+               ((0x14 << PLLCX_MISC_KA_SHIFT) | (0x38 << PLLCX_MISC_KB_SHIFT))
+#define PLLCX_MISC_KA_SHIFT 2
+#define PLLCX_MISC_KB_SHIFT 9
+#define PLLCX_MISC_DEFAULT (PLLCX_MISC_COEF_LOW_RANGE | \
+                           (0x19 << PLLCX_MISC_ALPHA_SHIFT) | \
+                           PLLCX_MISC_DIV_LOW_RANGE | \
+                           PLLCX_MISC_RESET)
+#define PLLCX_MISC1_DEFAULT 0x000d2308
+#define PLLCX_MISC2_DEFAULT 0x30211200
+#define PLLCX_MISC3_DEFAULT 0x200
+
+#define PMC_PLLM_WB0_OVERRIDE  0x1dc
+#define PMC_PLLM_WB0_OVERRIDE_2        0x2b0
+#define PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK BIT(27)
+
 #define PMC_SATA_PWRGT 0x1ac
 #define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)
 #define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4)
 #define divn_max(p) (divn_mask(p))
 #define divp_max(p) (1 << (divp_mask(p)))
 
+
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+/* PLLXC has 4-bit PDIV, but entry 15 is not allowed in h/w */
+#define PLLXC_PDIV_MAX                 14
+
+/* non-monotonic mapping below is not a typo */
+static u8 pllxc_p[PLLXC_PDIV_MAX + 1] = {
+       /* PDIV: 0, 1, 2, 3, 4, 5, 6,  7,  8,  9, 10, 11, 12, 13, 14 */
+       /* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32
+};
+
+#define PLLCX_PDIV_MAX 7
+static u8 pllcx_p[PLLCX_PDIV_MAX + 1] = {
+       /* PDIV: 0, 1, 2, 3, 4, 5,  6,  7 */
+       /* p: */ 1, 2, 3, 4, 6, 8, 12, 16
+};
+#endif
+
 static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
 {
        u32 val;
@@ -108,25 +168,36 @@ static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
        if (!(pll->flags & TEGRA_PLL_USE_LOCK))
                return;
 
+       if (!(pll->flags & TEGRA_PLL_HAS_LOCK_ENABLE))
+               return;
+
        val = pll_readl_misc(pll);
        val |= BIT(pll->params->lock_enable_bit_idx);
        pll_writel_misc(val, pll);
 }
 
-static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll,
-                                void __iomem *lock_addr, u32 lock_bit_idx)
+static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll)
 {
        int i;
-       u32 val;
+       u32 val, lock_mask;
+       void __iomem *lock_addr;
 
        if (!(pll->flags & TEGRA_PLL_USE_LOCK)) {
                udelay(pll->params->lock_delay);
                return 0;
        }
 
+       lock_addr = pll->clk_base;
+       if (pll->flags & TEGRA_PLL_LOCK_MISC)
+               lock_addr += pll->params->misc_reg;
+       else
+               lock_addr += pll->params->base_reg;
+
+       lock_mask = pll->params->lock_mask;
+
        for (i = 0; i < pll->params->lock_delay; i++) {
                val = readl_relaxed(lock_addr);
-               if (val & BIT(lock_bit_idx)) {
+               if ((val & lock_mask) == lock_mask) {
                        udelay(PLL_POST_LOCK_DELAY);
                        return 0;
                }
@@ -155,7 +226,7 @@ static int clk_pll_is_enabled(struct clk_hw *hw)
        return val & PLL_BASE_ENABLE ? 1 : 0;
 }
 
-static int _clk_pll_enable(struct clk_hw *hw)
+static void _clk_pll_enable(struct clk_hw *hw)
 {
        struct tegra_clk_pll *pll = to_clk_pll(hw);
        u32 val;
@@ -163,7 +234,8 @@ static int _clk_pll_enable(struct clk_hw *hw)
        clk_pll_enable_lock(pll);
 
        val = pll_readl_base(pll);
-       val &= ~PLL_BASE_BYPASS;
+       if (pll->flags & TEGRA_PLL_BYPASS)
+               val &= ~PLL_BASE_BYPASS;
        val |= PLL_BASE_ENABLE;
        pll_writel_base(val, pll);
 
@@ -172,11 +244,6 @@ static int _clk_pll_enable(struct clk_hw *hw)
                val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
                writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
        }
-
-       clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->base_reg,
-                             pll->params->lock_bit_idx);
-
-       return 0;
 }
 
 static void _clk_pll_disable(struct clk_hw *hw)
@@ -185,7 +252,9 @@ static void _clk_pll_disable(struct clk_hw *hw)
        u32 val;
 
        val = pll_readl_base(pll);
-       val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
+       if (pll->flags & TEGRA_PLL_BYPASS)
+               val &= ~PLL_BASE_BYPASS;
+       val &= ~PLL_BASE_ENABLE;
        pll_writel_base(val, pll);
 
        if (pll->flags & TEGRA_PLLM) {
@@ -204,7 +273,9 @@ static int clk_pll_enable(struct clk_hw *hw)
        if (pll->lock)
                spin_lock_irqsave(pll->lock, flags);
 
-       ret = _clk_pll_enable(hw);
+       _clk_pll_enable(hw);
+
+       ret = clk_pll_wait_for_lock(pll);
 
        if (pll->lock)
                spin_unlock_irqrestore(pll->lock, flags);
@@ -241,8 +312,6 @@ static int _get_table_rate(struct clk_hw *hw,
        if (sel->input_rate == 0)
                return -EINVAL;
 
-       BUG_ON(sel->p < 1);
-
        cfg->input_rate = sel->input_rate;
        cfg->output_rate = sel->output_rate;
        cfg->m = sel->m;
@@ -257,6 +326,7 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
                      unsigned long rate, unsigned long parent_rate)
 {
        struct tegra_clk_pll *pll = to_clk_pll(hw);
+       struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
        unsigned long cfreq;
        u32 p_div = 0;
 
@@ -290,88 +360,119 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
             cfg->output_rate <<= 1)
                p_div++;
 
-       cfg->p = 1 << p_div;
        cfg->m = parent_rate / cfreq;
        cfg->n = cfg->output_rate / cfreq;
        cfg->cpcon = OUT_OF_TABLE_CPCON;
 
        if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) ||
-           cfg->p > divp_max(pll) || cfg->output_rate > pll->params->vco_max) {
+           (1 << p_div) > divp_max(pll)
+           || cfg->output_rate > pll->params->vco_max) {
                pr_err("%s: Failed to set %s rate %lu\n",
                       __func__, __clk_get_name(hw->clk), rate);
                return -EINVAL;
        }
 
+       if (p_tohw) {
+               p_div = 1 << p_div;
+               while (p_tohw->pdiv) {
+                       if (p_div <= p_tohw->pdiv) {
+                               cfg->p = p_tohw->hw_val;
+                               break;
+                       }
+                       p_tohw++;
+               }
+               if (!p_tohw->pdiv)
+                       return -EINVAL;
+       } else
+               cfg->p = p_div;
+
        return 0;
 }
 
-static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
-                       unsigned long rate)
+static void _update_pll_mnp(struct tegra_clk_pll *pll,
+                           struct tegra_clk_pll_freq_table *cfg)
 {
-       struct tegra_clk_pll *pll = to_clk_pll(hw);
-       unsigned long flags = 0;
-       u32 divp, val, old_base;
-       int state;
-
-       divp = __ffs(cfg->p);
-
-       if (pll->flags & TEGRA_PLLU)
-               divp ^= 1;
+       u32 val;
 
-       if (pll->lock)
-               spin_lock_irqsave(pll->lock, flags);
+       val = pll_readl_base(pll);
 
-       old_base = val = pll_readl_base(pll);
        val &= ~((divm_mask(pll) << pll->divm_shift) |
                 (divn_mask(pll) << pll->divn_shift) |
                 (divp_mask(pll) << pll->divp_shift));
        val |= ((cfg->m << pll->divm_shift) |
                (cfg->n << pll->divn_shift) |
-               (divp << pll->divp_shift));
-       if (val == old_base) {
-               if (pll->lock)
-                       spin_unlock_irqrestore(pll->lock, flags);
-               return 0;
+               (cfg->p << pll->divp_shift));
+
+       pll_writel_base(val, pll);
+}
+
+static void _get_pll_mnp(struct tegra_clk_pll *pll,
+                        struct tegra_clk_pll_freq_table *cfg)
+{
+       u32 val;
+
+       val = pll_readl_base(pll);
+
+       cfg->m = (val >> pll->divm_shift) & (divm_mask(pll));
+       cfg->n = (val >> pll->divn_shift) & (divn_mask(pll));
+       cfg->p = (val >> pll->divp_shift) & (divp_mask(pll));
+}
+
+static void _update_pll_cpcon(struct tegra_clk_pll *pll,
+                             struct tegra_clk_pll_freq_table *cfg,
+                             unsigned long rate)
+{
+       u32 val;
+
+       val = pll_readl_misc(pll);
+
+       val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT);
+       val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT;
+
+       if (pll->flags & TEGRA_PLL_SET_LFCON) {
+               val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT);
+               if (cfg->n >= PLLDU_LFCON_SET_DIVN)
+                       val |= 1 << PLL_MISC_LFCON_SHIFT;
+       } else if (pll->flags & TEGRA_PLL_SET_DCCON) {
+               val &= ~(1 << PLL_MISC_DCCON_SHIFT);
+               if (rate >= (pll->params->vco_max >> 1))
+                       val |= 1 << PLL_MISC_DCCON_SHIFT;
        }
 
+       pll_writel_misc(val, pll);
+}
+
+static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
+                       unsigned long rate)
+{
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       int state, ret = 0;
+
        state = clk_pll_is_enabled(hw);
 
-       if (state) {
+       if (state)
                _clk_pll_disable(hw);
-               val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
-       }
-       pll_writel_base(val, pll);
 
-       if (pll->flags & TEGRA_PLL_HAS_CPCON) {
-               val = pll_readl_misc(pll);
-               val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT);
-               val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT;
-               if (pll->flags & TEGRA_PLL_SET_LFCON) {
-                       val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT);
-                       if (cfg->n >= PLLDU_LFCON_SET_DIVN)
-                               val |= 0x1 << PLL_MISC_LFCON_SHIFT;
-               } else if (pll->flags & TEGRA_PLL_SET_DCCON) {
-                       val &= ~(0x1 << PLL_MISC_DCCON_SHIFT);
-                       if (rate >= (pll->params->vco_max >> 1))
-                               val |= 0x1 << PLL_MISC_DCCON_SHIFT;
-               }
-               pll_writel_misc(val, pll);
-       }
+       _update_pll_mnp(pll, cfg);
 
-       if (pll->lock)
-               spin_unlock_irqrestore(pll->lock, flags);
+       if (pll->flags & TEGRA_PLL_HAS_CPCON)
+               _update_pll_cpcon(pll, cfg, rate);
 
-       if (state)
-               clk_pll_enable(hw);
+       if (state) {
+               _clk_pll_enable(hw);
+               ret = clk_pll_wait_for_lock(pll);
+       }
 
-       return 0;
+       return ret;
 }
 
 static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
                        unsigned long parent_rate)
 {
        struct tegra_clk_pll *pll = to_clk_pll(hw);
-       struct tegra_clk_pll_freq_table cfg;
+       struct tegra_clk_pll_freq_table cfg, old_cfg;
+       unsigned long flags = 0;
+       int ret = 0;
 
        if (pll->flags & TEGRA_PLL_FIXED) {
                if (rate != pll->fixed_rate) {
@@ -387,7 +488,18 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
            _calc_rate(hw, &cfg, rate, parent_rate))
                return -EINVAL;
 
-       return _program_pll(hw, &cfg, rate);
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       _get_pll_mnp(pll, &old_cfg);
+
+       if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_cfg.p != cfg.p)
+               ret = _program_pll(hw, &cfg, rate);
+
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+
+       return ret;
 }
 
 static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -409,7 +521,7 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
                return -EINVAL;
 
        output_rate *= cfg.n;
-       do_div(output_rate, cfg.m * cfg.p);
+       do_div(output_rate, cfg.m * (1 << cfg.p));
 
        return output_rate;
 }
@@ -418,11 +530,15 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
                                         unsigned long parent_rate)
 {
        struct tegra_clk_pll *pll = to_clk_pll(hw);
-       u32 val = pll_readl_base(pll);
-       u32 divn = 0, divm = 0, divp = 0;
+       struct tegra_clk_pll_freq_table cfg;
+       struct pdiv_map *p_tohw = pll->params->pdiv_tohw;
+       u32 val;
        u64 rate = parent_rate;
+       int pdiv;
+
+       val = pll_readl_base(pll);
 
-       if (val & PLL_BASE_BYPASS)
+       if ((pll->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS))
                return parent_rate;
 
        if ((pll->flags & TEGRA_PLL_FIXED) && !(val & PLL_BASE_OVERRIDE)) {
@@ -435,16 +551,29 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
                return pll->fixed_rate;
        }
 
-       divp = (val >> pll->divp_shift) & (divp_mask(pll));
-       if (pll->flags & TEGRA_PLLU)
-               divp ^= 1;
+       _get_pll_mnp(pll, &cfg);
 
-       divn = (val >> pll->divn_shift) & (divn_mask(pll));
-       divm = (val >> pll->divm_shift) & (divm_mask(pll));
-       divm *= (1 << divp);
+       if (p_tohw) {
+               while (p_tohw->pdiv) {
+                       if (cfg.p == p_tohw->hw_val) {
+                               pdiv = p_tohw->pdiv;
+                               break;
+                       }
+                       p_tohw++;
+               }
+
+               if (!p_tohw->pdiv) {
+                       WARN_ON(1);
+                       pdiv = 1;
+               }
+       } else
+               pdiv = 1 << cfg.p;
+
+       cfg.m *= pdiv;
+
+       rate *= cfg.n;
+       do_div(rate, cfg.m);
 
-       rate *= divn;
-       do_div(rate, divm);
        return rate;
 }
 
@@ -538,8 +667,8 @@ static int clk_plle_enable(struct clk_hw *hw)
        val |= (PLL_BASE_BYPASS | PLL_BASE_ENABLE);
        pll_writel_base(val, pll);
 
-       clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->misc_reg,
-                             pll->params->lock_bit_idx);
+       clk_pll_wait_for_lock(pll);
+
        return 0;
 }
 
@@ -577,72 +706,877 @@ const struct clk_ops tegra_clk_plle_ops = {
        .enable = clk_plle_enable,
 };
 
-static struct clk *_tegra_clk_register_pll(const char *name,
-               const char *parent_name, void __iomem *clk_base,
-               void __iomem *pmc, unsigned long flags,
-               unsigned long fixed_rate,
-               struct tegra_clk_pll_params *pll_params, u8 pll_flags,
-               struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock,
-               const struct clk_ops *ops)
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+
+static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params,
+                          unsigned long parent_rate)
 {
-       struct tegra_clk_pll *pll;
-       struct clk *clk;
-       struct clk_init_data init;
+       if (parent_rate > pll_params->cf_max)
+               return 2;
+       else
+               return 1;
+}
 
-       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
-       if (!pll)
-               return ERR_PTR(-ENOMEM);
+static int clk_pll_iddq_enable(struct clk_hw *hw)
+{
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       unsigned long flags = 0;
 
-       init.name = name;
-       init.ops = ops;
-       init.flags = flags;
-       init.parent_names = (parent_name ? &parent_name : NULL);
-       init.num_parents = (parent_name ? 1 : 0);
+       u32 val;
+       int ret;
 
-       pll->clk_base = clk_base;
-       pll->pmc = pmc;
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
 
-       pll->freq_table = freq_table;
-       pll->params = pll_params;
-       pll->fixed_rate = fixed_rate;
-       pll->flags = pll_flags;
-       pll->lock = lock;
+       val = pll_readl(pll->params->iddq_reg, pll);
+       val &= ~BIT(pll->params->iddq_bit_idx);
+       pll_writel(val, pll->params->iddq_reg, pll);
+       udelay(2);
 
-       pll->divp_shift = PLL_BASE_DIVP_SHIFT;
-       pll->divp_width = PLL_BASE_DIVP_WIDTH;
-       pll->divn_shift = PLL_BASE_DIVN_SHIFT;
-       pll->divn_width = PLL_BASE_DIVN_WIDTH;
-       pll->divm_shift = PLL_BASE_DIVM_SHIFT;
-       pll->divm_width = PLL_BASE_DIVM_WIDTH;
+       _clk_pll_enable(hw);
 
-       /* Data in .init is copied by clk_register(), so stack variable OK */
-       pll->hw.init = &init;
+       ret = clk_pll_wait_for_lock(pll);
 
-       clk = clk_register(NULL, &pll->hw);
-       if (IS_ERR(clk))
-               kfree(pll);
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
 
-       return clk;
+       return 0;
 }
 
-struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
-               void __iomem *clk_base, void __iomem *pmc,
-               unsigned long flags, unsigned long fixed_rate,
-               struct tegra_clk_pll_params *pll_params, u8 pll_flags,
-               struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
+static void clk_pll_iddq_disable(struct clk_hw *hw)
 {
-       return _tegra_clk_register_pll(name, parent_name, clk_base, pmc,
-                       flags, fixed_rate, pll_params, pll_flags, freq_table,
-                       lock, &tegra_clk_pll_ops);
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       unsigned long flags = 0;
+       u32 val;
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       _clk_pll_disable(hw);
+
+       val = pll_readl(pll->params->iddq_reg, pll);
+       val |= BIT(pll->params->iddq_bit_idx);
+       pll_writel(val, pll->params->iddq_reg, pll);
+       udelay(2);
+
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
 }
 
-struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
-               void __iomem *clk_base, void __iomem *pmc,
-               unsigned long flags, unsigned long fixed_rate,
-               struct tegra_clk_pll_params *pll_params, u8 pll_flags,
-               struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
+static int _calc_dynamic_ramp_rate(struct clk_hw *hw,
+                               struct tegra_clk_pll_freq_table *cfg,
+                               unsigned long rate, unsigned long parent_rate)
+{
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       unsigned int p;
+
+       if (!rate)
+               return -EINVAL;
+
+       p = DIV_ROUND_UP(pll->params->vco_min, rate);
+       cfg->m = _pll_fixed_mdiv(pll->params, parent_rate);
+       cfg->p = p;
+       cfg->output_rate = rate * cfg->p;
+       cfg->n = cfg->output_rate * cfg->m / parent_rate;
+
+       if (cfg->n > divn_max(pll) || cfg->output_rate > pll->params->vco_max)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int _pll_ramp_calc_pll(struct clk_hw *hw,
+                             struct tegra_clk_pll_freq_table *cfg,
+                             unsigned long rate, unsigned long parent_rate)
+{
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       int err = 0;
+
+       err = _get_table_rate(hw, cfg, rate, parent_rate);
+       if (err < 0)
+               err = _calc_dynamic_ramp_rate(hw, cfg, rate, parent_rate);
+       else if (cfg->m != _pll_fixed_mdiv(pll->params, parent_rate)) {
+                       WARN_ON(1);
+                       err = -EINVAL;
+                       goto out;
+       }
+
+       if (!cfg->p || (cfg->p >  pll->params->max_p))
+               err = -EINVAL;
+
+out:
+       return err;
+}
+
+static int clk_pllxc_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       struct tegra_clk_pll_freq_table cfg, old_cfg;
+       unsigned long flags = 0;
+       int ret = 0;
+       u8 old_p;
+
+       ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate);
+       if (ret < 0)
+               return ret;
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       _get_pll_mnp(pll, &old_cfg);
+
+       old_p = pllxc_p[old_cfg.p];
+       if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_p != cfg.p) {
+               cfg.p -= 1;
+               ret = _program_pll(hw, &cfg, rate);
+       }
+
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+
+       return ret;
+}
+
+static long clk_pll_ramp_round_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long *prate)
+{
+       struct tegra_clk_pll_freq_table cfg;
+       int ret = 0;
+       u64 output_rate = *prate;
+
+       ret = _pll_ramp_calc_pll(hw, &cfg, rate, *prate);
+       if (ret < 0)
+               return ret;
+
+       output_rate *= cfg.n;
+       do_div(output_rate, cfg.m * cfg.p);
+
+       return output_rate;
+}
+
+static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct tegra_clk_pll_freq_table cfg;
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       unsigned long flags = 0;
+       int state, ret = 0;
+       u32 val;
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       state = clk_pll_is_enabled(hw);
+       if (state) {
+               if (rate != clk_get_rate(hw->clk)) {
+                       pr_err("%s: Cannot change active PLLM\n", __func__);
+                       ret = -EINVAL;
+                       goto out;
+               }
+               goto out;
+       }
+
+       ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate);
+       if (ret < 0)
+               goto out;
+
+       cfg.p -= 1;
+
+       val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE);
+       if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE) {
+               val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE_2);
+               val = cfg.p ? (val | PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK) :
+                       (val & ~PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK);
+               writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE_2);
+
+               val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE);
+               val &= ~(divn_mask(pll) | divm_mask(pll));
+               val |= (cfg.m << pll->divm_shift) | (cfg.n << pll->divn_shift);
+               writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE);
+       } else
+               _update_pll_mnp(pll, &cfg);
+
+
+out:
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+
+       return ret;
+}
+
+static void _pllcx_strobe(struct tegra_clk_pll *pll)
+{
+       u32 val;
+
+       val = pll_readl_misc(pll);
+       val |= PLLCX_MISC_STROBE;
+       pll_writel_misc(val, pll);
+       udelay(2);
+
+       val &= ~PLLCX_MISC_STROBE;
+       pll_writel_misc(val, pll);
+}
+
+static int clk_pllc_enable(struct clk_hw *hw)
 {
-       return _tegra_clk_register_pll(name, parent_name, clk_base, pmc,
-                       flags, fixed_rate, pll_params, pll_flags, freq_table,
-                       lock, &tegra_clk_plle_ops);
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       u32 val;
+       int ret = 0;
+       unsigned long flags = 0;
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       _clk_pll_enable(hw);
+       udelay(2);
+
+       val = pll_readl_misc(pll);
+       val &= ~PLLCX_MISC_RESET;
+       pll_writel_misc(val, pll);
+       udelay(2);
+
+       _pllcx_strobe(pll);
+
+       ret = clk_pll_wait_for_lock(pll);
+
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+
+       return ret;
+}
+
+static void _clk_pllc_disable(struct clk_hw *hw)
+{
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       u32 val;
+
+       _clk_pll_disable(hw);
+
+       val = pll_readl_misc(pll);
+       val |= PLLCX_MISC_RESET;
+       pll_writel_misc(val, pll);
+       udelay(2);
+}
+
+static void clk_pllc_disable(struct clk_hw *hw)
+{
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       unsigned long flags = 0;
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       _clk_pllc_disable(hw);
+
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static int _pllcx_update_dynamic_coef(struct tegra_clk_pll *pll,
+                                       unsigned long input_rate, u32 n)
+{
+       u32 val, n_threshold;
+
+       switch (input_rate) {
+       case 12000000:
+               n_threshold = 70;
+               break;
+       case 13000000:
+       case 26000000:
+               n_threshold = 71;
+               break;
+       case 16800000:
+               n_threshold = 55;
+               break;
+       case 19200000:
+               n_threshold = 48;
+               break;
+       default:
+               pr_err("%s: Unexpected reference rate %lu\n",
+                       __func__, input_rate);
+               return -EINVAL;
+       }
+
+       val = pll_readl_misc(pll);
+       val &= ~(PLLCX_MISC_SDM_DIV_MASK | PLLCX_MISC_FILT_DIV_MASK);
+       val |= n <= n_threshold ?
+               PLLCX_MISC_DIV_LOW_RANGE : PLLCX_MISC_DIV_HIGH_RANGE;
+       pll_writel_misc(val, pll);
+
+       return 0;
+}
+
+static int clk_pllc_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct tegra_clk_pll_freq_table cfg;
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       unsigned long flags = 0;
+       int state, ret = 0;
+       u32 val;
+       u16 old_m, old_n;
+       u8 old_p;
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate);
+       if (ret < 0)
+               goto out;
+
+       val = pll_readl_base(pll);
+       old_m = (val >> pll->divm_shift) & (divm_mask(pll));
+       old_n = (val >> pll->divn_shift) & (divn_mask(pll));
+       old_p = pllcx_p[(val >> pll->divp_shift) & (divp_mask(pll))];
+
+       if (cfg.m != old_m) {
+               WARN_ON(1);
+               goto out;
+       }
+
+       if (old_n == cfg.n && old_p == cfg.p)
+               goto out;
+
+       cfg.p -= 1;
+
+       state = clk_pll_is_enabled(hw);
+       if (state)
+               _clk_pllc_disable(hw);
+
+       ret = _pllcx_update_dynamic_coef(pll, parent_rate, cfg.n);
+       if (ret < 0)
+               goto out;
+
+       _update_pll_mnp(pll, &cfg);
+
+       if (state)
+               ret = clk_pllc_enable(hw);
+
+out:
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+
+       return ret;
+}
+
+static long _pllre_calc_rate(struct tegra_clk_pll *pll,
+                            struct tegra_clk_pll_freq_table *cfg,
+                            unsigned long rate, unsigned long parent_rate)
+{
+       u16 m, n;
+       u64 output_rate = parent_rate;
+
+       m = _pll_fixed_mdiv(pll->params, parent_rate);
+       n = rate * m / parent_rate;
+
+       output_rate *= n;
+       do_div(output_rate, m);
+
+       if (cfg) {
+               cfg->m = m;
+               cfg->n = n;
+       }
+
+       return output_rate;
+}
+static int clk_pllre_set_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long parent_rate)
+{
+       struct tegra_clk_pll_freq_table cfg, old_cfg;
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       unsigned long flags = 0;
+       int state, ret = 0;
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       _pllre_calc_rate(pll, &cfg, rate, parent_rate);
+       _get_pll_mnp(pll, &old_cfg);
+       cfg.p = old_cfg.p;
+
+       if (cfg.m != old_cfg.m || cfg.n != old_cfg.n) {
+               state = clk_pll_is_enabled(hw);
+               if (state)
+                       _clk_pll_disable(hw);
+
+               _update_pll_mnp(pll, &cfg);
+
+               if (state) {
+                       _clk_pll_enable(hw);
+                       ret = clk_pll_wait_for_lock(pll);
+               }
+       }
+
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+
+       return ret;
+}
+
+static unsigned long clk_pllre_recalc_rate(struct clk_hw *hw,
+                                        unsigned long parent_rate)
+{
+       struct tegra_clk_pll_freq_table cfg;
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       u64 rate = parent_rate;
+
+       _get_pll_mnp(pll, &cfg);
+
+       rate *= cfg.n;
+       do_div(rate, cfg.m);
+
+       return rate;
+}
+
+static long clk_pllre_round_rate(struct clk_hw *hw, unsigned long rate,
+                                unsigned long *prate)
+{
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+
+       return _pllre_calc_rate(pll, NULL, rate, *prate);
+}
+
+static int clk_plle_tegra114_enable(struct clk_hw *hw)
+{
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       struct tegra_clk_pll_freq_table sel;
+       u32 val;
+       int ret;
+       unsigned long flags = 0;
+       unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));
+
+       if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))
+               return -EINVAL;
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       val = pll_readl_base(pll);
+       val &= ~BIT(29); /* Disable lock override */
+       pll_writel_base(val, pll);
+
+       val = pll_readl(pll->params->aux_reg, pll);
+       val |= PLLE_AUX_ENABLE_SWCTL;
+       val &= ~PLLE_AUX_SEQ_ENABLE;
+       pll_writel(val, pll->params->aux_reg, pll);
+       udelay(1);
+
+       val = pll_readl_misc(pll);
+       val |= PLLE_MISC_LOCK_ENABLE;
+       val |= PLLE_MISC_IDDQ_SW_CTRL;
+       val &= ~PLLE_MISC_IDDQ_SW_VALUE;
+       val |= PLLE_MISC_PLLE_PTS;
+       val |= PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK;
+       pll_writel_misc(val, pll);
+       udelay(5);
+
+       val = pll_readl(PLLE_SS_CTRL, pll);
+       val |= PLLE_SS_DISABLE;
+       pll_writel(val, PLLE_SS_CTRL, pll);
+
+       val = pll_readl_base(pll);
+       val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
+       val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
+       val |= sel.m << pll->divm_shift;
+       val |= sel.n << pll->divn_shift;
+       val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
+       pll_writel_base(val, pll);
+       udelay(1);
+
+       _clk_pll_enable(hw);
+       ret = clk_pll_wait_for_lock(pll);
+
+       if (ret < 0)
+               goto out;
+
+       /* TODO: enable hw control of xusb brick pll */
+
+out:
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+
+       return ret;
+}
+
+static void clk_plle_tegra114_disable(struct clk_hw *hw)
+{
+       struct tegra_clk_pll *pll = to_clk_pll(hw);
+       unsigned long flags = 0;
+       u32 val;
+
+       if (pll->lock)
+               spin_lock_irqsave(pll->lock, flags);
+
+       _clk_pll_disable(hw);
+
+       val = pll_readl_misc(pll);
+       val |= PLLE_MISC_IDDQ_SW_CTRL | PLLE_MISC_IDDQ_SW_VALUE;
+       pll_writel_misc(val, pll);
+       udelay(1);
+
+       if (pll->lock)
+               spin_unlock_irqrestore(pll->lock, flags);
+}
+#endif
+
+static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base,
+               void __iomem *pmc, unsigned long fixed_rate,
+               struct tegra_clk_pll_params *pll_params, u32 pll_flags,
+               struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
+{
+       struct tegra_clk_pll *pll;
+
+       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+       if (!pll)
+               return ERR_PTR(-ENOMEM);
+
+       pll->clk_base = clk_base;
+       pll->pmc = pmc;
+
+       pll->freq_table = freq_table;
+       pll->params = pll_params;
+       pll->fixed_rate = fixed_rate;
+       pll->flags = pll_flags;
+       pll->lock = lock;
+
+       pll->divp_shift = PLL_BASE_DIVP_SHIFT;
+       pll->divp_width = PLL_BASE_DIVP_WIDTH;
+       pll->divn_shift = PLL_BASE_DIVN_SHIFT;
+       pll->divn_width = PLL_BASE_DIVN_WIDTH;
+       pll->divm_shift = PLL_BASE_DIVM_SHIFT;
+       pll->divm_width = PLL_BASE_DIVM_WIDTH;
+
+       return pll;
+}
+
+static struct clk *_tegra_clk_register_pll(struct tegra_clk_pll *pll,
+               const char *name, const char *parent_name, unsigned long flags,
+               const struct clk_ops *ops)
+{
+       struct clk_init_data init;
+
+       init.name = name;
+       init.ops = ops;
+       init.flags = flags;
+       init.parent_names = (parent_name ? &parent_name : NULL);
+       init.num_parents = (parent_name ? 1 : 0);
+
+       /* Data in .init is copied by clk_register(), so stack variable OK */
+       pll->hw.init = &init;
+
+       return clk_register(NULL, &pll->hw);
+}
+
+struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
+               void __iomem *clk_base, void __iomem *pmc,
+               unsigned long flags, unsigned long fixed_rate,
+               struct tegra_clk_pll_params *pll_params, u32 pll_flags,
+               struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
+{
+       struct tegra_clk_pll *pll;
+       struct clk *clk;
+
+       pll_flags |= TEGRA_PLL_BYPASS;
+       pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
+       pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+                             freq_table, lock);
+       if (IS_ERR(pll))
+               return ERR_CAST(pll);
+
+       clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+                                     &tegra_clk_pll_ops);
+       if (IS_ERR(clk))
+               kfree(pll);
+
+       return clk;
+}
+
+struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
+               void __iomem *clk_base, void __iomem *pmc,
+               unsigned long flags, unsigned long fixed_rate,
+               struct tegra_clk_pll_params *pll_params, u32 pll_flags,
+               struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
+{
+       struct tegra_clk_pll *pll;
+       struct clk *clk;
+
+       pll_flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS;
+       pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
+       pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+                             freq_table, lock);
+       if (IS_ERR(pll))
+               return ERR_CAST(pll);
+
+       clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+                                     &tegra_clk_plle_ops);
+       if (IS_ERR(clk))
+               kfree(pll);
+
+       return clk;
+}
+
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+const struct clk_ops tegra_clk_pllxc_ops = {
+       .is_enabled = clk_pll_is_enabled,
+       .enable = clk_pll_iddq_enable,
+       .disable = clk_pll_iddq_disable,
+       .recalc_rate = clk_pll_recalc_rate,
+       .round_rate = clk_pll_ramp_round_rate,
+       .set_rate = clk_pllxc_set_rate,
+};
+
+const struct clk_ops tegra_clk_pllm_ops = {
+       .is_enabled = clk_pll_is_enabled,
+       .enable = clk_pll_iddq_enable,
+       .disable = clk_pll_iddq_disable,
+       .recalc_rate = clk_pll_recalc_rate,
+       .round_rate = clk_pll_ramp_round_rate,
+       .set_rate = clk_pllm_set_rate,
+};
+
+const struct clk_ops tegra_clk_pllc_ops = {
+       .is_enabled = clk_pll_is_enabled,
+       .enable = clk_pllc_enable,
+       .disable = clk_pllc_disable,
+       .recalc_rate = clk_pll_recalc_rate,
+       .round_rate = clk_pll_ramp_round_rate,
+       .set_rate = clk_pllc_set_rate,
+};
+
+const struct clk_ops tegra_clk_pllre_ops = {
+       .is_enabled = clk_pll_is_enabled,
+       .enable = clk_pll_iddq_enable,
+       .disable = clk_pll_iddq_disable,
+       .recalc_rate = clk_pllre_recalc_rate,
+       .round_rate = clk_pllre_round_rate,
+       .set_rate = clk_pllre_set_rate,
+};
+
+const struct clk_ops tegra_clk_plle_tegra114_ops = {
+       .is_enabled =  clk_pll_is_enabled,
+       .enable = clk_plle_tegra114_enable,
+       .disable = clk_plle_tegra114_disable,
+       .recalc_rate = clk_pll_recalc_rate,
+};
+
+
+struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
+                         void __iomem *clk_base, void __iomem *pmc,
+                         unsigned long flags, unsigned long fixed_rate,
+                         struct tegra_clk_pll_params *pll_params,
+                         u32 pll_flags,
+                         struct tegra_clk_pll_freq_table *freq_table,
+                         spinlock_t *lock)
+{
+       struct tegra_clk_pll *pll;
+       struct clk *clk;
+
+       if (!pll_params->pdiv_tohw)
+               return ERR_PTR(-EINVAL);
+
+       pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
+       pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+                             freq_table, lock);
+       if (IS_ERR(pll))
+               return ERR_CAST(pll);
+
+       clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+                                     &tegra_clk_pllxc_ops);
+       if (IS_ERR(clk))
+               kfree(pll);
+
+       return clk;
+}
+
+struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
+                         void __iomem *clk_base, void __iomem *pmc,
+                         unsigned long flags, unsigned long fixed_rate,
+                         struct tegra_clk_pll_params *pll_params,
+                         u32 pll_flags,
+                         struct tegra_clk_pll_freq_table *freq_table,
+                         spinlock_t *lock, unsigned long parent_rate)
+{
+       u32 val;
+       struct tegra_clk_pll *pll;
+       struct clk *clk;
+
+       pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
+       pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+                             freq_table, lock);
+       if (IS_ERR(pll))
+               return ERR_CAST(pll);
+
+       /* program minimum rate by default */
+
+       val = pll_readl_base(pll);
+       if (val & PLL_BASE_ENABLE)
+               WARN_ON(val & pll_params->iddq_bit_idx);
+       else {
+               int m;
+
+               m = _pll_fixed_mdiv(pll_params, parent_rate);
+               val = m << PLL_BASE_DIVM_SHIFT;
+               val |= (pll_params->vco_min / parent_rate)
+                               << PLL_BASE_DIVN_SHIFT;
+               pll_writel_base(val, pll);
+       }
+
+       /* disable lock override */
+
+       val = pll_readl_misc(pll);
+       val &= ~BIT(29);
+       pll_writel_misc(val, pll);
+
+       pll_flags |= TEGRA_PLL_LOCK_MISC;
+       clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+                                     &tegra_clk_pllre_ops);
+       if (IS_ERR(clk))
+               kfree(pll);
+
+       return clk;
+}
+
+struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
+                         void __iomem *clk_base, void __iomem *pmc,
+                         unsigned long flags, unsigned long fixed_rate,
+                         struct tegra_clk_pll_params *pll_params,
+                         u32 pll_flags,
+                         struct tegra_clk_pll_freq_table *freq_table,
+                         spinlock_t *lock)
+{
+       struct tegra_clk_pll *pll;
+       struct clk *clk;
+
+       if (!pll_params->pdiv_tohw)
+               return ERR_PTR(-EINVAL);
+
+       pll_flags |= TEGRA_PLL_BYPASS;
+       pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE;
+       pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+                             freq_table, lock);
+       if (IS_ERR(pll))
+               return ERR_CAST(pll);
+
+       clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+                                     &tegra_clk_pllm_ops);
+       if (IS_ERR(clk))
+               kfree(pll);
+
+       return clk;
+}
+
+struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
+                         void __iomem *clk_base, void __iomem *pmc,
+                         unsigned long flags, unsigned long fixed_rate,
+                         struct tegra_clk_pll_params *pll_params,
+                         u32 pll_flags,
+                         struct tegra_clk_pll_freq_table *freq_table,
+                         spinlock_t *lock)
+{
+       struct clk *parent, *clk;
+       struct pdiv_map *p_tohw = pll_params->pdiv_tohw;
+       struct tegra_clk_pll *pll;
+       struct tegra_clk_pll_freq_table cfg;
+       unsigned long parent_rate;
+
+       if (!p_tohw)
+               return ERR_PTR(-EINVAL);
+
+       parent = __clk_lookup(parent_name);
+       if (IS_ERR(parent)) {
+               WARN(1, "parent clk %s of %s must be registered first\n",
+                       name, parent_name);
+               return ERR_PTR(-EINVAL);
+       }
+
+       pll_flags |= TEGRA_PLL_BYPASS;
+       pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags,
+                             freq_table, lock);
+       if (IS_ERR(pll))
+               return ERR_CAST(pll);
+
+       parent_rate = __clk_get_rate(parent);
+
+       /*
+        * Most of PLLC register fields are shadowed, and can not be read
+        * directly from PLL h/w. Hence, actual PLLC boot state is unknown.
+        * Initialize PLL to default state: disabled, reset; shadow registers
+        * loaded with default parameters; dividers are preset for half of
+        * minimum VCO rate (the latter assured that shadowed divider settings
+        * are within supported range).
+        */
+
+       cfg.m = _pll_fixed_mdiv(pll_params, parent_rate);
+       cfg.n = cfg.m * pll_params->vco_min / parent_rate;
+
+       while (p_tohw->pdiv) {
+               if (p_tohw->pdiv == 2) {
+                       cfg.p = p_tohw->hw_val;
+                       break;
+               }
+               p_tohw++;
+       }
+
+       if (!p_tohw->pdiv) {
+               WARN_ON(1);
+               return ERR_PTR(-EINVAL);
+       }
+
+       pll_writel_base(0, pll);
+       _update_pll_mnp(pll, &cfg);
+
+       pll_writel_misc(PLLCX_MISC_DEFAULT, pll);
+       pll_writel(PLLCX_MISC1_DEFAULT, pll_params->ext_misc_reg[0], pll);
+       pll_writel(PLLCX_MISC2_DEFAULT, pll_params->ext_misc_reg[1], pll);
+       pll_writel(PLLCX_MISC3_DEFAULT, pll_params->ext_misc_reg[2], pll);
+
+       _pllcx_update_dynamic_coef(pll, parent_rate, cfg.n);
+
+       clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+                                     &tegra_clk_pllc_ops);
+       if (IS_ERR(clk))
+               kfree(pll);
+
+       return clk;
+}
+
+struct clk *tegra_clk_register_plle_tegra114(const char *name,
+                               const char *parent_name,
+                               void __iomem *clk_base, unsigned long flags,
+                               unsigned long fixed_rate,
+                               struct tegra_clk_pll_params *pll_params,
+                               struct tegra_clk_pll_freq_table *freq_table,
+                               spinlock_t *lock)
+{
+       struct tegra_clk_pll *pll;
+       struct clk *clk;
+       u32 val, val_aux;
+
+       pll = _tegra_init_pll(clk_base, NULL, fixed_rate, pll_params,
+                             TEGRA_PLL_HAS_LOCK_ENABLE, freq_table, lock);
+       if (IS_ERR(pll))
+               return ERR_CAST(pll);
+
+       /* ensure parent is set to pll_re_vco */
+
+       val = pll_readl_base(pll);
+       val_aux = pll_readl(pll_params->aux_reg, pll);
+
+       if (val & PLL_BASE_ENABLE) {
+               if (!(val_aux & PLLE_AUX_PLLRE_SEL))
+                       WARN(1, "pll_e enabled with unsupported parent %s\n",
+                         (val & PLLE_AUX_PLLP_SEL) ? "pllp_out0" : "pll_ref");
+       } else {
+               val_aux |= PLLE_AUX_PLLRE_SEL;
+               pll_writel(val, pll_params->aux_reg, pll);
+       }
+
+       clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
+                                     &tegra_clk_plle_tegra114_ops);
+       if (IS_ERR(clk))
+               kfree(pll);
+
+       return clk;
 }
+#endif
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
new file mode 100644 (file)
index 0000000..d78e16e
--- /dev/null
@@ -0,0 +1,2085 @@
+/*
+ * Copyright (c) 2012, 2013, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * 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 <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/delay.h>
+#include <linux/clk/tegra.h>
+
+#include "clk.h"
+
+#define RST_DEVICES_L                  0x004
+#define RST_DEVICES_H                  0x008
+#define RST_DEVICES_U                  0x00C
+#define RST_DEVICES_V                  0x358
+#define RST_DEVICES_W                  0x35C
+#define RST_DEVICES_X                  0x28C
+#define RST_DEVICES_SET_L              0x300
+#define RST_DEVICES_CLR_L              0x304
+#define RST_DEVICES_SET_H              0x308
+#define RST_DEVICES_CLR_H              0x30c
+#define RST_DEVICES_SET_U              0x310
+#define RST_DEVICES_CLR_U              0x314
+#define RST_DEVICES_SET_V              0x430
+#define RST_DEVICES_CLR_V              0x434
+#define RST_DEVICES_SET_W              0x438
+#define RST_DEVICES_CLR_W              0x43c
+#define RST_DEVICES_NUM                        5
+
+#define CLK_OUT_ENB_L                  0x010
+#define CLK_OUT_ENB_H                  0x014
+#define CLK_OUT_ENB_U                  0x018
+#define CLK_OUT_ENB_V                  0x360
+#define CLK_OUT_ENB_W                  0x364
+#define CLK_OUT_ENB_X                  0x280
+#define CLK_OUT_ENB_SET_L              0x320
+#define CLK_OUT_ENB_CLR_L              0x324
+#define CLK_OUT_ENB_SET_H              0x328
+#define CLK_OUT_ENB_CLR_H              0x32c
+#define CLK_OUT_ENB_SET_U              0x330
+#define CLK_OUT_ENB_CLR_U              0x334
+#define CLK_OUT_ENB_SET_V              0x440
+#define CLK_OUT_ENB_CLR_V              0x444
+#define CLK_OUT_ENB_SET_W              0x448
+#define CLK_OUT_ENB_CLR_W              0x44c
+#define CLK_OUT_ENB_SET_X              0x284
+#define CLK_OUT_ENB_CLR_X              0x288
+#define CLK_OUT_ENB_NUM                        6
+
+#define PLLC_BASE 0x80
+#define PLLC_MISC2 0x88
+#define PLLC_MISC 0x8c
+#define PLLC2_BASE 0x4e8
+#define PLLC2_MISC 0x4ec
+#define PLLC3_BASE 0x4fc
+#define PLLC3_MISC 0x500
+#define PLLM_BASE 0x90
+#define PLLM_MISC 0x9c
+#define PLLP_BASE 0xa0
+#define PLLP_MISC 0xac
+#define PLLX_BASE 0xe0
+#define PLLX_MISC 0xe4
+#define PLLX_MISC2 0x514
+#define PLLX_MISC3 0x518
+#define PLLD_BASE 0xd0
+#define PLLD_MISC 0xdc
+#define PLLD2_BASE 0x4b8
+#define PLLD2_MISC 0x4bc
+#define PLLE_BASE 0xe8
+#define PLLE_MISC 0xec
+#define PLLA_BASE 0xb0
+#define PLLA_MISC 0xbc
+#define PLLU_BASE 0xc0
+#define PLLU_MISC 0xcc
+#define PLLRE_BASE 0x4c4
+#define PLLRE_MISC 0x4c8
+
+#define PLL_MISC_LOCK_ENABLE 18
+#define PLLC_MISC_LOCK_ENABLE 24
+#define PLLDU_MISC_LOCK_ENABLE 22
+#define PLLE_MISC_LOCK_ENABLE 9
+#define PLLRE_MISC_LOCK_ENABLE 30
+
+#define PLLC_IDDQ_BIT 26
+#define PLLX_IDDQ_BIT 3
+#define PLLRE_IDDQ_BIT 16
+
+#define PLL_BASE_LOCK BIT(27)
+#define PLLE_MISC_LOCK BIT(11)
+#define PLLRE_MISC_LOCK BIT(24)
+#define PLLCX_BASE_LOCK (BIT(26)|BIT(27))
+
+#define PLLE_AUX 0x48c
+#define PLLC_OUT 0x84
+#define PLLM_OUT 0x94
+#define PLLP_OUTA 0xa4
+#define PLLP_OUTB 0xa8
+#define PLLA_OUT 0xb4
+
+#define AUDIO_SYNC_CLK_I2S0 0x4a0
+#define AUDIO_SYNC_CLK_I2S1 0x4a4
+#define AUDIO_SYNC_CLK_I2S2 0x4a8
+#define AUDIO_SYNC_CLK_I2S3 0x4ac
+#define AUDIO_SYNC_CLK_I2S4 0x4b0
+#define AUDIO_SYNC_CLK_SPDIF 0x4b4
+
+#define AUDIO_SYNC_DOUBLER 0x49c
+
+#define PMC_CLK_OUT_CNTRL 0x1a8
+#define PMC_DPD_PADS_ORIDE 0x1c
+#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
+#define PMC_CTRL 0
+#define PMC_CTRL_BLINK_ENB 7
+
+#define OSC_CTRL                       0x50
+#define OSC_CTRL_OSC_FREQ_SHIFT                28
+#define OSC_CTRL_PLL_REF_DIV_SHIFT     26
+
+#define PLLXC_SW_MAX_P                 6
+
+#define CCLKG_BURST_POLICY 0x368
+#define CCLKLP_BURST_POLICY 0x370
+#define SCLK_BURST_POLICY 0x028
+#define SYSTEM_CLK_RATE 0x030
+
+#define UTMIP_PLL_CFG2 0x488
+#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6)
+#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4)
+
+#define UTMIP_PLL_CFG1 0x484
+#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6)
+#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
+
+#define UTMIPLL_HW_PWRDN_CFG0                  0x52c
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE  BIT(25)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE       BIT(24)
+#define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET      BIT(6)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE    BIT(5)
+#define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL     BIT(4)
+#define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE    BIT(1)
+#define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL       BIT(0)
+
+#define CLK_SOURCE_I2S0 0x1d8
+#define CLK_SOURCE_I2S1 0x100
+#define CLK_SOURCE_I2S2 0x104
+#define CLK_SOURCE_NDFLASH 0x160
+#define CLK_SOURCE_I2S3 0x3bc
+#define CLK_SOURCE_I2S4 0x3c0
+#define CLK_SOURCE_SPDIF_OUT 0x108
+#define CLK_SOURCE_SPDIF_IN 0x10c
+#define CLK_SOURCE_PWM 0x110
+#define CLK_SOURCE_ADX 0x638
+#define CLK_SOURCE_AMX 0x63c
+#define CLK_SOURCE_HDA 0x428
+#define CLK_SOURCE_HDA2CODEC_2X 0x3e4
+#define CLK_SOURCE_SBC1 0x134
+#define CLK_SOURCE_SBC2 0x118
+#define CLK_SOURCE_SBC3 0x11c
+#define CLK_SOURCE_SBC4 0x1b4
+#define CLK_SOURCE_SBC5 0x3c8
+#define CLK_SOURCE_SBC6 0x3cc
+#define CLK_SOURCE_SATA_OOB 0x420
+#define CLK_SOURCE_SATA 0x424
+#define CLK_SOURCE_NDSPEED 0x3f8
+#define CLK_SOURCE_VFIR 0x168
+#define CLK_SOURCE_SDMMC1 0x150
+#define CLK_SOURCE_SDMMC2 0x154
+#define CLK_SOURCE_SDMMC3 0x1bc
+#define CLK_SOURCE_SDMMC4 0x164
+#define CLK_SOURCE_VDE 0x1c8
+#define CLK_SOURCE_CSITE 0x1d4
+#define CLK_SOURCE_LA 0x1f8
+#define CLK_SOURCE_TRACE 0x634
+#define CLK_SOURCE_OWR 0x1cc
+#define CLK_SOURCE_NOR 0x1d0
+#define CLK_SOURCE_MIPI 0x174
+#define CLK_SOURCE_I2C1 0x124
+#define CLK_SOURCE_I2C2 0x198
+#define CLK_SOURCE_I2C3 0x1b8
+#define CLK_SOURCE_I2C4 0x3c4
+#define CLK_SOURCE_I2C5 0x128
+#define CLK_SOURCE_UARTA 0x178
+#define CLK_SOURCE_UARTB 0x17c
+#define CLK_SOURCE_UARTC 0x1a0
+#define CLK_SOURCE_UARTD 0x1c0
+#define CLK_SOURCE_UARTE 0x1c4
+#define CLK_SOURCE_UARTA_DBG 0x178
+#define CLK_SOURCE_UARTB_DBG 0x17c
+#define CLK_SOURCE_UARTC_DBG 0x1a0
+#define CLK_SOURCE_UARTD_DBG 0x1c0
+#define CLK_SOURCE_UARTE_DBG 0x1c4
+#define CLK_SOURCE_3D 0x158
+#define CLK_SOURCE_2D 0x15c
+#define CLK_SOURCE_VI_SENSOR 0x1a8
+#define CLK_SOURCE_VI 0x148
+#define CLK_SOURCE_EPP 0x16c
+#define CLK_SOURCE_MSENC 0x1f0
+#define CLK_SOURCE_TSEC 0x1f4
+#define CLK_SOURCE_HOST1X 0x180
+#define CLK_SOURCE_HDMI 0x18c
+#define CLK_SOURCE_DISP1 0x138
+#define CLK_SOURCE_DISP2 0x13c
+#define CLK_SOURCE_CILAB 0x614
+#define CLK_SOURCE_CILCD 0x618
+#define CLK_SOURCE_CILE 0x61c
+#define CLK_SOURCE_DSIALP 0x620
+#define CLK_SOURCE_DSIBLP 0x624
+#define CLK_SOURCE_TSENSOR 0x3b8
+#define CLK_SOURCE_D_AUDIO 0x3d0
+#define CLK_SOURCE_DAM0 0x3d8
+#define CLK_SOURCE_DAM1 0x3dc
+#define CLK_SOURCE_DAM2 0x3e0
+#define CLK_SOURCE_ACTMON 0x3e8
+#define CLK_SOURCE_EXTERN1 0x3ec
+#define CLK_SOURCE_EXTERN2 0x3f0
+#define CLK_SOURCE_EXTERN3 0x3f4
+#define CLK_SOURCE_I2CSLOW 0x3fc
+#define CLK_SOURCE_SE 0x42c
+#define CLK_SOURCE_MSELECT 0x3b4
+#define CLK_SOURCE_SOC_THERM 0x644
+#define CLK_SOURCE_XUSB_HOST_SRC 0x600
+#define CLK_SOURCE_XUSB_FALCON_SRC 0x604
+#define CLK_SOURCE_XUSB_FS_SRC 0x608
+#define CLK_SOURCE_XUSB_SS_SRC 0x610
+#define CLK_SOURCE_XUSB_DEV_SRC 0x60c
+#define CLK_SOURCE_EMC 0x19c
+
+static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32];
+
+static void __iomem *clk_base;
+static void __iomem *pmc_base;
+
+static DEFINE_SPINLOCK(pll_d_lock);
+static DEFINE_SPINLOCK(pll_d2_lock);
+static DEFINE_SPINLOCK(pll_u_lock);
+static DEFINE_SPINLOCK(pll_div_lock);
+static DEFINE_SPINLOCK(pll_re_lock);
+static DEFINE_SPINLOCK(clk_doubler_lock);
+static DEFINE_SPINLOCK(clk_out_lock);
+static DEFINE_SPINLOCK(sysrate_lock);
+
+static struct pdiv_map pllxc_p[] = {
+       { .pdiv = 1, .hw_val = 0 },
+       { .pdiv = 2, .hw_val = 1 },
+       { .pdiv = 3, .hw_val = 2 },
+       { .pdiv = 4, .hw_val = 3 },
+       { .pdiv = 5, .hw_val = 4 },
+       { .pdiv = 6, .hw_val = 5 },
+       { .pdiv = 8, .hw_val = 6 },
+       { .pdiv = 10, .hw_val = 7 },
+       { .pdiv = 12, .hw_val = 8 },
+       { .pdiv = 16, .hw_val = 9 },
+       { .pdiv = 12, .hw_val = 10 },
+       { .pdiv = 16, .hw_val = 11 },
+       { .pdiv = 20, .hw_val = 12 },
+       { .pdiv = 24, .hw_val = 13 },
+       { .pdiv = 32, .hw_val = 14 },
+       { .pdiv = 0, .hw_val = 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
+       { 12000000, 624000000, 104, 0, 2},
+       { 12000000, 600000000, 100, 0, 2},
+       { 13000000, 600000000,  92, 0, 2},      /* actual: 598.0 MHz */
+       { 16800000, 600000000,  71, 0, 2},      /* actual: 596.4 MHz */
+       { 19200000, 600000000,  62, 0, 2},      /* actual: 595.2 MHz */
+       { 26000000, 600000000,  92, 1, 2},      /* actual: 598.0 MHz */
+       { 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_params pll_c_params = {
+       .input_min = 12000000,
+       .input_max = 800000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000,     /* s/w policy, h/w capability 50 MHz */
+       .vco_min = 600000000,
+       .vco_max = 1400000000,
+       .base_reg = PLLC_BASE,
+       .misc_reg = PLLC_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLLC_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .iddq_reg = PLLC_MISC,
+       .iddq_bit_idx = PLLC_IDDQ_BIT,
+       .max_p = PLLXC_SW_MAX_P,
+       .dyn_ramp_reg = PLLC_MISC2,
+       .stepa_shift = 17,
+       .stepb_shift = 9,
+       .pdiv_tohw = pllxc_p,
+};
+
+static struct pdiv_map pllc_p[] = {
+       { .pdiv = 1, .hw_val = 0 },
+       { .pdiv = 2, .hw_val = 1 },
+       { .pdiv = 4, .hw_val = 3 },
+       { .pdiv = 8, .hw_val = 5 },
+       { .pdiv = 16, .hw_val = 7 },
+       { .pdiv = 0, .hw_val = 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = {
+       {12000000, 600000000, 100, 0, 2},
+       {13000000, 600000000, 92, 0, 2},        /* actual: 598.0 MHz */
+       {16800000, 600000000, 71, 0, 2},        /* actual: 596.4 MHz */
+       {19200000, 600000000, 62, 0, 2},        /* actual: 595.2 MHz */
+       {26000000, 600000000, 92, 1, 2},        /* actual: 598.0 MHz */
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_c2_params = {
+       .input_min = 12000000,
+       .input_max = 48000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000,
+       .vco_min = 600000000,
+       .vco_max = 1200000000,
+       .base_reg = PLLC2_BASE,
+       .misc_reg = PLLC2_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .pdiv_tohw = pllc_p,
+       .ext_misc_reg[0] = 0x4f0,
+       .ext_misc_reg[1] = 0x4f4,
+       .ext_misc_reg[2] = 0x4f8,
+};
+
+static struct tegra_clk_pll_params pll_c3_params = {
+       .input_min = 12000000,
+       .input_max = 48000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000,
+       .vco_min = 600000000,
+       .vco_max = 1200000000,
+       .base_reg = PLLC3_BASE,
+       .misc_reg = PLLC3_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .pdiv_tohw = pllc_p,
+       .ext_misc_reg[0] = 0x504,
+       .ext_misc_reg[1] = 0x508,
+       .ext_misc_reg[2] = 0x50c,
+};
+
+static struct pdiv_map pllm_p[] = {
+       { .pdiv = 1, .hw_val = 0 },
+       { .pdiv = 2, .hw_val = 1 },
+       { .pdiv = 0, .hw_val = 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
+       {12000000, 800000000, 66, 0, 1},        /* actual: 792.0 MHz */
+       {13000000, 800000000, 61, 0, 1},        /* actual: 793.0 MHz */
+       {16800000, 800000000, 47, 0, 1},        /* actual: 789.6 MHz */
+       {19200000, 800000000, 41, 0, 1},        /* actual: 787.2 MHz */
+       {26000000, 800000000, 61, 1, 1},        /* actual: 793.0 MHz */
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_m_params = {
+       .input_min = 12000000,
+       .input_max = 500000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000,     /* s/w policy, h/w capability 50 MHz */
+       .vco_min = 400000000,
+       .vco_max = 1066000000,
+       .base_reg = PLLM_BASE,
+       .misc_reg = PLLM_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .max_p = 2,
+       .pdiv_tohw = pllm_p,
+};
+
+static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
+       {12000000, 216000000, 432, 12, 1, 8},
+       {13000000, 216000000, 432, 13, 1, 8},
+       {16800000, 216000000, 360, 14, 1, 8},
+       {19200000, 216000000, 360, 16, 1, 8},
+       {26000000, 216000000, 432, 26, 1, 8},
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_p_params = {
+       .input_min = 2000000,
+       .input_max = 31000000,
+       .cf_min = 1000000,
+       .cf_max = 6000000,
+       .vco_min = 200000000,
+       .vco_max = 700000000,
+       .base_reg = PLLP_BASE,
+       .misc_reg = PLLP_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+};
+
+static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
+       {9600000, 282240000, 147, 5, 0, 4},
+       {9600000, 368640000, 192, 5, 0, 4},
+       {9600000, 240000000, 200, 8, 0, 8},
+
+       {28800000, 282240000, 245, 25, 0, 8},
+       {28800000, 368640000, 320, 25, 0, 8},
+       {28800000, 240000000, 200, 24, 0, 8},
+       {0, 0, 0, 0, 0, 0},
+};
+
+
+static struct tegra_clk_pll_params pll_a_params = {
+       .input_min = 2000000,
+       .input_max = 31000000,
+       .cf_min = 1000000,
+       .cf_max = 6000000,
+       .vco_min = 200000000,
+       .vco_max = 700000000,
+       .base_reg = PLLA_BASE,
+       .misc_reg = PLLA_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+};
+
+static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
+       {12000000, 216000000, 864, 12, 2, 12},
+       {13000000, 216000000, 864, 13, 2, 12},
+       {16800000, 216000000, 720, 14, 2, 12},
+       {19200000, 216000000, 720, 16, 2, 12},
+       {26000000, 216000000, 864, 26, 2, 12},
+
+       {12000000, 594000000, 594, 12, 0, 12},
+       {13000000, 594000000, 594, 13, 0, 12},
+       {16800000, 594000000, 495, 14, 0, 12},
+       {19200000, 594000000, 495, 16, 0, 12},
+       {26000000, 594000000, 594, 26, 0, 12},
+
+       {12000000, 1000000000, 1000, 12, 0, 12},
+       {13000000, 1000000000, 1000, 13, 0, 12},
+       {19200000, 1000000000, 625, 12, 0, 12},
+       {26000000, 1000000000, 1000, 26, 0, 12},
+
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_d_params = {
+       .input_min = 2000000,
+       .input_max = 40000000,
+       .cf_min = 1000000,
+       .cf_max = 6000000,
+       .vco_min = 500000000,
+       .vco_max = 1000000000,
+       .base_reg = PLLD_BASE,
+       .misc_reg = PLLD_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+       .lock_delay = 1000,
+};
+
+static struct tegra_clk_pll_params pll_d2_params = {
+       .input_min = 2000000,
+       .input_max = 40000000,
+       .cf_min = 1000000,
+       .cf_max = 6000000,
+       .vco_min = 500000000,
+       .vco_max = 1000000000,
+       .base_reg = PLLD2_BASE,
+       .misc_reg = PLLD2_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+       .lock_delay = 1000,
+};
+
+static struct pdiv_map pllu_p[] = {
+       { .pdiv = 1, .hw_val = 1 },
+       { .pdiv = 2, .hw_val = 0 },
+       { .pdiv = 0, .hw_val = 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
+       {12000000, 480000000, 960, 12, 0, 12},
+       {13000000, 480000000, 960, 13, 0, 12},
+       {16800000, 480000000, 400, 7, 0, 5},
+       {19200000, 480000000, 200, 4, 0, 3},
+       {26000000, 480000000, 960, 26, 0, 12},
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_u_params = {
+       .input_min = 2000000,
+       .input_max = 40000000,
+       .cf_min = 1000000,
+       .cf_max = 6000000,
+       .vco_min = 480000000,
+       .vco_max = 960000000,
+       .base_reg = PLLU_BASE,
+       .misc_reg = PLLU_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+       .lock_delay = 1000,
+       .pdiv_tohw = pllu_p,
+};
+
+static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
+       /* 1 GHz */
+       {12000000, 1000000000, 83, 0, 1},       /* actual: 996.0 MHz */
+       {13000000, 1000000000, 76, 0, 1},       /* actual: 988.0 MHz */
+       {16800000, 1000000000, 59, 0, 1},       /* actual: 991.2 MHz */
+       {19200000, 1000000000, 52, 0, 1},       /* actual: 998.4 MHz */
+       {26000000, 1000000000, 76, 1, 1},       /* actual: 988.0 MHz */
+
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_x_params = {
+       .input_min = 12000000,
+       .input_max = 800000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000,     /* s/w policy, h/w capability 50 MHz */
+       .vco_min = 700000000,
+       .vco_max = 2400000000U,
+       .base_reg = PLLX_BASE,
+       .misc_reg = PLLX_MISC,
+       .lock_mask = PLL_BASE_LOCK,
+       .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .iddq_reg = PLLX_MISC3,
+       .iddq_bit_idx = PLLX_IDDQ_BIT,
+       .max_p = PLLXC_SW_MAX_P,
+       .dyn_ramp_reg = PLLX_MISC2,
+       .stepa_shift = 16,
+       .stepb_shift = 24,
+       .pdiv_tohw = pllxc_p,
+};
+
+static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
+       /* PLLE special case: use cpcon field to store cml divider value */
+       {336000000, 100000000, 100, 21, 16, 11},
+       {312000000, 100000000, 200, 26, 24, 13},
+       {0, 0, 0, 0, 0, 0},
+};
+
+static struct tegra_clk_pll_params pll_e_params = {
+       .input_min = 12000000,
+       .input_max = 1000000000,
+       .cf_min = 12000000,
+       .cf_max = 75000000,
+       .vco_min = 1600000000,
+       .vco_max = 2400000000U,
+       .base_reg = PLLE_BASE,
+       .misc_reg = PLLE_MISC,
+       .aux_reg = PLLE_AUX,
+       .lock_mask = PLLE_MISC_LOCK,
+       .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+};
+
+static struct tegra_clk_pll_params pll_re_vco_params = {
+       .input_min = 12000000,
+       .input_max = 1000000000,
+       .cf_min = 12000000,
+       .cf_max = 19200000, /* s/w policy, h/w capability 38 MHz */
+       .vco_min = 300000000,
+       .vco_max = 600000000,
+       .base_reg = PLLRE_BASE,
+       .misc_reg = PLLRE_MISC,
+       .lock_mask = PLLRE_MISC_LOCK,
+       .lock_enable_bit_idx = PLLRE_MISC_LOCK_ENABLE,
+       .lock_delay = 300,
+       .iddq_reg = PLLRE_MISC,
+       .iddq_bit_idx = PLLRE_IDDQ_BIT,
+};
+
+/* Peripheral clock registers */
+
+static struct tegra_clk_periph_regs periph_l_regs = {
+       .enb_reg = CLK_OUT_ENB_L,
+       .enb_set_reg = CLK_OUT_ENB_SET_L,
+       .enb_clr_reg = CLK_OUT_ENB_CLR_L,
+       .rst_reg = RST_DEVICES_L,
+       .rst_set_reg = RST_DEVICES_SET_L,
+       .rst_clr_reg = RST_DEVICES_CLR_L,
+};
+
+static struct tegra_clk_periph_regs periph_h_regs = {
+       .enb_reg = CLK_OUT_ENB_H,
+       .enb_set_reg = CLK_OUT_ENB_SET_H,
+       .enb_clr_reg = CLK_OUT_ENB_CLR_H,
+       .rst_reg = RST_DEVICES_H,
+       .rst_set_reg = RST_DEVICES_SET_H,
+       .rst_clr_reg = RST_DEVICES_CLR_H,
+};
+
+static struct tegra_clk_periph_regs periph_u_regs = {
+       .enb_reg = CLK_OUT_ENB_U,
+       .enb_set_reg = CLK_OUT_ENB_SET_U,
+       .enb_clr_reg = CLK_OUT_ENB_CLR_U,
+       .rst_reg = RST_DEVICES_U,
+       .rst_set_reg = RST_DEVICES_SET_U,
+       .rst_clr_reg = RST_DEVICES_CLR_U,
+};
+
+static struct tegra_clk_periph_regs periph_v_regs = {
+       .enb_reg = CLK_OUT_ENB_V,
+       .enb_set_reg = CLK_OUT_ENB_SET_V,
+       .enb_clr_reg = CLK_OUT_ENB_CLR_V,
+       .rst_reg = RST_DEVICES_V,
+       .rst_set_reg = RST_DEVICES_SET_V,
+       .rst_clr_reg = RST_DEVICES_CLR_V,
+};
+
+static struct tegra_clk_periph_regs periph_w_regs = {
+       .enb_reg = CLK_OUT_ENB_W,
+       .enb_set_reg = CLK_OUT_ENB_SET_W,
+       .enb_clr_reg = CLK_OUT_ENB_CLR_W,
+       .rst_reg = RST_DEVICES_W,
+       .rst_set_reg = RST_DEVICES_SET_W,
+       .rst_clr_reg = RST_DEVICES_CLR_W,
+};
+
+/* possible OSC frequencies in Hz */
+static unsigned long tegra114_input_freq[] = {
+       [0] = 13000000,
+       [1] = 16800000,
+       [4] = 19200000,
+       [5] = 38400000,
+       [8] = 12000000,
+       [9] = 48000000,
+       [12] = 260000000,
+};
+
+#define MASK(x) (BIT(x) - 1)
+
+#define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset,        \
+                           _clk_num, _regs, _gate_flags, _clk_id)      \
+       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+                       30, MASK(2), 0, 0, 8, 1, 0, _regs, _clk_num,    \
+                       periph_clk_enb_refcnt, _gate_flags, _clk_id,    \
+                       _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_MUX_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\
+                           _clk_num, _regs, _gate_flags, _clk_id, flags)\
+       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+                       30, MASK(2), 0, 0, 8, 1, 0, _regs, _clk_num,    \
+                       periph_clk_enb_refcnt, _gate_flags, _clk_id,    \
+                       _parents##_idx, flags)
+
+#define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \
+                            _clk_num, _regs, _gate_flags, _clk_id)     \
+       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+                       29, MASK(3), 0, 0, 8, 1, 0, _regs, _clk_num,    \
+                       periph_clk_enb_refcnt, _gate_flags, _clk_id,    \
+                       _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset,        \
+                           _clk_num, _regs, _gate_flags, _clk_id)      \
+       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+                       30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\
+                       _clk_num, periph_clk_enb_refcnt, _gate_flags,   \
+                       _clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_INT_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\
+                           _clk_num, _regs, _gate_flags, _clk_id, flags)\
+       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+                       30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\
+                       _clk_num, periph_clk_enb_refcnt, _gate_flags,   \
+                       _clk_id, _parents##_idx, flags)
+
+#define TEGRA_INIT_DATA_INT8(_name, _con_id, _dev_id, _parents, _offset,\
+                           _clk_num, _regs, _gate_flags, _clk_id)      \
+       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+                       29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\
+                       _clk_num, periph_clk_enb_refcnt, _gate_flags,   \
+                       _clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\
+                            _clk_num, _regs, _clk_id)                  \
+       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+                       30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART, _regs,\
+                       _clk_num, periph_clk_enb_refcnt, 0, _clk_id,    \
+                       _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_I2C(_name, _con_id, _dev_id, _parents, _offset,\
+                            _clk_num, _regs, _clk_id)                  \
+       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+                       30, MASK(2), 0, 0, 16, 0, 0, _regs, _clk_num,   \
+                       periph_clk_enb_refcnt, 0, _clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \
+                             _mux_shift, _mux_mask, _clk_num, _regs,   \
+                             _gate_flags, _clk_id)                     \
+       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\
+                       _mux_shift, _mux_mask, 0, 0, 0, 0, 0, _regs,    \
+                       _clk_num, periph_clk_enb_refcnt, _gate_flags,   \
+                       _clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_XUSB(_name, _con_id, _dev_id, _parents, _offset, \
+                            _clk_num, _regs, _gate_flags, _clk_id)      \
+       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset, \
+                       29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs, \
+                       _clk_num, periph_clk_enb_refcnt, _gate_flags,    \
+                       _clk_id, _parents##_idx, 0)
+
+#define TEGRA_INIT_DATA_AUDIO(_name, _con_id, _dev_id, _offset,  _clk_num,\
+                                _regs, _gate_flags, _clk_id)           \
+       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, mux_d_audio_clk, \
+                       _offset, 16, 0xE01F, 0, 0, 8, 1, 0, _regs, _clk_num, \
+                       periph_clk_enb_refcnt, _gate_flags , _clk_id,   \
+                       mux_d_audio_clk_idx, 0)
+
+enum tegra114_clk {
+       rtc = 4, timer = 5, uarta = 6, sdmmc2 = 9, i2s1 = 11, i2c1 = 12,
+       ndflash = 13, sdmmc1 = 14, sdmmc4 = 15, pwm = 17, i2s2 = 18, epp = 19,
+       gr_2d = 21, usbd = 22, isp = 23, gr_3d = 24, disp2 = 26, disp1 = 27,
+       host1x = 28, vcp = 29, i2s0 = 30, apbdma = 34, kbc = 36, kfuse = 40,
+       sbc1 = 41, nor = 42, sbc2 = 44, sbc3 = 46, i2c5 = 47, dsia = 48,
+       mipi = 50, hdmi = 51, csi = 52, i2c2 = 54, uartc = 55, mipi_cal = 56,
+       emc, usb2, usb3, vde = 61, bsea = 62, bsev = 63, uartd = 65,
+       i2c3 = 67, sbc4 = 68, sdmmc3 = 69, owr = 71, csite = 73,
+       la = 76, trace = 77, soc_therm = 78, dtv = 79, ndspeed = 80,
+       i2cslow = 81, dsib = 82, tsec = 83, xusb_host = 89, msenc = 91,
+       csus = 92, mselect = 99, tsensor = 100, i2s3 = 101, i2s4 = 102,
+       i2c4 = 103, sbc5 = 104, sbc6 = 105, d_audio, apbif = 107, dam0, dam1,
+       dam2, hda2codec_2x = 111, audio0_2x = 113, audio1_2x, audio2_2x,
+       audio3_2x, audio4_2x, spdif_2x, actmon = 119, extern1 = 120,
+       extern2 = 121, extern3 = 122, hda = 125, se = 127, hda2hdmi = 128,
+       cilab = 144, cilcd = 145, cile = 146, dsialp = 147, dsiblp = 148,
+       dds = 150, dp2 = 152, amx = 153, adx = 154, xusb_ss = 156, uartb = 192,
+       vfir, spdif_in, spdif_out, vi, vi_sensor, fuse, fuse_burn, clk_32k,
+       clk_m, clk_m_div2, clk_m_div4, pll_ref, pll_c, pll_c_out1, pll_c2,
+       pll_c3, pll_m, pll_m_out1, pll_p, pll_p_out1, pll_p_out2, pll_p_out3,
+       pll_p_out4, pll_a, pll_a_out0, pll_d, pll_d_out0, pll_d2, pll_d2_out0,
+       pll_u, pll_u_480M, pll_u_60M, pll_u_48M, pll_u_12M, pll_x, pll_x_out0,
+       pll_re_vco, pll_re_out, pll_e_out0, spdif_in_sync, i2s0_sync,
+       i2s1_sync, i2s2_sync, i2s3_sync, i2s4_sync, vimclk_sync, audio0,
+       audio1, audio2, audio3, audio4, spdif, clk_out_1, clk_out_2, clk_out_3,
+       blink, xusb_host_src = 252, xusb_falcon_src, xusb_fs_src, xusb_ss_src,
+       xusb_dev_src, xusb_dev, xusb_hs_src, sclk, hclk, pclk, cclk_g, cclk_lp,
+
+       /* Mux clocks */
+
+       audio0_mux = 300, audio1_mux, audio2_mux, audio3_mux, audio4_mux,
+       spdif_mux, clk_out_1_mux, clk_out_2_mux, clk_out_3_mux, dsia_mux,
+       dsib_mux, clk_max,
+};
+
+struct utmi_clk_param {
+       /* Oscillator Frequency in KHz */
+       u32 osc_frequency;
+       /* UTMIP PLL Enable Delay Count  */
+       u8 enable_delay_count;
+       /* UTMIP PLL Stable count */
+       u8 stable_count;
+       /*  UTMIP PLL Active delay count */
+       u8 active_delay_count;
+       /* UTMIP PLL Xtal frequency count */
+       u8 xtal_freq_count;
+};
+
+static const struct utmi_clk_param utmi_parameters[] = {
+       {.osc_frequency = 13000000, .enable_delay_count = 0x02,
+        .stable_count = 0x33, .active_delay_count = 0x05,
+        .xtal_freq_count = 0x7F},
+       {.osc_frequency = 19200000, .enable_delay_count = 0x03,
+        .stable_count = 0x4B, .active_delay_count = 0x06,
+        .xtal_freq_count = 0xBB},
+       {.osc_frequency = 12000000, .enable_delay_count = 0x02,
+        .stable_count = 0x2F, .active_delay_count = 0x04,
+        .xtal_freq_count = 0x76},
+       {.osc_frequency = 26000000, .enable_delay_count = 0x04,
+        .stable_count = 0x66, .active_delay_count = 0x09,
+        .xtal_freq_count = 0xFE},
+       {.osc_frequency = 16800000, .enable_delay_count = 0x03,
+        .stable_count = 0x41, .active_delay_count = 0x0A,
+        .xtal_freq_count = 0xA4},
+};
+
+/* peripheral mux definitions */
+
+#define MUX_I2S_SPDIF(_id)                                             \
+static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \
+                                                          #_id, "pll_p",\
+                                                          "clk_m"};
+MUX_I2S_SPDIF(audio0)
+MUX_I2S_SPDIF(audio1)
+MUX_I2S_SPDIF(audio2)
+MUX_I2S_SPDIF(audio3)
+MUX_I2S_SPDIF(audio4)
+MUX_I2S_SPDIF(audio)
+
+#define mux_pllaout0_audio0_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio1_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio2_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio3_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio4_2x_pllp_clkm_idx NULL
+#define mux_pllaout0_audio_2x_pllp_clkm_idx NULL
+
+static const char *mux_pllp_pllc_pllm_clkm[] = {
+       "pll_p", "pll_c", "pll_m", "clk_m"
+};
+#define mux_pllp_pllc_pllm_clkm_idx NULL
+
+static const char *mux_pllp_pllc_pllm[] = { "pll_p", "pll_c", "pll_m" };
+#define mux_pllp_pllc_pllm_idx NULL
+
+static const char *mux_pllp_pllc_clk32_clkm[] = {
+       "pll_p", "pll_c", "clk_32k", "clk_m"
+};
+#define mux_pllp_pllc_clk32_clkm_idx NULL
+
+static const char *mux_plla_pllc_pllp_clkm[] = {
+       "pll_a_out0", "pll_c", "pll_p", "clk_m"
+};
+#define mux_plla_pllc_pllp_clkm_idx mux_pllp_pllc_pllm_clkm_idx
+
+static const char *mux_pllp_pllc2_c_c3_pllm_clkm[] = {
+       "pll_p", "pll_c2", "pll_c", "pll_c3", "pll_m", "clk_m"
+};
+static u32 mux_pllp_pllc2_c_c3_pllm_clkm_idx[] = {
+       [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6,
+};
+
+static const char *mux_pllp_clkm[] = {
+       "pll_p", "clk_m"
+};
+static u32 mux_pllp_clkm_idx[] = {
+       [0] = 0, [1] = 3,
+};
+
+static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = {
+       "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0"
+};
+#define mux_pllm_pllc2_c_c3_pllp_plla_idx mux_pllp_pllc2_c_c3_pllm_clkm_idx
+
+static const char *mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = {
+       "pll_p", "pll_m", "pll_d_out0", "pll_a_out0", "pll_c",
+       "pll_d2_out0", "clk_m"
+};
+#define mux_pllp_pllm_plld_plla_pllc_plld2_clkm_idx NULL
+
+static const char *mux_pllm_pllc_pllp_plla[] = {
+       "pll_m", "pll_c", "pll_p", "pll_a_out0"
+};
+#define mux_pllm_pllc_pllp_plla_idx mux_pllp_pllc_pllm_clkm_idx
+
+static const char *mux_pllp_pllc_clkm[] = {
+       "pll_p", "pll_c", "pll_m"
+};
+static u32 mux_pllp_pllc_clkm_idx[] = {
+       [0] = 0, [1] = 1, [2] = 3,
+};
+
+static const char *mux_pllp_pllc_clkm_clk32[] = {
+       "pll_p", "pll_c", "clk_m", "clk_32k"
+};
+#define mux_pllp_pllc_clkm_clk32_idx NULL
+
+static const char *mux_plla_clk32_pllp_clkm_plle[] = {
+       "pll_a_out0", "clk_32k", "pll_p", "clk_m", "pll_e_out0"
+};
+#define mux_plla_clk32_pllp_clkm_plle_idx NULL
+
+static const char *mux_clkm_pllp_pllc_pllre[] = {
+       "clk_m", "pll_p", "pll_c", "pll_re_out"
+};
+static u32 mux_clkm_pllp_pllc_pllre_idx[] = {
+       [0] = 0, [1] = 1, [2] = 3, [3] = 5,
+};
+
+static const char *mux_clkm_48M_pllp_480M[] = {
+       "clk_m", "pll_u_48M", "pll_p", "pll_u_480M"
+};
+#define mux_clkm_48M_pllp_480M_idx NULL
+
+static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = {
+       "clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref"
+};
+static u32 mux_clkm_pllre_clk32_480M_pllc_ref_idx[] = {
+       [0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7,
+};
+
+static const char *mux_plld_out0_plld2_out0[] = {
+       "pll_d_out0", "pll_d2_out0",
+};
+#define mux_plld_out0_plld2_out0_idx NULL
+
+static const char *mux_d_audio_clk[] = {
+       "pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync",
+       "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
+};
+static u32 mux_d_audio_clk_idx[] = {
+       [0] = 0, [1] = 0x8000, [2] = 0xc000, [3] = 0xE000, [4] = 0xE001,
+       [5] = 0xE002, [6] = 0xE003, [7] = 0xE004, [8] = 0xE005, [9] = 0xE007,
+};
+
+static const char *mux_pllmcp_clkm[] = {
+       "pll_m_out0", "pll_c_out0", "pll_p_out0", "clk_m", "pll_m_ud",
+};
+
+static const struct clk_div_table pll_re_div_table[] = {
+       { .val = 0, .div = 1 },
+       { .val = 1, .div = 2 },
+       { .val = 2, .div = 3 },
+       { .val = 3, .div = 4 },
+       { .val = 4, .div = 5 },
+       { .val = 5, .div = 6 },
+       { .val = 0, .div = 0 },
+};
+
+static struct clk *clks[clk_max];
+static struct clk_onecell_data clk_data;
+
+static unsigned long osc_freq;
+static unsigned long pll_ref_freq;
+
+static int __init tegra114_osc_clk_init(void __iomem *clk_base)
+{
+       struct clk *clk;
+       u32 val, pll_ref_div;
+
+       val = readl_relaxed(clk_base + OSC_CTRL);
+
+       osc_freq = tegra114_input_freq[val >> OSC_CTRL_OSC_FREQ_SHIFT];
+       if (!osc_freq) {
+               WARN_ON(1);
+               return -EINVAL;
+       }
+
+       /* clk_m */
+       clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT,
+                                     osc_freq);
+       clk_register_clkdev(clk, "clk_m", NULL);
+       clks[clk_m] = clk;
+
+       /* pll_ref */
+       val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3;
+       pll_ref_div = 1 << val;
+       clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",
+                                       CLK_SET_RATE_PARENT, 1, pll_ref_div);
+       clk_register_clkdev(clk, "pll_ref", NULL);
+       clks[pll_ref] = clk;
+
+       pll_ref_freq = osc_freq / pll_ref_div;
+
+       return 0;
+}
+
+static void __init tegra114_fixed_clk_init(void __iomem *clk_base)
+{
+       struct clk *clk;
+
+       /* clk_32k */
+       clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT,
+                                     32768);
+       clk_register_clkdev(clk, "clk_32k", NULL);
+       clks[clk_32k] = clk;
+
+       /* clk_m_div2 */
+       clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m",
+                                       CLK_SET_RATE_PARENT, 1, 2);
+       clk_register_clkdev(clk, "clk_m_div2", NULL);
+       clks[clk_m_div2] = clk;
+
+       /* clk_m_div4 */
+       clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m",
+                                       CLK_SET_RATE_PARENT, 1, 4);
+       clk_register_clkdev(clk, "clk_m_div4", NULL);
+       clks[clk_m_div4] = clk;
+
+}
+
+static __init void tegra114_utmi_param_configure(void __iomem *clk_base)
+{
+       u32 reg;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
+               if (osc_freq == utmi_parameters[i].osc_frequency)
+                       break;
+       }
+
+       if (i >= ARRAY_SIZE(utmi_parameters)) {
+               pr_err("%s: Unexpected oscillator freq %lu\n", __func__,
+                      osc_freq);
+               return;
+       }
+
+       reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2);
+
+       /* Program UTMIP PLL stable and active counts */
+       /* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */
+       reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
+       reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count);
+
+       reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
+
+       reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i].
+                                           active_delay_count);
+
+       /* Remove power downs from UTMIP PLL control bits */
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN;
+
+       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2);
+
+       /* Program UTMIP PLL delay and oscillator frequency counts */
+       reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+       reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
+
+       reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i].
+                                           enable_delay_count);
+
+       reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
+       reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(utmi_parameters[i].
+                                          xtal_freq_count);
+
+       /* Remove power downs from UTMIP PLL control bits */
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP;
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
+       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+
+       /* Setup HW control of UTMIPLL */
+       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
+       reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
+       reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE;
+       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+       reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+
+       udelay(1);
+
+       /* Setup SW override of UTMIPLL assuming USB2.0
+          ports are assigned to USB2 */
+       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL;
+       reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
+       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+       udelay(1);
+
+       /* Enable HW control UTMIPLL */
+       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
+       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+}
+
+static void __init _clip_vco_min(struct tegra_clk_pll_params *pll_params)
+{
+       pll_params->vco_min =
+               DIV_ROUND_UP(pll_params->vco_min, pll_ref_freq) * pll_ref_freq;
+}
+
+static int __init _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params,
+                                     void __iomem *clk_base)
+{
+       u32 val;
+       u32 step_a, step_b;
+
+       switch (pll_ref_freq) {
+       case 12000000:
+       case 13000000:
+       case 26000000:
+               step_a = 0x2B;
+               step_b = 0x0B;
+               break;
+       case 16800000:
+               step_a = 0x1A;
+               step_b = 0x09;
+               break;
+       case 19200000:
+               step_a = 0x12;
+               step_b = 0x08;
+               break;
+       default:
+               pr_err("%s: Unexpected reference rate %lu\n",
+                       __func__, pll_ref_freq);
+               WARN_ON(1);
+               return -EINVAL;
+       }
+
+       val = step_a << pll_params->stepa_shift;
+       val |= step_b << pll_params->stepb_shift;
+       writel_relaxed(val, clk_base + pll_params->dyn_ramp_reg);
+
+       return 0;
+}
+
+static void __init _init_iddq(struct tegra_clk_pll_params *pll_params,
+                             void __iomem *clk_base)
+{
+       u32 val, val_iddq;
+
+       val = readl_relaxed(clk_base + pll_params->base_reg);
+       val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg);
+
+       if (val & BIT(30))
+               WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx));
+       else {
+               val_iddq |= BIT(pll_params->iddq_bit_idx);
+               writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg);
+       }
+}
+
+static void __init tegra114_pll_init(void __iomem *clk_base,
+                                    void __iomem *pmc)
+{
+       u32 val;
+       struct clk *clk;
+
+       /* PLLC */
+       _clip_vco_min(&pll_c_params);
+       if (_setup_dynamic_ramp(&pll_c_params, clk_base) >= 0) {
+               _init_iddq(&pll_c_params, clk_base);
+               clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base,
+                               pmc, 0, 0, &pll_c_params, TEGRA_PLL_USE_LOCK,
+                               pll_c_freq_table, NULL);
+               clk_register_clkdev(clk, "pll_c", NULL);
+               clks[pll_c] = clk;
+
+               /* PLLC_OUT1 */
+               clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c",
+                               clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+                               8, 8, 1, NULL);
+               clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div",
+                                       clk_base + PLLC_OUT, 1, 0,
+                                       CLK_SET_RATE_PARENT, 0, NULL);
+               clk_register_clkdev(clk, "pll_c_out1", NULL);
+               clks[pll_c_out1] = clk;
+       }
+
+       /* PLLC2 */
+       _clip_vco_min(&pll_c2_params);
+       clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, 0,
+                            &pll_c2_params, TEGRA_PLL_USE_LOCK,
+                            pll_cx_freq_table, NULL);
+       clk_register_clkdev(clk, "pll_c2", NULL);
+       clks[pll_c2] = clk;
+
+       /* PLLC3 */
+       _clip_vco_min(&pll_c3_params);
+       clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0, 0,
+                            &pll_c3_params, TEGRA_PLL_USE_LOCK,
+                            pll_cx_freq_table, NULL);
+       clk_register_clkdev(clk, "pll_c3", NULL);
+       clks[pll_c3] = clk;
+
+       /* PLLP */
+       clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, pmc, 0,
+                           408000000, &pll_p_params,
+                           TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK,
+                           pll_p_freq_table, NULL);
+       clk_register_clkdev(clk, "pll_p", NULL);
+       clks[pll_p] = clk;
+
+       /* PLLP_OUT1 */
+       clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p",
+                               clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
+                               TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, &pll_div_lock);
+       clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div",
+                               clk_base + PLLP_OUTA, 1, 0,
+                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+                               &pll_div_lock);
+       clk_register_clkdev(clk, "pll_p_out1", NULL);
+       clks[pll_p_out1] = clk;
+
+       /* PLLP_OUT2 */
+       clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p",
+                               clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
+                               TEGRA_DIVIDER_ROUND_UP, 24, 8, 1,
+                               &pll_div_lock);
+       clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div",
+                               clk_base + PLLP_OUTA, 17, 16,
+                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+                               &pll_div_lock);
+       clk_register_clkdev(clk, "pll_p_out2", NULL);
+       clks[pll_p_out2] = clk;
+
+       /* PLLP_OUT3 */
+       clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p",
+                               clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED |
+                               TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, &pll_div_lock);
+       clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div",
+                               clk_base + PLLP_OUTB, 1, 0,
+                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+                               &pll_div_lock);
+       clk_register_clkdev(clk, "pll_p_out3", NULL);
+       clks[pll_p_out3] = clk;
+
+       /* PLLP_OUT4 */
+       clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p",
+                               clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED |
+                               TEGRA_DIVIDER_ROUND_UP, 24, 8, 1,
+                               &pll_div_lock);
+       clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div",
+                               clk_base + PLLP_OUTB, 17, 16,
+                               CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+                               &pll_div_lock);
+       clk_register_clkdev(clk, "pll_p_out4", NULL);
+       clks[pll_p_out4] = clk;
+
+       /* PLLM */
+       _clip_vco_min(&pll_m_params);
+       clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc,
+                            CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0,
+                            &pll_m_params, TEGRA_PLL_USE_LOCK,
+                            pll_m_freq_table, NULL);
+       clk_register_clkdev(clk, "pll_m", NULL);
+       clks[pll_m] = clk;
+
+       /* PLLM_OUT1 */
+       clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m",
+                               clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+                               8, 8, 1, NULL);
+       clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
+                               clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
+                               CLK_SET_RATE_PARENT, 0, NULL);
+       clk_register_clkdev(clk, "pll_m_out1", NULL);
+       clks[pll_m_out1] = clk;
+
+       /* PLLM_UD */
+       clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m",
+                                       CLK_SET_RATE_PARENT, 1, 1);
+
+       /* PLLX */
+       _clip_vco_min(&pll_x_params);
+       if (_setup_dynamic_ramp(&pll_x_params, clk_base) >= 0) {
+               _init_iddq(&pll_x_params, clk_base);
+               clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base,
+                               pmc, CLK_IGNORE_UNUSED, 0, &pll_x_params,
+                               TEGRA_PLL_USE_LOCK, pll_x_freq_table, NULL);
+               clk_register_clkdev(clk, "pll_x", NULL);
+               clks[pll_x] = clk;
+       }
+
+       /* PLLX_OUT0 */
+       clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x",
+                                       CLK_SET_RATE_PARENT, 1, 2);
+       clk_register_clkdev(clk, "pll_x_out0", NULL);
+       clks[pll_x_out0] = clk;
+
+       /* PLLU */
+       val = readl(clk_base + pll_u_params.base_reg);
+       val &= ~BIT(24); /* disable PLLU_OVERRIDE */
+       writel(val, clk_base + pll_u_params.base_reg);
+
+       clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc, 0,
+                           0, &pll_u_params, TEGRA_PLLU |
+                           TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+                           TEGRA_PLL_USE_LOCK, pll_u_freq_table, &pll_u_lock);
+       clk_register_clkdev(clk, "pll_u", NULL);
+       clks[pll_u] = clk;
+
+       tegra114_utmi_param_configure(clk_base);
+
+       /* PLLU_480M */
+       clk = clk_register_gate(NULL, "pll_u_480M", "pll_u",
+                               CLK_SET_RATE_PARENT, clk_base + PLLU_BASE,
+                               22, 0, &pll_u_lock);
+       clk_register_clkdev(clk, "pll_u_480M", NULL);
+       clks[pll_u_480M] = clk;
+
+       /* PLLU_60M */
+       clk = clk_register_fixed_factor(NULL, "pll_u_60M", "pll_u",
+                                       CLK_SET_RATE_PARENT, 1, 8);
+       clk_register_clkdev(clk, "pll_u_60M", NULL);
+       clks[pll_u_60M] = clk;
+
+       /* PLLU_48M */
+       clk = clk_register_fixed_factor(NULL, "pll_u_48M", "pll_u",
+                                       CLK_SET_RATE_PARENT, 1, 10);
+       clk_register_clkdev(clk, "pll_u_48M", NULL);
+       clks[pll_u_48M] = clk;
+
+       /* PLLU_12M */
+       clk = clk_register_fixed_factor(NULL, "pll_u_12M", "pll_u",
+                                       CLK_SET_RATE_PARENT, 1, 40);
+       clk_register_clkdev(clk, "pll_u_12M", NULL);
+       clks[pll_u_12M] = clk;
+
+       /* PLLD */
+       clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc, 0,
+                           0, &pll_d_params,
+                           TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+                           TEGRA_PLL_USE_LOCK, pll_d_freq_table, &pll_d_lock);
+       clk_register_clkdev(clk, "pll_d", NULL);
+       clks[pll_d] = clk;
+
+       /* PLLD_OUT0 */
+       clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d",
+                                       CLK_SET_RATE_PARENT, 1, 2);
+       clk_register_clkdev(clk, "pll_d_out0", NULL);
+       clks[pll_d_out0] = clk;
+
+       /* PLLD2 */
+       clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc, 0,
+                           0, &pll_d2_params,
+                           TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON |
+                           TEGRA_PLL_USE_LOCK, pll_d_freq_table, &pll_d2_lock);
+       clk_register_clkdev(clk, "pll_d2", NULL);
+       clks[pll_d2] = clk;
+
+       /* PLLD2_OUT0 */
+       clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2",
+                                       CLK_SET_RATE_PARENT, 1, 2);
+       clk_register_clkdev(clk, "pll_d2_out0", NULL);
+       clks[pll_d2_out0] = clk;
+
+       /* PLLA */
+       clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, pmc, 0,
+                           0, &pll_a_params, TEGRA_PLL_HAS_CPCON |
+                           TEGRA_PLL_USE_LOCK, pll_a_freq_table, NULL);
+       clk_register_clkdev(clk, "pll_a", NULL);
+       clks[pll_a] = clk;
+
+       /* PLLA_OUT0 */
+       clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a",
+                               clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+                               8, 8, 1, NULL);
+       clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div",
+                               clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED |
+                               CLK_SET_RATE_PARENT, 0, NULL);
+       clk_register_clkdev(clk, "pll_a_out0", NULL);
+       clks[pll_a_out0] = clk;
+
+       /* PLLRE */
+       _clip_vco_min(&pll_re_vco_params);
+       clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc,
+                            0, 0, &pll_re_vco_params, TEGRA_PLL_USE_LOCK,
+                            NULL, &pll_re_lock, pll_ref_freq);
+       clk_register_clkdev(clk, "pll_re_vco", NULL);
+       clks[pll_re_vco] = clk;
+
+       clk = clk_register_divider_table(NULL, "pll_re_out", "pll_re_vco", 0,
+                                        clk_base + PLLRE_BASE, 16, 4, 0,
+                                        pll_re_div_table, &pll_re_lock);
+       clk_register_clkdev(clk, "pll_re_out", NULL);
+       clks[pll_re_out] = clk;
+
+       /* PLLE */
+       clk = tegra_clk_register_plle_tegra114("pll_e_out0", "pll_re_vco",
+                                     clk_base, 0, 100000000, &pll_e_params,
+                                     pll_e_freq_table, NULL);
+       clk_register_clkdev(clk, "pll_e_out0", NULL);
+       clks[pll_e_out0] = clk;
+}
+
+static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync",
+       "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
+};
+
+static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2",
+       "clk_m_div4", "extern1",
+};
+
+static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2",
+       "clk_m_div4", "extern2",
+};
+
+static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2",
+       "clk_m_div4", "extern3",
+};
+
+static void __init tegra114_audio_clk_init(void __iomem *clk_base)
+{
+       struct clk *clk;
+
+       /* spdif_in_sync */
+       clk = tegra_clk_register_sync_source("spdif_in_sync", 24000000,
+                                            24000000);
+       clk_register_clkdev(clk, "spdif_in_sync", NULL);
+       clks[spdif_in_sync] = clk;
+
+       /* i2s0_sync */
+       clk = tegra_clk_register_sync_source("i2s0_sync", 24000000, 24000000);
+       clk_register_clkdev(clk, "i2s0_sync", NULL);
+       clks[i2s0_sync] = clk;
+
+       /* i2s1_sync */
+       clk = tegra_clk_register_sync_source("i2s1_sync", 24000000, 24000000);
+       clk_register_clkdev(clk, "i2s1_sync", NULL);
+       clks[i2s1_sync] = clk;
+
+       /* i2s2_sync */
+       clk = tegra_clk_register_sync_source("i2s2_sync", 24000000, 24000000);
+       clk_register_clkdev(clk, "i2s2_sync", NULL);
+       clks[i2s2_sync] = clk;
+
+       /* i2s3_sync */
+       clk = tegra_clk_register_sync_source("i2s3_sync", 24000000, 24000000);
+       clk_register_clkdev(clk, "i2s3_sync", NULL);
+       clks[i2s3_sync] = clk;
+
+       /* i2s4_sync */
+       clk = tegra_clk_register_sync_source("i2s4_sync", 24000000, 24000000);
+       clk_register_clkdev(clk, "i2s4_sync", NULL);
+       clks[i2s4_sync] = clk;
+
+       /* vimclk_sync */
+       clk = tegra_clk_register_sync_source("vimclk_sync", 24000000, 24000000);
+       clk_register_clkdev(clk, "vimclk_sync", NULL);
+       clks[vimclk_sync] = clk;
+
+       /* audio0 */
+       clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk,
+                              ARRAY_SIZE(mux_audio_sync_clk), 0,
+                              clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0,
+                              NULL);
+       clks[audio0_mux] = clk;
+       clk = clk_register_gate(NULL, "audio0", "audio0_mux", 0,
+                               clk_base + AUDIO_SYNC_CLK_I2S0, 4,
+                               CLK_GATE_SET_TO_DISABLE, NULL);
+       clk_register_clkdev(clk, "audio0", NULL);
+       clks[audio0] = clk;
+
+       /* audio1 */
+       clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk,
+                              ARRAY_SIZE(mux_audio_sync_clk), 0,
+                              clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0,
+                              NULL);
+       clks[audio1_mux] = clk;
+       clk = clk_register_gate(NULL, "audio1", "audio1_mux", 0,
+                               clk_base + AUDIO_SYNC_CLK_I2S1, 4,
+                               CLK_GATE_SET_TO_DISABLE, NULL);
+       clk_register_clkdev(clk, "audio1", NULL);
+       clks[audio1] = clk;
+
+       /* audio2 */
+       clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk,
+                              ARRAY_SIZE(mux_audio_sync_clk), 0,
+                              clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0,
+                              NULL);
+       clks[audio2_mux] = clk;
+       clk = clk_register_gate(NULL, "audio2", "audio2_mux", 0,
+                               clk_base + AUDIO_SYNC_CLK_I2S2, 4,
+                               CLK_GATE_SET_TO_DISABLE, NULL);
+       clk_register_clkdev(clk, "audio2", NULL);
+       clks[audio2] = clk;
+
+       /* audio3 */
+       clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk,
+                              ARRAY_SIZE(mux_audio_sync_clk), 0,
+                              clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0,
+                              NULL);
+       clks[audio3_mux] = clk;
+       clk = clk_register_gate(NULL, "audio3", "audio3_mux", 0,
+                               clk_base + AUDIO_SYNC_CLK_I2S3, 4,
+                               CLK_GATE_SET_TO_DISABLE, NULL);
+       clk_register_clkdev(clk, "audio3", NULL);
+       clks[audio3] = clk;
+
+       /* audio4 */
+       clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk,
+                              ARRAY_SIZE(mux_audio_sync_clk), 0,
+                              clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0,
+                              NULL);
+       clks[audio4_mux] = clk;
+       clk = clk_register_gate(NULL, "audio4", "audio4_mux", 0,
+                               clk_base + AUDIO_SYNC_CLK_I2S4, 4,
+                               CLK_GATE_SET_TO_DISABLE, NULL);
+       clk_register_clkdev(clk, "audio4", NULL);
+       clks[audio4] = clk;
+
+       /* spdif */
+       clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk,
+                              ARRAY_SIZE(mux_audio_sync_clk), 0,
+                              clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0,
+                              NULL);
+       clks[spdif_mux] = clk;
+       clk = clk_register_gate(NULL, "spdif", "spdif_mux", 0,
+                               clk_base + AUDIO_SYNC_CLK_SPDIF, 4,
+                               CLK_GATE_SET_TO_DISABLE, NULL);
+       clk_register_clkdev(clk, "spdif", NULL);
+       clks[spdif] = clk;
+
+       /* audio0_2x */
+       clk = clk_register_fixed_factor(NULL, "audio0_doubler", "audio0",
+                                       CLK_SET_RATE_PARENT, 2, 1);
+       clk = tegra_clk_register_divider("audio0_div", "audio0_doubler",
+                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 24, 1,
+                               0, &clk_doubler_lock);
+       clk = tegra_clk_register_periph_gate("audio0_2x", "audio0_div",
+                                 TEGRA_PERIPH_NO_RESET, clk_base,
+                                 CLK_SET_RATE_PARENT, 113, &periph_v_regs,
+                                 periph_clk_enb_refcnt);
+       clk_register_clkdev(clk, "audio0_2x", NULL);
+       clks[audio0_2x] = clk;
+
+       /* audio1_2x */
+       clk = clk_register_fixed_factor(NULL, "audio1_doubler", "audio1",
+                                       CLK_SET_RATE_PARENT, 2, 1);
+       clk = tegra_clk_register_divider("audio1_div", "audio1_doubler",
+                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 25, 1,
+                               0, &clk_doubler_lock);
+       clk = tegra_clk_register_periph_gate("audio1_2x", "audio1_div",
+                                 TEGRA_PERIPH_NO_RESET, clk_base,
+                                 CLK_SET_RATE_PARENT, 114, &periph_v_regs,
+                                 periph_clk_enb_refcnt);
+       clk_register_clkdev(clk, "audio1_2x", NULL);
+       clks[audio1_2x] = clk;
+
+       /* audio2_2x */
+       clk = clk_register_fixed_factor(NULL, "audio2_doubler", "audio2",
+                                       CLK_SET_RATE_PARENT, 2, 1);
+       clk = tegra_clk_register_divider("audio2_div", "audio2_doubler",
+                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 26, 1,
+                               0, &clk_doubler_lock);
+       clk = tegra_clk_register_periph_gate("audio2_2x", "audio2_div",
+                                 TEGRA_PERIPH_NO_RESET, clk_base,
+                                 CLK_SET_RATE_PARENT, 115, &periph_v_regs,
+                                 periph_clk_enb_refcnt);
+       clk_register_clkdev(clk, "audio2_2x", NULL);
+       clks[audio2_2x] = clk;
+
+       /* audio3_2x */
+       clk = clk_register_fixed_factor(NULL, "audio3_doubler", "audio3",
+                                       CLK_SET_RATE_PARENT, 2, 1);
+       clk = tegra_clk_register_divider("audio3_div", "audio3_doubler",
+                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 27, 1,
+                               0, &clk_doubler_lock);
+       clk = tegra_clk_register_periph_gate("audio3_2x", "audio3_div",
+                                 TEGRA_PERIPH_NO_RESET, clk_base,
+                                 CLK_SET_RATE_PARENT, 116, &periph_v_regs,
+                                 periph_clk_enb_refcnt);
+       clk_register_clkdev(clk, "audio3_2x", NULL);
+       clks[audio3_2x] = clk;
+
+       /* audio4_2x */
+       clk = clk_register_fixed_factor(NULL, "audio4_doubler", "audio4",
+                                       CLK_SET_RATE_PARENT, 2, 1);
+       clk = tegra_clk_register_divider("audio4_div", "audio4_doubler",
+                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 28, 1,
+                               0, &clk_doubler_lock);
+       clk = tegra_clk_register_periph_gate("audio4_2x", "audio4_div",
+                                 TEGRA_PERIPH_NO_RESET, clk_base,
+                                 CLK_SET_RATE_PARENT, 117, &periph_v_regs,
+                                 periph_clk_enb_refcnt);
+       clk_register_clkdev(clk, "audio4_2x", NULL);
+       clks[audio4_2x] = clk;
+
+       /* spdif_2x */
+       clk = clk_register_fixed_factor(NULL, "spdif_doubler", "spdif",
+                                       CLK_SET_RATE_PARENT, 2, 1);
+       clk = tegra_clk_register_divider("spdif_div", "spdif_doubler",
+                               clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 29, 1,
+                               0, &clk_doubler_lock);
+       clk = tegra_clk_register_periph_gate("spdif_2x", "spdif_div",
+                                 TEGRA_PERIPH_NO_RESET, clk_base,
+                                 CLK_SET_RATE_PARENT, 118,
+                                 &periph_v_regs, periph_clk_enb_refcnt);
+       clk_register_clkdev(clk, "spdif_2x", NULL);
+       clks[spdif_2x] = clk;
+}
+
+static void __init tegra114_pmc_clk_init(void __iomem *pmc_base)
+{
+       struct clk *clk;
+
+       /* clk_out_1 */
+       clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents,
+                              ARRAY_SIZE(clk_out1_parents), 0,
+                              pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0,
+                              &clk_out_lock);
+       clks[clk_out_1_mux] = clk;
+       clk = clk_register_gate(NULL, "clk_out_1", "clk_out_1_mux", 0,
+                               pmc_base + PMC_CLK_OUT_CNTRL, 2, 0,
+                               &clk_out_lock);
+       clk_register_clkdev(clk, "extern1", "clk_out_1");
+       clks[clk_out_1] = clk;
+
+       /* clk_out_2 */
+       clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
+                              ARRAY_SIZE(clk_out1_parents), 0,
+                              pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
+                              &clk_out_lock);
+       clks[clk_out_2_mux] = clk;
+       clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0,
+                               pmc_base + PMC_CLK_OUT_CNTRL, 10, 0,
+                               &clk_out_lock);
+       clk_register_clkdev(clk, "extern2", "clk_out_2");
+       clks[clk_out_2] = clk;
+
+       /* clk_out_3 */
+       clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
+                              ARRAY_SIZE(clk_out1_parents), 0,
+                              pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
+                              &clk_out_lock);
+       clks[clk_out_3_mux] = clk;
+       clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0,
+                               pmc_base + PMC_CLK_OUT_CNTRL, 18, 0,
+                               &clk_out_lock);
+       clk_register_clkdev(clk, "extern3", "clk_out_3");
+       clks[clk_out_3] = clk;
+
+       /* blink */
+       clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
+                               pmc_base + PMC_DPD_PADS_ORIDE,
+                               PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
+       clk = clk_register_gate(NULL, "blink", "blink_override", 0,
+                               pmc_base + PMC_CTRL,
+                               PMC_CTRL_BLINK_ENB, 0, NULL);
+       clk_register_clkdev(clk, "blink", NULL);
+       clks[blink] = clk;
+
+}
+
+static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
+                              "pll_p_out3", "pll_p_out2", "unused",
+                              "clk_32k", "pll_m_out1" };
+
+static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
+                                       "pll_p", "pll_p_out4", "unused",
+                                       "unused", "pll_x" };
+
+static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
+                                        "pll_p", "pll_p_out4", "unused",
+                                        "unused", "pll_x", "pll_x_out0" };
+
+static void __init tegra114_super_clk_init(void __iomem *clk_base)
+{
+       struct clk *clk;
+
+       /* CCLKG */
+       clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents,
+                                       ARRAY_SIZE(cclk_g_parents),
+                                       CLK_SET_RATE_PARENT,
+                                       clk_base + CCLKG_BURST_POLICY,
+                                       0, 4, 0, 0, NULL);
+       clk_register_clkdev(clk, "cclk_g", NULL);
+       clks[cclk_g] = clk;
+
+       /* CCLKLP */
+       clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents,
+                                       ARRAY_SIZE(cclk_lp_parents),
+                                       CLK_SET_RATE_PARENT,
+                                       clk_base + CCLKLP_BURST_POLICY,
+                                       0, 4, 8, 9, NULL);
+       clk_register_clkdev(clk, "cclk_lp", NULL);
+       clks[cclk_lp] = clk;
+
+       /* SCLK */
+       clk = tegra_clk_register_super_mux("sclk", sclk_parents,
+                                       ARRAY_SIZE(sclk_parents),
+                                       CLK_SET_RATE_PARENT,
+                                       clk_base + SCLK_BURST_POLICY,
+                                       0, 4, 0, 0, NULL);
+       clk_register_clkdev(clk, "sclk", NULL);
+       clks[sclk] = clk;
+
+       /* HCLK */
+       clk = clk_register_divider(NULL, "hclk_div", "sclk", 0,
+                                  clk_base + SYSTEM_CLK_RATE, 4, 2, 0,
+                                  &sysrate_lock);
+       clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT |
+                               CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE,
+                               7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
+       clk_register_clkdev(clk, "hclk", NULL);
+       clks[hclk] = clk;
+
+       /* PCLK */
+       clk = clk_register_divider(NULL, "pclk_div", "hclk", 0,
+                                  clk_base + SYSTEM_CLK_RATE, 0, 2, 0,
+                                  &sysrate_lock);
+       clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT |
+                               CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE,
+                               3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock);
+       clk_register_clkdev(clk, "pclk", NULL);
+       clks[pclk] = clk;
+}
+
+static struct tegra_periph_init_data tegra_periph_clk_list[] = {
+       TEGRA_INIT_DATA_MUX("i2s0", NULL, "tegra30-i2s.0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s0),
+       TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra30-i2s.1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1),
+       TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra30-i2s.2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2),
+       TEGRA_INIT_DATA_MUX("i2s3", NULL, "tegra30-i2s.3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s3),
+       TEGRA_INIT_DATA_MUX("i2s4", NULL, "tegra30-i2s.4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s4),
+       TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra30-spdif", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out),
+       TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra30-spdif", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in),
+       TEGRA_INIT_DATA_MUX("pwm", NULL, "pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, &periph_l_regs, TEGRA_PERIPH_ON_APB, pwm),
+       TEGRA_INIT_DATA_MUX("adx", NULL, "adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, &periph_w_regs, TEGRA_PERIPH_ON_APB, adx),
+       TEGRA_INIT_DATA_MUX("amx", NULL, "amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, &periph_w_regs, TEGRA_PERIPH_ON_APB, amx),
+       TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, &periph_v_regs, TEGRA_PERIPH_ON_APB, hda),
+       TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, &periph_v_regs, TEGRA_PERIPH_ON_APB, hda2codec_2x),
+       TEGRA_INIT_DATA_MUX("sbc1", NULL, "tegra11-spi.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1),
+       TEGRA_INIT_DATA_MUX("sbc2", NULL, "tegra11-spi.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2),
+       TEGRA_INIT_DATA_MUX("sbc3", NULL, "tegra11-spi.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3),
+       TEGRA_INIT_DATA_MUX("sbc4", NULL, "tegra11-spi.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4),
+       TEGRA_INIT_DATA_MUX("sbc5", NULL, "tegra11-spi.4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC5, 104, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc5),
+       TEGRA_INIT_DATA_MUX("sbc6", NULL, "tegra11-spi.5", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC6, 105, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc6),
+       TEGRA_INIT_DATA_MUX8("ndflash", NULL, "tegra_nand", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed),
+       TEGRA_INIT_DATA_MUX8("ndspeed", NULL, "tegra_nand_speed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed),
+       TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, vfir),
+       TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, &periph_l_regs, 0, sdmmc1),
+       TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, &periph_l_regs, 0, sdmmc2),
+       TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, &periph_u_regs, 0, sdmmc3),
+       TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, &periph_l_regs, 0, sdmmc4),
+       TEGRA_INIT_DATA_INT("vde", NULL, "vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, vde),
+       TEGRA_INIT_DATA_MUX_FLAGS("csite", NULL, "csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, &periph_u_regs, TEGRA_PERIPH_ON_APB, csite, CLK_IGNORE_UNUSED),
+       TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, &periph_u_regs, TEGRA_PERIPH_ON_APB, la),
+       TEGRA_INIT_DATA_MUX("trace", NULL, "trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, &periph_u_regs, TEGRA_PERIPH_ON_APB, trace),
+       TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, &periph_u_regs, TEGRA_PERIPH_ON_APB, owr),
+       TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, &periph_h_regs, 0, nor),
+       TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, &periph_h_regs, TEGRA_PERIPH_ON_APB, mipi),
+       TEGRA_INIT_DATA_I2C("i2c1", "div-clk", "tegra11-i2c.0", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, &periph_l_regs, i2c1),
+       TEGRA_INIT_DATA_I2C("i2c2", "div-clk", "tegra11-i2c.1", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, &periph_h_regs, i2c2),
+       TEGRA_INIT_DATA_I2C("i2c3", "div-clk", "tegra11-i2c.2", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, &periph_u_regs, i2c3),
+       TEGRA_INIT_DATA_I2C("i2c4", "div-clk", "tegra11-i2c.3", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, &periph_v_regs, i2c4),
+       TEGRA_INIT_DATA_I2C("i2c5", "div-clk", "tegra11-i2c.4", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, &periph_h_regs, i2c5),
+       TEGRA_INIT_DATA_UART("uarta", NULL, "tegra_uart.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, &periph_l_regs, uarta),
+       TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, &periph_l_regs, uartb),
+       TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, &periph_h_regs, uartc),
+       TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, &periph_u_regs, uartd),
+       TEGRA_INIT_DATA_INT("3d", NULL, "3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, &periph_l_regs, 0, gr_3d),
+       TEGRA_INIT_DATA_INT("2d", NULL, "2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, &periph_l_regs, 0, gr_2d),
+       TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor),
+       TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, &periph_l_regs, 0, vi),
+       TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, epp),
+       TEGRA_INIT_DATA_INT8("msenc", NULL, "msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, &periph_h_regs, TEGRA_PERIPH_WAR_1005168, msenc),
+       TEGRA_INIT_DATA_INT8("tsec", NULL, "tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, &periph_u_regs, 0, tsec),
+       TEGRA_INIT_DATA_INT8("host1x", NULL, "host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, host1x),
+       TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, hdmi),
+       TEGRA_INIT_DATA_MUX("cilab", "cilab", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, &periph_w_regs, 0, cilab),
+       TEGRA_INIT_DATA_MUX("cilcd", "cilcd", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, &periph_w_regs, 0, cilcd),
+       TEGRA_INIT_DATA_MUX("cile", "cile", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, &periph_w_regs, 0, cile),
+       TEGRA_INIT_DATA_MUX("dsialp", "dsialp", "tegradc.0", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, &periph_w_regs, 0, dsialp),
+       TEGRA_INIT_DATA_MUX("dsiblp", "dsiblp", "tegradc.1", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, &periph_w_regs, 0, dsiblp),
+       TEGRA_INIT_DATA_MUX("tsensor", NULL, "tegra-tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, &periph_v_regs, TEGRA_PERIPH_ON_APB, tsensor),
+       TEGRA_INIT_DATA_MUX("actmon", NULL, "actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, &periph_v_regs, 0, actmon),
+       TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, &periph_v_regs, 0, extern1),
+       TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, &periph_v_regs, 0, extern2),
+       TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, &periph_v_regs, 0, extern3),
+       TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2cslow),
+       TEGRA_INIT_DATA_INT8("se", NULL, "se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, &periph_v_regs, TEGRA_PERIPH_ON_APB, se),
+       TEGRA_INIT_DATA_INT_FLAGS("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, &periph_v_regs, 0, mselect, CLK_IGNORE_UNUSED),
+       TEGRA_INIT_DATA_MUX8("soc_therm", NULL, "soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, &periph_u_regs, TEGRA_PERIPH_ON_APB, soc_therm),
+       TEGRA_INIT_DATA_XUSB("xusb_host_src", "host_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, &periph_w_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_host_src),
+       TEGRA_INIT_DATA_XUSB("xusb_falcon_src", "falcon_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_falcon_src),
+       TEGRA_INIT_DATA_XUSB("xusb_fs_src", "fs_src", "tegra_xhci", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_fs_src),
+       TEGRA_INIT_DATA_XUSB("xusb_ss_src", "ss_src", "tegra_xhci", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_ss_src),
+       TEGRA_INIT_DATA_XUSB("xusb_dev_src", "dev_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, &periph_u_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_dev_src),
+       TEGRA_INIT_DATA_AUDIO("d_audio", "d_audio", "tegra30-ahub", CLK_SOURCE_D_AUDIO, 106, &periph_v_regs, TEGRA_PERIPH_ON_APB, d_audio),
+       TEGRA_INIT_DATA_AUDIO("dam0", NULL, "tegra30-dam.0", CLK_SOURCE_DAM0, 108, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam0),
+       TEGRA_INIT_DATA_AUDIO("dam1", NULL, "tegra30-dam.1", CLK_SOURCE_DAM1, 109, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam1),
+       TEGRA_INIT_DATA_AUDIO("dam2", NULL, "tegra30-dam.2", CLK_SOURCE_DAM2, 110, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam2),
+};
+
+static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = {
+       TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, &periph_l_regs, 0, disp1),
+       TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, &periph_l_regs, 0, disp2),
+};
+
+static __init void tegra114_periph_clk_init(void __iomem *clk_base)
+{
+       struct tegra_periph_init_data *data;
+       struct clk *clk;
+       int i;
+       u32 val;
+
+       /* apbdma */
+       clk = tegra_clk_register_periph_gate("apbdma", "clk_m", 0, clk_base,
+                                 0, 34, &periph_h_regs,
+                                 periph_clk_enb_refcnt);
+       clks[apbdma] = clk;
+
+       /* rtc */
+       clk = tegra_clk_register_periph_gate("rtc", "clk_32k",
+                                   TEGRA_PERIPH_ON_APB |
+                                   TEGRA_PERIPH_NO_RESET, clk_base,
+                                   0, 4, &periph_l_regs,
+                                   periph_clk_enb_refcnt);
+       clk_register_clkdev(clk, NULL, "rtc-tegra");
+       clks[rtc] = clk;
+
+       /* kbc */
+       clk = tegra_clk_register_periph_gate("kbc", "clk_32k",
+                                   TEGRA_PERIPH_ON_APB |
+                                   TEGRA_PERIPH_NO_RESET, clk_base,
+                                   0, 36, &periph_h_regs,
+                                   periph_clk_enb_refcnt);
+       clks[kbc] = clk;
+
+       /* timer */
+       clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base,
+                                 0, 5, &periph_l_regs,
+                                 periph_clk_enb_refcnt);
+       clk_register_clkdev(clk, NULL, "timer");
+       clks[timer] = clk;
+
+       /* kfuse */
+       clk = tegra_clk_register_periph_gate("kfuse", "clk_m",
+                                 TEGRA_PERIPH_ON_APB, clk_base,  0, 40,
+                                 &periph_h_regs, periph_clk_enb_refcnt);
+       clks[kfuse] = clk;
+
+       /* fuse */
+       clk = tegra_clk_register_periph_gate("fuse", "clk_m",
+                                 TEGRA_PERIPH_ON_APB, clk_base,  0, 39,
+                                 &periph_h_regs, periph_clk_enb_refcnt);
+       clks[fuse] = clk;
+
+       /* fuse_burn */
+       clk = tegra_clk_register_periph_gate("fuse_burn", "clk_m",
+                                 TEGRA_PERIPH_ON_APB, clk_base,  0, 39,
+                                 &periph_h_regs, periph_clk_enb_refcnt);
+       clks[fuse_burn] = clk;
+
+       /* apbif */
+       clk = tegra_clk_register_periph_gate("apbif", "clk_m",
+                                 TEGRA_PERIPH_ON_APB, clk_base,  0, 107,
+                                 &periph_v_regs, periph_clk_enb_refcnt);
+       clks[apbif] = clk;
+
+       /* hda2hdmi */
+       clk = tegra_clk_register_periph_gate("hda2hdmi", "clk_m",
+                                   TEGRA_PERIPH_ON_APB, clk_base,  0, 128,
+                                   &periph_w_regs, periph_clk_enb_refcnt);
+       clks[hda2hdmi] = clk;
+
+       /* vcp */
+       clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, clk_base,  0,
+                                 29, &periph_l_regs,
+                                 periph_clk_enb_refcnt);
+       clks[vcp] = clk;
+
+       /* bsea */
+       clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, clk_base,
+                                 0, 62, &periph_h_regs,
+                                 periph_clk_enb_refcnt);
+       clks[bsea] = clk;
+
+       /* bsev */
+       clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, clk_base,
+                                 0, 63, &periph_h_regs,
+                                 periph_clk_enb_refcnt);
+       clks[bsev] = clk;
+
+       /* mipi-cal */
+       clk = tegra_clk_register_periph_gate("mipi-cal", "clk_m", 0, clk_base,
+                                  0, 56, &periph_h_regs,
+                                 periph_clk_enb_refcnt);
+       clks[mipi_cal] = clk;
+
+       /* usbd */
+       clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base,
+                                 0, 22, &periph_l_regs,
+                                 periph_clk_enb_refcnt);
+       clks[usbd] = clk;
+
+       /* usb2 */
+       clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base,
+                                 0, 58, &periph_h_regs,
+                                 periph_clk_enb_refcnt);
+       clks[usb2] = clk;
+
+       /* usb3 */
+       clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base,
+                                 0, 59, &periph_h_regs,
+                                 periph_clk_enb_refcnt);
+       clks[usb3] = clk;
+
+       /* csi */
+       clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base,
+                                  0, 52, &periph_h_regs,
+                                 periph_clk_enb_refcnt);
+       clks[csi] = clk;
+
+       /* isp */
+       clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0,
+                                 23, &periph_l_regs,
+                                 periph_clk_enb_refcnt);
+       clks[isp] = clk;
+
+       /* csus */
+       clk = tegra_clk_register_periph_gate("csus", "clk_m",
+                                 TEGRA_PERIPH_NO_RESET, clk_base, 0, 92,
+                                 &periph_u_regs, periph_clk_enb_refcnt);
+       clks[csus] = clk;
+
+       /* dds */
+       clk = tegra_clk_register_periph_gate("dds", "clk_m",
+                                 TEGRA_PERIPH_ON_APB, clk_base, 0, 150,
+                                 &periph_w_regs, periph_clk_enb_refcnt);
+       clks[dds] = clk;
+
+       /* dp2 */
+       clk = tegra_clk_register_periph_gate("dp2", "clk_m",
+                                 TEGRA_PERIPH_ON_APB, clk_base, 0, 152,
+                                 &periph_w_regs, periph_clk_enb_refcnt);
+       clks[dp2] = clk;
+
+       /* dtv */
+       clk = tegra_clk_register_periph_gate("dtv", "clk_m",
+                                   TEGRA_PERIPH_ON_APB, clk_base, 0, 79,
+                                   &periph_u_regs, periph_clk_enb_refcnt);
+       clks[dtv] = clk;
+
+       /* dsia */
+       clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0,
+                              ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
+                              clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock);
+       clks[dsia_mux] = clk;
+       clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base,
+                                   0, 48, &periph_h_regs,
+                                   periph_clk_enb_refcnt);
+       clks[dsia] = clk;
+
+       /* dsib */
+       clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0,
+                              ARRAY_SIZE(mux_plld_out0_plld2_out0), 0,
+                              clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock);
+       clks[dsib_mux] = clk;
+       clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base,
+                                   0, 82, &periph_u_regs,
+                                   periph_clk_enb_refcnt);
+       clks[dsib] = clk;
+
+       /* xusb_hs_src */
+       val = readl(clk_base + CLK_SOURCE_XUSB_SS_SRC);
+       val |= BIT(25); /* always select PLLU_60M */
+       writel(val, clk_base + CLK_SOURCE_XUSB_SS_SRC);
+
+       clk = clk_register_fixed_factor(NULL, "xusb_hs_src", "pll_u_60M", 0,
+                                       1, 1);
+       clks[xusb_hs_src] = clk;
+
+       /* xusb_host */
+       clk = tegra_clk_register_periph_gate("xusb_host", "xusb_host_src", 0,
+                                   clk_base, 0, 89, &periph_u_regs,
+                                   periph_clk_enb_refcnt);
+       clks[xusb_host] = clk;
+
+       /* xusb_ss */
+       clk = tegra_clk_register_periph_gate("xusb_ss", "xusb_ss_src", 0,
+                                   clk_base, 0, 156, &periph_w_regs,
+                                   periph_clk_enb_refcnt);
+       clks[xusb_host] = clk;
+
+       /* xusb_dev */
+       clk = tegra_clk_register_periph_gate("xusb_dev", "xusb_dev_src", 0,
+                                   clk_base, 0, 95, &periph_u_regs,
+                                   periph_clk_enb_refcnt);
+       clks[xusb_dev] = clk;
+
+       /* emc */
+       clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
+                              ARRAY_SIZE(mux_pllmcp_clkm), 0,
+                              clk_base + CLK_SOURCE_EMC,
+                              29, 3, 0, NULL);
+       clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base,
+                               CLK_IGNORE_UNUSED, 57, &periph_h_regs,
+                               periph_clk_enb_refcnt);
+       clks[emc] = clk;
+
+       for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
+               data = &tegra_periph_clk_list[i];
+               clk = tegra_clk_register_periph(data->name, data->parent_names,
+                               data->num_parents, &data->periph,
+                               clk_base, data->offset, data->flags);
+               clks[data->clk_id] = clk;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) {
+               data = &tegra_periph_nodiv_clk_list[i];
+               clk = tegra_clk_register_periph_nodiv(data->name,
+                               data->parent_names, data->num_parents,
+                               &data->periph, clk_base, data->offset);
+               clks[data->clk_id] = clk;
+       }
+}
+
+static struct tegra_cpu_car_ops tegra114_cpu_car_ops;
+
+static const struct of_device_id pmc_match[] __initconst = {
+       { .compatible = "nvidia,tegra114-pmc" },
+       {},
+};
+
+static __initdata struct tegra_clk_init_table init_table[] = {
+       {uarta, pll_p, 408000000, 0},
+       {uartb, pll_p, 408000000, 0},
+       {uartc, pll_p, 408000000, 0},
+       {uartd, pll_p, 408000000, 0},
+       {pll_a, clk_max, 564480000, 1},
+       {pll_a_out0, clk_max, 11289600, 1},
+       {extern1, pll_a_out0, 0, 1},
+       {clk_out_1_mux, extern1, 0, 1},
+       {clk_out_1, clk_max, 0, 1},
+       {i2s0, pll_a_out0, 11289600, 0},
+       {i2s1, pll_a_out0, 11289600, 0},
+       {i2s2, pll_a_out0, 11289600, 0},
+       {i2s3, pll_a_out0, 11289600, 0},
+       {i2s4, pll_a_out0, 11289600, 0},
+       {clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */
+};
+
+static void __init tegra114_clock_apply_init_table(void)
+{
+       tegra_init_from_table(init_table, clks, clk_max);
+}
+
+void __init tegra114_clock_init(struct device_node *np)
+{
+       struct device_node *node;
+       int i;
+
+       clk_base = of_iomap(np, 0);
+       if (!clk_base) {
+               pr_err("ioremap tegra114 CAR failed\n");
+               return;
+       }
+
+       node = of_find_matching_node(NULL, pmc_match);
+       if (!node) {
+               pr_err("Failed to find pmc node\n");
+               WARN_ON(1);
+               return;
+       }
+
+       pmc_base = of_iomap(node, 0);
+       if (!pmc_base) {
+               pr_err("Can't map pmc registers\n");
+               WARN_ON(1);
+               return;
+       }
+
+       if (tegra114_osc_clk_init(clk_base) < 0)
+               return;
+
+       tegra114_fixed_clk_init(clk_base);
+       tegra114_pll_init(clk_base, pmc_base);
+       tegra114_periph_clk_init(clk_base);
+       tegra114_audio_clk_init(clk_base);
+       tegra114_pmc_clk_init(pmc_base);
+       tegra114_super_clk_init(clk_base);
+
+       for (i = 0; i < ARRAY_SIZE(clks); i++) {
+               if (IS_ERR(clks[i])) {
+                       pr_err
+                           ("Tegra114 clk %d: register failed with %ld\n",
+                            i, PTR_ERR(clks[i]));
+               }
+               if (!clks[i])
+                       clks[i] = ERR_PTR(-EINVAL);
+       }
+
+       clk_data.clks = clks;
+       clk_data.clk_num = ARRAY_SIZE(clks);
+       of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+       tegra_clk_apply_init_table = tegra114_clock_apply_init_table;
+
+       tegra_cpu_car_ops = &tegra114_cpu_car_ops;
+}
index 143ce1f899ad74a5ce447652f64bb48c34b39652..8292a00c3de9f1dbae8b19e23b6ac45b3d275866 100644 (file)
@@ -86,8 +86,8 @@
 #define PLLE_BASE 0xe8
 #define PLLE_MISC 0xec
 
-#define PLL_BASE_LOCK 27
-#define PLLE_MISC_LOCK 11
+#define PLL_BASE_LOCK BIT(27)
+#define PLLE_MISC_LOCK BIT(11)
 
 #define PLL_MISC_LOCK_ENABLE 18
 #define PLLDU_MISC_LOCK_ENABLE 22
@@ -236,7 +236,7 @@ enum tegra20_clk {
        dvc, dsi, mipi = 50, hdmi, csi, tvdac, i2c2, uartc, emc = 57, usb2,
        usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3,
        pex, owr, afi, csite, pcie_xclk, avpucq = 75, la, irama = 84, iramb,
-       iramc, iramd, cram2, audio_2x, clk_d, csus = 92, cdev1, cdev2,
+       iramc, iramd, cram2, audio_2x, clk_d, csus = 92, cdev2, cdev1,
        uartb = 96, vfir, spdif_in, spdif_out, vi, vi_sensor, tvo, cve,
        osc, clk_32k, clk_m, sclk, cclk, hclk, pclk, blink, pll_a, pll_a_out0,
        pll_c, pll_c_out1, pll_d, pll_d_out0, pll_e, pll_m, pll_m_out1,
@@ -248,125 +248,125 @@ static struct clk *clks[clk_max];
 static struct clk_onecell_data clk_data;
 
 static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
-       { 12000000, 600000000, 600, 12, 1, 8 },
-       { 13000000, 600000000, 600, 13, 1, 8 },
-       { 19200000, 600000000, 500, 16, 1, 6 },
-       { 26000000, 600000000, 600, 26, 1, 8 },
+       { 12000000, 600000000, 600, 12, 0, 8 },
+       { 13000000, 600000000, 600, 13, 0, 8 },
+       { 19200000, 600000000, 500, 16, 0, 6 },
+       { 26000000, 600000000, 600, 26, 0, 8 },
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
-       { 12000000, 666000000, 666, 12, 1, 8},
-       { 13000000, 666000000, 666, 13, 1, 8},
-       { 19200000, 666000000, 555, 16, 1, 8},
-       { 26000000, 666000000, 666, 26, 1, 8},
-       { 12000000, 600000000, 600, 12, 1, 8},
-       { 13000000, 600000000, 600, 13, 1, 8},
-       { 19200000, 600000000, 375, 12, 1, 6},
-       { 26000000, 600000000, 600, 26, 1, 8},
+       { 12000000, 666000000, 666, 12, 0, 8},
+       { 13000000, 666000000, 666, 13, 0, 8},
+       { 19200000, 666000000, 555, 16, 0, 8},
+       { 26000000, 666000000, 666, 26, 0, 8},
+       { 12000000, 600000000, 600, 12, 0, 8},
+       { 13000000, 600000000, 600, 13, 0, 8},
+       { 19200000, 600000000, 375, 12, 0, 6},
+       { 26000000, 600000000, 600, 26, 0, 8},
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
-       { 12000000, 216000000, 432, 12, 2, 8},
-       { 13000000, 216000000, 432, 13, 2, 8},
-       { 19200000, 216000000, 90,   4, 2, 1},
-       { 26000000, 216000000, 432, 26, 2, 8},
-       { 12000000, 432000000, 432, 12, 1, 8},
-       { 13000000, 432000000, 432, 13, 1, 8},
-       { 19200000, 432000000, 90,   4, 1, 1},
-       { 26000000, 432000000, 432, 26, 1, 8},
+       { 12000000, 216000000, 432, 12, 1, 8},
+       { 13000000, 216000000, 432, 13, 1, 8},
+       { 19200000, 216000000, 90,   4, 1, 1},
+       { 26000000, 216000000, 432, 26, 1, 8},
+       { 12000000, 432000000, 432, 12, 0, 8},
+       { 13000000, 432000000, 432, 13, 0, 8},
+       { 19200000, 432000000, 90,   4, 0, 1},
+       { 26000000, 432000000, 432, 26, 0, 8},
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
-       { 28800000, 56448000, 49, 25, 1, 1},
-       { 28800000, 73728000, 64, 25, 1, 1},
-       { 28800000, 24000000,  5,  6, 1, 1},
+       { 28800000, 56448000, 49, 25, 0, 1},
+       { 28800000, 73728000, 64, 25, 0, 1},
+       { 28800000, 24000000,  5,  6, 0, 1},
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
-       { 12000000, 216000000, 216, 12, 1, 4},
-       { 13000000, 216000000, 216, 13, 1, 4},
-       { 19200000, 216000000, 135, 12, 1, 3},
-       { 26000000, 216000000, 216, 26, 1, 4},
+       { 12000000, 216000000, 216, 12, 0, 4},
+       { 13000000, 216000000, 216, 13, 0, 4},
+       { 19200000, 216000000, 135, 12, 0, 3},
+       { 26000000, 216000000, 216, 26, 0, 4},
 
-       { 12000000, 594000000, 594, 12, 1, 8},
-       { 13000000, 594000000, 594, 13, 1, 8},
-       { 19200000, 594000000, 495, 16, 1, 8},
-       { 26000000, 594000000, 594, 26, 1, 8},
+       { 12000000, 594000000, 594, 12, 0, 8},
+       { 13000000, 594000000, 594, 13, 0, 8},
+       { 19200000, 594000000, 495, 16, 0, 8},
+       { 26000000, 594000000, 594, 26, 0, 8},
 
-       { 12000000, 1000000000, 1000, 12, 1, 12},
-       { 13000000, 1000000000, 1000, 13, 1, 12},
-       { 19200000, 1000000000, 625,  12, 1, 8},
-       { 26000000, 1000000000, 1000, 26, 1, 12},
+       { 12000000, 1000000000, 1000, 12, 0, 12},
+       { 13000000, 1000000000, 1000, 13, 0, 12},
+       { 19200000, 1000000000, 625,  12, 0, 8},
+       { 26000000, 1000000000, 1000, 26, 0, 12},
 
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
-       { 12000000, 480000000, 960, 12, 2, 0},
-       { 13000000, 480000000, 960, 13, 2, 0},
-       { 19200000, 480000000, 200, 4,  2, 0},
-       { 26000000, 480000000, 960, 26, 2, 0},
+       { 12000000, 480000000, 960, 12, 0, 0},
+       { 13000000, 480000000, 960, 13, 0, 0},
+       { 19200000, 480000000, 200, 4,  0, 0},
+       { 26000000, 480000000, 960, 26, 0, 0},
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
        /* 1 GHz */
-       { 12000000, 1000000000, 1000, 12, 1, 12},
-       { 13000000, 1000000000, 1000, 13, 1, 12},
-       { 19200000, 1000000000, 625,  12, 1, 8},
-       { 26000000, 1000000000, 1000, 26, 1, 12},
+       { 12000000, 1000000000, 1000, 12, 0, 12},
+       { 13000000, 1000000000, 1000, 13, 0, 12},
+       { 19200000, 1000000000, 625,  12, 0, 8},
+       { 26000000, 1000000000, 1000, 26, 0, 12},
 
        /* 912 MHz */
-       { 12000000, 912000000,  912,  12, 1, 12},
-       { 13000000, 912000000,  912,  13, 1, 12},
-       { 19200000, 912000000,  760,  16, 1, 8},
-       { 26000000, 912000000,  912,  26, 1, 12},
+       { 12000000, 912000000,  912,  12, 0, 12},
+       { 13000000, 912000000,  912,  13, 0, 12},
+       { 19200000, 912000000,  760,  16, 0, 8},
+       { 26000000, 912000000,  912,  26, 0, 12},
 
        /* 816 MHz */
-       { 12000000, 816000000,  816,  12, 1, 12},
-       { 13000000, 816000000,  816,  13, 1, 12},
-       { 19200000, 816000000,  680,  16, 1, 8},
-       { 26000000, 816000000,  816,  26, 1, 12},
+       { 12000000, 816000000,  816,  12, 0, 12},
+       { 13000000, 816000000,  816,  13, 0, 12},
+       { 19200000, 816000000,  680,  16, 0, 8},
+       { 26000000, 816000000,  816,  26, 0, 12},
 
        /* 760 MHz */
-       { 12000000, 760000000,  760,  12, 1, 12},
-       { 13000000, 760000000,  760,  13, 1, 12},
-       { 19200000, 760000000,  950,  24, 1, 8},
-       { 26000000, 760000000,  760,  26, 1, 12},
+       { 12000000, 760000000,  760,  12, 0, 12},
+       { 13000000, 760000000,  760,  13, 0, 12},
+       { 19200000, 760000000,  950,  24, 0, 8},
+       { 26000000, 760000000,  760,  26, 0, 12},
 
        /* 750 MHz */
-       { 12000000, 750000000,  750,  12, 1, 12},
-       { 13000000, 750000000,  750,  13, 1, 12},
-       { 19200000, 750000000,  625,  16, 1, 8},
-       { 26000000, 750000000,  750,  26, 1, 12},
+       { 12000000, 750000000,  750,  12, 0, 12},
+       { 13000000, 750000000,  750,  13, 0, 12},
+       { 19200000, 750000000,  625,  16, 0, 8},
+       { 26000000, 750000000,  750,  26, 0, 12},
 
        /* 608 MHz */
-       { 12000000, 608000000,  608,  12, 1, 12},
-       { 13000000, 608000000,  608,  13, 1, 12},
-       { 19200000, 608000000,  380,  12, 1, 8},
-       { 26000000, 608000000,  608,  26, 1, 12},
+       { 12000000, 608000000,  608,  12, 0, 12},
+       { 13000000, 608000000,  608,  13, 0, 12},
+       { 19200000, 608000000,  380,  12, 0, 8},
+       { 26000000, 608000000,  608,  26, 0, 12},
 
        /* 456 MHz */
-       { 12000000, 456000000,  456,  12, 1, 12},
-       { 13000000, 456000000,  456,  13, 1, 12},
-       { 19200000, 456000000,  380,  16, 1, 8},
-       { 26000000, 456000000,  456,  26, 1, 12},
+       { 12000000, 456000000,  456,  12, 0, 12},
+       { 13000000, 456000000,  456,  13, 0, 12},
+       { 19200000, 456000000,  380,  16, 0, 8},
+       { 26000000, 456000000,  456,  26, 0, 12},
 
        /* 312 MHz */
-       { 12000000, 312000000,  312,  12, 1, 12},
-       { 13000000, 312000000,  312,  13, 1, 12},
-       { 19200000, 312000000,  260,  16, 1, 8},
-       { 26000000, 312000000,  312,  26, 1, 12},
+       { 12000000, 312000000,  312,  12, 0, 12},
+       { 13000000, 312000000,  312,  13, 0, 12},
+       { 19200000, 312000000,  260,  16, 0, 8},
+       { 26000000, 312000000,  312,  26, 0, 12},
 
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
-       { 12000000, 100000000,  200,  24, 1, 0 },
+       { 12000000, 100000000,  200,  24, 0, 0 },
        { 0, 0, 0, 0, 0, 0 },
 };
 
@@ -380,7 +380,7 @@ static struct tegra_clk_pll_params pll_c_params = {
        .vco_max = 1400000000,
        .base_reg = PLLC_BASE,
        .misc_reg = PLLC_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
 };
@@ -394,7 +394,7 @@ static struct tegra_clk_pll_params pll_m_params = {
        .vco_max = 1200000000,
        .base_reg = PLLM_BASE,
        .misc_reg = PLLM_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
 };
@@ -408,7 +408,7 @@ static struct tegra_clk_pll_params pll_p_params = {
        .vco_max = 1400000000,
        .base_reg = PLLP_BASE,
        .misc_reg = PLLP_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
 };
@@ -422,7 +422,7 @@ static struct tegra_clk_pll_params pll_a_params = {
        .vco_max = 1400000000,
        .base_reg = PLLA_BASE,
        .misc_reg = PLLA_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
 };
@@ -436,11 +436,17 @@ static struct tegra_clk_pll_params pll_d_params = {
        .vco_max = 1000000000,
        .base_reg = PLLD_BASE,
        .misc_reg = PLLD_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
 };
 
+static struct pdiv_map pllu_p[] = {
+       { .pdiv = 1, .hw_val = 1 },
+       { .pdiv = 2, .hw_val = 0 },
+       { .pdiv = 0, .hw_val = 0 },
+};
+
 static struct tegra_clk_pll_params pll_u_params = {
        .input_min = 2000000,
        .input_max = 40000000,
@@ -450,9 +456,10 @@ static struct tegra_clk_pll_params pll_u_params = {
        .vco_max = 960000000,
        .base_reg = PLLU_BASE,
        .misc_reg = PLLU_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
+       .pdiv_tohw = pllu_p,
 };
 
 static struct tegra_clk_pll_params pll_x_params = {
@@ -464,7 +471,7 @@ static struct tegra_clk_pll_params pll_x_params = {
        .vco_max = 1200000000,
        .base_reg = PLLX_BASE,
        .misc_reg = PLLX_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
 };
@@ -478,7 +485,7 @@ static struct tegra_clk_pll_params pll_e_params = {
        .vco_max = 0,
        .base_reg = PLLE_BASE,
        .misc_reg = PLLE_MISC,
-       .lock_bit_idx = PLLE_MISC_LOCK,
+       .lock_mask = PLLE_MISC_LOCK,
        .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
        .lock_delay = 0,
 };
@@ -703,7 +710,7 @@ static void tegra20_pll_init(void)
        clks[pll_a_out0] = clk;
 
        /* PLLE */
-       clk = tegra_clk_register_plle("pll_e", "pll_ref", clk_base, NULL,
+       clk = tegra_clk_register_plle("pll_e", "pll_ref", clk_base, pmc_base,
                             0, 100000000, &pll_e_params,
                             0, pll_e_freq_table, NULL);
        clk_register_clkdev(clk, "pll_e", NULL);
@@ -711,8 +718,8 @@ static void tegra20_pll_init(void)
 }
 
 static const char *cclk_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
-                                     "pll_p_cclk", "pll_p_out4_cclk",
-                                     "pll_p_out3_cclk", "clk_d", "pll_x" };
+                                     "pll_p", "pll_p_out4",
+                                     "pll_p_out3", "clk_d", "pll_x" };
 static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
                                      "pll_p_out3", "pll_p_out2", "clk_d",
                                      "clk_32k", "pll_m_out1" };
@@ -721,38 +728,6 @@ static void tegra20_super_clk_init(void)
 {
        struct clk *clk;
 
-       /*
-        * DIV_U71 dividers for CCLK, these dividers are used only
-        * if parent clock is fixed rate.
-        */
-
-       /*
-        * Clock input to cclk divided from pll_p using
-        * U71 divider of cclk.
-        */
-       clk = tegra_clk_register_divider("pll_p_cclk", "pll_p",
-                               clk_base + SUPER_CCLK_DIVIDER, 0,
-                               TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
-       clk_register_clkdev(clk, "pll_p_cclk", NULL);
-
-       /*
-        * Clock input to cclk divided from pll_p_out3 using
-        * U71 divider of cclk.
-        */
-       clk = tegra_clk_register_divider("pll_p_out3_cclk", "pll_p_out3",
-                               clk_base + SUPER_CCLK_DIVIDER, 0,
-                               TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
-       clk_register_clkdev(clk, "pll_p_out3_cclk", NULL);
-
-       /*
-        * Clock input to cclk divided from pll_p_out4 using
-        * U71 divider of cclk.
-        */
-       clk = tegra_clk_register_divider("pll_p_out4_cclk", "pll_p_out4",
-                               clk_base + SUPER_CCLK_DIVIDER, 0,
-                               TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
-       clk_register_clkdev(clk, "pll_p_out4_cclk", NULL);
-
        /* CCLK */
        clk = tegra_clk_register_super_mux("cclk", cclk_parents,
                              ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT,
@@ -1044,7 +1019,7 @@ static void __init tegra20_periph_clk_init(void)
                data = &tegra_periph_clk_list[i];
                clk = tegra_clk_register_periph(data->name, data->parent_names,
                                data->num_parents, &data->periph,
-                               clk_base, data->offset);
+                               clk_base, data->offset, data->flags);
                clk_register_clkdev(clk, data->con_id, data->dev_id);
                clks[data->clk_id] = clk;
        }
@@ -1279,9 +1254,16 @@ static __initdata struct tegra_clk_init_table init_table[] = {
        {host1x, pll_c, 150000000, 0},
        {disp1, pll_p, 600000000, 0},
        {disp2, pll_p, 600000000, 0},
+       {gr2d, pll_c, 300000000, 0},
+       {gr3d, pll_c, 300000000, 0},
        {clk_max, clk_max, 0, 0}, /* This MUST be the last entry */
 };
 
+static void __init tegra20_clock_apply_init_table(void)
+{
+       tegra_init_from_table(init_table, clks, clk_max);
+}
+
 /*
  * Some clocks may be used by different drivers depending on the board
  * configuration.  List those here to register them twice in the clock lookup
@@ -1292,7 +1274,6 @@ static struct tegra_clk_duplicate tegra_clk_duplicates[] = {
        TEGRA_CLK_DUPLICATE(usbd,   "tegra-ehci.0", NULL),
        TEGRA_CLK_DUPLICATE(usbd,   "tegra-otg",    NULL),
        TEGRA_CLK_DUPLICATE(cclk,   NULL,           "cpu"),
-       TEGRA_CLK_DUPLICATE(twd,    "smp_twd",      NULL),
        TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* Must be the last entry */
 };
 
@@ -1349,7 +1330,7 @@ void __init tegra20_clock_init(struct device_node *np)
        clk_data.clk_num = ARRAY_SIZE(clks);
        of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
-       tegra_init_from_table(init_table, clks, clk_max);
+       tegra_clk_apply_init_table = tegra20_clock_apply_init_table;
 
        tegra_cpu_car_ops = &tegra20_cpu_car_ops;
 }
index 32c61cb6d0bb186d01a37fbea5dc3b15ef126e86..2dc0c5602613eae83cb40704cc0516dd5d64a42b 100644 (file)
 #define PLLDU_MISC_LOCK_ENABLE 22
 #define PLLE_MISC_LOCK_ENABLE 9
 
-#define PLL_BASE_LOCK 27
-#define PLLE_MISC_LOCK 11
+#define PLL_BASE_LOCK BIT(27)
+#define PLLE_MISC_LOCK BIT(11)
 
 #define PLLE_AUX 0x48c
 #define PLLC_OUT 0x84
@@ -330,7 +330,7 @@ enum tegra30_clk {
        usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3,
        pcie, owr, afi, csite, pciex, avpucq, la, dtv = 79, ndspeed, i2cslow,
        dsib, irama = 84, iramb, iramc, iramd, cram2, audio_2x = 90, csus = 92,
-       cdev1, cdev2, cpu_g = 96, cpu_lp, gr3d2, mselect, tsensor, i2s3, i2s4,
+       cdev2, cdev1, cpu_g = 96, cpu_lp, gr3d2, mselect, tsensor, i2s3, i2s4,
        i2c4, sbc5, sbc6, d_audio, apbif, dam0, dam1, dam2, hda2codec_2x,
        atomics, audio0_2x, audio1_2x, audio2_2x, audio3_2x, audio4_2x,
        spdif_2x, actmon, extern1, extern2, extern3, sata_oob, sata, hda,
@@ -374,164 +374,170 @@ static const struct utmi_clk_param utmi_parameters[] = {
 };
 
 static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
-       { 12000000, 1040000000, 520,  6, 1, 8},
-       { 13000000, 1040000000, 480,  6, 1, 8},
-       { 16800000, 1040000000, 495,  8, 1, 8}, /* actual: 1039.5 MHz */
-       { 19200000, 1040000000, 325,  6, 1, 6},
-       { 26000000, 1040000000, 520, 13, 1, 8},
-
-       { 12000000, 832000000, 416,  6, 1, 8},
-       { 13000000, 832000000, 832, 13, 1, 8},
-       { 16800000, 832000000, 396,  8, 1, 8},  /* actual: 831.6 MHz */
-       { 19200000, 832000000, 260,  6, 1, 8},
-       { 26000000, 832000000, 416, 13, 1, 8},
-
-       { 12000000, 624000000, 624, 12, 1, 8},
-       { 13000000, 624000000, 624, 13, 1, 8},
-       { 16800000, 600000000, 520, 14, 1, 8},
-       { 19200000, 624000000, 520, 16, 1, 8},
-       { 26000000, 624000000, 624, 26, 1, 8},
-
-       { 12000000, 600000000, 600, 12, 1, 8},
-       { 13000000, 600000000, 600, 13, 1, 8},
-       { 16800000, 600000000, 500, 14, 1, 8},
-       { 19200000, 600000000, 375, 12, 1, 6},
-       { 26000000, 600000000, 600, 26, 1, 8},
-
-       { 12000000, 520000000, 520, 12, 1, 8},
-       { 13000000, 520000000, 520, 13, 1, 8},
-       { 16800000, 520000000, 495, 16, 1, 8},  /* actual: 519.75 MHz */
-       { 19200000, 520000000, 325, 12, 1, 6},
-       { 26000000, 520000000, 520, 26, 1, 8},
-
-       { 12000000, 416000000, 416, 12, 1, 8},
-       { 13000000, 416000000, 416, 13, 1, 8},
-       { 16800000, 416000000, 396, 16, 1, 8},  /* actual: 415.8 MHz */
-       { 19200000, 416000000, 260, 12, 1, 6},
-       { 26000000, 416000000, 416, 26, 1, 8},
+       { 12000000, 1040000000, 520,  6, 0, 8},
+       { 13000000, 1040000000, 480,  6, 0, 8},
+       { 16800000, 1040000000, 495,  8, 0, 8}, /* actual: 1039.5 MHz */
+       { 19200000, 1040000000, 325,  6, 0, 6},
+       { 26000000, 1040000000, 520, 13, 0, 8},
+
+       { 12000000, 832000000, 416,  6, 0, 8},
+       { 13000000, 832000000, 832, 13, 0, 8},
+       { 16800000, 832000000, 396,  8, 0, 8},  /* actual: 831.6 MHz */
+       { 19200000, 832000000, 260,  6, 0, 8},
+       { 26000000, 832000000, 416, 13, 0, 8},
+
+       { 12000000, 624000000, 624, 12, 0, 8},
+       { 13000000, 624000000, 624, 13, 0, 8},
+       { 16800000, 600000000, 520, 14, 0, 8},
+       { 19200000, 624000000, 520, 16, 0, 8},
+       { 26000000, 624000000, 624, 26, 0, 8},
+
+       { 12000000, 600000000, 600, 12, 0, 8},
+       { 13000000, 600000000, 600, 13, 0, 8},
+       { 16800000, 600000000, 500, 14, 0, 8},
+       { 19200000, 600000000, 375, 12, 0, 6},
+       { 26000000, 600000000, 600, 26, 0, 8},
+
+       { 12000000, 520000000, 520, 12, 0, 8},
+       { 13000000, 520000000, 520, 13, 0, 8},
+       { 16800000, 520000000, 495, 16, 0, 8},  /* actual: 519.75 MHz */
+       { 19200000, 520000000, 325, 12, 0, 6},
+       { 26000000, 520000000, 520, 26, 0, 8},
+
+       { 12000000, 416000000, 416, 12, 0, 8},
+       { 13000000, 416000000, 416, 13, 0, 8},
+       { 16800000, 416000000, 396, 16, 0, 8},  /* actual: 415.8 MHz */
+       { 19200000, 416000000, 260, 12, 0, 6},
+       { 26000000, 416000000, 416, 26, 0, 8},
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
-       { 12000000, 666000000, 666, 12, 1, 8},
-       { 13000000, 666000000, 666, 13, 1, 8},
-       { 16800000, 666000000, 555, 14, 1, 8},
-       { 19200000, 666000000, 555, 16, 1, 8},
-       { 26000000, 666000000, 666, 26, 1, 8},
-       { 12000000, 600000000, 600, 12, 1, 8},
-       { 13000000, 600000000, 600, 13, 1, 8},
-       { 16800000, 600000000, 500, 14, 1, 8},
-       { 19200000, 600000000, 375, 12, 1, 6},
-       { 26000000, 600000000, 600, 26, 1, 8},
+       { 12000000, 666000000, 666, 12, 0, 8},
+       { 13000000, 666000000, 666, 13, 0, 8},
+       { 16800000, 666000000, 555, 14, 0, 8},
+       { 19200000, 666000000, 555, 16, 0, 8},
+       { 26000000, 666000000, 666, 26, 0, 8},
+       { 12000000, 600000000, 600, 12, 0, 8},
+       { 13000000, 600000000, 600, 13, 0, 8},
+       { 16800000, 600000000, 500, 14, 0, 8},
+       { 19200000, 600000000, 375, 12, 0, 6},
+       { 26000000, 600000000, 600, 26, 0, 8},
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
-       { 12000000, 216000000, 432, 12, 2, 8},
-       { 13000000, 216000000, 432, 13, 2, 8},
-       { 16800000, 216000000, 360, 14, 2, 8},
-       { 19200000, 216000000, 360, 16, 2, 8},
-       { 26000000, 216000000, 432, 26, 2, 8},
+       { 12000000, 216000000, 432, 12, 1, 8},
+       { 13000000, 216000000, 432, 13, 1, 8},
+       { 16800000, 216000000, 360, 14, 1, 8},
+       { 19200000, 216000000, 360, 16, 1, 8},
+       { 26000000, 216000000, 432, 26, 1, 8},
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
-       { 9600000, 564480000, 294, 5, 1, 4},
-       { 9600000, 552960000, 288, 5, 1, 4},
-       { 9600000, 24000000,  5,   2, 1, 1},
+       { 9600000, 564480000, 294, 5, 0, 4},
+       { 9600000, 552960000, 288, 5, 0, 4},
+       { 9600000, 24000000,  5,   2, 0, 1},
 
-       { 28800000, 56448000, 49, 25, 1, 1},
-       { 28800000, 73728000, 64, 25, 1, 1},
-       { 28800000, 24000000,  5,  6, 1, 1},
+       { 28800000, 56448000, 49, 25, 0, 1},
+       { 28800000, 73728000, 64, 25, 0, 1},
+       { 28800000, 24000000,  5,  6, 0, 1},
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
-       { 12000000, 216000000, 216, 12, 1, 4},
-       { 13000000, 216000000, 216, 13, 1, 4},
-       { 16800000, 216000000, 180, 14, 1, 4},
-       { 19200000, 216000000, 180, 16, 1, 4},
-       { 26000000, 216000000, 216, 26, 1, 4},
-
-       { 12000000, 594000000, 594, 12, 1, 8},
-       { 13000000, 594000000, 594, 13, 1, 8},
-       { 16800000, 594000000, 495, 14, 1, 8},
-       { 19200000, 594000000, 495, 16, 1, 8},
-       { 26000000, 594000000, 594, 26, 1, 8},
-
-       { 12000000, 1000000000, 1000, 12, 1, 12},
-       { 13000000, 1000000000, 1000, 13, 1, 12},
-       { 19200000, 1000000000, 625,  12, 1, 8},
-       { 26000000, 1000000000, 1000, 26, 1, 12},
+       { 12000000, 216000000, 216, 12, 0, 4},
+       { 13000000, 216000000, 216, 13, 0, 4},
+       { 16800000, 216000000, 180, 14, 0, 4},
+       { 19200000, 216000000, 180, 16, 0, 4},
+       { 26000000, 216000000, 216, 26, 0, 4},
+
+       { 12000000, 594000000, 594, 12, 0, 8},
+       { 13000000, 594000000, 594, 13, 0, 8},
+       { 16800000, 594000000, 495, 14, 0, 8},
+       { 19200000, 594000000, 495, 16, 0, 8},
+       { 26000000, 594000000, 594, 26, 0, 8},
+
+       { 12000000, 1000000000, 1000, 12, 0, 12},
+       { 13000000, 1000000000, 1000, 13, 0, 12},
+       { 19200000, 1000000000, 625,  12, 0, 8},
+       { 26000000, 1000000000, 1000, 26, 0, 12},
 
        { 0, 0, 0, 0, 0, 0 },
 };
 
+static struct pdiv_map pllu_p[] = {
+       { .pdiv = 1, .hw_val = 1 },
+       { .pdiv = 2, .hw_val = 0 },
+       { .pdiv = 0, .hw_val = 0 },
+};
+
 static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
-       { 12000000, 480000000, 960, 12, 2, 12},
-       { 13000000, 480000000, 960, 13, 2, 12},
-       { 16800000, 480000000, 400, 7,  2, 5},
-       { 19200000, 480000000, 200, 4,  2, 3},
-       { 26000000, 480000000, 960, 26, 2, 12},
+       { 12000000, 480000000, 960, 12, 0, 12},
+       { 13000000, 480000000, 960, 13, 0, 12},
+       { 16800000, 480000000, 400, 7,  0, 5},
+       { 19200000, 480000000, 200, 4,  0, 3},
+       { 26000000, 480000000, 960, 26, 0, 12},
        { 0, 0, 0, 0, 0, 0 },
 };
 
 static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
        /* 1.7 GHz */
-       { 12000000, 1700000000, 850,  6,  1, 8},
-       { 13000000, 1700000000, 915,  7,  1, 8},        /* actual: 1699.2 MHz */
-       { 16800000, 1700000000, 708,  7,  1, 8},        /* actual: 1699.2 MHz */
-       { 19200000, 1700000000, 885,  10, 1, 8},        /* actual: 1699.2 MHz */
-       { 26000000, 1700000000, 850,  13, 1, 8},
+       { 12000000, 1700000000, 850,  6,  0, 8},
+       { 13000000, 1700000000, 915,  7,  0, 8},        /* actual: 1699.2 MHz */
+       { 16800000, 1700000000, 708,  7,  0, 8},        /* actual: 1699.2 MHz */
+       { 19200000, 1700000000, 885,  10, 0, 8},        /* actual: 1699.2 MHz */
+       { 26000000, 1700000000, 850,  13, 0, 8},
 
        /* 1.6 GHz */
-       { 12000000, 1600000000, 800,  6,  1, 8},
-       { 13000000, 1600000000, 738,  6,  1, 8},        /* actual: 1599.0 MHz */
-       { 16800000, 1600000000, 857,  9,  1, 8},        /* actual: 1599.7 MHz */
-       { 19200000, 1600000000, 500,  6,  1, 8},
-       { 26000000, 1600000000, 800,  13, 1, 8},
+       { 12000000, 1600000000, 800,  6,  0, 8},
+       { 13000000, 1600000000, 738,  6,  0, 8},        /* actual: 1599.0 MHz */
+       { 16800000, 1600000000, 857,  9,  0, 8},        /* actual: 1599.7 MHz */
+       { 19200000, 1600000000, 500,  6,  0, 8},
+       { 26000000, 1600000000, 800,  13, 0, 8},
 
        /* 1.5 GHz */
-       { 12000000, 1500000000, 750,  6,  1, 8},
-       { 13000000, 1500000000, 923,  8,  1, 8},        /* actual: 1499.8 MHz */
-       { 16800000, 1500000000, 625,  7,  1, 8},
-       { 19200000, 1500000000, 625,  8,  1, 8},
-       { 26000000, 1500000000, 750,  13, 1, 8},
+       { 12000000, 1500000000, 750,  6,  0, 8},
+       { 13000000, 1500000000, 923,  8,  0, 8},        /* actual: 1499.8 MHz */
+       { 16800000, 1500000000, 625,  7,  0, 8},
+       { 19200000, 1500000000, 625,  8,  0, 8},
+       { 26000000, 1500000000, 750,  13, 0, 8},
 
        /* 1.4 GHz */
-       { 12000000, 1400000000, 700,  6,  1, 8},
-       { 13000000, 1400000000, 969,  9,  1, 8},        /* actual: 1399.7 MHz */
-       { 16800000, 1400000000, 1000, 12, 1, 8},
-       { 19200000, 1400000000, 875,  12, 1, 8},
-       { 26000000, 1400000000, 700,  13, 1, 8},
+       { 12000000, 1400000000, 700,  6,  0, 8},
+       { 13000000, 1400000000, 969,  9,  0, 8},        /* actual: 1399.7 MHz */
+       { 16800000, 1400000000, 1000, 12, 0, 8},
+       { 19200000, 1400000000, 875,  12, 0, 8},
+       { 26000000, 1400000000, 700,  13, 0, 8},
 
        /* 1.3 GHz */
-       { 12000000, 1300000000, 975,  9,  1, 8},
-       { 13000000, 1300000000, 1000, 10, 1, 8},
-       { 16800000, 1300000000, 928,  12, 1, 8},        /* actual: 1299.2 MHz */
-       { 19200000, 1300000000, 812,  12, 1, 8},        /* actual: 1299.2 MHz */
-       { 26000000, 1300000000, 650,  13, 1, 8},
+       { 12000000, 1300000000, 975,  9,  0, 8},
+       { 13000000, 1300000000, 1000, 10, 0, 8},
+       { 16800000, 1300000000, 928,  12, 0, 8},        /* actual: 1299.2 MHz */
+       { 19200000, 1300000000, 812,  12, 0, 8},        /* actual: 1299.2 MHz */
+       { 26000000, 1300000000, 650,  13, 0, 8},
 
        /* 1.2 GHz */
-       { 12000000, 1200000000, 1000, 10, 1, 8},
-       { 13000000, 1200000000, 923,  10, 1, 8},        /* actual: 1199.9 MHz */
-       { 16800000, 1200000000, 1000, 14, 1, 8},
-       { 19200000, 1200000000, 1000, 16, 1, 8},
-       { 26000000, 1200000000, 600,  13, 1, 8},
+       { 12000000, 1200000000, 1000, 10, 0, 8},
+       { 13000000, 1200000000, 923,  10, 0, 8},        /* actual: 1199.9 MHz */
+       { 16800000, 1200000000, 1000, 14, 0, 8},
+       { 19200000, 1200000000, 1000, 16, 0, 8},
+       { 26000000, 1200000000, 600,  13, 0, 8},
 
        /* 1.1 GHz */
-       { 12000000, 1100000000, 825,  9,  1, 8},
-       { 13000000, 1100000000, 846,  10, 1, 8},        /* actual: 1099.8 MHz */
-       { 16800000, 1100000000, 982,  15, 1, 8},        /* actual: 1099.8 MHz */
-       { 19200000, 1100000000, 859,  15, 1, 8},        /* actual: 1099.5 MHz */
-       { 26000000, 1100000000, 550,  13, 1, 8},
+       { 12000000, 1100000000, 825,  9,  0, 8},
+       { 13000000, 1100000000, 846,  10, 0, 8},        /* actual: 1099.8 MHz */
+       { 16800000, 1100000000, 982,  15, 0, 8},        /* actual: 1099.8 MHz */
+       { 19200000, 1100000000, 859,  15, 0, 8},        /* actual: 1099.5 MHz */
+       { 26000000, 1100000000, 550,  13, 0, 8},
 
        /* 1 GHz */
-       { 12000000, 1000000000, 1000, 12, 1, 8},
-       { 13000000, 1000000000, 1000, 13, 1, 8},
-       { 16800000, 1000000000, 833,  14, 1, 8},        /* actual: 999.6 MHz */
-       { 19200000, 1000000000, 625,  12, 1, 8},
-       { 26000000, 1000000000, 1000, 26, 1, 8},
+       { 12000000, 1000000000, 1000, 12, 0, 8},
+       { 13000000, 1000000000, 1000, 13, 0, 8},
+       { 16800000, 1000000000, 833,  14, 0, 8},        /* actual: 999.6 MHz */
+       { 19200000, 1000000000, 625,  12, 0, 8},
+       { 26000000, 1000000000, 1000, 26, 0, 8},
 
        { 0, 0, 0, 0, 0, 0 },
 };
@@ -553,7 +559,7 @@ static struct tegra_clk_pll_params pll_c_params = {
        .vco_max = 1400000000,
        .base_reg = PLLC_BASE,
        .misc_reg = PLLC_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
 };
@@ -567,7 +573,7 @@ static struct tegra_clk_pll_params pll_m_params = {
        .vco_max = 1200000000,
        .base_reg = PLLM_BASE,
        .misc_reg = PLLM_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
 };
@@ -581,7 +587,7 @@ static struct tegra_clk_pll_params pll_p_params = {
        .vco_max = 1400000000,
        .base_reg = PLLP_BASE,
        .misc_reg = PLLP_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
 };
@@ -595,7 +601,7 @@ static struct tegra_clk_pll_params pll_a_params = {
        .vco_max = 1400000000,
        .base_reg = PLLA_BASE,
        .misc_reg = PLLA_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
 };
@@ -609,7 +615,7 @@ static struct tegra_clk_pll_params pll_d_params = {
        .vco_max = 1000000000,
        .base_reg = PLLD_BASE,
        .misc_reg = PLLD_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
 };
@@ -623,7 +629,7 @@ static struct tegra_clk_pll_params pll_d2_params = {
        .vco_max = 1000000000,
        .base_reg = PLLD2_BASE,
        .misc_reg = PLLD2_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
 };
@@ -637,9 +643,10 @@ static struct tegra_clk_pll_params pll_u_params = {
        .vco_max = 960000000,
        .base_reg = PLLU_BASE,
        .misc_reg = PLLU_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
        .lock_delay = 1000,
+       .pdiv_tohw = pllu_p,
 };
 
 static struct tegra_clk_pll_params pll_x_params = {
@@ -651,7 +658,7 @@ static struct tegra_clk_pll_params pll_x_params = {
        .vco_max = 1700000000,
        .base_reg = PLLX_BASE,
        .misc_reg = PLLX_MISC,
-       .lock_bit_idx = PLL_BASE_LOCK,
+       .lock_mask = PLL_BASE_LOCK,
        .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
        .lock_delay = 300,
 };
@@ -665,7 +672,7 @@ static struct tegra_clk_pll_params pll_e_params = {
        .vco_max = 2400000000U,
        .base_reg = PLLE_BASE,
        .misc_reg = PLLE_MISC,
-       .lock_bit_idx = PLLE_MISC_LOCK,
+       .lock_mask = PLLE_MISC_LOCK,
        .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
        .lock_delay = 300,
 };
@@ -1661,7 +1668,7 @@ static void __init tegra30_periph_clk_init(void)
                data = &tegra_periph_clk_list[i];
                clk = tegra_clk_register_periph(data->name, data->parent_names,
                                data->num_parents, &data->periph,
-                               clk_base, data->offset);
+                               clk_base, data->offset, data->flags);
                clk_register_clkdev(clk, data->con_id, data->dev_id);
                clks[data->clk_id] = clk;
        }
@@ -1911,9 +1918,16 @@ static __initdata struct tegra_clk_init_table init_table[] = {
        {disp1, pll_p, 600000000, 0},
        {disp2, pll_p, 600000000, 0},
        {twd, clk_max, 0, 1},
+       {gr2d, pll_c, 300000000, 0},
+       {gr3d, pll_c, 300000000, 0},
        {clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */
 };
 
+static void __init tegra30_clock_apply_init_table(void)
+{
+       tegra_init_from_table(init_table, clks, clk_max);
+}
+
 /*
  * Some clocks may be used by different drivers depending on the board
  * configuration.  List those here to register them twice in the clock lookup
@@ -1931,7 +1945,6 @@ static struct tegra_clk_duplicate tegra_clk_duplicates[] = {
        TEGRA_CLK_DUPLICATE(cml1, "tegra_sata_cml", NULL),
        TEGRA_CLK_DUPLICATE(cml0, "tegra_pcie", "cml"),
        TEGRA_CLK_DUPLICATE(pciex, "tegra_pcie", "pciex"),
-       TEGRA_CLK_DUPLICATE(twd, "smp_twd", NULL),
        TEGRA_CLK_DUPLICATE(vcp, "nvavp", "vcp"),
        TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* MUST be the last entry */
 };
@@ -1988,7 +2001,7 @@ void __init tegra30_clock_init(struct device_node *np)
        clk_data.clk_num = ARRAY_SIZE(clks);
        of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
 
-       tegra_init_from_table(init_table, clks, clk_max);
+       tegra_clk_apply_init_table = tegra30_clock_apply_init_table;
 
        tegra_cpu_car_ops = &tegra30_cpu_car_ops;
 }
index a603b9af0ad38cda8ca3ee590174909dcaea2994..923ca7ee46944c4d516f01938c2ce046e6fa6d6a 100644 (file)
@@ -22,7 +22,8 @@
 #include "clk.h"
 
 /* Global data of Tegra CPU CAR ops */
-struct tegra_cpu_car_ops *tegra_cpu_car_ops;
+static struct tegra_cpu_car_ops dummy_car_ops;
+struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops;
 
 void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
                                struct clk *clks[], int clk_max)
@@ -76,6 +77,7 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl,
 static const struct of_device_id tegra_dt_clk_match[] = {
        { .compatible = "nvidia,tegra20-car", .data = tegra20_clock_init },
        { .compatible = "nvidia,tegra30-car", .data = tegra30_clock_init },
+       { .compatible = "nvidia,tegra114-car", .data = tegra114_clock_init },
        { }
 };
 
@@ -83,3 +85,13 @@ void __init tegra_clocks_init(void)
 {
        of_clk_init(tegra_dt_clk_match);
 }
+
+tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
+
+void __init tegra_clocks_apply_init_table(void)
+{
+       if (!tegra_clk_apply_init_table)
+               return;
+
+       tegra_clk_apply_init_table();
+}
index 0744731c62291c7bcb4ec83ac04b468a179fac37..e0565620d68ea508f53aed0973a388f8aa6005e5 100644 (file)
@@ -1,4 +1,4 @@
-/*
+       /*
  * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
@@ -116,6 +116,17 @@ struct tegra_clk_pll_freq_table {
        u8              cpcon;
 };
 
+/**
+ * struct pdiv_map - map post divider to hw value
+ *
+ * @pdiv:              post divider
+ * @hw_val:            value to be written to the PLL hw
+ */
+struct pdiv_map {
+       u8 pdiv;
+       u8 hw_val;
+};
+
 /**
  * struct clk_pll_params - PLL parameters
  *
@@ -143,9 +154,18 @@ struct tegra_clk_pll_params {
        u32             base_reg;
        u32             misc_reg;
        u32             lock_reg;
-       u32             lock_bit_idx;
+       u32             lock_mask;
        u32             lock_enable_bit_idx;
+       u32             iddq_reg;
+       u32             iddq_bit_idx;
+       u32             aux_reg;
+       u32             dyn_ramp_reg;
+       u32             ext_misc_reg[3];
+       int             stepa_shift;
+       int             stepb_shift;
        int             lock_delay;
+       int             max_p;
+       struct pdiv_map *pdiv_tohw;
 };
 
 /**
@@ -182,12 +202,16 @@ struct tegra_clk_pll_params {
  * TEGRA_PLL_FIXED - We are not supposed to change output frequency
  *     of some plls.
  * TEGRA_PLLE_CONFIGURE - Configure PLLE when enabling.
+ * TEGRA_PLL_LOCK_MISC - Lock bit is in the misc register instead of the
+ *     base register.
+ * TEGRA_PLL_BYPASS - PLL has bypass bit
+ * TEGRA_PLL_HAS_LOCK_ENABLE - PLL has bit to enable lock monitoring
  */
 struct tegra_clk_pll {
        struct clk_hw   hw;
        void __iomem    *clk_base;
        void __iomem    *pmc;
-       u             flags;
+       u32             flags;
        unsigned long   fixed_rate;
        spinlock_t      *lock;
        u8              divn_shift;
@@ -210,20 +234,64 @@ struct tegra_clk_pll {
 #define TEGRA_PLLM BIT(5)
 #define TEGRA_PLL_FIXED BIT(6)
 #define TEGRA_PLLE_CONFIGURE BIT(7)
+#define TEGRA_PLL_LOCK_MISC BIT(8)
+#define TEGRA_PLL_BYPASS BIT(9)
+#define TEGRA_PLL_HAS_LOCK_ENABLE BIT(10)
 
 extern const struct clk_ops tegra_clk_pll_ops;
 extern const struct clk_ops tegra_clk_plle_ops;
 struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
                void __iomem *clk_base, void __iomem *pmc,
                unsigned long flags, unsigned long fixed_rate,
-               struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+               struct tegra_clk_pll_params *pll_params, u32 pll_flags,
                struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
+
 struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
                void __iomem *clk_base, void __iomem *pmc,
                unsigned long flags, unsigned long fixed_rate,
-               struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+               struct tegra_clk_pll_params *pll_params, u32 pll_flags,
                struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
 
+struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name,
+                           void __iomem *clk_base, void __iomem *pmc,
+                           unsigned long flags, unsigned long fixed_rate,
+                           struct tegra_clk_pll_params *pll_params,
+                           u32 pll_flags,
+                           struct tegra_clk_pll_freq_table *freq_table,
+                           spinlock_t *lock);
+
+struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name,
+                          void __iomem *clk_base, void __iomem *pmc,
+                          unsigned long flags, unsigned long fixed_rate,
+                          struct tegra_clk_pll_params *pll_params,
+                          u32 pll_flags,
+                          struct tegra_clk_pll_freq_table *freq_table,
+                          spinlock_t *lock);
+
+struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name,
+                          void __iomem *clk_base, void __iomem *pmc,
+                          unsigned long flags, unsigned long fixed_rate,
+                          struct tegra_clk_pll_params *pll_params,
+                          u32 pll_flags,
+                          struct tegra_clk_pll_freq_table *freq_table,
+                          spinlock_t *lock);
+
+struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name,
+                          void __iomem *clk_base, void __iomem *pmc,
+                          unsigned long flags, unsigned long fixed_rate,
+                          struct tegra_clk_pll_params *pll_params,
+                          u32 pll_flags,
+                          struct tegra_clk_pll_freq_table *freq_table,
+                          spinlock_t *lock, unsigned long parent_rate);
+
+struct clk *tegra_clk_register_plle_tegra114(const char *name,
+                               const char *parent_name,
+                               void __iomem *clk_base, unsigned long flags,
+                               unsigned long fixed_rate,
+                               struct tegra_clk_pll_params *pll_params,
+                               struct tegra_clk_pll_freq_table *freq_table,
+                               spinlock_t *lock);
+
 /**
  * struct tegra_clk_pll_out - PLL divider down clock
  *
@@ -290,6 +358,7 @@ struct tegra_clk_periph_regs {
  * TEGRA_PERIPH_ON_APB - If peripheral is in the APB bus then read the
  *     bus to flush the write operation in apb bus. This flag indicates
  *     that this peripheral is in apb bus.
+ * TEGRA_PERIPH_WAR_1005168 - Apply workaround for Tegra114 MSENC bug
  */
 struct tegra_clk_periph_gate {
        u32                     magic;
@@ -309,6 +378,7 @@ struct tegra_clk_periph_gate {
 #define TEGRA_PERIPH_NO_RESET BIT(0)
 #define TEGRA_PERIPH_MANUAL_RESET BIT(1)
 #define TEGRA_PERIPH_ON_APB BIT(2)
+#define TEGRA_PERIPH_WAR_1005168 BIT(3)
 
 void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert);
 extern const struct clk_ops tegra_clk_periph_gate_ops;
@@ -349,21 +419,22 @@ extern const struct clk_ops tegra_clk_periph_ops;
 struct clk *tegra_clk_register_periph(const char *name,
                const char **parent_names, int num_parents,
                struct tegra_clk_periph *periph, void __iomem *clk_base,
-               u32 offset);
+               u32 offset, unsigned long flags);
 struct clk *tegra_clk_register_periph_nodiv(const char *name,
                const char **parent_names, int num_parents,
                struct tegra_clk_periph *periph, void __iomem *clk_base,
                u32 offset);
 
-#define TEGRA_CLK_PERIPH(_mux_shift, _mux_width, _mux_flags,           \
+#define TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, _mux_flags,            \
                         _div_shift, _div_width, _div_frac_width,       \
                         _div_flags, _clk_num, _enb_refcnt, _regs,      \
-                        _gate_flags)                                   \
+                        _gate_flags, _table)                           \
        {                                                               \
                .mux = {                                                \
                        .flags = _mux_flags,                            \
                        .shift = _mux_shift,                            \
-                       .width = _mux_width,                            \
+                       .mask = _mux_mask,                              \
+                       .table = _table,                                \
                },                                                      \
                .divider = {                                            \
                        .flags = _div_flags,                            \
@@ -391,28 +462,41 @@ struct tegra_periph_init_data {
        u32 offset;
        const char *con_id;
        const char *dev_id;
+       unsigned long flags;
 };
 
-#define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset, \
-                       _mux_shift, _mux_width, _mux_flags, _div_shift, \
+#define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
+                       _mux_shift, _mux_mask, _mux_flags, _div_shift,  \
                        _div_width, _div_frac_width, _div_flags, _regs, \
-                       _clk_num, _enb_refcnt, _gate_flags, _clk_id)    \
+                       _clk_num, _enb_refcnt, _gate_flags, _clk_id, _table,\
+                       _flags) \
        {                                                               \
                .name = _name,                                          \
                .clk_id = _clk_id,                                      \
                .parent_names = _parent_names,                          \
                .num_parents = ARRAY_SIZE(_parent_names),               \
-               .periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_width,      \
+               .periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_mask,       \
                                           _mux_flags, _div_shift,      \
                                           _div_width, _div_frac_width, \
                                           _div_flags, _clk_num,        \
                                           _enb_refcnt, _regs,          \
-                                          _gate_flags),                \
+                                          _gate_flags, _table),        \
                .offset = _offset,                                      \
                .con_id = _con_id,                                      \
                .dev_id = _dev_id,                                      \
+               .flags = _flags                                         \
        }
 
+#define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\
+                       _mux_shift, _mux_width, _mux_flags, _div_shift, \
+                       _div_width, _div_frac_width, _div_flags, _regs, \
+                       _clk_num, _enb_refcnt, _gate_flags, _clk_id)    \
+       TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\
+                       _mux_shift, BIT(_mux_width) - 1, _mux_flags,    \
+                       _div_shift, _div_width, _div_frac_width, _div_flags, \
+                       _regs, _clk_num, _enb_refcnt, _gate_flags, _clk_id,\
+                       NULL, 0)
+
 /**
  * struct clk_super_mux - super clock
  *
@@ -499,4 +583,13 @@ void tegra30_clock_init(struct device_node *np);
 static inline void tegra30_clock_init(struct device_node *np) {}
 #endif /* CONFIG_ARCH_TEGRA_3x_SOC */
 
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+void tegra114_clock_init(struct device_node *np);
+#else
+static inline void tegra114_clock_init(struct device_node *np) {}
+#endif /* CONFIG_ARCH_TEGRA114_SOC */
+
+typedef void (*tegra_clk_apply_init_table_func)(void);
+extern tegra_clk_apply_init_table_func tegra_clk_apply_init_table;
+
 #endif /* TEGRA_CLK_H */
index 74faa7e3cf59f41658d3ebc4f05631970129c333..293a28854417374ee6fe3047be1637934eb343a9 100644 (file)
 struct clk_prcmu {
        struct clk_hw hw;
        u8 cg_sel;
+       int is_prepared;
        int is_enabled;
+       int opp_requested;
 };
 
 /* PRCMU clock operations. */
 
 static int clk_prcmu_prepare(struct clk_hw *hw)
 {
+       int ret;
        struct clk_prcmu *clk = to_clk_prcmu(hw);
-       return prcmu_request_clock(clk->cg_sel, true);
+
+       ret = prcmu_request_clock(clk->cg_sel, true);
+       if (!ret)
+               clk->is_prepared = 1;
+
+       return ret;;
 }
 
 static void clk_prcmu_unprepare(struct clk_hw *hw)
@@ -36,7 +44,15 @@ static void clk_prcmu_unprepare(struct clk_hw *hw)
        struct clk_prcmu *clk = to_clk_prcmu(hw);
        if (prcmu_request_clock(clk->cg_sel, false))
                pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
-                       hw->init->name);
+                       __clk_get_name(hw->clk));
+       else
+               clk->is_prepared = 0;
+}
+
+static int clk_prcmu_is_prepared(struct clk_hw *hw)
+{
+       struct clk_prcmu *clk = to_clk_prcmu(hw);
+       return clk->is_prepared;
 }
 
 static int clk_prcmu_enable(struct clk_hw *hw)
@@ -79,58 +95,52 @@ static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate,
        return prcmu_set_clock_rate(clk->cg_sel, rate);
 }
 
-static int request_ape_opp100(bool enable)
-{
-       static int reqs;
-       int err = 0;
-
-       if (enable) {
-               if (!reqs)
-                       err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
-                                                       "clock", 100);
-               if (!err)
-                       reqs++;
-       } else {
-               reqs--;
-               if (!reqs)
-                       prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
-                                               "clock");
-       }
-       return err;
-}
-
 static int clk_prcmu_opp_prepare(struct clk_hw *hw)
 {
        int err;
        struct clk_prcmu *clk = to_clk_prcmu(hw);
 
-       err = request_ape_opp100(true);
-       if (err) {
-               pr_err("clk_prcmu: %s failed to request APE OPP100 for %s.\n",
-                       __func__, hw->init->name);
-               return err;
+       if (!clk->opp_requested) {
+               err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP,
+                                               (char *)__clk_get_name(hw->clk),
+                                               100);
+               if (err) {
+                       pr_err("clk_prcmu: %s fail req APE OPP for %s.\n",
+                               __func__, __clk_get_name(hw->clk));
+                       return err;
+               }
+               clk->opp_requested = 1;
        }
 
        err = prcmu_request_clock(clk->cg_sel, true);
-       if (err)
-               request_ape_opp100(false);
+       if (err) {
+               prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
+                                       (char *)__clk_get_name(hw->clk));
+               clk->opp_requested = 0;
+               return err;
+       }
 
-       return err;
+       clk->is_prepared = 1;
+       return 0;
 }
 
 static void clk_prcmu_opp_unprepare(struct clk_hw *hw)
 {
        struct clk_prcmu *clk = to_clk_prcmu(hw);
 
-       if (prcmu_request_clock(clk->cg_sel, false))
-               goto out_error;
-       if (request_ape_opp100(false))
-               goto out_error;
-       return;
-
-out_error:
-       pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
-               hw->init->name);
+       if (prcmu_request_clock(clk->cg_sel, false)) {
+               pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
+                       __clk_get_name(hw->clk));
+               return;
+       }
+
+       if (clk->opp_requested) {
+               prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP,
+                                       (char *)__clk_get_name(hw->clk));
+               clk->opp_requested = 0;
+       }
+
+       clk->is_prepared = 0;
 }
 
 static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
@@ -138,38 +148,49 @@ static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw)
        int err;
        struct clk_prcmu *clk = to_clk_prcmu(hw);
 
-       err = prcmu_request_ape_opp_100_voltage(true);
-       if (err) {
-               pr_err("clk_prcmu: %s failed to request APE OPP VOLT for %s.\n",
-                       __func__, hw->init->name);
-               return err;
+       if (!clk->opp_requested) {
+               err = prcmu_request_ape_opp_100_voltage(true);
+               if (err) {
+                       pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n",
+                               __func__, __clk_get_name(hw->clk));
+                       return err;
+               }
+               clk->opp_requested = 1;
        }
 
        err = prcmu_request_clock(clk->cg_sel, true);
-       if (err)
+       if (err) {
                prcmu_request_ape_opp_100_voltage(false);
+               clk->opp_requested = 0;
+               return err;
+       }
 
-       return err;
+       clk->is_prepared = 1;
+       return 0;
 }
 
 static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw)
 {
        struct clk_prcmu *clk = to_clk_prcmu(hw);
 
-       if (prcmu_request_clock(clk->cg_sel, false))
-               goto out_error;
-       if (prcmu_request_ape_opp_100_voltage(false))
-               goto out_error;
-       return;
-
-out_error:
-       pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
-               hw->init->name);
+       if (prcmu_request_clock(clk->cg_sel, false)) {
+               pr_err("clk_prcmu: %s failed to disable %s.\n", __func__,
+                       __clk_get_name(hw->clk));
+               return;
+       }
+
+       if (clk->opp_requested) {
+               prcmu_request_ape_opp_100_voltage(false);
+               clk->opp_requested = 0;
+       }
+
+       clk->is_prepared = 0;
 }
 
 static struct clk_ops clk_prcmu_scalable_ops = {
        .prepare = clk_prcmu_prepare,
        .unprepare = clk_prcmu_unprepare,
+       .is_prepared = clk_prcmu_is_prepared,
        .enable = clk_prcmu_enable,
        .disable = clk_prcmu_disable,
        .is_enabled = clk_prcmu_is_enabled,
@@ -181,6 +202,7 @@ static struct clk_ops clk_prcmu_scalable_ops = {
 static struct clk_ops clk_prcmu_gate_ops = {
        .prepare = clk_prcmu_prepare,
        .unprepare = clk_prcmu_unprepare,
+       .is_prepared = clk_prcmu_is_prepared,
        .enable = clk_prcmu_enable,
        .disable = clk_prcmu_disable,
        .is_enabled = clk_prcmu_is_enabled,
@@ -202,6 +224,7 @@ static struct clk_ops clk_prcmu_rate_ops = {
 static struct clk_ops clk_prcmu_opp_gate_ops = {
        .prepare = clk_prcmu_opp_prepare,
        .unprepare = clk_prcmu_opp_unprepare,
+       .is_prepared = clk_prcmu_is_prepared,
        .enable = clk_prcmu_enable,
        .disable = clk_prcmu_disable,
        .is_enabled = clk_prcmu_is_enabled,
@@ -211,6 +234,7 @@ static struct clk_ops clk_prcmu_opp_gate_ops = {
 static struct clk_ops clk_prcmu_opp_volt_scalable_ops = {
        .prepare = clk_prcmu_opp_volt_prepare,
        .unprepare = clk_prcmu_opp_volt_unprepare,
+       .is_prepared = clk_prcmu_is_prepared,
        .enable = clk_prcmu_enable,
        .disable = clk_prcmu_disable,
        .is_enabled = clk_prcmu_is_enabled,
@@ -242,7 +266,9 @@ static struct clk *clk_reg_prcmu(const char *name,
        }
 
        clk->cg_sel = cg_sel;
+       clk->is_prepared = 1;
        clk->is_enabled = 1;
+       clk->opp_requested = 0;
        /* "rate" can be used for changing the initial frequency */
        if (rate)
                prcmu_set_clock_rate(cg_sel, rate);
index 6d6174978f95edfb95bbda0b205ac15a7d7ab364..5d9bab2b5012a2ad0ce3439361c88190511ed4c3 100644 (file)
@@ -31,6 +31,9 @@ config SUNXI_TIMER
 config VT8500_TIMER
        bool
 
+config CADENCE_TTC_TIMER
+       bool
+
 config CLKSRC_NOMADIK_MTU
        bool
        depends on (ARCH_NOMADIK || ARCH_U8500)
@@ -68,6 +71,11 @@ config CLKSRC_METAG_GENERIC
        help
          This option enables support for the Meta per-thread timers.
 
+config CLKSRC_EXYNOS_MCT
+       def_bool y if ARCH_EXYNOS
+       help
+         Support for Multi Core Timer controller on Exynos SoCs.
+
 config CLKSRC_SAMSUNG_PWM
        bool
        select CLKSRC_MMIO
index 891c9f2af0218f579746b76d9beade2b298c520b..2289f0cb4c4c517405b21cd8c862369314d37822 100644 (file)
@@ -19,6 +19,8 @@ obj-$(CONFIG_ARCH_BCM2835)    += bcm2835_timer.o
 obj-$(CONFIG_SUNXI_TIMER)      += sunxi_timer.o
 obj-$(CONFIG_ARCH_TEGRA)       += tegra20_timer.o
 obj-$(CONFIG_VT8500_TIMER)     += vt8500_timer.o
+obj-$(CONFIG_CADENCE_TTC_TIMER)        += cadence_ttc_timer.o
+obj-$(CONFIG_CLKSRC_EXYNOS_MCT)        += exynos_mct.o
 obj-$(CONFIG_CLKSRC_SAMSUNG_PWM)       += samsung_pwm_timer.o
 
 obj-$(CONFIG_ARM_ARCH_TIMER)           += arm_arch_timer.o
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c
new file mode 100644 (file)
index 0000000..685bc60
--- /dev/null
@@ -0,0 +1,436 @@
+/*
+ * This file contains driver for the Cadence Triple Timer Counter Rev 06
+ *
+ *  Copyright (C) 2011-2013 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/clk.h>
+#include <linux/interrupt.h>
+#include <linux/clockchips.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+
+/*
+ * 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 is configurable and
+ * obtained from device tree. The pre-scaler of 32 is used.
+ */
+
+/*
+ * Timer Register Offset Definitions of Timer 1, Increment base address by 4
+ * and use same offsets for Timer 2
+ */
+#define TTC_CLK_CNTRL_OFFSET           0x00 /* Clock Control Reg, RW */
+#define TTC_CNT_CNTRL_OFFSET           0x0C /* Counter Control Reg, RW */
+#define TTC_COUNT_VAL_OFFSET           0x18 /* Counter Value Reg, RO */
+#define TTC_INTR_VAL_OFFSET            0x24 /* Interval Count Reg, RW */
+#define TTC_ISR_OFFSET         0x54 /* Interrupt Status Reg, RO */
+#define TTC_IER_OFFSET         0x60 /* Interrupt Enable Reg, RW */
+
+#define TTC_CNT_CNTRL_DISABLE_MASK     0x1
+
+/*
+ * Setup the timers to use pre-scaling, using a fixed value for now that will
+ * work across most input frequency, but it may need to be more dynamic
+ */
+#define PRESCALE_EXPONENT      11      /* 2 ^ PRESCALE_EXPONENT = PRESCALE */
+#define PRESCALE               2048    /* The exponent must match this */
+#define CLK_CNTRL_PRESCALE     ((PRESCALE_EXPONENT - 1) << 1)
+#define CLK_CNTRL_PRESCALE_EN  1
+#define CNT_CNTRL_RESET                (1 << 4)
+
+/**
+ * struct ttc_timer - This definition defines local timer structure
+ *
+ * @base_addr: Base address of timer
+ * @clk:       Associated clock source
+ * @clk_rate_change_nb Notifier block for clock rate changes
+ */
+struct ttc_timer {
+       void __iomem *base_addr;
+       struct clk *clk;
+       struct notifier_block clk_rate_change_nb;
+};
+
+#define to_ttc_timer(x) \
+               container_of(x, struct ttc_timer, clk_rate_change_nb)
+
+struct ttc_timer_clocksource {
+       struct ttc_timer        ttc;
+       struct clocksource      cs;
+};
+
+#define to_ttc_timer_clksrc(x) \
+               container_of(x, struct ttc_timer_clocksource, cs)
+
+struct ttc_timer_clockevent {
+       struct ttc_timer                ttc;
+       struct clock_event_device       ce;
+};
+
+#define to_ttc_timer_clkevent(x) \
+               container_of(x, struct ttc_timer_clockevent, ce)
+
+/**
+ * ttc_set_interval - Set the timer interval value
+ *
+ * @timer:     Pointer to the timer instance
+ * @cycles:    Timer interval ticks
+ **/
+static void ttc_set_interval(struct ttc_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 + TTC_CNT_CNTRL_OFFSET);
+       ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK;
+       __raw_writel(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET);
+
+       __raw_writel(cycles, timer->base_addr + TTC_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 |= CNT_CNTRL_RESET;
+       ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK;
+       __raw_writel(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET);
+}
+
+/**
+ * ttc_clock_event_interrupt - Clock event timer interrupt handler
+ *
+ * @irq:       IRQ number of the Timer
+ * @dev_id:    void pointer to the ttc_timer instance
+ *
+ * returns: Always IRQ_HANDLED - success
+ **/
+static irqreturn_t ttc_clock_event_interrupt(int irq, void *dev_id)
+{
+       struct ttc_timer_clockevent *ttce = dev_id;
+       struct ttc_timer *timer = &ttce->ttc;
+
+       /* Acknowledge the interrupt and call event handler */
+       __raw_readl(timer->base_addr + TTC_ISR_OFFSET);
+
+       ttce->ce.event_handler(&ttce->ce);
+
+       return IRQ_HANDLED;
+}
+
+/**
+ * __ttc_clocksource_read - Reads the timer counter register
+ *
+ * returns: Current timer counter register value
+ **/
+static cycle_t __ttc_clocksource_read(struct clocksource *cs)
+{
+       struct ttc_timer *timer = &to_ttc_timer_clksrc(cs)->ttc;
+
+       return (cycle_t)__raw_readl(timer->base_addr +
+                               TTC_COUNT_VAL_OFFSET);
+}
+
+/**
+ * ttc_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 ttc_set_next_event(unsigned long cycles,
+                                       struct clock_event_device *evt)
+{
+       struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
+       struct ttc_timer *timer = &ttce->ttc;
+
+       ttc_set_interval(timer, cycles);
+       return 0;
+}
+
+/**
+ * ttc_set_mode - Sets the mode of timer
+ *
+ * @mode:      Mode to be set
+ * @evt:       Address of clock event instance
+ **/
+static void ttc_set_mode(enum clock_event_mode mode,
+                                       struct clock_event_device *evt)
+{
+       struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt);
+       struct ttc_timer *timer = &ttce->ttc;
+       u32 ctrl_reg;
+
+       switch (mode) {
+       case CLOCK_EVT_MODE_PERIODIC:
+               ttc_set_interval(timer,
+                               DIV_ROUND_CLOSEST(clk_get_rate(ttce->ttc.clk),
+                                       PRESCALE * HZ));
+               break;
+       case CLOCK_EVT_MODE_ONESHOT:
+       case CLOCK_EVT_MODE_UNUSED:
+       case CLOCK_EVT_MODE_SHUTDOWN:
+               ctrl_reg = __raw_readl(timer->base_addr +
+                                       TTC_CNT_CNTRL_OFFSET);
+               ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK;
+               __raw_writel(ctrl_reg,
+                               timer->base_addr + TTC_CNT_CNTRL_OFFSET);
+               break;
+       case CLOCK_EVT_MODE_RESUME:
+               ctrl_reg = __raw_readl(timer->base_addr +
+                                       TTC_CNT_CNTRL_OFFSET);
+               ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK;
+               __raw_writel(ctrl_reg,
+                               timer->base_addr + TTC_CNT_CNTRL_OFFSET);
+               break;
+       }
+}
+
+static int ttc_rate_change_clocksource_cb(struct notifier_block *nb,
+               unsigned long event, void *data)
+{
+       struct clk_notifier_data *ndata = data;
+       struct ttc_timer *ttc = to_ttc_timer(nb);
+       struct ttc_timer_clocksource *ttccs = container_of(ttc,
+                       struct ttc_timer_clocksource, ttc);
+
+       switch (event) {
+       case POST_RATE_CHANGE:
+               /*
+                * Do whatever is necessary to maintain a proper time base
+                *
+                * I cannot find a way to adjust the currently used clocksource
+                * to the new frequency. __clocksource_updatefreq_hz() sounds
+                * good, but does not work. Not sure what's that missing.
+                *
+                * This approach works, but triggers two clocksource switches.
+                * The first after unregister to clocksource jiffies. And
+                * another one after the register to the newly registered timer.
+                *
+                * Alternatively we could 'waste' another HW timer to ping pong
+                * between clock sources. That would also use one register and
+                * one unregister call, but only trigger one clocksource switch
+                * for the cost of another HW timer used by the OS.
+                */
+               clocksource_unregister(&ttccs->cs);
+               clocksource_register_hz(&ttccs->cs,
+                               ndata->new_rate / PRESCALE);
+               /* fall through */
+       case PRE_RATE_CHANGE:
+       case ABORT_RATE_CHANGE:
+       default:
+               return NOTIFY_DONE;
+       }
+}
+
+static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base)
+{
+       struct ttc_timer_clocksource *ttccs;
+       int err;
+
+       ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL);
+       if (WARN_ON(!ttccs))
+               return;
+
+       ttccs->ttc.clk = clk;
+
+       err = clk_prepare_enable(ttccs->ttc.clk);
+       if (WARN_ON(err)) {
+               kfree(ttccs);
+               return;
+       }
+
+       ttccs->ttc.clk_rate_change_nb.notifier_call =
+               ttc_rate_change_clocksource_cb;
+       ttccs->ttc.clk_rate_change_nb.next = NULL;
+       if (clk_notifier_register(ttccs->ttc.clk,
+                               &ttccs->ttc.clk_rate_change_nb))
+               pr_warn("Unable to register clock notifier.\n");
+
+       ttccs->ttc.base_addr = base;
+       ttccs->cs.name = "ttc_clocksource";
+       ttccs->cs.rating = 200;
+       ttccs->cs.read = __ttc_clocksource_read;
+       ttccs->cs.mask = CLOCKSOURCE_MASK(16);
+       ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+       /*
+        * 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.
+        */
+       __raw_writel(0x0,  ttccs->ttc.base_addr + TTC_IER_OFFSET);
+       __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
+                    ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET);
+       __raw_writel(CNT_CNTRL_RESET,
+                    ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET);
+
+       err = clocksource_register_hz(&ttccs->cs,
+                       clk_get_rate(ttccs->ttc.clk) / PRESCALE);
+       if (WARN_ON(err)) {
+               kfree(ttccs);
+               return;
+       }
+}
+
+static int ttc_rate_change_clockevent_cb(struct notifier_block *nb,
+               unsigned long event, void *data)
+{
+       struct clk_notifier_data *ndata = data;
+       struct ttc_timer *ttc = to_ttc_timer(nb);
+       struct ttc_timer_clockevent *ttcce = container_of(ttc,
+                       struct ttc_timer_clockevent, ttc);
+
+       switch (event) {
+       case POST_RATE_CHANGE:
+       {
+               unsigned long flags;
+
+               /*
+                * clockevents_update_freq should be called with IRQ disabled on
+                * the CPU the timer provides events for. The timer we use is
+                * common to both CPUs, not sure if we need to run on both
+                * cores.
+                */
+               local_irq_save(flags);
+               clockevents_update_freq(&ttcce->ce,
+                               ndata->new_rate / PRESCALE);
+               local_irq_restore(flags);
+
+               /* fall through */
+       }
+       case PRE_RATE_CHANGE:
+       case ABORT_RATE_CHANGE:
+       default:
+               return NOTIFY_DONE;
+       }
+}
+
+static void __init ttc_setup_clockevent(struct clk *clk,
+                                               void __iomem *base, u32 irq)
+{
+       struct ttc_timer_clockevent *ttcce;
+       int err;
+
+       ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL);
+       if (WARN_ON(!ttcce))
+               return;
+
+       ttcce->ttc.clk = clk;
+
+       err = clk_prepare_enable(ttcce->ttc.clk);
+       if (WARN_ON(err)) {
+               kfree(ttcce);
+               return;
+       }
+
+       ttcce->ttc.clk_rate_change_nb.notifier_call =
+               ttc_rate_change_clockevent_cb;
+       ttcce->ttc.clk_rate_change_nb.next = NULL;
+       if (clk_notifier_register(ttcce->ttc.clk,
+                               &ttcce->ttc.clk_rate_change_nb))
+               pr_warn("Unable to register clock notifier.\n");
+
+       ttcce->ttc.base_addr = base;
+       ttcce->ce.name = "ttc_clockevent";
+       ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+       ttcce->ce.set_next_event = ttc_set_next_event;
+       ttcce->ce.set_mode = ttc_set_mode;
+       ttcce->ce.rating = 200;
+       ttcce->ce.irq = irq;
+       ttcce->ce.cpumask = cpu_possible_mask;
+
+       /*
+        * Setup the clock event timer to be an interval timer which
+        * is prescaled by 32 using the interval interrupt. Leave it
+        * disabled for now.
+        */
+       __raw_writel(0x23, ttcce->ttc.base_addr + TTC_CNT_CNTRL_OFFSET);
+       __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN,
+                    ttcce->ttc.base_addr + TTC_CLK_CNTRL_OFFSET);
+       __raw_writel(0x1,  ttcce->ttc.base_addr + TTC_IER_OFFSET);
+
+       err = request_irq(irq, ttc_clock_event_interrupt,
+                         IRQF_DISABLED | IRQF_TIMER,
+                         ttcce->ce.name, ttcce);
+       if (WARN_ON(err)) {
+               kfree(ttcce);
+               return;
+       }
+
+       clockevents_config_and_register(&ttcce->ce,
+                       clk_get_rate(ttcce->ttc.clk) / PRESCALE, 1, 0xfffe);
+}
+
+/**
+ * ttc_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 ttc_timer_init(struct device_node *timer)
+{
+       unsigned int irq;
+       void __iomem *timer_baseaddr;
+       struct clk *clk;
+       static int initialized;
+
+       if (initialized)
+               return;
+
+       initialized = 1;
+
+       /*
+        * Get the 1st Triple Timer Counter (TTC) block from the device tree
+        * and use it. Note that the event timer uses the interrupt and it's the
+        * 2nd TTC hence the irq_of_parse_and_map(,1)
+        */
+       timer_baseaddr = of_iomap(timer, 0);
+       if (!timer_baseaddr) {
+               pr_err("ERROR: invalid timer base address\n");
+               BUG();
+       }
+
+       irq = irq_of_parse_and_map(timer, 1);
+       if (irq <= 0) {
+               pr_err("ERROR: invalid interrupt number\n");
+               BUG();
+       }
+
+       clk = of_clk_get_by_name(timer, "cpu_1x");
+       if (IS_ERR(clk)) {
+               pr_err("ERROR: timer input clock not found\n");
+               BUG();
+       }
+
+       ttc_setup_clocksource(clk, timer_baseaddr);
+       ttc_setup_clockevent(clk, timer_baseaddr + 4, irq);
+
+       pr_info("%s #0 at %p, irq=%d\n", timer->name, timer_baseaddr, irq);
+}
+
+CLOCKSOURCE_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init);
index e6a553cb73e807545270e3a873295b8b88dfc907..4329a29a5310d046eaedc12cd14229791c6e14f1 100644 (file)
@@ -399,7 +399,18 @@ static struct platform_driver em_sti_device_driver = {
        }
 };
 
-module_platform_driver(em_sti_device_driver);
+static int __init em_sti_init(void)
+{
+       return platform_driver_register(&em_sti_device_driver);
+}
+
+static void __exit em_sti_exit(void)
+{
+       platform_driver_unregister(&em_sti_device_driver);
+}
+
+subsys_initcall(em_sti_init);
+module_exit(em_sti_exit);
 
 MODULE_AUTHOR("Magnus Damm");
 MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver");
similarity index 65%
rename from arch/arm/mach-exynos/mct.c
rename to drivers/clocksource/exynos_mct.c
index c9d6650f9b5dec4cc4d5f9c7f3f4c2b87661a811..a6ca0fb0693985c843434a18b18ba98aa5327ee3 100644 (file)
 #include <linux/delay.h>
 #include <linux/percpu.h>
 #include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/clocksource.h>
 
 #include <asm/arch_timer.h>
 #include <asm/localtimer.h>
-
-#include <plat/cpu.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-#include <mach/regs-mct.h>
 #include <asm/mach/time.h>
 
+#define EXYNOS4_MCTREG(x)              (x)
+#define EXYNOS4_MCT_G_CNT_L            EXYNOS4_MCTREG(0x100)
+#define EXYNOS4_MCT_G_CNT_U            EXYNOS4_MCTREG(0x104)
+#define EXYNOS4_MCT_G_CNT_WSTAT                EXYNOS4_MCTREG(0x110)
+#define EXYNOS4_MCT_G_COMP0_L          EXYNOS4_MCTREG(0x200)
+#define EXYNOS4_MCT_G_COMP0_U          EXYNOS4_MCTREG(0x204)
+#define EXYNOS4_MCT_G_COMP0_ADD_INCR   EXYNOS4_MCTREG(0x208)
+#define EXYNOS4_MCT_G_TCON             EXYNOS4_MCTREG(0x240)
+#define EXYNOS4_MCT_G_INT_CSTAT                EXYNOS4_MCTREG(0x244)
+#define EXYNOS4_MCT_G_INT_ENB          EXYNOS4_MCTREG(0x248)
+#define EXYNOS4_MCT_G_WSTAT            EXYNOS4_MCTREG(0x24C)
+#define _EXYNOS4_MCT_L_BASE            EXYNOS4_MCTREG(0x300)
+#define EXYNOS4_MCT_L_BASE(x)          (_EXYNOS4_MCT_L_BASE + (0x100 * x))
+#define EXYNOS4_MCT_L_MASK             (0xffffff00)
+
+#define MCT_L_TCNTB_OFFSET             (0x00)
+#define MCT_L_ICNTB_OFFSET             (0x08)
+#define MCT_L_TCON_OFFSET              (0x20)
+#define MCT_L_INT_CSTAT_OFFSET         (0x30)
+#define MCT_L_INT_ENB_OFFSET           (0x34)
+#define MCT_L_WSTAT_OFFSET             (0x40)
+#define MCT_G_TCON_START               (1 << 8)
+#define MCT_G_TCON_COMP0_AUTO_INC      (1 << 1)
+#define MCT_G_TCON_COMP0_ENABLE                (1 << 0)
+#define MCT_L_TCON_INTERVAL_MODE       (1 << 2)
+#define MCT_L_TCON_INT_START           (1 << 1)
+#define MCT_L_TCON_TIMER_START         (1 << 0)
+
 #define TICK_BASE_CNT  1
 
 enum {
@@ -38,64 +63,75 @@ enum {
        MCT_INT_PPI
 };
 
+enum {
+       MCT_G0_IRQ,
+       MCT_G1_IRQ,
+       MCT_G2_IRQ,
+       MCT_G3_IRQ,
+       MCT_L0_IRQ,
+       MCT_L1_IRQ,
+       MCT_L2_IRQ,
+       MCT_L3_IRQ,
+       MCT_NR_IRQS,
+};
+
+static void __iomem *reg_base;
 static unsigned long clk_rate;
 static unsigned int mct_int_type;
+static int mct_irqs[MCT_NR_IRQS];
 
 struct mct_clock_event_device {
        struct clock_event_device *evt;
-       void __iomem *base;
+       unsigned long base;
        char name[10];
 };
 
-static void exynos4_mct_write(unsigned int value, void *addr)
+static void exynos4_mct_write(unsigned int value, unsigned long offset)
 {
-       void __iomem *stat_addr;
+       unsigned long stat_addr;
        u32 mask;
        u32 i;
 
-       __raw_writel(value, addr);
+       __raw_writel(value, reg_base + offset);
 
-       if (likely(addr >= EXYNOS4_MCT_L_BASE(0))) {
-               u32 base = (u32) addr & EXYNOS4_MCT_L_MASK;
-               switch ((u32) addr & ~EXYNOS4_MCT_L_MASK) {
-               case (u32) MCT_L_TCON_OFFSET:
-                       stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+       if (likely(offset >= EXYNOS4_MCT_L_BASE(0))) {
+               stat_addr = (offset & ~EXYNOS4_MCT_L_MASK) + MCT_L_WSTAT_OFFSET;
+               switch (offset & EXYNOS4_MCT_L_MASK) {
+               case MCT_L_TCON_OFFSET:
                        mask = 1 << 3;          /* L_TCON write status */
                        break;
-               case (u32) MCT_L_ICNTB_OFFSET:
-                       stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+               case MCT_L_ICNTB_OFFSET:
                        mask = 1 << 1;          /* L_ICNTB write status */
                        break;
-               case (u32) MCT_L_TCNTB_OFFSET:
-                       stat_addr = (void __iomem *) base + MCT_L_WSTAT_OFFSET;
+               case MCT_L_TCNTB_OFFSET:
                        mask = 1 << 0;          /* L_TCNTB write status */
                        break;
                default:
                        return;
                }
        } else {
-               switch ((u32) addr) {
-               case (u32) EXYNOS4_MCT_G_TCON:
+               switch (offset) {
+               case EXYNOS4_MCT_G_TCON:
                        stat_addr = EXYNOS4_MCT_G_WSTAT;
                        mask = 1 << 16;         /* G_TCON write status */
                        break;
-               case (u32) EXYNOS4_MCT_G_COMP0_L:
+               case EXYNOS4_MCT_G_COMP0_L:
                        stat_addr = EXYNOS4_MCT_G_WSTAT;
                        mask = 1 << 0;          /* G_COMP0_L write status */
                        break;
-               case (u32) EXYNOS4_MCT_G_COMP0_U:
+               case EXYNOS4_MCT_G_COMP0_U:
                        stat_addr = EXYNOS4_MCT_G_WSTAT;
                        mask = 1 << 1;          /* G_COMP0_U write status */
                        break;
-               case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
+               case EXYNOS4_MCT_G_COMP0_ADD_INCR:
                        stat_addr = EXYNOS4_MCT_G_WSTAT;
                        mask = 1 << 2;          /* G_COMP0_ADD_INCR w status */
                        break;
-               case (u32) EXYNOS4_MCT_G_CNT_L:
+               case EXYNOS4_MCT_G_CNT_L:
                        stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
                        mask = 1 << 0;          /* G_CNT_L write status */
                        break;
-               case (u32) EXYNOS4_MCT_G_CNT_U:
+               case EXYNOS4_MCT_G_CNT_U:
                        stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
                        mask = 1 << 1;          /* G_CNT_U write status */
                        break;
@@ -106,12 +142,12 @@ static void exynos4_mct_write(unsigned int value, void *addr)
 
        /* Wait maximum 1 ms until written values are applied */
        for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
-               if (__raw_readl(stat_addr) & mask) {
-                       __raw_writel(mask, stat_addr);
+               if (__raw_readl(reg_base + stat_addr) & mask) {
+                       __raw_writel(mask, reg_base + stat_addr);
                        return;
                }
 
-       panic("MCT hangs after writing %d (addr:0x%08x)\n", value, (u32)addr);
+       panic("MCT hangs after writing %d (offset:0x%lx)\n", value, offset);
 }
 
 /* Clocksource handling */
@@ -122,7 +158,7 @@ static void exynos4_mct_frc_start(u32 hi, u32 lo)
        exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L);
        exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U);
 
-       reg = __raw_readl(EXYNOS4_MCT_G_TCON);
+       reg = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
        reg |= MCT_G_TCON_START;
        exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
 }
@@ -130,12 +166,12 @@ static void exynos4_mct_frc_start(u32 hi, u32 lo)
 static cycle_t exynos4_frc_read(struct clocksource *cs)
 {
        unsigned int lo, hi;
-       u32 hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
+       u32 hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
 
        do {
                hi = hi2;
-               lo = __raw_readl(EXYNOS4_MCT_G_CNT_L);
-               hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
+               lo = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_L);
+               hi2 = __raw_readl(reg_base + EXYNOS4_MCT_G_CNT_U);
        } while (hi != hi2);
 
        return ((cycle_t)hi << 32) | lo;
@@ -167,7 +203,7 @@ static void exynos4_mct_comp0_stop(void)
 {
        unsigned int tcon;
 
-       tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
+       tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
        tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
 
        exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
@@ -180,7 +216,7 @@ static void exynos4_mct_comp0_start(enum clock_event_mode mode,
        unsigned int tcon;
        cycle_t comp_cycle;
 
-       tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
+       tcon = __raw_readl(reg_base + EXYNOS4_MCT_G_TCON);
 
        if (mode == CLOCK_EVT_MODE_PERIODIC) {
                tcon |= MCT_G_TCON_COMP0_AUTO_INC;
@@ -257,11 +293,7 @@ static void exynos4_clockevent_init(void)
        mct_comp_device.cpumask = cpumask_of(0);
        clockevents_config_and_register(&mct_comp_device, clk_rate,
                                        0xf, 0xffffffff);
-
-       if (soc_is_exynos5250())
-               setup_irq(EXYNOS5_IRQ_MCT_G0, &mct_comp_event_irq);
-       else
-               setup_irq(EXYNOS4_IRQ_MCT_G0, &mct_comp_event_irq);
+       setup_irq(mct_irqs[MCT_G0_IRQ], &mct_comp_event_irq);
 }
 
 #ifdef CONFIG_LOCAL_TIMERS
@@ -273,12 +305,12 @@ static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
 {
        unsigned long tmp;
        unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
-       void __iomem *addr = mevt->base + MCT_L_TCON_OFFSET;
+       unsigned long offset = mevt->base + MCT_L_TCON_OFFSET;
 
-       tmp = __raw_readl(addr);
+       tmp = __raw_readl(reg_base + offset);
        if (tmp & mask) {
                tmp &= ~mask;
-               exynos4_mct_write(tmp, addr);
+               exynos4_mct_write(tmp, offset);
        }
 }
 
@@ -297,7 +329,7 @@ static void exynos4_mct_tick_start(unsigned long cycles,
        /* enable MCT tick interrupt */
        exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
 
-       tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET);
+       tmp = __raw_readl(reg_base + mevt->base + MCT_L_TCON_OFFSET);
        tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
               MCT_L_TCON_INTERVAL_MODE;
        exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
@@ -349,7 +381,7 @@ static int exynos4_mct_tick_clear(struct mct_clock_event_device *mevt)
                exynos4_mct_tick_stop(mevt);
 
        /* Clear the MCT tick interrupt */
-       if (__raw_readl(mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
+       if (__raw_readl(reg_base + mevt->base + MCT_L_INT_CSTAT_OFFSET) & 1) {
                exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
                return 1;
        } else {
@@ -385,7 +417,6 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
 {
        struct mct_clock_event_device *mevt;
        unsigned int cpu = smp_processor_id();
-       int mct_lx_irq;
 
        mevt = this_cpu_ptr(&percpu_mct_tick);
        mevt->evt = evt;
@@ -406,21 +437,17 @@ static int __cpuinit exynos4_local_timer_setup(struct clock_event_device *evt)
 
        if (mct_int_type == MCT_INT_SPI) {
                if (cpu == 0) {
-                       mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L0 :
-                                               EXYNOS5_IRQ_MCT_L0;
                        mct_tick0_event_irq.dev_id = mevt;
-                       evt->irq = mct_lx_irq;
-                       setup_irq(mct_lx_irq, &mct_tick0_event_irq);
+                       evt->irq = mct_irqs[MCT_L0_IRQ];
+                       setup_irq(evt->irq, &mct_tick0_event_irq);
                } else {
-                       mct_lx_irq = soc_is_exynos4210() ? EXYNOS4_IRQ_MCT_L1 :
-                                               EXYNOS5_IRQ_MCT_L1;
                        mct_tick1_event_irq.dev_id = mevt;
-                       evt->irq = mct_lx_irq;
-                       setup_irq(mct_lx_irq, &mct_tick1_event_irq);
-                       irq_set_affinity(mct_lx_irq, cpumask_of(1));
+                       evt->irq = mct_irqs[MCT_L1_IRQ];
+                       setup_irq(evt->irq, &mct_tick1_event_irq);
+                       irq_set_affinity(evt->irq, cpumask_of(1));
                }
        } else {
-               enable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER, 0);
+               enable_percpu_irq(mct_irqs[MCT_L0_IRQ], 0);
        }
 
        return 0;
@@ -436,7 +463,7 @@ static void exynos4_local_timer_stop(struct clock_event_device *evt)
                else
                        remove_irq(evt->irq, &mct_tick1_event_irq);
        else
-               disable_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER);
+               disable_percpu_irq(mct_irqs[MCT_L0_IRQ]);
 }
 
 static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
@@ -445,41 +472,88 @@ static struct local_timer_ops exynos4_mct_tick_ops __cpuinitdata = {
 };
 #endif /* CONFIG_LOCAL_TIMERS */
 
-static void __init exynos4_timer_resources(void)
+static void __init exynos4_timer_resources(struct device_node *np, void __iomem *base)
 {
-       struct clk *mct_clk;
-       mct_clk = clk_get(NULL, "xtal");
+       struct clk *mct_clk, *tick_clk;
+
+       tick_clk = np ? of_clk_get_by_name(np, "fin_pll") :
+                               clk_get(NULL, "fin_pll");
+       if (IS_ERR(tick_clk))
+               panic("%s: unable to determine tick clock rate\n", __func__);
+       clk_rate = clk_get_rate(tick_clk);
 
-       clk_rate = clk_get_rate(mct_clk);
+       mct_clk = np ? of_clk_get_by_name(np, "mct") : clk_get(NULL, "mct");
+       if (IS_ERR(mct_clk))
+               panic("%s: unable to retrieve mct clock instance\n", __func__);
+       clk_prepare_enable(mct_clk);
+
+       reg_base = base;
+       if (!reg_base)
+               panic("%s: unable to ioremap mct address space\n", __func__);
 
 #ifdef CONFIG_LOCAL_TIMERS
        if (mct_int_type == MCT_INT_PPI) {
                int err;
 
-               err = request_percpu_irq(EXYNOS_IRQ_MCT_LOCALTIMER,
+               err = request_percpu_irq(mct_irqs[MCT_L0_IRQ],
                                         exynos4_mct_tick_isr, "MCT",
                                         &percpu_mct_tick);
                WARN(err, "MCT: can't request IRQ %d (%d)\n",
-                    EXYNOS_IRQ_MCT_LOCALTIMER, err);
+                    mct_irqs[MCT_L0_IRQ], err);
        }
 
        local_timer_register(&exynos4_mct_tick_ops);
 #endif /* CONFIG_LOCAL_TIMERS */
 }
 
-void __init exynos4_timer_init(void)
+void __init mct_init(void __iomem *base, int irq_g0, int irq_l0, int irq_l1)
 {
-       if (soc_is_exynos5440()) {
-               arch_timer_of_register();
-               return;
-       }
+       mct_irqs[MCT_G0_IRQ] = irq_g0;
+       mct_irqs[MCT_L0_IRQ] = irq_l0;
+       mct_irqs[MCT_L1_IRQ] = irq_l1;
+       mct_int_type = MCT_INT_SPI;
 
-       if ((soc_is_exynos4210()) || (soc_is_exynos5250()))
-               mct_int_type = MCT_INT_SPI;
-       else
-               mct_int_type = MCT_INT_PPI;
+       exynos4_timer_resources(NULL, base);
+       exynos4_clocksource_init();
+       exynos4_clockevent_init();
+}
+
+static void __init mct_init_dt(struct device_node *np, unsigned int int_type)
+{
+       u32 nr_irqs, i;
+
+       mct_int_type = int_type;
 
-       exynos4_timer_resources();
+       /* This driver uses only one global timer interrupt */
+       mct_irqs[MCT_G0_IRQ] = irq_of_parse_and_map(np, MCT_G0_IRQ);
+
+       /*
+        * Find out the number of local irqs specified. The local
+        * timer irqs are specified after the four global timer
+        * irqs are specified.
+        */
+#ifdef CONFIG_OF
+       nr_irqs = of_irq_count(np);
+#else
+       nr_irqs = 0;
+#endif
+       for (i = MCT_L0_IRQ; i < nr_irqs; i++)
+               mct_irqs[i] = irq_of_parse_and_map(np, i);
+
+       exynos4_timer_resources(np, of_iomap(np, 0));
        exynos4_clocksource_init();
        exynos4_clockevent_init();
 }
+
+
+static void __init mct_init_spi(struct device_node *np)
+{
+       return mct_init_dt(np, MCT_INT_SPI);
+}
+
+static void __init mct_init_ppi(struct device_node *np)
+{
+       return mct_init_dt(np, MCT_INT_PPI);
+}
+CLOCKSOURCE_OF_DECLARE(exynos4210, "samsung,exynos4210-mct", mct_init_spi);
+CLOCKSOURCE_OF_DECLARE(exynos4412, "samsung,exynos4412-mct", mct_init_ppi);
index 488c14cc8dbf4848085142ca03e171ed35526b40..08d0c418c94ae5ed3e4c5791ab929fc6501d0de3 100644 (file)
@@ -54,62 +54,100 @@ struct sh_cmt_priv {
        struct clocksource cs;
        unsigned long total_cycles;
        bool cs_enabled;
+
+       /* callbacks for CMSTR and CMCSR access */
+       unsigned long (*read_control)(void __iomem *base, unsigned long offs);
+       void (*write_control)(void __iomem *base, unsigned long offs,
+                             unsigned long value);
+
+       /* callbacks for CMCNT and CMCOR access */
+       unsigned long (*read_count)(void __iomem *base, unsigned long offs);
+       void (*write_count)(void __iomem *base, unsigned long offs,
+                           unsigned long value);
 };
 
-static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
+/* Examples of supported CMT timer register layouts and I/O access widths:
+ *
+ * "16-bit counter and 16-bit control" as found on sh7263:
+ * CMSTR 0xfffec000 16-bit
+ * CMCSR 0xfffec002 16-bit
+ * CMCNT 0xfffec004 16-bit
+ * CMCOR 0xfffec006 16-bit
+ *
+ * "32-bit counter and 16-bit control" as found on sh7372, sh73a0, r8a7740:
+ * CMSTR 0xffca0000 16-bit
+ * CMCSR 0xffca0060 16-bit
+ * CMCNT 0xffca0064 32-bit
+ * CMCOR 0xffca0068 32-bit
+ */
+
+static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs)
+{
+       return ioread16(base + (offs << 1));
+}
+
+static unsigned long sh_cmt_read32(void __iomem *base, unsigned long offs)
+{
+       return ioread32(base + (offs << 2));
+}
+
+static void sh_cmt_write16(void __iomem *base, unsigned long offs,
+                          unsigned long value)
+{
+       iowrite16(value, base + (offs << 1));
+}
+
+static void sh_cmt_write32(void __iomem *base, unsigned long offs,
+                          unsigned long value)
+{
+       iowrite32(value, base + (offs << 2));
+}
 
-#define CMSTR -1 /* shared register */
 #define CMCSR 0 /* channel register */
 #define CMCNT 1 /* channel register */
 #define CMCOR 2 /* channel register */
 
-static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr)
+static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p)
 {
        struct sh_timer_config *cfg = p->pdev->dev.platform_data;
-       void __iomem *base = p->mapbase;
-       unsigned long offs;
-
-       if (reg_nr == CMSTR) {
-               offs = 0;
-               base -= cfg->channel_offset;
-       } else
-               offs = reg_nr;
-
-       if (p->width == 16)
-               offs <<= 1;
-       else {
-               offs <<= 2;
-               if ((reg_nr == CMCNT) || (reg_nr == CMCOR))
-                       return ioread32(base + offs);
-       }
 
-       return ioread16(base + offs);
+       return p->read_control(p->mapbase - cfg->channel_offset, 0);
 }
 
-static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr,
-                               unsigned long value)
+static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p)
+{
+       return p->read_control(p->mapbase, CMCSR);
+}
+
+static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p)
+{
+       return p->read_count(p->mapbase, CMCNT);
+}
+
+static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p,
+                                     unsigned long value)
 {
        struct sh_timer_config *cfg = p->pdev->dev.platform_data;
-       void __iomem *base = p->mapbase;
-       unsigned long offs;
-
-       if (reg_nr == CMSTR) {
-               offs = 0;
-               base -= cfg->channel_offset;
-       } else
-               offs = reg_nr;
-
-       if (p->width == 16)
-               offs <<= 1;
-       else {
-               offs <<= 2;
-               if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) {
-                       iowrite32(value, base + offs);
-                       return;
-               }
-       }
 
-       iowrite16(value, base + offs);
+       p->write_control(p->mapbase - cfg->channel_offset, 0, value);
+}
+
+static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p,
+                                     unsigned long value)
+{
+       p->write_control(p->mapbase, CMCSR, value);
+}
+
+static inline void sh_cmt_write_cmcnt(struct sh_cmt_priv *p,
+                                     unsigned long value)
+{
+       p->write_count(p->mapbase, CMCNT, value);
+}
+
+static inline void sh_cmt_write_cmcor(struct sh_cmt_priv *p,
+                                     unsigned long value)
+{
+       p->write_count(p->mapbase, CMCOR, value);
 }
 
 static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
@@ -118,15 +156,15 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
        unsigned long v1, v2, v3;
        int o1, o2;
 
-       o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+       o1 = sh_cmt_read_cmcsr(p) & p->overflow_bit;
 
        /* Make sure the timer value is stable. Stolen from acpi_pm.c */
        do {
                o2 = o1;
-               v1 = sh_cmt_read(p, CMCNT);
-               v2 = sh_cmt_read(p, CMCNT);
-               v3 = sh_cmt_read(p, CMCNT);
-               o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit;
+               v1 = sh_cmt_read_cmcnt(p);
+               v2 = sh_cmt_read_cmcnt(p);
+               v3 = sh_cmt_read_cmcnt(p);
+               o1 = sh_cmt_read_cmcsr(p) & p->overflow_bit;
        } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3)
                          || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2)));
 
@@ -134,6 +172,7 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p,
        return v2;
 }
 
+static DEFINE_RAW_SPINLOCK(sh_cmt_lock);
 
 static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
 {
@@ -142,14 +181,14 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start)
 
        /* start stop register shared by multiple timer channels */
        raw_spin_lock_irqsave(&sh_cmt_lock, flags);
-       value = sh_cmt_read(p, CMSTR);
+       value = sh_cmt_read_cmstr(p);
 
        if (start)
                value |= 1 << cfg->timer_bit;
        else
                value &= ~(1 << cfg->timer_bit);
 
-       sh_cmt_write(p, CMSTR, value);
+       sh_cmt_write_cmstr(p, value);
        raw_spin_unlock_irqrestore(&sh_cmt_lock, flags);
 }
 
@@ -173,14 +212,14 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
        /* configure channel, periodic mode and maximum timeout */
        if (p->width == 16) {
                *rate = clk_get_rate(p->clk) / 512;
-               sh_cmt_write(p, CMCSR, 0x43);
+               sh_cmt_write_cmcsr(p, 0x43);
        } else {
                *rate = clk_get_rate(p->clk) / 8;
-               sh_cmt_write(p, CMCSR, 0x01a4);
+               sh_cmt_write_cmcsr(p, 0x01a4);
        }
 
-       sh_cmt_write(p, CMCOR, 0xffffffff);
-       sh_cmt_write(p, CMCNT, 0);
+       sh_cmt_write_cmcor(p, 0xffffffff);
+       sh_cmt_write_cmcnt(p, 0);
 
        /*
         * According to the sh73a0 user's manual, as CMCNT can be operated
@@ -194,12 +233,12 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate)
         * take RCLKx2 at maximum.
         */
        for (k = 0; k < 100; k++) {
-               if (!sh_cmt_read(p, CMCNT))
+               if (!sh_cmt_read_cmcnt(p))
                        break;
                udelay(1);
        }
 
-       if (sh_cmt_read(p, CMCNT)) {
+       if (sh_cmt_read_cmcnt(p)) {
                dev_err(&p->pdev->dev, "cannot clear CMCNT\n");
                ret = -ETIMEDOUT;
                goto err1;
@@ -222,7 +261,7 @@ static void sh_cmt_disable(struct sh_cmt_priv *p)
        sh_cmt_start_stop_ch(p, 0);
 
        /* disable interrupts in CMT block */
-       sh_cmt_write(p, CMCSR, 0);
+       sh_cmt_write_cmcsr(p, 0);
 
        /* stop clock */
        clk_disable(p->clk);
@@ -270,7 +309,7 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p,
                if (new_match > p->max_match_value)
                        new_match = p->max_match_value;
 
-               sh_cmt_write(p, CMCOR, new_match);
+               sh_cmt_write_cmcor(p, new_match);
 
                now = sh_cmt_get_counter(p, &has_wrapped);
                if (has_wrapped && (new_match > p->match_value)) {
@@ -346,7 +385,7 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id)
        struct sh_cmt_priv *p = dev_id;
 
        /* clear flags */
-       sh_cmt_write(p, CMCSR, sh_cmt_read(p, CMCSR) & p->clear_bits);
+       sh_cmt_write_cmcsr(p, sh_cmt_read_cmcsr(p) & p->clear_bits);
 
        /* update clock source counter to begin with if enabled
         * the wrap flag should be cleared by the timer specific
@@ -625,14 +664,6 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name,
                           unsigned long clockevent_rating,
                           unsigned long clocksource_rating)
 {
-       if (p->width == (sizeof(p->max_match_value) * 8))
-               p->max_match_value = ~0;
-       else
-               p->max_match_value = (1 << p->width) - 1;
-
-       p->match_value = p->max_match_value;
-       raw_spin_lock_init(&p->lock);
-
        if (clockevent_rating)
                sh_cmt_register_clockevent(p, name, clockevent_rating);
 
@@ -657,8 +688,6 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
                goto err0;
        }
 
-       platform_set_drvdata(pdev, p);
-
        res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(&p->pdev->dev, "failed to get I/O memory\n");
@@ -693,32 +722,51 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev)
                goto err1;
        }
 
+       p->read_control = sh_cmt_read16;
+       p->write_control = sh_cmt_write16;
+
        if (resource_size(res) == 6) {
                p->width = 16;
+               p->read_count = sh_cmt_read16;
+               p->write_count = sh_cmt_write16;
                p->overflow_bit = 0x80;
                p->clear_bits = ~0x80;
        } else {
                p->width = 32;
+               p->read_count = sh_cmt_read32;
+               p->write_count = sh_cmt_write32;
                p->overflow_bit = 0x8000;
                p->clear_bits = ~0xc000;
        }
 
+       if (p->width == (sizeof(p->max_match_value) * 8))
+               p->max_match_value = ~0;
+       else
+               p->max_match_value = (1 << p->width) - 1;
+
+       p->match_value = p->max_match_value;
+       raw_spin_lock_init(&p->lock);
+
        ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev),
                              cfg->clockevent_rating,
                              cfg->clocksource_rating);
        if (ret) {
                dev_err(&p->pdev->dev, "registration failed\n");
-               goto err1;
+               goto err2;
        }
        p->cs_enabled = false;
 
        ret = setup_irq(irq, &p->irqaction);
        if (ret) {
                dev_err(&p->pdev->dev, "failed to request irq %d\n", irq);
-               goto err1;
+               goto err2;
        }
 
+       platform_set_drvdata(pdev, p);
+
        return 0;
+err2:
+       clk_put(p->clk);
 
 err1:
        iounmap(p->mapbase);
@@ -751,7 +799,6 @@ static int sh_cmt_probe(struct platform_device *pdev)
        ret = sh_cmt_setup(p, pdev);
        if (ret) {
                kfree(p);
-               platform_set_drvdata(pdev, NULL);
                pm_runtime_idle(&pdev->dev);
                return ret;
        }
@@ -791,7 +838,7 @@ static void __exit sh_cmt_exit(void)
 }
 
 early_platform_init("earlytimer", &sh_cmt_device_driver);
-module_init(sh_cmt_init);
+subsys_initcall(sh_cmt_init);
 module_exit(sh_cmt_exit);
 
 MODULE_AUTHOR("Magnus Damm");
index 83943e27cfac9193e659ecf7221afcfb48bcd73d..4aac9ee0d0c054a7ba953b17ac3272946af7b47d 100644 (file)
@@ -386,7 +386,7 @@ static void __exit sh_mtu2_exit(void)
 }
 
 early_platform_init("earlytimer", &sh_mtu2_device_driver);
-module_init(sh_mtu2_init);
+subsys_initcall(sh_mtu2_init);
 module_exit(sh_mtu2_exit);
 
 MODULE_AUTHOR("Magnus Damm");
index b4502edce2a140eb3d1f197d0cb39c294e5f0b2f..78b8dae49628cce42fb45ebdff2b32ece5045a52 100644 (file)
@@ -549,7 +549,7 @@ static void __exit sh_tmu_exit(void)
 }
 
 early_platform_init("earlytimer", &sh_tmu_device_driver);
-module_init(sh_tmu_init);
+subsys_initcall(sh_tmu_init);
 module_exit(sh_tmu_exit);
 
 MODULE_AUTHOR("Magnus Damm");
index 4086b9167159391d07418e0d8b75509779bad6df..0ce85e29769b80ac7c9e2b958e84bf87505c09eb 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/sunxi_timer.h>
-#include <linux/clk-provider.h>
+#include <linux/clk/sunxi.h>
 
 #define TIMER_CTL_REG          0x00
 #define TIMER_CTL_ENABLE               (1 << 0)
@@ -123,7 +123,7 @@ void __init sunxi_timer_init(void)
        if (irq <= 0)
                panic("Can't parse IRQ");
 
-       of_clk_init(NULL);
+       sunxi_init_clocks();
 
        clk = of_clk_get(node, 0);
        if (IS_ERR(clk))
index 2e4d8a666c36d6ee40db523408f34a8b5927bebf..ae877b021b54449219cef0d1f3e43fe442c54bca 100644 (file)
@@ -172,7 +172,7 @@ static void __init tegra20_init_timer(struct device_node *np)
                BUG();
        }
 
-       clk = clk_get_sys("timer", NULL);
+       clk = of_clk_get(np, 0);
        if (IS_ERR(clk)) {
                pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n");
                rate = 12000000;
@@ -235,7 +235,7 @@ static void __init tegra20_init_rtc(struct device_node *np)
         * rtc registers are used by read_persistent_clock, keep the rtc clock
         * enabled
         */
-       clk = clk_get_sys("rtc-tegra", NULL);
+       clk = of_clk_get(np, 0);
        if (IS_ERR(clk))
                pr_warn("Unable to get rtc-tegra clock\n");
        else
index 937bc286591f9349b5366295fa210412b8ffb756..57a8774f0b4ee907ab67d9c9f8fefd1e3d18fdbd 100644 (file)
@@ -730,7 +730,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
            policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) {
                cpumask_copy(policy->cpus, perf->shared_cpu_map);
        }
-       cpumask_copy(policy->related_cpus, perf->shared_cpu_map);
 
 #ifdef CONFIG_SMP
        dmi_check_system(sw_any_bug_dmi_table);
@@ -742,7 +741,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy)
        if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) {
                cpumask_clear(policy->cpus);
                cpumask_set_cpu(cpu, policy->cpus);
-               cpumask_copy(policy->related_cpus, cpu_sibling_mask(cpu));
                policy->shared_type = CPUFREQ_SHARED_TYPE_HW;
                pr_info_once(PFX "overriding BIOS provided _PSD data\n");
        }
index 4e5b7fb8927cb5304e3baf37dc3ccb87e71c31b9..37d23a0f8c569f93896808fa53c7a9c09b29d0a9 100644 (file)
@@ -178,10 +178,16 @@ static struct cpufreq_driver cpu0_cpufreq_driver = {
 
 static int cpu0_cpufreq_probe(struct platform_device *pdev)
 {
-       struct device_node *np;
+       struct device_node *np, *parent;
        int ret;
 
-       for_each_child_of_node(of_find_node_by_path("/cpus"), np) {
+       parent = of_find_node_by_path("/cpus");
+       if (!parent) {
+               pr_err("failed to find OF /cpus\n");
+               return -ENOENT;
+       }
+
+       for_each_child_of_node(parent, np) {
                if (of_get_property(np, "operating-points", NULL))
                        break;
        }
index 46bde01eee623bd443d582013425257fbd11ec50..cc4bd2f6838a30febb93e8bc1f9c55978cb2c19c 100644 (file)
@@ -14,8 +14,8 @@
  * published by the Free Software Foundation.
  */
 
-#ifndef _CPUFREQ_GOVERNER_H
-#define _CPUFREQ_GOVERNER_H
+#ifndef _CPUFREQ_GOVERNOR_H
+#define _CPUFREQ_GOVERNOR_H
 
 #include <linux/cpufreq.h>
 #include <linux/kobject.h>
@@ -175,4 +175,4 @@ bool need_load_eval(struct cpu_dbs_common_info *cdbs,
                unsigned int sampling_rate);
 int cpufreq_governor_dbs(struct dbs_data *dbs_data,
                struct cpufreq_policy *policy, unsigned int event);
-#endif /* _CPUFREQ_GOVERNER_H */
+#endif /* _CPUFREQ_GOVERNOR_H */
index 2fd779eb1ed1f9fcdb7cb70ab54ed319fe1e4160..bfd6273fd873531d864f3b4e104d37018a5d8dda 100644 (file)
@@ -180,15 +180,19 @@ static void cpufreq_stats_free_sysfs(unsigned int cpu)
 {
        struct cpufreq_policy *policy = cpufreq_cpu_get(cpu);
 
-       if (!cpufreq_frequency_get_table(cpu))
+       if (!policy)
                return;
 
-       if (policy && !policy_is_shared(policy)) {
+       if (!cpufreq_frequency_get_table(cpu))
+               goto put_ref;
+
+       if (!policy_is_shared(policy)) {
                pr_debug("%s: Free sysfs stat\n", __func__);
                sysfs_remove_group(&policy->kobj, &stats_attr_group);
        }
-       if (policy)
-               cpufreq_cpu_put(policy);
+
+put_ref:
+       cpufreq_cpu_put(policy);
 }
 
 static int cpufreq_stats_create_table(struct cpufreq_policy *policy,
index f6dd1e7611293bf5a66531f2acb285713439430c..ad72922919ed79b181a83467dea455216676d56c 100644 (file)
@@ -358,14 +358,14 @@ static void intel_pstate_sysfs_expose_params(void)
 static int intel_pstate_min_pstate(void)
 {
        u64 value;
-       rdmsrl(0xCE, value);
+       rdmsrl(MSR_PLATFORM_INFO, value);
        return (value >> 40) & 0xFF;
 }
 
 static int intel_pstate_max_pstate(void)
 {
        u64 value;
-       rdmsrl(0xCE, value);
+       rdmsrl(MSR_PLATFORM_INFO, value);
        return (value >> 8) & 0xFF;
 }
 
@@ -373,7 +373,7 @@ static int intel_pstate_turbo_pstate(void)
 {
        u64 value;
        int nont, ret;
-       rdmsrl(0x1AD, value);
+       rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value);
        nont = intel_pstate_max_pstate();
        ret = ((value) & 255);
        if (ret <= nont)
@@ -454,7 +454,7 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu,
                                        sample->idletime_us * 100,
                                        sample->duration_us);
        core_pct = div64_u64(sample->aperf * 100, sample->mperf);
-       sample->freq = cpu->pstate.turbo_pstate * core_pct * 1000;
+       sample->freq = cpu->pstate.max_pstate * core_pct * 1000;
 
        sample->core_pct_busy = div_s64((sample->pstate_pct_busy * core_pct),
                                        100);
@@ -752,6 +752,29 @@ static struct cpufreq_driver intel_pstate_driver = {
 
 static int __initdata no_load;
 
+static int intel_pstate_msrs_not_valid(void)
+{
+       /* Check that all the msr's we are using are valid. */
+       u64 aperf, mperf, tmp;
+
+       rdmsrl(MSR_IA32_APERF, aperf);
+       rdmsrl(MSR_IA32_MPERF, mperf);
+
+       if (!intel_pstate_min_pstate() ||
+               !intel_pstate_max_pstate() ||
+               !intel_pstate_turbo_pstate())
+               return -ENODEV;
+
+       rdmsrl(MSR_IA32_APERF, tmp);
+       if (!(tmp - aperf))
+               return -ENODEV;
+
+       rdmsrl(MSR_IA32_MPERF, tmp);
+       if (!(tmp - mperf))
+               return -ENODEV;
+
+       return 0;
+}
 static int __init intel_pstate_init(void)
 {
        int cpu, rc = 0;
@@ -764,6 +787,9 @@ static int __init intel_pstate_init(void)
        if (!id)
                return -ENODEV;
 
+       if (intel_pstate_msrs_not_valid())
+               return -ENODEV;
+
        pr_info("Intel P-state driver initializing.\n");
 
        all_cpu_data = vmalloc(sizeof(void *) * num_possible_cpus());
index b2a0a0726a5405caf7c0f7d252745d9554e34643..cf268b14ae9a393890ac37597f29008ee2c93126 100644 (file)
@@ -1650,11 +1650,7 @@ struct caam_alg_template {
 };
 
 static struct caam_alg_template driver_algs[] = {
-       /*
-        * single-pass ipsec_esp descriptor
-        * authencesn(*,*) is also registered, although not present
-        * explicitly here.
-        */
+       /* single-pass ipsec_esp descriptor */
        {
                .name = "authenc(hmac(md5),cbc(aes))",
                .driver_name = "authenc-hmac-md5-cbc-aes-caam",
@@ -2217,9 +2213,7 @@ static int __init caam_algapi_init(void)
        for (i = 0; i < ARRAY_SIZE(driver_algs); i++) {
                /* TODO: check if h/w supports alg */
                struct caam_crypto_alg *t_alg;
-               bool done = false;
 
-authencesn:
                t_alg = caam_alg_alloc(ctrldev, &driver_algs[i]);
                if (IS_ERR(t_alg)) {
                        err = PTR_ERR(t_alg);
@@ -2233,25 +2227,8 @@ authencesn:
                        dev_warn(ctrldev, "%s alg registration failed\n",
                                t_alg->crypto_alg.cra_driver_name);
                        kfree(t_alg);
-               } else {
+               } else
                        list_add_tail(&t_alg->entry, &priv->alg_list);
-                       if (driver_algs[i].type == CRYPTO_ALG_TYPE_AEAD &&
-                           !memcmp(driver_algs[i].name, "authenc", 7) &&
-                           !done) {
-                               char *name;
-
-                               name = driver_algs[i].name;
-                               memmove(name + 10, name + 7, strlen(name) - 7);
-                               memcpy(name + 7, "esn", 3);
-
-                               name = driver_algs[i].driver_name;
-                               memmove(name + 10, name + 7, strlen(name) - 7);
-                               memcpy(name + 7, "esn", 3);
-
-                               done = true;
-                               goto authencesn;
-                       }
-               }
        }
        if (!list_empty(&priv->alg_list))
                dev_info(ctrldev, "%s algorithms registered in /proc/crypto\n",
index cf15e7813801a6cb8e1d631663a2fb4421cb5a7a..762aeff626ac6f7a980c8fe3019fcd72252ecd7c 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/types.h>
 #include <linux/debugfs.h>
 #include <linux/circ_buf.h>
-#include <linux/string.h>
 #include <net/xfrm.h>
 
 #include <crypto/algapi.h>
index 09b184adf31b73902a98651843805e0c129c15b9..5b2b5e61e4f9d0516e4b66090ba56ef79e941632 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/spinlock.h>
 #include <linux/rtnetlink.h>
 #include <linux/slab.h>
-#include <linux/string.h>
 
 #include <crypto/algapi.h>
 #include <crypto/aes.h>
@@ -1974,11 +1973,7 @@ struct talitos_alg_template {
 };
 
 static struct talitos_alg_template driver_algs[] = {
-       /*
-        * AEAD algorithms. These use a single-pass ipsec_esp descriptor.
-        * authencesn(*,*) is also registered, although not present
-        * explicitly here.
-        */
+       /* AEAD algorithms.  These use a single-pass ipsec_esp descriptor */
        {       .type = CRYPTO_ALG_TYPE_AEAD,
                .alg.crypto = {
                        .cra_name = "authenc(hmac(sha1),cbc(aes))",
@@ -2820,9 +2815,7 @@ static int talitos_probe(struct platform_device *ofdev)
                if (hw_supports(dev, driver_algs[i].desc_hdr_template)) {
                        struct talitos_crypto_alg *t_alg;
                        char *name = NULL;
-                       bool authenc = false;
 
-authencesn:
                        t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
                        if (IS_ERR(t_alg)) {
                                err = PTR_ERR(t_alg);
@@ -2837,8 +2830,6 @@ authencesn:
                                err = crypto_register_alg(
                                                &t_alg->algt.alg.crypto);
                                name = t_alg->algt.alg.crypto.cra_driver_name;
-                               authenc = authenc ? !authenc :
-                                         !(bool)memcmp(name, "authenc", 7);
                                break;
                        case CRYPTO_ALG_TYPE_AHASH:
                                err = crypto_register_ahash(
@@ -2851,25 +2842,8 @@ authencesn:
                                dev_err(dev, "%s alg registration failed\n",
                                        name);
                                kfree(t_alg);
-                       } else {
+                       } else
                                list_add_tail(&t_alg->entry, &priv->alg_list);
-                               if (authenc) {
-                                       struct crypto_alg *alg =
-                                               &driver_algs[i].alg.crypto;
-
-                                       name = alg->cra_name;
-                                       memmove(name + 10, name + 7,
-                                               strlen(name) - 7);
-                                       memcpy(name + 7, "esn", 3);
-
-                                       name = alg->cra_driver_name;
-                                       memmove(name + 10, name + 7,
-                                               strlen(name) - 7);
-                                       memcpy(name + 7, "esn", 3);
-
-                                       goto authencesn;
-                               }
-                       }
                }
        }
        if (!list_empty(&priv->alg_list))
index 80b69971cf28d01752abd3654a8cc296f25a8380..aeaea32bcfdacd5fed2eb7e53536169348791cc8 100644 (file)
@@ -83,6 +83,7 @@ config INTEL_IOP_ADMA
 
 config DW_DMAC
        tristate "Synopsys DesignWare AHB DMA support"
+       depends on GENERIC_HARDIRQS
        select DMA_ENGINE
        default y if CPU_AT32AP7000
        help
index c599558faedaf29128a5a10bb15eaed7dbc5d41c..43a5329d44837c4042687d6f93436b3caf0627c1 100644 (file)
@@ -1001,6 +1001,13 @@ static inline void convert_burst(u32 *maxburst)
                *maxburst = 0;
 }
 
+static inline void convert_slave_id(struct dw_dma_chan *dwc)
+{
+       struct dw_dma *dw = to_dw_dma(dwc->chan.device);
+
+       dwc->dma_sconfig.slave_id -= dw->request_line_base;
+}
+
 static int
 set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
 {
@@ -1015,6 +1022,7 @@ set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig)
 
        convert_burst(&dwc->dma_sconfig.src_maxburst);
        convert_burst(&dwc->dma_sconfig.dst_maxburst);
+       convert_slave_id(dwc);
 
        return 0;
 }
@@ -1276,9 +1284,9 @@ static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec,
        if (dma_spec->args_count != 3)
                return NULL;
 
-       fargs.req = be32_to_cpup(dma_spec->args+0);
-       fargs.src = be32_to_cpup(dma_spec->args+1);
-       fargs.dst = be32_to_cpup(dma_spec->args+2);
+       fargs.req = dma_spec->args[0];
+       fargs.src = dma_spec->args[1];
+       fargs.dst = dma_spec->args[2];
 
        if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS ||
                    fargs.src >= dw->nr_masters ||
@@ -1628,6 +1636,7 @@ dw_dma_parse_dt(struct platform_device *pdev)
 
 static int dw_probe(struct platform_device *pdev)
 {
+       const struct platform_device_id *match;
        struct dw_dma_platform_data *pdata;
        struct resource         *io;
        struct dw_dma           *dw;
@@ -1711,6 +1720,11 @@ static int dw_probe(struct platform_device *pdev)
                memcpy(dw->data_width, pdata->data_width, 4);
        }
 
+       /* Get the base request line if set */
+       match = platform_get_device_id(pdev);
+       if (match)
+               dw->request_line_base = (unsigned int)match->driver_data;
+
        /* Calculate all channel mask before DMA setup */
        dw->all_chan_mask = (1 << nr_channels) - 1;
 
@@ -1906,7 +1920,8 @@ MODULE_DEVICE_TABLE(of, dw_dma_id_table);
 #endif
 
 static const struct platform_device_id dw_dma_ids[] = {
-       { "INTL9C60", 0 },
+       /* Name,        Request Line Base */
+       { "INTL9C60",   (kernel_ulong_t)16 },
        { }
 };
 
index cf0ce5c77d609d52e024f3426ab521bdb86e7545..4d02c3669b75bcf023a7f03916d02d3749ec2e1e 100644 (file)
@@ -247,6 +247,7 @@ struct dw_dma {
        /* hardware configuration */
        unsigned char           nr_masters;
        unsigned char           data_width[4];
+       unsigned int            request_line_base;
 
        struct dw_dma_chan      chan[0];
 };
index 910b0116c12872aaebb5e72707ddc920d0722ce1..e1d13c463c9094e4f1b996311b1767725619f90f 100644 (file)
@@ -2048,12 +2048,18 @@ static int init_csrows(struct mem_ctl_info *mci)
                edac_dbg(1, "MC node: %d, csrow: %d\n",
                            pvt->mc_node_id, i);
 
-               if (row_dct0)
+               if (row_dct0) {
                        nr_pages = amd64_csrow_nr_pages(pvt, 0, i);
+                       csrow->channels[0]->dimm->nr_pages = nr_pages;
+               }
 
                /* K8 has only one DCT */
-               if (boot_cpu_data.x86 != 0xf && row_dct1)
-                       nr_pages += amd64_csrow_nr_pages(pvt, 1, i);
+               if (boot_cpu_data.x86 != 0xf && row_dct1) {
+                       int row_dct1_pages = amd64_csrow_nr_pages(pvt, 1, i);
+
+                       csrow->channels[1]->dimm->nr_pages = row_dct1_pages;
+                       nr_pages += row_dct1_pages;
+               }
 
                mtype = amd64_determine_memory_type(pvt, i);
 
@@ -2072,9 +2078,7 @@ static int init_csrows(struct mem_ctl_info *mci)
                        dimm = csrow->channels[j]->dimm;
                        dimm->mtype = mtype;
                        dimm->edac_mode = edac_mode;
-                       dimm->nr_pages = nr_pages;
                }
-               csrow->nr_pages = nr_pages;
        }
 
        return empty;
@@ -2419,7 +2423,6 @@ static int amd64_init_one_instance(struct pci_dev *F2)
 
        mci->pvt_info = pvt;
        mci->pdev = &pvt->F2->dev;
-       mci->csbased = 1;
 
        setup_mci_misc_attrs(mci, fam_type);
 
index cdb81aa73ab7aeb595be53f77430488486947e66..27e86d93826280a62744a559332bf0cd9bc03b3b 100644 (file)
@@ -86,7 +86,7 @@ static void edac_mc_dump_dimm(struct dimm_info *dimm, int number)
        edac_dimm_info_location(dimm, location, sizeof(location));
 
        edac_dbg(4, "%s%i: %smapped as virtual row %d, chan %d\n",
-                dimm->mci->mem_is_per_rank ? "rank" : "dimm",
+                dimm->mci->csbased ? "rank" : "dimm",
                 number, location, dimm->csrow, dimm->cschannel);
        edac_dbg(4, "  dimm = %p\n", dimm);
        edac_dbg(4, "  dimm->label = '%s'\n", dimm->label);
@@ -341,7 +341,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
        memcpy(mci->layers, layers, sizeof(*layer) * n_layers);
        mci->nr_csrows = tot_csrows;
        mci->num_cschannel = tot_channels;
-       mci->mem_is_per_rank = per_rank;
+       mci->csbased = per_rank;
 
        /*
         * Alocate and fill the csrow/channels structs
@@ -1235,7 +1235,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type,
                         * incrementing the compat API counters
                         */
                        edac_dbg(4, "%s csrows map: (%d,%d)\n",
-                                mci->mem_is_per_rank ? "rank" : "dimm",
+                                mci->csbased ? "rank" : "dimm",
                                 dimm->csrow, dimm->cschannel);
                        if (row == -1)
                                row = dimm->csrow;
index 4f4b6137d74e6c4ebd894e104cdeaf18cd565969..5899a76eec3bd9086d1edfc24fa1b4aca1ce7969 100644 (file)
@@ -143,7 +143,7 @@ static const char *edac_caps[] = {
  * and the per-dimm/per-rank one
  */
 #define DEVICE_ATTR_LEGACY(_name, _mode, _show, _store) \
-       struct device_attribute dev_attr_legacy_##_name = __ATTR(_name, _mode, _show, _store)
+       static struct device_attribute dev_attr_legacy_##_name = __ATTR(_name, _mode, _show, _store)
 
 struct dev_ch_attribute {
        struct device_attribute attr;
@@ -180,9 +180,6 @@ static ssize_t csrow_size_show(struct device *dev,
        int i;
        u32 nr_pages = 0;
 
-       if (csrow->mci->csbased)
-               return sprintf(data, "%u\n", PAGES_TO_MiB(csrow->nr_pages));
-
        for (i = 0; i < csrow->nr_channels; i++)
                nr_pages += csrow->channels[i]->dimm->nr_pages;
        return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages));
@@ -612,7 +609,7 @@ static int edac_create_dimm_object(struct mem_ctl_info *mci,
        device_initialize(&dimm->dev);
 
        dimm->dev.parent = &mci->dev;
-       if (mci->mem_is_per_rank)
+       if (mci->csbased)
                dev_set_name(&dimm->dev, "rank%d", index);
        else
                dev_set_name(&dimm->dev, "dimm%d", index);
@@ -778,14 +775,10 @@ static ssize_t mci_size_mb_show(struct device *dev,
        for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) {
                struct csrow_info *csrow = mci->csrows[csrow_idx];
 
-               if (csrow->mci->csbased) {
-                       total_pages += csrow->nr_pages;
-               } else {
-                       for (j = 0; j < csrow->nr_channels; j++) {
-                               struct dimm_info *dimm = csrow->channels[j]->dimm;
+               for (j = 0; j < csrow->nr_channels; j++) {
+                       struct dimm_info *dimm = csrow->channels[j]->dimm;
 
-                               total_pages += dimm->nr_pages;
-                       }
+                       total_pages += dimm->nr_pages;
                }
        }
 
index cdae207028a720f5080b3a55c9cf63e3e7b84424..6c3fca97d346db9c6912bd3977eec99c5c7d563a 100644 (file)
 /* There is only *one* pci_eisa device per machine, right ? */
 static struct eisa_root_device pci_eisa_root;
 
-static int __init pci_eisa_init(struct pci_dev *pdev,
-                               const struct pci_device_id *ent)
+static int __init pci_eisa_init(struct pci_dev *pdev)
 {
-       int rc;
+       int rc, i;
+       struct resource *res, *bus_res = NULL;
 
        if ((rc = pci_enable_device (pdev))) {
                printk (KERN_ERR "pci_eisa : Could not enable device %s\n",
@@ -30,9 +30,30 @@ static int __init pci_eisa_init(struct pci_dev *pdev,
                return rc;
        }
 
+       /*
+        * The Intel 82375 PCI-EISA bridge is a subtractive-decode PCI
+        * device, so the resources available on EISA are the same as those
+        * available on the 82375 bus.  This works the same as a PCI-PCI
+        * bridge in subtractive-decode mode (see pci_read_bridge_bases()).
+        * We assume other PCI-EISA bridges are similar.
+        *
+        * eisa_root_register() can only deal with a single io port resource,
+       *  so we use the first valid io port resource.
+        */
+       pci_bus_for_each_resource(pdev->bus, res, i)
+               if (res && (res->flags & IORESOURCE_IO)) {
+                       bus_res = res;
+                       break;
+               }
+
+       if (!bus_res) {
+               dev_err(&pdev->dev, "No resources available\n");
+               return -1;
+       }
+
        pci_eisa_root.dev              = &pdev->dev;
-       pci_eisa_root.res              = pdev->bus->resource[0];
-       pci_eisa_root.bus_base_addr    = pdev->bus->resource[0]->start;
+       pci_eisa_root.res              = bus_res;
+       pci_eisa_root.bus_base_addr    = bus_res->start;
        pci_eisa_root.slots            = EISA_MAX_SLOTS;
        pci_eisa_root.dma_mask         = pdev->dma_mask;
        dev_set_drvdata(pci_eisa_root.dev, &pci_eisa_root);
@@ -45,22 +66,26 @@ static int __init pci_eisa_init(struct pci_dev *pdev,
        return 0;
 }
 
-static struct pci_device_id pci_eisa_pci_tbl[] = {
-       { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-         PCI_CLASS_BRIDGE_EISA << 8, 0xffff00, 0 },
-       { 0, }
-};
+/*
+ * We have to call pci_eisa_init_early() before pnpacpi_init()/isapnp_init().
+ *   Otherwise pnp resource will get enabled early and could prevent eisa
+ *   to be initialized.
+ * Also need to make sure pci_eisa_init_early() is called after
+ * x86/pci_subsys_init().
+ * So need to use subsys_initcall_sync with it.
+ */
+static int __init pci_eisa_init_early(void)
+{
+       struct pci_dev *dev = NULL;
+       int ret;
 
-static struct pci_driver __refdata pci_eisa_driver = {
-       .name           = "pci_eisa",
-       .id_table       = pci_eisa_pci_tbl,
-       .probe          = pci_eisa_init,
-};
+       for_each_pci_dev(dev)
+               if ((dev->class >> 8) == PCI_CLASS_BRIDGE_EISA) {
+                       ret = pci_eisa_init(dev);
+                       if (ret)
+                               return ret;
+               }
 
-static int __init pci_eisa_init_module (void)
-{
-       return pci_register_driver (&pci_eisa_driver);
+       return 0;
 }
-
-device_initcall(pci_eisa_init_module);
-MODULE_DEVICE_TABLE(pci, pci_eisa_pci_tbl);
+subsys_initcall_sync(pci_eisa_init_early);
index b70e3815c45932a3b76f7f30fff98d69907a8483..8f3c947b0029ab4a864d25dcd4a5ccaf4dfce90e 100644 (file)
 #define        DEV_NAME                        "max77693-muic"
 #define        DELAY_MS_DEFAULT                20000           /* unit: millisecond */
 
+/*
+ * Default value of MAX77693 register to bring up MUIC device.
+ * If user don't set some initial value for MUIC device through platform data,
+ * extcon-max77693 driver use 'default_init_data' to bring up base operation
+ * of MAX77693 MUIC device.
+ */
+struct max77693_reg_data default_init_data[] = {
+       {
+               /* STATUS2 - [3]ChgDetRun */
+               .addr = MAX77693_MUIC_REG_STATUS2,
+               .data = STATUS2_CHGDETRUN_MASK,
+       }, {
+               /* INTMASK1 - Unmask [3]ADC1KM,[0]ADCM */
+               .addr = MAX77693_MUIC_REG_INTMASK1,
+               .data = INTMASK1_ADC1K_MASK
+                       | INTMASK1_ADC_MASK,
+       }, {
+               /* INTMASK2 - Unmask [0]ChgTypM */
+               .addr = MAX77693_MUIC_REG_INTMASK2,
+               .data = INTMASK2_CHGTYP_MASK,
+       }, {
+               /* INTMASK3 - Mask all of interrupts */
+               .addr = MAX77693_MUIC_REG_INTMASK3,
+               .data = 0x0,
+       }, {
+               /* CDETCTRL2 */
+               .addr = MAX77693_MUIC_REG_CDETCTRL2,
+               .data = CDETCTRL2_VIDRMEN_MASK
+                       | CDETCTRL2_DXOVPEN_MASK,
+       },
+};
+
 enum max77693_muic_adc_debounce_time {
        ADC_DEBOUNCE_TIME_5MS = 0,
        ADC_DEBOUNCE_TIME_10MS,
@@ -1045,8 +1077,9 @@ static int max77693_muic_probe(struct platform_device *pdev)
 {
        struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent);
        struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev);
-       struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;
        struct max77693_muic_info *info;
+       struct max77693_reg_data *init_data;
+       int num_init_data;
        int delay_jiffies;
        int ret;
        int i;
@@ -1145,15 +1178,25 @@ static int max77693_muic_probe(struct platform_device *pdev)
                goto err_irq;
        }
 
-       /* Initialize MUIC register by using platform data */
-       for (i = 0 ; i < muic_pdata->num_init_data ; i++) {
-               enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR;
+
+       /* Initialize MUIC register by using platform data or default data */
+       if (pdata->muic_data) {
+               init_data = pdata->muic_data->init_data;
+               num_init_data = pdata->muic_data->num_init_data;
+       } else {
+               init_data = default_init_data;
+               num_init_data = ARRAY_SIZE(default_init_data);
+       }
+
+       for (i = 0 ; i < num_init_data ; i++) {
+               enum max77693_irq_source irq_src
+                               = MAX77693_IRQ_GROUP_NR;
 
                max77693_write_reg(info->max77693->regmap_muic,
-                               muic_pdata->init_data[i].addr,
-                               muic_pdata->init_data[i].data);
+                               init_data[i].addr,
+                               init_data[i].data);
 
-               switch (muic_pdata->init_data[i].addr) {
+               switch (init_data[i].addr) {
                case MAX77693_MUIC_REG_INTMASK1:
                        irq_src = MUIC_INT1;
                        break;
@@ -1167,22 +1210,40 @@ static int max77693_muic_probe(struct platform_device *pdev)
 
                if (irq_src < MAX77693_IRQ_GROUP_NR)
                        info->max77693->irq_masks_cur[irq_src]
-                               = muic_pdata->init_data[i].data;
+                               = init_data[i].data;
        }
 
-       /*
-        * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
-        * h/w path of COMP2/COMN1 on CONTROL1 register.
-        */
-       if (muic_pdata->path_uart)
-               info->path_uart = muic_pdata->path_uart;
-       else
-               info->path_uart = CONTROL1_SW_UART;
+       if (pdata->muic_data) {
+               struct max77693_muic_platform_data *muic_pdata = pdata->muic_data;
 
-       if (muic_pdata->path_usb)
-               info->path_usb = muic_pdata->path_usb;
-       else
+               /*
+                * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
+                * h/w path of COMP2/COMN1 on CONTROL1 register.
+                */
+               if (muic_pdata->path_uart)
+                       info->path_uart = muic_pdata->path_uart;
+               else
+                       info->path_uart = CONTROL1_SW_UART;
+
+               if (muic_pdata->path_usb)
+                       info->path_usb = muic_pdata->path_usb;
+               else
+                       info->path_usb = CONTROL1_SW_USB;
+
+               /*
+                * Default delay time for detecting cable state
+                * after certain time.
+                */
+               if (muic_pdata->detcable_delay_ms)
+                       delay_jiffies =
+                               msecs_to_jiffies(muic_pdata->detcable_delay_ms);
+               else
+                       delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
+       } else {
                info->path_usb = CONTROL1_SW_USB;
+               info->path_uart = CONTROL1_SW_UART;
+               delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
+       }
 
        /* Set initial path for UART */
         max77693_muic_set_path(info, info->path_uart, true);
@@ -1208,10 +1269,6 @@ static int max77693_muic_probe(struct platform_device *pdev)
         * driver should notify cable state to upper layer.
         */
        INIT_DELAYED_WORK(&info->wq_detcable, max77693_muic_detect_cable_wq);
-       if (muic_pdata->detcable_delay_ms)
-               delay_jiffies = msecs_to_jiffies(muic_pdata->detcable_delay_ms);
-       else
-               delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
        schedule_delayed_work(&info->wq_detcable, delay_jiffies);
 
        return ret;
index e636d950ad6c15d11d279474d3b55d89b572e257..69641bcae325a8f73e226ee66d9f418730c2ddbd 100644 (file)
@@ -712,29 +712,45 @@ static int max8997_muic_probe(struct platform_device *pdev)
                goto err_irq;
        }
 
-       /* Initialize registers according to platform data */
        if (pdata->muic_pdata) {
-               struct max8997_muic_platform_data *mdata = info->muic_pdata;
-
-               for (i = 0; i < mdata->num_init_data; i++) {
-                       max8997_write_reg(info->muic, mdata->init_data[i].addr,
-                                       mdata->init_data[i].data);
+               struct max8997_muic_platform_data *muic_pdata
+                       = pdata->muic_pdata;
+
+               /* Initialize registers according to platform data */
+               for (i = 0; i < muic_pdata->num_init_data; i++) {
+                       max8997_write_reg(info->muic,
+                                       muic_pdata->init_data[i].addr,
+                                       muic_pdata->init_data[i].data);
                }
-       }
 
-       /*
-        * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
-        * h/w path of COMP2/COMN1 on CONTROL1 register.
-        */
-       if (pdata->muic_pdata->path_uart)
-               info->path_uart = pdata->muic_pdata->path_uart;
-       else
-               info->path_uart = CONTROL1_SW_UART;
+               /*
+                * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
+                * h/w path of COMP2/COMN1 on CONTROL1 register.
+                */
+               if (muic_pdata->path_uart)
+                       info->path_uart = muic_pdata->path_uart;
+               else
+                       info->path_uart = CONTROL1_SW_UART;
 
-       if (pdata->muic_pdata->path_usb)
-               info->path_usb = pdata->muic_pdata->path_usb;
-       else
+               if (muic_pdata->path_usb)
+                       info->path_usb = muic_pdata->path_usb;
+               else
+                       info->path_usb = CONTROL1_SW_USB;
+
+               /*
+                * Default delay time for detecting cable state
+                * after certain time.
+                */
+               if (muic_pdata->detcable_delay_ms)
+                       delay_jiffies =
+                               msecs_to_jiffies(muic_pdata->detcable_delay_ms);
+               else
+                       delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
+       } else {
+               info->path_uart = CONTROL1_SW_UART;
                info->path_usb = CONTROL1_SW_USB;
+               delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
+       }
 
        /* Set initial path for UART */
         max8997_muic_set_path(info, info->path_uart, true);
@@ -751,10 +767,6 @@ static int max8997_muic_probe(struct platform_device *pdev)
         * driver should notify cable state to upper layer.
         */
        INIT_DELAYED_WORK(&info->wq_detcable, max8997_muic_detect_cable_wq);
-       if (pdata->muic_pdata->detcable_delay_ms)
-               delay_jiffies = msecs_to_jiffies(pdata->muic_pdata->detcable_delay_ms);
-       else
-               delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
        schedule_delayed_work(&info->wq_detcable, delay_jiffies);
 
        return 0;
index 9b00072a020fb5141060c5ee89cfe31edbd651be..42c759a4d047f6754ddf8676a390d8d0dcdffafb 100644 (file)
@@ -53,6 +53,24 @@ config EFI_VARS
          Subsequent efibootmgr releases may be found at:
          <http://linux.dell.com/efibootmgr>
 
+config EFI_VARS_PSTORE
+       bool "Register efivars backend for pstore"
+       depends on EFI_VARS && PSTORE
+       default y
+       help
+         Say Y here to enable use efivars as a backend to pstore. This
+         will allow writing console messages, crash dumps, or anything
+         else supported by pstore to EFI variables.
+
+config EFI_VARS_PSTORE_DEFAULT_DISABLE
+       bool "Disable using efivars as a pstore backend by default"
+       depends on EFI_VARS_PSTORE
+       default n
+       help
+         Saying Y here will disable the use of efivars as a storage
+         backend for pstore by default. This setting can be overridden
+         using the efivars module's pstore_disable parameter.
+
 config EFI_PCDP
        bool "Console device selection via EFI PCDP or HCDP table"
        depends on ACPI && EFI && IA64
index fe62aa3922398ebc52e7f61b586a71814a4b9dfe..7acafb80fd4c79b19b1c53551bb5e7e8612af707 100644 (file)
@@ -103,6 +103,11 @@ MODULE_VERSION(EFIVARS_VERSION);
  */
 #define GUID_LEN 36
 
+static bool efivars_pstore_disable =
+       IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE);
+
+module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644);
+
 /*
  * The maximum size of VariableName + Data = 1024
  * Therefore, it's reasonable to save that much
@@ -165,6 +170,7 @@ efivar_create_sysfs_entry(struct efivars *efivars,
 
 static void efivar_update_sysfs_entries(struct work_struct *);
 static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries);
+static bool efivar_wq_enabled = true;
 
 /* Return the number of unicode characters in data */
 static unsigned long
@@ -1309,9 +1315,7 @@ static const struct inode_operations efivarfs_dir_inode_operations = {
        .create = efivarfs_create,
 };
 
-static struct pstore_info efi_pstore_info;
-
-#ifdef CONFIG_PSTORE
+#ifdef CONFIG_EFI_VARS_PSTORE
 
 static int efi_pstore_open(struct pstore_info *psi)
 {
@@ -1441,7 +1445,7 @@ static int efi_pstore_write(enum pstore_type_id type,
 
        spin_unlock_irqrestore(&efivars->lock, flags);
 
-       if (reason == KMSG_DUMP_OOPS)
+       if (reason == KMSG_DUMP_OOPS && efivar_wq_enabled)
                schedule_work(&efivar_work);
 
        *id = part;
@@ -1514,38 +1518,6 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
 
        return 0;
 }
-#else
-static int efi_pstore_open(struct pstore_info *psi)
-{
-       return 0;
-}
-
-static int efi_pstore_close(struct pstore_info *psi)
-{
-       return 0;
-}
-
-static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, int *count,
-                              struct timespec *timespec,
-                              char **buf, struct pstore_info *psi)
-{
-       return -1;
-}
-
-static int efi_pstore_write(enum pstore_type_id type,
-               enum kmsg_dump_reason reason, u64 *id,
-               unsigned int part, int count, size_t size,
-               struct pstore_info *psi)
-{
-       return 0;
-}
-
-static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count,
-                           struct timespec time, struct pstore_info *psi)
-{
-       return 0;
-}
-#endif
 
 static struct pstore_info efi_pstore_info = {
        .owner          = THIS_MODULE,
@@ -1557,6 +1529,24 @@ static struct pstore_info efi_pstore_info = {
        .erase          = efi_pstore_erase,
 };
 
+static void efivar_pstore_register(struct efivars *efivars)
+{
+       efivars->efi_pstore_info = efi_pstore_info;
+       efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL);
+       if (efivars->efi_pstore_info.buf) {
+               efivars->efi_pstore_info.bufsize = 1024;
+               efivars->efi_pstore_info.data = efivars;
+               spin_lock_init(&efivars->efi_pstore_info.buf_lock);
+               pstore_register(&efivars->efi_pstore_info);
+       }
+}
+#else
+static void efivar_pstore_register(struct efivars *efivars)
+{
+       return;
+}
+#endif
+
 static ssize_t efivar_create(struct file *filp, struct kobject *kobj,
                             struct bin_attribute *bin_attr,
                             char *buf, loff_t pos, size_t count)
@@ -1716,6 +1706,31 @@ static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor)
        return found;
 }
 
+/*
+ * Returns the size of variable_name, in bytes, including the
+ * terminating NULL character, or variable_name_size if no NULL
+ * character is found among the first variable_name_size bytes.
+ */
+static unsigned long var_name_strnsize(efi_char16_t *variable_name,
+                                      unsigned long variable_name_size)
+{
+       unsigned long len;
+       efi_char16_t c;
+
+       /*
+        * The variable name is, by definition, a NULL-terminated
+        * string, so make absolutely sure that variable_name_size is
+        * the value we expect it to be. If not, return the real size.
+        */
+       for (len = 2; len <= variable_name_size; len += sizeof(c)) {
+               c = variable_name[(len / sizeof(c)) - 1];
+               if (!c)
+                       break;
+       }
+
+       return min(len, variable_name_size);
+}
+
 static void efivar_update_sysfs_entries(struct work_struct *work)
 {
        struct efivars *efivars = &__efivars;
@@ -1756,10 +1771,13 @@ static void efivar_update_sysfs_entries(struct work_struct *work)
                if (!found) {
                        kfree(variable_name);
                        break;
-               } else
+               } else {
+                       variable_name_size = var_name_strnsize(variable_name,
+                                                              variable_name_size);
                        efivar_create_sysfs_entry(efivars,
                                                  variable_name_size,
                                                  variable_name, &vendor);
+               }
        }
 }
 
@@ -1958,6 +1976,35 @@ void unregister_efivars(struct efivars *efivars)
 }
 EXPORT_SYMBOL_GPL(unregister_efivars);
 
+/*
+ * Print a warning when duplicate EFI variables are encountered and
+ * disable the sysfs workqueue since the firmware is buggy.
+ */
+static void dup_variable_bug(efi_char16_t *s16, efi_guid_t *vendor_guid,
+                            unsigned long len16)
+{
+       size_t i, len8 = len16 / sizeof(efi_char16_t);
+       char *s8;
+
+       /*
+        * Disable the workqueue since the algorithm it uses for
+        * detecting new variables won't work with this buggy
+        * implementation of GetNextVariableName().
+        */
+       efivar_wq_enabled = false;
+
+       s8 = kzalloc(len8, GFP_KERNEL);
+       if (!s8)
+               return;
+
+       for (i = 0; i < len8; i++)
+               s8[i] = s16[i];
+
+       printk(KERN_WARNING "efivars: duplicate variable: %s-%pUl\n",
+              s8, vendor_guid);
+       kfree(s8);
+}
+
 int register_efivars(struct efivars *efivars,
                     const struct efivar_operations *ops,
                     struct kobject *parent_kobj)
@@ -2006,6 +2053,24 @@ int register_efivars(struct efivars *efivars,
                                                &vendor_guid);
                switch (status) {
                case EFI_SUCCESS:
+                       variable_name_size = var_name_strnsize(variable_name,
+                                                              variable_name_size);
+
+                       /*
+                        * Some firmware implementations return the
+                        * same variable name on multiple calls to
+                        * get_next_variable(). Terminate the loop
+                        * immediately as there is no guarantee that
+                        * we'll ever see a different variable name,
+                        * and may end up looping here forever.
+                        */
+                       if (variable_is_present(variable_name, &vendor_guid)) {
+                               dup_variable_bug(variable_name, &vendor_guid,
+                                                variable_name_size);
+                               status = EFI_NOT_FOUND;
+                               break;
+                       }
+
                        efivar_create_sysfs_entry(efivars,
                                                  variable_name_size,
                                                  variable_name,
@@ -2025,15 +2090,8 @@ int register_efivars(struct efivars *efivars,
        if (error)
                unregister_efivars(efivars);
 
-       efivars->efi_pstore_info = efi_pstore_info;
-
-       efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL);
-       if (efivars->efi_pstore_info.buf) {
-               efivars->efi_pstore_info.bufsize = 1024;
-               efivars->efi_pstore_info.data = efivars;
-               spin_lock_init(&efivars->efi_pstore_info.buf_lock);
-               pstore_register(&efivars->efi_pstore_info);
-       }
+       if (!efivars_pstore_disable)
+               efivar_pstore_register(efivars);
 
        register_filesystem(&efivarfs_type);
 
index 93aaadf99f28c34c23be40a8e2a4f5148c450641..b166e30b3bc4c3a599167847452f87219433fac5 100644 (file)
@@ -227,12 +227,6 @@ config GPIO_TS5500
          blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600
          LCD port.
 
-config GPIO_VT8500
-       bool "VIA/Wondermedia SoC GPIO Support"
-       depends on ARCH_VT8500
-       help
-         Say yes here to support the VT8500/WM8505/WM8650 GPIO controller.
-
 config GPIO_XILINX
        bool "Xilinx GPIO support"
        depends on PPC_OF || MICROBLAZE
index 22e07bc9fcb58d3ea3f5d60ab12e54fb1d15af74..7b6f8105d35282b7d995c860e056e85ef4126c33 100644 (file)
@@ -57,7 +57,7 @@ obj-$(CONFIG_GPIO_PL061)      += gpio-pl061.o
 obj-$(CONFIG_GPIO_PXA)         += gpio-pxa.o
 obj-$(CONFIG_GPIO_RC5T583)     += gpio-rc5t583.o
 obj-$(CONFIG_GPIO_RDC321X)     += gpio-rdc321x.o
-obj-$(CONFIG_PLAT_SAMSUNG)     += gpio-samsung.o
+obj-$(CONFIG_PLAT_SAMSUNG_SINGLE)      += gpio-samsung.o
 obj-$(CONFIG_ARCH_SA1100)      += gpio-sa1100.o
 obj-$(CONFIG_GPIO_SCH)         += gpio-sch.o
 obj-$(CONFIG_GPIO_SODAVILLE)   += gpio-sodaville.o
@@ -80,7 +80,6 @@ obj-$(CONFIG_GPIO_TWL6040)    += gpio-twl6040.o
 obj-$(CONFIG_GPIO_UCB1400)     += gpio-ucb1400.o
 obj-$(CONFIG_GPIO_VIPERBOARD)  += gpio-viperboard.o
 obj-$(CONFIG_GPIO_VR41XX)      += gpio-vr41xx.o
-obj-$(CONFIG_GPIO_VT8500)      += gpio-vt8500.o
 obj-$(CONFIG_GPIO_VX855)       += gpio-vx855.o
 obj-$(CONFIG_GPIO_WM831X)      += gpio-wm831x.o
 obj-$(CONFIG_GPIO_WM8350)      += gpio-wm8350.o
index f9dbd503fc40fb0f1bccd0fa8f0995816a06b538..de3c317bd3e2d46f788c09d4af95a68dbbc97c69 100644 (file)
@@ -214,7 +214,7 @@ static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr)
         * If it can't be trusted, assume that the pin can be used as a GPIO.
         */
        if (ichx_priv.desc->use_sel_ignore[nr / 32] & (1 << (nr & 0x1f)))
-               return 1;
+               return 0;
 
        return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV;
 }
index 7472182967ce15b44d964d184038fbca247724e8..61a6fde6c089b28a76f3ca5012309c101ebcf2b2 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/io.h>
 #include <linux/of_irq.h>
 #include <linux/of_device.h>
+#include <linux/clk.h>
 #include <linux/pinctrl/consumer.h>
 
 /*
@@ -496,6 +497,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
        struct resource *res;
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
+       struct clk *clk;
        unsigned int ngpios;
        int soc_variant;
        int i, cpu, id;
@@ -529,6 +531,11 @@ static int mvebu_gpio_probe(struct platform_device *pdev)
                return id;
        }
 
+       clk = devm_clk_get(&pdev->dev, NULL);
+       /* Not all SoCs require a clock.*/
+       if (!IS_ERR(clk))
+               clk_prepare_enable(clk);
+
        mvchip->soc_variant = soc_variant;
        mvchip->chip.label = dev_name(&pdev->dev);
        mvchip->chip.dev = &pdev->dev;
index b3643ff007e4772285731443e15c485b54ccbbda..99e0fa49fcbd85283bef3e29f1ff90606ba54c8b 100644 (file)
@@ -1122,8 +1122,12 @@ int samsung_gpiolib_to_irq(struct gpio_chip *chip, unsigned int offset)
 #ifdef CONFIG_PLAT_S3C24XX
 static int s3c24xx_gpiolib_fbank_to_irq(struct gpio_chip *chip, unsigned offset)
 {
-       if (offset < 4)
-               return IRQ_EINT0 + offset;
+       if (offset < 4) {
+               if (soc_is_s3c2412())
+                       return IRQ_EINT0_2412 + offset;
+               else
+                       return IRQ_EINT0 + offset;
+       }
 
        if (offset < 8)
                return IRQ_EINT4 + offset - 4;
@@ -3024,6 +3028,7 @@ static __init int samsung_gpiolib_init(void)
        static const struct of_device_id exynos_pinctrl_ids[] = {
                { .compatible = "samsung,exynos4210-pinctrl", },
                { .compatible = "samsung,exynos4x12-pinctrl", },
+               { .compatible = "samsung,exynos5250-pinctrl", },
                { .compatible = "samsung,exynos5440-pinctrl", },
        };
        for_each_matching_node(pctrl_np, exynos_pinctrl_ids)
index 770476a9da87fbc4ca3a0a64008768602db8f14d..3ce5bc38ac3180b015548271eeeb0b6a3c6c5543 100644 (file)
@@ -307,11 +307,15 @@ static const struct irq_domain_ops stmpe_gpio_irq_simple_ops = {
        .xlate = irq_domain_xlate_twocell,
 };
 
-static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio)
+static int stmpe_gpio_irq_init(struct stmpe_gpio *stmpe_gpio,
+               struct device_node *np)
 {
-       int base = stmpe_gpio->irq_base;
+       int base = 0;
 
-       stmpe_gpio->domain = irq_domain_add_simple(NULL,
+       if (!np)
+               base = stmpe_gpio->irq_base;
+
+       stmpe_gpio->domain = irq_domain_add_simple(np,
                                stmpe_gpio->chip.ngpio, base,
                                &stmpe_gpio_irq_simple_ops, stmpe_gpio);
        if (!stmpe_gpio->domain) {
@@ -346,6 +350,9 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
        stmpe_gpio->chip = template_chip;
        stmpe_gpio->chip.ngpio = stmpe->num_gpios;
        stmpe_gpio->chip.dev = &pdev->dev;
+#ifdef CONFIG_OF
+       stmpe_gpio->chip.of_node = np;
+#endif
        stmpe_gpio->chip.base = pdata ? pdata->gpio_base : -1;
 
        if (pdata)
@@ -366,7 +373,7 @@ static int stmpe_gpio_probe(struct platform_device *pdev)
                goto out_free;
 
        if (irq >= 0) {
-               ret = stmpe_gpio_irq_init(stmpe_gpio);
+               ret = stmpe_gpio_irq_init(stmpe_gpio, np);
                if (ret)
                        goto out_disable;
 
index 414ad912232f9ecc1558c42e865d289920375dfc..e3956359202c23080e5f751bf5484ba9792a3eb0 100644 (file)
@@ -72,6 +72,7 @@ struct tegra_gpio_bank {
        u32 oe[4];
        u32 int_enb[4];
        u32 int_lvl[4];
+       u32 wake_enb[4];
 #endif
 };
 
@@ -333,15 +334,31 @@ static int tegra_gpio_suspend(struct device *dev)
                        bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio));
                        bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio));
                        bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio));
+
+                       /* Enable gpio irq for wake up source */
+                       tegra_gpio_writel(bank->wake_enb[p],
+                                         GPIO_INT_ENB(gpio));
                }
        }
        local_irq_restore(flags);
        return 0;
 }
 
-static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
+static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable)
 {
        struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       int gpio = d->hwirq;
+       u32 port, bit, mask;
+
+       port = GPIO_PORT(gpio);
+       bit = GPIO_BIT(gpio);
+       mask = BIT(bit);
+
+       if (enable)
+               bank->wake_enb[port] |= mask;
+       else
+               bank->wake_enb[port] &= ~mask;
+
        return irq_set_irq_wake(bank->irq, enable);
 }
 #endif
@@ -353,7 +370,7 @@ static struct irq_chip tegra_gpio_irq_chip = {
        .irq_unmask     = tegra_gpio_irq_unmask,
        .irq_set_type   = tegra_gpio_irq_set_type,
 #ifdef CONFIG_PM_SLEEP
-       .irq_set_wake   = tegra_gpio_wake_enable,
+       .irq_set_wake   = tegra_gpio_irq_set_wake,
 #endif
 };
 
diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c
deleted file mode 100644 (file)
index 81683ca..0000000
+++ /dev/null
@@ -1,355 +0,0 @@
-/* drivers/gpio/gpio-vt8500.c
- *
- * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
- * Based on arch/arm/mach-vt8500/gpio.c:
- * - Copyright (C) 2010 Alexey Charkov <alchark@gmail.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.
- *
- */
-
-#include <linux/module.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/bitops.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-#include <linux/of_device.h>
-
-/*
-       We handle GPIOs by bank, each bank containing up to 32 GPIOs covered
-       by one set of registers (although not all may be valid).
-
-       Because different SoC's have different register offsets, we pass the
-       register offsets as data in vt8500_gpio_dt_ids[].
-
-       A value of NO_REG is used to indicate that this register is not
-       supported. Only used for ->en at the moment.
-*/
-
-#define NO_REG 0xFFFF
-
-/*
- * struct vt8500_gpio_bank_regoffsets
- * @en: offset to enable register of the bank
- * @dir: offset to direction register of the bank
- * @data_out: offset to the data out register of the bank
- * @data_in: offset to the data in register of the bank
- * @ngpio: highest valid pin in this bank
- */
-
-struct vt8500_gpio_bank_regoffsets {
-       unsigned int    en;
-       unsigned int    dir;
-       unsigned int    data_out;
-       unsigned int    data_in;
-       unsigned char   ngpio;
-};
-
-struct vt8500_gpio_data {
-       unsigned int                            num_banks;
-       struct vt8500_gpio_bank_regoffsets      banks[];
-};
-
-#define VT8500_BANK(__en, __dir, __out, __in, __ngpio)         \
-{                                                              \
-       .en = __en,                                             \
-       .dir = __dir,                                           \
-       .data_out = __out,                                      \
-       .data_in = __in,                                        \
-       .ngpio = __ngpio,                                       \
-}
-
-static struct vt8500_gpio_data vt8500_data = {
-       .num_banks      = 7,
-       .banks  = {
-               VT8500_BANK(NO_REG, 0x3C, 0x5C, 0x7C, 9),
-               VT8500_BANK(0x00, 0x20, 0x40, 0x60, 26),
-               VT8500_BANK(0x04, 0x24, 0x44, 0x64, 28),
-               VT8500_BANK(0x08, 0x28, 0x48, 0x68, 31),
-               VT8500_BANK(0x0C, 0x2C, 0x4C, 0x6C, 19),
-               VT8500_BANK(0x10, 0x30, 0x50, 0x70, 19),
-               VT8500_BANK(0x14, 0x34, 0x54, 0x74, 23),
-       },
-};
-
-static struct vt8500_gpio_data wm8505_data = {
-       .num_banks      = 10,
-       .banks  = {
-               VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22),
-               VT8500_BANK(0x40, 0x68, 0x90, 0xB8, 8),
-               VT8500_BANK(0x44, 0x6C, 0x94, 0xBC, 32),
-               VT8500_BANK(0x48, 0x70, 0x98, 0xC0, 6),
-               VT8500_BANK(0x4C, 0x74, 0x9C, 0xC4, 16),
-               VT8500_BANK(0x50, 0x78, 0xA0, 0xC8, 25),
-               VT8500_BANK(0x54, 0x7C, 0xA4, 0xCC, 5),
-               VT8500_BANK(0x58, 0x80, 0xA8, 0xD0, 5),
-               VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12),
-               VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16),
-               VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
-       },
-};
-
-/*
- * No information about which bits are valid so we just make
- * them all available until its figured out.
- */
-static struct vt8500_gpio_data wm8650_data = {
-       .num_banks      = 9,
-       .banks  = {
-               VT8500_BANK(0x40, 0x80, 0xC0, 0x00, 32),
-               VT8500_BANK(0x44, 0x84, 0xC4, 0x04, 32),
-               VT8500_BANK(0x48, 0x88, 0xC8, 0x08, 32),
-               VT8500_BANK(0x4C, 0x8C, 0xCC, 0x0C, 32),
-               VT8500_BANK(0x50, 0x90, 0xD0, 0x10, 32),
-               VT8500_BANK(0x54, 0x94, 0xD4, 0x14, 32),
-               VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32),
-               VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32),
-               VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32),
-               VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6),
-       },
-};
-
-struct vt8500_gpio_chip {
-       struct gpio_chip                chip;
-
-       const struct vt8500_gpio_bank_regoffsets *regs;
-       void __iomem    *base;
-};
-
-struct vt8500_data {
-       struct vt8500_gpio_chip *chip;
-       void __iomem *iobase;
-       int num_banks;
-};
-
-
-#define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
-
-static int vt8500_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-       u32 val;
-       struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
-
-       if (vt8500_chip->regs->en == NO_REG)
-               return 0;
-
-       val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->en);
-       val |= BIT(offset);
-       writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->en);
-
-       return 0;
-}
-
-static void vt8500_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-       struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
-       u32 val;
-
-       if (vt8500_chip->regs->en == NO_REG)
-               return;
-
-       val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->en);
-       val &= ~BIT(offset);
-       writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->en);
-}
-
-static int vt8500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
-
-       u32 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->dir);
-       val &= ~BIT(offset);
-       writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->dir);
-
-       return 0;
-}
-
-static int vt8500_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
-                                                               int value)
-{
-       struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
-
-       u32 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->dir);
-       val |= BIT(offset);
-       writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->dir);
-
-       if (value) {
-               val = readl_relaxed(vt8500_chip->base +
-                                               vt8500_chip->regs->data_out);
-               val |= BIT(offset);
-               writel_relaxed(val, vt8500_chip->base +
-                                               vt8500_chip->regs->data_out);
-       }
-       return 0;
-}
-
-static int vt8500_gpio_get_value(struct gpio_chip *chip, unsigned offset)
-{
-       struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
-
-       return (readl_relaxed(vt8500_chip->base + vt8500_chip->regs->data_in) >>
-                                                               offset) & 1;
-}
-
-static void vt8500_gpio_set_value(struct gpio_chip *chip, unsigned offset,
-                                                               int value)
-{
-       struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
-
-       u32 val = readl_relaxed(vt8500_chip->base +
-                                               vt8500_chip->regs->data_out);
-       if (value)
-               val |= BIT(offset);
-       else
-               val &= ~BIT(offset);
-
-       writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->data_out);
-}
-
-static int vt8500_of_xlate(struct gpio_chip *gc,
-                           const struct of_phandle_args *gpiospec, u32 *flags)
-{
-       /* bank if specificed in gpiospec->args[0] */
-       if (flags)
-               *flags = gpiospec->args[2];
-
-       return gpiospec->args[1];
-}
-
-static int vt8500_add_chips(struct platform_device *pdev, void __iomem *base,
-                               const struct vt8500_gpio_data *data)
-{
-       struct vt8500_data *priv;
-       struct vt8500_gpio_chip *vtchip;
-       struct gpio_chip *chip;
-       int i;
-       int pin_cnt = 0;
-
-       priv = devm_kzalloc(&pdev->dev, sizeof(struct vt8500_data), GFP_KERNEL);
-       if (!priv) {
-               dev_err(&pdev->dev, "failed to allocate memory\n");
-               return -ENOMEM;
-       }
-
-       priv->chip = devm_kzalloc(&pdev->dev,
-                       sizeof(struct vt8500_gpio_chip) * data->num_banks,
-                       GFP_KERNEL);
-       if (!priv->chip) {
-               dev_err(&pdev->dev, "failed to allocate chip memory\n");
-               return -ENOMEM;
-       }
-
-       priv->iobase = base;
-       priv->num_banks = data->num_banks;
-       platform_set_drvdata(pdev, priv);
-
-       vtchip = priv->chip;
-
-       for (i = 0; i < data->num_banks; i++) {
-               vtchip[i].base = base;
-               vtchip[i].regs = &data->banks[i];
-
-               chip = &vtchip[i].chip;
-
-               chip->of_xlate = vt8500_of_xlate;
-               chip->of_gpio_n_cells = 3;
-               chip->of_node = pdev->dev.of_node;
-
-               chip->request = vt8500_gpio_request;
-               chip->free = vt8500_gpio_free;
-               chip->direction_input = vt8500_gpio_direction_input;
-               chip->direction_output = vt8500_gpio_direction_output;
-               chip->get = vt8500_gpio_get_value;
-               chip->set = vt8500_gpio_set_value;
-               chip->can_sleep = 0;
-               chip->base = pin_cnt;
-               chip->ngpio = data->banks[i].ngpio;
-
-               pin_cnt += data->banks[i].ngpio;
-
-               gpiochip_add(chip);
-       }
-       return 0;
-}
-
-static struct of_device_id vt8500_gpio_dt_ids[] = {
-       { .compatible = "via,vt8500-gpio", .data = &vt8500_data, },
-       { .compatible = "wm,wm8505-gpio", .data = &wm8505_data, },
-       { .compatible = "wm,wm8650-gpio", .data = &wm8650_data, },
-       { /* Sentinel */ },
-};
-
-static int vt8500_gpio_probe(struct platform_device *pdev)
-{
-       int ret;
-       void __iomem *gpio_base;
-       struct resource *res;
-       const struct of_device_id *of_id =
-                               of_match_device(vt8500_gpio_dt_ids, &pdev->dev);
-
-       if (!of_id) {
-               dev_err(&pdev->dev, "No matching driver data\n");
-               return -ENODEV;
-       }
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(&pdev->dev, "Unable to get IO resource\n");
-               return -ENODEV;
-       }
-
-       gpio_base = devm_request_and_ioremap(&pdev->dev, res);
-       if (!gpio_base) {
-               dev_err(&pdev->dev, "Unable to map GPIO registers\n");
-               return -ENOMEM;
-       }
-
-       ret = vt8500_add_chips(pdev, gpio_base, of_id->data);
-
-       return ret;
-}
-
-static int vt8500_gpio_remove(struct platform_device *pdev)
-{
-       int i;
-       int ret;
-       struct vt8500_data *priv = platform_get_drvdata(pdev);
-       struct vt8500_gpio_chip *vtchip = priv->chip;
-
-       for (i = 0; i < priv->num_banks; i++) {
-               ret = gpiochip_remove(&vtchip[i].chip);
-               if (ret)
-                       dev_warn(&pdev->dev, "gpiochip_remove returned %d\n",
-                                ret);
-       }
-
-       return 0;
-}
-
-static struct platform_driver vt8500_gpio_driver = {
-       .probe          = vt8500_gpio_probe,
-       .remove         = vt8500_gpio_remove,
-       .driver         = {
-               .name   = "vt8500-gpio",
-               .owner  = THIS_MODULE,
-               .of_match_table = vt8500_gpio_dt_ids,
-       },
-};
-
-module_platform_driver(vt8500_gpio_driver);
-
-MODULE_DESCRIPTION("VT8500 GPIO Driver");
-MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
-MODULE_LICENSE("GPL v2");
-MODULE_DEVICE_TABLE(of, vt8500_gpio_dt_ids);
index a71a54a3e3f783a4151ed5919c01290ade8ffd5d..5150df6cba0815623c9fc7c86e96ff2ad099f0ed 100644 (file)
@@ -193,7 +193,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
        if (!np)
                return;
 
-       do {
+       for (;; index++) {
                ret = of_parse_phandle_with_args(np, "gpio-ranges",
                                "#gpio-range-cells", index, &pinspec);
                if (ret)
@@ -222,8 +222,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip)
 
                if (ret)
                        break;
-
-       } while (index++);
+       }
 }
 
 #else
index 792c3e3795cae819caedaf12121052b47ad34a89..dd64a06dc5b4b4415a17286a53aad3d1453f8e36 100644 (file)
@@ -2326,7 +2326,6 @@ int drm_mode_addfb(struct drm_device *dev,
        fb = dev->mode_config.funcs->fb_create(dev, file_priv, &r);
        if (IS_ERR(fb)) {
                DRM_DEBUG_KMS("could not create framebuffer\n");
-               drm_modeset_unlock_all(dev);
                return PTR_ERR(fb);
        }
 
@@ -2506,7 +2505,6 @@ int drm_mode_addfb2(struct drm_device *dev,
        fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
        if (IS_ERR(fb)) {
                DRM_DEBUG_KMS("could not create framebuffer\n");
-               drm_modeset_unlock_all(dev);
                return PTR_ERR(fb);
        }
 
index c194f4e680ad17cf7d2b665a277b10ad2f2edc6a..e2acfdbf7d3cc7f60104ba5b6c3fce3142e538b8 100644 (file)
@@ -1634,7 +1634,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
        unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo;
        unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo;
        unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo;
-       unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4;
+       unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 2 | pt->vsync_offset_pulse_width_lo >> 4;
        unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf);
 
        /* ignore tiny modes */
@@ -1715,6 +1715,7 @@ set_size:
        }
 
        mode->type = DRM_MODE_TYPE_DRIVER;
+       mode->vrefresh = drm_mode_vrefresh(mode);
        drm_mode_set_name(mode);
 
        return mode;
index 13fdcd10a6051ddd9359af281390748528a6885e..429e07d0b0f147f2c9f672d65a18849f0c57f0f4 100644 (file)
@@ -123,6 +123,7 @@ int drm_open(struct inode *inode, struct file *filp)
        int retcode = 0;
        int need_setup = 0;
        struct address_space *old_mapping;
+       struct address_space *old_imapping;
 
        minor = idr_find(&drm_minors_idr, minor_id);
        if (!minor)
@@ -137,6 +138,7 @@ int drm_open(struct inode *inode, struct file *filp)
        if (!dev->open_count++)
                need_setup = 1;
        mutex_lock(&dev->struct_mutex);
+       old_imapping = inode->i_mapping;
        old_mapping = dev->dev_mapping;
        if (old_mapping == NULL)
                dev->dev_mapping = &inode->i_data;
@@ -159,8 +161,8 @@ int drm_open(struct inode *inode, struct file *filp)
 
 err_undo:
        mutex_lock(&dev->struct_mutex);
-       filp->f_mapping = old_mapping;
-       inode->i_mapping = old_mapping;
+       filp->f_mapping = old_imapping;
+       inode->i_mapping = old_imapping;
        iput(container_of(dev->dev_mapping, struct inode, i_data));
        dev->dev_mapping = old_mapping;
        mutex_unlock(&dev->struct_mutex);
index 36493ce71f9a8c217ebe8af960598b299f1a95bb..98cc14725ba94c4d1dcd0d44242bb26d92eb75fa 100644 (file)
 /* position control register for hardware window 0, 2 ~ 4.*/
 #define VIDOSD_A(win)          (VIDOSD_BASE + 0x00 + (win) * 16)
 #define VIDOSD_B(win)          (VIDOSD_BASE + 0x04 + (win) * 16)
-/* size control register for hardware window 0. */
-#define VIDOSD_C_SIZE_W0       (VIDOSD_BASE + 0x08)
-/* alpha control register for hardware window 1 ~ 4. */
-#define VIDOSD_C(win)          (VIDOSD_BASE + 0x18 + (win) * 16)
-/* size control register for hardware window 1 ~ 4. */
+/*
+ * size control register for hardware windows 0 and alpha control register
+ * for hardware windows 1 ~ 4
+ */
+#define VIDOSD_C(win)          (VIDOSD_BASE + 0x08 + (win) * 16)
+/* size control register for hardware windows 1 ~ 2. */
 #define VIDOSD_D(win)          (VIDOSD_BASE + 0x0C + (win) * 16)
 
 #define VIDWx_BUF_START(win, buf)      (VIDW_BUF_START(buf) + (win) * 8)
@@ -50,9 +51,9 @@
 #define VIDWx_BUF_SIZE(win, buf)       (VIDW_BUF_SIZE(buf) + (win) * 4)
 
 /* color key control register for hardware window 1 ~ 4. */
-#define WKEYCON0_BASE(x)               ((WKEYCON0 + 0x140) + (x * 8))
+#define WKEYCON0_BASE(x)               ((WKEYCON0 + 0x140) + ((x - 1) * 8))
 /* color key value register for hardware window 1 ~ 4. */
-#define WKEYCON1_BASE(x)               ((WKEYCON1 + 0x140) + (x * 8))
+#define WKEYCON1_BASE(x)               ((WKEYCON1 + 0x140) + ((x - 1) * 8))
 
 /* FIMD has totally five hardware windows. */
 #define WINDOWS_NR     5
@@ -109,9 +110,9 @@ struct fimd_context {
 
 #ifdef CONFIG_OF
 static const struct of_device_id fimd_driver_dt_match[] = {
-       { .compatible = "samsung,exynos4-fimd",
+       { .compatible = "samsung,exynos4210-fimd",
          .data = &exynos4_fimd_driver_data },
-       { .compatible = "samsung,exynos5-fimd",
+       { .compatible = "samsung,exynos5250-fimd",
          .data = &exynos5_fimd_driver_data },
        {},
 };
@@ -581,7 +582,7 @@ static void fimd_win_commit(struct device *dev, int zpos)
        if (win != 3 && win != 4) {
                u32 offset = VIDOSD_D(win);
                if (win == 0)
-                       offset = VIDOSD_C_SIZE_W0;
+                       offset = VIDOSD_C(win);
                val = win_data->ovl_width * win_data->ovl_height;
                writel(val, ctx->regs + offset);
 
index 3b0da0378acf509976361d85322dc1fbc5c6779f..47a493c8a71f2629b7acf0de109bcd3eefc15bfd 100644 (file)
 
 /* registers for base address */
 #define G2D_SRC_BASE_ADDR              0x0304
+#define G2D_SRC_COLOR_MODE             0x030C
+#define G2D_SRC_LEFT_TOP               0x0310
+#define G2D_SRC_RIGHT_BOTTOM           0x0314
 #define G2D_SRC_PLANE2_BASE_ADDR       0x0318
 #define G2D_DST_BASE_ADDR              0x0404
+#define G2D_DST_COLOR_MODE             0x040C
+#define G2D_DST_LEFT_TOP               0x0410
+#define G2D_DST_RIGHT_BOTTOM           0x0414
 #define G2D_DST_PLANE2_BASE_ADDR       0x0418
 #define G2D_PAT_BASE_ADDR              0x0500
 #define G2D_MSK_BASE_ADDR              0x0520
@@ -82,7 +88,7 @@
 #define G2D_DMA_LIST_DONE_COUNT_OFFSET 17
 
 /* G2D_DMA_HOLD_CMD */
-#define G2D_USET_HOLD                  (1 << 2)
+#define G2D_USER_HOLD                  (1 << 2)
 #define G2D_LIST_HOLD                  (1 << 1)
 #define G2D_BITBLT_HOLD                        (1 << 0)
 
 #define G2D_START_NHOLT                        (1 << 1)
 #define G2D_START_BITBLT               (1 << 0)
 
+/* buffer color format */
+#define G2D_FMT_XRGB8888               0
+#define G2D_FMT_ARGB8888               1
+#define G2D_FMT_RGB565                 2
+#define G2D_FMT_XRGB1555               3
+#define G2D_FMT_ARGB1555               4
+#define G2D_FMT_XRGB4444               5
+#define G2D_FMT_ARGB4444               6
+#define G2D_FMT_PACKED_RGB888          7
+#define G2D_FMT_A8                     11
+#define G2D_FMT_L8                     12
+
+/* buffer valid length */
+#define G2D_LEN_MIN                    1
+#define G2D_LEN_MAX                    8000
+
 #define G2D_CMDLIST_SIZE               (PAGE_SIZE / 4)
 #define G2D_CMDLIST_NUM                        64
 #define G2D_CMDLIST_POOL_SIZE          (G2D_CMDLIST_SIZE * G2D_CMDLIST_NUM)
 #define G2D_CMDLIST_DATA_NUM           (G2D_CMDLIST_SIZE / sizeof(u32) - 2)
 
-#define MAX_BUF_ADDR_NR                        6
-
 /* maximum buffer pool size of userptr is 64MB as default */
 #define MAX_POOL               (64 * 1024 * 1024)
 
@@ -106,6 +126,17 @@ enum {
        BUF_TYPE_USERPTR,
 };
 
+enum g2d_reg_type {
+       REG_TYPE_NONE = -1,
+       REG_TYPE_SRC,
+       REG_TYPE_SRC_PLANE2,
+       REG_TYPE_DST,
+       REG_TYPE_DST_PLANE2,
+       REG_TYPE_PAT,
+       REG_TYPE_MSK,
+       MAX_REG_TYPE_NR
+};
+
 /* cmdlist data structure */
 struct g2d_cmdlist {
        u32             head;
@@ -113,6 +144,42 @@ struct g2d_cmdlist {
        u32             last;   /* last data offset */
 };
 
+/*
+ * A structure of buffer description
+ *
+ * @format: color format
+ * @left_x: the x coordinates of left top corner
+ * @top_y: the y coordinates of left top corner
+ * @right_x: the x coordinates of right bottom corner
+ * @bottom_y: the y coordinates of right bottom corner
+ *
+ */
+struct g2d_buf_desc {
+       unsigned int    format;
+       unsigned int    left_x;
+       unsigned int    top_y;
+       unsigned int    right_x;
+       unsigned int    bottom_y;
+};
+
+/*
+ * A structure of buffer information
+ *
+ * @map_nr: manages the number of mapped buffers
+ * @reg_types: stores regitster type in the order of requested command
+ * @handles: stores buffer handle in its reg_type position
+ * @types: stores buffer type in its reg_type position
+ * @descs: stores buffer description in its reg_type position
+ *
+ */
+struct g2d_buf_info {
+       unsigned int            map_nr;
+       enum g2d_reg_type       reg_types[MAX_REG_TYPE_NR];
+       unsigned long           handles[MAX_REG_TYPE_NR];
+       unsigned int            types[MAX_REG_TYPE_NR];
+       struct g2d_buf_desc     descs[MAX_REG_TYPE_NR];
+};
+
 struct drm_exynos_pending_g2d_event {
        struct drm_pending_event        base;
        struct drm_exynos_g2d_event     event;
@@ -131,14 +198,11 @@ struct g2d_cmdlist_userptr {
        bool                    in_pool;
        bool                    out_of_list;
 };
-
 struct g2d_cmdlist_node {
        struct list_head        list;
        struct g2d_cmdlist      *cmdlist;
-       unsigned int            map_nr;
-       unsigned long           handles[MAX_BUF_ADDR_NR];
-       unsigned int            obj_type[MAX_BUF_ADDR_NR];
        dma_addr_t              dma_addr;
+       struct g2d_buf_info     buf_info;
 
        struct drm_exynos_pending_g2d_event     *event;
 };
@@ -188,6 +252,7 @@ static int g2d_init_cmdlist(struct g2d_data *g2d)
        struct exynos_drm_subdrv *subdrv = &g2d->subdrv;
        int nr;
        int ret;
+       struct g2d_buf_info *buf_info;
 
        init_dma_attrs(&g2d->cmdlist_dma_attrs);
        dma_set_attr(DMA_ATTR_WRITE_COMBINE, &g2d->cmdlist_dma_attrs);
@@ -209,11 +274,17 @@ static int g2d_init_cmdlist(struct g2d_data *g2d)
        }
 
        for (nr = 0; nr < G2D_CMDLIST_NUM; nr++) {
+               unsigned int i;
+
                node[nr].cmdlist =
                        g2d->cmdlist_pool_virt + nr * G2D_CMDLIST_SIZE;
                node[nr].dma_addr =
                        g2d->cmdlist_pool + nr * G2D_CMDLIST_SIZE;
 
+               buf_info = &node[nr].buf_info;
+               for (i = 0; i < MAX_REG_TYPE_NR; i++)
+                       buf_info->reg_types[i] = REG_TYPE_NONE;
+
                list_add_tail(&node[nr].list, &g2d->free_cmdlist);
        }
 
@@ -450,7 +521,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
                                                DMA_BIDIRECTIONAL);
        if (ret < 0) {
                DRM_ERROR("failed to map sgt with dma region.\n");
-               goto err_free_sgt;
+               goto err_sg_free_table;
        }
 
        g2d_userptr->dma_addr = sgt->sgl[0].dma_address;
@@ -467,8 +538,10 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
 
        return &g2d_userptr->dma_addr;
 
-err_free_sgt:
+err_sg_free_table:
        sg_free_table(sgt);
+
+err_free_sgt:
        kfree(sgt);
        sgt = NULL;
 
@@ -506,36 +579,172 @@ static void g2d_userptr_free_all(struct drm_device *drm_dev,
        g2d->current_pool = 0;
 }
 
+static enum g2d_reg_type g2d_get_reg_type(int reg_offset)
+{
+       enum g2d_reg_type reg_type;
+
+       switch (reg_offset) {
+       case G2D_SRC_BASE_ADDR:
+       case G2D_SRC_COLOR_MODE:
+       case G2D_SRC_LEFT_TOP:
+       case G2D_SRC_RIGHT_BOTTOM:
+               reg_type = REG_TYPE_SRC;
+               break;
+       case G2D_SRC_PLANE2_BASE_ADDR:
+               reg_type = REG_TYPE_SRC_PLANE2;
+               break;
+       case G2D_DST_BASE_ADDR:
+       case G2D_DST_COLOR_MODE:
+       case G2D_DST_LEFT_TOP:
+       case G2D_DST_RIGHT_BOTTOM:
+               reg_type = REG_TYPE_DST;
+               break;
+       case G2D_DST_PLANE2_BASE_ADDR:
+               reg_type = REG_TYPE_DST_PLANE2;
+               break;
+       case G2D_PAT_BASE_ADDR:
+               reg_type = REG_TYPE_PAT;
+               break;
+       case G2D_MSK_BASE_ADDR:
+               reg_type = REG_TYPE_MSK;
+               break;
+       default:
+               reg_type = REG_TYPE_NONE;
+               DRM_ERROR("Unknown register offset![%d]\n", reg_offset);
+               break;
+       };
+
+       return reg_type;
+}
+
+static unsigned long g2d_get_buf_bpp(unsigned int format)
+{
+       unsigned long bpp;
+
+       switch (format) {
+       case G2D_FMT_XRGB8888:
+       case G2D_FMT_ARGB8888:
+               bpp = 4;
+               break;
+       case G2D_FMT_RGB565:
+       case G2D_FMT_XRGB1555:
+       case G2D_FMT_ARGB1555:
+       case G2D_FMT_XRGB4444:
+       case G2D_FMT_ARGB4444:
+               bpp = 2;
+               break;
+       case G2D_FMT_PACKED_RGB888:
+               bpp = 3;
+               break;
+       default:
+               bpp = 1;
+               break;
+       }
+
+       return bpp;
+}
+
+static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc,
+                                               enum g2d_reg_type reg_type,
+                                               unsigned long size)
+{
+       unsigned int width, height;
+       unsigned long area;
+
+       /*
+        * check source and destination buffers only.
+        * so the others are always valid.
+        */
+       if (reg_type != REG_TYPE_SRC && reg_type != REG_TYPE_DST)
+               return true;
+
+       width = buf_desc->right_x - buf_desc->left_x;
+       if (width < G2D_LEN_MIN || width > G2D_LEN_MAX) {
+               DRM_ERROR("width[%u] is out of range!\n", width);
+               return false;
+       }
+
+       height = buf_desc->bottom_y - buf_desc->top_y;
+       if (height < G2D_LEN_MIN || height > G2D_LEN_MAX) {
+               DRM_ERROR("height[%u] is out of range!\n", height);
+               return false;
+       }
+
+       area = (unsigned long)width * (unsigned long)height *
+                                       g2d_get_buf_bpp(buf_desc->format);
+       if (area > size) {
+               DRM_ERROR("area[%lu] is out of range[%lu]!\n", area, size);
+               return false;
+       }
+
+       return true;
+}
+
 static int g2d_map_cmdlist_gem(struct g2d_data *g2d,
                                struct g2d_cmdlist_node *node,
                                struct drm_device *drm_dev,
                                struct drm_file *file)
 {
        struct g2d_cmdlist *cmdlist = node->cmdlist;
+       struct g2d_buf_info *buf_info = &node->buf_info;
        int offset;
+       int ret;
        int i;
 
-       for (i = 0; i < node->map_nr; i++) {
+       for (i = 0; i < buf_info->map_nr; i++) {
+               struct g2d_buf_desc *buf_desc;
+               enum g2d_reg_type reg_type;
+               int reg_pos;
                unsigned long handle;
                dma_addr_t *addr;
 
-               offset = cmdlist->last - (i * 2 + 1);
-               handle = cmdlist->data[offset];
+               reg_pos = cmdlist->last - 2 * (i + 1);
+
+               offset = cmdlist->data[reg_pos];
+               handle = cmdlist->data[reg_pos + 1];
+
+               reg_type = g2d_get_reg_type(offset);
+               if (reg_type == REG_TYPE_NONE) {
+                       ret = -EFAULT;
+                       goto err;
+               }
+
+               buf_desc = &buf_info->descs[reg_type];
+
+               if (buf_info->types[reg_type] == BUF_TYPE_GEM) {
+                       unsigned long size;
+
+                       size = exynos_drm_gem_get_size(drm_dev, handle, file);
+                       if (!size) {
+                               ret = -EFAULT;
+                               goto err;
+                       }
+
+                       if (!g2d_check_buf_desc_is_valid(buf_desc, reg_type,
+                                                                       size)) {
+                               ret = -EFAULT;
+                               goto err;
+                       }
 
-               if (node->obj_type[i] == BUF_TYPE_GEM) {
                        addr = exynos_drm_gem_get_dma_addr(drm_dev, handle,
                                                                file);
                        if (IS_ERR(addr)) {
-                               node->map_nr = i;
-                               return -EFAULT;
+                               ret = -EFAULT;
+                               goto err;
                        }
                } else {
                        struct drm_exynos_g2d_userptr g2d_userptr;
 
                        if (copy_from_user(&g2d_userptr, (void __user *)handle,
                                sizeof(struct drm_exynos_g2d_userptr))) {
-                               node->map_nr = i;
-                               return -EFAULT;
+                               ret = -EFAULT;
+                               goto err;
+                       }
+
+                       if (!g2d_check_buf_desc_is_valid(buf_desc, reg_type,
+                                                       g2d_userptr.size)) {
+                               ret = -EFAULT;
+                               goto err;
                        }
 
                        addr = g2d_userptr_get_dma_addr(drm_dev,
@@ -544,16 +753,21 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d,
                                                        file,
                                                        &handle);
                        if (IS_ERR(addr)) {
-                               node->map_nr = i;
-                               return -EFAULT;
+                               ret = -EFAULT;
+                               goto err;
                        }
                }
 
-               cmdlist->data[offset] = *addr;
-               node->handles[i] = handle;
+               cmdlist->data[reg_pos + 1] = *addr;
+               buf_info->reg_types[i] = reg_type;
+               buf_info->handles[reg_type] = handle;
        }
 
        return 0;
+
+err:
+       buf_info->map_nr = i;
+       return ret;
 }
 
 static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d,
@@ -561,22 +775,33 @@ static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d,
                                  struct drm_file *filp)
 {
        struct exynos_drm_subdrv *subdrv = &g2d->subdrv;
+       struct g2d_buf_info *buf_info = &node->buf_info;
        int i;
 
-       for (i = 0; i < node->map_nr; i++) {
-               unsigned long handle = node->handles[i];
+       for (i = 0; i < buf_info->map_nr; i++) {
+               struct g2d_buf_desc *buf_desc;
+               enum g2d_reg_type reg_type;
+               unsigned long handle;
+
+               reg_type = buf_info->reg_types[i];
+
+               buf_desc = &buf_info->descs[reg_type];
+               handle = buf_info->handles[reg_type];
 
-               if (node->obj_type[i] == BUF_TYPE_GEM)
+               if (buf_info->types[reg_type] == BUF_TYPE_GEM)
                        exynos_drm_gem_put_dma_addr(subdrv->drm_dev, handle,
                                                        filp);
                else
                        g2d_userptr_put_dma_addr(subdrv->drm_dev, handle,
                                                        false);
 
-               node->handles[i] = 0;
+               buf_info->reg_types[i] = REG_TYPE_NONE;
+               buf_info->handles[reg_type] = 0;
+               buf_info->types[reg_type] = 0;
+               memset(buf_desc, 0x00, sizeof(*buf_desc));
        }
 
-       node->map_nr = 0;
+       buf_info->map_nr = 0;
 }
 
 static void g2d_dma_start(struct g2d_data *g2d,
@@ -589,10 +814,6 @@ static void g2d_dma_start(struct g2d_data *g2d,
        pm_runtime_get_sync(g2d->dev);
        clk_enable(g2d->gate_clk);
 
-       /* interrupt enable */
-       writel_relaxed(G2D_INTEN_ACF | G2D_INTEN_UCF | G2D_INTEN_GCF,
-                       g2d->regs + G2D_INTEN);
-
        writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR);
        writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND);
 }
@@ -643,7 +864,6 @@ static void g2d_runqueue_worker(struct work_struct *work)
        struct g2d_data *g2d = container_of(work, struct g2d_data,
                                            runqueue_work);
 
-
        mutex_lock(&g2d->runqueue_mutex);
        clk_disable(g2d->gate_clk);
        pm_runtime_put_sync(g2d->dev);
@@ -724,20 +944,14 @@ static int g2d_check_reg_offset(struct device *dev,
        int i;
 
        for (i = 0; i < nr; i++) {
-               index = cmdlist->last - 2 * (i + 1);
+               struct g2d_buf_info *buf_info = &node->buf_info;
+               struct g2d_buf_desc *buf_desc;
+               enum g2d_reg_type reg_type;
+               unsigned long value;
 
-               if (for_addr) {
-                       /* check userptr buffer type. */
-                       reg_offset = (cmdlist->data[index] &
-                                       ~0x7fffffff) >> 31;
-                       if (reg_offset) {
-                               node->obj_type[i] = BUF_TYPE_USERPTR;
-                               cmdlist->data[index] &= ~G2D_BUF_USERPTR;
-                       }
-               }
+               index = cmdlist->last - 2 * (i + 1);
 
                reg_offset = cmdlist->data[index] & ~0xfffff000;
-
                if (reg_offset < G2D_VALID_START || reg_offset > G2D_VALID_END)
                        goto err;
                if (reg_offset % 4)
@@ -753,8 +967,60 @@ static int g2d_check_reg_offset(struct device *dev,
                        if (!for_addr)
                                goto err;
 
-                       if (node->obj_type[i] != BUF_TYPE_USERPTR)
-                               node->obj_type[i] = BUF_TYPE_GEM;
+                       reg_type = g2d_get_reg_type(reg_offset);
+                       if (reg_type == REG_TYPE_NONE)
+                               goto err;
+
+                       /* check userptr buffer type. */
+                       if ((cmdlist->data[index] & ~0x7fffffff) >> 31) {
+                               buf_info->types[reg_type] = BUF_TYPE_USERPTR;
+                               cmdlist->data[index] &= ~G2D_BUF_USERPTR;
+                       } else
+                               buf_info->types[reg_type] = BUF_TYPE_GEM;
+                       break;
+               case G2D_SRC_COLOR_MODE:
+               case G2D_DST_COLOR_MODE:
+                       if (for_addr)
+                               goto err;
+
+                       reg_type = g2d_get_reg_type(reg_offset);
+                       if (reg_type == REG_TYPE_NONE)
+                               goto err;
+
+                       buf_desc = &buf_info->descs[reg_type];
+                       value = cmdlist->data[index + 1];
+
+                       buf_desc->format = value & 0xf;
+                       break;
+               case G2D_SRC_LEFT_TOP:
+               case G2D_DST_LEFT_TOP:
+                       if (for_addr)
+                               goto err;
+
+                       reg_type = g2d_get_reg_type(reg_offset);
+                       if (reg_type == REG_TYPE_NONE)
+                               goto err;
+
+                       buf_desc = &buf_info->descs[reg_type];
+                       value = cmdlist->data[index + 1];
+
+                       buf_desc->left_x = value & 0x1fff;
+                       buf_desc->top_y = (value & 0x1fff0000) >> 16;
+                       break;
+               case G2D_SRC_RIGHT_BOTTOM:
+               case G2D_DST_RIGHT_BOTTOM:
+                       if (for_addr)
+                               goto err;
+
+                       reg_type = g2d_get_reg_type(reg_offset);
+                       if (reg_type == REG_TYPE_NONE)
+                               goto err;
+
+                       buf_desc = &buf_info->descs[reg_type];
+                       value = cmdlist->data[index + 1];
+
+                       buf_desc->right_x = value & 0x1fff;
+                       buf_desc->bottom_y = (value & 0x1fff0000) >> 16;
                        break;
                default:
                        if (for_addr)
@@ -860,9 +1126,23 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
        cmdlist->data[cmdlist->last++] = G2D_SRC_BASE_ADDR;
        cmdlist->data[cmdlist->last++] = 0;
 
+       /*
+        * 'LIST_HOLD' command should be set to the DMA_HOLD_CMD_REG
+        * and GCF bit should be set to INTEN register if user wants
+        * G2D interrupt event once current command list execution is
+        * finished.
+        * Otherwise only ACF bit should be set to INTEN register so
+        * that one interrupt is occured after all command lists
+        * have been completed.
+        */
        if (node->event) {
+               cmdlist->data[cmdlist->last++] = G2D_INTEN;
+               cmdlist->data[cmdlist->last++] = G2D_INTEN_ACF | G2D_INTEN_GCF;
                cmdlist->data[cmdlist->last++] = G2D_DMA_HOLD_CMD;
                cmdlist->data[cmdlist->last++] = G2D_LIST_HOLD;
+       } else {
+               cmdlist->data[cmdlist->last++] = G2D_INTEN;
+               cmdlist->data[cmdlist->last++] = G2D_INTEN_ACF;
        }
 
        /* Check size of cmdlist: last 2 is about G2D_BITBLT_START */
@@ -887,7 +1167,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
        if (ret < 0)
                goto err_free_event;
 
-       node->map_nr = req->cmd_buf_nr;
+       node->buf_info.map_nr = req->cmd_buf_nr;
        if (req->cmd_buf_nr) {
                struct drm_exynos_g2d_cmd *cmd_buf;
 
index 67e17ce112b69eb5ce795358e1471fd9db2ad841..0e6fe000578c08c78be0df9fa00e2205429e8576 100644 (file)
@@ -164,6 +164,27 @@ out:
        exynos_gem_obj = NULL;
 }
 
+unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
+                                               unsigned int gem_handle,
+                                               struct drm_file *file_priv)
+{
+       struct exynos_drm_gem_obj *exynos_gem_obj;
+       struct drm_gem_object *obj;
+
+       obj = drm_gem_object_lookup(dev, file_priv, gem_handle);
+       if (!obj) {
+               DRM_ERROR("failed to lookup gem object.\n");
+               return 0;
+       }
+
+       exynos_gem_obj = to_exynos_gem_obj(obj);
+
+       drm_gem_object_unreference_unlocked(obj);
+
+       return exynos_gem_obj->buffer->size;
+}
+
+
 struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev,
                                                      unsigned long size)
 {
index 35ebac47dc2bacfec928d54001b6065aa9e75564..468766bee450837eefe19f37db7e7fdcc00133c6 100644 (file)
@@ -130,6 +130,11 @@ int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data,
 int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data,
                                      struct drm_file *file_priv);
 
+/* get buffer size to gem handle. */
+unsigned long exynos_drm_gem_get_size(struct drm_device *dev,
+                                               unsigned int gem_handle,
+                                               struct drm_file *file_priv);
+
 /* initialize gem object. */
 int exynos_drm_gem_init_object(struct drm_gem_object *obj);
 
index 13ccbd4bcfaa8c863f27d24870101c32166ecb47..9504b0cd825a4dc9d4b81c2be674eb0897eb137d 100644 (file)
@@ -117,13 +117,12 @@ static struct edid *vidi_get_edid(struct device *dev,
        }
 
        edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
-       edid = kzalloc(edid_len, GFP_KERNEL);
+       edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL);
        if (!edid) {
                DRM_DEBUG_KMS("failed to allocate edid\n");
                return ERR_PTR(-ENOMEM);
        }
 
-       memcpy(edid, ctx->raw_edid, edid_len);
        return edid;
 }
 
@@ -563,12 +562,11 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data,
                        return -EINVAL;
                }
                edid_len = (1 + raw_edid->extensions) * EDID_LENGTH;
-               ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL);
+               ctx->raw_edid = kmemdup(raw_edid, edid_len, GFP_KERNEL);
                if (!ctx->raw_edid) {
                        DRM_DEBUG_KMS("failed to allocate raw_edid.\n");
                        return -ENOMEM;
                }
-               memcpy(ctx->raw_edid, raw_edid, edid_len);
        } else {
                /*
                 * with connection = 0, free raw_edid
index e919aba29b3dfde038979f5c417966bc8bf147c1..2f4f72f070475a62f77ce15451540962eb011153 100644 (file)
@@ -818,7 +818,7 @@ static void mixer_win_disable(void *ctx, int win)
        mixer_ctx->win_data[win].enabled = false;
 }
 
-int mixer_check_timing(void *ctx, struct fb_videomode *timing)
+static int mixer_check_timing(void *ctx, struct fb_videomode *timing)
 {
        struct mixer_context *mixer_ctx = ctx;
        u32 w, h;
index aae31489c89304f8d79ad2319bbb0ecb97897cef..7299ea45dd03dec217944f31422f5f1a62bcc6eb 100644 (file)
@@ -103,7 +103,7 @@ static const char *cache_level_str(int type)
 static void
 describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj)
 {
-       seq_printf(m, "%p: %s%s %8zdKiB %02x %02x %d %d %d%s%s%s",
+       seq_printf(m, "%pK: %s%s %8zdKiB %02x %02x %d %d %d%s%s%s",
                   &obj->base,
                   get_pin_flag(obj),
                   get_tiling_flag(obj),
index 0a8eceb7590244af233d153845a91c79e6662420..e9b57893db2b1ebba1348a71e37c845f98c3286b 100644 (file)
@@ -125,6 +125,11 @@ MODULE_PARM_DESC(preliminary_hw_support,
                "Enable Haswell and ValleyView Support. "
                "(default: false)");
 
+int i915_disable_power_well __read_mostly = 0;
+module_param_named(disable_power_well, i915_disable_power_well, int, 0600);
+MODULE_PARM_DESC(disable_power_well,
+                "Disable the power well when possible (default: false)");
+
 static struct drm_driver driver;
 extern int intel_agp_enabled;
 
index e95337c974594d34c936d071975f5040c78754d1..01769e2a99538e9e99cd191b328d7746439d328b 100644 (file)
@@ -1398,6 +1398,7 @@ extern int i915_enable_fbc __read_mostly;
 extern bool i915_enable_hangcheck __read_mostly;
 extern int i915_enable_ppgtt __read_mostly;
 extern unsigned int i915_preliminary_hw_support __read_mostly;
+extern int i915_disable_power_well __read_mostly;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
 extern int i915_resume(struct drm_device *dev);
index 2f2daebd0eefd581c38415489164ed080e0d141a..9a48e1a2d417ce7d294af15dd393ea93ec419cbb 100644 (file)
@@ -57,7 +57,7 @@ eb_create(struct drm_i915_gem_execbuffer2 *args)
        if (eb == NULL) {
                int size = args->buffer_count;
                int count = PAGE_SIZE / sizeof(struct hlist_head) / 2;
-               BUILD_BUG_ON(!is_power_of_2(PAGE_SIZE / sizeof(struct hlist_head)));
+               BUILD_BUG_ON_NOT_POWER_OF_2(PAGE_SIZE / sizeof(struct hlist_head));
                while (count > 2*size)
                        count >>= 1;
                eb = kzalloc(count*sizeof(struct hlist_head) +
@@ -732,6 +732,8 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
                   int count)
 {
        int i;
+       int relocs_total = 0;
+       int relocs_max = INT_MAX / sizeof(struct drm_i915_gem_relocation_entry);
 
        for (i = 0; i < count; i++) {
                char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr;
@@ -740,10 +742,13 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec,
                if (exec[i].flags & __EXEC_OBJECT_UNKNOWN_FLAGS)
                        return -EINVAL;
 
-               /* First check for malicious input causing overflow */
-               if (exec[i].relocation_count >
-                   INT_MAX / sizeof(struct drm_i915_gem_relocation_entry))
+               /* First check for malicious input causing overflow in
+                * the worst case where we need to allocate the entire
+                * relocation tree as a single array.
+                */
+               if (exec[i].relocation_count > relocs_max - relocs_total)
                        return -EINVAL;
+               relocs_total += exec[i].relocation_count;
 
                length = exec[i].relocation_count *
                        sizeof(struct drm_i915_gem_relocation_entry);
index 32a3693905ecb14f697fd82b4f8a2419e2818552..1ce45a0a2d3e35bed35c03386f4f63a6b9ef0f97 100644 (file)
@@ -45,6 +45,9 @@
 
 struct intel_crt {
        struct intel_encoder base;
+       /* DPMS state is stored in the connector, which we need in the
+        * encoder's enable/disable callbacks */
+       struct intel_connector *connector;
        bool force_hotplug_required;
        u32 adpa_reg;
 };
@@ -81,29 +84,6 @@ static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
        return true;
 }
 
-static void intel_disable_crt(struct intel_encoder *encoder)
-{
-       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-       struct intel_crt *crt = intel_encoder_to_crt(encoder);
-       u32 temp;
-
-       temp = I915_READ(crt->adpa_reg);
-       temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
-       temp &= ~ADPA_DAC_ENABLE;
-       I915_WRITE(crt->adpa_reg, temp);
-}
-
-static void intel_enable_crt(struct intel_encoder *encoder)
-{
-       struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
-       struct intel_crt *crt = intel_encoder_to_crt(encoder);
-       u32 temp;
-
-       temp = I915_READ(crt->adpa_reg);
-       temp |= ADPA_DAC_ENABLE;
-       I915_WRITE(crt->adpa_reg, temp);
-}
-
 /* Note: The caller is required to filter out dpms modes not supported by the
  * platform. */
 static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
@@ -135,6 +115,19 @@ static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
        I915_WRITE(crt->adpa_reg, temp);
 }
 
+static void intel_disable_crt(struct intel_encoder *encoder)
+{
+       intel_crt_set_dpms(encoder, DRM_MODE_DPMS_OFF);
+}
+
+static void intel_enable_crt(struct intel_encoder *encoder)
+{
+       struct intel_crt *crt = intel_encoder_to_crt(encoder);
+
+       intel_crt_set_dpms(encoder, crt->connector->base.dpms);
+}
+
+
 static void intel_crt_dpms(struct drm_connector *connector, int mode)
 {
        struct drm_device *dev = connector->dev;
@@ -746,6 +739,7 @@ void intel_crt_init(struct drm_device *dev)
        }
 
        connector = &intel_connector->base;
+       crt->connector = intel_connector;
        drm_connector_init(dev, &intel_connector->base,
                           &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
 
index 287b42c9d1a8250e56d8a72d1b527cbb7dc1ad38..b20d50192fcc8f3dda5c7efbe098d1a560e95f71 100644 (file)
@@ -5771,6 +5771,11 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc,
                num_connectors++;
        }
 
+       if (is_cpu_edp)
+               intel_crtc->cpu_transcoder = TRANSCODER_EDP;
+       else
+               intel_crtc->cpu_transcoder = pipe;
+
        /* We are not sure yet this won't happen. */
        WARN(!HAS_PCH_LPT(dev), "Unexpected PCH type %d\n",
             INTEL_PCH_TYPE(dev));
@@ -5837,11 +5842,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
        int pipe = intel_crtc->pipe;
        int ret;
 
-       if (IS_HASWELL(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP))
-               intel_crtc->cpu_transcoder = TRANSCODER_EDP;
-       else
-               intel_crtc->cpu_transcoder = pipe;
-
        drm_vblank_pre_modeset(dev, pipe);
 
        ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode,
index 6f728e5ee79391d3bf726f971eb7b96af307df0d..8fc93f90a7cdf9262d52186697b09ca84879b137 100644 (file)
@@ -820,6 +820,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
        struct intel_link_m_n m_n;
        int pipe = intel_crtc->pipe;
        enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder;
+       int target_clock;
 
        /*
         * Find the lane count in the intel_encoder private
@@ -835,13 +836,22 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode,
                }
        }
 
+       target_clock = mode->clock;
+       for_each_encoder_on_crtc(dev, crtc, intel_encoder) {
+               if (intel_encoder->type == INTEL_OUTPUT_EDP) {
+                       target_clock = intel_edp_target_clock(intel_encoder,
+                                                             mode);
+                       break;
+               }
+       }
+
        /*
         * Compute the GMCH and Link ratios. The '3' here is
         * the number of bytes_per_pixel post-LUT, which we always
         * set up for 8-bits of R/G/B, or 3 bytes total.
         */
        intel_link_compute_m_n(intel_crtc->bpp, lane_count,
-                              mode->clock, adjusted_mode->clock, &m_n);
+                              target_clock, adjusted_mode->clock, &m_n);
 
        if (IS_HASWELL(dev)) {
                I915_WRITE(PIPE_DATA_M1(cpu_transcoder),
@@ -1930,7 +1940,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp)
                for (i = 0; i < intel_dp->lane_count; i++)
                        if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0)
                                break;
-               if (i == intel_dp->lane_count && voltage_tries == 5) {
+               if (i == intel_dp->lane_count) {
                        ++loop_tries;
                        if (loop_tries == 5) {
                                DRM_DEBUG_KMS("too many full retries, give up\n");
@@ -2549,12 +2559,15 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 {
        struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
        struct intel_dp *intel_dp = &intel_dig_port->dp;
+       struct drm_device *dev = intel_dp_to_dev(intel_dp);
 
        i2c_del_adapter(&intel_dp->adapter);
        drm_encoder_cleanup(encoder);
        if (is_edp(intel_dp)) {
                cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+               mutex_lock(&dev->mode_config.mutex);
                ironlake_panel_vdd_off_sync(intel_dp);
+               mutex_unlock(&dev->mode_config.mutex);
        }
        kfree(intel_dig_port);
 }
index acf8aec9ada7162543954e4adf7c7b28d1bb4770..ef4744e1bf0bc44be8424a2cb936c26ff716da28 100644 (file)
@@ -203,7 +203,13 @@ intel_gpio_setup(struct intel_gmbus *bus, u32 pin)
        algo->data = bus;
 }
 
-#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 4)
+/*
+ * gmbus on gen4 seems to be able to generate legacy interrupts even when in MSI
+ * mode. This results in spurious interrupt warnings if the legacy irq no. is
+ * shared with another device. The kernel then disables that interrupt source
+ * and so prevents the other device from working properly.
+ */
+#define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 5)
 static int
 gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
                     u32 gmbus2_status,
@@ -214,6 +220,9 @@ gmbus_wait_hw_status(struct drm_i915_private *dev_priv,
        u32 gmbus2 = 0;
        DEFINE_WAIT(wait);
 
+       if (!HAS_GMBUS_IRQ(dev_priv->dev))
+               gmbus4_irq_en = 0;
+
        /* Important: The hw handles only the first bit, so set only one! Since
         * we also need to check for NAKs besides the hw ready/idle signal, we
         * need to wake up periodically and check that ourselves. */
index a3730e0289e5eefa15afb9f04a54c65c817f7886..bee8cb6108a7d44883286ef4b35bb6d7f8713a0f 100644 (file)
@@ -321,9 +321,6 @@ void intel_panel_enable_backlight(struct drm_device *dev,
        if (dev_priv->backlight_level == 0)
                dev_priv->backlight_level = intel_panel_get_max_backlight(dev);
 
-       dev_priv->backlight_enabled = true;
-       intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);
-
        if (INTEL_INFO(dev)->gen >= 4) {
                uint32_t reg, tmp;
 
@@ -359,12 +356,12 @@ void intel_panel_enable_backlight(struct drm_device *dev,
        }
 
 set_level:
-       /* Check the current backlight level and try to set again if it's zero.
-        * On some machines, BLC_PWM_CPU_CTL is cleared to zero automatically
-        * when BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1 are written.
+       /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1.
+        * BLC_PWM_CPU_CTL may be cleared to zero automatically when these
+        * registers are set.
         */
-       if (!intel_panel_get_backlight(dev))
-               intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);
+       dev_priv->backlight_enabled = true;
+       intel_panel_actually_set_backlight(dev, dev_priv->backlight_level);
 }
 
 static void intel_panel_init_backlight(struct drm_device *dev)
index a1794c6df1bf1b80917f60e2145c39ae741aa478..adca00783e61b304723d3d05197b53f47b6b33db 100644 (file)
@@ -4079,6 +4079,9 @@ void intel_set_power_well(struct drm_device *dev, bool enable)
        if (!IS_HASWELL(dev))
                return;
 
+       if (!i915_disable_power_well && !enable)
+               return;
+
        tmp = I915_READ(HSW_PWR_WELL_DRIVER);
        is_enabled = tmp & HSW_PWR_WELL_STATE;
        enable_requested = tmp & HSW_PWR_WELL_ENABLE;
index a274b9906ef892334460f061e542839a752a591f..fe22bb780e1d048efc76e92d7296ab98f94294db 100644 (file)
@@ -382,19 +382,19 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
        m = n = p = 0;
        vcomax = 800000;
        vcomin = 400000;
-       pllreffreq = 3333;
+       pllreffreq = 33333;
 
        delta = 0xffffffff;
        permitteddelta = clock * 5 / 1000;
 
-       for (testp = 16; testp > 0; testp--) {
+       for (testp = 16; testp > 0; testp >>= 1) {
                if (clock * testp > vcomax)
                        continue;
                if (clock * testp < vcomin)
                        continue;
 
                for (testm = 1; testm < 33; testm++) {
-                       for (testn = 1; testn < 257; testn++) {
+                       for (testn = 17; testn < 257; testn++) {
                                computed = (pllreffreq * testn) /
                                        (testm * testp);
                                if (computed > clock)
@@ -404,11 +404,11 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
                                if (tmpdelta < delta) {
                                        delta = tmpdelta;
                                        n = testn - 1;
-                                       m = (testm - 1) | ((n >> 1) & 0x80);
+                                       m = (testm - 1);
                                        p = testp - 1;
                                }
                                if ((clock * testp) >= 600000)
-                                       p |= 80;
+                                       p |= 0x80;
                        }
                }
        }
index 0daab62ea14c68a13f9fa1e58b681f4d39d760e0..3b2e7b6304d39862ac60159416018d4417f33ec6 100644 (file)
@@ -278,7 +278,6 @@ nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle)
        struct nouveau_object *parent = NULL;
        struct nouveau_object *namedb = NULL;
        struct nouveau_handle *handle = NULL;
-       int ret = -EINVAL;
 
        parent = nouveau_handle_ref(client, _parent);
        if (!parent)
@@ -295,7 +294,7 @@ nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle)
        }
 
        nouveau_object_ref(NULL, &parent);
-       return ret;
+       return handle ? 0 : -EINVAL;
 }
 
 int
index 5fa13267bd9f427b7f83251f22e6bd13a80683b3..02e369f80449a2d222375349aa4937623f2ac9e7 100644 (file)
@@ -544,13 +544,13 @@ nv50_disp_curs_ofuncs = {
 static void
 nv50_disp_base_vblank_enable(struct nouveau_event *event, int head)
 {
-       nv_mask(event->priv, 0x61002c, (1 << head), (1 << head));
+       nv_mask(event->priv, 0x61002c, (4 << head), (4 << head));
 }
 
 static void
 nv50_disp_base_vblank_disable(struct nouveau_event *event, int head)
 {
-       nv_mask(event->priv, 0x61002c, (1 << head), (0 << head));
+       nv_mask(event->priv, 0x61002c, (4 << head), 0);
 }
 
 static int
index 6b17b614629f64172a6ace41ed5a1593889c94ad..0b20fc0d19c16861f969f5acdda2938559243be1 100644 (file)
@@ -4,7 +4,7 @@
 #include <core/device.h>
 #include <core/subdev.h>
 
-enum nouveau_therm_mode {
+enum nouveau_therm_fan_mode {
        NOUVEAU_THERM_CTRL_NONE = 0,
        NOUVEAU_THERM_CTRL_MANUAL = 1,
        NOUVEAU_THERM_CTRL_AUTO = 2,
index e816f06637a7210e9862a68734b753d447ffc28e..0e2c1a4f16595b09a5fa2023ac93691fd74da3b9 100644 (file)
@@ -248,6 +248,22 @@ nouveau_bios_shadow_pci(struct nouveau_bios *bios)
        }
 }
 
+static void
+nouveau_bios_shadow_platform(struct nouveau_bios *bios)
+{
+       struct pci_dev *pdev = nv_device(bios)->pdev;
+       size_t size;
+
+       void __iomem *rom = pci_platform_rom(pdev, &size);
+       if (rom && size) {
+               bios->data = kmalloc(size, GFP_KERNEL);
+               if (bios->data) {
+                       memcpy_fromio(bios->data, rom, size);
+                       bios->size = size;
+               }
+       }
+}
+
 static int
 nouveau_bios_score(struct nouveau_bios *bios, const bool writeable)
 {
@@ -288,6 +304,7 @@ nouveau_bios_shadow(struct nouveau_bios *bios)
                { "PROM", nouveau_bios_shadow_prom, false, 0, 0, NULL },
                { "ACPI", nouveau_bios_shadow_acpi, true, 0, 0, NULL },
                { "PCIROM", nouveau_bios_shadow_pci, true, 0, 0, NULL },
+               { "PLATFORM", nouveau_bios_shadow_platform, true, 0, 0, NULL },
                {}
        };
        struct methods *mthd, *best;
index f794dc89a3b2a1ddaf68dc686b5ef13c0f9bbbcb..a00a5a76e2d62b82d5717923e98e85541bb7597c 100644 (file)
@@ -134,7 +134,7 @@ nouveau_therm_alarm(struct nouveau_alarm *alarm)
 }
 
 int
-nouveau_therm_mode(struct nouveau_therm *therm, int mode)
+nouveau_therm_fan_mode(struct nouveau_therm *therm, int mode)
 {
        struct nouveau_therm_priv *priv = (void *)therm;
        struct nouveau_device *device = nv_device(therm);
@@ -149,10 +149,15 @@ nouveau_therm_mode(struct nouveau_therm *therm, int mode)
            (mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0))
                return -EINVAL;
 
+       /* do not allow automatic fan management if the thermal sensor is
+        * not available */
+       if (priv->mode == 2 && therm->temp_get(therm) < 0)
+               return -EINVAL;
+
        if (priv->mode == mode)
                return 0;
 
-       nv_info(therm, "Thermal management: %s\n", name[mode]);
+       nv_info(therm, "fan management: %s\n", name[mode]);
        nouveau_therm_update(therm, mode);
        return 0;
 }
@@ -213,7 +218,7 @@ nouveau_therm_attr_set(struct nouveau_therm *therm,
                priv->fan->bios.max_duty = value;
                return 0;
        case NOUVEAU_THERM_ATTR_FAN_MODE:
-               return nouveau_therm_mode(therm, value);
+               return nouveau_therm_fan_mode(therm, value);
        case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST:
                priv->bios_sensor.thrs_fan_boost.temp = value;
                priv->sensor.program_alarms(therm);
@@ -263,7 +268,7 @@ _nouveau_therm_init(struct nouveau_object *object)
                return ret;
 
        if (priv->suspend >= 0)
-               nouveau_therm_mode(therm, priv->mode);
+               nouveau_therm_fan_mode(therm, priv->mode);
        priv->sensor.program_alarms(therm);
        return 0;
 }
@@ -313,11 +318,12 @@ nouveau_therm_create_(struct nouveau_object *parent,
 int
 nouveau_therm_preinit(struct nouveau_therm *therm)
 {
-       nouveau_therm_ic_ctor(therm);
        nouveau_therm_sensor_ctor(therm);
+       nouveau_therm_ic_ctor(therm);
        nouveau_therm_fan_ctor(therm);
 
-       nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_NONE);
+       nouveau_therm_fan_mode(therm, NOUVEAU_THERM_CTRL_NONE);
+       nouveau_therm_sensor_preinit(therm);
        return 0;
 }
 
index e24090bac195687c34f9175103b34a9e7e0cb8d5..8b3adec5fbb19e8a34cdb53fa83420f7b57f21b2 100644 (file)
@@ -32,6 +32,7 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c,
                        struct i2c_board_info *info)
 {
        struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c);
+       struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
        struct i2c_client *client;
 
        request_module("%s%s", I2C_MODULE_PREFIX, info->type);
@@ -46,8 +47,9 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c,
        }
 
        nv_info(priv,
-               "Found an %s at address 0x%x (controlled by lm_sensors)\n",
-               info->type, info->addr);
+               "Found an %s at address 0x%x (controlled by lm_sensors, "
+               "temp offset %+i C)\n",
+               info->type, info->addr, sensor->offset_constant);
        priv->ic = client;
 
        return true;
index 0f5363edb96435ec8fb992abab3479a462bcdf88..a70d1b7e397b4b3ffe280b1f0ad6152679f6f15b 100644 (file)
@@ -29,54 +29,83 @@ struct nv40_therm_priv {
        struct nouveau_therm_priv base;
 };
 
+enum nv40_sensor_style { INVALID_STYLE = -1, OLD_STYLE = 0, NEW_STYLE = 1 };
+
+static enum nv40_sensor_style
+nv40_sensor_style(struct nouveau_therm *therm)
+{
+       struct nouveau_device *device = nv_device(therm);
+
+       switch (device->chipset) {
+       case 0x43:
+       case 0x44:
+       case 0x4a:
+       case 0x47:
+               return OLD_STYLE;
+
+       case 0x46:
+       case 0x49:
+       case 0x4b:
+       case 0x4e:
+       case 0x4c:
+       case 0x67:
+       case 0x68:
+       case 0x63:
+               return NEW_STYLE;
+       default:
+               return INVALID_STYLE;
+       }
+}
+
 static int
 nv40_sensor_setup(struct nouveau_therm *therm)
 {
-       struct nouveau_device *device = nv_device(therm);
+       enum nv40_sensor_style style = nv40_sensor_style(therm);
 
        /* enable ADC readout and disable the ALARM threshold */
-       if (device->chipset >= 0x46) {
+       if (style == NEW_STYLE) {
                nv_mask(therm, 0x15b8, 0x80000000, 0);
                nv_wr32(therm, 0x15b0, 0x80003fff);
-               mdelay(10); /* wait for the temperature to stabilize */
+               mdelay(20); /* wait for the temperature to stabilize */
                return nv_rd32(therm, 0x15b4) & 0x3fff;
-       } else {
+       } else if (style == OLD_STYLE) {
                nv_wr32(therm, 0x15b0, 0xff);
+               mdelay(20); /* wait for the temperature to stabilize */
                return nv_rd32(therm, 0x15b4) & 0xff;
-       }
+       } else
+               return -ENODEV;
 }
 
 static int
 nv40_temp_get(struct nouveau_therm *therm)
 {
        struct nouveau_therm_priv *priv = (void *)therm;
-       struct nouveau_device *device = nv_device(therm);
        struct nvbios_therm_sensor *sensor = &priv->bios_sensor;
+       enum nv40_sensor_style style = nv40_sensor_style(therm);
        int core_temp;
 
-       if (device->chipset >= 0x46) {
+       if (style == NEW_STYLE) {
                nv_wr32(therm, 0x15b0, 0x80003fff);
                core_temp = nv_rd32(therm, 0x15b4) & 0x3fff;
-       } else {
+       } else if (style == OLD_STYLE) {
                nv_wr32(therm, 0x15b0, 0xff);
                core_temp = nv_rd32(therm, 0x15b4) & 0xff;
-       }
-
-       /* Setup the sensor if the temperature is 0 */
-       if (core_temp == 0)
-               core_temp = nv40_sensor_setup(therm);
+       } else
+               return -ENODEV;
 
-       if (sensor->slope_div == 0)
-               sensor->slope_div = 1;
-       if (sensor->offset_den == 0)
-               sensor->offset_den = 1;
-       if (sensor->slope_mult < 1)
-               sensor->slope_mult = 1;
+       /* if the slope or the offset is unset, do no use the sensor */
+       if (!sensor->slope_div || !sensor->slope_mult ||
+           !sensor->offset_num || !sensor->offset_den)
+           return -ENODEV;
 
        core_temp = core_temp * sensor->slope_mult / sensor->slope_div;
        core_temp = core_temp + sensor->offset_num / sensor->offset_den;
        core_temp = core_temp + sensor->offset_constant - 8;
 
+       /* reserve negative temperatures for errors */
+       if (core_temp < 0)
+               core_temp = 0;
+
        return core_temp;
 }
 
index 06b98706b3fc163460aa807af2a699ec62a8af98..438d9824b7741c5733bf2aa0f8ec306784569efe 100644 (file)
@@ -102,7 +102,7 @@ struct nouveau_therm_priv {
        struct i2c_client *ic;
 };
 
-int nouveau_therm_mode(struct nouveau_therm *therm, int mode);
+int nouveau_therm_fan_mode(struct nouveau_therm *therm, int mode);
 int nouveau_therm_attr_get(struct nouveau_therm *therm,
                       enum nouveau_therm_attr_type type);
 int nouveau_therm_attr_set(struct nouveau_therm *therm,
@@ -122,6 +122,7 @@ int nouveau_therm_fan_sense(struct nouveau_therm *therm);
 
 int nouveau_therm_preinit(struct nouveau_therm *);
 
+void nouveau_therm_sensor_preinit(struct nouveau_therm *);
 void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm,
                                             enum nouveau_therm_thrs thrs,
                                             enum nouveau_therm_thrs_state st);
index b37624af82977543142f7035a2f2ba7b8a89cc63..470f6a47b6565bfe4d3ad257fa5d7f038ca25755 100644 (file)
@@ -34,10 +34,6 @@ nouveau_therm_temp_set_defaults(struct nouveau_therm *therm)
 {
        struct nouveau_therm_priv *priv = (void *)therm;
 
-       priv->bios_sensor.slope_mult = 1;
-       priv->bios_sensor.slope_div = 1;
-       priv->bios_sensor.offset_num = 0;
-       priv->bios_sensor.offset_den = 1;
        priv->bios_sensor.offset_constant = 0;
 
        priv->bios_sensor.thrs_fan_boost.temp = 90;
@@ -60,11 +56,6 @@ nouveau_therm_temp_safety_checks(struct nouveau_therm *therm)
        struct nouveau_therm_priv *priv = (void *)therm;
        struct nvbios_therm_sensor *s = &priv->bios_sensor;
 
-       if (!priv->bios_sensor.slope_div)
-               priv->bios_sensor.slope_div = 1;
-       if (!priv->bios_sensor.offset_den)
-               priv->bios_sensor.offset_den = 1;
-
        /* enforce a minimum hysteresis on thresholds */
        s->thrs_fan_boost.hysteresis = max_t(u8, s->thrs_fan_boost.hysteresis, 2);
        s->thrs_down_clock.hysteresis = max_t(u8, s->thrs_down_clock.hysteresis, 2);
@@ -106,16 +97,16 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm,
        const char *thresolds[] = {
                "fanboost", "downclock", "critical", "shutdown"
        };
-       uint8_t temperature = therm->temp_get(therm);
+       int temperature = therm->temp_get(therm);
 
        if (thrs < 0 || thrs > 3)
                return;
 
        if (dir == NOUVEAU_THERM_THRS_FALLING)
-               nv_info(therm, "temperature (%u C) went below the '%s' threshold\n",
+               nv_info(therm, "temperature (%i C) went below the '%s' threshold\n",
                        temperature, thresolds[thrs]);
        else
-               nv_info(therm, "temperature (%u C) hit the '%s' threshold\n",
+               nv_info(therm, "temperature (%i C) hit the '%s' threshold\n",
                        temperature, thresolds[thrs]);
 
        active = (dir == NOUVEAU_THERM_THRS_RISING);
@@ -123,7 +114,7 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm,
        case NOUVEAU_THERM_THRS_FANBOOST:
                if (active) {
                        nouveau_therm_fan_set(therm, true, 100);
-                       nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_AUTO);
+                       nouveau_therm_fan_mode(therm, NOUVEAU_THERM_CTRL_AUTO);
                }
                break;
        case NOUVEAU_THERM_THRS_DOWNCLOCK:
@@ -202,7 +193,7 @@ alarm_timer_callback(struct nouveau_alarm *alarm)
                                             NOUVEAU_THERM_THRS_SHUTDOWN);
 
        /* schedule the next poll in one second */
-       if (list_empty(&alarm->head))
+       if (therm->temp_get(therm) >= 0 && list_empty(&alarm->head))
                ptimer->alarm(ptimer, 1000 * 1000 * 1000, alarm);
 
        spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags);
@@ -225,6 +216,17 @@ nouveau_therm_program_alarms_polling(struct nouveau_therm *therm)
        alarm_timer_callback(&priv->sensor.therm_poll_alarm);
 }
 
+void
+nouveau_therm_sensor_preinit(struct nouveau_therm *therm)
+{
+       const char *sensor_avail = "yes";
+
+       if (therm->temp_get(therm) < 0)
+               sensor_avail = "no";
+
+       nv_info(therm, "internal sensor: %s\n", sensor_avail);
+}
+
 int
 nouveau_therm_sensor_ctor(struct nouveau_therm *therm)
 {
index 41241922263fd79641a2486033d933932025524e..5eb3e0da7c6eb1eb213e527021668ddd96bccaa1 100644 (file)
@@ -116,6 +116,11 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16,
 {
        struct nouveau_abi16_ntfy *ntfy, *temp;
 
+       /* wait for all activity to stop before releasing notify object, which
+        * may be still in use */
+       if (chan->chan && chan->ntfy)
+               nouveau_channel_idle(chan->chan);
+
        /* cleanup notifier state */
        list_for_each_entry_safe(ntfy, temp, &chan->notifiers, head) {
                nouveau_abi16_ntfy_fini(chan, ntfy);
@@ -386,7 +391,7 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_device *device = nv_device(drm->device);
        struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
-       struct nouveau_abi16_chan *chan, *temp;
+       struct nouveau_abi16_chan *chan = NULL, *temp;
        struct nouveau_abi16_ntfy *ntfy;
        struct nouveau_object *object;
        struct nv_dma_class args = {};
@@ -399,10 +404,11 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS)
        if (unlikely(nv_device(abi16->device)->card_type >= NV_C0))
                return nouveau_abi16_put(abi16, -EINVAL);
 
-       list_for_each_entry_safe(chan, temp, &abi16->channels, head) {
-               if (chan->chan->handle == (NVDRM_CHAN | info->channel))
+       list_for_each_entry(temp, &abi16->channels, head) {
+               if (temp->chan->handle == (NVDRM_CHAN | info->channel)) {
+                       chan = temp;
                        break;
-               chan = NULL;
+               }
        }
 
        if (!chan)
@@ -454,17 +460,18 @@ nouveau_abi16_ioctl_gpuobj_free(ABI16_IOCTL_ARGS)
 {
        struct drm_nouveau_gpuobj_free *fini = data;
        struct nouveau_abi16 *abi16 = nouveau_abi16_get(file_priv, dev);
-       struct nouveau_abi16_chan *chan, *temp;
+       struct nouveau_abi16_chan *chan = NULL, *temp;
        struct nouveau_abi16_ntfy *ntfy;
        int ret;
 
        if (unlikely(!abi16))
                return -ENOMEM;
 
-       list_for_each_entry_safe(chan, temp, &abi16->channels, head) {
-               if (chan->chan->handle == (NVDRM_CHAN | fini->channel))
+       list_for_each_entry(temp, &abi16->channels, head) {
+               if (temp->chan->handle == (NVDRM_CHAN | fini->channel)) {
+                       chan = temp;
                        break;
-               chan = NULL;
+               }
        }
 
        if (!chan)
index 11ca82148edcb13505d9c7d06a303ad25053b04b..7ff10711a4d0a437d856df1dafbb0eddf9cee82e 100644 (file)
@@ -801,7 +801,7 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
                stride  = 16 * 4;
                height  = amount / stride;
 
-               if (new_mem->mem_type == TTM_PL_VRAM &&
+               if (old_mem->mem_type == TTM_PL_VRAM &&
                    nouveau_bo_tile_layout(nvbo)) {
                        ret = RING_SPACE(chan, 8);
                        if (ret)
@@ -823,7 +823,7 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
                        BEGIN_NV04(chan, NvSubCopy, 0x0200, 1);
                        OUT_RING  (chan, 1);
                }
-               if (old_mem->mem_type == TTM_PL_VRAM &&
+               if (new_mem->mem_type == TTM_PL_VRAM &&
                    nouveau_bo_tile_layout(nvbo)) {
                        ret = RING_SPACE(chan, 8);
                        if (ret)
index d1099365bfc1f47d6aa1be0e640f66c3fb66fcf2..c95decf543e904cbe89a6792fa9c709a2b87ad17 100644 (file)
@@ -71,12 +71,26 @@ module_param_named(modeset, nouveau_modeset, int, 0400);
 
 static struct drm_driver driver;
 
+static int
+nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head)
+{
+       struct nouveau_drm *drm =
+               container_of(event, struct nouveau_drm, vblank[head]);
+       drm_handle_vblank(drm->dev, head);
+       return NVKM_EVENT_KEEP;
+}
+
 static int
 nouveau_drm_vblank_enable(struct drm_device *dev, int head)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_disp *pdisp = nouveau_disp(drm->device);
-       nouveau_event_get(pdisp->vblank, head, &drm->vblank);
+
+       if (WARN_ON_ONCE(head > ARRAY_SIZE(drm->vblank)))
+               return -EIO;
+       WARN_ON_ONCE(drm->vblank[head].func);
+       drm->vblank[head].func = nouveau_drm_vblank_handler;
+       nouveau_event_get(pdisp->vblank, head, &drm->vblank[head]);
        return 0;
 }
 
@@ -85,16 +99,11 @@ nouveau_drm_vblank_disable(struct drm_device *dev, int head)
 {
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_disp *pdisp = nouveau_disp(drm->device);
-       nouveau_event_put(pdisp->vblank, head, &drm->vblank);
-}
-
-static int
-nouveau_drm_vblank_handler(struct nouveau_eventh *event, int head)
-{
-       struct nouveau_drm *drm =
-               container_of(event, struct nouveau_drm, vblank);
-       drm_handle_vblank(drm->dev, head);
-       return NVKM_EVENT_KEEP;
+       if (drm->vblank[head].func)
+               nouveau_event_put(pdisp->vblank, head, &drm->vblank[head]);
+       else
+               WARN_ON_ONCE(1);
+       drm->vblank[head].func = NULL;
 }
 
 static u64
@@ -292,7 +301,6 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags)
 
        dev->dev_private = drm;
        drm->dev = dev;
-       drm->vblank.func = nouveau_drm_vblank_handler;
 
        INIT_LIST_HEAD(&drm->clients);
        spin_lock_init(&drm->tile.lock);
index b25df374c901df36f1c6e9408225ef9a2ed4b813..9c39bafbef2c23680fa757fdd251e158a56ae931 100644 (file)
@@ -113,7 +113,7 @@ struct nouveau_drm {
        struct nvbios vbios;
        struct nouveau_display *display;
        struct backlight_device *backlight;
-       struct nouveau_eventh vblank;
+       struct nouveau_eventh vblank[4];
 
        /* power management */
        struct nouveau_pm *pm;
index bb54098c6d970bd4c0b45582220490fb11b15426..936b442a6ab7f3f2e09ecea341e3105df51ed630 100644 (file)
@@ -402,8 +402,12 @@ nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf)
        struct drm_device *dev = dev_get_drvdata(d);
        struct nouveau_drm *drm = nouveau_drm(dev);
        struct nouveau_therm *therm = nouveau_therm(drm->device);
+       int temp = therm->temp_get(therm);
 
-       return snprintf(buf, PAGE_SIZE, "%d\n", therm->temp_get(therm) * 1000);
+       if (temp < 0)
+               return temp;
+
+       return snprintf(buf, PAGE_SIZE, "%d\n", temp * 1000);
 }
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp,
                                                  NULL, 0);
@@ -871,7 +875,12 @@ static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO | S_IWUSR,
                          nouveau_hwmon_get_pwm1_max,
                          nouveau_hwmon_set_pwm1_max, 0);
 
-static struct attribute *hwmon_attributes[] = {
+static struct attribute *hwmon_default_attributes[] = {
+       &sensor_dev_attr_name.dev_attr.attr,
+       &sensor_dev_attr_update_rate.dev_attr.attr,
+       NULL
+};
+static struct attribute *hwmon_temp_attributes[] = {
        &sensor_dev_attr_temp1_input.dev_attr.attr,
        &sensor_dev_attr_temp1_auto_point1_pwm.dev_attr.attr,
        &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr,
@@ -882,8 +891,6 @@ static struct attribute *hwmon_attributes[] = {
        &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr,
        &sensor_dev_attr_temp1_emergency.dev_attr.attr,
        &sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr,
-       &sensor_dev_attr_name.dev_attr.attr,
-       &sensor_dev_attr_update_rate.dev_attr.attr,
        NULL
 };
 static struct attribute *hwmon_fan_rpm_attributes[] = {
@@ -898,8 +905,11 @@ static struct attribute *hwmon_pwm_fan_attributes[] = {
        NULL
 };
 
-static const struct attribute_group hwmon_attrgroup = {
-       .attrs = hwmon_attributes,
+static const struct attribute_group hwmon_default_attrgroup = {
+       .attrs = hwmon_default_attributes,
+};
+static const struct attribute_group hwmon_temp_attrgroup = {
+       .attrs = hwmon_temp_attributes,
 };
 static const struct attribute_group hwmon_fan_rpm_attrgroup = {
        .attrs = hwmon_fan_rpm_attributes,
@@ -931,13 +941,22 @@ nouveau_hwmon_init(struct drm_device *dev)
        }
        dev_set_drvdata(hwmon_dev, dev);
 
-       /* default sysfs entries */
-       ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_attrgroup);
+       /* set the default attributes */
+       ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_default_attrgroup);
        if (ret) {
                if (ret)
                        goto error;
        }
 
+       /* if the card has a working thermal sensor */
+       if (therm->temp_get(therm) >= 0) {
+               ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_temp_attrgroup);
+               if (ret) {
+                       if (ret)
+                               goto error;
+               }
+       }
+
        /* if the card has a pwm fan */
        /*XXX: incorrect, need better detection for this, some boards have
         *     the gpio entries for pwm fan control even when there's no
@@ -979,11 +998,10 @@ nouveau_hwmon_fini(struct drm_device *dev)
        struct nouveau_pm *pm = nouveau_pm(dev);
 
        if (pm->hwmon) {
-               sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup);
-               sysfs_remove_group(&pm->hwmon->kobj,
-                                  &hwmon_pwm_fan_attrgroup);
-               sysfs_remove_group(&pm->hwmon->kobj,
-                                  &hwmon_fan_rpm_attrgroup);
+               sysfs_remove_group(&pm->hwmon->kobj, &hwmon_default_attrgroup);
+               sysfs_remove_group(&pm->hwmon->kobj, &hwmon_temp_attrgroup);
+               sysfs_remove_group(&pm->hwmon->kobj, &hwmon_pwm_fan_attrgroup);
+               sysfs_remove_group(&pm->hwmon->kobj, &hwmon_fan_rpm_attrgroup);
 
                hwmon_device_unregister(pm->hwmon);
        }
index 87a5a56ed358f2dda0098f955d98c6ca0df2104b..7f0e6c3f37d1fae4983bd6d8270364e52f00fc30 100644 (file)
@@ -524,6 +524,8 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
        swap_interval <<= 4;
        if (swap_interval == 0)
                swap_interval |= 0x100;
+       if (chan == NULL)
+               evo_sync(crtc->dev);
 
        push = evo_wait(sync, 128);
        if (unlikely(push == NULL))
@@ -586,8 +588,6 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
                sync->addr ^= 0x10;
                sync->data++;
                FIRE_RING (chan);
-       } else {
-               evo_sync(crtc->dev);
        }
 
        /* queue the flip */
@@ -2276,6 +2276,7 @@ nv50_display_create(struct drm_device *dev)
                        NV_WARN(drm, "failed to create encoder %d/%d/%d: %d\n",
                                     dcbe->location, dcbe->type,
                                     ffs(dcbe->or) - 1, ret);
+                       ret = 0;
                }
        }
 
index d4c633e12863bb9c546d6eae81d3fb7f835303e9..27769e724b6de1d238fc402b844d056ed69bb4b8 100644 (file)
@@ -468,13 +468,19 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                    (rdev->pdev->device == 0x9907) ||
                    (rdev->pdev->device == 0x9908) ||
                    (rdev->pdev->device == 0x9909) ||
+                   (rdev->pdev->device == 0x990B) ||
+                   (rdev->pdev->device == 0x990C) ||
+                   (rdev->pdev->device == 0x990F) ||
                    (rdev->pdev->device == 0x9910) ||
-                   (rdev->pdev->device == 0x9917)) {
+                   (rdev->pdev->device == 0x9917) ||
+                   (rdev->pdev->device == 0x9999)) {
                        rdev->config.cayman.max_simds_per_se = 6;
                        rdev->config.cayman.max_backends_per_se = 2;
                } else if ((rdev->pdev->device == 0x9903) ||
                           (rdev->pdev->device == 0x9904) ||
                           (rdev->pdev->device == 0x990A) ||
+                          (rdev->pdev->device == 0x990D) ||
+                          (rdev->pdev->device == 0x990E) ||
                           (rdev->pdev->device == 0x9913) ||
                           (rdev->pdev->device == 0x9918)) {
                        rdev->config.cayman.max_simds_per_se = 4;
@@ -483,6 +489,9 @@ static void cayman_gpu_init(struct radeon_device *rdev)
                           (rdev->pdev->device == 0x9990) ||
                           (rdev->pdev->device == 0x9991) ||
                           (rdev->pdev->device == 0x9994) ||
+                          (rdev->pdev->device == 0x9995) ||
+                          (rdev->pdev->device == 0x9996) ||
+                          (rdev->pdev->device == 0x999A) ||
                           (rdev->pdev->device == 0x99A0)) {
                        rdev->config.cayman.max_simds_per_se = 3;
                        rdev->config.cayman.max_backends_per_se = 1;
@@ -616,11 +625,22 @@ static void cayman_gpu_init(struct radeon_device *rdev)
        WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config);
        WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config);
 
-       tmp = gb_addr_config & NUM_PIPES_MASK;
-       tmp = r6xx_remap_render_backend(rdev, tmp,
-                                       rdev->config.cayman.max_backends_per_se *
-                                       rdev->config.cayman.max_shader_engines,
-                                       CAYMAN_MAX_BACKENDS, disabled_rb_mask);
+       if ((rdev->config.cayman.max_backends_per_se == 1) &&
+           (rdev->flags & RADEON_IS_IGP)) {
+               if ((disabled_rb_mask & 3) == 1) {
+                       /* RB0 disabled, RB1 enabled */
+                       tmp = 0x11111111;
+               } else {
+                       /* RB1 disabled, RB0 enabled */
+                       tmp = 0x00000000;
+               }
+       } else {
+               tmp = gb_addr_config & NUM_PIPES_MASK;
+               tmp = r6xx_remap_render_backend(rdev, tmp,
+                                               rdev->config.cayman.max_backends_per_se *
+                                               rdev->config.cayman.max_shader_engines,
+                                               CAYMAN_MAX_BACKENDS, disabled_rb_mask);
+       }
        WREG32(GB_BACKEND_MAP, tmp);
 
        cgts_tcc_disable = 0xffff0000;
@@ -1771,6 +1791,7 @@ int cayman_resume(struct radeon_device *rdev)
 int cayman_suspend(struct radeon_device *rdev)
 {
        r600_audio_fini(rdev);
+       radeon_vm_manager_fini(rdev);
        cayman_cp_enable(rdev, false);
        cayman_dma_stop(rdev);
        evergreen_irq_suspend(rdev);
index bedda9caadd9fe7d43bca2539bf51fd5df669f1f..6e05a2e75a46c211bcd5b4236e7c094b1636c9a1 100644 (file)
@@ -122,10 +122,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
                goto out_cleanup;
        }
 
-       /* r100 doesn't have dma engine so skip the test */
-       /* also, VRAM-to-VRAM test doesn't make much sense for DMA */
-       /* skip it as well if domains are the same */
-       if ((rdev->asic->copy.dma) && (sdomain != ddomain)) {
+       if (rdev->asic->copy.dma) {
                time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
                                                RADEON_BENCHMARK_COPY_DMA, n);
                if (time < 0)
@@ -135,13 +132,15 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size,
                                                     sdomain, ddomain, "dma");
        }
 
-       time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
-                                       RADEON_BENCHMARK_COPY_BLIT, n);
-       if (time < 0)
-               goto out_cleanup;
-       if (time > 0)
-               radeon_benchmark_log_results(n, size, time,
-                                            sdomain, ddomain, "blit");
+       if (rdev->asic->copy.blit) {
+               time = radeon_benchmark_do_move(rdev, size, saddr, daddr,
+                                               RADEON_BENCHMARK_COPY_BLIT, n);
+               if (time < 0)
+                       goto out_cleanup;
+               if (time > 0)
+                       radeon_benchmark_log_results(n, size, time,
+                                                    sdomain, ddomain, "blit");
+       }
 
 out_cleanup:
        if (sobj) {
index b8015913d3823547425b91b1a1c323db6cb3bfb2..fa3c56fba294fe1a433b2d7b6a3e1507e357d1ca 100644 (file)
@@ -99,6 +99,29 @@ static bool radeon_read_bios(struct radeon_device *rdev)
        return true;
 }
 
+static bool radeon_read_platform_bios(struct radeon_device *rdev)
+{
+       uint8_t __iomem *bios;
+       size_t size;
+
+       rdev->bios = NULL;
+
+       bios = pci_platform_rom(rdev->pdev, &size);
+       if (!bios) {
+               return false;
+       }
+
+       if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) {
+               return false;
+       }
+       rdev->bios = kmemdup(bios, size, GFP_KERNEL);
+       if (rdev->bios == NULL) {
+               return false;
+       }
+
+       return true;
+}
+
 #ifdef CONFIG_ACPI
 /* ATRM is used to get the BIOS on the discrete cards in
  * dual-gpu systems.
@@ -620,6 +643,9 @@ bool radeon_get_bios(struct radeon_device *rdev)
        if (r == false) {
                r = radeon_read_disabled_bios(rdev);
        }
+       if (r == false) {
+               r = radeon_read_platform_bios(rdev);
+       }
        if (r == false || rdev->bios == NULL) {
                DRM_ERROR("Unable to locate a BIOS ROM\n");
                rdev->bios = NULL;
index 9128120da04441621ec1050b8cb0ff236704b7cf..bafbe3216952510dc4736c823c08aa4e4de0a8c6 100644 (file)
@@ -4469,6 +4469,7 @@ int si_resume(struct radeon_device *rdev)
 
 int si_suspend(struct radeon_device *rdev)
 {
+       radeon_vm_manager_fini(rdev);
        si_cp_enable(rdev, false);
        cayman_dma_stop(rdev);
        si_irq_suspend(rdev);
index 512b01c04ea7610bcb6466208255a9d83a36cb1d..aa341d135867eea541c9ffdd7113f75641eef5c4 100644 (file)
@@ -2077,7 +2077,6 @@ static const struct hid_device_id hid_ignore_list[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_BEATPAD) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_MASTERKIT, USB_DEVICE_ID_MASTERKIT_MA901RADIO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1024LS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MCC, USB_DEVICE_ID_MCC_PMD1208LS) },
        { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1) },
@@ -2244,6 +2243,18 @@ bool hid_ignore(struct hid_device *hdev)
                     hdev->product <= USB_DEVICE_ID_VELLEMAN_K8061_LAST))
                        return true;
                break;
+       case USB_VENDOR_ID_ATMEL_V_USB:
+               /* Masterkit MA901 usb radio based on Atmel tiny85 chip and
+                * it has the same USB ID as many Atmel V-USB devices. This
+                * usb radio is handled by radio-ma901.c driver so we want
+                * ignore the hid. Check the name, bus, product and ignore
+                * if we have MA901 usb radio.
+                */
+               if (hdev->product == USB_DEVICE_ID_ATMEL_V_USB &&
+                       hdev->bus == BUS_USB &&
+                       strncmp(hdev->name, "www.masterkit.ru MA901", 22) == 0)
+                       return true;
+               break;
        }
 
        if (hdev->type == HID_TYPE_USBMOUSE &&
index 92e47e5c956426878e0e69d80811831d9b92e483..5309fd5eb0ebae7357044046f91ec9e0efe7e345 100644 (file)
 #define USB_VENDOR_ID_ATMEL            0x03eb
 #define USB_DEVICE_ID_ATMEL_MULTITOUCH 0x211c
 #define USB_DEVICE_ID_ATMEL_MXT_DIGITIZER      0x2118
+#define USB_VENDOR_ID_ATMEL_V_USB      0x16c0
+#define USB_DEVICE_ID_ATMEL_V_USB      0x05df
 
 #define USB_VENDOR_ID_AUREAL           0x0755
 #define USB_DEVICE_ID_AUREAL_W01RN     0x2626
 #define USB_VENDOR_ID_MADCATZ          0x0738
 #define USB_DEVICE_ID_MADCATZ_BEATPAD  0x4540
 
-#define USB_VENDOR_ID_MASTERKIT                        0x16c0
-#define USB_DEVICE_ID_MASTERKIT_MA901RADIO     0x05df
-
 #define USB_VENDOR_ID_MCC              0x09db
 #define USB_DEVICE_ID_MCC_PMD1024LS    0x0076
 #define USB_DEVICE_ID_MCC_PMD1208LS    0x007a
 #define USB_VENDOR_ID_MONTEREY         0x0566
 #define USB_DEVICE_ID_GENIUS_KB29E     0x3004
 
+#define USB_VENDOR_ID_MSI              0x1770
+#define USB_DEVICE_ID_MSI_GX680R_LED_PANEL     0xff00
+
 #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400
 #define USB_DEVICE_ID_N_S_HARMONY      0xc359
 
 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001                0x3001
 #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008                0x3008
 
+#define USB_VENDOR_ID_REALTEK          0x0bda
+#define USB_DEVICE_ID_REALTEK_READER   0x0152
+
 #define USB_VENDOR_ID_ROCCAT           0x1e7d
 #define USB_DEVICE_ID_ROCCAT_ARVO      0x30d4
 #define USB_DEVICE_ID_ROCCAT_ISKU      0x319c
index f7f113ba083eb43fb1073d189a4979f7d4d6d724..a8ce44296cfddaf34a486a7c78edde4836cd3115 100644 (file)
@@ -462,6 +462,21 @@ static int magicmouse_input_mapping(struct hid_device *hdev,
        return 0;
 }
 
+static void magicmouse_input_configured(struct hid_device *hdev,
+               struct hid_input *hi)
+
+{
+       struct magicmouse_sc *msc = hid_get_drvdata(hdev);
+
+       int ret = magicmouse_setup_input(msc->input, hdev);
+       if (ret) {
+               hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
+               /* clean msc->input to notify probe() of the failure */
+               msc->input = NULL;
+       }
+}
+
+
 static int magicmouse_probe(struct hid_device *hdev,
        const struct hid_device_id *id)
 {
@@ -493,15 +508,10 @@ static int magicmouse_probe(struct hid_device *hdev,
                goto err_free;
        }
 
-       /* We do this after hid-input is done parsing reports so that
-        * hid-input uses the most natural button and axis IDs.
-        */
-       if (msc->input) {
-               ret = magicmouse_setup_input(msc->input, hdev);
-               if (ret) {
-                       hid_err(hdev, "magicmouse setup input failed (%d)\n", ret);
-                       goto err_stop_hw;
-               }
+       if (!msc->input) {
+               hid_err(hdev, "magicmouse input not registered\n");
+               ret = -ENOMEM;
+               goto err_stop_hw;
        }
 
        if (id->product == USB_DEVICE_ID_APPLE_MAGICMOUSE)
@@ -568,6 +578,7 @@ static struct hid_driver magicmouse_driver = {
        .remove = magicmouse_remove,
        .raw_event = magicmouse_raw_event,
        .input_mapping = magicmouse_input_mapping,
+       .input_configured = magicmouse_input_configured,
 };
 module_hid_driver(magicmouse_driver);
 
index 7a1ebb867cf499596e9c4fe5b1a43860b86d4351..82e9211b3ca97cfec8f316d33870f22f6fac0617 100644 (file)
@@ -621,6 +621,7 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
 {
        struct mt_device *td = hid_get_drvdata(hid);
        __s32 quirks = td->mtclass.quirks;
+       struct input_dev *input = field->hidinput->input;
 
        if (hid->claimed & HID_CLAIMED_INPUT) {
                switch (usage->hid) {
@@ -670,13 +671,16 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field,
                        break;
 
                default:
+                       if (usage->type)
+                               input_event(input, usage->type, usage->code,
+                                               value);
                        return;
                }
 
                if (usage->usage_index + 1 == field->report_count) {
                        /* we only take into account the last report. */
                        if (usage->hid == td->last_slot_field)
-                               mt_complete_slot(td, field->hidinput->input);
+                               mt_complete_slot(td, input);
 
                        if (field->index == td->last_field_index
                                && td->num_received >= td->num_expected)
index e0e6abf1cd3bd9b3cfa3d7cc73a2247c84c31be4..19b8360f2330ddec85856e09605a1ce69e32d880 100644 (file)
@@ -73,6 +73,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
@@ -80,6 +81,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET },
index 41df29f59b0e5dd011f8258c228b14650a174f5f..ebbb9f4f27a3357714f9c654979d73def306c766 100644 (file)
@@ -422,6 +422,7 @@ static struct attribute *pem_input_attributes[] = {
        &sensor_dev_attr_in2_input.dev_attr.attr,
        &sensor_dev_attr_curr1_input.dev_attr.attr,
        &sensor_dev_attr_power1_input.dev_attr.attr,
+       NULL
 };
 
 static const struct attribute_group pem_input_group = {
@@ -432,6 +433,7 @@ static struct attribute *pem_fan_attributes[] = {
        &sensor_dev_attr_fan1_input.dev_attr.attr,
        &sensor_dev_attr_fan2_input.dev_attr.attr,
        &sensor_dev_attr_fan3_input.dev_attr.attr,
+       NULL
 };
 
 static const struct attribute_group pem_fan_group = {
index 668ff4721323a22842b94823d17505da6bf68b27..5cde94e56f17cf3105b9d84d5b5dd0359661821a 100644 (file)
@@ -25,7 +25,7 @@
     which contains this code, we don't worry about the wasted space.
 */
 
-#include <linux/hwmon.h>
+#include <linux/kernel.h>
 
 /* straight from the datasheet */
 #define LM75_TEMP_MIN (-55000)
index a58de38e23d821f969a720e9fe03be6aca87752a..6d6130752f942380b6fe475504c9a2f75b422f44 100644 (file)
@@ -59,7 +59,7 @@ enum chips { ltc2978, ltc3880 };
 struct ltc2978_data {
        enum chips id;
        int vin_min, vin_max;
-       int temp_min, temp_max;
+       int temp_min, temp_max[2];
        int vout_min[8], vout_max[8];
        int iout_max[2];
        int temp2_max;
@@ -113,9 +113,10 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page,
                ret = pmbus_read_word_data(client, page,
                                           LTC2978_MFR_TEMPERATURE_PEAK);
                if (ret >= 0) {
-                       if (lin11_to_val(ret) > lin11_to_val(data->temp_max))
-                               data->temp_max = ret;
-                       ret = data->temp_max;
+                       if (lin11_to_val(ret)
+                           > lin11_to_val(data->temp_max[page]))
+                               data->temp_max[page] = ret;
+                       ret = data->temp_max[page];
                }
                break;
        case PMBUS_VIRT_RESET_VOUT_HISTORY:
@@ -266,7 +267,7 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page,
                break;
        case PMBUS_VIRT_RESET_TEMP_HISTORY:
                data->temp_min = 0x7bff;
-               data->temp_max = 0x7c00;
+               data->temp_max[page] = 0x7c00;
                ret = ltc2978_clear_peaks(client, page, data->id);
                break;
        default:
@@ -323,7 +324,8 @@ static int ltc2978_probe(struct i2c_client *client,
        data->vin_min = 0x7bff;
        data->vin_max = 0x7c00;
        data->temp_min = 0x7bff;
-       data->temp_max = 0x7c00;
+       for (i = 0; i < ARRAY_SIZE(data->temp_max); i++)
+               data->temp_max[i] = 0x7c00;
        data->temp2_max = 0x7c00;
 
        switch (data->id) {
index 80eef50c50fd27f9022f3f3176ff6434ad945867..9add60920ac00ed5aa70ca0e1113887836e0ae7d 100644 (file)
@@ -766,12 +766,14 @@ static ssize_t pmbus_show_label(struct device *dev,
 static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr)
 {
        if (data->num_attributes >= data->max_attributes - 1) {
-               data->max_attributes += PMBUS_ATTR_ALLOC_SIZE;
-               data->group.attrs = krealloc(data->group.attrs,
-                                            sizeof(struct attribute *) *
-                                            data->max_attributes, GFP_KERNEL);
-               if (data->group.attrs == NULL)
+               int new_max_attrs = data->max_attributes + PMBUS_ATTR_ALLOC_SIZE;
+               void *new_attrs = krealloc(data->group.attrs,
+                                          new_max_attrs * sizeof(void *),
+                                          GFP_KERNEL);
+               if (!new_attrs)
                        return -ENOMEM;
+               data->group.attrs = new_attrs;
+               data->max_attributes = new_max_attrs;
        }
 
        data->group.attrs[data->num_attributes++] = attr;
index 46cde098c11c2fe993dea722f1dd37d0ec3c7498..e380c6eef3af6500edc94b3a8db668bb59dfa258 100644 (file)
@@ -4,7 +4,6 @@
 
 menuconfig I2C
        tristate "I2C support"
-       depends on !S390
        select RT_MUTEXES
        ---help---
          I2C (pronounce: I-squared-C) is a slow serial bus protocol used in
@@ -76,6 +75,7 @@ config I2C_HELPER_AUTO
 
 config I2C_SMBUS
        tristate "SMBus-specific protocols" if !I2C_HELPER_AUTO
+       depends on GENERIC_HARDIRQS
        help
          Say Y here if you want support for SMBus extensions to the I2C
          specification. At the moment, the only supported extension is
index a3725de923848baba3c55f3067588f42759b5227..adfee98486b159843b38ff107c8ea9dd25189ed5 100644 (file)
@@ -114,7 +114,7 @@ config I2C_I801
 
 config I2C_ISCH
        tristate "Intel SCH SMBus 1.0"
-       depends on PCI
+       depends on PCI && GENERIC_HARDIRQS
        select LPC_SCH
        help
          Say Y here if you want to use SMBus controller on the Intel SCH
@@ -543,6 +543,7 @@ config I2C_NUC900
 
 config I2C_OCORES
        tristate "OpenCores I2C Controller"
+       depends on GENERIC_HARDIRQS
        help
          If you say yes to this option, support will be included for the
          OpenCores I2C controller. For details see
@@ -777,7 +778,7 @@ config I2C_DIOLAN_U2C
 
 config I2C_PARPORT
        tristate "Parallel port adapter"
-       depends on PARPORT
+       depends on PARPORT && GENERIC_HARDIRQS
        select I2C_ALGOBIT
        select I2C_SMBUS
        help
@@ -802,6 +803,7 @@ config I2C_PARPORT
 
 config I2C_PARPORT_LIGHT
        tristate "Parallel port adapter (light)"
+       depends on GENERIC_HARDIRQS
        select I2C_ALGOBIT
        select I2C_SMBUS
        help
index 0ceb6e1b0f6595fb0ca006bec70a3501bcd83594..e3085c487ace5943650e79ae7ffdde03d0ffcfb9 100644 (file)
@@ -182,7 +182,6 @@ static int dw_i2c_probe(struct platform_device *pdev)
        adap->algo = &i2c_dw_algo;
        adap->dev.parent = &pdev->dev;
        adap->dev.of_node = pdev->dev.of_node;
-       ACPI_HANDLE_SET(&adap->dev, ACPI_HANDLE(&pdev->dev));
 
        r = i2c_add_numbered_adapter(adap);
        if (r) {
index e9205ee8cf94cb5a822635346df8451e5d5155bc..130f02cc9d94a233eacce7857214d34278141939 100644 (file)
@@ -80,6 +80,7 @@
 /* PCI DIDs for the Intel SMBus Message Transport (SMT) Devices */
 #define PCI_DEVICE_ID_INTEL_S1200_SMT0 0x0c59
 #define PCI_DEVICE_ID_INTEL_S1200_SMT1 0x0c5a
+#define PCI_DEVICE_ID_INTEL_AVOTON_SMT 0x1f15
 
 #define ISMT_DESC_ENTRIES      32      /* number of descriptor entries */
 #define ISMT_MAX_RETRIES       3       /* number of SMBus retries to attempt */
@@ -185,6 +186,7 @@ struct ismt_priv {
 static const DEFINE_PCI_DEVICE_TABLE(ismt_ids) = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT0) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT1) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMT) },
        { 0, }
 };
 
index 36704e3ab3fa9a87cdd9ca53e825f80792c28732..b714776b6ddd1828258ee1a81d33728d1aba3c75 100644 (file)
@@ -411,7 +411,11 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
        int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE;
        u32 clk_divisor;
 
-       tegra_i2c_clock_enable(i2c_dev);
+       err = tegra_i2c_clock_enable(i2c_dev);
+       if (err < 0) {
+               dev_err(i2c_dev->dev, "Clock enable failed %d\n", err);
+               return err;
+       }
 
        tegra_periph_reset_assert(i2c_dev->div_clk);
        udelay(2);
@@ -628,7 +632,12 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
        if (i2c_dev->is_suspended)
                return -EBUSY;
 
-       tegra_i2c_clock_enable(i2c_dev);
+       ret = tegra_i2c_clock_enable(i2c_dev);
+       if (ret < 0) {
+               dev_err(i2c_dev->dev, "Clock enable failed %d\n", ret);
+               return ret;
+       }
+
        for (i = 0; i < num; i++) {
                enum msg_end_type end_type = MSG_END_STOP;
                if (i < (num - 1)) {
index f3b8f9a6a89b65eb29050c591e181b908d0358f3..966a18a5d12d2397d2a43f25bcd22a65420cc5e4 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (c) 2010 Ericsson AB.
  *
- * Author: Guenter Roeck <guenter.roeck@ericsson.com>
+ * Author: Guenter Roeck <linux@roeck-us.net>
  *
  * Derived from:
  *  pca954x.c
index 0198324a8b0cf87c5f6b1f84f31b0b8f7b9070eb..bd33473f8e38afd4deeeb243f12c2bf981587740 100644 (file)
@@ -62,7 +62,7 @@ st_sensors_match_odr_error:
 int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr)
 {
        int err;
-       struct st_sensor_odr_avl odr_out;
+       struct st_sensor_odr_avl odr_out = {0, 0};
        struct st_sensor_data *sdata = iio_priv(indio_dev);
 
        err = st_sensors_match_odr(sdata->sensor, odr, &odr_out);
@@ -114,7 +114,7 @@ st_sensors_match_odr_error:
 
 static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs)
 {
-       int err, i;
+       int err, i = 0;
        struct st_sensor_data *sdata = iio_priv(indio_dev);
 
        err = st_sensors_match_fs(sdata->sensor, fs, &i);
@@ -139,14 +139,13 @@ st_accel_set_fullscale_error:
 
 int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable)
 {
-       bool found;
        u8 tmp_value;
        int err = -EINVAL;
-       struct st_sensor_odr_avl odr_out;
+       bool found = false;
+       struct st_sensor_odr_avl odr_out = {0, 0};
        struct st_sensor_data *sdata = iio_priv(indio_dev);
 
        if (enable) {
-               found = false;
                tmp_value = sdata->sensor->pw.value_on;
                if ((sdata->sensor->odr.addr == sdata->sensor->pw.addr) &&
                        (sdata->sensor->odr.mask == sdata->sensor->pw.mask)) {
index 2fe1d4edcb2f2b93fdc21b30fdb777d9d4bc923b..74f2d52795f6e6c44fe49025b49adbe13f33fc39 100644 (file)
@@ -27,7 +27,6 @@
 #define AD5064_ADDR(x)                         ((x) << 20)
 #define AD5064_CMD(x)                          ((x) << 24)
 
-#define AD5064_ADDR_DAC(chan)                  (chan)
 #define AD5064_ADDR_ALL_DAC                    0xF
 
 #define AD5064_CMD_WRITE_INPUT_N               0x0
@@ -131,15 +130,15 @@ static int ad5064_write(struct ad5064_state *st, unsigned int cmd,
 }
 
 static int ad5064_sync_powerdown_mode(struct ad5064_state *st,
-       unsigned int channel)
+       const struct iio_chan_spec *chan)
 {
        unsigned int val;
        int ret;
 
-       val = (0x1 << channel);
+       val = (0x1 << chan->address);
 
-       if (st->pwr_down[channel])
-               val |= st->pwr_down_mode[channel] << 8;
+       if (st->pwr_down[chan->channel])
+               val |= st->pwr_down_mode[chan->channel] << 8;
 
        ret = ad5064_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0);
 
@@ -169,7 +168,7 @@ static int ad5064_set_powerdown_mode(struct iio_dev *indio_dev,
        mutex_lock(&indio_dev->mlock);
        st->pwr_down_mode[chan->channel] = mode + 1;
 
-       ret = ad5064_sync_powerdown_mode(st, chan->channel);
+       ret = ad5064_sync_powerdown_mode(st, chan);
        mutex_unlock(&indio_dev->mlock);
 
        return ret;
@@ -205,7 +204,7 @@ static ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev,
        mutex_lock(&indio_dev->mlock);
        st->pwr_down[chan->channel] = pwr_down;
 
-       ret = ad5064_sync_powerdown_mode(st, chan->channel);
+       ret = ad5064_sync_powerdown_mode(st, chan);
        mutex_unlock(&indio_dev->mlock);
        return ret ? ret : len;
 }
@@ -258,7 +257,7 @@ static int ad5064_write_raw(struct iio_dev *indio_dev,
 
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               if (val > (1 << chan->scan_type.realbits) || val < 0)
+               if (val >= (1 << chan->scan_type.realbits) || val < 0)
                        return -EINVAL;
 
                mutex_lock(&indio_dev->mlock);
@@ -292,34 +291,44 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
        { },
 };
 
-#define AD5064_CHANNEL(chan, bits) {                           \
+#define AD5064_CHANNEL(chan, addr, bits) {                     \
        .type = IIO_VOLTAGE,                                    \
        .indexed = 1,                                           \
        .output = 1,                                            \
        .channel = (chan),                                      \
        .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT |           \
        IIO_CHAN_INFO_SCALE_SEPARATE_BIT,                       \
-       .address = AD5064_ADDR_DAC(chan),                       \
+       .address = addr,                                        \
        .scan_type = IIO_ST('u', (bits), 16, 20 - (bits)),      \
        .ext_info = ad5064_ext_info,                            \
 }
 
 #define DECLARE_AD5064_CHANNELS(name, bits) \
 const struct iio_chan_spec name[] = { \
-       AD5064_CHANNEL(0, bits), \
-       AD5064_CHANNEL(1, bits), \
-       AD5064_CHANNEL(2, bits), \
-       AD5064_CHANNEL(3, bits), \
-       AD5064_CHANNEL(4, bits), \
-       AD5064_CHANNEL(5, bits), \
-       AD5064_CHANNEL(6, bits), \
-       AD5064_CHANNEL(7, bits), \
+       AD5064_CHANNEL(0, 0, bits), \
+       AD5064_CHANNEL(1, 1, bits), \
+       AD5064_CHANNEL(2, 2, bits), \
+       AD5064_CHANNEL(3, 3, bits), \
+       AD5064_CHANNEL(4, 4, bits), \
+       AD5064_CHANNEL(5, 5, bits), \
+       AD5064_CHANNEL(6, 6, bits), \
+       AD5064_CHANNEL(7, 7, bits), \
+}
+
+#define DECLARE_AD5065_CHANNELS(name, bits) \
+const struct iio_chan_spec name[] = { \
+       AD5064_CHANNEL(0, 0, bits), \
+       AD5064_CHANNEL(1, 3, bits), \
 }
 
 static DECLARE_AD5064_CHANNELS(ad5024_channels, 12);
 static DECLARE_AD5064_CHANNELS(ad5044_channels, 14);
 static DECLARE_AD5064_CHANNELS(ad5064_channels, 16);
 
+static DECLARE_AD5065_CHANNELS(ad5025_channels, 12);
+static DECLARE_AD5065_CHANNELS(ad5045_channels, 14);
+static DECLARE_AD5065_CHANNELS(ad5065_channels, 16);
+
 static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
        [ID_AD5024] = {
                .shared_vref = false,
@@ -328,7 +337,7 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
        },
        [ID_AD5025] = {
                .shared_vref = false,
-               .channels = ad5024_channels,
+               .channels = ad5025_channels,
                .num_channels = 2,
        },
        [ID_AD5044] = {
@@ -338,7 +347,7 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
        },
        [ID_AD5045] = {
                .shared_vref = false,
-               .channels = ad5044_channels,
+               .channels = ad5045_channels,
                .num_channels = 2,
        },
        [ID_AD5064] = {
@@ -353,7 +362,7 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
        },
        [ID_AD5065] = {
                .shared_vref = false,
-               .channels = ad5064_channels,
+               .channels = ad5065_channels,
                .num_channels = 2,
        },
        [ID_AD5628_1] = {
@@ -429,6 +438,7 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type,
 {
        struct iio_dev *indio_dev;
        struct ad5064_state *st;
+       unsigned int midscale;
        unsigned int i;
        int ret;
 
@@ -465,11 +475,6 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type,
                        goto error_free_reg;
        }
 
-       for (i = 0; i < st->chip_info->num_channels; ++i) {
-               st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K;
-               st->dac_cache[i] = 0x8000;
-       }
-
        indio_dev->dev.parent = dev;
        indio_dev->name = name;
        indio_dev->info = &ad5064_info;
@@ -477,6 +482,13 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type,
        indio_dev->channels = st->chip_info->channels;
        indio_dev->num_channels = st->chip_info->num_channels;
 
+       midscale = (1 << indio_dev->channels[0].scan_type.realbits) /  2;
+
+       for (i = 0; i < st->chip_info->num_channels; ++i) {
+               st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K;
+               st->dac_cache[i] = midscale;
+       }
+
        ret = iio_device_register(indio_dev);
        if (ret)
                goto error_disable_reg;
index b5cfa3a354cfe5e98ad9dd7b664adbaff10a00f9..361b2328453d478cd5ba945e91b9c242310b6119 100644 (file)
@@ -5,6 +5,7 @@
 config INV_MPU6050_IIO
        tristate "Invensense MPU6050 devices"
        depends on I2C && SYSFS
+       select IIO_BUFFER
        select IIO_TRIGGERED_BUFFER
        help
          This driver supports the Invensense MPU6050 devices.
index 565bfb161c1a7d34098cb1c6ef7919aebe38f382..a3fde52840ca29b5c046e11533a86b2dcdad67b3 100644 (file)
@@ -1575,6 +1575,12 @@ static int c4iw_reconnect(struct c4iw_ep *ep)
 
        neigh = dst_neigh_lookup(ep->dst,
                        &ep->com.cm_id->remote_addr.sin_addr.s_addr);
+       if (!neigh) {
+               pr_err("%s - cannot alloc neigh.\n", __func__);
+               err = -ENOMEM;
+               goto fail4;
+       }
+
        /* get a l2t entry */
        if (neigh->dev->flags & IFF_LOOPBACK) {
                PDBG("%s LOOPBACK\n", __func__);
@@ -3053,6 +3059,12 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb)
        dst = &rt->dst;
        neigh = dst_neigh_lookup_skb(dst, skb);
 
+       if (!neigh) {
+               pr_err("%s - failed to allocate neigh!\n",
+                      __func__);
+               goto free_dst;
+       }
+
        if (neigh->dev->flags & IFF_LOOPBACK) {
                pdev = ip_dev_find(&init_net, iph->daddr);
                e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh,
index 17ba4f8bc12d0b19ec7d380dc6677796d79f12de..70b1808a08f4d12bf9d1668cb5bae06d1cd2e202 100644 (file)
@@ -186,8 +186,10 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq,
        wq->rq.queue = dma_alloc_coherent(&(rdev->lldi.pdev->dev),
                                          wq->rq.memsize, &(wq->rq.dma_addr),
                                          GFP_KERNEL);
-       if (!wq->rq.queue)
+       if (!wq->rq.queue) {
+               ret = -ENOMEM;
                goto free_sq;
+       }
        PDBG("%s sq base va 0x%p pa 0x%llx rq base va 0x%p pa 0x%llx\n",
                __func__, wq->sq.queue,
                (unsigned long long)virt_to_phys(wq->sq.queue),
index 439c35d4a669978aba8820151f2f6c98f5a47558..ea93870266eb7fda30ddf502b5d233fb1116423b 100644 (file)
@@ -620,7 +620,7 @@ void ipath_ib_rcv(struct ipath_ibdev *dev, void *rhdr, void *data,
                goto bail;
        }
 
-       opcode = be32_to_cpu(ohdr->bth[0]) >> 24;
+       opcode = (be32_to_cpu(ohdr->bth[0]) >> 24) & 0x7f;
        dev->opstats[opcode].n_bytes += tlen;
        dev->opstats[opcode].n_packets++;
 
index e0d79b2395e4f859f51c51e9c314f9306834f123..add98d01476c1307629bd813d341bac6d34c9a76 100644 (file)
@@ -362,7 +362,6 @@ void mlx4_ib_cm_paravirt_init(struct mlx4_ib_dev *dev)
        INIT_LIST_HEAD(&dev->sriov.cm_list);
        dev->sriov.sl_id_map = RB_ROOT;
        idr_init(&dev->sriov.pv_id_table);
-       idr_pre_get(&dev->sriov.pv_id_table, GFP_KERNEL);
 }
 
 /* slave = -1 ==> all slaves */
index 8349f9c5064c042d568cf56619b76dd391410402..1e603a375069022bfed295f071f8c729b4ad826b 100644 (file)
@@ -1,7 +1,7 @@
 config INFINIBAND_QIB
-       tristate "QLogic PCIe HCA support"
+       tristate "Intel PCIe HCA support"
        depends on 64BIT
        ---help---
-       This is a low-level driver for QLogic PCIe QLE InfiniBand host
-       channel adapters.  This driver does not support the QLogic
+       This is a low-level driver for Intel PCIe QLE InfiniBand host
+       channel adapters.  This driver does not support the Intel
        HyperTransport card (model QHT7140).
index 5423edcab51f4404905e47674957cb32e5f33b9f..216092477dfcf7eb4a51187ffe825110c5eb3286 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2013 Intel Corporation. All rights reserved.
  * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
@@ -63,8 +64,8 @@ MODULE_PARM_DESC(compat_ddr_negotiate,
                 "Attempt pre-IBTA 1.2 DDR speed negotiation");
 
 MODULE_LICENSE("Dual BSD/GPL");
-MODULE_AUTHOR("QLogic <support@qlogic.com>");
-MODULE_DESCRIPTION("QLogic IB driver");
+MODULE_AUTHOR("Intel <ibsupport@intel.com>");
+MODULE_DESCRIPTION("Intel IB driver");
 MODULE_VERSION(QIB_DRIVER_VERSION);
 
 /*
index a099ac171e226f1073f4a70ccb680e669b2ff048..0232ae56b1fa2b185e1a551e074e5d256f15c087 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2013 Intel Corporation. All rights reserved.
  * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation.
  * All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
@@ -51,7 +52,7 @@ static u32 qib_6120_iblink_state(u64);
 
 /*
  * This file contains all the chip-specific register information and
- * access functions for the QLogic QLogic_IB PCI-Express chip.
+ * access functions for the Intel Intel_IB PCI-Express chip.
  *
  */
 
index 50e33aa0b4e39628c5de95e314d57de68bbc4be5..173f805790da4522f3f4a8881b8b2df5883b9b4b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2012, 2013 Intel Corporation.  All rights reserved.
  * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
@@ -1138,7 +1138,7 @@ void qib_disable_after_error(struct qib_devdata *dd)
 static void qib_remove_one(struct pci_dev *);
 static int qib_init_one(struct pci_dev *, const struct pci_device_id *);
 
-#define DRIVER_LOAD_MSG "QLogic " QIB_DRV_NAME " loaded: "
+#define DRIVER_LOAD_MSG "Intel " QIB_DRV_NAME " loaded: "
 #define PFX QIB_DRV_NAME ": "
 
 static DEFINE_PCI_DEVICE_TABLE(qib_pci_tbl) = {
@@ -1355,7 +1355,7 @@ static int qib_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                dd = qib_init_iba6120_funcs(pdev, ent);
 #else
                qib_early_err(&pdev->dev,
-                       "QLogic PCIE device 0x%x cannot work if CONFIG_PCI_MSI is not enabled\n",
+                       "Intel PCIE device 0x%x cannot work if CONFIG_PCI_MSI is not enabled\n",
                        ent->device);
                dd = ERR_PTR(-ENODEV);
 #endif
@@ -1371,7 +1371,7 @@ static int qib_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        default:
                qib_early_err(&pdev->dev,
-                       "Failing on unknown QLogic deviceid 0x%x\n",
+                       "Failing on unknown Intel deviceid 0x%x\n",
                        ent->device);
                ret = -ENODEV;
        }
index 50a8a0d4fe676f5467c677d66a4985170900059d..911205d3d5a0bf255fae65126740ab47eaa4a8ef 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Intel Corporation. All rights reserved.
+ * Copyright (c) 2013 Intel Corporation. All rights reserved.
  * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved.
  * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved.
  *
index ba51a4715a1dcdd5963261d84497dc1e6974c070..7c0ab16a2fe230fc31b44fd43b04f3e92d2a26b8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2012, 2013 Intel Corporation.  All rights reserved.
  * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved.
  * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved.
  *
@@ -2224,7 +2224,7 @@ int qib_register_ib_device(struct qib_devdata *dd)
        ibdev->dma_ops = &qib_dma_mapping_ops;
 
        snprintf(ibdev->node_desc, sizeof(ibdev->node_desc),
-                "QLogic Infiniband HCA %s", init_utsname()->nodename);
+                "Intel Infiniband HCA %s", init_utsname()->nodename);
 
        ret = ib_register_device(ibdev, qib_create_port_files);
        if (ret)
index 67b0c1d23678d26565981cf9815993027c0a1b5e..1ef880de3a41d97fe328951069f3b6c30066daf1 100644 (file)
@@ -758,9 +758,13 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_
                if (++priv->tx_outstanding == ipoib_sendq_size) {
                        ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n",
                                  tx->qp->qp_num);
-                       if (ib_req_notify_cq(priv->send_cq, IB_CQ_NEXT_COMP))
-                               ipoib_warn(priv, "request notify on send CQ failed\n");
                        netif_stop_queue(dev);
+                       rc = ib_req_notify_cq(priv->send_cq,
+                               IB_CQ_NEXT_COMP | IB_CQ_REPORT_MISSED_EVENTS);
+                       if (rc < 0)
+                               ipoib_warn(priv, "request notify on send CQ failed\n");
+                       else if (rc)
+                               ipoib_send_comp_handler(priv->send_cq, dev);
                }
        }
 }
index 7cd74e29cbc87a6495277ecd74d7135ebcd75ad3..9135606c86496511919a5238898aa98cf1c74996 100644 (file)
@@ -158,14 +158,10 @@ static unsigned int get_time_pit(void)
 #define GET_TIME(x)    rdtscl(x)
 #define DELTA(x,y)     ((y)-(x))
 #define TIME_NAME      "TSC"
-#elif defined(__alpha__)
+#elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_TILE)
 #define GET_TIME(x)    do { x = get_cycles(); } while (0)
 #define DELTA(x,y)     ((y)-(x))
-#define TIME_NAME      "PCC"
-#elif defined(CONFIG_MN10300) || defined(CONFIG_TILE)
-#define GET_TIME(x)    do { x = get_cycles(); } while (0)
-#define DELTA(x, y)    ((x) - (y))
-#define TIME_NAME      "TSC"
+#define TIME_NAME      "get_cycles"
 #else
 #define FAKE_TIME
 static unsigned long analog_faketime = 0;
index 2fb0d76a04c4f06d072a45765349406c2d2810f7..208de7cbb7fae2460dac5576c69f5847165ac3c9 100644 (file)
@@ -70,8 +70,6 @@
 #define TC3589x_EVT_INT_CLR    0x2
 #define TC3589x_KBD_INT_CLR    0x1
 
-#define TC3589x_KBD_KEYMAP_SIZE     64
-
 /**
  * struct tc_keypad - data structure used by keypad driver
  * @tc3589x:    pointer to tc35893
@@ -88,7 +86,7 @@ struct tc_keypad {
        const struct tc3589x_keypad_platform_data *board;
        unsigned int krow;
        unsigned int kcol;
-       unsigned short keymap[TC3589x_KBD_KEYMAP_SIZE];
+       unsigned short *keymap;
        bool keypad_stopped;
 };
 
@@ -338,12 +336,14 @@ static int tc3589x_keypad_probe(struct platform_device *pdev)
 
        error = matrix_keypad_build_keymap(plat->keymap_data, NULL,
                                           TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL,
-                                          keypad->keymap, input);
+                                          NULL, input);
        if (error) {
                dev_err(&pdev->dev, "Failed to build keymap\n");
                goto err_free_mem;
        }
 
+       keypad->keymap = input->keycode;
+
        input_set_capability(input, EV_MSC, MSC_SCAN);
        if (!plat->no_autorepeat)
                __set_bit(EV_REP, input->evbit);
index 7b99fc7c9438dbcbcc115248403e4b9704611f29..0238e0e143350a3254e07bf0f73e035e2b3cef57 100644 (file)
@@ -490,6 +490,29 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p)
        f->y_map |= (p[5] & 0x20) << 6;
 }
 
+static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p)
+{
+       f->first_mp = !!(p[0] & 0x02);
+       f->is_mp = !!(p[0] & 0x20);
+
+       f->fingers = ((p[0] & 0x6) >> 1 |
+                    (p[0] & 0x10) >> 2);
+       f->x_map = ((p[2] & 0x60) >> 5) |
+                  ((p[4] & 0x7f) << 2) |
+                  ((p[5] & 0x7f) << 9) |
+                  ((p[3] & 0x07) << 16) |
+                  ((p[3] & 0x70) << 15) |
+                  ((p[0] & 0x01) << 22);
+       f->y_map = (p[1] & 0x7f) |
+                  ((p[2] & 0x1f) << 7);
+
+       f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7));
+       f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3));
+       f->z = (p[0] & 4) ? 0 : p[5] & 0x7f;
+
+       alps_decode_buttons_v3(f, p);
+}
+
 static void alps_process_touchpad_packet_v3(struct psmouse *psmouse)
 {
        struct alps_data *priv = psmouse->private;
@@ -874,7 +897,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse)
        }
 
        /* Bytes 2 - pktsize should have 0 in the highest bit */
-       if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
+       if (priv->proto_version != ALPS_PROTO_V5 &&
+           psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize &&
            (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) {
                psmouse_dbg(psmouse, "refusing packet[%i] = %x\n",
                            psmouse->pktcnt - 1,
@@ -994,8 +1018,7 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command,
        return 0;
 }
 
-static int alps_enter_command_mode(struct psmouse *psmouse,
-                                  unsigned char *resp)
+static int alps_enter_command_mode(struct psmouse *psmouse)
 {
        unsigned char param[4];
 
@@ -1004,14 +1027,12 @@ static int alps_enter_command_mode(struct psmouse *psmouse,
                return -1;
        }
 
-       if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) {
+       if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) &&
+           param[0] != 0x73) {
                psmouse_dbg(psmouse,
                            "unknown response while entering command mode\n");
                return -1;
        }
-
-       if (resp)
-               *resp = param[2];
        return 0;
 }
 
@@ -1176,7 +1197,7 @@ static int alps_passthrough_mode_v3(struct psmouse *psmouse,
 {
        int reg_val, ret = -1;
 
-       if (alps_enter_command_mode(psmouse, NULL))
+       if (alps_enter_command_mode(psmouse))
                return -1;
 
        reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008);
@@ -1216,7 +1237,7 @@ static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base)
 {
        int ret = -EIO, reg_val;
 
-       if (alps_enter_command_mode(psmouse, NULL))
+       if (alps_enter_command_mode(psmouse))
                goto error;
 
        reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08);
@@ -1279,7 +1300,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base)
                 * supported by this driver. If bit 1 isn't set the packet
                 * format is different.
                 */
-               if (alps_enter_command_mode(psmouse, NULL) ||
+               if (alps_enter_command_mode(psmouse) ||
                    alps_command_mode_write_reg(psmouse,
                                                reg_base + 0x08, 0x82) ||
                    alps_exit_command_mode(psmouse))
@@ -1306,7 +1327,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse)
            alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO)
                goto error;
 
-       if (alps_enter_command_mode(psmouse, NULL) ||
+       if (alps_enter_command_mode(psmouse) ||
            alps_absolute_mode_v3(psmouse)) {
                psmouse_err(psmouse, "Failed to enter absolute mode\n");
                goto error;
@@ -1381,7 +1402,7 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse)
                        priv->flags &= ~ALPS_DUALPOINT;
        }
 
-       if (alps_enter_command_mode(psmouse, NULL) ||
+       if (alps_enter_command_mode(psmouse) ||
            alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 ||
            alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00))
                goto error;
@@ -1431,7 +1452,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse)
        struct ps2dev *ps2dev = &psmouse->ps2dev;
        unsigned char param[4];
 
-       if (alps_enter_command_mode(psmouse, NULL))
+       if (alps_enter_command_mode(psmouse))
                goto error;
 
        if (alps_absolute_mode_v4(psmouse)) {
@@ -1499,6 +1520,23 @@ error:
        return -1;
 }
 
+static int alps_hw_init_dolphin_v1(struct psmouse *psmouse)
+{
+       struct ps2dev *ps2dev = &psmouse->ps2dev;
+       unsigned char param[2];
+
+       /* This is dolphin "v1" as empirically defined by florin9doi */
+       param[0] = 0x64;
+       param[1] = 0x28;
+
+       if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) ||
+           ps2_command(ps2dev, &param[0], PSMOUSE_CMD_SETRATE) ||
+           ps2_command(ps2dev, &param[1], PSMOUSE_CMD_SETRATE))
+               return -1;
+
+       return 0;
+}
+
 static void alps_set_defaults(struct alps_data *priv)
 {
        priv->byte0 = 0x8f;
@@ -1532,6 +1570,21 @@ static void alps_set_defaults(struct alps_data *priv)
                priv->nibble_commands = alps_v4_nibble_commands;
                priv->addr_command = PSMOUSE_CMD_DISABLE;
                break;
+       case ALPS_PROTO_V5:
+               priv->hw_init = alps_hw_init_dolphin_v1;
+               priv->process_packet = alps_process_packet_v3;
+               priv->decode_fields = alps_decode_dolphin;
+               priv->set_abs_params = alps_set_abs_params_mt;
+               priv->nibble_commands = alps_v3_nibble_commands;
+               priv->addr_command = PSMOUSE_CMD_RESET_WRAP;
+               priv->byte0 = 0xc8;
+               priv->mask0 = 0xc8;
+               priv->flags = 0;
+               priv->x_max = 1360;
+               priv->y_max = 660;
+               priv->x_bits = 23;
+               priv->y_bits = 12;
+               break;
        }
 }
 
@@ -1591,6 +1644,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv)
                return -EIO;
 
        if (alps_match_table(psmouse, priv, e7, ec) == 0) {
+               return 0;
+       } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 &&
+                  ec[0] == 0x73 && ec[1] == 0x01) {
+               priv->proto_version = ALPS_PROTO_V5;
+               alps_set_defaults(priv);
+
                return 0;
        } else if (ec[0] == 0x88 && ec[1] == 0x08) {
                priv->proto_version = ALPS_PROTO_V3;
index 970480551b6e67e540fdb76b2865e8dd573d550a..eee59853b9ce0c21bc755c206430911e15789964 100644 (file)
@@ -16,6 +16,7 @@
 #define ALPS_PROTO_V2  2
 #define ALPS_PROTO_V3  3
 #define ALPS_PROTO_V4  4
+#define ALPS_PROTO_V5  5
 
 /**
  * struct alps_model_info - touchpad ID table
index 1673dc6c8092b9697e95d2c5dc4beeffa92852f6..f51765fff0545e91be567942255cf19532f94a71 100644 (file)
@@ -236,6 +236,13 @@ static int cypress_read_fw_version(struct psmouse *psmouse)
        cytp->fw_version = param[2] & FW_VERSION_MASX;
        cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0;
 
+       /*
+        * Trackpad fw_version 11 (in Dell XPS12) yields a bogus response to
+        * CYTP_CMD_READ_TP_METRICS so do not try to use it. LP: #1103594.
+        */
+       if (cytp->fw_version >= 11)
+               cytp->tp_metrics_supported = 0;
+
        psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version);
        psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n",
                 cytp->tp_metrics_supported);
@@ -258,6 +265,9 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse)
        cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width;
        cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high;
 
+       if (!cytp->tp_metrics_supported)
+               return 0;
+
        memset(param, 0, sizeof(param));
        if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) {
                /* Update trackpad parameters. */
@@ -315,18 +325,15 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse)
 
 static int cypress_query_hardware(struct psmouse *psmouse)
 {
-       struct cytp_data *cytp = psmouse->private;
        int ret;
 
        ret = cypress_read_fw_version(psmouse);
        if (ret)
                return ret;
 
-       if (cytp->tp_metrics_supported) {
-               ret = cypress_read_tp_metrics(psmouse);
-               if (ret)
-                       return ret;
-       }
+       ret = cypress_read_tp_metrics(psmouse);
+       if (ret)
+               return ret;
 
        return 0;
 }
index 41b6fbf601122b26500c397d24e34f9789286f81..1daa97913b7d20068845865a405387404fffe1d8 100644 (file)
@@ -2017,6 +2017,9 @@ static const struct wacom_features wacom_features_0x100 =
 static const struct wacom_features wacom_features_0x101 =
        { "Wacom ISDv4 101",      WACOM_PKGLEN_MTTPC,     26202, 16325,  255,
          0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0x10D =
+       { "Wacom ISDv4 10D",      WACOM_PKGLEN_MTTPC,     26202, 16325,  255,
+         0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x4001 =
        { "Wacom ISDv4 4001",      WACOM_PKGLEN_MTTPC,     26202, 16325,  255,
          0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
@@ -2201,6 +2204,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xEF) },
        { USB_DEVICE_WACOM(0x100) },
        { USB_DEVICE_WACOM(0x101) },
+       { USB_DEVICE_WACOM(0x10D) },
        { USB_DEVICE_WACOM(0x4001) },
        { USB_DEVICE_WACOM(0x47) },
        { USB_DEVICE_WACOM(0xF4) },
index 4f702b3ec1a3f1f9e4210d4e666c5be1beea8801..434c3df250caa3bc0a058a890e6b64f9bd78b450 100644 (file)
@@ -236,7 +236,12 @@ static void __ads7846_disable(struct ads7846 *ts)
 /* Must be called with ts->lock held */
 static void __ads7846_enable(struct ads7846 *ts)
 {
-       regulator_enable(ts->reg);
+       int error;
+
+       error = regulator_enable(ts->reg);
+       if (error != 0)
+               dev_err(&ts->spi->dev, "Failed to enable supply: %d\n", error);
+
        ads7846_restart(ts);
 }
 
index 4a29ddf6bf1e9a9bfed9a1afcc8cba810e66800c..1443532fe6c4d112f15a317d598ddc4f4dc78fb5 100644 (file)
@@ -314,15 +314,27 @@ static int mms114_start(struct mms114_data *data)
        struct i2c_client *client = data->client;
        int error;
 
-       if (data->core_reg)
-               regulator_enable(data->core_reg);
-       if (data->io_reg)
-               regulator_enable(data->io_reg);
+       error = regulator_enable(data->core_reg);
+       if (error) {
+               dev_err(&client->dev, "Failed to enable avdd: %d\n", error);
+               return error;
+       }
+
+       error = regulator_enable(data->io_reg);
+       if (error) {
+               dev_err(&client->dev, "Failed to enable vdd: %d\n", error);
+               regulator_disable(data->core_reg);
+               return error;
+       }
+
        mdelay(MMS114_POWERON_DELAY);
 
        error = mms114_setup_regs(data);
-       if (error < 0)
+       if (error < 0) {
+               regulator_disable(data->io_reg);
+               regulator_disable(data->core_reg);
                return error;
+       }
 
        if (data->pdata->cfg_pin)
                data->pdata->cfg_pin(true);
@@ -335,16 +347,20 @@ static int mms114_start(struct mms114_data *data)
 static void mms114_stop(struct mms114_data *data)
 {
        struct i2c_client *client = data->client;
+       int error;
 
        disable_irq(client->irq);
 
        if (data->pdata->cfg_pin)
                data->pdata->cfg_pin(false);
 
-       if (data->io_reg)
-               regulator_disable(data->io_reg);
-       if (data->core_reg)
-               regulator_disable(data->core_reg);
+       error = regulator_disable(data->io_reg);
+       if (error)
+               dev_warn(&client->dev, "Failed to disable vdd: %d\n", error);
+
+       error = regulator_disable(data->core_reg);
+       if (error)
+               dev_warn(&client->dev, "Failed to disable avdd: %d\n", error);
 }
 
 static int mms114_input_open(struct input_dev *dev)
index 5c514d0711d1b57669b6acee551400bf88d44265..c332fb98480d28e42739e9b674b7b99ce8be427d 100644 (file)
@@ -130,7 +130,7 @@ config IRQ_REMAP
 # OMAP IOMMU support
 config OMAP_IOMMU
        bool "OMAP IOMMU Support"
-       depends on ARCH_OMAP
+       depends on ARCH_OMAP2PLUS
        select IOMMU_API
 
 config OMAP_IOVMM
index 98f555dafb55c8edc32393919ee48140d024b184..b287ca33833df792350baad6f82fefbe1494e038 100644 (file)
@@ -2466,18 +2466,16 @@ static int device_change_notifier(struct notifier_block *nb,
 
                /* allocate a protection domain if a device is added */
                dma_domain = find_protection_domain(devid);
-               if (dma_domain)
-                       goto out;
-               dma_domain = dma_ops_domain_alloc();
-               if (!dma_domain)
-                       goto out;
-               dma_domain->target_dev = devid;
-
-               spin_lock_irqsave(&iommu_pd_list_lock, flags);
-               list_add_tail(&dma_domain->list, &iommu_pd_list);
-               spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
-
-               dev_data = get_dev_data(dev);
+               if (!dma_domain) {
+                       dma_domain = dma_ops_domain_alloc();
+                       if (!dma_domain)
+                               goto out;
+                       dma_domain->target_dev = devid;
+
+                       spin_lock_irqsave(&iommu_pd_list_lock, flags);
+                       list_add_tail(&dma_domain->list, &iommu_pd_list);
+                       spin_unlock_irqrestore(&iommu_pd_list_lock, flags);
+               }
 
                dev->archdata.dma_ops = &amd_iommu_dma_ops;
 
index b6ecddb63cd0fc9397ccf24e0951dbf13ea9a719..e3c2d74b7684596790fd0293461dc74922a850ba 100644 (file)
@@ -980,7 +980,7 @@ static void __init free_iommu_all(void)
  *     BIOS should disable L2B micellaneous clock gating by setting
  *     L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b
  */
-static void __init amd_iommu_erratum_746_workaround(struct amd_iommu *iommu)
+static void amd_iommu_erratum_746_workaround(struct amd_iommu *iommu)
 {
        u32 value;
 
index d56f8c17c5fe4dcc2e4db23085d4914b977c0fd0..7c11ff368d07f88dc357dd3f6e22c9fbe2ed6cc1 100644 (file)
@@ -2,7 +2,6 @@
 #include <linux/cpumask.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/cpumask.h>
 #include <linux/errno.h>
 #include <linux/msi.h>
 #include <linux/irq.h>
index a350969e5efe4254c65b7ed7841609bebb1b0102..4a33351c25dce61c805a9c99258f893792a1ec2a 100644 (file)
@@ -25,6 +25,14 @@ config ARM_VIC_NR
          The maximum number of VICs available in the system, for
          power management.
 
+config RENESAS_INTC_IRQPIN
+       bool
+       select IRQ_DOMAIN
+
+config RENESAS_IRQC
+       bool
+       select IRQ_DOMAIN
+
 config VERSATILE_FPGA_IRQ
        bool
        select IRQ_DOMAIN
index 98e3b87bdf1b48761df4320a9c588af26f38bb2c..48fbdf978494c36c8e8fa82fb8dcaab19f3f1d3d 100644 (file)
@@ -2,10 +2,14 @@ obj-$(CONFIG_IRQCHIP)                 += irqchip.o
 
 obj-$(CONFIG_ARCH_BCM2835)             += irq-bcm2835.o
 obj-$(CONFIG_ARCH_EXYNOS)              += exynos-combiner.o
+obj-$(CONFIG_ARCH_S3C24XX)             += irq-s3c24xx.o
 obj-$(CONFIG_METAG)                    += irq-metag-ext.o
 obj-$(CONFIG_METAG_PERFCOUNTER_IRQS)   += irq-metag.o
 obj-$(CONFIG_ARCH_SUNXI)               += irq-sunxi.o
 obj-$(CONFIG_ARCH_SPEAR3XX)            += spear-shirq.o
 obj-$(CONFIG_ARM_GIC)                  += irq-gic.o
 obj-$(CONFIG_ARM_VIC)                  += irq-vic.o
+obj-$(CONFIG_RENESAS_INTC_IRQPIN)      += irq-renesas-intc-irqpin.o
+obj-$(CONFIG_RENESAS_IRQC)             += irq-renesas-irqc.o
 obj-$(CONFIG_VERSATILE_FPGA_IRQ)       += irq-versatile-fpga.o
+obj-$(CONFIG_ARCH_VT8500)              += irq-vt8500.o
index 04d86a9803f44862f6686513f8702870d03737be..494c2e21b538a0b060a5c3044fc34acfa1e5f09c 100644 (file)
 #include <linux/export.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/slab.h>
 #include <linux/irqdomain.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <asm/mach/irq.h>
 
+#ifdef CONFIG_EXYNOS_ATAGS
 #include <plat/cpu.h>
+#endif
 
 #include "irqchip.h"
 
 #define COMBINER_ENABLE_CLEAR  0x4
 #define COMBINER_INT_STATUS    0xC
 
+#define IRQ_IN_COMBINER                8
+
 static DEFINE_SPINLOCK(irq_controller_lock);
 
 struct combiner_chip_data {
-       unsigned int irq_offset;
+       unsigned int hwirq_offset;
        unsigned int irq_mask;
        void __iomem *base;
+       unsigned int parent_irq;
 };
 
 static struct irq_domain *combiner_irq_domain;
-static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
 
 static inline void __iomem *combiner_base(struct irq_data *data)
 {
@@ -75,11 +80,11 @@ static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
        if (status == 0)
                goto out;
 
-       combiner_irq = __ffs(status);
+       combiner_irq = chip_data->hwirq_offset + __ffs(status);
+       cascade_irq = irq_find_mapping(combiner_irq_domain, combiner_irq);
 
-       cascade_irq = combiner_irq + (chip_data->irq_offset & ~31);
-       if (unlikely(cascade_irq >= NR_IRQS))
-               do_bad_IRQ(cascade_irq, desc);
+       if (unlikely(!cascade_irq))
+               do_bad_IRQ(irq, desc);
        else
                generic_handle_irq(cascade_irq);
 
@@ -87,39 +92,49 @@ static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
        chained_irq_exit(chip, desc);
 }
 
-static struct irq_chip combiner_chip = {
-       .name           = "COMBINER",
-       .irq_mask       = combiner_mask_irq,
-       .irq_unmask     = combiner_unmask_irq,
-};
-
-static void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
+#ifdef CONFIG_SMP
+static int combiner_set_affinity(struct irq_data *d,
+                                const struct cpumask *mask_val, bool force)
 {
-       unsigned int max_nr;
+       struct combiner_chip_data *chip_data = irq_data_get_irq_chip_data(d);
+       struct irq_chip *chip = irq_get_chip(chip_data->parent_irq);
+       struct irq_data *data = irq_get_irq_data(chip_data->parent_irq);
 
-       if (soc_is_exynos5250())
-               max_nr = EXYNOS5_MAX_COMBINER_NR;
+       if (chip && chip->irq_set_affinity)
+               return chip->irq_set_affinity(data, mask_val, force);
        else
-               max_nr = EXYNOS4_MAX_COMBINER_NR;
+               return -EINVAL;
+}
+#endif
 
-       if (combiner_nr >= max_nr)
-               BUG();
-       if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
+static struct irq_chip combiner_chip = {
+       .name                   = "COMBINER",
+       .irq_mask               = combiner_mask_irq,
+       .irq_unmask             = combiner_unmask_irq,
+#ifdef CONFIG_SMP
+       .irq_set_affinity       = combiner_set_affinity,
+#endif
+};
+
+static void __init combiner_cascade_irq(struct combiner_chip_data *combiner_data,
+                                       unsigned int irq)
+{
+       if (irq_set_handler_data(irq, combiner_data) != 0)
                BUG();
        irq_set_chained_handler(irq, combiner_handle_cascade_irq);
 }
 
-static void __init combiner_init_one(unsigned int combiner_nr,
-                                    void __iomem *base)
+static void __init combiner_init_one(struct combiner_chip_data *combiner_data,
+                                    unsigned int combiner_nr,
+                                    void __iomem *base, unsigned int irq)
 {
-       combiner_data[combiner_nr].base = base;
-       combiner_data[combiner_nr].irq_offset = irq_find_mapping(
-               combiner_irq_domain, combiner_nr * MAX_IRQ_IN_COMBINER);
-       combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
+       combiner_data->base = base;
+       combiner_data->hwirq_offset = (combiner_nr & ~3) * IRQ_IN_COMBINER;
+       combiner_data->irq_mask = 0xff << ((combiner_nr % 4) << 3);
+       combiner_data->parent_irq = irq;
 
        /* Disable all interrupts */
-       __raw_writel(combiner_data[combiner_nr].irq_mask,
-                    base + COMBINER_ENABLE_CLEAR);
+       __raw_writel(combiner_data->irq_mask, base + COMBINER_ENABLE_CLEAR);
 }
 
 #ifdef CONFIG_OF
@@ -135,7 +150,7 @@ static int combiner_irq_domain_xlate(struct irq_domain *d,
        if (intsize < 2)
                return -EINVAL;
 
-       *out_hwirq = intspec[0] * MAX_IRQ_IN_COMBINER + intspec[1];
+       *out_hwirq = intspec[0] * IRQ_IN_COMBINER + intspec[1];
        *out_type = 0;
 
        return 0;
@@ -154,6 +169,8 @@ static int combiner_irq_domain_xlate(struct irq_domain *d,
 static int combiner_irq_domain_map(struct irq_domain *d, unsigned int irq,
                                   irq_hw_number_t hw)
 {
+       struct combiner_chip_data *combiner_data = d->host_data;
+
        irq_set_chip_and_handler(irq, &combiner_chip, handle_level_irq);
        irq_set_chip_data(irq, &combiner_data[hw >> 3]);
        set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
@@ -166,46 +183,61 @@ static struct irq_domain_ops combiner_irq_domain_ops = {
        .map    = combiner_irq_domain_map,
 };
 
-void __init combiner_init(void __iomem *combiner_base,
-                         struct device_node *np)
+static unsigned int combiner_lookup_irq(int group)
 {
-       int i, irq, irq_base;
-       unsigned int max_nr, nr_irq;
-
-       if (np) {
-               if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) {
-                       pr_warning("%s: number of combiners not specified, "
-                               "setting default as %d.\n",
-                               __func__, EXYNOS4_MAX_COMBINER_NR);
-                       max_nr = EXYNOS4_MAX_COMBINER_NR;
-               }
-       } else {
-               max_nr = soc_is_exynos5250() ? EXYNOS5_MAX_COMBINER_NR :
-                                               EXYNOS4_MAX_COMBINER_NR;
+#ifdef CONFIG_EXYNOS_ATAGS
+       if (group < EXYNOS4210_MAX_COMBINER_NR || soc_is_exynos5250())
+               return IRQ_SPI(group);
+
+       switch (group) {
+       case 16:
+               return IRQ_SPI(107);
+       case 17:
+               return IRQ_SPI(108);
+       case 18:
+               return IRQ_SPI(48);
+       case 19:
+               return IRQ_SPI(42);
        }
-       nr_irq = max_nr * MAX_IRQ_IN_COMBINER;
+#endif
+       return 0;
+}
+
+void __init combiner_init(void __iomem *combiner_base,
+                         struct device_node *np,
+                         unsigned int max_nr,
+                         int irq_base)
+{
+       int i, irq;
+       unsigned int nr_irq;
+       struct combiner_chip_data *combiner_data;
+
+       nr_irq = max_nr * IRQ_IN_COMBINER;
 
-       irq_base = irq_alloc_descs(COMBINER_IRQ(0, 0), 1, nr_irq, 0);
-       if (IS_ERR_VALUE(irq_base)) {
-               irq_base = COMBINER_IRQ(0, 0);
-               pr_warning("%s: irq desc alloc failed. Continuing with %d as linux irq base\n", __func__, irq_base);
+       combiner_data = kcalloc(max_nr, sizeof (*combiner_data), GFP_KERNEL);
+       if (!combiner_data) {
+               pr_warning("%s: could not allocate combiner data\n", __func__);
+               return;
        }
 
-       combiner_irq_domain = irq_domain_add_legacy(np, nr_irq, irq_base, 0,
-                               &combiner_irq_domain_ops, &combiner_data);
+       combiner_irq_domain = irq_domain_add_simple(np, nr_irq, irq_base,
+                               &combiner_irq_domain_ops, combiner_data);
        if (WARN_ON(!combiner_irq_domain)) {
                pr_warning("%s: irq domain init failed\n", __func__);
                return;
        }
 
        for (i = 0; i < max_nr; i++) {
-               combiner_init_one(i, combiner_base + (i >> 2) * 0x10);
-               irq = IRQ_SPI(i);
 #ifdef CONFIG_OF
                if (np)
                        irq = irq_of_parse_and_map(np, i);
+               else
 #endif
-               combiner_cascade_irq(i, irq);
+                       irq = combiner_lookup_irq(i);
+
+               combiner_init_one(&combiner_data[i], i,
+                                 combiner_base + (i >> 2) * 0x10, irq);
+               combiner_cascade_irq(&combiner_data[i], irq);
        }
 }
 
@@ -214,6 +246,8 @@ static int __init combiner_of_init(struct device_node *np,
                                   struct device_node *parent)
 {
        void __iomem *combiner_base;
+       unsigned int max_nr = 20;
+       int irq_base = -1;
 
        combiner_base = of_iomap(np, 0);
        if (!combiner_base) {
@@ -221,7 +255,20 @@ static int __init combiner_of_init(struct device_node *np,
                return -ENXIO;
        }
 
-       combiner_init(combiner_base, np);
+       if (of_property_read_u32(np, "samsung,combiner-nr", &max_nr)) {
+               pr_info("%s: number of combiners not specified, "
+                       "setting default as %d.\n",
+                       __func__, max_nr);
+       }
+
+       /* 
+        * FIXME: This is a hardwired COMBINER_IRQ(0,0). Once all devices
+        * get their IRQ from DT, remove this in order to get dynamic
+        * allocation.
+        */
+       irq_base = 160;
+
+       combiner_init(combiner_base, np, max_nr, irq_base);
 
        return 0;
 }
index 644d724684232d9b389fcc056f78aaab1e155817..a32e0d5aa45f43eb71c91ab9020696436212ae95 100644 (file)
@@ -648,7 +648,7 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
 
        /* Convert our logical CPU mask into a physical one. */
        for_each_cpu(cpu, mask)
-               map |= 1 << cpu_logical_map(cpu);
+               map |= gic_cpu_map[cpu];
 
        /*
         * Ensure that stores to Normal memory are visible to the
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
new file mode 100644 (file)
index 0000000..5a68e5a
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+ * Renesas INTC External IRQ Pin Driver
+ *
+ *  Copyright (C) 2013 Magnus Damm
+ *
+ * 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
+ *
+ * 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/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_data/irq-renesas-intc-irqpin.h>
+
+#define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */
+
+#define INTC_IRQPIN_REG_SENSE 0 /* ICRn */
+#define INTC_IRQPIN_REG_PRIO 1 /* INTPRInn */
+#define INTC_IRQPIN_REG_SOURCE 2 /* INTREQnn */
+#define INTC_IRQPIN_REG_MASK 3 /* INTMSKnn */
+#define INTC_IRQPIN_REG_CLEAR 4 /* INTMSKCLRnn */
+#define INTC_IRQPIN_REG_NR 5
+
+/* INTC external IRQ PIN hardware register access:
+ *
+ * SENSE is read-write 32-bit with 2-bits or 4-bits per IRQ (*)
+ * PRIO is read-write 32-bit with 4-bits per IRQ (**)
+ * SOURCE is read-only 32-bit or 8-bit with 1-bit per IRQ (***)
+ * MASK is write-only 32-bit or 8-bit with 1-bit per IRQ (***)
+ * CLEAR is write-only 32-bit or 8-bit with 1-bit per IRQ (***)
+ *
+ * (*) May be accessed by more than one driver instance - lock needed
+ * (**) Read-modify-write access by one driver instance - lock needed
+ * (***) Accessed by one driver instance only - no locking needed
+ */
+
+struct intc_irqpin_iomem {
+       void __iomem *iomem;
+       unsigned long (*read)(void __iomem *iomem);
+       void (*write)(void __iomem *iomem, unsigned long data);
+       int width;
+};
+
+struct intc_irqpin_irq {
+       int hw_irq;
+       int requested_irq;
+       int domain_irq;
+       struct intc_irqpin_priv *p;
+};
+
+struct intc_irqpin_priv {
+       struct intc_irqpin_iomem iomem[INTC_IRQPIN_REG_NR];
+       struct intc_irqpin_irq irq[INTC_IRQPIN_MAX];
+       struct renesas_intc_irqpin_config config;
+       unsigned int number_of_irqs;
+       struct platform_device *pdev;
+       struct irq_chip irq_chip;
+       struct irq_domain *irq_domain;
+       bool shared_irqs;
+       u8 shared_irq_mask;
+};
+
+static unsigned long intc_irqpin_read32(void __iomem *iomem)
+{
+       return ioread32(iomem);
+}
+
+static unsigned long intc_irqpin_read8(void __iomem *iomem)
+{
+       return ioread8(iomem);
+}
+
+static void intc_irqpin_write32(void __iomem *iomem, unsigned long data)
+{
+       iowrite32(data, iomem);
+}
+
+static void intc_irqpin_write8(void __iomem *iomem, unsigned long data)
+{
+       iowrite8(data, iomem);
+}
+
+static inline unsigned long intc_irqpin_read(struct intc_irqpin_priv *p,
+                                            int reg)
+{
+       struct intc_irqpin_iomem *i = &p->iomem[reg];
+
+       return i->read(i->iomem);
+}
+
+static inline void intc_irqpin_write(struct intc_irqpin_priv *p,
+                                    int reg, unsigned long data)
+{
+       struct intc_irqpin_iomem *i = &p->iomem[reg];
+
+       i->write(i->iomem, data);
+}
+
+static inline unsigned long intc_irqpin_hwirq_mask(struct intc_irqpin_priv *p,
+                                                  int reg, int hw_irq)
+{
+       return BIT((p->iomem[reg].width - 1) - hw_irq);
+}
+
+static inline void intc_irqpin_irq_write_hwirq(struct intc_irqpin_priv *p,
+                                              int reg, int hw_irq)
+{
+       intc_irqpin_write(p, reg, intc_irqpin_hwirq_mask(p, reg, hw_irq));
+}
+
+static DEFINE_RAW_SPINLOCK(intc_irqpin_lock); /* only used by slow path */
+
+static void intc_irqpin_read_modify_write(struct intc_irqpin_priv *p,
+                                         int reg, int shift,
+                                         int width, int value)
+{
+       unsigned long flags;
+       unsigned long tmp;
+
+       raw_spin_lock_irqsave(&intc_irqpin_lock, flags);
+
+       tmp = intc_irqpin_read(p, reg);
+       tmp &= ~(((1 << width) - 1) << shift);
+       tmp |= value << shift;
+       intc_irqpin_write(p, reg, tmp);
+
+       raw_spin_unlock_irqrestore(&intc_irqpin_lock, flags);
+}
+
+static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p,
+                                        int irq, int do_mask)
+{
+       int bitfield_width = 4; /* PRIO assumed to have fixed bitfield width */
+       int shift = (7 - irq) * bitfield_width; /* PRIO assumed to be 32-bit */
+
+       intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_PRIO,
+                                     shift, bitfield_width,
+                                     do_mask ? 0 : (1 << bitfield_width) - 1);
+}
+
+static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value)
+{
+       int bitfield_width = p->config.sense_bitfield_width;
+       int shift = (7 - irq) * bitfield_width; /* SENSE assumed to be 32-bit */
+
+       dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value);
+
+       if (value >= (1 << bitfield_width))
+               return -EINVAL;
+
+       intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_SENSE, shift,
+                                     bitfield_width, value);
+       return 0;
+}
+
+static void intc_irqpin_dbg(struct intc_irqpin_irq *i, char *str)
+{
+       dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n",
+               str, i->requested_irq, i->hw_irq, i->domain_irq);
+}
+
+static void intc_irqpin_irq_enable(struct irq_data *d)
+{
+       struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+       int hw_irq = irqd_to_hwirq(d);
+
+       intc_irqpin_dbg(&p->irq[hw_irq], "enable");
+       intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_CLEAR, hw_irq);
+}
+
+static void intc_irqpin_irq_disable(struct irq_data *d)
+{
+       struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+       int hw_irq = irqd_to_hwirq(d);
+
+       intc_irqpin_dbg(&p->irq[hw_irq], "disable");
+       intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_MASK, hw_irq);
+}
+
+static void intc_irqpin_shared_irq_enable(struct irq_data *d)
+{
+       struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+       int hw_irq = irqd_to_hwirq(d);
+
+       intc_irqpin_dbg(&p->irq[hw_irq], "shared enable");
+       intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_CLEAR, hw_irq);
+
+       p->shared_irq_mask &= ~BIT(hw_irq);
+}
+
+static void intc_irqpin_shared_irq_disable(struct irq_data *d)
+{
+       struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+       int hw_irq = irqd_to_hwirq(d);
+
+       intc_irqpin_dbg(&p->irq[hw_irq], "shared disable");
+       intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_MASK, hw_irq);
+
+       p->shared_irq_mask |= BIT(hw_irq);
+}
+
+static void intc_irqpin_irq_enable_force(struct irq_data *d)
+{
+       struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+       int irq = p->irq[irqd_to_hwirq(d)].requested_irq;
+
+       intc_irqpin_irq_enable(d);
+
+       /* enable interrupt through parent interrupt controller,
+        * assumes non-shared interrupt with 1:1 mapping
+        * needed for busted IRQs on some SoCs like sh73a0
+        */
+       irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq));
+}
+
+static void intc_irqpin_irq_disable_force(struct irq_data *d)
+{
+       struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+       int irq = p->irq[irqd_to_hwirq(d)].requested_irq;
+
+       /* disable interrupt through parent interrupt controller,
+        * assumes non-shared interrupt with 1:1 mapping
+        * needed for busted IRQs on some SoCs like sh73a0
+        */
+       irq_get_chip(irq)->irq_mask(irq_get_irq_data(irq));
+       intc_irqpin_irq_disable(d);
+}
+
+#define INTC_IRQ_SENSE_VALID 0x10
+#define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID)
+
+static unsigned char intc_irqpin_sense[IRQ_TYPE_SENSE_MASK + 1] = {
+       [IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x00),
+       [IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x01),
+       [IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x02),
+       [IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x03),
+       [IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x04),
+};
+
+static int intc_irqpin_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       unsigned char value = intc_irqpin_sense[type & IRQ_TYPE_SENSE_MASK];
+       struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d);
+
+       if (!(value & INTC_IRQ_SENSE_VALID))
+               return -EINVAL;
+
+       return intc_irqpin_set_sense(p, irqd_to_hwirq(d),
+                                    value ^ INTC_IRQ_SENSE_VALID);
+}
+
+static irqreturn_t intc_irqpin_irq_handler(int irq, void *dev_id)
+{
+       struct intc_irqpin_irq *i = dev_id;
+       struct intc_irqpin_priv *p = i->p;
+       unsigned long bit;
+
+       intc_irqpin_dbg(i, "demux1");
+       bit = intc_irqpin_hwirq_mask(p, INTC_IRQPIN_REG_SOURCE, i->hw_irq);
+
+       if (intc_irqpin_read(p, INTC_IRQPIN_REG_SOURCE) & bit) {
+               intc_irqpin_write(p, INTC_IRQPIN_REG_SOURCE, ~bit);
+               intc_irqpin_dbg(i, "demux2");
+               generic_handle_irq(i->domain_irq);
+               return IRQ_HANDLED;
+       }
+       return IRQ_NONE;
+}
+
+static irqreturn_t intc_irqpin_shared_irq_handler(int irq, void *dev_id)
+{
+       struct intc_irqpin_priv *p = dev_id;
+       unsigned int reg_source = intc_irqpin_read(p, INTC_IRQPIN_REG_SOURCE);
+       irqreturn_t status = IRQ_NONE;
+       int k;
+
+       for (k = 0; k < 8; k++) {
+               if (reg_source & BIT(7 - k)) {
+                       if (BIT(k) & p->shared_irq_mask)
+                               continue;
+
+                       status |= intc_irqpin_irq_handler(irq, &p->irq[k]);
+               }
+       }
+
+       return status;
+}
+
+static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq,
+                                     irq_hw_number_t hw)
+{
+       struct intc_irqpin_priv *p = h->host_data;
+
+       p->irq[hw].domain_irq = virq;
+       p->irq[hw].hw_irq = hw;
+
+       intc_irqpin_dbg(&p->irq[hw], "map");
+       irq_set_chip_data(virq, h->host_data);
+       irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
+       set_irq_flags(virq, IRQF_VALID); /* kill me now */
+       return 0;
+}
+
+static struct irq_domain_ops intc_irqpin_irq_domain_ops = {
+       .map    = intc_irqpin_irq_domain_map,
+       .xlate  = irq_domain_xlate_twocell,
+};
+
+static int intc_irqpin_probe(struct platform_device *pdev)
+{
+       struct renesas_intc_irqpin_config *pdata = pdev->dev.platform_data;
+       struct intc_irqpin_priv *p;
+       struct intc_irqpin_iomem *i;
+       struct resource *io[INTC_IRQPIN_REG_NR];
+       struct resource *irq;
+       struct irq_chip *irq_chip;
+       void (*enable_fn)(struct irq_data *d);
+       void (*disable_fn)(struct irq_data *d);
+       const char *name = dev_name(&pdev->dev);
+       int ref_irq;
+       int ret;
+       int k;
+
+       p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
+       if (!p) {
+               dev_err(&pdev->dev, "failed to allocate driver data\n");
+               ret = -ENOMEM;
+               goto err0;
+       }
+
+       /* deal with driver instance configuration */
+       if (pdata)
+               memcpy(&p->config, pdata, sizeof(*pdata));
+       if (!p->config.sense_bitfield_width)
+               p->config.sense_bitfield_width = 4; /* default to 4 bits */
+
+       p->pdev = pdev;
+       platform_set_drvdata(pdev, p);
+
+       /* get hold of manadatory IOMEM */
+       for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
+               io[k] = platform_get_resource(pdev, IORESOURCE_MEM, k);
+               if (!io[k]) {
+                       dev_err(&pdev->dev, "not enough IOMEM resources\n");
+                       ret = -EINVAL;
+                       goto err0;
+               }
+       }
+
+       /* allow any number of IRQs between 1 and INTC_IRQPIN_MAX */
+       for (k = 0; k < INTC_IRQPIN_MAX; k++) {
+               irq = platform_get_resource(pdev, IORESOURCE_IRQ, k);
+               if (!irq)
+                       break;
+
+               p->irq[k].p = p;
+               p->irq[k].requested_irq = irq->start;
+       }
+
+       p->number_of_irqs = k;
+       if (p->number_of_irqs < 1) {
+               dev_err(&pdev->dev, "not enough IRQ resources\n");
+               ret = -EINVAL;
+               goto err0;
+       }
+
+       /* ioremap IOMEM and setup read/write callbacks */
+       for (k = 0; k < INTC_IRQPIN_REG_NR; k++) {
+               i = &p->iomem[k];
+
+               switch (resource_size(io[k])) {
+               case 1:
+                       i->width = 8;
+                       i->read = intc_irqpin_read8;
+                       i->write = intc_irqpin_write8;
+                       break;
+               case 4:
+                       i->width = 32;
+                       i->read = intc_irqpin_read32;
+                       i->write = intc_irqpin_write32;
+                       break;
+               default:
+                       dev_err(&pdev->dev, "IOMEM size mismatch\n");
+                       ret = -EINVAL;
+                       goto err0;
+               }
+
+               i->iomem = devm_ioremap_nocache(&pdev->dev, io[k]->start,
+                                               resource_size(io[k]));
+               if (!i->iomem) {
+                       dev_err(&pdev->dev, "failed to remap IOMEM\n");
+                       ret = -ENXIO;
+                       goto err0;
+               }
+       }
+
+       /* mask all interrupts using priority */
+       for (k = 0; k < p->number_of_irqs; k++)
+               intc_irqpin_mask_unmask_prio(p, k, 1);
+
+       /* clear all pending interrupts */
+       intc_irqpin_write(p, INTC_IRQPIN_REG_SOURCE, 0x0);
+
+       /* scan for shared interrupt lines */
+       ref_irq = p->irq[0].requested_irq;
+       p->shared_irqs = true;
+       for (k = 1; k < p->number_of_irqs; k++) {
+               if (ref_irq != p->irq[k].requested_irq) {
+                       p->shared_irqs = false;
+                       break;
+               }
+       }
+
+       /* use more severe masking method if requested */
+       if (p->config.control_parent) {
+               enable_fn = intc_irqpin_irq_enable_force;
+               disable_fn = intc_irqpin_irq_disable_force;
+       } else if (!p->shared_irqs) {
+               enable_fn = intc_irqpin_irq_enable;
+               disable_fn = intc_irqpin_irq_disable;
+       } else {
+               enable_fn = intc_irqpin_shared_irq_enable;
+               disable_fn = intc_irqpin_shared_irq_disable;
+       }
+
+       irq_chip = &p->irq_chip;
+       irq_chip->name = name;
+       irq_chip->irq_mask = disable_fn;
+       irq_chip->irq_unmask = enable_fn;
+       irq_chip->irq_enable = enable_fn;
+       irq_chip->irq_disable = disable_fn;
+       irq_chip->irq_set_type = intc_irqpin_irq_set_type;
+       irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
+
+       p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
+                                             p->number_of_irqs,
+                                             p->config.irq_base,
+                                             &intc_irqpin_irq_domain_ops, p);
+       if (!p->irq_domain) {
+               ret = -ENXIO;
+               dev_err(&pdev->dev, "cannot initialize irq domain\n");
+               goto err0;
+       }
+
+       if (p->shared_irqs) {
+               /* request one shared interrupt */
+               if (devm_request_irq(&pdev->dev, p->irq[0].requested_irq,
+                               intc_irqpin_shared_irq_handler,
+                               IRQF_SHARED, name, p)) {
+                       dev_err(&pdev->dev, "failed to request low IRQ\n");
+                       ret = -ENOENT;
+                       goto err1;
+               }
+       } else {
+               /* request interrupts one by one */
+               for (k = 0; k < p->number_of_irqs; k++) {
+                       if (devm_request_irq(&pdev->dev,
+                                       p->irq[k].requested_irq,
+                                       intc_irqpin_irq_handler,
+                                       0, name, &p->irq[k])) {
+                               dev_err(&pdev->dev,
+                                       "failed to request low IRQ\n");
+                               ret = -ENOENT;
+                               goto err1;
+                       }
+               }
+       }
+
+       /* unmask all interrupts on prio level */
+       for (k = 0; k < p->number_of_irqs; k++)
+               intc_irqpin_mask_unmask_prio(p, k, 0);
+
+       dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs);
+
+       /* warn in case of mismatch if irq base is specified */
+       if (p->config.irq_base) {
+               if (p->config.irq_base != p->irq[0].domain_irq)
+                       dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
+                                p->config.irq_base, p->irq[0].domain_irq);
+       }
+
+       return 0;
+
+err1:
+       irq_domain_remove(p->irq_domain);
+err0:
+       return ret;
+}
+
+static int intc_irqpin_remove(struct platform_device *pdev)
+{
+       struct intc_irqpin_priv *p = platform_get_drvdata(pdev);
+
+       irq_domain_remove(p->irq_domain);
+
+       return 0;
+}
+
+static const struct of_device_id intc_irqpin_dt_ids[] = {
+       { .compatible = "renesas,intc-irqpin", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids);
+
+static struct platform_driver intc_irqpin_device_driver = {
+       .probe          = intc_irqpin_probe,
+       .remove         = intc_irqpin_remove,
+       .driver         = {
+               .name   = "renesas_intc_irqpin",
+               .of_match_table = intc_irqpin_dt_ids,
+               .owner  = THIS_MODULE,
+       }
+};
+
+static int __init intc_irqpin_init(void)
+{
+       return platform_driver_register(&intc_irqpin_device_driver);
+}
+postcore_initcall(intc_irqpin_init);
+
+static void __exit intc_irqpin_exit(void)
+{
+       platform_driver_unregister(&intc_irqpin_device_driver);
+}
+module_exit(intc_irqpin_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("Renesas INTC External IRQ Pin Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c
new file mode 100644 (file)
index 0000000..927bff3
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Renesas IRQC Driver
+ *
+ *  Copyright (C) 2013 Magnus Damm
+ *
+ * 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
+ *
+ * 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/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_data/irq-renesas-irqc.h>
+
+#define IRQC_IRQ_MAX 32 /* maximum 32 interrupts per driver instance */
+
+#define IRQC_REQ_STS 0x00
+#define IRQC_EN_STS 0x04
+#define IRQC_EN_SET 0x08
+#define IRQC_INT_CPU_BASE(n) (0x000 + ((n) * 0x10))
+#define DETECT_STATUS 0x100
+#define IRQC_CONFIG(n) (0x180 + ((n) * 0x04))
+
+struct irqc_irq {
+       int hw_irq;
+       int requested_irq;
+       int domain_irq;
+       struct irqc_priv *p;
+};
+
+struct irqc_priv {
+       void __iomem *iomem;
+       void __iomem *cpu_int_base;
+       struct irqc_irq irq[IRQC_IRQ_MAX];
+       struct renesas_irqc_config config;
+       unsigned int number_of_irqs;
+       struct platform_device *pdev;
+       struct irq_chip irq_chip;
+       struct irq_domain *irq_domain;
+};
+
+static void irqc_dbg(struct irqc_irq *i, char *str)
+{
+       dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n",
+               str, i->requested_irq, i->hw_irq, i->domain_irq);
+}
+
+static void irqc_irq_enable(struct irq_data *d)
+{
+       struct irqc_priv *p = irq_data_get_irq_chip_data(d);
+       int hw_irq = irqd_to_hwirq(d);
+
+       irqc_dbg(&p->irq[hw_irq], "enable");
+       iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_SET);
+}
+
+static void irqc_irq_disable(struct irq_data *d)
+{
+       struct irqc_priv *p = irq_data_get_irq_chip_data(d);
+       int hw_irq = irqd_to_hwirq(d);
+
+       irqc_dbg(&p->irq[hw_irq], "disable");
+       iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_STS);
+}
+
+#define INTC_IRQ_SENSE_VALID 0x10
+#define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID)
+
+static unsigned char irqc_sense[IRQ_TYPE_SENSE_MASK + 1] = {
+       [IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x01),
+       [IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x02),
+       [IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x04), /* Synchronous */
+       [IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x08), /* Synchronous */
+       [IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x0c),  /* Synchronous */
+};
+
+static int irqc_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       struct irqc_priv *p = irq_data_get_irq_chip_data(d);
+       int hw_irq = irqd_to_hwirq(d);
+       unsigned char value = irqc_sense[type & IRQ_TYPE_SENSE_MASK];
+       unsigned long tmp;
+
+       irqc_dbg(&p->irq[hw_irq], "sense");
+
+       if (!(value & INTC_IRQ_SENSE_VALID))
+               return -EINVAL;
+
+       tmp = ioread32(p->iomem + IRQC_CONFIG(hw_irq));
+       tmp &= ~0x3f;
+       tmp |= value ^ INTC_IRQ_SENSE_VALID;
+       iowrite32(tmp, p->iomem + IRQC_CONFIG(hw_irq));
+       return 0;
+}
+
+static irqreturn_t irqc_irq_handler(int irq, void *dev_id)
+{
+       struct irqc_irq *i = dev_id;
+       struct irqc_priv *p = i->p;
+       unsigned long bit = BIT(i->hw_irq);
+
+       irqc_dbg(i, "demux1");
+
+       if (ioread32(p->iomem + DETECT_STATUS) & bit) {
+               iowrite32(bit, p->iomem + DETECT_STATUS);
+               irqc_dbg(i, "demux2");
+               generic_handle_irq(i->domain_irq);
+               return IRQ_HANDLED;
+       }
+       return IRQ_NONE;
+}
+
+static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq,
+                              irq_hw_number_t hw)
+{
+       struct irqc_priv *p = h->host_data;
+
+       p->irq[hw].domain_irq = virq;
+       p->irq[hw].hw_irq = hw;
+
+       irqc_dbg(&p->irq[hw], "map");
+       irq_set_chip_data(virq, h->host_data);
+       irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq);
+       set_irq_flags(virq, IRQF_VALID); /* kill me now */
+       return 0;
+}
+
+static struct irq_domain_ops irqc_irq_domain_ops = {
+       .map    = irqc_irq_domain_map,
+       .xlate  = irq_domain_xlate_twocell,
+};
+
+static int irqc_probe(struct platform_device *pdev)
+{
+       struct renesas_irqc_config *pdata = pdev->dev.platform_data;
+       struct irqc_priv *p;
+       struct resource *io;
+       struct resource *irq;
+       struct irq_chip *irq_chip;
+       const char *name = dev_name(&pdev->dev);
+       int ret;
+       int k;
+
+       p = kzalloc(sizeof(*p), GFP_KERNEL);
+       if (!p) {
+               dev_err(&pdev->dev, "failed to allocate driver data\n");
+               ret = -ENOMEM;
+               goto err0;
+       }
+
+       /* deal with driver instance configuration */
+       if (pdata)
+               memcpy(&p->config, pdata, sizeof(*pdata));
+
+       p->pdev = pdev;
+       platform_set_drvdata(pdev, p);
+
+       /* get hold of manadatory IOMEM */
+       io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!io) {
+               dev_err(&pdev->dev, "not enough IOMEM resources\n");
+               ret = -EINVAL;
+               goto err1;
+       }
+
+       /* allow any number of IRQs between 1 and IRQC_IRQ_MAX */
+       for (k = 0; k < IRQC_IRQ_MAX; k++) {
+               irq = platform_get_resource(pdev, IORESOURCE_IRQ, k);
+               if (!irq)
+                       break;
+
+               p->irq[k].p = p;
+               p->irq[k].requested_irq = irq->start;
+       }
+
+       p->number_of_irqs = k;
+       if (p->number_of_irqs < 1) {
+               dev_err(&pdev->dev, "not enough IRQ resources\n");
+               ret = -EINVAL;
+               goto err1;
+       }
+
+       /* ioremap IOMEM and setup read/write callbacks */
+       p->iomem = ioremap_nocache(io->start, resource_size(io));
+       if (!p->iomem) {
+               dev_err(&pdev->dev, "failed to remap IOMEM\n");
+               ret = -ENXIO;
+               goto err2;
+       }
+
+       p->cpu_int_base = p->iomem + IRQC_INT_CPU_BASE(0); /* SYS-SPI */
+
+       irq_chip = &p->irq_chip;
+       irq_chip->name = name;
+       irq_chip->irq_mask = irqc_irq_disable;
+       irq_chip->irq_unmask = irqc_irq_enable;
+       irq_chip->irq_enable = irqc_irq_enable;
+       irq_chip->irq_disable = irqc_irq_disable;
+       irq_chip->irq_set_type = irqc_irq_set_type;
+       irq_chip->flags = IRQCHIP_SKIP_SET_WAKE;
+
+       p->irq_domain = irq_domain_add_simple(pdev->dev.of_node,
+                                             p->number_of_irqs,
+                                             p->config.irq_base,
+                                             &irqc_irq_domain_ops, p);
+       if (!p->irq_domain) {
+               ret = -ENXIO;
+               dev_err(&pdev->dev, "cannot initialize irq domain\n");
+               goto err2;
+       }
+
+       /* request interrupts one by one */
+       for (k = 0; k < p->number_of_irqs; k++) {
+               if (request_irq(p->irq[k].requested_irq, irqc_irq_handler,
+                               0, name, &p->irq[k])) {
+                       dev_err(&pdev->dev, "failed to request IRQ\n");
+                       ret = -ENOENT;
+                       goto err3;
+               }
+       }
+
+       dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs);
+
+       /* warn in case of mismatch if irq base is specified */
+       if (p->config.irq_base) {
+               if (p->config.irq_base != p->irq[0].domain_irq)
+                       dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n",
+                                p->config.irq_base, p->irq[0].domain_irq);
+       }
+
+       return 0;
+err3:
+       for (; k >= 0; k--)
+               free_irq(p->irq[k - 1].requested_irq, &p->irq[k - 1]);
+
+       irq_domain_remove(p->irq_domain);
+err2:
+       iounmap(p->iomem);
+err1:
+       kfree(p);
+err0:
+       return ret;
+}
+
+static int irqc_remove(struct platform_device *pdev)
+{
+       struct irqc_priv *p = platform_get_drvdata(pdev);
+       int k;
+
+       for (k = 0; k < p->number_of_irqs; k++)
+               free_irq(p->irq[k].requested_irq, &p->irq[k]);
+
+       irq_domain_remove(p->irq_domain);
+       iounmap(p->iomem);
+       kfree(p);
+       return 0;
+}
+
+static const struct of_device_id irqc_dt_ids[] = {
+       { .compatible = "renesas,irqc", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, irqc_dt_ids);
+
+static struct platform_driver irqc_device_driver = {
+       .probe          = irqc_probe,
+       .remove         = irqc_remove,
+       .driver         = {
+               .name   = "renesas_irqc",
+               .of_match_table = irqc_dt_ids,
+               .owner  = THIS_MODULE,
+       }
+};
+
+static int __init irqc_init(void)
+{
+       return platform_driver_register(&irqc_device_driver);
+}
+postcore_initcall(irqc_init);
+
+static void __exit irqc_exit(void)
+{
+       platform_driver_unregister(&irqc_device_driver);
+}
+module_exit(irqc_exit);
+
+MODULE_AUTHOR("Magnus Damm");
+MODULE_DESCRIPTION("Renesas IRQC Driver");
+MODULE_LICENSE("GPL v2");
similarity index 52%
rename from arch/arm/mach-s3c24xx/irq.c
rename to drivers/irqchip/irq-s3c24xx.c
index cb9f5e011e73a1fb5f055dc6a3c6498aa095f7e0..5e40b3424df8479a3f5728c8ba91901af526b5e1 100644 (file)
 #include <linux/ioport.h>
 #include <linux/device.h>
 #include <linux/irqdomain.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
 
+#include <asm/exception.h>
 #include <asm/mach/irq.h>
 
 #include <mach/regs-irq.h>
@@ -34,7 +38,8 @@
 #include <plat/cpu.h>
 #include <plat/regs-irqtype.h>
 #include <plat/pm.h>
-#include <plat/irq.h>
+
+#include "irqchip.h"
 
 #define S3C_IRQTYPE_NONE       0
 #define S3C_IRQTYPE_EINT       1
@@ -43,6 +48,7 @@
 
 struct s3c_irq_data {
        unsigned int type;
+       unsigned long offset;
        unsigned long parent_irq;
 
        /* data gets filled during init */
@@ -69,23 +75,34 @@ struct s3c_irq_intc {
        struct s3c_irq_data     *irqs;
 };
 
+/*
+ * Array holding pointers to the global controller structs
+ * [0] ... main_intc
+ * [1] ... sub_intc
+ * [2] ... main_intc2 on s3c2416
+ */
+static struct s3c_irq_intc *s3c_intc[3];
+
 static void s3c_irq_mask(struct irq_data *data)
 {
-       struct s3c_irq_intc *intc = data->domain->host_data;
+       struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
+       struct s3c_irq_intc *intc = irq_data->intc;
        struct s3c_irq_intc *parent_intc = intc->parent;
-       struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq];
        struct s3c_irq_data *parent_data;
        unsigned long mask;
        unsigned int irqno;
 
        mask = __raw_readl(intc->reg_mask);
-       mask |= (1UL << data->hwirq);
+       mask |= (1UL << irq_data->offset);
        __raw_writel(mask, intc->reg_mask);
 
-       if (parent_intc && irq_data->parent_irq) {
+       if (parent_intc) {
                parent_data = &parent_intc->irqs[irq_data->parent_irq];
 
-               /* check to see if we need to mask the parent IRQ */
+               /* check to see if we need to mask the parent IRQ
+                * The parent_irq is always in main_intc, so the hwirq
+                * for find_mapping does not need an offset in any case.
+                */
                if ((mask & parent_data->sub_bits) == parent_data->sub_bits) {
                        irqno = irq_find_mapping(parent_intc->domain,
                                         irq_data->parent_irq);
@@ -96,17 +113,17 @@ static void s3c_irq_mask(struct irq_data *data)
 
 static void s3c_irq_unmask(struct irq_data *data)
 {
-       struct s3c_irq_intc *intc = data->domain->host_data;
+       struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
+       struct s3c_irq_intc *intc = irq_data->intc;
        struct s3c_irq_intc *parent_intc = intc->parent;
-       struct s3c_irq_data *irq_data = &intc->irqs[data->hwirq];
        unsigned long mask;
        unsigned int irqno;
 
        mask = __raw_readl(intc->reg_mask);
-       mask &= ~(1UL << data->hwirq);
+       mask &= ~(1UL << irq_data->offset);
        __raw_writel(mask, intc->reg_mask);
 
-       if (parent_intc && irq_data->parent_irq) {
+       if (parent_intc) {
                irqno = irq_find_mapping(parent_intc->domain,
                                         irq_data->parent_irq);
                s3c_irq_unmask(irq_get_irq_data(irqno));
@@ -115,14 +132,37 @@ static void s3c_irq_unmask(struct irq_data *data)
 
 static inline void s3c_irq_ack(struct irq_data *data)
 {
-       struct s3c_irq_intc *intc = data->domain->host_data;
-       unsigned long bitval = 1UL << data->hwirq;
+       struct s3c_irq_data *irq_data = irq_data_get_irq_chip_data(data);
+       struct s3c_irq_intc *intc = irq_data->intc;
+       unsigned long bitval = 1UL << irq_data->offset;
 
        __raw_writel(bitval, intc->reg_pending);
        if (intc->reg_intpnd)
                __raw_writel(bitval, intc->reg_intpnd);
 }
 
+static int s3c_irq_type(struct irq_data *data, unsigned int type)
+{
+       switch (type) {
+       case IRQ_TYPE_NONE:
+               break;
+       case IRQ_TYPE_EDGE_RISING:
+       case IRQ_TYPE_EDGE_FALLING:
+       case IRQ_TYPE_EDGE_BOTH:
+               irq_set_handler(data->irq, handle_edge_irq);
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+       case IRQ_TYPE_LEVEL_HIGH:
+               irq_set_handler(data->irq, handle_level_irq);
+               break;
+       default:
+               pr_err("No such irq type %d", type);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int s3c_irqext_type_set(void __iomem *gpcon_reg,
                               void __iomem *extint_reg,
                               unsigned long gpcon_offset,
@@ -175,8 +215,7 @@ static int s3c_irqext_type_set(void __iomem *gpcon_reg,
        return 0;
 }
 
-/* FIXME: make static when it's out of plat-samsung/irq.h */
-int s3c_irqext_type(struct irq_data *data, unsigned int type)
+static int s3c_irqext_type(struct irq_data *data, unsigned int type)
 {
        void __iomem *extint_reg;
        void __iomem *gpcon_reg;
@@ -224,19 +263,21 @@ static int s3c_irqext0_type(struct irq_data *data, unsigned int type)
                                   extint_offset, type);
 }
 
-struct irq_chip s3c_irq_chip = {
+static struct irq_chip s3c_irq_chip = {
        .name           = "s3c",
        .irq_ack        = s3c_irq_ack,
        .irq_mask       = s3c_irq_mask,
        .irq_unmask     = s3c_irq_unmask,
+       .irq_set_type   = s3c_irq_type,
        .irq_set_wake   = s3c_irq_wake
 };
 
-struct irq_chip s3c_irq_level_chip = {
+static struct irq_chip s3c_irq_level_chip = {
        .name           = "s3c-level",
        .irq_mask       = s3c_irq_mask,
        .irq_unmask     = s3c_irq_unmask,
        .irq_ack        = s3c_irq_ack,
+       .irq_set_type   = s3c_irq_type,
 };
 
 static struct irq_chip s3c_irqext_chip = {
@@ -260,12 +301,19 @@ static struct irq_chip s3c_irq_eint0t4 = {
 static void s3c_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
        struct irq_chip *chip = irq_desc_get_chip(desc);
-       struct s3c_irq_intc *intc = desc->irq_data.domain->host_data;
-       struct s3c_irq_data *irq_data = &intc->irqs[desc->irq_data.hwirq];
+       struct s3c_irq_data *irq_data = irq_desc_get_chip_data(desc);
+       struct s3c_irq_intc *intc = irq_data->intc;
        struct s3c_irq_intc *sub_intc = irq_data->sub_intc;
        unsigned long src;
        unsigned long msk;
        unsigned int n;
+       unsigned int offset;
+
+       /* we're using individual domains for the non-dt case
+        * and one big domain for the dt case where the subintc
+        * starts at hwirq number 32.
+        */
+       offset = (intc->domain->of_node) ? 32 : 0;
 
        chained_irq_enter(chip, desc);
 
@@ -278,12 +326,64 @@ static void s3c_irq_demux(unsigned int irq, struct irq_desc *desc)
        while (src) {
                n = __ffs(src);
                src &= ~(1 << n);
-               generic_handle_irq(irq_find_mapping(sub_intc->domain, n));
+               irq = irq_find_mapping(sub_intc->domain, offset + n);
+               generic_handle_irq(irq);
        }
 
        chained_irq_exit(chip, desc);
 }
 
+static inline int s3c24xx_handle_intc(struct s3c_irq_intc *intc,
+                                     struct pt_regs *regs, int intc_offset)
+{
+       int pnd;
+       int offset;
+       int irq;
+
+       pnd = __raw_readl(intc->reg_intpnd);
+       if (!pnd)
+               return false;
+
+       /* non-dt machines use individual domains */
+       if (!intc->domain->of_node)
+               intc_offset = 0;
+
+       /* We have a problem that the INTOFFSET register does not always
+        * show one interrupt. Occasionally we get two interrupts through
+        * the prioritiser, and this causes the INTOFFSET register to show
+        * what looks like the logical-or of the two interrupt numbers.
+        *
+        * Thanks to Klaus, Shannon, et al for helping to debug this problem
+        */
+       offset = __raw_readl(intc->reg_intpnd + 4);
+
+       /* Find the bit manually, when the offset is wrong.
+        * The pending register only ever contains the one bit of the next
+        * interrupt to handle.
+        */
+       if (!(pnd & (1 << offset)))
+               offset =  __ffs(pnd);
+
+       irq = irq_find_mapping(intc->domain, intc_offset + offset);
+       handle_IRQ(irq, regs);
+       return true;
+}
+
+asmlinkage void __exception_irq_entry s3c24xx_handle_irq(struct pt_regs *regs)
+{
+       do {
+               if (likely(s3c_intc[0]))
+                       if (s3c24xx_handle_intc(s3c_intc[0], regs, 0))
+                               continue;
+
+               if (s3c_intc[2])
+                       if (s3c24xx_handle_intc(s3c_intc[2], regs, 64))
+                               continue;
+
+               break;
+       } while (1);
+}
+
 #ifdef CONFIG_FIQ
 /**
  * s3c24xx_set_fiq - set the FIQ routing
@@ -326,25 +426,21 @@ static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
        struct s3c_irq_data *parent_irq_data;
        unsigned int irqno;
 
-       if (!intc) {
-               pr_err("irq-s3c24xx: no controller found for hwirq %lu\n", hw);
-               return -EINVAL;
-       }
-
-       if (!irq_data) {
-               pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n", hw);
-               return -EINVAL;
-       }
-
        /* attach controller pointer to irq_data */
        irq_data->intc = intc;
+       irq_data->offset = hw;
+
+       parent_intc = intc->parent;
 
        /* set handler and flags */
        switch (irq_data->type) {
        case S3C_IRQTYPE_NONE:
                return 0;
        case S3C_IRQTYPE_EINT:
-               if (irq_data->parent_irq)
+               /* On the S3C2412, the EINT0to3 have a parent irq
+                * but need the s3c_irq_eint0t4 chip
+                */
+               if (parent_intc && (!soc_is_s3c2412() || hw >= 4))
                        irq_set_chip_and_handler(virq, &s3c_irqext_chip,
                                                 handle_edge_irq);
                else
@@ -352,8 +448,7 @@ static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
                                                 handle_edge_irq);
                break;
        case S3C_IRQTYPE_EDGE:
-               if (irq_data->parent_irq ||
-                   intc->reg_pending == S3C2416_SRCPND2)
+               if (parent_intc || intc->reg_pending == S3C2416_SRCPND2)
                        irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
                                                 handle_edge_irq);
                else
@@ -361,7 +456,7 @@ static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
                                                 handle_edge_irq);
                break;
        case S3C_IRQTYPE_LEVEL:
-               if (irq_data->parent_irq)
+               if (parent_intc)
                        irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
                                                 handle_level_irq);
                else
@@ -372,23 +467,19 @@ static int s3c24xx_irq_map(struct irq_domain *h, unsigned int virq,
                pr_err("irq-s3c24xx: unsupported irqtype %d\n", irq_data->type);
                return -EINVAL;
        }
+
+       irq_set_chip_data(virq, irq_data);
+
        set_irq_flags(virq, IRQF_VALID);
 
-       if (irq_data->parent_irq) {
-               parent_intc = intc->parent;
-               if (!parent_intc) {
-                       pr_err("irq-s3c24xx: no parent controller found for hwirq %lu\n",
-                              hw);
+       if (parent_intc && irq_data->type != S3C_IRQTYPE_NONE) {
+               if (irq_data->parent_irq > 31) {
+                       pr_err("irq-s3c24xx: parent irq %lu is out of range\n",
+                              irq_data->parent_irq);
                        goto err;
                }
 
                parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
-               if (!irq_data) {
-                       pr_err("irq-s3c24xx: no irq data found for hwirq %lu\n",
-                              hw);
-                       goto err;
-               }
-
                parent_irq_data->sub_intc = intc;
                parent_irq_data->sub_bits |= (1UL << hw);
 
@@ -443,7 +534,7 @@ static void s3c24xx_clear_intc(struct s3c_irq_intc *intc)
        }
 }
 
-struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
+static struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
                                       struct s3c_irq_data *irq_data,
                                       struct s3c_irq_intc *parent,
                                       unsigned long address)
@@ -452,7 +543,6 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
        void __iomem *base = (void *)0xf6000000; /* static mapping */
        int irq_num;
        int irq_start;
-       int irq_offset;
        int ret;
 
        intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
@@ -476,7 +566,6 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
                intc->reg_intpnd = base + 0x10;
                irq_num = 32;
                irq_start = S3C2410_IRQ(0);
-               irq_offset = 0;
                break;
        case 0x4a000018:
                pr_debug("irq: found subintc\n");
@@ -484,7 +573,6 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
                intc->reg_mask = base + 0x1c;
                irq_num = 29;
                irq_start = S3C2410_IRQSUB(0);
-               irq_offset = 0;
                break;
        case 0x4a000040:
                pr_debug("irq: found intc2\n");
@@ -493,7 +581,6 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
                intc->reg_intpnd = base + 0x50;
                irq_num = 8;
                irq_start = S3C2416_IRQ(0);
-               irq_offset = 0;
                break;
        case 0x560000a4:
                pr_debug("irq: found eintc\n");
@@ -501,9 +588,8 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
 
                intc->reg_mask = base + 0xa4;
                intc->reg_pending = base + 0x08;
-               irq_num = 20;
+               irq_num = 24;
                irq_start = S3C2410_IRQ(32);
-               irq_offset = 4;
                break;
        default:
                pr_err("irq: unsupported controller address\n");
@@ -514,7 +600,7 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
        /* now that all the data is complete, init the irq-domain */
        s3c24xx_clear_intc(intc);
        intc->domain = irq_domain_add_legacy(np, irq_num, irq_start,
-                                            irq_offset, &s3c24xx_irq_ops,
+                                            0, &s3c24xx_irq_ops,
                                             intc);
        if (!intc->domain) {
                pr_err("irq: could not create irq-domain\n");
@@ -522,6 +608,8 @@ struct s3c_irq_intc *s3c24xx_init_intc(struct device_node *np,
                goto err;
        }
 
+       set_handle_irq(s3c24xx_handle_irq);
+
        return intc;
 
 err:
@@ -529,12 +617,35 @@ err:
        return ERR_PTR(ret);
 }
 
-/* s3c24xx_init_irq
- *
- * Initialise S3C2410 IRQ system
-*/
+static struct s3c_irq_data init_eint[32] = {
+       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT7 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT8 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT9 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT10 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT11 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT12 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT13 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT14 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT15 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT16 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT17 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT18 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT19 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT20 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT21 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT22 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
+};
 
-static struct s3c_irq_data init_base[32] = {
+#ifdef CONFIG_CPU_S3C2410
+static struct s3c_irq_data init_s3c2410base[32] = {
        { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
        { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
        { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
@@ -569,11 +680,80 @@ static struct s3c_irq_data init_base[32] = {
        { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
 };
 
-static struct s3c_irq_data init_eint[32] = {
-       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
-       { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+static struct s3c_irq_data init_s3c2410subint[32] = {
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+};
+
+void __init s3c2410_init_irq(void)
+{
+#ifdef CONFIG_FIQ
+       init_FIQ(FIQ_START);
+#endif
+
+       s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2410base[0], NULL,
+                                       0x4a000000);
+       if (IS_ERR(s3c_intc[0])) {
+               pr_err("irq: could not create main interrupt controller\n");
+               return;
+       }
+
+       s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2410subint[0],
+                                       s3c_intc[0], 0x4a000018);
+       s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+}
+#endif
+
+#ifdef CONFIG_CPU_S3C2412
+static struct s3c_irq_data init_s3c2412base[32] = {
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT0 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT1 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT2 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT3 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
        { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+       { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* SDI/CF */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
        { .type = S3C_IRQTYPE_NONE, }, /* reserved */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+static struct s3c_irq_data init_s3c2412eint[32] = {
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 0 }, /* EINT0 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 1 }, /* EINT1 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 2 }, /* EINT2 */
+       { .type = S3C_IRQTYPE_EINT, .parent_irq = 3 }, /* EINT3 */
        { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT4 */
        { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT5 */
        { .type = S3C_IRQTYPE_EINT, .parent_irq = 4 }, /* EINT6 */
@@ -596,7 +776,7 @@ static struct s3c_irq_data init_eint[32] = {
        { .type = S3C_IRQTYPE_EINT, .parent_irq = 5 }, /* EINT23 */
 };
 
-static struct s3c_irq_data init_subint[32] = {
+static struct s3c_irq_data init_s3c2412subint[32] = {
        { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
        { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
        { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
@@ -608,25 +788,32 @@ static struct s3c_irq_data init_subint[32] = {
        { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
        { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
        { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+       { .type = S3C_IRQTYPE_NONE, },
+       { .type = S3C_IRQTYPE_NONE, },
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* SDI */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 21 }, /* CF */
 };
 
-void __init s3c24xx_init_irq(void)
+void s3c2412_init_irq(void)
 {
-       struct s3c_irq_intc *main_intc;
+       pr_info("S3C2412: IRQ Support\n");
 
 #ifdef CONFIG_FIQ
        init_FIQ(FIQ_START);
 #endif
 
-       main_intc = s3c24xx_init_intc(NULL, &init_base[0], NULL, 0x4a000000);
-       if (IS_ERR(main_intc)) {
+       s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2412base[0], NULL,
+                                       0x4a000000);
+       if (IS_ERR(s3c_intc[0])) {
                pr_err("irq: could not create main interrupt controller\n");
                return;
        }
 
-       s3c24xx_init_intc(NULL, &init_subint[0], main_intc, 0x4a000018);
-       s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
+       s3c24xx_init_intc(NULL, &init_s3c2412eint[0], s3c_intc[0], 0x560000a4);
+       s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2412subint[0],
+                                       s3c_intc[0], 0x4a000018);
 }
+#endif
 
 #ifdef CONFIG_CPU_S3C2416
 static struct s3c_irq_data init_s3c2416base[32] = {
@@ -698,37 +885,185 @@ static struct s3c_irq_data init_s3c2416subint[32] = {
 
 static struct s3c_irq_data init_s3c2416_second[32] = {
        { .type = S3C_IRQTYPE_EDGE }, /* 2D */
-       { .type = S3C_IRQTYPE_EDGE }, /* IIC1 */
+       { .type = S3C_IRQTYPE_NONE }, /* reserved */
        { .type = S3C_IRQTYPE_NONE }, /* reserved */
        { .type = S3C_IRQTYPE_NONE }, /* reserved */
        { .type = S3C_IRQTYPE_EDGE }, /* PCM0 */
-       { .type = S3C_IRQTYPE_EDGE }, /* PCM1 */
+       { .type = S3C_IRQTYPE_NONE }, /* reserved */
        { .type = S3C_IRQTYPE_EDGE }, /* I2S0 */
-       { .type = S3C_IRQTYPE_EDGE }, /* I2S1 */
 };
 
 void __init s3c2416_init_irq(void)
 {
-       struct s3c_irq_intc *main_intc;
-
        pr_info("S3C2416: IRQ Support\n");
 
 #ifdef CONFIG_FIQ
        init_FIQ(FIQ_START);
 #endif
 
-       main_intc = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL, 0x4a000000);
-       if (IS_ERR(main_intc)) {
+       s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2416base[0], NULL,
+                                       0x4a000000);
+       if (IS_ERR(s3c_intc[0])) {
                pr_err("irq: could not create main interrupt controller\n");
                return;
        }
 
-       s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
-       s3c24xx_init_intc(NULL, &init_s3c2416subint[0], main_intc, 0x4a000018);
+       s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+       s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2416subint[0],
+                                       s3c_intc[0], 0x4a000018);
+
+       s3c_intc[2] = s3c24xx_init_intc(NULL, &init_s3c2416_second[0],
+                                       NULL, 0x4a000040);
+}
+
+#endif
+
+#ifdef CONFIG_CPU_S3C2440
+static struct s3c_irq_data init_s3c2440base[32] = {
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
+       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* WDT/AC97 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+static struct s3c_irq_data init_s3c2440subint[32] = {
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* WDT */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 9 }, /* AC97 */
+};
+
+void __init s3c2440_init_irq(void)
+{
+       pr_info("S3C2440: IRQ Support\n");
 
-       s3c24xx_init_intc(NULL, &init_s3c2416_second[0], NULL, 0x4a000040);
+#ifdef CONFIG_FIQ
+       init_FIQ(FIQ_START);
+#endif
+
+       s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2440base[0], NULL,
+                                       0x4a000000);
+       if (IS_ERR(s3c_intc[0])) {
+               pr_err("irq: could not create main interrupt controller\n");
+               return;
+       }
+
+       s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+       s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2440subint[0],
+                                       s3c_intc[0], 0x4a000018);
 }
+#endif
 
+#ifdef CONFIG_CPU_S3C2442
+static struct s3c_irq_data init_s3c2442base[32] = {
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT0 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT1 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT2 */
+       { .type = S3C_IRQTYPE_EINT, }, /* EINT3 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT4to7 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* EINT8to23 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* CAM */
+       { .type = S3C_IRQTYPE_EDGE, }, /* nBATT_FLT */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TICK */
+       { .type = S3C_IRQTYPE_EDGE, }, /* WDT */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* TIMER4 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* LCD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA2 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* DMA3 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SDI */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI0 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART1 */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* NFCON */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBD */
+       { .type = S3C_IRQTYPE_EDGE, }, /* USBH */
+       { .type = S3C_IRQTYPE_EDGE, }, /* IIC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* UART0 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* SPI1 */
+       { .type = S3C_IRQTYPE_EDGE, }, /* RTC */
+       { .type = S3C_IRQTYPE_LEVEL, }, /* ADCPARENT */
+};
+
+static struct s3c_irq_data init_s3c2442subint[32] = {
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 28 }, /* UART0-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 23 }, /* UART1-ERR */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-RX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-TX */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 15 }, /* UART2-ERR */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* TC */
+       { .type = S3C_IRQTYPE_EDGE, .parent_irq = 31 }, /* ADC */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_C */
+       { .type = S3C_IRQTYPE_LEVEL, .parent_irq = 6 }, /* CAM_P */
+};
+
+void __init s3c2442_init_irq(void)
+{
+       pr_info("S3C2442: IRQ Support\n");
+
+#ifdef CONFIG_FIQ
+       init_FIQ(FIQ_START);
+#endif
+
+       s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2442base[0], NULL,
+                                       0x4a000000);
+       if (IS_ERR(s3c_intc[0])) {
+               pr_err("irq: could not create main interrupt controller\n");
+               return;
+       }
+
+       s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+       s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2442subint[0],
+                                       s3c_intc[0], 0x4a000018);
+}
 #endif
 
 #ifdef CONFIG_CPU_S3C2443
@@ -802,21 +1137,219 @@ static struct s3c_irq_data init_s3c2443subint[32] = {
 
 void __init s3c2443_init_irq(void)
 {
-       struct s3c_irq_intc *main_intc;
-
        pr_info("S3C2443: IRQ Support\n");
 
 #ifdef CONFIG_FIQ
        init_FIQ(FIQ_START);
 #endif
 
-       main_intc = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL, 0x4a000000);
-       if (IS_ERR(main_intc)) {
+       s3c_intc[0] = s3c24xx_init_intc(NULL, &init_s3c2443base[0], NULL,
+                                       0x4a000000);
+       if (IS_ERR(s3c_intc[0])) {
                pr_err("irq: could not create main interrupt controller\n");
                return;
        }
 
-       s3c24xx_init_intc(NULL, &init_eint[0], main_intc, 0x560000a4);
-       s3c24xx_init_intc(NULL, &init_s3c2443subint[0], main_intc, 0x4a000018);
+       s3c24xx_init_intc(NULL, &init_eint[0], s3c_intc[0], 0x560000a4);
+       s3c_intc[1] = s3c24xx_init_intc(NULL, &init_s3c2443subint[0],
+                                       s3c_intc[0], 0x4a000018);
+}
+#endif
+
+#ifdef CONFIG_OF
+static int s3c24xx_irq_map_of(struct irq_domain *h, unsigned int virq,
+                                                       irq_hw_number_t hw)
+{
+       unsigned int ctrl_num = hw / 32;
+       unsigned int intc_hw = hw % 32;
+       struct s3c_irq_intc *intc = s3c_intc[ctrl_num];
+       struct s3c_irq_intc *parent_intc = intc->parent;
+       struct s3c_irq_data *irq_data = &intc->irqs[intc_hw];
+
+       /* attach controller pointer to irq_data */
+       irq_data->intc = intc;
+       irq_data->offset = intc_hw;
+
+       if (!parent_intc)
+               irq_set_chip_and_handler(virq, &s3c_irq_chip, handle_edge_irq);
+       else
+               irq_set_chip_and_handler(virq, &s3c_irq_level_chip,
+                                        handle_edge_irq);
+
+       irq_set_chip_data(virq, irq_data);
+
+       set_irq_flags(virq, IRQF_VALID);
+
+       return 0;
+}
+
+/* Translate our of irq notation
+ * format: <ctrl_num ctrl_irq parent_irq type>
+ */
+static int s3c24xx_irq_xlate_of(struct irq_domain *d, struct device_node *n,
+                       const u32 *intspec, unsigned int intsize,
+                       irq_hw_number_t *out_hwirq, unsigned int *out_type)
+{
+       struct s3c_irq_intc *intc;
+       struct s3c_irq_intc *parent_intc;
+       struct s3c_irq_data *irq_data;
+       struct s3c_irq_data *parent_irq_data;
+       int irqno;
+
+       if (WARN_ON(intsize < 4))
+               return -EINVAL;
+
+       if (intspec[0] > 2 || !s3c_intc[intspec[0]]) {
+               pr_err("controller number %d invalid\n", intspec[0]);
+               return -EINVAL;
+       }
+       intc = s3c_intc[intspec[0]];
+
+       *out_hwirq = intspec[0] * 32 + intspec[2];
+       *out_type = intspec[3] & IRQ_TYPE_SENSE_MASK;
+
+       parent_intc = intc->parent;
+       if (parent_intc) {
+               irq_data = &intc->irqs[intspec[2]];
+               irq_data->parent_irq = intspec[1];
+               parent_irq_data = &parent_intc->irqs[irq_data->parent_irq];
+               parent_irq_data->sub_intc = intc;
+               parent_irq_data->sub_bits |= (1UL << intspec[2]);
+
+               /* parent_intc is always s3c_intc[0], so no offset */
+               irqno = irq_create_mapping(parent_intc->domain, intspec[1]);
+               if (irqno < 0) {
+                       pr_err("irq: could not map parent interrupt\n");
+                       return irqno;
+               }
+
+               irq_set_chained_handler(irqno, s3c_irq_demux);
+       }
+
+       return 0;
+}
+
+static struct irq_domain_ops s3c24xx_irq_ops_of = {
+       .map = s3c24xx_irq_map_of,
+       .xlate = s3c24xx_irq_xlate_of,
+};
+
+struct s3c24xx_irq_of_ctrl {
+       char                    *name;
+       unsigned long           offset;
+       struct s3c_irq_intc     **handle;
+       struct s3c_irq_intc     **parent;
+       struct irq_domain_ops   *ops;
+};
+
+static int __init s3c_init_intc_of(struct device_node *np,
+                       struct device_node *interrupt_parent,
+                       struct s3c24xx_irq_of_ctrl *s3c_ctrl, int num_ctrl)
+{
+       struct s3c_irq_intc *intc;
+       struct s3c24xx_irq_of_ctrl *ctrl;
+       struct irq_domain *domain;
+       void __iomem *reg_base;
+       int i;
+
+       reg_base = of_iomap(np, 0);
+       if (!reg_base) {
+               pr_err("irq-s3c24xx: could not map irq registers\n");
+               return -EINVAL;
+       }
+
+       domain = irq_domain_add_linear(np, num_ctrl * 32,
+                                                    &s3c24xx_irq_ops_of, NULL);
+       if (!domain) {
+               pr_err("irq: could not create irq-domain\n");
+               return -EINVAL;
+       }
+
+       for (i = 0; i < num_ctrl; i++) {
+               ctrl = &s3c_ctrl[i];
+
+               pr_debug("irq: found controller %s\n", ctrl->name);
+
+               intc = kzalloc(sizeof(struct s3c_irq_intc), GFP_KERNEL);
+               if (!intc)
+                       return -ENOMEM;
+
+               intc->domain = domain;
+               intc->irqs = kzalloc(sizeof(struct s3c_irq_data) * 32,
+                                    GFP_KERNEL);
+               if (!intc->irqs) {
+                       kfree(intc);
+                       return -ENOMEM;
+               }
+
+               if (ctrl->parent) {
+                       intc->reg_pending = reg_base + ctrl->offset;
+                       intc->reg_mask = reg_base + ctrl->offset + 0x4;
+
+                       if (*(ctrl->parent)) {
+                               intc->parent = *(ctrl->parent);
+                       } else {
+                               pr_warn("irq: parent of %s missing\n",
+                                       ctrl->name);
+                               kfree(intc->irqs);
+                               kfree(intc);
+                               continue;
+                       }
+               } else {
+                       intc->reg_pending = reg_base + ctrl->offset;
+                       intc->reg_mask = reg_base + ctrl->offset + 0x08;
+                       intc->reg_intpnd = reg_base + ctrl->offset + 0x10;
+               }
+
+               s3c24xx_clear_intc(intc);
+               s3c_intc[i] = intc;
+       }
+
+       set_handle_irq(s3c24xx_handle_irq);
+
+       return 0;
+}
+
+static struct s3c24xx_irq_of_ctrl s3c2410_ctrl[] = {
+       {
+               .name = "intc",
+               .offset = 0,
+       }, {
+               .name = "subintc",
+               .offset = 0x18,
+               .parent = &s3c_intc[0],
+       }
+};
+
+int __init s3c2410_init_intc_of(struct device_node *np,
+                       struct device_node *interrupt_parent,
+                       struct s3c24xx_irq_of_ctrl *ctrl, int num_ctrl)
+{
+       return s3c_init_intc_of(np, interrupt_parent,
+                               s3c2410_ctrl, ARRAY_SIZE(s3c2410_ctrl));
+}
+IRQCHIP_DECLARE(s3c2410_irq, "samsung,s3c2410-irq", s3c2410_init_intc_of);
+
+static struct s3c24xx_irq_of_ctrl s3c2416_ctrl[] = {
+       {
+               .name = "intc",
+               .offset = 0,
+       }, {
+               .name = "subintc",
+               .offset = 0x18,
+               .parent = &s3c_intc[0],
+       }, {
+               .name = "intc2",
+               .offset = 0x40,
+       }
+};
+
+int __init s3c2416_init_intc_of(struct device_node *np,
+                       struct device_node *interrupt_parent,
+                       struct s3c24xx_irq_of_ctrl *ctrl, int num_ctrl)
+{
+       return s3c_init_intc_of(np, interrupt_parent,
+                               s3c2416_ctrl, ARRAY_SIZE(s3c2416_ctrl));
 }
+IRQCHIP_DECLARE(s3c2416_irq, "samsung,s3c2416-irq", s3c2416_init_intc_of);
 #endif
similarity index 97%
rename from arch/arm/mach-vt8500/irq.c
rename to drivers/irqchip/irq-vt8500.c
index b9cf5ce9efbbbe7d5557b4cea3c1952095d292a0..d97059550a2cc328fea132189b999d85dc62d887 100644 (file)
@@ -37,6 +37,9 @@
 
 #include <asm/irq.h>
 #include <asm/exception.h>
+#include <asm/mach/irq.h>
+
+#include "irqchip.h"
 
 #define VT8500_ICPC_IRQ                0x20
 #define VT8500_ICPC_FIQ                0x24
@@ -225,6 +228,8 @@ int __init vt8500_irq_init(struct device_node *node, struct device_node *parent)
                goto out;
        }
 
+       set_handle_irq(vt8500_handle_irq);
+
        vt8500_init_irq_hw(intc[active_cnt].base);
 
        pr_info("vt8500-irq: Added interrupt controller\n");
@@ -251,3 +256,4 @@ out:
        return 0;
 }
 
+IRQCHIP_DECLARE(vt8500_irq, "via,vt8500-intc", vt8500_irq_init);
index 5313c9ea44dc906acc7ce2069693bbc94c5be260..d9edcc94c2a878d2636f49ed7e7b682838749266 100644 (file)
@@ -237,7 +237,8 @@ config HISAX_MIC
 
 config HISAX_NETJET
        bool "NETjet card"
-       depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
+       depends on PCI && (BROKEN || !(PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
+       depends on VIRT_TO_BUS
        help
          This enables HiSax support for the NetJet from Traverse
          Technologies.
@@ -248,7 +249,8 @@ config HISAX_NETJET
 
 config HISAX_NETJET_U
        bool "NETspider U card"
-       depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
+       depends on PCI && (BROKEN || !(PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN)))
+       depends on VIRT_TO_BUS
        help
          This enables HiSax support for the Netspider U interface ISDN card
          from Traverse Technologies.
index d8a7d832341436ce62e1dfaacc6b6578ab79e224..ebaebdf30f98dce768d187a7e471ab6455604bd3 100644 (file)
@@ -902,7 +902,9 @@ isdn_tty_send_msg(modem_info *info, atemu *m, char *msg)
        int j;
        int l;
 
-       l = strlen(msg);
+       l = min(strlen(msg), sizeof(cmd.parm) - sizeof(cmd.parm.cmsg)
+               + sizeof(cmd.parm.cmsg.para) - 2);
+
        if (!l) {
                isdn_tty_modem_result(RESULT_ERROR, info);
                return;
index 3c955e10a618c2487422efa8063d1f9924a483cc..c6083132c4b8ccaf21c7addb61cf8596165bf915 100644 (file)
@@ -1025,6 +1025,8 @@ void dm_bufio_prefetch(struct dm_bufio_client *c,
 {
        struct blk_plug plug;
 
+       BUG_ON(dm_bufio_in_request());
+
        blk_start_plug(&plug);
        dm_bufio_lock(c);
 
index fbd3625f27480f2611d81eed181d13f11b3ab7a1..83e995fece88c1330335c85a23ef42b2ed54a1f4 100644 (file)
@@ -83,6 +83,8 @@ struct cache_disk_superblock {
        __le32 read_misses;
        __le32 write_hits;
        __le32 write_misses;
+
+       __le32 policy_version[CACHE_POLICY_VERSION_SIZE];
 } __packed;
 
 struct dm_cache_metadata {
@@ -109,6 +111,7 @@ struct dm_cache_metadata {
        bool clean_when_opened:1;
 
        char policy_name[CACHE_POLICY_NAME_SIZE];
+       unsigned policy_version[CACHE_POLICY_VERSION_SIZE];
        size_t policy_hint_size;
        struct dm_cache_statistics stats;
 };
@@ -268,7 +271,8 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd)
        memset(disk_super->uuid, 0, sizeof(disk_super->uuid));
        disk_super->magic = cpu_to_le64(CACHE_SUPERBLOCK_MAGIC);
        disk_super->version = cpu_to_le32(CACHE_VERSION);
-       memset(disk_super->policy_name, 0, CACHE_POLICY_NAME_SIZE);
+       memset(disk_super->policy_name, 0, sizeof(disk_super->policy_name));
+       memset(disk_super->policy_version, 0, sizeof(disk_super->policy_version));
        disk_super->policy_hint_size = 0;
 
        r = dm_sm_copy_root(cmd->metadata_sm, &disk_super->metadata_space_map_root,
@@ -284,7 +288,6 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd)
        disk_super->metadata_block_size = cpu_to_le32(DM_CACHE_METADATA_BLOCK_SIZE >> SECTOR_SHIFT);
        disk_super->data_block_size = cpu_to_le32(cmd->data_block_size);
        disk_super->cache_blocks = cpu_to_le32(0);
-       memset(disk_super->policy_name, 0, sizeof(disk_super->policy_name));
 
        disk_super->read_hits = cpu_to_le32(0);
        disk_super->read_misses = cpu_to_le32(0);
@@ -478,6 +481,9 @@ static void read_superblock_fields(struct dm_cache_metadata *cmd,
        cmd->data_block_size = le32_to_cpu(disk_super->data_block_size);
        cmd->cache_blocks = to_cblock(le32_to_cpu(disk_super->cache_blocks));
        strncpy(cmd->policy_name, disk_super->policy_name, sizeof(cmd->policy_name));
+       cmd->policy_version[0] = le32_to_cpu(disk_super->policy_version[0]);
+       cmd->policy_version[1] = le32_to_cpu(disk_super->policy_version[1]);
+       cmd->policy_version[2] = le32_to_cpu(disk_super->policy_version[2]);
        cmd->policy_hint_size = le32_to_cpu(disk_super->policy_hint_size);
 
        cmd->stats.read_hits = le32_to_cpu(disk_super->read_hits);
@@ -572,6 +578,9 @@ static int __commit_transaction(struct dm_cache_metadata *cmd,
        disk_super->discard_nr_blocks = cpu_to_le64(from_dblock(cmd->discard_nr_blocks));
        disk_super->cache_blocks = cpu_to_le32(from_cblock(cmd->cache_blocks));
        strncpy(disk_super->policy_name, cmd->policy_name, sizeof(disk_super->policy_name));
+       disk_super->policy_version[0] = cpu_to_le32(cmd->policy_version[0]);
+       disk_super->policy_version[1] = cpu_to_le32(cmd->policy_version[1]);
+       disk_super->policy_version[2] = cpu_to_le32(cmd->policy_version[2]);
 
        disk_super->read_hits = cpu_to_le32(cmd->stats.read_hits);
        disk_super->read_misses = cpu_to_le32(cmd->stats.read_misses);
@@ -854,18 +863,43 @@ struct thunk {
        bool hints_valid;
 };
 
+static bool policy_unchanged(struct dm_cache_metadata *cmd,
+                            struct dm_cache_policy *policy)
+{
+       const char *policy_name = dm_cache_policy_get_name(policy);
+       const unsigned *policy_version = dm_cache_policy_get_version(policy);
+       size_t policy_hint_size = dm_cache_policy_get_hint_size(policy);
+
+       /*
+        * Ensure policy names match.
+        */
+       if (strncmp(cmd->policy_name, policy_name, sizeof(cmd->policy_name)))
+               return false;
+
+       /*
+        * Ensure policy major versions match.
+        */
+       if (cmd->policy_version[0] != policy_version[0])
+               return false;
+
+       /*
+        * Ensure policy hint sizes match.
+        */
+       if (cmd->policy_hint_size != policy_hint_size)
+               return false;
+
+       return true;
+}
+
 static bool hints_array_initialized(struct dm_cache_metadata *cmd)
 {
        return cmd->hint_root && cmd->policy_hint_size;
 }
 
 static bool hints_array_available(struct dm_cache_metadata *cmd,
-                                 const char *policy_name)
+                                 struct dm_cache_policy *policy)
 {
-       bool policy_names_match = !strncmp(cmd->policy_name, policy_name,
-                                          sizeof(cmd->policy_name));
-
-       return cmd->clean_when_opened && policy_names_match &&
+       return cmd->clean_when_opened && policy_unchanged(cmd, policy) &&
                hints_array_initialized(cmd);
 }
 
@@ -899,7 +933,8 @@ static int __load_mapping(void *context, uint64_t cblock, void *leaf)
        return r;
 }
 
-static int __load_mappings(struct dm_cache_metadata *cmd, const char *policy_name,
+static int __load_mappings(struct dm_cache_metadata *cmd,
+                          struct dm_cache_policy *policy,
                           load_mapping_fn fn, void *context)
 {
        struct thunk thunk;
@@ -909,18 +944,19 @@ static int __load_mappings(struct dm_cache_metadata *cmd, const char *policy_nam
 
        thunk.cmd = cmd;
        thunk.respect_dirty_flags = cmd->clean_when_opened;
-       thunk.hints_valid = hints_array_available(cmd, policy_name);
+       thunk.hints_valid = hints_array_available(cmd, policy);
 
        return dm_array_walk(&cmd->info, cmd->root, __load_mapping, &thunk);
 }
 
-int dm_cache_load_mappings(struct dm_cache_metadata *cmd, const char *policy_name,
+int dm_cache_load_mappings(struct dm_cache_metadata *cmd,
+                          struct dm_cache_policy *policy,
                           load_mapping_fn fn, void *context)
 {
        int r;
 
        down_read(&cmd->root_lock);
-       r = __load_mappings(cmd, policy_name, fn, context);
+       r = __load_mappings(cmd, policy, fn, context);
        up_read(&cmd->root_lock);
 
        return r;
@@ -979,7 +1015,7 @@ static int __dirty(struct dm_cache_metadata *cmd, dm_cblock_t cblock, bool dirty
                /* nothing to be done */
                return 0;
 
-       value = pack_value(oblock, flags | (dirty ? M_DIRTY : 0));
+       value = pack_value(oblock, (flags & ~M_DIRTY) | (dirty ? M_DIRTY : 0));
        __dm_bless_for_disk(&value);
 
        r = dm_array_set_value(&cmd->info, cmd->root, from_cblock(cblock),
@@ -1070,13 +1106,15 @@ static int begin_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *po
        __le32 value;
        size_t hint_size;
        const char *policy_name = dm_cache_policy_get_name(policy);
+       const unsigned *policy_version = dm_cache_policy_get_version(policy);
 
        if (!policy_name[0] ||
            (strlen(policy_name) > sizeof(cmd->policy_name) - 1))
                return -EINVAL;
 
-       if (strcmp(cmd->policy_name, policy_name)) {
+       if (!policy_unchanged(cmd, policy)) {
                strncpy(cmd->policy_name, policy_name, sizeof(cmd->policy_name));
+               memcpy(cmd->policy_version, policy_version, sizeof(cmd->policy_version));
 
                hint_size = dm_cache_policy_get_hint_size(policy);
                if (!hint_size)
index 135864ea0eee18343853d950e68a96a227a53622..f45cef21f3d0dac7f5437aac6edf5c2551bd0183 100644 (file)
@@ -89,7 +89,7 @@ typedef int (*load_mapping_fn)(void *context, dm_oblock_t oblock,
                               dm_cblock_t cblock, bool dirty,
                               uint32_t hint, bool hint_valid);
 int dm_cache_load_mappings(struct dm_cache_metadata *cmd,
-                          const char *policy_name,
+                          struct dm_cache_policy *policy,
                           load_mapping_fn fn,
                           void *context);
 
index cc05d70b3cb89a4f8fdcb8cf1887baadca365323..b04d1f904d0763c43870e38c857fcd25baad4b7e 100644 (file)
@@ -17,7 +17,6 @@
 /*----------------------------------------------------------------*/
 
 #define DM_MSG_PREFIX "cache cleaner"
-#define CLEANER_VERSION "1.0.0"
 
 /* Cache entry struct. */
 struct wb_cache_entry {
@@ -434,6 +433,7 @@ static struct dm_cache_policy *wb_create(dm_cblock_t cache_size,
 
 static struct dm_cache_policy_type wb_policy_type = {
        .name = "cleaner",
+       .version = {1, 0, 0},
        .hint_size = 0,
        .owner = THIS_MODULE,
        .create = wb_create
@@ -446,7 +446,10 @@ static int __init wb_init(void)
        if (r < 0)
                DMERR("register failed %d", r);
        else
-               DMINFO("version " CLEANER_VERSION " loaded");
+               DMINFO("version %u.%u.%u loaded",
+                      wb_policy_type.version[0],
+                      wb_policy_type.version[1],
+                      wb_policy_type.version[2]);
 
        return r;
 }
index 52a75beeced59a4ac50a27a7b646bce3d194e668..0928abdc49f023de5a696dd082e160bc65d37cdd 100644 (file)
@@ -117,6 +117,8 @@ void dm_cache_policy_destroy(struct dm_cache_policy *p);
  */
 const char *dm_cache_policy_get_name(struct dm_cache_policy *p);
 
+const unsigned *dm_cache_policy_get_version(struct dm_cache_policy *p);
+
 size_t dm_cache_policy_get_hint_size(struct dm_cache_policy *p);
 
 /*----------------------------------------------------------------*/
index 964153255076bad8a1a24765ec9b7f884af4cd4b..dc112a7137fe9280fca348908ed99b77f36f9417 100644 (file)
@@ -14,7 +14,6 @@
 #include <linux/vmalloc.h>
 
 #define DM_MSG_PREFIX "cache-policy-mq"
-#define MQ_VERSION     "1.0.0"
 
 static struct kmem_cache *mq_entry_cache;
 
@@ -1133,6 +1132,7 @@ bad_cache_alloc:
 
 static struct dm_cache_policy_type mq_policy_type = {
        .name = "mq",
+       .version = {1, 0, 0},
        .hint_size = 4,
        .owner = THIS_MODULE,
        .create = mq_create
@@ -1140,6 +1140,7 @@ static struct dm_cache_policy_type mq_policy_type = {
 
 static struct dm_cache_policy_type default_policy_type = {
        .name = "default",
+       .version = {1, 0, 0},
        .hint_size = 4,
        .owner = THIS_MODULE,
        .create = mq_create
@@ -1164,7 +1165,10 @@ static int __init mq_init(void)
 
        r = dm_cache_policy_register(&default_policy_type);
        if (!r) {
-               DMINFO("version " MQ_VERSION " loaded");
+               DMINFO("version %u.%u.%u loaded",
+                      mq_policy_type.version[0],
+                      mq_policy_type.version[1],
+                      mq_policy_type.version[2]);
                return 0;
        }
 
index 2cbf5fdaac52e8573eed195fe17330c456243bd6..21c03c570c06b7d2bac4bf1abc1d41147d7cd168 100644 (file)
@@ -150,6 +150,14 @@ const char *dm_cache_policy_get_name(struct dm_cache_policy *p)
 }
 EXPORT_SYMBOL_GPL(dm_cache_policy_get_name);
 
+const unsigned *dm_cache_policy_get_version(struct dm_cache_policy *p)
+{
+       struct dm_cache_policy_type *t = p->private;
+
+       return t->version;
+}
+EXPORT_SYMBOL_GPL(dm_cache_policy_get_version);
+
 size_t dm_cache_policy_get_hint_size(struct dm_cache_policy *p)
 {
        struct dm_cache_policy_type *t = p->private;
index f0f51b260544decc116a193fc2a2a45ede286a78..558bdfdabf5f2da39e5bef487dc5008a2399b659 100644 (file)
@@ -196,6 +196,7 @@ struct dm_cache_policy {
  * We maintain a little register of the different policy types.
  */
 #define CACHE_POLICY_NAME_SIZE 16
+#define CACHE_POLICY_VERSION_SIZE 3
 
 struct dm_cache_policy_type {
        /* For use by the register code only. */
@@ -206,6 +207,7 @@ struct dm_cache_policy_type {
         * what gets passed on the target line to select your policy.
         */
        char name[CACHE_POLICY_NAME_SIZE];
+       unsigned version[CACHE_POLICY_VERSION_SIZE];
 
        /*
         * Policies may store a hint for each each cache block.
index 0f4e84b15c303c0de380dbeb6a683f693b1b0592..10744091e6cabb5f6bb55e59709eb4ba0350a98b 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "dm.h"
 #include "dm-bio-prison.h"
+#include "dm-bio-record.h"
 #include "dm-cache-metadata.h"
 
 #include <linux/dm-io.h>
@@ -142,6 +143,7 @@ struct cache {
        spinlock_t lock;
        struct bio_list deferred_bios;
        struct bio_list deferred_flush_bios;
+       struct bio_list deferred_writethrough_bios;
        struct list_head quiesced_migrations;
        struct list_head completed_migrations;
        struct list_head need_commit_migrations;
@@ -158,7 +160,7 @@ struct cache {
        /*
         * origin_blocks entries, discarded if set.
         */
-       sector_t discard_block_size; /* a power of 2 times sectors per block */
+       uint32_t discard_block_size; /* a power of 2 times sectors per block */
        dm_dblock_t discard_nr_blocks;
        unsigned long *discard_bitset;
 
@@ -199,6 +201,16 @@ struct per_bio_data {
        bool tick:1;
        unsigned req_nr:2;
        struct dm_deferred_entry *all_io_entry;
+
+       /*
+        * writethrough fields.  These MUST remain at the end of this
+        * structure and the 'cache' member must be the first as it
+        * is used to determine the offsetof the writethrough fields.
+        */
+       struct cache *cache;
+       dm_cblock_t cblock;
+       bio_end_io_t *saved_bi_end_io;
+       struct dm_bio_details bio_details;
 };
 
 struct dm_cache_migration {
@@ -412,17 +424,24 @@ static bool block_size_is_power_of_two(struct cache *cache)
        return cache->sectors_per_block_shift >= 0;
 }
 
+static dm_block_t block_div(dm_block_t b, uint32_t n)
+{
+       do_div(b, n);
+
+       return b;
+}
+
 static dm_dblock_t oblock_to_dblock(struct cache *cache, dm_oblock_t oblock)
 {
-       sector_t discard_blocks = cache->discard_block_size;
+       uint32_t discard_blocks = cache->discard_block_size;
        dm_block_t b = from_oblock(oblock);
 
        if (!block_size_is_power_of_two(cache))
-               (void) sector_div(discard_blocks, cache->sectors_per_block);
+               discard_blocks = discard_blocks / cache->sectors_per_block;
        else
                discard_blocks >>= cache->sectors_per_block_shift;
 
-       (void) sector_div(b, discard_blocks);
+       b = block_div(b, discard_blocks);
 
        return to_dblock(b);
 }
@@ -500,16 +519,28 @@ static void save_stats(struct cache *cache)
 /*----------------------------------------------------------------
  * Per bio data
  *--------------------------------------------------------------*/
-static struct per_bio_data *get_per_bio_data(struct bio *bio)
+
+/*
+ * If using writeback, leave out struct per_bio_data's writethrough fields.
+ */
+#define PB_DATA_SIZE_WB (offsetof(struct per_bio_data, cache))
+#define PB_DATA_SIZE_WT (sizeof(struct per_bio_data))
+
+static size_t get_per_bio_data_size(struct cache *cache)
 {
-       struct per_bio_data *pb = dm_per_bio_data(bio, sizeof(struct per_bio_data));
+       return cache->features.write_through ? PB_DATA_SIZE_WT : PB_DATA_SIZE_WB;
+}
+
+static struct per_bio_data *get_per_bio_data(struct bio *bio, size_t data_size)
+{
+       struct per_bio_data *pb = dm_per_bio_data(bio, data_size);
        BUG_ON(!pb);
        return pb;
 }
 
-static struct per_bio_data *init_per_bio_data(struct bio *bio)
+static struct per_bio_data *init_per_bio_data(struct bio *bio, size_t data_size)
 {
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       struct per_bio_data *pb = get_per_bio_data(bio, data_size);
 
        pb->tick = false;
        pb->req_nr = dm_bio_get_target_bio_nr(bio);
@@ -543,7 +574,8 @@ static void remap_to_cache(struct cache *cache, struct bio *bio,
 static void check_if_tick_bio_needed(struct cache *cache, struct bio *bio)
 {
        unsigned long flags;
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
+       struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
        spin_lock_irqsave(&cache->lock, flags);
        if (cache->need_tick_bio &&
@@ -609,6 +641,58 @@ static void issue(struct cache *cache, struct bio *bio)
        spin_unlock_irqrestore(&cache->lock, flags);
 }
 
+static void defer_writethrough_bio(struct cache *cache, struct bio *bio)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&cache->lock, flags);
+       bio_list_add(&cache->deferred_writethrough_bios, bio);
+       spin_unlock_irqrestore(&cache->lock, flags);
+
+       wake_worker(cache);
+}
+
+static void writethrough_endio(struct bio *bio, int err)
+{
+       struct per_bio_data *pb = get_per_bio_data(bio, PB_DATA_SIZE_WT);
+       bio->bi_end_io = pb->saved_bi_end_io;
+
+       if (err) {
+               bio_endio(bio, err);
+               return;
+       }
+
+       dm_bio_restore(&pb->bio_details, bio);
+       remap_to_cache(pb->cache, bio, pb->cblock);
+
+       /*
+        * We can't issue this bio directly, since we're in interrupt
+        * context.  So it get's put on a bio list for processing by the
+        * worker thread.
+        */
+       defer_writethrough_bio(pb->cache, bio);
+}
+
+/*
+ * When running in writethrough mode we need to send writes to clean blocks
+ * to both the cache and origin devices.  In future we'd like to clone the
+ * bio and send them in parallel, but for now we're doing them in
+ * series as this is easier.
+ */
+static void remap_to_origin_then_cache(struct cache *cache, struct bio *bio,
+                                      dm_oblock_t oblock, dm_cblock_t cblock)
+{
+       struct per_bio_data *pb = get_per_bio_data(bio, PB_DATA_SIZE_WT);
+
+       pb->cache = cache;
+       pb->cblock = cblock;
+       pb->saved_bi_end_io = bio->bi_end_io;
+       dm_bio_record(&pb->bio_details, bio);
+       bio->bi_end_io = writethrough_endio;
+
+       remap_to_origin_clear_discard(pb->cache, bio, oblock);
+}
+
 /*----------------------------------------------------------------
  * Migration processing
  *
@@ -972,7 +1056,8 @@ static void defer_bio(struct cache *cache, struct bio *bio)
 
 static void process_flush_bio(struct cache *cache, struct bio *bio)
 {
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
+       struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
        BUG_ON(bio->bi_size);
        if (!pb->req_nr)
@@ -1002,7 +1087,7 @@ static void process_discard_bio(struct cache *cache, struct bio *bio)
        dm_block_t end_block = bio->bi_sector + bio_sectors(bio);
        dm_block_t b;
 
-       (void) sector_div(end_block, cache->discard_block_size);
+       end_block = block_div(end_block, cache->discard_block_size);
 
        for (b = start_block; b < end_block; b++)
                set_discard(cache, to_dblock(b));
@@ -1044,7 +1129,8 @@ static void process_bio(struct cache *cache, struct prealloc *structs,
        dm_oblock_t block = get_bio_block(cache, bio);
        struct dm_bio_prison_cell *cell_prealloc, *old_ocell, *new_ocell;
        struct policy_result lookup_result;
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
+       struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
        bool discarded_block = is_discarded_oblock(cache, block);
        bool can_migrate = discarded_block || spare_migration_bandwidth(cache);
 
@@ -1070,14 +1156,9 @@ static void process_bio(struct cache *cache, struct prealloc *structs,
                inc_hit_counter(cache, bio);
                pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
 
-               if (is_writethrough_io(cache, bio, lookup_result.cblock)) {
-                       /*
-                        * No need to mark anything dirty in write through mode.
-                        */
-                       pb->req_nr == 0 ?
-                               remap_to_cache(cache, bio, lookup_result.cblock) :
-                               remap_to_origin_clear_discard(cache, bio, block);
-               } else
+               if (is_writethrough_io(cache, bio, lookup_result.cblock))
+                       remap_to_origin_then_cache(cache, bio, block, lookup_result.cblock);
+               else
                        remap_to_cache_dirty(cache, bio, block, lookup_result.cblock);
 
                issue(cache, bio);
@@ -1086,17 +1167,8 @@ static void process_bio(struct cache *cache, struct prealloc *structs,
        case POLICY_MISS:
                inc_miss_counter(cache, bio);
                pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
-
-               if (pb->req_nr != 0) {
-                       /*
-                        * This is a duplicate writethrough io that is no
-                        * longer needed because the block has been demoted.
-                        */
-                       bio_endio(bio, 0);
-               } else {
-                       remap_to_origin_clear_discard(cache, bio, block);
-                       issue(cache, bio);
-               }
+               remap_to_origin_clear_discard(cache, bio, block);
+               issue(cache, bio);
                break;
 
        case POLICY_NEW:
@@ -1217,6 +1289,23 @@ static void process_deferred_flush_bios(struct cache *cache, bool submit_bios)
                submit_bios ? generic_make_request(bio) : bio_io_error(bio);
 }
 
+static void process_deferred_writethrough_bios(struct cache *cache)
+{
+       unsigned long flags;
+       struct bio_list bios;
+       struct bio *bio;
+
+       bio_list_init(&bios);
+
+       spin_lock_irqsave(&cache->lock, flags);
+       bio_list_merge(&bios, &cache->deferred_writethrough_bios);
+       bio_list_init(&cache->deferred_writethrough_bios);
+       spin_unlock_irqrestore(&cache->lock, flags);
+
+       while ((bio = bio_list_pop(&bios)))
+               generic_make_request(bio);
+}
+
 static void writeback_some_dirty_blocks(struct cache *cache)
 {
        int r = 0;
@@ -1313,6 +1402,7 @@ static int more_work(struct cache *cache)
        else
                return !bio_list_empty(&cache->deferred_bios) ||
                        !bio_list_empty(&cache->deferred_flush_bios) ||
+                       !bio_list_empty(&cache->deferred_writethrough_bios) ||
                        !list_empty(&cache->quiesced_migrations) ||
                        !list_empty(&cache->completed_migrations) ||
                        !list_empty(&cache->need_commit_migrations);
@@ -1331,6 +1421,8 @@ static void do_worker(struct work_struct *ws)
 
                writeback_some_dirty_blocks(cache);
 
+               process_deferred_writethrough_bios(cache);
+
                if (commit_if_needed(cache)) {
                        process_deferred_flush_bios(cache, false);
 
@@ -1756,8 +1848,11 @@ static int create_cache_policy(struct cache *cache, struct cache_args *ca,
        }
 
        r = set_config_values(cache->policy, ca->policy_argc, ca->policy_argv);
-       if (r)
+       if (r) {
+               *error = "Error setting cache policy's config values";
                dm_cache_policy_destroy(cache->policy);
+               cache->policy = NULL;
+       }
 
        return r;
 }
@@ -1793,8 +1888,6 @@ static sector_t calculate_discard_block_size(sector_t cache_block_size,
 
 #define DEFAULT_MIGRATION_THRESHOLD (2048 * 100)
 
-static unsigned cache_num_write_bios(struct dm_target *ti, struct bio *bio);
-
 static int cache_create(struct cache_args *ca, struct cache **result)
 {
        int r = 0;
@@ -1811,7 +1904,6 @@ static int cache_create(struct cache_args *ca, struct cache **result)
 
        cache->ti = ca->ti;
        ti->private = cache;
-       ti->per_bio_data_size = sizeof(struct per_bio_data);
        ti->num_flush_bios = 2;
        ti->flush_supported = true;
 
@@ -1820,9 +1912,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
        ti->discard_zeroes_data_unsupported = true;
 
        memcpy(&cache->features, &ca->features, sizeof(cache->features));
-
-       if (cache->features.write_through)
-               ti->num_write_bios = cache_num_write_bios;
+       ti->per_bio_data_size = get_per_bio_data_size(cache);
 
        cache->callbacks.congested_fn = cache_is_congested;
        dm_table_add_target_callbacks(ti->table, &cache->callbacks);
@@ -1835,7 +1925,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
 
        /* FIXME: factor out this whole section */
        origin_blocks = cache->origin_sectors = ca->origin_sectors;
-       (void) sector_div(origin_blocks, ca->block_size);
+       origin_blocks = block_div(origin_blocks, ca->block_size);
        cache->origin_blocks = to_oblock(origin_blocks);
 
        cache->sectors_per_block = ca->block_size;
@@ -1848,7 +1938,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
                dm_block_t cache_size = ca->cache_sectors;
 
                cache->sectors_per_block_shift = -1;
-               (void) sector_div(cache_size, ca->block_size);
+               cache_size = block_div(cache_size, ca->block_size);
                cache->cache_size = to_cblock(cache_size);
        } else {
                cache->sectors_per_block_shift = __ffs(ca->block_size);
@@ -1873,6 +1963,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
        spin_lock_init(&cache->lock);
        bio_list_init(&cache->deferred_bios);
        bio_list_init(&cache->deferred_flush_bios);
+       bio_list_init(&cache->deferred_writethrough_bios);
        INIT_LIST_HEAD(&cache->quiesced_migrations);
        INIT_LIST_HEAD(&cache->completed_migrations);
        INIT_LIST_HEAD(&cache->need_commit_migrations);
@@ -2002,6 +2093,8 @@ static int cache_ctr(struct dm_target *ti, unsigned argc, char **argv)
                goto out;
 
        r = cache_create(ca, &cache);
+       if (r)
+               goto out;
 
        r = copy_ctr_args(cache, argc - 3, (const char **)argv + 3);
        if (r) {
@@ -2016,26 +2109,13 @@ out:
        return r;
 }
 
-static unsigned cache_num_write_bios(struct dm_target *ti, struct bio *bio)
-{
-       int r;
-       struct cache *cache = ti->private;
-       dm_oblock_t block = get_bio_block(cache, bio);
-       dm_cblock_t cblock;
-
-       r = policy_lookup(cache->policy, block, &cblock);
-       if (r < 0)
-               return 2;       /* assume the worst */
-
-       return (!r && !is_dirty(cache, cblock)) ? 2 : 1;
-}
-
 static int cache_map(struct dm_target *ti, struct bio *bio)
 {
        struct cache *cache = ti->private;
 
        int r;
        dm_oblock_t block = get_bio_block(cache, bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
        bool can_migrate = false;
        bool discarded_block;
        struct dm_bio_prison_cell *cell;
@@ -2052,7 +2132,7 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
                return DM_MAPIO_REMAPPED;
        }
 
-       pb = init_per_bio_data(bio);
+       pb = init_per_bio_data(bio, pb_data_size);
 
        if (bio->bi_rw & (REQ_FLUSH | REQ_FUA | REQ_DISCARD)) {
                defer_bio(cache, bio);
@@ -2097,18 +2177,12 @@ static int cache_map(struct dm_target *ti, struct bio *bio)
                inc_hit_counter(cache, bio);
                pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds);
 
-               if (is_writethrough_io(cache, bio, lookup_result.cblock)) {
-                       /*
-                        * No need to mark anything dirty in write through mode.
-                        */
-                       pb->req_nr == 0 ?
-                               remap_to_cache(cache, bio, lookup_result.cblock) :
-                               remap_to_origin_clear_discard(cache, bio, block);
-                       cell_defer(cache, cell, false);
-               } else {
+               if (is_writethrough_io(cache, bio, lookup_result.cblock))
+                       remap_to_origin_then_cache(cache, bio, block, lookup_result.cblock);
+               else
                        remap_to_cache_dirty(cache, bio, block, lookup_result.cblock);
-                       cell_defer(cache, cell, false);
-               }
+
+               cell_defer(cache, cell, false);
                break;
 
        case POLICY_MISS:
@@ -2143,7 +2217,8 @@ static int cache_end_io(struct dm_target *ti, struct bio *bio, int error)
 {
        struct cache *cache = ti->private;
        unsigned long flags;
-       struct per_bio_data *pb = get_per_bio_data(bio);
+       size_t pb_data_size = get_per_bio_data_size(cache);
+       struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
        if (pb->tick) {
                policy_tick(cache->policy);
@@ -2319,8 +2394,7 @@ static int cache_preresume(struct dm_target *ti)
        }
 
        if (!cache->loaded_mappings) {
-               r = dm_cache_load_mappings(cache->cmd,
-                                          dm_cache_policy_get_name(cache->policy),
+               r = dm_cache_load_mappings(cache->cmd, cache->policy,
                                           load_mapping, cache);
                if (r) {
                        DMERR("could not load cache mappings");
@@ -2535,7 +2609,7 @@ static void cache_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
 static struct target_type cache_target = {
        .name = "cache",
-       .version = {1, 0, 0},
+       .version = {1, 1, 0},
        .module = THIS_MODULE,
        .ctr = cache_ctr,
        .dtr = cache_dtr,
index 009339d628287e9ab124d664677ffa69864732f1..004ad1652b73477dae0194b957842434cf48c38d 100644 (file)
@@ -1577,6 +1577,11 @@ static bool data_dev_supports_discard(struct pool_c *pt)
        return q && blk_queue_discard(q);
 }
 
+static bool is_factor(sector_t block_size, uint32_t n)
+{
+       return !sector_div(block_size, n);
+}
+
 /*
  * If discard_passdown was enabled verify that the data device
  * supports discards.  Disable discard_passdown if not.
@@ -1602,7 +1607,7 @@ static void disable_passdown_if_not_supported(struct pool_c *pt)
        else if (data_limits->discard_granularity > block_size)
                reason = "discard granularity larger than a block";
 
-       else if (block_size & (data_limits->discard_granularity - 1))
+       else if (!is_factor(block_size, data_limits->discard_granularity))
                reason = "discard granularity not a factor of block size";
 
        if (reason) {
@@ -2544,7 +2549,7 @@ static struct target_type pool_target = {
        .name = "thin-pool",
        .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
                    DM_TARGET_IMMUTABLE,
-       .version = {1, 6, 1},
+       .version = {1, 7, 0},
        .module = THIS_MODULE,
        .ctr = pool_ctr,
        .dtr = pool_dtr,
@@ -2831,7 +2836,7 @@ static int thin_iterate_devices(struct dm_target *ti,
 
 static struct target_type thin_target = {
        .name = "thin",
-       .version = {1, 7, 1},
+       .version = {1, 8, 0},
        .module = THIS_MODULE,
        .ctr = thin_ctr,
        .dtr = thin_dtr,
index 6ad538375c3c82ba0d345d2ccab3955b31ab3f30..a746f1d21c661bec7b809c9a688fddf44284581f 100644 (file)
@@ -93,6 +93,13 @@ struct dm_verity_io {
         */
 };
 
+struct dm_verity_prefetch_work {
+       struct work_struct work;
+       struct dm_verity *v;
+       sector_t block;
+       unsigned n_blocks;
+};
+
 static struct shash_desc *io_hash_desc(struct dm_verity *v, struct dm_verity_io *io)
 {
        return (struct shash_desc *)(io + 1);
@@ -424,15 +431,18 @@ static void verity_end_io(struct bio *bio, int error)
  * The root buffer is not prefetched, it is assumed that it will be cached
  * all the time.
  */
-static void verity_prefetch_io(struct dm_verity *v, struct dm_verity_io *io)
+static void verity_prefetch_io(struct work_struct *work)
 {
+       struct dm_verity_prefetch_work *pw =
+               container_of(work, struct dm_verity_prefetch_work, work);
+       struct dm_verity *v = pw->v;
        int i;
 
        for (i = v->levels - 2; i >= 0; i--) {
                sector_t hash_block_start;
                sector_t hash_block_end;
-               verity_hash_at_level(v, io->block, i, &hash_block_start, NULL);
-               verity_hash_at_level(v, io->block + io->n_blocks - 1, i, &hash_block_end, NULL);
+               verity_hash_at_level(v, pw->block, i, &hash_block_start, NULL);
+               verity_hash_at_level(v, pw->block + pw->n_blocks - 1, i, &hash_block_end, NULL);
                if (!i) {
                        unsigned cluster = ACCESS_ONCE(dm_verity_prefetch_cluster);
 
@@ -452,6 +462,25 @@ no_prefetch_cluster:
                dm_bufio_prefetch(v->bufio, hash_block_start,
                                  hash_block_end - hash_block_start + 1);
        }
+
+       kfree(pw);
+}
+
+static void verity_submit_prefetch(struct dm_verity *v, struct dm_verity_io *io)
+{
+       struct dm_verity_prefetch_work *pw;
+
+       pw = kmalloc(sizeof(struct dm_verity_prefetch_work),
+               GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
+
+       if (!pw)
+               return;
+
+       INIT_WORK(&pw->work, verity_prefetch_io);
+       pw->v = v;
+       pw->block = io->block;
+       pw->n_blocks = io->n_blocks;
+       queue_work(v->verify_wq, &pw->work);
 }
 
 /*
@@ -498,7 +527,7 @@ static int verity_map(struct dm_target *ti, struct bio *bio)
        memcpy(io->io_vec, bio_iovec(bio),
               io->io_vec_size * sizeof(struct bio_vec));
 
-       verity_prefetch_io(v, io);
+       verity_submit_prefetch(v, io);
 
        generic_make_request(bio);
 
@@ -858,7 +887,7 @@ bad:
 
 static struct target_type verity_target = {
        .name           = "verity",
-       .version        = {1, 1, 1},
+       .version        = {1, 2, 0},
        .module         = THIS_MODULE,
        .ctr            = verity_ctr,
        .dtr            = verity_dtr,
index fcb878f88796c8ab884da058b36ea5f287fe2eab..aeceedfc530b90b5da5b45e12ffdc9e4d665e16d 100644 (file)
@@ -7663,10 +7663,8 @@ static int remove_and_add_spares(struct mddev *mddev)
                                removed++;
                        }
                }
-       if (removed)
-               sysfs_notify(&mddev->kobj, NULL,
-                            "degraded");
-
+       if (removed && mddev->kobj.sd)
+               sysfs_notify(&mddev->kobj, NULL, "degraded");
 
        rdev_for_each(rdev, mddev) {
                if (rdev->raid_disk >= 0 &&
index eca59c3074ef65bee75301f92411d9968adbaf9d..d90fb1a879e1902200c63117cc9465781a5eb871 100644 (file)
@@ -506,7 +506,7 @@ static inline char * mdname (struct mddev * mddev)
 static inline int sysfs_link_rdev(struct mddev *mddev, struct md_rdev *rdev)
 {
        char nm[20];
-       if (!test_bit(Replacement, &rdev->flags)) {
+       if (!test_bit(Replacement, &rdev->flags) && mddev->kobj.sd) {
                sprintf(nm, "rd%d", rdev->raid_disk);
                return sysfs_create_link(&mddev->kobj, &rdev->kobj, nm);
        } else
@@ -516,7 +516,7 @@ static inline int sysfs_link_rdev(struct mddev *mddev, struct md_rdev *rdev)
 static inline void sysfs_unlink_rdev(struct mddev *mddev, struct md_rdev *rdev)
 {
        char nm[20];
-       if (!test_bit(Replacement, &rdev->flags)) {
+       if (!test_bit(Replacement, &rdev->flags) && mddev->kobj.sd) {
                sprintf(nm, "rd%d", rdev->raid_disk);
                sysfs_remove_link(&mddev->kobj, nm);
        }
index c4f28133ef829340d966393f7e6d9eba6857111d..b88757cd0d1d93728d27d1c1366edf0c45479daf 100644 (file)
@@ -139,15 +139,8 @@ struct child {
        struct btree_node *n;
 };
 
-static struct dm_btree_value_type le64_type = {
-       .context = NULL,
-       .size = sizeof(__le64),
-       .inc = NULL,
-       .dec = NULL,
-       .equal = NULL
-};
-
-static int init_child(struct dm_btree_info *info, struct btree_node *parent,
+static int init_child(struct dm_btree_info *info, struct dm_btree_value_type *vt,
+                     struct btree_node *parent,
                      unsigned index, struct child *result)
 {
        int r, inc;
@@ -164,7 +157,7 @@ static int init_child(struct dm_btree_info *info, struct btree_node *parent,
        result->n = dm_block_data(result->block);
 
        if (inc)
-               inc_children(info->tm, result->n, &le64_type);
+               inc_children(info->tm, result->n, vt);
 
        *((__le64 *) value_ptr(parent, index)) =
                cpu_to_le64(dm_block_location(result->block));
@@ -236,7 +229,7 @@ static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent,
 }
 
 static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
-                     unsigned left_index)
+                     struct dm_btree_value_type *vt, unsigned left_index)
 {
        int r;
        struct btree_node *parent;
@@ -244,11 +237,11 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info,
 
        parent = dm_block_data(shadow_current(s));
 
-       r = init_child(info, parent, left_index, &left);
+       r = init_child(info, vt, parent, left_index, &left);
        if (r)
                return r;
 
-       r = init_child(info, parent, left_index + 1, &right);
+       r = init_child(info, vt, parent, left_index + 1, &right);
        if (r) {
                exit_child(info, &left);
                return r;
@@ -368,7 +361,7 @@ static void __rebalance3(struct dm_btree_info *info, struct btree_node *parent,
 }
 
 static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
-                     unsigned left_index)
+                     struct dm_btree_value_type *vt, unsigned left_index)
 {
        int r;
        struct btree_node *parent = dm_block_data(shadow_current(s));
@@ -377,17 +370,17 @@ static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info,
        /*
         * FIXME: fill out an array?
         */
-       r = init_child(info, parent, left_index, &left);
+       r = init_child(info, vt, parent, left_index, &left);
        if (r)
                return r;
 
-       r = init_child(info, parent, left_index + 1, &center);
+       r = init_child(info, vt, parent, left_index + 1, &center);
        if (r) {
                exit_child(info, &left);
                return r;
        }
 
-       r = init_child(info, parent, left_index + 2, &right);
+       r = init_child(info, vt, parent, left_index + 2, &right);
        if (r) {
                exit_child(info, &left);
                exit_child(info, &center);
@@ -434,7 +427,8 @@ static int get_nr_entries(struct dm_transaction_manager *tm,
 }
 
 static int rebalance_children(struct shadow_spine *s,
-                             struct dm_btree_info *info, uint64_t key)
+                             struct dm_btree_info *info,
+                             struct dm_btree_value_type *vt, uint64_t key)
 {
        int i, r, has_left_sibling, has_right_sibling;
        uint32_t child_entries;
@@ -472,13 +466,13 @@ static int rebalance_children(struct shadow_spine *s,
        has_right_sibling = i < (le32_to_cpu(n->header.nr_entries) - 1);
 
        if (!has_left_sibling)
-               r = rebalance2(s, info, i);
+               r = rebalance2(s, info, vt, i);
 
        else if (!has_right_sibling)
-               r = rebalance2(s, info, i - 1);
+               r = rebalance2(s, info, vt, i - 1);
 
        else
-               r = rebalance3(s, info, i - 1);
+               r = rebalance3(s, info, vt, i - 1);
 
        return r;
 }
@@ -529,7 +523,7 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
                if (le32_to_cpu(n->header.flags) & LEAF_NODE)
                        return do_leaf(n, key, index);
 
-               r = rebalance_children(s, info, key);
+               r = rebalance_children(s, info, vt, key);
                if (r)
                        break;
 
@@ -550,6 +544,14 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info,
        return r;
 }
 
+static struct dm_btree_value_type le64_type = {
+       .context = NULL,
+       .size = sizeof(__le64),
+       .inc = NULL,
+       .dec = NULL,
+       .equal = NULL
+};
+
 int dm_btree_remove(struct dm_btree_info *info, dm_block_t root,
                    uint64_t *keys, dm_block_t *new_root)
 {
index 3ee2912889e7110274acabc28df3c6664abcb0f7..24909eb13fec1b0bf22e40caa4ff7a76967f80e4 100644 (file)
@@ -671,9 +671,11 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                        bi->bi_next = NULL;
                        if (rrdev)
                                set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags);
-                       trace_block_bio_remap(bdev_get_queue(bi->bi_bdev),
-                                             bi, disk_devt(conf->mddev->gendisk),
-                                             sh->dev[i].sector);
+
+                       if (conf->mddev->gendisk)
+                               trace_block_bio_remap(bdev_get_queue(bi->bi_bdev),
+                                                     bi, disk_devt(conf->mddev->gendisk),
+                                                     sh->dev[i].sector);
                        generic_make_request(bi);
                }
                if (rrdev) {
@@ -701,9 +703,10 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s)
                        rbi->bi_io_vec[0].bv_offset = 0;
                        rbi->bi_size = STRIPE_SIZE;
                        rbi->bi_next = NULL;
-                       trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev),
-                                             rbi, disk_devt(conf->mddev->gendisk),
-                                             sh->dev[i].sector);
+                       if (conf->mddev->gendisk)
+                               trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev),
+                                                     rbi, disk_devt(conf->mddev->gendisk),
+                                                     sh->dev[i].sector);
                        generic_make_request(rbi);
                }
                if (!rdev && !rrdev) {
@@ -2280,17 +2283,6 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,
        int level = conf->level;
 
        if (rcw) {
-               /* if we are not expanding this is a proper write request, and
-                * there will be bios with new data to be drained into the
-                * stripe cache
-                */
-               if (!expand) {
-                       sh->reconstruct_state = reconstruct_state_drain_run;
-                       set_bit(STRIPE_OP_BIODRAIN, &s->ops_request);
-               } else
-                       sh->reconstruct_state = reconstruct_state_run;
-
-               set_bit(STRIPE_OP_RECONSTRUCT, &s->ops_request);
 
                for (i = disks; i--; ) {
                        struct r5dev *dev = &sh->dev[i];
@@ -2303,6 +2295,21 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,
                                s->locked++;
                        }
                }
+               /* if we are not expanding this is a proper write request, and
+                * there will be bios with new data to be drained into the
+                * stripe cache
+                */
+               if (!expand) {
+                       if (!s->locked)
+                               /* False alarm, nothing to do */
+                               return;
+                       sh->reconstruct_state = reconstruct_state_drain_run;
+                       set_bit(STRIPE_OP_BIODRAIN, &s->ops_request);
+               } else
+                       sh->reconstruct_state = reconstruct_state_run;
+
+               set_bit(STRIPE_OP_RECONSTRUCT, &s->ops_request);
+
                if (s->locked + conf->max_degraded == disks)
                        if (!test_and_set_bit(STRIPE_FULL_WRITE, &sh->state))
                                atomic_inc(&conf->pending_full_writes);
@@ -2311,11 +2318,6 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,
                BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) ||
                        test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags)));
 
-               sh->reconstruct_state = reconstruct_state_prexor_drain_run;
-               set_bit(STRIPE_OP_PREXOR, &s->ops_request);
-               set_bit(STRIPE_OP_BIODRAIN, &s->ops_request);
-               set_bit(STRIPE_OP_RECONSTRUCT, &s->ops_request);
-
                for (i = disks; i--; ) {
                        struct r5dev *dev = &sh->dev[i];
                        if (i == pd_idx)
@@ -2330,6 +2332,13 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s,
                                s->locked++;
                        }
                }
+               if (!s->locked)
+                       /* False alarm - nothing to do */
+                       return;
+               sh->reconstruct_state = reconstruct_state_prexor_drain_run;
+               set_bit(STRIPE_OP_PREXOR, &s->ops_request);
+               set_bit(STRIPE_OP_BIODRAIN, &s->ops_request);
+               set_bit(STRIPE_OP_RECONSTRUCT, &s->ops_request);
        }
 
        /* keep the parity disk(s) locked while asynchronous operations
@@ -2564,6 +2573,8 @@ handle_failed_sync(struct r5conf *conf, struct stripe_head *sh,
        int i;
 
        clear_bit(STRIPE_SYNCING, &sh->state);
+       if (test_and_clear_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags))
+               wake_up(&conf->wait_for_overlap);
        s->syncing = 0;
        s->replacing = 0;
        /* There is nothing more to do for sync/check/repair.
@@ -2737,6 +2748,7 @@ static void handle_stripe_clean_event(struct r5conf *conf,
 {
        int i;
        struct r5dev *dev;
+       int discard_pending = 0;
 
        for (i = disks; i--; )
                if (sh->dev[i].written) {
@@ -2765,9 +2777,23 @@ static void handle_stripe_clean_event(struct r5conf *conf,
                                                STRIPE_SECTORS,
                                         !test_bit(STRIPE_DEGRADED, &sh->state),
                                                0);
-                       }
-               } else if (test_bit(R5_Discard, &sh->dev[i].flags))
-                       clear_bit(R5_Discard, &sh->dev[i].flags);
+                       } else if (test_bit(R5_Discard, &dev->flags))
+                               discard_pending = 1;
+               }
+       if (!discard_pending &&
+           test_bit(R5_Discard, &sh->dev[sh->pd_idx].flags)) {
+               clear_bit(R5_Discard, &sh->dev[sh->pd_idx].flags);
+               clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags);
+               if (sh->qd_idx >= 0) {
+                       clear_bit(R5_Discard, &sh->dev[sh->qd_idx].flags);
+                       clear_bit(R5_UPTODATE, &sh->dev[sh->qd_idx].flags);
+               }
+               /* now that discard is done we can proceed with any sync */
+               clear_bit(STRIPE_DISCARD, &sh->state);
+               if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state))
+                       set_bit(STRIPE_HANDLE, &sh->state);
+
+       }
 
        if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state))
                if (atomic_dec_and_test(&conf->pending_full_writes))
@@ -2826,8 +2852,10 @@ static void handle_stripe_dirtying(struct r5conf *conf,
        set_bit(STRIPE_HANDLE, &sh->state);
        if (rmw < rcw && rmw > 0) {
                /* prefer read-modify-write, but need to get some data */
-               blk_add_trace_msg(conf->mddev->queue, "raid5 rmw %llu %d",
-                                 (unsigned long long)sh->sector, rmw);
+               if (conf->mddev->queue)
+                       blk_add_trace_msg(conf->mddev->queue,
+                                         "raid5 rmw %llu %d",
+                                         (unsigned long long)sh->sector, rmw);
                for (i = disks; i--; ) {
                        struct r5dev *dev = &sh->dev[i];
                        if ((dev->towrite || i == sh->pd_idx) &&
@@ -2877,7 +2905,7 @@ static void handle_stripe_dirtying(struct r5conf *conf,
                                }
                        }
                }
-               if (rcw)
+               if (rcw && conf->mddev->queue)
                        blk_add_trace_msg(conf->mddev->queue, "raid5 rcw %llu %d %d %d",
                                          (unsigned long long)sh->sector,
                                          rcw, qread, test_bit(STRIPE_DELAYED, &sh->state));
@@ -3417,9 +3445,15 @@ static void handle_stripe(struct stripe_head *sh)
                return;
        }
 
-       if (test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
-               set_bit(STRIPE_SYNCING, &sh->state);
-               clear_bit(STRIPE_INSYNC, &sh->state);
+       if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
+               spin_lock(&sh->stripe_lock);
+               /* Cannot process 'sync' concurrently with 'discard' */
+               if (!test_bit(STRIPE_DISCARD, &sh->state) &&
+                   test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
+                       set_bit(STRIPE_SYNCING, &sh->state);
+                       clear_bit(STRIPE_INSYNC, &sh->state);
+               }
+               spin_unlock(&sh->stripe_lock);
        }
        clear_bit(STRIPE_DELAYED, &sh->state);
 
@@ -3579,6 +3613,8 @@ static void handle_stripe(struct stripe_head *sh)
            test_bit(STRIPE_INSYNC, &sh->state)) {
                md_done_sync(conf->mddev, STRIPE_SECTORS, 1);
                clear_bit(STRIPE_SYNCING, &sh->state);
+               if (test_and_clear_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags))
+                       wake_up(&conf->wait_for_overlap);
        }
 
        /* If the failed drives are just a ReadError, then we might need
@@ -3982,9 +4018,10 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio)
                atomic_inc(&conf->active_aligned_reads);
                spin_unlock_irq(&conf->device_lock);
 
-               trace_block_bio_remap(bdev_get_queue(align_bi->bi_bdev),
-                                     align_bi, disk_devt(mddev->gendisk),
-                                     raid_bio->bi_sector);
+               if (mddev->gendisk)
+                       trace_block_bio_remap(bdev_get_queue(align_bi->bi_bdev),
+                                             align_bi, disk_devt(mddev->gendisk),
+                                             raid_bio->bi_sector);
                generic_make_request(align_bi);
                return 1;
        } else {
@@ -4078,7 +4115,8 @@ static void raid5_unplug(struct blk_plug_cb *blk_cb, bool from_schedule)
                }
                spin_unlock_irq(&conf->device_lock);
        }
-       trace_block_unplug(mddev->queue, cnt, !from_schedule);
+       if (mddev->queue)
+               trace_block_unplug(mddev->queue, cnt, !from_schedule);
        kfree(cb);
 }
 
@@ -4141,6 +4179,13 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi)
                sh = get_active_stripe(conf, logical_sector, 0, 0, 0);
                prepare_to_wait(&conf->wait_for_overlap, &w,
                                TASK_UNINTERRUPTIBLE);
+               set_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags);
+               if (test_bit(STRIPE_SYNCING, &sh->state)) {
+                       release_stripe(sh);
+                       schedule();
+                       goto again;
+               }
+               clear_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags);
                spin_lock_irq(&sh->stripe_lock);
                for (d = 0; d < conf->raid_disks; d++) {
                        if (d == sh->pd_idx || d == sh->qd_idx)
@@ -4153,6 +4198,7 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi)
                                goto again;
                        }
                }
+               set_bit(STRIPE_DISCARD, &sh->state);
                finish_wait(&conf->wait_for_overlap, &w);
                for (d = 0; d < conf->raid_disks; d++) {
                        if (d == sh->pd_idx || d == sh->qd_idx)
index 18b2c4a8a1fdf55af4af03ccd5ca71d2e84db1cb..b0b663b119a8f324ba7fa3b58953b42c81030fa4 100644 (file)
@@ -221,10 +221,6 @@ struct stripe_head {
        struct stripe_operations {
                int                  target, target2;
                enum sum_check_flags zero_sum_result;
-               #ifdef CONFIG_MULTICORE_RAID456
-               unsigned long        request;
-               wait_queue_head_t    wait_for_ops;
-               #endif
        } ops;
        struct r5dev {
                /* rreq and rvec are used for the replacement device when
@@ -323,6 +319,7 @@ enum {
        STRIPE_COMPUTE_RUN,
        STRIPE_OPS_REQ_PENDING,
        STRIPE_ON_UNPLUG_LIST,
+       STRIPE_DISCARD,
 };
 
 /*
index d4e7567b367c04d25b9a21ba4c50d0db314596aa..0b899cb6cda1904b6f07cdb924f94be3d76ccb56 100644 (file)
@@ -724,7 +724,7 @@ static int m5mols_s_stream(struct v4l2_subdev *sd, int enable)
        if (enable) {
                if (is_code(code, M5MOLS_RESTYPE_MONITOR))
                        ret = m5mols_start_monitor(info);
-               if (is_code(code, M5MOLS_RESTYPE_CAPTURE))
+               else if (is_code(code, M5MOLS_RESTYPE_CAPTURE))
                        ret = m5mols_start_capture(info);
                else
                        ret = -EINVAL;
index ccd18e4ee7892e62034a0d9b1e351107fb787749..54579e4c740b4da7f8590ad345145553d63d8062 100644 (file)
@@ -250,17 +250,19 @@ static u8 SRAM_Table[][60] =
    vdelay      start of active video in 2 * field lines relative to
                trailing edge of /VRESET pulse (VDELAY register).
    sheight     height of active video in 2 * field lines.
+   extraheight Added to sheight for cropcap.bounds.height only
    videostart0 ITU-R frame line number of the line corresponding
                to vdelay in the first field. */
 #define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth,     \
-               vdelay, sheight, videostart0)                            \
+               vdelay, sheight, extraheight, videostart0)               \
        .cropcap.bounds.left = minhdelayx1,                              \
        /* * 2 because vertically we count field lines times two, */     \
        /* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */           \
        .cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \
        /* 4 is a safety margin at the end of the line. */               \
        .cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4,        \
-       .cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY,      \
+       .cropcap.bounds.height = (sheight) + (extraheight) + (vdelay) -  \
+                                MIN_VDELAY,                             \
        .cropcap.defrect.left = hdelayx1,                                \
        .cropcap.defrect.top = (videostart0) * 2,                        \
        .cropcap.defrect.width = swidth,                                 \
@@ -301,9 +303,10 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                        /* totalwidth */ 1135,
                        /* sqwidth */ 944,
                        /* vdelay */ 0x20,
-               /* bt878 (and bt848?) can capture another
-                  line below active video. */
-                       /* sheight */ (576 + 2) + 0x20 - 2,
+                       /* sheight */ 576,
+                       /* bt878 (and bt848?) can capture another
+                          line below active video. */
+                       /* extraheight */ 2,
                        /* videostart0 */ 23)
        },{
                .v4l2_id        = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR,
@@ -330,6 +333,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                        /* sqwidth */ 780,
                        /* vdelay */ 0x1a,
                        /* sheight */ 480,
+                       /* extraheight */ 0,
                        /* videostart0 */ 23)
        },{
                .v4l2_id        = V4L2_STD_SECAM,
@@ -355,6 +359,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                        /* sqwidth */ 944,
                        /* vdelay */ 0x20,
                        /* sheight */ 576,
+                       /* extraheight */ 0,
                        /* videostart0 */ 23)
        },{
                .v4l2_id        = V4L2_STD_PAL_Nc,
@@ -380,6 +385,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                        /* sqwidth */ 780,
                        /* vdelay */ 0x1a,
                        /* sheight */ 576,
+                       /* extraheight */ 0,
                        /* videostart0 */ 23)
        },{
                .v4l2_id        = V4L2_STD_PAL_M,
@@ -405,6 +411,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                        /* sqwidth */ 780,
                        /* vdelay */ 0x1a,
                        /* sheight */ 480,
+                       /* extraheight */ 0,
                        /* videostart0 */ 23)
        },{
                .v4l2_id        = V4L2_STD_PAL_N,
@@ -430,6 +437,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                        /* sqwidth */ 944,
                        /* vdelay */ 0x20,
                        /* sheight */ 576,
+                       /* extraheight */ 0,
                        /* videostart0 */ 23)
        },{
                .v4l2_id        = V4L2_STD_NTSC_M_JP,
@@ -455,6 +463,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                        /* sqwidth */ 780,
                        /* vdelay */ 0x16,
                        /* sheight */ 480,
+                       /* extraheight */ 0,
                        /* videostart0 */ 23)
        },{
                /* that one hopefully works with the strange timing
@@ -484,6 +493,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = {
                        /* sqwidth */ 944,
                        /* vdelay */ 0x1a,
                        /* sheight */ 480,
+                       /* extraheight */ 0,
                        /* videostart0 */ 23)
        }
 };
index 05d7b6333461c68f5aaeb919ad1c9dc584cf5952..a0639e77997357d96422568422e2ef28c12a2772 100644 (file)
@@ -204,7 +204,7 @@ config VIDEO_SAMSUNG_EXYNOS_GSC
 
 config VIDEO_SH_VEU
        tristate "SuperH VEU mem2mem video processing driver"
-       depends on VIDEO_DEV && VIDEO_V4L2
+       depends on VIDEO_DEV && VIDEO_V4L2 && GENERIC_HARDIRQS
        select VIDEOBUF2_DMA_CONTIG
        select V4L2_MEM2MEM_DEV
        help
index 82d9f6ac12f3a271481e106df7f75017b3f962c1..33b5ffc8d66dfe136e2cd0df4129963b6c60ad79 100644 (file)
@@ -1054,16 +1054,18 @@ static int gsc_m2m_suspend(struct gsc_dev *gsc)
 
 static int gsc_m2m_resume(struct gsc_dev *gsc)
 {
+       struct gsc_ctx *ctx;
        unsigned long flags;
 
        spin_lock_irqsave(&gsc->slock, flags);
        /* Clear for full H/W setup in first run after resume */
+       ctx = gsc->m2m.ctx;
        gsc->m2m.ctx = NULL;
        spin_unlock_irqrestore(&gsc->slock, flags);
 
        if (test_and_clear_bit(ST_M2M_SUSPENDED, &gsc->state))
-               gsc_m2m_job_finish(gsc->m2m.ctx,
-                                   VB2_BUF_STATE_ERROR);
+               gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
+
        return 0;
 }
 
@@ -1204,7 +1206,7 @@ static int gsc_resume(struct device *dev)
        /* Do not resume if the device was idle before system suspend */
        spin_lock_irqsave(&gsc->slock, flags);
        if (!test_and_clear_bit(ST_SUSPEND, &gsc->state) ||
-           !gsc_m2m_active(gsc)) {
+           !gsc_m2m_opened(gsc)) {
                spin_unlock_irqrestore(&gsc->slock, flags);
                return 0;
        }
index e3916bde45cf13a4cb92b8bcd83715b1c1a07ce0..0f513dd19f86de105f36913a6d5e6e59839fd91a 100644 (file)
@@ -850,16 +850,18 @@ static int fimc_m2m_suspend(struct fimc_dev *fimc)
 
 static int fimc_m2m_resume(struct fimc_dev *fimc)
 {
+       struct fimc_ctx *ctx;
        unsigned long flags;
 
        spin_lock_irqsave(&fimc->slock, flags);
        /* Clear for full H/W setup in first run after resume */
+       ctx = fimc->m2m.ctx;
        fimc->m2m.ctx = NULL;
        spin_unlock_irqrestore(&fimc->slock, flags);
 
        if (test_and_clear_bit(ST_M2M_SUSPENDED, &fimc->state))
-               fimc_m2m_job_finish(fimc->m2m.ctx,
-                                   VB2_BUF_STATE_ERROR);
+               fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
+
        return 0;
 }
 
index f0af0754a7b46a04cee5f41552ede4d8bc2e96ed..ac9663ce2a4927a0a3249bde33107fb1a17a9783 100644 (file)
@@ -128,10 +128,10 @@ static const u32 src_pixfmt_map[8][3] = {
 void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f)
 {
        enum v4l2_mbus_pixelcode pixelcode = dev->fmt->mbus_code;
-       unsigned int i = ARRAY_SIZE(src_pixfmt_map);
+       int i = ARRAY_SIZE(src_pixfmt_map);
        u32 cfg;
 
-       while (i-- >= 0) {
+       while (--i >= 0) {
                if (src_pixfmt_map[i][0] == pixelcode)
                        break;
        }
@@ -224,9 +224,9 @@ static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f)
                { V4L2_MBUS_FMT_VYUY8_2X8, FLITE_REG_CIODMAFMT_CRYCBY },
        };
        u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT);
-       unsigned int i = ARRAY_SIZE(pixcode);
+       int i = ARRAY_SIZE(pixcode);
 
-       while (i-- >= 0)
+       while (--i >= 0)
                if (pixcode[i][0] == dev->fmt->mbus_code)
                        break;
        cfg &= ~FLITE_REG_CIODMAFMT_YCBCR_ORDER_MASK;
index bfc4206935c85a93fa75b6893e3afdcc8efb7c92..bbc35de7db278fe053c6de4d02be7fc7c40d4321 100644 (file)
@@ -1408,6 +1408,7 @@ static const struct v4l2_ctrl_config fimc_lite_ctrl = {
        .id     = V4L2_CTRL_CLASS_USER | 0x1001,
        .type   = V4L2_CTRL_TYPE_BOOLEAN,
        .name   = "Test Pattern 640x480",
+       .step   = 1,
 };
 
 static int fimc_lite_create_capture_subdev(struct fimc_lite *fimc)
index a17fcb2d5d413ca66ed9a16a31a34045a83a0d6b..cd38d708ab584ef4487d4d1960aabe06d6b7138b 100644 (file)
@@ -827,7 +827,7 @@ static int fimc_md_link_notify(struct media_pad *source,
        struct fimc_pipeline *pipeline;
        struct v4l2_subdev *sd;
        struct mutex *lock;
-       int ret = 0;
+       int i, ret = 0;
        int ref_count;
 
        if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
@@ -854,29 +854,28 @@ static int fimc_md_link_notify(struct media_pad *source,
                return 0;
        }
 
+       mutex_lock(lock);
+       ref_count = fimc ? fimc->vid_cap.refcnt : fimc_lite->ref_count;
+
        if (!(flags & MEDIA_LNK_FL_ENABLED)) {
-               int i;
-               mutex_lock(lock);
-               ret = __fimc_pipeline_close(pipeline);
+               if (ref_count > 0) {
+                       ret = __fimc_pipeline_close(pipeline);
+                       if (!ret && fimc)
+                               fimc_ctrls_delete(fimc->vid_cap.ctx);
+               }
                for (i = 0; i < IDX_MAX; i++)
                        pipeline->subdevs[i] = NULL;
-               if (fimc)
-                       fimc_ctrls_delete(fimc->vid_cap.ctx);
-               mutex_unlock(lock);
-               return ret;
+       } else if (ref_count > 0) {
+               /*
+                * Link activation. Enable power of pipeline elements only if
+                * the pipeline is already in use, i.e. its video node is open.
+                * Recreate the controls destroyed during the link deactivation.
+                */
+               ret = __fimc_pipeline_open(pipeline,
+                                          source->entity, true);
+               if (!ret && fimc)
+                       ret = fimc_capture_ctrls_create(fimc);
        }
-       /*
-        * Link activation. Enable power of pipeline elements only if the
-        * pipeline is already in use, i.e. its video node is opened.
-        * Recreate the controls destroyed during the link deactivation.
-        */
-       mutex_lock(lock);
-
-       ref_count = fimc ? fimc->vid_cap.refcnt : fimc_lite->ref_count;
-       if (ref_count > 0)
-               ret = __fimc_pipeline_open(pipeline, source->entity, true);
-       if (!ret && fimc)
-               ret = fimc_capture_ctrls_create(fimc);
 
        mutex_unlock(lock);
        return ret ? -EPIPE : ret;
index e84703c314ce0d50a9861cf674244b9a3342615f..1cb6d57987c6f2dd06e0ff8d8965d0c02179039e 100644 (file)
@@ -276,7 +276,7 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err)
        unsigned int frame_type;
 
        dspl_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev);
-       frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
+       frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_disp_frame_type, ctx);
 
        /* If frame is same as previous then skip and do not dequeue */
        if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) {
index 2356fd52a169abf2680dd22ebb9e17453c4ac52d..4f6b553c4b2de90f6686f2da38cf5221f68c352d 100644 (file)
@@ -232,6 +232,7 @@ static struct mfc_control controls[] = {
                .minimum = 0,
                .maximum = 1,
                .default_value = 0,
+               .step = 1,
                .menu_skip_mask = 0,
        },
        {
index c61f590029ad7c05ef75911c69e5fdbe50f24e8e..348dafc0318aae60de8d18660334cb5244e2dd98 100644 (file)
@@ -347,9 +347,20 @@ static void usb_ma901radio_release(struct v4l2_device *v4l2_dev)
 static int usb_ma901radio_probe(struct usb_interface *intf,
                                const struct usb_device_id *id)
 {
+       struct usb_device *dev = interface_to_usbdev(intf);
        struct ma901radio_device *radio;
        int retval = 0;
 
+       /* Masterkit MA901 usb radio has the same USB ID as many others
+        * Atmel V-USB devices. Let's make additional checks to be sure
+        * that this is our device.
+        */
+
+       if (dev->product && dev->manufacturer &&
+               (strncmp(dev->product, "MA901", 5) != 0
+               || strncmp(dev->manufacturer, "www.masterkit.ru", 16) != 0))
+               return -ENODEV;
+
        radio = kzalloc(sizeof(struct ma901radio_device), GFP_KERNEL);
        if (!radio) {
                dev_err(&intf->dev, "kzalloc for ma901radio_device failed\n");
index 19f3563c61da651673b5ea7884b43b8e4c2145e1..5a79c333d45e66308e5b0f75cbc91ed9d60ce329 100644 (file)
@@ -291,7 +291,7 @@ config IR_TTUSBIR
 
 config IR_RX51
        tristate "Nokia N900 IR transmitter diode"
-       depends on OMAP_DM_TIMER && LIRC && !ARCH_MULTIPLATFORM
+       depends on OMAP_DM_TIMER && ARCH_OMAP2PLUS && LIRC && !ARCH_MULTIPLATFORM
        ---help---
           Say Y or M here if you want to enable support for the IR
           transmitter diode built in the Nokia N900 (RX51) device.
index a9d355230e8eb2efb52fb3fbdff2a5b8297a7a73..768aaf62d5dc300a7b2d7e150265e27035ef15cb 100644 (file)
@@ -10,7 +10,7 @@ ifeq ($(CONFIG_COMPAT),y)
   videodev-objs += v4l2-compat-ioctl32.o
 endif
 
-obj-$(CONFIG_VIDEO_DEV) += videodev.o
+obj-$(CONFIG_VIDEO_V4L2) += videodev.o
 obj-$(CONFIG_VIDEO_V4L2_INT_DEVICE) += v4l2-int-device.o
 obj-$(CONFIG_VIDEO_V4L2) += v4l2-common.o
 
index 671f5b171c737d78c9659d2afe3a68e02fd3981f..c346941a251593bbe42bd8f3d3171acc6a93c2cf 100644 (file)
@@ -858,6 +858,7 @@ config EZX_PCAP
 config AB8500_CORE
        bool "ST-Ericsson AB8500 Mixed Signal Power Management chip"
        depends on GENERIC_HARDIRQS && ABX500_CORE && MFD_DB8500_PRCMU
+       select POWER_SUPPLY
        select MFD_CORE
        select IRQ_DOMAIN
        help
index b1f3561b023f0aaa4939bc469e3c0a40a718d0db..5f341a50ee5a5783e6e84118124e9efcfe177bd3 100644 (file)
@@ -594,9 +594,12 @@ static int ab8500_gpadc_runtime_suspend(struct device *dev)
 static int ab8500_gpadc_runtime_resume(struct device *dev)
 {
        struct ab8500_gpadc *gpadc = dev_get_drvdata(dev);
+       int ret;
 
-       regulator_enable(gpadc->regu);
-       return 0;
+       ret = regulator_enable(gpadc->regu);
+       if (ret)
+               dev_err(dev, "Failed to enable vtvout LDO: %d\n", ret);
+       return ret;
 }
 
 static int ab8500_gpadc_runtime_idle(struct device *dev)
@@ -643,7 +646,7 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
        }
 
        /* VTVout LDO used to power up ab8500-GPADC */
-       gpadc->regu = regulator_get(&pdev->dev, "vddadc");
+       gpadc->regu = devm_regulator_get(&pdev->dev, "vddadc");
        if (IS_ERR(gpadc->regu)) {
                ret = PTR_ERR(gpadc->regu);
                dev_err(gpadc->dev, "failed to get vtvout LDO\n");
@@ -652,7 +655,11 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, gpadc);
 
-       regulator_enable(gpadc->regu);
+       ret = regulator_enable(gpadc->regu);
+       if (ret) {
+               dev_err(gpadc->dev, "Failed to enable vtvout LDO: %d\n", ret);
+               goto fail_enable;
+       }
 
        pm_runtime_set_autosuspend_delay(gpadc->dev, GPADC_AUDOSUSPEND_DELAY);
        pm_runtime_use_autosuspend(gpadc->dev);
@@ -663,6 +670,8 @@ static int ab8500_gpadc_probe(struct platform_device *pdev)
        list_add_tail(&gpadc->node, &ab8500_gpadc_list);
        dev_dbg(gpadc->dev, "probe success\n");
        return 0;
+
+fail_enable:
 fail_irq:
        free_irq(gpadc->irq, gpadc);
 fail:
index 6b5edf64de2b3a4eafbdc0ace93a5a4bd2d4caea..4febc5c7fdeece4a87be9c2dca0eb642357d4cc7 100644 (file)
@@ -460,15 +460,15 @@ static void omap_usbhs_init(struct device *dev)
 
        switch (omap->usbhs_rev) {
        case OMAP_USBHS_REV1:
-               omap_usbhs_rev1_hostconfig(omap, reg);
+               reg = omap_usbhs_rev1_hostconfig(omap, reg);
                break;
 
        case OMAP_USBHS_REV2:
-               omap_usbhs_rev2_hostconfig(omap, reg);
+               reg = omap_usbhs_rev2_hostconfig(omap, reg);
                break;
 
        default:        /* newer revisions */
-               omap_usbhs_rev2_hostconfig(omap, reg);
+               reg = omap_usbhs_rev2_hostconfig(omap, reg);
                break;
        }
 
index bbdbc50a3ccadb7ec98d5d6cd6176c36b9d85a50..73bf76df1044cc70b04bc383d2ad7ec9384a7fcc 100644 (file)
@@ -257,9 +257,24 @@ static struct regmap_irq_chip palmas_irq_chip = {
                        PALMAS_INT1_MASK),
 };
 
-static void palmas_dt_to_pdata(struct device_node *node,
+static int palmas_set_pdata_irq_flag(struct i2c_client *i2c,
                struct palmas_platform_data *pdata)
 {
+       struct irq_data *irq_data = irq_get_irq_data(i2c->irq);
+       if (!irq_data) {
+               dev_err(&i2c->dev, "Invalid IRQ: %d\n", i2c->irq);
+               return -EINVAL;
+       }
+
+       pdata->irq_flags = irqd_get_trigger_type(irq_data);
+       dev_info(&i2c->dev, "Irq flag is 0x%08x\n", pdata->irq_flags);
+       return 0;
+}
+
+static void palmas_dt_to_pdata(struct i2c_client *i2c,
+               struct palmas_platform_data *pdata)
+{
+       struct device_node *node = i2c->dev.of_node;
        int ret;
        u32 prop;
 
@@ -283,6 +298,8 @@ static void palmas_dt_to_pdata(struct device_node *node,
                pdata->power_ctrl = PALMAS_POWER_CTRL_NSLEEP_MASK |
                                        PALMAS_POWER_CTRL_ENABLE1_MASK |
                                        PALMAS_POWER_CTRL_ENABLE2_MASK;
+       if (i2c->irq)
+               palmas_set_pdata_irq_flag(i2c, pdata);
 }
 
 static int palmas_i2c_probe(struct i2c_client *i2c,
@@ -304,7 +321,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
                if (!pdata)
                        return -ENOMEM;
 
-               palmas_dt_to_pdata(node, pdata);
+               palmas_dt_to_pdata(i2c, pdata);
        }
 
        if (!pdata)
@@ -344,6 +361,19 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
                }
        }
 
+       /* Change interrupt line output polarity */
+       if (pdata->irq_flags & IRQ_TYPE_LEVEL_HIGH)
+               reg = PALMAS_POLARITY_CTRL_INT_POLARITY;
+       else
+               reg = 0;
+       ret = palmas_update_bits(palmas, PALMAS_PU_PD_OD_BASE,
+                       PALMAS_POLARITY_CTRL, PALMAS_POLARITY_CTRL_INT_POLARITY,
+                       reg);
+       if (ret < 0) {
+               dev_err(palmas->dev, "POLARITY_CTRL updat failed: %d\n", ret);
+               goto err;
+       }
+
        /* Change IRQ into clear on read mode for efficiency */
        slave = PALMAS_BASE_TO_SLAVE(PALMAS_INTERRUPT_BASE);
        addr = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT_CTRL);
@@ -352,7 +382,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c,
        regmap_write(palmas->regmap[slave], addr, reg);
 
        ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq,
-                       IRQF_ONESHOT | IRQF_TRIGGER_LOW, 0, &palmas_irq_chip,
+                       IRQF_ONESHOT | pdata->irq_flags, 0, &palmas_irq_chip,
                        &palmas->irq_data);
        if (ret < 0)
                goto err;
index 4658b5bdcd84488d3379a2ef4f33e334eb96ea2f..aeb8e40ab4249ac2acdbdb43d7149ca8ca5efde4 100644 (file)
@@ -169,6 +169,7 @@ err:
 void tps65912_device_exit(struct tps65912 *tps65912)
 {
        mfd_remove_devices(tps65912->dev);
+       tps65912_irq_exit(tps65912);
        kfree(tps65912);
 }
 
index e16edca926709bbe501d52dc5fb37f578e9710a4..d2ab222138c29eb24ed8d62247928dda7127b31d 100644 (file)
@@ -118,7 +118,7 @@ EXPORT_SYMBOL_GPL(twl4030_audio_enable_resource);
  * Disable the resource.
  * The function returns with error or the content of the register
  */
-int twl4030_audio_disable_resource(unsigned id)
+int twl4030_audio_disable_resource(enum twl4030_audio_res id)
 {
        struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev);
        int val;
index 88ff9dc83305e2d2a644c6c049abb35439c2b5ad..942b666a2a07b20ad02f97b864500db0259b8669 100644 (file)
@@ -800,7 +800,7 @@ static int twl4030_madc_remove(struct platform_device *pdev)
 
 static struct platform_driver twl4030_madc_driver = {
        .probe = twl4030_madc_probe,
-       .remove = __exit_p(twl4030_madc_remove),
+       .remove = twl4030_madc_remove,
        .driver = {
                   .name = "twl4030_madc",
                   .owner = THIS_MODULE,
index 45ea7185c003d5b5deee66ad1a274c23212ed77f..642c6223fa6cd177f22c66e40b3d3531a6d841a4 100644 (file)
@@ -151,6 +151,20 @@ static void mei_me_intr_disable(struct mei_device *dev)
        mei_hcsr_set(hw, hcsr);
 }
 
+/**
+ * mei_me_hw_reset_release - release device from the reset
+ *
+ * @dev: the device structure
+ */
+static void mei_me_hw_reset_release(struct mei_device *dev)
+{
+       struct mei_me_hw *hw = to_me_hw(dev);
+       u32 hcsr = mei_hcsr_read(hw);
+
+       hcsr |= H_IG;
+       hcsr &= ~H_RST;
+       mei_hcsr_set(hw, hcsr);
+}
 /**
  * mei_me_hw_reset - resets fw via mei csr register.
  *
@@ -169,18 +183,14 @@ static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable)
        if (intr_enable)
                hcsr |= H_IE;
        else
-               hcsr &= ~H_IE;
-
-       mei_hcsr_set(hw, hcsr);
-
-       hcsr = mei_hcsr_read(hw) | H_IG;
-       hcsr &= ~H_RST;
+               hcsr |= ~H_IE;
 
        mei_hcsr_set(hw, hcsr);
 
-       hcsr = mei_hcsr_read(hw);
+       if (dev->dev_state == MEI_DEV_POWER_DOWN)
+               mei_me_hw_reset_release(dev);
 
-       dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", hcsr);
+       dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", mei_hcsr_read(hw));
 }
 
 /**
@@ -466,7 +476,8 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id)
                        mutex_unlock(&dev->device_lock);
                        return IRQ_HANDLED;
                } else {
-                       dev_dbg(&dev->pdev->dev, "FW not ready.\n");
+                       dev_dbg(&dev->pdev->dev, "Reset Completed.\n");
+                       mei_me_hw_reset_release(dev);
                        mutex_unlock(&dev->device_lock);
                        return IRQ_HANDLED;
                }
index 6ec530168afbbe2268da06d1c2508fd044cb943d..356179991a2e9ff87f7e34efb452b5ad4a547aa6 100644 (file)
@@ -183,6 +183,24 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled)
        mei_cl_all_write_clear(dev);
 }
 
+void mei_stop(struct mei_device *dev)
+{
+       dev_dbg(&dev->pdev->dev, "stopping the device.\n");
+
+       mutex_lock(&dev->device_lock);
+
+       cancel_delayed_work(&dev->timer_work);
+
+       mei_wd_stop(dev);
+
+       dev->dev_state = MEI_DEV_POWER_DOWN;
+       mei_reset(dev, 0);
+
+       mutex_unlock(&dev->device_lock);
+
+       flush_scheduled_work();
+}
+
 
 
 
index cb80166161f0f82ad725e1073baf1bc607fcc6bf..97873812e33b28c06e85dc000869ef48f1312471 100644 (file)
@@ -381,6 +381,7 @@ static inline unsigned long mei_secs_to_jiffies(unsigned long sec)
 void mei_device_init(struct mei_device *dev);
 void mei_reset(struct mei_device *dev, int interrupts);
 int mei_hw_init(struct mei_device *dev);
+void mei_stop(struct mei_device *dev);
 
 /*
  *  MEI interrupt functions prototype
index b40ec0601ab0bcc7325f0dfedb8ebefccdd896ec..b8b5c9c3ad0375bab4605b038bcbda60ff970b4f 100644 (file)
@@ -247,44 +247,14 @@ static void mei_remove(struct pci_dev *pdev)
 
        hw = to_me_hw(dev);
 
-       mutex_lock(&dev->device_lock);
-
-       cancel_delayed_work(&dev->timer_work);
 
-       mei_wd_stop(dev);
+       dev_err(&pdev->dev, "stop\n");
+       mei_stop(dev);
 
        mei_pdev = NULL;
 
-       if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) {
-               dev->iamthif_cl.state = MEI_FILE_DISCONNECTING;
-               mei_cl_disconnect(&dev->iamthif_cl);
-       }
-       if (dev->wd_cl.state == MEI_FILE_CONNECTED) {
-               dev->wd_cl.state = MEI_FILE_DISCONNECTING;
-               mei_cl_disconnect(&dev->wd_cl);
-       }
-
-       /* Unregistering watchdog device */
        mei_watchdog_unregister(dev);
 
-       /* remove entry if already in list */
-       dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
-
-       if (dev->open_handle_count > 0)
-               dev->open_handle_count--;
-       mei_cl_unlink(&dev->wd_cl);
-
-       if (dev->open_handle_count > 0)
-               dev->open_handle_count--;
-       mei_cl_unlink(&dev->iamthif_cl);
-
-       dev->iamthif_current_cb = NULL;
-       dev->me_clients_num = 0;
-
-       mutex_unlock(&dev->device_lock);
-
-       flush_scheduled_work();
-
        /* disable interrupts */
        mei_disable_interrupts(dev);
 
@@ -308,28 +278,20 @@ static int mei_pci_suspend(struct device *device)
 {
        struct pci_dev *pdev = to_pci_dev(device);
        struct mei_device *dev = pci_get_drvdata(pdev);
-       int err;
 
        if (!dev)
                return -ENODEV;
-       mutex_lock(&dev->device_lock);
 
-       cancel_delayed_work(&dev->timer_work);
+       dev_err(&pdev->dev, "suspend\n");
 
-       /* Stop watchdog if exists */
-       err = mei_wd_stop(dev);
-       /* Set new mei state */
-       if (dev->dev_state == MEI_DEV_ENABLED ||
-           dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) {
-               dev->dev_state = MEI_DEV_POWER_DOWN;
-               mei_reset(dev, 0);
-       }
-       mutex_unlock(&dev->device_lock);
+       mei_stop(dev);
+
+       mei_disable_interrupts(dev);
 
        free_irq(pdev->irq, dev);
        pci_disable_msi(pdev);
 
-       return err;
+       return 0;
 }
 
 static int mei_pci_resume(struct device *device)
index ed5c433cd4936f8b52c98352bbf21ead11a67ae8..f3cdd904fe4d6e1ae5c48288858d793dbc0af22c 100644 (file)
@@ -42,9 +42,11 @@ struct datagram_entry {
 
 struct delayed_datagram_info {
        struct datagram_entry *entry;
-       struct vmci_datagram msg;
        struct work_struct work;
        bool in_dg_host_queue;
+       /* msg and msg_payload must be together. */
+       struct vmci_datagram msg;
+       u8 msg_payload[];
 };
 
 /* Number of in-flight host->host datagrams */
index d88219e1d86e551cda21b16559a8cdff910e1ac3..d0547448606debe28df373728b85542b43b924f4 100644 (file)
@@ -180,7 +180,7 @@ config MMC_SDHCI_TEGRA
 
 config MMC_SDHCI_S3C
        tristate "SDHCI support on Samsung S3C SoC"
-       depends on MMC_SDHCI && PLAT_SAMSUNG
+       depends on MMC_SDHCI && PLAT_SAMSUNG_SINGLE
        help
          This selects the Secure Digital Host Controller Interface (SDHCI)
          often referrered to as the HSMMC block in some of the Samsung S3C
index 63fb265e0da6545456fcc020029abf21ceca72a5..8d6794cdf899cd812e394b862c111a6c65b53dc4 100644 (file)
 
 #include <mach/dma.h>
 
-#include <mach/regs-sdi.h>
-
 #include <linux/platform_data/mmc-s3cmci.h>
 
 #include "s3cmci.h"
 
 #define DRIVER_NAME "s3c-mci"
 
+#define S3C2410_SDICON                 (0x00)
+#define S3C2410_SDIPRE                 (0x04)
+#define S3C2410_SDICMDARG              (0x08)
+#define S3C2410_SDICMDCON              (0x0C)
+#define S3C2410_SDICMDSTAT             (0x10)
+#define S3C2410_SDIRSP0                        (0x14)
+#define S3C2410_SDIRSP1                        (0x18)
+#define S3C2410_SDIRSP2                        (0x1C)
+#define S3C2410_SDIRSP3                        (0x20)
+#define S3C2410_SDITIMER               (0x24)
+#define S3C2410_SDIBSIZE               (0x28)
+#define S3C2410_SDIDCON                        (0x2C)
+#define S3C2410_SDIDCNT                        (0x30)
+#define S3C2410_SDIDSTA                        (0x34)
+#define S3C2410_SDIFSTA                        (0x38)
+
+#define S3C2410_SDIDATA                        (0x3C)
+#define S3C2410_SDIIMSK                        (0x40)
+
+#define S3C2440_SDIDATA                        (0x40)
+#define S3C2440_SDIIMSK                        (0x3C)
+
+#define S3C2440_SDICON_SDRESET         (1 << 8)
+#define S3C2410_SDICON_SDIOIRQ         (1 << 3)
+#define S3C2410_SDICON_FIFORESET       (1 << 1)
+#define S3C2410_SDICON_CLOCKTYPE       (1 << 0)
+
+#define S3C2410_SDICMDCON_LONGRSP      (1 << 10)
+#define S3C2410_SDICMDCON_WAITRSP      (1 << 9)
+#define S3C2410_SDICMDCON_CMDSTART     (1 << 8)
+#define S3C2410_SDICMDCON_SENDERHOST   (1 << 6)
+#define S3C2410_SDICMDCON_INDEX                (0x3f)
+
+#define S3C2410_SDICMDSTAT_CRCFAIL     (1 << 12)
+#define S3C2410_SDICMDSTAT_CMDSENT     (1 << 11)
+#define S3C2410_SDICMDSTAT_CMDTIMEOUT  (1 << 10)
+#define S3C2410_SDICMDSTAT_RSPFIN      (1 << 9)
+
+#define S3C2440_SDIDCON_DS_WORD                (2 << 22)
+#define S3C2410_SDIDCON_TXAFTERRESP    (1 << 20)
+#define S3C2410_SDIDCON_RXAFTERCMD     (1 << 19)
+#define S3C2410_SDIDCON_BLOCKMODE      (1 << 17)
+#define S3C2410_SDIDCON_WIDEBUS                (1 << 16)
+#define S3C2410_SDIDCON_DMAEN          (1 << 15)
+#define S3C2410_SDIDCON_STOP           (1 << 14)
+#define S3C2440_SDIDCON_DATSTART       (1 << 14)
+
+#define S3C2410_SDIDCON_XFER_RXSTART   (2 << 12)
+#define S3C2410_SDIDCON_XFER_TXSTART   (3 << 12)
+
+#define S3C2410_SDIDCON_BLKNUM_MASK    (0xFFF)
+
+#define S3C2410_SDIDSTA_SDIOIRQDETECT  (1 << 9)
+#define S3C2410_SDIDSTA_FIFOFAIL       (1 << 8)
+#define S3C2410_SDIDSTA_CRCFAIL                (1 << 7)
+#define S3C2410_SDIDSTA_RXCRCFAIL      (1 << 6)
+#define S3C2410_SDIDSTA_DATATIMEOUT    (1 << 5)
+#define S3C2410_SDIDSTA_XFERFINISH     (1 << 4)
+#define S3C2410_SDIDSTA_TXDATAON       (1 << 1)
+#define S3C2410_SDIDSTA_RXDATAON       (1 << 0)
+
+#define S3C2440_SDIFSTA_FIFORESET      (1 << 16)
+#define S3C2440_SDIFSTA_FIFOFAIL       (3 << 14)
+#define S3C2410_SDIFSTA_TFDET          (1 << 13)
+#define S3C2410_SDIFSTA_RFDET          (1 << 12)
+#define S3C2410_SDIFSTA_COUNTMASK      (0x7f)
+
+#define S3C2410_SDIIMSK_RESPONSECRC    (1 << 17)
+#define S3C2410_SDIIMSK_CMDSENT                (1 << 16)
+#define S3C2410_SDIIMSK_CMDTIMEOUT     (1 << 15)
+#define S3C2410_SDIIMSK_RESPONSEND     (1 << 14)
+#define S3C2410_SDIIMSK_SDIOIRQ                (1 << 12)
+#define S3C2410_SDIIMSK_FIFOFAIL       (1 << 11)
+#define S3C2410_SDIIMSK_CRCSTATUS      (1 << 10)
+#define S3C2410_SDIIMSK_DATACRC                (1 << 9)
+#define S3C2410_SDIIMSK_DATATIMEOUT    (1 << 8)
+#define S3C2410_SDIIMSK_DATAFINISH     (1 << 7)
+#define S3C2410_SDIIMSK_TXFIFOHALF     (1 << 4)
+#define S3C2410_SDIIMSK_RXFIFOLAST     (1 << 2)
+#define S3C2410_SDIIMSK_RXFIFOHALF     (1 << 0)
+
 enum dbg_channels {
        dbg_err   = (1 << 0),
        dbg_debug = (1 << 1),
index 7363efe72287482def2cf32f4e4e515788c33d80..e4f52b5c259210b7ede730fbab29cd680e59e224 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/platform_device.h>
+#include <linux/platform_data/mmc-sdhci-s3c.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/io.h>
@@ -28,9 +29,7 @@
 
 #include <linux/mmc/host.h>
 
-#include <plat/sdhci.h>
-#include <plat/regs-sdhci.h>
-
+#include "sdhci-s3c-regs.h"
 #include "sdhci.h"
 
 #define MAX_BUS_CLK    (4)
index 63feb75cc8e01d2048949343955023b01fc7fadc..9279a9174f84ad9cd3a2ae2c7117c29cc8134e9e 100644 (file)
 /* 10 parts were found on sflash on Netgear WNDR4500 */
 #define BCM47XXPART_MAX_PARTS          12
 
+/*
+ * Amount of bytes we read when analyzing each block of flash memory.
+ * Set it big enough to allow detecting partition and reading important data.
+ */
+#define BCM47XXPART_BYTES_TO_READ      0x404
+
 /* Magics */
 #define BOARD_DATA_MAGIC               0x5246504D      /* MPFR */
 #define POT_MAGIC1                     0x54544f50      /* POTT */
@@ -57,17 +63,15 @@ static int bcm47xxpart_parse(struct mtd_info *master,
        struct trx_header *trx;
        int trx_part = -1;
        int last_trx_part = -1;
-       int max_bytes_to_read = 0x8004;
+       int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, };
 
        if (blocksize <= 0x10000)
                blocksize = 0x10000;
-       if (blocksize == 0x20000)
-               max_bytes_to_read = 0x18004;
 
        /* Alloc */
        parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS,
                        GFP_KERNEL);
-       buf = kzalloc(max_bytes_to_read, GFP_KERNEL);
+       buf = kzalloc(BCM47XXPART_BYTES_TO_READ, GFP_KERNEL);
 
        /* Parse block by block looking for magics */
        for (offset = 0; offset <= master->size - blocksize;
@@ -82,7 +86,7 @@ static int bcm47xxpart_parse(struct mtd_info *master,
                }
 
                /* Read beginning of the block */
-               if (mtd_read(master, offset, max_bytes_to_read,
+               if (mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ,
                             &bytes_read, (uint8_t *)buf) < 0) {
                        pr_err("mtd_read error while parsing (offset: 0x%X)!\n",
                               offset);
@@ -96,20 +100,6 @@ static int bcm47xxpart_parse(struct mtd_info *master,
                        continue;
                }
 
-               /* Standard NVRAM */
-               if (buf[0x000 / 4] == NVRAM_HEADER ||
-                   buf[0x1000 / 4] == NVRAM_HEADER ||
-                   buf[0x8000 / 4] == NVRAM_HEADER ||
-                   (blocksize == 0x20000 && (
-                     buf[0x10000 / 4] == NVRAM_HEADER ||
-                     buf[0x11000 / 4] == NVRAM_HEADER ||
-                     buf[0x18000 / 4] == NVRAM_HEADER))) {
-                       bcm47xxpart_add_part(&parts[curr_part++], "nvram",
-                                            offset, 0);
-                       offset = rounddown(offset, blocksize);
-                       continue;
-               }
-
                /*
                 * board_data starts with board_id which differs across boards,
                 * but we can use 'MPFR' (hopefully) magic at 0x100
@@ -178,6 +168,30 @@ static int bcm47xxpart_parse(struct mtd_info *master,
                        continue;
                }
        }
+
+       /* Look for NVRAM at the end of the last block. */
+       for (i = 0; i < ARRAY_SIZE(possible_nvram_sizes); i++) {
+               if (curr_part > BCM47XXPART_MAX_PARTS) {
+                       pr_warn("Reached maximum number of partitions, scanning stopped!\n");
+                       break;
+               }
+
+               offset = master->size - possible_nvram_sizes[i];
+               if (mtd_read(master, offset, 0x4, &bytes_read,
+                            (uint8_t *)buf) < 0) {
+                       pr_err("mtd_read error while reading at offset 0x%X!\n",
+                              offset);
+                       continue;
+               }
+
+               /* Standard NVRAM */
+               if (buf[0] == NVRAM_HEADER) {
+                       bcm47xxpart_add_part(&parts[curr_part++], "nvram",
+                                            master->size - blocksize, 0);
+                       break;
+               }
+       }
+
        kfree(buf);
 
        /*
index 43214151b882bcf4d2717eb48f20b1b2e0fd9a46..42c63927609dbee8697c691c8e97515cf509b990 100644 (file)
@@ -1523,6 +1523,14 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                                        oobreadlen -= toread;
                                }
                        }
+
+                       if (chip->options & NAND_NEED_READRDY) {
+                               /* Apply delay or wait for ready/busy pin */
+                               if (!chip->dev_ready)
+                                       udelay(chip->chip_delay);
+                               else
+                                       nand_wait_ready(mtd);
+                       }
                } else {
                        memcpy(buf, chip->buffers->databuf + col, bytes);
                        buf += bytes;
@@ -1787,6 +1795,14 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
                len = min(len, readlen);
                buf = nand_transfer_oob(chip, buf, ops, len);
 
+               if (chip->options & NAND_NEED_READRDY) {
+                       /* Apply delay or wait for ready/busy pin */
+                       if (!chip->dev_ready)
+                               udelay(chip->chip_delay);
+                       else
+                               nand_wait_ready(mtd);
+               }
+
                readlen -= len;
                if (!readlen)
                        break;
index e3aa2748a6e7af1cac818aaa170d5f6aff253056..9c612388e5deff15def3bc8014fd1d6408222142 100644 (file)
 *      512     512 Byte page size
 */
 struct nand_flash_dev nand_flash_ids[] = {
+#define SP_OPTIONS NAND_NEED_READRDY
+#define SP_OPTIONS16 (SP_OPTIONS | NAND_BUSWIDTH_16)
 
 #ifdef CONFIG_MTD_NAND_MUSEUM_IDS
-       {"NAND 1MiB 5V 8-bit",          0x6e, 256, 1, 0x1000, 0},
-       {"NAND 2MiB 5V 8-bit",          0x64, 256, 2, 0x1000, 0},
-       {"NAND 4MiB 5V 8-bit",          0x6b, 512, 4, 0x2000, 0},
-       {"NAND 1MiB 3,3V 8-bit",        0xe8, 256, 1, 0x1000, 0},
-       {"NAND 1MiB 3,3V 8-bit",        0xec, 256, 1, 0x1000, 0},
-       {"NAND 2MiB 3,3V 8-bit",        0xea, 256, 2, 0x1000, 0},
-       {"NAND 4MiB 3,3V 8-bit",        0xd5, 512, 4, 0x2000, 0},
-       {"NAND 4MiB 3,3V 8-bit",        0xe3, 512, 4, 0x2000, 0},
-       {"NAND 4MiB 3,3V 8-bit",        0xe5, 512, 4, 0x2000, 0},
-       {"NAND 8MiB 3,3V 8-bit",        0xd6, 512, 8, 0x2000, 0},
-
-       {"NAND 8MiB 1,8V 8-bit",        0x39, 512, 8, 0x2000, 0},
-       {"NAND 8MiB 3,3V 8-bit",        0xe6, 512, 8, 0x2000, 0},
-       {"NAND 8MiB 1,8V 16-bit",       0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16},
-       {"NAND 8MiB 3,3V 16-bit",       0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16},
+       {"NAND 1MiB 5V 8-bit",          0x6e, 256, 1, 0x1000, SP_OPTIONS},
+       {"NAND 2MiB 5V 8-bit",          0x64, 256, 2, 0x1000, SP_OPTIONS},
+       {"NAND 4MiB 5V 8-bit",          0x6b, 512, 4, 0x2000, SP_OPTIONS},
+       {"NAND 1MiB 3,3V 8-bit",        0xe8, 256, 1, 0x1000, SP_OPTIONS},
+       {"NAND 1MiB 3,3V 8-bit",        0xec, 256, 1, 0x1000, SP_OPTIONS},
+       {"NAND 2MiB 3,3V 8-bit",        0xea, 256, 2, 0x1000, SP_OPTIONS},
+       {"NAND 4MiB 3,3V 8-bit",        0xd5, 512, 4, 0x2000, SP_OPTIONS},
+       {"NAND 4MiB 3,3V 8-bit",        0xe3, 512, 4, 0x2000, SP_OPTIONS},
+       {"NAND 4MiB 3,3V 8-bit",        0xe5, 512, 4, 0x2000, SP_OPTIONS},
+       {"NAND 8MiB 3,3V 8-bit",        0xd6, 512, 8, 0x2000, SP_OPTIONS},
+
+       {"NAND 8MiB 1,8V 8-bit",        0x39, 512, 8, 0x2000, SP_OPTIONS},
+       {"NAND 8MiB 3,3V 8-bit",        0xe6, 512, 8, 0x2000, SP_OPTIONS},
+       {"NAND 8MiB 1,8V 16-bit",       0x49, 512, 8, 0x2000, SP_OPTIONS16},
+       {"NAND 8MiB 3,3V 16-bit",       0x59, 512, 8, 0x2000, SP_OPTIONS16},
 #endif
 
-       {"NAND 16MiB 1,8V 8-bit",       0x33, 512, 16, 0x4000, 0},
-       {"NAND 16MiB 3,3V 8-bit",       0x73, 512, 16, 0x4000, 0},
-       {"NAND 16MiB 1,8V 16-bit",      0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16},
-       {"NAND 16MiB 3,3V 16-bit",      0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16},
-
-       {"NAND 32MiB 1,8V 8-bit",       0x35, 512, 32, 0x4000, 0},
-       {"NAND 32MiB 3,3V 8-bit",       0x75, 512, 32, 0x4000, 0},
-       {"NAND 32MiB 1,8V 16-bit",      0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16},
-       {"NAND 32MiB 3,3V 16-bit",      0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16},
-
-       {"NAND 64MiB 1,8V 8-bit",       0x36, 512, 64, 0x4000, 0},
-       {"NAND 64MiB 3,3V 8-bit",       0x76, 512, 64, 0x4000, 0},
-       {"NAND 64MiB 1,8V 16-bit",      0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16},
-       {"NAND 64MiB 3,3V 16-bit",      0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16},
-
-       {"NAND 128MiB 1,8V 8-bit",      0x78, 512, 128, 0x4000, 0},
-       {"NAND 128MiB 1,8V 8-bit",      0x39, 512, 128, 0x4000, 0},
-       {"NAND 128MiB 3,3V 8-bit",      0x79, 512, 128, 0x4000, 0},
-       {"NAND 128MiB 1,8V 16-bit",     0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-       {"NAND 128MiB 1,8V 16-bit",     0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-       {"NAND 128MiB 3,3V 16-bit",     0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-       {"NAND 128MiB 3,3V 16-bit",     0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16},
-
-       {"NAND 256MiB 3,3V 8-bit",      0x71, 512, 256, 0x4000, 0},
+       {"NAND 16MiB 1,8V 8-bit",       0x33, 512, 16, 0x4000, SP_OPTIONS},
+       {"NAND 16MiB 3,3V 8-bit",       0x73, 512, 16, 0x4000, SP_OPTIONS},
+       {"NAND 16MiB 1,8V 16-bit",      0x43, 512, 16, 0x4000, SP_OPTIONS16},
+       {"NAND 16MiB 3,3V 16-bit",      0x53, 512, 16, 0x4000, SP_OPTIONS16},
+
+       {"NAND 32MiB 1,8V 8-bit",       0x35, 512, 32, 0x4000, SP_OPTIONS},
+       {"NAND 32MiB 3,3V 8-bit",       0x75, 512, 32, 0x4000, SP_OPTIONS},
+       {"NAND 32MiB 1,8V 16-bit",      0x45, 512, 32, 0x4000, SP_OPTIONS16},
+       {"NAND 32MiB 3,3V 16-bit",      0x55, 512, 32, 0x4000, SP_OPTIONS16},
+
+       {"NAND 64MiB 1,8V 8-bit",       0x36, 512, 64, 0x4000, SP_OPTIONS},
+       {"NAND 64MiB 3,3V 8-bit",       0x76, 512, 64, 0x4000, SP_OPTIONS},
+       {"NAND 64MiB 1,8V 16-bit",      0x46, 512, 64, 0x4000, SP_OPTIONS16},
+       {"NAND 64MiB 3,3V 16-bit",      0x56, 512, 64, 0x4000, SP_OPTIONS16},
+
+       {"NAND 128MiB 1,8V 8-bit",      0x78, 512, 128, 0x4000, SP_OPTIONS},
+       {"NAND 128MiB 1,8V 8-bit",      0x39, 512, 128, 0x4000, SP_OPTIONS},
+       {"NAND 128MiB 3,3V 8-bit",      0x79, 512, 128, 0x4000, SP_OPTIONS},
+       {"NAND 128MiB 1,8V 16-bit",     0x72, 512, 128, 0x4000, SP_OPTIONS16},
+       {"NAND 128MiB 1,8V 16-bit",     0x49, 512, 128, 0x4000, SP_OPTIONS16},
+       {"NAND 128MiB 3,3V 16-bit",     0x74, 512, 128, 0x4000, SP_OPTIONS16},
+       {"NAND 128MiB 3,3V 16-bit",     0x59, 512, 128, 0x4000, SP_OPTIONS16},
+
+       {"NAND 256MiB 3,3V 8-bit",      0x71, 512, 256, 0x4000, SP_OPTIONS},
 
        /*
         * These are the new chips with large page size. The pagesize and the
index 33f2a8fb8df9a86d524f600c9c0ea973344a02c9..2cf74085f93524c784f9adc3c3920713da570f5a 100644 (file)
 #include <linux/mtd/partitions.h>
 #include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 
 #include <asm/mach/flash.h>
-#include <plat/regs-onenand.h>
 
-#include <linux/io.h>
+#include "samsung.h"
 
 enum soc_type {
        TYPE_S3C6400,
similarity index 98%
rename from arch/arm/plat-samsung/include/plat/regs-onenand.h
rename to drivers/mtd/onenand/samsung.h
index 930ea8b88ed3b15dea01f98e1a1a81b8e7e40d8e..c4a80e67e438cf1656e42ccf38c4d57faf26947f 100644 (file)
@@ -11,8 +11,6 @@
 #ifndef __SAMSUNG_ONENAND_H__
 #define __SAMSUNG_ONENAND_H__
 
-#include <mach/hardware.h>
-
 /*
  * OneNAND Controller
  */
index 7bd068a6056a3ef3c66bde04f108d1bbf5dcd926..171b10f167a501a75fe8c7639c6d8dba0953f4b3 100644 (file)
@@ -1746,6 +1746,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 
        bond_compute_features(bond);
 
+       bond_update_speed_duplex(new_slave);
+
        read_lock(&bond->lock);
 
        new_slave->last_arp_rx = jiffies -
@@ -1798,8 +1800,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
                new_slave->link == BOND_LINK_DOWN ? "DOWN" :
                        (new_slave->link == BOND_LINK_UP ? "UP" : "BACK"));
 
-       bond_update_speed_duplex(new_slave);
-
        if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) {
                /* if there is a primary slave, remember it */
                if (strcmp(bond->params.primary, new_slave->dev->name) == 0) {
@@ -1964,7 +1964,6 @@ static int __bond_release_one(struct net_device *bond_dev,
        }
 
        block_netpoll_tx();
-       call_netdevice_notifiers(NETDEV_RELEASE, bond_dev);
        write_lock_bh(&bond->lock);
 
        slave = bond_get_slave_by_dev(bond, slave_dev);
@@ -1977,12 +1976,11 @@ static int __bond_release_one(struct net_device *bond_dev,
                return -EINVAL;
        }
 
+       write_unlock_bh(&bond->lock);
        /* unregister rx_handler early so bond_handle_frame wouldn't be called
         * for this slave anymore.
         */
        netdev_rx_handler_unregister(slave_dev);
-       write_unlock_bh(&bond->lock);
-       synchronize_net();
        write_lock_bh(&bond->lock);
 
        if (!all && !bond->params.fail_over_mac) {
@@ -2066,8 +2064,10 @@ static int __bond_release_one(struct net_device *bond_dev,
        write_unlock_bh(&bond->lock);
        unblock_netpoll_tx();
 
-       if (bond->slave_cnt == 0)
+       if (bond->slave_cnt == 0) {
                call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev);
+               call_netdevice_notifiers(NETDEV_RELEASE, bond->dev);
+       }
 
        bond_compute_features(bond);
        if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) &&
@@ -2373,8 +2373,6 @@ static void bond_miimon_commit(struct bonding *bond)
                                bond_set_backup_slave(slave);
                        }
 
-                       bond_update_speed_duplex(slave);
-
                        pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex.\n",
                                bond->dev->name, slave->dev->name,
                                slave->speed, slave->duplex ? "full" : "half");
@@ -4904,8 +4902,8 @@ static void __exit bonding_exit(void)
 
        bond_destroy_debugfs();
 
-       rtnl_link_unregister(&bond_link_ops);
        unregister_pernet_subsys(&bond_net_ops);
+       rtnl_link_unregister(&bond_link_ops);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
        /*
index 1c9e09fbdff8346e99413e0313d03ed401f463e2..ea7a388f484306710a33375f3a553fd1ecc5b621 100644 (file)
@@ -183,6 +183,11 @@ int bond_create_slave_symlinks(struct net_device *master,
        sprintf(linkname, "slave_%s", slave->name);
        ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj),
                                linkname);
+
+       /* free the master link created earlier in case of error */
+       if (ret)
+               sysfs_remove_link(&(slave->dev.kobj), "master");
+
        return ret;
 
 }
@@ -522,7 +527,7 @@ static ssize_t bonding_store_arp_interval(struct device *d,
                goto out;
        }
        if (new_value < 0) {
-               pr_err("%s: Invalid arp_interval value %d not in range 1-%d; rejected.\n",
+               pr_err("%s: Invalid arp_interval value %d not in range 0-%d; rejected.\n",
                       bond->dev->name, new_value, INT_MAX);
                ret = -EINVAL;
                goto out;
@@ -537,14 +542,15 @@ static ssize_t bonding_store_arp_interval(struct device *d,
        pr_info("%s: Setting ARP monitoring interval to %d.\n",
                bond->dev->name, new_value);
        bond->params.arp_interval = new_value;
-       if (bond->params.miimon) {
-               pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
-                       bond->dev->name, bond->dev->name);
-               bond->params.miimon = 0;
-       }
-       if (!bond->params.arp_targets[0]) {
-               pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
-                       bond->dev->name);
+       if (new_value) {
+               if (bond->params.miimon) {
+                       pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
+                               bond->dev->name, bond->dev->name);
+                       bond->params.miimon = 0;
+               }
+               if (!bond->params.arp_targets[0])
+                       pr_info("%s: ARP monitoring has been set up, but no ARP targets have been specified.\n",
+                               bond->dev->name);
        }
        if (bond->dev->flags & IFF_UP) {
                /* If the interface is up, we may need to fire off
@@ -552,10 +558,13 @@ static ssize_t bonding_store_arp_interval(struct device *d,
                 * timer will get fired off when the open function
                 * is called.
                 */
-               cancel_delayed_work_sync(&bond->mii_work);
-               queue_delayed_work(bond->wq, &bond->arp_work, 0);
+               if (!new_value) {
+                       cancel_delayed_work_sync(&bond->arp_work);
+               } else {
+                       cancel_delayed_work_sync(&bond->mii_work);
+                       queue_delayed_work(bond->wq, &bond->arp_work, 0);
+               }
        }
-
 out:
        rtnl_unlock();
        return ret;
@@ -697,7 +706,7 @@ static ssize_t bonding_store_downdelay(struct device *d,
        }
        if (new_value < 0) {
                pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
-                      bond->dev->name, new_value, 1, INT_MAX);
+                      bond->dev->name, new_value, 0, INT_MAX);
                ret = -EINVAL;
                goto out;
        } else {
@@ -752,8 +761,8 @@ static ssize_t bonding_store_updelay(struct device *d,
                goto out;
        }
        if (new_value < 0) {
-               pr_err("%s: Invalid down delay value %d not in range %d-%d; rejected.\n",
-                      bond->dev->name, new_value, 1, INT_MAX);
+               pr_err("%s: Invalid up delay value %d not in range %d-%d; rejected.\n",
+                      bond->dev->name, new_value, 0, INT_MAX);
                ret = -EINVAL;
                goto out;
        } else {
@@ -963,37 +972,37 @@ static ssize_t bonding_store_miimon(struct device *d,
        }
        if (new_value < 0) {
                pr_err("%s: Invalid miimon value %d not in range %d-%d; rejected.\n",
-                      bond->dev->name, new_value, 1, INT_MAX);
+                      bond->dev->name, new_value, 0, INT_MAX);
                ret = -EINVAL;
                goto out;
-       } else {
-               pr_info("%s: Setting MII monitoring interval to %d.\n",
-                       bond->dev->name, new_value);
-               bond->params.miimon = new_value;
-               if (bond->params.updelay)
-                       pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
-                               bond->dev->name,
-                               bond->params.updelay * bond->params.miimon);
-               if (bond->params.downdelay)
-                       pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
-                               bond->dev->name,
-                               bond->params.downdelay * bond->params.miimon);
-               if (bond->params.arp_interval) {
-                       pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
-                               bond->dev->name);
-                       bond->params.arp_interval = 0;
-                       if (bond->params.arp_validate) {
-                               bond->params.arp_validate =
-                                       BOND_ARP_VALIDATE_NONE;
-                       }
-               }
-
-               if (bond->dev->flags & IFF_UP) {
-                       /* If the interface is up, we may need to fire off
-                        * the MII timer. If the interface is down, the
-                        * timer will get fired off when the open function
-                        * is called.
-                        */
+       }
+       pr_info("%s: Setting MII monitoring interval to %d.\n",
+               bond->dev->name, new_value);
+       bond->params.miimon = new_value;
+       if (bond->params.updelay)
+               pr_info("%s: Note: Updating updelay (to %d) since it is a multiple of the miimon value.\n",
+                       bond->dev->name,
+                       bond->params.updelay * bond->params.miimon);
+       if (bond->params.downdelay)
+               pr_info("%s: Note: Updating downdelay (to %d) since it is a multiple of the miimon value.\n",
+                       bond->dev->name,
+                       bond->params.downdelay * bond->params.miimon);
+       if (new_value && bond->params.arp_interval) {
+               pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
+                       bond->dev->name);
+               bond->params.arp_interval = 0;
+               if (bond->params.arp_validate)
+                       bond->params.arp_validate = BOND_ARP_VALIDATE_NONE;
+       }
+       if (bond->dev->flags & IFF_UP) {
+               /* If the interface is up, we may need to fire off
+                * the MII timer. If the interface is down, the
+                * timer will get fired off when the open function
+                * is called.
+                */
+               if (!new_value) {
+                       cancel_delayed_work_sync(&bond->mii_work);
+               } else {
                        cancel_delayed_work_sync(&bond->arp_work);
                        queue_delayed_work(bond->wq, &bond->mii_work, 0);
                }
index b39ca5b3ea7faee34c2264ea7fbc6ac14e3caf35..ff2ba86cd4a495cdd29020f02561a1f31926ff11 100644 (file)
@@ -46,6 +46,7 @@ config CAN_EMS_PCI
 config CAN_PEAK_PCMCIA
        tristate "PEAK PCAN-PC Card"
        depends on PCMCIA
+       depends on HAS_IOPORT
        ---help---
          This driver is for the PCAN-PC Card PCMCIA adapter (1 or 2 channels)
          from PEAK-System (http://www.peak-system.com). To compile this
index a042cdc260dc720f982c44ae1bf8da315c0faaf6..3c18d7d000edaabe3b8ec93f1d2841d3300df087 100644 (file)
@@ -348,7 +348,7 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv)
         */
        if ((priv->read_reg(priv, REG_CR) & REG_CR_BASICCAN_INITIAL_MASK) ==
            REG_CR_BASICCAN_INITIAL &&
-           (priv->read_reg(priv, REG_SR) == REG_SR_BASICCAN_INITIAL) &&
+           (priv->read_reg(priv, SJA1000_REG_SR) == REG_SR_BASICCAN_INITIAL) &&
            (priv->read_reg(priv, REG_IR) == REG_IR_BASICCAN_INITIAL))
                flag = 1;
 
@@ -360,7 +360,7 @@ static inline int plx_pci_check_sja1000(const struct sja1000_priv *priv)
         * See states on p. 23 of the Datasheet.
         */
        if (priv->read_reg(priv, REG_MOD) == REG_MOD_PELICAN_INITIAL &&
-           priv->read_reg(priv, REG_SR) == REG_SR_PELICAN_INITIAL &&
+           priv->read_reg(priv, SJA1000_REG_SR) == REG_SR_PELICAN_INITIAL &&
            priv->read_reg(priv, REG_IR) == REG_IR_PELICAN_INITIAL)
                return flag;
 
index daf4013a8fc720ca0c73a9df96b647ad5c314839..e4df307eaa9081b9e39a81731714e0bd3969ea3b 100644 (file)
@@ -92,7 +92,7 @@ static void sja1000_write_cmdreg(struct sja1000_priv *priv, u8 val)
         */
        spin_lock_irqsave(&priv->cmdreg_lock, flags);
        priv->write_reg(priv, REG_CMR, val);
-       priv->read_reg(priv, REG_SR);
+       priv->read_reg(priv, SJA1000_REG_SR);
        spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
 }
 
@@ -502,7 +502,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
 
        while ((isrc = priv->read_reg(priv, REG_IR)) && (n < SJA1000_MAX_IRQ)) {
                n++;
-               status = priv->read_reg(priv, REG_SR);
+               status = priv->read_reg(priv, SJA1000_REG_SR);
                /* check for absent controller due to hw unplug */
                if (status == 0xFF && sja1000_is_absent(priv))
                        return IRQ_NONE;
@@ -530,7 +530,7 @@ irqreturn_t sja1000_interrupt(int irq, void *dev_id)
                        /* receive interrupt */
                        while (status & SR_RBS) {
                                sja1000_rx(dev);
-                               status = priv->read_reg(priv, REG_SR);
+                               status = priv->read_reg(priv, SJA1000_REG_SR);
                                /* check for absent controller */
                                if (status == 0xFF && sja1000_is_absent(priv))
                                        return IRQ_NONE;
index afa99847a5101ffa6399726b57d4189f6c3057f5..aa48e053da27ce26ed394e8a4584ef9805828372 100644 (file)
@@ -56,7 +56,7 @@
 /* SJA1000 registers - manual section 6.4 (Pelican Mode) */
 #define REG_MOD                0x00
 #define REG_CMR                0x01
-#define REG_SR         0x02
+#define SJA1000_REG_SR         0x02
 #define REG_IR         0x03
 #define REG_IER                0x04
 #define REG_ALC                0x0B
index 829b5ad71d0da0a4634cd211bc3f5ffc67215db6..b5fd934585e9f9f14595f60a2ec2e069cd2bed35 100644 (file)
@@ -186,7 +186,7 @@ struct atl1e_tpd_desc {
 /* how about 0x2000 */
 #define MAX_TX_BUF_LEN      0x2000
 #define MAX_TX_BUF_SHIFT    13
-/*#define MAX_TX_BUF_LEN  0x3000 */
+#define MAX_TSO_SEG_SIZE    0x3c00
 
 /* rrs word 1 bit 0:31 */
 #define RRS_RX_CSUM_MASK       0xFFFF
@@ -438,7 +438,6 @@ struct atl1e_adapter {
        struct atl1e_hw        hw;
        struct atl1e_hw_stats  hw_stats;
 
-       bool have_msi;
        u32 wol;
        u16 link_speed;
        u16 link_duplex;
index 92f4734f860d3f18ece977946b4562c028df35e6..ac25f05ff68f03b9eda25867d0ace6707efc2d41 100644 (file)
@@ -1849,34 +1849,19 @@ static void atl1e_free_irq(struct atl1e_adapter *adapter)
        struct net_device *netdev = adapter->netdev;
 
        free_irq(adapter->pdev->irq, netdev);
-
-       if (adapter->have_msi)
-               pci_disable_msi(adapter->pdev);
 }
 
 static int atl1e_request_irq(struct atl1e_adapter *adapter)
 {
        struct pci_dev    *pdev   = adapter->pdev;
        struct net_device *netdev = adapter->netdev;
-       int flags = 0;
        int err = 0;
 
-       adapter->have_msi = true;
-       err = pci_enable_msi(pdev);
-       if (err) {
-               netdev_dbg(netdev,
-                          "Unable to allocate MSI interrupt Error: %d\n", err);
-               adapter->have_msi = false;
-       }
-
-       if (!adapter->have_msi)
-               flags |= IRQF_SHARED;
-       err = request_irq(pdev->irq, atl1e_intr, flags, netdev->name, netdev);
+       err = request_irq(pdev->irq, atl1e_intr, IRQF_SHARED, netdev->name,
+                         netdev);
        if (err) {
                netdev_dbg(adapter->netdev,
                           "Unable to allocate interrupt Error: %d\n", err);
-               if (adapter->have_msi)
-                       pci_disable_msi(pdev);
                return err;
        }
        netdev_dbg(netdev, "atl1e_request_irq OK\n");
@@ -2344,6 +2329,7 @@ static int atl1e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        INIT_WORK(&adapter->reset_task, atl1e_reset_task);
        INIT_WORK(&adapter->link_chg_task, atl1e_link_chg_task);
+       netif_set_gso_max_size(netdev, MAX_TSO_SEG_SIZE);
        err = register_netdev(netdev);
        if (err) {
                netdev_err(netdev, "register netdevice failed\n");
index a923bc4d5a1f5540704423215a8f772bd3a8831a..4046f97378c29fa737d7123347ba1e940bd8e46d 100644 (file)
@@ -2760,6 +2760,7 @@ load_error2:
        bp->port.pmf = 0;
 load_error1:
        bnx2x_napi_disable(bp);
+       bnx2x_del_all_napi(bp);
 
        /* clear pf_load status, as it was already set */
        if (IS_PF(bp))
index 568205436a15f4d5b37528eb155df6e00ee3f07c..91ecd6a00d05a77453e4311eb5741064ba03ded2 100644 (file)
@@ -2139,12 +2139,12 @@ static u8 bnx2x_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap)
                        break;
                default:
                        BNX2X_ERR("Non valid capability ID\n");
-                       rval = -EINVAL;
+                       rval = 1;
                        break;
                }
        } else {
                DP(BNX2X_MSG_DCB, "DCB disabled\n");
-               rval = -EINVAL;
+               rval = 1;
        }
 
        DP(BNX2X_MSG_DCB, "capid %d:%x\n", capid, *cap);
@@ -2170,12 +2170,12 @@ static int bnx2x_dcbnl_get_numtcs(struct net_device *netdev, int tcid, u8 *num)
                        break;
                default:
                        BNX2X_ERR("Non valid TC-ID\n");
-                       rval = -EINVAL;
+                       rval = 1;
                        break;
                }
        } else {
                DP(BNX2X_MSG_DCB, "DCB disabled\n");
-               rval = -EINVAL;
+               rval = 1;
        }
 
        return rval;
@@ -2188,7 +2188,7 @@ static int bnx2x_dcbnl_set_numtcs(struct net_device *netdev, int tcid, u8 num)
        return -EINVAL;
 }
 
-static u8  bnx2x_dcbnl_get_pfc_state(struct net_device *netdev)
+static u8 bnx2x_dcbnl_get_pfc_state(struct net_device *netdev)
 {
        struct bnx2x *bp = netdev_priv(netdev);
        DP(BNX2X_MSG_DCB, "state = %d\n", bp->dcbx_local_feat.pfc.enabled);
@@ -2390,12 +2390,12 @@ static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid,
                        break;
                default:
                        BNX2X_ERR("Non valid featrue-ID\n");
-                       rval = -EINVAL;
+                       rval = 1;
                        break;
                }
        } else {
                DP(BNX2X_MSG_DCB, "DCB disabled\n");
-               rval = -EINVAL;
+               rval = 1;
        }
 
        return rval;
@@ -2431,12 +2431,12 @@ static u8 bnx2x_dcbnl_set_featcfg(struct net_device *netdev, int featid,
                        break;
                default:
                        BNX2X_ERR("Non valid featrue-ID\n");
-                       rval = -EINVAL;
+                       rval = 1;
                        break;
                }
        } else {
                DP(BNX2X_MSG_DCB, "dcbnl call not valid\n");
-               rval = -EINVAL;
+               rval = 1;
        }
 
        return rval;
index 31c5787970dbc342ad2ea4fc959d81baa187d356..77ebae0ac64aa9a4e681a506129c5a835d85ef4e 100644 (file)
@@ -8647,7 +8647,9 @@ void bnx2x_handle_module_detect_int(struct link_params *params)
                                                MDIO_WC_DEVAD,
                                                MDIO_WC_REG_DIGITAL5_MISC6,
                                                &rx_tx_in_reset);
-                               if (!rx_tx_in_reset) {
+                               if ((!rx_tx_in_reset) &&
+                                   (params->link_flags &
+                                    PHY_INITIALIZED)) {
                                        bnx2x_warpcore_reset_lane(bp, phy, 1);
                                        bnx2x_warpcore_config_sfi(phy, params);
                                        bnx2x_warpcore_reset_lane(bp, phy, 0);
@@ -12527,6 +12529,8 @@ int bnx2x_phy_init(struct link_params *params, struct link_vars *vars)
        vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
        vars->mac_type = MAC_TYPE_NONE;
        vars->phy_flags = 0;
+       vars->check_kr2_recovery_cnt = 0;
+       params->link_flags = PHY_INITIALIZED;
        /* Driver opens NIG-BRB filters */
        bnx2x_set_rx_filter(params, 1);
        /* Check if link flap can be avoided */
@@ -12691,6 +12695,7 @@ int bnx2x_lfa_reset(struct link_params *params,
        struct bnx2x *bp = params->bp;
        vars->link_up = 0;
        vars->phy_flags = 0;
+       params->link_flags &= ~PHY_INITIALIZED;
        if (!params->lfa_base)
                return bnx2x_link_reset(params, vars, 1);
        /*
@@ -13411,6 +13416,7 @@ static void bnx2x_disable_kr2(struct link_params *params,
        vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
        bnx2x_update_link_attr(params, vars->link_attr_sync);
 
+       vars->check_kr2_recovery_cnt = CHECK_KR2_RECOVERY_CNT;
        /* Restart AN on leading lane */
        bnx2x_warpcore_restart_AN_KR(phy, params);
 }
@@ -13439,6 +13445,15 @@ static void bnx2x_check_kr2_wa(struct link_params *params,
                return;
        }
 
+       /* Once KR2 was disabled, wait 5 seconds before checking KR2 recovery
+        * since some switches tend to reinit the AN process and clear the
+        * advertised BP/NP after ~2 seconds causing the KR2 to be disabled
+        * and recovered many times
+        */
+       if (vars->check_kr2_recovery_cnt > 0) {
+               vars->check_kr2_recovery_cnt--;
+               return;
+       }
        lane = bnx2x_get_warpcore_lane(phy, params);
        CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
                          MDIO_AER_BLOCK_AER_REG, lane);
index be5c195d03dd01addf2706c81896d1872b94d96c..56c2aae4e2c81b33818d6628cc342e67862d7ebd 100644 (file)
@@ -309,6 +309,7 @@ struct link_params {
                                req_flow_ctrl is set to AUTO */
        u16 link_flags;
 #define LINK_FLAGS_INT_DISABLED                (1<<0)
+#define PHY_INITIALIZED                (1<<1)
        u32 lfa_base;
 };
 
@@ -342,7 +343,8 @@ struct link_vars {
        u32 link_status;
        u32 eee_status;
        u8 fault_detected;
-       u8 rsrv1;
+       u8 check_kr2_recovery_cnt;
+#define CHECK_KR2_RECOVERY_CNT 5
        u16 periodic_flags;
 #define PERIODIC_FLAGS_LINK_EVENT      0x0001
 
index 364e37ecbc5cc013573ab63f5e1125f1e8cd750e..198f6f1c9ad5a342736f0d51528539ee5f22f775 100644 (file)
@@ -459,8 +459,9 @@ struct bnx2x_fw_port_stats_old {
 
 #define UPDATE_QSTAT(s, t) \
        do { \
-               qstats->t##_hi = qstats_old->t##_hi + le32_to_cpu(s.hi); \
                qstats->t##_lo = qstats_old->t##_lo + le32_to_cpu(s.lo); \
+               qstats->t##_hi = qstats_old->t##_hi + le32_to_cpu(s.hi) \
+                       + ((qstats->t##_lo < qstats_old->t##_lo) ? 1 : 0); \
        } while (0)
 
 #define UPDATE_QSTAT_OLD(f) \
index fdb9b5655414e77dc6506cdda13642ef16115e27..17a972734ba746d9218df4bf025218a91ebee947 100644 (file)
@@ -1869,6 +1869,8 @@ static void tg3_link_report(struct tg3 *tp)
 
                tg3_ump_link_report(tp);
        }
+
+       tp->link_up = netif_carrier_ok(tp->dev);
 }
 
 static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl)
@@ -2522,12 +2524,6 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
        return err;
 }
 
-static void tg3_carrier_on(struct tg3 *tp)
-{
-       netif_carrier_on(tp->dev);
-       tp->link_up = true;
-}
-
 static void tg3_carrier_off(struct tg3 *tp)
 {
        netif_carrier_off(tp->dev);
@@ -2553,7 +2549,7 @@ static int tg3_phy_reset(struct tg3 *tp)
                return -EBUSY;
 
        if (netif_running(tp->dev) && tp->link_up) {
-               tg3_carrier_off(tp);
+               netif_carrier_off(tp->dev);
                tg3_link_report(tp);
        }
 
@@ -4134,6 +4130,14 @@ static void tg3_phy_copper_begin(struct tg3 *tp)
                tp->link_config.active_speed = tp->link_config.speed;
                tp->link_config.active_duplex = tp->link_config.duplex;
 
+               if (tg3_asic_rev(tp) == ASIC_REV_5714) {
+                       /* With autoneg disabled, 5715 only links up when the
+                        * advertisement register has the configured speed
+                        * enabled.
+                        */
+                       tg3_writephy(tp, MII_ADVERTISE, ADVERTISE_ALL);
+               }
+
                bmcr = 0;
                switch (tp->link_config.speed) {
                default:
@@ -4262,9 +4266,9 @@ static bool tg3_test_and_report_link_chg(struct tg3 *tp, int curr_link_up)
 {
        if (curr_link_up != tp->link_up) {
                if (curr_link_up) {
-                       tg3_carrier_on(tp);
+                       netif_carrier_on(tp->dev);
                } else {
-                       tg3_carrier_off(tp);
+                       netif_carrier_off(tp->dev);
                        if (tp->phy_flags & TG3_PHYFLG_MII_SERDES)
                                tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT;
                }
@@ -14600,8 +14604,11 @@ static void tg3_read_vpd(struct tg3 *tp)
                if (j + len > block_end)
                        goto partno;
 
-               memcpy(tp->fw_ver, &vpd_data[j], len);
-               strncat(tp->fw_ver, " bc ", vpdlen - len - 1);
+               if (len >= sizeof(tp->fw_ver))
+                       len = sizeof(tp->fw_ver) - 1;
+               memset(tp->fw_ver, 0, sizeof(tp->fw_ver));
+               snprintf(tp->fw_ver, sizeof(tp->fw_ver), "%.*s bc ", len,
+                        &vpd_data[j]);
        }
 
 partno:
index a170065b597382ed9408239d98c36cec98a535a2..b0ebc9f6d55e9844e1ebe9367e9340681cba2a72 100644 (file)
 #define XGMAC_FLOW_CTRL_FCB_BPA        0x00000001      /* Flow Control Busy ... */
 
 /* XGMAC_INT_STAT reg */
+#define XGMAC_INT_STAT_PMTIM   0x00800000      /* PMT Interrupt Mask */
 #define XGMAC_INT_STAT_PMT     0x0080          /* PMT Interrupt Status */
 #define XGMAC_INT_STAT_LPI     0x0040          /* LPI Interrupt Status */
 
@@ -960,6 +961,9 @@ static int xgmac_hw_init(struct net_device *dev)
        writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_STATUS);
        writel(DMA_INTR_DEFAULT_MASK, ioaddr + XGMAC_DMA_INTR_ENA);
 
+       /* Mask power mgt interrupt */
+       writel(XGMAC_INT_STAT_PMTIM, ioaddr + XGMAC_INT_STAT);
+
        /* XGMAC requires AXI bus init. This is a 'magic number' for now */
        writel(0x0077000E, ioaddr + XGMAC_DMA_AXI_BUS);
 
@@ -1141,6 +1145,9 @@ static int xgmac_rx(struct xgmac_priv *priv, int limit)
                struct sk_buff *skb;
                int frame_len;
 
+               if (!dma_ring_cnt(priv->rx_head, priv->rx_tail, DMA_RX_RING_SZ))
+                       break;
+
                entry = priv->rx_tail;
                p = priv->dma_rx + entry;
                if (desc_get_owner(p))
@@ -1825,7 +1832,7 @@ static void xgmac_pmt(void __iomem *ioaddr, unsigned long mode)
        unsigned int pmt = 0;
 
        if (mode & WAKE_MAGIC)
-               pmt |= XGMAC_PMT_POWERDOWN | XGMAC_PMT_MAGIC_PKT;
+               pmt |= XGMAC_PMT_POWERDOWN | XGMAC_PMT_MAGIC_PKT_EN;
        if (mode & WAKE_UCAST)
                pmt |= XGMAC_PMT_POWERDOWN | XGMAC_PMT_GLBL_UNICAST;
 
index 4ce62031f62fa3a51500d8a571feba701e2fa6ed..8049268ce0f25f50f99a5a0ef7137d0f97c1e763 100644 (file)
@@ -497,8 +497,9 @@ int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len,
 }
 
 #define EEPROM_STAT_ADDR   0x7bfc
-#define VPD_BASE           0
 #define VPD_LEN            512
+#define VPD_BASE           0x400
+#define VPD_BASE_OLD       0
 
 /**
  *     t4_seeprom_wp - enable/disable EEPROM write protection
@@ -524,7 +525,7 @@ int t4_seeprom_wp(struct adapter *adapter, bool enable)
 int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
 {
        u32 cclk_param, cclk_val;
-       int i, ret;
+       int i, ret, addr;
        int ec, sn;
        u8 *vpd, csum;
        unsigned int vpdr_len, kw_offset, id_len;
@@ -533,7 +534,12 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p)
        if (!vpd)
                return -ENOMEM;
 
-       ret = pci_read_vpd(adapter->pdev, VPD_BASE, VPD_LEN, vpd);
+       ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(u32), vpd);
+       if (ret < 0)
+               goto out;
+       addr = *vpd == 0x82 ? VPD_BASE : VPD_BASE_OLD;
+
+       ret = pci_read_vpd(adapter->pdev, addr, VPD_LEN, vpd);
        if (ret < 0)
                goto out;
 
index 8cdf02503d13d5bdd52348f77995c0ce47618f1c..9eada8e86078fe83981223e023bd45f3929b1a70 100644 (file)
@@ -257,6 +257,107 @@ static void dm9000_dumpblk_32bit(void __iomem *reg, int count)
                tmp = readl(reg);
 }
 
+/*
+ * Sleep, either by using msleep() or if we are suspending, then
+ * use mdelay() to sleep.
+ */
+static void dm9000_msleep(board_info_t *db, unsigned int ms)
+{
+       if (db->in_suspend)
+               mdelay(ms);
+       else
+               msleep(ms);
+}
+
+/* Read a word from phyxcer */
+static int
+dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
+{
+       board_info_t *db = netdev_priv(dev);
+       unsigned long flags;
+       unsigned int reg_save;
+       int ret;
+
+       mutex_lock(&db->addr_lock);
+
+       spin_lock_irqsave(&db->lock, flags);
+
+       /* Save previous register address */
+       reg_save = readb(db->io_addr);
+
+       /* Fill the phyxcer register into REG_0C */
+       iow(db, DM9000_EPAR, DM9000_PHY | reg);
+
+       /* Issue phyxcer read command */
+       iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS);
+
+       writeb(reg_save, db->io_addr);
+       spin_unlock_irqrestore(&db->lock, flags);
+
+       dm9000_msleep(db, 1);           /* Wait read complete */
+
+       spin_lock_irqsave(&db->lock, flags);
+       reg_save = readb(db->io_addr);
+
+       iow(db, DM9000_EPCR, 0x0);      /* Clear phyxcer read command */
+
+       /* The read data keeps on REG_0D & REG_0E */
+       ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
+
+       /* restore the previous address */
+       writeb(reg_save, db->io_addr);
+       spin_unlock_irqrestore(&db->lock, flags);
+
+       mutex_unlock(&db->addr_lock);
+
+       dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
+       return ret;
+}
+
+/* Write a word to phyxcer */
+static void
+dm9000_phy_write(struct net_device *dev,
+                int phyaddr_unused, int reg, int value)
+{
+       board_info_t *db = netdev_priv(dev);
+       unsigned long flags;
+       unsigned long reg_save;
+
+       dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
+       mutex_lock(&db->addr_lock);
+
+       spin_lock_irqsave(&db->lock, flags);
+
+       /* Save previous register address */
+       reg_save = readb(db->io_addr);
+
+       /* Fill the phyxcer register into REG_0C */
+       iow(db, DM9000_EPAR, DM9000_PHY | reg);
+
+       /* Fill the written data into REG_0D & REG_0E */
+       iow(db, DM9000_EPDRL, value);
+       iow(db, DM9000_EPDRH, value >> 8);
+
+       /* Issue phyxcer write command */
+       iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);
+
+       writeb(reg_save, db->io_addr);
+       spin_unlock_irqrestore(&db->lock, flags);
+
+       dm9000_msleep(db, 1);           /* Wait write complete */
+
+       spin_lock_irqsave(&db->lock, flags);
+       reg_save = readb(db->io_addr);
+
+       iow(db, DM9000_EPCR, 0x0);      /* Clear phyxcer write command */
+
+       /* restore the previous address */
+       writeb(reg_save, db->io_addr);
+
+       spin_unlock_irqrestore(&db->lock, flags);
+       mutex_unlock(&db->addr_lock);
+}
+
 /* dm9000_set_io
  *
  * select the specified set of io routines to use with the
@@ -795,6 +896,9 @@ dm9000_init_dm9000(struct net_device *dev)
 
        iow(db, DM9000_GPCR, GPCR_GEP_CNTL);    /* Let GPIO0 output */
 
+       dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */
+       dm9000_phy_write(dev, 0, MII_DM_DSPCR, DSPCR_INIT_PARAM); /* Init */
+
        ncr = (db->flags & DM9000_PLATF_EXT_PHY) ? NCR_EXT_PHY : 0;
 
        /* if wol is needed, then always set NCR_WAKEEN otherwise we end
@@ -1201,109 +1305,6 @@ dm9000_open(struct net_device *dev)
        return 0;
 }
 
-/*
- * Sleep, either by using msleep() or if we are suspending, then
- * use mdelay() to sleep.
- */
-static void dm9000_msleep(board_info_t *db, unsigned int ms)
-{
-       if (db->in_suspend)
-               mdelay(ms);
-       else
-               msleep(ms);
-}
-
-/*
- *   Read a word from phyxcer
- */
-static int
-dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg)
-{
-       board_info_t *db = netdev_priv(dev);
-       unsigned long flags;
-       unsigned int reg_save;
-       int ret;
-
-       mutex_lock(&db->addr_lock);
-
-       spin_lock_irqsave(&db->lock,flags);
-
-       /* Save previous register address */
-       reg_save = readb(db->io_addr);
-
-       /* Fill the phyxcer register into REG_0C */
-       iow(db, DM9000_EPAR, DM9000_PHY | reg);
-
-       iow(db, DM9000_EPCR, EPCR_ERPRR | EPCR_EPOS);   /* Issue phyxcer read command */
-
-       writeb(reg_save, db->io_addr);
-       spin_unlock_irqrestore(&db->lock,flags);
-
-       dm9000_msleep(db, 1);           /* Wait read complete */
-
-       spin_lock_irqsave(&db->lock,flags);
-       reg_save = readb(db->io_addr);
-
-       iow(db, DM9000_EPCR, 0x0);      /* Clear phyxcer read command */
-
-       /* The read data keeps on REG_0D & REG_0E */
-       ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL);
-
-       /* restore the previous address */
-       writeb(reg_save, db->io_addr);
-       spin_unlock_irqrestore(&db->lock,flags);
-
-       mutex_unlock(&db->addr_lock);
-
-       dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret);
-       return ret;
-}
-
-/*
- *   Write a word to phyxcer
- */
-static void
-dm9000_phy_write(struct net_device *dev,
-                int phyaddr_unused, int reg, int value)
-{
-       board_info_t *db = netdev_priv(dev);
-       unsigned long flags;
-       unsigned long reg_save;
-
-       dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value);
-       mutex_lock(&db->addr_lock);
-
-       spin_lock_irqsave(&db->lock,flags);
-
-       /* Save previous register address */
-       reg_save = readb(db->io_addr);
-
-       /* Fill the phyxcer register into REG_0C */
-       iow(db, DM9000_EPAR, DM9000_PHY | reg);
-
-       /* Fill the written data into REG_0D & REG_0E */
-       iow(db, DM9000_EPDRL, value);
-       iow(db, DM9000_EPDRH, value >> 8);
-
-       iow(db, DM9000_EPCR, EPCR_EPOS | EPCR_ERPRW);   /* Issue phyxcer write command */
-
-       writeb(reg_save, db->io_addr);
-       spin_unlock_irqrestore(&db->lock, flags);
-
-       dm9000_msleep(db, 1);           /* Wait write complete */
-
-       spin_lock_irqsave(&db->lock,flags);
-       reg_save = readb(db->io_addr);
-
-       iow(db, DM9000_EPCR, 0x0);      /* Clear phyxcer write command */
-
-       /* restore the previous address */
-       writeb(reg_save, db->io_addr);
-
-       spin_unlock_irqrestore(&db->lock, flags);
-       mutex_unlock(&db->addr_lock);
-}
-
 static void
 dm9000_shutdown(struct net_device *dev)
 {
@@ -1502,7 +1503,12 @@ dm9000_probe(struct platform_device *pdev)
        db->flags |= DM9000_PLATF_SIMPLE_PHY;
 #endif
 
-       dm9000_reset(db);
+       /* Fixing bug on dm9000_probe, takeover dm9000_reset(db),
+        * Need 'NCR_MAC_LBK' bit to indeed stable our DM9000 fifo
+        * while probe stage.
+        */
+
+       iow(db, DM9000_NCR, NCR_MAC_LBK | NCR_RST);
 
        /* try multiple times, DM9000 sometimes gets the read wrong */
        for (i = 0; i < 8; i++) {
index 55688bd1a3ef0bb83ed90391c33bce894a16da89..9ce058adababcf28c83f644819b0b501079ef898 100644 (file)
@@ -69,7 +69,9 @@
 #define NCR_WAKEEN          (1<<6)
 #define NCR_FCOL            (1<<4)
 #define NCR_FDX             (1<<3)
-#define NCR_LBK             (3<<1)
+
+#define NCR_RESERVED        (3<<1)
+#define NCR_MAC_LBK         (1<<1)
 #define NCR_RST                    (1<<0)
 
 #define NSR_SPEED           (1<<7)
 #define ISR_LNKCHNG            (1<<5)
 #define ISR_UNDERRUN           (1<<4)
 
+/* Davicom MII registers.
+ */
+
+#define MII_DM_DSPCR           0x1b    /* DSP Control Register */
+
+#define DSPCR_INIT_PARAM       0xE100  /* DSP init parameter */
+
 #endif /* _DM9000X_H_ */
 
index 0c37fb2cc867530c266902c9d1b79c095a63ba99..1df33c799c0012a9144811c90c39a063e92fb45e 100644 (file)
@@ -108,6 +108,7 @@ config TULIP_DM910X
 config DE4X5
        tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA"
        depends on (PCI || EISA)
+       depends on VIRT_TO_BUS || ALPHA || PPC || SPARC
        select CRC32
        ---help---
          This is support for the DIGITAL series of PCI/EISA Ethernet cards.
index 28ceb84141851e26e8d49f1175099235a512d54b..29aff55f2eea414bf8dec52d61bee70a034fc12c 100644 (file)
@@ -349,6 +349,7 @@ struct be_adapter {
        struct pci_dev *pdev;
        struct net_device *netdev;
 
+       u8 __iomem *csr;        /* CSR BAR used only for BE2/3 */
        u8 __iomem *db;         /* Door Bell */
 
        struct mutex mbox_lock; /* For serializing mbox cmds to BE card */
index 071aea79d218f01eb166d910a310ef0f49efa470..3c9b4f12e3e516ff8775c208a3b138c9acd5c109 100644 (file)
@@ -473,19 +473,17 @@ static int be_mbox_notify_wait(struct be_adapter *adapter)
        return 0;
 }
 
-static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage)
+static u16 be_POST_stage_get(struct be_adapter *adapter)
 {
        u32 sem;
-       u32 reg = skyhawk_chip(adapter) ? SLIPORT_SEMAPHORE_OFFSET_SH :
-                                         SLIPORT_SEMAPHORE_OFFSET_BE;
 
-       pci_read_config_dword(adapter->pdev, reg, &sem);
-       *stage = sem & POST_STAGE_MASK;
-
-       if ((sem >> POST_ERR_SHIFT) & POST_ERR_MASK)
-               return -1;
+       if (BEx_chip(adapter))
+               sem  = ioread32(adapter->csr + SLIPORT_SEMAPHORE_OFFSET_BEx);
        else
-               return 0;
+               pci_read_config_dword(adapter->pdev,
+                                     SLIPORT_SEMAPHORE_OFFSET_SH, &sem);
+
+       return sem & POST_STAGE_MASK;
 }
 
 int lancer_wait_ready(struct be_adapter *adapter)
@@ -579,19 +577,17 @@ int be_fw_wait_ready(struct be_adapter *adapter)
        }
 
        do {
-               status = be_POST_stage_get(adapter, &stage);
-               if (status) {
-                       dev_err(dev, "POST error; stage=0x%x\n", stage);
-                       return -1;
-               } else if (stage != POST_STAGE_ARMFW_RDY) {
-                       if (msleep_interruptible(2000)) {
-                               dev_err(dev, "Waiting for POST aborted\n");
-                               return -EINTR;
-                       }
-                       timeout += 2;
-               } else {
+               stage = be_POST_stage_get(adapter);
+               if (stage == POST_STAGE_ARMFW_RDY)
                        return 0;
+
+               dev_info(dev, "Waiting for POST, %ds elapsed\n",
+                        timeout);
+               if (msleep_interruptible(2000)) {
+                       dev_err(dev, "Waiting for POST aborted\n");
+                       return -EINTR;
                }
+               timeout += 2;
        } while (timeout < 60);
 
        dev_err(dev, "POST timeout; stage=0x%x\n", stage);
index 541d4530d5bfadb2d038b3aa4e233a069cf9c94a..62dc220695f724999c8df269531274ba38ec0b4a 100644 (file)
@@ -32,8 +32,8 @@
 #define MPU_EP_CONTROL                 0
 
 /********** MPU semphore: used for SH & BE  *************/
-#define SLIPORT_SEMAPHORE_OFFSET_BE            0x7c
-#define SLIPORT_SEMAPHORE_OFFSET_SH            0x94
+#define SLIPORT_SEMAPHORE_OFFSET_BEx           0xac  /* CSR BAR offset */
+#define SLIPORT_SEMAPHORE_OFFSET_SH            0x94  /* PCI-CFG offset */
 #define POST_STAGE_MASK                                0x0000FFFF
 #define POST_ERR_MASK                          0x1
 #define POST_ERR_SHIFT                         31
index 3860888ac711a7fe7630cad2c06bb3819eb1f3a0..08e54f3d288bc9a2e23faa8bb954dcb4bd8cf584 100644 (file)
@@ -3688,6 +3688,8 @@ static void be_netdev_init(struct net_device *netdev)
 
 static void be_unmap_pci_bars(struct be_adapter *adapter)
 {
+       if (adapter->csr)
+               pci_iounmap(adapter->pdev, adapter->csr);
        if (adapter->db)
                pci_iounmap(adapter->pdev, adapter->db);
 }
@@ -3721,6 +3723,12 @@ static int be_map_pci_bars(struct be_adapter *adapter)
        adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >>
                                SLI_INTF_IF_TYPE_SHIFT;
 
+       if (BEx_chip(adapter) && be_physfn(adapter)) {
+               adapter->csr = pci_iomap(adapter->pdev, 2, 0);
+               if (adapter->csr == NULL)
+                       return -ENOMEM;
+       }
+
        addr = pci_iomap(adapter->pdev, db_bar(adapter), 0);
        if (addr == NULL)
                goto pci_map_err;
@@ -4329,6 +4337,8 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev)
        pci_restore_state(pdev);
 
        /* Check if card is ok and fw is ready */
+       dev_info(&adapter->pdev->dev,
+                "Waiting for FW to be ready after EEH reset\n");
        status = be_fw_wait_ready(adapter);
        if (status)
                return PCI_ERS_RESULT_DISCONNECT;
index 069a155d16ed40c57da5e70a8088eef767d0690b..f292c3aa423fbdeabb83ebdafa3b1699e988b19a 100644 (file)
@@ -345,6 +345,53 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        return NETDEV_TX_OK;
 }
 
+/* Init RX & TX buffer descriptors
+ */
+static void fec_enet_bd_init(struct net_device *dev)
+{
+       struct fec_enet_private *fep = netdev_priv(dev);
+       struct bufdesc *bdp;
+       unsigned int i;
+
+       /* Initialize the receive buffer descriptors. */
+       bdp = fep->rx_bd_base;
+       for (i = 0; i < RX_RING_SIZE; i++) {
+
+               /* Initialize the BD for every fragment in the page. */
+               if (bdp->cbd_bufaddr)
+                       bdp->cbd_sc = BD_ENET_RX_EMPTY;
+               else
+                       bdp->cbd_sc = 0;
+               bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+       }
+
+       /* Set the last buffer to wrap */
+       bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+       bdp->cbd_sc |= BD_SC_WRAP;
+
+       fep->cur_rx = fep->rx_bd_base;
+
+       /* ...and the same for transmit */
+       bdp = fep->tx_bd_base;
+       fep->cur_tx = bdp;
+       for (i = 0; i < TX_RING_SIZE; i++) {
+
+               /* Initialize the BD for every fragment in the page. */
+               bdp->cbd_sc = 0;
+               if (bdp->cbd_bufaddr && fep->tx_skbuff[i]) {
+                       dev_kfree_skb_any(fep->tx_skbuff[i]);
+                       fep->tx_skbuff[i] = NULL;
+               }
+               bdp->cbd_bufaddr = 0;
+               bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
+       }
+
+       /* Set the last buffer to wrap */
+       bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
+       bdp->cbd_sc |= BD_SC_WRAP;
+       fep->dirty_tx = bdp;
+}
+
 /* This function is called to start or restart the FEC during a link
  * change.  This only happens when switching between half and full
  * duplex.
@@ -388,6 +435,8 @@ fec_restart(struct net_device *ndev, int duplex)
        /* Set maximum receive buffer size. */
        writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
 
+       fec_enet_bd_init(ndev);
+
        /* Set receive and transmit descriptor base. */
        writel(fep->bd_dma, fep->hwp + FEC_R_DES_START);
        if (fep->bufdesc_ex)
@@ -397,7 +446,6 @@ fec_restart(struct net_device *ndev, int duplex)
                writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc)
                        * RX_RING_SIZE, fep->hwp + FEC_X_DES_START);
 
-       fep->cur_rx = fep->rx_bd_base;
 
        for (i = 0; i <= TX_RING_MOD_MASK; i++) {
                if (fep->tx_skbuff[i]) {
@@ -934,24 +982,28 @@ static void fec_enet_adjust_link(struct net_device *ndev)
                goto spin_unlock;
        }
 
-       /* Duplex link change */
        if (phy_dev->link) {
-               if (fep->full_duplex != phy_dev->duplex) {
-                       fec_restart(ndev, phy_dev->duplex);
-                       /* prevent unnecessary second fec_restart() below */
+               if (!fep->link) {
                        fep->link = phy_dev->link;
                        status_change = 1;
                }
-       }
 
-       /* Link on or off change */
-       if (phy_dev->link != fep->link) {
-               fep->link = phy_dev->link;
-               if (phy_dev->link)
+               if (fep->full_duplex != phy_dev->duplex)
+                       status_change = 1;
+
+               if (phy_dev->speed != fep->speed) {
+                       fep->speed = phy_dev->speed;
+                       status_change = 1;
+               }
+
+               /* if any of the above changed restart the FEC */
+               if (status_change)
                        fec_restart(ndev, phy_dev->duplex);
-               else
+       } else {
+               if (fep->link) {
                        fec_stop(ndev);
-               status_change = 1;
+                       status_change = 1;
+               }
        }
 
 spin_unlock:
@@ -1328,7 +1380,7 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
 static void fec_enet_free_buffers(struct net_device *ndev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
-       int i;
+       unsigned int i;
        struct sk_buff *skb;
        struct bufdesc  *bdp;
 
@@ -1352,7 +1404,7 @@ static void fec_enet_free_buffers(struct net_device *ndev)
 static int fec_enet_alloc_buffers(struct net_device *ndev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
-       int i;
+       unsigned int i;
        struct sk_buff *skb;
        struct bufdesc  *bdp;
 
@@ -1437,6 +1489,7 @@ fec_enet_close(struct net_device *ndev)
        struct fec_enet_private *fep = netdev_priv(ndev);
 
        /* Don't know what to do yet. */
+       napi_disable(&fep->napi);
        fep->opened = 0;
        netif_stop_queue(ndev);
        fec_stop(ndev);
@@ -1592,8 +1645,6 @@ static int fec_enet_init(struct net_device *ndev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
        struct bufdesc *cbd_base;
-       struct bufdesc *bdp;
-       int i;
 
        /* Allocate memory for buffer descriptors. */
        cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma,
@@ -1603,6 +1654,7 @@ static int fec_enet_init(struct net_device *ndev)
                return -ENOMEM;
        }
 
+       memset(cbd_base, 0, PAGE_SIZE);
        spin_lock_init(&fep->hw_lock);
 
        fep->netdev = ndev;
@@ -1626,35 +1678,6 @@ static int fec_enet_init(struct net_device *ndev)
        writel(FEC_RX_DISABLED_IMASK, fep->hwp + FEC_IMASK);
        netif_napi_add(ndev, &fep->napi, fec_enet_rx_napi, FEC_NAPI_WEIGHT);
 
-       /* Initialize the receive buffer descriptors. */
-       bdp = fep->rx_bd_base;
-       for (i = 0; i < RX_RING_SIZE; i++) {
-
-               /* Initialize the BD for every fragment in the page. */
-               bdp->cbd_sc = 0;
-               bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-       }
-
-       /* Set the last buffer to wrap */
-       bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
-       bdp->cbd_sc |= BD_SC_WRAP;
-
-       /* ...and the same for transmit */
-       bdp = fep->tx_bd_base;
-       fep->cur_tx = bdp;
-       for (i = 0; i < TX_RING_SIZE; i++) {
-
-               /* Initialize the BD for every fragment in the page. */
-               bdp->cbd_sc = 0;
-               bdp->cbd_bufaddr = 0;
-               bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex);
-       }
-
-       /* Set the last buffer to wrap */
-       bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
-       bdp->cbd_sc |= BD_SC_WRAP;
-       fep->dirty_tx = bdp;
-
        fec_restart(ndev, 0);
 
        return 0;
index f5390071efd0622832686d753f501c49039906c2..eb4372962839c216ed1ad68e29ba09a7aaf487ea 100644 (file)
@@ -240,6 +240,7 @@ struct fec_enet_private {
        phy_interface_t phy_interface;
        int     link;
        int     full_duplex;
+       int     speed;
        struct  completion mdio_done;
        int     irq[FEC_IRQ_NUM];
        int     bufdesc_ex;
index 1f17ca0f22019d8350af2affdcc6b00739ce966f..0d8df400a4798c06a1345773b9a0f821b4ab7cb2 100644 (file)
@@ -128,6 +128,7 @@ void fec_ptp_start_cyclecounter(struct net_device *ndev)
 
        spin_unlock_irqrestore(&fep->tmreg_lock, flags);
 }
+EXPORT_SYMBOL(fec_ptp_start_cyclecounter);
 
 /**
  * fec_ptp_adjfreq - adjust ptp cycle frequency
@@ -318,6 +319,7 @@ int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd)
        return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
            -EFAULT : 0;
 }
+EXPORT_SYMBOL(fec_ptp_ioctl);
 
 /**
  * fec_time_keep - call timecounter_read every second to avoid timer overrun
@@ -383,3 +385,4 @@ void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev)
                pr_info("registered PHC device on %s\n", ndev->name);
        }
 }
+EXPORT_SYMBOL(fec_ptp_init);
index 43462d596a4e5b04050793d66e26b0172a4f78de..ffd287196bf875560e40e5330c68e0a84b50e930 100644 (file)
@@ -1053,6 +1053,10 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
                txdr->buffer_info[i].dma =
                        dma_map_single(&pdev->dev, skb->data, skb->len,
                                       DMA_TO_DEVICE);
+               if (dma_mapping_error(&pdev->dev, txdr->buffer_info[i].dma)) {
+                       ret_val = 4;
+                       goto err_nomem;
+               }
                tx_desc->buffer_addr = cpu_to_le64(txdr->buffer_info[i].dma);
                tx_desc->lower.data = cpu_to_le32(skb->len);
                tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP |
@@ -1069,7 +1073,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
        rxdr->buffer_info = kcalloc(rxdr->count, sizeof(struct e1000_buffer),
                                    GFP_KERNEL);
        if (!rxdr->buffer_info) {
-               ret_val = 4;
+               ret_val = 5;
                goto err_nomem;
        }
 
@@ -1077,7 +1081,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
        rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
                                        GFP_KERNEL);
        if (!rxdr->desc) {
-               ret_val = 5;
+               ret_val = 6;
                goto err_nomem;
        }
        memset(rxdr->desc, 0, rxdr->size);
@@ -1101,7 +1105,7 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 
                skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL);
                if (!skb) {
-                       ret_val = 6;
+                       ret_val = 7;
                        goto err_nomem;
                }
                skb_reserve(skb, NET_IP_ALIGN);
@@ -1110,6 +1114,10 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
                rxdr->buffer_info[i].dma =
                        dma_map_single(&pdev->dev, skb->data,
                                       E1000_RXBUFFER_2048, DMA_FROM_DEVICE);
+               if (dma_mapping_error(&pdev->dev, rxdr->buffer_info[i].dma)) {
+                       ret_val = 8;
+                       goto err_nomem;
+               }
                rx_desc->buffer_addr = cpu_to_le64(rxdr->buffer_info[i].dma);
                memset(skb->data, 0x00, skb->len);
        }
index 2c1813737f6d2562189065d945a5002750d8e10c..f91a8f3f9d48beff868f0e9e567ec1779273c877 100644 (file)
@@ -36,6 +36,7 @@
 #include <linux/delay.h>
 #include <linux/vmalloc.h>
 #include <linux/mdio.h>
+#include <linux/pm_runtime.h>
 
 #include "e1000.h"
 
@@ -2229,7 +2230,19 @@ static int e1000e_get_ts_info(struct net_device *netdev,
        return 0;
 }
 
+static int e1000e_ethtool_begin(struct net_device *netdev)
+{
+       return pm_runtime_get_sync(netdev->dev.parent);
+}
+
+static void e1000e_ethtool_complete(struct net_device *netdev)
+{
+       pm_runtime_put_sync(netdev->dev.parent);
+}
+
 static const struct ethtool_ops e1000_ethtool_ops = {
+       .begin                  = e1000e_ethtool_begin,
+       .complete               = e1000e_ethtool_complete,
        .get_settings           = e1000_get_settings,
        .set_settings           = e1000_set_settings,
        .get_drvinfo            = e1000_get_drvinfo,
index dff7bff8b8e0f1d5ee4e6ca4af510516b3d7fd49..121a865c7fbd12855b32b5dff2883332f3b9485b 100644 (file)
@@ -781,6 +781,59 @@ release:
        return ret_val;
 }
 
+/**
+ *  e1000_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP
+ *  @hw:   pointer to the HW structure
+ *  @link: link up bool flag
+ *
+ *  When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications
+ *  preventing further DMA write requests.  Workaround the issue by disabling
+ *  the de-assertion of the clock request when in 1Gpbs mode.
+ **/
+static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link)
+{
+       u32 fextnvm6 = er32(FEXTNVM6);
+       s32 ret_val = 0;
+
+       if (link && (er32(STATUS) & E1000_STATUS_SPEED_1000)) {
+               u16 kmrn_reg;
+
+               ret_val = hw->phy.ops.acquire(hw);
+               if (ret_val)
+                       return ret_val;
+
+               ret_val =
+                   e1000e_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
+                                               &kmrn_reg);
+               if (ret_val)
+                       goto release;
+
+               ret_val =
+                   e1000e_write_kmrn_reg_locked(hw,
+                                                E1000_KMRNCTRLSTA_K1_CONFIG,
+                                                kmrn_reg &
+                                                ~E1000_KMRNCTRLSTA_K1_ENABLE);
+               if (ret_val)
+                       goto release;
+
+               usleep_range(10, 20);
+
+               ew32(FEXTNVM6, fextnvm6 | E1000_FEXTNVM6_REQ_PLL_CLK);
+
+               ret_val =
+                   e1000e_write_kmrn_reg_locked(hw,
+                                                E1000_KMRNCTRLSTA_K1_CONFIG,
+                                                kmrn_reg);
+release:
+               hw->phy.ops.release(hw);
+       } else {
+               /* clear FEXTNVM6 bit 8 on link down or 10/100 */
+               ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
+       }
+
+       return ret_val;
+}
+
 /**
  *  e1000_check_for_copper_link_ich8lan - Check for link (Copper)
  *  @hw: pointer to the HW structure
@@ -818,6 +871,14 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
                        return ret_val;
        }
 
+       /* Work-around I218 hang issue */
+       if ((hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
+           (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_V)) {
+               ret_val = e1000_k1_workaround_lpt_lp(hw, link);
+               if (ret_val)
+                       return ret_val;
+       }
+
        /* Clear link partner's EEE ability */
        hw->dev_spec.ich8lan.eee_lp_ability = 0;
 
@@ -3954,8 +4015,16 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
 
        phy_ctrl = er32(PHY_CTRL);
        phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE;
+
        if (hw->phy.type == e1000_phy_i217) {
-               u16 phy_reg;
+               u16 phy_reg, device_id = hw->adapter->pdev->device;
+
+               if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
+                   (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V)) {
+                       u32 fextnvm6 = er32(FEXTNVM6);
+
+                       ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
+               }
 
                ret_val = hw->phy.ops.acquire(hw);
                if (ret_val)
index b6d3174d7d2d737ff599b2f3f17d6bb7bb1b7cc6..8bf4655c2e17f25a26b70bb6c0ad268034bf8c04 100644 (file)
@@ -92,6 +92,8 @@
 #define E1000_FEXTNVM4_BEACON_DURATION_8USEC   0x7
 #define E1000_FEXTNVM4_BEACON_DURATION_16USEC  0x3
 
+#define E1000_FEXTNVM6_REQ_PLL_CLK     0x00000100
+
 #define PCIE_ICH8_SNOOP_ALL    PCIE_NO_SNOOP_ALL
 
 #define E1000_ICH_RAR_ENTRIES  7
index a177b8b65c44c615271b85840c18bd217f959212..7e615e2bf7e6a4e96971945d33e3e332301e88bb 100644 (file)
@@ -848,11 +848,16 @@ check_page:
                        }
                }
 
-               if (!buffer_info->dma)
+               if (!buffer_info->dma) {
                        buffer_info->dma = dma_map_page(&pdev->dev,
                                                        buffer_info->page, 0,
                                                        PAGE_SIZE,
                                                        DMA_FROM_DEVICE);
+                       if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
+                               adapter->alloc_rx_buff_failed++;
+                               break;
+                       }
+               }
 
                rx_desc = E1000_RX_DESC_EXT(*rx_ring, i);
                rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma);
@@ -4303,6 +4308,7 @@ static int e1000_open(struct net_device *netdev)
        netif_start_queue(netdev);
 
        adapter->idle_check = true;
+       hw->mac.get_link_status = true;
        pm_runtime_put(&pdev->dev);
 
        /* fire a link status change interrupt to start the watchdog */
@@ -4662,6 +4668,7 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
            (adapter->hw.phy.media_type == e1000_media_type_copper)) {
                int ret_val;
 
+               pm_runtime_get_sync(&adapter->pdev->dev);
                ret_val = e1e_rphy(hw, MII_BMCR, &phy->bmcr);
                ret_val |= e1e_rphy(hw, MII_BMSR, &phy->bmsr);
                ret_val |= e1e_rphy(hw, MII_ADVERTISE, &phy->advertise);
@@ -4672,6 +4679,7 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter)
                ret_val |= e1e_rphy(hw, MII_ESTATUS, &phy->estatus);
                if (ret_val)
                        e_warn("Error reading PHY register\n");
+               pm_runtime_put_sync(&adapter->pdev->dev);
        } else {
                /* Do not read PHY registers if link is not up
                 * Set values to typical power-on defaults
@@ -5887,8 +5895,7 @@ release:
        return retval;
 }
 
-static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
-                           bool runtime)
+static int __e1000_shutdown(struct pci_dev *pdev, bool runtime)
 {
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
@@ -5912,10 +5919,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
        }
        e1000e_reset_interrupt_capability(adapter);
 
-       retval = pci_save_state(pdev);
-       if (retval)
-               return retval;
-
        status = er32(STATUS);
        if (status & E1000_STATUS_LU)
                wufc &= ~E1000_WUFC_LNKC;
@@ -5971,13 +5974,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
                ew32(WUFC, 0);
        }
 
-       *enable_wake = !!wufc;
-
-       /* make sure adapter isn't asleep if manageability is enabled */
-       if ((adapter->flags & FLAG_MNG_PT_ENABLED) ||
-           (hw->mac.ops.check_mng_mode(hw)))
-               *enable_wake = true;
-
        if (adapter->hw.phy.type == e1000_phy_igp_3)
                e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw);
 
@@ -5986,27 +5982,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake,
         */
        e1000e_release_hw_control(adapter);
 
-       pci_disable_device(pdev);
-
-       return 0;
-}
-
-static void e1000_power_off(struct pci_dev *pdev, bool sleep, bool wake)
-{
-       if (sleep && wake) {
-               pci_prepare_to_sleep(pdev);
-               return;
-       }
-
-       pci_wake_from_d3(pdev, wake);
-       pci_set_power_state(pdev, PCI_D3hot);
-}
-
-static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
-                                    bool wake)
-{
-       struct net_device *netdev = pci_get_drvdata(pdev);
-       struct e1000_adapter *adapter = netdev_priv(netdev);
+       pci_clear_master(pdev);
 
        /* The pci-e switch on some quad port adapters will report a
         * correctable error when the MAC transitions from D0 to D3.  To
@@ -6021,12 +5997,13 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep,
                pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL,
                                           (devctl & ~PCI_EXP_DEVCTL_CERE));
 
-               e1000_power_off(pdev, sleep, wake);
+               pci_save_state(pdev);
+               pci_prepare_to_sleep(pdev);
 
                pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, devctl);
-       } else {
-               e1000_power_off(pdev, sleep, wake);
        }
+
+       return 0;
 }
 
 #ifdef CONFIG_PCIEASPM
@@ -6084,9 +6061,7 @@ static int __e1000_resume(struct pci_dev *pdev)
        if (aspm_disable_flag)
                e1000e_disable_aspm(pdev, aspm_disable_flag);
 
-       pci_set_power_state(pdev, PCI_D0);
-       pci_restore_state(pdev);
-       pci_save_state(pdev);
+       pci_set_master(pdev);
 
        e1000e_set_interrupt_capability(adapter);
        if (netif_running(netdev)) {
@@ -6152,14 +6127,8 @@ static int __e1000_resume(struct pci_dev *pdev)
 static int e1000_suspend(struct device *dev)
 {
        struct pci_dev *pdev = to_pci_dev(dev);
-       int retval;
-       bool wake;
 
-       retval = __e1000_shutdown(pdev, &wake, false);
-       if (!retval)
-               e1000_complete_shutdown(pdev, true, wake);
-
-       return retval;
+       return __e1000_shutdown(pdev, false);
 }
 
 static int e1000_resume(struct device *dev)
@@ -6182,13 +6151,10 @@ static int e1000_runtime_suspend(struct device *dev)
        struct net_device *netdev = pci_get_drvdata(pdev);
        struct e1000_adapter *adapter = netdev_priv(netdev);
 
-       if (e1000e_pm_ready(adapter)) {
-               bool wake;
-
-               __e1000_shutdown(pdev, &wake, true);
-       }
+       if (!e1000e_pm_ready(adapter))
+               return 0;
 
-       return 0;
+       return __e1000_shutdown(pdev, true);
 }
 
 static int e1000_idle(struct device *dev)
@@ -6226,12 +6192,7 @@ static int e1000_runtime_resume(struct device *dev)
 
 static void e1000_shutdown(struct pci_dev *pdev)
 {
-       bool wake = false;
-
-       __e1000_shutdown(pdev, &wake, false);
-
-       if (system_state == SYSTEM_POWER_OFF)
-               e1000_complete_shutdown(pdev, false, wake);
+       __e1000_shutdown(pdev, false);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -6352,9 +6313,9 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev)
                        "Cannot re-enable PCI device after reset.\n");
                result = PCI_ERS_RESULT_DISCONNECT;
        } else {
-               pci_set_master(pdev);
                pdev->state_saved = true;
                pci_restore_state(pdev);
+               pci_set_master(pdev);
 
                pci_enable_wake(pdev, PCI_D3hot, 0);
                pci_enable_wake(pdev, PCI_D3cold, 0);
@@ -6783,7 +6744,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        /* initialize the wol settings based on the eeprom settings */
        adapter->wol = adapter->eeprom_wol;
-       device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
+       /* make sure adapter isn't asleep if manageability is enabled */
+       if (adapter->wol || (adapter->flags & FLAG_MNG_PT_ENABLED) ||
+           (hw->mac.ops.check_mng_mode(hw)))
+               device_wakeup_enable(&pdev->dev);
 
        /* save off EEPROM version number */
        e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers);
index 794fe14976667059b3cb33924f49dec84cde2aef..a7e6a3e37257b34f200ba01c3525fd3269964943 100644 (file)
@@ -42,6 +42,7 @@
 #define E1000_FEXTNVM  0x00028 /* Future Extended NVM - RW */
 #define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */
 #define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */
+#define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */
 #define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */
 #define E1000_FCT      0x00030 /* Flow Control Type - RW */
 #define E1000_VET      0x00038 /* VLAN Ether Type - RW */
index 84e7e0909def4bb866411851b2a8ceecffeb1212..12b1d84808084269971e5f83f55bd8b0f3fb8240 100644 (file)
@@ -1361,11 +1361,16 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw)
        switch (hw->phy.type) {
        case e1000_phy_i210:
        case e1000_phy_m88:
-               if (hw->phy.id == I347AT4_E_PHY_ID ||
-                   hw->phy.id == M88E1112_E_PHY_ID)
+               switch (hw->phy.id) {
+               case I347AT4_E_PHY_ID:
+               case M88E1112_E_PHY_ID:
+               case I210_I_PHY_ID:
                        ret_val = igb_copper_link_setup_m88_gen2(hw);
-               else
+                       break;
+               default:
                        ret_val = igb_copper_link_setup_m88(hw);
+                       break;
+               }
                break;
        case e1000_phy_igp_3:
                ret_val = igb_copper_link_setup_igp(hw);
@@ -1813,27 +1818,32 @@ out:
  **/
 void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf)
 {
-       u32 dtxswc;
+       u32 reg_val, reg_offset;
 
        switch (hw->mac.type) {
        case e1000_82576:
+               reg_offset = E1000_DTXSWC;
+               break;
        case e1000_i350:
-               dtxswc = rd32(E1000_DTXSWC);
-               if (enable) {
-                       dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK |
-                                  E1000_DTXSWC_VLAN_SPOOF_MASK);
-                       /* The PF can spoof - it has to in order to
-                        * support emulation mode NICs */
-                       dtxswc ^= (1 << pf | 1 << (pf + MAX_NUM_VFS));
-               } else {
-                       dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
-                                   E1000_DTXSWC_VLAN_SPOOF_MASK);
-               }
-               wr32(E1000_DTXSWC, dtxswc);
+               reg_offset = E1000_TXSWC;
                break;
        default:
-               break;
+               return;
+       }
+
+       reg_val = rd32(reg_offset);
+       if (enable) {
+               reg_val |= (E1000_DTXSWC_MAC_SPOOF_MASK |
+                            E1000_DTXSWC_VLAN_SPOOF_MASK);
+               /* The PF can spoof - it has to in order to
+                * support emulation mode NICs
+                */
+               reg_val ^= (1 << pf | 1 << (pf + MAX_NUM_VFS));
+       } else {
+               reg_val &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
+                            E1000_DTXSWC_VLAN_SPOOF_MASK);
        }
+       wr32(reg_offset, reg_val);
 }
 
 /**
index d27edbc63923a2f2429ef85d3e7713c50f8e8469..25151401c2abe54dcec7fe1fe6f48791e0660a64 100644 (file)
@@ -447,7 +447,7 @@ struct igb_adapter {
 #endif
        struct i2c_algo_bit_data i2c_algo;
        struct i2c_adapter i2c_adap;
-       struct igb_i2c_client_list *i2c_clients;
+       struct i2c_client *i2c_client;
 };
 
 #define IGB_FLAG_HAS_MSI               (1 << 0)
index 0a9b073d0b033ea7e03f745e4983e048804daf1f..0478a1abe54110d1374c6d77d950f6a4d7bf0327 100644 (file)
 #include <linux/pci.h>
 
 #ifdef CONFIG_IGB_HWMON
+static struct i2c_board_info i350_sensor_info = {
+       I2C_BOARD_INFO("i350bb", (0Xf8 >> 1)),
+};
+
 /* hwmon callback functions */
 static ssize_t igb_hwmon_show_location(struct device *dev,
                                         struct device_attribute *attr,
@@ -188,6 +192,7 @@ int igb_sysfs_init(struct igb_adapter *adapter)
        unsigned int i;
        int n_attrs;
        int rc = 0;
+       struct i2c_client *client = NULL;
 
        /* If this method isn't defined we don't support thermals */
        if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL)
@@ -198,6 +203,15 @@ int igb_sysfs_init(struct igb_adapter *adapter)
                if (rc)
                        goto exit;
 
+       /* init i2c_client */
+       client = i2c_new_device(&adapter->i2c_adap, &i350_sensor_info);
+       if (client == NULL) {
+               dev_info(&adapter->pdev->dev,
+                       "Failed to create new i2c device..\n");
+               goto exit;
+       }
+       adapter->i2c_client = client;
+
        /* Allocation space for max attributes
         * max num sensors * values (loc, temp, max, caution)
         */
index ed79a1c53b59b0c101f1e5a2c2363f67f1fe0b04..8496adfc6a685580f6ec1c50b86f0fed62b2b121 100644 (file)
@@ -1923,10 +1923,6 @@ void igb_set_fw_version(struct igb_adapter *adapter)
        return;
 }
 
-static const struct i2c_board_info i350_sensor_info = {
-       I2C_BOARD_INFO("i350bb", 0Xf8),
-};
-
 /*  igb_init_i2c - Init I2C interface
  *  @adapter: pointer to adapter structure
  *
@@ -2546,8 +2542,8 @@ static void igb_probe_vfs(struct igb_adapter *adapter)
        if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211))
                return;
 
-       igb_enable_sriov(pdev, max_vfs);
        pci_sriov_set_totalvfs(pdev, 7);
+       igb_enable_sriov(pdev, max_vfs);
 
 #endif /* CONFIG_PCI_IOV */
 }
@@ -2656,7 +2652,7 @@ static int igb_sw_init(struct igb_adapter *adapter)
                if (max_vfs > 7) {
                        dev_warn(&pdev->dev,
                                 "Maximum of 7 VFs per PF, using max\n");
-                       adapter->vfs_allocated_count = 7;
+                       max_vfs = adapter->vfs_allocated_count = 7;
                } else
                        adapter->vfs_allocated_count = max_vfs;
                if (adapter->vfs_allocated_count)
@@ -6227,13 +6223,6 @@ static struct sk_buff *igb_build_rx_buffer(struct igb_ring *rx_ring,
        /* If we spanned a buffer we have a huge mess so test for it */
        BUG_ON(unlikely(!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP)));
 
-       /* Guarantee this function can be used by verifying buffer sizes */
-       BUILD_BUG_ON(SKB_WITH_OVERHEAD(IGB_RX_BUFSZ) < (NET_SKB_PAD +
-                                                       NET_IP_ALIGN +
-                                                       IGB_TS_HDR_LEN +
-                                                       ETH_FRAME_LEN +
-                                                       ETH_FCS_LEN));
-
        rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean];
        page = rx_buffer->page;
        prefetchw(page);
@@ -7724,67 +7713,6 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba)
        }
 }
 
-static DEFINE_SPINLOCK(i2c_clients_lock);
-
-/*  igb_get_i2c_client - returns matching client
- *  in adapters's client list.
- *  @adapter: adapter struct
- *  @dev_addr: device address of i2c needed.
- */
-static struct i2c_client *
-igb_get_i2c_client(struct igb_adapter *adapter, u8 dev_addr)
-{
-       ulong flags;
-       struct igb_i2c_client_list *client_list;
-       struct i2c_client *client = NULL;
-       struct i2c_board_info client_info = {
-               I2C_BOARD_INFO("igb", 0x00),
-       };
-
-       spin_lock_irqsave(&i2c_clients_lock, flags);
-       client_list = adapter->i2c_clients;
-
-       /* See if we already have an i2c_client */
-       while (client_list) {
-               if (client_list->client->addr == (dev_addr >> 1)) {
-                       client = client_list->client;
-                       goto exit;
-               } else {
-                       client_list = client_list->next;
-               }
-       }
-
-       /* no client_list found, create a new one */
-       client_list = kzalloc(sizeof(*client_list), GFP_ATOMIC);
-       if (client_list == NULL)
-               goto exit;
-
-       /* dev_addr passed to us is left-shifted by 1 bit
-        * i2c_new_device call expects it to be flush to the right.
-        */
-       client_info.addr = dev_addr >> 1;
-       client_info.platform_data = adapter;
-       client_list->client = i2c_new_device(&adapter->i2c_adap, &client_info);
-       if (client_list->client == NULL) {
-               dev_info(&adapter->pdev->dev,
-                       "Failed to create new i2c device..\n");
-               goto err_no_client;
-       }
-
-       /* insert new client at head of list */
-       client_list->next = adapter->i2c_clients;
-       adapter->i2c_clients = client_list;
-
-       client = client_list->client;
-       goto exit;
-
-err_no_client:
-       kfree(client_list);
-exit:
-       spin_unlock_irqrestore(&i2c_clients_lock, flags);
-       return client;
-}
-
 /*  igb_read_i2c_byte - Reads 8 bit word over I2C
  *  @hw: pointer to hardware structure
  *  @byte_offset: byte offset to read
@@ -7798,7 +7726,7 @@ s32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset,
                                u8 dev_addr, u8 *data)
 {
        struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw);
-       struct i2c_client *this_client = igb_get_i2c_client(adapter, dev_addr);
+       struct i2c_client *this_client = adapter->i2c_client;
        s32 status;
        u16 swfw_mask = 0;
 
@@ -7835,7 +7763,7 @@ s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset,
                                 u8 dev_addr, u8 data)
 {
        struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw);
-       struct i2c_client *this_client = igb_get_i2c_client(adapter, dev_addr);
+       struct i2c_client *this_client = adapter->i2c_client;
        s32 status;
        u16 swfw_mask = E1000_SWFW_PHY0_SM;
 
index 0987822359f00590d7f36bc5e126c8a4f20ee1ac..0a237507ee85008e9e11c703b07f58730202e072 100644 (file)
@@ -740,7 +740,7 @@ void igb_ptp_init(struct igb_adapter *adapter)
        case e1000_82576:
                snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr);
                adapter->ptp_caps.owner = THIS_MODULE;
-               adapter->ptp_caps.max_adj = 1000000000;
+               adapter->ptp_caps.max_adj = 999999881;
                adapter->ptp_caps.n_ext_ts = 0;
                adapter->ptp_caps.pps = 0;
                adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82576;
index ea48083734359e52b229f592e84abf7654a82523..b5f94abe3cffc9c406f8e2aaa27ed9cd77ad6542 100644 (file)
@@ -2159,6 +2159,10 @@ map_skb:
                                                  skb->data,
                                                  adapter->rx_buffer_len,
                                                  DMA_FROM_DEVICE);
+               if (dma_mapping_error(&pdev->dev, buffer_info->dma)) {
+                       adapter->alloc_rx_buff_failed++;
+                       break;
+               }
 
                rx_desc = IXGB_RX_DESC(*rx_ring, i);
                rx_desc->buff_addr = cpu_to_le64(buffer_info->dma);
@@ -2168,7 +2172,8 @@ map_skb:
                rx_desc->status = 0;
 
 
-               if (++i == rx_ring->count) i = 0;
+               if (++i == rx_ring->count)
+                       i = 0;
                buffer_info = &rx_ring->buffer_info[i];
        }
 
index db5611ae407ed5ec3a2c90341e96c12e6945ff9d..79f4a26ea6cc580c1b23cd72fee362c3c495880a 100644 (file)
@@ -7922,12 +7922,19 @@ static int __init ixgbe_init_module(void)
        ixgbe_dbg_init();
 #endif /* CONFIG_DEBUG_FS */
 
+       ret = pci_register_driver(&ixgbe_driver);
+       if (ret) {
+#ifdef CONFIG_DEBUG_FS
+               ixgbe_dbg_exit();
+#endif /* CONFIG_DEBUG_FS */
+               return ret;
+       }
+
 #ifdef CONFIG_IXGBE_DCA
        dca_register_notify(&dca_notifier);
 #endif
 
-       ret = pci_register_driver(&ixgbe_driver);
-       return ret;
+       return 0;
 }
 
 module_init(ixgbe_init_module);
index c3db6cd69b68b0135f42908fd738bd7c9fd4fddc..2b6cb5ca48eefe8f0a075b1166f24dff7aaaaa83 100644 (file)
@@ -944,9 +944,17 @@ free_queue_irqs:
                free_irq(adapter->msix_entries[vector].vector,
                         adapter->q_vector[vector]);
        }
-       pci_disable_msix(adapter->pdev);
-       kfree(adapter->msix_entries);
-       adapter->msix_entries = NULL;
+       /* This failure is non-recoverable - it indicates the system is
+        * out of MSIX vector resources and the VF driver cannot run
+        * without them.  Set the number of msix vectors to zero
+        * indicating that not enough can be allocated.  The error
+        * will be returned to the user indicating device open failed.
+        * Any further attempts to force the driver to open will also
+        * fail.  The only way to recover is to unload the driver and
+        * reload it again.  If the system has recovered some MSIX
+        * vectors then it may succeed.
+        */
+       adapter->num_msix_vectors = 0;
        return err;
 }
 
@@ -2572,6 +2580,15 @@ static int ixgbevf_open(struct net_device *netdev)
        struct ixgbe_hw *hw = &adapter->hw;
        int err;
 
+       /* A previous failure to open the device because of a lack of
+        * available MSIX vector resources may have reset the number
+        * of msix vectors variable to zero.  The only way to recover
+        * is to unload/reload the driver and hope that the system has
+        * been able to recover some MSIX vector resources.
+        */
+       if (!adapter->num_msix_vectors)
+               return -ENOMEM;
+
        /* disallow open during test */
        if (test_bit(__IXGBEVF_TESTING, &adapter->state))
                return -EBUSY;
@@ -2628,7 +2645,6 @@ static int ixgbevf_open(struct net_device *netdev)
 
 err_req_irq:
        ixgbevf_down(adapter);
-       ixgbevf_free_irq(adapter);
 err_setup_rx:
        ixgbevf_free_all_rx_resources(adapter);
 err_setup_tx:
index 6a2127489af78e718264f202737ba0667770ba1b..bfdb06860397e720a848d6e8cab7b324ded6ea1c 100644 (file)
@@ -769,7 +769,7 @@ ltq_etop_probe(struct platform_device *pdev)
        return 0;
 
 err_free:
-       kfree(dev);
+       free_netdev(dev);
 err_out:
        return err;
 }
index 29140502b71aea8765a917f2b68e34d8d645b249..6562c736a1d83df96a8feb249a289268b014a854 100644 (file)
@@ -1081,6 +1081,45 @@ static void txq_set_fixed_prio_mode(struct tx_queue *txq)
 
 
 /* mii management interface *************************************************/
+static void mv643xx_adjust_pscr(struct mv643xx_eth_private *mp)
+{
+       u32 pscr = rdlp(mp, PORT_SERIAL_CONTROL);
+       u32 autoneg_disable = FORCE_LINK_PASS |
+                    DISABLE_AUTO_NEG_SPEED_GMII |
+                    DISABLE_AUTO_NEG_FOR_FLOW_CTRL |
+                    DISABLE_AUTO_NEG_FOR_DUPLEX;
+
+       if (mp->phy->autoneg == AUTONEG_ENABLE) {
+               /* enable auto negotiation */
+               pscr &= ~autoneg_disable;
+               goto out_write;
+       }
+
+       pscr |= autoneg_disable;
+
+       if (mp->phy->speed == SPEED_1000) {
+               /* force gigabit, half duplex not supported */
+               pscr |= SET_GMII_SPEED_TO_1000;
+               pscr |= SET_FULL_DUPLEX_MODE;
+               goto out_write;
+       }
+
+       pscr &= ~SET_GMII_SPEED_TO_1000;
+
+       if (mp->phy->speed == SPEED_100)
+               pscr |= SET_MII_SPEED_TO_100;
+       else
+               pscr &= ~SET_MII_SPEED_TO_100;
+
+       if (mp->phy->duplex == DUPLEX_FULL)
+               pscr |= SET_FULL_DUPLEX_MODE;
+       else
+               pscr &= ~SET_FULL_DUPLEX_MODE;
+
+out_write:
+       wrlp(mp, PORT_SERIAL_CONTROL, pscr);
+}
+
 static irqreturn_t mv643xx_eth_err_irq(int irq, void *dev_id)
 {
        struct mv643xx_eth_shared_private *msp = dev_id;
@@ -1499,6 +1538,7 @@ static int
 mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
        struct mv643xx_eth_private *mp = netdev_priv(dev);
+       int ret;
 
        if (mp->phy == NULL)
                return -EINVAL;
@@ -1508,7 +1548,10 @@ mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
         */
        cmd->advertising &= ~ADVERTISED_1000baseT_Half;
 
-       return phy_ethtool_sset(mp->phy, cmd);
+       ret = phy_ethtool_sset(mp->phy, cmd);
+       if (!ret)
+               mv643xx_adjust_pscr(mp);
+       return ret;
 }
 
 static void mv643xx_eth_get_drvinfo(struct net_device *dev,
@@ -2442,11 +2485,15 @@ static int mv643xx_eth_stop(struct net_device *dev)
 static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 {
        struct mv643xx_eth_private *mp = netdev_priv(dev);
+       int ret;
 
-       if (mp->phy != NULL)
-               return phy_mii_ioctl(mp->phy, ifr, cmd);
+       if (mp->phy == NULL)
+               return -ENOTSUPP;
 
-       return -EOPNOTSUPP;
+       ret = phy_mii_ioctl(mp->phy, ifr, cmd);
+       if (!ret)
+               mv643xx_adjust_pscr(mp);
+       return ret;
 }
 
 static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu)
index fc07ca35721b29ba07dba97bf6e52dc74f446534..6a0e671fcecd6e399952056646130578191ba57d 100644 (file)
@@ -1067,7 +1067,7 @@ static void sky2_ramset(struct sky2_hw *hw, u16 q, u32 start, u32 space)
                sky2_write32(hw, RB_ADDR(q, RB_RX_UTHP), tp);
                sky2_write32(hw, RB_ADDR(q, RB_RX_LTHP), space/2);
 
-               tp = space - 2048/8;
+               tp = space - 8192/8;
                sky2_write32(hw, RB_ADDR(q, RB_RX_UTPP), tp);
                sky2_write32(hw, RB_ADDR(q, RB_RX_LTPP), space/4);
        } else {
index 615ac63ea8603a802896d2bd810d4c2ac874204c..ec6dcd80152bdd46550b0aaf0865d00a01261a93 100644 (file)
@@ -2074,7 +2074,7 @@ enum {
        GM_IS_RX_FF_OR  = 1<<1, /* Receive FIFO Overrun */
        GM_IS_RX_COMPL  = 1<<0, /* Frame Reception Complete */
 
-#define GMAC_DEF_MSK     GM_IS_TX_FF_UR
+#define GMAC_DEF_MSK     (GM_IS_TX_FF_UR | GM_IS_RX_FF_OR)
 };
 
 /*     GMAC_LINK_CTRL  16 bit  GMAC Link Control Reg (YUKON only) */
index 7e64033d7de39ed7723c162c75e24cf49cd3d6fa..0706623cfb96abf74b2d6ebb15d15f05d18504f5 100644 (file)
@@ -226,7 +226,7 @@ void __mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
 
 static void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn)
 {
-       u64 in_param;
+       u64 in_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
index bb4d8d99f36d2d69060a534e4e39ca07a69187a8..30d78f806dc3735dd3d8a4aa0c9a21a867976cd2 100644 (file)
@@ -411,8 +411,8 @@ static int mlx4_en_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
 
 static void mlx4_en_u64_to_mac(unsigned char dst_mac[ETH_ALEN + 2], u64 src_mac)
 {
-       unsigned int i;
-       for (i = ETH_ALEN - 1; i; --i) {
+       int i;
+       for (i = ETH_ALEN - 1; i >= 0; --i) {
                dst_mac[i] = src_mac & 0xff;
                src_mac >>= 8;
        }
@@ -565,34 +565,38 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv)
        struct mlx4_en_dev *mdev = priv->mdev;
        struct mlx4_dev *dev = mdev->dev;
        int qpn = priv->base_qpn;
-       u64 mac = mlx4_en_mac_to_u64(priv->dev->dev_addr);
-
-       en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
-              priv->dev->dev_addr);
-       mlx4_unregister_mac(dev, priv->port, mac);
+       u64 mac;
 
-       if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) {
+       if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) {
+               mac = mlx4_en_mac_to_u64(priv->dev->dev_addr);
+               en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
+                      priv->dev->dev_addr);
+               mlx4_unregister_mac(dev, priv->port, mac);
+       } else {
                struct mlx4_mac_entry *entry;
                struct hlist_node *tmp;
                struct hlist_head *bucket;
-               unsigned int mac_hash;
+               unsigned int i;
 
-               mac_hash = priv->dev->dev_addr[MLX4_EN_MAC_HASH_IDX];
-               bucket = &priv->mac_hash[mac_hash];
-               hlist_for_each_entry_safe(entry, tmp, bucket, hlist) {
-                       if (ether_addr_equal_64bits(entry->mac,
-                                                   priv->dev->dev_addr)) {
-                               en_dbg(DRV, priv, "Releasing qp: port %d, MAC %pM, qpn %d\n",
-                                      priv->port, priv->dev->dev_addr, qpn);
+               for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) {
+                       bucket = &priv->mac_hash[i];
+                       hlist_for_each_entry_safe(entry, tmp, bucket, hlist) {
+                               mac = mlx4_en_mac_to_u64(entry->mac);
+                               en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n",
+                                      entry->mac);
                                mlx4_en_uc_steer_release(priv, entry->mac,
                                                         qpn, entry->reg_id);
-                               mlx4_qp_release_range(dev, qpn, 1);
 
+                               mlx4_unregister_mac(dev, priv->port, mac);
                                hlist_del_rcu(&entry->hlist);
                                kfree_rcu(entry, rcu);
-                               break;
                        }
                }
+
+               en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n",
+                      priv->port, qpn);
+               mlx4_qp_release_range(dev, qpn, 1);
+               priv->flags &= ~MLX4_EN_FLAG_FORCE_PROMISC;
        }
 }
 
@@ -650,28 +654,10 @@ u64 mlx4_en_mac_to_u64(u8 *addr)
        return mac;
 }
 
-static int mlx4_en_set_mac(struct net_device *dev, void *addr)
+static int mlx4_en_do_set_mac(struct mlx4_en_priv *priv)
 {
-       struct mlx4_en_priv *priv = netdev_priv(dev);
-       struct mlx4_en_dev *mdev = priv->mdev;
-       struct sockaddr *saddr = addr;
-
-       if (!is_valid_ether_addr(saddr->sa_data))
-               return -EADDRNOTAVAIL;
-
-       memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
-       queue_work(mdev->workqueue, &priv->mac_task);
-       return 0;
-}
-
-static void mlx4_en_do_set_mac(struct work_struct *work)
-{
-       struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv,
-                                                mac_task);
-       struct mlx4_en_dev *mdev = priv->mdev;
        int err = 0;
 
-       mutex_lock(&mdev->state_lock);
        if (priv->port_up) {
                /* Remove old MAC and insert the new one */
                err = mlx4_en_replace_mac(priv, priv->base_qpn,
@@ -683,7 +669,26 @@ static void mlx4_en_do_set_mac(struct work_struct *work)
        } else
                en_dbg(HW, priv, "Port is down while registering mac, exiting...\n");
 
+       return err;
+}
+
+static int mlx4_en_set_mac(struct net_device *dev, void *addr)
+{
+       struct mlx4_en_priv *priv = netdev_priv(dev);
+       struct mlx4_en_dev *mdev = priv->mdev;
+       struct sockaddr *saddr = addr;
+       int err;
+
+       if (!is_valid_ether_addr(saddr->sa_data))
+               return -EADDRNOTAVAIL;
+
+       memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN);
+
+       mutex_lock(&mdev->state_lock);
+       err = mlx4_en_do_set_mac(priv);
        mutex_unlock(&mdev->state_lock);
+
+       return err;
 }
 
 static void mlx4_en_clear_list(struct net_device *dev)
@@ -1348,7 +1353,7 @@ static void mlx4_en_do_get_stats(struct work_struct *work)
                queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
        }
        if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) {
-               queue_work(mdev->workqueue, &priv->mac_task);
+               mlx4_en_do_set_mac(priv);
                mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0;
        }
        mutex_unlock(&mdev->state_lock);
@@ -1632,6 +1637,17 @@ void mlx4_en_stop_port(struct net_device *dev, int detach)
        /* Flush multicast filter */
        mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG);
 
+       /* Remove flow steering rules for the port*/
+       if (mdev->dev->caps.steering_mode ==
+           MLX4_STEERING_MODE_DEVICE_MANAGED) {
+               ASSERT_RTNL();
+               list_for_each_entry_safe(flow, tmp_flow,
+                                        &priv->ethtool_list, list) {
+                       mlx4_flow_detach(mdev->dev, flow->id);
+                       list_del(&flow->list);
+               }
+       }
+
        mlx4_en_destroy_drop_qp(priv);
 
        /* Free TX Rings */
@@ -1652,17 +1668,6 @@ void mlx4_en_stop_port(struct net_device *dev, int detach)
        if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAGS2_REASSIGN_MAC_EN))
                mdev->mac_removed[priv->port] = 1;
 
-       /* Remove flow steering rules for the port*/
-       if (mdev->dev->caps.steering_mode ==
-           MLX4_STEERING_MODE_DEVICE_MANAGED) {
-               ASSERT_RTNL();
-               list_for_each_entry_safe(flow, tmp_flow,
-                                        &priv->ethtool_list, list) {
-                       mlx4_flow_detach(mdev->dev, flow->id);
-                       list_del(&flow->list);
-               }
-       }
-
        /* Free RX Rings */
        for (i = 0; i < priv->rx_ring_num; i++) {
                mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]);
@@ -1828,9 +1833,11 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv)
        }
 
 #ifdef CONFIG_RFS_ACCEL
-       priv->dev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->mdev->dev->caps.comp_pool);
-       if (!priv->dev->rx_cpu_rmap)
-               goto err;
+       if (priv->mdev->dev->caps.comp_pool) {
+               priv->dev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->mdev->dev->caps.comp_pool);
+               if (!priv->dev->rx_cpu_rmap)
+                       goto err;
+       }
 #endif
 
        return 0;
@@ -2078,7 +2085,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        priv->msg_enable = MLX4_EN_MSG_LEVEL;
        spin_lock_init(&priv->stats_lock);
        INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode);
-       INIT_WORK(&priv->mac_task, mlx4_en_do_set_mac);
        INIT_WORK(&priv->watchdog_task, mlx4_en_restart);
        INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate);
        INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats);
index 251ae2f9311680cb69eaada07cf3ad8a3cf58354..8e3123a1df886de6b0afb2c60397ecd28be3e4b9 100644 (file)
@@ -771,7 +771,7 @@ int mlx4_MAP_EQ_wrapper(struct mlx4_dev *dev, int slave,
        struct mlx4_slave_event_eq_info *event_eq =
                priv->mfunc.master.slave_state[slave].event_eq;
        u32 in_modifier = vhcr->in_modifier;
-       u32 eqn = in_modifier & 0x1FF;
+       u32 eqn = in_modifier & 0x3FF;
        u64 in_param =  vhcr->in_param;
        int err = 0;
        int i;
index 50917eb3013e1bad3aef4a572a006002d5ba61f0..f6245579962d5f0c1a81e31f757a52d16c7cd3de 100644 (file)
@@ -787,6 +787,14 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
        bmme_flags &= ~MLX4_BMME_FLAG_TYPE_2_WIN;
        MLX4_PUT(outbox->buf, bmme_flags, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
 
+       /* turn off device-managed steering capability if not enabled */
+       if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) {
+               MLX4_GET(field, outbox->buf,
+                        QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
+               field &= 0x7f;
+               MLX4_PUT(outbox->buf, field,
+                        QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET);
+       }
        return 0;
 }
 
index d180bc46826afd0189eb7aa0360baf598615c02b..16abde20e1fcd2daaefc6b9a671b4c6c1a4313bb 100644 (file)
@@ -1555,7 +1555,7 @@ void __mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
 
 void mlx4_counter_free(struct mlx4_dev *dev, u32 idx)
 {
-       u64 in_param;
+       u64 in_param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&in_param, idx);
index cf883345af8887eeac97eb5b7278b98a98ffe4bb..d738454116a088db7a098c88f2ef5fc9b7eb1698 100644 (file)
@@ -1235,7 +1235,7 @@ int mlx4_get_qp_per_mgm(struct mlx4_dev *dev);
 
 static inline void set_param_l(u64 *arg, u32 val)
 {
-       *((u32 *)arg) = val;
+       *arg = (*arg & 0xffffffff00000000ULL) | (u64) val;
 }
 
 static inline void set_param_h(u64 *arg, u32 val)
index c313d7e943a95cbd049d2ed000dc76ab8c4e0009..f710b7ce0dcbbf9ef740d0661add1bb744921b9f 100644 (file)
@@ -509,7 +509,6 @@ struct mlx4_en_priv {
        struct mlx4_en_cq rx_cq[MAX_RX_RINGS];
        struct mlx4_qp drop_qp;
        struct work_struct rx_mode_task;
-       struct work_struct mac_task;
        struct work_struct watchdog_task;
        struct work_struct linkstate_task;
        struct delayed_work stats_task;
index 602ca9bf78e46b22ec921140c4539105b8597454..f91719a08cbac000dc34f68f7d40252aa652ac58 100644 (file)
@@ -183,7 +183,7 @@ u32 __mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
 
 static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
 {
-       u64 in_param;
+       u64 in_param = 0;
        u64 out_param;
        int err;
 
@@ -240,7 +240,7 @@ void __mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order)
 
 static void mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order)
 {
-       u64 in_param;
+       u64 in_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
@@ -351,7 +351,7 @@ void __mlx4_mpt_release(struct mlx4_dev *dev, u32 index)
 
 static void mlx4_mpt_release(struct mlx4_dev *dev, u32 index)
 {
-       u64 in_param;
+       u64 in_param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&in_param, index);
@@ -374,7 +374,7 @@ int __mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index)
 
 static int mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index)
 {
-       u64 param;
+       u64 param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&param, index);
@@ -395,7 +395,7 @@ void __mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index)
 
 static void mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index)
 {
-       u64 in_param;
+       u64 in_param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&in_param, index);
index 1ac88637ad9de145f81d9e4851fda2387da12158..00f223acada79a8f0bf6b52ae21e75afbfb60ce0 100644 (file)
@@ -101,7 +101,7 @@ void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
 
 void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn)
 {
-       u64 in_param;
+       u64 in_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
index 719ead15e49181f1fc419b0c18310db521280eff..10c57c86388baed3626cc803fc8acadf605ca855 100644 (file)
@@ -175,7 +175,7 @@ EXPORT_SYMBOL_GPL(__mlx4_register_mac);
 
 int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac)
 {
-       u64 out_param;
+       u64 out_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
@@ -222,7 +222,7 @@ EXPORT_SYMBOL_GPL(__mlx4_unregister_mac);
 
 void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac)
 {
-       u64 out_param;
+       u64 out_param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&out_param, port);
@@ -361,7 +361,7 @@ out:
 
 int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index)
 {
-       u64 out_param;
+       u64 out_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
@@ -406,7 +406,7 @@ out:
 
 void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index)
 {
-       u64 in_param;
+       u64 in_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
index 81e2abe07bbbf656689ba327ab0d4d22368961df..e891b058c1befdc09927ea1ab49aa70e282d4278 100644 (file)
@@ -222,7 +222,7 @@ int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align,
 
 int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base)
 {
-       u64 in_param;
+       u64 in_param = 0;
        u64 out_param;
        int err;
 
@@ -255,7 +255,7 @@ void __mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt)
 
 void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt)
 {
-       u64 in_param;
+       u64 in_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
@@ -319,7 +319,7 @@ err_out:
 
 static int mlx4_qp_alloc_icm(struct mlx4_dev *dev, int qpn)
 {
-       u64 param;
+       u64 param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&param, qpn);
@@ -344,7 +344,7 @@ void __mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn)
 
 static void mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn)
 {
-       u64 in_param;
+       u64 in_param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&in_param, qpn);
index 083fb48dc3d7bd7bfa014f8ddc9a7eed81dffca5..1391b52f443aa5489ec31ee7e155b087f0372b0c 100644 (file)
@@ -99,6 +99,7 @@ struct res_qp {
        struct list_head        mcg_list;
        spinlock_t              mcg_spl;
        int                     local_qpn;
+       atomic_t                ref_count;
 };
 
 enum res_mtt_states {
@@ -197,6 +198,7 @@ enum res_fs_rule_states {
 
 struct res_fs_rule {
        struct res_common       com;
+       int                     qpn;
 };
 
 static void *res_tracker_lookup(struct rb_root *root, u64 res_id)
@@ -355,7 +357,7 @@ static int mpt_mask(struct mlx4_dev *dev)
        return dev->caps.num_mpts - 1;
 }
 
-static void *find_res(struct mlx4_dev *dev, int res_id,
+static void *find_res(struct mlx4_dev *dev, u64 res_id,
                      enum mlx4_resource type)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
@@ -447,6 +449,7 @@ static struct res_common *alloc_qp_tr(int id)
        ret->local_qpn = id;
        INIT_LIST_HEAD(&ret->mcg_list);
        spin_lock_init(&ret->mcg_spl);
+       atomic_set(&ret->ref_count, 0);
 
        return &ret->com;
 }
@@ -554,7 +557,7 @@ static struct res_common *alloc_xrcdn_tr(int id)
        return &ret->com;
 }
 
-static struct res_common *alloc_fs_rule_tr(u64 id)
+static struct res_common *alloc_fs_rule_tr(u64 id, int qpn)
 {
        struct res_fs_rule *ret;
 
@@ -564,7 +567,7 @@ static struct res_common *alloc_fs_rule_tr(u64 id)
 
        ret->com.res_id = id;
        ret->com.state = RES_FS_RULE_ALLOCATED;
-
+       ret->qpn = qpn;
        return &ret->com;
 }
 
@@ -602,7 +605,7 @@ static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave,
                ret = alloc_xrcdn_tr(id);
                break;
        case RES_FS_RULE:
-               ret = alloc_fs_rule_tr(id);
+               ret = alloc_fs_rule_tr(id, extra);
                break;
        default:
                return NULL;
@@ -671,10 +674,14 @@ undo:
 
 static int remove_qp_ok(struct res_qp *res)
 {
-       if (res->com.state == RES_QP_BUSY)
+       if (res->com.state == RES_QP_BUSY || atomic_read(&res->ref_count) ||
+           !list_empty(&res->mcg_list)) {
+               pr_err("resource tracker: fail to remove qp, state %d, ref_count %d\n",
+                      res->com.state, atomic_read(&res->ref_count));
                return -EBUSY;
-       else if (res->com.state != RES_QP_RESERVED)
+       } else if (res->com.state != RES_QP_RESERVED) {
                return -EPERM;
+       }
 
        return 0;
 }
@@ -2990,6 +2997,9 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
        u8 steer_type_mask = 2;
        enum mlx4_steer_type type = (gid[7] & steer_type_mask) >> 1;
 
+       if (dev->caps.steering_mode != MLX4_STEERING_MODE_B0)
+               return -EINVAL;
+
        qpn = vhcr->in_modifier & 0xffffff;
        err = get_res(dev, slave, qpn, RES_QP, &rqp);
        if (err)
@@ -3121,6 +3131,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
        struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC];
        int err;
        int qpn;
+       struct res_qp *rqp;
        struct mlx4_net_trans_rule_hw_ctrl *ctrl;
        struct _rule_hw  *rule_header;
        int header_id;
@@ -3131,7 +3142,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
 
        ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
        qpn = be32_to_cpu(ctrl->qpn) & 0xffffff;
-       err = get_res(dev, slave, qpn, RES_QP, NULL);
+       err = get_res(dev, slave, qpn, RES_QP, &rqp);
        if (err) {
                pr_err("Steering rule with qpn 0x%x rejected.\n", qpn);
                return err;
@@ -3172,14 +3183,16 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
        if (err)
                goto err_put;
 
-       err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, 0);
+       err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, qpn);
        if (err) {
                mlx4_err(dev, "Fail to add flow steering resources.\n ");
                /* detach rule*/
                mlx4_cmd(dev, vhcr->out_param, 0, 0,
                         MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
                         MLX4_CMD_NATIVE);
+               goto err_put;
        }
+       atomic_inc(&rqp->ref_count);
 err_put:
        put_res(dev, slave, qpn, RES_QP);
        return err;
@@ -3192,20 +3205,35 @@ int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave,
                                         struct mlx4_cmd_info *cmd)
 {
        int err;
+       struct res_qp *rqp;
+       struct res_fs_rule *rrule;
 
        if (dev->caps.steering_mode !=
            MLX4_STEERING_MODE_DEVICE_MANAGED)
                return -EOPNOTSUPP;
 
+       err = get_res(dev, slave, vhcr->in_param, RES_FS_RULE, &rrule);
+       if (err)
+               return err;
+       /* Release the rule form busy state before removal */
+       put_res(dev, slave, vhcr->in_param, RES_FS_RULE);
+       err = get_res(dev, slave, rrule->qpn, RES_QP, &rqp);
+       if (err)
+               return err;
+
        err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE, 0);
        if (err) {
                mlx4_err(dev, "Fail to remove flow steering resources.\n ");
-               return err;
+               goto out;
        }
 
        err = mlx4_cmd(dev, vhcr->in_param, 0, 0,
                       MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A,
                       MLX4_CMD_NATIVE);
+       if (!err)
+               atomic_dec(&rqp->ref_count);
+out:
+       put_res(dev, slave, rrule->qpn, RES_QP);
        return err;
 }
 
@@ -3803,6 +3831,7 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
        mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
        /*VLAN*/
        rem_slave_macs(dev, slave);
+       rem_slave_fs_rule(dev, slave);
        rem_slave_qps(dev, slave);
        rem_slave_srqs(dev, slave);
        rem_slave_cqs(dev, slave);
@@ -3811,6 +3840,5 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave)
        rem_slave_mtts(dev, slave);
        rem_slave_counters(dev, slave);
        rem_slave_xrcdns(dev, slave);
-       rem_slave_fs_rule(dev, slave);
        mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex);
 }
index feda6c00829f391e0d5bd822db970c5d6a2f7ca2..e329fe1f11b736d8e717880c7e6e7e092db2a14c 100644 (file)
@@ -149,7 +149,7 @@ void __mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn)
 
 static void mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn)
 {
-       u64 in_param;
+       u64 in_param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&in_param, srqn);
index 33bcb63d56a2355c93dbd1306f24bce816eab23c..8fb481252e2cb653f45f7543f7e41c70cef9401e 100644 (file)
@@ -528,7 +528,7 @@ static void ks8851_rx_pkts(struct ks8851_net *ks)
        for (; rxfc != 0; rxfc--) {
                rxh = ks8851_rdreg32(ks, KS_RXFHSR);
                rxstat = rxh & 0xffff;
-               rxlen = rxh >> 16;
+               rxlen = (rxh >> 16) & 0xfff;
 
                netif_dbg(ks, rx_status, ks->netdev,
                          "rx: stat 0x%04x, len 0x%04x\n", rxstat, rxlen);
index c4122c86f829293cc60d6dd48c72602d7dded49f..efa29b712d5f1bdc9793648ebd76f9201cc3f99a 100644 (file)
@@ -1472,7 +1472,8 @@ static int lpc_eth_drv_probe(struct platform_device *pdev)
        }
        platform_set_drvdata(pdev, ndev);
 
-       if (lpc_mii_init(pldat) != 0)
+       ret = lpc_mii_init(pldat);
+       if (ret)
                goto err_out_unregister_netdev;
 
        netdev_info(ndev, "LPC mac at 0x%08x irq %d\n",
index 39ab4d09faaa2eb500748466ba6ab0fbe4074ac9..73ce7dd6b9544d470a6e14b163f7ae751d3d749d 100644 (file)
@@ -1726,9 +1726,9 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter,
 
                        skb->protocol = eth_type_trans(skb, netdev);
                        if (tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK)
-                               skb->ip_summed = CHECKSUM_NONE;
-                       else
                                skb->ip_summed = CHECKSUM_UNNECESSARY;
+                       else
+                               skb->ip_summed = CHECKSUM_NONE;
 
                        napi_gro_receive(&adapter->napi, skb);
                        (*work_done)++;
index 28fb50a1e9c350851b3844592bf85adea877f604..4ecbe64a758d8b05dd5a016a9659b20bfdfb90c5 100644 (file)
@@ -3818,6 +3818,30 @@ static void rtl_init_mdio_ops(struct rtl8169_private *tp)
        }
 }
 
+static void rtl_speed_down(struct rtl8169_private *tp)
+{
+       u32 adv;
+       int lpa;
+
+       rtl_writephy(tp, 0x1f, 0x0000);
+       lpa = rtl_readphy(tp, MII_LPA);
+
+       if (lpa & (LPA_10HALF | LPA_10FULL))
+               adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full;
+       else if (lpa & (LPA_100HALF | LPA_100FULL))
+               adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+                     ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full;
+       else
+               adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+                     ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
+                     (tp->mii.supports_gmii ?
+                      ADVERTISED_1000baseT_Half |
+                      ADVERTISED_1000baseT_Full : 0);
+
+       rtl8169_set_speed(tp->dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
+                         adv);
+}
+
 static void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
 {
        void __iomem *ioaddr = tp->mmio_addr;
@@ -3848,9 +3872,7 @@ static bool rtl_wol_pll_power_down(struct rtl8169_private *tp)
        if (!(__rtl8169_get_wol(tp) & WAKE_ANY))
                return false;
 
-       rtl_writephy(tp, 0x1f, 0x0000);
-       rtl_writephy(tp, MII_BMCR, 0x0000);
-
+       rtl_speed_down(tp);
        rtl_wol_suspend_quirk(tp);
 
        return true;
index 33e96176e4d82167a2d62a51f1f1eb5d711f7375..6ed333fe5c04cd36618c465c0a3bec8dafbe8fcc 100644 (file)
@@ -1216,10 +1216,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
                if (felic_stat & ECSR_LCHNG) {
                        /* Link Changed */
                        if (mdp->cd->no_psr || mdp->no_ether_link) {
-                               if (mdp->link == PHY_DOWN)
-                                       link_stat = 0;
-                               else
-                                       link_stat = PHY_ST_LINK;
+                               goto ignore_link;
                        } else {
                                link_stat = (sh_eth_read(ndev, PSR));
                                if (mdp->ether_link_active_low)
@@ -1242,6 +1239,7 @@ static void sh_eth_error(struct net_device *ndev, int intr_status)
                }
        }
 
+ignore_link:
        if (intr_status & EESR_TWB) {
                /* Write buck end. unused write back interrupt */
                if (intr_status & EESR_TABT)    /* Transmit Abort int */
@@ -1326,12 +1324,18 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev)
        struct sh_eth_private *mdp = netdev_priv(ndev);
        struct sh_eth_cpu_data *cd = mdp->cd;
        irqreturn_t ret = IRQ_NONE;
-       u32 intr_status = 0;
+       unsigned long intr_status;
 
        spin_lock(&mdp->lock);
 
-       /* Get interrpt stat */
+       /* Get interrupt status */
        intr_status = sh_eth_read(ndev, EESR);
+       /* Mask it with the interrupt mask, forcing ECI interrupt to be always
+        * enabled since it's the one that  comes thru regardless of the mask,
+        * and we need to fully handle it in sh_eth_error() in order to quench
+        * it as it doesn't get cleared by just writing 1 to the ECI bit...
+        */
+       intr_status &= sh_eth_read(ndev, EESIPR) | DMAC_M_ECI;
        /* Clear interrupt */
        if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF |
                        EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF |
@@ -1373,7 +1377,7 @@ static void sh_eth_adjust_link(struct net_device *ndev)
        struct phy_device *phydev = mdp->phydev;
        int new_state = 0;
 
-       if (phydev->link != PHY_DOWN) {
+       if (phydev->link) {
                if (phydev->duplex != mdp->duplex) {
                        new_state = 1;
                        mdp->duplex = phydev->duplex;
@@ -1387,17 +1391,21 @@ static void sh_eth_adjust_link(struct net_device *ndev)
                        if (mdp->cd->set_rate)
                                mdp->cd->set_rate(ndev);
                }
-               if (mdp->link == PHY_DOWN) {
+               if (!mdp->link) {
                        sh_eth_write(ndev,
                                (sh_eth_read(ndev, ECMR) & ~ECMR_TXF), ECMR);
                        new_state = 1;
                        mdp->link = phydev->link;
+                       if (mdp->cd->no_psr || mdp->no_ether_link)
+                               sh_eth_rcv_snd_enable(ndev);
                }
        } else if (mdp->link) {
                new_state = 1;
-               mdp->link = PHY_DOWN;
+               mdp->link = 0;
                mdp->speed = 0;
                mdp->duplex = -1;
+               if (mdp->cd->no_psr || mdp->no_ether_link)
+                       sh_eth_rcv_snd_disable(ndev);
        }
 
        if (new_state && netif_msg_link(mdp))
@@ -1414,7 +1422,7 @@ static int sh_eth_phy_init(struct net_device *ndev)
        snprintf(phy_id, sizeof(phy_id), PHY_ID_FMT,
                mdp->mii_bus->id , mdp->phy_id);
 
-       mdp->link = PHY_DOWN;
+       mdp->link = 0;
        mdp->speed = 0;
        mdp->duplex = -1;
 
@@ -2220,6 +2228,7 @@ static void sh_eth_tsu_init(struct sh_eth_private *mdp)
 /* MDIO bus release function */
 static int sh_mdio_release(struct net_device *ndev)
 {
+       struct sh_eth_private *mdp = netdev_priv(ndev);
        struct mii_bus *bus = dev_get_drvdata(&ndev->dev);
 
        /* unregister mdio bus */
@@ -2234,6 +2243,9 @@ static int sh_mdio_release(struct net_device *ndev)
        /* free bitbang info */
        free_mdio_bitbang(bus);
 
+       /* free bitbang memory */
+       kfree(mdp->bitbang);
+
        return 0;
 }
 
@@ -2262,6 +2274,7 @@ static int sh_mdio_init(struct net_device *ndev, int id,
        bitbang->ctrl.ops = &bb_ops;
 
        /* MII controller setting */
+       mdp->bitbang = bitbang;
        mdp->mii_bus = alloc_mdio_bitbang(&bitbang->ctrl);
        if (!mdp->mii_bus) {
                ret = -ENOMEM;
@@ -2441,6 +2454,11 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
                }
                mdp->tsu_addr = ioremap(rtsu->start,
                                        resource_size(rtsu));
+               if (mdp->tsu_addr == NULL) {
+                       ret = -ENOMEM;
+                       dev_err(&pdev->dev, "TSU ioremap failed.\n");
+                       goto out_release;
+               }
                mdp->port = devno % 2;
                ndev->features = NETIF_F_HW_VLAN_FILTER;
        }
index bae84fd2e73a7419504d8b29b195c0a118711b8a..828be4515008145507f59a5bbe34ac64eb28090b 100644 (file)
@@ -705,6 +705,7 @@ struct sh_eth_private {
        const u16 *reg_offset;
        void __iomem *addr;
        void __iomem *tsu_addr;
+       struct bb_info *bitbang;
        u32 num_rx_ring;
        u32 num_tx_ring;
        dma_addr_t rx_desc_dma;
@@ -722,7 +723,7 @@ struct sh_eth_private {
        u32 phy_id;                                     /* PHY ID */
        struct mii_bus *mii_bus;        /* MDIO bus control */
        struct phy_device *phydev;      /* PHY device control */
-       enum phy_state link;
+       int link;
        phy_interface_t phy_interface;
        int msg_enable;
        int speed;
index 50247dfe8f574d2a7184c8ea675b5ecabdcc37cc..d2f790df6dcbf6872084c49d74a8a63efb58f569 100644 (file)
@@ -171,9 +171,9 @@ static inline void efx_device_detach_sync(struct efx_nic *efx)
         * TX scheduler is stopped when we're done and before
         * netif_device_present() becomes false.
         */
-       netif_tx_lock(dev);
+       netif_tx_lock_bh(dev);
        netif_device_detach(dev);
-       netif_tx_unlock(dev);
+       netif_tx_unlock_bh(dev);
 }
 
 #endif /* EFX_EFX_H */
index 0ad790cc473cb1697e71bd422af0e0086c0242a9..eaa8e874a3cb0580cbe68ca40ba5004942a91e5f 100644 (file)
@@ -376,7 +376,8 @@ efx_may_push_tx_desc(struct efx_tx_queue *tx_queue, unsigned int write_count)
                return false;
 
        tx_queue->empty_read_count = 0;
-       return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0;
+       return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0
+               && tx_queue->write_count - write_count == 1;
 }
 
 /* For each entry inserted into the software descriptor ring, create a
index 879ff5849bbd181e58e9d5be8e75f28d89f2ddad..bb579a6128c8ce883ac7156ea24ac541d4901e38 100644 (file)
@@ -215,7 +215,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue)
                rx_buf = efx_rx_buffer(rx_queue, index);
                rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN;
                rx_buf->u.page = page;
-               rx_buf->page_offset = page_offset;
+               rx_buf->page_offset = page_offset + EFX_PAGE_IP_ALIGN;
                rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
                rx_buf->flags = EFX_RX_BUF_PAGE;
                ++rx_queue->added_count;
index 01ffbc48698298d1678b478599c1b46f2ee55ef9..80cad06e5eb21337b111bc32af0376e6da2d7065 100644 (file)
@@ -436,7 +436,7 @@ void cpsw_tx_handler(void *token, int len, int status)
         * queue is stopped then start the queue as we have free desc for tx
         */
        if (unlikely(netif_queue_stopped(ndev)))
-               netif_start_queue(ndev);
+               netif_wake_queue(ndev);
        cpts_tx_timestamp(priv->cpts, skb);
        priv->stats.tx_packets++;
        priv->stats.tx_bytes += len;
@@ -905,7 +905,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb,
        /* If there is no more tx desc left free then we need to
         * tell the kernel to stop sending us tx frames.
         */
-       if (unlikely(cpdma_check_free_tx_desc(priv->txch)))
+       if (unlikely(!cpdma_check_free_tx_desc(priv->txch)))
                netif_stop_queue(ndev);
 
        return NETDEV_TX_OK;
@@ -1364,7 +1364,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data,
                struct platform_device *mdio;
 
                parp = of_get_property(slave_node, "phy_id", &lenp);
-               if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) {
+               if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) {
                        pr_err("Missing slave[%d] phy_id property\n", i);
                        ret = -EINVAL;
                        goto error_ret;
index 52c05366599aca9338267d013ca814abe5b61e78..72300bc9e3783842ef3608be24f0f33d2ed0f69b 100644 (file)
@@ -1053,7 +1053,7 @@ static void emac_tx_handler(void *token, int len, int status)
         * queue is stopped then start the queue as we have free desc for tx
         */
        if (unlikely(netif_queue_stopped(ndev)))
-               netif_start_queue(ndev);
+               netif_wake_queue(ndev);
        ndev->stats.tx_packets++;
        ndev->stats.tx_bytes += len;
        dev_kfree_skb_any(skb);
@@ -1102,7 +1102,7 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev)
        /* If there is no more tx desc left free then we need to
         * tell the kernel to stop sending us tx frames.
         */
-       if (unlikely(cpdma_check_free_tx_desc(priv->txchan)))
+       if (unlikely(!cpdma_check_free_tx_desc(priv->txchan)))
                netif_stop_queue(ndev);
 
        return NETDEV_TX_OK;
index e5b19b05690967ed93f9ac50be4d1548911bf38a..3c4d6274bb9b25527aa2af7e1daf4f07fe3a84d0 100644 (file)
@@ -202,6 +202,9 @@ static int rr_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        return 0;
 
  out:
+       if (rrpriv->evt_ring)
+               pci_free_consistent(pdev, EVT_RING_SIZE, rrpriv->evt_ring,
+                                   rrpriv->evt_ring_dma);
        if (rrpriv->rx_ring)
                pci_free_consistent(pdev, RX_TOTAL_SIZE, rrpriv->rx_ring,
                                    rrpriv->rx_ring_dma);
index 417b2af1aa8097fd3e158e8b9e09b59885d8c723..73abbc1655d5c7b793601f93027dad37d2923150 100644 (file)
@@ -660,6 +660,7 @@ void macvlan_common_setup(struct net_device *dev)
        ether_setup(dev);
 
        dev->priv_flags        &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING);
+       dev->priv_flags        |= IFF_UNICAST_FLT;
        dev->netdev_ops         = &macvlan_netdev_ops;
        dev->destructor         = free_netdev;
        dev->header_ops         = &macvlan_hard_header_ops,
index 37add21a3d7d630d2a989312deab132017eb5fcf..59ac143dec2576a697d9f383ef4d5d7372eef93c 100644 (file)
@@ -666,6 +666,7 @@ static int netconsole_netdev_event(struct notifier_block *this,
                goto done;
 
        spin_lock_irqsave(&target_list_lock, flags);
+restart:
        list_for_each_entry(nt, &target_list, list) {
                netconsole_target_get(nt);
                if (nt->np.dev == dev) {
@@ -678,15 +679,17 @@ static int netconsole_netdev_event(struct notifier_block *this,
                        case NETDEV_UNREGISTER:
                                /*
                                 * rtnl_lock already held
+                                * we might sleep in __netpoll_cleanup()
                                 */
-                               if (nt->np.dev) {
-                                       __netpoll_cleanup(&nt->np);
-                                       dev_put(nt->np.dev);
-                                       nt->np.dev = NULL;
-                               }
+                               spin_unlock_irqrestore(&target_list_lock, flags);
+                               __netpoll_cleanup(&nt->np);
+                               spin_lock_irqsave(&target_list_lock, flags);
+                               dev_put(nt->np.dev);
+                               nt->np.dev = NULL;
                                nt->enabled = 0;
                                stopped = true;
-                               break;
+                               netconsole_target_put(nt);
+                               goto restart;
                        }
                }
                netconsole_target_put(nt);
index 05c5efe8459148be152db604da421fe35e95ba41..bf3419297875b102da599162c0852ecfd9eb71eb 100644 (file)
@@ -1138,6 +1138,8 @@ static int team_port_del(struct team *team, struct net_device *port_dev)
        netdev_upper_dev_unlink(port_dev, dev);
        team_port_disable_netpoll(port);
        vlan_vids_del_by_dev(port_dev, dev);
+       dev_uc_unsync(port_dev, dev);
+       dev_mc_unsync(port_dev, dev);
        dev_close(port_dev);
        team_port_leave(team, port);
 
index 2c6a22e278ea15843b7fb4500749304aad0a1444..b7c457adc0dc7439cc2a842409ed3871207f079b 100644 (file)
@@ -747,6 +747,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
                goto drop;
        skb_orphan(skb);
 
+       nf_reset(skb);
+
        /* Enqueue packet */
        skb_queue_tail(&tfile->socket.sk->sk_receive_queue, skb);
 
index 3b6e9b83342db08c28f318c38253d315ae60317c..7c769d8e25ad835440321d9840822b3484f0d08b 100644 (file)
@@ -268,7 +268,7 @@ config USB_NET_SMSC75XX
        select CRC16
        select CRC32
        help
-         This option adds support for SMSC LAN95XX based USB 2.0
+         This option adds support for SMSC LAN75XX based USB 2.0
          Gigabit Ethernet adapters.
 
 config USB_NET_SMSC95XX
index 248d2dc765a5c06c64ab3c27c47f38d36bf14c20..16c842997291483eb12306d9ccf0a638772f18f0 100644 (file)
@@ -68,18 +68,9 @@ static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf)
        struct cdc_ncm_ctx *ctx;
        struct usb_driver *subdriver = ERR_PTR(-ENODEV);
        int ret = -ENODEV;
-       u8 data_altsetting = CDC_NCM_DATA_ALTSETTING_NCM;
+       u8 data_altsetting = cdc_ncm_select_altsetting(dev, intf);
        struct cdc_mbim_state *info = (void *)&dev->data;
 
-       /* see if interface supports MBIM alternate setting */
-       if (intf->num_altsetting == 2) {
-               if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
-                       usb_set_interface(dev->udev,
-                                         intf->cur_altsetting->desc.bInterfaceNumber,
-                                         CDC_NCM_COMM_ALTSETTING_MBIM);
-               data_altsetting = CDC_NCM_DATA_ALTSETTING_MBIM;
-       }
-
        /* Probably NCM, defer for cdc_ncm_bind */
        if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
                goto err;
index 61b74a2b89ac4fbcf2ac494fc0045645efc379a0..4709fa3497cf2efcada053ccdefc06f7061971bc 100644 (file)
 
 #define        DRIVER_VERSION                          "14-Mar-2012"
 
+#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
+static bool prefer_mbim = true;
+#else
+static bool prefer_mbim;
+#endif
+module_param(prefer_mbim, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(prefer_mbim, "Prefer MBIM setting on dual NCM/MBIM functions");
+
 static void cdc_ncm_txpath_bh(unsigned long param);
 static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx);
 static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer);
@@ -550,9 +558,12 @@ void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf)
 }
 EXPORT_SYMBOL_GPL(cdc_ncm_unbind);
 
-static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
+/* Select the MBIM altsetting iff it is preferred and available,
+ * returning the number of the corresponding data interface altsetting
+ */
+u8 cdc_ncm_select_altsetting(struct usbnet *dev, struct usb_interface *intf)
 {
-       int ret;
+       struct usb_host_interface *alt;
 
        /* The MBIM spec defines a NCM compatible default altsetting,
         * which we may have matched:
@@ -568,23 +579,27 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
         *   endpoint descriptors, shall be constructed according to
         *   the rules given in section 6 (USB Device Model) of this
         *   specification."
-        *
-        * Do not bind to such interfaces, allowing cdc_mbim to handle
-        * them
         */
-#if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM)
-       if ((intf->num_altsetting == 2) &&
-           !usb_set_interface(dev->udev,
-                              intf->cur_altsetting->desc.bInterfaceNumber,
-                              CDC_NCM_COMM_ALTSETTING_MBIM)) {
-               if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
-                       return -ENODEV;
-               else
-                       usb_set_interface(dev->udev,
-                                         intf->cur_altsetting->desc.bInterfaceNumber,
-                                         CDC_NCM_COMM_ALTSETTING_NCM);
+       if (prefer_mbim && intf->num_altsetting == 2) {
+               alt = usb_altnum_to_altsetting(intf, CDC_NCM_COMM_ALTSETTING_MBIM);
+               if (alt && cdc_ncm_comm_intf_is_mbim(alt) &&
+                   !usb_set_interface(dev->udev,
+                                      intf->cur_altsetting->desc.bInterfaceNumber,
+                                      CDC_NCM_COMM_ALTSETTING_MBIM))
+                       return CDC_NCM_DATA_ALTSETTING_MBIM;
        }
-#endif
+       return CDC_NCM_DATA_ALTSETTING_NCM;
+}
+EXPORT_SYMBOL_GPL(cdc_ncm_select_altsetting);
+
+static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+       int ret;
+
+       /* MBIM backwards compatible function? */
+       cdc_ncm_select_altsetting(dev, intf);
+       if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting))
+               return -ENODEV;
 
        /* NCM data altsetting is always 1 */
        ret = cdc_ncm_bind_common(dev, intf, 1);
index efb5c7c33a28c946c7ca44a0b8a05aeeb8048345..968d5d50751dc120b406f54fffca49b46eafa230 100644 (file)
@@ -139,16 +139,9 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf)
 
        BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state)));
 
-       /* control and data is shared? */
-       if (intf->cur_altsetting->desc.bNumEndpoints == 3) {
-               info->control = intf;
-               info->data = intf;
-               goto shared;
-       }
-
-       /* else require a single interrupt status endpoint on control intf */
-       if (intf->cur_altsetting->desc.bNumEndpoints != 1)
-               goto err;
+       /* set up initial state */
+       info->control = intf;
+       info->data = intf;
 
        /* and a number of CDC descriptors */
        while (len > 3) {
@@ -207,25 +200,14 @@ next_desc:
                buf += h->bLength;
        }
 
-       /* did we find all the required ones? */
-       if (!(found & (1 << USB_CDC_HEADER_TYPE)) ||
-           !(found & (1 << USB_CDC_UNION_TYPE))) {
-               dev_err(&intf->dev, "CDC functional descriptors missing\n");
-               goto err;
-       }
-
-       /* verify CDC Union */
-       if (desc->bInterfaceNumber != cdc_union->bMasterInterface0) {
-               dev_err(&intf->dev, "bogus CDC Union: master=%u\n", cdc_union->bMasterInterface0);
-               goto err;
-       }
-
-       /* need to save these for unbind */
-       info->control = intf;
-       info->data = usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0);
-       if (!info->data) {
-               dev_err(&intf->dev, "bogus CDC Union: slave=%u\n", cdc_union->bSlaveInterface0);
-               goto err;
+       /* Use separate control and data interfaces if we found a CDC Union */
+       if (cdc_union) {
+               info->data = usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0);
+               if (desc->bInterfaceNumber != cdc_union->bMasterInterface0 || !info->data) {
+                       dev_err(&intf->dev, "bogus CDC Union: master=%u, slave=%u\n",
+                               cdc_union->bMasterInterface0, cdc_union->bSlaveInterface0);
+                       goto err;
+               }
        }
 
        /* errors aren't fatal - we can live with the dynamic address */
@@ -235,11 +217,12 @@ next_desc:
        }
 
        /* claim data interface and set it up */
-       status = usb_driver_claim_interface(driver, info->data, dev);
-       if (status < 0)
-               goto err;
+       if (info->control != info->data) {
+               status = usb_driver_claim_interface(driver, info->data, dev);
+               if (status < 0)
+                       goto err;
+       }
 
-shared:
        status = qmi_wwan_register_subdriver(dev);
        if (status < 0 && info->control != info->data) {
                usb_set_intfdata(info->data, NULL);
index 9abe51710f229377cb9f405ffedb198eab580738..1a15ec14c386f3c4e05808722bd84a196d82f3a8 100644 (file)
@@ -914,8 +914,12 @@ static int smsc75xx_set_rx_max_frame_length(struct usbnet *dev, int size)
 static int smsc75xx_change_mtu(struct net_device *netdev, int new_mtu)
 {
        struct usbnet *dev = netdev_priv(netdev);
+       int ret;
+
+       if (new_mtu > MAX_SINGLE_PACKET_SIZE)
+               return -EINVAL;
 
-       int ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu);
+       ret = smsc75xx_set_rx_max_frame_length(dev, new_mtu + ETH_HLEN);
        if (ret < 0) {
                netdev_warn(dev->net, "Failed to set mac rx frame length\n");
                return ret;
@@ -1324,7 +1328,7 @@ static int smsc75xx_reset(struct usbnet *dev)
 
        netif_dbg(dev, ifup, dev->net, "FCT_TX_CTL set to 0x%08x\n", buf);
 
-       ret = smsc75xx_set_rx_max_frame_length(dev, 1514);
+       ret = smsc75xx_set_rx_max_frame_length(dev, dev->net->mtu + ETH_HLEN);
        if (ret < 0) {
                netdev_warn(dev->net, "Failed to set max rx frame length\n");
                return ret;
@@ -2134,8 +2138,8 @@ static int smsc75xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
                        else if (rx_cmd_a & (RX_CMD_A_LONG | RX_CMD_A_RUNT))
                                dev->net->stats.rx_frame_errors++;
                } else {
-                       /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */
-                       if (unlikely(size > (ETH_FRAME_LEN + 12))) {
+                       /* MAX_SINGLE_PACKET_SIZE + 4(CRC) + 2(COE) + 4(Vlan) */
+                       if (unlikely(size > (MAX_SINGLE_PACKET_SIZE + ETH_HLEN + 12))) {
                                netif_dbg(dev, rx_err, dev->net,
                                          "size err rx_cmd_a=0x%08x\n",
                                          rx_cmd_a);
index 4aad350e4daec8e5c252052153688b19ae51996d..eae7a03d4f9bb7a5b69414d9c161bb7b0f777b77 100644 (file)
@@ -2958,6 +2958,7 @@ vmxnet3_probe_device(struct pci_dev *pdev,
 
        adapter->num_rx_queues = num_rx_queues;
        adapter->num_tx_queues = num_tx_queues;
+       adapter->rx_buf_per_pkt = 1;
 
        size = sizeof(struct Vmxnet3_TxQueueDesc) * adapter->num_tx_queues;
        size += sizeof(struct Vmxnet3_RxQueueDesc) * adapter->num_rx_queues;
index a0feb17a023844fac5840e8c92998f46d119464e..63a124340cbecb19f3ad0d5f9b43f6fcfed6b4e0 100644 (file)
@@ -472,6 +472,12 @@ vmxnet3_set_ringparam(struct net_device *netdev,
                                                VMXNET3_RX_RING_MAX_SIZE)
                return -EINVAL;
 
+       /* if adapter not yet initialized, do nothing */
+       if (adapter->rx_buf_per_pkt == 0) {
+               netdev_err(netdev, "adapter not completely initialized, "
+                          "ring size cannot be changed yet\n");
+               return -EOPNOTSUPP;
+       }
 
        /* round it up to a multiple of VMXNET3_RING_SIZE_ALIGN */
        new_tx_ring_size = (param->tx_pending + VMXNET3_RING_SIZE_MASK) &
index 3198384689d9fbcb5119c029706844b7d8bc86bc..35418146fa170100ec1f8aef59c123e6a5b908df 100644 (file)
 /*
  * Version numbers
  */
-#define VMXNET3_DRIVER_VERSION_STRING   "1.1.29.0-k"
+#define VMXNET3_DRIVER_VERSION_STRING   "1.1.30.0-k"
 
 /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */
-#define VMXNET3_DRIVER_VERSION_NUM      0x01011D00
+#define VMXNET3_DRIVER_VERSION_NUM      0x01011E00
 
 #if defined(CONFIG_PCI_MSI)
        /* RSS only makes sense if MSI-X is supported. */
index f10e58ac9c1b6078527ecbc88b2c59fe54d4ea66..7cee7a3068ec11ae9a7f91efa612748dfdd0463e 100644 (file)
@@ -961,6 +961,8 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
        iph->ttl        = ttl ? : ip4_dst_hoplimit(&rt->dst);
        tunnel_ip_select_ident(skb, old_iph, &rt->dst);
 
+       nf_reset(skb);
+
        vxlan_set_owner(dev, skb);
 
        /* See iptunnel_xmit() */
@@ -1504,6 +1506,14 @@ static __net_init int vxlan_init_net(struct net *net)
 static __net_exit void vxlan_exit_net(struct net *net)
 {
        struct vxlan_net *vn = net_generic(net, vxlan_net_id);
+       struct vxlan_dev *vxlan;
+       unsigned h;
+
+       rtnl_lock();
+       for (h = 0; h < VNI_HASH_SIZE; ++h)
+               hlist_for_each_entry(vxlan, &vn->vni_list[h], hlist)
+                       dev_close(vxlan->dev);
+       rtnl_unlock();
 
        if (vn->sock) {
                sk_release_kernel(vn->sock->sk);
index 4cc13940c8950d2a7ad2a3fdf1a092ac3736a7d5..f76c3ca07a4501603883bbcbe9feb901d4eca390 100644 (file)
@@ -1023,6 +1023,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
                                          AR_PHY_AGC_CONTROL_FLTR_CAL   |
                                          AR_PHY_AGC_CONTROL_PKDET_CAL;
 
+       /* Use chip chainmask only for calibration */
        ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
 
        if (rtt) {
@@ -1150,6 +1151,9 @@ skip_tx_iqcal:
                ar9003_hw_rtt_disable(ah);
        }
 
+       /* Revert chainmask to runtime parameters */
+       ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+
        /* Initialize list pointers */
        ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
 
index ade3afb21f911e86589e325c2e99b49b7fe91289..7fdac6c7b3ea5dc030136d66c4574c4d8373a82e 100644 (file)
@@ -28,21 +28,21 @@ void ath_tx_complete_poll_work(struct work_struct *work)
        int i;
        bool needreset = false;
 
-       for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
-               if (ATH_TXQ_SETUP(sc, i)) {
-                       txq = &sc->tx.txq[i];
-                       ath_txq_lock(sc, txq);
-                       if (txq->axq_depth) {
-                               if (txq->axq_tx_inprogress) {
-                                       needreset = true;
-                                       ath_txq_unlock(sc, txq);
-                                       break;
-                               } else {
-                                       txq->axq_tx_inprogress = true;
-                               }
+       for (i = 0; i < IEEE80211_NUM_ACS; i++) {
+               txq = sc->tx.txq_map[i];
+
+               ath_txq_lock(sc, txq);
+               if (txq->axq_depth) {
+                       if (txq->axq_tx_inprogress) {
+                               needreset = true;
+                               ath_txq_unlock(sc, txq);
+                               break;
+                       } else {
+                               txq->axq_tx_inprogress = true;
                        }
-                       ath_txq_unlock_complete(sc, txq);
                }
+               ath_txq_unlock_complete(sc, txq);
+       }
 
        if (needreset) {
                ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
@@ -170,7 +170,8 @@ void ath_rx_poll(unsigned long data)
 {
        struct ath_softc *sc = (struct ath_softc *)data;
 
-       ieee80211_queue_work(sc->hw, &sc->hw_check_work);
+       if (!test_bit(SC_OP_INVALID, &sc->sc_flags))
+               ieee80211_queue_work(sc->hw, &sc->hw_check_work);
 }
 
 /*
index 38bc5a7997ffd43b9a8c8f45a6329fe4ffdac5c1..122146943bf204693b540b124f6c947bec34833b 100644 (file)
@@ -1487,8 +1487,12 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
        const struct b43_dma_ops *ops;
        struct b43_dmaring *ring;
        struct b43_dmadesc_meta *meta;
+       static const struct b43_txstatus fake; /* filled with 0 */
+       const struct b43_txstatus *txstat;
        int slot, firstused;
        bool frame_succeed;
+       int skip;
+       static u8 err_out1, err_out2;
 
        ring = parse_cookie(dev, status->cookie, &slot);
        if (unlikely(!ring))
@@ -1501,13 +1505,36 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
        firstused = ring->current_slot - ring->used_slots + 1;
        if (firstused < 0)
                firstused = ring->nr_slots + firstused;
+
+       skip = 0;
        if (unlikely(slot != firstused)) {
                /* This possibly is a firmware bug and will result in
-                * malfunction, memory leaks and/or stall of DMA functionality. */
-               b43dbg(dev->wl, "Out of order TX status report on DMA ring %d. "
-                      "Expected %d, but got %d\n",
-                      ring->index, firstused, slot);
-               return;
+                * malfunction, memory leaks and/or stall of DMA functionality.
+                */
+               if (slot == next_slot(ring, next_slot(ring, firstused))) {
+                       /* If a single header/data pair was missed, skip over
+                        * the first two slots in an attempt to recover.
+                        */
+                       slot = firstused;
+                       skip = 2;
+                       if (!err_out1) {
+                               /* Report the error once. */
+                               b43dbg(dev->wl,
+                                      "Skip on DMA ring %d slot %d.\n",
+                                      ring->index, slot);
+                               err_out1 = 1;
+                       }
+               } else {
+                       /* More than a single header/data pair were missed.
+                        * Report this error once.
+                        */
+                       if (!err_out2)
+                               b43dbg(dev->wl,
+                                      "Out of order TX status report on DMA ring %d. Expected %d, but got %d\n",
+                                      ring->index, firstused, slot);
+                       err_out2 = 1;
+                       return;
+               }
        }
 
        ops = ring->ops;
@@ -1522,11 +1549,13 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
                               slot, firstused, ring->index);
                        break;
                }
+
                if (meta->skb) {
                        struct b43_private_tx_info *priv_info =
-                               b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
+                            b43_get_priv_tx_info(IEEE80211_SKB_CB(meta->skb));
 
-                       unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1);
+                       unmap_descbuffer(ring, meta->dmaaddr,
+                                        meta->skb->len, 1);
                        kfree(priv_info->bouncebuffer);
                        priv_info->bouncebuffer = NULL;
                } else {
@@ -1538,8 +1567,9 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
                        struct ieee80211_tx_info *info;
 
                        if (unlikely(!meta->skb)) {
-                               /* This is a scatter-gather fragment of a frame, so
-                                * the skb pointer must not be NULL. */
+                               /* This is a scatter-gather fragment of a frame,
+                                * so the skb pointer must not be NULL.
+                                */
                                b43dbg(dev->wl, "TX status unexpected NULL skb "
                                       "at slot %d (first=%d) on ring %d\n",
                                       slot, firstused, ring->index);
@@ -1550,9 +1580,18 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
 
                        /*
                         * Call back to inform the ieee80211 subsystem about
-                        * the status of the transmission.
+                        * the status of the transmission. When skipping over
+                        * a missed TX status report, use a status structure
+                        * filled with zeros to indicate that the frame was not
+                        * sent (frame_count 0) and not acknowledged
                         */
-                       frame_succeed = b43_fill_txstatus_report(dev, info, status);
+                       if (unlikely(skip))
+                               txstat = &fake;
+                       else
+                               txstat = status;
+
+                       frame_succeed = b43_fill_txstatus_report(dev, info,
+                                                                txstat);
 #ifdef CONFIG_B43_DEBUG
                        if (frame_succeed)
                                ring->nr_succeed_tx_packets++;
@@ -1580,12 +1619,14 @@ void b43_dma_handle_txstatus(struct b43_wldev *dev,
                /* Everything unmapped and free'd. So it's not used anymore. */
                ring->used_slots--;
 
-               if (meta->is_last_fragment) {
+               if (meta->is_last_fragment && !skip) {
                        /* This is the last scatter-gather
                         * fragment of the frame. We are done. */
                        break;
                }
                slot = next_slot(ring, slot);
+               if (skip > 0)
+                       --skip;
        }
        if (ring->stopped) {
                B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME);
index 3c35382ee6c23ebfbaed8d1dcfdf33e804faec96..e8486c1e091af2f2db2a23827dc612315398751b 100644 (file)
@@ -1564,7 +1564,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
        u16 clip_off[2] = { 0xFFFF, 0xFFFF };
 
        u8 vcm_final = 0;
-       s8 offset[4];
+       s32 offset[4];
        s32 results[8][4] = { };
        s32 results_min[4] = { };
        s32 poll_results[4] = { };
@@ -1615,7 +1615,7 @@ static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
                }
                for (i = 0; i < 4; i += 2) {
                        s32 curr;
-                       s32 mind = 40;
+                       s32 mind = 0x100000;
                        s32 minpoll = 249;
                        u8 minvcm = 0;
                        if (2 * core != i)
@@ -1732,7 +1732,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
        u8 regs_save_radio[2];
        u16 regs_save_phy[2];
 
-       s8 offset[4];
+       s32 offset[4];
        u8 core;
        u8 rail;
 
@@ -1799,7 +1799,7 @@ static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
        }
 
        for (i = 0; i < 4; i++) {
-               s32 mind = 40;
+               s32 mind = 0x100000;
                u8 minvcm = 0;
                s32 minpoll = 249;
                s32 curr;
index 21a824232478f2ac02d593495ac5fe82ff94df77..18d37645e2cde25f2d291a94bd51a3e3675db5be 100644 (file)
@@ -1137,9 +1137,8 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
        gain0_15 = ((biq1 & 0xf) << 12) |
                   ((tia & 0xf) << 8) |
                   ((lna2 & 0x3) << 6) |
-                  ((lna2 & 0x3) << 4) |
-                  ((lna1 & 0x3) << 2) |
-                  ((lna1 & 0x3) << 0);
+                  ((lna2 &
+                    0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
 
        mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
        mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
@@ -1157,8 +1156,6 @@ wlc_lcnphy_set_rx_gain_by_distribution(struct brcms_phy *pi,
        }
 
        mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
-       mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
-       mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
 
 }
 
@@ -1331,43 +1328,6 @@ static u32 wlc_lcnphy_measure_digital_power(struct brcms_phy *pi, u16 nsamples)
        return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
 }
 
-static bool wlc_lcnphy_rx_iq_cal_gain(struct brcms_phy *pi, u16 biq1_gain,
-                                     u16 tia_gain, u16 lna2_gain)
-{
-       u32 i_thresh_l, q_thresh_l;
-       u32 i_thresh_h, q_thresh_h;
-       struct lcnphy_iq_est iq_est_h, iq_est_l;
-
-       wlc_lcnphy_set_rx_gain_by_distribution(pi, 0, 0, 0, biq1_gain, tia_gain,
-                                              lna2_gain, 0);
-
-       wlc_lcnphy_rx_gain_override_enable(pi, true);
-       wlc_lcnphy_start_tx_tone(pi, 2000, (40 >> 1), 0);
-       udelay(500);
-       write_radio_reg(pi, RADIO_2064_REG112, 0);
-       if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_l))
-               return false;
-
-       wlc_lcnphy_start_tx_tone(pi, 2000, 40, 0);
-       udelay(500);
-       write_radio_reg(pi, RADIO_2064_REG112, 0);
-       if (!wlc_lcnphy_rx_iq_est(pi, 1024, 32, &iq_est_h))
-               return false;
-
-       i_thresh_l = (iq_est_l.i_pwr << 1);
-       i_thresh_h = (iq_est_l.i_pwr << 2) + iq_est_l.i_pwr;
-
-       q_thresh_l = (iq_est_l.q_pwr << 1);
-       q_thresh_h = (iq_est_l.q_pwr << 2) + iq_est_l.q_pwr;
-       if ((iq_est_h.i_pwr > i_thresh_l) &&
-           (iq_est_h.i_pwr < i_thresh_h) &&
-           (iq_est_h.q_pwr > q_thresh_l) &&
-           (iq_est_h.q_pwr < q_thresh_h))
-               return true;
-
-       return false;
-}
-
 static bool
 wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
                     const struct lcnphy_rx_iqcomp *iqcomp,
@@ -1382,8 +1342,8 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
            RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
            rfoverride3_old, rfoverride3val_old, rfoverride4_old,
            rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
-       int tia_gain, lna2_gain, biq1_gain;
-       bool set_gain;
+       int tia_gain;
+       u32 received_power, rx_pwr_threshold;
        u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
        u16 values_to_save[11];
        s16 *ptr;
@@ -1408,134 +1368,126 @@ wlc_lcnphy_rx_iq_cal(struct brcms_phy *pi,
                goto cal_done;
        }
 
-       WARN_ON(module != 1);
-       tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
-       wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
-
-       for (i = 0; i < 11; i++)
-               values_to_save[i] =
-                       read_radio_reg(pi, rxiq_cal_rf_reg[i]);
-       Core1TxControl_old = read_phy_reg(pi, 0x631);
-
-       or_phy_reg(pi, 0x631, 0x0015);
-
-       RFOverride0_old = read_phy_reg(pi, 0x44c);
-       RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
-       rfoverride2_old = read_phy_reg(pi, 0x4b0);
-       rfoverride2val_old = read_phy_reg(pi, 0x4b1);
-       rfoverride3_old = read_phy_reg(pi, 0x4f9);
-       rfoverride3val_old = read_phy_reg(pi, 0x4fa);
-       rfoverride4_old = read_phy_reg(pi, 0x938);
-       rfoverride4val_old = read_phy_reg(pi, 0x939);
-       afectrlovr_old = read_phy_reg(pi, 0x43b);
-       afectrlovrval_old = read_phy_reg(pi, 0x43c);
-       old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
-       old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
-
-       tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
-       if (tx_gain_override_old) {
-               wlc_lcnphy_get_tx_gain(pi, &old_gains);
-               tx_gain_index_old = pi_lcn->lcnphy_current_index;
-       }
-
-       wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
+       if (module == 1) {
 
-       mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
-       mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+               tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+               wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
 
-       mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
-       mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+               for (i = 0; i < 11; i++)
+                       values_to_save[i] =
+                               read_radio_reg(pi, rxiq_cal_rf_reg[i]);
+               Core1TxControl_old = read_phy_reg(pi, 0x631);
+
+               or_phy_reg(pi, 0x631, 0x0015);
+
+               RFOverride0_old = read_phy_reg(pi, 0x44c);
+               RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
+               rfoverride2_old = read_phy_reg(pi, 0x4b0);
+               rfoverride2val_old = read_phy_reg(pi, 0x4b1);
+               rfoverride3_old = read_phy_reg(pi, 0x4f9);
+               rfoverride3val_old = read_phy_reg(pi, 0x4fa);
+               rfoverride4_old = read_phy_reg(pi, 0x938);
+               rfoverride4val_old = read_phy_reg(pi, 0x939);
+               afectrlovr_old = read_phy_reg(pi, 0x43b);
+               afectrlovrval_old = read_phy_reg(pi, 0x43c);
+               old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+               old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
+
+               tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+               if (tx_gain_override_old) {
+                       wlc_lcnphy_get_tx_gain(pi, &old_gains);
+                       tx_gain_index_old = pi_lcn->lcnphy_current_index;
+               }
 
-       write_radio_reg(pi, RADIO_2064_REG116, 0x06);
-       write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
-       write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
-       write_radio_reg(pi, RADIO_2064_REG098, 0x03);
-       write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
-       mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
-       write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
-       write_radio_reg(pi, RADIO_2064_REG114, 0x01);
-       write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
-       write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
-
-       mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
-       mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
-       mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
-       mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
-       mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
-       mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
-       mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
-       mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
-       mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
-       mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
+               wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
 
-       mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
-       mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+               mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+               mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
 
-       write_phy_reg(pi, 0x6da, 0xffff);
-       or_phy_reg(pi, 0x6db, 0x3);
+               mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+               mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
 
-       wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
-       set_gain = false;
-
-       lna2_gain = 3;
-       while ((lna2_gain >= 0) && !set_gain) {
-               tia_gain = 4;
-
-               while ((tia_gain >= 0) && !set_gain) {
-                       biq1_gain = 6;
-
-                       while ((biq1_gain >= 0) && !set_gain) {
-                               set_gain = wlc_lcnphy_rx_iq_cal_gain(pi,
-                                                                    (u16)
-                                                                    biq1_gain,
-                                                                    (u16)
-                                                                    tia_gain,
-                                                                    (u16)
-                                                                    lna2_gain);
-                               biq1_gain -= 1;
-                       }
+               write_radio_reg(pi, RADIO_2064_REG116, 0x06);
+               write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
+               write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
+               write_radio_reg(pi, RADIO_2064_REG098, 0x03);
+               write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+               mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
+               write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
+               write_radio_reg(pi, RADIO_2064_REG114, 0x01);
+               write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
+               write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
+
+               mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
+               mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
+               mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
+               mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
+               mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
+               mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
+               mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
+               mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
+               mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
+               mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
+
+               mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+               mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+               wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
+               write_phy_reg(pi, 0x6da, 0xffff);
+               or_phy_reg(pi, 0x6db, 0x3);
+               wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
+               wlc_lcnphy_rx_gain_override_enable(pi, true);
+
+               tia_gain = 8;
+               rx_pwr_threshold = 950;
+               while (tia_gain > 0) {
                        tia_gain -= 1;
+                       wlc_lcnphy_set_rx_gain_by_distribution(pi,
+                                                              0, 0, 2, 2,
+                                                              (u16)
+                                                              tia_gain, 1, 0);
+                       udelay(500);
+
+                       received_power =
+                               wlc_lcnphy_measure_digital_power(pi, 2000);
+                       if (received_power < rx_pwr_threshold)
+                               break;
                }
-               lna2_gain -= 1;
-       }
+               result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
 
-       if (set_gain)
-               result = wlc_lcnphy_calc_rx_iq_comp(pi, 1024);
-       else
-               result = false;
+               wlc_lcnphy_stop_tx_tone(pi);
 
-       wlc_lcnphy_stop_tx_tone(pi);
+               write_phy_reg(pi, 0x631, Core1TxControl_old);
 
-       write_phy_reg(pi, 0x631, Core1TxControl_old);
-
-       write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
-       write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
-       write_phy_reg(pi, 0x4b0, rfoverride2_old);
-       write_phy_reg(pi, 0x4b1, rfoverride2val_old);
-       write_phy_reg(pi, 0x4f9, rfoverride3_old);
-       write_phy_reg(pi, 0x4fa, rfoverride3val_old);
-       write_phy_reg(pi, 0x938, rfoverride4_old);
-       write_phy_reg(pi, 0x939, rfoverride4val_old);
-       write_phy_reg(pi, 0x43b, afectrlovr_old);
-       write_phy_reg(pi, 0x43c, afectrlovrval_old);
-       write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
-       write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
+               write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
+               write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
+               write_phy_reg(pi, 0x4b0, rfoverride2_old);
+               write_phy_reg(pi, 0x4b1, rfoverride2val_old);
+               write_phy_reg(pi, 0x4f9, rfoverride3_old);
+               write_phy_reg(pi, 0x4fa, rfoverride3val_old);
+               write_phy_reg(pi, 0x938, rfoverride4_old);
+               write_phy_reg(pi, 0x939, rfoverride4val_old);
+               write_phy_reg(pi, 0x43b, afectrlovr_old);
+               write_phy_reg(pi, 0x43c, afectrlovrval_old);
+               write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+               write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
 
-       wlc_lcnphy_clear_trsw_override(pi);
+               wlc_lcnphy_clear_trsw_override(pi);
 
-       mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
+               mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
 
-       for (i = 0; i < 11; i++)
-               write_radio_reg(pi, rxiq_cal_rf_reg[i],
-                               values_to_save[i]);
+               for (i = 0; i < 11; i++)
+                       write_radio_reg(pi, rxiq_cal_rf_reg[i],
+                                       values_to_save[i]);
 
-       if (tx_gain_override_old)
-               wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
-       else
-               wlc_lcnphy_disable_tx_gain_override(pi);
+               if (tx_gain_override_old)
+                       wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
+               else
+                       wlc_lcnphy_disable_tx_gain_override(pi);
 
-       wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
-       wlc_lcnphy_rx_gain_override_enable(pi, false);
+               wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
+               wlc_lcnphy_rx_gain_override_enable(pi, false);
+       }
 
 cal_done:
        kfree(ptr);
@@ -1829,17 +1781,6 @@ wlc_lcnphy_radio_2064_channel_tune_4313(struct brcms_phy *pi, u8 channel)
                write_radio_reg(pi, RADIO_2064_REG038, 3);
                write_radio_reg(pi, RADIO_2064_REG091, 7);
        }
-
-       if (!(pi->sh->boardflags & BFL_FEM)) {
-               u8 reg038[14] = {0xd, 0xe, 0xd, 0xd, 0xd, 0xc,
-                       0xa, 0xb, 0xb, 0x3, 0x3, 0x2, 0x0, 0x0};
-
-               write_radio_reg(pi, RADIO_2064_REG02A, 0xf);
-               write_radio_reg(pi, RADIO_2064_REG091, 0x3);
-               write_radio_reg(pi, RADIO_2064_REG038, 0x3);
-
-               write_radio_reg(pi, RADIO_2064_REG038, reg038[channel - 1]);
-       }
 }
 
 static int
@@ -2034,16 +1975,6 @@ wlc_lcnphy_set_tssi_mux(struct brcms_phy *pi, enum lcnphy_tssi_mode pos)
                } else {
                        mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
                        mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
-                       mod_radio_reg(pi, RADIO_2064_REG028, 0x1, 0x0);
-                       mod_radio_reg(pi, RADIO_2064_REG11A, 0x4, 1<<2);
-                       mod_radio_reg(pi, RADIO_2064_REG036, 0x10, 0x0);
-                       mod_radio_reg(pi, RADIO_2064_REG11A, 0x10, 1<<4);
-                       mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
-                       mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x77);
-                       mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0xe<<1);
-                       mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1<<7);
-                       mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 1<<1);
-                       mod_radio_reg(pi, RADIO_2064_REG029, 0xf0, 0<<4);
                }
        } else {
                mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
@@ -2130,14 +2061,12 @@ static void wlc_lcnphy_pwrctrl_rssiparams(struct brcms_phy *pi)
                    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
 
        mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
-       mod_radio_reg(pi, RADIO_2064_REG07C, (1 << 0), (1 << 0));
 }
 
 static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 {
        struct phytbl_info tab;
        u32 rfseq, ind;
-       u8 tssi_sel;
 
        tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
        tab.tbl_width = 32;
@@ -2159,13 +2088,7 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 
        mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
 
-       if (pi->sh->boardflags & BFL_FEM) {
-               tssi_sel = 0x1;
-               wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
-       } else {
-               tssi_sel = 0xe;
-               wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_POST_PA);
-       }
+       wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
        mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
 
        mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
@@ -2201,10 +2124,9 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
        mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
 
        if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
-               mod_radio_reg(pi, RADIO_2064_REG028, 0xf, tssi_sel);
+               mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
                mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
        } else {
-               mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, tssi_sel << 1);
                mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
                mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
        }
@@ -2251,10 +2173,6 @@ static void wlc_lcnphy_tssi_setup(struct brcms_phy *pi)
 
        mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
 
-       mod_radio_reg(pi, RADIO_2064_REG035, 0xff, 0x0);
-       mod_radio_reg(pi, RADIO_2064_REG036, 0x3, 0x0);
-       mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
-
        wlc_lcnphy_pwrctrl_rssiparams(pi);
 }
 
@@ -2873,8 +2791,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
                read_radio_reg(pi, RADIO_2064_REG007) & 1;
        u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
        u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
-       u8 SAVE_bbmult = wlc_lcnphy_get_bbmult(pi);
-
        idleTssi = read_phy_reg(pi, 0x4ab);
        suspend = (0 == (bcma_read32(pi->d11core, D11REGOFFS(maccontrol)) &
                         MCTL_EN_MAC));
@@ -2892,12 +2808,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
        mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
        mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
        wlc_lcnphy_tssi_setup(pi);
-
-       mod_phy_reg(pi, 0x4d7, (0x1 << 0), (1 << 0));
-       mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1 << 6));
-
-       wlc_lcnphy_set_bbmult(pi, 0x0);
-
        wlc_phy_do_dummy_tx(pi, true, OFF);
        idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
                    >> 0);
@@ -2919,7 +2829,6 @@ static void wlc_lcnphy_idle_tssi_est(struct brcms_phy_pub *ppi)
 
        mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
 
-       wlc_lcnphy_set_bbmult(pi, SAVE_bbmult);
        wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
        wlc_lcnphy_set_tx_gain(pi, &old_gains);
        wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
@@ -3133,11 +3042,6 @@ static void wlc_lcnphy_tx_pwr_ctrl_init(struct brcms_phy_pub *ppi)
                        wlc_lcnphy_write_table(pi, &tab);
                        tab.tbl_offset++;
                }
-               mod_phy_reg(pi, 0x4d0, (0x1 << 0), (0) << 0);
-               mod_phy_reg(pi, 0x4d3, (0xff << 0), (0) << 0);
-               mod_phy_reg(pi, 0x4d3, (0xff << 8), (0) << 8);
-               mod_phy_reg(pi, 0x4d0, (0x1 << 4), (0) << 4);
-               mod_phy_reg(pi, 0x4d0, (0x1 << 2), (0) << 2);
 
                mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
 
@@ -3939,6 +3843,7 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
        target_gains.pad_gain = 21;
        target_gains.dac_gain = 0;
        wlc_lcnphy_set_tx_gain(pi, &target_gains);
+       wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
 
        if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
 
@@ -3949,7 +3854,6 @@ static void wlc_lcnphy_txpwrtbl_iqlo_cal(struct brcms_phy *pi)
                                        lcnphy_recal ? LCNPHY_CAL_RECAL :
                                        LCNPHY_CAL_FULL), false);
        } else {
-               wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
                wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
        }
 
@@ -4374,22 +4278,17 @@ wlc_lcnphy_load_tx_gain_table(struct brcms_phy *pi,
        if (CHSPEC_IS5G(pi->radio_chanspec))
                pa_gain = 0x70;
        else
-               pa_gain = 0x60;
+               pa_gain = 0x70;
 
        if (pi->sh->boardflags & BFL_FEM)
                pa_gain = 0x10;
-
        tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
        tab.tbl_width = 32;
        tab.tbl_len = 1;
        tab.tbl_ptr = &val;
 
        for (j = 0; j < 128; j++) {
-               if (pi->sh->boardflags & BFL_FEM)
-                       gm_gain = gain_table[j].gm;
-               else
-                       gm_gain = 15;
-
+               gm_gain = gain_table[j].gm;
                val = (((u32) pa_gain << 24) |
                       (gain_table[j].pad << 16) |
                       (gain_table[j].pga << 8) | gm_gain);
@@ -4600,10 +4499,7 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
 
        write_phy_reg(pi, 0x4ea, 0x4688);
 
-       if (pi->sh->boardflags & BFL_FEM)
-               mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
-       else
-               mod_phy_reg(pi, 0x4eb, (0x7 << 0), 3 << 0);
+       mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
 
        mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
 
@@ -4614,13 +4510,6 @@ static void wlc_radio_2064_init(struct brcms_phy *pi)
        wlc_lcnphy_rcal(pi);
 
        wlc_lcnphy_rc_cal(pi);
-
-       if (!(pi->sh->boardflags & BFL_FEM)) {
-               write_radio_reg(pi, RADIO_2064_REG032, 0x6f);
-               write_radio_reg(pi, RADIO_2064_REG033, 0x19);
-               write_radio_reg(pi, RADIO_2064_REG039, 0xe);
-       }
-
 }
 
 static void wlc_lcnphy_radio_init(struct brcms_phy *pi)
@@ -4650,20 +4539,22 @@ static void wlc_lcnphy_tbl_init(struct brcms_phy *pi)
                wlc_lcnphy_write_table(pi, &tab);
        }
 
-       if (!(pi->sh->boardflags & BFL_FEM)) {
-               tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
-               tab.tbl_width = 16;
-               tab.tbl_ptr = &val;
-               tab.tbl_len = 1;
+       tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+       tab.tbl_width = 16;
+       tab.tbl_ptr = &val;
+       tab.tbl_len = 1;
 
-               val = 150;
-               tab.tbl_offset = 0;
-               wlc_lcnphy_write_table(pi, &tab);
+       val = 114;
+       tab.tbl_offset = 0;
+       wlc_lcnphy_write_table(pi, &tab);
 
-               val = 220;
-               tab.tbl_offset = 1;
-               wlc_lcnphy_write_table(pi, &tab);
-       }
+       val = 130;
+       tab.tbl_offset = 1;
+       wlc_lcnphy_write_table(pi, &tab);
+
+       val = 6;
+       tab.tbl_offset = 8;
+       wlc_lcnphy_write_table(pi, &tab);
 
        if (CHSPEC_IS2G(pi->radio_chanspec)) {
                if (pi->sh->boardflags & BFL_FEM)
@@ -5055,7 +4946,6 @@ void wlc_phy_chanspec_set_lcnphy(struct brcms_phy *pi, u16 chanspec)
                wlc_lcnphy_load_tx_iir_filter(pi, true, 3);
 
        mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
-       wlc_lcnphy_tssi_setup(pi);
 }
 
 void wlc_phy_detach_lcnphy(struct brcms_phy *pi)
@@ -5094,7 +4984,8 @@ bool wlc_phy_attach_lcnphy(struct brcms_phy *pi)
        if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
                return false;
 
-       if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+       if ((pi->sh->boardflags & BFL_FEM) &&
+           (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
                if (pi_lcn->lcnphy_tempsense_option == 3) {
                        pi->hwpwrctrl = true;
                        pi->hwpwrctrl_capable = true;
index b7e95acc2084033dd5c27de24b80bebd78f8dfbe..622c01ca72c5d24e8bfc55c3b84ad61633c4bb92 100644 (file)
@@ -1992,70 +1992,70 @@ static const u16 dot11lcn_sw_ctrl_tbl_4313_epa_rev0[] = {
 };
 
 static const u16 dot11lcn_sw_ctrl_tbl_4313_rev0[] = {
-       0x0009,
        0x000a,
-       0x0005,
-       0x0006,
        0x0009,
-       0x000a,
-       0x0005,
        0x0006,
-       0x0009,
-       0x000a,
        0x0005,
-       0x0006,
-       0x0009,
        0x000a,
-       0x0005,
-       0x0006,
        0x0009,
-       0x000a,
-       0x0005,
        0x0006,
-       0x0009,
-       0x000a,
        0x0005,
-       0x0006,
-       0x0009,
        0x000a,
-       0x0005,
-       0x0006,
        0x0009,
-       0x000a,
-       0x0005,
        0x0006,
-       0x0009,
-       0x000a,
        0x0005,
-       0x0006,
-       0x0009,
        0x000a,
-       0x0005,
-       0x0006,
        0x0009,
-       0x000a,
-       0x0005,
        0x0006,
-       0x0009,
-       0x000a,
        0x0005,
-       0x0006,
+       0x000a,
        0x0009,
+       0x0006,
+       0x0005,
        0x000a,
+       0x0009,
+       0x0006,
        0x0005,
+       0x000a,
+       0x0009,
        0x0006,
+       0x0005,
+       0x000a,
        0x0009,
+       0x0006,
+       0x0005,
        0x000a,
+       0x0009,
+       0x0006,
        0x0005,
+       0x000a,
+       0x0009,
        0x0006,
+       0x0005,
+       0x000a,
        0x0009,
+       0x0006,
+       0x0005,
        0x000a,
+       0x0009,
+       0x0006,
        0x0005,
+       0x000a,
+       0x0009,
        0x0006,
+       0x0005,
+       0x000a,
        0x0009,
+       0x0006,
+       0x0005,
        0x000a,
+       0x0009,
+       0x0006,
        0x0005,
+       0x000a,
+       0x0009,
        0x0006,
+       0x0005,
 };
 
 static const u16 dot11lcn_sw_ctrl_tbl_rev0[] = {
index 3630a41df50d7c64815abae048696ea04329a703..c353b5f19c8c639480be47121f06c166dfc9f71c 100644 (file)
@@ -475,6 +475,7 @@ il3945_tx_skb(struct il_priv *il,
        dma_addr_t txcmd_phys;
        int txq_id = skb_get_queue_mapping(skb);
        u16 len, idx, hdr_len;
+       u16 firstlen, secondlen;
        u8 id;
        u8 unicast;
        u8 sta_id;
@@ -589,21 +590,22 @@ il3945_tx_skb(struct il_priv *il,
        len =
            sizeof(struct il3945_tx_cmd) + sizeof(struct il_cmd_header) +
            hdr_len;
-       len = (len + 3) & ~3;
+       firstlen = (len + 3) & ~3;
 
        /* Physical address of this Tx command's header (not MAC header!),
         * within command buffer array. */
        txcmd_phys =
-           pci_map_single(il->pci_dev, &out_cmd->hdr, len, PCI_DMA_TODEVICE);
+           pci_map_single(il->pci_dev, &out_cmd->hdr, firstlen,
+                          PCI_DMA_TODEVICE);
        if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys)))
                goto drop_unlock;
 
        /* Set up TFD's 2nd entry to point directly to remainder of skb,
         * if any (802.11 null frames have no payload). */
-       len = skb->len - hdr_len;
-       if (len) {
+       secondlen = skb->len - hdr_len;
+       if (secondlen > 0) {
                phys_addr =
-                   pci_map_single(il->pci_dev, skb->data + hdr_len, len,
+                   pci_map_single(il->pci_dev, skb->data + hdr_len, secondlen,
                                   PCI_DMA_TODEVICE);
                if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr)))
                        goto drop_unlock;
@@ -611,12 +613,12 @@ il3945_tx_skb(struct il_priv *il,
 
        /* Add buffer containing Tx command and MAC(!) header to TFD's
         * first entry */
-       il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0);
+       il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0);
        dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
-       dma_unmap_len_set(out_meta, len, len);
-       if (len)
-               il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, len, 0,
-                                              U32_PAD(len));
+       dma_unmap_len_set(out_meta, len, firstlen);
+       if (secondlen > 0)
+               il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, secondlen, 0,
+                                              U32_PAD(secondlen));
 
        if (!ieee80211_has_morefrags(hdr->frame_control)) {
                txq->need_update = 1;
index e8324b5e5bfe836610f5680f86cf9c742fc4061b..6c7493c2d698e6a2c83de679131890726aff6456 100644 (file)
@@ -2152,7 +2152,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf,
        int rate_idx;
        int i;
        u32 rate;
-       u8 use_green = il4965_rs_use_green(il, sta);
+       u8 use_green;
        u8 active_tbl = 0;
        u8 valid_tx_ant;
        struct il_station_priv *sta_priv;
@@ -2160,6 +2160,7 @@ il4965_rs_initialize_lq(struct il_priv *il, struct ieee80211_conf *conf,
        if (!sta || !lq_sta)
                return;
 
+       use_green = il4965_rs_use_green(il, sta);
        sta_priv = (void *)sta->drv_priv;
 
        i = lq_sta->last_txrate_idx;
index 86ea5f4c39398077efa5e13c4a16a7dcf769bf05..44ca0e57f9f76fd8b3b58c183a630fdb057f78ad 100644 (file)
@@ -1261,6 +1261,15 @@ int iwl_dvm_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
                return -EIO;
        }
 
+       /*
+        * This can happen upon FW ASSERT: we clear the STATUS_FW_ERROR flag
+        * in iwl_down but cancel the workers only later.
+        */
+       if (!priv->ucode_loaded) {
+               IWL_ERR(priv, "Fw not loaded - dropping CMD: %x\n", cmd->id);
+               return -EIO;
+       }
+
        /*
         * Synchronous commands from this op-mode must hold
         * the mutex, this ensures we don't try to send two
index 23be948cf16220828e1b3bcbceeb5aff31ced74b..a82b6b39d4ff6df26375334963aa3d42114f7c32 100644 (file)
@@ -1419,6 +1419,14 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
 
        mutex_lock(&priv->mutex);
 
+       if (changes & BSS_CHANGED_IDLE && bss_conf->idle) {
+               /*
+                * If we go idle, then clearly no "passive-no-rx"
+                * workaround is needed any more, this is a reset.
+                */
+               iwlagn_lift_passive_no_rx(priv);
+       }
+
        if (unlikely(!iwl_is_ready(priv))) {
                IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
                mutex_unlock(&priv->mutex);
@@ -1450,16 +1458,6 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
                        priv->timestamp = bss_conf->sync_tsf;
                        ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
                } else {
-                       /*
-                        * If we disassociate while there are pending
-                        * frames, just wake up the queues and let the
-                        * frames "escape" ... This shouldn't really
-                        * be happening to start with, but we should
-                        * not get stuck in this case either since it
-                        * can happen if userspace gets confused.
-                        */
-                       iwlagn_lift_passive_no_rx(priv);
-
                        ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 
                        if (ctx->ctxid == IWL_RXON_CTX_BSS)
index 94ef33838bc69b615f8f47140922bf0d13eb2453..b775769f8322c437558712af955332296e95db89 100644 (file)
@@ -151,7 +151,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
                       sta_id, sta->sta.addr, flags & CMD_ASYNC ?  "a" : "");
 
        if (!(flags & CMD_ASYNC)) {
-               cmd.flags |= CMD_WANT_SKB | CMD_WANT_HCMD;
+               cmd.flags |= CMD_WANT_SKB;
                might_sleep();
        }
 
index 6aec2df3bb27768fcfbcb5555384746a9e5026ec..d1a670d7b10cfd05f28c07624616f436ebf6c321 100644 (file)
@@ -1192,7 +1192,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
                        memset(&info->status, 0, sizeof(info->status));
 
                        if (status == TX_STATUS_FAIL_PASSIVE_NO_RX &&
-                           iwl_is_associated_ctx(ctx) && ctx->vif &&
+                           ctx->vif &&
                            ctx->vif->type == NL80211_IFTYPE_STATION) {
                                /* block and stop all queues */
                                priv->passive_no_rx = true;
index 736fe9bb140ebab643e065742469ef0a9f667e31..1a4ac9236a4446e2d8b30722cad23e826756a660 100644 (file)
@@ -367,6 +367,8 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
                return -EIO;
        }
 
+       priv->ucode_loaded = true;
+
        if (ucode_type != IWL_UCODE_WOWLAN) {
                /* delay a bit to give rfkill time to run */
                msleep(5);
@@ -380,8 +382,6 @@ int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
                return ret;
        }
 
-       priv->ucode_loaded = true;
-
        return 0;
 }
 
index 10f01793d7a605cf4dc7e4d6312ac4af8f4caa64..81aa91fab5aafcc1dc7fa597c85878d01ab83685 100644 (file)
@@ -363,7 +363,7 @@ TRACE_EVENT(iwlwifi_dev_hcmd,
                __entry->flags = cmd->flags;
                memcpy(__get_dynamic_array(hcmd), hdr, sizeof(*hdr));
 
-               for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+               for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
                        if (!cmd->len[i])
                                continue;
                        memcpy((u8 *)__get_dynamic_array(hcmd) + offset,
index 6f228bb2b84431e61cd8292d1563f81faa91efc6..fbfd2d1371176e247a22e5fca00ee5809088c306 100644 (file)
@@ -1102,7 +1102,6 @@ void iwl_drv_stop(struct iwl_drv *drv)
 
 /* shared module parameters */
 struct iwl_mod_params iwlwifi_mod_params = {
-       .amsdu_size_8K = 1,
        .restart_fw = 1,
        .plcp_check = true,
        .bt_coex_active = true,
@@ -1207,7 +1206,7 @@ MODULE_PARM_DESC(11n_disable,
        "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX");
 module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K,
                   int, S_IRUGO);
-MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
+MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)");
 module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, int, S_IRUGO);
 MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
 
index e5e3a79eae2fbd5e8f544db2cc9605522770dddb..2c2a729092f5e894013c39f1eccb0a739a5e56d4 100644 (file)
@@ -91,7 +91,7 @@ enum iwl_power_level {
  * @sw_crypto: using hardware encryption, default = 0
  * @disable_11n: disable 11n capabilities, default = 0,
  *     use IWL_DISABLE_HT_* constants
- * @amsdu_size_8K: enable 8K amsdu size, default = 1
+ * @amsdu_size_8K: enable 8K amsdu size, default = 0
  * @restart_fw: restart firmware, default = 1
  * @plcp_check: enable plcp health check, default = true
  * @wd_disable: enable stuck queue check, default = 0
index 8c7bec6b9a0be92d29136a47fc20f920a5ce7a6d..0cac2b7af78b99eb1e8c8951a9638c12033e382c 100644 (file)
@@ -186,19 +186,13 @@ struct iwl_rx_packet {
  * @CMD_ASYNC: Return right away and don't want for the response
  * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the
  *     response. The caller needs to call iwl_free_resp when done.
- * @CMD_WANT_HCMD: The caller needs to get the HCMD that was sent in the
- *     response handler. Chunks flagged by %IWL_HCMD_DFL_NOCOPY won't be
- *     copied. The pointer passed to the response handler is in the transport
- *     ownership and don't need to be freed by the op_mode. This also means
- *     that the pointer is invalidated after the op_mode's handler returns.
  * @CMD_ON_DEMAND: This command is sent by the test mode pipe.
  */
 enum CMD_MODE {
        CMD_SYNC                = 0,
        CMD_ASYNC               = BIT(0),
        CMD_WANT_SKB            = BIT(1),
-       CMD_WANT_HCMD           = BIT(2),
-       CMD_ON_DEMAND           = BIT(3),
+       CMD_ON_DEMAND           = BIT(2),
 };
 
 #define DEF_CMD_PAYLOAD_SIZE 320
@@ -217,7 +211,11 @@ struct iwl_device_cmd {
 
 #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
 
-#define IWL_MAX_CMD_TFDS       2
+/*
+ * number of transfer buffers (fragments) per transmit frame descriptor;
+ * this is just the driver's idea, the hardware supports 20
+ */
+#define IWL_MAX_CMD_TBS_PER_TFD        2
 
 /**
  * struct iwl_hcmd_dataflag - flag for each one of the chunks of the command
@@ -254,15 +252,15 @@ enum iwl_hcmd_dataflag {
  * @id: id of the host command
  */
 struct iwl_host_cmd {
-       const void *data[IWL_MAX_CMD_TFDS];
+       const void *data[IWL_MAX_CMD_TBS_PER_TFD];
        struct iwl_rx_packet *resp_pkt;
        unsigned long _rx_page_addr;
        u32 _rx_page_order;
        int handler_status;
 
        u32 flags;
-       u16 len[IWL_MAX_CMD_TFDS];
-       u8 dataflags[IWL_MAX_CMD_TFDS];
+       u16 len[IWL_MAX_CMD_TBS_PER_TFD];
+       u8 dataflags[IWL_MAX_CMD_TBS_PER_TFD];
        u8 id;
 };
 
index 23eebda848b05ae64f9ae8dfb6ce5647dded4b19..2adb61f103f4cd310ae654fdd83ff466a843dda5 100644 (file)
@@ -762,18 +762,20 @@ struct iwl_phy_context_cmd {
 #define IWL_RX_INFO_PHY_CNT 8
 #define IWL_RX_INFO_AGC_IDX 1
 #define IWL_RX_INFO_RSSI_AB_IDX 2
-#define IWL_RX_INFO_RSSI_C_IDX 3
-#define IWL_OFDM_AGC_DB_MSK 0xfe00
-#define IWL_OFDM_AGC_DB_POS 9
+#define IWL_OFDM_AGC_A_MSK 0x0000007f
+#define IWL_OFDM_AGC_A_POS 0
+#define IWL_OFDM_AGC_B_MSK 0x00003f80
+#define IWL_OFDM_AGC_B_POS 7
+#define IWL_OFDM_AGC_CODE_MSK 0x3fe00000
+#define IWL_OFDM_AGC_CODE_POS 20
 #define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff
-#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00
 #define IWL_OFDM_RSSI_A_POS 0
+#define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00
+#define IWL_OFDM_RSSI_ALLBAND_A_POS 8
 #define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000
-#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000
 #define IWL_OFDM_RSSI_B_POS 16
-#define IWL_OFDM_RSSI_INBAND_C_MSK 0x00ff
-#define IWL_OFDM_RSSI_ALLBAND_C_MSK 0xff00
-#define IWL_OFDM_RSSI_C_POS 0
+#define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000
+#define IWL_OFDM_RSSI_ALLBAND_B_POS 24
 
 /**
  * struct iwl_rx_phy_info - phy info
index d3d959db03a9727e7033a871fc4717654dc3ec10..500f818dba0412df8e5a76d018ddaec761529820 100644 (file)
 #define UCODE_VALID_OK cpu_to_le32(0x1)
 
 /* Default calibration values for WkP - set to INIT image w/o running */
-static const u8 wkp_calib_values_bb_filter[] = { 0xbf, 0x00, 0x5f, 0x00, 0x2f,
-                                                0x00, 0x18, 0x00 };
-static const u8 wkp_calib_values_rx_dc[] = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
-                                            0x7f, 0x7f, 0x7f };
-static const u8 wkp_calib_values_tx_lo[] = { 0x00, 0x00, 0x00, 0x00 };
-static const u8 wkp_calib_values_tx_iq[] = { 0xff, 0x00, 0xff, 0x00, 0x00,
-                                            0x00 };
-static const u8 wkp_calib_values_rx_iq[] = { 0xff, 0x00, 0x00, 0x00 };
 static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 };
 static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 };
-static const u8 wkp_calib_values_xtal[] = { 0xd2, 0xd2 };
 
 struct iwl_calib_default_data {
        u16 size;
@@ -99,12 +90,7 @@ struct iwl_calib_default_data {
 #define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf}
 
 static const struct iwl_calib_default_data wkp_calib_default_data[12] = {
-       [5] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_dc),
-       [6] = CALIB_SIZE_N_DATA(wkp_calib_values_bb_filter),
-       [7] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_lo),
-       [8] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq),
        [9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew),
-       [10] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq),
        [11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew),
 };
 
@@ -241,20 +227,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
 
        return 0;
 }
-#define IWL_HW_REV_ID_RAINBOW  0x2
-#define IWL_PROJ_TYPE_LHP      0x5
-
-static u32 iwl_mvm_build_phy_cfg(struct iwl_mvm *mvm)
-{
-       struct iwl_nvm_data *data = mvm->nvm_data;
-       /* Temp calls to static definitions, will be changed to CSR calls */
-       u8 hw_rev_id = IWL_HW_REV_ID_RAINBOW;
-       u8 project_type = IWL_PROJ_TYPE_LHP;
-
-       return data->radio_cfg_dash | (data->radio_cfg_step << 2) |
-               (hw_rev_id << 4) | ((project_type & 0x7f) << 6) |
-               (data->valid_tx_ant << 16) | (data->valid_rx_ant << 20);
-}
 
 static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
 {
@@ -262,7 +234,7 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
        enum iwl_ucode_type ucode_type = mvm->cur_ucode;
 
        /* Set parameters */
-       phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_build_phy_cfg(mvm));
+       phy_cfg_cmd.phy_cfg = cpu_to_le32(mvm->fw->phy_config);
        phy_cfg_cmd.calib_control.event_trigger =
                mvm->fw->default_calib[ucode_type].event_trigger;
        phy_cfg_cmd.calib_control.flow_trigger =
@@ -275,103 +247,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
                                    sizeof(phy_cfg_cmd), &phy_cfg_cmd);
 }
 
-/* Starting with the new PHY DB implementation - New calibs are enabled */
-/* Value - 0x405e7 */
-#define IWL_CALIB_DEFAULT_FLOW_INIT    (IWL_CALIB_CFG_XTAL_IDX         |\
-                                        IWL_CALIB_CFG_TEMPERATURE_IDX  |\
-                                        IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
-                                        IWL_CALIB_CFG_DC_IDX           |\
-                                        IWL_CALIB_CFG_BB_FILTER_IDX    |\
-                                        IWL_CALIB_CFG_LO_LEAKAGE_IDX   |\
-                                        IWL_CALIB_CFG_TX_IQ_IDX        |\
-                                        IWL_CALIB_CFG_RX_IQ_IDX        |\
-                                        IWL_CALIB_CFG_AGC_IDX)
-
-#define IWL_CALIB_DEFAULT_EVENT_INIT   0x0
-
-/* Value 0x41567 */
-#define IWL_CALIB_DEFAULT_FLOW_RUN     (IWL_CALIB_CFG_XTAL_IDX         |\
-                                        IWL_CALIB_CFG_TEMPERATURE_IDX  |\
-                                        IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
-                                        IWL_CALIB_CFG_BB_FILTER_IDX    |\
-                                        IWL_CALIB_CFG_DC_IDX           |\
-                                        IWL_CALIB_CFG_TX_IQ_IDX        |\
-                                        IWL_CALIB_CFG_RX_IQ_IDX        |\
-                                        IWL_CALIB_CFG_SENSITIVITY_IDX  |\
-                                        IWL_CALIB_CFG_AGC_IDX)
-
-#define IWL_CALIB_DEFAULT_EVENT_RUN    (IWL_CALIB_CFG_XTAL_IDX         |\
-                                        IWL_CALIB_CFG_TEMPERATURE_IDX  |\
-                                        IWL_CALIB_CFG_VOLTAGE_READ_IDX |\
-                                        IWL_CALIB_CFG_TX_PWR_IDX       |\
-                                        IWL_CALIB_CFG_DC_IDX           |\
-                                        IWL_CALIB_CFG_TX_IQ_IDX        |\
-                                        IWL_CALIB_CFG_SENSITIVITY_IDX)
-
-/*
- * Sets the calibrations trigger values that will be sent to the FW for runtime
- * and init calibrations.
- * The ones given in the FW TLV are not correct.
- */
-static void iwl_set_default_calib_trigger(struct iwl_mvm *mvm)
-{
-       struct iwl_tlv_calib_ctrl default_calib;
-
-       /*
-        * WkP FW TLV calib bits are wrong, overwrite them.
-        * This defines the dynamic calibrations which are implemented in the
-        * uCode both for init(flow) calculation and event driven calibs.
-        */
-
-       /* Init Image */
-       default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_INIT);
-       default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_INIT);
-
-       if (default_calib.event_trigger !=
-           mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger)
-               IWL_ERR(mvm,
-                       "Updating the event calib for INIT image: 0x%x -> 0x%x\n",
-                       mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger,
-                       default_calib.event_trigger);
-       if (default_calib.flow_trigger !=
-           mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger)
-               IWL_ERR(mvm,
-                       "Updating the flow calib for INIT image: 0x%x -> 0x%x\n",
-                       mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger,
-                       default_calib.flow_trigger);
-
-       memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_INIT],
-              &default_calib, sizeof(struct iwl_tlv_calib_ctrl));
-       IWL_ERR(mvm,
-               "Setting uCode init calibrations event 0x%x, trigger 0x%x\n",
-               default_calib.event_trigger,
-               default_calib.flow_trigger);
-
-       /* Run time image */
-       default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_RUN);
-       default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_RUN);
-
-       if (default_calib.event_trigger !=
-           mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger)
-               IWL_ERR(mvm,
-                       "Updating the event calib for RT image: 0x%x -> 0x%x\n",
-                       mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger,
-                       default_calib.event_trigger);
-       if (default_calib.flow_trigger !=
-           mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger)
-               IWL_ERR(mvm,
-                       "Updating the flow calib for RT image: 0x%x -> 0x%x\n",
-                       mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger,
-                       default_calib.flow_trigger);
-
-       memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_REGULAR],
-              &default_calib, sizeof(struct iwl_tlv_calib_ctrl));
-       IWL_ERR(mvm,
-               "Setting uCode runtime calibs event 0x%x, trigger 0x%x\n",
-               default_calib.event_trigger,
-               default_calib.flow_trigger);
-}
-
 static int iwl_set_default_calibrations(struct iwl_mvm *mvm)
 {
        u8 cmd_raw[16]; /* holds the variable size commands */
@@ -446,8 +321,10 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
        ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
        WARN_ON(ret);
 
-       /* Override the calibrations from TLV and the const of fw */
-       iwl_set_default_calib_trigger(mvm);
+       /* Send TX valid antennas before triggering calibrations */
+       ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant);
+       if (ret)
+               goto error;
 
        /* WkP doesn't have all calibrations, need to set default values */
        if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) {
index 537711b1047865cf42fb9ed271369917c4f736fb..bdae700c769eb292223d8871b1789a46f6f13610 100644 (file)
@@ -80,7 +80,8 @@
 
 #define IWL_INVALID_MAC80211_QUEUE     0xff
 #define IWL_MVM_MAX_ADDRESSES          2
-#define IWL_RSSI_OFFSET 44
+/* RSSI offset for WkP */
+#define IWL_RSSI_OFFSET 50
 
 enum iwl_mvm_tx_fifo {
        IWL_MVM_TX_FIFO_BK = 0,
index aa59adf87db333f66b0a2e925ddd66afd574ae60..d0f9c1e0475e71659576b609b8f3365196435f02 100644 (file)
@@ -624,12 +624,8 @@ static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
        ieee80211_free_txskb(mvm->hw, skb);
 }
 
-static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
+static void iwl_mvm_nic_restart(struct iwl_mvm *mvm)
 {
-       struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
-
-       iwl_mvm_dump_nic_error_log(mvm);
-
        iwl_abort_notification_waits(&mvm->notif_wait);
 
        /*
@@ -663,9 +659,21 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
        }
 }
 
+static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode)
+{
+       struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+
+       iwl_mvm_dump_nic_error_log(mvm);
+
+       iwl_mvm_nic_restart(mvm);
+}
+
 static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode)
 {
+       struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
+
        WARN_ON(1);
+       iwl_mvm_nic_restart(mvm);
 }
 
 static const struct iwl_op_mode_ops iwl_mvm_ops = {
index 3f40ab05bbd8181d55d4e1999ebc77f5f977b6f9..b0b190d0ec23659279f9a33e7d57b21428114f30 100644 (file)
@@ -131,33 +131,42 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
 static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm,
                             struct iwl_rx_phy_info *phy_info)
 {
-       u32 rssi_a, rssi_b, rssi_c, max_rssi, agc_db;
+       int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm;
+       int rssi_all_band_a, rssi_all_band_b;
+       u32 agc_a, agc_b, max_agc;
        u32 val;
 
-       /* Find max rssi among 3 possible receivers.
+       /* Find max rssi among 2 possible receivers.
         * These values are measured by the Digital Signal Processor (DSP).
         * They should stay fairly constant even as the signal strength varies,
         * if the radio's Automatic Gain Control (AGC) is working right.
         * AGC value (see below) will provide the "interesting" info.
         */
+       val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
+       agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS;
+       agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS;
+       max_agc = max_t(u32, agc_a, agc_b);
+
        val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_AB_IDX]);
        rssi_a = (val & IWL_OFDM_RSSI_INBAND_A_MSK) >> IWL_OFDM_RSSI_A_POS;
        rssi_b = (val & IWL_OFDM_RSSI_INBAND_B_MSK) >> IWL_OFDM_RSSI_B_POS;
-       val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_C_IDX]);
-       rssi_c = (val & IWL_OFDM_RSSI_INBAND_C_MSK) >> IWL_OFDM_RSSI_C_POS;
-
-       val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]);
-       agc_db = (val & IWL_OFDM_AGC_DB_MSK) >> IWL_OFDM_AGC_DB_POS;
+       rssi_all_band_a = (val & IWL_OFDM_RSSI_ALLBAND_A_MSK) >>
+                               IWL_OFDM_RSSI_ALLBAND_A_POS;
+       rssi_all_band_b = (val & IWL_OFDM_RSSI_ALLBAND_B_MSK) >>
+                               IWL_OFDM_RSSI_ALLBAND_B_POS;
 
-       max_rssi = max_t(u32, rssi_a, rssi_b);
-       max_rssi = max_t(u32, max_rssi, rssi_c);
+       /*
+        * dBm = rssi dB - agc dB - constant.
+        * Higher AGC (higher radio gain) means lower signal.
+        */
+       rssi_a_dbm = rssi_a - IWL_RSSI_OFFSET - agc_a;
+       rssi_b_dbm = rssi_b - IWL_RSSI_OFFSET - agc_b;
+       max_rssi_dbm = max_t(int, rssi_a_dbm, rssi_b_dbm);
 
-       IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
-                       rssi_a, rssi_b, rssi_c, max_rssi, agc_db);
+       IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n",
+                       rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b);
 
-       /* dBm = max_rssi dB - agc dB - constant.
-        * Higher AGC (higher radio gain) means lower signal. */
-       return max_rssi - agc_db - IWL_RSSI_OFFSET;
+       return max_rssi_dbm;
 }
 
 /*
index 861a7f9f8e7f4c0a932e4ce71e607bdc8a3b94fa..274f44e2ef60e52d1fb39f66735c98563036449e 100644 (file)
@@ -770,6 +770,16 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
        u16 txq_id;
        int err;
 
+
+       /*
+        * If mac80211 is cleaning its state, then say that we finished since
+        * our state has been cleared anyway.
+        */
+       if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) {
+               ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+               return 0;
+       }
+
        spin_lock_bh(&mvmsta->lock);
 
        txq_id = tid_data->txq_id;
index 6b67ce3f679ceb8ad4907c14c32926d0828f9f75..6645efe5c03edfdc3c4523f0c06ab1d7bc0c7629 100644 (file)
@@ -607,12 +607,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
 
                /* Single frame failure in an AMPDU queue => send BAR */
                if (txq_id >= IWL_FIRST_AMPDU_QUEUE &&
-                   !(info->flags & IEEE80211_TX_STAT_ACK)) {
-                       /* there must be only one skb in the skb_list */
-                       WARN_ON_ONCE(skb_freed > 1 ||
-                                    !skb_queue_empty(&skbs));
+                   !(info->flags & IEEE80211_TX_STAT_ACK))
                        info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
-               }
 
                /* W/A FW bug: seq_ctl is wrong when the queue is flushed */
                if (status == TX_STATUS_FAIL_FIFO_FLUSHED) {
index 3d62e8055352b667ee4a776f4d218d7d4d3431ee..148843e7f34f26f9ea98d8ae269e366765cba115 100644 (file)
@@ -137,10 +137,6 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd)
 struct iwl_cmd_meta {
        /* only for SYNC commands, iff the reply skb is wanted */
        struct iwl_host_cmd *source;
-
-       DEFINE_DMA_UNMAP_ADDR(mapping);
-       DEFINE_DMA_UNMAP_LEN(len);
-
        u32 flags;
 };
 
@@ -185,25 +181,36 @@ struct iwl_queue {
 /*
  * The FH will write back to the first TB only, so we need
  * to copy some data into the buffer regardless of whether
- * it should be mapped or not. This indicates how much to
- * copy, even for HCMDs it must be big enough to fit the
- * DRAM scratch from the TX cmd, at least 16 bytes.
+ * it should be mapped or not. This indicates how big the
+ * first TB must be to include the scratch buffer. Since
+ * the scratch is 4 bytes at offset 12, it's 16 now. If we
+ * make it bigger then allocations will be bigger and copy
+ * slower, so that's probably not useful.
  */
-#define IWL_HCMD_MIN_COPY_SIZE 16
+#define IWL_HCMD_SCRATCHBUF_SIZE       16
 
 struct iwl_pcie_txq_entry {
        struct iwl_device_cmd *cmd;
-       struct iwl_device_cmd *copy_cmd;
        struct sk_buff *skb;
        /* buffer to free after command completes */
        const void *free_buf;
        struct iwl_cmd_meta meta;
 };
 
+struct iwl_pcie_txq_scratch_buf {
+       struct iwl_cmd_header hdr;
+       u8 buf[8];
+       __le32 scratch;
+};
+
 /**
  * struct iwl_txq - Tx Queue for DMA
  * @q: generic Rx/Tx queue descriptor
  * @tfds: transmit frame descriptors (DMA memory)
+ * @scratchbufs: start of command headers, including scratch buffers, for
+ *     the writeback -- this is DMA memory and an array holding one buffer
+ *     for each command on the queue
+ * @scratchbufs_dma: DMA address for the scratchbufs start
  * @entries: transmit entries (driver state)
  * @lock: queue lock
  * @stuck_timer: timer that fires if queue gets stuck
@@ -217,6 +224,8 @@ struct iwl_pcie_txq_entry {
 struct iwl_txq {
        struct iwl_queue q;
        struct iwl_tfd *tfds;
+       struct iwl_pcie_txq_scratch_buf *scratchbufs;
+       dma_addr_t scratchbufs_dma;
        struct iwl_pcie_txq_entry *entries;
        spinlock_t lock;
        struct timer_list stuck_timer;
@@ -225,6 +234,13 @@ struct iwl_txq {
        u8 active;
 };
 
+static inline dma_addr_t
+iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx)
+{
+       return txq->scratchbufs_dma +
+              sizeof(struct iwl_pcie_txq_scratch_buf) * idx;
+}
+
 /**
  * struct iwl_trans_pcie - PCIe transport specific data
  * @rxq: all the RX queue data
index b0ae06d2456f1c388ba47fcdbb88f74063ea1162..567e67ad1f617682cbba7a90f2ca95e53eb07eea 100644 (file)
@@ -637,22 +637,14 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans,
                index = SEQ_TO_INDEX(sequence);
                cmd_index = get_cmd_index(&txq->q, index);
 
-               if (reclaim) {
-                       struct iwl_pcie_txq_entry *ent;
-                       ent = &txq->entries[cmd_index];
-                       cmd = ent->copy_cmd;
-                       WARN_ON_ONCE(!cmd && ent->meta.flags & CMD_WANT_HCMD);
-               } else {
+               if (reclaim)
+                       cmd = txq->entries[cmd_index].cmd;
+               else
                        cmd = NULL;
-               }
 
                err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd);
 
                if (reclaim) {
-                       /* The original command isn't needed any more */
-                       kfree(txq->entries[cmd_index].copy_cmd);
-                       txq->entries[cmd_index].copy_cmd = NULL;
-                       /* nor is the duplicated part of the command */
                        kfree(txq->entries[cmd_index].free_buf);
                        txq->entries[cmd_index].free_buf = NULL;
                }
index 17bedc50e753d62613055eb3662c4095fe9f41bf..12c4f31ca8fbddcc95925cebf4b269b150a64ef2 100644 (file)
@@ -475,6 +475,10 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans,
 
        /* If platform's RF_KILL switch is NOT set to KILL */
        hw_rfkill = iwl_is_rfkill_set(trans);
+       if (hw_rfkill)
+               set_bit(STATUS_RFKILL, &trans_pcie->status);
+       else
+               clear_bit(STATUS_RFKILL, &trans_pcie->status);
        iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
        if (hw_rfkill && !run_in_rfkill)
                return -ERFKILL;
@@ -641,6 +645,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
 
 static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
 {
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        bool hw_rfkill;
        int err;
 
@@ -656,6 +661,10 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
        iwl_enable_rfkill_int(trans);
 
        hw_rfkill = iwl_is_rfkill_set(trans);
+       if (hw_rfkill)
+               set_bit(STATUS_RFKILL, &trans_pcie->status);
+       else
+               clear_bit(STATUS_RFKILL, &trans_pcie->status);
        iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
 
        return 0;
@@ -694,6 +703,10 @@ static void iwl_trans_pcie_stop_hw(struct iwl_trans *trans,
                 * op_mode.
                 */
                hw_rfkill = iwl_is_rfkill_set(trans);
+               if (hw_rfkill)
+                       set_bit(STATUS_RFKILL, &trans_pcie->status);
+               else
+                       clear_bit(STATUS_RFKILL, &trans_pcie->status);
                iwl_op_mode_hw_rf_kill(trans->op_mode, hw_rfkill);
        }
 }
index 8b625a7f56859a32523e73f1e502d967f65d8aea..cb5c6792e3a8de2679022370c140263b8e1e9e57 100644 (file)
@@ -191,12 +191,9 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
        }
 
        for (i = q->read_ptr; i != q->write_ptr;
-            i = iwl_queue_inc_wrap(i, q->n_bd)) {
-               struct iwl_tx_cmd *tx_cmd =
-                       (struct iwl_tx_cmd *)txq->entries[i].cmd->payload;
+            i = iwl_queue_inc_wrap(i, q->n_bd))
                IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
-                       get_unaligned_le32(&tx_cmd->scratch));
-       }
+                       le32_to_cpu(txq->scratchbufs[i].scratch));
 
        iwl_op_mode_nic_error(trans->op_mode);
 }
@@ -367,8 +364,8 @@ static inline u8 iwl_pcie_tfd_get_num_tbs(struct iwl_tfd *tfd)
 }
 
 static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
-                              struct iwl_cmd_meta *meta, struct iwl_tfd *tfd,
-                              enum dma_data_direction dma_dir)
+                              struct iwl_cmd_meta *meta,
+                              struct iwl_tfd *tfd)
 {
        int i;
        int num_tbs;
@@ -382,17 +379,12 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
                return;
        }
 
-       /* Unmap tx_cmd */
-       if (num_tbs)
-               dma_unmap_single(trans->dev,
-                               dma_unmap_addr(meta, mapping),
-                               dma_unmap_len(meta, len),
-                               DMA_BIDIRECTIONAL);
+       /* first TB is never freed - it's the scratchbuf data */
 
-       /* Unmap chunks, if any. */
        for (i = 1; i < num_tbs; i++)
                dma_unmap_single(trans->dev, iwl_pcie_tfd_tb_get_addr(tfd, i),
-                                iwl_pcie_tfd_tb_get_len(tfd, i), dma_dir);
+                                iwl_pcie_tfd_tb_get_len(tfd, i),
+                                DMA_TO_DEVICE);
 
        tfd->num_tbs = 0;
 }
@@ -406,8 +398,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans,
  * Does NOT advance any TFD circular buffer read/write indexes
  * Does NOT free the TFD itself (which is within circular buffer)
  */
-static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
-                                 enum dma_data_direction dma_dir)
+static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)
 {
        struct iwl_tfd *tfd_tmp = txq->tfds;
 
@@ -418,8 +409,7 @@ static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
        lockdep_assert_held(&txq->lock);
 
        /* We have only q->n_window txq->entries, but we use q->n_bd tfds */
-       iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr],
-                          dma_dir);
+       iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr]);
 
        /* free SKB */
        if (txq->entries) {
@@ -479,6 +469,7 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans,
 {
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX;
+       size_t scratchbuf_sz;
        int i;
 
        if (WARN_ON(txq->entries || txq->tfds))
@@ -514,9 +505,25 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans,
                IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz);
                goto error;
        }
+
+       BUILD_BUG_ON(IWL_HCMD_SCRATCHBUF_SIZE != sizeof(*txq->scratchbufs));
+       BUILD_BUG_ON(offsetof(struct iwl_pcie_txq_scratch_buf, scratch) !=
+                       sizeof(struct iwl_cmd_header) +
+                       offsetof(struct iwl_tx_cmd, scratch));
+
+       scratchbuf_sz = sizeof(*txq->scratchbufs) * slots_num;
+
+       txq->scratchbufs = dma_alloc_coherent(trans->dev, scratchbuf_sz,
+                                             &txq->scratchbufs_dma,
+                                             GFP_KERNEL);
+       if (!txq->scratchbufs)
+               goto err_free_tfds;
+
        txq->q.id = txq_id;
 
        return 0;
+err_free_tfds:
+       dma_free_coherent(trans->dev, tfd_sz, txq->tfds, txq->q.dma_addr);
 error:
        if (txq->entries && txq_id == trans_pcie->cmd_queue)
                for (i = 0; i < slots_num; i++)
@@ -565,22 +572,13 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
        struct iwl_txq *txq = &trans_pcie->txq[txq_id];
        struct iwl_queue *q = &txq->q;
-       enum dma_data_direction dma_dir;
 
        if (!q->n_bd)
                return;
 
-       /* In the command queue, all the TBs are mapped as BIDI
-        * so unmap them as such.
-        */
-       if (txq_id == trans_pcie->cmd_queue)
-               dma_dir = DMA_BIDIRECTIONAL;
-       else
-               dma_dir = DMA_TO_DEVICE;
-
        spin_lock_bh(&txq->lock);
        while (q->write_ptr != q->read_ptr) {
-               iwl_pcie_txq_free_tfd(trans, txq, dma_dir);
+               iwl_pcie_txq_free_tfd(trans, txq);
                q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
        }
        spin_unlock_bh(&txq->lock);
@@ -610,7 +608,6 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
        if (txq_id == trans_pcie->cmd_queue)
                for (i = 0; i < txq->q.n_window; i++) {
                        kfree(txq->entries[i].cmd);
-                       kfree(txq->entries[i].copy_cmd);
                        kfree(txq->entries[i].free_buf);
                }
 
@@ -619,6 +616,10 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
                dma_free_coherent(dev, sizeof(struct iwl_tfd) *
                                  txq->q.n_bd, txq->tfds, txq->q.dma_addr);
                txq->q.dma_addr = 0;
+
+               dma_free_coherent(dev,
+                                 sizeof(*txq->scratchbufs) * txq->q.n_window,
+                                 txq->scratchbufs, txq->scratchbufs_dma);
        }
 
        kfree(txq->entries);
@@ -962,7 +963,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
 
                iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq);
 
-               iwl_pcie_txq_free_tfd(trans, txq, DMA_TO_DEVICE);
+               iwl_pcie_txq_free_tfd(trans, txq);
        }
 
        iwl_pcie_txq_progress(trans_pcie, txq);
@@ -1152,29 +1153,29 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
        void *dup_buf = NULL;
        dma_addr_t phys_addr;
        int idx;
-       u16 copy_size, cmd_size, dma_size;
+       u16 copy_size, cmd_size, scratch_size;
        bool had_nocopy = false;
        int i;
        u32 cmd_pos;
-       const u8 *cmddata[IWL_MAX_CMD_TFDS];
-       u16 cmdlen[IWL_MAX_CMD_TFDS];
+       const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD];
+       u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD];
 
        copy_size = sizeof(out_cmd->hdr);
        cmd_size = sizeof(out_cmd->hdr);
 
        /* need one for the header if the first is NOCOPY */
-       BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1);
+       BUILD_BUG_ON(IWL_MAX_CMD_TBS_PER_TFD > IWL_NUM_OF_TBS - 1);
 
-       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+       for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
                cmddata[i] = cmd->data[i];
                cmdlen[i] = cmd->len[i];
 
                if (!cmd->len[i])
                        continue;
 
-               /* need at least IWL_HCMD_MIN_COPY_SIZE copied */
-               if (copy_size < IWL_HCMD_MIN_COPY_SIZE) {
-                       int copy = IWL_HCMD_MIN_COPY_SIZE - copy_size;
+               /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */
+               if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) {
+                       int copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size;
 
                        if (copy > cmdlen[i])
                                copy = cmdlen[i];
@@ -1260,15 +1261,15 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
        /* and copy the data that needs to be copied */
        cmd_pos = offsetof(struct iwl_device_cmd, payload);
        copy_size = sizeof(out_cmd->hdr);
-       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+       for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
                int copy = 0;
 
-               if (!cmd->len)
+               if (!cmd->len[i])
                        continue;
 
-               /* need at least IWL_HCMD_MIN_COPY_SIZE copied */
-               if (copy_size < IWL_HCMD_MIN_COPY_SIZE) {
-                       copy = IWL_HCMD_MIN_COPY_SIZE - copy_size;
+               /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */
+               if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) {
+                       copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size;
 
                        if (copy > cmd->len[i])
                                copy = cmd->len[i];
@@ -1286,50 +1287,38 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
                }
        }
 
-       WARN_ON_ONCE(txq->entries[idx].copy_cmd);
-
-       /*
-        * since out_cmd will be the source address of the FH, it will write
-        * the retry count there. So when the user needs to receivce the HCMD
-        * that corresponds to the response in the response handler, it needs
-        * to set CMD_WANT_HCMD.
-        */
-       if (cmd->flags & CMD_WANT_HCMD) {
-               txq->entries[idx].copy_cmd =
-                       kmemdup(out_cmd, cmd_pos, GFP_ATOMIC);
-               if (unlikely(!txq->entries[idx].copy_cmd)) {
-                       idx = -ENOMEM;
-                       goto out;
-               }
-       }
-
        IWL_DEBUG_HC(trans,
                     "Sending command %s (#%x), seq: 0x%04X, %d bytes at %d[%d]:%d\n",
                     get_cmd_string(trans_pcie, out_cmd->hdr.cmd),
                     out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence),
                     cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue);
 
-       /*
-        * If the entire command is smaller than IWL_HCMD_MIN_COPY_SIZE, we must
-        * still map at least that many bytes for the hardware to write back to.
-        * We have enough space, so that's not a problem.
-        */
-       dma_size = max_t(u16, copy_size, IWL_HCMD_MIN_COPY_SIZE);
+       /* start the TFD with the scratchbuf */
+       scratch_size = min_t(int, copy_size, IWL_HCMD_SCRATCHBUF_SIZE);
+       memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size);
+       iwl_pcie_txq_build_tfd(trans, txq,
+                              iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr),
+                              scratch_size, 1);
+
+       /* map first command fragment, if any remains */
+       if (copy_size > scratch_size) {
+               phys_addr = dma_map_single(trans->dev,
+                                          ((u8 *)&out_cmd->hdr) + scratch_size,
+                                          copy_size - scratch_size,
+                                          DMA_TO_DEVICE);
+               if (dma_mapping_error(trans->dev, phys_addr)) {
+                       iwl_pcie_tfd_unmap(trans, out_meta,
+                                          &txq->tfds[q->write_ptr]);
+                       idx = -ENOMEM;
+                       goto out;
+               }
 
-       phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, dma_size,
-                                  DMA_BIDIRECTIONAL);
-       if (unlikely(dma_mapping_error(trans->dev, phys_addr))) {
-               idx = -ENOMEM;
-               goto out;
+               iwl_pcie_txq_build_tfd(trans, txq, phys_addr,
+                                      copy_size - scratch_size, 0);
        }
 
-       dma_unmap_addr_set(out_meta, mapping, phys_addr);
-       dma_unmap_len_set(out_meta, len, dma_size);
-
-       iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1);
-
        /* map the remaining (adjusted) nocopy/dup fragments */
-       for (i = 0; i < IWL_MAX_CMD_TFDS; i++) {
+       for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
                const void *data = cmddata[i];
 
                if (!cmdlen[i])
@@ -1340,11 +1329,10 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
                if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP)
                        data = dup_buf;
                phys_addr = dma_map_single(trans->dev, (void *)data,
-                                          cmdlen[i], DMA_BIDIRECTIONAL);
+                                          cmdlen[i], DMA_TO_DEVICE);
                if (dma_mapping_error(trans->dev, phys_addr)) {
                        iwl_pcie_tfd_unmap(trans, out_meta,
-                                          &txq->tfds[q->write_ptr],
-                                          DMA_BIDIRECTIONAL);
+                                          &txq->tfds[q->write_ptr]);
                        idx = -ENOMEM;
                        goto out;
                }
@@ -1418,7 +1406,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans,
        cmd = txq->entries[cmd_index].cmd;
        meta = &txq->entries[cmd_index].meta;
 
-       iwl_pcie_tfd_unmap(trans, meta, &txq->tfds[index], DMA_BIDIRECTIONAL);
+       iwl_pcie_tfd_unmap(trans, meta, &txq->tfds[index]);
 
        /* Input error checking is done when commands are added to queue. */
        if (meta->flags & CMD_WANT_SKB) {
@@ -1597,10 +1585,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
        struct iwl_cmd_meta *out_meta;
        struct iwl_txq *txq;
        struct iwl_queue *q;
-       dma_addr_t phys_addr = 0;
-       dma_addr_t txcmd_phys;
-       dma_addr_t scratch_phys;
-       u16 len, firstlen, secondlen;
+       dma_addr_t tb0_phys, tb1_phys, scratch_phys;
+       void *tb1_addr;
+       u16 len, tb1_len, tb2_len;
        u8 wait_write_ptr = 0;
        __le16 fc = hdr->frame_control;
        u8 hdr_len = ieee80211_hdrlen(fc);
@@ -1638,85 +1625,80 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
                cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
                            INDEX_TO_SEQ(q->write_ptr)));
 
+       tb0_phys = iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr);
+       scratch_phys = tb0_phys + sizeof(struct iwl_cmd_header) +
+                      offsetof(struct iwl_tx_cmd, scratch);
+
+       tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
+       tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
+
        /* Set up first empty entry in queue's array of Tx/cmd buffers */
        out_meta = &txq->entries[q->write_ptr].meta;
 
        /*
-        * Use the first empty entry in this queue's command buffer array
-        * to contain the Tx command and MAC header concatenated together
-        * (payload data will be in another buffer).
-        * Size of this varies, due to varying MAC header length.
-        * If end is not dword aligned, we'll have 2 extra bytes at the end
-        * of the MAC header (device reads on dword boundaries).
-        * We'll tell device about this padding later.
+        * The second TB (tb1) points to the remainder of the TX command
+        * and the 802.11 header - dword aligned size
+        * (This calculation modifies the TX command, so do it before the
+        * setup of the first TB)
         */
-       len = sizeof(struct iwl_tx_cmd) +
-               sizeof(struct iwl_cmd_header) + hdr_len;
-       firstlen = (len + 3) & ~3;
+       len = sizeof(struct iwl_tx_cmd) + sizeof(struct iwl_cmd_header) +
+             hdr_len - IWL_HCMD_SCRATCHBUF_SIZE;
+       tb1_len = (len + 3) & ~3;
 
        /* Tell NIC about any 2-byte padding after MAC header */
-       if (firstlen != len)
+       if (tb1_len != len)
                tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
 
-       /* Physical address of this Tx command's header (not MAC header!),
-        * within command buffer array. */
-       txcmd_phys = dma_map_single(trans->dev,
-                                   &dev_cmd->hdr, firstlen,
-                                   DMA_BIDIRECTIONAL);
-       if (unlikely(dma_mapping_error(trans->dev, txcmd_phys)))
-               goto out_err;
-       dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
-       dma_unmap_len_set(out_meta, len, firstlen);
+       /* The first TB points to the scratchbuf data - min_copy bytes */
+       memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr,
+              IWL_HCMD_SCRATCHBUF_SIZE);
+       iwl_pcie_txq_build_tfd(trans, txq, tb0_phys,
+                              IWL_HCMD_SCRATCHBUF_SIZE, 1);
 
-       if (!ieee80211_has_morefrags(fc)) {
-               txq->need_update = 1;
-       } else {
-               wait_write_ptr = 1;
-               txq->need_update = 0;
-       }
+       /* there must be data left over for TB1 or this code must be changed */
+       BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_HCMD_SCRATCHBUF_SIZE);
 
-       /* Set up TFD's 2nd entry to point directly to remainder of skb,
-        * if any (802.11 null frames have no payload). */
-       secondlen = skb->len - hdr_len;
-       if (secondlen > 0) {
-               phys_addr = dma_map_single(trans->dev, skb->data + hdr_len,
-                                          secondlen, DMA_TO_DEVICE);
-               if (unlikely(dma_mapping_error(trans->dev, phys_addr))) {
-                       dma_unmap_single(trans->dev,
-                                        dma_unmap_addr(out_meta, mapping),
-                                        dma_unmap_len(out_meta, len),
-                                        DMA_BIDIRECTIONAL);
+       /* map the data for TB1 */
+       tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_HCMD_SCRATCHBUF_SIZE;
+       tb1_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE);
+       if (unlikely(dma_mapping_error(trans->dev, tb1_phys)))
+               goto out_err;
+       iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, 0);
+
+       /*
+        * Set up TFD's third entry to point directly to remainder
+        * of skb, if any (802.11 null frames have no payload).
+        */
+       tb2_len = skb->len - hdr_len;
+       if (tb2_len > 0) {
+               dma_addr_t tb2_phys = dma_map_single(trans->dev,
+                                                    skb->data + hdr_len,
+                                                    tb2_len, DMA_TO_DEVICE);
+               if (unlikely(dma_mapping_error(trans->dev, tb2_phys))) {
+                       iwl_pcie_tfd_unmap(trans, out_meta,
+                                          &txq->tfds[q->write_ptr]);
                        goto out_err;
                }
+               iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, 0);
        }
 
-       /* Attach buffers to TFD */
-       iwl_pcie_txq_build_tfd(trans, txq, txcmd_phys, firstlen, 1);
-       if (secondlen > 0)
-               iwl_pcie_txq_build_tfd(trans, txq, phys_addr, secondlen, 0);
-
-       scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
-                               offsetof(struct iwl_tx_cmd, scratch);
-
-       /* take back ownership of DMA buffer to enable update */
-       dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen,
-                               DMA_BIDIRECTIONAL);
-       tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
-       tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys);
-
        /* Set up entry for this TFD in Tx byte-count array */
        iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len));
 
-       dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen,
-                                  DMA_BIDIRECTIONAL);
-
        trace_iwlwifi_dev_tx(trans->dev, skb,
                             &txq->tfds[txq->q.write_ptr],
                             sizeof(struct iwl_tfd),
-                            &dev_cmd->hdr, firstlen,
-                            skb->data + hdr_len, secondlen);
+                            &dev_cmd->hdr, IWL_HCMD_SCRATCHBUF_SIZE + tb1_len,
+                            skb->data + hdr_len, tb2_len);
        trace_iwlwifi_dev_tx_data(trans->dev, skb,
-                                 skb->data + hdr_len, secondlen);
+                                 skb->data + hdr_len, tb2_len);
+
+       if (!ieee80211_has_morefrags(fc)) {
+               txq->need_update = 1;
+       } else {
+               wait_write_ptr = 1;
+               txq->need_update = 0;
+       }
 
        /* start timer if queue currently empty */
        if (txq->need_update && q->read_ptr == q->write_ptr &&
index a44023a7bd571ca228be0a4fe16f09d4fe42a1a8..8aaf56ade4d9d086f36b7dee9d880f7628b50b23 100644 (file)
@@ -1892,7 +1892,8 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy,
                }
        }
 
-       for (i = 0; i < request->n_channels; i++) {
+       for (i = 0; i < min_t(u32, request->n_channels,
+                             MWIFIEX_USER_SCAN_CHAN_MAX); i++) {
                chan = request->channels[i];
                priv->user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
                priv->user_scan_cfg->chan_list[i].radio_type = chan->band;
index 20a6c55558737b3bc3e3968856c5fe827780c688..b5c8b962ce12f74077fb6159b3e8558f521f10a5 100644 (file)
@@ -157,6 +157,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
                return -1;
        }
 
+       cmd_code = le16_to_cpu(host_cmd->command);
+       cmd_size = le16_to_cpu(host_cmd->size);
+
+       if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET &&
+           cmd_code != HostCmd_CMD_FUNC_SHUTDOWN &&
+           cmd_code != HostCmd_CMD_FUNC_INIT) {
+               dev_err(adapter->dev,
+                       "DNLD_CMD: FW in reset state, ignore cmd %#x\n",
+                       cmd_code);
+               mwifiex_complete_cmd(adapter, cmd_node);
+               mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+               return -1;
+       }
+
        /* Set command sequence number */
        adapter->seq_num++;
        host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO
@@ -168,9 +182,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
        adapter->curr_cmd = cmd_node;
        spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
 
-       cmd_code = le16_to_cpu(host_cmd->command);
-       cmd_size = le16_to_cpu(host_cmd->size);
-
        /* Adjust skb length */
        if (cmd_node->cmd_skb->len > cmd_size)
                /*
@@ -484,8 +495,6 @@ int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no,
 
        ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid,
                                     data_buf);
-       if (!ret)
-               ret = mwifiex_wait_queue_complete(adapter);
 
        return ret;
 }
@@ -588,9 +597,10 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
        if (cmd_no == HostCmd_CMD_802_11_SCAN) {
                mwifiex_queue_scan_cmd(priv, cmd_node);
        } else {
-               adapter->cmd_queued = cmd_node;
                mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
                queue_work(adapter->workqueue, &adapter->main_work);
+               if (cmd_node->wait_q_enabled)
+                       ret = mwifiex_wait_queue_complete(adapter, cmd_node);
        }
 
        return ret;
index e38aa9b3663d0a76c0cfe1c7f0698f923fc58587..0ff4c37ab42ae6853dbe6c85f8bb33f476b531e1 100644 (file)
@@ -709,6 +709,14 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter)
                return ret;
        }
 
+       /* cancel current command */
+       if (adapter->curr_cmd) {
+               dev_warn(adapter->dev, "curr_cmd is still in processing\n");
+               del_timer(&adapter->cmd_timer);
+               mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd);
+               adapter->curr_cmd = NULL;
+       }
+
        /* shut down mwifiex */
        dev_dbg(adapter->dev, "info: shutdown mwifiex...\n");
 
index 246aa62a48172d849cff8bd3d42947b28d7803a0..2fe0ceba4400ad017d99ca5324707aa96093d6be 100644 (file)
@@ -1117,10 +1117,9 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv,
                adhoc_join->bss_descriptor.bssid,
                adhoc_join->bss_descriptor.ssid);
 
-       for (i = 0; bss_desc->supported_rates[i] &&
-                       i < MWIFIEX_SUPPORTED_RATES;
-                       i++)
-                       ;
+       for (i = 0; i < MWIFIEX_SUPPORTED_RATES &&
+                   bss_desc->supported_rates[i]; i++)
+               ;
        rates_size = i;
 
        /* Copy Data Rates from the Rates recorded in scan response */
index 553adfb0aa81a35c468e44a07943b3f8fdf6e79e..7035ade9af74aeb08ceeea6b1545b28bd8e105d9 100644 (file)
@@ -723,7 +723,6 @@ struct mwifiex_adapter {
        u16 cmd_wait_q_required;
        struct mwifiex_wait_queue cmd_wait_q;
        u8 scan_wait_q_woken;
-       struct cmd_ctrl_node *cmd_queued;
        spinlock_t queue_lock;          /* lock for tx queues */
        struct completion fw_load;
        u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
@@ -1018,7 +1017,8 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
                        struct mwifiex_multicast_list *mcast_list);
 int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
                            struct net_device *dev);
-int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter);
+int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
+                               struct cmd_ctrl_node *cmd_queued);
 int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
                      struct cfg80211_ssid *req_ssid);
 int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type);
index 5c395e2e6a2b874fb0257424663a73cb7abf0c17..feb20461339767df1c8912b216b9d62a1c11f5da 100644 (file)
@@ -1508,6 +1508,7 @@ static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter)
                }
                memcpy(adapter->upld_buf, skb->data,
                       min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len));
+               skb_push(skb, INTF_HEADER_LEN);
                if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE,
                                           PCI_DMA_FROMDEVICE))
                        return -1;
index bb60c2754a97ea54cc8c709206ba31a861e05d2e..d215b4d3c51b57db90eee2293f6c153059fe037b 100644 (file)
@@ -1388,10 +1388,13 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
                        list_del(&cmd_node->list);
                        spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
                                               flags);
-                       adapter->cmd_queued = cmd_node;
                        mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
                                                        true);
                        queue_work(adapter->workqueue, &adapter->main_work);
+
+                       /* Perform internal scan synchronously */
+                       if (!priv->scan_request)
+                               mwifiex_wait_queue_complete(adapter, cmd_node);
                } else {
                        spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
                                               flags);
@@ -1946,9 +1949,6 @@ int mwifiex_request_scan(struct mwifiex_private *priv,
                /* Normal scan */
                ret = mwifiex_scan_networks(priv, NULL);
 
-       if (!ret)
-               ret = mwifiex_wait_queue_complete(priv->adapter);
-
        up(&priv->async_sem);
 
        return ret;
index 9f33c92c90f5b8dc32bf9685bd3b708171b66acc..13100f8de3db1729b613333f16d21438104cd2e0 100644 (file)
@@ -54,16 +54,10 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
  * This function waits on a cmd wait queue. It also cancels the pending
  * request after waking up, in case of errors.
  */
-int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
+int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter,
+                               struct cmd_ctrl_node *cmd_queued)
 {
        int status;
-       struct cmd_ctrl_node *cmd_queued;
-
-       if (!adapter->cmd_queued)
-               return 0;
-
-       cmd_queued = adapter->cmd_queued;
-       adapter->cmd_queued = NULL;
 
        dev_dbg(adapter->dev, "cmd pending\n");
        atomic_inc(&adapter->cmd_pending);
index 44d6ead433411eeddc801dc8e1eea0cce40d67e4..2bf4efa331867acaea139bb81dcca75a66532ef4 100644 (file)
@@ -55,10 +55,10 @@ config RT61PCI
 
 config RT2800PCI
        tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support"
-       depends on PCI || RALINK_RT288X || RALINK_RT305X
+       depends on PCI || SOC_RT288X || SOC_RT305X
        select RT2800_LIB
        select RT2X00_LIB_PCI if PCI
-       select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X
+       select RT2X00_LIB_SOC if SOC_RT288X || SOC_RT305X
        select RT2X00_LIB_FIRMWARE
        select RT2X00_LIB_CRYPTO
        select CRC_CCITT
index 48a01aa21f1c94039d9485d5e635926d58a17750..ded73da4de0b0d52cd6331d837c8c68e86b87749 100644 (file)
@@ -89,7 +89,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token)
        rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
 }
 
-#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
+#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
 static int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
 {
        void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE);
@@ -107,7 +107,7 @@ static inline int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev)
 {
        return -ENOMEM;
 }
-#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */
+#endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */
 
 #ifdef CONFIG_PCI
 static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom)
@@ -1177,7 +1177,7 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table);
 #endif /* CONFIG_PCI */
 MODULE_LICENSE("GPL");
 
-#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
+#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
 static int rt2800soc_probe(struct platform_device *pdev)
 {
        return rt2x00soc_probe(pdev, &rt2800pci_ops);
@@ -1194,7 +1194,7 @@ static struct platform_driver rt2800soc_driver = {
        .suspend        = rt2x00soc_suspend,
        .resume         = rt2x00soc_resume,
 };
-#endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */
+#endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */
 
 #ifdef CONFIG_PCI
 static int rt2800pci_probe(struct pci_dev *pci_dev,
@@ -1217,7 +1217,7 @@ static int __init rt2800pci_init(void)
 {
        int ret = 0;
 
-#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
+#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
        ret = platform_driver_register(&rt2800soc_driver);
        if (ret)
                return ret;
@@ -1225,7 +1225,7 @@ static int __init rt2800pci_init(void)
 #ifdef CONFIG_PCI
        ret = pci_register_driver(&rt2800pci_driver);
        if (ret) {
-#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
+#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
                platform_driver_unregister(&rt2800soc_driver);
 #endif
                return ret;
@@ -1240,7 +1240,7 @@ static void __exit rt2800pci_exit(void)
 #ifdef CONFIG_PCI
        pci_unregister_driver(&rt2800pci_driver);
 #endif
-#if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X)
+#if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X)
        platform_driver_unregister(&rt2800soc_driver);
 #endif
 }
index b1ccff474c7953f2431cb2cd0390f2e0ebf89591..c08d0f4c5f3d3fe8416195951ea6547a80429030 100644 (file)
@@ -1376,75 +1376,58 @@ void rtl92cu_card_disable(struct ieee80211_hw *hw)
 }
 
 void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
-{
-       /* dummy routine needed for callback from rtl_op_configure_filter() */
-}
-
-/*========================================================================== */
-
-static void _rtl92cu_set_check_bssid(struct ieee80211_hw *hw,
-                             enum nl80211_iftype type)
 {
        struct rtl_priv *rtlpriv = rtl_priv(hw);
-       u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR);
        struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
-       struct rtl_phy *rtlphy = &(rtlpriv->phy);
-       u8 filterout_non_associated_bssid = false;
+       u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR);
 
-       switch (type) {
-       case NL80211_IFTYPE_ADHOC:
-       case NL80211_IFTYPE_STATION:
-               filterout_non_associated_bssid = true;
-               break;
-       case NL80211_IFTYPE_UNSPECIFIED:
-       case NL80211_IFTYPE_AP:
-       default:
-               break;
-       }
-       if (filterout_non_associated_bssid) {
+       if (rtlpriv->psc.rfpwr_state != ERFON)
+               return;
+
+       if (check_bssid) {
+               u8 tmp;
                if (IS_NORMAL_CHIP(rtlhal->version)) {
-                       switch (rtlphy->current_io_type) {
-                       case IO_CMD_RESUME_DM_BY_SCAN:
-                               reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
-                               rtlpriv->cfg->ops->set_hw_reg(hw,
-                                                HW_VAR_RCR, (u8 *)(&reg_rcr));
-                               /* enable update TSF */
-                               _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
-                               break;
-                       case IO_CMD_PAUSE_DM_BY_SCAN:
-                               reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
-                               rtlpriv->cfg->ops->set_hw_reg(hw,
-                                                HW_VAR_RCR, (u8 *)(&reg_rcr));
-                               /* disable update TSF */
-                               _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
-                               break;
-                       }
+                       reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+                       tmp = BIT(4);
                } else {
-                       reg_rcr |= (RCR_CBSSID);
-                       rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
-                                                     (u8 *)(&reg_rcr));
-                       _rtl92cu_set_bcn_ctrl_reg(hw, 0, (BIT(4)|BIT(5)));
+                       reg_rcr |= RCR_CBSSID;
+                       tmp = BIT(4) | BIT(5);
                }
-       } else if (filterout_non_associated_bssid == false) {
+               rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
+                                             (u8 *) (&reg_rcr));
+               _rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp);
+       } else {
+               u8 tmp;
                if (IS_NORMAL_CHIP(rtlhal->version)) {
-                       reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
-                       rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
-                                                     (u8 *)(&reg_rcr));
-                       _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
+                       reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+                       tmp = BIT(4);
                } else {
-                       reg_rcr &= (~RCR_CBSSID);
-                       rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
-                                                     (u8 *)(&reg_rcr));
-                       _rtl92cu_set_bcn_ctrl_reg(hw, (BIT(4)|BIT(5)), 0);
+                       reg_rcr &= ~RCR_CBSSID;
+                       tmp = BIT(4) | BIT(5);
                }
+               reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
+               rtlpriv->cfg->ops->set_hw_reg(hw,
+                                             HW_VAR_RCR, (u8 *) (&reg_rcr));
+               _rtl92cu_set_bcn_ctrl_reg(hw, tmp, 0);
        }
 }
 
+/*========================================================================== */
+
 int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
 {
+       struct rtl_priv *rtlpriv = rtl_priv(hw);
+
        if (_rtl92cu_set_media_status(hw, type))
                return -EOPNOTSUPP;
-       _rtl92cu_set_check_bssid(hw, type);
+
+       if (rtlpriv->mac80211.link_state == MAC80211_LINKED) {
+               if (type != NL80211_IFTYPE_AP)
+                       rtl92cu_set_check_bssid(hw, true);
+       } else {
+               rtl92cu_set_check_bssid(hw, false);
+       }
+
        return 0;
 }
 
@@ -2058,8 +2041,6 @@ void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw,
                               (shortgi_rate << 4) | (shortgi_rate);
        }
        rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value);
-       RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n",
-                rtl_read_dword(rtlpriv, REG_ARFR0));
 }
 
 void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
index 156b52732f3d576cb458bc3f6b3e2eb2818f2d90..5847d6d0881e7ce30180d26cc275425c55eda76b 100644 (file)
@@ -851,6 +851,7 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb,
        if (unlikely(!_urb)) {
                RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
                         "Can't allocate urb. Drop skb!\n");
+               kfree_skb(skb);
                return;
        }
        _rtl_submit_tx_urb(hw, _urb);
index eef38cfd812ea330c76d799bd93caae1b7a5c0d8..ca33ae193935bc3c3e75ffa809aa0573a5e24692 100644 (file)
@@ -22,7 +22,7 @@
 #include <linux/slab.h>
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
-#include <linux/mei_bus.h>
+#include <linux/mei_cl_bus.h>
 
 #include <linux/nfc.h>
 #include <net/nfc/hci.h>
@@ -32,9 +32,6 @@
 
 #define MICROREAD_DRIVER_NAME "microread"
 
-#define MICROREAD_UUID UUID_LE(0x0bb17a78, 0x2a8e, 0x4c50, 0x94, \
-                              0xd4, 0x50, 0x26, 0x67, 0x23, 0x77, 0x5c)
-
 struct mei_nfc_hdr {
        u8 cmd;
        u8 status;
@@ -48,7 +45,7 @@ struct mei_nfc_hdr {
 #define MEI_NFC_MAX_READ (MEI_NFC_HEADER_SIZE + MEI_NFC_MAX_HCI_PAYLOAD)
 
 struct microread_mei_phy {
-       struct mei_device *mei_device;
+       struct mei_cl_device *device;
        struct nfc_hci_dev *hdev;
 
        int powered;
@@ -105,14 +102,14 @@ static int microread_mei_write(void *phy_id, struct sk_buff *skb)
 
        MEI_DUMP_SKB_OUT("mei frame sent", skb);
 
-       r = mei_send(phy->device, skb->data, skb->len);
+       r = mei_cl_send(phy->device, skb->data, skb->len);
        if (r > 0)
                r = 0;
 
        return r;
 }
 
-static void microread_event_cb(struct mei_device *device, u32 events,
+static void microread_event_cb(struct mei_cl_device *device, u32 events,
                               void *context)
 {
        struct microread_mei_phy *phy = context;
@@ -120,7 +117,7 @@ static void microread_event_cb(struct mei_device *device, u32 events,
        if (phy->hard_fault != 0)
                return;
 
-       if (events & BIT(MEI_EVENT_RX)) {
+       if (events & BIT(MEI_CL_EVENT_RX)) {
                struct sk_buff *skb;
                int reply_size;
 
@@ -128,7 +125,7 @@ static void microread_event_cb(struct mei_device *device, u32 events,
                if (!skb)
                        return;
 
-               reply_size = mei_recv(device, skb->data, MEI_NFC_MAX_READ);
+               reply_size = mei_cl_recv(device, skb->data, MEI_NFC_MAX_READ);
                if (reply_size < MEI_NFC_HEADER_SIZE) {
                        kfree(skb);
                        return;
@@ -149,8 +146,8 @@ static struct nfc_phy_ops mei_phy_ops = {
        .disable = microread_mei_disable,
 };
 
-static int microread_mei_probe(struct mei_device *device,
-                              const struct mei_id *id)
+static int microread_mei_probe(struct mei_cl_device *device,
+                              const struct mei_cl_device_id *id)
 {
        struct microread_mei_phy *phy;
        int r;
@@ -164,9 +161,9 @@ static int microread_mei_probe(struct mei_device *device,
        }
 
        phy->device = device;
-       mei_set_clientdata(device, phy);
+       mei_cl_set_drvdata(device, phy);
 
-       r = mei_register_event_cb(device, microread_event_cb, phy);
+       r = mei_cl_register_event_cb(device, microread_event_cb, phy);
        if (r) {
                pr_err(MICROREAD_DRIVER_NAME ": event cb registration failed\n");
                goto err_out;
@@ -186,9 +183,9 @@ err_out:
        return r;
 }
 
-static int microread_mei_remove(struct mei_device *device)
+static int microread_mei_remove(struct mei_cl_device *device)
 {
-       struct microread_mei_phy *phy = mei_get_clientdata(device);
+       struct microread_mei_phy *phy = mei_cl_get_drvdata(device);
 
        pr_info("Removing microread\n");
 
@@ -202,16 +199,15 @@ static int microread_mei_remove(struct mei_device *device)
        return 0;
 }
 
-static struct mei_id microread_mei_tbl[] = {
-       { MICROREAD_DRIVER_NAME, MICROREAD_UUID },
+static struct mei_cl_device_id microread_mei_tbl[] = {
+       { MICROREAD_DRIVER_NAME },
 
        /* required last entry */
        { }
 };
-
 MODULE_DEVICE_TABLE(mei, microread_mei_tbl);
 
-static struct mei_driver microread_driver = {
+static struct mei_cl_driver microread_driver = {
        .id_table = microread_mei_tbl,
        .name = MICROREAD_DRIVER_NAME,
 
@@ -225,7 +221,7 @@ static int microread_mei_init(void)
 
        pr_debug(DRIVER_DESC ": %s\n", __func__);
 
-       r = mei_driver_register(&microread_driver);
+       r = mei_cl_driver_register(&microread_driver);
        if (r) {
                pr_err(MICROREAD_DRIVER_NAME ": driver registration failed\n");
                return r;
@@ -236,7 +232,7 @@ static int microread_mei_init(void)
 
 static void microread_mei_exit(void)
 {
-       mei_driver_unregister(&microread_driver);
+       mei_cl_driver_unregister(&microread_driver);
 }
 
 module_init(microread_mei_init);
index 321d3ef050065e12b2d639e02fada00ec6b9e658..c6443de58fb0f29fd093497639ff82cac4085e5a 100644 (file)
@@ -745,6 +745,64 @@ struct device_node *of_find_node_by_phandle(phandle handle)
 }
 EXPORT_SYMBOL(of_find_node_by_phandle);
 
+/**
+ * of_find_property_value_of_size
+ *
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ * @len:       requested length of property value
+ *
+ * Search for a property in a device node and valid the requested size.
+ * Returns the property value on success, -EINVAL if the property does not
+ *  exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ */
+static void *of_find_property_value_of_size(const struct device_node *np,
+                       const char *propname, u32 len)
+{
+       struct property *prop = of_find_property(np, propname, NULL);
+
+       if (!prop)
+               return ERR_PTR(-EINVAL);
+       if (!prop->value)
+               return ERR_PTR(-ENODATA);
+       if (len > prop->length)
+               return ERR_PTR(-EOVERFLOW);
+
+       return prop->value;
+}
+
+/**
+ * of_property_read_u32_index - Find and read a u32 from a multi-value property.
+ *
+ * @np:                device node from which the property value is to be read.
+ * @propname:  name of the property to be searched.
+ * @index:     index of the u32 in the list of values
+ * @out_value: pointer to return value, modified only if no error.
+ *
+ * Search for a property in a device node and read nth 32-bit value from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * The out_value is modified only if a valid u32 value can be decoded.
+ */
+int of_property_read_u32_index(const struct device_node *np,
+                                      const char *propname,
+                                      u32 index, u32 *out_value)
+{
+       const u32 *val = of_find_property_value_of_size(np, propname,
+                                       ((index + 1) * sizeof(*out_value)));
+
+       if (IS_ERR(val))
+               return PTR_ERR(val);
+
+       *out_value = be32_to_cpup(((__be32 *)val) + index);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u32_index);
+
 /**
  * of_property_read_u8_array - Find and read an array of u8 from a property.
  *
@@ -766,17 +824,12 @@ EXPORT_SYMBOL(of_find_node_by_phandle);
 int of_property_read_u8_array(const struct device_node *np,
                        const char *propname, u8 *out_values, size_t sz)
 {
-       struct property *prop = of_find_property(np, propname, NULL);
-       const u8 *val;
+       const u8 *val = of_find_property_value_of_size(np, propname,
+                                               (sz * sizeof(*out_values)));
 
-       if (!prop)
-               return -EINVAL;
-       if (!prop->value)
-               return -ENODATA;
-       if ((sz * sizeof(*out_values)) > prop->length)
-               return -EOVERFLOW;
+       if (IS_ERR(val))
+               return PTR_ERR(val);
 
-       val = prop->value;
        while (sz--)
                *out_values++ = *val++;
        return 0;
@@ -804,17 +857,12 @@ EXPORT_SYMBOL_GPL(of_property_read_u8_array);
 int of_property_read_u16_array(const struct device_node *np,
                        const char *propname, u16 *out_values, size_t sz)
 {
-       struct property *prop = of_find_property(np, propname, NULL);
-       const __be16 *val;
+       const __be16 *val = of_find_property_value_of_size(np, propname,
+                                               (sz * sizeof(*out_values)));
 
-       if (!prop)
-               return -EINVAL;
-       if (!prop->value)
-               return -ENODATA;
-       if ((sz * sizeof(*out_values)) > prop->length)
-               return -EOVERFLOW;
+       if (IS_ERR(val))
+               return PTR_ERR(val);
 
-       val = prop->value;
        while (sz--)
                *out_values++ = be16_to_cpup(val++);
        return 0;
@@ -841,17 +889,12 @@ int of_property_read_u32_array(const struct device_node *np,
                               const char *propname, u32 *out_values,
                               size_t sz)
 {
-       struct property *prop = of_find_property(np, propname, NULL);
-       const __be32 *val;
+       const __be32 *val = of_find_property_value_of_size(np, propname,
+                                               (sz * sizeof(*out_values)));
 
-       if (!prop)
-               return -EINVAL;
-       if (!prop->value)
-               return -ENODATA;
-       if ((sz * sizeof(*out_values)) > prop->length)
-               return -EOVERFLOW;
+       if (IS_ERR(val))
+               return PTR_ERR(val);
 
-       val = prop->value;
        while (sz--)
                *out_values++ = be32_to_cpup(val++);
        return 0;
@@ -874,15 +917,13 @@ EXPORT_SYMBOL_GPL(of_property_read_u32_array);
 int of_property_read_u64(const struct device_node *np, const char *propname,
                         u64 *out_value)
 {
-       struct property *prop = of_find_property(np, propname, NULL);
+       const __be32 *val = of_find_property_value_of_size(np, propname,
+                                               sizeof(*out_value));
 
-       if (!prop)
-               return -EINVAL;
-       if (!prop->value)
-               return -ENODATA;
-       if (sizeof(*out_value) > prop->length)
-               return -EOVERFLOW;
-       *out_value = of_read_number(prop->value, 2);
+       if (IS_ERR(val))
+               return PTR_ERR(val);
+
+       *out_value = of_read_number(val, 2);
        return 0;
 }
 EXPORT_SYMBOL_GPL(of_property_read_u64);
index dee5dddaa292a04ad2200c005ad59b959ed5ad7e..5147c210df52999c5ebe9d00e08b357c24dfd4c6 100644 (file)
@@ -53,14 +53,15 @@ static void pci_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
                return;
        }
 
-       if (!pci_dev->pm_cap || !pci_dev->pme_support
-            || pci_check_pme_status(pci_dev)) {
-               if (pci_dev->pme_poll)
-                       pci_dev->pme_poll = false;
+       /* Clear PME Status if set. */
+       if (pci_dev->pme_support)
+               pci_check_pme_status(pci_dev);
 
-               pci_wakeup_event(pci_dev);
-               pm_runtime_resume(&pci_dev->dev);
-       }
+       if (pci_dev->pme_poll)
+               pci_dev->pme_poll = false;
+
+       pci_wakeup_event(pci_dev);
+       pm_runtime_resume(&pci_dev->dev);
 
        if (pci_dev->subordinate)
                pci_pme_wakeup_bus(pci_dev->subordinate);
index 1fa1e482a99976d36d8e91b2affee58af3bda693..79277fb36c6bf7a85b4634df28ff13d1905d703d 100644 (file)
@@ -390,9 +390,10 @@ static void pci_device_shutdown(struct device *dev)
 
        /*
         * Turn off Bus Master bit on the device to tell it to not
-        * continue to do DMA
+        * continue to do DMA. Don't touch devices in D3cold or unknown states.
         */
-       pci_clear_master(pci_dev);
+       if (pci_dev->current_state <= PCI_D3hot)
+               pci_clear_master(pci_dev);
 }
 
 #ifdef CONFIG_PM
index 08c243ab034e9bc9172dfd593f4cb0ceabbe2f60..ed4d0949833796869f9d7713909e0323a611609a 100644 (file)
@@ -184,14 +184,6 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
 #define PCIE_PORTDRV_PM_OPS    NULL
 #endif /* !PM */
 
-/*
- * PCIe port runtime suspend is broken for some chipsets, so use a
- * black list to disable runtime PM for these chipsets.
- */
-static const struct pci_device_id port_runtime_pm_black_list[] = {
-       { /* end: all zeroes */ }
-};
-
 /*
  * pcie_portdrv_probe - Probe PCI-Express port devices
  * @dev: PCI-Express port device being probed
@@ -225,16 +217,11 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
         * it by default.
         */
        dev->d3cold_allowed = false;
-       if (!pci_match_id(port_runtime_pm_black_list, dev))
-               pm_runtime_put_noidle(&dev->dev);
-
        return 0;
 }
 
 static void pcie_portdrv_remove(struct pci_dev *dev)
 {
-       if (!pci_match_id(port_runtime_pm_black_list, dev))
-               pm_runtime_get_noresume(&dev->dev);
        pcie_port_device_remove(dev);
        pci_disable_device(dev);
 }
index ab886b7ee327af413f98976382869242fcba679b..c5d0a08a87473a24dc43dacb8081abf7c737b852 100644 (file)
@@ -117,18 +117,12 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size)
        loff_t start;
        void __iomem *rom;
 
-       /*
-        * Some devices may provide ROMs via a source other than the BAR
-        */
-       if (pdev->rom && pdev->romlen) {
-               *size = pdev->romlen;
-               return phys_to_virt(pdev->rom);
        /*
         * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy
         * memory map if the VGA enable bit of the Bridge Control register is
         * set for embedded VGA.
         */
-       } else if (res->flags & IORESOURCE_ROM_SHADOW) {
+       if (res->flags & IORESOURCE_ROM_SHADOW) {
                /* primary video rom always starts here */
                start = (loff_t)0xC0000;
                *size = 0x20000; /* cover C000:0 through E000:0 */
@@ -187,8 +181,7 @@ void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom)
        if (res->flags & (IORESOURCE_ROM_COPY | IORESOURCE_ROM_BIOS_COPY))
                return;
 
-       if (!pdev->rom || !pdev->romlen)
-               iounmap(rom);
+       iounmap(rom);
 
        /* Disable again before continuing, leave enabled if pci=rom */
        if (!(res->flags & (IORESOURCE_ROM_ENABLE | IORESOURCE_ROM_SHADOW)))
@@ -212,7 +205,24 @@ void pci_cleanup_rom(struct pci_dev *pdev)
        }
 }
 
+/**
+ * pci_platform_rom - provides a pointer to any ROM image provided by the
+ * platform
+ * @pdev: pointer to pci device struct
+ * @size: pointer to receive size of pci window over ROM
+ */
+void __iomem *pci_platform_rom(struct pci_dev *pdev, size_t *size)
+{
+       if (pdev->rom && pdev->romlen) {
+               *size = pdev->romlen;
+               return phys_to_virt((phys_addr_t)pdev->rom);
+       }
+
+       return NULL;
+}
+
 EXPORT_SYMBOL(pci_map_rom);
 EXPORT_SYMBOL(pci_unmap_rom);
 EXPORT_SYMBOL_GPL(pci_enable_rom);
 EXPORT_SYMBOL_GPL(pci_disable_rom);
+EXPORT_SYMBOL(pci_platform_rom);
index 34f51d2d90d2ed118a4aa0682a062d2d86a4ecb9..35e94009829bf6eb2a4a444e624cae10362fde7c 100644 (file)
@@ -229,6 +229,7 @@ config PINCTRL_EXYNOS5440
 source "drivers/pinctrl/mvebu/Kconfig"
 source "drivers/pinctrl/sh-pfc/Kconfig"
 source "drivers/pinctrl/spear/Kconfig"
+source "drivers/pinctrl/vt8500/Kconfig"
 
 config PINCTRL_XWAY
        bool
index f82cc5baf767829aac92d7f16efc7fa14f9d3122..a5a52c83c13a42eeb70d52cc9598586ad23d02c6 100644 (file)
@@ -52,3 +52,4 @@ obj-$(CONFIG_PLAT_ORION)        += mvebu/
 obj-$(CONFIG_ARCH_SHMOBILE)    += sh-pfc/
 obj-$(CONFIG_SUPERH)           += sh-pfc/
 obj-$(CONFIG_PLAT_SPEAR)       += spear/
+obj-$(CONFIG_ARCH_VT8500)      += vt8500/
index c689c04a4f523248e9b2712e77d7e041f5b074d7..2d2f0a43d36b409cf287f6d6629b506e517948a9 100644 (file)
@@ -620,7 +620,7 @@ int mvebu_pinctrl_probe(struct platform_device *pdev)
 
                /* special soc specific control */
                if (ctrl->mpp_get || ctrl->mpp_set) {
-                       if (!ctrl->name || !ctrl->mpp_set || !ctrl->mpp_set) {
+                       if (!ctrl->name || !ctrl->mpp_get || !ctrl->mpp_set) {
                                dev_err(&pdev->dev, "wrong soc control info\n");
                                return -EINVAL;
                        }
index ac8d382a79bbfe43de8769ea43d1c13ab2fac036..d611ecfcbf70d8401946767f01833069ef60c431 100644 (file)
@@ -622,7 +622,7 @@ static const struct file_operations pinconf_dbg_pinname_fops = {
 static int pinconf_dbg_state_print(struct seq_file *s, void *d)
 {
        if (strlen(dbg_state_name))
-               seq_printf(s, "%s\n", dbg_pinname);
+               seq_printf(s, "%s\n", dbg_state_name);
        else
                seq_printf(s, "No pin state set\n");
        return 0;
index e3ed8cb072a5a4dd410015c66e3202ded90dd49c..bfda73d64eed527b2fce7e0a084b7459943bfb1e 100644 (file)
@@ -90,7 +90,7 @@ static inline void pinconf_init_device_debugfs(struct dentry *devroot,
  * pin config.
  */
 
-#ifdef CONFIG_GENERIC_PINCONF
+#if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_DEBUG_FS)
 
 void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev,
                              struct seq_file *s, unsigned pin);
index caecdd37306126d7352b57365932b00b5e7ac1f2..c542a97c82f37cc743fa9d97e914c13dfe55aaa7 100644 (file)
@@ -422,7 +422,7 @@ static u8 abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip,
        }
 
        /* check if pin use AlternateFunction register */
-       if ((af.alt_bit1 == UNUSED) && (af.alt_bit1 == UNUSED))
+       if ((af.alt_bit1 == UNUSED) && (af.alt_bit2 == UNUSED))
                return mode;
        /*
         * if pin GPIOSEL bit is set and pin supports alternate function,
index 75933a6aa8284c0cbf466a968ed2c846c7c14d69..efb7f10e902a0e1aa9701ed5506a23d204b1a9df 100644 (file)
@@ -1277,21 +1277,80 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type)
 }
 
 #ifdef CONFIG_PM
+
+static u32 wakeups[MAX_GPIO_BANKS];
+static u32 backups[MAX_GPIO_BANKS];
+
 static int gpio_irq_set_wake(struct irq_data *d, unsigned state)
 {
        struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d);
        unsigned        bank = at91_gpio->pioc_idx;
+       unsigned mask = 1 << d->hwirq;
 
        if (unlikely(bank >= MAX_GPIO_BANKS))
                return -EINVAL;
 
+       if (state)
+               wakeups[bank] |= mask;
+       else
+               wakeups[bank] &= ~mask;
+
        irq_set_irq_wake(at91_gpio->pioc_virq, state);
 
        return 0;
 }
+
+void at91_pinctrl_gpio_suspend(void)
+{
+       int i;
+
+       for (i = 0; i < gpio_banks; i++) {
+               void __iomem  *pio;
+
+               if (!gpio_chips[i])
+                       continue;
+
+               pio = gpio_chips[i]->regbase;
+
+               backups[i] = __raw_readl(pio + PIO_IMR);
+               __raw_writel(backups[i], pio + PIO_IDR);
+               __raw_writel(wakeups[i], pio + PIO_IER);
+
+               if (!wakeups[i]) {
+                       clk_unprepare(gpio_chips[i]->clock);
+                       clk_disable(gpio_chips[i]->clock);
+               } else {
+                       printk(KERN_DEBUG "GPIO-%c may wake for %08x\n",
+                              'A'+i, wakeups[i]);
+               }
+       }
+}
+
+void at91_pinctrl_gpio_resume(void)
+{
+       int i;
+
+       for (i = 0; i < gpio_banks; i++) {
+               void __iomem  *pio;
+
+               if (!gpio_chips[i])
+                       continue;
+
+               pio = gpio_chips[i]->regbase;
+
+               if (!wakeups[i]) {
+                       if (clk_prepare(gpio_chips[i]->clock) == 0)
+                               clk_enable(gpio_chips[i]->clock);
+               }
+
+               __raw_writel(wakeups[i], pio + PIO_IDR);
+               __raw_writel(backups[i], pio + PIO_IER);
+       }
+}
+
 #else
 #define gpio_irq_set_wake      NULL
-#endif
+#endif /* CONFIG_PM */
 
 static struct irq_chip gpio_irqchip = {
        .name           = "GPIO",
index 4eb6d2c4e4df80c3222415ff7463b4db67b730ab..2a2e427d765ee7b35b0635959d58dcdb3a28f0e5 100644 (file)
@@ -699,11 +699,6 @@ static int bcm2835_pctl_dt_node_to_map_pull(struct bcm2835_pinctrl *pc,
        return 0;
 }
 
-static inline u32 prop_u32(struct property *p, int i)
-{
-       return be32_to_cpup(((__be32 *)p->value) + i);
-}
-
 static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
                struct device_node *np,
                struct pinctrl_map **map, unsigned *num_maps)
@@ -761,7 +756,9 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
                return -ENOMEM;
 
        for (i = 0; i < num_pins; i++) {
-               pin = prop_u32(pins, i);
+               err = of_property_read_u32_index(np, "brcm,pins", i, &pin);
+               if (err)
+                       goto out;
                if (pin >= ARRAY_SIZE(bcm2835_gpio_pins)) {
                        dev_err(pc->dev, "%s: invalid brcm,pins value %d\n",
                                of_node_full_name(np), pin);
@@ -770,14 +767,20 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
                }
 
                if (num_funcs) {
-                       func = prop_u32(funcs, (num_funcs > 1) ? i : 0);
+                       err = of_property_read_u32_index(np, "brcm,function",
+                                       (num_funcs > 1) ? i : 0, &func);
+                       if (err)
+                               goto out;
                        err = bcm2835_pctl_dt_node_to_map_func(pc, np, pin,
                                                        func, &cur_map);
                        if (err)
                                goto out;
                }
                if (num_pulls) {
-                       pull = prop_u32(pulls, (num_pulls > 1) ? i : 0);
+                       err = of_property_read_u32_index(np, "brcm,pull",
+                                       (num_funcs > 1) ? i : 0, &pull);
+                       if (err)
+                               goto out;
                        err = bcm2835_pctl_dt_node_to_map_pull(pc, np, pin,
                                                        pull, &cur_map);
                        if (err)
index 538b9ddaadf7e63783e6d8e1349377224f576399..8738933a57d73c9ffc9193a83c3a375ae34151e2 100644 (file)
@@ -677,3 +677,111 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = {
                .label          = "exynos4x12-gpio-ctrl3",
        },
 };
+
+/* pin banks of exynos5250 pin-controller 0 */
+static struct samsung_pin_bank exynos5250_pin_banks0[] = {
+       EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00),
+       EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04),
+       EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08),
+       EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpb0", 0x0c),
+       EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpb1", 0x10),
+       EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpb2", 0x14),
+       EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpb3", 0x18),
+       EXYNOS_PIN_BANK_EINTG(7, 0x0E0, "gpc0", 0x1c),
+       EXYNOS_PIN_BANK_EINTG(4, 0x100, "gpc1", 0x20),
+       EXYNOS_PIN_BANK_EINTG(7, 0x120, "gpc2", 0x24),
+       EXYNOS_PIN_BANK_EINTG(7, 0x140, "gpc3", 0x28),
+       EXYNOS_PIN_BANK_EINTG(4, 0x160, "gpd0", 0x2c),
+       EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpd1", 0x30),
+       EXYNOS_PIN_BANK_EINTG(7, 0x2E0, "gpc4", 0x34),
+       EXYNOS_PIN_BANK_EINTN(6, 0x1A0, "gpy0"),
+       EXYNOS_PIN_BANK_EINTN(4, 0x1C0, "gpy1"),
+       EXYNOS_PIN_BANK_EINTN(6, 0x1E0, "gpy2"),
+       EXYNOS_PIN_BANK_EINTN(8, 0x200, "gpy3"),
+       EXYNOS_PIN_BANK_EINTN(8, 0x220, "gpy4"),
+       EXYNOS_PIN_BANK_EINTN(8, 0x240, "gpy5"),
+       EXYNOS_PIN_BANK_EINTN(8, 0x260, "gpy6"),
+       EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00),
+       EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04),
+       EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08),
+       EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c),
+};
+
+/* pin banks of exynos5250 pin-controller 1 */
+static struct samsung_pin_bank exynos5250_pin_banks1[] = {
+       EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpe0", 0x00),
+       EXYNOS_PIN_BANK_EINTG(2, 0x020, "gpe1", 0x04),
+       EXYNOS_PIN_BANK_EINTG(4, 0x040, "gpf0", 0x08),
+       EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpf1", 0x0c),
+       EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpg0", 0x10),
+       EXYNOS_PIN_BANK_EINTG(8, 0x0A0, "gpg1", 0x14),
+       EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpg2", 0x18),
+       EXYNOS_PIN_BANK_EINTG(4, 0x0E0, "gph0", 0x1c),
+       EXYNOS_PIN_BANK_EINTG(8, 0x100, "gph1", 0x20),
+};
+
+/* pin banks of exynos5250 pin-controller 2 */
+static struct samsung_pin_bank exynos5250_pin_banks2[] = {
+       EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00),
+       EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04),
+       EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv2", 0x08),
+       EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpv3", 0x0c),
+       EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpv4", 0x10),
+};
+
+/* pin banks of exynos5250 pin-controller 3 */
+static struct samsung_pin_bank exynos5250_pin_banks3[] = {
+       EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00),
+};
+
+/*
+ * Samsung pinctrl driver data for Exynos5250 SoC. Exynos5250 SoC includes
+ * four gpio/pin-mux/pinconfig controllers.
+ */
+struct samsung_pin_ctrl exynos5250_pin_ctrl[] = {
+       {
+               /* pin-controller instance 0 data */
+               .pin_banks      = exynos5250_pin_banks0,
+               .nr_banks       = ARRAY_SIZE(exynos5250_pin_banks0),
+               .geint_con      = EXYNOS_GPIO_ECON_OFFSET,
+               .geint_mask     = EXYNOS_GPIO_EMASK_OFFSET,
+               .geint_pend     = EXYNOS_GPIO_EPEND_OFFSET,
+               .weint_con      = EXYNOS_WKUP_ECON_OFFSET,
+               .weint_mask     = EXYNOS_WKUP_EMASK_OFFSET,
+               .weint_pend     = EXYNOS_WKUP_EPEND_OFFSET,
+               .svc            = EXYNOS_SVC_OFFSET,
+               .eint_gpio_init = exynos_eint_gpio_init,
+               .eint_wkup_init = exynos_eint_wkup_init,
+               .label          = "exynos5250-gpio-ctrl0",
+       }, {
+               /* pin-controller instance 1 data */
+               .pin_banks      = exynos5250_pin_banks1,
+               .nr_banks       = ARRAY_SIZE(exynos5250_pin_banks1),
+               .geint_con      = EXYNOS_GPIO_ECON_OFFSET,
+               .geint_mask     = EXYNOS_GPIO_EMASK_OFFSET,
+               .geint_pend     = EXYNOS_GPIO_EPEND_OFFSET,
+               .svc            = EXYNOS_SVC_OFFSET,
+               .eint_gpio_init = exynos_eint_gpio_init,
+               .label          = "exynos5250-gpio-ctrl1",
+       }, {
+               /* pin-controller instance 2 data */
+               .pin_banks      = exynos5250_pin_banks2,
+               .nr_banks       = ARRAY_SIZE(exynos5250_pin_banks2),
+               .geint_con      = EXYNOS_GPIO_ECON_OFFSET,
+               .geint_mask     = EXYNOS_GPIO_EMASK_OFFSET,
+               .geint_pend     = EXYNOS_GPIO_EPEND_OFFSET,
+               .svc            = EXYNOS_SVC_OFFSET,
+               .eint_gpio_init = exynos_eint_gpio_init,
+               .label          = "exynos5250-gpio-ctrl2",
+       }, {
+               /* pin-controller instance 3 data */
+               .pin_banks      = exynos5250_pin_banks3,
+               .nr_banks       = ARRAY_SIZE(exynos5250_pin_banks3),
+               .geint_con      = EXYNOS_GPIO_ECON_OFFSET,
+               .geint_mask     = EXYNOS_GPIO_EMASK_OFFSET,
+               .geint_pend     = EXYNOS_GPIO_EPEND_OFFSET,
+               .svc            = EXYNOS_SVC_OFFSET,
+               .eint_gpio_init = exynos_eint_gpio_init,
+               .label          = "exynos5250-gpio-ctrl3",
+       },
+};
index f206df1756568b2e0727ac06ac65ae07d5a83b0e..3d5cf639aa46c91f288e9cade71d9230023b01e1 100644 (file)
@@ -948,6 +948,8 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = {
                .data = (void *)exynos4210_pin_ctrl },
        { .compatible = "samsung,exynos4x12-pinctrl",
                .data = (void *)exynos4x12_pin_ctrl },
+       { .compatible = "samsung,exynos5250-pinctrl",
+               .data = (void *)exynos5250_pin_ctrl },
        {},
 };
 MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match);
index e2d4e67f7e882c5314d7bfc82235be586c48a438..ee964aadce0c3390d4a774771a66cf83ed9ab50a 100644 (file)
@@ -237,5 +237,6 @@ struct samsung_pmx_func {
 /* list of all exported SoC specific data */
 extern struct samsung_pin_ctrl exynos4210_pin_ctrl[];
 extern struct samsung_pin_ctrl exynos4x12_pin_ctrl[];
+extern struct samsung_pin_ctrl exynos5250_pin_ctrl[];
 
 #endif /* __PINCTRL_SAMSUNG_H */
index 1a00658b3ea070f336333160411f1b01bbc8f96e..bd83c8b01cd102e7c0f194c38389bb4a083c5dec 100644 (file)
@@ -194,6 +194,11 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin,
        }
 
        if (!gpio_range) {
+               /*
+                * A pin should not be freed more times than allocated.
+                */
+               if (WARN_ON(!desc->mux_usecount))
+                       return NULL;
                desc->mux_usecount--;
                if (desc->mux_usecount)
                        return NULL;
index 709008e941244dc022cb5804157cede7ac9ef0b7..6f15c03077a0f286f8b674b9341412544b0c11dc 100644 (file)
@@ -2733,9 +2733,9 @@ static struct pinmux_data_reg pinmux_data_regs[] = {
        { },
 };
 
-/* IRQ pins through INTCS with IRQ0->15 from 0x200 and IRQ16-31 from 0x3200 */
-#define EXT_IRQ16L(n) intcs_evt2irq(0x200 + ((n) << 5))
-#define EXT_IRQ16H(n) intcs_evt2irq(0x3200 + ((n - 16) << 5))
+/* External IRQ pins mapped at IRQPIN_BASE */
+#define EXT_IRQ16L(n) irq_pin(n)
+#define EXT_IRQ16H(n) irq_pin(n)
 
 static struct pinmux_irq pinmux_irqs[] = {
        PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0),
diff --git a/drivers/pinctrl/vt8500/Kconfig b/drivers/pinctrl/vt8500/Kconfig
new file mode 100644 (file)
index 0000000..55724a7
--- /dev/null
@@ -0,0 +1,52 @@
+#
+# VIA/Wondermedia PINCTRL drivers
+#
+
+if ARCH_VT8500
+
+config PINCTRL_WMT
+       bool
+       select PINMUX
+       select GENERIC_PINCONF
+
+config PINCTRL_VT8500
+       bool "VIA VT8500 pin controller driver"
+       depends on ARCH_WM8505
+       select PINCTRL_WMT
+       help
+         Say yes here to support the gpio/pin control module on
+         VIA VT8500 SoCs.
+
+config PINCTRL_WM8505
+       bool "Wondermedia WM8505 pin controller driver"
+       depends on ARCH_WM8505
+       select PINCTRL_WMT
+       help
+         Say yes here to support the gpio/pin control module on
+         Wondermedia WM8505 SoCs.
+
+config PINCTRL_WM8650
+       bool "Wondermedia WM8650 pin controller driver"
+       depends on ARCH_WM8505
+       select PINCTRL_WMT
+       help
+         Say yes here to support the gpio/pin control module on
+         Wondermedia WM8650 SoCs.
+
+config PINCTRL_WM8750
+       bool "Wondermedia WM8750 pin controller driver"
+       depends on ARCH_WM8750
+       select PINCTRL_WMT
+       help
+         Say yes here to support the gpio/pin control module on
+         Wondermedia WM8750 SoCs.
+
+config PINCTRL_WM8850
+       bool "Wondermedia WM8850 pin controller driver"
+       depends on ARCH_WM8850
+       select PINCTRL_WMT
+       help
+         Say yes here to support the gpio/pin control module on
+         Wondermedia WM8850 SoCs.
+
+endif
diff --git a/drivers/pinctrl/vt8500/Makefile b/drivers/pinctrl/vt8500/Makefile
new file mode 100644 (file)
index 0000000..24ec45d
--- /dev/null
@@ -0,0 +1,8 @@
+# VIA/Wondermedia pinctrl support
+
+obj-$(CONFIG_PINCTRL_WMT)      += pinctrl-wmt.o
+obj-$(CONFIG_PINCTRL_VT8500)   += pinctrl-vt8500.o
+obj-$(CONFIG_PINCTRL_WM8505)   += pinctrl-wm8505.o
+obj-$(CONFIG_PINCTRL_WM8650)   += pinctrl-wm8650.o
+obj-$(CONFIG_PINCTRL_WM8750)   += pinctrl-wm8750.o
+obj-$(CONFIG_PINCTRL_WM8850)   += pinctrl-wm8850.o
diff --git a/drivers/pinctrl/vt8500/pinctrl-vt8500.c b/drivers/pinctrl/vt8500/pinctrl-vt8500.c
new file mode 100644 (file)
index 0000000..f2fe9f8
--- /dev/null
@@ -0,0 +1,501 @@
+/*
+ * Pinctrl data for VIA VT8500 SoC
+ *
+ * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "pinctrl-wmt.h"
+
+/*
+ * Describe the register offsets within the GPIO memory space
+ * The dedicated external GPIO's should always be listed in bank 0
+ * so they are exported in the 0..31 range which is what users
+ * expect.
+ *
+ * Do not reorder these banks as it will change the pin numbering
+ */
+static const struct wmt_pinctrl_bank_registers vt8500_banks[] = {
+       WMT_PINCTRL_BANK(NO_REG, 0x3C, 0x5C, 0x7C, NO_REG, NO_REG),     /* 0 */
+       WMT_PINCTRL_BANK(0x00, 0x20, 0x40, 0x60, NO_REG, NO_REG),       /* 1 */
+       WMT_PINCTRL_BANK(0x04, 0x24, 0x44, 0x64, NO_REG, NO_REG),       /* 2 */
+       WMT_PINCTRL_BANK(0x08, 0x28, 0x48, 0x68, NO_REG, NO_REG),       /* 3 */
+       WMT_PINCTRL_BANK(0x0C, 0x2C, 0x4C, 0x6C, NO_REG, NO_REG),       /* 4 */
+       WMT_PINCTRL_BANK(0x10, 0x30, 0x50, 0x70, NO_REG, NO_REG),       /* 5 */
+       WMT_PINCTRL_BANK(0x14, 0x34, 0x54, 0x74, NO_REG, NO_REG),       /* 6 */
+};
+
+/* Please keep sorted by bank/bit */
+#define WMT_PIN_EXTGPIO0       WMT_PIN(0, 0)
+#define WMT_PIN_EXTGPIO1       WMT_PIN(0, 1)
+#define WMT_PIN_EXTGPIO2       WMT_PIN(0, 2)
+#define WMT_PIN_EXTGPIO3       WMT_PIN(0, 3)
+#define WMT_PIN_EXTGPIO4       WMT_PIN(0, 4)
+#define WMT_PIN_EXTGPIO5       WMT_PIN(0, 5)
+#define WMT_PIN_EXTGPIO6       WMT_PIN(0, 6)
+#define WMT_PIN_EXTGPIO7       WMT_PIN(0, 7)
+#define WMT_PIN_EXTGPIO8       WMT_PIN(0, 8)
+#define WMT_PIN_UART0RTS       WMT_PIN(1, 0)
+#define WMT_PIN_UART0TXD       WMT_PIN(1, 1)
+#define WMT_PIN_UART0CTS       WMT_PIN(1, 2)
+#define WMT_PIN_UART0RXD       WMT_PIN(1, 3)
+#define WMT_PIN_UART1RTS       WMT_PIN(1, 4)
+#define WMT_PIN_UART1TXD       WMT_PIN(1, 5)
+#define WMT_PIN_UART1CTS       WMT_PIN(1, 6)
+#define WMT_PIN_UART1RXD       WMT_PIN(1, 7)
+#define WMT_PIN_SPI0CLK                WMT_PIN(1, 8)
+#define WMT_PIN_SPI0SS         WMT_PIN(1, 9)
+#define WMT_PIN_SPI0MISO       WMT_PIN(1, 10)
+#define WMT_PIN_SPI0MOSI       WMT_PIN(1, 11)
+#define WMT_PIN_SPI1CLK                WMT_PIN(1, 12)
+#define WMT_PIN_SPI1SS         WMT_PIN(1, 13)
+#define WMT_PIN_SPI1MISO       WMT_PIN(1, 14)
+#define WMT_PIN_SPI1MOSI       WMT_PIN(1, 15)
+#define WMT_PIN_SPI2CLK                WMT_PIN(1, 16)
+#define WMT_PIN_SPI2SS         WMT_PIN(1, 17)
+#define WMT_PIN_SPI2MISO       WMT_PIN(1, 18)
+#define WMT_PIN_SPI2MOSI       WMT_PIN(1, 19)
+#define WMT_PIN_SDDATA0                WMT_PIN(2, 0)
+#define WMT_PIN_SDDATA1                WMT_PIN(2, 1)
+#define WMT_PIN_SDDATA2                WMT_PIN(2, 2)
+#define WMT_PIN_SDDATA3                WMT_PIN(2, 3)
+#define WMT_PIN_MMCDATA0       WMT_PIN(2, 4)
+#define WMT_PIN_MMCDATA1       WMT_PIN(2, 5)
+#define WMT_PIN_MMCDATA2       WMT_PIN(2, 6)
+#define WMT_PIN_MMCDATA3       WMT_PIN(2, 7)
+#define WMT_PIN_SDCLK          WMT_PIN(2, 8)
+#define WMT_PIN_SDWP           WMT_PIN(2, 9)
+#define WMT_PIN_SDCMD          WMT_PIN(2, 10)
+#define WMT_PIN_MSDATA0                WMT_PIN(2, 16)
+#define WMT_PIN_MSDATA1                WMT_PIN(2, 17)
+#define WMT_PIN_MSDATA2                WMT_PIN(2, 18)
+#define WMT_PIN_MSDATA3                WMT_PIN(2, 19)
+#define WMT_PIN_MSCLK          WMT_PIN(2, 20)
+#define WMT_PIN_MSBS           WMT_PIN(2, 21)
+#define WMT_PIN_MSINS          WMT_PIN(2, 22)
+#define WMT_PIN_I2C0SCL                WMT_PIN(2, 24)
+#define WMT_PIN_I2C0SDA                WMT_PIN(2, 25)
+#define WMT_PIN_I2C1SCL                WMT_PIN(2, 26)
+#define WMT_PIN_I2C1SDA                WMT_PIN(2, 27)
+#define WMT_PIN_MII0RXD0       WMT_PIN(3, 0)
+#define WMT_PIN_MII0RXD1       WMT_PIN(3, 1)
+#define WMT_PIN_MII0RXD2       WMT_PIN(3, 2)
+#define WMT_PIN_MII0RXD3       WMT_PIN(3, 3)
+#define WMT_PIN_MII0RXCLK      WMT_PIN(3, 4)
+#define WMT_PIN_MII0RXDV       WMT_PIN(3, 5)
+#define WMT_PIN_MII0RXERR      WMT_PIN(3, 6)
+#define WMT_PIN_MII0PHYRST     WMT_PIN(3, 7)
+#define WMT_PIN_MII0TXD0       WMT_PIN(3, 8)
+#define WMT_PIN_MII0TXD1       WMT_PIN(3, 9)
+#define WMT_PIN_MII0TXD2       WMT_PIN(3, 10)
+#define WMT_PIN_MII0TXD3       WMT_PIN(3, 11)
+#define WMT_PIN_MII0TXCLK      WMT_PIN(3, 12)
+#define WMT_PIN_MII0TXEN       WMT_PIN(3, 13)
+#define WMT_PIN_MII0TXERR      WMT_PIN(3, 14)
+#define WMT_PIN_MII0PHYPD      WMT_PIN(3, 15)
+#define WMT_PIN_MII0COL                WMT_PIN(3, 16)
+#define WMT_PIN_MII0CRS                WMT_PIN(3, 17)
+#define WMT_PIN_MII0MDIO       WMT_PIN(3, 18)
+#define WMT_PIN_MII0MDC                WMT_PIN(3, 19)
+#define WMT_PIN_SEECS          WMT_PIN(3, 20)
+#define WMT_PIN_SEECK          WMT_PIN(3, 21)
+#define WMT_PIN_SEEDI          WMT_PIN(3, 22)
+#define WMT_PIN_SEEDO          WMT_PIN(3, 23)
+#define WMT_PIN_IDEDREQ0       WMT_PIN(3, 24)
+#define WMT_PIN_IDEDREQ1       WMT_PIN(3, 25)
+#define WMT_PIN_IDEIOW         WMT_PIN(3, 26)
+#define WMT_PIN_IDEIOR         WMT_PIN(3, 27)
+#define WMT_PIN_IDEDACK                WMT_PIN(3, 28)
+#define WMT_PIN_IDEIORDY       WMT_PIN(3, 29)
+#define WMT_PIN_IDEINTRQ       WMT_PIN(3, 30)
+#define WMT_PIN_VDIN0          WMT_PIN(4, 0)
+#define WMT_PIN_VDIN1          WMT_PIN(4, 1)
+#define WMT_PIN_VDIN2          WMT_PIN(4, 2)
+#define WMT_PIN_VDIN3          WMT_PIN(4, 3)
+#define WMT_PIN_VDIN4          WMT_PIN(4, 4)
+#define WMT_PIN_VDIN5          WMT_PIN(4, 5)
+#define WMT_PIN_VDIN6          WMT_PIN(4, 6)
+#define WMT_PIN_VDIN7          WMT_PIN(4, 7)
+#define WMT_PIN_VDOUT0         WMT_PIN(4, 8)
+#define WMT_PIN_VDOUT1         WMT_PIN(4, 9)
+#define WMT_PIN_VDOUT2         WMT_PIN(4, 10)
+#define WMT_PIN_VDOUT3         WMT_PIN(4, 11)
+#define WMT_PIN_VDOUT4         WMT_PIN(4, 12)
+#define WMT_PIN_VDOUT5         WMT_PIN(4, 13)
+#define WMT_PIN_NANDCLE0       WMT_PIN(4, 14)
+#define WMT_PIN_NANDCLE1       WMT_PIN(4, 15)
+#define WMT_PIN_VDOUT6_7       WMT_PIN(4, 16)
+#define WMT_PIN_VHSYNC         WMT_PIN(4, 17)
+#define WMT_PIN_VVSYNC         WMT_PIN(4, 18)
+#define WMT_PIN_TSDIN0         WMT_PIN(5, 8)
+#define WMT_PIN_TSDIN1         WMT_PIN(5, 9)
+#define WMT_PIN_TSDIN2         WMT_PIN(5, 10)
+#define WMT_PIN_TSDIN3         WMT_PIN(5, 11)
+#define WMT_PIN_TSDIN4         WMT_PIN(5, 12)
+#define WMT_PIN_TSDIN5         WMT_PIN(5, 13)
+#define WMT_PIN_TSDIN6         WMT_PIN(5, 14)
+#define WMT_PIN_TSDIN7         WMT_PIN(5, 15)
+#define WMT_PIN_TSSYNC         WMT_PIN(5, 16)
+#define WMT_PIN_TSVALID                WMT_PIN(5, 17)
+#define WMT_PIN_TSCLK          WMT_PIN(5, 18)
+#define WMT_PIN_LCDD0          WMT_PIN(6, 0)
+#define WMT_PIN_LCDD1          WMT_PIN(6, 1)
+#define WMT_PIN_LCDD2          WMT_PIN(6, 2)
+#define WMT_PIN_LCDD3          WMT_PIN(6, 3)
+#define WMT_PIN_LCDD4          WMT_PIN(6, 4)
+#define WMT_PIN_LCDD5          WMT_PIN(6, 5)
+#define WMT_PIN_LCDD6          WMT_PIN(6, 6)
+#define WMT_PIN_LCDD7          WMT_PIN(6, 7)
+#define WMT_PIN_LCDD8          WMT_PIN(6, 8)
+#define WMT_PIN_LCDD9          WMT_PIN(6, 9)
+#define WMT_PIN_LCDD10         WMT_PIN(6, 10)
+#define WMT_PIN_LCDD11         WMT_PIN(6, 11)
+#define WMT_PIN_LCDD12         WMT_PIN(6, 12)
+#define WMT_PIN_LCDD13         WMT_PIN(6, 13)
+#define WMT_PIN_LCDD14         WMT_PIN(6, 14)
+#define WMT_PIN_LCDD15         WMT_PIN(6, 15)
+#define WMT_PIN_LCDD16         WMT_PIN(6, 16)
+#define WMT_PIN_LCDD17         WMT_PIN(6, 17)
+#define WMT_PIN_LCDCLK         WMT_PIN(6, 18)
+#define WMT_PIN_LCDDEN         WMT_PIN(6, 19)
+#define WMT_PIN_LCDLINE                WMT_PIN(6, 20)
+#define WMT_PIN_LCDFRM         WMT_PIN(6, 21)
+#define WMT_PIN_LCDBIAS                WMT_PIN(6, 22)
+
+static const struct pinctrl_pin_desc vt8500_pins[] = {
+       PINCTRL_PIN(WMT_PIN_EXTGPIO0, "extgpio0"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO1, "extgpio1"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO2, "extgpio2"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO3, "extgpio3"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO4, "extgpio4"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO5, "extgpio5"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO6, "extgpio6"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO7, "extgpio7"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO8, "extgpio8"),
+       PINCTRL_PIN(WMT_PIN_UART0RTS, "uart0_rts"),
+       PINCTRL_PIN(WMT_PIN_UART0TXD, "uart0_txd"),
+       PINCTRL_PIN(WMT_PIN_UART0CTS, "uart0_cts"),
+       PINCTRL_PIN(WMT_PIN_UART0RXD, "uart0_rxd"),
+       PINCTRL_PIN(WMT_PIN_UART1RTS, "uart1_rts"),
+       PINCTRL_PIN(WMT_PIN_UART1TXD, "uart1_txd"),
+       PINCTRL_PIN(WMT_PIN_UART1CTS, "uart1_cts"),
+       PINCTRL_PIN(WMT_PIN_UART1RXD, "uart1_rxd"),
+       PINCTRL_PIN(WMT_PIN_SPI0CLK, "spi0_clk"),
+       PINCTRL_PIN(WMT_PIN_SPI0SS, "spi0_ss"),
+       PINCTRL_PIN(WMT_PIN_SPI0MISO, "spi0_miso"),
+       PINCTRL_PIN(WMT_PIN_SPI0MOSI, "spi0_mosi"),
+       PINCTRL_PIN(WMT_PIN_SPI1CLK, "spi1_clk"),
+       PINCTRL_PIN(WMT_PIN_SPI1SS, "spi1_ss"),
+       PINCTRL_PIN(WMT_PIN_SPI1MISO, "spi1_miso"),
+       PINCTRL_PIN(WMT_PIN_SPI1MOSI, "spi1_mosi"),
+       PINCTRL_PIN(WMT_PIN_SPI2CLK, "spi2_clk"),
+       PINCTRL_PIN(WMT_PIN_SPI2SS, "spi2_ss"),
+       PINCTRL_PIN(WMT_PIN_SPI2MISO, "spi2_miso"),
+       PINCTRL_PIN(WMT_PIN_SPI2MOSI, "spi2_mosi"),
+       PINCTRL_PIN(WMT_PIN_SDDATA0, "sd_data0"),
+       PINCTRL_PIN(WMT_PIN_SDDATA1, "sd_data1"),
+       PINCTRL_PIN(WMT_PIN_SDDATA2, "sd_data2"),
+       PINCTRL_PIN(WMT_PIN_SDDATA3, "sd_data3"),
+       PINCTRL_PIN(WMT_PIN_MMCDATA0, "mmc_data0"),
+       PINCTRL_PIN(WMT_PIN_MMCDATA1, "mmc_data1"),
+       PINCTRL_PIN(WMT_PIN_MMCDATA2, "mmc_data2"),
+       PINCTRL_PIN(WMT_PIN_MMCDATA3, "mmc_data3"),
+       PINCTRL_PIN(WMT_PIN_SDCLK, "sd_clk"),
+       PINCTRL_PIN(WMT_PIN_SDWP, "sd_wp"),
+       PINCTRL_PIN(WMT_PIN_SDCMD, "sd_cmd"),
+       PINCTRL_PIN(WMT_PIN_MSDATA0, "ms_data0"),
+       PINCTRL_PIN(WMT_PIN_MSDATA1, "ms_data1"),
+       PINCTRL_PIN(WMT_PIN_MSDATA2, "ms_data2"),
+       PINCTRL_PIN(WMT_PIN_MSDATA3, "ms_data3"),
+       PINCTRL_PIN(WMT_PIN_MSCLK, "ms_clk"),
+       PINCTRL_PIN(WMT_PIN_MSBS, "ms_bs"),
+       PINCTRL_PIN(WMT_PIN_MSINS, "ms_ins"),
+       PINCTRL_PIN(WMT_PIN_I2C0SCL, "i2c0_scl"),
+       PINCTRL_PIN(WMT_PIN_I2C0SDA, "i2c0_sda"),
+       PINCTRL_PIN(WMT_PIN_I2C1SCL, "i2c1_scl"),
+       PINCTRL_PIN(WMT_PIN_I2C1SDA, "i2c1_sda"),
+       PINCTRL_PIN(WMT_PIN_MII0RXD0, "mii0_rxd0"),
+       PINCTRL_PIN(WMT_PIN_MII0RXD1, "mii0_rxd1"),
+       PINCTRL_PIN(WMT_PIN_MII0RXD2, "mii0_rxd2"),
+       PINCTRL_PIN(WMT_PIN_MII0RXD3, "mii0_rxd3"),
+       PINCTRL_PIN(WMT_PIN_MII0RXCLK, "mii0_rxclk"),
+       PINCTRL_PIN(WMT_PIN_MII0RXDV, "mii0_rxdv"),
+       PINCTRL_PIN(WMT_PIN_MII0RXERR, "mii0_rxerr"),
+       PINCTRL_PIN(WMT_PIN_MII0PHYRST, "mii0_phyrst"),
+       PINCTRL_PIN(WMT_PIN_MII0TXD0, "mii0_txd0"),
+       PINCTRL_PIN(WMT_PIN_MII0TXD1, "mii0_txd1"),
+       PINCTRL_PIN(WMT_PIN_MII0TXD2, "mii0_txd2"),
+       PINCTRL_PIN(WMT_PIN_MII0TXD3, "mii0_txd3"),
+       PINCTRL_PIN(WMT_PIN_MII0TXCLK, "mii0_txclk"),
+       PINCTRL_PIN(WMT_PIN_MII0TXEN, "mii0_txen"),
+       PINCTRL_PIN(WMT_PIN_MII0TXERR, "mii0_txerr"),
+       PINCTRL_PIN(WMT_PIN_MII0PHYPD, "mii0_phypd"),
+       PINCTRL_PIN(WMT_PIN_MII0COL, "mii0_col"),
+       PINCTRL_PIN(WMT_PIN_MII0CRS, "mii0_crs"),
+       PINCTRL_PIN(WMT_PIN_MII0MDIO, "mii0_mdio"),
+       PINCTRL_PIN(WMT_PIN_MII0MDC, "mii0_mdc"),
+       PINCTRL_PIN(WMT_PIN_SEECS, "see_cs"),
+       PINCTRL_PIN(WMT_PIN_SEECK, "see_ck"),
+       PINCTRL_PIN(WMT_PIN_SEEDI, "see_di"),
+       PINCTRL_PIN(WMT_PIN_SEEDO, "see_do"),
+       PINCTRL_PIN(WMT_PIN_IDEDREQ0, "ide_dreq0"),
+       PINCTRL_PIN(WMT_PIN_IDEDREQ1, "ide_dreq1"),
+       PINCTRL_PIN(WMT_PIN_IDEIOW, "ide_iow"),
+       PINCTRL_PIN(WMT_PIN_IDEIOR, "ide_ior"),
+       PINCTRL_PIN(WMT_PIN_IDEDACK, "ide_dack"),
+       PINCTRL_PIN(WMT_PIN_IDEIORDY, "ide_iordy"),
+       PINCTRL_PIN(WMT_PIN_IDEINTRQ, "ide_intrq"),
+       PINCTRL_PIN(WMT_PIN_VDIN0, "vdin0"),
+       PINCTRL_PIN(WMT_PIN_VDIN1, "vdin1"),
+       PINCTRL_PIN(WMT_PIN_VDIN2, "vdin2"),
+       PINCTRL_PIN(WMT_PIN_VDIN3, "vdin3"),
+       PINCTRL_PIN(WMT_PIN_VDIN4, "vdin4"),
+       PINCTRL_PIN(WMT_PIN_VDIN5, "vdin5"),
+       PINCTRL_PIN(WMT_PIN_VDIN6, "vdin6"),
+       PINCTRL_PIN(WMT_PIN_VDIN7, "vdin7"),
+       PINCTRL_PIN(WMT_PIN_VDOUT0, "vdout0"),
+       PINCTRL_PIN(WMT_PIN_VDOUT1, "vdout1"),
+       PINCTRL_PIN(WMT_PIN_VDOUT2, "vdout2"),
+       PINCTRL_PIN(WMT_PIN_VDOUT3, "vdout3"),
+       PINCTRL_PIN(WMT_PIN_VDOUT4, "vdout4"),
+       PINCTRL_PIN(WMT_PIN_VDOUT5, "vdout5"),
+       PINCTRL_PIN(WMT_PIN_NANDCLE0, "nand_cle0"),
+       PINCTRL_PIN(WMT_PIN_NANDCLE1, "nand_cle1"),
+       PINCTRL_PIN(WMT_PIN_VDOUT6_7, "vdout6_7"),
+       PINCTRL_PIN(WMT_PIN_VHSYNC, "vhsync"),
+       PINCTRL_PIN(WMT_PIN_VVSYNC, "vvsync"),
+       PINCTRL_PIN(WMT_PIN_TSDIN0, "tsdin0"),
+       PINCTRL_PIN(WMT_PIN_TSDIN1, "tsdin1"),
+       PINCTRL_PIN(WMT_PIN_TSDIN2, "tsdin2"),
+       PINCTRL_PIN(WMT_PIN_TSDIN3, "tsdin3"),
+       PINCTRL_PIN(WMT_PIN_TSDIN4, "tsdin4"),
+       PINCTRL_PIN(WMT_PIN_TSDIN5, "tsdin5"),
+       PINCTRL_PIN(WMT_PIN_TSDIN6, "tsdin6"),
+       PINCTRL_PIN(WMT_PIN_TSDIN7, "tsdin7"),
+       PINCTRL_PIN(WMT_PIN_TSSYNC, "tssync"),
+       PINCTRL_PIN(WMT_PIN_TSVALID, "tsvalid"),
+       PINCTRL_PIN(WMT_PIN_TSCLK, "tsclk"),
+       PINCTRL_PIN(WMT_PIN_LCDD0, "lcd_d0"),
+       PINCTRL_PIN(WMT_PIN_LCDD1, "lcd_d1"),
+       PINCTRL_PIN(WMT_PIN_LCDD2, "lcd_d2"),
+       PINCTRL_PIN(WMT_PIN_LCDD3, "lcd_d3"),
+       PINCTRL_PIN(WMT_PIN_LCDD4, "lcd_d4"),
+       PINCTRL_PIN(WMT_PIN_LCDD5, "lcd_d5"),
+       PINCTRL_PIN(WMT_PIN_LCDD6, "lcd_d6"),
+       PINCTRL_PIN(WMT_PIN_LCDD7, "lcd_d7"),
+       PINCTRL_PIN(WMT_PIN_LCDD8, "lcd_d8"),
+       PINCTRL_PIN(WMT_PIN_LCDD9, "lcd_d9"),
+       PINCTRL_PIN(WMT_PIN_LCDD10, "lcd_d10"),
+       PINCTRL_PIN(WMT_PIN_LCDD11, "lcd_d11"),
+       PINCTRL_PIN(WMT_PIN_LCDD12, "lcd_d12"),
+       PINCTRL_PIN(WMT_PIN_LCDD13, "lcd_d13"),
+       PINCTRL_PIN(WMT_PIN_LCDD14, "lcd_d14"),
+       PINCTRL_PIN(WMT_PIN_LCDD15, "lcd_d15"),
+       PINCTRL_PIN(WMT_PIN_LCDD16, "lcd_d16"),
+       PINCTRL_PIN(WMT_PIN_LCDD17, "lcd_d17"),
+       PINCTRL_PIN(WMT_PIN_LCDCLK, "lcd_clk"),
+       PINCTRL_PIN(WMT_PIN_LCDDEN, "lcd_den"),
+       PINCTRL_PIN(WMT_PIN_LCDLINE, "lcd_line"),
+       PINCTRL_PIN(WMT_PIN_LCDFRM, "lcd_frm"),
+       PINCTRL_PIN(WMT_PIN_LCDBIAS, "lcd_bias"),
+};
+
+/* Order of these names must match the above list */
+static const char * const vt8500_groups[] = {
+       "extgpio0",
+       "extgpio1",
+       "extgpio2",
+       "extgpio3",
+       "extgpio4",
+       "extgpio5",
+       "extgpio6",
+       "extgpio7",
+       "extgpio8",
+       "uart0_rts",
+       "uart0_txd",
+       "uart0_cts",
+       "uart0_rxd",
+       "uart1_rts",
+       "uart1_txd",
+       "uart1_cts",
+       "uart1_rxd",
+       "spi0_clk",
+       "spi0_ss",
+       "spi0_miso",
+       "spi0_mosi",
+       "spi1_clk",
+       "spi1_ss",
+       "spi1_miso",
+       "spi1_mosi",
+       "spi2_clk",
+       "spi2_ss",
+       "spi2_miso",
+       "spi2_mosi",
+       "sd_data0",
+       "sd_data1",
+       "sd_data2",
+       "sd_data3",
+       "mmc_data0",
+       "mmc_data1",
+       "mmc_data2",
+       "mmc_data3",
+       "sd_clk",
+       "sd_wp",
+       "sd_cmd",
+       "ms_data0",
+       "ms_data1",
+       "ms_data2",
+       "ms_data3",
+       "ms_clk",
+       "ms_bs",
+       "ms_ins",
+       "i2c0_scl",
+       "i2c0_sda",
+       "i2c1_scl",
+       "i2c1_sda",
+       "mii0_rxd0",
+       "mii0_rxd1",
+       "mii0_rxd2",
+       "mii0_rxd3",
+       "mii0_rxclk",
+       "mii0_rxdv",
+       "mii0_rxerr",
+       "mii0_phyrst",
+       "mii0_txd0",
+       "mii0_txd1",
+       "mii0_txd2",
+       "mii0_txd3",
+       "mii0_txclk",
+       "mii0_txen",
+       "mii0_txerr",
+       "mii0_phypd",
+       "mii0_col",
+       "mii0_crs",
+       "mii0_mdio",
+       "mii0_mdc",
+       "see_cs",
+       "see_ck",
+       "see_di",
+       "see_do",
+       "ide_dreq0",
+       "ide_dreq1",
+       "ide_iow",
+       "ide_ior",
+       "ide_dack",
+       "ide_iordy",
+       "ide_intrq",
+       "vdin0",
+       "vdin1",
+       "vdin2",
+       "vdin3",
+       "vdin4",
+       "vdin5",
+       "vdin6",
+       "vdin7",
+       "vdout0",
+       "vdout1",
+       "vdout2",
+       "vdout3",
+       "vdout4",
+       "vdout5",
+       "nand_cle0",
+       "nand_cle1",
+       "vdout6_7",
+       "vhsync",
+       "vvsync",
+       "tsdin0",
+       "tsdin1",
+       "tsdin2",
+       "tsdin3",
+       "tsdin4",
+       "tsdin5",
+       "tsdin6",
+       "tsdin7",
+       "tssync",
+       "tsvalid",
+       "tsclk",
+       "lcd_d0",
+       "lcd_d1",
+       "lcd_d2",
+       "lcd_d3",
+       "lcd_d4",
+       "lcd_d5",
+       "lcd_d6",
+       "lcd_d7",
+       "lcd_d8",
+       "lcd_d9",
+       "lcd_d10",
+       "lcd_d11",
+       "lcd_d12",
+       "lcd_d13",
+       "lcd_d14",
+       "lcd_d15",
+       "lcd_d16",
+       "lcd_d17",
+       "lcd_clk",
+       "lcd_den",
+       "lcd_line",
+       "lcd_frm",
+       "lcd_bias",
+};
+
+static int vt8500_pinctrl_probe(struct platform_device *pdev)
+{
+       struct wmt_pinctrl_data *data;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data) {
+               dev_err(&pdev->dev, "failed to allocate data\n");
+               return -ENOMEM;
+       }
+
+       data->banks = vt8500_banks;
+       data->nbanks = ARRAY_SIZE(vt8500_banks);
+       data->pins = vt8500_pins;
+       data->npins = ARRAY_SIZE(vt8500_pins);
+       data->groups = vt8500_groups;
+       data->ngroups = ARRAY_SIZE(vt8500_groups);
+
+       return wmt_pinctrl_probe(pdev, data);
+}
+
+static int vt8500_pinctrl_remove(struct platform_device *pdev)
+{
+       return wmt_pinctrl_remove(pdev);
+}
+
+static struct of_device_id wmt_pinctrl_of_match[] = {
+       { .compatible = "via,vt8500-pinctrl" },
+       { /* sentinel */ },
+};
+
+static struct platform_driver wmt_pinctrl_driver = {
+       .probe  = vt8500_pinctrl_probe,
+       .remove = vt8500_pinctrl_remove,
+       .driver = {
+               .name   = "pinctrl-vt8500",
+               .owner  = THIS_MODULE,
+               .of_match_table = wmt_pinctrl_of_match,
+       },
+};
+
+module_platform_driver(wmt_pinctrl_driver);
+
+MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
+MODULE_DESCRIPTION("VIA VT8500 Pincontrol driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8505.c b/drivers/pinctrl/vt8500/pinctrl-wm8505.c
new file mode 100644 (file)
index 0000000..483ba73
--- /dev/null
@@ -0,0 +1,532 @@
+/*
+ * Pinctrl data for Wondermedia WM8505 SoC
+ *
+ * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "pinctrl-wmt.h"
+
+/*
+ * Describe the register offsets within the GPIO memory space
+ * The dedicated external GPIO's should always be listed in bank 0
+ * so they are exported in the 0..31 range which is what users
+ * expect.
+ *
+ * Do not reorder these banks as it will change the pin numbering
+ */
+static const struct wmt_pinctrl_bank_registers wm8505_banks[] = {
+       WMT_PINCTRL_BANK(0x64, 0x8C, 0xB4, 0xDC, NO_REG, NO_REG),       /* 0 */
+       WMT_PINCTRL_BANK(0x40, 0x68, 0x90, 0xB8, NO_REG, NO_REG),       /* 1 */
+       WMT_PINCTRL_BANK(0x44, 0x6C, 0x94, 0xBC, NO_REG, NO_REG),       /* 2 */
+       WMT_PINCTRL_BANK(0x48, 0x70, 0x98, 0xC0, NO_REG, NO_REG),       /* 3 */
+       WMT_PINCTRL_BANK(0x4C, 0x74, 0x9C, 0xC4, NO_REG, NO_REG),       /* 4 */
+       WMT_PINCTRL_BANK(0x50, 0x78, 0xA0, 0xC8, NO_REG, NO_REG),       /* 5 */
+       WMT_PINCTRL_BANK(0x54, 0x7C, 0xA4, 0xD0, NO_REG, NO_REG),       /* 6 */
+       WMT_PINCTRL_BANK(0x58, 0x80, 0xA8, 0xD4, NO_REG, NO_REG),       /* 7 */
+       WMT_PINCTRL_BANK(0x5C, 0x84, 0xAC, 0xD8, NO_REG, NO_REG),       /* 8 */
+       WMT_PINCTRL_BANK(0x60, 0x88, 0xB0, 0xDC, NO_REG, NO_REG),       /* 9 */
+       WMT_PINCTRL_BANK(0x500, 0x504, 0x508, 0x50C, NO_REG, NO_REG),   /* 10 */
+};
+
+/* Please keep sorted by bank/bit */
+#define WMT_PIN_EXTGPIO0       WMT_PIN(0, 0)
+#define WMT_PIN_EXTGPIO1       WMT_PIN(0, 1)
+#define WMT_PIN_EXTGPIO2       WMT_PIN(0, 2)
+#define WMT_PIN_EXTGPIO3       WMT_PIN(0, 3)
+#define WMT_PIN_EXTGPIO4       WMT_PIN(0, 4)
+#define WMT_PIN_EXTGPIO5       WMT_PIN(0, 5)
+#define WMT_PIN_EXTGPIO6       WMT_PIN(0, 6)
+#define WMT_PIN_EXTGPIO7       WMT_PIN(0, 7)
+#define WMT_PIN_WAKEUP0                WMT_PIN(0, 16)
+#define WMT_PIN_WAKEUP1                WMT_PIN(0, 17)
+#define WMT_PIN_WAKEUP2                WMT_PIN(0, 18)
+#define WMT_PIN_WAKEUP3                WMT_PIN(0, 19)
+#define WMT_PIN_SUSGPIO0       WMT_PIN(0, 21)
+#define WMT_PIN_SDDATA0                WMT_PIN(1, 0)
+#define WMT_PIN_SDDATA1                WMT_PIN(1, 1)
+#define WMT_PIN_SDDATA2                WMT_PIN(1, 2)
+#define WMT_PIN_SDDATA3                WMT_PIN(1, 3)
+#define WMT_PIN_MMCDATA0       WMT_PIN(1, 4)
+#define WMT_PIN_MMCDATA1       WMT_PIN(1, 5)
+#define WMT_PIN_MMCDATA2       WMT_PIN(1, 6)
+#define WMT_PIN_MMCDATA3       WMT_PIN(1, 7)
+#define WMT_PIN_VDIN0          WMT_PIN(2, 0)
+#define WMT_PIN_VDIN1          WMT_PIN(2, 1)
+#define WMT_PIN_VDIN2          WMT_PIN(2, 2)
+#define WMT_PIN_VDIN3          WMT_PIN(2, 3)
+#define WMT_PIN_VDIN4          WMT_PIN(2, 4)
+#define WMT_PIN_VDIN5          WMT_PIN(2, 5)
+#define WMT_PIN_VDIN6          WMT_PIN(2, 6)
+#define WMT_PIN_VDIN7          WMT_PIN(2, 7)
+#define WMT_PIN_VDOUT0         WMT_PIN(2, 8)
+#define WMT_PIN_VDOUT1         WMT_PIN(2, 9)
+#define WMT_PIN_VDOUT2         WMT_PIN(2, 10)
+#define WMT_PIN_VDOUT3         WMT_PIN(2, 11)
+#define WMT_PIN_VDOUT4         WMT_PIN(2, 12)
+#define WMT_PIN_VDOUT5         WMT_PIN(2, 13)
+#define WMT_PIN_VDOUT6         WMT_PIN(2, 14)
+#define WMT_PIN_VDOUT7         WMT_PIN(2, 15)
+#define WMT_PIN_VDOUT8         WMT_PIN(2, 16)
+#define WMT_PIN_VDOUT9         WMT_PIN(2, 17)
+#define WMT_PIN_VDOUT10                WMT_PIN(2, 18)
+#define WMT_PIN_VDOUT11                WMT_PIN(2, 19)
+#define WMT_PIN_VDOUT12                WMT_PIN(2, 20)
+#define WMT_PIN_VDOUT13                WMT_PIN(2, 21)
+#define WMT_PIN_VDOUT14                WMT_PIN(2, 22)
+#define WMT_PIN_VDOUT15                WMT_PIN(2, 23)
+#define WMT_PIN_VDOUT16                WMT_PIN(2, 24)
+#define WMT_PIN_VDOUT17                WMT_PIN(2, 25)
+#define WMT_PIN_VDOUT18                WMT_PIN(2, 26)
+#define WMT_PIN_VDOUT19                WMT_PIN(2, 27)
+#define WMT_PIN_VDOUT20                WMT_PIN(2, 28)
+#define WMT_PIN_VDOUT21                WMT_PIN(2, 29)
+#define WMT_PIN_VDOUT22                WMT_PIN(2, 30)
+#define WMT_PIN_VDOUT23                WMT_PIN(2, 31)
+#define WMT_PIN_VHSYNC         WMT_PIN(3, 0)
+#define WMT_PIN_VVSYNC         WMT_PIN(3, 1)
+#define WMT_PIN_VGAHSYNC       WMT_PIN(3, 2)
+#define WMT_PIN_VGAVSYNC       WMT_PIN(3, 3)
+#define WMT_PIN_VDHSYNC                WMT_PIN(3, 4)
+#define WMT_PIN_VDVSYNC                WMT_PIN(3, 5)
+#define WMT_PIN_NORD0          WMT_PIN(4, 0)
+#define WMT_PIN_NORD1          WMT_PIN(4, 1)
+#define WMT_PIN_NORD2          WMT_PIN(4, 2)
+#define WMT_PIN_NORD3          WMT_PIN(4, 3)
+#define WMT_PIN_NORD4          WMT_PIN(4, 4)
+#define WMT_PIN_NORD5          WMT_PIN(4, 5)
+#define WMT_PIN_NORD6          WMT_PIN(4, 6)
+#define WMT_PIN_NORD7          WMT_PIN(4, 7)
+#define WMT_PIN_NORD8          WMT_PIN(4, 8)
+#define WMT_PIN_NORD9          WMT_PIN(4, 9)
+#define WMT_PIN_NORD10         WMT_PIN(4, 10)
+#define WMT_PIN_NORD11         WMT_PIN(4, 11)
+#define WMT_PIN_NORD12         WMT_PIN(4, 12)
+#define WMT_PIN_NORD13         WMT_PIN(4, 13)
+#define WMT_PIN_NORD14         WMT_PIN(4, 14)
+#define WMT_PIN_NORD15         WMT_PIN(4, 15)
+#define WMT_PIN_NORA0          WMT_PIN(5, 0)
+#define WMT_PIN_NORA1          WMT_PIN(5, 1)
+#define WMT_PIN_NORA2          WMT_PIN(5, 2)
+#define WMT_PIN_NORA3          WMT_PIN(5, 3)
+#define WMT_PIN_NORA4          WMT_PIN(5, 4)
+#define WMT_PIN_NORA5          WMT_PIN(5, 5)
+#define WMT_PIN_NORA6          WMT_PIN(5, 6)
+#define WMT_PIN_NORA7          WMT_PIN(5, 7)
+#define WMT_PIN_NORA8          WMT_PIN(5, 8)
+#define WMT_PIN_NORA9          WMT_PIN(5, 9)
+#define WMT_PIN_NORA10         WMT_PIN(5, 10)
+#define WMT_PIN_NORA11         WMT_PIN(5, 11)
+#define WMT_PIN_NORA12         WMT_PIN(5, 12)
+#define WMT_PIN_NORA13         WMT_PIN(5, 13)
+#define WMT_PIN_NORA14         WMT_PIN(5, 14)
+#define WMT_PIN_NORA15         WMT_PIN(5, 15)
+#define WMT_PIN_NORA16         WMT_PIN(5, 16)
+#define WMT_PIN_NORA17         WMT_PIN(5, 17)
+#define WMT_PIN_NORA18         WMT_PIN(5, 18)
+#define WMT_PIN_NORA19         WMT_PIN(5, 19)
+#define WMT_PIN_NORA20         WMT_PIN(5, 20)
+#define WMT_PIN_NORA21         WMT_PIN(5, 21)
+#define WMT_PIN_NORA22         WMT_PIN(5, 22)
+#define WMT_PIN_NORA23         WMT_PIN(5, 23)
+#define WMT_PIN_NORA24         WMT_PIN(5, 24)
+#define WMT_PIN_AC97SDI                WMT_PIN(6, 0)
+#define WMT_PIN_AC97SYNC       WMT_PIN(6, 1)
+#define WMT_PIN_AC97SDO                WMT_PIN(6, 2)
+#define WMT_PIN_AC97BCLK       WMT_PIN(6, 3)
+#define WMT_PIN_AC97RST                WMT_PIN(6, 4)
+#define WMT_PIN_SFDO           WMT_PIN(7, 0)
+#define WMT_PIN_SFCS0          WMT_PIN(7, 1)
+#define WMT_PIN_SFCS1          WMT_PIN(7, 2)
+#define WMT_PIN_SFCLK          WMT_PIN(7, 3)
+#define WMT_PIN_SFDI           WMT_PIN(7, 4)
+#define WMT_PIN_SPI0CLK                WMT_PIN(8, 0)
+#define WMT_PIN_SPI0MISO       WMT_PIN(8, 1)
+#define WMT_PIN_SPI0MOSI       WMT_PIN(8, 2)
+#define WMT_PIN_SPI0SS         WMT_PIN(8, 3)
+#define WMT_PIN_SPI1CLK                WMT_PIN(8, 4)
+#define WMT_PIN_SPI1MISO       WMT_PIN(8, 5)
+#define WMT_PIN_SPI1MOSI       WMT_PIN(8, 6)
+#define WMT_PIN_SPI1SS         WMT_PIN(8, 7)
+#define WMT_PIN_SPI2CLK                WMT_PIN(8, 8)
+#define WMT_PIN_SPI2MISO       WMT_PIN(8, 9)
+#define WMT_PIN_SPI2MOSI       WMT_PIN(8, 10)
+#define WMT_PIN_SPI2SS         WMT_PIN(8, 11)
+#define WMT_PIN_UART0_RTS      WMT_PIN(9, 0)
+#define WMT_PIN_UART0_TXD      WMT_PIN(9, 1)
+#define WMT_PIN_UART0_CTS      WMT_PIN(9, 2)
+#define WMT_PIN_UART0_RXD      WMT_PIN(9, 3)
+#define WMT_PIN_UART1_RTS      WMT_PIN(9, 4)
+#define WMT_PIN_UART1_TXD      WMT_PIN(9, 5)
+#define WMT_PIN_UART1_CTS      WMT_PIN(9, 6)
+#define WMT_PIN_UART1_RXD      WMT_PIN(9, 7)
+#define WMT_PIN_UART2_RTS      WMT_PIN(9, 8)
+#define WMT_PIN_UART2_TXD      WMT_PIN(9, 9)
+#define WMT_PIN_UART2_CTS      WMT_PIN(9, 10)
+#define WMT_PIN_UART2_RXD      WMT_PIN(9, 11)
+#define WMT_PIN_UART3_RTS      WMT_PIN(9, 12)
+#define WMT_PIN_UART3_TXD      WMT_PIN(9, 13)
+#define WMT_PIN_UART3_CTS      WMT_PIN(9, 14)
+#define WMT_PIN_UART3_RXD      WMT_PIN(9, 15)
+#define WMT_PIN_I2C0SCL                WMT_PIN(10, 0)
+#define WMT_PIN_I2C0SDA                WMT_PIN(10, 1)
+#define WMT_PIN_I2C1SCL                WMT_PIN(10, 2)
+#define WMT_PIN_I2C1SDA                WMT_PIN(10, 3)
+#define WMT_PIN_I2C2SCL                WMT_PIN(10, 4)
+#define WMT_PIN_I2C2SDA                WMT_PIN(10, 5)
+
+static const struct pinctrl_pin_desc wm8505_pins[] = {
+       PINCTRL_PIN(WMT_PIN_EXTGPIO0, "extgpio0"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO1, "extgpio1"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO2, "extgpio2"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO3, "extgpio3"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO4, "extgpio4"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO5, "extgpio5"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO6, "extgpio6"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO7, "extgpio7"),
+       PINCTRL_PIN(WMT_PIN_WAKEUP0, "wakeup0"),
+       PINCTRL_PIN(WMT_PIN_WAKEUP1, "wakeup1"),
+       PINCTRL_PIN(WMT_PIN_WAKEUP2, "wakeup2"),
+       PINCTRL_PIN(WMT_PIN_WAKEUP3, "wakeup3"),
+       PINCTRL_PIN(WMT_PIN_SUSGPIO0, "susgpio0"),
+       PINCTRL_PIN(WMT_PIN_SDDATA0, "sd_data0"),
+       PINCTRL_PIN(WMT_PIN_SDDATA1, "sd_data1"),
+       PINCTRL_PIN(WMT_PIN_SDDATA2, "sd_data2"),
+       PINCTRL_PIN(WMT_PIN_SDDATA3, "sd_data3"),
+       PINCTRL_PIN(WMT_PIN_MMCDATA0, "mmc_data0"),
+       PINCTRL_PIN(WMT_PIN_MMCDATA1, "mmc_data1"),
+       PINCTRL_PIN(WMT_PIN_MMCDATA2, "mmc_data2"),
+       PINCTRL_PIN(WMT_PIN_MMCDATA3, "mmc_data3"),
+       PINCTRL_PIN(WMT_PIN_VDIN0, "vdin0"),
+       PINCTRL_PIN(WMT_PIN_VDIN1, "vdin1"),
+       PINCTRL_PIN(WMT_PIN_VDIN2, "vdin2"),
+       PINCTRL_PIN(WMT_PIN_VDIN3, "vdin3"),
+       PINCTRL_PIN(WMT_PIN_VDIN4, "vdin4"),
+       PINCTRL_PIN(WMT_PIN_VDIN5, "vdin5"),
+       PINCTRL_PIN(WMT_PIN_VDIN6, "vdin6"),
+       PINCTRL_PIN(WMT_PIN_VDIN7, "vdin7"),
+       PINCTRL_PIN(WMT_PIN_VDOUT0, "vdout0"),
+       PINCTRL_PIN(WMT_PIN_VDOUT1, "vdout1"),
+       PINCTRL_PIN(WMT_PIN_VDOUT2, "vdout2"),
+       PINCTRL_PIN(WMT_PIN_VDOUT3, "vdout3"),
+       PINCTRL_PIN(WMT_PIN_VDOUT4, "vdout4"),
+       PINCTRL_PIN(WMT_PIN_VDOUT5, "vdout5"),
+       PINCTRL_PIN(WMT_PIN_VDOUT6, "vdout6"),
+       PINCTRL_PIN(WMT_PIN_VDOUT7, "vdout7"),
+       PINCTRL_PIN(WMT_PIN_VDOUT8, "vdout8"),
+       PINCTRL_PIN(WMT_PIN_VDOUT9, "vdout9"),
+       PINCTRL_PIN(WMT_PIN_VDOUT10, "vdout10"),
+       PINCTRL_PIN(WMT_PIN_VDOUT11, "vdout11"),
+       PINCTRL_PIN(WMT_PIN_VDOUT12, "vdout12"),
+       PINCTRL_PIN(WMT_PIN_VDOUT13, "vdout13"),
+       PINCTRL_PIN(WMT_PIN_VDOUT14, "vdout14"),
+       PINCTRL_PIN(WMT_PIN_VDOUT15, "vdout15"),
+       PINCTRL_PIN(WMT_PIN_VDOUT16, "vdout16"),
+       PINCTRL_PIN(WMT_PIN_VDOUT17, "vdout17"),
+       PINCTRL_PIN(WMT_PIN_VDOUT18, "vdout18"),
+       PINCTRL_PIN(WMT_PIN_VDOUT19, "vdout19"),
+       PINCTRL_PIN(WMT_PIN_VDOUT20, "vdout20"),
+       PINCTRL_PIN(WMT_PIN_VDOUT21, "vdout21"),
+       PINCTRL_PIN(WMT_PIN_VDOUT22, "vdout22"),
+       PINCTRL_PIN(WMT_PIN_VDOUT23, "vdout23"),
+       PINCTRL_PIN(WMT_PIN_VHSYNC, "v_hsync"),
+       PINCTRL_PIN(WMT_PIN_VVSYNC, "v_vsync"),
+       PINCTRL_PIN(WMT_PIN_VGAHSYNC, "vga_hsync"),
+       PINCTRL_PIN(WMT_PIN_VGAVSYNC, "vga_vsync"),
+       PINCTRL_PIN(WMT_PIN_VDHSYNC, "vd_hsync"),
+       PINCTRL_PIN(WMT_PIN_VDVSYNC, "vd_vsync"),
+       PINCTRL_PIN(WMT_PIN_NORD0, "nor_d0"),
+       PINCTRL_PIN(WMT_PIN_NORD1, "nor_d1"),
+       PINCTRL_PIN(WMT_PIN_NORD2, "nor_d2"),
+       PINCTRL_PIN(WMT_PIN_NORD3, "nor_d3"),
+       PINCTRL_PIN(WMT_PIN_NORD4, "nor_d4"),
+       PINCTRL_PIN(WMT_PIN_NORD5, "nor_d5"),
+       PINCTRL_PIN(WMT_PIN_NORD6, "nor_d6"),
+       PINCTRL_PIN(WMT_PIN_NORD7, "nor_d7"),
+       PINCTRL_PIN(WMT_PIN_NORD8, "nor_d8"),
+       PINCTRL_PIN(WMT_PIN_NORD9, "nor_d9"),
+       PINCTRL_PIN(WMT_PIN_NORD10, "nor_d10"),
+       PINCTRL_PIN(WMT_PIN_NORD11, "nor_d11"),
+       PINCTRL_PIN(WMT_PIN_NORD12, "nor_d12"),
+       PINCTRL_PIN(WMT_PIN_NORD13, "nor_d13"),
+       PINCTRL_PIN(WMT_PIN_NORD14, "nor_d14"),
+       PINCTRL_PIN(WMT_PIN_NORD15, "nor_d15"),
+       PINCTRL_PIN(WMT_PIN_NORA0, "nor_a0"),
+       PINCTRL_PIN(WMT_PIN_NORA1, "nor_a1"),
+       PINCTRL_PIN(WMT_PIN_NORA2, "nor_a2"),
+       PINCTRL_PIN(WMT_PIN_NORA3, "nor_a3"),
+       PINCTRL_PIN(WMT_PIN_NORA4, "nor_a4"),
+       PINCTRL_PIN(WMT_PIN_NORA5, "nor_a5"),
+       PINCTRL_PIN(WMT_PIN_NORA6, "nor_a6"),
+       PINCTRL_PIN(WMT_PIN_NORA7, "nor_a7"),
+       PINCTRL_PIN(WMT_PIN_NORA8, "nor_a8"),
+       PINCTRL_PIN(WMT_PIN_NORA9, "nor_a9"),
+       PINCTRL_PIN(WMT_PIN_NORA10, "nor_a10"),
+       PINCTRL_PIN(WMT_PIN_NORA11, "nor_a11"),
+       PINCTRL_PIN(WMT_PIN_NORA12, "nor_a12"),
+       PINCTRL_PIN(WMT_PIN_NORA13, "nor_a13"),
+       PINCTRL_PIN(WMT_PIN_NORA14, "nor_a14"),
+       PINCTRL_PIN(WMT_PIN_NORA15, "nor_a15"),
+       PINCTRL_PIN(WMT_PIN_NORA16, "nor_a16"),
+       PINCTRL_PIN(WMT_PIN_NORA17, "nor_a17"),
+       PINCTRL_PIN(WMT_PIN_NORA18, "nor_a18"),
+       PINCTRL_PIN(WMT_PIN_NORA19, "nor_a19"),
+       PINCTRL_PIN(WMT_PIN_NORA20, "nor_a20"),
+       PINCTRL_PIN(WMT_PIN_NORA21, "nor_a21"),
+       PINCTRL_PIN(WMT_PIN_NORA22, "nor_a22"),
+       PINCTRL_PIN(WMT_PIN_NORA23, "nor_a23"),
+       PINCTRL_PIN(WMT_PIN_NORA24, "nor_a24"),
+       PINCTRL_PIN(WMT_PIN_AC97SDI, "ac97_sdi"),
+       PINCTRL_PIN(WMT_PIN_AC97SYNC, "ac97_sync"),
+       PINCTRL_PIN(WMT_PIN_AC97SDO, "ac97_sdo"),
+       PINCTRL_PIN(WMT_PIN_AC97BCLK, "ac97_bclk"),
+       PINCTRL_PIN(WMT_PIN_AC97RST, "ac97_rst"),
+       PINCTRL_PIN(WMT_PIN_SFDO, "sf_do"),
+       PINCTRL_PIN(WMT_PIN_SFCS0, "sf_cs0"),
+       PINCTRL_PIN(WMT_PIN_SFCS1, "sf_cs1"),
+       PINCTRL_PIN(WMT_PIN_SFCLK, "sf_clk"),
+       PINCTRL_PIN(WMT_PIN_SFDI, "sf_di"),
+       PINCTRL_PIN(WMT_PIN_SPI0CLK, "spi0_clk"),
+       PINCTRL_PIN(WMT_PIN_SPI0MISO, "spi0_miso"),
+       PINCTRL_PIN(WMT_PIN_SPI0MOSI, "spi0_mosi"),
+       PINCTRL_PIN(WMT_PIN_SPI0SS, "spi0_ss"),
+       PINCTRL_PIN(WMT_PIN_SPI1CLK, "spi1_clk"),
+       PINCTRL_PIN(WMT_PIN_SPI1MISO, "spi1_miso"),
+       PINCTRL_PIN(WMT_PIN_SPI1MOSI, "spi1_mosi"),
+       PINCTRL_PIN(WMT_PIN_SPI1SS, "spi1_ss"),
+       PINCTRL_PIN(WMT_PIN_SPI2CLK, "spi2_clk"),
+       PINCTRL_PIN(WMT_PIN_SPI2MISO, "spi2_miso"),
+       PINCTRL_PIN(WMT_PIN_SPI2MOSI, "spi2_mosi"),
+       PINCTRL_PIN(WMT_PIN_SPI2SS, "spi2_ss"),
+       PINCTRL_PIN(WMT_PIN_UART0_RTS, "uart0_rts"),
+       PINCTRL_PIN(WMT_PIN_UART0_TXD, "uart0_txd"),
+       PINCTRL_PIN(WMT_PIN_UART0_CTS, "uart0_cts"),
+       PINCTRL_PIN(WMT_PIN_UART0_RXD, "uart0_rxd"),
+       PINCTRL_PIN(WMT_PIN_UART1_RTS, "uart1_rts"),
+       PINCTRL_PIN(WMT_PIN_UART1_TXD, "uart1_txd"),
+       PINCTRL_PIN(WMT_PIN_UART1_CTS, "uart1_cts"),
+       PINCTRL_PIN(WMT_PIN_UART1_RXD, "uart1_rxd"),
+       PINCTRL_PIN(WMT_PIN_UART2_RTS, "uart2_rts"),
+       PINCTRL_PIN(WMT_PIN_UART2_TXD, "uart2_txd"),
+       PINCTRL_PIN(WMT_PIN_UART2_CTS, "uart2_cts"),
+       PINCTRL_PIN(WMT_PIN_UART2_RXD, "uart2_rxd"),
+       PINCTRL_PIN(WMT_PIN_UART3_RTS, "uart3_rts"),
+       PINCTRL_PIN(WMT_PIN_UART3_TXD, "uart3_txd"),
+       PINCTRL_PIN(WMT_PIN_UART3_CTS, "uart3_cts"),
+       PINCTRL_PIN(WMT_PIN_UART3_RXD, "uart3_rxd"),
+       PINCTRL_PIN(WMT_PIN_I2C0SCL, "i2c0_scl"),
+       PINCTRL_PIN(WMT_PIN_I2C0SDA, "i2c0_sda"),
+       PINCTRL_PIN(WMT_PIN_I2C1SCL, "i2c1_scl"),
+       PINCTRL_PIN(WMT_PIN_I2C1SDA, "i2c1_sda"),
+       PINCTRL_PIN(WMT_PIN_I2C2SCL, "i2c2_scl"),
+       PINCTRL_PIN(WMT_PIN_I2C2SDA, "i2c2_sda"),
+};
+
+/* Order of these names must match the above list */
+static const char * const wm8505_groups[] = {
+       "extgpio0",
+       "extgpio1",
+       "extgpio2",
+       "extgpio3",
+       "extgpio4",
+       "extgpio5",
+       "extgpio6",
+       "extgpio7",
+       "wakeup0",
+       "wakeup1",
+       "wakeup2",
+       "wakeup3",
+       "susgpio0",
+       "sd_data0",
+       "sd_data1",
+       "sd_data2",
+       "sd_data3",
+       "mmc_data0",
+       "mmc_data1",
+       "mmc_data2",
+       "mmc_data3",
+       "vdin0",
+       "vdin1",
+       "vdin2",
+       "vdin3",
+       "vdin4",
+       "vdin5",
+       "vdin6",
+       "vdin7",
+       "vdout0",
+       "vdout1",
+       "vdout2",
+       "vdout3",
+       "vdout4",
+       "vdout5",
+       "vdout6",
+       "vdout7",
+       "vdout8",
+       "vdout9",
+       "vdout10",
+       "vdout11",
+       "vdout12",
+       "vdout13",
+       "vdout14",
+       "vdout15",
+       "vdout16",
+       "vdout17",
+       "vdout18",
+       "vdout19",
+       "vdout20",
+       "vdout21",
+       "vdout22",
+       "vdout23",
+       "v_hsync",
+       "v_vsync",
+       "vga_hsync",
+       "vga_vsync",
+       "vd_hsync",
+       "vd_vsync",
+       "nor_d0",
+       "nor_d1",
+       "nor_d2",
+       "nor_d3",
+       "nor_d4",
+       "nor_d5",
+       "nor_d6",
+       "nor_d7",
+       "nor_d8",
+       "nor_d9",
+       "nor_d10",
+       "nor_d11",
+       "nor_d12",
+       "nor_d13",
+       "nor_d14",
+       "nor_d15",
+       "nor_a0",
+       "nor_a1",
+       "nor_a2",
+       "nor_a3",
+       "nor_a4",
+       "nor_a5",
+       "nor_a6",
+       "nor_a7",
+       "nor_a8",
+       "nor_a9",
+       "nor_a10",
+       "nor_a11",
+       "nor_a12",
+       "nor_a13",
+       "nor_a14",
+       "nor_a15",
+       "nor_a16",
+       "nor_a17",
+       "nor_a18",
+       "nor_a19",
+       "nor_a20",
+       "nor_a21",
+       "nor_a22",
+       "nor_a23",
+       "nor_a24",
+       "ac97_sdi",
+       "ac97_sync",
+       "ac97_sdo",
+       "ac97_bclk",
+       "ac97_rst",
+       "sf_do",
+       "sf_cs0",
+       "sf_cs1",
+       "sf_clk",
+       "sf_di",
+       "spi0_clk",
+       "spi0_miso",
+       "spi0_mosi",
+       "spi0_ss",
+       "spi1_clk",
+       "spi1_miso",
+       "spi1_mosi",
+       "spi1_ss",
+       "spi2_clk",
+       "spi2_miso",
+       "spi2_mosi",
+       "spi2_ss",
+       "uart0_rts",
+       "uart0_txd",
+       "uart0_cts",
+       "uart0_rxd",
+       "uart1_rts",
+       "uart1_txd",
+       "uart1_cts",
+       "uart1_rxd",
+       "uart2_rts",
+       "uart2_txd",
+       "uart2_cts",
+       "uart2_rxd",
+       "uart3_rts",
+       "uart3_txd",
+       "uart3_cts",
+       "uart3_rxd",
+       "i2c0_scl",
+       "i2c0_sda",
+       "i2c1_scl",
+       "i2c1_sda",
+       "i2c2_scl",
+       "i2c2_sda",
+};
+
+static int wm8505_pinctrl_probe(struct platform_device *pdev)
+{
+       struct wmt_pinctrl_data *data;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data) {
+               dev_err(&pdev->dev, "failed to allocate data\n");
+               return -ENOMEM;
+       }
+
+       data->banks = wm8505_banks;
+       data->nbanks = ARRAY_SIZE(wm8505_banks);
+       data->pins = wm8505_pins;
+       data->npins = ARRAY_SIZE(wm8505_pins);
+       data->groups = wm8505_groups;
+       data->ngroups = ARRAY_SIZE(wm8505_groups);
+
+       return wmt_pinctrl_probe(pdev, data);
+}
+
+static int wm8505_pinctrl_remove(struct platform_device *pdev)
+{
+       return wmt_pinctrl_remove(pdev);
+}
+
+static struct of_device_id wmt_pinctrl_of_match[] = {
+       { .compatible = "wm,wm8505-pinctrl" },
+       { /* sentinel */ },
+};
+
+static struct platform_driver wmt_pinctrl_driver = {
+       .probe  = wm8505_pinctrl_probe,
+       .remove = wm8505_pinctrl_remove,
+       .driver = {
+               .name   = "pinctrl-wm8505",
+               .owner  = THIS_MODULE,
+               .of_match_table = wmt_pinctrl_of_match,
+       },
+};
+
+module_platform_driver(wmt_pinctrl_driver);
+
+MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
+MODULE_DESCRIPTION("Wondermedia WM8505 Pincontrol driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8650.c b/drivers/pinctrl/vt8500/pinctrl-wm8650.c
new file mode 100644 (file)
index 0000000..7de57f0
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ * Pinctrl data for Wondermedia WM8650 SoC
+ *
+ * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "pinctrl-wmt.h"
+
+/*
+ * Describe the register offsets within the GPIO memory space
+ * The dedicated external GPIO's should always be listed in bank 0
+ * so they are exported in the 0..31 range which is what users
+ * expect.
+ *
+ * Do not reorder these banks as it will change the pin numbering
+ */
+static const struct wmt_pinctrl_bank_registers wm8650_banks[] = {
+       WMT_PINCTRL_BANK(0x40, 0x80, 0xC0, 0x00, 0x480, 0x4C0),         /* 0 */
+       WMT_PINCTRL_BANK(0x44, 0x84, 0xC4, 0x04, 0x484, 0x4C4),         /* 1 */
+       WMT_PINCTRL_BANK(0x48, 0x88, 0xC8, 0x08, 0x488, 0x4C8),         /* 2 */
+       WMT_PINCTRL_BANK(0x4C, 0x8C, 0xCC, 0x0C, 0x48C, 0x4CC),         /* 3 */
+       WMT_PINCTRL_BANK(0x50, 0x90, 0xD0, 0x10, 0x490, 0x4D0),         /* 4 */
+       WMT_PINCTRL_BANK(0x54, 0x94, 0xD4, 0x14, 0x494, 0x4D4),         /* 5 */
+       WMT_PINCTRL_BANK(0x58, 0x98, 0xD8, 0x18, 0x498, 0x4D8),         /* 6 */
+       WMT_PINCTRL_BANK(0x5C, 0x9C, 0xDC, 0x1C, 0x49C, 0x4DC),         /* 7 */
+};
+
+/* Please keep sorted by bank/bit */
+#define WMT_PIN_EXTGPIO0       WMT_PIN(0, 0)
+#define WMT_PIN_EXTGPIO1       WMT_PIN(0, 1)
+#define WMT_PIN_EXTGPIO2       WMT_PIN(0, 2)
+#define WMT_PIN_EXTGPIO3       WMT_PIN(0, 3)
+#define WMT_PIN_EXTGPIO4       WMT_PIN(0, 4)
+#define WMT_PIN_EXTGPIO5       WMT_PIN(0, 5)
+#define WMT_PIN_EXTGPIO6       WMT_PIN(0, 6)
+#define WMT_PIN_EXTGPIO7       WMT_PIN(0, 7)
+#define WMT_PIN_WAKEUP0                WMT_PIN(0, 16)
+#define WMT_PIN_WAKEUP1                WMT_PIN(0, 17)
+#define WMT_PIN_SUSGPIO0       WMT_PIN(0, 21)
+#define WMT_PIN_SD0CD          WMT_PIN(0, 28)
+#define WMT_PIN_SD1CD          WMT_PIN(0, 29)
+#define WMT_PIN_VDOUT0         WMT_PIN(1, 0)
+#define WMT_PIN_VDOUT1         WMT_PIN(1, 1)
+#define WMT_PIN_VDOUT2         WMT_PIN(1, 2)
+#define WMT_PIN_VDOUT3         WMT_PIN(1, 3)
+#define WMT_PIN_VDOUT4         WMT_PIN(1, 4)
+#define WMT_PIN_VDOUT5         WMT_PIN(1, 5)
+#define WMT_PIN_VDOUT6         WMT_PIN(1, 6)
+#define WMT_PIN_VDOUT7         WMT_PIN(1, 7)
+#define WMT_PIN_VDOUT8         WMT_PIN(1, 8)
+#define WMT_PIN_VDOUT9         WMT_PIN(1, 9)
+#define WMT_PIN_VDOUT10                WMT_PIN(1, 10)
+#define WMT_PIN_VDOUT11                WMT_PIN(1, 11)
+#define WMT_PIN_VDOUT12                WMT_PIN(1, 12)
+#define WMT_PIN_VDOUT13                WMT_PIN(1, 13)
+#define WMT_PIN_VDOUT14                WMT_PIN(1, 14)
+#define WMT_PIN_VDOUT15                WMT_PIN(1, 15)
+#define WMT_PIN_VDOUT16                WMT_PIN(1, 16)
+#define WMT_PIN_VDOUT17                WMT_PIN(1, 17)
+#define WMT_PIN_VDOUT18                WMT_PIN(1, 18)
+#define WMT_PIN_VDOUT19                WMT_PIN(1, 19)
+#define WMT_PIN_VDOUT20                WMT_PIN(1, 20)
+#define WMT_PIN_VDOUT21                WMT_PIN(1, 21)
+#define WMT_PIN_VDOUT22                WMT_PIN(1, 22)
+#define WMT_PIN_VDOUT23                WMT_PIN(1, 23)
+#define WMT_PIN_VDIN0          WMT_PIN(2, 0)
+#define WMT_PIN_VDIN1          WMT_PIN(2, 1)
+#define WMT_PIN_VDIN2          WMT_PIN(2, 2)
+#define WMT_PIN_VDIN3          WMT_PIN(2, 3)
+#define WMT_PIN_VDIN4          WMT_PIN(2, 4)
+#define WMT_PIN_VDIN5          WMT_PIN(2, 5)
+#define WMT_PIN_VDIN6          WMT_PIN(2, 6)
+#define WMT_PIN_VDIN7          WMT_PIN(2, 7)
+#define WMT_PIN_I2C1SCL                WMT_PIN(2, 12)
+#define WMT_PIN_I2C1SDA                WMT_PIN(2, 13)
+#define WMT_PIN_SPI0MOSI       WMT_PIN(2, 24)
+#define WMT_PIN_SPI0MISO       WMT_PIN(2, 25)
+#define WMT_PIN_SPI0SS0                WMT_PIN(2, 26)
+#define WMT_PIN_SPI0CLK                WMT_PIN(2, 27)
+#define WMT_PIN_SD0DATA0       WMT_PIN(3, 8)
+#define WMT_PIN_SD0DATA1       WMT_PIN(3, 9)
+#define WMT_PIN_SD0DATA2       WMT_PIN(3, 10)
+#define WMT_PIN_SD0DATA3       WMT_PIN(3, 11)
+#define WMT_PIN_SD0CLK         WMT_PIN(3, 12)
+#define WMT_PIN_SD0WP          WMT_PIN(3, 13)
+#define WMT_PIN_SD0CMD         WMT_PIN(3, 14)
+#define WMT_PIN_SD1DATA0       WMT_PIN(3, 24)
+#define WMT_PIN_SD1DATA1       WMT_PIN(3, 25)
+#define WMT_PIN_SD1DATA2       WMT_PIN(3, 26)
+#define WMT_PIN_SD1DATA3       WMT_PIN(3, 27)
+#define WMT_PIN_SD1DATA4       WMT_PIN(3, 28)
+#define WMT_PIN_SD1DATA5       WMT_PIN(3, 29)
+#define WMT_PIN_SD1DATA6       WMT_PIN(3, 30)
+#define WMT_PIN_SD1DATA7       WMT_PIN(3, 31)
+#define WMT_PIN_I2C0SCL                WMT_PIN(5, 8)
+#define WMT_PIN_I2C0SDA                WMT_PIN(5, 9)
+#define WMT_PIN_UART0RTS       WMT_PIN(5, 16)
+#define WMT_PIN_UART0TXD       WMT_PIN(5, 17)
+#define WMT_PIN_UART0CTS       WMT_PIN(5, 18)
+#define WMT_PIN_UART0RXD       WMT_PIN(5, 19)
+#define WMT_PIN_UART1RTS       WMT_PIN(5, 20)
+#define WMT_PIN_UART1TXD       WMT_PIN(5, 21)
+#define WMT_PIN_UART1CTS       WMT_PIN(5, 22)
+#define WMT_PIN_UART1RXD       WMT_PIN(5, 23)
+#define WMT_PIN_UART2RTS       WMT_PIN(5, 24)
+#define WMT_PIN_UART2TXD       WMT_PIN(5, 25)
+#define WMT_PIN_UART2CTS       WMT_PIN(5, 26)
+#define WMT_PIN_UART2RXD       WMT_PIN(5, 27)
+#define WMT_PIN_UART3RTS       WMT_PIN(5, 28)
+#define WMT_PIN_UART3TXD       WMT_PIN(5, 29)
+#define WMT_PIN_UART3CTS       WMT_PIN(5, 30)
+#define WMT_PIN_UART3RXD       WMT_PIN(5, 31)
+#define WMT_PIN_KPADROW0       WMT_PIN(6, 16)
+#define WMT_PIN_KPADROW1       WMT_PIN(6, 17)
+#define WMT_PIN_KPADCOL0       WMT_PIN(6, 18)
+#define WMT_PIN_KPADCOL1       WMT_PIN(6, 19)
+#define WMT_PIN_SD1CLK         WMT_PIN(7, 0)
+#define WMT_PIN_SD1CMD         WMT_PIN(7, 1)
+#define WMT_PIN_SD1WP          WMT_PIN(7, 13)
+
+static const struct pinctrl_pin_desc wm8650_pins[] = {
+       PINCTRL_PIN(WMT_PIN_EXTGPIO0, "extgpio0"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO1, "extgpio1"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO2, "extgpio2"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO3, "extgpio3"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO4, "extgpio4"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO5, "extgpio5"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO6, "extgpio6"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO7, "extgpio7"),
+       PINCTRL_PIN(WMT_PIN_WAKEUP0, "wakeup0"),
+       PINCTRL_PIN(WMT_PIN_WAKEUP1, "wakeup1"),
+       PINCTRL_PIN(WMT_PIN_SUSGPIO0, "susgpio0"),
+       PINCTRL_PIN(WMT_PIN_SD0CD, "sd0_cd"),
+       PINCTRL_PIN(WMT_PIN_SD1CD, "sd1_cd"),
+       PINCTRL_PIN(WMT_PIN_VDOUT0, "vdout0"),
+       PINCTRL_PIN(WMT_PIN_VDOUT1, "vdout1"),
+       PINCTRL_PIN(WMT_PIN_VDOUT2, "vdout2"),
+       PINCTRL_PIN(WMT_PIN_VDOUT3, "vdout3"),
+       PINCTRL_PIN(WMT_PIN_VDOUT4, "vdout4"),
+       PINCTRL_PIN(WMT_PIN_VDOUT5, "vdout5"),
+       PINCTRL_PIN(WMT_PIN_VDOUT6, "vdout6"),
+       PINCTRL_PIN(WMT_PIN_VDOUT7, "vdout7"),
+       PINCTRL_PIN(WMT_PIN_VDOUT8, "vdout8"),
+       PINCTRL_PIN(WMT_PIN_VDOUT9, "vdout9"),
+       PINCTRL_PIN(WMT_PIN_VDOUT10, "vdout10"),
+       PINCTRL_PIN(WMT_PIN_VDOUT11, "vdout11"),
+       PINCTRL_PIN(WMT_PIN_VDOUT12, "vdout12"),
+       PINCTRL_PIN(WMT_PIN_VDOUT13, "vdout13"),
+       PINCTRL_PIN(WMT_PIN_VDOUT14, "vdout14"),
+       PINCTRL_PIN(WMT_PIN_VDOUT15, "vdout15"),
+       PINCTRL_PIN(WMT_PIN_VDOUT16, "vdout16"),
+       PINCTRL_PIN(WMT_PIN_VDOUT17, "vdout17"),
+       PINCTRL_PIN(WMT_PIN_VDOUT18, "vdout18"),
+       PINCTRL_PIN(WMT_PIN_VDOUT19, "vdout19"),
+       PINCTRL_PIN(WMT_PIN_VDOUT20, "vdout20"),
+       PINCTRL_PIN(WMT_PIN_VDOUT21, "vdout21"),
+       PINCTRL_PIN(WMT_PIN_VDOUT22, "vdout22"),
+       PINCTRL_PIN(WMT_PIN_VDOUT23, "vdout23"),
+       PINCTRL_PIN(WMT_PIN_VDIN0, "vdin0"),
+       PINCTRL_PIN(WMT_PIN_VDIN1, "vdin1"),
+       PINCTRL_PIN(WMT_PIN_VDIN2, "vdin2"),
+       PINCTRL_PIN(WMT_PIN_VDIN3, "vdin3"),
+       PINCTRL_PIN(WMT_PIN_VDIN4, "vdin4"),
+       PINCTRL_PIN(WMT_PIN_VDIN5, "vdin5"),
+       PINCTRL_PIN(WMT_PIN_VDIN6, "vdin6"),
+       PINCTRL_PIN(WMT_PIN_VDIN7, "vdin7"),
+       PINCTRL_PIN(WMT_PIN_I2C1SCL, "i2c1_scl"),
+       PINCTRL_PIN(WMT_PIN_I2C1SDA, "i2c1_sda"),
+       PINCTRL_PIN(WMT_PIN_SPI0MOSI, "spi0_mosi"),
+       PINCTRL_PIN(WMT_PIN_SPI0MISO, "spi0_miso"),
+       PINCTRL_PIN(WMT_PIN_SPI0SS0, "spi0_ss0"),
+       PINCTRL_PIN(WMT_PIN_SPI0CLK, "spi0_clk"),
+       PINCTRL_PIN(WMT_PIN_SD0DATA0, "sd0_data0"),
+       PINCTRL_PIN(WMT_PIN_SD0DATA1, "sd0_data1"),
+       PINCTRL_PIN(WMT_PIN_SD0DATA2, "sd0_data2"),
+       PINCTRL_PIN(WMT_PIN_SD0DATA3, "sd0_data3"),
+       PINCTRL_PIN(WMT_PIN_SD0CLK, "sd0_clk"),
+       PINCTRL_PIN(WMT_PIN_SD0WP, "sd0_wp"),
+       PINCTRL_PIN(WMT_PIN_SD0CMD, "sd0_cmd"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA0, "sd1_data0"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA1, "sd1_data1"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA2, "sd1_data2"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA3, "sd1_data3"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA4, "sd1_data4"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA5, "sd1_data5"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA6, "sd1_data6"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA7, "sd1_data7"),
+       PINCTRL_PIN(WMT_PIN_I2C0SCL, "i2c0_scl"),
+       PINCTRL_PIN(WMT_PIN_I2C0SDA, "i2c0_sda"),
+       PINCTRL_PIN(WMT_PIN_UART0RTS, "uart0_rts"),
+       PINCTRL_PIN(WMT_PIN_UART0TXD, "uart0_txd"),
+       PINCTRL_PIN(WMT_PIN_UART0CTS, "uart0_cts"),
+       PINCTRL_PIN(WMT_PIN_UART0RXD, "uart0_rxd"),
+       PINCTRL_PIN(WMT_PIN_UART1RTS, "uart1_rts"),
+       PINCTRL_PIN(WMT_PIN_UART1TXD, "uart1_txd"),
+       PINCTRL_PIN(WMT_PIN_UART1CTS, "uart1_cts"),
+       PINCTRL_PIN(WMT_PIN_UART1RXD, "uart1_rxd"),
+       PINCTRL_PIN(WMT_PIN_UART2RTS, "uart2_rts"),
+       PINCTRL_PIN(WMT_PIN_UART2TXD, "uart2_txd"),
+       PINCTRL_PIN(WMT_PIN_UART2CTS, "uart2_cts"),
+       PINCTRL_PIN(WMT_PIN_UART2RXD, "uart2_rxd"),
+       PINCTRL_PIN(WMT_PIN_UART3RTS, "uart3_rts"),
+       PINCTRL_PIN(WMT_PIN_UART3TXD, "uart3_txd"),
+       PINCTRL_PIN(WMT_PIN_UART3CTS, "uart3_cts"),
+       PINCTRL_PIN(WMT_PIN_UART3RXD, "uart3_rxd"),
+       PINCTRL_PIN(WMT_PIN_KPADROW0, "kpadrow0"),
+       PINCTRL_PIN(WMT_PIN_KPADROW1, "kpadrow1"),
+       PINCTRL_PIN(WMT_PIN_KPADCOL0, "kpadcol0"),
+       PINCTRL_PIN(WMT_PIN_KPADCOL1, "kpadcol1"),
+       PINCTRL_PIN(WMT_PIN_SD1CLK, "sd1_clk"),
+       PINCTRL_PIN(WMT_PIN_SD1CMD, "sd1_cmd"),
+       PINCTRL_PIN(WMT_PIN_SD1WP, "sd1_wp"),
+};
+
+/* Order of these names must match the above list */
+static const char * const wm8650_groups[] = {
+       "extgpio0",
+       "extgpio1",
+       "extgpio2",
+       "extgpio3",
+       "extgpio4",
+       "extgpio5",
+       "extgpio6",
+       "extgpio7",
+       "wakeup0",
+       "wakeup1",
+       "susgpio0",
+       "sd0_cd",
+       "sd1_cd",
+       "vdout0",
+       "vdout1",
+       "vdout2",
+       "vdout3",
+       "vdout4",
+       "vdout5",
+       "vdout6",
+       "vdout7",
+       "vdout8",
+       "vdout9",
+       "vdout10",
+       "vdout11",
+       "vdout12",
+       "vdout13",
+       "vdout14",
+       "vdout15",
+       "vdout16",
+       "vdout17",
+       "vdout18",
+       "vdout19",
+       "vdout20",
+       "vdout21",
+       "vdout22",
+       "vdout23",
+       "vdin0",
+       "vdin1",
+       "vdin2",
+       "vdin3",
+       "vdin4",
+       "vdin5",
+       "vdin6",
+       "vdin7",
+       "i2c1_scl",
+       "i2c1_sda",
+       "spi0_mosi",
+       "spi0_miso",
+       "spi0_ss0",
+       "spi0_clk",
+       "sd0_data0",
+       "sd0_data1",
+       "sd0_data2",
+       "sd0_data3",
+       "sd0_clk",
+       "sd0_wp",
+       "sd0_cmd",
+       "sd1_data0",
+       "sd1_data1",
+       "sd1_data2",
+       "sd1_data3",
+       "sd1_data4",
+       "sd1_data5",
+       "sd1_data6",
+       "sd1_data7",
+       "i2c0_scl",
+       "i2c0_sda",
+       "uart0_rts",
+       "uart0_txd",
+       "uart0_cts",
+       "uart0_rxd",
+       "uart1_rts",
+       "uart1_txd",
+       "uart1_cts",
+       "uart1_rxd",
+       "uart2_rts",
+       "uart2_txd",
+       "uart2_cts",
+       "uart2_rxd",
+       "uart3_rts",
+       "uart3_txd",
+       "uart3_cts",
+       "uart3_rxd",
+       "kpadrow0",
+       "kpadrow1",
+       "kpadcol0",
+       "kpadcol1",
+       "sd1_clk",
+       "sd1_cmd",
+       "sd1_wp",
+};
+
+static int wm8650_pinctrl_probe(struct platform_device *pdev)
+{
+       struct wmt_pinctrl_data *data;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data) {
+               dev_err(&pdev->dev, "failed to allocate data\n");
+               return -ENOMEM;
+       }
+
+       data->banks = wm8650_banks;
+       data->nbanks = ARRAY_SIZE(wm8650_banks);
+       data->pins = wm8650_pins;
+       data->npins = ARRAY_SIZE(wm8650_pins);
+       data->groups = wm8650_groups;
+       data->ngroups = ARRAY_SIZE(wm8650_groups);
+
+       return wmt_pinctrl_probe(pdev, data);
+}
+
+static int wm8650_pinctrl_remove(struct platform_device *pdev)
+{
+       return wmt_pinctrl_remove(pdev);
+}
+
+static struct of_device_id wmt_pinctrl_of_match[] = {
+       { .compatible = "wm,wm8650-pinctrl" },
+       { /* sentinel */ },
+};
+
+static struct platform_driver wmt_pinctrl_driver = {
+       .probe  = wm8650_pinctrl_probe,
+       .remove = wm8650_pinctrl_remove,
+       .driver = {
+               .name   = "pinctrl-wm8650",
+               .owner  = THIS_MODULE,
+               .of_match_table = wmt_pinctrl_of_match,
+       },
+};
+
+module_platform_driver(wmt_pinctrl_driver);
+
+MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
+MODULE_DESCRIPTION("Wondermedia WM8650 Pincontrol driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8750.c b/drivers/pinctrl/vt8500/pinctrl-wm8750.c
new file mode 100644 (file)
index 0000000..b964cc5
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ * Pinctrl data for Wondermedia WM8750 SoC
+ *
+ * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "pinctrl-wmt.h"
+
+/*
+ * Describe the register offsets within the GPIO memory space
+ * The dedicated external GPIO's should always be listed in bank 0
+ * so they are exported in the 0..31 range which is what users
+ * expect.
+ *
+ * Do not reorder these banks as it will change the pin numbering
+ */
+static const struct wmt_pinctrl_bank_registers wm8750_banks[] = {
+       WMT_PINCTRL_BANK(0x40, 0x80, 0xC0, 0x00, 0x480, 0x4C0), /* 0 */
+       WMT_PINCTRL_BANK(0x44, 0x84, 0xC4, 0x04, 0x484, 0x4C4), /* 1 */
+       WMT_PINCTRL_BANK(0x48, 0x88, 0xC8, 0x08, 0x488, 0x4C8), /* 2 */
+       WMT_PINCTRL_BANK(0x4C, 0x8C, 0xCC, 0x0C, 0x48C, 0x4CC), /* 3 */
+       WMT_PINCTRL_BANK(0x50, 0x90, 0xD0, 0x10, 0x490, 0x4D0), /* 4 */
+       WMT_PINCTRL_BANK(0x54, 0x94, 0xD4, 0x14, 0x494, 0x4D4), /* 5 */
+       WMT_PINCTRL_BANK(0x58, 0x98, 0xD8, 0x18, 0x498, 0x4D8), /* 6 */
+       WMT_PINCTRL_BANK(0x5C, 0x9C, 0xDC, 0x1C, 0x49C, 0x4DC), /* 7 */
+       WMT_PINCTRL_BANK(0x60, 0xA0, 0xE0, 0x20, 0x4A0, 0x4E0), /* 8 */
+       WMT_PINCTRL_BANK(0x70, 0xB0, 0xF0, 0x30, 0x4B0, 0x4F0), /* 9 */
+       WMT_PINCTRL_BANK(0x7C, 0xBC, 0xDC, 0x3C, 0x4BC, 0x4FC), /* 10 */
+};
+
+/* Please keep sorted by bank/bit */
+#define WMT_PIN_EXTGPIO0       WMT_PIN(0, 0)
+#define WMT_PIN_EXTGPIO1       WMT_PIN(0, 1)
+#define WMT_PIN_EXTGPIO2       WMT_PIN(0, 2)
+#define WMT_PIN_EXTGPIO3       WMT_PIN(0, 3)
+#define WMT_PIN_EXTGPIO4       WMT_PIN(0, 4)
+#define WMT_PIN_EXTGPIO5       WMT_PIN(0, 5)
+#define WMT_PIN_EXTGPIO6       WMT_PIN(0, 6)
+#define WMT_PIN_EXTGPIO7       WMT_PIN(0, 7)
+#define WMT_PIN_WAKEUP0                WMT_PIN(0, 16)
+#define WMT_PIN_WAKEUP1                WMT_PIN(0, 16)
+#define WMT_PIN_SD0CD          WMT_PIN(0, 28)
+#define WMT_PIN_VDOUT0         WMT_PIN(1, 0)
+#define WMT_PIN_VDOUT1         WMT_PIN(1, 1)
+#define WMT_PIN_VDOUT2         WMT_PIN(1, 2)
+#define WMT_PIN_VDOUT3         WMT_PIN(1, 3)
+#define WMT_PIN_VDOUT4         WMT_PIN(1, 4)
+#define WMT_PIN_VDOUT5         WMT_PIN(1, 5)
+#define WMT_PIN_VDOUT6         WMT_PIN(1, 6)
+#define WMT_PIN_VDOUT7         WMT_PIN(1, 7)
+#define WMT_PIN_VDOUT8         WMT_PIN(1, 8)
+#define WMT_PIN_VDOUT9         WMT_PIN(1, 9)
+#define WMT_PIN_VDOUT10                WMT_PIN(1, 10)
+#define WMT_PIN_VDOUT11                WMT_PIN(1, 11)
+#define WMT_PIN_VDOUT12                WMT_PIN(1, 12)
+#define WMT_PIN_VDOUT13                WMT_PIN(1, 13)
+#define WMT_PIN_VDOUT14                WMT_PIN(1, 14)
+#define WMT_PIN_VDOUT15                WMT_PIN(1, 15)
+#define WMT_PIN_VDOUT16                WMT_PIN(1, 16)
+#define WMT_PIN_VDOUT17                WMT_PIN(1, 17)
+#define WMT_PIN_VDOUT18                WMT_PIN(1, 18)
+#define WMT_PIN_VDOUT19                WMT_PIN(1, 19)
+#define WMT_PIN_VDOUT20                WMT_PIN(1, 20)
+#define WMT_PIN_VDOUT21                WMT_PIN(1, 21)
+#define WMT_PIN_VDOUT22                WMT_PIN(1, 22)
+#define WMT_PIN_VDOUT23                WMT_PIN(1, 23)
+#define WMT_PIN_VDIN0          WMT_PIN(2, 0)
+#define WMT_PIN_VDIN1          WMT_PIN(2, 1)
+#define WMT_PIN_VDIN2          WMT_PIN(2, 2)
+#define WMT_PIN_VDIN3          WMT_PIN(2, 3)
+#define WMT_PIN_VDIN4          WMT_PIN(2, 4)
+#define WMT_PIN_VDIN5          WMT_PIN(2, 5)
+#define WMT_PIN_VDIN6          WMT_PIN(2, 6)
+#define WMT_PIN_VDIN7          WMT_PIN(2, 7)
+#define WMT_PIN_SPI0_MOSI      WMT_PIN(2, 24)
+#define WMT_PIN_SPI0_MISO      WMT_PIN(2, 25)
+#define WMT_PIN_SPI0_SS                WMT_PIN(2, 26)
+#define WMT_PIN_SPI0_CLK       WMT_PIN(2, 27)
+#define WMT_PIN_SPI0_SSB       WMT_PIN(2, 28)
+#define WMT_PIN_SD0CLK         WMT_PIN(3, 17)
+#define WMT_PIN_SD0CMD         WMT_PIN(3, 18)
+#define WMT_PIN_SD0WP          WMT_PIN(3, 19)
+#define WMT_PIN_SD0DATA0       WMT_PIN(3, 20)
+#define WMT_PIN_SD0DATA1       WMT_PIN(3, 21)
+#define WMT_PIN_SD0DATA2       WMT_PIN(3, 22)
+#define WMT_PIN_SD0DATA3       WMT_PIN(3, 23)
+#define WMT_PIN_SD1DATA0       WMT_PIN(3, 24)
+#define WMT_PIN_SD1DATA1       WMT_PIN(3, 25)
+#define WMT_PIN_SD1DATA2       WMT_PIN(3, 26)
+#define WMT_PIN_SD1DATA3       WMT_PIN(3, 27)
+#define WMT_PIN_SD1DATA4       WMT_PIN(3, 28)
+#define WMT_PIN_SD1DATA5       WMT_PIN(3, 29)
+#define WMT_PIN_SD1DATA6       WMT_PIN(3, 30)
+#define WMT_PIN_SD1DATA7       WMT_PIN(3, 31)
+#define WMT_PIN_I2C0_SCL       WMT_PIN(5, 8)
+#define WMT_PIN_I2C0_SDA       WMT_PIN(5, 9)
+#define WMT_PIN_I2C1_SCL       WMT_PIN(5, 10)
+#define WMT_PIN_I2C1_SDA       WMT_PIN(5, 11)
+#define WMT_PIN_I2C2_SCL       WMT_PIN(5, 12)
+#define WMT_PIN_I2C2_SDA       WMT_PIN(5, 13)
+#define WMT_PIN_UART0_RTS      WMT_PIN(5, 16)
+#define WMT_PIN_UART0_TXD      WMT_PIN(5, 17)
+#define WMT_PIN_UART0_CTS      WMT_PIN(5, 18)
+#define WMT_PIN_UART0_RXD      WMT_PIN(5, 19)
+#define WMT_PIN_UART1_RTS      WMT_PIN(5, 20)
+#define WMT_PIN_UART1_TXD      WMT_PIN(5, 21)
+#define WMT_PIN_UART1_CTS      WMT_PIN(5, 22)
+#define WMT_PIN_UART1_RXD      WMT_PIN(5, 23)
+#define WMT_PIN_UART2_RTS      WMT_PIN(5, 24)
+#define WMT_PIN_UART2_TXD      WMT_PIN(5, 25)
+#define WMT_PIN_UART2_CTS      WMT_PIN(5, 26)
+#define WMT_PIN_UART2_RXD      WMT_PIN(5, 27)
+#define WMT_PIN_UART3_RTS      WMT_PIN(5, 28)
+#define WMT_PIN_UART3_TXD      WMT_PIN(5, 29)
+#define WMT_PIN_UART3_CTS      WMT_PIN(5, 30)
+#define WMT_PIN_UART3_RXD      WMT_PIN(5, 31)
+#define WMT_PIN_SD2CD          WMT_PIN(6, 0)
+#define WMT_PIN_SD2DATA3       WMT_PIN(6, 1)
+#define WMT_PIN_SD2DATA0       WMT_PIN(6, 2)
+#define WMT_PIN_SD2WP          WMT_PIN(6, 3)
+#define WMT_PIN_SD2DATA1       WMT_PIN(6, 4)
+#define WMT_PIN_SD2DATA2       WMT_PIN(6, 5)
+#define WMT_PIN_SD2CMD         WMT_PIN(6, 6)
+#define WMT_PIN_SD2CLK         WMT_PIN(6, 7)
+#define WMT_PIN_SD2PWR         WMT_PIN(6, 9)
+#define WMT_PIN_SD1CLK         WMT_PIN(7, 0)
+#define WMT_PIN_SD1CMD         WMT_PIN(7, 1)
+#define WMT_PIN_SD1PWR         WMT_PIN(7, 10)
+#define WMT_PIN_SD1WP          WMT_PIN(7, 11)
+#define WMT_PIN_SD1CD          WMT_PIN(7, 12)
+#define WMT_PIN_SPI0SS3                WMT_PIN(7, 24)
+#define WMT_PIN_SPI0SS2                WMT_PIN(7, 25)
+#define WMT_PIN_PWMOUT1                WMT_PIN(7, 26)
+#define WMT_PIN_PWMOUT0                WMT_PIN(7, 27)
+
+static const struct pinctrl_pin_desc wm8750_pins[] = {
+       PINCTRL_PIN(WMT_PIN_EXTGPIO0, "extgpio0"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO1, "extgpio1"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO2, "extgpio2"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO3, "extgpio3"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO4, "extgpio4"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO5, "extgpio5"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO6, "extgpio6"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO7, "extgpio7"),
+       PINCTRL_PIN(WMT_PIN_WAKEUP0, "wakeup0"),
+       PINCTRL_PIN(WMT_PIN_WAKEUP1, "wakeup1"),
+       PINCTRL_PIN(WMT_PIN_SD0CD, "sd0_cd"),
+       PINCTRL_PIN(WMT_PIN_VDOUT0, "vdout0"),
+       PINCTRL_PIN(WMT_PIN_VDOUT1, "vdout1"),
+       PINCTRL_PIN(WMT_PIN_VDOUT2, "vdout2"),
+       PINCTRL_PIN(WMT_PIN_VDOUT3, "vdout3"),
+       PINCTRL_PIN(WMT_PIN_VDOUT4, "vdout4"),
+       PINCTRL_PIN(WMT_PIN_VDOUT5, "vdout5"),
+       PINCTRL_PIN(WMT_PIN_VDOUT6, "vdout6"),
+       PINCTRL_PIN(WMT_PIN_VDOUT7, "vdout7"),
+       PINCTRL_PIN(WMT_PIN_VDOUT8, "vdout8"),
+       PINCTRL_PIN(WMT_PIN_VDOUT9, "vdout9"),
+       PINCTRL_PIN(WMT_PIN_VDOUT10, "vdout10"),
+       PINCTRL_PIN(WMT_PIN_VDOUT11, "vdout11"),
+       PINCTRL_PIN(WMT_PIN_VDOUT12, "vdout12"),
+       PINCTRL_PIN(WMT_PIN_VDOUT13, "vdout13"),
+       PINCTRL_PIN(WMT_PIN_VDOUT14, "vdout14"),
+       PINCTRL_PIN(WMT_PIN_VDOUT15, "vdout15"),
+       PINCTRL_PIN(WMT_PIN_VDOUT16, "vdout16"),
+       PINCTRL_PIN(WMT_PIN_VDOUT17, "vdout17"),
+       PINCTRL_PIN(WMT_PIN_VDOUT18, "vdout18"),
+       PINCTRL_PIN(WMT_PIN_VDOUT19, "vdout19"),
+       PINCTRL_PIN(WMT_PIN_VDOUT20, "vdout20"),
+       PINCTRL_PIN(WMT_PIN_VDOUT21, "vdout21"),
+       PINCTRL_PIN(WMT_PIN_VDOUT22, "vdout22"),
+       PINCTRL_PIN(WMT_PIN_VDOUT23, "vdout23"),
+       PINCTRL_PIN(WMT_PIN_VDIN0, "vdin0"),
+       PINCTRL_PIN(WMT_PIN_VDIN1, "vdin1"),
+       PINCTRL_PIN(WMT_PIN_VDIN2, "vdin2"),
+       PINCTRL_PIN(WMT_PIN_VDIN3, "vdin3"),
+       PINCTRL_PIN(WMT_PIN_VDIN4, "vdin4"),
+       PINCTRL_PIN(WMT_PIN_VDIN5, "vdin5"),
+       PINCTRL_PIN(WMT_PIN_VDIN6, "vdin6"),
+       PINCTRL_PIN(WMT_PIN_VDIN7, "vdin7"),
+       PINCTRL_PIN(WMT_PIN_SPI0_MOSI, "spi0_mosi"),
+       PINCTRL_PIN(WMT_PIN_SPI0_MISO, "spi0_miso"),
+       PINCTRL_PIN(WMT_PIN_SPI0_SS, "spi0_ss"),
+       PINCTRL_PIN(WMT_PIN_SPI0_CLK, "spi0_clk"),
+       PINCTRL_PIN(WMT_PIN_SPI0_SSB, "spi0_ssb"),
+       PINCTRL_PIN(WMT_PIN_SD0CLK, "sd0_clk"),
+       PINCTRL_PIN(WMT_PIN_SD0CMD, "sd0_cmd"),
+       PINCTRL_PIN(WMT_PIN_SD0WP, "sd0_wp"),
+       PINCTRL_PIN(WMT_PIN_SD0DATA0, "sd0_data0"),
+       PINCTRL_PIN(WMT_PIN_SD0DATA1, "sd0_data1"),
+       PINCTRL_PIN(WMT_PIN_SD0DATA2, "sd0_data2"),
+       PINCTRL_PIN(WMT_PIN_SD0DATA3, "sd0_data3"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA0, "sd1_data0"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA1, "sd1_data1"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA2, "sd1_data2"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA3, "sd1_data3"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA4, "sd1_data4"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA5, "sd1_data5"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA6, "sd1_data6"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA7, "sd1_data7"),
+       PINCTRL_PIN(WMT_PIN_I2C0_SCL, "i2c0_scl"),
+       PINCTRL_PIN(WMT_PIN_I2C0_SDA, "i2c0_sda"),
+       PINCTRL_PIN(WMT_PIN_I2C1_SCL, "i2c1_scl"),
+       PINCTRL_PIN(WMT_PIN_I2C1_SDA, "i2c1_sda"),
+       PINCTRL_PIN(WMT_PIN_I2C2_SCL, "i2c2_scl"),
+       PINCTRL_PIN(WMT_PIN_I2C2_SDA, "i2c2_sda"),
+       PINCTRL_PIN(WMT_PIN_UART0_RTS, "uart0_rts"),
+       PINCTRL_PIN(WMT_PIN_UART0_TXD, "uart0_txd"),
+       PINCTRL_PIN(WMT_PIN_UART0_CTS, "uart0_cts"),
+       PINCTRL_PIN(WMT_PIN_UART0_RXD, "uart0_rxd"),
+       PINCTRL_PIN(WMT_PIN_UART1_RTS, "uart1_rts"),
+       PINCTRL_PIN(WMT_PIN_UART1_TXD, "uart1_txd"),
+       PINCTRL_PIN(WMT_PIN_UART1_CTS, "uart1_cts"),
+       PINCTRL_PIN(WMT_PIN_UART1_RXD, "uart1_rxd"),
+       PINCTRL_PIN(WMT_PIN_UART2_RTS, "uart2_rts"),
+       PINCTRL_PIN(WMT_PIN_UART2_TXD, "uart2_txd"),
+       PINCTRL_PIN(WMT_PIN_UART2_CTS, "uart2_cts"),
+       PINCTRL_PIN(WMT_PIN_UART2_RXD, "uart2_rxd"),
+       PINCTRL_PIN(WMT_PIN_UART3_RTS, "uart3_rts"),
+       PINCTRL_PIN(WMT_PIN_UART3_TXD, "uart3_txd"),
+       PINCTRL_PIN(WMT_PIN_UART3_CTS, "uart3_cts"),
+       PINCTRL_PIN(WMT_PIN_UART3_RXD, "uart3_rxd"),
+       PINCTRL_PIN(WMT_PIN_SD2CD, "sd2_cd"),
+       PINCTRL_PIN(WMT_PIN_SD2DATA3, "sd2_data3"),
+       PINCTRL_PIN(WMT_PIN_SD2DATA0, "sd2_data0"),
+       PINCTRL_PIN(WMT_PIN_SD2WP, "sd2_wp"),
+       PINCTRL_PIN(WMT_PIN_SD2DATA1, "sd2_data1"),
+       PINCTRL_PIN(WMT_PIN_SD2DATA2, "sd2_data2"),
+       PINCTRL_PIN(WMT_PIN_SD2CMD, "sd2_cmd"),
+       PINCTRL_PIN(WMT_PIN_SD2CLK, "sd2_clk"),
+       PINCTRL_PIN(WMT_PIN_SD2PWR, "sd2_pwr"),
+       PINCTRL_PIN(WMT_PIN_SD1CLK, "sd1_clk"),
+       PINCTRL_PIN(WMT_PIN_SD1CMD, "sd1_cmd"),
+       PINCTRL_PIN(WMT_PIN_SD1PWR, "sd1_pwr"),
+       PINCTRL_PIN(WMT_PIN_SD1WP, "sd1_wp"),
+       PINCTRL_PIN(WMT_PIN_SD1CD, "sd1_cd"),
+       PINCTRL_PIN(WMT_PIN_SPI0SS3, "spi0_ss3"),
+       PINCTRL_PIN(WMT_PIN_SPI0SS2, "spi0_ss2"),
+       PINCTRL_PIN(WMT_PIN_PWMOUT1, "pwmout1"),
+       PINCTRL_PIN(WMT_PIN_PWMOUT0, "pwmout0"),
+};
+
+/* Order of these names must match the above list */
+static const char * const wm8750_groups[] = {
+       "extgpio0",
+       "extgpio1",
+       "extgpio2",
+       "extgpio3",
+       "extgpio4",
+       "extgpio5",
+       "extgpio6",
+       "extgpio7",
+       "wakeup0",
+       "wakeup1",
+       "sd0_cd",
+       "vdout0",
+       "vdout1",
+       "vdout2",
+       "vdout3",
+       "vdout4",
+       "vdout5",
+       "vdout6",
+       "vdout7",
+       "vdout8",
+       "vdout9",
+       "vdout10",
+       "vdout11",
+       "vdout12",
+       "vdout13",
+       "vdout14",
+       "vdout15",
+       "vdout16",
+       "vdout17",
+       "vdout18",
+       "vdout19",
+       "vdout20",
+       "vdout21",
+       "vdout22",
+       "vdout23",
+       "vdin0",
+       "vdin1",
+       "vdin2",
+       "vdin3",
+       "vdin4",
+       "vdin5",
+       "vdin6",
+       "vdin7",
+       "spi0_mosi",
+       "spi0_miso",
+       "spi0_ss",
+       "spi0_clk",
+       "spi0_ssb",
+       "sd0_clk",
+       "sd0_cmd",
+       "sd0_wp",
+       "sd0_data0",
+       "sd0_data1",
+       "sd0_data2",
+       "sd0_data3",
+       "sd1_data0",
+       "sd1_data1",
+       "sd1_data2",
+       "sd1_data3",
+       "sd1_data4",
+       "sd1_data5",
+       "sd1_data6",
+       "sd1_data7",
+       "i2c0_scl",
+       "i2c0_sda",
+       "i2c1_scl",
+       "i2c1_sda",
+       "i2c2_scl",
+       "i2c2_sda",
+       "uart0_rts",
+       "uart0_txd",
+       "uart0_cts",
+       "uart0_rxd",
+       "uart1_rts",
+       "uart1_txd",
+       "uart1_cts",
+       "uart1_rxd",
+       "uart2_rts",
+       "uart2_txd",
+       "uart2_cts",
+       "uart2_rxd",
+       "uart3_rts",
+       "uart3_txd",
+       "uart3_cts",
+       "uart3_rxd",
+       "sd2_cd",
+       "sd2_data3",
+       "sd2_data0",
+       "sd2_wp",
+       "sd2_data1",
+       "sd2_data2",
+       "sd2_cmd",
+       "sd2_clk",
+       "sd2_pwr",
+       "sd1_clk",
+       "sd1_cmd",
+       "sd1_pwr",
+       "sd1_wp",
+       "sd1_cd",
+       "spi0_ss3",
+       "spi0_ss2",
+       "pwmout1",
+       "pwmout0",
+};
+
+static int wm8750_pinctrl_probe(struct platform_device *pdev)
+{
+       struct wmt_pinctrl_data *data;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data) {
+               dev_err(&pdev->dev, "failed to allocate data\n");
+               return -ENOMEM;
+       }
+
+       data->banks = wm8750_banks;
+       data->nbanks = ARRAY_SIZE(wm8750_banks);
+       data->pins = wm8750_pins;
+       data->npins = ARRAY_SIZE(wm8750_pins);
+       data->groups = wm8750_groups;
+       data->ngroups = ARRAY_SIZE(wm8750_groups);
+
+       return wmt_pinctrl_probe(pdev, data);
+}
+
+static int wm8750_pinctrl_remove(struct platform_device *pdev)
+{
+       return wmt_pinctrl_remove(pdev);
+}
+
+static struct of_device_id wmt_pinctrl_of_match[] = {
+       { .compatible = "wm,wm8750-pinctrl" },
+       { /* sentinel */ },
+};
+
+static struct platform_driver wmt_pinctrl_driver = {
+       .probe  = wm8750_pinctrl_probe,
+       .remove = wm8750_pinctrl_remove,
+       .driver = {
+               .name   = "pinctrl-wm8750",
+               .owner  = THIS_MODULE,
+               .of_match_table = wmt_pinctrl_of_match,
+       },
+};
+
+module_platform_driver(wmt_pinctrl_driver);
+
+MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
+MODULE_DESCRIPTION("Wondermedia WM8750 Pincontrol driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8850.c b/drivers/pinctrl/vt8500/pinctrl-wm8850.c
new file mode 100644 (file)
index 0000000..ecadce9
--- /dev/null
@@ -0,0 +1,388 @@
+/*
+ * Pinctrl data for Wondermedia WM8850 SoC
+ *
+ * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "pinctrl-wmt.h"
+
+/*
+ * Describe the register offsets within the GPIO memory space
+ * The dedicated external GPIO's should always be listed in bank 0
+ * so they are exported in the 0..31 range which is what users
+ * expect.
+ *
+ * Do not reorder these banks as it will change the pin numbering
+ */
+static const struct wmt_pinctrl_bank_registers wm8850_banks[] = {
+       WMT_PINCTRL_BANK(0x40, 0x80, 0xC0, 0x00, 0x480, 0x4C0),         /* 0 */
+       WMT_PINCTRL_BANK(0x44, 0x84, 0xC4, 0x04, 0x484, 0x4C4),         /* 1 */
+       WMT_PINCTRL_BANK(0x48, 0x88, 0xC8, 0x08, 0x488, 0x4C8),         /* 2 */
+       WMT_PINCTRL_BANK(0x4C, 0x8C, 0xCC, 0x0C, 0x48C, 0x4CC),         /* 3 */
+       WMT_PINCTRL_BANK(0x50, 0x90, 0xD0, 0x10, 0x490, 0x4D0),         /* 4 */
+       WMT_PINCTRL_BANK(0x54, 0x94, 0xD4, 0x14, 0x494, 0x4D4),         /* 5 */
+       WMT_PINCTRL_BANK(0x58, 0x98, 0xD8, 0x18, 0x498, 0x4D8),         /* 6 */
+       WMT_PINCTRL_BANK(0x5C, 0x9C, 0xDC, 0x1C, 0x49C, 0x4DC),         /* 7 */
+       WMT_PINCTRL_BANK(0x60, 0xA0, 0xE0, 0x20, 0x4A0, 0x4E0),         /* 8 */
+       WMT_PINCTRL_BANK(0x70, 0xB0, 0xF0, 0x30, 0x4B0, 0x4F0),         /* 9 */
+       WMT_PINCTRL_BANK(0x7C, 0xBC, 0xDC, 0x3C, 0x4BC, 0x4FC),         /* 10 */
+};
+
+/* Please keep sorted by bank/bit */
+#define WMT_PIN_EXTGPIO0       WMT_PIN(0, 0)
+#define WMT_PIN_EXTGPIO1       WMT_PIN(0, 1)
+#define WMT_PIN_EXTGPIO2       WMT_PIN(0, 2)
+#define WMT_PIN_EXTGPIO3       WMT_PIN(0, 3)
+#define WMT_PIN_EXTGPIO4       WMT_PIN(0, 4)
+#define WMT_PIN_EXTGPIO5       WMT_PIN(0, 5)
+#define WMT_PIN_EXTGPIO6       WMT_PIN(0, 6)
+#define WMT_PIN_EXTGPIO7       WMT_PIN(0, 7)
+#define WMT_PIN_WAKEUP0                WMT_PIN(0, 16)
+#define WMT_PIN_WAKEUP1                WMT_PIN(0, 17)
+#define WMT_PIN_WAKEUP2                WMT_PIN(0, 18)
+#define WMT_PIN_WAKEUP3                WMT_PIN(0, 19)
+#define WMT_PIN_SUSGPIO0       WMT_PIN(0, 21)
+#define WMT_PIN_SUSGPIO1       WMT_PIN(0, 22)
+#define WMT_PIN_SD0CD          WMT_PIN(0, 28)
+#define WMT_PIN_VDOUT0         WMT_PIN(1, 0)
+#define WMT_PIN_VDOUT1         WMT_PIN(1, 1)
+#define WMT_PIN_VDOUT2         WMT_PIN(1, 2)
+#define WMT_PIN_VDOUT3         WMT_PIN(1, 3)
+#define WMT_PIN_VDOUT4         WMT_PIN(1, 4)
+#define WMT_PIN_VDOUT5         WMT_PIN(1, 5)
+#define WMT_PIN_VDOUT6         WMT_PIN(1, 6)
+#define WMT_PIN_VDOUT7         WMT_PIN(1, 7)
+#define WMT_PIN_VDOUT8         WMT_PIN(1, 8)
+#define WMT_PIN_VDOUT9         WMT_PIN(1, 9)
+#define WMT_PIN_VDOUT10                WMT_PIN(1, 10)
+#define WMT_PIN_VDOUT11                WMT_PIN(1, 11)
+#define WMT_PIN_VDOUT12                WMT_PIN(1, 12)
+#define WMT_PIN_VDOUT13                WMT_PIN(1, 13)
+#define WMT_PIN_VDOUT14                WMT_PIN(1, 14)
+#define WMT_PIN_VDOUT15                WMT_PIN(1, 15)
+#define WMT_PIN_VDOUT16                WMT_PIN(1, 16)
+#define WMT_PIN_VDOUT17                WMT_PIN(1, 17)
+#define WMT_PIN_VDOUT18                WMT_PIN(1, 18)
+#define WMT_PIN_VDOUT19                WMT_PIN(1, 19)
+#define WMT_PIN_VDOUT20                WMT_PIN(1, 20)
+#define WMT_PIN_VDOUT21                WMT_PIN(1, 21)
+#define WMT_PIN_VDOUT22                WMT_PIN(1, 22)
+#define WMT_PIN_VDOUT23                WMT_PIN(1, 23)
+#define WMT_PIN_VDIN0          WMT_PIN(2, 0)
+#define WMT_PIN_VDIN1          WMT_PIN(2, 1)
+#define WMT_PIN_VDIN2          WMT_PIN(2, 2)
+#define WMT_PIN_VDIN3          WMT_PIN(2, 3)
+#define WMT_PIN_VDIN4          WMT_PIN(2, 4)
+#define WMT_PIN_VDIN5          WMT_PIN(2, 5)
+#define WMT_PIN_VDIN6          WMT_PIN(2, 6)
+#define WMT_PIN_VDIN7          WMT_PIN(2, 7)
+#define WMT_PIN_SPI0_MOSI      WMT_PIN(2, 24)
+#define WMT_PIN_SPI0_MISO      WMT_PIN(2, 25)
+#define WMT_PIN_SPI0_SS                WMT_PIN(2, 26)
+#define WMT_PIN_SPI0_CLK       WMT_PIN(2, 27)
+#define WMT_PIN_SPI0_SSB       WMT_PIN(2, 28)
+#define WMT_PIN_SD0CLK         WMT_PIN(3, 17)
+#define WMT_PIN_SD0CMD         WMT_PIN(3, 18)
+#define WMT_PIN_SD0WP          WMT_PIN(3, 19)
+#define WMT_PIN_SD0DATA0       WMT_PIN(3, 20)
+#define WMT_PIN_SD0DATA1       WMT_PIN(3, 21)
+#define WMT_PIN_SD0DATA2       WMT_PIN(3, 22)
+#define WMT_PIN_SD0DATA3       WMT_PIN(3, 23)
+#define WMT_PIN_SD1DATA0       WMT_PIN(3, 24)
+#define WMT_PIN_SD1DATA1       WMT_PIN(3, 25)
+#define WMT_PIN_SD1DATA2       WMT_PIN(3, 26)
+#define WMT_PIN_SD1DATA3       WMT_PIN(3, 27)
+#define WMT_PIN_SD1DATA4       WMT_PIN(3, 28)
+#define WMT_PIN_SD1DATA5       WMT_PIN(3, 29)
+#define WMT_PIN_SD1DATA6       WMT_PIN(3, 30)
+#define WMT_PIN_SD1DATA7       WMT_PIN(3, 31)
+#define WMT_PIN_I2C0_SCL       WMT_PIN(5, 8)
+#define WMT_PIN_I2C0_SDA       WMT_PIN(5, 9)
+#define WMT_PIN_I2C1_SCL       WMT_PIN(5, 10)
+#define WMT_PIN_I2C1_SDA       WMT_PIN(5, 11)
+#define WMT_PIN_I2C2_SCL       WMT_PIN(5, 12)
+#define WMT_PIN_I2C2_SDA       WMT_PIN(5, 13)
+#define WMT_PIN_UART0_RTS      WMT_PIN(5, 16)
+#define WMT_PIN_UART0_TXD      WMT_PIN(5, 17)
+#define WMT_PIN_UART0_CTS      WMT_PIN(5, 18)
+#define WMT_PIN_UART0_RXD      WMT_PIN(5, 19)
+#define WMT_PIN_UART1_RTS      WMT_PIN(5, 20)
+#define WMT_PIN_UART1_TXD      WMT_PIN(5, 21)
+#define WMT_PIN_UART1_CTS      WMT_PIN(5, 22)
+#define WMT_PIN_UART1_RXD      WMT_PIN(5, 23)
+#define WMT_PIN_UART2_RTS      WMT_PIN(5, 24)
+#define WMT_PIN_UART2_TXD      WMT_PIN(5, 25)
+#define WMT_PIN_UART2_CTS      WMT_PIN(5, 26)
+#define WMT_PIN_UART2_RXD      WMT_PIN(5, 27)
+#define WMT_PIN_SD2WP          WMT_PIN(6, 3)
+#define WMT_PIN_SD2CMD         WMT_PIN(6, 6)
+#define WMT_PIN_SD2CLK         WMT_PIN(6, 7)
+#define WMT_PIN_SD2PWR         WMT_PIN(6, 9)
+#define WMT_PIN_SD1CLK         WMT_PIN(7, 0)
+#define WMT_PIN_SD1CMD         WMT_PIN(7, 1)
+#define WMT_PIN_SD1PWR         WMT_PIN(7, 10)
+#define WMT_PIN_SD1WP          WMT_PIN(7, 11)
+#define WMT_PIN_SD1CD          WMT_PIN(7, 12)
+#define WMT_PIN_PWMOUT1                WMT_PIN(7, 26)
+#define WMT_PIN_PWMOUT0                WMT_PIN(7, 27)
+
+static const struct pinctrl_pin_desc wm8850_pins[] = {
+       PINCTRL_PIN(WMT_PIN_EXTGPIO0, "extgpio0"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO1, "extgpio1"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO2, "extgpio2"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO3, "extgpio3"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO4, "extgpio4"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO5, "extgpio5"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO6, "extgpio6"),
+       PINCTRL_PIN(WMT_PIN_EXTGPIO7, "extgpio7"),
+       PINCTRL_PIN(WMT_PIN_WAKEUP0, "wakeup0"),
+       PINCTRL_PIN(WMT_PIN_WAKEUP1, "wakeup1"),
+       PINCTRL_PIN(WMT_PIN_WAKEUP2, "wakeup2"),
+       PINCTRL_PIN(WMT_PIN_WAKEUP3, "wakeup3"),
+       PINCTRL_PIN(WMT_PIN_SUSGPIO0, "susgpio0"),
+       PINCTRL_PIN(WMT_PIN_SUSGPIO1, "susgpio1"),
+       PINCTRL_PIN(WMT_PIN_SD0CD, "sd0_cd"),
+       PINCTRL_PIN(WMT_PIN_VDOUT0, "vdout0"),
+       PINCTRL_PIN(WMT_PIN_VDOUT1, "vdout1"),
+       PINCTRL_PIN(WMT_PIN_VDOUT2, "vdout2"),
+       PINCTRL_PIN(WMT_PIN_VDOUT3, "vdout3"),
+       PINCTRL_PIN(WMT_PIN_VDOUT4, "vdout4"),
+       PINCTRL_PIN(WMT_PIN_VDOUT5, "vdout5"),
+       PINCTRL_PIN(WMT_PIN_VDOUT6, "vdout6"),
+       PINCTRL_PIN(WMT_PIN_VDOUT7, "vdout7"),
+       PINCTRL_PIN(WMT_PIN_VDOUT8, "vdout8"),
+       PINCTRL_PIN(WMT_PIN_VDOUT9, "vdout9"),
+       PINCTRL_PIN(WMT_PIN_VDOUT10, "vdout10"),
+       PINCTRL_PIN(WMT_PIN_VDOUT11, "vdout11"),
+       PINCTRL_PIN(WMT_PIN_VDOUT12, "vdout12"),
+       PINCTRL_PIN(WMT_PIN_VDOUT13, "vdout13"),
+       PINCTRL_PIN(WMT_PIN_VDOUT14, "vdout14"),
+       PINCTRL_PIN(WMT_PIN_VDOUT15, "vdout15"),
+       PINCTRL_PIN(WMT_PIN_VDOUT16, "vdout16"),
+       PINCTRL_PIN(WMT_PIN_VDOUT17, "vdout17"),
+       PINCTRL_PIN(WMT_PIN_VDOUT18, "vdout18"),
+       PINCTRL_PIN(WMT_PIN_VDOUT19, "vdout19"),
+       PINCTRL_PIN(WMT_PIN_VDOUT20, "vdout20"),
+       PINCTRL_PIN(WMT_PIN_VDOUT21, "vdout21"),
+       PINCTRL_PIN(WMT_PIN_VDOUT22, "vdout22"),
+       PINCTRL_PIN(WMT_PIN_VDOUT23, "vdout23"),
+       PINCTRL_PIN(WMT_PIN_VDIN0, "vdin0"),
+       PINCTRL_PIN(WMT_PIN_VDIN1, "vdin1"),
+       PINCTRL_PIN(WMT_PIN_VDIN2, "vdin2"),
+       PINCTRL_PIN(WMT_PIN_VDIN3, "vdin3"),
+       PINCTRL_PIN(WMT_PIN_VDIN4, "vdin4"),
+       PINCTRL_PIN(WMT_PIN_VDIN5, "vdin5"),
+       PINCTRL_PIN(WMT_PIN_VDIN6, "vdin6"),
+       PINCTRL_PIN(WMT_PIN_VDIN7, "vdin7"),
+       PINCTRL_PIN(WMT_PIN_SPI0_MOSI, "spi0_mosi"),
+       PINCTRL_PIN(WMT_PIN_SPI0_MISO, "spi0_miso"),
+       PINCTRL_PIN(WMT_PIN_SPI0_SS, "spi0_ss"),
+       PINCTRL_PIN(WMT_PIN_SPI0_CLK, "spi0_clk"),
+       PINCTRL_PIN(WMT_PIN_SPI0_SSB, "spi0_ssb"),
+       PINCTRL_PIN(WMT_PIN_SD0CLK, "sd0_clk"),
+       PINCTRL_PIN(WMT_PIN_SD0CMD, "sd0_cmd"),
+       PINCTRL_PIN(WMT_PIN_SD0WP, "sd0_wp"),
+       PINCTRL_PIN(WMT_PIN_SD0DATA0, "sd0_data0"),
+       PINCTRL_PIN(WMT_PIN_SD0DATA1, "sd0_data1"),
+       PINCTRL_PIN(WMT_PIN_SD0DATA2, "sd0_data2"),
+       PINCTRL_PIN(WMT_PIN_SD0DATA3, "sd0_data3"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA0, "sd1_data0"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA1, "sd1_data1"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA2, "sd1_data2"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA3, "sd1_data3"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA4, "sd1_data4"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA5, "sd1_data5"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA6, "sd1_data6"),
+       PINCTRL_PIN(WMT_PIN_SD1DATA7, "sd1_data7"),
+       PINCTRL_PIN(WMT_PIN_I2C0_SCL, "i2c0_scl"),
+       PINCTRL_PIN(WMT_PIN_I2C0_SDA, "i2c0_sda"),
+       PINCTRL_PIN(WMT_PIN_I2C1_SCL, "i2c1_scl"),
+       PINCTRL_PIN(WMT_PIN_I2C1_SDA, "i2c1_sda"),
+       PINCTRL_PIN(WMT_PIN_I2C2_SCL, "i2c2_scl"),
+       PINCTRL_PIN(WMT_PIN_I2C2_SDA, "i2c2_sda"),
+       PINCTRL_PIN(WMT_PIN_UART0_RTS, "uart0_rts"),
+       PINCTRL_PIN(WMT_PIN_UART0_TXD, "uart0_txd"),
+       PINCTRL_PIN(WMT_PIN_UART0_CTS, "uart0_cts"),
+       PINCTRL_PIN(WMT_PIN_UART0_RXD, "uart0_rxd"),
+       PINCTRL_PIN(WMT_PIN_UART1_RTS, "uart1_rts"),
+       PINCTRL_PIN(WMT_PIN_UART1_TXD, "uart1_txd"),
+       PINCTRL_PIN(WMT_PIN_UART1_CTS, "uart1_cts"),
+       PINCTRL_PIN(WMT_PIN_UART1_RXD, "uart1_rxd"),
+       PINCTRL_PIN(WMT_PIN_UART2_RTS, "uart2_rts"),
+       PINCTRL_PIN(WMT_PIN_UART2_TXD, "uart2_txd"),
+       PINCTRL_PIN(WMT_PIN_UART2_CTS, "uart2_cts"),
+       PINCTRL_PIN(WMT_PIN_UART2_RXD, "uart2_rxd"),
+       PINCTRL_PIN(WMT_PIN_SD2WP, "sd2_wp"),
+       PINCTRL_PIN(WMT_PIN_SD2CMD, "sd2_cmd"),
+       PINCTRL_PIN(WMT_PIN_SD2CLK, "sd2_clk"),
+       PINCTRL_PIN(WMT_PIN_SD2PWR, "sd2_pwr"),
+       PINCTRL_PIN(WMT_PIN_SD1CLK, "sd1_clk"),
+       PINCTRL_PIN(WMT_PIN_SD1CMD, "sd1_cmd"),
+       PINCTRL_PIN(WMT_PIN_SD1PWR, "sd1_pwr"),
+       PINCTRL_PIN(WMT_PIN_SD1WP, "sd1_wp"),
+       PINCTRL_PIN(WMT_PIN_SD1CD, "sd1_cd"),
+       PINCTRL_PIN(WMT_PIN_PWMOUT1, "pwmout1"),
+       PINCTRL_PIN(WMT_PIN_PWMOUT0, "pwmout0"),
+};
+
+/* Order of these names must match the above list */
+static const char * const wm8850_groups[] = {
+       "extgpio0",
+       "extgpio1",
+       "extgpio2",
+       "extgpio3",
+       "extgpio4",
+       "extgpio5",
+       "extgpio6",
+       "extgpio7",
+       "wakeup0",
+       "wakeup1",
+       "wakeup2",
+       "wakeup3",
+       "susgpio0",
+       "susgpio1",
+       "sd0_cd",
+       "vdout0",
+       "vdout1",
+       "vdout2",
+       "vdout3",
+       "vdout4",
+       "vdout5",
+       "vdout6",
+       "vdout7",
+       "vdout8",
+       "vdout9",
+       "vdout10",
+       "vdout11",
+       "vdout12",
+       "vdout13",
+       "vdout14",
+       "vdout15",
+       "vdout16",
+       "vdout17",
+       "vdout18",
+       "vdout19",
+       "vdout20",
+       "vdout21",
+       "vdout22",
+       "vdout23",
+       "vdin0",
+       "vdin1",
+       "vdin2",
+       "vdin3",
+       "vdin4",
+       "vdin5",
+       "vdin6",
+       "vdin7",
+       "spi0_mosi",
+       "spi0_miso",
+       "spi0_ss",
+       "spi0_clk",
+       "spi0_ssb",
+       "sd0_clk",
+       "sd0_cmd",
+       "sd0_wp",
+       "sd0_data0",
+       "sd0_data1",
+       "sd0_data2",
+       "sd0_data3",
+       "sd1_data0",
+       "sd1_data1",
+       "sd1_data2",
+       "sd1_data3",
+       "sd1_data4",
+       "sd1_data5",
+       "sd1_data6",
+       "sd1_data7",
+       "i2c0_scl",
+       "i2c0_sda",
+       "i2c1_scl",
+       "i2c1_sda",
+       "i2c2_scl",
+       "i2c2_sda",
+       "uart0_rts",
+       "uart0_txd",
+       "uart0_cts",
+       "uart0_rxd",
+       "uart1_rts",
+       "uart1_txd",
+       "uart1_cts",
+       "uart1_rxd",
+       "uart2_rts",
+       "uart2_txd",
+       "uart2_cts",
+       "uart2_rxd",
+       "sd2_wp",
+       "sd2_cmd",
+       "sd2_clk",
+       "sd2_pwr",
+       "sd1_clk",
+       "sd1_cmd",
+       "sd1_pwr",
+       "sd1_wp",
+       "sd1_cd",
+       "pwmout1",
+       "pwmout0",
+};
+
+static int wm8850_pinctrl_probe(struct platform_device *pdev)
+{
+       struct wmt_pinctrl_data *data;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data) {
+               dev_err(&pdev->dev, "failed to allocate data\n");
+               return -ENOMEM;
+       }
+
+       data->banks = wm8850_banks;
+       data->nbanks = ARRAY_SIZE(wm8850_banks);
+       data->pins = wm8850_pins;
+       data->npins = ARRAY_SIZE(wm8850_pins);
+       data->groups = wm8850_groups;
+       data->ngroups = ARRAY_SIZE(wm8850_groups);
+
+       return wmt_pinctrl_probe(pdev, data);
+}
+
+static int wm8850_pinctrl_remove(struct platform_device *pdev)
+{
+       return wmt_pinctrl_remove(pdev);
+}
+
+static struct of_device_id wmt_pinctrl_of_match[] = {
+       { .compatible = "wm,wm8850-pinctrl" },
+       { /* sentinel */ },
+};
+
+static struct platform_driver wmt_pinctrl_driver = {
+       .probe  = wm8850_pinctrl_probe,
+       .remove = wm8850_pinctrl_remove,
+       .driver = {
+               .name   = "pinctrl-wm8850",
+               .owner  = THIS_MODULE,
+               .of_match_table = wmt_pinctrl_of_match,
+       },
+};
+
+module_platform_driver(wmt_pinctrl_driver);
+
+MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>");
+MODULE_DESCRIPTION("Wondermedia WM8850 Pincontrol driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match);
diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c
new file mode 100644 (file)
index 0000000..ab63104
--- /dev/null
@@ -0,0 +1,632 @@
+/*
+ * Pinctrl driver for the Wondermedia SoC's
+ *
+ * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * 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.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/machine.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "pinctrl-wmt.h"
+
+static inline void wmt_setbits(struct wmt_pinctrl_data *data, u32 reg,
+                                u32 mask)
+{
+       u32 val;
+
+       val = readl_relaxed(data->base + reg);
+       val |= mask;
+       writel_relaxed(val, data->base + reg);
+}
+
+static inline void wmt_clearbits(struct wmt_pinctrl_data *data, u32 reg,
+                                  u32 mask)
+{
+       u32 val;
+
+       val = readl_relaxed(data->base + reg);
+       val &= ~mask;
+       writel_relaxed(val, data->base + reg);
+}
+
+enum wmt_func_sel {
+       WMT_FSEL_GPIO_IN = 0,
+       WMT_FSEL_GPIO_OUT = 1,
+       WMT_FSEL_ALT = 2,
+       WMT_FSEL_COUNT = 3,
+};
+
+static const char * const wmt_functions[WMT_FSEL_COUNT] = {
+       [WMT_FSEL_GPIO_IN] = "gpio_in",
+       [WMT_FSEL_GPIO_OUT] = "gpio_out",
+       [WMT_FSEL_ALT] = "alt",
+};
+
+static int wmt_pmx_get_functions_count(struct pinctrl_dev *pctldev)
+{
+       return WMT_FSEL_COUNT;
+}
+
+static const char *wmt_pmx_get_function_name(struct pinctrl_dev *pctldev,
+                                            unsigned selector)
+{
+       return wmt_functions[selector];
+}
+
+static int wmt_pmx_get_function_groups(struct pinctrl_dev *pctldev,
+                                      unsigned selector,
+                                      const char * const **groups,
+                                      unsigned * const num_groups)
+{
+       struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
+
+       /* every pin does every function */
+       *groups = data->groups;
+       *num_groups = data->ngroups;
+
+       return 0;
+}
+
+static int wmt_set_pinmux(struct wmt_pinctrl_data *data, unsigned func,
+                         unsigned pin)
+{
+       u32 bank = WMT_BANK_FROM_PIN(pin);
+       u32 bit = WMT_BIT_FROM_PIN(pin);
+       u32 reg_en = data->banks[bank].reg_en;
+       u32 reg_dir = data->banks[bank].reg_dir;
+
+       if (reg_dir == NO_REG) {
+               dev_err(data->dev, "pin:%d no direction register defined\n",
+                       pin);
+               return -EINVAL;
+       }
+
+       /*
+        * If reg_en == NO_REG, we assume it is a dedicated GPIO and cannot be
+        * disabled (as on VT8500) and that no alternate function is available.
+        */
+       switch (func) {
+       case WMT_FSEL_GPIO_IN:
+               if (reg_en != NO_REG)
+                       wmt_setbits(data, reg_en, BIT(bit));
+               wmt_clearbits(data, reg_dir, BIT(bit));
+               break;
+       case WMT_FSEL_GPIO_OUT:
+               if (reg_en != NO_REG)
+                       wmt_setbits(data, reg_en, BIT(bit));
+               wmt_setbits(data, reg_dir, BIT(bit));
+               break;
+       case WMT_FSEL_ALT:
+               if (reg_en == NO_REG) {
+                       dev_err(data->dev, "pin:%d no alt function available\n",
+                               pin);
+                       return -EINVAL;
+               }
+               wmt_clearbits(data, reg_en, BIT(bit));
+       }
+
+       return 0;
+}
+
+static int wmt_pmx_enable(struct pinctrl_dev *pctldev,
+                         unsigned func_selector,
+                         unsigned group_selector)
+{
+       struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
+       u32 pinnum = data->pins[group_selector].number;
+
+       return wmt_set_pinmux(data, func_selector, pinnum);
+}
+
+static void wmt_pmx_disable(struct pinctrl_dev *pctldev,
+                           unsigned func_selector,
+                           unsigned group_selector)
+{
+       struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
+       u32 pinnum = data->pins[group_selector].number;
+
+       /* disable by setting GPIO_IN */
+       wmt_set_pinmux(data, WMT_FSEL_GPIO_IN, pinnum);
+}
+
+static void wmt_pmx_gpio_disable_free(struct pinctrl_dev *pctldev,
+                                     struct pinctrl_gpio_range *range,
+                                     unsigned offset)
+{
+       struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
+
+       /* disable by setting GPIO_IN */
+       wmt_set_pinmux(data, WMT_FSEL_GPIO_IN, offset);
+}
+
+static int wmt_pmx_gpio_set_direction(struct pinctrl_dev *pctldev,
+                                     struct pinctrl_gpio_range *range,
+                                     unsigned offset,
+                                     bool input)
+{
+       struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
+
+       wmt_set_pinmux(data, (input ? WMT_FSEL_GPIO_IN : WMT_FSEL_GPIO_OUT),
+                      offset);
+
+       return 0;
+}
+
+static struct pinmux_ops wmt_pinmux_ops = {
+       .get_functions_count = wmt_pmx_get_functions_count,
+       .get_function_name = wmt_pmx_get_function_name,
+       .get_function_groups = wmt_pmx_get_function_groups,
+       .enable = wmt_pmx_enable,
+       .disable = wmt_pmx_disable,
+       .gpio_disable_free = wmt_pmx_gpio_disable_free,
+       .gpio_set_direction = wmt_pmx_gpio_set_direction,
+};
+
+static int wmt_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
+
+       return data->ngroups;
+}
+
+static const char *wmt_get_group_name(struct pinctrl_dev *pctldev,
+                                     unsigned selector)
+{
+       struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
+
+       return data->groups[selector];
+}
+
+static int wmt_get_group_pins(struct pinctrl_dev *pctldev,
+                             unsigned selector,
+                             const unsigned **pins,
+                             unsigned *num_pins)
+{
+       struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
+
+       *pins = &data->pins[selector].number;
+       *num_pins = 1;
+
+       return 0;
+}
+
+static int wmt_pctl_find_group_by_pin(struct wmt_pinctrl_data *data, u32 pin)
+{
+       int i;
+
+       for (i = 0; i < data->npins; i++) {
+               if (data->pins[i].number == pin)
+                       return i;
+       }
+
+       return -EINVAL;
+}
+
+static int wmt_pctl_dt_node_to_map_func(struct wmt_pinctrl_data *data,
+                                       struct device_node *np,
+                                       u32 pin, u32 fnum,
+                                       struct pinctrl_map **maps)
+{
+       int group;
+       struct pinctrl_map *map = *maps;
+
+       if (fnum >= ARRAY_SIZE(wmt_functions)) {
+               dev_err(data->dev, "invalid wm,function %d\n", fnum);
+               return -EINVAL;
+       }
+
+       group = wmt_pctl_find_group_by_pin(data, pin);
+       if (group < 0) {
+               dev_err(data->dev, "unable to match pin %d to group\n", pin);
+               return group;
+       }
+
+       map->type = PIN_MAP_TYPE_MUX_GROUP;
+       map->data.mux.group = data->groups[group];
+       map->data.mux.function = wmt_functions[fnum];
+       (*maps)++;
+
+       return 0;
+}
+
+static int wmt_pctl_dt_node_to_map_pull(struct wmt_pinctrl_data *data,
+                                       struct device_node *np,
+                                       u32 pin, u32 pull,
+                                       struct pinctrl_map **maps)
+{
+       int group;
+       unsigned long *configs;
+       struct pinctrl_map *map = *maps;
+
+       if (pull > 2) {
+               dev_err(data->dev, "invalid wm,pull %d\n", pull);
+               return -EINVAL;
+       }
+
+       group = wmt_pctl_find_group_by_pin(data, pin);
+       if (group < 0) {
+               dev_err(data->dev, "unable to match pin %d to group\n", pin);
+               return group;
+       }
+
+       configs = kzalloc(sizeof(*configs), GFP_KERNEL);
+       if (!configs)
+               return -ENOMEM;
+
+       configs[0] = pull;
+
+       map->type = PIN_MAP_TYPE_CONFIGS_PIN;
+       map->data.configs.group_or_pin = data->groups[group];
+       map->data.configs.configs = configs;
+       map->data.configs.num_configs = 1;
+       (*maps)++;
+
+       return 0;
+}
+
+static void wmt_pctl_dt_free_map(struct pinctrl_dev *pctldev,
+                                struct pinctrl_map *maps,
+                                unsigned num_maps)
+{
+       int i;
+
+       for (i = 0; i < num_maps; i++)
+               if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN)
+                       kfree(maps[i].data.configs.configs);
+
+       kfree(maps);
+}
+
+static int wmt_pctl_dt_node_to_map(struct pinctrl_dev *pctldev,
+                                  struct device_node *np,
+                                  struct pinctrl_map **map,
+                                  unsigned *num_maps)
+{
+       struct pinctrl_map *maps, *cur_map;
+       struct property *pins, *funcs, *pulls;
+       u32 pin, func, pull;
+       int num_pins, num_funcs, num_pulls, maps_per_pin;
+       int i, err;
+       struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
+
+       pins = of_find_property(np, "wm,pins", NULL);
+       if (!pins) {
+               dev_err(data->dev, "missing wmt,pins property\n");
+               return -EINVAL;
+       }
+
+       funcs = of_find_property(np, "wm,function", NULL);
+       pulls = of_find_property(np, "wm,pull", NULL);
+
+       if (!funcs && !pulls) {
+               dev_err(data->dev, "neither wm,function nor wm,pull specified\n");
+               return -EINVAL;
+       }
+
+       /*
+        * The following lines calculate how many values are defined for each
+        * of the properties.
+        */
+       num_pins = pins->length / sizeof(u32);
+       num_funcs = funcs ? (funcs->length / sizeof(u32)) : 0;
+       num_pulls = pulls ? (pulls->length / sizeof(u32)) : 0;
+
+       if (num_funcs > 1 && num_funcs != num_pins) {
+               dev_err(data->dev, "wm,function must have 1 or %d entries\n",
+                       num_pins);
+               return -EINVAL;
+       }
+
+       if (num_pulls > 1 && num_pulls != num_pins) {
+               dev_err(data->dev, "wm,pull must have 1 or %d entries\n",
+                       num_pins);
+               return -EINVAL;
+       }
+
+       maps_per_pin = 0;
+       if (num_funcs)
+               maps_per_pin++;
+       if (num_pulls)
+               maps_per_pin++;
+
+       cur_map = maps = kzalloc(num_pins * maps_per_pin * sizeof(*maps),
+                                GFP_KERNEL);
+       if (!maps)
+               return -ENOMEM;
+
+       for (i = 0; i < num_pins; i++) {
+               err = of_property_read_u32_index(np, "wm,pins", i, &pin);
+               if (err)
+                       goto fail;
+
+               if (pin >= (data->nbanks * 32)) {
+                       dev_err(data->dev, "invalid wm,pins value\n");
+                       err = -EINVAL;
+                       goto fail;
+               }
+
+               if (num_funcs) {
+                       err = of_property_read_u32_index(np, "wm,function",
+                                               (num_funcs > 1 ? i : 0), &func);
+                       if (err)
+                               goto fail;
+
+                       err = wmt_pctl_dt_node_to_map_func(data, np, pin, func,
+                                                          &cur_map);
+                       if (err)
+                               goto fail;
+               }
+
+               if (num_pulls) {
+                       err = of_property_read_u32_index(np, "wm,pull",
+                                               (num_pulls > 1 ? i : 0), &pull);
+                       if (err)
+                               goto fail;
+
+                       err = wmt_pctl_dt_node_to_map_pull(data, np, pin, pull,
+                                                          &cur_map);
+                       if (err)
+                               goto fail;
+               }
+       }
+       *map = maps;
+       *num_maps = num_pins * maps_per_pin;
+       return 0;
+
+/*
+ * The fail path removes any maps that have been allocated. The fail path is
+ * only called from code after maps has been kzalloc'd. It is also safe to
+ * pass 'num_pins * maps_per_pin' as the map count even though we probably
+ * failed before all the mappings were read as all maps are allocated at once,
+ * and configs are only allocated for .type = PIN_MAP_TYPE_CONFIGS_PIN - there
+ * is no failpath where a config can be allocated without .type being set.
+ */
+fail:
+       wmt_pctl_dt_free_map(pctldev, maps, num_pins * maps_per_pin);
+       return err;
+}
+
+static struct pinctrl_ops wmt_pctl_ops = {
+       .get_groups_count = wmt_get_groups_count,
+       .get_group_name = wmt_get_group_name,
+       .get_group_pins = wmt_get_group_pins,
+       .dt_node_to_map = wmt_pctl_dt_node_to_map,
+       .dt_free_map = wmt_pctl_dt_free_map,
+};
+
+static int wmt_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
+                          unsigned long *config)
+{
+       return -ENOTSUPP;
+}
+
+static int wmt_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
+                          unsigned long config)
+{
+       struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev);
+       enum pin_config_param param = pinconf_to_config_param(config);
+       u16 arg = pinconf_to_config_argument(config);
+       u32 bank = WMT_BANK_FROM_PIN(pin);
+       u32 bit = WMT_BIT_FROM_PIN(pin);
+       u32 reg_pull_en = data->banks[bank].reg_pull_en;
+       u32 reg_pull_cfg = data->banks[bank].reg_pull_cfg;
+
+       if ((reg_pull_en == NO_REG) || (reg_pull_cfg == NO_REG)) {
+               dev_err(data->dev, "bias functions not supported on pin %d\n",
+                       pin);
+               return -EINVAL;
+       }
+
+       if ((param == PIN_CONFIG_BIAS_PULL_DOWN) ||
+           (param == PIN_CONFIG_BIAS_PULL_UP)) {
+               if (arg == 0)
+                       param = PIN_CONFIG_BIAS_DISABLE;
+       }
+
+       switch (param) {
+       case PIN_CONFIG_BIAS_DISABLE:
+               wmt_clearbits(data, reg_pull_en, BIT(bit));
+               break;
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               wmt_clearbits(data, reg_pull_cfg, BIT(bit));
+               wmt_setbits(data, reg_pull_en, BIT(bit));
+               break;
+       case PIN_CONFIG_BIAS_PULL_UP:
+               wmt_setbits(data, reg_pull_cfg, BIT(bit));
+               wmt_setbits(data, reg_pull_en, BIT(bit));
+               break;
+       default:
+               dev_err(data->dev, "unknown pinconf param\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct pinconf_ops wmt_pinconf_ops = {
+       .pin_config_get = wmt_pinconf_get,
+       .pin_config_set = wmt_pinconf_set,
+};
+
+static struct pinctrl_desc wmt_desc = {
+       .owner = THIS_MODULE,
+       .name = "pinctrl-wmt",
+       .pctlops = &wmt_pctl_ops,
+       .pmxops = &wmt_pinmux_ops,
+       .confops = &wmt_pinconf_ops,
+};
+
+static int wmt_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       return pinctrl_request_gpio(chip->base + offset);
+}
+
+static void wmt_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       pinctrl_free_gpio(chip->base + offset);
+}
+
+static int wmt_gpio_get_direction(struct gpio_chip *chip, unsigned offset)
+{
+       struct wmt_pinctrl_data *data = dev_get_drvdata(chip->dev);
+       u32 bank = WMT_BANK_FROM_PIN(offset);
+       u32 bit = WMT_BIT_FROM_PIN(offset);
+       u32 reg_dir = data->banks[bank].reg_dir;
+       u32 val;
+
+       val = readl_relaxed(data->base + reg_dir);
+       if (val & BIT(bit))
+               return GPIOF_DIR_OUT;
+       else
+               return GPIOF_DIR_IN;
+}
+
+static int wmt_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+       return pinctrl_gpio_direction_input(chip->base + offset);
+}
+
+static int wmt_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+                                    int value)
+{
+       return pinctrl_gpio_direction_output(chip->base + offset);
+}
+
+static int wmt_gpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+       struct wmt_pinctrl_data *data = dev_get_drvdata(chip->dev);
+       u32 bank = WMT_BANK_FROM_PIN(offset);
+       u32 bit = WMT_BIT_FROM_PIN(offset);
+       u32 reg_data_in = data->banks[bank].reg_data_in;
+
+       if (reg_data_in == NO_REG) {
+               dev_err(data->dev, "no data in register defined\n");
+               return -EINVAL;
+       }
+
+       return !!(readl_relaxed(data->base + reg_data_in) & BIT(bit));
+}
+
+static void wmt_gpio_set_value(struct gpio_chip *chip, unsigned offset,
+                              int val)
+{
+       struct wmt_pinctrl_data *data = dev_get_drvdata(chip->dev);
+       u32 bank = WMT_BANK_FROM_PIN(offset);
+       u32 bit = WMT_BIT_FROM_PIN(offset);
+       u32 reg_data_out = data->banks[bank].reg_data_out;
+
+       if (reg_data_out == NO_REG) {
+               dev_err(data->dev, "no data out register defined\n");
+               return;
+       }
+
+       if (val)
+               wmt_setbits(data, reg_data_out, BIT(bit));
+       else
+               wmt_clearbits(data, reg_data_out, BIT(bit));
+}
+
+static struct gpio_chip wmt_gpio_chip = {
+       .label = "gpio-wmt",
+       .owner = THIS_MODULE,
+       .request = wmt_gpio_request,
+       .free = wmt_gpio_free,
+       .get_direction = wmt_gpio_get_direction,
+       .direction_input = wmt_gpio_direction_input,
+       .direction_output = wmt_gpio_direction_output,
+       .get = wmt_gpio_get_value,
+       .set = wmt_gpio_set_value,
+       .can_sleep = 0,
+};
+
+int wmt_pinctrl_probe(struct platform_device *pdev,
+                     struct wmt_pinctrl_data *data)
+{
+       int err;
+       struct resource *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       data->base = devm_request_and_ioremap(&pdev->dev, res);
+       if (!data->base) {
+               dev_err(&pdev->dev, "failed to map memory resource\n");
+               return -EBUSY;
+       }
+
+       wmt_desc.pins = data->pins;
+       wmt_desc.npins = data->npins;
+
+       data->gpio_chip = wmt_gpio_chip;
+       data->gpio_chip.dev = &pdev->dev;
+       data->gpio_chip.of_node = pdev->dev.of_node;
+       data->gpio_chip.ngpio = data->nbanks * 32;
+
+       platform_set_drvdata(pdev, data);
+
+       data->dev = &pdev->dev;
+
+       data->pctl_dev = pinctrl_register(&wmt_desc, &pdev->dev, data);
+       if (!data->pctl_dev) {
+               dev_err(&pdev->dev, "Failed to register pinctrl\n");
+               return -EINVAL;
+       }
+
+       err = gpiochip_add(&data->gpio_chip);
+       if (err) {
+               dev_err(&pdev->dev, "could not add GPIO chip\n");
+               goto fail_gpio;
+       }
+
+       err = gpiochip_add_pin_range(&data->gpio_chip, dev_name(data->dev),
+                                    0, 0, data->nbanks * 32);
+       if (err)
+               goto fail_range;
+
+       dev_info(&pdev->dev, "Pin controller initialized\n");
+
+       return 0;
+
+fail_range:
+       err = gpiochip_remove(&data->gpio_chip);
+       if (err)
+               dev_err(&pdev->dev, "failed to remove gpio chip\n");
+fail_gpio:
+       pinctrl_unregister(data->pctl_dev);
+       return err;
+}
+
+int wmt_pinctrl_remove(struct platform_device *pdev)
+{
+       struct wmt_pinctrl_data *data = platform_get_drvdata(pdev);
+       int err;
+
+       err = gpiochip_remove(&data->gpio_chip);
+       if (err)
+               dev_err(&pdev->dev, "failed to remove gpio chip\n");
+
+       pinctrl_unregister(data->pctl_dev);
+
+       return 0;
+}
diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.h b/drivers/pinctrl/vt8500/pinctrl-wmt.h
new file mode 100644 (file)
index 0000000..41f5f2d
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Pinctrl driver for the Wondermedia SoC's
+ *
+ * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * 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.
+ */
+
+#include <linux/gpio.h>
+
+/* VT8500 has no enable register in the extgpio bank. */
+#define NO_REG 0xFFFF
+
+#define WMT_PINCTRL_BANK(__en, __dir, __dout, __din, __pen, __pcfg)    \
+{                                                                      \
+       .reg_en         = __en,                                         \
+       .reg_dir        = __dir,                                        \
+       .reg_data_out   = __dout,                                       \
+       .reg_data_in    = __din,                                        \
+       .reg_pull_en    = __pen,                                        \
+       .reg_pull_cfg   = __pcfg,                                       \
+}
+
+/* Encode/decode the bank/bit pairs into a pin value */
+#define WMT_PIN(__bank, __offset)      ((__bank << 5) | __offset)
+#define WMT_BANK_FROM_PIN(__pin)       (__pin >> 5)
+#define WMT_BIT_FROM_PIN(__pin)                (__pin & 0x1f)
+
+#define WMT_GROUP(__name, __data)              \
+{                                              \
+       .name = __name,                         \
+       .pins = __data,                         \
+       .npins = ARRAY_SIZE(__data),            \
+}
+
+struct wmt_pinctrl_bank_registers {
+       u32     reg_en;
+       u32     reg_dir;
+       u32     reg_data_out;
+       u32     reg_data_in;
+
+       u32     reg_pull_en;
+       u32     reg_pull_cfg;
+};
+
+struct wmt_pinctrl_group {
+       const char *name;
+       const unsigned int *pins;
+       const unsigned npins;
+};
+
+struct wmt_pinctrl_data {
+       struct device *dev;
+       struct pinctrl_dev *pctl_dev;
+
+       /* must be initialized before calling wmt_pinctrl_probe */
+       void __iomem *base;
+       const struct wmt_pinctrl_bank_registers *banks;
+       const struct pinctrl_pin_desc *pins;
+       const char * const *groups;
+
+       u32 nbanks;
+       u32 npins;
+       u32 ngroups;
+
+       struct gpio_chip gpio_chip;
+       struct pinctrl_gpio_range gpio_range;
+};
+
+int wmt_pinctrl_probe(struct platform_device *pdev,
+                     struct wmt_pinctrl_data *data);
+int wmt_pinctrl_remove(struct platform_device *pdev);
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
new file mode 100644 (file)
index 0000000..c9d04f7
--- /dev/null
@@ -0,0 +1,13 @@
+config ARCH_HAS_RESET_CONTROLLER
+       bool
+
+menuconfig RESET_CONTROLLER
+       bool "Reset Controller Support"
+       default y if ARCH_HAS_RESET_CONTROLLER
+       help
+         Generic Reset Controller support.
+
+         This framework is designed to abstract reset handling of devices
+         via GPIOs or SoC-internal reset controller modules.
+
+         If unsure, say no.
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
new file mode 100644 (file)
index 0000000..1e2d83f
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_RESET_CONTROLLER) += core.o
diff --git a/drivers/reset/core.c b/drivers/reset/core.c
new file mode 100644 (file)
index 0000000..d1b6089
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * Reset Controller framework
+ *
+ * Copyright 2013 Philipp Zabel, Pengutronix
+ *
+ * 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/device.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/reset.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+
+static DEFINE_MUTEX(reset_controller_list_mutex);
+static LIST_HEAD(reset_controller_list);
+
+/**
+ * struct reset_control - a reset control
+ * @rcdev: a pointer to the reset controller device
+ *         this reset control belongs to
+ * @id: ID of the reset controller in the reset
+ *      controller device
+ */
+struct reset_control {
+       struct reset_controller_dev *rcdev;
+       struct device *dev;
+       unsigned int id;
+};
+
+/**
+ * of_reset_simple_xlate - translate reset_spec to the reset line number
+ * @rcdev: a pointer to the reset controller device
+ * @reset_spec: reset line specifier as found in the device tree
+ * @flags: a flags pointer to fill in (optional)
+ *
+ * This simple translation function should be used for reset controllers
+ * with 1:1 mapping, where reset lines can be indexed by number without gaps.
+ */
+int of_reset_simple_xlate(struct reset_controller_dev *rcdev,
+                         const struct of_phandle_args *reset_spec)
+{
+       if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells))
+               return -EINVAL;
+
+       if (reset_spec->args[0] >= rcdev->nr_resets)
+               return -EINVAL;
+
+       return reset_spec->args[0];
+}
+EXPORT_SYMBOL_GPL(of_reset_simple_xlate);
+
+/**
+ * reset_controller_register - register a reset controller device
+ * @rcdev: a pointer to the initialized reset controller device
+ */
+int reset_controller_register(struct reset_controller_dev *rcdev)
+{
+       if (!rcdev->of_xlate) {
+               rcdev->of_reset_n_cells = 1;
+               rcdev->of_xlate = of_reset_simple_xlate;
+       }
+
+       mutex_lock(&reset_controller_list_mutex);
+       list_add(&rcdev->list, &reset_controller_list);
+       mutex_unlock(&reset_controller_list_mutex);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(reset_controller_register);
+
+/**
+ * reset_controller_unregister - unregister a reset controller device
+ * @rcdev: a pointer to the reset controller device
+ */
+void reset_controller_unregister(struct reset_controller_dev *rcdev)
+{
+       mutex_lock(&reset_controller_list_mutex);
+       list_del(&rcdev->list);
+       mutex_unlock(&reset_controller_list_mutex);
+}
+EXPORT_SYMBOL_GPL(reset_controller_unregister);
+
+/**
+ * reset_control_reset - reset the controlled device
+ * @rstc: reset controller
+ */
+int reset_control_reset(struct reset_control *rstc)
+{
+       if (rstc->rcdev->ops->reset)
+               return rstc->rcdev->ops->reset(rstc->rcdev, rstc->id);
+
+       return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(reset_control_reset);
+
+/**
+ * reset_control_assert - asserts the reset line
+ * @rstc: reset controller
+ */
+int reset_control_assert(struct reset_control *rstc)
+{
+       if (rstc->rcdev->ops->assert)
+               return rstc->rcdev->ops->assert(rstc->rcdev, rstc->id);
+
+       return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(reset_control_assert);
+
+/**
+ * reset_control_deassert - deasserts the reset line
+ * @rstc: reset controller
+ */
+int reset_control_deassert(struct reset_control *rstc)
+{
+       if (rstc->rcdev->ops->deassert)
+               return rstc->rcdev->ops->deassert(rstc->rcdev, rstc->id);
+
+       return -ENOSYS;
+}
+EXPORT_SYMBOL_GPL(reset_control_deassert);
+
+/**
+ * reset_control_get - Lookup and obtain a reference to a reset controller.
+ * @dev: device to be reset by the controller
+ * @id: reset line name
+ *
+ * Returns a struct reset_control or IS_ERR() condition containing errno.
+ *
+ * Use of id names is optional.
+ */
+struct reset_control *reset_control_get(struct device *dev, const char *id)
+{
+       struct reset_control *rstc = ERR_PTR(-EPROBE_DEFER);
+       struct reset_controller_dev *r, *rcdev;
+       struct of_phandle_args args;
+       int index = 0;
+       int rstc_id;
+       int ret;
+
+       if (!dev)
+               return ERR_PTR(-EINVAL);
+
+       if (id)
+               index = of_property_match_string(dev->of_node,
+                                                "reset-names", id);
+       ret = of_parse_phandle_with_args(dev->of_node, "resets", "#reset-cells",
+                                        index, &args);
+       if (ret)
+               return ERR_PTR(ret);
+
+       mutex_lock(&reset_controller_list_mutex);
+       rcdev = NULL;
+       list_for_each_entry(r, &reset_controller_list, list) {
+               if (args.np == r->of_node) {
+                       rcdev = r;
+                       break;
+               }
+       }
+       of_node_put(args.np);
+
+       if (!rcdev) {
+               mutex_unlock(&reset_controller_list_mutex);
+               return ERR_PTR(-ENODEV);
+       }
+
+       rstc_id = rcdev->of_xlate(rcdev, &args);
+       if (rstc_id < 0) {
+               mutex_unlock(&reset_controller_list_mutex);
+               return ERR_PTR(rstc_id);
+       }
+
+       try_module_get(rcdev->owner);
+       mutex_unlock(&reset_controller_list_mutex);
+
+       rstc = kzalloc(sizeof(*rstc), GFP_KERNEL);
+       if (!rstc) {
+               module_put(rcdev->owner);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       rstc->dev = dev;
+       rstc->rcdev = rcdev;
+       rstc->id = rstc_id;
+
+       return rstc;
+}
+EXPORT_SYMBOL_GPL(reset_control_get);
+
+/**
+ * reset_control_put - free the reset controller
+ * @rstc: reset controller
+ */
+
+void reset_control_put(struct reset_control *rstc)
+{
+       if (IS_ERR(rstc))
+               return;
+
+       module_put(rstc->rcdev->owner);
+       kfree(rstc);
+}
+EXPORT_SYMBOL_GPL(reset_control_put);
+
+static void devm_reset_control_release(struct device *dev, void *res)
+{
+       reset_control_put(*(struct reset_control **)res);
+}
+
+/**
+ * devm_reset_control_get - resource managed reset_control_get()
+ * @dev: device to be reset by the controller
+ * @id: reset line name
+ *
+ * Managed reset_control_get(). For reset controllers returned from this
+ * function, reset_control_put() is called automatically on driver detach.
+ * See reset_control_get() for more information.
+ */
+struct reset_control *devm_reset_control_get(struct device *dev, const char *id)
+{
+       struct reset_control **ptr, *rstc;
+
+       ptr = devres_alloc(devm_reset_control_release, sizeof(*ptr),
+                          GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       rstc = reset_control_get(dev, id);
+       if (!IS_ERR(rstc)) {
+               *ptr = rstc;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return rstc;
+}
+EXPORT_SYMBOL_GPL(devm_reset_control_get);
+
+static int devm_reset_control_match(struct device *dev, void *res, void *data)
+{
+       struct reset_control **rstc = res;
+       if (WARN_ON(!rstc || !*rstc))
+               return 0;
+       return *rstc == data;
+}
+
+/**
+ * devm_reset_control_put - resource managed reset_control_put()
+ * @rstc: reset controller to free
+ *
+ * Deallocate a reset control allocated withd devm_reset_control_get().
+ * This function will not need to be called normally, as devres will take
+ * care of freeing the resource.
+ */
+void devm_reset_control_put(struct reset_control *rstc)
+{
+       int ret;
+
+       ret = devres_release(rstc->dev, devm_reset_control_release,
+                            devm_reset_control_match, rstc);
+       if (ret)
+               WARN_ON(ret);
+}
+EXPORT_SYMBOL_GPL(devm_reset_control_put);
+
+/**
+ * device_reset - find reset controller associated with the device
+ *                and perform reset
+ * @dev: device to be reset by the controller
+ *
+ * Convenience wrapper for reset_control_get() and reset_control_reset().
+ * This is useful for the common case of devices with single, dedicated reset
+ * lines.
+ */
+int device_reset(struct device *dev)
+{
+       struct reset_control *rstc;
+       int ret;
+
+       rstc = reset_control_get(dev, NULL);
+       if (IS_ERR(rstc))
+               return PTR_ERR(rstc);
+
+       ret = reset_control_reset(rstc);
+
+       reset_control_put(rstc);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(device_reset);
index 0dde688ca09b4785bf6968393f1b1a7579233b8f..969abbad7fe346d0f815c4da6f566b01aeedea45 100644 (file)
@@ -239,11 +239,9 @@ static int da9052_rtc_probe(struct platform_device *pdev)
 
        rtc->da9052 = dev_get_drvdata(pdev->dev.parent);
        platform_set_drvdata(pdev, rtc);
-       rtc->irq = platform_get_irq_byname(pdev, "ALM");
-       ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL,
-                               da9052_rtc_irq,
-                               IRQF_TRIGGER_LOW | IRQF_ONESHOT,
-                               "ALM", rtc);
+       rtc->irq =  DA9052_IRQ_ALARM;
+       ret = da9052_request_irq(rtc->da9052, rtc->irq, "ALM",
+                               da9052_rtc_irq, rtc);
        if (ret != 0) {
                rtc_err(rtc->da9052, "irq registration failed: %d\n", ret);
                return ret;
index 57233c8859989d15a2a6ce5b041c1363d07374c2..8f87fec27ce78ffa9c191bf104cb9326368f88fc 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
 #include <linux/gfp.h>
 #include <linux/module.h>
 
@@ -41,6 +42,7 @@ struct rtc_plat_data {
        struct rtc_device *rtc;
        void __iomem *ioaddr;
        int             irq;
+       struct clk      *clk;
 };
 
 static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm)
@@ -221,6 +223,7 @@ static int mv_rtc_probe(struct platform_device *pdev)
        struct rtc_plat_data *pdata;
        resource_size_t size;
        u32 rtc_time;
+       int ret = 0;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res)
@@ -239,11 +242,17 @@ static int mv_rtc_probe(struct platform_device *pdev)
        if (!pdata->ioaddr)
                return -ENOMEM;
 
+       pdata->clk = devm_clk_get(&pdev->dev, NULL);
+       /* Not all SoCs require a clock.*/
+       if (!IS_ERR(pdata->clk))
+               clk_prepare_enable(pdata->clk);
+
        /* make sure the 24 hours mode is enabled */
        rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
        if (rtc_time & RTC_HOURS_12H_MODE) {
                dev_err(&pdev->dev, "24 Hours mode not supported.\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto out;
        }
 
        /* make sure it is actually functional */
@@ -252,7 +261,8 @@ static int mv_rtc_probe(struct platform_device *pdev)
                rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS);
                if (rtc_time == 0x01000000) {
                        dev_err(&pdev->dev, "internal RTC not ticking\n");
-                       return -ENODEV;
+                       ret = -ENODEV;
+                       goto out;
                }
        }
 
@@ -268,8 +278,10 @@ static int mv_rtc_probe(struct platform_device *pdev)
        } else
                pdata->rtc = rtc_device_register(pdev->name, &pdev->dev,
                                                 &mv_rtc_ops, THIS_MODULE);
-       if (IS_ERR(pdata->rtc))
-               return PTR_ERR(pdata->rtc);
+       if (IS_ERR(pdata->rtc)) {
+               ret = PTR_ERR(pdata->rtc);
+               goto out;
+       }
 
        if (pdata->irq >= 0) {
                writel(0, pdata->ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS);
@@ -282,6 +294,11 @@ static int mv_rtc_probe(struct platform_device *pdev)
        }
 
        return 0;
+out:
+       if (!IS_ERR(pdata->clk))
+               clk_disable_unprepare(pdata->clk);
+
+       return ret;
 }
 
 static int __exit mv_rtc_remove(struct platform_device *pdev)
@@ -292,6 +309,9 @@ static int __exit mv_rtc_remove(struct platform_device *pdev)
                device_init_wakeup(&pdev->dev, 0);
 
        rtc_device_unregister(pdata->rtc);
+       if (!IS_ERR(pdata->clk))
+               clk_disable_unprepare(pdata->clk);
+
        return 0;
 }
 
index fb994e9ddc156de9a98465531db161202826fe57..7995f79d07e10d4e1f09888ea673a8ad95986cd9 100644 (file)
@@ -29,9 +29,8 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-#include <mach/hardware.h>
 #include <asm/irq.h>
-#include <plat/regs-rtc.h>
+#include "rtc-s3c.h"
 
 enum s3c_cpu_type {
        TYPE_S3C2410,
similarity index 97%
rename from arch/arm/plat-samsung/include/plat/regs-rtc.h
rename to drivers/rtc/rtc-s3c.h
index 0f8263e93eea94678b28f8e8d60cbbc1f6a48763..004b61a8343ff8896305c426dc298a33adddc13c 100644 (file)
@@ -1,5 +1,4 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-rtc.h
- *
+/*
  * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
  *                   http://www.simtec.co.uk/products/SWLINUX/
  *
index 9978ad4433cb460ea96dcc5f7a4bd0d7e8c5bdd6..e9b9c83928325fc708b72df751d51c08bf7bde82 100644 (file)
@@ -135,6 +135,11 @@ static const struct block_device_operations scm_blk_devops = {
        .release = scm_release,
 };
 
+static bool scm_permit_request(struct scm_blk_dev *bdev, struct request *req)
+{
+       return rq_data_dir(req) != WRITE || bdev->state != SCM_WR_PROHIBIT;
+}
+
 static void scm_request_prepare(struct scm_request *scmrq)
 {
        struct scm_blk_dev *bdev = scmrq->bdev;
@@ -195,14 +200,18 @@ void scm_request_requeue(struct scm_request *scmrq)
 
        scm_release_cluster(scmrq);
        blk_requeue_request(bdev->rq, scmrq->request);
+       atomic_dec(&bdev->queued_reqs);
        scm_request_done(scmrq);
        scm_ensure_queue_restart(bdev);
 }
 
 void scm_request_finish(struct scm_request *scmrq)
 {
+       struct scm_blk_dev *bdev = scmrq->bdev;
+
        scm_release_cluster(scmrq);
        blk_end_request_all(scmrq->request, scmrq->error);
+       atomic_dec(&bdev->queued_reqs);
        scm_request_done(scmrq);
 }
 
@@ -218,6 +227,10 @@ static void scm_blk_request(struct request_queue *rq)
                if (req->cmd_type != REQ_TYPE_FS)
                        continue;
 
+               if (!scm_permit_request(bdev, req)) {
+                       scm_ensure_queue_restart(bdev);
+                       return;
+               }
                scmrq = scm_request_fetch();
                if (!scmrq) {
                        SCM_LOG(5, "no request");
@@ -231,11 +244,13 @@ static void scm_blk_request(struct request_queue *rq)
                        return;
                }
                if (scm_need_cluster_request(scmrq)) {
+                       atomic_inc(&bdev->queued_reqs);
                        blk_start_request(req);
                        scm_initiate_cluster_request(scmrq);
                        return;
                }
                scm_request_prepare(scmrq);
+               atomic_inc(&bdev->queued_reqs);
                blk_start_request(req);
 
                ret = scm_start_aob(scmrq->aob);
@@ -244,7 +259,6 @@ static void scm_blk_request(struct request_queue *rq)
                        scm_request_requeue(scmrq);
                        return;
                }
-               atomic_inc(&bdev->queued_reqs);
        }
 }
 
@@ -280,6 +294,38 @@ void scm_blk_irq(struct scm_device *scmdev, void *data, int error)
        tasklet_hi_schedule(&bdev->tasklet);
 }
 
+static void scm_blk_handle_error(struct scm_request *scmrq)
+{
+       struct scm_blk_dev *bdev = scmrq->bdev;
+       unsigned long flags;
+
+       if (scmrq->error != -EIO)
+               goto restart;
+
+       /* For -EIO the response block is valid. */
+       switch (scmrq->aob->response.eqc) {
+       case EQC_WR_PROHIBIT:
+               spin_lock_irqsave(&bdev->lock, flags);
+               if (bdev->state != SCM_WR_PROHIBIT)
+                       pr_info("%lx: Write access to the SCM increment is suspended\n",
+                               (unsigned long) bdev->scmdev->address);
+               bdev->state = SCM_WR_PROHIBIT;
+               spin_unlock_irqrestore(&bdev->lock, flags);
+               goto requeue;
+       default:
+               break;
+       }
+
+restart:
+       if (!scm_start_aob(scmrq->aob))
+               return;
+
+requeue:
+       spin_lock_irqsave(&bdev->rq_lock, flags);
+       scm_request_requeue(scmrq);
+       spin_unlock_irqrestore(&bdev->rq_lock, flags);
+}
+
 static void scm_blk_tasklet(struct scm_blk_dev *bdev)
 {
        struct scm_request *scmrq;
@@ -293,11 +339,8 @@ static void scm_blk_tasklet(struct scm_blk_dev *bdev)
                spin_unlock_irqrestore(&bdev->lock, flags);
 
                if (scmrq->error && scmrq->retries-- > 0) {
-                       if (scm_start_aob(scmrq->aob)) {
-                               spin_lock_irqsave(&bdev->rq_lock, flags);
-                               scm_request_requeue(scmrq);
-                               spin_unlock_irqrestore(&bdev->rq_lock, flags);
-                       }
+                       scm_blk_handle_error(scmrq);
+
                        /* Request restarted or requeued, handle next. */
                        spin_lock_irqsave(&bdev->lock, flags);
                        continue;
@@ -310,7 +353,6 @@ static void scm_blk_tasklet(struct scm_blk_dev *bdev)
                }
 
                scm_request_finish(scmrq);
-               atomic_dec(&bdev->queued_reqs);
                spin_lock_irqsave(&bdev->lock, flags);
        }
        spin_unlock_irqrestore(&bdev->lock, flags);
@@ -332,6 +374,7 @@ int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev)
        }
 
        bdev->scmdev = scmdev;
+       bdev->state = SCM_OPER;
        spin_lock_init(&bdev->rq_lock);
        spin_lock_init(&bdev->lock);
        INIT_LIST_HEAD(&bdev->finished_requests);
@@ -396,6 +439,18 @@ void scm_blk_dev_cleanup(struct scm_blk_dev *bdev)
        put_disk(bdev->gendisk);
 }
 
+void scm_blk_set_available(struct scm_blk_dev *bdev)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&bdev->lock, flags);
+       if (bdev->state == SCM_WR_PROHIBIT)
+               pr_info("%lx: Write access to the SCM increment is restored\n",
+                       (unsigned long) bdev->scmdev->address);
+       bdev->state = SCM_OPER;
+       spin_unlock_irqrestore(&bdev->lock, flags);
+}
+
 static int __init scm_blk_init(void)
 {
        int ret = -EINVAL;
@@ -408,12 +463,15 @@ static int __init scm_blk_init(void)
                goto out;
 
        scm_major = ret;
-       if (scm_alloc_rqs(nr_requests))
+       ret = scm_alloc_rqs(nr_requests);
+       if (ret)
                goto out_unreg;
 
        scm_debug = debug_register("scm_log", 16, 1, 16);
-       if (!scm_debug)
+       if (!scm_debug) {
+               ret = -ENOMEM;
                goto out_free;
+       }
 
        debug_register_view(scm_debug, &debug_hex_ascii_view);
        debug_set_level(scm_debug, 2);
index 3c1ccf4946478dd5817b9a3c0435d89d5f164c06..8b387b32fd622b981a19e951eca1b3fd30c783bf 100644 (file)
@@ -21,6 +21,7 @@ struct scm_blk_dev {
        spinlock_t rq_lock;     /* guard the request queue */
        spinlock_t lock;        /* guard the rest of the blockdev */
        atomic_t queued_reqs;
+       enum {SCM_OPER, SCM_WR_PROHIBIT} state;
        struct list_head finished_requests;
 #ifdef CONFIG_SCM_BLOCK_CLUSTER_WRITE
        struct list_head cluster_list;
@@ -48,6 +49,7 @@ struct scm_request {
 
 int scm_blk_dev_setup(struct scm_blk_dev *, struct scm_device *);
 void scm_blk_dev_cleanup(struct scm_blk_dev *);
+void scm_blk_set_available(struct scm_blk_dev *);
 void scm_blk_irq(struct scm_device *, void *, int);
 
 void scm_request_finish(struct scm_request *);
index 9fa0a908607b013ce3ef0981a323d3b4e9043bde..c98cf52d78d19331adea46fc12cff94034f25b6b 100644 (file)
 #include <asm/eadm.h>
 #include "scm_blk.h"
 
-static void notify(struct scm_device *scmdev)
+static void scm_notify(struct scm_device *scmdev, enum scm_event event)
 {
-       pr_info("%lu: The capabilities of the SCM increment changed\n",
-               (unsigned long) scmdev->address);
-       SCM_LOG(2, "State changed");
-       SCM_LOG_STATE(2, scmdev);
+       struct scm_blk_dev *bdev = dev_get_drvdata(&scmdev->dev);
+
+       switch (event) {
+       case SCM_CHANGE:
+               pr_info("%lx: The capabilities of the SCM increment changed\n",
+                       (unsigned long) scmdev->address);
+               SCM_LOG(2, "State changed");
+               SCM_LOG_STATE(2, scmdev);
+               break;
+       case SCM_AVAIL:
+               SCM_LOG(2, "Increment available");
+               SCM_LOG_STATE(2, scmdev);
+               scm_blk_set_available(bdev);
+               break;
+       }
 }
 
 static int scm_probe(struct scm_device *scmdev)
@@ -64,7 +75,7 @@ static struct scm_driver scm_drv = {
                .name = "scm_block",
                .owner = THIS_MODULE,
        },
-       .notify = notify,
+       .notify = scm_notify,
        .probe = scm_probe,
        .remove = scm_remove,
        .handler = scm_blk_irq,
index 30a2255389e55303934d2e454fbd01fcfe947b2e..cd798386b622173172906cc021306d9cc64941bf 100644 (file)
@@ -627,6 +627,8 @@ static int __init sclp_detect_standby_memory(void)
        struct read_storage_sccb *sccb;
        int i, id, assigned, rc;
 
+       if (OLDMEM_BASE) /* No standby memory in kdump mode */
+               return 0;
        if (!early_read_info_sccb_valid)
                return 0;
        if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL)
index b907dba24025e12239960f97feb0c5510d9d33cd..cee69dac3e182b6e2de94300b49ac9ec35658430 100644 (file)
@@ -915,7 +915,7 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
        int i, rc;
 
        /* Check if the tty3270 is already there. */
-       view = raw3270_find_view(&tty3270_fn, tty->index);
+       view = raw3270_find_view(&tty3270_fn, tty->index + RAW3270_FIRSTMINOR);
        if (!IS_ERR(view)) {
                tp = container_of(view, struct tty3270, view);
                tty->driver_data = tp;
@@ -927,15 +927,16 @@ static int tty3270_install(struct tty_driver *driver, struct tty_struct *tty)
                tp->inattr = TF_INPUT;
                return tty_port_install(&tp->port, driver, tty);
        }
-       if (tty3270_max_index < tty->index)
-               tty3270_max_index = tty->index;
+       if (tty3270_max_index < tty->index + 1)
+               tty3270_max_index = tty->index + 1;
 
        /* Allocate tty3270 structure on first open. */
        tp = tty3270_alloc_view();
        if (IS_ERR(tp))
                return PTR_ERR(tp);
 
-       rc = raw3270_add_view(&tp->view, &tty3270_fn, tty->index);
+       rc = raw3270_add_view(&tp->view, &tty3270_fn,
+                             tty->index + RAW3270_FIRSTMINOR);
        if (rc) {
                tty3270_free_view(tp);
                return rc;
@@ -1846,12 +1847,12 @@ static const struct tty_operations tty3270_ops = {
 
 void tty3270_create_cb(int minor)
 {
-       tty_register_device(tty3270_driver, minor, NULL);
+       tty_register_device(tty3270_driver, minor - RAW3270_FIRSTMINOR, NULL);
 }
 
 void tty3270_destroy_cb(int minor)
 {
-       tty_unregister_device(tty3270_driver, minor);
+       tty_unregister_device(tty3270_driver, minor - RAW3270_FIRSTMINOR);
 }
 
 struct raw3270_notifier tty3270_notifier =
@@ -1884,7 +1885,8 @@ static int __init tty3270_init(void)
        driver->driver_name = "tty3270";
        driver->name = "3270/tty";
        driver->major = IBM_TTY3270_MAJOR;
-       driver->minor_start = 0;
+       driver->minor_start = RAW3270_FIRSTMINOR;
+       driver->name_base = RAW3270_FIRSTMINOR;
        driver->type = TTY_DRIVER_TYPE_SYSTEM;
        driver->subtype = SYSTEM_TYPE_TTY;
        driver->init_termios = tty_std_termios;
index 31ceef1beb8b06715090b9459f879997067896dd..e16c553f65561f453c4eed2a97eb4cda8a539231 100644 (file)
@@ -433,6 +433,20 @@ static void chsc_process_sei_scm_change(struct chsc_sei_nt0_area *sei_area)
                              " failed (rc=%d).\n", ret);
 }
 
+static void chsc_process_sei_scm_avail(struct chsc_sei_nt0_area *sei_area)
+{
+       int ret;
+
+       CIO_CRW_EVENT(4, "chsc: scm available information\n");
+       if (sei_area->rs != 7)
+               return;
+
+       ret = scm_process_availability_information();
+       if (ret)
+               CIO_CRW_EVENT(0, "chsc: process availability information"
+                             " failed (rc=%d).\n", ret);
+}
+
 static void chsc_process_sei_nt2(struct chsc_sei_nt2_area *sei_area)
 {
        switch (sei_area->cc) {
@@ -468,6 +482,9 @@ static void chsc_process_sei_nt0(struct chsc_sei_nt0_area *sei_area)
        case 12: /* scm change notification */
                chsc_process_sei_scm_change(sei_area);
                break;
+       case 14: /* scm available notification */
+               chsc_process_sei_scm_avail(sei_area);
+               break;
        default: /* other stuff */
                CIO_CRW_EVENT(2, "chsc: sei nt0 unhandled cc=%d\n",
                              sei_area->cc);
index 227e05f674b38a6151a3c3b99534c6700835640f..349d5fc471963a20d7f1dd4fec393ef44877d6a6 100644 (file)
@@ -156,8 +156,10 @@ int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token);
 
 #ifdef CONFIG_SCM_BUS
 int scm_update_information(void);
+int scm_process_availability_information(void);
 #else /* CONFIG_SCM_BUS */
 static inline int scm_update_information(void) { return 0; }
+static inline int scm_process_availability_information(void) { return 0; }
 #endif /* CONFIG_SCM_BUS */
 
 
index bcf20f3aa51b67fd148ae807e0cbc070e09e8b22..46ec25632e8bd4ef8e0be26a3f515697abd7f760 100644 (file)
@@ -211,7 +211,7 @@ static void scmdev_update(struct scm_device *scmdev, struct sale *sale)
                goto out;
        scmdrv = to_scm_drv(scmdev->dev.driver);
        if (changed && scmdrv->notify)
-               scmdrv->notify(scmdev);
+               scmdrv->notify(scmdev, SCM_CHANGE);
 out:
        device_unlock(&scmdev->dev);
        if (changed)
@@ -297,6 +297,22 @@ int scm_update_information(void)
        return ret;
 }
 
+static int scm_dev_avail(struct device *dev, void *unused)
+{
+       struct scm_driver *scmdrv = to_scm_drv(dev->driver);
+       struct scm_device *scmdev = to_scm_dev(dev);
+
+       if (dev->driver && scmdrv->notify)
+               scmdrv->notify(scmdev, SCM_AVAIL);
+
+       return 0;
+}
+
+int scm_process_availability_information(void)
+{
+       return bus_for_each_dev(&scm_bus_type, NULL, NULL, scm_dev_avail);
+}
+
 static int __init scm_init(void)
 {
        int ret;
index d87961d4c0defe7aced66b6430b34cc0c032d886..8c0622399fcd67bd7353b6274a3d370b3d9caaa4 100644 (file)
@@ -916,6 +916,7 @@ int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *,
        void *reply_param);
 int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int);
 int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int);
+int qeth_get_elements_for_frags(struct sk_buff *);
 int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *,
                        struct sk_buff *, struct qeth_hdr *, int, int, int);
 int qeth_do_send_packet(struct qeth_card *, struct qeth_qdio_out_q *,
index 0d8cdff818139e8ee267f57df08c78494c1592d0..0d73a999983d90ff632c0dcdcf6d54bedbd5a289 100644 (file)
@@ -3679,6 +3679,25 @@ int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb,
 }
 EXPORT_SYMBOL_GPL(qeth_get_priority_queue);
 
+int qeth_get_elements_for_frags(struct sk_buff *skb)
+{
+       int cnt, length, e, elements = 0;
+       struct skb_frag_struct *frag;
+       char *data;
+
+       for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) {
+               frag = &skb_shinfo(skb)->frags[cnt];
+               data = (char *)page_to_phys(skb_frag_page(frag)) +
+                       frag->page_offset;
+               length = frag->size;
+               e = PFN_UP((unsigned long)data + length - 1) -
+                       PFN_DOWN((unsigned long)data);
+               elements += e;
+       }
+       return elements;
+}
+EXPORT_SYMBOL_GPL(qeth_get_elements_for_frags);
+
 int qeth_get_elements_no(struct qeth_card *card, void *hdr,
                     struct sk_buff *skb, int elems)
 {
@@ -3686,7 +3705,8 @@ int qeth_get_elements_no(struct qeth_card *card, void *hdr,
        int elements_needed = PFN_UP((unsigned long)skb->data + dlen - 1) -
                PFN_DOWN((unsigned long)skb->data);
 
-       elements_needed += skb_shinfo(skb)->nr_frags;
+       elements_needed += qeth_get_elements_for_frags(skb);
+
        if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) {
                QETH_DBF_MESSAGE(2, "Invalid size of IP packet "
                        "(Number=%d / Length=%d). Discarded.\n",
@@ -3771,12 +3791,23 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb,
 
        for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) {
                frag = &skb_shinfo(skb)->frags[cnt];
-               buffer->element[element].addr = (char *)
-                       page_to_phys(skb_frag_page(frag))
-                       + frag->page_offset;
-               buffer->element[element].length = frag->size;
-               buffer->element[element].eflags = SBAL_EFLAGS_MIDDLE_FRAG;
-               element++;
+               data = (char *)page_to_phys(skb_frag_page(frag)) +
+                       frag->page_offset;
+               length = frag->size;
+               while (length > 0) {
+                       length_here = PAGE_SIZE -
+                               ((unsigned long) data % PAGE_SIZE);
+                       if (length < length_here)
+                               length_here = length;
+
+                       buffer->element[element].addr = data;
+                       buffer->element[element].length = length_here;
+                       buffer->element[element].eflags =
+                               SBAL_EFLAGS_MIDDLE_FRAG;
+                       length -= length_here;
+                       data += length_here;
+                       element++;
+               }
        }
 
        if (buffer->element[element - 1].eflags)
index 091ca0efa1c539e0ca27f57f55a00cb543bfc304..8710337dab3eceb4e5fa692d6a39accd697ba508 100644 (file)
@@ -623,7 +623,7 @@ static int qeth_l3_send_setrouting(struct qeth_card *card,
        return rc;
 }
 
-static void qeth_l3_correct_routing_type(struct qeth_card *card,
+static int qeth_l3_correct_routing_type(struct qeth_card *card,
                enum qeth_routing_types *type, enum qeth_prot_versions prot)
 {
        if (card->info.type == QETH_CARD_TYPE_IQD) {
@@ -632,7 +632,7 @@ static void qeth_l3_correct_routing_type(struct qeth_card *card,
                case PRIMARY_CONNECTOR:
                case SECONDARY_CONNECTOR:
                case MULTICAST_ROUTER:
-                       return;
+                       return 0;
                default:
                        goto out_inval;
                }
@@ -641,17 +641,18 @@ static void qeth_l3_correct_routing_type(struct qeth_card *card,
                case NO_ROUTER:
                case PRIMARY_ROUTER:
                case SECONDARY_ROUTER:
-                       return;
+                       return 0;
                case MULTICAST_ROUTER:
                        if (qeth_is_ipafunc_supported(card, prot,
                                                      IPA_OSA_MC_ROUTER))
-                               return;
+                               return 0;
                default:
                        goto out_inval;
                }
        }
 out_inval:
        *type = NO_ROUTER;
+       return -EINVAL;
 }
 
 int qeth_l3_setrouting_v4(struct qeth_card *card)
@@ -660,8 +661,10 @@ int qeth_l3_setrouting_v4(struct qeth_card *card)
 
        QETH_CARD_TEXT(card, 3, "setrtg4");
 
-       qeth_l3_correct_routing_type(card, &card->options.route4.type,
+       rc = qeth_l3_correct_routing_type(card, &card->options.route4.type,
                                  QETH_PROT_IPV4);
+       if (rc)
+               return rc;
 
        rc = qeth_l3_send_setrouting(card, card->options.route4.type,
                                  QETH_PROT_IPV4);
@@ -683,8 +686,10 @@ int qeth_l3_setrouting_v6(struct qeth_card *card)
 
        if (!qeth_is_supported(card, IPA_IPV6))
                return 0;
-       qeth_l3_correct_routing_type(card, &card->options.route6.type,
+       rc = qeth_l3_correct_routing_type(card, &card->options.route6.type,
                                  QETH_PROT_IPV6);
+       if (rc)
+               return rc;
 
        rc = qeth_l3_send_setrouting(card, card->options.route6.type,
                                  QETH_PROT_IPV6);
@@ -2898,7 +2903,9 @@ static inline int qeth_l3_tso_elements(struct sk_buff *skb)
                tcp_hdr(skb)->doff * 4;
        int tcpd_len = skb->len - (tcpd - (unsigned long)skb->data);
        int elements = PFN_UP(tcpd + tcpd_len - 1) - PFN_DOWN(tcpd);
-       elements += skb_shinfo(skb)->nr_frags;
+
+       elements += qeth_get_elements_for_frags(skb);
+
        return elements;
 }
 
@@ -3348,7 +3355,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)
                rc = -ENODEV;
                goto out_remove;
        }
-       qeth_trace_features(card);
 
        if (!card->dev && qeth_l3_setup_netdev(card)) {
                rc = -ENODEV;
@@ -3425,6 +3431,7 @@ contin:
                qeth_l3_set_multicast_list(card->dev);
                rtnl_unlock();
        }
+       qeth_trace_features(card);
        /* let user_space know that device is online */
        kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE);
        mutex_unlock(&card->conf_mutex);
index ebc3794862675e591b45395f29cc0f6cf4c5e801..e70af2406ff9da388828660bb0bed2b73bf5cb71 100644 (file)
@@ -87,6 +87,8 @@ static ssize_t qeth_l3_dev_route_store(struct qeth_card *card,
                        rc = qeth_l3_setrouting_v6(card);
        }
 out:
+       if (rc)
+               route->type = old_route_type;
        mutex_unlock(&card->conf_mutex);
        return rc ? rc : count;
 }
index 2daf4b0da434c8711c4a7907916b1b8138c412f2..90bc7bd00966e9a87845bee59c1976a74d959fb3 100644 (file)
@@ -940,6 +940,7 @@ static int bnx2fc_libfc_config(struct fc_lport *lport)
        fc_exch_init(lport);
        fc_rport_init(lport);
        fc_disc_init(lport);
+       fc_disc_config(lport, lport);
        return 0;
 }
 
@@ -2133,6 +2134,7 @@ static int _bnx2fc_create(struct net_device *netdev,
        }
 
        ctlr = bnx2fc_to_ctlr(interface);
+       cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
        interface->vlan_id = vlan_id;
 
        interface->timer_work_queue =
@@ -2143,7 +2145,7 @@ static int _bnx2fc_create(struct net_device *netdev,
                goto ifput_err;
        }
 
-       lport = bnx2fc_if_create(interface, &interface->hba->pcidev->dev, 0);
+       lport = bnx2fc_if_create(interface, &cdev->dev, 0);
        if (!lport) {
                printk(KERN_ERR PFX "Failed to create interface (%s)\n",
                        netdev->name);
@@ -2159,8 +2161,6 @@ static int _bnx2fc_create(struct net_device *netdev,
        /* Make this master N_port */
        ctlr->lp = lport;
 
-       cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
-
        if (link_state == BNX2FC_CREATE_LINK_UP)
                cdev->enabled = FCOE_CTLR_ENABLED;
        else
index b5d92fc93c7023f6d0f395c5ce44c4589afeabea..9bfdc9a3f897a2e16dc9e0a34d5d6e47969c0d1c 100644 (file)
@@ -490,7 +490,6 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
 {
        struct net_device *netdev = fcoe->netdev;
        struct fcoe_ctlr *fip = fcoe_to_ctlr(fcoe);
-       struct fcoe_ctlr_device *ctlr_dev = fcoe_ctlr_to_ctlr_dev(fip);
 
        rtnl_lock();
        if (!fcoe->removed)
@@ -501,7 +500,6 @@ static void fcoe_interface_cleanup(struct fcoe_interface *fcoe)
        /* tear-down the FCoE controller */
        fcoe_ctlr_destroy(fip);
        scsi_host_put(fip->lp->host);
-       fcoe_ctlr_device_delete(ctlr_dev);
        dev_put(netdev);
        module_put(THIS_MODULE);
 }
@@ -2194,6 +2192,8 @@ out_nodev:
  */
 static void fcoe_destroy_work(struct work_struct *work)
 {
+       struct fcoe_ctlr_device *cdev;
+       struct fcoe_ctlr *ctlr;
        struct fcoe_port *port;
        struct fcoe_interface *fcoe;
        struct Scsi_Host *shost;
@@ -2224,10 +2224,15 @@ static void fcoe_destroy_work(struct work_struct *work)
        mutex_lock(&fcoe_config_mutex);
 
        fcoe = port->priv;
+       ctlr = fcoe_to_ctlr(fcoe);
+       cdev = fcoe_ctlr_to_ctlr_dev(ctlr);
+
        fcoe_if_destroy(port->lport);
        fcoe_interface_cleanup(fcoe);
 
        mutex_unlock(&fcoe_config_mutex);
+
+       fcoe_ctlr_device_delete(cdev);
 }
 
 /**
@@ -2335,7 +2340,9 @@ static int _fcoe_create(struct net_device *netdev, enum fip_state fip_mode,
                rc = -EIO;
                rtnl_unlock();
                fcoe_interface_cleanup(fcoe);
-               goto out_nortnl;
+               mutex_unlock(&fcoe_config_mutex);
+               fcoe_ctlr_device_delete(ctlr_dev);
+               goto out;
        }
 
        /* Make this the "master" N_Port */
@@ -2375,8 +2382,8 @@ static int _fcoe_create(struct net_device *netdev, enum fip_state fip_mode,
 
 out_nodev:
        rtnl_unlock();
-out_nortnl:
        mutex_unlock(&fcoe_config_mutex);
+out:
        return rc;
 }
 
index 08c3bc398da2c1b234dadb62a56f1e1b47da5500..a76247201be570987fe28b44545184bd777e65c0 100644 (file)
@@ -2814,6 +2814,47 @@ unlock:
                fc_lport_set_local_id(fip->lp, new_port_id);
 }
 
+/**
+ * fcoe_ctlr_mode_set() - Set or reset the ctlr's mode
+ * @lport: The local port to be (re)configured
+ * @fip:   The FCoE controller whose mode is changing
+ * @fip_mode: The new fip mode
+ *
+ * Note that the we shouldn't be changing the libfc discovery settings
+ * (fc_disc_config) while an lport is going through the libfc state
+ * machine. The mode can only be changed when a fcoe_ctlr device is
+ * disabled, so that should ensure that this routine is only called
+ * when nothing is happening.
+ */
+void fcoe_ctlr_mode_set(struct fc_lport *lport, struct fcoe_ctlr *fip,
+                       enum fip_state fip_mode)
+{
+       void *priv;
+
+       WARN_ON(lport->state != LPORT_ST_RESET &&
+               lport->state != LPORT_ST_DISABLED);
+
+       if (fip_mode == FIP_MODE_VN2VN) {
+               lport->rport_priv_size = sizeof(struct fcoe_rport);
+               lport->point_to_multipoint = 1;
+               lport->tt.disc_recv_req = fcoe_ctlr_disc_recv;
+               lport->tt.disc_start = fcoe_ctlr_disc_start;
+               lport->tt.disc_stop = fcoe_ctlr_disc_stop;
+               lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final;
+               priv = fip;
+       } else {
+               lport->rport_priv_size = 0;
+               lport->point_to_multipoint = 0;
+               lport->tt.disc_recv_req = NULL;
+               lport->tt.disc_start = NULL;
+               lport->tt.disc_stop = NULL;
+               lport->tt.disc_stop_final = NULL;
+               priv = lport;
+       }
+
+       fc_disc_config(lport, priv);
+}
+
 /**
  * fcoe_libfc_config() - Sets up libfc related properties for local port
  * @lport:    The local port to configure libfc for
@@ -2833,21 +2874,9 @@ int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip,
        fc_exch_init(lport);
        fc_elsct_init(lport);
        fc_lport_init(lport);
-       if (fip->mode == FIP_MODE_VN2VN)
-               lport->rport_priv_size = sizeof(struct fcoe_rport);
        fc_rport_init(lport);
-       if (fip->mode == FIP_MODE_VN2VN) {
-               lport->point_to_multipoint = 1;
-               lport->tt.disc_recv_req = fcoe_ctlr_disc_recv;
-               lport->tt.disc_start = fcoe_ctlr_disc_start;
-               lport->tt.disc_stop = fcoe_ctlr_disc_stop;
-               lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final;
-               mutex_init(&lport->disc.disc_mutex);
-               INIT_LIST_HEAD(&lport->disc.rports);
-               lport->disc.priv = fip;
-       } else {
-               fc_disc_init(lport);
-       }
+       fc_disc_init(lport);
+       fcoe_ctlr_mode_set(lport, fip, fip->mode);
        return 0;
 }
 EXPORT_SYMBOL_GPL(fcoe_libfc_config);
@@ -2875,6 +2904,7 @@ EXPORT_SYMBOL(fcoe_fcf_get_selected);
 void fcoe_ctlr_set_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
 {
        struct fcoe_ctlr *ctlr = fcoe_ctlr_device_priv(ctlr_dev);
+       struct fc_lport *lport = ctlr->lp;
 
        mutex_lock(&ctlr->ctlr_mutex);
        switch (ctlr_dev->mode) {
@@ -2888,5 +2918,7 @@ void fcoe_ctlr_set_fip_mode(struct fcoe_ctlr_device *ctlr_dev)
        }
 
        mutex_unlock(&ctlr->ctlr_mutex);
+
+       fcoe_ctlr_mode_set(lport, ctlr, ctlr->mode);
 }
 EXPORT_SYMBOL(fcoe_ctlr_set_fip_mode);
index 8e561e6a557cd956188366488d5b4ed3dfe66021..880a9068ca1268baf851ea8804f3bdb4216049f6 100644 (file)
@@ -712,12 +712,13 @@ static void fc_disc_stop_final(struct fc_lport *lport)
 }
 
 /**
- * fc_disc_init() - Initialize the discovery layer for a local port
- * @lport: The local port that needs the discovery layer to be initialized
+ * fc_disc_config() - Configure the discovery layer for a local port
+ * @lport: The local port that needs the discovery layer to be configured
+ * @priv: Private data structre for users of the discovery layer
  */
-int fc_disc_init(struct fc_lport *lport)
+void fc_disc_config(struct fc_lport *lport, void *priv)
 {
-       struct fc_disc *disc;
+       struct fc_disc *disc = &lport->disc;
 
        if (!lport->tt.disc_start)
                lport->tt.disc_start = fc_disc_start;
@@ -732,12 +733,21 @@ int fc_disc_init(struct fc_lport *lport)
                lport->tt.disc_recv_req = fc_disc_recv_req;
 
        disc = &lport->disc;
+
+       disc->priv = priv;
+}
+EXPORT_SYMBOL(fc_disc_config);
+
+/**
+ * fc_disc_init() - Initialize the discovery layer for a local port
+ * @lport: The local port that needs the discovery layer to be initialized
+ */
+void fc_disc_init(struct fc_lport *lport)
+{
+       struct fc_disc *disc = &lport->disc;
+
        INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout);
        mutex_init(&disc->disc_mutex);
        INIT_LIST_HEAD(&disc->rports);
-
-       disc->priv = lport;
-
-       return 0;
 }
 EXPORT_SYMBOL(fc_disc_init);
index f80eee74a3116c5a8935378d908fce904e3351f6..2be0de920d6756345de9cc78e04a7c1136ef9d4d 100644 (file)
@@ -55,6 +55,7 @@ comment "SPI Master Controller Drivers"
 
 config SPI_ALTERA
        tristate "Altera SPI Controller"
+       depends on GENERIC_HARDIRQS
        select SPI_BITBANG
        help
          This is the driver for the Altera SPI Controller.
@@ -310,7 +311,7 @@ config SPI_PXA2XX_DMA
 
 config SPI_PXA2XX
        tristate "PXA2xx SSP SPI master"
-       depends on ARCH_PXA || PCI || ACPI
+       depends on (ARCH_PXA || PCI || ACPI) && GENERIC_HARDIRQS
        select PXA_SSP if ARCH_PXA
        help
          This enables using a PXA2xx or Sodaville SSP port as a SPI master
index 9578af782a7732e3c9d4e4242c780f0bb7a21d01..d7df435d962e54db6a3121b55a4546f05bb69303 100644 (file)
@@ -152,7 +152,6 @@ static void bcm63xx_spi_setup_transfer(struct spi_device *spi,
 static int bcm63xx_spi_setup(struct spi_device *spi)
 {
        struct bcm63xx_spi *bs;
-       int ret;
 
        bs = spi_master_get_devdata(spi->master);
 
@@ -490,7 +489,7 @@ static int bcm63xx_spi_probe(struct platform_device *pdev)
        default:
                dev_err(dev, "unsupported MSG_CTL width: %d\n",
                         bs->msg_ctl_width);
-               goto out_clk_disable;
+               goto out_err;
        }
 
        /* Initialize hardware */
index 89480b281d74715ad0eaa6cf63bf354546f99fc4..3e490ee7f275be30447ce5a3030f7872da634695 100644 (file)
@@ -164,7 +164,7 @@ static int mpc512x_psc_spi_transfer_rxtx(struct spi_device *spi,
 
                for (i = count; i > 0; i--) {
                        data = tx_buf ? *tx_buf++ : 0;
-                       if (len == EOFBYTE)
+                       if (len == EOFBYTE && t->cs_change)
                                setbits32(&fifo->txcmd, MPC512x_PSC_FIFO_EOF);
                        out_8(&fifo->txdata_8, data);
                        len--;
index 90b27a3508a65072bf8916fecea96f16ee73cbeb..810413883c79326d3cd31b18db2f9a8972a96967 100644 (file)
@@ -1168,7 +1168,6 @@ static int pxa2xx_spi_probe(struct platform_device *pdev)
 
        master->dev.parent = &pdev->dev;
        master->dev.of_node = pdev->dev.of_node;
-       ACPI_HANDLE_SET(&master->dev, ACPI_HANDLE(&pdev->dev));
        /* the spi->mode bits understood by this driver: */
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
 
index e862ab8853aa1f9ff242cdde3bf741dc2a257dd2..4188b2faac5cbb97a88225e39da14a78674ea74d 100644 (file)
@@ -994,25 +994,30 @@ static irqreturn_t s3c64xx_spi_irq(int irq, void *data)
 {
        struct s3c64xx_spi_driver_data *sdd = data;
        struct spi_master *spi = sdd->master;
-       unsigned int val;
+       unsigned int val, clr = 0;
 
-       val = readl(sdd->regs + S3C64XX_SPI_PENDING_CLR);
+       val = readl(sdd->regs + S3C64XX_SPI_STATUS);
 
-       val &= S3C64XX_SPI_PND_RX_OVERRUN_CLR |
-               S3C64XX_SPI_PND_RX_UNDERRUN_CLR |
-               S3C64XX_SPI_PND_TX_OVERRUN_CLR |
-               S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
-
-       writel(val, sdd->regs + S3C64XX_SPI_PENDING_CLR);
-
-       if (val & S3C64XX_SPI_PND_RX_OVERRUN_CLR)
+       if (val & S3C64XX_SPI_ST_RX_OVERRUN_ERR) {
+               clr = S3C64XX_SPI_PND_RX_OVERRUN_CLR;
                dev_err(&spi->dev, "RX overrun\n");
-       if (val & S3C64XX_SPI_PND_RX_UNDERRUN_CLR)
+       }
+       if (val & S3C64XX_SPI_ST_RX_UNDERRUN_ERR) {
+               clr |= S3C64XX_SPI_PND_RX_UNDERRUN_CLR;
                dev_err(&spi->dev, "RX underrun\n");
-       if (val & S3C64XX_SPI_PND_TX_OVERRUN_CLR)
+       }
+       if (val & S3C64XX_SPI_ST_TX_OVERRUN_ERR) {
+               clr |= S3C64XX_SPI_PND_TX_OVERRUN_CLR;
                dev_err(&spi->dev, "TX overrun\n");
-       if (val & S3C64XX_SPI_PND_TX_UNDERRUN_CLR)
+       }
+       if (val & S3C64XX_SPI_ST_TX_UNDERRUN_ERR) {
+               clr |= S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
                dev_err(&spi->dev, "TX underrun\n");
+       }
+
+       /* Clear the pending irq by setting and then clearing it */
+       writel(clr, sdd->regs + S3C64XX_SPI_PENDING_CLR);
+       writel(0, sdd->regs + S3C64XX_SPI_PENDING_CLR);
 
        return IRQ_HANDLED;
 }
@@ -1036,9 +1041,13 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
        writel(0, regs + S3C64XX_SPI_MODE_CFG);
        writel(0, regs + S3C64XX_SPI_PACKET_CNT);
 
-       /* Clear any irq pending bits */
-       writel(readl(regs + S3C64XX_SPI_PENDING_CLR),
-                               regs + S3C64XX_SPI_PENDING_CLR);
+       /* Clear any irq pending bits, should set and clear the bits */
+       val = S3C64XX_SPI_PND_RX_OVERRUN_CLR |
+               S3C64XX_SPI_PND_RX_UNDERRUN_CLR |
+               S3C64XX_SPI_PND_TX_OVERRUN_CLR |
+               S3C64XX_SPI_PND_TX_UNDERRUN_CLR;
+       writel(val, regs + S3C64XX_SPI_PENDING_CLR);
+       writel(0, regs + S3C64XX_SPI_PENDING_CLR);
 
        writel(0, regs + S3C64XX_SPI_SWAP_CFG);
 
index b8698b389ef3ec6980da435317ec383f2c1ea22a..a829563f471380dfe04d530f8ec6155bff19c4a7 100644 (file)
@@ -858,21 +858,6 @@ static int tegra_slink_setup(struct spi_device *spi)
        return 0;
 }
 
-static int tegra_slink_prepare_transfer(struct spi_master *master)
-{
-       struct tegra_slink_data *tspi = spi_master_get_devdata(master);
-
-       return pm_runtime_get_sync(tspi->dev);
-}
-
-static int tegra_slink_unprepare_transfer(struct spi_master *master)
-{
-       struct tegra_slink_data *tspi = spi_master_get_devdata(master);
-
-       pm_runtime_put(tspi->dev);
-       return 0;
-}
-
 static int tegra_slink_transfer_one_message(struct spi_master *master,
                        struct spi_message *msg)
 {
@@ -885,6 +870,12 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
 
        msg->status = 0;
        msg->actual_length = 0;
+       ret = pm_runtime_get_sync(tspi->dev);
+       if (ret < 0) {
+               dev_err(tspi->dev, "runtime get failed: %d\n", ret);
+               goto done;
+       }
+
        single_xfer = list_is_singular(&msg->transfers);
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
                INIT_COMPLETION(tspi->xfer_completion);
@@ -921,6 +912,8 @@ static int tegra_slink_transfer_one_message(struct spi_master *master,
 exit:
        tegra_slink_writel(tspi, tspi->def_command_reg, SLINK_COMMAND);
        tegra_slink_writel(tspi, tspi->def_command2_reg, SLINK_COMMAND2);
+       pm_runtime_put(tspi->dev);
+done:
        msg->status = ret;
        spi_finalize_current_message(master);
        return ret;
@@ -1148,9 +1141,7 @@ static int tegra_slink_probe(struct platform_device *pdev)
        /* the spi->mode bits understood by this driver: */
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
        master->setup = tegra_slink_setup;
-       master->prepare_transfer_hardware = tegra_slink_prepare_transfer;
        master->transfer_one_message = tegra_slink_transfer_one_message;
-       master->unprepare_transfer_hardware = tegra_slink_unprepare_transfer;
        master->num_chipselect = MAX_CHIP_SELECT;
        master->bus_num = -1;
 
index f996c600eb8c6a63b0d3122dd0b267a95d032555..004b10f184d4e7fe00916af3fc5acad6d7866139 100644 (file)
@@ -543,17 +543,16 @@ static void spi_pump_messages(struct kthread_work *work)
        /* Lock queue and check for queue work */
        spin_lock_irqsave(&master->queue_lock, flags);
        if (list_empty(&master->queue) || !master->running) {
-               if (master->busy && master->unprepare_transfer_hardware) {
-                       ret = master->unprepare_transfer_hardware(master);
-                       if (ret) {
-                               spin_unlock_irqrestore(&master->queue_lock, flags);
-                               dev_err(&master->dev,
-                                       "failed to unprepare transfer hardware\n");
-                               return;
-                       }
+               if (!master->busy) {
+                       spin_unlock_irqrestore(&master->queue_lock, flags);
+                       return;
                }
                master->busy = false;
                spin_unlock_irqrestore(&master->queue_lock, flags);
+               if (master->unprepare_transfer_hardware &&
+                   master->unprepare_transfer_hardware(master))
+                       dev_err(&master->dev,
+                               "failed to unprepare transfer hardware\n");
                return;
        }
 
@@ -984,7 +983,7 @@ static void acpi_register_spi_devices(struct spi_master *master)
        acpi_status status;
        acpi_handle handle;
 
-       handle = ACPI_HANDLE(&master->dev);
+       handle = ACPI_HANDLE(master->dev.parent);
        if (!handle)
                return;
 
index 192cf088f834a07c2388b50f0cc357e9f9298d36..57b4519047911dc36000580b87296e1716ebf5ed 100644 (file)
@@ -947,12 +947,13 @@ static int dt9812_di_rinsn(struct comedi_device *dev,
                           unsigned int *data)
 {
        struct comedi_dt9812 *devpriv = dev->private;
+       unsigned int channel = CR_CHAN(insn->chanspec);
        int n;
        u8 bits = 0;
 
        dt9812_digital_in(devpriv->slot, &bits);
        for (n = 0; n < insn->n; n++)
-               data[n] = ((1 << insn->chanspec) & bits) != 0;
+               data[n] = ((1 << channel) & bits) != 0;
        return n;
 }
 
@@ -961,12 +962,13 @@ static int dt9812_do_winsn(struct comedi_device *dev,
                           unsigned int *data)
 {
        struct comedi_dt9812 *devpriv = dev->private;
+       unsigned int channel = CR_CHAN(insn->chanspec);
        int n;
        u8 bits = 0;
 
        dt9812_digital_out_shadow(devpriv->slot, &bits);
        for (n = 0; n < insn->n; n++) {
-               u8 mask = 1 << insn->chanspec;
+               u8 mask = 1 << channel;
 
                bits &= ~mask;
                if (data[n])
@@ -981,13 +983,13 @@ static int dt9812_ai_rinsn(struct comedi_device *dev,
                           unsigned int *data)
 {
        struct comedi_dt9812 *devpriv = dev->private;
+       unsigned int channel = CR_CHAN(insn->chanspec);
        int n;
 
        for (n = 0; n < insn->n; n++) {
                u16 value = 0;
 
-               dt9812_analog_in(devpriv->slot, insn->chanspec, &value,
-                                DT9812_GAIN_1);
+               dt9812_analog_in(devpriv->slot, channel, &value, DT9812_GAIN_1);
                data[n] = value;
        }
        return n;
@@ -998,12 +1000,13 @@ static int dt9812_ao_rinsn(struct comedi_device *dev,
                           unsigned int *data)
 {
        struct comedi_dt9812 *devpriv = dev->private;
+       unsigned int channel = CR_CHAN(insn->chanspec);
        int n;
        u16 value;
 
        for (n = 0; n < insn->n; n++) {
                value = 0;
-               dt9812_analog_out_shadow(devpriv->slot, insn->chanspec, &value);
+               dt9812_analog_out_shadow(devpriv->slot, channel, &value);
                data[n] = value;
        }
        return n;
@@ -1014,10 +1017,11 @@ static int dt9812_ao_winsn(struct comedi_device *dev,
                           unsigned int *data)
 {
        struct comedi_dt9812 *devpriv = dev->private;
+       unsigned int channel = CR_CHAN(insn->chanspec);
        int n;
 
        for (n = 0; n < insn->n; n++)
-               dt9812_analog_out(devpriv->slot, insn->chanspec, data[n]);
+               dt9812_analog_out(devpriv->slot, channel, data[n]);
        return n;
 }
 
index 81a1fe661579d365ff82dfac8c0de06b53045110..71a73ec5af8d90811faebf7d087c705231a0a316 100644 (file)
@@ -1483,7 +1483,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
        case TRIG_NONE:
                /*  continous acquisition */
                devpriv->ai_continous = 1;
-               devpriv->ai_sample_count = 0;
+               devpriv->ai_sample_count = 1;
                break;
        }
 
index 1a0062a04456c54c517acc7d73454014555a7611..6aac1f60bc42c1cc927cd2a9930aa1bc356f28cb 100644 (file)
@@ -730,10 +730,14 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb)
 static int usbduxsub_start(struct usbduxsub *usbduxsub)
 {
        int errcode = 0;
-       uint8_t local_transfer_buffer[16];
+       uint8_t *local_transfer_buffer;
+
+       local_transfer_buffer = kmalloc(1, GFP_KERNEL);
+       if (!local_transfer_buffer)
+               return -ENOMEM;
 
        /* 7f92 to zero */
-       local_transfer_buffer[0] = 0;
+       *local_transfer_buffer = 0;
        errcode = usb_control_msg(usbduxsub->usbdev,
                                  /* create a pipe for a control transfer */
                                  usb_sndctrlpipe(usbduxsub->usbdev, 0),
@@ -751,22 +755,25 @@ static int usbduxsub_start(struct usbduxsub *usbduxsub)
                                  1,
                                  /* Timeout */
                                  BULK_TIMEOUT);
-       if (errcode < 0) {
+       if (errcode < 0)
                dev_err(&usbduxsub->interface->dev,
                        "comedi_: control msg failed (start)\n");
-               return errcode;
-       }
-       return 0;
+
+       kfree(local_transfer_buffer);
+       return errcode;
 }
 
 static int usbduxsub_stop(struct usbduxsub *usbduxsub)
 {
        int errcode = 0;
+       uint8_t *local_transfer_buffer;
 
-       uint8_t local_transfer_buffer[16];
+       local_transfer_buffer = kmalloc(1, GFP_KERNEL);
+       if (!local_transfer_buffer)
+               return -ENOMEM;
 
        /* 7f92 to one */
-       local_transfer_buffer[0] = 1;
+       *local_transfer_buffer = 1;
        errcode = usb_control_msg(usbduxsub->usbdev,
                                  usb_sndctrlpipe(usbduxsub->usbdev, 0),
                                  /* bRequest, "Firmware" */
@@ -781,12 +788,12 @@ static int usbduxsub_stop(struct usbduxsub *usbduxsub)
                                  1,
                                  /* Timeout */
                                  BULK_TIMEOUT);
-       if (errcode < 0) {
+       if (errcode < 0)
                dev_err(&usbduxsub->interface->dev,
                        "comedi_: control msg failed (stop)\n");
-               return errcode;
-       }
-       return 0;
+
+       kfree(local_transfer_buffer);
+       return errcode;
 }
 
 static int usbduxsub_upload(struct usbduxsub *usbduxsub,
index 4bf5dd094dc9da043b2aea8302c6638e229cf926..1ba0e3df492d1e9ceeedcebe4af3e85b82a08491 100644 (file)
@@ -436,10 +436,14 @@ static void usbduxfastsub_ai_Irq(struct urb *urb)
 static int usbduxfastsub_start(struct usbduxfastsub_s *udfs)
 {
        int ret;
-       unsigned char local_transfer_buffer[16];
+       unsigned char *local_transfer_buffer;
+
+       local_transfer_buffer = kmalloc(1, GFP_KERNEL);
+       if (!local_transfer_buffer)
+               return -ENOMEM;
 
        /* 7f92 to zero */
-       local_transfer_buffer[0] = 0;
+       *local_transfer_buffer = 0;
        /* bRequest, "Firmware" */
        ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0),
                              USBDUXFASTSUB_FIRMWARE,
@@ -450,22 +454,25 @@ static int usbduxfastsub_start(struct usbduxfastsub_s *udfs)
                              local_transfer_buffer,
                              1,      /* Length */
                              EZTIMEOUT);    /* Timeout */
-       if (ret < 0) {
+       if (ret < 0)
                dev_err(&udfs->interface->dev,
                        "control msg failed (start)\n");
-               return ret;
-       }
 
-       return 0;
+       kfree(local_transfer_buffer);
+       return ret;
 }
 
 static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs)
 {
        int ret;
-       unsigned char local_transfer_buffer[16];
+       unsigned char *local_transfer_buffer;
+
+       local_transfer_buffer = kmalloc(1, GFP_KERNEL);
+       if (!local_transfer_buffer)
+               return -ENOMEM;
 
        /* 7f92 to one */
-       local_transfer_buffer[0] = 1;
+       *local_transfer_buffer = 1;
        /* bRequest, "Firmware" */
        ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0),
                              USBDUXFASTSUB_FIRMWARE,
@@ -474,13 +481,12 @@ static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs)
                              0x0000,   /* Index */
                              local_transfer_buffer, 1, /* Length */
                              EZTIMEOUT);       /* Timeout */
-       if (ret < 0) {
+       if (ret < 0)
                dev_err(&udfs->interface->dev,
                        "control msg failed (stop)\n");
-               return ret;
-       }
 
-       return 0;
+       kfree(local_transfer_buffer);
+       return ret;
 }
 
 static int usbduxfastsub_upload(struct usbduxfastsub_s *udfs,
index d066351a71b2793d4f1ad60dd27e8db7dd0ea0e7..a728c8fc32a270e4a8963dc0eca3e14799fd6602 100644 (file)
@@ -681,7 +681,11 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb)
 static int usbduxsub_start(struct usbduxsub *usbduxsub)
 {
        int errcode = 0;
-       uint8_t local_transfer_buffer[16];
+       uint8_t *local_transfer_buffer;
+
+       local_transfer_buffer = kmalloc(16, GFP_KERNEL);
+       if (!local_transfer_buffer)
+               return -ENOMEM;
 
        /* 7f92 to zero */
        local_transfer_buffer[0] = 0;
@@ -702,19 +706,22 @@ static int usbduxsub_start(struct usbduxsub *usbduxsub)
                                  1,
                                  /* Timeout */
                                  BULK_TIMEOUT);
-       if (errcode < 0) {
+       if (errcode < 0)
                dev_err(&usbduxsub->interface->dev,
                        "comedi_: control msg failed (start)\n");
-               return errcode;
-       }
-       return 0;
+
+       kfree(local_transfer_buffer);
+       return errcode;
 }
 
 static int usbduxsub_stop(struct usbduxsub *usbduxsub)
 {
        int errcode = 0;
+       uint8_t *local_transfer_buffer;
 
-       uint8_t local_transfer_buffer[16];
+       local_transfer_buffer = kmalloc(16, GFP_KERNEL);
+       if (!local_transfer_buffer)
+               return -ENOMEM;
 
        /* 7f92 to one */
        local_transfer_buffer[0] = 1;
@@ -732,12 +739,12 @@ static int usbduxsub_stop(struct usbduxsub *usbduxsub)
                                  1,
                                  /* Timeout */
                                  BULK_TIMEOUT);
-       if (errcode < 0) {
+       if (errcode < 0)
                dev_err(&usbduxsub->interface->dev,
                        "comedi_: control msg failed (stop)\n");
-               return errcode;
-       }
-       return 0;
+
+       kfree(local_transfer_buffer);
+       return errcode;
 }
 
 static int usbduxsub_upload(struct usbduxsub *usbduxsub,
index 4b3a019409b5793632efa538cdcf65e0030f217f..b028b0d1317b8c4d89967c64bd5d5e20cdfa9f35 100644 (file)
@@ -483,17 +483,6 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc,
                goto err_out;
        }
 
-       ipu_crtc->irq = ipu_idmac_channel_irq(ipu, ipu_crtc->ipu_ch,
-                       IPU_IRQ_EOF);
-       ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0,
-                       "imx_drm", ipu_crtc);
-       if (ret < 0) {
-               dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
-               goto err_out;
-       }
-
-       disable_irq(ipu_crtc->irq);
-
        return 0;
 err_out:
        ipu_put_resources(ipu_crtc);
@@ -504,6 +493,7 @@ err_out:
 static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
                struct ipu_client_platformdata *pdata)
 {
+       struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent);
        int ret;
 
        ret = ipu_get_resources(ipu_crtc, pdata);
@@ -522,6 +512,17 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
                goto err_put_resources;
        }
 
+       ipu_crtc->irq = ipu_idmac_channel_irq(ipu, ipu_crtc->ipu_ch,
+                       IPU_IRQ_EOF);
+       ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0,
+                       "imx_drm", ipu_crtc);
+       if (ret < 0) {
+               dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret);
+               goto err_put_resources;
+       }
+
+       disable_irq(ipu_crtc->irq);
+
        return 0;
 
 err_put_resources:
index db1da28cecba84d4800363df964647e85b8177c9..be26917a68968897758d0ce70fbd56ebb976f484 100644 (file)
@@ -76,37 +76,28 @@ int drv_insert_node_res_element(void *hnode, void *node_resource,
        struct node_res_object **node_res_obj =
            (struct node_res_object **)node_resource;
        struct process_context *ctxt = (struct process_context *)process_ctxt;
-       int status = 0;
        int retval;
 
        *node_res_obj = kzalloc(sizeof(struct node_res_object), GFP_KERNEL);
-       if (!*node_res_obj) {
-               status = -ENOMEM;
-               goto func_end;
-       }
+       if (!*node_res_obj)
+               return -ENOMEM;
 
        (*node_res_obj)->node = hnode;
-       retval = idr_get_new(ctxt->node_id, *node_res_obj,
-                                               &(*node_res_obj)->id);
-       if (retval == -EAGAIN) {
-               if (!idr_pre_get(ctxt->node_id, GFP_KERNEL)) {
-                       pr_err("%s: OUT OF MEMORY\n", __func__);
-                       status = -ENOMEM;
-                       goto func_end;
-               }
-
-               retval = idr_get_new(ctxt->node_id, *node_res_obj,
-                                               &(*node_res_obj)->id);
+       retval = idr_alloc(ctxt->node_id, *node_res_obj, 0, 0, GFP_KERNEL);
+       if (retval >= 0) {
+               (*node_res_obj)->id = retval;
+               return 0;
        }
-       if (retval) {
+
+       kfree(*node_res_obj);
+
+       if (retval == -ENOSPC) {
                pr_err("%s: FAILED, IDR is FULL\n", __func__);
-               status = -EFAULT;
+               return -EFAULT;
+       } else {
+               pr_err("%s: OUT OF MEMORY\n", __func__);
+               return -ENOMEM;
        }
-func_end:
-       if (status)
-               kfree(*node_res_obj);
-
-       return status;
 }
 
 /* Release all Node resources and its context
@@ -201,35 +192,26 @@ int drv_proc_insert_strm_res_element(void *stream_obj,
        struct strm_res_object **pstrm_res =
            (struct strm_res_object **)strm_res;
        struct process_context *ctxt = (struct process_context *)process_ctxt;
-       int status = 0;
        int retval;
 
        *pstrm_res = kzalloc(sizeof(struct strm_res_object), GFP_KERNEL);
-       if (*pstrm_res == NULL) {
-               status = -EFAULT;
-               goto func_end;
-       }
+       if (*pstrm_res == NULL)
+               return -EFAULT;
 
        (*pstrm_res)->stream = stream_obj;
-       retval = idr_get_new(ctxt->stream_id, *pstrm_res,
-                                               &(*pstrm_res)->id);
-       if (retval == -EAGAIN) {
-               if (!idr_pre_get(ctxt->stream_id, GFP_KERNEL)) {
-                       pr_err("%s: OUT OF MEMORY\n", __func__);
-                       status = -ENOMEM;
-                       goto func_end;
-               }
-
-               retval = idr_get_new(ctxt->stream_id, *pstrm_res,
-                                               &(*pstrm_res)->id);
+       retval = idr_alloc(ctxt->stream_id, *pstrm_res, 0, 0, GFP_KERNEL);
+       if (retval >= 0) {
+               (*pstrm_res)->id = retval;
+               return 0;
        }
-       if (retval) {
+
+       if (retval == -ENOSPC) {
                pr_err("%s: FAILED, IDR is FULL\n", __func__);
-               status = -EPERM;
+               return -EPERM;
+       } else {
+               pr_err("%s: OUT OF MEMORY\n", __func__);
+               return -ENOMEM;
        }
-
-func_end:
-       return status;
 }
 
 static int drv_proc_free_strm_res(int id, void *p, void *process_ctxt)
index 22918a106d7365df4e1f1dbd06bd975c7f9c41d1..d2479b766450e69e81d198ad768b5564ad3f6336 100644 (file)
@@ -790,7 +790,7 @@ u64 CARDqGetNextTBTT(u64 qwTSF, WORD wBeaconInterval)
        if ((~uLowNextTBTT) < uLowRemain)
                qwTSF = ((qwTSF >> 32) + 1) << 32;
 
-       qwTSF = (qwTSF & 0xffffffff00000000UL) |
+       qwTSF = (qwTSF & 0xffffffff00000000ULL) |
                (u64)(uLowNextTBTT + uLowRemain);
 
     return (qwTSF);
index d5f53e1a74a2e8509e5e3f28eb77b17fa8943204..a5063a6f64d9f669e59eb08167a1ef0e93ec277d 100644 (file)
@@ -669,8 +669,6 @@ static int vt6656_suspend(struct usb_interface *intf, pm_message_t message)
        if (device->flags & DEVICE_FLAGS_OPENED)
                device_close(device->dev);
 
-       usb_put_dev(interface_to_usbdev(intf));
-
        return 0;
 }
 
@@ -681,8 +679,6 @@ static int vt6656_resume(struct usb_interface *intf)
        if (!device || !device->dev)
                return -ENODEV;
 
-       usb_get_dev(interface_to_usbdev(intf));
-
        if (!(device->flags & DEVICE_FLAGS_OPENED))
                device_open(device->dev);
 
index 73582705e8c5bc71081494a7e4481b7eb36d42e8..5c3714530961c5ede430f7745706d24c833781ce 100644 (file)
@@ -15,7 +15,7 @@ config RAMSTER
        depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE=y
        depends on NET
        # must ensure struct page is 8-byte aligned
-       select HAVE_ALIGNED_STRUCT_PAGE if !64_BIT
+       select HAVE_ALIGNED_STRUCT_PAGE if !64BIT
        default n
        help
          RAMster allows RAM on other machines in a cluster to be utilized
index aa2a1a763aa41440a1663e0c5e8b45153294708c..f6e1e5209d88586f6e33fc43138bed199fb239af 100644 (file)
@@ -300,27 +300,22 @@ static u8 r2net_num_from_nn(struct r2net_node *nn)
 
 static int r2net_prep_nsw(struct r2net_node *nn, struct r2net_status_wait *nsw)
 {
-       int ret = 0;
+       int ret;
 
-       do {
-               if (!idr_pre_get(&nn->nn_status_idr, GFP_ATOMIC)) {
-                       ret = -EAGAIN;
-                       break;
-               }
-               spin_lock(&nn->nn_lock);
-               ret = idr_get_new(&nn->nn_status_idr, nsw, &nsw->ns_id);
-               if (ret == 0)
-                       list_add_tail(&nsw->ns_node_item,
-                                     &nn->nn_status_list);
-               spin_unlock(&nn->nn_lock);
-       } while (ret == -EAGAIN);
+       spin_lock(&nn->nn_lock);
+       ret = idr_alloc(&nn->nn_status_idr, nsw, 0, 0, GFP_ATOMIC);
+       if (ret >= 0) {
+               nsw->ns_id = ret;
+               list_add_tail(&nsw->ns_node_item, &nn->nn_status_list);
+       }
+       spin_unlock(&nn->nn_lock);
 
-       if (ret == 0)  {
+       if (ret >= 0) {
                init_waitqueue_head(&nsw->ns_wq);
                nsw->ns_sys_status = R2NET_ERR_NONE;
                nsw->ns_status = 0;
+               return 0;
        }
-
        return ret;
 }
 
index db0cf7c8adde04db2b272660a6047297fa848a78..a0fc7b9eea652c570419052deff33fec88210209 100644 (file)
@@ -166,6 +166,7 @@ static int chap_server_compute_md5(
 {
        char *endptr;
        unsigned long id;
+       unsigned char id_as_uchar;
        unsigned char digest[MD5_SIGNATURE_SIZE];
        unsigned char type, response[MD5_SIGNATURE_SIZE * 2 + 2];
        unsigned char identifier[10], *challenge = NULL;
@@ -355,7 +356,9 @@ static int chap_server_compute_md5(
                goto out;
        }
 
-       sg_init_one(&sg, &id, 1);
+       /* To handle both endiannesses */
+       id_as_uchar = id;
+       sg_init_one(&sg, &id_as_uchar, 1);
        ret = crypto_hash_update(&desc, &sg, 1);
        if (ret < 0) {
                pr_err("crypto_hash_update() failed for id\n");
index bc02b018ae46b0d0340db390adbf518990e77174..37ffc5bd23992a5f1e1124b2c6eba9889e7119ff 100644 (file)
@@ -7,7 +7,7 @@
 #define FD_DEVICE_QUEUE_DEPTH  32
 #define FD_MAX_DEVICE_QUEUE_DEPTH 128
 #define FD_BLOCKSIZE           512
-#define FD_MAX_SECTORS         1024
+#define FD_MAX_SECTORS         2048
 
 #define RRF_EMULATE_CDB                0x01
 #define RRF_GOT_LBA            0x02
index 82e78d72fdb61f1849f1204e6d02d0970fdb7b41..e992b27aa0904b75320991b0adbb65b3d84037b6 100644 (file)
@@ -883,7 +883,14 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                pr_debug("PSCSI: i: %d page: %p len: %d off: %d\n", i,
                        page, len, off);
 
-               while (len > 0 && data_len > 0) {
+               /*
+                * We only have one page of data in each sg element,
+                * we can not cross a page boundary.
+                */
+               if (off + len > PAGE_SIZE)
+                       goto fail;
+
+               if (len > 0 && data_len > 0) {
                        bytes = min_t(unsigned int, len, PAGE_SIZE - off);
                        bytes = min(bytes, data_len);
 
@@ -940,9 +947,7 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                                bio = NULL;
                        }
 
-                       len -= bytes;
                        data_len -= bytes;
-                       off = 0;
                }
        }
 
index 290230de2c53c72c0c192930c7b2dff63a3b24a9..60d4b5185f32979739c01e04c5aa94de6fcd838f 100644 (file)
@@ -464,8 +464,11 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
                break;
        case SYNCHRONIZE_CACHE:
        case SYNCHRONIZE_CACHE_16:
-               if (!ops->execute_sync_cache)
-                       return TCM_UNSUPPORTED_SCSI_OPCODE;
+               if (!ops->execute_sync_cache) {
+                       size = 0;
+                       cmd->execute_cmd = sbc_emulate_noop;
+                       break;
+               }
 
                /*
                 * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE
index 9169d6a5d7e4bff83f2aec0ecfc84c8667f9bab6..aac9d2727e3c8584a20db563ef5c914bc758de19 100644 (file)
@@ -711,7 +711,8 @@ int core_tpg_register(
 
        if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) {
                if (core_tpg_setup_virtual_lun0(se_tpg) < 0) {
-                       kfree(se_tpg);
+                       array_free(se_tpg->tpg_lun_list,
+                                  TRANSPORT_MAX_LUNS_PER_TPG);
                        return -ENOMEM;
                }
        }
index 2030b608136d3cfb7dc4509105ff061a3a621e14..3243ea790eaba9ee0db1b4152ac4e3450148ecd3 100644 (file)
@@ -1139,8 +1139,10 @@ target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb)
                return ret;
 
        ret = target_check_reservation(cmd);
-       if (ret)
+       if (ret) {
+               cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
                return ret;
+       }
 
        ret = dev->transport->parse_cdb(cmd);
        if (ret)
index 7b0bfa0e7a9c231a450012d104e6de093ca2c001..3078c403b42d84029968b23ff20b39ebd4af295d 100644 (file)
@@ -143,22 +143,18 @@ static int dove_thermal_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
-       priv->sensor = devm_request_and_ioremap(&pdev->dev, res);
-       if (!priv->sensor) {
-               dev_err(&pdev->dev, "Failed to request_ioremap memory\n");
-               return -EADDRNOTAVAIL;
-       }
+       priv->sensor = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(priv->sensor))
+               return PTR_ERR(priv->sensor);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
        if (!res) {
                dev_err(&pdev->dev, "Failed to get platform resource\n");
                return -ENODEV;
        }
-       priv->control = devm_request_and_ioremap(&pdev->dev, res);
-       if (!priv->control) {
-               dev_err(&pdev->dev, "Failed to request_ioremap memory\n");
-               return -EADDRNOTAVAIL;
-       }
+       priv->control = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(priv->control))
+               return PTR_ERR(priv->control);
 
        ret = dove_init_sensor(priv);
        if (ret) {
index e04ebd8671aca27dc390c32d6ec00d6033c7d7ae..b777ae6f0a8fed33d44701b867239e4973d37749 100644 (file)
@@ -39,8 +39,6 @@
 #include <linux/cpu_cooling.h>
 #include <linux/of.h>
 
-#include <plat/cpu.h>
-
 /* Exynos generic registers */
 #define EXYNOS_TMU_REG_TRIMINFO                0x0
 #define EXYNOS_TMU_REG_CONTROL         0x20
@@ -476,7 +474,7 @@ static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf)
 
        if (IS_ERR(th_zone->therm_dev)) {
                pr_err("Failed to register thermal zone device\n");
-               ret = -EINVAL;
+               ret = PTR_ERR(th_zone->therm_dev);
                goto err_unregister;
        }
        th_zone->mode = THERMAL_DEVICE_ENABLED;
index 65cb4f09e8f6ffb19123c6aaa2a7a55f3442323b..e5500edb528568a009597b9336fa3d951df852ac 100644 (file)
@@ -85,11 +85,9 @@ static int kirkwood_thermal_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
-       priv->sensor = devm_request_and_ioremap(&pdev->dev, res);
-       if (!priv->sensor) {
-               dev_err(&pdev->dev, "Failed to request_ioremap memory\n");
-               return -EADDRNOTAVAIL;
-       }
+       priv->sensor = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(priv->sensor))
+               return PTR_ERR(priv->sensor);
 
        thermal = thermal_zone_device_register("kirkwood_thermal", 0, 0,
                                               priv, &ops, NULL, 0, 0);
index 28f0919940137dcaf57fce04df69ddcdecfc173f..2cc5b6115e3e200d13955f8103b97a2ddf3c0514 100644 (file)
@@ -145,6 +145,7 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv)
        struct device *dev = rcar_priv_to_dev(priv);
        int i;
        int ctemp, old, new;
+       int ret = -EINVAL;
 
        mutex_lock(&priv->lock);
 
@@ -174,7 +175,7 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv)
 
        if (!ctemp) {
                dev_err(dev, "thermal sensor was broken\n");
-               return -EINVAL;
+               goto err_out_unlock;
        }
 
        /*
@@ -192,10 +193,10 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv)
        dev_dbg(dev, "thermal%d  %d -> %d\n", priv->id, priv->ctemp, ctemp);
 
        priv->ctemp = ctemp;
-
+       ret = 0;
+err_out_unlock:
        mutex_unlock(&priv->lock);
-
-       return 0;
+       return ret;
 }
 
 static int rcar_thermal_get_temp(struct thermal_zone_device *zone,
@@ -363,6 +364,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
        struct resource *res, *irq;
        int mres = 0;
        int i;
+       int ret = -ENODEV;
        int idle = IDLE_INTERVAL;
 
        common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL);
@@ -399,11 +401,9 @@ static int rcar_thermal_probe(struct platform_device *pdev)
                /*
                 * rcar_has_irq_support() will be enabled
                 */
-               common->base = devm_request_and_ioremap(dev, res);
-               if (!common->base) {
-                       dev_err(dev, "Unable to ioremap thermal register\n");
-                       return -ENOMEM;
-               }
+               common->base = devm_ioremap_resource(dev, res);
+               if (IS_ERR(common->base))
+                       return PTR_ERR(common->base);
 
                /* enable temperature comparation */
                rcar_thermal_common_write(common, ENR, 0x00030303);
@@ -422,11 +422,9 @@ static int rcar_thermal_probe(struct platform_device *pdev)
                        return -ENOMEM;
                }
 
-               priv->base = devm_request_and_ioremap(dev, res);
-               if (!priv->base) {
-                       dev_err(dev, "Unable to ioremap priv register\n");
-                       return -ENOMEM;
-               }
+               priv->base = devm_ioremap_resource(dev, res);
+               if (IS_ERR(priv->base))
+                       return PTR_ERR(priv->base);
 
                priv->common = common;
                priv->id = i;
@@ -441,6 +439,7 @@ static int rcar_thermal_probe(struct platform_device *pdev)
                                                idle);
                if (IS_ERR(priv->zone)) {
                        dev_err(dev, "can't register thermal zone\n");
+                       ret = PTR_ERR(priv->zone);
                        goto error_unregister;
                }
 
@@ -460,7 +459,7 @@ error_unregister:
        rcar_thermal_for_each_priv(priv, common)
                thermal_zone_device_unregister(priv->zone);
 
-       return -ENODEV;
+       return ret;
 }
 
 static int rcar_thermal_remove(struct platform_device *pdev)
similarity index 98%
rename from drivers/tty/serial/8250/8250.c
rename to drivers/tty/serial/8250/8250_core.c
index 0efc815a496869fbe80cec247fb99af9286105f9..35f9c96aada9c9f6d31238accab3ddd7887ed2fb 100644 (file)
@@ -301,7 +301,28 @@ static const struct serial8250_config uart_config[] = {
        },
        [PORT_8250_CIR] = {
                .name           = "CIR port"
-       }
+       },
+       [PORT_ALTR_16550_F32] = {
+               .name           = "Altera 16550 FIFO32",
+               .fifo_size      = 32,
+               .tx_loadsz      = 32,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
+       [PORT_ALTR_16550_F64] = {
+               .name           = "Altera 16550 FIFO64",
+               .fifo_size      = 64,
+               .tx_loadsz      = 64,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
+       [PORT_ALTR_16550_F128] = {
+               .name           = "Altera 16550 FIFO128",
+               .fifo_size      = 128,
+               .tx_loadsz      = 128,
+               .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
 };
 
 /* Uart divisor latch read */
@@ -3396,3 +3417,34 @@ module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
 MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
 #endif
 MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
+
+#ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS
+#ifndef MODULE
+/* This module was renamed to 8250_core in 3.7.  Keep the old "8250" name
+ * working as well for the module options so we don't break people.  We
+ * need to keep the names identical and the convenient macros will happily
+ * refuse to let us do that by failing the build with redefinition errors
+ * of global variables.  So we stick them inside a dummy function to avoid
+ * those conflicts.  The options still get parsed, and the redefined
+ * MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive.
+ *
+ * This is hacky.  I'm sorry.
+ */
+static void __used s8250_options(void)
+{
+#undef MODULE_PARAM_PREFIX
+#define MODULE_PARAM_PREFIX "8250_core."
+
+       module_param_cb(share_irqs, &param_ops_uint, &share_irqs, 0644);
+       module_param_cb(nr_uarts, &param_ops_uint, &nr_uarts, 0644);
+       module_param_cb(skip_txen_test, &param_ops_uint, &skip_txen_test, 0644);
+#ifdef CONFIG_SERIAL_8250_RSA
+       __module_param_call(MODULE_PARAM_PREFIX, probe_rsa,
+               &param_array_ops, .arr = &__param_arr_probe_rsa,
+               0444, -1);
+#endif
+}
+#else
+MODULE_ALIAS("8250_core");
+#endif
+#endif
index 791c5a77ec61d473495190049ab5776e8a02a846..26e3a97ab157ed16d23825c1a62bec4d53cd81b9 100644 (file)
@@ -1554,6 +1554,7 @@ pci_wch_ch353_setup(struct serial_private *priv,
 #define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001
 #define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d
 #define PCI_VENDOR_ID_WCH              0x4348
+#define PCI_DEVICE_ID_WCH_CH352_2S     0x3253
 #define PCI_DEVICE_ID_WCH_CH353_4S     0x3453
 #define PCI_DEVICE_ID_WCH_CH353_2S1PF  0x5046
 #define PCI_DEVICE_ID_WCH_CH353_2S1P   0x7053
@@ -1571,6 +1572,7 @@ pci_wch_ch353_setup(struct serial_private *priv,
 
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
 #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584        0x1584
+#define PCI_SUBDEVICE_ID_UNKNOWN_0x1588        0x1588
 
 /*
  * Master list of serial port init/setup/exit quirks.
@@ -1850,15 +1852,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .setup          = pci_default_setup,
                .exit           = pci_plx9050_exit,
        },
-       {
-               .vendor         = PCI_VENDOR_ID_PLX,
-               .device         = PCI_DEVICE_ID_PLX_9050,
-               .subvendor      = PCI_VENDOR_ID_PLX,
-               .subdevice      = PCI_SUBDEVICE_ID_UNKNOWN_0x1584,
-               .init           = pci_plx9050_init,
-               .setup          = pci_default_setup,
-               .exit           = pci_plx9050_exit,
-       },
        {
                .vendor         = PCI_VENDOR_ID_PLX,
                .device         = PCI_DEVICE_ID_PLX_ROMULUS,
@@ -2180,6 +2173,14 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
                .subdevice      = PCI_ANY_ID,
                .setup          = pci_wch_ch353_setup,
        },
+       /* WCH CH352 2S card (16550 clone) */
+       {
+               .vendor         = PCI_VENDOR_ID_WCH,
+               .device         = PCI_DEVICE_ID_WCH_CH352_2S,
+               .subvendor      = PCI_ANY_ID,
+               .subdevice      = PCI_ANY_ID,
+               .setup          = pci_wch_ch353_setup,
+       },
        /*
         * ASIX devices with FIFO bug
         */
@@ -3733,7 +3734,12 @@ static struct pci_device_id serial_pci_tbl[] = {
        {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
                PCI_VENDOR_ID_PLX,
                PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0,
-               pbn_b0_4_115200 },
+               pbn_b2_4_115200 },
+       /* Unknown card - subdevice 0x1588 */
+       {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
+               PCI_VENDOR_ID_PLX,
+               PCI_SUBDEVICE_ID_UNKNOWN_0x1588, 0, 0,
+               pbn_b2_8_115200 },
        {       PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050,
                PCI_SUBVENDOR_ID_KEYSPAN,
                PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0,
@@ -4791,6 +4797,10 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_VENDOR_ID_IBM, 0x0299,
                0, 0, pbn_b0_bt_2_115200 },
 
+       {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
+               0x1000, 0x0012,
+               0, 0, pbn_b0_bt_2_115200 },
+
        {       PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901,
                0xA000, 0x1000,
                0, 0, pbn_b0_1_115200 },
@@ -4869,6 +4879,10 @@ static struct pci_device_id serial_pci_tbl[] = {
                PCI_ANY_ID, PCI_ANY_ID,
                0, 0, pbn_b0_bt_2_115200 },
 
+       {       PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH352_2S,
+               PCI_ANY_ID, PCI_ANY_ID,
+               0, 0, pbn_b0_bt_2_115200 },
+
        /*
         * Commtech, Inc. Fastcom adapters
         */
index 35d9ab95c5cbb51d6092f67540678f00e4ee52bd..b3455a970a1da01c0afcf013d8c31a49e1004005 100644 (file)
@@ -429,6 +429,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
 {
        struct uart_8250_port uart;
        int ret, line, flags = dev_id->driver_data;
+       struct resource *res = NULL;
 
        if (flags & UNKNOWN_DEV) {
                ret = serial_pnp_guess_board(dev);
@@ -439,11 +440,12 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id)
        memset(&uart, 0, sizeof(uart));
        if (pnp_irq_valid(dev, 0))
                uart.port.irq = pnp_irq(dev, 0);
-       if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) {
-               uart.port.iobase = pnp_port_start(dev, 2);
-               uart.port.iotype = UPIO_PORT;
-       } else if (pnp_port_valid(dev, 0)) {
-               uart.port.iobase = pnp_port_start(dev, 0);
+       if ((flags & CIR_PORT) && pnp_port_valid(dev, 2))
+               res = pnp_get_resource(dev, IORESOURCE_IO, 2);
+       else if (pnp_port_valid(dev, 0))
+               res = pnp_get_resource(dev, IORESOURCE_IO, 0);
+       if (pnp_resource_enabled(res)) {
+               uart.port.iobase = res->start;
                uart.port.iotype = UPIO_PORT;
        } else if (pnp_mem_valid(dev, 0)) {
                uart.port.mapbase = pnp_mem_start(dev, 0);
index 2ef9537bcb2cda6a985d27f9dda8c3385187fe3a..80fe91e64a527da06e82d9cf237be64a26faf662 100644 (file)
@@ -33,6 +33,23 @@ config SERIAL_8250
          Most people will say Y or M here, so that they can use serial mice,
          modems and similar devices connecting to the standard serial ports.
 
+config SERIAL_8250_DEPRECATED_OPTIONS
+       bool "Support 8250_core.* kernel options (DEPRECATED)"
+       depends on SERIAL_8250
+       default y
+       ---help---
+         In 3.7 we renamed 8250 to 8250_core by mistake, so now we have to
+         accept kernel parameters in both forms like 8250_core.nr_uarts=4 and
+         8250.nr_uarts=4. We now renamed the module back to 8250, but if
+         anybody noticed in 3.7 and changed their userspace we still have to
+         keep the 8350_core.* options around until they revert the changes
+         they already did.
+
+         If 8250 is built as a module, this adds 8250_core alias instead. 
+
+         If you did not notice yet and/or you have userspace from pre-3.7, it
+         is safe (and recommended) to say N here.
+
 config SERIAL_8250_PNP
        bool "8250/16550 PNP device support" if EXPERT
        depends on SERIAL_8250 && PNP
index a23838a4d5353773c1ec8d15adbecec3ceee123c..36d68d0543072c21f48807d3b932ed426e843685 100644 (file)
@@ -2,10 +2,10 @@
 # Makefile for the 8250 serial device drivers.
 #
 
-obj-$(CONFIG_SERIAL_8250)              += 8250_core.o
-8250_core-y                            := 8250.o
-8250_core-$(CONFIG_SERIAL_8250_PNP)    += 8250_pnp.o
-8250_core-$(CONFIG_SERIAL_8250_DMA)    += 8250_dma.o
+obj-$(CONFIG_SERIAL_8250)              += 8250.o
+8250-y                                 := 8250_core.o
+8250-$(CONFIG_SERIAL_8250_PNP)         += 8250_pnp.o
+8250-$(CONFIG_SERIAL_8250_DMA)         += 8250_dma.o
 obj-$(CONFIG_SERIAL_8250_GSC)          += 8250_gsc.o
 obj-$(CONFIG_SERIAL_8250_PCI)          += 8250_pci.o
 obj-$(CONFIG_SERIAL_8250_HP300)                += 8250_hp300.o
index cf9210db9fa917cd213559ec2c0cffd53c9f123b..7e7006fd404e62000b19b728274c0abf8a51bf38 100644 (file)
@@ -211,14 +211,14 @@ config SERIAL_SAMSUNG
 config SERIAL_SAMSUNG_UARTS_4
        bool
        depends on PLAT_SAMSUNG
-       default y if !(CPU_S3C2410 || SERIAL_S3C2412 || CPU_S3C2440 || CPU_S3C2442)
+       default y if !(CPU_S3C2410 || CPU_S3C2412 || CPU_S3C2440 || CPU_S3C2442)
        help
          Internal node for the common case of 4 Samsung compatible UARTs
 
 config SERIAL_SAMSUNG_UARTS
        int
        depends on PLAT_SAMSUNG
-       default 6 if ARCH_S5P6450
+       default 6 if CPU_S5P6450
        default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416
        default 3
        help
index d4a7c241b751279d3422f6d024b45cbb1a04a2de..3467462869ce2dce88ca8832002d7f294d5eaae6 100644 (file)
@@ -158,7 +158,7 @@ struct atmel_uart_port {
 };
 
 static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART];
-static unsigned long atmel_ports_in_use;
+static DECLARE_BITMAP(atmel_ports_in_use, ATMEL_MAX_UART);
 
 #ifdef SUPPORT_SYSRQ
 static struct console atmel_console;
@@ -1769,15 +1769,14 @@ static int atmel_serial_probe(struct platform_device *pdev)
        if (ret < 0)
                /* port id not found in platform data nor device-tree aliases:
                 * auto-enumerate it */
-               ret = find_first_zero_bit(&atmel_ports_in_use,
-                               sizeof(atmel_ports_in_use));
+               ret = find_first_zero_bit(atmel_ports_in_use, ATMEL_MAX_UART);
 
-       if (ret > ATMEL_MAX_UART) {
+       if (ret >= ATMEL_MAX_UART) {
                ret = -ENODEV;
                goto err;
        }
 
-       if (test_and_set_bit(ret, &atmel_ports_in_use)) {
+       if (test_and_set_bit(ret, atmel_ports_in_use)) {
                /* port already in use */
                ret = -EBUSY;
                goto err;
@@ -1857,7 +1856,7 @@ static int atmel_serial_remove(struct platform_device *pdev)
 
        /* "port" is allocated statically, so we shouldn't free it */
 
-       clear_bit(port->line, &atmel_ports_in_use);
+       clear_bit(port->line, atmel_ports_in_use);
 
        clk_put(atmel_port->clk);
 
index 719594e5fc219aafe5826730e1a4af659f7639b9..52a3ecd404219c7365850debe309d06b99a2d8c8 100644 (file)
@@ -235,7 +235,7 @@ static const char *bcm_uart_type(struct uart_port *port)
  */
 static void bcm_uart_do_rx(struct uart_port *port)
 {
-       struct tty_port *port = &port->state->port;
+       struct tty_port *tty_port = &port->state->port;
        unsigned int max_count;
 
        /* limit number of char read in interrupt, should not be
@@ -260,7 +260,7 @@ static void bcm_uart_do_rx(struct uart_port *port)
                        bcm_uart_writel(port, val, UART_CTL_REG);
 
                        port->icount.overrun++;
-                       tty_insert_flip_char(port, 0, TTY_OVERRUN);
+                       tty_insert_flip_char(tty_port, 0, TTY_OVERRUN);
                }
 
                if (!(iestat & UART_IR_STAT(UART_IR_RXNOTEMPTY)))
@@ -299,11 +299,11 @@ static void bcm_uart_do_rx(struct uart_port *port)
 
 
                if ((cstat & port->ignore_status_mask) == 0)
-                       tty_insert_flip_char(port, c, flag);
+                       tty_insert_flip_char(tty_port, c, flag);
 
        } while (--max_count);
 
-       tty_flip_buffer_push(port);
+       tty_flip_buffer_push(tty_port);
 }
 
 /*
index c0e1fad51be76f5969b71b561983cf6b6bba9b92..018bad922554fc45b9ad711bcab2a106fc683b6e 100644 (file)
@@ -550,7 +550,7 @@ static int mpc512x_psc_clock(struct uart_port *port, int enable)
                return 0;
 
        psc_num = (port->mapbase & 0xf00) >> 8;
-       snprintf(clk_name, sizeof(clk_name), "psc%d_clk", psc_num);
+       snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
        psc_clk = clk_get(port->dev, clk_name);
        if (IS_ERR(psc_clk)) {
                dev_err(port->dev, "Failed to get PSC clock entry!\n");
index d5874605682b77c69a272d71307fc24c70289b24..b025d54382754456efbb021e466079727381bcba 100644 (file)
@@ -241,6 +241,12 @@ static struct of_device_id of_platform_serial_table[] = {
        { .compatible = "ns16850",  .data = (void *)PORT_16850, },
        { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, },
        { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, },
+       { .compatible = "altr,16550-FIFO32",
+               .data = (void *)PORT_ALTR_16550_F32, },
+       { .compatible = "altr,16550-FIFO64",
+               .data = (void *)PORT_ALTR_16550_F64, },
+       { .compatible = "altr,16550-FIFO128",
+               .data = (void *)PORT_ALTR_16550_F128, },
 #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL
        { .compatible = "ibm,qpace-nwp-serial",
                .data = (void *)PORT_NWPSERIAL, },
index e343d6670854e3b0fa097a0e66135daa065ce2b9..451687cb96850cd55c1fdd15f4832e591eae8f5d 100644 (file)
@@ -968,6 +968,7 @@ static struct uart_ops sunsu_pops = {
 #define UART_NR        4
 
 static struct uart_sunsu_port sunsu_ports[UART_NR];
+static int nr_inst; /* Number of already registered ports */
 
 #ifdef CONFIG_SERIO
 
@@ -1337,13 +1338,8 @@ static int __init sunsu_console_setup(struct console *co, char *options)
        printk("Console: ttyS%d (SU)\n",
               (sunsu_reg.minor - 64) + co->index);
 
-       /*
-        * Check whether an invalid uart number has been specified, and
-        * if so, search for the first available port that does have
-        * console support.
-        */
-       if (co->index >= UART_NR)
-               co->index = 0;
+       if (co->index > nr_inst)
+               return -ENODEV;
        port = &sunsu_ports[co->index].port;
 
        /*
@@ -1408,7 +1404,6 @@ static enum su_type su_get_type(struct device_node *dp)
 
 static int su_probe(struct platform_device *op)
 {
-       static int inst;
        struct device_node *dp = op->dev.of_node;
        struct uart_sunsu_port *up;
        struct resource *rp;
@@ -1418,16 +1413,16 @@ static int su_probe(struct platform_device *op)
 
        type = su_get_type(dp);
        if (type == SU_PORT_PORT) {
-               if (inst >= UART_NR)
+               if (nr_inst >= UART_NR)
                        return -EINVAL;
-               up = &sunsu_ports[inst];
+               up = &sunsu_ports[nr_inst];
        } else {
                up = kzalloc(sizeof(*up), GFP_KERNEL);
                if (!up)
                        return -ENOMEM;
        }
 
-       up->port.line = inst;
+       up->port.line = nr_inst;
 
        spin_lock_init(&up->port.lock);
 
@@ -1461,6 +1456,8 @@ static int su_probe(struct platform_device *op)
                }
                dev_set_drvdata(&op->dev, up);
 
+               nr_inst++;
+
                return 0;
        }
 
@@ -1488,7 +1485,7 @@ static int su_probe(struct platform_device *op)
 
        dev_set_drvdata(&op->dev, up);
 
-       inst++;
+       nr_inst++;
 
        return 0;
 
index a3f9dd5c9dff40dacf86966ae3d6ff1335055f97..705240e6c4ec1714fb0c367e9f226eb23d705464 100644 (file)
@@ -611,14 +611,7 @@ static int vt8500_serial_probe(struct platform_device *pdev)
        vt8500_port->uart.dev = &pdev->dev;
        vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
 
-       vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0);
-       if (!IS_ERR(vt8500_port->clk)) {
-               vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk);
-       } else {
-               /* use the default of 24Mhz if not specified and warn */
-               pr_warn("%s: serial clock source not specified\n", __func__);
-               vt8500_port->uart.uartclk = 24000000;
-       }
+       vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk);
 
        snprintf(vt8500_port->name, sizeof(vt8500_port->name),
                 "VT8500 UART%d", pdev->id);
index ba451c7209fc6b9bbaaf47b9e2d2458f202feaf8..f36bbba1ac8b9070cc7cefafb8a33265a7872253 100644 (file)
@@ -578,6 +578,8 @@ static int xuartps_startup(struct uart_port *port)
        /* Receive Timeout register is enabled with value of 10 */
        xuartps_writel(10, XUARTPS_RXTOUT_OFFSET);
 
+       /* Clear out any pending interrupts before enabling them */
+       xuartps_writel(xuartps_readl(XUARTPS_ISR_OFFSET), XUARTPS_ISR_OFFSET);
 
        /* Set the Interrupt Registers with desired interrupts */
        xuartps_writel(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY |
index bb119934e76cd8c70bdde28038553b60867b3282..578aa7594b11febce9cf50b6f5863bc8a34dfe8c 100644 (file)
@@ -425,7 +425,7 @@ static void flush_to_ldisc(struct work_struct *work)
        struct tty_ldisc *disc;
 
        tty = port->itty;
-       if (WARN_RATELIMIT(tty == NULL, "tty is NULL\n"))
+       if (tty == NULL)
                return;
 
        disc = tty_ldisc_ref(tty);
index e4ca345873c3279761f8dcf6cee3f06053205088..d7799deacb21a66805d8e4308bcc199b64894fbf 100644 (file)
@@ -93,7 +93,7 @@ vcs_poll_data_free(struct vcs_poll_data *poll)
 static struct vcs_poll_data *
 vcs_poll_data_get(struct file *file)
 {
-       struct vcs_poll_data *poll = file->private_data;
+       struct vcs_poll_data *poll = file->private_data, *kill = NULL;
 
        if (poll)
                return poll;
@@ -122,10 +122,12 @@ vcs_poll_data_get(struct file *file)
                file->private_data = poll;
        } else {
                /* someone else raced ahead of us */
-               vcs_poll_data_free(poll);
+               kill = poll;
                poll = file->private_data;
        }
        spin_unlock(&file->f_lock);
+       if (kill)
+               vcs_poll_data_free(kill);
 
        return poll;
 }
index f5ed3d75fa5a2ce615f32b10b7f0461f839e5757..8f5ebced5df0010e4d881c7978a5e132d92c8306 100644 (file)
@@ -46,7 +46,7 @@ obj-$(CONFIG_USB_MICROTEK)    += image/
 obj-$(CONFIG_USB_SERIAL)       += serial/
 
 obj-$(CONFIG_USB)              += misc/
-obj-$(CONFIG_USB_COMMON)       += phy/
+obj-$(CONFIG_USB_OTG_UTILS)    += phy/
 obj-$(CONFIG_EARLY_PRINTK_DBGP)        += early/
 
 obj-$(CONFIG_USB_ATM)          += atm/
index a03fbc15fa9cce3ed28f209380f2a091e73223c7..aa491627a45ba83b51a881e0f5b7226a26139933 100644 (file)
@@ -100,7 +100,7 @@ struct c67x00_urb_priv {
 #define TD_PIDEP_OFFSET                0x04
 #define TD_PIDEPMASK_PID       0xF0
 #define TD_PIDEPMASK_EP                0x0F
-#define TD_PORTLENMASK_DL      0x02FF
+#define TD_PORTLENMASK_DL      0x03FF
 #define TD_PORTLENMASK_PN      0xC000
 
 #define TD_STATUS_OFFSET       0x07
@@ -590,7 +590,7 @@ static int c67x00_create_td(struct c67x00_hcd *c67x00, struct urb *urb,
 {
        struct c67x00_td *td;
        struct c67x00_urb_priv *urbp = urb->hcpriv;
-       const __u8 active_flag = 1, retry_cnt = 1;
+       const __u8 active_flag = 1, retry_cnt = 3;
        __u8 cmd = 0;
        int tt = 0;
 
index 2f45bba8561d10a5f8b52607344cfdeb957a540e..f64fbea1cf20aa689452ea50198ea9f8f70701b3 100644 (file)
@@ -1767,7 +1767,7 @@ static int udc_start(struct ci13xxx *ci)
                goto put_transceiver;
        }
 
-       retval = dbg_create_files(&ci->gadget.dev);
+       retval = dbg_create_files(ci->dev);
        if (retval)
                goto unreg_device;
 
@@ -1796,7 +1796,7 @@ remove_trans:
 
        dev_err(dev, "error = %i\n", retval);
 remove_dbg:
-       dbg_remove_files(&ci->gadget.dev);
+       dbg_remove_files(ci->dev);
 unreg_device:
        device_unregister(&ci->gadget.dev);
 put_transceiver:
@@ -1836,7 +1836,7 @@ static void udc_stop(struct ci13xxx *ci)
                if (ci->global_phy)
                        usb_put_phy(ci->transceiver);
        }
-       dbg_remove_files(&ci->gadget.dev);
+       dbg_remove_files(ci->dev);
        device_unregister(&ci->gadget.dev);
        /* my kobject is dynamic, I swear! */
        memset(&ci->gadget, 0, sizeof(ci->gadget));
index 8ac25adf31b41d857a6919299f1848cf2ee43710..387dc6c8ad25b0d43a7d954ce71d877618fcb63d 100644 (file)
@@ -593,7 +593,6 @@ static void acm_port_destruct(struct tty_port *port)
 
        dev_dbg(&acm->control->dev, "%s\n", __func__);
 
-       tty_unregister_device(acm_tty_driver, acm->minor);
        acm_release_minor(acm);
        usb_put_intf(acm->control);
        kfree(acm->country_codes);
@@ -977,6 +976,8 @@ static int acm_probe(struct usb_interface *intf,
        int num_rx_buf;
        int i;
        int combined_interfaces = 0;
+       struct device *tty_dev;
+       int rv = -ENOMEM;
 
        /* normal quirks */
        quirks = (unsigned long)id->driver_info;
@@ -1339,11 +1340,24 @@ skip_countries:
        usb_set_intfdata(data_interface, acm);
 
        usb_get_intf(control_interface);
-       tty_port_register_device(&acm->port, acm_tty_driver, minor,
+       tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor,
                        &control_interface->dev);
+       if (IS_ERR(tty_dev)) {
+               rv = PTR_ERR(tty_dev);
+               goto alloc_fail8;
+       }
 
        return 0;
+alloc_fail8:
+       if (acm->country_codes) {
+               device_remove_file(&acm->control->dev,
+                               &dev_attr_wCountryCodes);
+               device_remove_file(&acm->control->dev,
+                               &dev_attr_iCountryCodeRelDate);
+       }
+       device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities);
 alloc_fail7:
+       usb_set_intfdata(intf, NULL);
        for (i = 0; i < ACM_NW; i++)
                usb_free_urb(acm->wb[i].urb);
 alloc_fail6:
@@ -1359,7 +1373,7 @@ alloc_fail2:
        acm_release_minor(acm);
        kfree(acm);
 alloc_fail:
-       return -ENOMEM;
+       return rv;
 }
 
 static void stop_data_traffic(struct acm *acm)
@@ -1411,6 +1425,8 @@ static void acm_disconnect(struct usb_interface *intf)
 
        stop_data_traffic(acm);
 
+       tty_unregister_device(acm_tty_driver, acm->minor);
+
        usb_free_urb(acm->ctrlurb);
        for (i = 0; i < ACM_NW; i++)
                usb_free_urb(acm->wb[i].urb);
index 5f0cb417b736bb4b61c73afc52672029af59cbda..122d056d96d570c2d59762fda22e0e973ac081b5 100644 (file)
@@ -56,6 +56,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids);
 #define WDM_RESPONDING         7
 #define WDM_SUSPENDING         8
 #define WDM_RESETTING          9
+#define WDM_OVERFLOW           10
 
 #define WDM_MAX                        16
 
@@ -155,6 +156,7 @@ static void wdm_in_callback(struct urb *urb)
 {
        struct wdm_device *desc = urb->context;
        int status = urb->status;
+       int length = urb->actual_length;
 
        spin_lock(&desc->iuspin);
        clear_bit(WDM_RESPONDING, &desc->flags);
@@ -185,9 +187,17 @@ static void wdm_in_callback(struct urb *urb)
        }
 
        desc->rerr = status;
-       desc->reslength = urb->actual_length;
-       memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength);
-       desc->length += desc->reslength;
+       if (length + desc->length > desc->wMaxCommand) {
+               /* The buffer would overflow */
+               set_bit(WDM_OVERFLOW, &desc->flags);
+       } else {
+               /* we may already be in overflow */
+               if (!test_bit(WDM_OVERFLOW, &desc->flags)) {
+                       memmove(desc->ubuf + desc->length, desc->inbuf, length);
+                       desc->length += length;
+                       desc->reslength = length;
+               }
+       }
 skip_error:
        wake_up(&desc->wait);
 
@@ -435,6 +445,11 @@ retry:
                        rv = -ENODEV;
                        goto err;
                }
+               if (test_bit(WDM_OVERFLOW, &desc->flags)) {
+                       clear_bit(WDM_OVERFLOW, &desc->flags);
+                       rv = -ENOBUFS;
+                       goto err;
+               }
                i++;
                if (file->f_flags & O_NONBLOCK) {
                        if (!test_bit(WDM_READ, &desc->flags)) {
@@ -478,6 +493,7 @@ retry:
                        spin_unlock_irq(&desc->iuspin);
                        goto retry;
                }
+
                if (!desc->reslength) { /* zero length read */
                        dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__);
                        clear_bit(WDM_READ, &desc->flags);
@@ -1004,6 +1020,7 @@ static int wdm_post_reset(struct usb_interface *intf)
        struct wdm_device *desc = wdm_find_device(intf);
        int rv;
 
+       clear_bit(WDM_OVERFLOW, &desc->flags);
        clear_bit(WDM_RESETTING, &desc->flags);
        rv = recover_from_urb_loss(desc);
        mutex_unlock(&desc->wlock);
index 622b4a48e732e7a83b6c760d6563994394b0caa9..2b487d4797bd74057a9ad88148af199360d9de1d 100644 (file)
@@ -173,6 +173,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
        struct hc_driver        *driver;
        struct usb_hcd          *hcd;
        int                     retval;
+       int                     hcd_irq = 0;
 
        if (usb_disabled())
                return -ENODEV;
@@ -187,15 +188,19 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
                return -ENODEV;
        dev->current_state = PCI_D0;
 
-       /* The xHCI driver supports MSI and MSI-X,
-        * so don't fail if the BIOS doesn't provide a legacy IRQ.
+       /*
+        * The xHCI driver has its own irq management
+        * make sure irq setup is not touched for xhci in generic hcd code
         */
-       if (!dev->irq && (driver->flags & HCD_MASK) != HCD_USB3) {
-               dev_err(&dev->dev,
-                       "Found HC with no IRQ.  Check BIOS/PCI %s setup!\n",
-                       pci_name(dev));
-               retval = -ENODEV;
-               goto disable_pci;
+       if ((driver->flags & HCD_MASK) != HCD_USB3) {
+               if (!dev->irq) {
+                       dev_err(&dev->dev,
+                       "Found HC with no IRQ. Check BIOS/PCI %s setup!\n",
+                               pci_name(dev));
+                       retval = -ENODEV;
+                       goto disable_pci;
+               }
+               hcd_irq = dev->irq;
        }
 
        hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev));
@@ -245,7 +250,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
        pci_set_master(dev);
 
-       retval = usb_add_hcd(hcd, dev->irq, IRQF_SHARED);
+       retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED);
        if (retval != 0)
                goto unmap_registers;
        set_hs_companion(dev, hcd);
index 99b34a30354f4a2a3e06deef32addaefb3e46e61..f9ec44cbb82fb1ff6fa8e620367de8a9daec2c70 100644 (file)
@@ -2412,6 +2412,14 @@ int usb_hcd_is_primary_hcd(struct usb_hcd *hcd)
 }
 EXPORT_SYMBOL_GPL(usb_hcd_is_primary_hcd);
 
+int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1)
+{
+       if (!hcd->driver->find_raw_port_number)
+               return port1;
+
+       return hcd->driver->find_raw_port_number(hcd, port1);
+}
+
 static int usb_hcd_request_irqs(struct usb_hcd *hcd,
                unsigned int irqnum, unsigned long irqflags)
 {
index 797f9d51473298582d166858b30e5e464ee2b18c..65d4e55552c68f01fa606331afcd3096bdc31300 100644 (file)
@@ -67,7 +67,6 @@ static void usb_port_device_release(struct device *dev)
 {
        struct usb_port *port_dev = to_usb_port(dev);
 
-       dev_pm_qos_hide_flags(dev);
        kfree(port_dev);
 }
 
index b6f4bad3f756eefb173097767ffde6970e06220e..255c14464bf2ea7a30dffab6fa1770c7b030c0aa 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/kernel.h>
 #include <linux/acpi.h>
 #include <linux/pci.h>
+#include <linux/usb/hcd.h>
 #include <acpi/acpi_bus.h>
 
 #include "usb.h"
@@ -188,8 +189,13 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle)
                 * connected to.
                 */
                if (!udev->parent) {
-                       *handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev),
+                       struct usb_hcd *hcd = bus_to_hcd(udev->bus);
+                       int raw_port_num;
+
+                       raw_port_num = usb_hcd_find_raw_port_number(hcd,
                                port_num);
+                       *handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev),
+                               raw_port_num);
                        if (!*handle)
                                return -ENODEV;
                } else {
index 999909451e37ef75e9fb49d42f35fc34bceb646f..ffa6b004a84bec3b4d58b9e5b6bd515d499e603d 100644 (file)
@@ -583,6 +583,7 @@ static int dwc3_remove(struct platform_device *pdev)
                break;
        }
 
+       dwc3_free_event_buffers(dwc);
        dwc3_core_exit(dwc);
 
        return 0;
index b50da53e9a52046a5441a9ea230e267d6a476c93..b082bec7343e0e79cd3e1d062c2aba16173ffbab 100644 (file)
@@ -23,8 +23,6 @@
 #include <linux/usb/nop-usb-xceiv.h>
 #include <linux/of.h>
 
-#include "core.h"
-
 struct dwc3_exynos {
        struct platform_device  *dwc3;
        struct platform_device  *usb2_phy;
index 22f337f572190234c4f75fd06a78b14ce4a2faf9..afa05e3c9cf40b9b731e6d16f8543c07a6cb62c8 100644 (file)
@@ -54,8 +54,6 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/nop-usb-xceiv.h>
 
-#include "core.h"
-
 /*
  * All these registers belong to OMAP's Wrapper around the
  * DesignWare USB3 Core.
@@ -465,20 +463,20 @@ static int dwc3_omap_remove(struct platform_device *pdev)
        return 0;
 }
 
-static const struct of_device_id of_dwc3_matach[] = {
+static const struct of_device_id of_dwc3_match[] = {
        {
                "ti,dwc3",
        },
        { },
 };
-MODULE_DEVICE_TABLE(of, of_dwc3_matach);
+MODULE_DEVICE_TABLE(of, of_dwc3_match);
 
 static struct platform_driver dwc3_omap_driver = {
        .probe          = dwc3_omap_probe,
        .remove         = dwc3_omap_remove,
        .driver         = {
                .name   = "omap-dwc3",
-               .of_match_table = of_dwc3_matach,
+               .of_match_table = of_dwc3_match,
        },
 };
 
index 7d70f44567d2a80fb9b5cf459f36ac0f61dafdf3..e8d77689a322d941042643a980e423545f7bc365 100644 (file)
@@ -45,8 +45,6 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/nop-usb-xceiv.h>
 
-#include "core.h"
-
 /* FIXME define these in <linux/pci_ids.h> */
 #define PCI_VENDOR_ID_SYNOPSYS         0x16c3
 #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3        0xabcd
index d7da073a23fee142edc051e562d5cba498c97e63..1d139ca05ef17bdd56cdfa3ba9027ea70c337d88 100644 (file)
@@ -891,7 +891,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
                                DWC3_TRBCTL_CONTROL_DATA);
        } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket)
                        && (dep->number == 0)) {
-               u32             transfer_size;
+               u32     transfer_size;
+               u32     maxpacket;
 
                ret = usb_gadget_map_request(&dwc->gadget, &req->request,
                                dep->number);
@@ -902,8 +903,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
 
                WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE);
 
-               transfer_size = roundup(req->request.length,
-                               (u32) dep->endpoint.maxpacket);
+               maxpacket = dep->endpoint.maxpacket;
+               transfer_size = roundup(req->request.length, maxpacket);
 
                dwc->ep0_bounced = true;
 
index a04342f6cbfae6979f1f053776e7e1297ca1bdfb..82e160e96fcafd20f15c4443cba953d569c071f1 100644 (file)
@@ -2159,7 +2159,6 @@ static void dwc3_gadget_phy_suspend(struct dwc3 *dwc, u8 speed)
 
 static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 {
-       struct dwc3_gadget_ep_cmd_params params;
        struct dwc3_ep          *dep;
        int                     ret;
        u32                     reg;
@@ -2167,8 +2166,6 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
 
        dev_vdbg(dwc->dev, "%s\n", __func__);
 
-       memset(&params, 0x00, sizeof(params));
-
        reg = dwc3_readl(dwc->regs, DWC3_DSTS);
        speed = reg & DWC3_DSTS_CONNECTSPD;
        dwc->speed = speed;
index 5a0c541daf893a33a428bedb8d68ec1fa72d4234..c7525b1cad74a0f92dc1057621dca509f80d671c 100644 (file)
@@ -145,6 +145,7 @@ config USB_LPC32XX
        tristate "LPC32XX USB Peripheral Controller"
        depends on ARCH_LPC32XX
        select USB_ISP1301
+       select USB_OTG_UTILS
        help
           This option selects the USB device controller in the LPC32xx SoC.
 
index 97a13c349cc52bfa4928c6eab5fd11470bcc5a26..82fb22511356d4ffd610d57b2787f457a93e5f9e 100644 (file)
@@ -35,6 +35,12 @@ mv_udc-y                     := mv_udc_core.o
 obj-$(CONFIG_USB_FUSB300)      += fusb300_udc.o
 obj-$(CONFIG_USB_MV_U3D)       += mv_u3d_core.o
 
+# USB Functions
+obj-$(CONFIG_USB_F_ACM)                += f_acm.o
+f_ss_lb-y                      := f_loopback.o f_sourcesink.o
+obj-$(CONFIG_USB_F_SS_LB)      += f_ss_lb.o
+obj-$(CONFIG_USB_U_SERIAL)     += u_serial.o
+
 #
 # USB gadget drivers
 #
@@ -74,9 +80,3 @@ obj-$(CONFIG_USB_G_WEBCAM)    += g_webcam.o
 obj-$(CONFIG_USB_G_NCM)                += g_ncm.o
 obj-$(CONFIG_USB_G_ACM_MS)     += g_acm_ms.o
 obj-$(CONFIG_USB_GADGET_TARGET)        += tcm_usb_gadget.o
-
-# USB Functions
-obj-$(CONFIG_USB_F_ACM)                += f_acm.o
-f_ss_lb-y                      := f_loopback.o f_sourcesink.o
-obj-$(CONFIG_USB_F_SS_LB)      += f_ss_lb.o
-obj-$(CONFIG_USB_U_SERIAL)     += u_serial.o
index 7c821de8ce3d95d53d03beffd85e4ab9f962f571..c0d62b2786104a6ed2a3501d2bd74e739841c970 100644 (file)
@@ -1757,10 +1757,7 @@ static const struct usb_gadget_driver composite_driver_template = {
 /**
  * usb_composite_probe() - register a composite driver
  * @driver: the driver to register
- * @bind: the callback used to allocate resources that are shared across the
- *     whole device, such as string IDs, and add its configurations using
- *     @usb_add_config().  This may fail by returning a negative errno
- *     value; it should return zero on successful initialization.
+ *
  * Context: single threaded during gadget setup
  *
  * This function is used to register drivers using the composite driver
index 71beeb83355874b601998a5764abddc076515138..cc9c49c57c803a9e787887fd8977e05c585d630e 100644 (file)
@@ -447,14 +447,13 @@ static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req)
 static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req)
 {
        struct f_rndis                  *rndis = req->context;
-       struct usb_composite_dev        *cdev = rndis->port.func.config->cdev;
        int                             status;
 
        /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
 //     spin_lock(&dev->lock);
        status = rndis_msg_parser(rndis->config, (u8 *) req->buf);
        if (status < 0)
-               ERROR(cdev, "RNDIS command error %d, %d/%d\n",
+               pr_err("RNDIS command error %d, %d/%d\n",
                        status, req->actual, req->length);
 //     spin_unlock(&dev->lock);
 }
index f570e667a640d0619cd6abaffaf9705738fcab24..fa8ea4ea00c1a3014be0fdc35dfcc52bb17af166 100644 (file)
@@ -418,6 +418,7 @@ static int audio_get_intf_req(struct usb_function *f,
 
        req->context = audio;
        req->complete = f_audio_complete;
+       len = min_t(size_t, sizeof(value), len);
        memcpy(req->buf, &value, len);
 
        return len;
index 3953dd4d7186827d0ee65b3e631701a093e7f618..3b343b23e4b0cfee227fc56965565bb0fb768d33 100644 (file)
@@ -357,7 +357,7 @@ static int gfs_bind(struct usb_composite_dev *cdev)
                goto error;
        gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id;
 
-       for (i = func_num; --i; ) {
+       for (i = func_num; i--; ) {
                ret = functionfs_bind(ffs_tab[i].ffs_data, cdev);
                if (unlikely(ret < 0)) {
                        while (++i < func_num)
@@ -413,7 +413,7 @@ static int gfs_unbind(struct usb_composite_dev *cdev)
                gether_cleanup();
        gfs_ether_setup = false;
 
-       for (i = func_num; --i; )
+       for (i = func_num; i--; )
                if (ffs_tab[i].ffs_data)
                        functionfs_unbind(ffs_tab[i].ffs_data);
 
index 8efd7555fa21a93884a48a52eb743d28407f2410..5bd930d779b9dd957b51d610469b4e6e4ead5663 100644 (file)
@@ -1334,27 +1334,18 @@ static int imx_udc_start(struct usb_gadget *gadget,
                struct usb_gadget_driver *driver)
 {
        struct imx_udc_struct *imx_usb;
-       int retval;
 
        imx_usb = container_of(gadget, struct imx_udc_struct, gadget);
        /* first hook up the driver ... */
        imx_usb->driver = driver;
        imx_usb->gadget.dev.driver = &driver->driver;
 
-       retval = device_add(&imx_usb->gadget.dev);
-       if (retval)
-               goto fail;
-
        D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n",
                __func__, driver->driver.name);
 
        imx_udc_enable(imx_usb);
 
        return 0;
-fail:
-       imx_usb->driver = NULL;
-       imx_usb->gadget.dev.driver = NULL;
-       return retval;
 }
 
 static int imx_udc_stop(struct usb_gadget *gadget,
@@ -1370,8 +1361,6 @@ static int imx_udc_stop(struct usb_gadget *gadget,
        imx_usb->gadget.dev.driver = NULL;
        imx_usb->driver = NULL;
 
-       device_del(&imx_usb->gadget.dev);
-
        D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n",
                __func__, driver->driver.name);
 
@@ -1477,6 +1466,10 @@ static int __init imx_udc_probe(struct platform_device *pdev)
        imx_usb->gadget.dev.parent = &pdev->dev;
        imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask;
 
+       ret = device_add(&imx_usb->gadget.dev);
+       if (retval)
+               goto fail4;
+
        platform_set_drvdata(pdev, imx_usb);
 
        usb_init_data(imx_usb);
@@ -1488,9 +1481,11 @@ static int __init imx_udc_probe(struct platform_device *pdev)
 
        ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget);
        if (ret)
-               goto fail4;
+               goto fail5;
 
        return 0;
+fail5:
+       device_unregister(&imx_usb->gadget.dev);
 fail4:
        for (i = 0; i < IMX_USB_NB_EP + 1; i++)
                free_irq(imx_usb->usbd_int[i], imx_usb);
@@ -1514,6 +1509,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev)
        int i;
 
        usb_del_gadget_udc(&imx_usb->gadget);
+       device_unregister(&imx_usb->gadget.dev);
        imx_udc_disable(imx_usb);
        del_timer(&imx_usb->timer);
 
index d226058e3b88ab7a3f6d07783886d8f23e8b7365..32524b631959eda7a62e2e2b005c3ba7a2e88f4b 100644 (file)
@@ -59,7 +59,7 @@ static const char * const ep_name[] = {
 };
 
 #define DMA_ADDR_INVALID       (~(dma_addr_t)0)
-#ifdef CONFIG_USB_GADGET_NET2272_DMA
+#ifdef CONFIG_USB_NET2272_DMA
 /*
  * use_dma: the NET2272 can use an external DMA controller.
  * Note that since there is no generic DMA api, some functions,
@@ -1495,6 +1495,13 @@ stop_activity(struct net2272 *dev, struct usb_gadget_driver *driver)
        for (i = 0; i < 4; ++i)
                net2272_dequeue_all(&dev->ep[i]);
 
+       /* report disconnect; the driver is already quiesced */
+       if (driver) {
+               spin_unlock(&dev->lock);
+               driver->disconnect(&dev->gadget);
+               spin_lock(&dev->lock);
+       }
+
        net2272_usb_reinit(dev);
 }
 
index a1b650e11339797ca9a17ca41e6de5cd8ab07ca2..3bd0f992fb49aebe5b5c4dc9e45356bb77c01581 100644 (file)
@@ -1924,7 +1924,6 @@ static int net2280_start(struct usb_gadget *_gadget,
 err_func:
        device_remove_file (&dev->pdev->dev, &dev_attr_function);
 err_unbind:
-       driver->unbind (&dev->gadget);
        dev->gadget.dev.driver = NULL;
        dev->driver = NULL;
        return retval;
@@ -1946,6 +1945,13 @@ stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)
        for (i = 0; i < 7; i++)
                nuke (&dev->ep [i]);
 
+       /* report disconnect; the driver is already quiesced */
+       if (driver) {
+               spin_unlock(&dev->lock);
+               driver->disconnect(&dev->gadget);
+               spin_lock(&dev->lock);
+       }
+
        usb_reinit (dev);
 }
 
index 06be85c2b2337a7b9f909822fb3f8ab37313ad0c..f8445653577fbb107256576fec5481b4b94f758f 100644 (file)
@@ -62,6 +62,7 @@
 #define        DRIVER_VERSION  "4 October 2004"
 
 #define OMAP_DMA_USB_W2FC_TX0          29
+#define OMAP_DMA_USB_W2FC_RX0          26
 
 /*
  * The OMAP UDC needs _very_ early endpoint setup:  before enabling the
@@ -1310,7 +1311,7 @@ static int omap_pullup(struct usb_gadget *gadget, int is_on)
 }
 
 static int omap_udc_start(struct usb_gadget *g,
-               struct usb_gadget_driver *driver)
+               struct usb_gadget_driver *driver);
 static int omap_udc_stop(struct usb_gadget *g,
                struct usb_gadget_driver *driver);
 
index 2bbcdce942dc2b7a8c29f17361e2a95fd59f47db..d0f37484b6b0cf67faf1875db8440521b030f1a2 100644 (file)
@@ -1266,13 +1266,6 @@ static int pxa25x_udc_start(struct usb_gadget *g,
        dev->gadget.dev.driver = &driver->driver;
        dev->pullup = 1;
 
-       retval = device_add (&dev->gadget.dev);
-       if (retval) {
-               dev->driver = NULL;
-               dev->gadget.dev.driver = NULL;
-               return retval;
-       }
-
        /* ... then enable host detection and ep0; and we're ready
         * for set_configuration as well as eventual disconnect.
         */
@@ -1310,6 +1303,10 @@ stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver)
        }
        del_timer_sync(&dev->timer);
 
+       /* report disconnect; the driver is already quiesced */
+       if (driver)
+               driver->disconnect(&dev->gadget);
+
        /* re-init driver-visible data structures */
        udc_reinit(dev);
 }
@@ -1331,7 +1328,6 @@ static int pxa25x_udc_stop(struct usb_gadget*g,
        dev->gadget.dev.driver = NULL;
        dev->driver = NULL;
 
-       device_del (&dev->gadget.dev);
        dump_state(dev);
 
        return 0;
@@ -2146,6 +2142,13 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev)
        dev->gadget.dev.parent = &pdev->dev;
        dev->gadget.dev.dma_mask = pdev->dev.dma_mask;
 
+       retval = device_add(&dev->gadget.dev);
+       if (retval) {
+               dev->driver = NULL;
+               dev->gadget.dev.driver = NULL;
+               goto err_device_add;
+       }
+
        the_controller = dev;
        platform_set_drvdata(pdev, dev);
 
@@ -2196,6 +2199,8 @@ lubbock_fail0:
        free_irq(irq, dev);
 #endif
  err_irq1:
+       device_unregister(&dev->gadget.dev);
+ err_device_add:
        if (gpio_is_valid(dev->mach->gpio_pullup))
                gpio_free(dev->mach->gpio_pullup);
  err_gpio_pullup:
@@ -2217,10 +2222,11 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev)
 {
        struct pxa25x_udc *dev = platform_get_drvdata(pdev);
 
-       usb_del_gadget_udc(&dev->gadget);
        if (dev->driver)
                return -EBUSY;
 
+       usb_del_gadget_udc(&dev->gadget);
+       device_unregister(&dev->gadget.dev);
        dev->pullup = 0;
        pullup(dev);
 
index f7d25795821ac2830aa6ae587eda30c714c16342..2fc867652ef5df8f97e55c7c3ebe45196c672ab7 100644 (file)
@@ -1814,11 +1814,6 @@ static int pxa27x_udc_start(struct usb_gadget *g,
        udc->gadget.dev.driver = &driver->driver;
        dplus_pullup(udc, 1);
 
-       retval = device_add(&udc->gadget.dev);
-       if (retval) {
-               dev_err(udc->dev, "device_add error %d\n", retval);
-               goto fail;
-       }
        if (!IS_ERR_OR_NULL(udc->transceiver)) {
                retval = otg_set_peripheral(udc->transceiver->otg,
                                                &udc->gadget);
@@ -1876,7 +1871,6 @@ static int pxa27x_udc_stop(struct usb_gadget *g,
 
        udc->driver = NULL;
 
-       device_del(&udc->gadget.dev);
 
        if (!IS_ERR_OR_NULL(udc->transceiver))
                return otg_set_peripheral(udc->transceiver->otg, NULL);
@@ -2480,13 +2474,24 @@ static int __init pxa_udc_probe(struct platform_device *pdev)
                        driver_name, udc->irq, retval);
                goto err_irq;
        }
+
+       retval = device_add(&udc->gadget.dev);
+       if (retval) {
+               dev_err(udc->dev, "device_add error %d\n", retval);
+               goto err_dev_add;
+       }
+
        retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget);
        if (retval)
                goto err_add_udc;
 
        pxa_init_debugfs(udc);
+
        return 0;
+
 err_add_udc:
+       device_unregister(&udc->gadget.dev);
+err_dev_add:
        free_irq(udc->irq, udc);
 err_irq:
        iounmap(udc->regs);
@@ -2507,6 +2512,7 @@ static int __exit pxa_udc_remove(struct platform_device *_dev)
        int gpio = udc->mach->gpio_pullup;
 
        usb_del_gadget_udc(&udc->gadget);
+       device_del(&udc->gadget.dev);
        usb_gadget_unregister_driver(udc->driver);
        free_irq(udc->irq, udc);
        pxa_cleanup_debugfs(udc);
index fc07b43812867d4070143093060be8d328fad9ff..08f89652533baa0702bf4a85429d282b56973695 100644 (file)
@@ -1668,8 +1668,7 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev)
 static int s3c2410_udc_start(struct usb_gadget *g,
                struct usb_gadget_driver *driver)
 {
-       struct s3c2410_udc *udc = to_s3c2410(g)
-       int             retval;
+       struct s3c2410_udc *udc = to_s3c2410(g);
 
        dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name);
 
@@ -1677,22 +1676,10 @@ static int s3c2410_udc_start(struct usb_gadget *g,
        udc->driver = driver;
        udc->gadget.dev.driver = &driver->driver;
 
-       /* Bind the driver */
-       retval = device_add(&udc->gadget.dev);
-       if (retval) {
-               dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval);
-               goto register_error;
-       }
-
        /* Enable udc */
        s3c2410_udc_enable(udc);
 
        return 0;
-
-register_error:
-       udc->driver = NULL;
-       udc->gadget.dev.driver = NULL;
-       return retval;
 }
 
 static int s3c2410_udc_stop(struct usb_gadget *g,
@@ -1700,7 +1687,6 @@ static int s3c2410_udc_stop(struct usb_gadget *g,
 {
        struct s3c2410_udc *udc = to_s3c2410(g);
 
-       device_del(&udc->gadget.dev);
        udc->driver = NULL;
 
        /* Disable udc */
@@ -1842,6 +1828,13 @@ static int s3c2410_udc_probe(struct platform_device *pdev)
        udc->gadget.dev.parent = &pdev->dev;
        udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
 
+       /* Bind the driver */
+       retval = device_add(&udc->gadget.dev);
+       if (retval) {
+               dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval);
+               goto err_device_add;
+       }
+
        the_controller = udc;
        platform_set_drvdata(pdev, udc);
 
@@ -1930,6 +1923,8 @@ err_gpio_claim:
 err_int:
        free_irq(IRQ_USBD, udc);
 err_map:
+       device_unregister(&udc->gadget.dev);
+err_device_add:
        iounmap(base_addr);
 err_mem:
        release_mem_region(rsrc_start, rsrc_len);
@@ -1947,10 +1942,11 @@ static int s3c2410_udc_remove(struct platform_device *pdev)
 
        dev_dbg(&pdev->dev, "%s()\n", __func__);
 
-       usb_del_gadget_udc(&udc->gadget);
        if (udc->driver)
                return -EBUSY;
 
+       usb_del_gadget_udc(&udc->gadget);
+       device_unregister(&udc->gadget.dev);
        debugfs_remove(udc->regs_info);
 
        if (udc_info && !udc_info->udc_command &&
index c5034d9c946b479b52e7e06cba68729392727d07..b369292d4b90cd0c5c66dd147434f5d8aadbd752 100644 (file)
@@ -136,7 +136,7 @@ static struct portmaster {
        pr_debug(fmt, ##arg)
 #endif /* pr_vdebug */
 #else
-#ifndef pr_vdebig
+#ifndef pr_vdebug
 #define pr_vdebug(fmt, arg...) \
        ({ if (0) pr_debug(fmt, ##arg); })
 #endif /* pr_vdebug */
index e0c5e88e03ed30dc02c533d0eae3a41b94bcb00b..c7d460f43390da9dd5bfad40774f8c6b3fccf54d 100644 (file)
@@ -240,8 +240,11 @@ static int gaudio_open_snd_dev(struct gaudio *card)
        snd = &card->playback;
        snd->filp = filp_open(fn_play, O_WRONLY, 0);
        if (IS_ERR(snd->filp)) {
+               int ret = PTR_ERR(snd->filp);
+
                ERROR(card, "No such PCM playback device: %s\n", fn_play);
                snd->filp = NULL;
+               return ret;
        }
        pcm_file = snd->filp->private_data;
        snd->substream = pcm_file->substream;
index 2a9cd369f71cd857cce96f48acb4b600a828c981..f8f62c3ed65e7a468b97f7348aac97ea133bbcf1 100644 (file)
@@ -216,7 +216,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc)
        usb_gadget_disconnect(udc->gadget);
        udc->driver->disconnect(udc->gadget);
        udc->driver->unbind(udc->gadget);
-       usb_gadget_udc_stop(udc->gadget, udc->driver);
+       usb_gadget_udc_stop(udc->gadget, NULL);
 
        udc->driver = NULL;
        udc->dev.driver = NULL;
index b416a3fc99594f30afbb15995191313f6c9315a6..416a6dce5e11c8adeeed2eef487b93c93dd5d728 100644 (file)
@@ -302,6 +302,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
 
 static void end_unlink_async(struct ehci_hcd *ehci);
 static void unlink_empty_async(struct ehci_hcd *ehci);
+static void unlink_empty_async_suspended(struct ehci_hcd *ehci);
 static void ehci_work(struct ehci_hcd *ehci);
 static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
 static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh);
@@ -748,11 +749,9 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
                /* guard against (alleged) silicon errata */
                if (cmd & CMD_IAAD)
                        ehci_dbg(ehci, "IAA with IAAD still set?\n");
-               if (ehci->async_iaa) {
+               if (ehci->async_iaa)
                        COUNT(ehci->stats.iaa);
-                       end_unlink_async(ehci);
-               } else
-                       ehci_dbg(ehci, "IAA with nothing unlinked?\n");
+               end_unlink_async(ehci);
        }
 
        /* remote wakeup [4.3.1] */
index 4d3b294f203e3acefe469db340d695786b2ffc3f..7d06e77f6c4fa0116ea69ad239753ea4dffe20fd 100644 (file)
@@ -328,7 +328,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
        ehci->rh_state = EHCI_RH_SUSPENDED;
 
        end_unlink_async(ehci);
-       unlink_empty_async(ehci);
+       unlink_empty_async_suspended(ehci);
        ehci_handle_intr_unlinks(ehci);
        end_free_itds(ehci);
 
index fd252f0cfb3a7873ec7bad8226a036a9668b182e..23d13690428591b3c71d6c10bc9b29a4ffd0c973 100644 (file)
@@ -135,7 +135,7 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
                 * qtd is updated in qh_completions(). Update the QH
                 * overlay here.
                 */
-               if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) {
+               if (qh->hw->hw_token & ACTIVE_BIT(ehci)) {
                        qh->hw->hw_qtd_next = qtd->hw_next;
                        qtd = NULL;
                }
@@ -449,11 +449,19 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
                        else if (last_status == -EINPROGRESS && !urb->unlinked)
                                continue;
 
-                       /* qh unlinked; token in overlay may be most current */
-                       if (state == QH_STATE_IDLE
-                                       && cpu_to_hc32(ehci, qtd->qtd_dma)
-                                               == hw->hw_current) {
+                       /*
+                        * If this was the active qtd when the qh was unlinked
+                        * and the overlay's token is active, then the overlay
+                        * hasn't been written back to the qtd yet so use its
+                        * token instead of the qtd's.  After the qtd is
+                        * processed and removed, the overlay won't be valid
+                        * any more.
+                        */
+                       if (state == QH_STATE_IDLE &&
+                                       qh->qtd_list.next == &qtd->qtd_list &&
+                                       (hw->hw_token & ACTIVE_BIT(ehci))) {
                                token = hc32_to_cpu(ehci, hw->hw_token);
+                               hw->hw_token &= ~ACTIVE_BIT(ehci);
 
                                /* An unlink may leave an incomplete
                                 * async transaction in the TT buffer.
@@ -1170,7 +1178,7 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh)
        struct ehci_qh          *prev;
 
        /* Add to the end of the list of QHs waiting for the next IAAD */
-       qh->qh_state = QH_STATE_UNLINK;
+       qh->qh_state = QH_STATE_UNLINK_WAIT;
        if (ehci->async_unlink)
                ehci->async_unlink_last->unlink_next = qh;
        else
@@ -1213,9 +1221,19 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested)
 
                /* Do only the first waiting QH (nVidia bug?) */
                qh = ehci->async_unlink;
-               ehci->async_iaa = qh;
-               ehci->async_unlink = qh->unlink_next;
-               qh->unlink_next = NULL;
+
+               /*
+                * Intel (?) bug: The HC can write back the overlay region
+                * even after the IAA interrupt occurs.  In self-defense,
+                * always go through two IAA cycles for each QH.
+                */
+               if (qh->qh_state == QH_STATE_UNLINK_WAIT) {
+                       qh->qh_state = QH_STATE_UNLINK;
+               } else {
+                       ehci->async_iaa = qh;
+                       ehci->async_unlink = qh->unlink_next;
+                       qh->unlink_next = NULL;
+               }
 
                /* Make sure the unlinks are all visible to the hardware */
                wmb();
@@ -1298,6 +1316,19 @@ static void unlink_empty_async(struct ehci_hcd *ehci)
        }
 }
 
+/* The root hub is suspended; unlink all the async QHs */
+static void unlink_empty_async_suspended(struct ehci_hcd *ehci)
+{
+       struct ehci_qh          *qh;
+
+       while (ehci->async->qh_next.qh) {
+               qh = ehci->async->qh_next.qh;
+               WARN_ON(!list_empty(&qh->qtd_list));
+               single_unlink_async(ehci, qh);
+       }
+       start_iaa_cycle(ehci, false);
+}
+
 /* makes sure the async qh will become idle */
 /* caller must own ehci->lock */
 
index b476daf49f6f3c6cf226b920f5c8ff01ca5d23aa..010f686d8881fc9796fd3bbee1c1f5c3aa71e878 100644 (file)
@@ -1214,6 +1214,7 @@ itd_urb_transaction (
 
                memset (itd, 0, sizeof *itd);
                itd->itd_dma = itd_dma;
+               itd->frame = 9999;              /* an invalid value */
                list_add (&itd->itd_list, &sched->td_list);
        }
        spin_unlock_irqrestore (&ehci->lock, flags);
@@ -1915,6 +1916,7 @@ sitd_urb_transaction (
 
                memset (sitd, 0, sizeof *sitd);
                sitd->sitd_dma = sitd_dma;
+               sitd->frame = 9999;             /* an invalid value */
                list_add (&sitd->sitd_list, &iso_sched->td_list);
        }
 
index 20dbdcbe9b0fc1fb1330da115bebb3546e45b8f2..c3fa1305f830bf53070a6553446428368553691d 100644 (file)
@@ -304,7 +304,7 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci)
         * (a) SMP races against real IAA firing and retriggering, and
         * (b) clean HC shutdown, when IAA watchdog was pending.
         */
-       if (ehci->async_iaa) {
+       if (1) {
                u32 cmd, status;
 
                /* If we get here, IAA is *REALLY* late.  It's barely
index 35616ffbe3ae7435155bf29196d295f35a719b71..6dc238c592bc9aef5e3d8a564240b085e401cf6b 100644 (file)
@@ -1022,44 +1022,24 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,
  * is attached to (or the roothub port its ancestor hub is attached to).  All we
  * know is the index of that port under either the USB 2.0 or the USB 3.0
  * roothub, but that doesn't give us the real index into the HW port status
- * registers.  Scan through the xHCI roothub port array, looking for the Nth
- * entry of the correct port speed.  Return the port number of that entry.
+ * registers. Call xhci_find_raw_port_number() to get real index.
  */
 static u32 xhci_find_real_port_number(struct xhci_hcd *xhci,
                struct usb_device *udev)
 {
        struct usb_device *top_dev;
-       unsigned int num_similar_speed_ports;
-       unsigned int faked_port_num;
-       int i;
+       struct usb_hcd *hcd;
+
+       if (udev->speed == USB_SPEED_SUPER)
+               hcd = xhci->shared_hcd;
+       else
+               hcd = xhci->main_hcd;
 
        for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
                        top_dev = top_dev->parent)
                /* Found device below root hub */;
-       faked_port_num = top_dev->portnum;
-       for (i = 0, num_similar_speed_ports = 0;
-                       i < HCS_MAX_PORTS(xhci->hcs_params1); i++) {
-               u8 port_speed = xhci->port_array[i];
-
-               /*
-                * Skip ports that don't have known speeds, or have duplicate
-                * Extended Capabilities port speed entries.
-                */
-               if (port_speed == 0 || port_speed == DUPLICATE_ENTRY)
-                       continue;
 
-               /*
-                * USB 3.0 ports are always under a USB 3.0 hub.  USB 2.0 and
-                * 1.1 ports are under the USB 2.0 hub.  If the port speed
-                * matches the device speed, it's a similar speed port.
-                */
-               if ((port_speed == 0x03) == (udev->speed == USB_SPEED_SUPER))
-                       num_similar_speed_ports++;
-               if (num_similar_speed_ports == faked_port_num)
-                       /* Roothub ports are numbered from 1 to N */
-                       return i+1;
-       }
-       return 0;
+       return  xhci_find_raw_port_number(hcd, top_dev->portnum);
 }
 
 /* Setup an xHCI virtual device for a Set Address command */
index af259e0ec172aa4a5664ca15acb2adf8d90bf02c..1a30c380043ce258aa660e67edb38210707fffd6 100644 (file)
@@ -313,6 +313,7 @@ static const struct hc_driver xhci_pci_hc_driver = {
        .set_usb2_hw_lpm =      xhci_set_usb2_hardware_lpm,
        .enable_usb3_lpm_timeout =      xhci_enable_usb3_lpm_timeout,
        .disable_usb3_lpm_timeout =     xhci_disable_usb3_lpm_timeout,
+       .find_raw_port_number = xhci_find_raw_port_number,
 };
 
 /*-------------------------------------------------------------------------*/
index 88287546530179a867da6f3a9d88f615d87f9a81..1969c001b3f9a8bacbe926dfc4777c95206101a1 100644 (file)
@@ -1599,14 +1599,20 @@ static void handle_port_status(struct xhci_hcd *xhci,
        max_ports = HCS_MAX_PORTS(xhci->hcs_params1);
        if ((port_id <= 0) || (port_id > max_ports)) {
                xhci_warn(xhci, "Invalid port id %d\n", port_id);
-               bogus_port_status = true;
-               goto cleanup;
+               inc_deq(xhci, xhci->event_ring);
+               return;
        }
 
        /* Figure out which usb_hcd this port is attached to:
         * is it a USB 3.0 port or a USB 2.0/1.1 port?
         */
        major_revision = xhci->port_array[port_id - 1];
+
+       /* Find the right roothub. */
+       hcd = xhci_to_hcd(xhci);
+       if ((major_revision == 0x03) != (hcd->speed == HCD_USB3))
+               hcd = xhci->shared_hcd;
+
        if (major_revision == 0) {
                xhci_warn(xhci, "Event for port %u not in "
                                "Extended Capabilities, ignoring.\n",
@@ -1629,10 +1635,6 @@ static void handle_port_status(struct xhci_hcd *xhci,
         * into the index into the ports on the correct split roothub, and the
         * correct bus_state structure.
         */
-       /* Find the right roothub. */
-       hcd = xhci_to_hcd(xhci);
-       if ((major_revision == 0x03) != (hcd->speed == HCD_USB3))
-               hcd = xhci->shared_hcd;
        bus_state = &xhci->bus_state[hcd_index(hcd)];
        if (hcd->speed == HCD_USB3)
                port_array = xhci->usb3_ports;
@@ -2027,8 +2029,8 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
                if (event_trb != ep_ring->dequeue &&
                                event_trb != td->last_trb)
                        td->urb->actual_length =
-                               td->urb->transfer_buffer_length
-                               TRB_LEN(le32_to_cpu(event->transfer_len));
+                               td->urb->transfer_buffer_length -
+                               EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
                else
                        td->urb->actual_length = 0;
 
@@ -2060,7 +2062,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
                /* Maybe the event was for the data stage? */
                        td->urb->actual_length =
                                td->urb->transfer_buffer_length -
-                               TRB_LEN(le32_to_cpu(event->transfer_len));
+                               EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
                        xhci_dbg(xhci, "Waiting for status "
                                        "stage event\n");
                        return 0;
@@ -2096,7 +2098,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
        /* handle completion code */
        switch (trb_comp_code) {
        case COMP_SUCCESS:
-               if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
+               if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) {
                        frame->status = 0;
                        break;
                }
@@ -2141,7 +2143,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
                                len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
                }
                len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
-                       TRB_LEN(le32_to_cpu(event->transfer_len));
+                       EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
 
                if (trb_comp_code != COMP_STOP_INVAL) {
                        frame->actual_length = len;
@@ -2199,7 +2201,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
        case COMP_SUCCESS:
                /* Double check that the HW transferred everything. */
                if (event_trb != td->last_trb ||
-                               TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
+                   EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
                        xhci_warn(xhci, "WARN Successful completion "
                                        "on short TX\n");
                        if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
@@ -2227,18 +2229,18 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
                                "%d bytes untransferred\n",
                                td->urb->ep->desc.bEndpointAddress,
                                td->urb->transfer_buffer_length,
-                               TRB_LEN(le32_to_cpu(event->transfer_len)));
+                               EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
        /* Fast path - was this the last TRB in the TD for this URB? */
        if (event_trb == td->last_trb) {
-               if (TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
+               if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
                        td->urb->actual_length =
                                td->urb->transfer_buffer_length -
-                               TRB_LEN(le32_to_cpu(event->transfer_len));
+                               EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
                        if (td->urb->transfer_buffer_length <
                                        td->urb->actual_length) {
                                xhci_warn(xhci, "HC gave bad length "
                                                "of %d bytes left\n",
-                                         TRB_LEN(le32_to_cpu(event->transfer_len)));
+                                         EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)));
                                td->urb->actual_length = 0;
                                if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
                                        *status = -EREMOTEIO;
@@ -2280,7 +2282,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
                if (trb_comp_code != COMP_STOP_INVAL)
                        td->urb->actual_length +=
                                TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
-                               TRB_LEN(le32_to_cpu(event->transfer_len));
+                               EVENT_TRB_LEN(le32_to_cpu(event->transfer_len));
        }
 
        return finish_td(xhci, td, event_trb, event, ep, status, false);
@@ -2368,7 +2370,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
         * transfer type
         */
        case COMP_SUCCESS:
-               if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
+               if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0)
                        break;
                if (xhci->quirks & XHCI_TRUST_TX_LENGTH)
                        trb_comp_code = COMP_SHORT_TX;
@@ -2461,14 +2463,21 @@ static int handle_tx_event(struct xhci_hcd *xhci,
                 * TD list.
                 */
                if (list_empty(&ep_ring->td_list)) {
-                       xhci_warn(xhci, "WARN Event TRB for slot %d ep %d "
-                                       "with no TDs queued?\n",
-                                 TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
-                                 ep_index);
-                       xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
-                                (le32_to_cpu(event->flags) &
-                                 TRB_TYPE_BITMASK)>>10);
-                       xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
+                       /*
+                        * A stopped endpoint may generate an extra completion
+                        * event if the device was suspended.  Don't print
+                        * warnings.
+                        */
+                       if (!(trb_comp_code == COMP_STOP ||
+                                               trb_comp_code == COMP_STOP_INVAL)) {
+                               xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n",
+                                               TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
+                                               ep_index);
+                               xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
+                                               (le32_to_cpu(event->flags) &
+                                                TRB_TYPE_BITMASK)>>10);
+                               xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
+                       }
                        if (ep->skip) {
                                ep->skip = false;
                                xhci_dbg(xhci, "td_list is empty while skip "
index f1f01a834ba792cee0935c5ffb9373d53fb368bd..53b8f89a0b1c7e6199c95672c85d3d27fb3e0b90 100644 (file)
@@ -350,7 +350,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
         * generate interrupts.  Don't even try to enable MSI.
         */
        if (xhci->quirks & XHCI_BROKEN_MSI)
-               return 0;
+               goto legacy_irq;
 
        /* unregister the legacy interrupt */
        if (hcd->irq)
@@ -371,6 +371,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
                return -EINVAL;
        }
 
+ legacy_irq:
        /* fall back to legacy interrupt*/
        ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED,
                        hcd->irq_descr, hcd);
@@ -3778,6 +3779,28 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
        return 0;
 }
 
+/*
+ * Transfer the port index into real index in the HW port status
+ * registers. Caculate offset between the port's PORTSC register
+ * and port status base. Divide the number of per port register
+ * to get the real index. The raw port number bases 1.
+ */
+int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1)
+{
+       struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+       __le32 __iomem *base_addr = &xhci->op_regs->port_status_base;
+       __le32 __iomem *addr;
+       int raw_port;
+
+       if (hcd->speed != HCD_USB3)
+               addr = xhci->usb2_ports[port1 - 1];
+       else
+               addr = xhci->usb3_ports[port1 - 1];
+
+       raw_port = (addr - base_addr)/NUM_PORT_REGS + 1;
+       return raw_port;
+}
+
 #ifdef CONFIG_USB_SUSPEND
 
 /* BESL to HIRD Encoding array for USB2 LPM */
index f791bd0aee6cda4ad2bf5407ba5ad71b912cc5f5..63582719e0fb26cafb4d19f5248c2b5f9aa8a43a 100644 (file)
@@ -206,8 +206,8 @@ struct xhci_op_regs {
 /* bits 12:31 are reserved (and should be preserved on writes). */
 
 /* IMAN - Interrupt Management Register */
-#define IMAN_IP                (1 << 1)
-#define IMAN_IE                (1 << 0)
+#define IMAN_IE                (1 << 1)
+#define IMAN_IP                (1 << 0)
 
 /* USBSTS - USB status - status bitmasks */
 /* HC not running - set to 1 when run/stop bit is cleared. */
@@ -972,6 +972,10 @@ struct xhci_transfer_event {
        __le32  flags;
 };
 
+/* Transfer event TRB length bit mask */
+/* bits 0:23 */
+#define        EVENT_TRB_LEN(p)                ((p) & 0xffffff)
+
 /** Transfer Event bit fields **/
 #define        TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f)
 
@@ -1829,6 +1833,7 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
 int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex,
                char *buf, u16 wLength);
 int xhci_hub_status_data(struct usb_hcd *hcd, char *buf);
+int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1);
 
 #ifdef CONFIG_PM
 int xhci_bus_suspend(struct usb_hcd *hcd);
index 45b19e2c60bacfe396469c2d4ea426c3ff68c830..05e51432dd2f77eb08bda0b43293df5363425ef0 100644 (file)
@@ -7,11 +7,6 @@
 config USB_MUSB_HDRC
        tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)'
        depends on USB && USB_GADGET
-       select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN)
-       select NOP_USB_XCEIV if (SOC_TI81XX || SOC_AM33XX)
-       select TWL4030_USB if MACH_OMAP_3430SDP
-       select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
-       select OMAP_CONTROL_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA
        select USB_OTG_UTILS
        help
          Say Y here if your system has a dual role high speed USB
index 7c71769d71ff37370e6e8bf23be5c837bd72a677..41613a2b35e8530d8278bd8e4191bafae5617828 100644 (file)
@@ -327,7 +327,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci)
                u8 devctl = musb_readb(mregs, MUSB_DEVCTL);
                int err;
 
-               err = musb->int_usb & USB_INTR_VBUSERROR;
+               err = musb->int_usb & MUSB_INTR_VBUSERROR;
                if (err) {
                        /*
                         * The Mentor core doesn't debounce VBUS as needed
index 60b41cc28da446558690f0e37bff33111823f281..daec6e0f7e381e52750cffab9112488c3af1e01d 100644 (file)
@@ -1624,8 +1624,6 @@ EXPORT_SYMBOL_GPL(musb_dma_completion);
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef CONFIG_SYSFS
-
 static ssize_t
 musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -1742,8 +1740,6 @@ static const struct attribute_group musb_attr_group = {
        .attrs = musb_attributes,
 };
 
-#endif /* sysfs */
-
 /* Only used to provide driver mode change events */
 static void musb_irq_work(struct work_struct *data)
 {
@@ -1968,11 +1964,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl)
        if (status < 0)
                goto fail4;
 
-#ifdef CONFIG_SYSFS
        status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group);
        if (status)
                goto fail5;
-#endif
 
        pm_runtime_put(musb->controller);
 
index be18537c5f1407cca17b31f65965863c0fa47385..83eddedcd9be5895908672b329ebf881d26d8f2f 100644 (file)
@@ -141,7 +141,9 @@ static inline void map_dma_buffer(struct musb_request *request,
 static inline void unmap_dma_buffer(struct musb_request *request,
                                struct musb *musb)
 {
-       if (!is_buffer_mapped(request))
+       struct musb_ep *musb_ep = request->ep;
+
+       if (!is_buffer_mapped(request) || !musb_ep->dma)
                return;
 
        if (request->request.dma == DMA_ADDR_INVALID) {
@@ -195,7 +197,10 @@ __acquires(ep->musb->lock)
 
        ep->busy = 1;
        spin_unlock(&musb->lock);
-       unmap_dma_buffer(req, musb);
+
+       if (!dma_mapping_error(&musb->g.dev, request->dma))
+               unmap_dma_buffer(req, musb);
+
        if (request->status == 0)
                dev_dbg(musb->controller, "%s done request %p,  %d/%d\n",
                                ep->end_point.name, request,
index 1762354fe793198fbfc075fb95ab22468dc34a8b..1a42a458f2c4ff64cb8e9e3492bf368cf79cf0c3 100644 (file)
@@ -51,7 +51,7 @@ struct omap2430_glue {
 };
 #define glue_to_musb(g)                platform_get_drvdata(g->musb)
 
-struct omap2430_glue           *_glue;
+static struct omap2430_glue    *_glue;
 
 static struct timer_list musb_idle_timer;
 
@@ -237,9 +237,13 @@ void omap_musb_mailbox(enum omap_musb_vbus_id_status status)
 {
        struct omap2430_glue    *glue = _glue;
 
-       if (glue && glue_to_musb(glue)) {
-               glue->status = status;
-       } else {
+       if (!glue) {
+               pr_err("%s: musb core is not yet initialized\n", __func__);
+               return;
+       }
+       glue->status = status;
+
+       if (!glue_to_musb(glue)) {
                pr_err("%s: musb core is not yet ready\n", __func__);
                return;
        }
index e1814397ca3ab9631872a481d0a60c2b77b89afc..2bd03d261a50f4f8f8df3583dcc57961c3b8ec34 100644 (file)
@@ -130,7 +130,7 @@ struct usb_phy *usb_get_phy(enum usb_phy_type type)
        spin_lock_irqsave(&phy_lock, flags);
 
        phy = __usb_find_phy(&phy_list, type);
-       if (IS_ERR(phy)) {
+       if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
                pr_err("unable to find transceiver of type %s\n",
                        usb_phy_type_string(type));
                goto err0;
@@ -228,7 +228,7 @@ struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index)
        spin_lock_irqsave(&phy_lock, flags);
 
        phy = __usb_find_phy_dev(dev, &phy_bind_list, index);
-       if (IS_ERR(phy)) {
+       if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) {
                pr_err("unable to find transceiver\n");
                goto err0;
        }
@@ -301,8 +301,12 @@ EXPORT_SYMBOL(devm_usb_put_phy);
  */
 void usb_put_phy(struct usb_phy *x)
 {
-       if (x)
+       if (x) {
+               struct module *owner = x->dev->driver->owner;
+
                put_device(x->dev);
+               module_put(owner);
+       }
 }
 EXPORT_SYMBOL(usb_put_phy);
 
index 65217a5900689028e68a61e28c8011fbc9cbbaea..90549382eba5f139c6d54b7617319132189e6596 100644 (file)
@@ -38,6 +38,7 @@ config USB_ISP1301
        tristate "NXP ISP1301 USB transceiver support"
        depends on USB || USB_GADGET
        depends on I2C
+       select USB_OTG_UTILS
        help
          Say Y here to add support for the NXP ISP1301 USB transceiver driver.
          This chip is typically used as USB transceiver for USB host, gadget
index 5323b71c3521f4ebe41ad74260787103e6933ce5..1419ceda9759c591f5036dddda8c5c673a2d7fa4 100644 (file)
@@ -219,32 +219,26 @@ static int omap_control_usb_probe(struct platform_device *pdev)
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
                "control_dev_conf");
-       control_usb->dev_conf = devm_request_and_ioremap(&pdev->dev, res);
-       if (!control_usb->dev_conf) {
-               dev_err(&pdev->dev, "Failed to obtain io memory\n");
-               return -EADDRNOTAVAIL;
-       }
+       control_usb->dev_conf = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(control_usb->dev_conf))
+               return PTR_ERR(control_usb->dev_conf);
 
        if (control_usb->type == OMAP_CTRL_DEV_TYPE1) {
                res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
                        "otghs_control");
-               control_usb->otghs_control = devm_request_and_ioremap(
+               control_usb->otghs_control = devm_ioremap_resource(
                        &pdev->dev, res);
-               if (!control_usb->otghs_control) {
-                       dev_err(&pdev->dev, "Failed to obtain io memory\n");
-                       return -EADDRNOTAVAIL;
-               }
+               if (IS_ERR(control_usb->otghs_control))
+                       return PTR_ERR(control_usb->otghs_control);
        }
 
        if (control_usb->type == OMAP_CTRL_DEV_TYPE2) {
                res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
                        "phy_power_usb");
-               control_usb->phy_power = devm_request_and_ioremap(
+               control_usb->phy_power = devm_ioremap_resource(
                        &pdev->dev, res);
-               if (!control_usb->phy_power) {
-                       dev_dbg(&pdev->dev, "Failed to obtain io memory\n");
-                       return -EADDRNOTAVAIL;
-               }
+               if (IS_ERR(control_usb->phy_power))
+                       return PTR_ERR(control_usb->phy_power);
 
                control_usb->sys_clk = devm_clk_get(control_usb->dev,
                        "sys_clkin");
index fadc0c2b65bb7baf6b633c97cb187a16c4bd9d93..a6e60b1e102e84c070a44e139d8e9ac2b1ff01c7 100644 (file)
@@ -212,11 +212,9 @@ static int omap_usb3_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl");
-       phy->pll_ctrl_base = devm_request_and_ioremap(&pdev->dev, res);
-       if (!phy->pll_ctrl_base) {
-               dev_err(&pdev->dev, "ioremap of pll_ctrl failed\n");
-               return -ENOMEM;
-       }
+       phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(phy->pll_ctrl_base))
+               return PTR_ERR(phy->pll_ctrl_base);
 
        phy->dev                = &pdev->dev;
 
index 6ea5537338325f6f8ed9fe10cb7756bb79f2daf2..967101ec15fdf268cc8d2a73493be36df718d687 100644 (file)
@@ -787,11 +787,9 @@ static int samsung_usbphy_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
-       phy_base = devm_request_and_ioremap(dev, phy_mem);
-       if (!phy_base) {
-               dev_err(dev, "%s: register mapping failed\n", __func__);
-               return -ENXIO;
-       }
+       phy_base = devm_ioremap_resource(dev, phy_mem);
+       if (IS_ERR(phy_base))
+               return PTR_ERR(phy_base);
 
        sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL);
        if (!sphy)
index cbd904b8fba55f42ec07ed0d3a741878b516157c..4775f8209e5502b7f893d0a00a8f51622746a138 100644 (file)
@@ -62,7 +62,6 @@ static int is_irda(struct usb_serial *serial)
 }
 
 struct ark3116_private {
-       wait_queue_head_t       delta_msr_wait;
        struct async_icount     icount;
        int                     irda;   /* 1 for irda device */
 
@@ -146,7 +145,6 @@ static int ark3116_port_probe(struct usb_serial_port *port)
        if (!priv)
                return -ENOMEM;
 
-       init_waitqueue_head(&priv->delta_msr_wait);
        mutex_init(&priv->hw_lock);
        spin_lock_init(&priv->status_lock);
 
@@ -456,10 +454,14 @@ static int ark3116_ioctl(struct tty_struct *tty,
        case TIOCMIWAIT:
                for (;;) {
                        struct async_icount prev = priv->icount;
-                       interruptible_sleep_on(&priv->delta_msr_wait);
+                       interruptible_sleep_on(&port->delta_msr_wait);
                        /* see if a signal did it */
                        if (signal_pending(current))
                                return -ERESTARTSYS;
+
+                       if (port->serial->disconnected)
+                               return -EIO;
+
                        if ((prev.rng == priv->icount.rng) &&
                            (prev.dsr == priv->icount.dsr) &&
                            (prev.dcd == priv->icount.dcd) &&
@@ -580,7 +582,7 @@ static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr)
                        priv->icount.dcd++;
                if (msr & UART_MSR_TERI)
                        priv->icount.rng++;
-               wake_up_interruptible(&priv->delta_msr_wait);
+               wake_up_interruptible(&port->delta_msr_wait);
        }
 }
 
index d255f66e708e80ee78d72bc052bef4e71ba578e2..07d4650a32abe2d89149ef8fc2a22bc17bebe8b2 100644 (file)
@@ -80,7 +80,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 struct ch341_private {
        spinlock_t lock; /* access lock */
-       wait_queue_head_t delta_msr_wait; /* wait queue for modem status */
        unsigned baud_rate; /* set baud rate */
        u8 line_control; /* set line control value RTS/DTR */
        u8 line_status; /* active status of modem control inputs */
@@ -252,7 +251,6 @@ static int ch341_port_probe(struct usb_serial_port *port)
                return -ENOMEM;
 
        spin_lock_init(&priv->lock);
-       init_waitqueue_head(&priv->delta_msr_wait);
        priv->baud_rate = DEFAULT_BAUD_RATE;
        priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
@@ -298,7 +296,7 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on)
                priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
        spin_unlock_irqrestore(&priv->lock, flags);
        ch341_set_handshake(port->serial->dev, priv->line_control);
-       wake_up_interruptible(&priv->delta_msr_wait);
+       wake_up_interruptible(&port->delta_msr_wait);
 }
 
 static void ch341_close(struct usb_serial_port *port)
@@ -491,7 +489,7 @@ static void ch341_read_int_callback(struct urb *urb)
                        tty_kref_put(tty);
                }
 
-               wake_up_interruptible(&priv->delta_msr_wait);
+               wake_up_interruptible(&port->delta_msr_wait);
        }
 
 exit:
@@ -517,11 +515,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        spin_unlock_irqrestore(&priv->lock, flags);
 
        while (!multi_change) {
-               interruptible_sleep_on(&priv->delta_msr_wait);
+               interruptible_sleep_on(&port->delta_msr_wait);
                /* see if a signal did it */
                if (signal_pending(current))
                        return -ERESTARTSYS;
 
+               if (port->serial->disconnected)
+                       return -EIO;
+
                spin_lock_irqsave(&priv->lock, flags);
                status = priv->line_status;
                multi_change = priv->multi_status_change;
index edc0f0dcad8378f4298d68815d2935404d8fedac..4747d1c328ffbdc13e1ca4337dc11a6c557711f5 100644 (file)
@@ -85,6 +85,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */
        { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */
        { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */
+       { USB_DEVICE(0x2405, 0x0003) }, /* West Mountain Radio RIGblaster Advantage */
        { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */
        { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */
        { USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */
@@ -150,6 +151,25 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */
        { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */
        { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */
+       { USB_DEVICE(0x1FB9, 0x0100) }, /* Lake Shore Model 121 Current Source */
+       { USB_DEVICE(0x1FB9, 0x0200) }, /* Lake Shore Model 218A Temperature Monitor */
+       { USB_DEVICE(0x1FB9, 0x0201) }, /* Lake Shore Model 219 Temperature Monitor */
+       { USB_DEVICE(0x1FB9, 0x0202) }, /* Lake Shore Model 233 Temperature Transmitter */
+       { USB_DEVICE(0x1FB9, 0x0203) }, /* Lake Shore Model 235 Temperature Transmitter */
+       { USB_DEVICE(0x1FB9, 0x0300) }, /* Lake Shore Model 335 Temperature Controller */
+       { USB_DEVICE(0x1FB9, 0x0301) }, /* Lake Shore Model 336 Temperature Controller */
+       { USB_DEVICE(0x1FB9, 0x0302) }, /* Lake Shore Model 350 Temperature Controller */
+       { USB_DEVICE(0x1FB9, 0x0303) }, /* Lake Shore Model 371 AC Bridge */
+       { USB_DEVICE(0x1FB9, 0x0400) }, /* Lake Shore Model 411 Handheld Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0401) }, /* Lake Shore Model 425 Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0402) }, /* Lake Shore Model 455A Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0403) }, /* Lake Shore Model 475A Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0404) }, /* Lake Shore Model 465 Three Axis Gaussmeter */
+       { USB_DEVICE(0x1FB9, 0x0600) }, /* Lake Shore Model 625A Superconducting MPS */
+       { USB_DEVICE(0x1FB9, 0x0601) }, /* Lake Shore Model 642A Magnet Power Supply */
+       { USB_DEVICE(0x1FB9, 0x0602) }, /* Lake Shore Model 648 Magnet Power Supply */
+       { USB_DEVICE(0x1FB9, 0x0700) }, /* Lake Shore Model 737 VSM Controller */
+       { USB_DEVICE(0x1FB9, 0x0701) }, /* Lake Shore Model 776 Hall Matrix */
        { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */
        { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */
        { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */
index 8efa19d0e9fba756d37f7ea1f0b0d7e813ab9610..ba7352e4187efbd1ef73a09297d1cbb1825a4b08 100644 (file)
@@ -111,7 +111,6 @@ struct cypress_private {
        int baud_rate;                     /* stores current baud rate in
                                              integer form */
        int isthrottled;                   /* if throttled, discard reads */
-       wait_queue_head_t delta_msr_wait;  /* used for TIOCMIWAIT */
        char prev_status, diff_status;     /* used for TIOCMIWAIT */
        /* we pass a pointer to this as the argument sent to
           cypress_set_termios old_termios */
@@ -449,7 +448,6 @@ static int cypress_generic_port_probe(struct usb_serial_port *port)
                kfree(priv);
                return -ENOMEM;
        }
-       init_waitqueue_head(&priv->delta_msr_wait);
 
        usb_reset_configuration(serial->dev);
 
@@ -868,12 +866,16 @@ static int cypress_ioctl(struct tty_struct *tty,
        switch (cmd) {
        /* This code comes from drivers/char/serial.c and ftdi_sio.c */
        case TIOCMIWAIT:
-               while (priv != NULL) {
-                       interruptible_sleep_on(&priv->delta_msr_wait);
+               for (;;) {
+                       interruptible_sleep_on(&port->delta_msr_wait);
                        /* see if a signal did it */
                        if (signal_pending(current))
                                return -ERESTARTSYS;
-                       else {
+
+                       if (port->serial->disconnected)
+                               return -EIO;
+
+                       {
                                char diff = priv->diff_status;
                                if (diff == 0)
                                        return -EIO; /* no change => error */
@@ -1187,7 +1189,7 @@ static void cypress_read_int_callback(struct urb *urb)
        if (priv->current_status != priv->prev_status) {
                priv->diff_status |= priv->current_status ^
                        priv->prev_status;
-               wake_up_interruptible(&priv->delta_msr_wait);
+               wake_up_interruptible(&port->delta_msr_wait);
                priv->prev_status = priv->current_status;
        }
        spin_unlock_irqrestore(&priv->lock, flags);
index b1b2dc64b50be013eab09a2dd5ce535875aeeb5a..a172ad5c5ce80c1c00983960a04339ac3c13fb24 100644 (file)
@@ -47,7 +47,6 @@ MODULE_DEVICE_TABLE(usb, id_table);
 
 struct f81232_private {
        spinlock_t lock;
-       wait_queue_head_t delta_msr_wait;
        u8 line_control;
        u8 line_status;
 };
@@ -111,7 +110,7 @@ static void f81232_process_read_urb(struct urb *urb)
        line_status = priv->line_status;
        priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
        spin_unlock_irqrestore(&priv->lock, flags);
-       wake_up_interruptible(&priv->delta_msr_wait);
+       wake_up_interruptible(&port->delta_msr_wait);
 
        if (!urb->actual_length)
                return;
@@ -256,11 +255,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        spin_unlock_irqrestore(&priv->lock, flags);
 
        while (1) {
-               interruptible_sleep_on(&priv->delta_msr_wait);
+               interruptible_sleep_on(&port->delta_msr_wait);
                /* see if a signal did it */
                if (signal_pending(current))
                        return -ERESTARTSYS;
 
+               if (port->serial->disconnected)
+                       return -EIO;
+
                spin_lock_irqsave(&priv->lock, flags);
                status = priv->line_status;
                spin_unlock_irqrestore(&priv->lock, flags);
@@ -322,7 +324,6 @@ static int f81232_port_probe(struct usb_serial_port *port)
                return -ENOMEM;
 
        spin_lock_init(&priv->lock);
-       init_waitqueue_head(&priv->delta_msr_wait);
 
        usb_set_serial_port_data(port, priv);
 
index edd162df49caed8b02a1c0823a497c6c5d9d180e..9886180e45f1b5d73ddc1903f2e13eecb6297013 100644 (file)
@@ -69,9 +69,7 @@ struct ftdi_private {
        int flags;              /* some ASYNC_xxxx flags are supported */
        unsigned long last_dtr_rts;     /* saved modem control outputs */
        struct async_icount     icount;
-       wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
        char prev_status;        /* Used for TIOCMIWAIT */
-       bool dev_gone;        /* Used to abort TIOCMIWAIT */
        char transmit_empty;    /* If transmitter is empty or not */
        __u16 interface;        /* FT2232C, FT2232H or FT4232H port interface
                                   (0 for FT232/245) */
@@ -642,6 +640,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) },
        { USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) },
        { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) },
+       { USB_DEVICE(MITSUBISHI_VID, MITSUBISHI_FXUSB_PID) },
        { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) },
        { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) },
        { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) },
@@ -1691,10 +1690,8 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port)
 
        kref_init(&priv->kref);
        mutex_init(&priv->cfg_lock);
-       init_waitqueue_head(&priv->delta_msr_wait);
 
        priv->flags = ASYNC_LOW_LATENCY;
-       priv->dev_gone = false;
 
        if (quirk && quirk->port_probe)
                quirk->port_probe(priv);
@@ -1840,8 +1837,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port)
 {
        struct ftdi_private *priv = usb_get_serial_port_data(port);
 
-       priv->dev_gone = true;
-       wake_up_interruptible_all(&priv->delta_msr_wait);
+       wake_up_interruptible(&port->delta_msr_wait);
 
        remove_sysfs_attrs(port);
 
@@ -1989,7 +1985,7 @@ static int ftdi_process_packet(struct usb_serial_port *port,
                if (diff_status & FTDI_RS0_RLSD)
                        priv->icount.dcd++;
 
-               wake_up_interruptible_all(&priv->delta_msr_wait);
+               wake_up_interruptible(&port->delta_msr_wait);
                priv->prev_status = status;
        }
 
@@ -2440,11 +2436,15 @@ static int ftdi_ioctl(struct tty_struct *tty,
         */
        case TIOCMIWAIT:
                cprev = priv->icount;
-               while (!priv->dev_gone) {
-                       interruptible_sleep_on(&priv->delta_msr_wait);
+               for (;;) {
+                       interruptible_sleep_on(&port->delta_msr_wait);
                        /* see if a signal did it */
                        if (signal_pending(current))
                                return -ERESTARTSYS;
+
+                       if (port->serial->disconnected)
+                               return -EIO;
+
                        cnow = priv->icount;
                        if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
                            ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
@@ -2454,8 +2454,6 @@ static int ftdi_ioctl(struct tty_struct *tty,
                        }
                        cprev = cnow;
                }
-               return -EIO;
-               break;
        case TIOCSERGETLSR:
                return get_lsr_info(port, (struct serial_struct __user *)arg);
                break;
index 9d359e189a645f7dcd13222433b9377787f81a34..e79861eeed4cca1471e4531ff727f0f8425e7892 100644 (file)
 #define CONTEC_VID             0x06CE  /* Vendor ID */
 #define CONTEC_COM1USBH_PID    0x8311  /* COM-1(USB)H */
 
+/*
+ * Mitsubishi Electric Corp. (http://www.meau.com)
+ * Submitted by Konstantin Holoborodko
+ */
+#define MITSUBISHI_VID         0x06D3
+#define MITSUBISHI_FXUSB_PID   0x0284 /* USB/RS422 converters: FX-USB-AW/-BD */
+
 /*
  * Definitions for B&B Electronics products.
  */
index 1a07b12ef341a08e2bdb880d3d446054dccd5339..81caf5623ee295d609acce00a1e06a20ef34c20f 100644 (file)
@@ -956,10 +956,7 @@ static void garmin_close(struct usb_serial_port *port)
        if (!serial)
                return;
 
-       mutex_lock(&port->serial->disc_mutex);
-
-       if (!port->serial->disconnected)
-               garmin_clear(garmin_data_p);
+       garmin_clear(garmin_data_p);
 
        /* shutdown our urbs */
        usb_kill_urb(port->read_urb);
@@ -968,8 +965,6 @@ static void garmin_close(struct usb_serial_port *port)
        /* keep reset state so we know that we must start a new session */
        if (garmin_data_p->state != STATE_RESET)
                garmin_data_p->state = STATE_DISCONNECTED;
-
-       mutex_unlock(&port->serial->disc_mutex);
 }
 
 
index b00e5cbf741f16b63071c8273c7f69eaa279ca6d..efd8b978128c1d86412322f0c37e9da32b00610a 100644 (file)
@@ -110,7 +110,6 @@ struct edgeport_port {
        wait_queue_head_t       wait_chase;             /* for handling sleeping while waiting for chase to finish */
        wait_queue_head_t       wait_open;              /* for handling sleeping while waiting for open to finish */
        wait_queue_head_t       wait_command;           /* for handling sleeping while waiting for command to finish */
-       wait_queue_head_t       delta_msr_wait;         /* for handling sleeping while waiting for msr change to happen */
 
        struct async_icount     icount;
        struct usb_serial_port  *port;                  /* loop back to the owner of this object */
@@ -884,7 +883,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
        /* initialize our wait queues */
        init_waitqueue_head(&edge_port->wait_open);
        init_waitqueue_head(&edge_port->wait_chase);
-       init_waitqueue_head(&edge_port->delta_msr_wait);
        init_waitqueue_head(&edge_port->wait_command);
 
        /* initialize our icount structure */
@@ -1669,13 +1667,17 @@ static int edge_ioctl(struct tty_struct *tty,
                dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__,  port->number);
                cprev = edge_port->icount;
                while (1) {
-                       prepare_to_wait(&edge_port->delta_msr_wait,
+                       prepare_to_wait(&port->delta_msr_wait,
                                                &wait, TASK_INTERRUPTIBLE);
                        schedule();
-                       finish_wait(&edge_port->delta_msr_wait, &wait);
+                       finish_wait(&port->delta_msr_wait, &wait);
                        /* see if a signal did it */
                        if (signal_pending(current))
                                return -ERESTARTSYS;
+
+                       if (port->serial->disconnected)
+                               return -EIO;
+
                        cnow = edge_port->icount;
                        if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
                            cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
@@ -2051,7 +2053,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr)
                        icount->dcd++;
                if (newMsr & EDGEPORT_MSR_DELTA_RI)
                        icount->rng++;
-               wake_up_interruptible(&edge_port->delta_msr_wait);
+               wake_up_interruptible(&edge_port->port->delta_msr_wait);
        }
 
        /* Save the new modem status */
index c23776679f7029a37598e5cea826060670be7e64..7777172206de1b42a971acb0747d97180230d670 100644 (file)
@@ -87,9 +87,6 @@ struct edgeport_port {
        int close_pending;
        int lsr_event;
        struct async_icount     icount;
-       wait_queue_head_t       delta_msr_wait; /* for handling sleeping while
-                                                  waiting for msr change to
-                                                  happen */
        struct edgeport_serial  *edge_serial;
        struct usb_serial_port  *port;
        __u8 bUartMode;         /* Port type, 0: RS232, etc. */
@@ -1459,7 +1456,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr)
                        icount->dcd++;
                if (msr & EDGEPORT_MSR_DELTA_RI)
                        icount->rng++;
-               wake_up_interruptible(&edge_port->delta_msr_wait);
+               wake_up_interruptible(&edge_port->port->delta_msr_wait);
        }
 
        /* Save the new modem status */
@@ -1754,7 +1751,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port)
        dev = port->serial->dev;
 
        memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount));
-       init_waitqueue_head(&edge_port->delta_msr_wait);
 
        /* turn off loopback */
        status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0);
@@ -2434,10 +2430,14 @@ static int edge_ioctl(struct tty_struct *tty,
                dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);
                cprev = edge_port->icount;
                while (1) {
-                       interruptible_sleep_on(&edge_port->delta_msr_wait);
+                       interruptible_sleep_on(&port->delta_msr_wait);
                        /* see if a signal did it */
                        if (signal_pending(current))
                                return -ERESTARTSYS;
+
+                       if (port->serial->disconnected)
+                               return -EIO;
+
                        cnow = edge_port->icount;
                        if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
                            cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
@@ -2649,6 +2649,7 @@ static struct usb_serial_driver edgeport_2port_device = {
        .set_termios            = edge_set_termios,
        .tiocmget               = edge_tiocmget,
        .tiocmset               = edge_tiocmset,
+       .get_icount             = edge_get_icount,
        .write                  = edge_write,
        .write_room             = edge_write_room,
        .chars_in_buffer        = edge_chars_in_buffer,
index a64d420f687b0a198ded7bac0cd38a17b89494c0..06d5a60be2c4cb87279744372edef4a41864b74b 100644 (file)
@@ -114,8 +114,6 @@ struct mct_u232_private {
        unsigned char        last_msr;      /* Modem Status Register */
        unsigned int         rx_flags;      /* Throttling flags */
        struct async_icount  icount;
-       wait_queue_head_t    msr_wait;  /* for handling sleeping while waiting
-                                               for msr change to happen */
 };
 
 #define THROTTLED              0x01
@@ -409,7 +407,6 @@ static int mct_u232_port_probe(struct usb_serial_port *port)
                return -ENOMEM;
 
        spin_lock_init(&priv->lock);
-       init_waitqueue_head(&priv->msr_wait);
 
        usb_set_serial_port_data(port, priv);
 
@@ -601,7 +598,7 @@ static void mct_u232_read_int_callback(struct urb *urb)
                tty_kref_put(tty);
        }
 #endif
-       wake_up_interruptible(&priv->msr_wait);
+       wake_up_interruptible(&port->delta_msr_wait);
        spin_unlock_irqrestore(&priv->lock, flags);
 exit:
        retval = usb_submit_urb(urb, GFP_ATOMIC);
@@ -810,13 +807,17 @@ static int  mct_u232_ioctl(struct tty_struct *tty,
                cprev = mct_u232_port->icount;
                spin_unlock_irqrestore(&mct_u232_port->lock, flags);
                for ( ; ; ) {
-                       prepare_to_wait(&mct_u232_port->msr_wait,
+                       prepare_to_wait(&port->delta_msr_wait,
                                        &wait, TASK_INTERRUPTIBLE);
                        schedule();
-                       finish_wait(&mct_u232_port->msr_wait, &wait);
+                       finish_wait(&port->delta_msr_wait, &wait);
                        /* see if a signal did it */
                        if (signal_pending(current))
                                return -ERESTARTSYS;
+
+                       if (port->serial->disconnected)
+                               return -EIO;
+
                        spin_lock_irqsave(&mct_u232_port->lock, flags);
                        cnow = mct_u232_port->icount;
                        spin_unlock_irqrestore(&mct_u232_port->lock, flags);
index 809fb329eca5f945d13c25e75f74bf79145389df..b8051fa61911a54a23de8f9a1662518181b6c084 100644 (file)
@@ -219,7 +219,6 @@ struct moschip_port {
        char open;
        char open_ports;
        wait_queue_head_t wait_chase;   /* for handling sleeping while waiting for chase to finish */
-       wait_queue_head_t delta_msr_wait;       /* for handling sleeping while waiting for msr change to happen */
        int delta_msr_cond;
        struct async_icount icount;
        struct usb_serial_port *port;   /* loop back to the owner of this object */
@@ -423,6 +422,9 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr)
                        icount->rng++;
                        smp_wmb();
                }
+
+               mos7840_port->delta_msr_cond = 1;
+               wake_up_interruptible(&port->port->delta_msr_wait);
        }
 }
 
@@ -1127,7 +1129,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port)
 
        /* initialize our wait queues */
        init_waitqueue_head(&mos7840_port->wait_chase);
-       init_waitqueue_head(&mos7840_port->delta_msr_wait);
 
        /* initialize our icount structure */
        memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount));
@@ -2017,8 +2018,6 @@ static void mos7840_change_port_settings(struct tty_struct *tty,
                        mos7840_port->read_urb_busy = false;
                }
        }
-       wake_up(&mos7840_port->delta_msr_wait);
-       mos7840_port->delta_msr_cond = 1;
        dev_dbg(&port->dev, "%s - mos7840_port->shadowLCR is End %x\n", __func__,
                mos7840_port->shadowLCR);
 }
@@ -2219,13 +2218,18 @@ static int mos7840_ioctl(struct tty_struct *tty,
                while (1) {
                        /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */
                        mos7840_port->delta_msr_cond = 0;
-                       wait_event_interruptible(mos7840_port->delta_msr_wait,
-                                                (mos7840_port->
+                       wait_event_interruptible(port->delta_msr_wait,
+                                                (port->serial->disconnected ||
+                                                 mos7840_port->
                                                  delta_msr_cond == 1));
 
                        /* see if a signal did it */
                        if (signal_pending(current))
                                return -ERESTARTSYS;
+
+                       if (port->serial->disconnected)
+                               return -EIO;
+
                        cnow = mos7840_port->icount;
                        smp_rmb();
                        if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
index f7d339d8187bd690b86b22ccf85b740781257226..558adfc05007dbdf46f2dc9a5280579b3cdbdab2 100644 (file)
@@ -341,6 +341,8 @@ static void option_instat_callback(struct urb *urb);
 #define CINTERION_PRODUCT_EU3_E                        0x0051
 #define CINTERION_PRODUCT_EU3_P                        0x0052
 #define CINTERION_PRODUCT_PH8                  0x0053
+#define CINTERION_PRODUCT_AH6                  0x0055
+#define CINTERION_PRODUCT_PLS8                 0x0060
 
 /* Olivetti products */
 #define OLIVETTI_VENDOR_ID                     0x0b3c
@@ -579,6 +581,7 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(QUANTA_VENDOR_ID, 0xea42),
                .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c05, USB_CLASS_COMM, 0x02, 0xff) },
+       { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c1f, USB_CLASS_COMM, 0x02, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff),
                .driver_info = (kernel_ulong_t) &net_intf1_blacklist },
@@ -1260,6 +1263,8 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) },
+       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AH6) },
+       { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLS8) },
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, 
        { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) },
        { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) },
index a958fd41b5b312a699b5d963d8db1a49ea56810b..87c71ccfee87bfd06d41034a52a6e5dc27a21c7f 100644 (file)
@@ -188,7 +188,6 @@ struct oti6858_private {
        u8 setup_done;
        struct delayed_work delayed_setup_work;
 
-       wait_queue_head_t intr_wait;
        struct usb_serial_port *port;   /* USB port with which associated */
 };
 
@@ -339,7 +338,6 @@ static int oti6858_port_probe(struct usb_serial_port *port)
                return -ENOMEM;
 
        spin_lock_init(&priv->lock);
-       init_waitqueue_head(&priv->intr_wait);
        priv->port = port;
        INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line);
        INIT_DELAYED_WORK(&priv->delayed_write_work, send_data);
@@ -664,11 +662,15 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        spin_unlock_irqrestore(&priv->lock, flags);
 
        while (1) {
-               wait_event_interruptible(priv->intr_wait,
+               wait_event_interruptible(port->delta_msr_wait,
+                                       port->serial->disconnected ||
                                        priv->status.pin_state != prev);
                if (signal_pending(current))
                        return -ERESTARTSYS;
 
+               if (port->serial->disconnected)
+                       return -EIO;
+
                spin_lock_irqsave(&priv->lock, flags);
                status = priv->status.pin_state & PIN_MASK;
                spin_unlock_irqrestore(&priv->lock, flags);
@@ -763,7 +765,7 @@ static void oti6858_read_int_callback(struct urb *urb)
 
                if (!priv->transient) {
                        if (xs->pin_state != priv->status.pin_state)
-                               wake_up_interruptible(&priv->intr_wait);
+                               wake_up_interruptible(&port->delta_msr_wait);
                        memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE);
                }
 
index 54adc9125e5c1e9eb29b37573433e0d6324dce0e..3b10018d89a34e44e03b5ffb5562c34c7e4e6b85 100644 (file)
@@ -139,7 +139,6 @@ struct pl2303_serial_private {
 
 struct pl2303_private {
        spinlock_t lock;
-       wait_queue_head_t delta_msr_wait;
        u8 line_control;
        u8 line_status;
 };
@@ -233,7 +232,6 @@ static int pl2303_port_probe(struct usb_serial_port *port)
                return -ENOMEM;
 
        spin_lock_init(&priv->lock);
-       init_waitqueue_head(&priv->delta_msr_wait);
 
        usb_set_serial_port_data(port, priv);
 
@@ -607,11 +605,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        spin_unlock_irqrestore(&priv->lock, flags);
 
        while (1) {
-               interruptible_sleep_on(&priv->delta_msr_wait);
+               interruptible_sleep_on(&port->delta_msr_wait);
                /* see if a signal did it */
                if (signal_pending(current))
                        return -ERESTARTSYS;
 
+               if (port->serial->disconnected)
+                       return -EIO;
+
                spin_lock_irqsave(&priv->lock, flags);
                status = priv->line_status;
                spin_unlock_irqrestore(&priv->lock, flags);
@@ -719,7 +720,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port,
        spin_unlock_irqrestore(&priv->lock, flags);
        if (priv->line_status & UART_BREAK_ERROR)
                usb_serial_handle_break(port);
-       wake_up_interruptible(&priv->delta_msr_wait);
+       wake_up_interruptible(&port->delta_msr_wait);
 
        tty = tty_port_tty_get(&port->port);
        if (!tty)
@@ -783,7 +784,7 @@ static void pl2303_process_read_urb(struct urb *urb)
        line_status = priv->line_status;
        priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
        spin_unlock_irqrestore(&priv->lock, flags);
-       wake_up_interruptible(&priv->delta_msr_wait);
+       wake_up_interruptible(&port->delta_msr_wait);
 
        if (!urb->actual_length)
                return;
index 9b1b96f2d0955d8d8e98a284bf0fda6123c6c900..31f81c3c15eb780a10eccaa3b937cebb9f713df3 100644 (file)
@@ -69,6 +69,7 @@ static struct usb_device_id id_table[] = {
        { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) },  /* NMEA */
        { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) },  /* WMC */
        { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) },  /* DIAG */
+       { USB_DEVICE_AND_INTERFACE_INFO(0x1fac, 0x0151, 0xff, 0xff, 0xff) },
        { },
 };
 MODULE_DEVICE_TABLE(usb, id_table);
index 24662547dc5b2e60ffc51abc846e930e0afc1182..59b32b7821264d6d02b34fe4df881496ebf271b2 100644 (file)
@@ -197,12 +197,15 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id)
 
        if (is_gobi1k) {
                /* Gobi 1K USB layout:
-                * 0: serial port (doesn't respond)
+                * 0: DM/DIAG (use libqcdm from ModemManager for communication)
                 * 1: serial port (doesn't respond)
                 * 2: AT-capable modem port
                 * 3: QMI/net
                 */
-               if (ifnum == 2)
+               if (ifnum == 0) {
+                       dev_dbg(dev, "Gobi 1K DM/DIAG interface found\n");
+                       altsetting = 1;
+               } else if (ifnum == 2)
                        dev_dbg(dev, "Modem port found\n");
                else
                        altsetting = -1;
index 00e6c9bac8a309b0df675903654ce0521f991cad..75f125ddb0c94136da28ebf5fa5d4e4200a0b410 100644 (file)
@@ -128,7 +128,6 @@ struct qt2_port_private {
        u8          shadowLSR;
        u8          shadowMSR;
 
-       wait_queue_head_t   delta_msr_wait; /* Used for TIOCMIWAIT */
        struct async_icount icount;
 
        struct usb_serial_port *port;
@@ -506,8 +505,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        spin_unlock_irqrestore(&priv->lock, flags);
 
        while (1) {
-               wait_event_interruptible(priv->delta_msr_wait,
-                                        ((priv->icount.rng != prev.rng) ||
+               wait_event_interruptible(port->delta_msr_wait,
+                                        (port->serial->disconnected ||
+                                         (priv->icount.rng != prev.rng) ||
                                          (priv->icount.dsr != prev.dsr) ||
                                          (priv->icount.dcd != prev.dcd) ||
                                          (priv->icount.cts != prev.cts)));
@@ -515,6 +515,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
                if (signal_pending(current))
                        return -ERESTARTSYS;
 
+               if (port->serial->disconnected)
+                       return -EIO;
+
                spin_lock_irqsave(&priv->lock, flags);
                cur = priv->icount;
                spin_unlock_irqrestore(&priv->lock, flags);
@@ -661,7 +664,9 @@ void qt2_process_read_urb(struct urb *urb)
                                                 __func__);
                                        break;
                                }
-                               tty_flip_buffer_push(&port->port);
+
+                               if (port_priv->is_open)
+                                       tty_flip_buffer_push(&port->port);
 
                                newport = *(ch + 3);
 
@@ -704,7 +709,8 @@ void qt2_process_read_urb(struct urb *urb)
                tty_insert_flip_string(&port->port, ch, 1);
        }
 
-       tty_flip_buffer_push(&port->port);
+       if (port_priv->is_open)
+               tty_flip_buffer_push(&port->port);
 }
 
 static void qt2_write_bulk_callback(struct urb *urb)
@@ -824,7 +830,6 @@ static int qt2_port_probe(struct usb_serial_port *port)
 
        spin_lock_init(&port_priv->lock);
        spin_lock_init(&port_priv->urb_lock);
-       init_waitqueue_head(&port_priv->delta_msr_wait);
        port_priv->port = port;
 
        port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL);
@@ -967,7 +972,7 @@ static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch)
                if (newMSR & UART_MSR_TERI)
                        port_priv->icount.rng++;
 
-               wake_up_interruptible(&port_priv->delta_msr_wait);
+               wake_up_interruptible(&port->delta_msr_wait);
        }
 }
 
index 91ff8e3bddbd76a4daa3502d17dd2aaab96ac154..549ef68ff5fa2ea156fa31ea65f3b823353b1cfa 100644 (file)
@@ -149,7 +149,6 @@ enum spcp8x5_type {
 struct spcp8x5_private {
        spinlock_t      lock;
        enum spcp8x5_type       type;
-       wait_queue_head_t       delta_msr_wait;
        u8                      line_control;
        u8                      line_status;
 };
@@ -179,7 +178,6 @@ static int spcp8x5_port_probe(struct usb_serial_port *port)
                return -ENOMEM;
 
        spin_lock_init(&priv->lock);
-       init_waitqueue_head(&priv->delta_msr_wait);
        priv->type = type;
 
        usb_set_serial_port_data(port , priv);
@@ -475,7 +473,7 @@ static void spcp8x5_process_read_urb(struct urb *urb)
        priv->line_status &= ~UART_STATE_TRANSIENT_MASK;
        spin_unlock_irqrestore(&priv->lock, flags);
        /* wake up the wait for termios */
-       wake_up_interruptible(&priv->delta_msr_wait);
+       wake_up_interruptible(&port->delta_msr_wait);
 
        if (!urb->actual_length)
                return;
@@ -526,12 +524,15 @@ static int spcp8x5_wait_modem_info(struct usb_serial_port *port,
 
        while (1) {
                /* wake up in bulk read */
-               interruptible_sleep_on(&priv->delta_msr_wait);
+               interruptible_sleep_on(&port->delta_msr_wait);
 
                /* see if a signal did it */
                if (signal_pending(current))
                        return -ERESTARTSYS;
 
+               if (port->serial->disconnected)
+                       return -EIO;
+
                spin_lock_irqsave(&priv->lock, flags);
                status = priv->line_status;
                spin_unlock_irqrestore(&priv->lock, flags);
index b57cf841c5b6aa2ab1c21e13c12e063d51a2a9e7..4b2a19757b4d531baa8dfb48c8009517d2d21cb5 100644 (file)
@@ -61,7 +61,6 @@ struct ssu100_port_private {
        spinlock_t status_lock;
        u8 shadowLSR;
        u8 shadowMSR;
-       wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */
        struct async_icount icount;
 };
 
@@ -355,8 +354,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
        spin_unlock_irqrestore(&priv->status_lock, flags);
 
        while (1) {
-               wait_event_interruptible(priv->delta_msr_wait,
-                                        ((priv->icount.rng != prev.rng) ||
+               wait_event_interruptible(port->delta_msr_wait,
+                                        (port->serial->disconnected ||
+                                         (priv->icount.rng != prev.rng) ||
                                          (priv->icount.dsr != prev.dsr) ||
                                          (priv->icount.dcd != prev.dcd) ||
                                          (priv->icount.cts != prev.cts)));
@@ -364,6 +364,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
                if (signal_pending(current))
                        return -ERESTARTSYS;
 
+               if (port->serial->disconnected)
+                       return -EIO;
+
                spin_lock_irqsave(&priv->status_lock, flags);
                cur = priv->icount;
                spin_unlock_irqrestore(&priv->status_lock, flags);
@@ -445,7 +448,6 @@ static int ssu100_port_probe(struct usb_serial_port *port)
                return -ENOMEM;
 
        spin_lock_init(&priv->status_lock);
-       init_waitqueue_head(&priv->delta_msr_wait);
 
        usb_set_serial_port_data(port, priv);
 
@@ -537,7 +539,7 @@ static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)
                        priv->icount.dcd++;
                if (msr & UART_MSR_TERI)
                        priv->icount.rng++;
-               wake_up_interruptible(&priv->delta_msr_wait);
+               wake_up_interruptible(&port->delta_msr_wait);
        }
 }
 
index 39cb9b807c3cf998842c39267e9d217b82460e59..73deb029fc05d3d9c9b728f1fae1616a8efee6e4 100644 (file)
@@ -74,7 +74,6 @@ struct ti_port {
        int                     tp_flags;
        int                     tp_closing_wait;/* in .01 secs */
        struct async_icount     tp_icount;
-       wait_queue_head_t       tp_msr_wait;    /* wait for msr change */
        wait_queue_head_t       tp_write_wait;
        struct ti_device        *tp_tdev;
        struct usb_serial_port  *tp_port;
@@ -432,7 +431,6 @@ static int ti_port_probe(struct usb_serial_port *port)
        else
                tport->tp_uart_base_addr = TI_UART2_BASE_ADDR;
        tport->tp_closing_wait = closing_wait;
-       init_waitqueue_head(&tport->tp_msr_wait);
        init_waitqueue_head(&tport->tp_write_wait);
        if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) {
                kfree(tport);
@@ -784,9 +782,13 @@ static int ti_ioctl(struct tty_struct *tty,
                dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__);
                cprev = tport->tp_icount;
                while (1) {
-                       interruptible_sleep_on(&tport->tp_msr_wait);
+                       interruptible_sleep_on(&port->delta_msr_wait);
                        if (signal_pending(current))
                                return -ERESTARTSYS;
+
+                       if (port->serial->disconnected)
+                               return -EIO;
+
                        cnow = tport->tp_icount;
                        if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
                            cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
@@ -1392,7 +1394,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr)
                        icount->dcd++;
                if (msr & TI_MSR_DELTA_RI)
                        icount->rng++;
-               wake_up_interruptible(&tport->tp_msr_wait);
+               wake_up_interruptible(&tport->tp_port->delta_msr_wait);
                spin_unlock_irqrestore(&tport->tp_lock, flags);
        }
 
index a19ed74d770d73b016e69070cb27e282bbc21fad..5d9b178484fdf805bfd9a6e264732d5082216088 100644 (file)
@@ -151,6 +151,7 @@ static void destroy_serial(struct kref *kref)
                }
        }
 
+       usb_put_intf(serial->interface);
        usb_put_dev(serial->dev);
        kfree(serial);
 }
@@ -620,7 +621,7 @@ static struct usb_serial *create_serial(struct usb_device *dev,
        }
        serial->dev = usb_get_dev(dev);
        serial->type = driver;
-       serial->interface = interface;
+       serial->interface = usb_get_intf(interface);
        kref_init(&serial->kref);
        mutex_init(&serial->disc_mutex);
        serial->minor = SERIAL_TTY_NO_MINOR;
@@ -902,6 +903,7 @@ static int usb_serial_probe(struct usb_interface *interface,
                port->port.ops = &serial_port_ops;
                port->serial = serial;
                spin_lock_init(&port->lock);
+               init_waitqueue_head(&port->delta_msr_wait);
                /* Keep this for private driver use for the moment but
                   should probably go away */
                INIT_WORK(&port->work, usb_serial_port_work);
index 7ab9046ae0eca5fe64ea930206c18a7cdeda1420..105d900150c1a80155c2afcec6a61f4fb07fd0b4 100644 (file)
@@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us)
        return 0;
 }
 
-/* This places the HUAWEI usb dongles in multi-port mode */
-static int usb_stor_huawei_feature_init(struct us_data *us)
+/* This places the HUAWEI E220 devices in multi-port mode */
+int usb_stor_huawei_e220_init(struct us_data *us)
 {
        int result;
 
@@ -104,75 +104,3 @@ static int usb_stor_huawei_feature_init(struct us_data *us)
        US_DEBUGP("Huawei mode set result is %d\n", result);
        return 0;
 }
-
-/*
- * It will send a scsi switch command called rewind' to huawei dongle.
- * When the dongle receives this command at the first time,
- * it will reboot immediately. After rebooted, it will ignore this command.
- * So it is  unnecessary to read its response.
- */
-static int usb_stor_huawei_scsi_init(struct us_data *us)
-{
-       int result = 0;
-       int act_len = 0;
-       struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf;
-       char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00,
-                       0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-       bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN);
-       bcbw->Tag = 0;
-       bcbw->DataTransferLength = 0;
-       bcbw->Flags = bcbw->Lun = 0;
-       bcbw->Length = sizeof(rewind_cmd);
-       memset(bcbw->CDB, 0, sizeof(bcbw->CDB));
-       memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd));
-
-       result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw,
-                                       US_BULK_CB_WRAP_LEN, &act_len);
-       US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result);
-       return result;
-}
-
-/*
- * It tries to find the supported Huawei USB dongles.
- * In Huawei, they assign the following product IDs
- * for all of their mobile broadband dongles,
- * including the new dongles in the future.
- * So if the product ID is not included in this list,
- * it means it is not Huawei's mobile broadband dongles.
- */
-static int usb_stor_huawei_dongles_pid(struct us_data *us)
-{
-       struct usb_interface_descriptor *idesc;
-       int idProduct;
-
-       idesc = &us->pusb_intf->cur_altsetting->desc;
-       idProduct = le16_to_cpu(us->pusb_dev->descriptor.idProduct);
-       /* The first port is CDROM,
-        * means the dongle in the single port mode,
-        * and a switch command is required to be sent. */
-       if (idesc && idesc->bInterfaceNumber == 0) {
-               if ((idProduct == 0x1001)
-                       || (idProduct == 0x1003)
-                       || (idProduct == 0x1004)
-                       || (idProduct >= 0x1401 && idProduct <= 0x1500)
-                       || (idProduct >= 0x1505 && idProduct <= 0x1600)
-                       || (idProduct >= 0x1c02 && idProduct <= 0x2202)) {
-                       return 1;
-               }
-       }
-       return 0;
-}
-
-int usb_stor_huawei_init(struct us_data *us)
-{
-       int result = 0;
-
-       if (usb_stor_huawei_dongles_pid(us)) {
-               if (le16_to_cpu(us->pusb_dev->descriptor.idProduct) >= 0x1446)
-                       result = usb_stor_huawei_scsi_init(us);
-               else
-                       result = usb_stor_huawei_feature_init(us);
-       }
-       return result;
-}
index 5376d4fc76f04c25092244765237f94f44456ba1..529327fbb06be1b6876e8802b84bd281287291c3 100644 (file)
@@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us);
  * flash reader */
 int usb_stor_ucr61s2b_init(struct us_data *us);
 
-/* This places the HUAWEI usb dongles in multi-port mode */
-int usb_stor_huawei_init(struct us_data *us);
+/* This places the HUAWEI E220 devices in multi-port mode */
+int usb_stor_huawei_e220_init(struct us_data *us);
index 72923b56bbf6b871a6da926168d43cf8db3e6383..1799335288bd5e60522a60def1c311f07df62286 100644 (file)
  * as opposed to devices that do something strangely or wrongly.
  */
 
+/* In-kernel mode switching is deprecated.  Do not add new devices to
+ * this list for the sole purpose of switching them to a different
+ * mode.  Existing userspace solutions are superior.
+ *
+ * New mode switching devices should instead be added to the database
+ * maintained at http://www.draisberghof.de/usb_modeswitch/
+ */
+
 #if !defined(CONFIG_USB_STORAGE_SDDR09) && \
                !defined(CONFIG_USB_STORAGE_SDDR09_MODULE)
 #define NO_SDDR09
@@ -488,6 +496,13 @@ UNUSUAL_DEV(  0x04e8, 0x5122, 0x0000, 0x9999,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG),
 
+/* Added by Dmitry Artamonow <mad_soft@inbox.ru> */
+UNUSUAL_DEV(  0x04e8, 0x5136, 0x0000, 0x9999,
+               "Samsung",
+               "YP-Z3",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_MAX_SECTORS_64),
+
 /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>.
  * Device uses standards-violating 32-byte Bulk Command Block Wrappers and
  * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011.
@@ -1527,10 +1542,335 @@ UNUSUAL_DEV(  0x1210, 0x0003, 0x0100, 0x0100,
 /* Reported by fangxiaozhi <huananhu@huawei.com>
  * This brings the HUAWEI data card devices into multi-port mode
  */
-UNUSUAL_VENDOR_INTF(0x12d1, 0x08, 0x06, 0x50,
+UNUSUAL_DEV(  0x12d1, 0x1001, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1003, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1004, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1401, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1402, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1403, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1404, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1405, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1406, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1407, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1408, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1409, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x140A, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x140B, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x140C, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x140D, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x140E, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x140F, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1410, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1411, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1412, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1413, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1414, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1415, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1416, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1417, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1418, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1419, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x141A, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x141B, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x141C, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x141D, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x141E, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x141F, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1420, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1421, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1422, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1423, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1424, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1425, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1426, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1427, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1428, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1429, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x142A, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x142B, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x142C, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x142D, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x142E, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x142F, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1430, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1431, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1432, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1433, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1434, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1435, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1436, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1437, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1438, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x1439, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x143A, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x143B, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x143C, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x143D, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x143E, 0x0000, 0x0000,
+               "HUAWEI MOBILE",
+               "Mass Storage",
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
+               0),
+UNUSUAL_DEV(  0x12d1, 0x143F, 0x0000, 0x0000,
                "HUAWEI MOBILE",
                "Mass Storage",
-               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_init,
+               USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init,
                0),
 
 /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
index 964ff22bf2819e5de87786e517fefe2bc50956af..aeb00fc2d3bea2caf19a650d30e4517caf89a76d 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/pci.h>
 #include <linux/uaccess.h>
 #include <linux/vfio.h>
+#include <linux/slab.h>
 
 #include "vfio_pci_private.h"
 
index 3639371fa697e63e9bf6d3e5ccc49453e5ecff76..a96509187deb677a03e0a7e4902d76fe1f3c81a5 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/vfio.h>
 #include <linux/wait.h>
 #include <linux/workqueue.h>
+#include <linux/slab.h>
 
 #include "vfio_pci_private.h"
 
index 959b1cd89e6a5be5a402a79089077609f8e30716..ec6fb3fa59bb5962281bb6277220941b91df053c 100644 (file)
@@ -339,7 +339,8 @@ static void handle_tx(struct vhost_net *net)
                                msg.msg_controllen = 0;
                                ubufs = NULL;
                        } else {
-                               struct ubuf_info *ubuf = &vq->ubuf_info[head];
+                               struct ubuf_info *ubuf;
+                               ubuf = vq->ubuf_info + vq->upend_idx;
 
                                vq->heads[vq->upend_idx].len =
                                        VHOST_DMA_IN_PROGRESS;
index 9951297b24279105aa118c1e9bba1c0320972a15..2968b4934659aab01dd626334a9ab7fc0e607383 100644 (file)
@@ -60,6 +60,15 @@ enum {
        VHOST_SCSI_VQ_IO = 2,
 };
 
+/*
+ * VIRTIO_RING_F_EVENT_IDX seems broken. Not sure the bug is in
+ * kernel but disabling it helps.
+ * TODO: debug and remove the workaround.
+ */
+enum {
+       VHOST_SCSI_FEATURES = VHOST_FEATURES & (~VIRTIO_RING_F_EVENT_IDX)
+};
+
 #define VHOST_SCSI_MAX_TARGET  256
 #define VHOST_SCSI_MAX_VQ      128
 
@@ -850,7 +859,7 @@ static int vhost_scsi_clear_endpoint(
        for (index = 0; index < vs->dev.nvqs; ++index) {
                if (!vhost_vq_access_ok(&vs->vqs[index])) {
                        ret = -EFAULT;
-                       goto err;
+                       goto err_dev;
                }
        }
        for (i = 0; i < VHOST_SCSI_MAX_TARGET; i++) {
@@ -860,10 +869,11 @@ static int vhost_scsi_clear_endpoint(
                if (!tv_tpg)
                        continue;
 
+               mutex_lock(&tv_tpg->tv_tpg_mutex);
                tv_tport = tv_tpg->tport;
                if (!tv_tport) {
                        ret = -ENODEV;
-                       goto err;
+                       goto err_tpg;
                }
 
                if (strcmp(tv_tport->tport_name, t->vhost_wwpn)) {
@@ -872,16 +882,19 @@ static int vhost_scsi_clear_endpoint(
                                tv_tport->tport_name, tv_tpg->tport_tpgt,
                                t->vhost_wwpn, t->vhost_tpgt);
                        ret = -EINVAL;
-                       goto err;
+                       goto err_tpg;
                }
                tv_tpg->tv_tpg_vhost_count--;
                vs->vs_tpg[target] = NULL;
                vs->vs_endpoint = false;
+               mutex_unlock(&tv_tpg->tv_tpg_mutex);
        }
        mutex_unlock(&vs->dev.mutex);
        return 0;
 
-err:
+err_tpg:
+       mutex_unlock(&tv_tpg->tv_tpg_mutex);
+err_dev:
        mutex_unlock(&vs->dev.mutex);
        return ret;
 }
@@ -937,11 +950,12 @@ static void vhost_scsi_flush(struct vhost_scsi *vs)
 
        for (i = 0; i < VHOST_SCSI_MAX_VQ; i++)
                vhost_scsi_flush_vq(vs, i);
+       vhost_work_flush(&vs->dev, &vs->vs_completion_work);
 }
 
 static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features)
 {
-       if (features & ~VHOST_FEATURES)
+       if (features & ~VHOST_SCSI_FEATURES)
                return -EOPNOTSUPP;
 
        mutex_lock(&vs->dev.mutex);
@@ -987,7 +1001,7 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl,
                        return -EFAULT;
                return 0;
        case VHOST_GET_FEATURES:
-               features = VHOST_FEATURES;
+               features = VHOST_SCSI_FEATURES;
                if (copy_to_user(featurep, &features, sizeof features))
                        return -EFAULT;
                return 0;
index 12cf5f31ee8f008158dfbee172b077185f3ef241..c1a2914447e14c4aef834a9e23fc70d6ad49377b 100644 (file)
 #define ATMEL_LCDC_DMA_BURST_LEN       8       /* words */
 #define ATMEL_LCDC_FIFO_SIZE           512     /* words */
 
+struct atmel_lcdfb_config {
+       bool have_alt_pixclock;
+       bool have_hozval;
+       bool have_intensity_bit;
+};
+
+static struct atmel_lcdfb_config at91sam9261_config = {
+       .have_hozval            = true,
+       .have_intensity_bit     = true,
+};
+
+static struct atmel_lcdfb_config at91sam9263_config = {
+       .have_intensity_bit     = true,
+};
+
+static struct atmel_lcdfb_config at91sam9g10_config = {
+       .have_hozval            = true,
+};
+
+static struct atmel_lcdfb_config at91sam9g45_config = {
+       .have_alt_pixclock      = true,
+};
+
+static struct atmel_lcdfb_config at91sam9g45es_config = {
+};
+
+static struct atmel_lcdfb_config at91sam9rl_config = {
+       .have_intensity_bit     = true,
+};
+
+static struct atmel_lcdfb_config at32ap_config = {
+       .have_hozval            = true,
+};
+
+static const struct platform_device_id atmel_lcdfb_devtypes[] = {
+       {
+               .name = "at91sam9261-lcdfb",
+               .driver_data = (unsigned long)&at91sam9261_config,
+       }, {
+               .name = "at91sam9263-lcdfb",
+               .driver_data = (unsigned long)&at91sam9263_config,
+       }, {
+               .name = "at91sam9g10-lcdfb",
+               .driver_data = (unsigned long)&at91sam9g10_config,
+       }, {
+               .name = "at91sam9g45-lcdfb",
+               .driver_data = (unsigned long)&at91sam9g45_config,
+       }, {
+               .name = "at91sam9g45es-lcdfb",
+               .driver_data = (unsigned long)&at91sam9g45es_config,
+       }, {
+               .name = "at91sam9rl-lcdfb",
+               .driver_data = (unsigned long)&at91sam9rl_config,
+       }, {
+               .name = "at32ap-lcdfb",
+               .driver_data = (unsigned long)&at32ap_config,
+       }, {
+               /* terminator */
+       }
+};
+
+static struct atmel_lcdfb_config *
+atmel_lcdfb_get_config(struct platform_device *pdev)
+{
+       unsigned long data;
+
+       data = platform_get_device_id(pdev)->driver_data;
+
+       return (struct atmel_lcdfb_config *)data;
+}
+
 #if defined(CONFIG_ARCH_AT91)
 #define        ATMEL_LCDFB_FBINFO_DEFAULT      (FBINFO_DEFAULT \
                                         | FBINFO_PARTIAL_PAN_OK \
@@ -193,14 +264,16 @@ static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = {
        .accel          = FB_ACCEL_NONE,
 };
 
-static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2)
+static unsigned long compute_hozval(struct atmel_lcdfb_info *sinfo,
+                                                       unsigned long xres)
 {
+       unsigned long lcdcon2;
        unsigned long value;
 
-       if (!(cpu_is_at91sam9261() || cpu_is_at91sam9g10()
-               || cpu_is_at32ap7000()))
+       if (!sinfo->config->have_hozval)
                return xres;
 
+       lcdcon2 = lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2);
        value = xres;
        if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) {
                /* STN display */
@@ -422,17 +495,22 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var,
                        = var->bits_per_pixel;
                break;
        case 16:
+               /* Older SOCs use IBGR:555 rather than BGR:565. */
+               if (sinfo->config->have_intensity_bit)
+                       var->green.length = 5;
+               else
+                       var->green.length = 6;
+
                if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) {
-                       /* RGB:565 mode */
-                       var->red.offset = 11;
+                       /* RGB:5X5 mode */
+                       var->red.offset = var->green.length + 5;
                        var->blue.offset = 0;
                } else {
-                       /* BGR:565 mode */
+                       /* BGR:5X5 mode */
                        var->red.offset = 0;
-                       var->blue.offset = 11;
+                       var->blue.offset = var->green.length + 5;
                }
                var->green.offset = 5;
-               var->green.length = 6;
                var->red.length = var->blue.length = 5;
                break;
        case 32:
@@ -526,7 +604,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
        /* Now, the LCDC core... */
 
        /* Set pixel clock */
-       if (cpu_is_at91sam9g45() && !cpu_is_at91sam9g45es())
+       if (sinfo->config->have_alt_pixclock)
                pix_factor = 1;
 
        clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000;
@@ -586,8 +664,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info)
        lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value);
 
        /* Horizontal value (aka line size) */
-       hozval_linesz = compute_hozval(info->var.xres,
-                                       lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2));
+       hozval_linesz = compute_hozval(sinfo, info->var.xres);
 
        /* Display size */
        value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET;
@@ -679,8 +756,7 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red,
 
        case FB_VISUAL_PSEUDOCOLOR:
                if (regno < 256) {
-                       if (cpu_is_at91sam9261() || cpu_is_at91sam9263()
-                           || cpu_is_at91sam9rl()) {
+                       if (sinfo->config->have_intensity_bit) {
                                /* old style I+BGR:555 */
                                val  = ((red   >> 11) & 0x001f);
                                val |= ((green >>  6) & 0x03e0);
@@ -817,15 +893,13 @@ static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo)
 
 static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo)
 {
-       if (sinfo->bus_clk)
-               clk_enable(sinfo->bus_clk);
+       clk_enable(sinfo->bus_clk);
        clk_enable(sinfo->lcdc_clk);
 }
 
 static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo)
 {
-       if (sinfo->bus_clk)
-               clk_disable(sinfo->bus_clk);
+       clk_disable(sinfo->bus_clk);
        clk_disable(sinfo->lcdc_clk);
 }
 
@@ -870,6 +944,9 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
        }
        sinfo->info = info;
        sinfo->pdev = pdev;
+       sinfo->config = atmel_lcdfb_get_config(pdev);
+       if (!sinfo->config)
+               goto free_info;
 
        strcpy(info->fix.id, sinfo->pdev->name);
        info->flags = ATMEL_LCDFB_FBINFO_DEFAULT;
@@ -880,13 +957,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev)
        info->fix = atmel_lcdfb_fix;
 
        /* Enable LCDC Clocks */
-       if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()
-        || cpu_is_at32ap7000()) {
-               sinfo->bus_clk = clk_get(dev, "hck1");
-               if (IS_ERR(sinfo->bus_clk)) {
-                       ret = PTR_ERR(sinfo->bus_clk);
-                       goto free_info;
-               }
+       sinfo->bus_clk = clk_get(dev, "hclk");
+       if (IS_ERR(sinfo->bus_clk)) {
+               ret = PTR_ERR(sinfo->bus_clk);
+               goto free_info;
        }
        sinfo->lcdc_clk = clk_get(dev, "lcdc_clk");
        if (IS_ERR(sinfo->lcdc_clk)) {
@@ -1047,8 +1121,7 @@ stop_clk:
        atmel_lcdfb_stop_clock(sinfo);
        clk_put(sinfo->lcdc_clk);
 put_bus_clk:
-       if (sinfo->bus_clk)
-               clk_put(sinfo->bus_clk);
+       clk_put(sinfo->bus_clk);
 free_info:
        framebuffer_release(info);
 out:
@@ -1073,8 +1146,7 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev)
        unregister_framebuffer(info);
        atmel_lcdfb_stop_clock(sinfo);
        clk_put(sinfo->lcdc_clk);
-       if (sinfo->bus_clk)
-               clk_put(sinfo->bus_clk);
+       clk_put(sinfo->bus_clk);
        fb_dealloc_cmap(&info->cmap);
        free_irq(sinfo->irq_base, info);
        iounmap(sinfo->mmio);
@@ -1143,7 +1215,7 @@ static struct platform_driver atmel_lcdfb_driver = {
        .remove         = __exit_p(atmel_lcdfb_remove),
        .suspend        = atmel_lcdfb_suspend,
        .resume         = atmel_lcdfb_resume,
-
+       .id_table       = atmel_lcdfb_devtypes,
        .driver         = {
                .name   = "atmel_lcdfb",
                .owner  = THIS_MODULE,
index 3f2519d3071574bd42dbe646afbf24dd1ba3d034..e06cd5d90c97806cb38c76f458c004a20b4acca0 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <linux/fb.h>
+#include <linux/io.h>
 
 #include <linux/platform_data/video-ep93xx.h>
 
index 94ad0f71383c7fa71563332b3ab0fad9276dd2ab..7f6709991a5c60d26a4b892ac24c0331cda06b58 100644 (file)
@@ -1400,7 +1400,7 @@ int fb_videomode_from_videomode(const struct videomode *vm,
        fbmode->vmode = 0;
        if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH)
                fbmode->sync |= FB_SYNC_HOR_HIGH_ACT;
-       if (vm->dmt_flags & VESA_DMT_HSYNC_HIGH)
+       if (vm->dmt_flags & VESA_DMT_VSYNC_HIGH)
                fbmode->sync |= FB_SYNC_VERT_HIGH_ACT;
        if (vm->data_flags & DISPLAY_FLAGS_INTERLACED)
                fbmode->vmode |= FB_VMODE_INTERLACED;
index 755556ca5b2d988ec68b8cc3c1f9bbe7aadf6a34..45169cbaba6e288e714e2ce414dff1061a4569af 100644 (file)
@@ -169,6 +169,7 @@ struct mxsfb_info {
        unsigned dotclk_delay;
        const struct mxsfb_devdata *devdata;
        int mapped;
+       u32 sync;
 };
 
 #define mxsfb_is_v3(host) (host->devdata->ipversion == 3)
@@ -456,9 +457,9 @@ static int mxsfb_set_par(struct fb_info *fb_info)
                vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH;
        if (fb_info->var.sync & FB_SYNC_VERT_HIGH_ACT)
                vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH;
-       if (fb_info->var.sync & FB_SYNC_DATA_ENABLE_HIGH_ACT)
+       if (host->sync & MXSFB_SYNC_DATA_ENABLE_HIGH_ACT)
                vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH;
-       if (fb_info->var.sync & FB_SYNC_DOTCLK_FAILING_ACT)
+       if (host->sync & MXSFB_SYNC_DOTCLK_FAILING_ACT)
                vdctrl0 |= VDCTRL0_DOTCLK_ACT_FAILING;
 
        writel(vdctrl0, host->base + LCDC_VDCTRL0);
@@ -861,6 +862,8 @@ static int mxsfb_probe(struct platform_device *pdev)
 
        INIT_LIST_HEAD(&fb_info->modelist);
 
+       host->sync = pdata->sync;
+
        ret = mxsfb_init_fbinfo(host);
        if (ret != 0)
                goto error_init_fb;
index ed4cad87fbcdb39717e283ed8b764312b745fff3..4a5f2cd3d3bf01a5776df21c137ce11586109689 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/lcd.h>
 #include <linux/gpio.h>
 
+#include <mach/hardware.h>
 #include <mach/board-ams-delta.h>
 
 #include "omapfb.h"
index 3aa62da89195949d89e7dd3bb4d44cc60342c7d4..7fbe04bce0ed6402371edf515641175c4d8320bf 100644 (file)
 #include <linux/platform_device.h>
 
 #include <asm/gpio.h>
+
+#include <mach/hardware.h>
 #include <mach/mux.h>
+
 #include "omapfb.h"
 
 static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev)
index e31f5b33b501e155fed50e9a5463614e9cdc1690..d40612c31a989d9437e482496ff52c6f451404d8 100644 (file)
@@ -32,6 +32,8 @@
 
 #include <linux/omap-dma.h>
 
+#include <mach/hardware.h>
+
 #include "omapfb.h"
 #include "lcdc.h"
 
index 6b6643911d296c707e7eaa29c30412081378cc5f..048c98381ef6affd36417518881b890ec1f170dd 100644 (file)
@@ -63,6 +63,9 @@ struct tpo_td043_device {
        u32 power_on_resume:1;
 };
 
+/* used to pass spi_device from SPI to DSS portion of the driver */
+static struct tpo_td043_device *g_tpo_td043;
+
 static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
 {
        struct spi_message      m;
@@ -403,7 +406,7 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev)
 
 static int tpo_td043_probe(struct omap_dss_device *dssdev)
 {
-       struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
+       struct tpo_td043_device *tpo_td043 = g_tpo_td043;
        int nreset_gpio = dssdev->reset_gpio;
        int ret = 0;
 
@@ -440,6 +443,8 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev)
        if (ret)
                dev_warn(&dssdev->dev, "failed to create sysfs files\n");
 
+       dev_set_drvdata(&dssdev->dev, tpo_td043);
+
        return 0;
 
 fail_gpio_req:
@@ -505,6 +510,9 @@ static int tpo_td043_spi_probe(struct spi_device *spi)
                return -ENODEV;
        }
 
+       if (g_tpo_td043 != NULL)
+               return -EBUSY;
+
        spi->bits_per_word = 16;
        spi->mode = SPI_MODE_0;
 
@@ -521,7 +529,7 @@ static int tpo_td043_spi_probe(struct spi_device *spi)
        tpo_td043->spi = spi;
        tpo_td043->nreset_gpio = dssdev->reset_gpio;
        dev_set_drvdata(&spi->dev, tpo_td043);
-       dev_set_drvdata(&dssdev->dev, tpo_td043);
+       g_tpo_td043 = tpo_td043;
 
        omap_dss_register_driver(&tpo_td043_driver);
 
@@ -534,6 +542,7 @@ static int tpo_td043_spi_remove(struct spi_device *spi)
 
        omap_dss_unregister_driver(&tpo_td043_driver);
        kfree(tpo_td043);
+       g_tpo_td043 = NULL;
 
        return 0;
 }
index d7d66ef5cb58098c6f80268651c0a277957fc2e0..7f791aeda4d24a1025e4d712f11e1b828cdb8b24 100644 (file)
@@ -202,12 +202,10 @@ static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = {
 
 static const enum omap_dss_output_id omap4_dss_supported_outputs[] = {
        /* OMAP_DSS_CHANNEL_LCD */
-       OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
-       OMAP_DSS_OUTPUT_DSI1,
+       OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1,
 
        /* OMAP_DSS_CHANNEL_DIGIT */
-       OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI |
-       OMAP_DSS_OUTPUT_DPI,
+       OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI,
 
        /* OMAP_DSS_CHANNEL_LCD2 */
        OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI |
index 63203acef812211cb17788454116fcbe77debdd7..0264704a52be3d9e02b23178e489b2e567ec4c56 100644 (file)
@@ -858,6 +858,7 @@ static void sh_mobile_lcdc_geometry(struct sh_mobile_lcdc_chan *ch)
        tmp = ((mode->xres & 7) << 24) | ((display_h_total & 7) << 16)
            | ((mode->hsync_len & 7) << 8) | (hsync_pos & 7);
        lcdc_write_chan(ch, LDHAJR, tmp);
+       lcdc_write_chan_mirror(ch, LDHAJR, tmp);
 }
 
 static void sh_mobile_lcdc_overlay_setup(struct sh_mobile_lcdc_overlay *ovl)
index b75db01864883e5fea61f63cc95e3df35e749ea2..d4284458377e80103d230524d573e10e63b2ac14 100644 (file)
@@ -1973,7 +1973,8 @@ static int uvesafb_init(void)
                        err = -ENOMEM;
 
                if (err) {
-                       platform_device_put(uvesafb_device);
+                       if (uvesafb_device)
+                               platform_device_put(uvesafb_device);
                        platform_driver_unregister(&uvesafb_driver);
                        cn_del_callback(&uvesafb_cn_id);
                        return err;
index d39dfa4cc23570b9c6cc8e57e7aa3a8d759a007b..46d97014342ef1f27f37046332e35d6e40a5b108 100644 (file)
@@ -47,11 +47,13 @@ static u8 w1_gpio_read_bit(void *data)
        return gpio_get_value(pdata->pin) ? 1 : 0;
 }
 
+#if defined(CONFIG_OF)
 static struct of_device_id w1_gpio_dt_ids[] = {
        { .compatible = "w1-gpio" },
        {}
 };
 MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids);
+#endif
 
 static int w1_gpio_probe_dt(struct platform_device *pdev)
 {
@@ -158,7 +160,7 @@ static int w1_gpio_probe(struct platform_device *pdev)
        return err;
 }
 
-static int __exit w1_gpio_remove(struct platform_device *pdev)
+static int w1_gpio_remove(struct platform_device *pdev)
 {
        struct w1_bus_master *master = platform_get_drvdata(pdev);
        struct w1_gpio_platform_data *pdata = pdev->dev.platform_data;
@@ -210,7 +212,7 @@ static struct platform_driver w1_gpio_driver = {
                .of_match_table = of_match_ptr(w1_gpio_dt_ids),
        },
        .probe = w1_gpio_probe,
-       .remove = __exit_p(w1_gpio_remove),
+       .remove = w1_gpio_remove,
        .suspend = w1_gpio_suspend,
        .resume = w1_gpio_resume,
 };
index 7994d933f040bd85ef9f26dfee1587c38e37cba5..7ce277d2bb676182dcbcddae1f500a77ae038842 100644 (file)
@@ -924,7 +924,8 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb
                        tmp64 = (triplet_ret >> 2);
                        rn |= (tmp64 << i);
 
-                       if (kthread_should_stop()) {
+                       /* ensure we're called from kthread and not by netlink callback */
+                       if (!dev->priv && kthread_should_stop()) {
                                mutex_unlock(&dev->bus_mutex);
                                dev_dbg(&dev->dev, "Abort w1_search\n");
                                return;
index e3b8f757d2d3f641810cece7a0423fa268cf2b88..0e9d8c479c3551e2bb5a51cb9bfcd055f2bcb3e7 100644 (file)
 #include "sp5100_tco.h"
 
 /* Module and version information */
-#define TCO_VERSION "0.03"
+#define TCO_VERSION "0.05"
 #define TCO_MODULE_NAME "SP5100 TCO timer"
 #define TCO_DRIVER_NAME   TCO_MODULE_NAME ", v" TCO_VERSION
 
 /* internal variables */
 static u32 tcobase_phys;
-static u32 resbase_phys;
 static u32 tco_wdt_fired;
 static void __iomem *tcobase;
 static unsigned int pm_iobase;
@@ -54,10 +53,6 @@ static DEFINE_SPINLOCK(tco_lock);    /* Guards the hardware */
 static unsigned long timer_alive;
 static char tco_expect_close;
 static struct pci_dev *sp5100_tco_pci;
-static struct resource wdt_res = {
-       .name = "Watchdog Timer",
-       .flags = IORESOURCE_MEM,
-};
 
 /* the watchdog platform device */
 static struct platform_device *sp5100_tco_platform_device;
@@ -75,12 +70,6 @@ module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started."
                " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-static unsigned int force_addr;
-module_param(force_addr, uint, 0);
-MODULE_PARM_DESC(force_addr, "Force the use of specified MMIO address."
-               " ONLY USE THIS PARAMETER IF YOU REALLY KNOW"
-               " WHAT YOU ARE DOING (default=none)");
-
 /*
  * Some TCO specific functions
  */
@@ -176,39 +165,6 @@ static void tco_timer_enable(void)
        }
 }
 
-static void tco_timer_disable(void)
-{
-       int val;
-
-       if (sp5100_tco_pci->revision >= 0x40) {
-               /* For SB800 or later */
-               /* Enable watchdog decode bit and Disable watchdog timer */
-               outb(SB800_PM_WATCHDOG_CONTROL, SB800_IO_PM_INDEX_REG);
-               val = inb(SB800_IO_PM_DATA_REG);
-               val |= SB800_PCI_WATCHDOG_DECODE_EN;
-               val |= SB800_PM_WATCHDOG_DISABLE;
-               outb(val, SB800_IO_PM_DATA_REG);
-       } else {
-               /* For SP5100 or SB7x0 */
-               /* Enable watchdog decode bit */
-               pci_read_config_dword(sp5100_tco_pci,
-                                     SP5100_PCI_WATCHDOG_MISC_REG,
-                                     &val);
-
-               val |= SP5100_PCI_WATCHDOG_DECODE_EN;
-
-               pci_write_config_dword(sp5100_tco_pci,
-                                      SP5100_PCI_WATCHDOG_MISC_REG,
-                                      val);
-
-               /* Disable Watchdog timer */
-               outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG);
-               val = inb(SP5100_IO_PM_DATA_REG);
-               val |= SP5100_PM_WATCHDOG_DISABLE;
-               outb(val, SP5100_IO_PM_DATA_REG);
-       }
-}
-
 /*
  *     /dev/watchdog handling
  */
@@ -361,7 +317,7 @@ static unsigned char sp5100_tco_setupdevice(void)
 {
        struct pci_dev *dev = NULL;
        const char *dev_name = NULL;
-       u32 val, tmp_val;
+       u32 val;
        u32 index_reg, data_reg, base_addr;
 
        /* Match the PCI device */
@@ -459,63 +415,8 @@ static unsigned char sp5100_tco_setupdevice(void)
        } else
                pr_debug("SBResource_MMIO is disabled(0x%04x)\n", val);
 
-       /*
-        * Lastly re-programming the watchdog timer MMIO address,
-        * This method is a last resort...
-        *
-        * Before re-programming, to ensure that the watchdog timer
-        * is disabled, disable the watchdog timer.
-        */
-       tco_timer_disable();
-
-       if (force_addr) {
-               /*
-                * Force the use of watchdog timer MMIO address, and aligned to
-                * 8byte boundary.
-                */
-               force_addr &= ~0x7;
-               val = force_addr;
-
-               pr_info("Force the use of 0x%04x as MMIO address\n", val);
-       } else {
-               /*
-                * Get empty slot into the resource tree for watchdog timer.
-                */
-               if (allocate_resource(&iomem_resource,
-                                     &wdt_res,
-                                     SP5100_WDT_MEM_MAP_SIZE,
-                                     0xf0000000,
-                                     0xfffffff8,
-                                     0x8,
-                                     NULL,
-                                     NULL)) {
-                       pr_err("MMIO allocation failed\n");
-                       goto unreg_region;
-               }
-
-               val = resbase_phys = wdt_res.start;
-               pr_debug("Got 0x%04x from resource tree\n", val);
-       }
-
-       /* Restore to the low three bits */
-       outb(base_addr+0, index_reg);
-       tmp_val = val | (inb(data_reg) & 0x7);
-
-       /* Re-programming the watchdog timer base address */
-       outb(base_addr+0, index_reg);
-       outb((tmp_val >>  0) & 0xff, data_reg);
-       outb(base_addr+1, index_reg);
-       outb((tmp_val >>  8) & 0xff, data_reg);
-       outb(base_addr+2, index_reg);
-       outb((tmp_val >> 16) & 0xff, data_reg);
-       outb(base_addr+3, index_reg);
-       outb((tmp_val >> 24) & 0xff, data_reg);
-
-       if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE,
-                                                                  dev_name)) {
-               pr_err("MMIO address 0x%04x already in use\n", val);
-               goto unreg_resource;
-       }
+       pr_notice("failed to find MMIO address, giving up.\n");
+       goto  unreg_region;
 
 setup_wdt:
        tcobase_phys = val;
@@ -555,9 +456,6 @@ setup_wdt:
 
 unreg_mem_region:
        release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
-unreg_resource:
-       if (resbase_phys)
-               release_resource(&wdt_res);
 unreg_region:
        release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
 exit:
@@ -567,7 +465,6 @@ exit:
 static int sp5100_tco_init(struct platform_device *dev)
 {
        int ret;
-       char addr_str[16];
 
        /*
         * Check whether or not the hardware watchdog is there. If found, then
@@ -599,23 +496,14 @@ static int sp5100_tco_init(struct platform_device *dev)
        clear_bit(0, &timer_alive);
 
        /* Show module parameters */
-       if (force_addr == tcobase_phys)
-               /* The force_addr is vaild */
-               sprintf(addr_str, "0x%04x", force_addr);
-       else
-               strcpy(addr_str, "none");
-
-       pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d, "
-               "force_addr=%s)\n",
-               tcobase, heartbeat, nowayout, addr_str);
+       pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n",
+               tcobase, heartbeat, nowayout);
 
        return 0;
 
 exit:
        iounmap(tcobase);
        release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
-       if (resbase_phys)
-               release_resource(&wdt_res);
        release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
        return ret;
 }
@@ -630,8 +518,6 @@ static void sp5100_tco_cleanup(void)
        misc_deregister(&sp5100_tco_miscdev);
        iounmap(tcobase);
        release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE);
-       if (resbase_phys)
-               release_resource(&wdt_res);
        release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE);
 }
 
index 71594a0c14b735f56decde5e1ac5e01543fbda6c..2b28c00da0df00d2f99a8c5283b2d2b7c84a9ffa 100644 (file)
@@ -57,7 +57,7 @@
 #define SB800_PM_WATCHDOG_DISABLE      (1 << 2)
 #define SB800_PM_WATCHDOG_SECOND_RES   (3 << 0)
 #define SB800_ACPI_MMIO_DECODE_EN      (1 << 0)
-#define SB800_ACPI_MMIO_SEL            (1 << 2)
+#define SB800_ACPI_MMIO_SEL            (1 << 1)
 
 
 #define SB800_PM_WDT_MMIO_OFFSET       0xB00
index 5a32232cf7c15cdc05536ecb157eeb86048154e0..67af155cf60286f87c6dc1c576d72008d6e5c4fb 100644 (file)
@@ -182,7 +182,7 @@ config XEN_PRIVCMD
 
 config XEN_STUB
        bool "Xen stub drivers"
-       depends on XEN && X86_64
+       depends on XEN && X86_64 && BROKEN
        default n
        help
          Allow kernel to install stub drivers, to reserve space for Xen drivers,
index d17aa41a9041428fbff17a890b2af18b64422ef4..aa85881d17b23f7ff6425be0140b6aed0c63c942 100644 (file)
@@ -403,11 +403,23 @@ static void unmask_evtchn(int port)
 
        if (unlikely((cpu != cpu_from_evtchn(port))))
                do_hypercall = 1;
-       else
+       else {
+               /*
+                * Need to clear the mask before checking pending to
+                * avoid a race with an event becoming pending.
+                *
+                * EVTCHNOP_unmask will only trigger an upcall if the
+                * mask bit was set, so if a hypercall is needed
+                * remask the event.
+                */
+               sync_clear_bit(port, BM(&s->evtchn_mask[0]));
                evtchn_pending = sync_test_bit(port, BM(&s->evtchn_pending[0]));
 
-       if (unlikely(evtchn_pending && xen_hvm_domain()))
-               do_hypercall = 1;
+               if (unlikely(evtchn_pending && xen_hvm_domain())) {
+                       sync_set_bit(port, BM(&s->evtchn_mask[0]));
+                       do_hypercall = 1;
+               }
+       }
 
        /* Slow path (hypercall) if this is a non-local port or if this is
         * an hvm domain and an event is pending (hvm domains don't have
@@ -418,8 +430,6 @@ static void unmask_evtchn(int port)
        } else {
                struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu);
 
-               sync_clear_bit(port, BM(&s->evtchn_mask[0]));
-
                /*
                 * The following is basically the equivalent of
                 * 'hw_resend_irq'. Just like a real IO-APIC we 'lose
index 0ef7c4d40f86b9018ed2ae2ed0eda2071d4d7bfd..b04fb64c5a91ee2613b21c8d9c146ab16f82a941 100644 (file)
@@ -44,7 +44,7 @@ int xen_event_channel_op_compat(int cmd, void *arg)
 }
 EXPORT_SYMBOL_GPL(xen_event_channel_op_compat);
 
-int HYPERVISOR_physdev_op_compat(int cmd, void *arg)
+int xen_physdev_op_compat(int cmd, void *arg)
 {
        struct physdev_op op;
        int rc;
@@ -78,3 +78,4 @@ int HYPERVISOR_physdev_op_compat(int cmd, void *arg)
 
        return rc;
 }
+EXPORT_SYMBOL_GPL(xen_physdev_op_compat);
index 316df65163cfa5d6485a256edf2cdab24e8805d6..90e34ac7e522dfcf2c5af269639f5f877d95ac3b 100644 (file)
@@ -500,16 +500,19 @@ static int __init xen_acpi_processor_init(void)
        (void)acpi_processor_preregister_performance(acpi_perf_data);
 
        for_each_possible_cpu(i) {
+               struct acpi_processor *pr;
                struct acpi_processor_performance *perf;
 
+               pr = per_cpu(processors, i);
                perf = per_cpu_ptr(acpi_perf_data, i);
-               rc = acpi_processor_register_performance(perf, i);
+               if (!pr)
+                       continue;
+
+               pr->performance = perf;
+               rc = acpi_processor_get_performance_info(pr);
                if (rc)
                        goto err_out;
        }
-       rc = acpi_processor_notify_smm(THIS_MODULE);
-       if (rc)
-               goto err_unregister;
 
        for_each_possible_cpu(i) {
                struct acpi_processor *_pr;
index 9204126f1560ced72321b267b96099acfe71b8dd..a2278ba7fb273a523476e0504388e49e48511093 100644 (file)
@@ -17,6 +17,7 @@
 #include <xen/events.h>
 #include <asm/xen/pci.h>
 #include <asm/xen/hypervisor.h>
+#include <xen/interface/physdev.h>
 #include "pciback.h"
 #include "conf_space.h"
 #include "conf_space_quirks.h"
@@ -85,37 +86,52 @@ static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev)
 static void pcistub_device_release(struct kref *kref)
 {
        struct pcistub_device *psdev;
+       struct pci_dev *dev;
        struct xen_pcibk_dev_data *dev_data;
 
        psdev = container_of(kref, struct pcistub_device, kref);
-       dev_data = pci_get_drvdata(psdev->dev);
+       dev = psdev->dev;
+       dev_data = pci_get_drvdata(dev);
 
-       dev_dbg(&psdev->dev->dev, "pcistub_device_release\n");
+       dev_dbg(&dev->dev, "pcistub_device_release\n");
 
-       xen_unregister_device_domain_owner(psdev->dev);
+       xen_unregister_device_domain_owner(dev);
 
        /* Call the reset function which does not take lock as this
         * is called from "unbind" which takes a device_lock mutex.
         */
-       __pci_reset_function_locked(psdev->dev);
-       if (pci_load_and_free_saved_state(psdev->dev,
-                                         &dev_data->pci_saved_state)) {
-               dev_dbg(&psdev->dev->dev, "Could not reload PCI state\n");
-       } else
-               pci_restore_state(psdev->dev);
+       __pci_reset_function_locked(dev);
+       if (pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state))
+               dev_dbg(&dev->dev, "Could not reload PCI state\n");
+       else
+               pci_restore_state(dev);
+
+       if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) {
+               struct physdev_pci_device ppdev = {
+                       .seg = pci_domain_nr(dev->bus),
+                       .bus = dev->bus->number,
+                       .devfn = dev->devfn
+               };
+               int err = HYPERVISOR_physdev_op(PHYSDEVOP_release_msix,
+                                               &ppdev);
+
+               if (err)
+                       dev_warn(&dev->dev, "MSI-X release failed (%d)\n",
+                                err);
+       }
 
        /* Disable the device */
-       xen_pcibk_reset_device(psdev->dev);
+       xen_pcibk_reset_device(dev);
 
        kfree(dev_data);
-       pci_set_drvdata(psdev->dev, NULL);
+       pci_set_drvdata(dev, NULL);
 
        /* Clean-up the device */
-       xen_pcibk_config_free_dyn_fields(psdev->dev);
-       xen_pcibk_config_free_dev(psdev->dev);
+       xen_pcibk_config_free_dyn_fields(dev);
+       xen_pcibk_config_free_dev(dev);
 
-       psdev->dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED;
-       pci_dev_put(psdev->dev);
+       dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED;
+       pci_dev_put(dev);
 
        kfree(psdev);
 }
@@ -355,6 +371,19 @@ static int pcistub_init_device(struct pci_dev *dev)
        if (err)
                goto config_release;
 
+       if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) {
+               struct physdev_pci_device ppdev = {
+                       .seg = pci_domain_nr(dev->bus),
+                       .bus = dev->bus->number,
+                       .devfn = dev->devfn
+               };
+
+               err = HYPERVISOR_physdev_op(PHYSDEVOP_prepare_msix, &ppdev);
+               if (err)
+                       dev_err(&dev->dev, "MSI-X preparation failed (%d)\n",
+                               err);
+       }
+
        /* We need the device active to save the state. */
        dev_dbg(&dev->dev, "save state of device\n");
        pci_save_state(dev);
index 37c1f825f513764c998e808acf482d9d20cda7e0..b98cf0c35725a1714afbc498ee1ab49864eb1ff3 100644 (file)
@@ -113,7 +113,8 @@ void xen_pcibk_reset_device(struct pci_dev *dev)
                if (dev->msi_enabled)
                        pci_disable_msi(dev);
 #endif
-               pci_disable_device(dev);
+               if (pci_is_enabled(dev))
+                       pci_disable_device(dev);
 
                pci_write_config_word(dev, PCI_COMMAND, 0);
 
index d85e411cbf8924ceaf8e3947ab961e1c5ea68744..bbef194c5b0183181f74405103ebeb782935c33f 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/export.h>
 #include <linux/types.h>
 #include <linux/acpi.h>
-#include <acpi/acpi_drivers.h>
 #include <xen/acpi.h>
 
 #ifdef CONFIG_ACPI
index aea605c98ba6b4eb920a022acaf6c4587ed653f9..aae187a7f94a661edb82189496242fdac4c33fcf 100644 (file)
@@ -551,6 +551,7 @@ struct block_device *bdgrab(struct block_device *bdev)
        ihold(bdev->bd_inode);
        return bdev;
 }
+EXPORT_SYMBOL(bdgrab);
 
 long nr_blockdev_pages(void)
 {
index ecd25a1b4e519562ff874112515052403877fbc4..ca9d8f1a3bb67968dab36b8df98c0c2093a2300f 100644 (file)
@@ -651,6 +651,8 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,
        if (tree_mod_dont_log(fs_info, NULL))
                return 0;
 
+       __tree_mod_log_free_eb(fs_info, old_root);
+
        ret = tree_mod_alloc(fs_info, flags, &tm);
        if (ret < 0)
                goto out;
@@ -736,7 +738,7 @@ tree_mod_log_search(struct btrfs_fs_info *fs_info, u64 start, u64 min_seq)
 static noinline void
 tree_mod_log_eb_copy(struct btrfs_fs_info *fs_info, struct extent_buffer *dst,
                     struct extent_buffer *src, unsigned long dst_offset,
-                    unsigned long src_offset, int nr_items)
+                    unsigned long src_offset, int nr_items, int log_removal)
 {
        int ret;
        int i;
@@ -750,10 +752,12 @@ tree_mod_log_eb_copy(struct btrfs_fs_info *fs_info, struct extent_buffer *dst,
        }
 
        for (i = 0; i < nr_items; i++) {
-               ret = tree_mod_log_insert_key_locked(fs_info, src,
-                                                    i + src_offset,
-                                                    MOD_LOG_KEY_REMOVE);
-               BUG_ON(ret < 0);
+               if (log_removal) {
+                       ret = tree_mod_log_insert_key_locked(fs_info, src,
+                                                       i + src_offset,
+                                                       MOD_LOG_KEY_REMOVE);
+                       BUG_ON(ret < 0);
+               }
                ret = tree_mod_log_insert_key_locked(fs_info, dst,
                                                     i + dst_offset,
                                                     MOD_LOG_KEY_ADD);
@@ -927,7 +931,6 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
                        ret = btrfs_dec_ref(trans, root, buf, 1, 1);
                        BUG_ON(ret); /* -ENOMEM */
                }
-               tree_mod_log_free_eb(root->fs_info, buf);
                clean_tree_block(trans, root, buf);
                *last_ref = 1;
        }
@@ -1046,6 +1049,7 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
                btrfs_set_node_ptr_generation(parent, parent_slot,
                                              trans->transid);
                btrfs_mark_buffer_dirty(parent);
+               tree_mod_log_free_eb(root->fs_info, buf);
                btrfs_free_tree_block(trans, root, buf, parent_start,
                                      last_ref);
        }
@@ -1750,7 +1754,6 @@ static noinline int balance_level(struct btrfs_trans_handle *trans,
                        goto enospc;
                }
 
-               tree_mod_log_free_eb(root->fs_info, root->node);
                tree_mod_log_set_root_pointer(root, child);
                rcu_assign_pointer(root->node, child);
 
@@ -2995,7 +2998,7 @@ static int push_node_left(struct btrfs_trans_handle *trans,
                push_items = min(src_nritems - 8, push_items);
 
        tree_mod_log_eb_copy(root->fs_info, dst, src, dst_nritems, 0,
-                            push_items);
+                            push_items, 1);
        copy_extent_buffer(dst, src,
                           btrfs_node_key_ptr_offset(dst_nritems),
                           btrfs_node_key_ptr_offset(0),
@@ -3066,7 +3069,7 @@ static int balance_node_right(struct btrfs_trans_handle *trans,
                                      sizeof(struct btrfs_key_ptr));
 
        tree_mod_log_eb_copy(root->fs_info, dst, src, 0,
-                            src_nritems - push_items, push_items);
+                            src_nritems - push_items, push_items, 1);
        copy_extent_buffer(dst, src,
                           btrfs_node_key_ptr_offset(0),
                           btrfs_node_key_ptr_offset(src_nritems - push_items),
@@ -3218,12 +3221,18 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
        int mid;
        int ret;
        u32 c_nritems;
+       int tree_mod_log_removal = 1;
 
        c = path->nodes[level];
        WARN_ON(btrfs_header_generation(c) != trans->transid);
        if (c == root->node) {
                /* trying to split the root, lets make a new one */
                ret = insert_new_root(trans, root, path, level + 1);
+               /*
+                * removal of root nodes has been logged by
+                * tree_mod_log_set_root_pointer due to locking
+                */
+               tree_mod_log_removal = 0;
                if (ret)
                        return ret;
        } else {
@@ -3261,7 +3270,8 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
                            (unsigned long)btrfs_header_chunk_tree_uuid(split),
                            BTRFS_UUID_SIZE);
 
-       tree_mod_log_eb_copy(root->fs_info, split, c, 0, mid, c_nritems - mid);
+       tree_mod_log_eb_copy(root->fs_info, split, c, 0, mid, c_nritems - mid,
+                            tree_mod_log_removal);
        copy_extent_buffer(split, c,
                           btrfs_node_key_ptr_offset(0),
                           btrfs_node_key_ptr_offset(mid),
index 7d84651e850b22cb937b29c68d34c1119af1e4a0..6d19a0a554aadc3aeadbe1df6eff03acd489375e 100644 (file)
@@ -1291,6 +1291,7 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
                                      0, objectid, NULL, 0, 0, 0);
        if (IS_ERR(leaf)) {
                ret = PTR_ERR(leaf);
+               leaf = NULL;
                goto fail;
        }
 
@@ -1334,11 +1335,16 @@ struct btrfs_root *btrfs_create_tree(struct btrfs_trans_handle *trans,
 
        btrfs_tree_unlock(leaf);
 
+       return root;
+
 fail:
-       if (ret)
-               return ERR_PTR(ret);
+       if (leaf) {
+               btrfs_tree_unlock(leaf);
+               free_extent_buffer(leaf);
+       }
+       kfree(root);
 
-       return root;
+       return ERR_PTR(ret);
 }
 
 static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans,
@@ -3253,7 +3259,7 @@ void btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root)
        if (btrfs_root_refs(&root->root_item) == 0)
                synchronize_srcu(&fs_info->subvol_srcu);
 
-       if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
+       if (test_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state)) {
                btrfs_free_log(NULL, root);
                btrfs_free_log_root_tree(NULL, fs_info);
        }
index 3e074dab2d57a3e39ad16538f7a51bfde8e4ed91..3d551231cabae9e43c7a1e90385f22fd25891239 100644 (file)
@@ -257,7 +257,8 @@ static int exclude_super_stripes(struct btrfs_root *root,
                cache->bytes_super += stripe_len;
                ret = add_excluded_extent(root, cache->key.objectid,
                                          stripe_len);
-               BUG_ON(ret); /* -ENOMEM */
+               if (ret)
+                       return ret;
        }
 
        for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
@@ -265,13 +266,17 @@ static int exclude_super_stripes(struct btrfs_root *root,
                ret = btrfs_rmap_block(&root->fs_info->mapping_tree,
                                       cache->key.objectid, bytenr,
                                       0, &logical, &nr, &stripe_len);
-               BUG_ON(ret); /* -ENOMEM */
+               if (ret)
+                       return ret;
 
                while (nr--) {
                        cache->bytes_super += stripe_len;
                        ret = add_excluded_extent(root, logical[nr],
                                                  stripe_len);
-                       BUG_ON(ret); /* -ENOMEM */
+                       if (ret) {
+                               kfree(logical);
+                               return ret;
+                       }
                }
 
                kfree(logical);
@@ -1467,8 +1472,11 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
        if (ret && !insert) {
                err = -ENOENT;
                goto out;
+       } else if (ret) {
+               err = -EIO;
+               WARN_ON(1);
+               goto out;
        }
-       BUG_ON(ret); /* Corruption */
 
        leaf = path->nodes[0];
        item_size = btrfs_item_size_nr(leaf, path->slots[0]);
@@ -4435,7 +4443,7 @@ static void update_global_block_rsv(struct btrfs_fs_info *fs_info)
        spin_lock(&sinfo->lock);
        spin_lock(&block_rsv->lock);
 
-       block_rsv->size = num_bytes;
+       block_rsv->size = min_t(u64, num_bytes, 512 * 1024 * 1024);
 
        num_bytes = sinfo->bytes_used + sinfo->bytes_pinned +
                    sinfo->bytes_reserved + sinfo->bytes_readonly +
@@ -4790,14 +4798,49 @@ out_fail:
         * If the inodes csum_bytes is the same as the original
         * csum_bytes then we know we haven't raced with any free()ers
         * so we can just reduce our inodes csum bytes and carry on.
-        * Otherwise we have to do the normal free thing to account for
-        * the case that the free side didn't free up its reserve
-        * because of this outstanding reservation.
         */
-       if (BTRFS_I(inode)->csum_bytes == csum_bytes)
+       if (BTRFS_I(inode)->csum_bytes == csum_bytes) {
                calc_csum_metadata_size(inode, num_bytes, 0);
-       else
-               to_free = calc_csum_metadata_size(inode, num_bytes, 0);
+       } else {
+               u64 orig_csum_bytes = BTRFS_I(inode)->csum_bytes;
+               u64 bytes;
+
+               /*
+                * This is tricky, but first we need to figure out how much we
+                * free'd from any free-ers that occured during this
+                * reservation, so we reset ->csum_bytes to the csum_bytes
+                * before we dropped our lock, and then call the free for the
+                * number of bytes that were freed while we were trying our
+                * reservation.
+                */
+               bytes = csum_bytes - BTRFS_I(inode)->csum_bytes;
+               BTRFS_I(inode)->csum_bytes = csum_bytes;
+               to_free = calc_csum_metadata_size(inode, bytes, 0);
+
+
+               /*
+                * Now we need to see how much we would have freed had we not
+                * been making this reservation and our ->csum_bytes were not
+                * artificially inflated.
+                */
+               BTRFS_I(inode)->csum_bytes = csum_bytes - num_bytes;
+               bytes = csum_bytes - orig_csum_bytes;
+               bytes = calc_csum_metadata_size(inode, bytes, 0);
+
+               /*
+                * Now reset ->csum_bytes to what it should be.  If bytes is
+                * more than to_free then we would have free'd more space had we
+                * not had an artificially high ->csum_bytes, so we need to free
+                * the remainder.  If bytes is the same or less then we don't
+                * need to do anything, the other free-ers did the correct
+                * thing.
+                */
+               BTRFS_I(inode)->csum_bytes = orig_csum_bytes - num_bytes;
+               if (bytes > to_free)
+                       to_free = bytes - to_free;
+               else
+                       to_free = 0;
+       }
        spin_unlock(&BTRFS_I(inode)->lock);
        if (dropped)
                to_free += btrfs_calc_trans_metadata_size(root, dropped);
@@ -7944,7 +7987,17 @@ int btrfs_read_block_groups(struct btrfs_root *root)
                 * info has super bytes accounted for, otherwise we'll think
                 * we have more space than we actually do.
                 */
-               exclude_super_stripes(root, cache);
+               ret = exclude_super_stripes(root, cache);
+               if (ret) {
+                       /*
+                        * We may have excluded something, so call this just in
+                        * case.
+                        */
+                       free_excluded_extents(root, cache);
+                       kfree(cache->free_space_ctl);
+                       kfree(cache);
+                       goto error;
+               }
 
                /*
                 * check for two cases, either we are full, and therefore
@@ -8086,7 +8139,17 @@ int btrfs_make_block_group(struct btrfs_trans_handle *trans,
 
        cache->last_byte_to_unpin = (u64)-1;
        cache->cached = BTRFS_CACHE_FINISHED;
-       exclude_super_stripes(root, cache);
+       ret = exclude_super_stripes(root, cache);
+       if (ret) {
+               /*
+                * We may have excluded something, so call this just in
+                * case.
+                */
+               free_excluded_extents(root, cache);
+               kfree(cache->free_space_ctl);
+               kfree(cache);
+               return ret;
+       }
 
        add_new_free_space(cache, root->fs_info, chunk_offset,
                           chunk_offset + size);
index f173c5af64610de66597cce1e38ac493729d6125..cdee391fc7bfd57c596204a8474142e7afe60335 100644 (file)
@@ -1257,6 +1257,39 @@ int unlock_extent(struct extent_io_tree *tree, u64 start, u64 end)
                                GFP_NOFS);
 }
 
+int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end)
+{
+       unsigned long index = start >> PAGE_CACHE_SHIFT;
+       unsigned long end_index = end >> PAGE_CACHE_SHIFT;
+       struct page *page;
+
+       while (index <= end_index) {
+               page = find_get_page(inode->i_mapping, index);
+               BUG_ON(!page); /* Pages should be in the extent_io_tree */
+               clear_page_dirty_for_io(page);
+               page_cache_release(page);
+               index++;
+       }
+       return 0;
+}
+
+int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end)
+{
+       unsigned long index = start >> PAGE_CACHE_SHIFT;
+       unsigned long end_index = end >> PAGE_CACHE_SHIFT;
+       struct page *page;
+
+       while (index <= end_index) {
+               page = find_get_page(inode->i_mapping, index);
+               BUG_ON(!page); /* Pages should be in the extent_io_tree */
+               account_page_redirty(page);
+               __set_page_dirty_nobuffers(page);
+               page_cache_release(page);
+               index++;
+       }
+       return 0;
+}
+
 /*
  * helper function to set both pages and extents in the tree writeback
  */
index 6068a1985560eed72a8df42fa528377c3584c93a..258c92156857f1d1e9e525a89d7a706d6c126c66 100644 (file)
@@ -325,6 +325,8 @@ int map_private_extent_buffer(struct extent_buffer *eb, unsigned long offset,
                      unsigned long *map_len);
 int extent_range_uptodate(struct extent_io_tree *tree,
                          u64 start, u64 end);
+int extent_range_clear_dirty_for_io(struct inode *inode, u64 start, u64 end);
+int extent_range_redirty_for_io(struct inode *inode, u64 start, u64 end);
 int extent_clear_unlock_delalloc(struct inode *inode,
                                struct extent_io_tree *tree,
                                u64 start, u64 end, struct page *locked_page,
index ec160202be3e38057c26498558e2f309af7859b7..c4628a201cb30fe6e2daa09eff83bd1fec79ecf1 100644 (file)
@@ -118,9 +118,11 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans,
                csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]);
                csums_in_item /= csum_size;
 
-               if (csum_offset >= csums_in_item) {
+               if (csum_offset == csums_in_item) {
                        ret = -EFBIG;
                        goto fail;
+               } else if (csum_offset > csums_in_item) {
+                       goto fail;
                }
        }
        item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item);
@@ -728,7 +730,6 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans,
                return -ENOMEM;
 
        sector_sum = sums->sums;
-       trans->adding_csums = 1;
 again:
        next_offset = (u64)-1;
        found_next = 0;
@@ -899,7 +900,6 @@ next_sector:
                goto again;
        }
 out:
-       trans->adding_csums = 0;
        btrfs_free_path(path);
        return ret;
 
index af1d0605a5c1e74b3f30392d4e28c0faf34400ad..ade03e6f7bd2706bbaac3406f1bcc31cf70cb578 100644 (file)
@@ -591,6 +591,7 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                }
                compressed = test_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
                clear_bit(EXTENT_FLAG_PINNED, &em->flags);
+               clear_bit(EXTENT_FLAG_LOGGING, &flags);
                remove_extent_mapping(em_tree, em);
                if (no_splits)
                        goto next;
@@ -2141,6 +2142,7 @@ static long btrfs_fallocate(struct file *file, int mode,
 {
        struct inode *inode = file_inode(file);
        struct extent_state *cached_state = NULL;
+       struct btrfs_root *root = BTRFS_I(inode)->root;
        u64 cur_offset;
        u64 last_byte;
        u64 alloc_start;
@@ -2168,6 +2170,11 @@ static long btrfs_fallocate(struct file *file, int mode,
        ret = btrfs_check_data_free_space(inode, alloc_end - alloc_start);
        if (ret)
                return ret;
+       if (root->fs_info->quota_enabled) {
+               ret = btrfs_qgroup_reserve(root, alloc_end - alloc_start);
+               if (ret)
+                       goto out_reserve_fail;
+       }
 
        /*
         * wait for ordered IO before we have any locks.  We'll loop again
@@ -2271,6 +2278,9 @@ static long btrfs_fallocate(struct file *file, int mode,
                             &cached_state, GFP_NOFS);
 out:
        mutex_unlock(&inode->i_mutex);
+       if (root->fs_info->quota_enabled)
+               btrfs_qgroup_free(root, alloc_end - alloc_start);
+out_reserve_fail:
        /* Let go of our reservation. */
        btrfs_free_reserved_data_space(inode, alloc_end - alloc_start);
        return ret;
index d1470adca8f87aafa6a028995eeac0e91ee781db..09c58a35b429d6a82dc261014df2875e7c15f920 100644 (file)
@@ -353,6 +353,7 @@ static noinline int compress_file_range(struct inode *inode,
        int i;
        int will_compress;
        int compress_type = root->fs_info->compress_type;
+       int redirty = 0;
 
        /* if this is a small write inside eof, kick off a defrag */
        if ((end - start + 1) < 16 * 1024 &&
@@ -415,6 +416,17 @@ again:
                if (BTRFS_I(inode)->force_compress)
                        compress_type = BTRFS_I(inode)->force_compress;
 
+               /*
+                * we need to call clear_page_dirty_for_io on each
+                * page in the range.  Otherwise applications with the file
+                * mmap'd can wander in and change the page contents while
+                * we are compressing them.
+                *
+                * If the compression fails for any reason, we set the pages
+                * dirty again later on.
+                */
+               extent_range_clear_dirty_for_io(inode, start, end);
+               redirty = 1;
                ret = btrfs_compress_pages(compress_type,
                                           inode->i_mapping, start,
                                           total_compressed, pages,
@@ -554,6 +566,8 @@ cleanup_and_bail_uncompressed:
                        __set_page_dirty_nobuffers(locked_page);
                        /* unlocked later on in the async handlers */
                }
+               if (redirty)
+                       extent_range_redirty_for_io(inode, start, end);
                add_async_extent(async_cow, start, end - start + 1,
                                 0, NULL, 0, BTRFS_COMPRESS_NONE);
                *num_added += 1;
@@ -1743,8 +1757,10 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans,
        struct btrfs_ordered_sum *sum;
 
        list_for_each_entry(sum, list, list) {
+               trans->adding_csums = 1;
                btrfs_csum_file_blocks(trans,
                       BTRFS_I(inode)->root->fs_info->csum_root, sum);
+               trans->adding_csums = 0;
        }
        return 0;
 }
@@ -2312,6 +2328,7 @@ again:
        key.type = BTRFS_EXTENT_DATA_KEY;
        key.offset = start;
 
+       path->leave_spinning = 1;
        if (merge) {
                struct btrfs_file_extent_item *fi;
                u64 extent_len;
@@ -2368,6 +2385,7 @@ again:
 
        btrfs_mark_buffer_dirty(leaf);
        inode_add_bytes(inode, len);
+       btrfs_release_path(path);
 
        ret = btrfs_inc_extent_ref(trans, root, new->bytenr,
                        new->disk_len, 0,
@@ -2381,6 +2399,7 @@ again:
        ret = 1;
 out_free_path:
        btrfs_release_path(path);
+       path->leave_spinning = 0;
        btrfs_end_transaction(trans, root);
 out_unlock:
        unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start, lock_end,
@@ -3676,11 +3695,9 @@ static struct btrfs_trans_handle *__unlink_start_trans(struct inode *dir,
         * 1 for the dir item
         * 1 for the dir index
         * 1 for the inode ref
-        * 1 for the inode ref in the tree log
-        * 2 for the dir entries in the log
         * 1 for the inode
         */
-       trans = btrfs_start_transaction(root, 8);
+       trans = btrfs_start_transaction(root, 5);
        if (!IS_ERR(trans) || PTR_ERR(trans) != -ENOSPC)
                return trans;
 
@@ -8124,7 +8141,7 @@ static int btrfs_rename(struct inode *old_dir, struct dentry *old_dentry,
         * inodes.  So 5 * 2 is 10, plus 1 for the new link, so 11 total items
         * should cover the worst case number of items we'll modify.
         */
-       trans = btrfs_start_transaction(root, 20);
+       trans = btrfs_start_transaction(root, 11);
        if (IS_ERR(trans)) {
                 ret = PTR_ERR(trans);
                 goto out_notrans;
index ca52681e5f4049c45f2a228a3f8237ca23815772..b81e0e9a48941891681eef385d10d071f6cbe51b 100644 (file)
@@ -26,7 +26,6 @@
 
 void btrfs_tree_lock(struct extent_buffer *eb);
 void btrfs_tree_unlock(struct extent_buffer *eb);
-int btrfs_try_spin_lock(struct extent_buffer *eb);
 
 void btrfs_tree_read_lock(struct extent_buffer *eb);
 void btrfs_tree_read_unlock(struct extent_buffer *eb);
index dc08d77b717ea47f0eb7d43e351153f556c75eaa..005c45db699eecc0fef93fca0832b91633dd5d8a 100644 (file)
@@ -557,6 +557,7 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput)
        INIT_LIST_HEAD(&splice);
        INIT_LIST_HEAD(&works);
 
+       mutex_lock(&root->fs_info->ordered_operations_mutex);
        spin_lock(&root->fs_info->ordered_extent_lock);
        list_splice_init(&root->fs_info->ordered_extents, &splice);
        while (!list_empty(&splice)) {
@@ -600,6 +601,7 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput)
 
                cond_resched();
        }
+       mutex_unlock(&root->fs_info->ordered_operations_mutex);
 }
 
 /*
index aee4b1cc3d988ccc0dbde615000d07bcf5d35051..b44124dd2370ea726e66a099400163c342d8fa12 100644 (file)
@@ -1153,7 +1153,7 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle *trans,
        ret = btrfs_find_all_roots(trans, fs_info, node->bytenr,
                                   sgn > 0 ? node->seq - 1 : node->seq, &roots);
        if (ret < 0)
-               goto out;
+               return ret;
 
        spin_lock(&fs_info->qgroup_lock);
        quota_root = fs_info->quota_root;
@@ -1275,7 +1275,6 @@ int btrfs_qgroup_account_ref(struct btrfs_trans_handle *trans,
        ret = 0;
 unlock:
        spin_unlock(&fs_info->qgroup_lock);
-out:
        ulist_free(roots);
        ulist_free(tmp);
 
@@ -1525,21 +1524,23 @@ int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes)
 
                if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) &&
                    qg->reserved + qg->rfer + num_bytes >
-                   qg->max_rfer)
+                   qg->max_rfer) {
                        ret = -EDQUOT;
+                       goto out;
+               }
 
                if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) &&
                    qg->reserved + qg->excl + num_bytes >
-                   qg->max_excl)
+                   qg->max_excl) {
                        ret = -EDQUOT;
+                       goto out;
+               }
 
                list_for_each_entry(glist, &qg->groups, next_group) {
                        ulist_add(ulist, glist->group->qgroupid,
                                  (uintptr_t)glist->group, GFP_ATOMIC);
                }
        }
-       if (ret)
-               goto out;
 
        /*
         * no limits exceeded, now record the reservation into all qgroups
index 53c3501fa4ca348f13cb17617b363643a59b1f6f..85e072b956d564d64c527c1b58d3b5b26019c34f 100644 (file)
@@ -542,7 +542,6 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
        eb = path->nodes[0];
        ei = btrfs_item_ptr(eb, path->slots[0], struct btrfs_extent_item);
        item_size = btrfs_item_size_nr(eb, path->slots[0]);
-       btrfs_release_path(path);
 
        if (flags & BTRFS_EXTENT_FLAG_TREE_BLOCK) {
                do {
@@ -558,7 +557,9 @@ static void scrub_print_warning(const char *errstr, struct scrub_block *sblock)
                                ret < 0 ? -1 : ref_level,
                                ret < 0 ? -1 : ref_root);
                } while (ret != 1);
+               btrfs_release_path(path);
        } else {
+               btrfs_release_path(path);
                swarn.path = path;
                swarn.dev = dev;
                iterate_extent_inodes(fs_info, found_key.objectid,
index f7a8b861058b5234094d24e9fc35a49d9e78fe1c..c85e7c6b4598af950d240582f648224570889ca4 100644 (file)
@@ -3945,12 +3945,10 @@ static int is_extent_unchanged(struct send_ctx *sctx,
                    found_key.type != key.type) {
                        key.offset += right_len;
                        break;
-               } else {
-                       if (found_key.offset != key.offset + right_len) {
-                               /* Should really not happen */
-                               ret = -EIO;
-                               goto out;
-                       }
+               }
+               if (found_key.offset != key.offset + right_len) {
+                       ret = 0;
+                       goto out;
                }
                key = found_key;
        }
index 9250b9c4f01e1b826e25414e6ace942487e2ccca..50767bbaad6c6bfeb40e4d0e815446effd5392b3 100644 (file)
@@ -625,14 +625,13 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
 
        btrfs_trans_release_metadata(trans, root);
        trans->block_rsv = NULL;
-       /*
-        * the same root has to be passed to start_transaction and
-        * end_transaction. Subvolume quota depends on this.
-        */
-       WARN_ON(trans->root != root);
 
        if (trans->qgroup_reserved) {
-               btrfs_qgroup_free(root, trans->qgroup_reserved);
+               /*
+                * the same root has to be passed here between start_transaction
+                * and end_transaction. Subvolume quota depends on this.
+                */
+               btrfs_qgroup_free(trans->root, trans->qgroup_reserved);
                trans->qgroup_reserved = 0;
        }
 
index 6b9cff42265d06e5b26a7ed53684a5551675a930..2854c824ab6443d04eac19cf0b540f79c257cfa0 100644 (file)
@@ -684,6 +684,12 @@ int btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
                __btrfs_close_devices(fs_devices);
                free_fs_devices(fs_devices);
        }
+       /*
+        * Wait for rcu kworkers under __btrfs_close_devices
+        * to finish all blkdev_puts so device is really
+        * free when umount is done.
+        */
+       rcu_barrier();
        return ret;
 }
 
@@ -4929,7 +4935,18 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
        em = lookup_extent_mapping(em_tree, chunk_start, 1);
        read_unlock(&em_tree->lock);
 
-       BUG_ON(!em || em->start != chunk_start);
+       if (!em) {
+               printk(KERN_ERR "btrfs: couldn't find em for chunk %Lu\n",
+                      chunk_start);
+               return -EIO;
+       }
+
+       if (em->start != chunk_start) {
+               printk(KERN_ERR "btrfs: bad chunk start, em=%Lu, wanted=%Lu\n",
+                      em->start, chunk_start);
+               free_extent_map(em);
+               return -EIO;
+       }
        map = (struct map_lookup *)em->bdev;
 
        length = em->len;
index cfd1ce34e0bc7b8c4794c81e1aa937e7f009ca75..1d36db114772b953065555cd7e80aa5abca36a7d 100644 (file)
@@ -614,53 +614,10 @@ decode_negTokenInit(unsigned char *security_blob, int length,
                }
        }
 
-       /* mechlistMIC */
-       if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-               /* Check if we have reached the end of the blob, but with
-                  no mechListMic (e.g. NTLMSSP instead of KRB5) */
-               if (ctx.error == ASN1_ERR_DEC_EMPTY)
-                       goto decode_negtoken_exit;
-               cFYI(1, "Error decoding last part negTokenInit exit3");
-               return 0;
-       } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
-               /* tag = 3 indicating mechListMIC */
-               cFYI(1, "Exit 4 cls = %d con = %d tag = %d end = %p (%d)",
-                       cls, con, tag, end, *end);
-               return 0;
-       }
-
-       /* sequence */
-       if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-               cFYI(1, "Error decoding last part negTokenInit exit5");
-               return 0;
-       } else if ((cls != ASN1_UNI) || (con != ASN1_CON)
-                  || (tag != ASN1_SEQ)) {
-               cFYI(1, "cls = %d con = %d tag = %d end = %p (%d)",
-                       cls, con, tag, end, *end);
-       }
-
-       /* sequence of */
-       if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-               cFYI(1, "Error decoding last part negTokenInit exit 7");
-               return 0;
-       } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) {
-               cFYI(1, "Exit 8 cls = %d con = %d tag = %d end = %p (%d)",
-                       cls, con, tag, end, *end);
-               return 0;
-       }
-
-       /* general string */
-       if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) {
-               cFYI(1, "Error decoding last part negTokenInit exit9");
-               return 0;
-       } else if ((cls != ASN1_UNI) || (con != ASN1_PRI)
-                  || (tag != ASN1_GENSTR)) {
-               cFYI(1, "Exit10 cls = %d con = %d tag = %d end = %p (%d)",
-                       cls, con, tag, end, *end);
-               return 0;
-       }
-       cFYI(1, "Need to call asn1_octets_decode() function for %s",
-               ctx.pointer);   /* is this UTF-8 or ASCII? */
-decode_negtoken_exit:
+       /*
+        * We currently ignore anything at the end of the SPNEGO blob after
+        * the mechTypes have been parsed, since none of that info is
+        * used at the moment.
+        */
        return 1;
 }
index 1a052c0eee8eae9181e0e58ac5d0ff8852c0db8e..345fc89c4286985ed55cd972410c287a09c440f3 100644 (file)
@@ -91,6 +91,30 @@ struct workqueue_struct      *cifsiod_wq;
 __u8 cifs_client_guid[SMB2_CLIENT_GUID_SIZE];
 #endif
 
+/*
+ * Bumps refcount for cifs super block.
+ * Note that it should be only called if a referece to VFS super block is
+ * already held, e.g. in open-type syscalls context. Otherwise it can race with
+ * atomic_dec_and_test in deactivate_locked_super.
+ */
+void
+cifs_sb_active(struct super_block *sb)
+{
+       struct cifs_sb_info *server = CIFS_SB(sb);
+
+       if (atomic_inc_return(&server->active) == 1)
+               atomic_inc(&sb->s_active);
+}
+
+void
+cifs_sb_deactive(struct super_block *sb)
+{
+       struct cifs_sb_info *server = CIFS_SB(sb);
+
+       if (atomic_dec_and_test(&server->active))
+               deactivate_super(sb);
+}
+
 static int
 cifs_read_super(struct super_block *sb)
 {
@@ -777,6 +801,7 @@ struct file_system_type cifs_fs_type = {
        .kill_sb = cifs_kill_sb,
        /*  .fs_flags */
 };
+MODULE_ALIAS_FS("cifs");
 const struct inode_operations cifs_dir_inode_ops = {
        .create = cifs_create,
        .atomic_open = cifs_atomic_open,
index 7163419cecd95186f912522ba1736eb4e8c95454..0e32c3446ce9330b21898c59e72bd5430c47e48b 100644 (file)
@@ -41,6 +41,10 @@ extern struct file_system_type cifs_fs_type;
 extern const struct address_space_operations cifs_addr_ops;
 extern const struct address_space_operations cifs_addr_ops_smallbuf;
 
+/* Functions related to super block operations */
+extern void cifs_sb_active(struct super_block *sb);
+extern void cifs_sb_deactive(struct super_block *sb);
+
 /* Functions related to inodes */
 extern const struct inode_operations cifs_dir_inode_ops;
 extern struct inode *cifs_root_iget(struct super_block *);
index 8c0d8557731443ffb564905bb1ad0a9c64b8169b..7a0dd99e45077dfd2f7f780c140954575c9145a6 100644 (file)
@@ -300,6 +300,8 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
        INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
        mutex_init(&cfile->fh_mutex);
 
+       cifs_sb_active(inode->i_sb);
+
        /*
         * If the server returned a read oplock and we have mandatory brlocks,
         * set oplock level to None.
@@ -349,7 +351,8 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
        struct cifs_tcon *tcon = tlink_tcon(cifs_file->tlink);
        struct TCP_Server_Info *server = tcon->ses->server;
        struct cifsInodeInfo *cifsi = CIFS_I(inode);
-       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+       struct super_block *sb = inode->i_sb;
+       struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
        struct cifsLockInfo *li, *tmp;
        struct cifs_fid fid;
        struct cifs_pending_open open;
@@ -414,6 +417,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file)
 
        cifs_put_tlink(cifs_file->tlink);
        dput(cifs_file->dentry);
+       cifs_sb_deactive(sb);
        kfree(cifs_file);
 }
 
index 0079696305c980def5c17cc1906f75d20f3565c4..20887bf63121286e3d52f582db922ec64f4a71e5 100644 (file)
@@ -1043,7 +1043,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
                                   cifs_sb->mnt_cifs_flags &
                                            CIFS_MOUNT_MAP_SPECIAL_CHR);
        if (rc != 0) {
-               rc = -ETXTBSY;
+               rc = -EBUSY;
                goto undo_setattr;
        }
 
@@ -1062,7 +1062,7 @@ cifs_rename_pending_delete(const char *full_path, struct dentry *dentry,
                if (rc == -ENOENT)
                        rc = 0;
                else if (rc != 0) {
-                       rc = -ETXTBSY;
+                       rc = -EBUSY;
                        goto undo_rename;
                }
                cifsInode->delete_pending = true;
@@ -1169,15 +1169,13 @@ psx_del_no_retry:
                        cifs_drop_nlink(inode);
        } else if (rc == -ENOENT) {
                d_drop(dentry);
-       } else if (rc == -ETXTBSY) {
+       } else if (rc == -EBUSY) {
                if (server->ops->rename_pending_delete) {
                        rc = server->ops->rename_pending_delete(full_path,
                                                                dentry, xid);
                        if (rc == 0)
                                cifs_drop_nlink(inode);
                }
-               if (rc == -ETXTBSY)
-                       rc = -EBUSY;
        } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
                attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
                if (attrs == NULL) {
@@ -1518,7 +1516,7 @@ cifs_do_rename(const unsigned int xid, struct dentry *from_dentry,
         * source. Note that cross directory moves do not work with
         * rename by filehandle to various Windows servers.
         */
-       if (rc == 0 || rc != -ETXTBSY)
+       if (rc == 0 || rc != -EBUSY)
                goto do_rename_exit;
 
        /* open-file renames don't work across directories */
index a82bc51fdc82abad102b286399fd037ef10428c5..c0b25b28be6ccc1079185bc3effd6672c56976de 100644 (file)
@@ -62,7 +62,7 @@ static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
        {ERRdiffdevice, -EXDEV},
        {ERRnofiles, -ENOENT},
        {ERRwriteprot, -EROFS},
-       {ERRbadshare, -ETXTBSY},
+       {ERRbadshare, -EBUSY},
        {ERRlock, -EACCES},
        {ERRunsup, -EINVAL},
        {ERRnosuchshare, -ENXIO},
index fe40fde291111b0f4d521756403dbc530be4da8a..d487985dd0ead4261079ff4157d7245d2ea6e2bb 100644 (file)
@@ -558,6 +558,10 @@ ssize_t compat_rw_copy_check_uvector(int type,
        }
        *ret_pointer = iov;
 
+       ret = -EFAULT;
+       if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
+               goto out;
+
        /*
         * Single unix specification:
         * We should -EINVAL if an element length is not >= 0 and fitting an
@@ -1080,17 +1084,12 @@ static ssize_t compat_do_readv_writev(int type, struct file *file,
        if (!file->f_op)
                goto out;
 
-       ret = -EFAULT;
-       if (!access_ok(VERIFY_READ, uvector, nr_segs*sizeof(*uvector)))
-               goto out;
-
-       tot_len = compat_rw_copy_check_uvector(type, uvector, nr_segs,
+       ret = compat_rw_copy_check_uvector(type, uvector, nr_segs,
                                               UIO_FASTIOV, iovstack, &iov);
-       if (tot_len == 0) {
-               ret = 0;
+       if (ret <= 0)
                goto out;
-       }
 
+       tot_len = ret;
        ret = rw_verify_area(type, file, pos, tot_len);
        if (ret < 0)
                goto out;
index fbfae008ba44e3e8223f42d4823cfeae2a673ac9..e8bc3420d63edcc28f0992217c860082fe424261 100644 (file)
@@ -2542,7 +2542,6 @@ static int prepend_path(const struct path *path,
        bool slash = false;
        int error = 0;
 
-       br_read_lock(&vfsmount_lock);
        while (dentry != root->dentry || vfsmnt != root->mnt) {
                struct dentry * parent;
 
@@ -2572,8 +2571,6 @@ static int prepend_path(const struct path *path,
        if (!error && !slash)
                error = prepend(buffer, buflen, "/", 1);
 
-out:
-       br_read_unlock(&vfsmount_lock);
        return error;
 
 global_root:
@@ -2590,7 +2587,7 @@ global_root:
                error = prepend(buffer, buflen, "/", 1);
        if (!error)
                error = is_mounted(vfsmnt) ? 1 : 2;
-       goto out;
+       return error;
 }
 
 /**
@@ -2617,9 +2614,11 @@ char *__d_path(const struct path *path,
        int error;
 
        prepend(&res, &buflen, "\0", 1);
+       br_read_lock(&vfsmount_lock);
        write_seqlock(&rename_lock);
        error = prepend_path(path, root, &res, &buflen);
        write_sequnlock(&rename_lock);
+       br_read_unlock(&vfsmount_lock);
 
        if (error < 0)
                return ERR_PTR(error);
@@ -2636,9 +2635,11 @@ char *d_absolute_path(const struct path *path,
        int error;
 
        prepend(&res, &buflen, "\0", 1);
+       br_read_lock(&vfsmount_lock);
        write_seqlock(&rename_lock);
        error = prepend_path(path, &root, &res, &buflen);
        write_sequnlock(&rename_lock);
+       br_read_unlock(&vfsmount_lock);
 
        if (error > 1)
                error = -EINVAL;
@@ -2702,11 +2703,13 @@ char *d_path(const struct path *path, char *buf, int buflen)
                return path->dentry->d_op->d_dname(path->dentry, buf, buflen);
 
        get_fs_root(current->fs, &root);
+       br_read_lock(&vfsmount_lock);
        write_seqlock(&rename_lock);
        error = path_with_deleted(path, &root, &res, &buflen);
+       write_sequnlock(&rename_lock);
+       br_read_unlock(&vfsmount_lock);
        if (error < 0)
                res = ERR_PTR(error);
-       write_sequnlock(&rename_lock);
        path_put(&root);
        return res;
 }
@@ -2830,6 +2833,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
        get_fs_root_and_pwd(current->fs, &root, &pwd);
 
        error = -ENOENT;
+       br_read_lock(&vfsmount_lock);
        write_seqlock(&rename_lock);
        if (!d_unlinked(pwd.dentry)) {
                unsigned long len;
@@ -2839,6 +2843,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
                prepend(&cwd, &buflen, "\0", 1);
                error = prepend_path(&pwd, &root, &cwd, &buflen);
                write_sequnlock(&rename_lock);
+               br_read_unlock(&vfsmount_lock);
 
                if (error < 0)
                        goto out;
@@ -2859,6 +2864,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
                }
        } else {
                write_sequnlock(&rename_lock);
+               br_read_unlock(&vfsmount_lock);
        }
 
 out:
index 8f370e012e613e73016856a9cab3c6257666a1a1..7cadd823bb311643a6cb7042222870767224b4c9 100644 (file)
@@ -118,7 +118,6 @@ void ext2_free_inode (struct inode * inode)
         * as writing the quota to disk may need the lock as well.
         */
        /* Quota is already initialized in iput() */
-       ext2_xattr_delete_inode(inode);
        dquot_free_inode(inode);
        dquot_drop(inode);
 
index c3881e56662efac8c80ec409c5808771303ed24f..fe60cc1117d834a1fbdc086b9aad01367518903b 100644 (file)
@@ -34,6 +34,7 @@
 #include "ext2.h"
 #include "acl.h"
 #include "xip.h"
+#include "xattr.h"
 
 static int __ext2_write_inode(struct inode *inode, int do_sync);
 
@@ -88,6 +89,7 @@ void ext2_evict_inode(struct inode * inode)
                inode->i_size = 0;
                if (inode->i_blocks)
                        ext2_truncate_blocks(inode, 0);
+               ext2_xattr_delete_inode(inode);
        }
 
        invalidate_inode_buffers(inode);
index 1d6e2ed853229edfebb4de3a51fff8e86846e1ae..fb5120a5505c055b9de9e7b948713256329cf690 100644 (file)
@@ -353,7 +353,7 @@ static struct block_device *ext3_blkdev_get(dev_t dev, struct super_block *sb)
        return bdev;
 
 fail:
-       ext3_msg(sb, "error: failed to open journal device %s: %ld",
+       ext3_msg(sb, KERN_ERR, "error: failed to open journal device %s: %ld",
                __bdevname(dev, b), PTR_ERR(bdev));
 
        return NULL;
@@ -887,7 +887,7 @@ static ext3_fsblk_t get_sb_block(void **data, struct super_block *sb)
        /*todo: use simple_strtoll with >32bit ext3 */
        sb_block = simple_strtoul(options, &options, 0);
        if (*options && *options != ',') {
-               ext3_msg(sb, "error: invalid sb specification: %s",
+               ext3_msg(sb, KERN_ERR, "error: invalid sb specification: %s",
                       (char *) *data);
                return 1;
        }
index 4a01ba315262259241081ec695c1f1d3d179eb32..3b83cd6047964ab7218aeb26ab73bce7be472430 100644 (file)
@@ -335,9 +335,9 @@ struct ext4_group_desc
  */
 
 struct flex_groups {
-       atomic_t free_inodes;
-       atomic_t free_clusters;
-       atomic_t used_dirs;
+       atomic64_t      free_clusters;
+       atomic_t        free_inodes;
+       atomic_t        used_dirs;
 };
 
 #define EXT4_BG_INODE_UNINIT   0x0001 /* Inode table/bitmap not in use */
@@ -2617,7 +2617,7 @@ extern int ext4_move_extents(struct file *o_filp, struct file *d_filp,
 extern int __init ext4_init_pageio(void);
 extern void ext4_add_complete_io(ext4_io_end_t *io_end);
 extern void ext4_exit_pageio(void);
-extern void ext4_ioend_wait(struct inode *);
+extern void ext4_ioend_shutdown(struct inode *);
 extern void ext4_free_io_end(ext4_io_end_t *io);
 extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags);
 extern void ext4_end_io_work(struct work_struct *work);
index 28dd8eeea6a93f2ce5ae727777ede13582e2038f..9c6d06dcef8bf1f997c0f05bfe443fcde993d72b 100644 (file)
@@ -1584,10 +1584,12 @@ ext4_can_extents_be_merged(struct inode *inode, struct ext4_extent *ex1,
        unsigned short ext1_ee_len, ext2_ee_len, max_len;
 
        /*
-        * Make sure that either both extents are uninitialized, or
-        * both are _not_.
+        * Make sure that both extents are initialized. We don't merge
+        * uninitialized extents so that we can be sure that end_io code has
+        * the extent that was written properly split out and conversion to
+        * initialized is trivial.
         */
-       if (ext4_ext_is_uninitialized(ex1) ^ ext4_ext_is_uninitialized(ex2))
+       if (ext4_ext_is_uninitialized(ex1) || ext4_ext_is_uninitialized(ex2))
                return 0;
 
        if (ext4_ext_is_uninitialized(ex1))
@@ -2923,7 +2925,7 @@ static int ext4_split_extent_at(handle_t *handle,
 {
        ext4_fsblk_t newblock;
        ext4_lblk_t ee_block;
-       struct ext4_extent *ex, newex, orig_ex;
+       struct ext4_extent *ex, newex, orig_ex, zero_ex;
        struct ext4_extent *ex2 = NULL;
        unsigned int ee_len, depth;
        int err = 0;
@@ -2943,6 +2945,10 @@ static int ext4_split_extent_at(handle_t *handle,
        newblock = split - ee_block + ext4_ext_pblock(ex);
 
        BUG_ON(split < ee_block || split >= (ee_block + ee_len));
+       BUG_ON(!ext4_ext_is_uninitialized(ex) &&
+              split_flag & (EXT4_EXT_MAY_ZEROOUT |
+                            EXT4_EXT_MARK_UNINIT1 |
+                            EXT4_EXT_MARK_UNINIT2));
 
        err = ext4_ext_get_access(handle, inode, path + depth);
        if (err)
@@ -2990,12 +2996,29 @@ static int ext4_split_extent_at(handle_t *handle,
        err = ext4_ext_insert_extent(handle, inode, path, &newex, flags);
        if (err == -ENOSPC && (EXT4_EXT_MAY_ZEROOUT & split_flag)) {
                if (split_flag & (EXT4_EXT_DATA_VALID1|EXT4_EXT_DATA_VALID2)) {
-                       if (split_flag & EXT4_EXT_DATA_VALID1)
+                       if (split_flag & EXT4_EXT_DATA_VALID1) {
                                err = ext4_ext_zeroout(inode, ex2);
-                       else
+                               zero_ex.ee_block = ex2->ee_block;
+                               zero_ex.ee_len = cpu_to_le16(
+                                               ext4_ext_get_actual_len(ex2));
+                               ext4_ext_store_pblock(&zero_ex,
+                                                     ext4_ext_pblock(ex2));
+                       } else {
                                err = ext4_ext_zeroout(inode, ex);
-               } else
+                               zero_ex.ee_block = ex->ee_block;
+                               zero_ex.ee_len = cpu_to_le16(
+                                               ext4_ext_get_actual_len(ex));
+                               ext4_ext_store_pblock(&zero_ex,
+                                                     ext4_ext_pblock(ex));
+                       }
+               } else {
                        err = ext4_ext_zeroout(inode, &orig_ex);
+                       zero_ex.ee_block = orig_ex.ee_block;
+                       zero_ex.ee_len = cpu_to_le16(
+                                               ext4_ext_get_actual_len(&orig_ex));
+                       ext4_ext_store_pblock(&zero_ex,
+                                             ext4_ext_pblock(&orig_ex));
+               }
 
                if (err)
                        goto fix_extent_len;
@@ -3003,6 +3026,12 @@ static int ext4_split_extent_at(handle_t *handle,
                ex->ee_len = cpu_to_le16(ee_len);
                ext4_ext_try_to_merge(handle, inode, path, ex);
                err = ext4_ext_dirty(handle, inode, path + path->p_depth);
+               if (err)
+                       goto fix_extent_len;
+
+               /* update extent status tree */
+               err = ext4_es_zeroout(inode, &zero_ex);
+
                goto out;
        } else if (err)
                goto fix_extent_len;
@@ -3041,6 +3070,7 @@ static int ext4_split_extent(handle_t *handle,
        int err = 0;
        int uninitialized;
        int split_flag1, flags1;
+       int allocated = map->m_len;
 
        depth = ext_depth(inode);
        ex = path[depth].p_ext;
@@ -3060,20 +3090,29 @@ static int ext4_split_extent(handle_t *handle,
                                map->m_lblk + map->m_len, split_flag1, flags1);
                if (err)
                        goto out;
+       } else {
+               allocated = ee_len - (map->m_lblk - ee_block);
        }
-
+       /*
+        * Update path is required because previous ext4_split_extent_at() may
+        * result in split of original leaf or extent zeroout.
+        */
        ext4_ext_drop_refs(path);
        path = ext4_ext_find_extent(inode, map->m_lblk, path);
        if (IS_ERR(path))
                return PTR_ERR(path);
+       depth = ext_depth(inode);
+       ex = path[depth].p_ext;
+       uninitialized = ext4_ext_is_uninitialized(ex);
+       split_flag1 = 0;
 
        if (map->m_lblk >= ee_block) {
-               split_flag1 = split_flag & (EXT4_EXT_MAY_ZEROOUT |
-                                           EXT4_EXT_DATA_VALID2);
-               if (uninitialized)
+               split_flag1 = split_flag & EXT4_EXT_DATA_VALID2;
+               if (uninitialized) {
                        split_flag1 |= EXT4_EXT_MARK_UNINIT1;
-               if (split_flag & EXT4_EXT_MARK_UNINIT2)
-                       split_flag1 |= EXT4_EXT_MARK_UNINIT2;
+                       split_flag1 |= split_flag & (EXT4_EXT_MAY_ZEROOUT |
+                                                    EXT4_EXT_MARK_UNINIT2);
+               }
                err = ext4_split_extent_at(handle, inode, path,
                                map->m_lblk, split_flag1, flags);
                if (err)
@@ -3082,7 +3121,7 @@ static int ext4_split_extent(handle_t *handle,
 
        ext4_ext_show_leaf(inode, path);
 out:
-       return err ? err : map->m_len;
+       return err ? err : allocated;
 }
 
 /*
@@ -3137,6 +3176,7 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
        ee_block = le32_to_cpu(ex->ee_block);
        ee_len = ext4_ext_get_actual_len(ex);
        allocated = ee_len - (map->m_lblk - ee_block);
+       zero_ex.ee_len = 0;
 
        trace_ext4_ext_convert_to_initialized_enter(inode, map, ex);
 
@@ -3227,13 +3267,16 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
 
        if (EXT4_EXT_MAY_ZEROOUT & split_flag)
                max_zeroout = sbi->s_extent_max_zeroout_kb >>
-                       inode->i_sb->s_blocksize_bits;
+                       (inode->i_sb->s_blocksize_bits - 10);
 
        /* If extent is less than s_max_zeroout_kb, zeroout directly */
        if (max_zeroout && (ee_len <= max_zeroout)) {
                err = ext4_ext_zeroout(inode, ex);
                if (err)
                        goto out;
+               zero_ex.ee_block = ex->ee_block;
+               zero_ex.ee_len = cpu_to_le16(ext4_ext_get_actual_len(ex));
+               ext4_ext_store_pblock(&zero_ex, ext4_ext_pblock(ex));
 
                err = ext4_ext_get_access(handle, inode, path + depth);
                if (err)
@@ -3292,6 +3335,9 @@ static int ext4_ext_convert_to_initialized(handle_t *handle,
                err = allocated;
 
 out:
+       /* If we have gotten a failure, don't zero out status tree */
+       if (!err)
+               err = ext4_es_zeroout(inode, &zero_ex);
        return err ? err : allocated;
 }
 
@@ -3374,8 +3420,19 @@ static int ext4_convert_unwritten_extents_endio(handle_t *handle,
                "block %llu, max_blocks %u\n", inode->i_ino,
                  (unsigned long long)ee_block, ee_len);
 
-       /* If extent is larger than requested then split is required */
+       /* If extent is larger than requested it is a clear sign that we still
+        * have some extent state machine issues left. So extent_split is still
+        * required.
+        * TODO: Once all related issues will be fixed this situation should be
+        * illegal.
+        */
        if (ee_block != map->m_lblk || ee_len > map->m_len) {
+#ifdef EXT4_DEBUG
+               ext4_warning("Inode (%ld) finished: extent logical block %llu,"
+                            " len %u; IO logical block %llu, len %u\n",
+                            inode->i_ino, (unsigned long long)ee_block, ee_len,
+                            (unsigned long long)map->m_lblk, map->m_len);
+#endif
                err = ext4_split_unwritten_extents(handle, inode, map, path,
                                                   EXT4_GET_BLOCKS_CONVERT);
                if (err < 0)
@@ -3626,6 +3683,10 @@ ext4_ext_handle_uninitialized_extents(handle_t *handle, struct inode *inode,
                                                 path, map->m_len);
                } else
                        err = ret;
+               map->m_flags |= EXT4_MAP_MAPPED;
+               if (allocated > map->m_len)
+                       allocated = map->m_len;
+               map->m_len = allocated;
                goto out2;
        }
        /* buffered IO case */
@@ -3675,6 +3736,7 @@ out:
                                        allocated - map->m_len);
                allocated = map->m_len;
        }
+       map->m_len = allocated;
 
        /*
         * If we have done fallocate with the offset that is already
@@ -4106,9 +4168,6 @@ got_allocated_blocks:
                        }
                } else {
                        BUG_ON(allocated_clusters < reserved_clusters);
-                       /* We will claim quota for all newly allocated blocks.*/
-                       ext4_da_update_reserve_space(inode, allocated_clusters,
-                                                       1);
                        if (reserved_clusters < allocated_clusters) {
                                struct ext4_inode_info *ei = EXT4_I(inode);
                                int reservation = allocated_clusters -
@@ -4159,6 +4218,15 @@ got_allocated_blocks:
                                ei->i_reserved_data_blocks += reservation;
                                spin_unlock(&ei->i_block_reservation_lock);
                        }
+                       /*
+                        * We will claim quota for all newly allocated blocks.
+                        * We're updating the reserved space *after* the
+                        * correction above so we do not accidentally free
+                        * all the metadata reservation because we might
+                        * actually need it later on.
+                        */
+                       ext4_da_update_reserve_space(inode, allocated_clusters,
+                                                       1);
                }
        }
 
@@ -4368,8 +4436,6 @@ long ext4_fallocate(struct file *file, int mode, loff_t offset, loff_t len)
        if (len <= EXT_UNINIT_MAX_LEN << blkbits)
                flags |= EXT4_GET_BLOCKS_NO_NORMALIZE;
 
-       /* Prevent race condition between unwritten */
-       ext4_flush_unwritten_io(inode);
 retry:
        while (ret >= 0 && ret < max_blocks) {
                map.m_lblk = map.m_lblk + ret;
index 95796a1b7522b7e02dd72dfab15fbf2cebdb6b13..fe3337a85edeaecd6135333759173d8c6fbc0e78 100644 (file)
@@ -333,17 +333,27 @@ static void ext4_es_free_extent(struct inode *inode, struct extent_status *es)
 static int ext4_es_can_be_merged(struct extent_status *es1,
                                 struct extent_status *es2)
 {
-       if (es1->es_lblk + es1->es_len != es2->es_lblk)
+       if (ext4_es_status(es1) != ext4_es_status(es2))
                return 0;
 
-       if (ext4_es_status(es1) != ext4_es_status(es2))
+       if (((__u64) es1->es_len) + es2->es_len > 0xFFFFFFFFULL)
                return 0;
 
-       if ((ext4_es_is_written(es1) || ext4_es_is_unwritten(es1)) &&
-           (ext4_es_pblock(es1) + es1->es_len != ext4_es_pblock(es2)))
+       if (((__u64) es1->es_lblk) + es1->es_len != es2->es_lblk)
                return 0;
 
-       return 1;
+       if ((ext4_es_is_written(es1) || ext4_es_is_unwritten(es1)) &&
+           (ext4_es_pblock(es1) + es1->es_len == ext4_es_pblock(es2)))
+               return 1;
+
+       if (ext4_es_is_hole(es1))
+               return 1;
+
+       /* we need to check delayed extent is without unwritten status */
+       if (ext4_es_is_delayed(es1) && !ext4_es_is_unwritten(es1))
+               return 1;
+
+       return 0;
 }
 
 static struct extent_status *
@@ -389,6 +399,179 @@ ext4_es_try_to_merge_right(struct inode *inode, struct extent_status *es)
        return es;
 }
 
+#ifdef ES_AGGRESSIVE_TEST
+static void ext4_es_insert_extent_ext_check(struct inode *inode,
+                                           struct extent_status *es)
+{
+       struct ext4_ext_path *path = NULL;
+       struct ext4_extent *ex;
+       ext4_lblk_t ee_block;
+       ext4_fsblk_t ee_start;
+       unsigned short ee_len;
+       int depth, ee_status, es_status;
+
+       path = ext4_ext_find_extent(inode, es->es_lblk, NULL);
+       if (IS_ERR(path))
+               return;
+
+       depth = ext_depth(inode);
+       ex = path[depth].p_ext;
+
+       if (ex) {
+
+               ee_block = le32_to_cpu(ex->ee_block);
+               ee_start = ext4_ext_pblock(ex);
+               ee_len = ext4_ext_get_actual_len(ex);
+
+               ee_status = ext4_ext_is_uninitialized(ex) ? 1 : 0;
+               es_status = ext4_es_is_unwritten(es) ? 1 : 0;
+
+               /*
+                * Make sure ex and es are not overlap when we try to insert
+                * a delayed/hole extent.
+                */
+               if (!ext4_es_is_written(es) && !ext4_es_is_unwritten(es)) {
+                       if (in_range(es->es_lblk, ee_block, ee_len)) {
+                               pr_warn("ES insert assertation failed for "
+                                       "inode: %lu we can find an extent "
+                                       "at block [%d/%d/%llu/%c], but we "
+                                       "want to add an delayed/hole extent "
+                                       "[%d/%d/%llu/%llx]\n",
+                                       inode->i_ino, ee_block, ee_len,
+                                       ee_start, ee_status ? 'u' : 'w',
+                                       es->es_lblk, es->es_len,
+                                       ext4_es_pblock(es), ext4_es_status(es));
+                       }
+                       goto out;
+               }
+
+               /*
+                * We don't check ee_block == es->es_lblk, etc. because es
+                * might be a part of whole extent, vice versa.
+                */
+               if (es->es_lblk < ee_block ||
+                   ext4_es_pblock(es) != ee_start + es->es_lblk - ee_block) {
+                       pr_warn("ES insert assertation failed for inode: %lu "
+                               "ex_status [%d/%d/%llu/%c] != "
+                               "es_status [%d/%d/%llu/%c]\n", inode->i_ino,
+                               ee_block, ee_len, ee_start,
+                               ee_status ? 'u' : 'w', es->es_lblk, es->es_len,
+                               ext4_es_pblock(es), es_status ? 'u' : 'w');
+                       goto out;
+               }
+
+               if (ee_status ^ es_status) {
+                       pr_warn("ES insert assertation failed for inode: %lu "
+                               "ex_status [%d/%d/%llu/%c] != "
+                               "es_status [%d/%d/%llu/%c]\n", inode->i_ino,
+                               ee_block, ee_len, ee_start,
+                               ee_status ? 'u' : 'w', es->es_lblk, es->es_len,
+                               ext4_es_pblock(es), es_status ? 'u' : 'w');
+               }
+       } else {
+               /*
+                * We can't find an extent on disk.  So we need to make sure
+                * that we don't want to add an written/unwritten extent.
+                */
+               if (!ext4_es_is_delayed(es) && !ext4_es_is_hole(es)) {
+                       pr_warn("ES insert assertation failed for inode: %lu "
+                               "can't find an extent at block %d but we want "
+                               "to add an written/unwritten extent "
+                               "[%d/%d/%llu/%llx]\n", inode->i_ino,
+                               es->es_lblk, es->es_lblk, es->es_len,
+                               ext4_es_pblock(es), ext4_es_status(es));
+               }
+       }
+out:
+       if (path) {
+               ext4_ext_drop_refs(path);
+               kfree(path);
+       }
+}
+
+static void ext4_es_insert_extent_ind_check(struct inode *inode,
+                                           struct extent_status *es)
+{
+       struct ext4_map_blocks map;
+       int retval;
+
+       /*
+        * Here we call ext4_ind_map_blocks to lookup a block mapping because
+        * 'Indirect' structure is defined in indirect.c.  So we couldn't
+        * access direct/indirect tree from outside.  It is too dirty to define
+        * this function in indirect.c file.
+        */
+
+       map.m_lblk = es->es_lblk;
+       map.m_len = es->es_len;
+
+       retval = ext4_ind_map_blocks(NULL, inode, &map, 0);
+       if (retval > 0) {
+               if (ext4_es_is_delayed(es) || ext4_es_is_hole(es)) {
+                       /*
+                        * We want to add a delayed/hole extent but this
+                        * block has been allocated.
+                        */
+                       pr_warn("ES insert assertation failed for inode: %lu "
+                               "We can find blocks but we want to add a "
+                               "delayed/hole extent [%d/%d/%llu/%llx]\n",
+                               inode->i_ino, es->es_lblk, es->es_len,
+                               ext4_es_pblock(es), ext4_es_status(es));
+                       return;
+               } else if (ext4_es_is_written(es)) {
+                       if (retval != es->es_len) {
+                               pr_warn("ES insert assertation failed for "
+                                       "inode: %lu retval %d != es_len %d\n",
+                                       inode->i_ino, retval, es->es_len);
+                               return;
+                       }
+                       if (map.m_pblk != ext4_es_pblock(es)) {
+                               pr_warn("ES insert assertation failed for "
+                                       "inode: %lu m_pblk %llu != "
+                                       "es_pblk %llu\n",
+                                       inode->i_ino, map.m_pblk,
+                                       ext4_es_pblock(es));
+                               return;
+                       }
+               } else {
+                       /*
+                        * We don't need to check unwritten extent because
+                        * indirect-based file doesn't have it.
+                        */
+                       BUG_ON(1);
+               }
+       } else if (retval == 0) {
+               if (ext4_es_is_written(es)) {
+                       pr_warn("ES insert assertation failed for inode: %lu "
+                               "We can't find the block but we want to add "
+                               "an written extent [%d/%d/%llu/%llx]\n",
+                               inode->i_ino, es->es_lblk, es->es_len,
+                               ext4_es_pblock(es), ext4_es_status(es));
+                       return;
+               }
+       }
+}
+
+static inline void ext4_es_insert_extent_check(struct inode *inode,
+                                              struct extent_status *es)
+{
+       /*
+        * We don't need to worry about the race condition because
+        * caller takes i_data_sem locking.
+        */
+       BUG_ON(!rwsem_is_locked(&EXT4_I(inode)->i_data_sem));
+       if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))
+               ext4_es_insert_extent_ext_check(inode, es);
+       else
+               ext4_es_insert_extent_ind_check(inode, es);
+}
+#else
+static inline void ext4_es_insert_extent_check(struct inode *inode,
+                                              struct extent_status *es)
+{
+}
+#endif
+
 static int __es_insert_extent(struct inode *inode, struct extent_status *newes)
 {
        struct ext4_es_tree *tree = &EXT4_I(inode)->i_es_tree;
@@ -471,6 +654,8 @@ int ext4_es_insert_extent(struct inode *inode, ext4_lblk_t lblk,
        ext4_es_store_status(&newes, status);
        trace_ext4_es_insert_extent(inode, &newes);
 
+       ext4_es_insert_extent_check(inode, &newes);
+
        write_lock(&EXT4_I(inode)->i_es_lock);
        err = __es_remove_extent(inode, lblk, end);
        if (err != 0)
@@ -669,6 +854,23 @@ int ext4_es_remove_extent(struct inode *inode, ext4_lblk_t lblk,
        return err;
 }
 
+int ext4_es_zeroout(struct inode *inode, struct ext4_extent *ex)
+{
+       ext4_lblk_t  ee_block;
+       ext4_fsblk_t ee_pblock;
+       unsigned int ee_len;
+
+       ee_block  = le32_to_cpu(ex->ee_block);
+       ee_len    = ext4_ext_get_actual_len(ex);
+       ee_pblock = ext4_ext_pblock(ex);
+
+       if (ee_len == 0)
+               return 0;
+
+       return ext4_es_insert_extent(inode, ee_block, ee_len, ee_pblock,
+                                    EXTENT_STATUS_WRITTEN);
+}
+
 static int ext4_es_shrink(struct shrinker *shrink, struct shrink_control *sc)
 {
        struct ext4_sb_info *sbi = container_of(shrink,
index f190dfe969dacc59e34d15f03e2a7c5e3c5ef5e2..d8e2d4dc311e62c99843fa16c7fc8d4a0798bddb 100644 (file)
 #define es_debug(fmt, ...)     no_printk(fmt, ##__VA_ARGS__)
 #endif
 
+/*
+ * With ES_AGGRESSIVE_TEST defined, the result of es caching will be
+ * checked with old map_block's result.
+ */
+#define ES_AGGRESSIVE_TEST__
+
 /*
  * These flags live in the high bits of extent_status.es_pblk
  */
@@ -33,6 +39,8 @@
                                 EXTENT_STATUS_DELAYED | \
                                 EXTENT_STATUS_HOLE)
 
+struct ext4_extent;
+
 struct extent_status {
        struct rb_node rb_node;
        ext4_lblk_t es_lblk;    /* first logical block extent covers */
@@ -58,6 +66,7 @@ extern void ext4_es_find_delayed_extent(struct inode *inode, ext4_lblk_t lblk,
                                        struct extent_status *es);
 extern int ext4_es_lookup_extent(struct inode *inode, ext4_lblk_t lblk,
                                 struct extent_status *es);
+extern int ext4_es_zeroout(struct inode *inode, struct ext4_extent *ex);
 
 static inline int ext4_es_is_written(struct extent_status *es)
 {
index 32fd2b9075dd4029925d11adb0b84df1a399a8b1..6c5bb8d993fe8ebb07ae48dab2697e247c78ea01 100644 (file)
@@ -324,8 +324,8 @@ error_return:
 }
 
 struct orlov_stats {
+       __u64 free_clusters;
        __u32 free_inodes;
-       __u32 free_clusters;
        __u32 used_dirs;
 };
 
@@ -342,7 +342,7 @@ static void get_orlov_stats(struct super_block *sb, ext4_group_t g,
 
        if (flex_size > 1) {
                stats->free_inodes = atomic_read(&flex_group[g].free_inodes);
-               stats->free_clusters = atomic_read(&flex_group[g].free_clusters);
+               stats->free_clusters = atomic64_read(&flex_group[g].free_clusters);
                stats->used_dirs = atomic_read(&flex_group[g].used_dirs);
                return;
        }
index b505a145a5937a426184d5c289b6825ee62d0e17..a04183127ef049190ad96c0b7052ea4495fd33e9 100644 (file)
@@ -1539,9 +1539,9 @@ static int free_hole_blocks(handle_t *handle, struct inode *inode,
                blk = *i_data;
                if (level > 0) {
                        ext4_lblk_t first2;
-                       bh = sb_bread(inode->i_sb, blk);
+                       bh = sb_bread(inode->i_sb, le32_to_cpu(blk));
                        if (!bh) {
-                               EXT4_ERROR_INODE_BLOCK(inode, blk,
+                               EXT4_ERROR_INODE_BLOCK(inode, le32_to_cpu(blk),
                                                       "Read failure");
                                return -EIO;
                        }
index 9ea0cde3fa9e0ffe7aebc28940293c422ae75a63..b3a5213bc73eac2082cbfa16bad66bba89c32ed4 100644 (file)
@@ -185,8 +185,6 @@ void ext4_evict_inode(struct inode *inode)
 
        trace_ext4_evict_inode(inode);
 
-       ext4_ioend_wait(inode);
-
        if (inode->i_nlink) {
                /*
                 * When journalling data dirty buffers are tracked only in the
@@ -207,7 +205,8 @@ void ext4_evict_inode(struct inode *inode)
                 * don't use page cache.
                 */
                if (ext4_should_journal_data(inode) &&
-                   (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode))) {
+                   (S_ISLNK(inode->i_mode) || S_ISREG(inode->i_mode)) &&
+                   inode->i_ino != EXT4_JOURNAL_INO) {
                        journal_t *journal = EXT4_SB(inode->i_sb)->s_journal;
                        tid_t commit_tid = EXT4_I(inode)->i_datasync_tid;
 
@@ -216,6 +215,7 @@ void ext4_evict_inode(struct inode *inode)
                        filemap_write_and_wait(&inode->i_data);
                }
                truncate_inode_pages(&inode->i_data, 0);
+               ext4_ioend_shutdown(inode);
                goto no_delete;
        }
 
@@ -225,6 +225,7 @@ void ext4_evict_inode(struct inode *inode)
        if (ext4_should_order_data(inode))
                ext4_begin_ordered_truncate(inode, 0);
        truncate_inode_pages(&inode->i_data, 0);
+       ext4_ioend_shutdown(inode);
 
        if (is_bad_inode(inode))
                goto no_delete;
@@ -482,6 +483,58 @@ static pgoff_t ext4_num_dirty_pages(struct inode *inode, pgoff_t idx,
        return num;
 }
 
+#ifdef ES_AGGRESSIVE_TEST
+static void ext4_map_blocks_es_recheck(handle_t *handle,
+                                      struct inode *inode,
+                                      struct ext4_map_blocks *es_map,
+                                      struct ext4_map_blocks *map,
+                                      int flags)
+{
+       int retval;
+
+       map->m_flags = 0;
+       /*
+        * There is a race window that the result is not the same.
+        * e.g. xfstests #223 when dioread_nolock enables.  The reason
+        * is that we lookup a block mapping in extent status tree with
+        * out taking i_data_sem.  So at the time the unwritten extent
+        * could be converted.
+        */
+       if (!(flags & EXT4_GET_BLOCKS_NO_LOCK))
+               down_read((&EXT4_I(inode)->i_data_sem));
+       if (ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) {
+               retval = ext4_ext_map_blocks(handle, inode, map, flags &
+                                            EXT4_GET_BLOCKS_KEEP_SIZE);
+       } else {
+               retval = ext4_ind_map_blocks(handle, inode, map, flags &
+                                            EXT4_GET_BLOCKS_KEEP_SIZE);
+       }
+       if (!(flags & EXT4_GET_BLOCKS_NO_LOCK))
+               up_read((&EXT4_I(inode)->i_data_sem));
+       /*
+        * Clear EXT4_MAP_FROM_CLUSTER and EXT4_MAP_BOUNDARY flag
+        * because it shouldn't be marked in es_map->m_flags.
+        */
+       map->m_flags &= ~(EXT4_MAP_FROM_CLUSTER | EXT4_MAP_BOUNDARY);
+
+       /*
+        * We don't check m_len because extent will be collpased in status
+        * tree.  So the m_len might not equal.
+        */
+       if (es_map->m_lblk != map->m_lblk ||
+           es_map->m_flags != map->m_flags ||
+           es_map->m_pblk != map->m_pblk) {
+               printk("ES cache assertation failed for inode: %lu "
+                      "es_cached ex [%d/%d/%llu/%x] != "
+                      "found ex [%d/%d/%llu/%x] retval %d flags %x\n",
+                      inode->i_ino, es_map->m_lblk, es_map->m_len,
+                      es_map->m_pblk, es_map->m_flags, map->m_lblk,
+                      map->m_len, map->m_pblk, map->m_flags,
+                      retval, flags);
+       }
+}
+#endif /* ES_AGGRESSIVE_TEST */
+
 /*
  * The ext4_map_blocks() function tries to look up the requested blocks,
  * and returns if the blocks are already mapped.
@@ -509,6 +562,11 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
 {
        struct extent_status es;
        int retval;
+#ifdef ES_AGGRESSIVE_TEST
+       struct ext4_map_blocks orig_map;
+
+       memcpy(&orig_map, map, sizeof(*map));
+#endif
 
        map->m_flags = 0;
        ext_debug("ext4_map_blocks(): inode %lu, flag %d, max_blocks %u,"
@@ -531,6 +589,10 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
                } else {
                        BUG_ON(1);
                }
+#ifdef ES_AGGRESSIVE_TEST
+               ext4_map_blocks_es_recheck(handle, inode, map,
+                                          &orig_map, flags);
+#endif
                goto found;
        }
 
@@ -551,6 +613,15 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
                int ret;
                unsigned long long status;
 
+#ifdef ES_AGGRESSIVE_TEST
+               if (retval != map->m_len) {
+                       printk("ES len assertation failed for inode: %lu "
+                              "retval %d != map->m_len %d "
+                              "in %s (lookup)\n", inode->i_ino, retval,
+                              map->m_len, __func__);
+               }
+#endif
+
                status = map->m_flags & EXT4_MAP_UNWRITTEN ?
                                EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
                if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) &&
@@ -643,6 +714,24 @@ found:
                int ret;
                unsigned long long status;
 
+#ifdef ES_AGGRESSIVE_TEST
+               if (retval != map->m_len) {
+                       printk("ES len assertation failed for inode: %lu "
+                              "retval %d != map->m_len %d "
+                              "in %s (allocation)\n", inode->i_ino, retval,
+                              map->m_len, __func__);
+               }
+#endif
+
+               /*
+                * If the extent has been zeroed out, we don't need to update
+                * extent status tree.
+                */
+               if ((flags & EXT4_GET_BLOCKS_PRE_IO) &&
+                   ext4_es_lookup_extent(inode, map->m_lblk, &es)) {
+                       if (ext4_es_is_written(&es))
+                               goto has_zeroout;
+               }
                status = map->m_flags & EXT4_MAP_UNWRITTEN ?
                                EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
                if (!(flags & EXT4_GET_BLOCKS_DELALLOC_RESERVE) &&
@@ -655,6 +744,7 @@ found:
                        retval = ret;
        }
 
+has_zeroout:
        up_write((&EXT4_I(inode)->i_data_sem));
        if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
                int ret = check_block_validity(inode, map);
@@ -1215,6 +1305,55 @@ static int ext4_journalled_write_end(struct file *file,
        return ret ? ret : copied;
 }
 
+/*
+ * Reserve a metadata for a single block located at lblock
+ */
+static int ext4_da_reserve_metadata(struct inode *inode, ext4_lblk_t lblock)
+{
+       int retries = 0;
+       struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb);
+       struct ext4_inode_info *ei = EXT4_I(inode);
+       unsigned int md_needed;
+       ext4_lblk_t save_last_lblock;
+       int save_len;
+
+       /*
+        * recalculate the amount of metadata blocks to reserve
+        * in order to allocate nrblocks
+        * worse case is one extent per block
+        */
+repeat:
+       spin_lock(&ei->i_block_reservation_lock);
+       /*
+        * ext4_calc_metadata_amount() has side effects, which we have
+        * to be prepared undo if we fail to claim space.
+        */
+       save_len = ei->i_da_metadata_calc_len;
+       save_last_lblock = ei->i_da_metadata_calc_last_lblock;
+       md_needed = EXT4_NUM_B2C(sbi,
+                                ext4_calc_metadata_amount(inode, lblock));
+       trace_ext4_da_reserve_space(inode, md_needed);
+
+       /*
+        * We do still charge estimated metadata to the sb though;
+        * we cannot afford to run out of free blocks.
+        */
+       if (ext4_claim_free_clusters(sbi, md_needed, 0)) {
+               ei->i_da_metadata_calc_len = save_len;
+               ei->i_da_metadata_calc_last_lblock = save_last_lblock;
+               spin_unlock(&ei->i_block_reservation_lock);
+               if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
+                       cond_resched();
+                       goto repeat;
+               }
+               return -ENOSPC;
+       }
+       ei->i_reserved_meta_blocks += md_needed;
+       spin_unlock(&ei->i_block_reservation_lock);
+
+       return 0;       /* success */
+}
+
 /*
  * Reserve a single cluster located at lblock
  */
@@ -1263,7 +1402,7 @@ repeat:
                ei->i_da_metadata_calc_last_lblock = save_last_lblock;
                spin_unlock(&ei->i_block_reservation_lock);
                if (ext4_should_retry_alloc(inode->i_sb, &retries)) {
-                       yield();
+                       cond_resched();
                        goto repeat;
                }
                dquot_release_reservation_block(inode, EXT4_C2B(sbi, 1));
@@ -1768,6 +1907,11 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
        struct extent_status es;
        int retval;
        sector_t invalid_block = ~((sector_t) 0xffff);
+#ifdef ES_AGGRESSIVE_TEST
+       struct ext4_map_blocks orig_map;
+
+       memcpy(&orig_map, map, sizeof(*map));
+#endif
 
        if (invalid_block < ext4_blocks_count(EXT4_SB(inode->i_sb)->s_es))
                invalid_block = ~0;
@@ -1809,6 +1953,9 @@ static int ext4_da_map_blocks(struct inode *inode, sector_t iblock,
                else
                        BUG_ON(1);
 
+#ifdef ES_AGGRESSIVE_TEST
+               ext4_map_blocks_es_recheck(NULL, inode, map, &orig_map, 0);
+#endif
                return retval;
        }
 
@@ -1843,8 +1990,11 @@ add_delayed:
                 * XXX: __block_prepare_write() unmaps passed block,
                 * is it OK?
                 */
-               /* If the block was allocated from previously allocated cluster,
-                * then we dont need to reserve it again. */
+               /*
+                * If the block was allocated from previously allocated cluster,
+                * then we don't need to reserve it again. However we still need
+                * to reserve metadata for every block we're going to write.
+                */
                if (!(map->m_flags & EXT4_MAP_FROM_CLUSTER)) {
                        ret = ext4_da_reserve_space(inode, iblock);
                        if (ret) {
@@ -1852,6 +2002,13 @@ add_delayed:
                                retval = ret;
                                goto out_unlock;
                        }
+               } else {
+                       ret = ext4_da_reserve_metadata(inode, iblock);
+                       if (ret) {
+                               /* not enough space to reserve */
+                               retval = ret;
+                               goto out_unlock;
+                       }
                }
 
                ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len,
@@ -1873,6 +2030,15 @@ add_delayed:
                int ret;
                unsigned long long status;
 
+#ifdef ES_AGGRESSIVE_TEST
+               if (retval != map->m_len) {
+                       printk("ES len assertation failed for inode: %lu "
+                              "retval %d != map->m_len %d "
+                              "in %s (lookup)\n", inode->i_ino, retval,
+                              map->m_len, __func__);
+               }
+#endif
+
                status = map->m_flags & EXT4_MAP_UNWRITTEN ?
                                EXTENT_STATUS_UNWRITTEN : EXTENT_STATUS_WRITTEN;
                ret = ext4_es_insert_extent(inode, map->m_lblk, map->m_len,
@@ -2908,8 +3074,8 @@ static int ext4_releasepage(struct page *page, gfp_t wait)
 
        trace_ext4_releasepage(page);
 
-       WARN_ON(PageChecked(page));
-       if (!page_has_buffers(page))
+       /* Page has dirty journalled data -> cannot release */
+       if (PageChecked(page))
                return 0;
        if (journal)
                return jbd2_journal_try_to_free_buffers(journal, page, wait);
index 7bb713a46fe4c3f85ae9d35bd15bea73aa7957f5..ee6614bdb63950b7481443f944ca3c87681903be 100644 (file)
@@ -2804,8 +2804,8 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac,
        if (sbi->s_log_groups_per_flex) {
                ext4_group_t flex_group = ext4_flex_group(sbi,
                                                          ac->ac_b_ex.fe_group);
-               atomic_sub(ac->ac_b_ex.fe_len,
-                          &sbi->s_flex_groups[flex_group].free_clusters);
+               atomic64_sub(ac->ac_b_ex.fe_len,
+                            &sbi->s_flex_groups[flex_group].free_clusters);
        }
 
        err = ext4_handle_dirty_metadata(handle, NULL, bitmap_bh);
@@ -3692,11 +3692,7 @@ repeat:
        if (free < needed && busy) {
                busy = 0;
                ext4_unlock_group(sb, group);
-               /*
-                * Yield the CPU here so that we don't get soft lockup
-                * in non preempt case.
-                */
-               yield();
+               cond_resched();
                goto repeat;
        }
 
@@ -4246,7 +4242,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle,
                        ext4_claim_free_clusters(sbi, ar->len, ar->flags)) {
 
                        /* let others to free the space */
-                       yield();
+                       cond_resched();
                        ar->len = ar->len >> 1;
                }
                if (!ar->len) {
@@ -4464,7 +4460,6 @@ void ext4_free_blocks(handle_t *handle, struct inode *inode,
        struct buffer_head *bitmap_bh = NULL;
        struct super_block *sb = inode->i_sb;
        struct ext4_group_desc *gdp;
-       unsigned long freed = 0;
        unsigned int overflow;
        ext4_grpblk_t bit;
        struct buffer_head *gd_bh;
@@ -4666,14 +4661,12 @@ do_more:
 
        if (sbi->s_log_groups_per_flex) {
                ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
-               atomic_add(count_clusters,
-                          &sbi->s_flex_groups[flex_group].free_clusters);
+               atomic64_add(count_clusters,
+                            &sbi->s_flex_groups[flex_group].free_clusters);
        }
 
        ext4_mb_unload_buddy(&e4b);
 
-       freed += count;
-
        if (!(flags & EXT4_FREE_BLOCKS_NO_QUOT_UPDATE))
                dquot_free_block(inode, EXT4_C2B(sbi, count_clusters));
 
@@ -4811,8 +4804,8 @@ int ext4_group_add_blocks(handle_t *handle, struct super_block *sb,
 
        if (sbi->s_log_groups_per_flex) {
                ext4_group_t flex_group = ext4_flex_group(sbi, block_group);
-               atomic_add(EXT4_NUM_B2C(sbi, blocks_freed),
-                          &sbi->s_flex_groups[flex_group].free_clusters);
+               atomic64_add(EXT4_NUM_B2C(sbi, blocks_freed),
+                            &sbi->s_flex_groups[flex_group].free_clusters);
        }
 
        ext4_mb_unload_buddy(&e4b);
index 4e81d47aa8cb8af0553b93c1cb7dcbbea2d5d0a8..33e1c086858b54ad704e80345c92b946ae3c565b 100644 (file)
  */
 static inline int
 get_ext_path(struct inode *inode, ext4_lblk_t lblock,
-               struct ext4_ext_path **path)
+               struct ext4_ext_path **orig_path)
 {
        int ret = 0;
+       struct ext4_ext_path *path;
 
-       *path = ext4_ext_find_extent(inode, lblock, *path);
-       if (IS_ERR(*path)) {
-               ret = PTR_ERR(*path);
-               *path = NULL;
-       } else if ((*path)[ext_depth(inode)].p_ext == NULL)
+       path = ext4_ext_find_extent(inode, lblock, *orig_path);
+       if (IS_ERR(path))
+               ret = PTR_ERR(path);
+       else if (path[ext_depth(inode)].p_ext == NULL)
                ret = -ENODATA;
+       else
+               *orig_path = path;
 
        return ret;
 }
@@ -611,24 +613,25 @@ mext_check_coverage(struct inode *inode, ext4_lblk_t from, ext4_lblk_t count,
 {
        struct ext4_ext_path *path = NULL;
        struct ext4_extent *ext;
+       int ret = 0;
        ext4_lblk_t last = from + count;
        while (from < last) {
                *err = get_ext_path(inode, from, &path);
                if (*err)
-                       return 0;
+                       goto out;
                ext = path[ext_depth(inode)].p_ext;
-               if (!ext) {
-                       ext4_ext_drop_refs(path);
-                       return 0;
-               }
-               if (uninit != ext4_ext_is_uninitialized(ext)) {
-                       ext4_ext_drop_refs(path);
-                       return 0;
-               }
+               if (uninit != ext4_ext_is_uninitialized(ext))
+                       goto out;
                from += ext4_ext_get_actual_len(ext);
                ext4_ext_drop_refs(path);
        }
-       return 1;
+       ret = 1;
+out:
+       if (path) {
+               ext4_ext_drop_refs(path);
+               kfree(path);
+       }
+       return ret;
 }
 
 /**
@@ -666,6 +669,14 @@ mext_replace_branches(handle_t *handle, struct inode *orig_inode,
        int replaced_count = 0;
        int dext_alen;
 
+       *err = ext4_es_remove_extent(orig_inode, from, count);
+       if (*err)
+               goto out;
+
+       *err = ext4_es_remove_extent(donor_inode, from, count);
+       if (*err)
+               goto out;
+
        /* Get the original extent for the block "orig_off" */
        *err = get_ext_path(orig_inode, orig_off, &orig_path);
        if (*err)
index 809b31003ecc0fedd35d71e8abed4047bbe18beb..047a6de04a0ac8195d5453de514a8e95526fcce4 100644 (file)
@@ -50,11 +50,21 @@ void ext4_exit_pageio(void)
        kmem_cache_destroy(io_page_cachep);
 }
 
-void ext4_ioend_wait(struct inode *inode)
+/*
+ * This function is called by ext4_evict_inode() to make sure there is
+ * no more pending I/O completion work left to do.
+ */
+void ext4_ioend_shutdown(struct inode *inode)
 {
        wait_queue_head_t *wq = ext4_ioend_wq(inode);
 
        wait_event(*wq, (atomic_read(&EXT4_I(inode)->i_ioend_count) == 0));
+       /*
+        * We need to make sure the work structure is finished being
+        * used before we let the inode get destroyed.
+        */
+       if (work_pending(&EXT4_I(inode)->i_unwritten_work))
+               cancel_work_sync(&EXT4_I(inode)->i_unwritten_work);
 }
 
 static void put_io_page(struct ext4_io_page *io_page)
index b2c8ee56eb98744ab7481e4d0849e2fb5ca71365..c169477a62c987a1ba2d3362dde6bd8d3cd0f260 100644 (file)
@@ -1360,8 +1360,8 @@ static void ext4_update_super(struct super_block *sb,
            sbi->s_log_groups_per_flex) {
                ext4_group_t flex_group;
                flex_group = ext4_flex_group(sbi, group_data[0].group);
-               atomic_add(EXT4_NUM_B2C(sbi, free_blocks),
-                          &sbi->s_flex_groups[flex_group].free_clusters);
+               atomic64_add(EXT4_NUM_B2C(sbi, free_blocks),
+                            &sbi->s_flex_groups[flex_group].free_clusters);
                atomic_add(EXT4_INODES_PER_GROUP(sb) * flex_gd->count,
                           &sbi->s_flex_groups[flex_group].free_inodes);
        }
index 34e8552192310a709e6d3d9ccedb35cbe3fca972..5d6d53578124dda01132a6545100a5acb2025f73 100644 (file)
@@ -91,6 +91,7 @@ static struct file_system_type ext2_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV,
 };
 MODULE_ALIAS_FS("ext2");
+MODULE_ALIAS("ext2");
 #define IS_EXT2_SB(sb) ((sb)->s_bdev->bd_holder == &ext2_fs_type)
 #else
 #define IS_EXT2_SB(sb) (0)
@@ -106,6 +107,7 @@ static struct file_system_type ext3_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV,
 };
 MODULE_ALIAS_FS("ext3");
+MODULE_ALIAS("ext3");
 #define IS_EXT3_SB(sb) ((sb)->s_bdev->bd_holder == &ext3_fs_type)
 #else
 #define IS_EXT3_SB(sb) (0)
@@ -1925,8 +1927,8 @@ static int ext4_fill_flex_info(struct super_block *sb)
                flex_group = ext4_flex_group(sbi, i);
                atomic_add(ext4_free_inodes_count(sb, gdp),
                           &sbi->s_flex_groups[flex_group].free_inodes);
-               atomic_add(ext4_free_group_clusters(sb, gdp),
-                          &sbi->s_flex_groups[flex_group].free_clusters);
+               atomic64_add(ext4_free_group_clusters(sb, gdp),
+                            &sbi->s_flex_groups[flex_group].free_clusters);
                atomic_add(ext4_used_dirs_count(sb, gdp),
                           &sbi->s_flex_groups[flex_group].used_dirs);
        }
index 45507430806924e7cb1462c29c3bf1376ce9bc5d..e37eb274e492a9dfd36d4f717d363b6932ae90b5 100644 (file)
@@ -258,6 +258,7 @@ static struct file_system_type vxfs_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV,
 };
 MODULE_ALIAS_FS("vxfs"); /* makes mount -t vxfs autoload the module */
+MODULE_ALIAS("vxfs");
 
 static int __init
 vxfs_init(void)
index 019f45e450971341f9cfba1c50a0116295b2dfd3..d79c2dadc536662370c3c084b100f1cecd303855 100644 (file)
@@ -923,8 +923,11 @@ static int gfs2_lock(struct file *file, int cmd, struct file_lock *fl)
                cmd = F_SETLK;
                fl->fl_type = F_UNLCK;
        }
-       if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags)))
+       if (unlikely(test_bit(SDF_SHUTDOWN, &sdp->sd_flags))) {
+               if (fl->fl_type == F_UNLCK)
+                       posix_lock_file_wait(file, fl);
                return -EIO;
+       }
        if (IS_GETLK(cmd))
                return dlm_posix_get(ls->ls_dlm, ip->i_no_addr, file, fl);
        else if (fl->fl_type == F_UNLCK)
index 156e42ec84ea488c9c223400284c9040b5c86f69..5c29216e9cc1d000053aa4f34a5dd1a6d936cb2f 100644 (file)
@@ -588,6 +588,7 @@ struct lm_lockstruct {
        struct dlm_lksb ls_control_lksb; /* control_lock */
        char ls_control_lvb[GDLM_LVB_SIZE]; /* control_lock lvb */
        struct completion ls_sync_wait; /* {control,mounted}_{lock,unlock} */
+       char *ls_lvb_bits;
 
        spinlock_t ls_recover_spin; /* protects following fields */
        unsigned long ls_recover_flags; /* DFL_ */
index 9802de0f85e61fe061ea150d15177c39b4128ca3..c8423d6de6c3ee54341d5ea5c4eb7e20ca7255de 100644 (file)
@@ -483,12 +483,8 @@ static void control_lvb_write(struct lm_lockstruct *ls, uint32_t lvb_gen,
 
 static int all_jid_bits_clear(char *lvb)
 {
-       int i;
-       for (i = JID_BITMAP_OFFSET; i < GDLM_LVB_SIZE; i++) {
-               if (lvb[i])
-                       return 0;
-       }
-       return 1;
+       return !memchr_inv(lvb + JID_BITMAP_OFFSET, 0,
+                       GDLM_LVB_SIZE - JID_BITMAP_OFFSET);
 }
 
 static void sync_wait_cb(void *arg)
@@ -580,7 +576,6 @@ static void gfs2_control_func(struct work_struct *work)
 {
        struct gfs2_sbd *sdp = container_of(work, struct gfs2_sbd, sd_control_work.work);
        struct lm_lockstruct *ls = &sdp->sd_lockstruct;
-       char lvb_bits[GDLM_LVB_SIZE];
        uint32_t block_gen, start_gen, lvb_gen, flags;
        int recover_set = 0;
        int write_lvb = 0;
@@ -634,7 +629,7 @@ static void gfs2_control_func(struct work_struct *work)
                return;
        }
 
-       control_lvb_read(ls, &lvb_gen, lvb_bits);
+       control_lvb_read(ls, &lvb_gen, ls->ls_lvb_bits);
 
        spin_lock(&ls->ls_recover_spin);
        if (block_gen != ls->ls_recover_block ||
@@ -664,10 +659,10 @@ static void gfs2_control_func(struct work_struct *work)
 
                        ls->ls_recover_result[i] = 0;
 
-                       if (!test_bit_le(i, lvb_bits + JID_BITMAP_OFFSET))
+                       if (!test_bit_le(i, ls->ls_lvb_bits + JID_BITMAP_OFFSET))
                                continue;
 
-                       __clear_bit_le(i, lvb_bits + JID_BITMAP_OFFSET);
+                       __clear_bit_le(i, ls->ls_lvb_bits + JID_BITMAP_OFFSET);
                        write_lvb = 1;
                }
        }
@@ -691,7 +686,7 @@ static void gfs2_control_func(struct work_struct *work)
                                continue;
                        if (ls->ls_recover_submit[i] < start_gen) {
                                ls->ls_recover_submit[i] = 0;
-                               __set_bit_le(i, lvb_bits + JID_BITMAP_OFFSET);
+                               __set_bit_le(i, ls->ls_lvb_bits + JID_BITMAP_OFFSET);
                        }
                }
                /* even if there are no bits to set, we need to write the
@@ -705,7 +700,7 @@ static void gfs2_control_func(struct work_struct *work)
        spin_unlock(&ls->ls_recover_spin);
 
        if (write_lvb) {
-               control_lvb_write(ls, start_gen, lvb_bits);
+               control_lvb_write(ls, start_gen, ls->ls_lvb_bits);
                flags = DLM_LKF_CONVERT | DLM_LKF_VALBLK;
        } else {
                flags = DLM_LKF_CONVERT;
@@ -725,7 +720,7 @@ static void gfs2_control_func(struct work_struct *work)
         */
 
        for (i = 0; i < recover_size; i++) {
-               if (test_bit_le(i, lvb_bits + JID_BITMAP_OFFSET)) {
+               if (test_bit_le(i, ls->ls_lvb_bits + JID_BITMAP_OFFSET)) {
                        fs_info(sdp, "recover generation %u jid %d\n",
                                start_gen, i);
                        gfs2_recover_set(sdp, i);
@@ -758,7 +753,6 @@ static void gfs2_control_func(struct work_struct *work)
 static int control_mount(struct gfs2_sbd *sdp)
 {
        struct lm_lockstruct *ls = &sdp->sd_lockstruct;
-       char lvb_bits[GDLM_LVB_SIZE];
        uint32_t start_gen, block_gen, mount_gen, lvb_gen;
        int mounted_mode;
        int retries = 0;
@@ -857,7 +851,7 @@ locks_done:
         * lvb_gen will be non-zero.
         */
 
-       control_lvb_read(ls, &lvb_gen, lvb_bits);
+       control_lvb_read(ls, &lvb_gen, ls->ls_lvb_bits);
 
        if (lvb_gen == 0xFFFFFFFF) {
                /* special value to force mount attempts to fail */
@@ -887,7 +881,7 @@ locks_done:
         * and all lvb bits to be clear (no pending journal recoveries.)
         */
 
-       if (!all_jid_bits_clear(lvb_bits)) {
+       if (!all_jid_bits_clear(ls->ls_lvb_bits)) {
                /* journals need recovery, wait until all are clear */
                fs_info(sdp, "control_mount wait for journal recovery\n");
                goto restart;
@@ -949,7 +943,6 @@ static int dlm_recovery_wait(void *word)
 static int control_first_done(struct gfs2_sbd *sdp)
 {
        struct lm_lockstruct *ls = &sdp->sd_lockstruct;
-       char lvb_bits[GDLM_LVB_SIZE];
        uint32_t start_gen, block_gen;
        int error;
 
@@ -991,8 +984,8 @@ restart:
        memset(ls->ls_recover_result, 0, ls->ls_recover_size*sizeof(uint32_t));
        spin_unlock(&ls->ls_recover_spin);
 
-       memset(lvb_bits, 0, sizeof(lvb_bits));
-       control_lvb_write(ls, start_gen, lvb_bits);
+       memset(ls->ls_lvb_bits, 0, GDLM_LVB_SIZE);
+       control_lvb_write(ls, start_gen, ls->ls_lvb_bits);
 
        error = mounted_lock(sdp, DLM_LOCK_PR, DLM_LKF_CONVERT);
        if (error)
@@ -1022,6 +1015,12 @@ static int set_recover_size(struct gfs2_sbd *sdp, struct dlm_slot *slots,
        uint32_t old_size, new_size;
        int i, max_jid;
 
+       if (!ls->ls_lvb_bits) {
+               ls->ls_lvb_bits = kzalloc(GDLM_LVB_SIZE, GFP_NOFS);
+               if (!ls->ls_lvb_bits)
+                       return -ENOMEM;
+       }
+
        max_jid = 0;
        for (i = 0; i < num_slots; i++) {
                if (max_jid < slots[i].slot - 1)
@@ -1057,6 +1056,7 @@ static int set_recover_size(struct gfs2_sbd *sdp, struct dlm_slot *slots,
 
 static void free_recover_size(struct lm_lockstruct *ls)
 {
+       kfree(ls->ls_lvb_bits);
        kfree(ls->ls_recover_submit);
        kfree(ls->ls_recover_result);
        ls->ls_recover_submit = NULL;
@@ -1205,6 +1205,7 @@ static int gdlm_mount(struct gfs2_sbd *sdp, const char *table)
        ls->ls_recover_size = 0;
        ls->ls_recover_submit = NULL;
        ls->ls_recover_result = NULL;
+       ls->ls_lvb_bits = NULL;
 
        error = set_recover_size(sdp, NULL, 0);
        if (error)
index d1f51fd73f86eeb6fc136e176a8cd5cbdcac2af8..5a51265a4341df35fe0855db5f530a1e8e55771f 100644 (file)
@@ -576,7 +576,7 @@ int gfs2_rs_alloc(struct gfs2_inode *ip)
        RB_CLEAR_NODE(&ip->i_res->rs_node);
 out:
        up_write(&ip->i_rw_mutex);
-       return 0;
+       return error;
 }
 
 static void dump_rs(struct seq_file *seq, const struct gfs2_blkreserv *rs)
@@ -1181,12 +1181,9 @@ int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset,
                             const struct gfs2_bitmap *bi, unsigned minlen, u64 *ptrimmed)
 {
        struct super_block *sb = sdp->sd_vfs;
-       struct block_device *bdev = sb->s_bdev;
-       const unsigned int sects_per_blk = sdp->sd_sb.sb_bsize /
-                                          bdev_logical_block_size(sb->s_bdev);
        u64 blk;
        sector_t start = 0;
-       sector_t nr_sects = 0;
+       sector_t nr_blks = 0;
        int rv;
        unsigned int x;
        u32 trimmed = 0;
@@ -1206,35 +1203,34 @@ int gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset,
                if (diff == 0)
                        continue;
                blk = offset + ((bi->bi_start + x) * GFS2_NBBY);
-               blk *= sects_per_blk; /* convert to sectors */
                while(diff) {
                        if (diff & 1) {
-                               if (nr_sects == 0)
+                               if (nr_blks == 0)
                                        goto start_new_extent;
-                               if ((start + nr_sects) != blk) {
-                                       if (nr_sects >= minlen) {
-                                               rv = blkdev_issue_discard(bdev,
-                                                       start, nr_sects,
+                               if ((start + nr_blks) != blk) {
+                                       if (nr_blks >= minlen) {
+                                               rv = sb_issue_discard(sb,
+                                                       start, nr_blks,
                                                        GFP_NOFS, 0);
                                                if (rv)
                                                        goto fail;
-                                               trimmed += nr_sects;
+                                               trimmed += nr_blks;
                                        }
-                                       nr_sects = 0;
+                                       nr_blks = 0;
 start_new_extent:
                                        start = blk;
                                }
-                               nr_sects += sects_per_blk;
+                               nr_blks++;
                        }
                        diff >>= 2;
-                       blk += sects_per_blk;
+                       blk++;
                }
        }
-       if (nr_sects >= minlen) {
-               rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS, 0);
+       if (nr_blks >= minlen) {
+               rv = sb_issue_discard(sb, start, nr_blks, GFP_NOFS, 0);
                if (rv)
                        goto fail;
-               trimmed += nr_sects;
+               trimmed += nr_blks;
        }
        if (ptrimmed)
                *ptrimmed = trimmed;
index fbabb906066fa4756c846e6c6e6e577f00f1b6ed..0f6e52d22b8420fdbd3e5b315fe403d742c0a52f 100644 (file)
@@ -845,15 +845,8 @@ int hostfs_setattr(struct dentry *dentry, struct iattr *attr)
                return err;
 
        if ((attr->ia_valid & ATTR_SIZE) &&
-           attr->ia_size != i_size_read(inode)) {
-               int error;
-
-               error = inode_newsize_ok(inode, attr->ia_size);
-               if (error)
-                       return error;
-
+           attr->ia_size != i_size_read(inode))
                truncate_setsize(inode, attr->ia_size);
-       }
 
        setattr_copy(inode, attr);
        mark_inode_dirty(inode);
@@ -993,6 +986,7 @@ static struct file_system_type hostfs_type = {
        .kill_sb        = hostfs_kill_sb,
        .fs_flags       = 0,
 };
+MODULE_ALIAS_FS("hostfs");
 
 static int __init init_hostfs(void)
 {
index a3076228523db4db7a105a966f6049a8570b705c..a0617e7069579c61baed047b3ba2992b294d6082 100644 (file)
@@ -688,6 +688,7 @@ static struct file_system_type hpfs_fs_type = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("hpfs");
 
 static int __init init_hpfs_fs(void)
 {
index 507141fceb99669f7554e330d81605d2fff248b2..4be78237d896d759229eaf300f583288e1a28086 100644 (file)
@@ -125,3 +125,8 @@ extern int invalidate_inodes(struct super_block *, bool);
  * dcache.c
  */
 extern struct dentry *__d_alloc(struct super_block *, const struct qstr *);
+
+/*
+ * read_write.c
+ */
+extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *);
index a67f16e846a2c766341fea2a6437c77d61700769..d9b8aebdeb22b467eb9717996b823734f8446300 100644 (file)
@@ -1557,6 +1557,7 @@ static struct file_system_type iso9660_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV,
 };
 MODULE_ALIAS_FS("iso9660");
+MODULE_ALIAS("iso9660");
 
 static int __init init_iso9660_fs(void)
 {
index d6ee5aed56b178ef98850b3a9abc75f6afc54f7f..325bc019ed8813ea00321594405e86c739dad5fb 100644 (file)
@@ -1065,9 +1065,12 @@ out:
 void jbd2_journal_set_triggers(struct buffer_head *bh,
                               struct jbd2_buffer_trigger_type *type)
 {
-       struct journal_head *jh = bh2jh(bh);
+       struct journal_head *jh = jbd2_journal_grab_journal_head(bh);
 
+       if (WARN_ON(!jh))
+               return;
        jh->b_triggers = type;
+       jbd2_journal_put_journal_head(jh);
 }
 
 void jbd2_buffer_frozen_trigger(struct journal_head *jh, void *mapped_data,
@@ -1119,17 +1122,18 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
 {
        transaction_t *transaction = handle->h_transaction;
        journal_t *journal = transaction->t_journal;
-       struct journal_head *jh = bh2jh(bh);
+       struct journal_head *jh;
        int ret = 0;
 
-       jbd_debug(5, "journal_head %p\n", jh);
-       JBUFFER_TRACE(jh, "entry");
        if (is_handle_aborted(handle))
                goto out;
-       if (!buffer_jbd(bh)) {
+       jh = jbd2_journal_grab_journal_head(bh);
+       if (!jh) {
                ret = -EUCLEAN;
                goto out;
        }
+       jbd_debug(5, "journal_head %p\n", jh);
+       JBUFFER_TRACE(jh, "entry");
 
        jbd_lock_bh_state(bh);
 
@@ -1220,6 +1224,7 @@ int jbd2_journal_dirty_metadata(handle_t *handle, struct buffer_head *bh)
        spin_unlock(&journal->j_list_lock);
 out_unlock_bh:
        jbd_unlock_bh_state(bh);
+       jbd2_journal_put_journal_head(jh);
 out:
        JBUFFER_TRACE(jh, "exit");
        WARN_ON(ret);   /* All errors are bugs, so dump the stack */
index 50ca17d3cb4506de87465bb4d62f3da5f00553a5..d581e45c0a9fd6ada94edd2bb6ea4fe4c7fc9e23 100644 (file)
@@ -798,6 +798,10 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
        }
 
        mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~MNT_WRITE_HOLD;
+       /* Don't allow unprivileged users to change mount flags */
+       if ((flag & CL_UNPRIVILEGED) && (mnt->mnt.mnt_flags & MNT_READONLY))
+               mnt->mnt.mnt_flags |= MNT_LOCK_READONLY;
+
        atomic_inc(&sb->s_active);
        mnt->mnt.mnt_sb = sb;
        mnt->mnt.mnt_root = dget(root);
@@ -1713,6 +1717,9 @@ static int change_mount_flags(struct vfsmount *mnt, int ms_flags)
        if (readonly_request == __mnt_is_readonly(mnt))
                return 0;
 
+       if (mnt->mnt_flags & MNT_LOCK_READONLY)
+               return -EPERM;
+
        if (readonly_request)
                error = mnt_make_readonly(real_mount(mnt));
        else
@@ -2339,7 +2346,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
        /* First pass: copy the tree topology */
        copy_flags = CL_COPY_ALL | CL_EXPIRE;
        if (user_ns != mnt_ns->user_ns)
-               copy_flags |= CL_SHARED_TO_SLAVE;
+               copy_flags |= CL_SHARED_TO_SLAVE | CL_UNPRIVILEGED;
        new = copy_tree(old, old->mnt.mnt_root, copy_flags);
        if (IS_ERR(new)) {
                up_write(&namespace_sem);
@@ -2732,6 +2739,51 @@ bool our_mnt(struct vfsmount *mnt)
        return check_mnt(real_mount(mnt));
 }
 
+bool current_chrooted(void)
+{
+       /* Does the current process have a non-standard root */
+       struct path ns_root;
+       struct path fs_root;
+       bool chrooted;
+
+       /* Find the namespace root */
+       ns_root.mnt = &current->nsproxy->mnt_ns->root->mnt;
+       ns_root.dentry = ns_root.mnt->mnt_root;
+       path_get(&ns_root);
+       while (d_mountpoint(ns_root.dentry) && follow_down_one(&ns_root))
+               ;
+
+       get_fs_root(current->fs, &fs_root);
+
+       chrooted = !path_equal(&fs_root, &ns_root);
+
+       path_put(&fs_root);
+       path_put(&ns_root);
+
+       return chrooted;
+}
+
+void update_mnt_policy(struct user_namespace *userns)
+{
+       struct mnt_namespace *ns = current->nsproxy->mnt_ns;
+       struct mount *mnt;
+
+       down_read(&namespace_sem);
+       list_for_each_entry(mnt, &ns->list, mnt_list) {
+               switch (mnt->mnt.mnt_sb->s_magic) {
+               case SYSFS_MAGIC:
+                       userns->may_mount_sysfs = true;
+                       break;
+               case PROC_SUPER_MAGIC:
+                       userns->may_mount_proc = true;
+                       break;
+               }
+               if (userns->may_mount_sysfs && userns->may_mount_proc)
+                       break;
+       }
+       up_read(&namespace_sem);
+}
+
 static void *mntns_get(struct task_struct *task)
 {
        struct mnt_namespace *ns = NULL;
index 737d839bc17b5aa0ae58e5350a235af1f8adfb2b..6fc7b5cae92bf6526bee07696f12977322f2cb5e 100644 (file)
@@ -55,7 +55,8 @@ static void dev_remove(struct net *net, dev_t dev)
 
        bl_pipe_msg.bl_wq = &nn->bl_wq;
        memset(msg, 0, sizeof(*msg));
-       msg->data = kzalloc(1 + sizeof(bl_umount_request), GFP_NOFS);
+       msg->len = sizeof(bl_msg) + bl_msg.totallen;
+       msg->data = kzalloc(msg->len, GFP_NOFS);
        if (!msg->data)
                goto out;
 
@@ -66,7 +67,6 @@ static void dev_remove(struct net *net, dev_t dev)
        memcpy(msg->data, &bl_msg, sizeof(bl_msg));
        dataptr = (uint8_t *) msg->data;
        memcpy(&dataptr[sizeof(bl_msg)], &bl_umount_request, sizeof(bl_umount_request));
-       msg->len = sizeof(bl_msg) + bl_msg.totallen;
 
        add_wait_queue(&nn->bl_wq, &wq);
        if (rpc_queue_upcall(nn->bl_device_pipe, msg) < 0) {
index dc0f98dfa71773bd467a1b6891b2f916b696b734..c516da5873fd12df0d3c9877b2c3189423c0dec4 100644 (file)
@@ -726,9 +726,9 @@ out1:
        return ret;
 }
 
-static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data)
+static int nfs_idmap_instantiate(struct key *key, struct key *authkey, char *data, size_t datalen)
 {
-       return key_instantiate_and_link(key, data, strlen(data) + 1,
+       return key_instantiate_and_link(key, data, datalen,
                                        id_resolver_cache->thread_keyring,
                                        authkey);
 }
@@ -738,6 +738,7 @@ static int nfs_idmap_read_and_verify_message(struct idmap_msg *im,
                struct key *key, struct key *authkey)
 {
        char id_str[NFS_UINT_MAXLEN];
+       size_t len;
        int ret = -ENOKEY;
 
        /* ret = -ENOKEY */
@@ -747,13 +748,15 @@ static int nfs_idmap_read_and_verify_message(struct idmap_msg *im,
        case IDMAP_CONV_NAMETOID:
                if (strcmp(upcall->im_name, im->im_name) != 0)
                        break;
-               sprintf(id_str, "%d", im->im_id);
-               ret = nfs_idmap_instantiate(key, authkey, id_str);
+               /* Note: here we store the NUL terminator too */
+               len = sprintf(id_str, "%d", im->im_id) + 1;
+               ret = nfs_idmap_instantiate(key, authkey, id_str, len);
                break;
        case IDMAP_CONV_IDTONAME:
                if (upcall->im_id != im->im_id)
                        break;
-               ret = nfs_idmap_instantiate(key, authkey, im->im_name);
+               len = strlen(im->im_name);
+               ret = nfs_idmap_instantiate(key, authkey, im->im_name, len);
                break;
        default:
                ret = -EINVAL;
index 49eeb044c109c0bb3c3878db7b8b60a780b50f97..4fb234d3aefb240f3d067523bda6df467336d2d0 100644 (file)
@@ -129,7 +129,6 @@ static void filelayout_fenceme(struct inode *inode, struct pnfs_layout_hdr *lo)
 {
        if (!test_and_clear_bit(NFS_LAYOUT_RETURN, &lo->plh_flags))
                return;
-       clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(inode)->flags);
        pnfs_return_layout(inode);
 }
 
index b2671cb0f901b8e904ee4b91961d2029e12fb2dc..26431cf62ddbc393fd5fe1e432742be37d06e12e 100644 (file)
@@ -2632,7 +2632,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr,
        int status;
 
        if (pnfs_ld_layoutret_on_setattr(inode))
-               pnfs_return_layout(inode);
+               pnfs_commit_and_return_layout(inode);
 
        nfs_fattr_init(fattr);
        
@@ -6416,22 +6416,8 @@ nfs4_layoutcommit_done(struct rpc_task *task, void *calldata)
 static void nfs4_layoutcommit_release(void *calldata)
 {
        struct nfs4_layoutcommit_data *data = calldata;
-       struct pnfs_layout_segment *lseg, *tmp;
-       unsigned long *bitlock = &NFS_I(data->args.inode)->flags;
 
        pnfs_cleanup_layoutcommit(data);
-       /* Matched by references in pnfs_set_layoutcommit */
-       list_for_each_entry_safe(lseg, tmp, &data->lseg_list, pls_lc_list) {
-               list_del_init(&lseg->pls_lc_list);
-               if (test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT,
-                                      &lseg->pls_flags))
-                       pnfs_put_lseg(lseg);
-       }
-
-       clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock);
-       smp_mb__after_clear_bit();
-       wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING);
-
        put_rpccred(data->cred);
        kfree(data);
 }
index 48ac5aad62589cd7140f55a52d5ee63f31e743b5..4bdffe0ba025228803b65d4fe54ab5cb0adda0ed 100644 (file)
@@ -417,6 +417,16 @@ should_free_lseg(struct pnfs_layout_range *lseg_range,
               lo_seg_intersecting(lseg_range, recall_range);
 }
 
+static bool pnfs_lseg_dec_and_remove_zero(struct pnfs_layout_segment *lseg,
+               struct list_head *tmp_list)
+{
+       if (!atomic_dec_and_test(&lseg->pls_refcount))
+               return false;
+       pnfs_layout_remove_lseg(lseg->pls_layout, lseg);
+       list_add(&lseg->pls_list, tmp_list);
+       return true;
+}
+
 /* Returns 1 if lseg is removed from list, 0 otherwise */
 static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
                             struct list_head *tmp_list)
@@ -430,11 +440,8 @@ static int mark_lseg_invalid(struct pnfs_layout_segment *lseg,
                 */
                dprintk("%s: lseg %p ref %d\n", __func__, lseg,
                        atomic_read(&lseg->pls_refcount));
-               if (atomic_dec_and_test(&lseg->pls_refcount)) {
-                       pnfs_layout_remove_lseg(lseg->pls_layout, lseg);
-                       list_add(&lseg->pls_list, tmp_list);
+               if (pnfs_lseg_dec_and_remove_zero(lseg, tmp_list))
                        rv = 1;
-               }
        }
        return rv;
 }
@@ -777,6 +784,21 @@ send_layoutget(struct pnfs_layout_hdr *lo,
        return lseg;
 }
 
+static void pnfs_clear_layoutcommit(struct inode *inode,
+               struct list_head *head)
+{
+       struct nfs_inode *nfsi = NFS_I(inode);
+       struct pnfs_layout_segment *lseg, *tmp;
+
+       if (!test_and_clear_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags))
+               return;
+       list_for_each_entry_safe(lseg, tmp, &nfsi->layout->plh_segs, pls_list) {
+               if (!test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
+                       continue;
+               pnfs_lseg_dec_and_remove_zero(lseg, head);
+       }
+}
+
 /*
  * Initiates a LAYOUTRETURN(FILE), and removes the pnfs_layout_hdr
  * when the layout segment list is empty.
@@ -808,6 +830,7 @@ _pnfs_return_layout(struct inode *ino)
        /* Reference matched in nfs4_layoutreturn_release */
        pnfs_get_layout_hdr(lo);
        empty = list_empty(&lo->plh_segs);
+       pnfs_clear_layoutcommit(ino, &tmp_list);
        pnfs_mark_matching_lsegs_invalid(lo, &tmp_list, NULL);
        /* Don't send a LAYOUTRETURN if list was initially empty */
        if (empty) {
@@ -820,8 +843,6 @@ _pnfs_return_layout(struct inode *ino)
        spin_unlock(&ino->i_lock);
        pnfs_free_lseg_list(&tmp_list);
 
-       WARN_ON(test_bit(NFS_INO_LAYOUTCOMMIT, &nfsi->flags));
-
        lrp = kzalloc(sizeof(*lrp), GFP_KERNEL);
        if (unlikely(lrp == NULL)) {
                status = -ENOMEM;
@@ -845,6 +866,33 @@ out:
 }
 EXPORT_SYMBOL_GPL(_pnfs_return_layout);
 
+int
+pnfs_commit_and_return_layout(struct inode *inode)
+{
+       struct pnfs_layout_hdr *lo;
+       int ret;
+
+       spin_lock(&inode->i_lock);
+       lo = NFS_I(inode)->layout;
+       if (lo == NULL) {
+               spin_unlock(&inode->i_lock);
+               return 0;
+       }
+       pnfs_get_layout_hdr(lo);
+       /* Block new layoutgets and read/write to ds */
+       lo->plh_block_lgets++;
+       spin_unlock(&inode->i_lock);
+       filemap_fdatawait(inode->i_mapping);
+       ret = pnfs_layoutcommit_inode(inode, true);
+       if (ret == 0)
+               ret = _pnfs_return_layout(inode);
+       spin_lock(&inode->i_lock);
+       lo->plh_block_lgets--;
+       spin_unlock(&inode->i_lock);
+       pnfs_put_layout_hdr(lo);
+       return ret;
+}
+
 bool pnfs_roc(struct inode *ino)
 {
        struct pnfs_layout_hdr *lo;
@@ -1458,7 +1506,6 @@ static void pnfs_ld_handle_write_error(struct nfs_write_data *data)
        dprintk("pnfs write error = %d\n", hdr->pnfs_error);
        if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags &
            PNFS_LAYOUTRET_ON_ERROR) {
-               clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags);
                pnfs_return_layout(hdr->inode);
        }
        if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags))
@@ -1613,7 +1660,6 @@ static void pnfs_ld_handle_read_error(struct nfs_read_data *data)
        dprintk("pnfs read error = %d\n", hdr->pnfs_error);
        if (NFS_SERVER(hdr->inode)->pnfs_curr_ld->flags &
            PNFS_LAYOUTRET_ON_ERROR) {
-               clear_bit(NFS_INO_LAYOUTCOMMIT, &NFS_I(hdr->inode)->flags);
                pnfs_return_layout(hdr->inode);
        }
        if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags))
@@ -1746,11 +1792,27 @@ static void pnfs_list_write_lseg(struct inode *inode, struct list_head *listp)
 
        list_for_each_entry(lseg, &NFS_I(inode)->layout->plh_segs, pls_list) {
                if (lseg->pls_range.iomode == IOMODE_RW &&
-                   test_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
+                   test_and_clear_bit(NFS_LSEG_LAYOUTCOMMIT, &lseg->pls_flags))
                        list_add(&lseg->pls_lc_list, listp);
        }
 }
 
+static void pnfs_list_write_lseg_done(struct inode *inode, struct list_head *listp)
+{
+       struct pnfs_layout_segment *lseg, *tmp;
+       unsigned long *bitlock = &NFS_I(inode)->flags;
+
+       /* Matched by references in pnfs_set_layoutcommit */
+       list_for_each_entry_safe(lseg, tmp, listp, pls_lc_list) {
+               list_del_init(&lseg->pls_lc_list);
+               pnfs_put_lseg(lseg);
+       }
+
+       clear_bit_unlock(NFS_INO_LAYOUTCOMMITTING, bitlock);
+       smp_mb__after_clear_bit();
+       wake_up_bit(bitlock, NFS_INO_LAYOUTCOMMITTING);
+}
+
 void pnfs_set_lo_fail(struct pnfs_layout_segment *lseg)
 {
        pnfs_layout_io_set_failed(lseg->pls_layout, lseg->pls_range.iomode);
@@ -1795,6 +1857,7 @@ void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data)
 
        if (nfss->pnfs_curr_ld->cleanup_layoutcommit)
                nfss->pnfs_curr_ld->cleanup_layoutcommit(data);
+       pnfs_list_write_lseg_done(data->args.inode, &data->lseg_list);
 }
 
 /*
index 94ba804177483d3c78694ae1708e95a2d34048d5..f5f8a470a647c7dc2f3a475e3e852d1aa7c97f5e 100644 (file)
@@ -219,6 +219,7 @@ void pnfs_set_layoutcommit(struct nfs_write_data *wdata);
 void pnfs_cleanup_layoutcommit(struct nfs4_layoutcommit_data *data);
 int pnfs_layoutcommit_inode(struct inode *inode, bool sync);
 int _pnfs_return_layout(struct inode *);
+int pnfs_commit_and_return_layout(struct inode *);
 void pnfs_ld_write_done(struct nfs_write_data *);
 void pnfs_ld_read_done(struct nfs_read_data *);
 struct pnfs_layout_segment *pnfs_update_layout(struct inode *ino,
@@ -407,6 +408,11 @@ static inline int pnfs_return_layout(struct inode *ino)
        return 0;
 }
 
+static inline int pnfs_commit_and_return_layout(struct inode *inode)
+{
+       return 0;
+}
+
 static inline bool
 pnfs_ld_layoutret_on_setattr(struct inode *inode)
 {
index 95cdcb208dfb630396058a0688c4341a170b4968..2f8a29db0f1bed59a8300d64038ebe4404d611a6 100644 (file)
@@ -335,6 +335,7 @@ struct file_system_type nfs4_fs_type = {
        .fs_flags       = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA,
 };
 MODULE_ALIAS_FS("nfs4");
+MODULE_ALIAS("nfs4");
 EXPORT_SYMBOL_GPL(nfs4_fs_type);
 
 static int __init register_nfs4_fs(void)
index 16d39c6c4fbb56b11c25ac8927b8913b1a928a15..2e27430b9070fc6ca71a56432409b85f465f5d0a 100644 (file)
@@ -230,37 +230,6 @@ static void nfs4_file_put_access(struct nfs4_file *fp, int oflag)
                __nfs4_file_put_access(fp, oflag);
 }
 
-static inline int get_new_stid(struct nfs4_stid *stid)
-{
-       static int min_stateid = 0;
-       struct idr *stateids = &stid->sc_client->cl_stateids;
-       int new_stid;
-       int error;
-
-       error = idr_get_new_above(stateids, stid, min_stateid, &new_stid);
-       /*
-        * Note: the necessary preallocation was done in
-        * nfs4_alloc_stateid().  The idr code caps the number of
-        * preallocations that can exist at a time, but the state lock
-        * prevents anyone from using ours before we get here:
-        */
-       WARN_ON_ONCE(error);
-       /*
-        * It shouldn't be a problem to reuse an opaque stateid value.
-        * I don't think it is for 4.1.  But with 4.0 I worry that, for
-        * example, a stray write retransmission could be accepted by
-        * the server when it should have been rejected.  Therefore,
-        * adopt a trick from the sctp code to attempt to maximize the
-        * amount of time until an id is reused, by ensuring they always
-        * "increase" (mod INT_MAX):
-        */
-
-       min_stateid = new_stid+1;
-       if (min_stateid == INT_MAX)
-               min_stateid = 0;
-       return new_stid;
-}
-
 static struct nfs4_stid *nfs4_alloc_stid(struct nfs4_client *cl, struct
 kmem_cache *slab)
 {
@@ -273,9 +242,8 @@ kmem_cache *slab)
        if (!stid)
                return NULL;
 
-       if (!idr_pre_get(stateids, GFP_KERNEL))
-               goto out_free;
-       if (idr_get_new_above(stateids, stid, min_stateid, &new_id))
+       new_id = idr_alloc(stateids, stid, min_stateid, 0, GFP_KERNEL);
+       if (new_id < 0)
                goto out_free;
        stid->sc_client = cl;
        stid->sc_type = 0;
index 01168865dd37395a047cbeeb0175d7c8a5b80f88..a2720071f282f7607f13d63af8d6e9d6cf18bce6 100644 (file)
@@ -264,7 +264,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
                iattr->ia_valid |= ATTR_SIZE;
        }
        if (bmval[0] & FATTR4_WORD0_ACL) {
-               int nace;
+               u32 nace;
                struct nfs4_ace *ace;
 
                READ_BUF(4); len += 4;
index 62c1ee128aebafbd82e70863e57caa74de804e13..ca05f6dc3544b4c216eb369d9e01fe7a48f0e90a 100644 (file)
@@ -102,7 +102,8 @@ nfsd_reply_cache_free_locked(struct svc_cacherep *rp)
 {
        if (rp->c_type == RC_REPLBUFF)
                kfree(rp->c_replvec.iov_base);
-       hlist_del(&rp->c_hash);
+       if (!hlist_unhashed(&rp->c_hash))
+               hlist_del(&rp->c_hash);
        list_del(&rp->c_lru);
        --num_drc_entries;
        kmem_cache_free(drc_slab, rp);
@@ -118,6 +119,10 @@ nfsd_reply_cache_free(struct svc_cacherep *rp)
 
 int nfsd_reply_cache_init(void)
 {
+       INIT_LIST_HEAD(&lru_head);
+       max_drc_entries = nfsd_cache_size_limit();
+       num_drc_entries = 0;
+
        register_shrinker(&nfsd_reply_cache_shrinker);
        drc_slab = kmem_cache_create("nfsd_drc", sizeof(struct svc_cacherep),
                                        0, 0, NULL);
@@ -128,10 +133,6 @@ int nfsd_reply_cache_init(void)
        if (!cache_hash)
                goto out_nomem;
 
-       INIT_LIST_HEAD(&lru_head);
-       max_drc_entries = nfsd_cache_size_limit();
-       num_drc_entries = 0;
-
        return 0;
 out_nomem:
        printk(KERN_ERR "nfsd: failed to allocate reply cache\n");
index 2a7eb536de0bec80dfbfd7d981139f2e925e644e..2b2e2396a86913b4d4e69c376852ded82dd9be3a 100644 (file)
@@ -1013,6 +1013,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
        int                     host_err;
        int                     stable = *stablep;
        int                     use_wgather;
+       loff_t                  pos = offset;
 
        dentry = file->f_path.dentry;
        inode = dentry->d_inode;
@@ -1025,7 +1026,7 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file,
 
        /* Write the data. */
        oldfs = get_fs(); set_fs(KERNEL_DS);
-       host_err = vfs_writev(file, (struct iovec __user *)vec, vlen, &offset);
+       host_err = vfs_writev(file, (struct iovec __user *)vec, vlen, &pos);
        set_fs(oldfs);
        if (host_err < 0)
                goto out_nfserr;
index 64a494cef0a00be57d0800637b71caf2537c2694..2234f3f61f8d8fbc6a1f77dbaae6412130b8a5d4 100644 (file)
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -863,6 +863,9 @@ pipe_rdwr_open(struct inode *inode, struct file *filp)
 {
        int ret = -ENOENT;
 
+       if (!(filp->f_mode & (FMODE_READ|FMODE_WRITE)))
+               return -EINVAL;
+
        mutex_lock(&inode->i_mutex);
 
        if (inode->i_pipe) {
index 3e000a51ac0d09556d184d26422a91d0bc4c0ff9..8b29d2164da6aef6edb88b9872368c849e658530 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/mnt_namespace.h>
 #include <linux/mount.h>
 #include <linux/fs.h>
+#include <linux/nsproxy.h>
 #include "internal.h"
 #include "pnode.h"
 
@@ -220,6 +221,7 @@ static struct mount *get_source(struct mount *dest,
 int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry,
                    struct mount *source_mnt, struct list_head *tree_list)
 {
+       struct user_namespace *user_ns = current->nsproxy->mnt_ns->user_ns;
        struct mount *m, *child;
        int ret = 0;
        struct mount *prev_dest_mnt = dest_mnt;
@@ -237,6 +239,10 @@ int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry,
 
                source =  get_source(m, prev_dest_mnt, prev_src_mnt, &type);
 
+               /* Notice when we are propagating across user namespaces */
+               if (m->mnt_ns->user_ns != user_ns)
+                       type |= CL_UNPRIVILEGED;
+
                child = copy_tree(source, source->mnt.mnt_root, type);
                if (IS_ERR(child)) {
                        ret = PTR_ERR(child);
index 19b853a3445cb907665b4403484984a0c525af68..a0493d5ebfbf52be2eb07a794df459ab2a32cd6a 100644 (file)
@@ -23,6 +23,7 @@
 #define CL_MAKE_SHARED                 0x08
 #define CL_PRIVATE             0x10
 #define CL_SHARED_TO_SLAVE     0x20
+#define CL_UNPRIVILEGED                0x40
 
 static inline void set_mnt_shared(struct mount *mnt)
 {
index a86aebc9ba7c252bbfa73907612b59c177fca202..869116c2afbe4d192bee231541d141b8622cd6e3 100644 (file)
@@ -446,9 +446,10 @@ static const struct file_operations proc_reg_file_ops_no_compat = {
 
 struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
 {
-       struct inode *inode = iget_locked(sb, de->low_ino);
+       struct inode *inode = new_inode_pseudo(sb);
 
-       if (inode && (inode->i_state & I_NEW)) {
+       if (inode) {
+               inode->i_ino = de->low_ino;
                inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
                PROC_I(inode)->pde = de;
 
@@ -476,7 +477,6 @@ struct inode *proc_get_inode(struct super_block *sb, struct proc_dir_entry *de)
                                inode->i_fop = de->proc_fops;
                        }
                }
-               unlock_new_inode(inode);
        } else
               pde_put(de);
        return inode;
index c6e9fac26bace4e9b63bd57dce624589dc67dfd7..9c7fab1d23f0d17d68446bf3d46ce1a906ae0907 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/sched.h>
 #include <linux/module.h>
 #include <linux/bitops.h>
+#include <linux/user_namespace.h>
 #include <linux/mount.h>
 #include <linux/pid_namespace.h>
 #include <linux/parser.h>
@@ -108,6 +109,9 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
        } else {
                ns = task_active_pid_ns(current);
                options = data;
+
+               if (!current_user_ns()->may_mount_proc)
+                       return ERR_PTR(-EPERM);
        }
 
        sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns);
index 05ae3c97f7a5fc552e771f9cf7312e4b61cffc1f..3e64169ef52710ff11f9c7f8c44ee3c910cbd321 100644 (file)
@@ -1439,8 +1439,11 @@ static void __dquot_initialize(struct inode *inode, int type)
                         * did a write before quota was turned on
                         */
                        rsv = inode_get_rsv_space(inode);
-                       if (unlikely(rsv))
+                       if (unlikely(rsv)) {
+                               spin_lock(&dq_data_lock);
                                dquot_resv_space(inode->i_dquot[cnt], rsv);
+                               spin_unlock(&dq_data_lock);
+                       }
                }
        }
 out_err:
index a698eff457fb6e510c0543c9b762cc8c8d702f23..e6ddc8dceb96fc48a8fbe379799d0efed52d2b4a 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/splice.h>
 #include <linux/compat.h>
 #include "read_write.h"
+#include "internal.h"
 
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -417,6 +418,33 @@ ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, lof
 
 EXPORT_SYMBOL(do_sync_write);
 
+ssize_t __kernel_write(struct file *file, const char *buf, size_t count, loff_t *pos)
+{
+       mm_segment_t old_fs;
+       const char __user *p;
+       ssize_t ret;
+
+       if (!file->f_op || (!file->f_op->write && !file->f_op->aio_write))
+               return -EINVAL;
+
+       old_fs = get_fs();
+       set_fs(get_ds());
+       p = (__force const char __user *)buf;
+       if (count > MAX_RW_COUNT)
+               count =  MAX_RW_COUNT;
+       if (file->f_op->write)
+               ret = file->f_op->write(file, p, count, pos);
+       else
+               ret = do_sync_write(file, p, count, pos);
+       set_fs(old_fs);
+       if (ret > 0) {
+               fsnotify_modify(file);
+               add_wchar(current, ret);
+       }
+       inc_syscw(current);
+       return ret;
+}
+
 ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)
 {
        ssize_t ret;
index 194113b1b11bf045f232899d01c28effe6cab786..f8a23c3078f87d5eda59c30d55cea7ecc94b9273 100644 (file)
@@ -1147,8 +1147,7 @@ static int reiserfs_parse_options(struct super_block *s, char *options,   /* strin
                                                         "on filesystem root.");
                                        return 0;
                                }
-                               qf_names[qtype] =
-                                   kmalloc(strlen(arg) + 1, GFP_KERNEL);
+                               qf_names[qtype] = kstrdup(arg, GFP_KERNEL);
                                if (!qf_names[qtype]) {
                                        reiserfs_warning(s, "reiserfs-2502",
                                                         "not enough memory "
@@ -1156,7 +1155,6 @@ static int reiserfs_parse_options(struct super_block *s, char *options,   /* strin
                                                         "quotafile name.");
                                        return 0;
                                }
-                               strcpy(qf_names[qtype], arg);
                                if (qtype == USRQUOTA)
                                        *mount_options |= 1 << REISERFS_USRQUOTA;
                                else
index c196369fe4083128163ed66707d85cde1c0367fb..4cce1d9552fbbcd5f23447245a8b6f942c6fe89c 100644 (file)
@@ -187,8 +187,8 @@ fill_with_dentries(void *buf, const char *name, int namelen, loff_t offset,
        if (dbuf->count == ARRAY_SIZE(dbuf->dentries))
                return -ENOSPC;
 
-       if (name[0] == '.' && (name[1] == '\0' ||
-                              (name[1] == '.' && name[2] == '\0')))
+       if (name[0] == '.' && (namelen < 2 ||
+                              (namelen == 2 && name[1] == '.')))
                return 0;
 
        dentry = lookup_one_len(name, dbuf->xadir, namelen);
index 718bd0056384688af6ead056156574638c0be6e9..29e394e49ddda7c7721d3939d993632a29f4499a 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/security.h>
 #include <linux/gfp.h>
 #include <linux/socket.h>
+#include "internal.h"
 
 /*
  * Attempt to steal a page from a pipe buffer. This should perhaps go into
@@ -1048,9 +1049,10 @@ static int write_pipe_buf(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
 {
        int ret;
        void *data;
+       loff_t tmp = sd->pos;
 
        data = buf->ops->map(pipe, buf, 0);
-       ret = kernel_write(sd->u.file, data + buf->offset, sd->len, sd->pos);
+       ret = __kernel_write(sd->u.file, data + buf->offset, sd->len, &tmp);
        buf->ops->unmap(pipe, buf, data);
 
        return ret;
index 260e3928d4f52bb94076e0025f5fd8bef08bb1c3..60553a9053ca82b7264862e8168b61df0ce7de89 100644 (file)
@@ -489,6 +489,7 @@ static struct file_system_type squashfs_fs_type = {
        .kill_sb = kill_block_super,
        .fs_flags = FS_REQUIRES_DEV
 };
+MODULE_ALIAS_FS("squashfs");
 
 static const struct super_operations squashfs_super_ops = {
        .alloc_inode = squashfs_alloc_inode,
index 2fbdff6be25ce3d546e17fa4e72783e9d3f03637..e14512678c9b7b8042f5ba55a329a0101849f606 100644 (file)
@@ -1020,6 +1020,8 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
                ino = parent_sd->s_ino;
                if (filldir(dirent, ".", 1, filp->f_pos, ino, DT_DIR) == 0)
                        filp->f_pos++;
+               else
+                       return 0;
        }
        if (filp->f_pos == 1) {
                if (parent_sd->s_parent)
@@ -1028,6 +1030,8 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
                        ino = parent_sd->s_ino;
                if (filldir(dirent, "..", 2, filp->f_pos, ino, DT_DIR) == 0)
                        filp->f_pos++;
+               else
+                       return 0;
        }
        mutex_lock(&sysfs_mutex);
        for (pos = sysfs_dir_pos(ns, parent_sd, filp->f_pos, pos);
@@ -1058,10 +1062,21 @@ static int sysfs_readdir(struct file * filp, void * dirent, filldir_t filldir)
        return 0;
 }
 
+static loff_t sysfs_dir_llseek(struct file *file, loff_t offset, int whence)
+{
+       struct inode *inode = file_inode(file);
+       loff_t ret;
+
+       mutex_lock(&inode->i_mutex);
+       ret = generic_file_llseek(file, offset, whence);
+       mutex_unlock(&inode->i_mutex);
+
+       return ret;
+}
 
 const struct file_operations sysfs_dir_operations = {
        .read           = generic_read_dir,
        .readdir        = sysfs_readdir,
        .release        = sysfs_dir_release,
-       .llseek         = generic_file_llseek,
+       .llseek         = sysfs_dir_llseek,
 };
index 8d924b5ec733450e37599c8338ab69ea3b15027f..afd83273e6cea8112e1570c8835bfa829303b2f8 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 #include <linux/magic.h>
 #include <linux/slab.h>
+#include <linux/user_namespace.h>
 
 #include "sysfs.h"
 
@@ -111,6 +112,9 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
        struct super_block *sb;
        int error;
 
+       if (!(flags & MS_KERNMOUNT) && !current_user_ns()->may_mount_sysfs)
+               return ERR_PTR(-EPERM);
+
        info = kzalloc(sizeof(*info), GFP_KERNEL);
        if (!info)
                return ERR_PTR(-ENOMEM);
index a39938b1feea148dcecbb8db3731bd37832396fc..d0c6a007ce835cf869fac695eb5445b34be6d814 100644 (file)
@@ -555,6 +555,7 @@ static struct file_system_type v7_fs_type = {
        .fs_flags       = FS_REQUIRES_DEV,
 };
 MODULE_ALIAS_FS("v7");
+MODULE_ALIAS("v7");
 
 static int __init init_sysv_fs(void)
 {
index ac838b844936cdc29be5f3eff7192e9cb9a15582..f21acf0ef01f9535b7d3a576361c387593414747 100644 (file)
@@ -1568,6 +1568,12 @@ static int ubifs_remount_rw(struct ubifs_info *c)
        c->remounting_rw = 1;
        c->ro_mount = 0;
 
+       if (c->space_fixup) {
+               err = ubifs_fixup_free_space(c);
+               if (err)
+                       return err;
+       }
+
        err = check_free_space(c);
        if (err)
                goto out;
@@ -1684,12 +1690,6 @@ static int ubifs_remount_rw(struct ubifs_info *c)
                err = dbg_check_space_info(c);
        }
 
-       if (c->space_fixup) {
-               err = ubifs_fixup_free_space(c);
-               if (err)
-                       goto out;
-       }
-
        mutex_unlock(&c->umount_mutex);
        return err;
 
index bc5b30a819e82e8622d2ead088c52ef5cf7c268e..9ac4057a86c90f64a84ea2cee0b92e4f549ac01a 100644 (file)
@@ -118,6 +118,7 @@ static struct file_system_type udf_fstype = {
        .kill_sb        = kill_block_super,
        .fs_flags       = FS_REQUIRES_DEV,
 };
+MODULE_ALIAS_FS("udf");
 
 static struct kmem_cache *udf_inode_cachep;
 
index 4e8f0df82d025e6bc38615a94d254bf003c24972..8459b5d8cb71ceaa98ff64990cae8d4daaf6f1b1 100644 (file)
@@ -1334,6 +1334,12 @@ _xfs_buf_ioapply(
        int             size;
        int             i;
 
+       /*
+        * Make sure we capture only current IO errors rather than stale errors
+        * left over from previous use of the buffer (e.g. failed readahead).
+        */
+       bp->b_error = 0;
+
        if (bp->b_flags & XBF_WRITE) {
                if (bp->b_flags & XBF_SYNCIO)
                        rw = WRITE_SYNC;
index 912d83d8860a984a938b604f3e2447c3e390ce89..5a30dd899d2b32c38dbc1fc552e323d233f33e50 100644 (file)
@@ -325,7 +325,7 @@ xfs_iomap_eof_want_preallocate(
  * rather than falling short due to things like stripe unit/width alignment of
  * real extents.
  */
-STATIC int
+STATIC xfs_fsblock_t
 xfs_iomap_eof_prealloc_initial_size(
        struct xfs_mount        *mp,
        struct xfs_inode        *ip,
@@ -413,7 +413,7 @@ xfs_iomap_prealloc_size(
                 * have a large file on a small filesystem and the above
                 * lowspace thresholds are smaller than MAXEXTLEN.
                 */
-               while (alloc_blocks >= freesp)
+               while (alloc_blocks && alloc_blocks >= freesp)
                        alloc_blocks >>= 4;
        }
 
index 555d0337ad955bbdccd6a7f5b261e9d0777462c3..b327b5a9296d36fb6c31fd26e382488fd0b45cbb 100644 (file)
@@ -235,6 +235,9 @@ extern void acpi_processor_unregister_performance(struct
          if a _PPC object exists, rmmod is disallowed then */
 int acpi_processor_notify_smm(struct module *calling_module);
 
+/* parsing the _P* objects. */
+extern int acpi_processor_get_performance_info(struct acpi_processor *pr);
+
 /* for communication between multiple parts of the processor kernel module */
 DECLARE_PER_CPU(struct acpi_processor *, processors);
 extern struct acpi_processor_errata errata;
index 1ced6413ea0345580830394554e0ed2b69ba1224..33bd2de3bc1e930da34dcb8b6007825807ddacb3 100644 (file)
@@ -136,12 +136,6 @@ static inline void atomic_dec(atomic_t *v)
 #define atomic_xchg(ptr, v)            (xchg(&(ptr)->counter, (v)))
 #define atomic_cmpxchg(v, old, new)    (cmpxchg(&((v)->counter), (old), (new)))
 
-#define cmpxchg_local(ptr, o, n)                                              \
-       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
-                       (unsigned long)(n), sizeof(*(ptr))))
-
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-
 static inline int __atomic_add_unless(atomic_t *v, int a, int u)
 {
   int c, old;
index 14883026015dc50be00508f8eccf9cf805ea0ef4..811fb1e9b06131303d41f07797becb024e61d77f 100644 (file)
@@ -92,6 +92,16 @@ unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
  */
 #include <asm-generic/cmpxchg-local.h>
 
+#ifndef cmpxchg_local
+#define cmpxchg_local(ptr, o, n)                                              \
+       ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\
+                       (unsigned long)(n), sizeof(*(ptr))))
+#endif
+
+#ifndef cmpxchg64_local
+#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
+#endif
+
 #define cmpxchg(ptr, o, n)     cmpxchg_local((ptr), (o), (n))
 #define cmpxchg64(ptr, o, n)   cmpxchg64_local((ptr), (o), (n))
 
index a386b0b654cced33e17eb6a7917a935c76ff1de5..918e8fe2f5e9b3f07d49fbf9f71252c60f318692 100644 (file)
        {0x1002, 0x9908, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9909, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x990A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
-       {0x1002, 0x990F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x990B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x990C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x990D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x990E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x990F, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9910, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9913, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9917, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9992, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9993, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x9994, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9995, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9996, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9997, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9998, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x9999, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x999A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
+       {0x1002, 0x999B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x99A0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x99A2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_IS_MOBILITY|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
        {0x1002, 0x99A4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ARUBA|RADEON_NEW_MEMMAP|RADEON_IS_IGP}, \
index 9c7f5807824b82fcf94a25771de576fe1c8cf247..dd7adff76e81fef6e2cc9fa8b2d18ac3c52bc174 100644 (file)
@@ -152,7 +152,7 @@ struct clk {
                },                                              \
                .reg = _reg,                                    \
                .shift = _shift,                                \
-               .width = _width,                                \
+               .mask = BIT(_width) - 1,                        \
                .flags = _mux_flags,                            \
                .lock = _lock,                                  \
        };                                                      \
index 7f197d7addb0be18141a66ad225135b9b0730b24..1f03528027949b61fe0897de5ddbe51d7165fbfe 100644 (file)
@@ -45,6 +45,14 @@ struct clk_hw;
  *             undo any work done in the @prepare callback. Called with
  *             prepare_lock held.
  *
+ * @is_prepared: Queries the hardware to determine if the clock is prepared.
+ *             This function is allowed to sleep. Optional, if this op is not
+ *             set then the prepare count will be used.
+ *
+ * @unprepare_unused: Unprepare the clock atomically.  Only called from
+ *             clk_disable_unused for prepare clocks with special needs.
+ *             Called with prepare mutex held. This function may sleep.
+ *
  * @enable:    Enable the clock atomically. This must not return until the
  *             clock is generating a valid clock signal, usable by consumer
  *             devices. Called with enable_lock held. This function must not
@@ -108,6 +116,8 @@ struct clk_hw;
 struct clk_ops {
        int             (*prepare)(struct clk_hw *hw);
        void            (*unprepare)(struct clk_hw *hw);
+       int             (*is_prepared)(struct clk_hw *hw);
+       void            (*unprepare_unused)(struct clk_hw *hw);
        int             (*enable)(struct clk_hw *hw);
        void            (*disable)(struct clk_hw *hw);
        int             (*is_enabled)(struct clk_hw *hw);
@@ -287,8 +297,9 @@ struct clk *clk_register_divider_table(struct device *dev, const char *name,
 struct clk_mux {
        struct clk_hw   hw;
        void __iomem    *reg;
+       u32             *table;
+       u32             mask;
        u8              shift;
-       u8              width;
        u8              flags;
        spinlock_t      *lock;
 };
@@ -297,11 +308,17 @@ struct clk_mux {
 #define CLK_MUX_INDEX_BIT              BIT(1)
 
 extern const struct clk_ops clk_mux_ops;
+
 struct clk *clk_register_mux(struct device *dev, const char *name,
                const char **parent_names, u8 num_parents, unsigned long flags,
                void __iomem *reg, u8 shift, u8 width,
                u8 clk_mux_flags, spinlock_t *lock);
 
+struct clk *clk_register_mux_table(struct device *dev, const char *name,
+               const char **parent_names, u8 num_parents, unsigned long flags,
+               void __iomem *reg, u8 shift, u32 mask,
+               u8 clk_mux_flags, u32 *table, spinlock_t *lock);
+
 /**
  * struct clk_fixed_factor - fixed multiplier and divider clock
  *
@@ -325,6 +342,37 @@ struct clk *clk_register_fixed_factor(struct device *dev, const char *name,
                const char *parent_name, unsigned long flags,
                unsigned int mult, unsigned int div);
 
+/***
+ * struct clk_composite - aggregate clock of mux, divider and gate clocks
+ *
+ * @hw:                handle between common and hardware-specific interfaces
+ * @mux_hw:    handle between composite and hardware-specifix mux clock
+ * @div_hw:    handle between composite and hardware-specifix divider clock
+ * @gate_hw:   handle between composite and hardware-specifix gate clock
+ * @mux_ops:   clock ops for mux
+ * @div_ops:   clock ops for divider
+ * @gate_ops:  clock ops for gate
+ */
+struct clk_composite {
+       struct clk_hw   hw;
+       struct clk_ops  ops;
+
+       struct clk_hw   *mux_hw;
+       struct clk_hw   *div_hw;
+       struct clk_hw   *gate_hw;
+
+       const struct clk_ops    *mux_ops;
+       const struct clk_ops    *div_ops;
+       const struct clk_ops    *gate_ops;
+};
+
+struct clk *clk_register_composite(struct device *dev, const char *name,
+               const char **parent_names, int num_parents,
+               struct clk_hw *mux_hw, const struct clk_ops *mux_ops,
+               struct clk_hw *div_hw, const struct clk_ops *div_ops,
+               struct clk_hw *gate_hw, const struct clk_ops *gate_ops,
+               unsigned long flags);
+
 /**
  * clk_register - allocate a new clock, register it and return an opaque cookie
  * @dev: device that is registering this clock
@@ -351,6 +399,7 @@ unsigned int __clk_get_enable_count(struct clk *clk);
 unsigned int __clk_get_prepare_count(struct clk *clk);
 unsigned long __clk_get_rate(struct clk *clk);
 unsigned long __clk_get_flags(struct clk *clk);
+bool __clk_is_prepared(struct clk *clk);
 bool __clk_is_enabled(struct clk *clk);
 struct clk *__clk_lookup(const char *name);
 
diff --git a/include/linux/clk/sunxi.h b/include/linux/clk/sunxi.h
new file mode 100644 (file)
index 0000000..e074fdd
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2012 Maxime Ripard
+ *
+ * Maxime Ripard <maxime.ripard@free-electrons.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.
+ */
+
+#ifndef __LINUX_CLK_SUNXI_H_
+#define __LINUX_CLK_SUNXI_H_
+
+void __init sunxi_init_clocks(void);
+
+#endif
index 404d6f940872b0da7373f6ee13172ab089fdf97b..642789baec741cf6574d661587091c75d864b946 100644 (file)
@@ -123,5 +123,6 @@ static inline void tegra_cpu_clock_resume(void)
 void tegra_periph_reset_deassert(struct clk *c);
 void tegra_periph_reset_assert(struct clk *c);
 void tegra_clocks_init(void);
+void tegra_clocks_apply_init_table(void);
 
 #endif /* __LINUX_CLK_TEGRA_H_ */
index 76a87fb57ac258c4f004cee14737d8570da048f0..377cd8c3395eed02ac9f4dbadf7cac96dcf09de9 100644 (file)
@@ -141,11 +141,11 @@ typedef struct {
 } compat_sigset_t;
 
 struct compat_sigaction {
-#ifndef __ARCH_HAS_ODD_SIGACTION
+#ifndef __ARCH_HAS_IRIX_SIGACTION
        compat_uptr_t                   sa_handler;
        compat_ulong_t                  sa_flags;
 #else
-       compat_ulong_t                  sa_flags;
+       compat_uint_t                   sa_flags;
        compat_uptr_t                   sa_handler;
 #endif
 #ifdef __ARCH_HAS_SA_RESTORER
index a975de1ff59feaba6758afa9682ca9203bfc2c42..3bd46f766751caa9b143adcc5ce546441f6b868d 100644 (file)
@@ -51,7 +51,7 @@ struct task_struct;
 extern void debug_show_all_locks(void);
 extern void debug_show_held_locks(struct task_struct *task);
 extern void debug_check_no_locks_freed(const void *from, unsigned long len);
-extern void debug_check_no_locks_held(void);
+extern void debug_check_no_locks_held(struct task_struct *task);
 #else
 static inline void debug_show_all_locks(void)
 {
@@ -67,7 +67,7 @@ debug_check_no_locks_freed(const void *from, unsigned long len)
 }
 
 static inline void
-debug_check_no_locks_held(void)
+debug_check_no_locks_held(struct task_struct *task)
 {
 }
 #endif
index e83ef39b3bea7359475d328aeed2e81d6b8926af..fe8c4476f7e4b36f4f7b4a778c73b8cfd77c2336 100644 (file)
@@ -213,7 +213,7 @@ struct devfreq_simple_ondemand_data {
 #endif
 
 #else /* !CONFIG_PM_DEVFREQ */
-static struct devfreq *devfreq_add_device(struct device *dev,
+static inline struct devfreq *devfreq_add_device(struct device *dev,
                                          struct devfreq_dev_profile *profile,
                                          const char *governor_name,
                                          void *data)
@@ -221,34 +221,34 @@ static struct devfreq *devfreq_add_device(struct device *dev,
        return NULL;
 }
 
-static int devfreq_remove_device(struct devfreq *devfreq)
+static inline int devfreq_remove_device(struct devfreq *devfreq)
 {
        return 0;
 }
 
-static int devfreq_suspend_device(struct devfreq *devfreq)
+static inline int devfreq_suspend_device(struct devfreq *devfreq)
 {
        return 0;
 }
 
-static int devfreq_resume_device(struct devfreq *devfreq)
+static inline int devfreq_resume_device(struct devfreq *devfreq)
 {
        return 0;
 }
 
-static struct opp *devfreq_recommended_opp(struct device *dev,
+static inline struct opp *devfreq_recommended_opp(struct device *dev,
                                           unsigned long *freq, u32 flags)
 {
-       return -EINVAL;
+       return ERR_PTR(-EINVAL);
 }
 
-static int devfreq_register_opp_notifier(struct device *dev,
+static inline int devfreq_register_opp_notifier(struct device *dev,
                                         struct devfreq *devfreq)
 {
        return -EINVAL;
 }
 
-static int devfreq_unregister_opp_notifier(struct device *dev,
+static inline int devfreq_unregister_opp_notifier(struct device *dev,
                                           struct devfreq *devfreq)
 {
        return -EINVAL;
index 4fd4999ccb5bf3386db3c27fec3f0f1d4a048b42..0b763276f6199a255d304b572e0c414c90252056 100644 (file)
@@ -561,7 +561,6 @@ struct csrow_info {
 
        u32 ue_count;           /* Uncorrectable Errors for this csrow */
        u32 ce_count;           /* Correctable Errors for this csrow */
-       u32 nr_pages;           /* combined pages count of all channels */
 
        struct mem_ctl_info *mci;       /* the parent */
 
@@ -676,11 +675,11 @@ struct mem_ctl_info {
         * sees memory sticks ("dimms"), and the ones that sees memory ranks.
         * All old memory controllers enumerate memories per rank, but most
         * of the recent drivers enumerate memories per DIMM, instead.
-        * When the memory controller is per rank, mem_is_per_rank is true.
+        * When the memory controller is per rank, csbased is true.
         */
        unsigned n_layers;
        struct edac_mc_layer *layers;
-       bool mem_is_per_rank;
+       bool csbased;
 
        /*
         * DIMM info. Will eventually remove the entire csrows_info some day
@@ -741,8 +740,6 @@ struct mem_ctl_info {
        u32 fake_inject_ue;
        u16 fake_inject_count;
 #endif
-       __u8 csbased : 1,       /* csrow-based memory controller */
-            __resv  : 7;
 };
 
 #endif
index 043a5cf8b5baf3e917dd9ba265c365a334365216..e70df40d84f6fe83c72f732aa44b454148661b6e 100644 (file)
@@ -3,7 +3,6 @@
 #ifndef FREEZER_H_INCLUDED
 #define FREEZER_H_INCLUDED
 
-#include <linux/debug_locks.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
 #include <linux/atomic.h>
@@ -49,8 +48,6 @@ extern void thaw_kernel_threads(void);
 
 static inline bool try_to_freeze(void)
 {
-       if (!(current->flags & PF_NOFREEZE))
-               debug_check_no_locks_held();
        might_sleep();
        if (likely(!freezing(current)))
                return false;
index 729eded4b24f09fa93b7f85b50aaca4b297fd2f9..2b93a9a5a1e6b8ef4a15a6aaf36ade3b48bd0d98 100644 (file)
@@ -50,4 +50,6 @@ static inline void get_fs_root_and_pwd(struct fs_struct *fs, struct path *root,
        spin_unlock(&fs->lock);
 }
 
+extern bool current_chrooted(void);
+
 #endif /* _LINUX_FS_STRUCT_H */
index 61c97ae22e01881d7e1744401e52705c7986fb99..f09a0ae4d858557c8bc7c071c34cd5ec46c29043 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <asm/types.h>
+#include <linux/compiler.h>
 
 /* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
 #define GOLDEN_RATIO_PRIME_32 0x9e370001UL
@@ -31,7 +32,7 @@
 #error Wordsize not 32 or 64
 #endif
 
-static inline u64 hash_64(u64 val, unsigned int bits)
+static __always_inline u64 hash_64(u64 val, unsigned int bits)
 {
        u64 hash = val;
 
index a6f38b5c34e47d000f73483b6a8b3967a7c2f39e..2640c7e99e51c65489d817ee9a44f6205a2cb0ad 100644 (file)
@@ -73,8 +73,6 @@ struct idr {
  */
 
 void *idr_find_slowpath(struct idr *idp, int id);
-int idr_pre_get(struct idr *idp, gfp_t gfp_mask);
-int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
 void idr_preload(gfp_t gfp_mask);
 int idr_alloc(struct idr *idp, void *ptr, int start, int end, gfp_t gfp_mask);
 int idr_for_each(struct idr *idp,
@@ -99,7 +97,7 @@ static inline void idr_preload_end(void)
 
 /**
  * idr_find - return pointer for given id
- * @idp: idr handle
+ * @idr: idr handle
  * @id: lookup key
  *
  * Return the pointer given the id it has been registered with.  A %NULL
@@ -119,19 +117,6 @@ static inline void *idr_find(struct idr *idr, int id)
        return idr_find_slowpath(idr, id);
 }
 
-/**
- * idr_get_new - allocate new idr entry
- * @idp: idr handle
- * @ptr: pointer you want associated with the id
- * @id: pointer to the allocated handle
- *
- * Simple wrapper around idr_get_new_above() w/ @starting_id of zero.
- */
-static inline int idr_get_new(struct idr *idp, void *ptr, int *id)
-{
-       return idr_get_new_above(idp, ptr, 0, id);
-}
-
 /**
  * idr_for_each_entry - iterate over an idr's elements of a given type
  * @idp:     idr handle
@@ -143,7 +128,56 @@ static inline int idr_get_new(struct idr *idp, void *ptr, int *id)
             entry != NULL;                                             \
             ++id, entry = (typeof(entry))idr_get_next((idp), &(id)))
 
-void __idr_remove_all(struct idr *idp);        /* don't use */
+/*
+ * Don't use the following functions.  These exist only to suppress
+ * deprecated warnings on EXPORT_SYMBOL()s.
+ */
+int __idr_pre_get(struct idr *idp, gfp_t gfp_mask);
+int __idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
+void __idr_remove_all(struct idr *idp);
+
+/**
+ * idr_pre_get - reserve resources for idr allocation
+ * @idp:       idr handle
+ * @gfp_mask:  memory allocation flags
+ *
+ * Part of old alloc interface.  This is going away.  Use
+ * idr_preload[_end]() and idr_alloc() instead.
+ */
+static inline int __deprecated idr_pre_get(struct idr *idp, gfp_t gfp_mask)
+{
+       return __idr_pre_get(idp, gfp_mask);
+}
+
+/**
+ * idr_get_new_above - allocate new idr entry above or equal to a start id
+ * @idp: idr handle
+ * @ptr: pointer you want associated with the id
+ * @starting_id: id to start search at
+ * @id: pointer to the allocated handle
+ *
+ * Part of old alloc interface.  This is going away.  Use
+ * idr_preload[_end]() and idr_alloc() instead.
+ */
+static inline int __deprecated idr_get_new_above(struct idr *idp, void *ptr,
+                                                int starting_id, int *id)
+{
+       return __idr_get_new_above(idp, ptr, starting_id, id);
+}
+
+/**
+ * idr_get_new - allocate new idr entry
+ * @idp: idr handle
+ * @ptr: pointer you want associated with the id
+ * @id: pointer to the allocated handle
+ *
+ * Part of old alloc interface.  This is going away.  Use
+ * idr_preload[_end]() and idr_alloc() instead.
+ */
+static inline int __deprecated idr_get_new(struct idr *idp, void *ptr, int *id)
+{
+       return __idr_get_new_above(idp, ptr, 0, id);
+}
 
 /**
  * idr_remove_all - remove all ids from the given idr tree
index 1f86a97ab2e2016407e68fe352bba3b4d018880d..8bd12be0b02f875f1182e9fdcaee69598bc8e083 100644 (file)
@@ -227,14 +227,17 @@ struct st_sensor_data {
 };
 
 #ifdef CONFIG_IIO_BUFFER
+irqreturn_t st_sensors_trigger_handler(int irq, void *p);
+
+int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf);
+#endif
+
+#ifdef CONFIG_IIO_TRIGGER
 int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
                                const struct iio_trigger_ops *trigger_ops);
 
 void st_sensors_deallocate_trigger(struct iio_dev *indio_dev);
 
-irqreturn_t st_sensors_trigger_handler(int irq, void *p);
-
-int st_sensors_get_buffer_element(struct iio_dev *indio_dev, u8 *buf);
 #else
 static inline int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
                                const struct iio_trigger_ops *trigger_ops)
index f5dbce50466e6546fc72f4084ed0d0c91d91fe1e..66017028dcb3d0aebf70aa7281e7758a42bcb3bf 100644 (file)
@@ -37,7 +37,7 @@ void irq_work_sync(struct irq_work *work);
 #ifdef CONFIG_IRQ_WORK
 bool irq_work_needs_cpu(void);
 #else
-static bool irq_work_needs_cpu(void) { return false; }
+static inline bool irq_work_needs_cpu(void) { return false; }
 #endif
 
 #endif /* _LINUX_IRQ_WORK_H */
index 80d36874689b40da26a3107ba509a8ca10dc74da..79fdd80a42d4f001157bc70b9570aa5eda0b8f6c 100644 (file)
@@ -390,7 +390,6 @@ extern struct pid *session_of_pgrp(struct pid *pgrp);
 unsigned long int_sqrt(unsigned long);
 
 extern void bust_spinlocks(int yes);
-extern void wake_up_klogd(void);
 extern int oops_in_progress;           /* If set, an oops, panic(), BUG() or die() is in progress */
 extern int panic_timeout;
 extern int panic_on_oops;
index cad77fe09d770e47a03f8a802bd09fd30b3d136b..c13958251927d6c122c32795c712e8f994c29109 100644 (file)
@@ -518,7 +518,7 @@ int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data,
 int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
                           void *data, unsigned long len);
 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
-                             gpa_t gpa);
+                             gpa_t gpa, unsigned long len);
 int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len);
 int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len);
 struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn);
index fa7cc7244cbdbf019591f644e42622145c8dd28b..b0bcce0ddc95a531dd30c30e91a89c92e961b8d4 100644 (file)
@@ -71,6 +71,7 @@ struct gfn_to_hva_cache {
        u64 generation;
        gpa_t gpa;
        unsigned long hva;
+       unsigned long len;
        struct kvm_memory_slot *memslot;
 };
 
index d991cc147c98f81fbca56ca0cbdf6a6b62aa6c3e..6a1f8df9144bcfd5c1af3e9cbad600fe61749c29 100644 (file)
@@ -667,7 +667,9 @@ static inline void hlist_move_list(struct hlist_head *old,
             pos = n)
 
 #define hlist_entry_safe(ptr, type, member) \
-       (ptr) ? hlist_entry(ptr, type, member) : NULL
+       ({ typeof(ptr) ____ptr = (ptr); \
+          ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
+       })
 
 /**
  * hlist_for_each_entry        - iterate over list of given type
index 5b18ecde69b58be85c4fb39db00464de7d6885bf..1aa4f13cdfa6a4f2b0ceec56a689600f8d53626c 100644 (file)
@@ -106,6 +106,29 @@ enum max77693_muic_reg {
        MAX77693_MUIC_REG_END,
 };
 
+/* MAX77693 INTMASK1~2 Register */
+#define INTMASK1_ADC1K_SHIFT           3
+#define INTMASK1_ADCERR_SHIFT          2
+#define INTMASK1_ADCLOW_SHIFT          1
+#define INTMASK1_ADC_SHIFT             0
+#define INTMASK1_ADC1K_MASK            (1 << INTMASK1_ADC1K_SHIFT)
+#define INTMASK1_ADCERR_MASK           (1 << INTMASK1_ADCERR_SHIFT)
+#define INTMASK1_ADCLOW_MASK           (1 << INTMASK1_ADCLOW_SHIFT)
+#define INTMASK1_ADC_MASK              (1 << INTMASK1_ADC_SHIFT)
+
+#define INTMASK2_VIDRM_SHIFT           5
+#define INTMASK2_VBVOLT_SHIFT          4
+#define INTMASK2_DXOVP_SHIFT           3
+#define INTMASK2_DCDTMR_SHIFT          2
+#define INTMASK2_CHGDETRUN_SHIFT       1
+#define INTMASK2_CHGTYP_SHIFT          0
+#define INTMASK2_VIDRM_MASK            (1 << INTMASK2_VIDRM_SHIFT)
+#define INTMASK2_VBVOLT_MASK           (1 << INTMASK2_VBVOLT_SHIFT)
+#define INTMASK2_DXOVP_MASK            (1 << INTMASK2_DXOVP_SHIFT)
+#define INTMASK2_DCDTMR_MASK           (1 << INTMASK2_DCDTMR_SHIFT)
+#define INTMASK2_CHGDETRUN_MASK                (1 << INTMASK2_CHGDETRUN_SHIFT)
+#define INTMASK2_CHGTYP_MASK           (1 << INTMASK2_CHGTYP_SHIFT)
+
 /* MAX77693 MUIC - STATUS1~3 Register */
 #define STATUS1_ADC_SHIFT              (0)
 #define STATUS1_ADCLOW_SHIFT           (5)
index a4d13d7cd00187cf2928de2d651d486388078224..3bbda22721ea083cc35251e399a37742b72c8bae 100644 (file)
@@ -221,6 +221,7 @@ struct palmas_clk_platform_data {
 };
 
 struct palmas_platform_data {
+       int irq_flags;
        int gpio_base;
 
        /* bit value to be loaded to the POWER_CTRL register */
index aaceab402ec53a35fdbe3eb57ebe6aeb90610753..6d309032dc0ddc7da95e8a1b6b20b275fef0b7bb 100644 (file)
@@ -323,5 +323,6 @@ int tps65912_device_init(struct tps65912 *tps65912);
 void tps65912_device_exit(struct tps65912 *tps65912);
 int tps65912_irq_init(struct tps65912 *tps65912, int irq,
                        struct tps65912_platform_data *pdata);
+int tps65912_irq_exit(struct tps65912 *tps65912);
 
 #endif /*  __LINUX_MFD_TPS65912_H */
index b132067e9e997252c2fa19bf5c4be3c48b0f8f87..867aa23f93704b04154d9ff958990e3b635abc50 100644 (file)
@@ -15,6 +15,8 @@
 #ifndef __MFD_WM831X_AUXADC_H__
 #define __MFD_WM831X_AUXADC_H__
 
+struct wm831x;
+
 /*
  * R16429 (0x402D) - AuxADC Data
  */
index 4a3b83a776148eb2ace611436b38ab42e931450e..76c22648436f22dad8ee59cec7f69ee984322a47 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/irqdomain.h>
 #include <linux/list.h>
 #include <linux/regmap.h>
+#include <linux/mfd/wm831x/auxadc.h>
 
 /*
  * Register values.
@@ -355,7 +356,6 @@ enum wm831x_parent {
 };
 
 struct wm831x;
-enum wm831x_auxadc;
 
 typedef int (*wm831x_auxadc_read_fn)(struct wm831x *wm831x,
                                     enum wm831x_auxadc input);
index 7acc9dc73c9f272bda990e741041a1b5c1237cc5..e19ff30ad0a21453cece0df7524d0b336a69078f 100644 (file)
@@ -87,7 +87,6 @@ extern unsigned int kobjsize(const void *objp);
 #define VM_PFNMAP      0x00000400      /* Page-ranges managed without "struct page", just pure PFN */
 #define VM_DENYWRITE   0x00000800      /* ETXTBSY on write attempts.. */
 
-#define VM_POPULATE     0x00001000
 #define VM_LOCKED      0x00002000
 #define VM_IO           0x00004000     /* Memory mapped I/O or similar */
 
index 61c7a87e5d2b358484dc16ab1b0db79253fc93b3..9aa863da287fedf383f3c507c287aa220cbd6a86 100644 (file)
@@ -79,8 +79,6 @@ calc_vm_flag_bits(unsigned long flags)
 {
        return _calc_vm_trans(flags, MAP_GROWSDOWN,  VM_GROWSDOWN ) |
               _calc_vm_trans(flags, MAP_DENYWRITE,  VM_DENYWRITE ) |
-              ((flags & MAP_LOCKED) ? (VM_LOCKED | VM_POPULATE) : 0) |
-              (((flags & (MAP_POPULATE | MAP_NONBLOCK)) == MAP_POPULATE) ?
-                                                       VM_POPULATE : 0);
+              _calc_vm_trans(flags, MAP_LOCKED,     VM_LOCKED    );
 }
 #endif /* _LINUX_MMAN_H */
index ede274957e05b59e61725f85f0c4acff7b482f33..c74092eebf5c9da5a052168b8885c75290efa2d2 100644 (file)
@@ -527,7 +527,7 @@ static inline int zone_is_oom_locked(const struct zone *zone)
        return test_bit(ZONE_OOM_LOCKED, &zone->flags);
 }
 
-static inline unsigned zone_end_pfn(const struct zone *zone)
+static inline unsigned long zone_end_pfn(const struct zone *zone)
 {
        return zone->zone_start_pfn + zone->spanned_pages;
 }
index d7029f4a191a093ef9294104c75756b6d3b7faee..73005f9957ead2b95adb4107329434afbbf482a7 100644 (file)
@@ -47,6 +47,8 @@ struct mnt_namespace;
 
 #define MNT_INTERNAL   0x4000
 
+#define MNT_LOCK_READONLY      0x400000
+
 struct vfsmount {
        struct dentry *mnt_root;        /* root of the mounted tree */
        struct super_block *mnt_sb;     /* pointer to superblock */
index 7ccb3c59ed605d592fcd0663680b41427a218e7d..ef52d9c91459e0204e31c98483922b7ab95b1ebb 100644 (file)
@@ -187,6 +187,13 @@ typedef enum {
  * This happens with the Renesas AG-AND chips, possibly others.
  */
 #define BBT_AUTO_REFRESH       0x00000080
+/*
+ * Chip requires ready check on read (for auto-incremented sequential read).
+ * True only for small page devices; large page devices do not support
+ * autoincrement.
+ */
+#define NAND_NEED_READRDY      0x00000100
+
 /* Chip does not allow subpage writes */
 #define NAND_NO_SUBPAGE_WRITE  0x00000200
 
index f14943d55315695e36186a75c5db56f07407dd20..f80af86743425ca6219c8c2cfc5b180f2325c85b 100644 (file)
@@ -24,8 +24,8 @@
 #define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
 #define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
 
-#define FB_SYNC_DATA_ENABLE_HIGH_ACT   (1 << 6)
-#define FB_SYNC_DOTCLK_FAILING_ACT     (1 << 7) /* failing/negtive edge sampling */
+#define MXSFB_SYNC_DATA_ENABLE_HIGH_ACT        (1 << 6)
+#define MXSFB_SYNC_DOTCLK_FAILING_ACT  (1 << 7) /* failing/negtive edge sampling */
 
 struct mxsfb_platform_data {
        struct fb_videomode *mode_list;
@@ -44,6 +44,9 @@ struct mxsfb_platform_data {
                                 * allocated. If specified,fb_size must also be specified.
                                 * fb_phys must be unused by Linux.
                                 */
+       u32 sync;               /* sync mask, contains MXSFB specifics not
+                                * carried in fb_info->var.sync
+                                */
 };
 
 #endif /* __LINUX_MXSFB_H */
index b3d00fa4b3149b614365dd215a611ed638fdb924..6151e903eef0a4a380ca03cb24f26e5121543758 100644 (file)
@@ -210,9 +210,9 @@ struct netdev_hw_addr {
 #define NETDEV_HW_ADDR_T_SLAVE         3
 #define NETDEV_HW_ADDR_T_UNICAST       4
 #define NETDEV_HW_ADDR_T_MULTICAST     5
-       bool                    synced;
        bool                    global_use;
        int                     refcount;
+       int                     synced;
        struct rcu_head         rcu_head;
 };
 
@@ -895,7 +895,7 @@ struct netdev_fcoe_hbainfo {
  *
  * int (*ndo_bridge_setlink)(struct net_device *dev, struct nlmsghdr *nlh)
  * int (*ndo_bridge_getlink)(struct sk_buff *skb, u32 pid, u32 seq,
- *                          struct net_device *dev)
+ *                          struct net_device *dev, u32 filter_mask)
  *
  * int (*ndo_change_carrier)(struct net_device *dev, bool new_carrier);
  *     Called to change device carrier. Soft-devices (like dummy, team, etc)
index c25cccaa555a420b5cc6fd26d5e83a89937470a6..4fa3b0b9b071358a779c4448d874e3dffe57900d 100644 (file)
@@ -137,6 +137,34 @@ enum {
        NVME_LBAF_RP_DEGRADED   = 3,
 };
 
+struct nvme_smart_log {
+       __u8                    critical_warning;
+       __u8                    temperature[2];
+       __u8                    avail_spare;
+       __u8                    spare_thresh;
+       __u8                    percent_used;
+       __u8                    rsvd6[26];
+       __u8                    data_units_read[16];
+       __u8                    data_units_written[16];
+       __u8                    host_reads[16];
+       __u8                    host_writes[16];
+       __u8                    ctrl_busy_time[16];
+       __u8                    power_cycles[16];
+       __u8                    power_on_hours[16];
+       __u8                    unsafe_shutdowns[16];
+       __u8                    media_errors[16];
+       __u8                    num_err_log_entries[16];
+       __u8                    rsvd192[320];
+};
+
+enum {
+       NVME_SMART_CRIT_SPARE           = 1 << 0,
+       NVME_SMART_CRIT_TEMPERATURE     = 1 << 1,
+       NVME_SMART_CRIT_RELIABILITY     = 1 << 2,
+       NVME_SMART_CRIT_MEDIA           = 1 << 3,
+       NVME_SMART_CRIT_VOLATILE_MEMORY = 1 << 4,
+};
+
 struct nvme_lba_range_type {
        __u8                    type;
        __u8                    attributes;
index a0f129284948e86bde078d794dd35fbe37629acd..c0747a44eafffad720fe4e625866cdb6639b8cf7 100644 (file)
@@ -235,6 +235,9 @@ extern struct device_node *of_find_node_with_property(
 extern struct property *of_find_property(const struct device_node *np,
                                         const char *name,
                                         int *lenp);
+extern int of_property_read_u32_index(const struct device_node *np,
+                                      const char *propname,
+                                      u32 index, u32 *out_value);
 extern int of_property_read_u8_array(const struct device_node *np,
                        const char *propname, u8 *out_values, size_t sz);
 extern int of_property_read_u16_array(const struct device_node *np,
@@ -394,6 +397,12 @@ static inline struct device_node *of_find_compatible_node(
        return NULL;
 }
 
+static inline int of_property_read_u32_index(const struct device_node *np,
+                       const char *propname, u32 index, u32 *out_value)
+{
+       return -ENOSYS;
+}
+
 static inline int of_property_read_u8_array(const struct device_node *np,
                        const char *propname, u8 *out_values, size_t sz)
 {
index 2461033a798728203f456eff4d6a0099816a7072..710067f3618c5ea93f79072462f6edccbfd2fdb7 100644 (file)
@@ -916,6 +916,7 @@ void pci_disable_rom(struct pci_dev *pdev);
 void __iomem __must_check *pci_map_rom(struct pci_dev *pdev, size_t *size);
 void pci_unmap_rom(struct pci_dev *pdev, void __iomem *rom);
 size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size);
+void __iomem __must_check *pci_platform_rom(struct pci_dev *pdev, size_t *size);
 
 /* Power management related routines */
 int pci_save_state(struct pci_dev *dev);
index e47ee462c2f2e69a8cbef4ef3a3d7bfc873cb51f..1d795df6f4cfdb53575efe2fd756015c0ad363de 100644 (file)
@@ -799,6 +799,12 @@ static inline int __perf_event_disable(void *info)                 { return -1; }
 static inline void perf_event_task_tick(void)                          { }
 #endif
 
+#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL)
+extern void perf_restore_debug_store(void);
+#else
+static inline void perf_restore_debug_store(void)                      { }
+#endif
+
 #define perf_output_put(handle, x) perf_output_copy((handle), &(x), sizeof(x))
 
 /*
diff --git a/include/linux/platform_data/irq-renesas-intc-irqpin.h b/include/linux/platform_data/irq-renesas-intc-irqpin.h
new file mode 100644 (file)
index 0000000..e4cb911
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Renesas INTC External IRQ Pin Driver
+ *
+ *  Copyright (C) 2013 Magnus Damm
+ *
+ * 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
+ *
+ * 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 __IRQ_RENESAS_INTC_IRQPIN_H__
+#define __IRQ_RENESAS_INTC_IRQPIN_H__
+
+struct renesas_intc_irqpin_config {
+       unsigned int sense_bitfield_width;
+       unsigned int irq_base;
+       bool control_parent;
+};
+
+#endif /* __IRQ_RENESAS_INTC_IRQPIN_H__ */
diff --git a/include/linux/platform_data/irq-renesas-irqc.h b/include/linux/platform_data/irq-renesas-irqc.h
new file mode 100644 (file)
index 0000000..3ae17b3
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Renesas IRQC Driver
+ *
+ *  Copyright (C) 2013 Magnus Damm
+ *
+ * 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
+ *
+ * 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 __IRQ_RENESAS_IRQC_H__
+#define __IRQ_RENESAS_IRQC_H__
+
+struct renesas_irqc_config {
+       unsigned int irq_base;
+};
+
+#endif /* __IRQ_RENESAS_IRQC_H__ */
diff --git a/include/linux/platform_data/mmc-sdhci-s3c.h b/include/linux/platform_data/mmc-sdhci-s3c.h
new file mode 100644 (file)
index 0000000..249f023
--- /dev/null
@@ -0,0 +1,56 @@
+#ifndef __PLATFORM_DATA_SDHCI_S3C_H
+#define __PLATFORM_DATA_SDHCI_S3C_H
+
+struct platform_device;
+
+enum cd_types {
+       S3C_SDHCI_CD_INTERNAL,  /* use mmc internal CD line */
+       S3C_SDHCI_CD_EXTERNAL,  /* use external callback */
+       S3C_SDHCI_CD_GPIO,      /* use external gpio pin for CD line */
+       S3C_SDHCI_CD_NONE,      /* no CD line, use polling to detect card */
+       S3C_SDHCI_CD_PERMANENT, /* no CD line, card permanently wired to host */
+};
+
+/**
+ * struct s3c_sdhci_platdata() - Platform device data for Samsung SDHCI
+ * @max_width: The maximum number of data bits supported.
+ * @host_caps: Standard MMC host capabilities bit field.
+ * @host_caps2: The second standard MMC host capabilities bit field.
+ * @cd_type: Type of Card Detection method (see cd_types enum above)
+ * @ext_cd_init: Initialize external card detect subsystem. Called on
+ *              sdhci-s3c driver probe when cd_type == S3C_SDHCI_CD_EXTERNAL.
+ *              notify_func argument is a callback to the sdhci-s3c driver
+ *              that triggers the card detection event. Callback arguments:
+ *              dev is pointer to platform device of the host controller,
+ *              state is new state of the card (0 - removed, 1 - inserted).
+ * @ext_cd_cleanup: Cleanup external card detect subsystem. Called on
+ *              sdhci-s3c driver remove when cd_type == S3C_SDHCI_CD_EXTERNAL.
+ *              notify_func argument is the same callback as for ext_cd_init.
+ * @ext_cd_gpio: gpio pin used for external CD line, valid only if
+ *              cd_type == S3C_SDHCI_CD_GPIO
+ * @ext_cd_gpio_invert: invert values for external CD gpio line
+ * @cfg_gpio: Configure the GPIO for a specific card bit-width
+ *
+ * Initialisation data specific to either the machine or the platform
+ * for the device driver to use or call-back when configuring gpio or
+ * card speed information.
+*/
+struct s3c_sdhci_platdata {
+       unsigned int    max_width;
+       unsigned int    host_caps;
+       unsigned int    host_caps2;
+       unsigned int    pm_caps;
+       enum cd_types   cd_type;
+
+       int             ext_cd_gpio;
+       bool            ext_cd_gpio_invert;
+       int     (*ext_cd_init)(void (*notify_func)(struct platform_device *,
+                                                  int state));
+       int     (*ext_cd_cleanup)(void (*notify_func)(struct platform_device *,
+                                                     int state));
+
+       void    (*cfg_gpio)(struct platform_device *dev, int width);
+};
+
+
+#endif /* __PLATFORM_DATA_SDHCI_S3C_H */
index 1249a54d17e0ab471501919dbdc8d63e27658c35..822171fcb1c82bd110472975d63fd4c2ed5fe8f2 100644 (file)
@@ -134,6 +134,8 @@ extern int printk_delay_msec;
 extern int dmesg_restrict;
 extern int kptr_restrict;
 
+extern void wake_up_klogd(void);
+
 void log_buf_kexec_setup(void);
 void __init setup_log_buf(int early);
 #else
@@ -162,6 +164,10 @@ static inline bool printk_timed_ratelimit(unsigned long *caller_jiffies,
        return false;
 }
 
+static inline void wake_up_klogd(void)
+{
+}
+
 static inline void log_buf_kexec_setup(void)
 {
 }
index 5ae8456d967010b8cb35b1d861d28a487e2103ba..c23099413ad6c03b935826d6680388cc3976ce81 100644 (file)
@@ -14,6 +14,7 @@
  */
 
 #include <linux/cgroup.h>
+#include <linux/errno.h>
 
 /*
  * The core object. the cgroup that wishes to account for some
diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h
new file mode 100644 (file)
index 0000000..2f61311
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef _LINUX_RESET_CONTROLLER_H_
+#define _LINUX_RESET_CONTROLLER_H_
+
+#include <linux/list.h>
+
+struct reset_controller_dev;
+
+/**
+ * struct reset_control_ops
+ *
+ * @reset: for self-deasserting resets, does all necessary
+ *         things to reset the device
+ * @assert: manually assert the reset line, if supported
+ * @deassert: manually deassert the reset line, if supported
+ */
+struct reset_control_ops {
+       int (*reset)(struct reset_controller_dev *rcdev, unsigned long id);
+       int (*assert)(struct reset_controller_dev *rcdev, unsigned long id);
+       int (*deassert)(struct reset_controller_dev *rcdev, unsigned long id);
+};
+
+struct module;
+struct device_node;
+
+/**
+ * struct reset_controller_dev - reset controller entity that might
+ *                               provide multiple reset controls
+ * @ops: a pointer to device specific struct reset_control_ops
+ * @owner: kernel module of the reset controller driver
+ * @list: internal list of reset controller devices
+ * @of_node: corresponding device tree node as phandle target
+ * @of_reset_n_cells: number of cells in reset line specifiers
+ * @of_xlate: translation function to translate from specifier as found in the
+ *            device tree to id as given to the reset control ops
+ * @nr_resets: number of reset controls in this reset controller device
+ */
+struct reset_controller_dev {
+       struct reset_control_ops *ops;
+       struct module *owner;
+       struct list_head list;
+       struct device_node *of_node;
+       int of_reset_n_cells;
+       int (*of_xlate)(struct reset_controller_dev *rcdev,
+                       const struct of_phandle_args *reset_spec);
+       unsigned int nr_resets;
+};
+
+int reset_controller_register(struct reset_controller_dev *rcdev);
+void reset_controller_unregister(struct reset_controller_dev *rcdev);
+
+#endif
diff --git a/include/linux/reset.h b/include/linux/reset.h
new file mode 100644 (file)
index 0000000..6082247
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef _LINUX_RESET_H_
+#define _LINUX_RESET_H_
+
+struct device;
+struct reset_control;
+
+int reset_control_reset(struct reset_control *rstc);
+int reset_control_assert(struct reset_control *rstc);
+int reset_control_deassert(struct reset_control *rstc);
+
+struct reset_control *reset_control_get(struct device *dev, const char *id);
+void reset_control_put(struct reset_control *rstc);
+struct reset_control *devm_reset_control_get(struct device *dev, const char *id);
+
+int device_reset(struct device *dev);
+
+#endif
index a2dcb94ea49de76e81bc6c9d200b555d4cbbba04..9475c5cb28bcc82827e9ed8c540fa59acd5067e9 100644 (file)
@@ -250,11 +250,11 @@ extern int show_unhandled_signals;
 extern int sigsuspend(sigset_t *);
 
 struct sigaction {
-#ifndef __ARCH_HAS_ODD_SIGACTION
+#ifndef __ARCH_HAS_IRIX_SIGACTION
        __sighandler_t  sa_handler;
        unsigned long   sa_flags;
 #else
-       unsigned long   sa_flags;
+       unsigned int    sa_flags;
        __sighandler_t  sa_handler;
 #endif
 #ifdef __ARCH_HAS_SA_RESTORER
index 821c7f45d2a7357085c757c2309177e443b34990..b8292d8cc9fa6238ed0691194f714f827cabd058 100644 (file)
@@ -500,7 +500,7 @@ struct sk_buff {
        union {
                __u32           mark;
                __u32           dropcount;
-               __u32           avail_size;
+               __u32           reserved_tailroom;
        };
 
        sk_buff_data_t          inner_transport_header;
@@ -1288,11 +1288,13 @@ static inline void __skb_fill_page_desc(struct sk_buff *skb, int i,
         * do not lose pfmemalloc information as the pages would not be
         * allocated using __GFP_MEMALLOC.
         */
-       if (page->pfmemalloc && !page->mapping)
-               skb->pfmemalloc = true;
        frag->page.p              = page;
        frag->page_offset         = off;
        skb_frag_size_set(frag, size);
+
+       page = compound_head(page);
+       if (page->pfmemalloc && !page->mapping)
+               skb->pfmemalloc = true;
 }
 
 /**
@@ -1447,7 +1449,10 @@ static inline int skb_tailroom(const struct sk_buff *skb)
  */
 static inline int skb_availroom(const struct sk_buff *skb)
 {
-       return skb_is_nonlinear(skb) ? 0 : skb->avail_size - skb->len;
+       if (skb_is_nonlinear(skb))
+               return 0;
+
+       return skb->end - skb->tail - skb->reserved_tailroom;
 }
 
 /**
@@ -2638,6 +2643,13 @@ static inline void nf_reset(struct sk_buff *skb)
 #endif
 }
 
+static inline void nf_reset_trace(struct sk_buff *skb)
+{
+#if IS_ENABLED(CONFIG_NETFILTER_XT_TARGET_TRACE)
+       skb->nf_trace = 0;
+#endif
+}
+
 /* Note: This doesn't put any conntrack and bridge info in dst. */
 static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src)
 {
index f0bd7f90a90d45d3aeeb3aed8bc2d2f8295c8be0..e3c0ae9bb1faf876afca191701e481ecc30a4f1b 100644 (file)
@@ -44,7 +44,7 @@
 /* Adding event notification support elements */
 #define THERMAL_GENL_FAMILY_NAME                "thermal_event"
 #define THERMAL_GENL_VERSION                    0x01
-#define THERMAL_GENL_MCAST_GROUP_NAME           "thermal_mc_group"
+#define THERMAL_GENL_MCAST_GROUP_NAME           "thermal_mc_grp"
 
 /* Default Thermal Governor */
 #if defined(CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE)
index 9d81de123c9017f4463ba4fa09a61b8b7425a8bf..42278bbf7a882d90360d141db9c8cc1b1eca1719 100644 (file)
@@ -68,6 +68,7 @@ struct udp_sock {
         * For encapsulation sockets.
         */
        int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
+       void (*encap_destroy)(struct sock *sk);
 };
 
 static inline struct udp_sock *udp_sk(const struct sock *sk)
index 3b8f9d4fc3fe7df42af02fda48f83379b24e77ca..cc25b70af33c0b641caa53422c5faacc929809a7 100644 (file)
@@ -127,6 +127,7 @@ struct cdc_ncm_ctx {
        u16 connected;
 };
 
+extern u8 cdc_ncm_select_altsetting(struct usbnet *dev, struct usb_interface *intf);
 extern int cdc_ncm_bind_common(struct usbnet *dev, struct usb_interface *intf, u8 data_altsetting);
 extern void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf);
 extern struct sk_buff *cdc_ncm_fill_tx_frame(struct cdc_ncm_ctx *ctx, struct sk_buff *skb, __le32 sign);
index 3c671c1b37f65350c7f18a6afac3e6a7c594a820..8860594d6364b30f4a5e1c2d4b64be63a28d2a9a 100644 (file)
@@ -60,7 +60,7 @@ struct usb_configuration;
  * @name: For diagnostics, identifies the function.
  * @strings: tables of strings, keyed by identifiers assigned during bind()
  *     and by language IDs provided in control requests
- * @descriptors: Table of full (or low) speed descriptors, using interface and
+ * @fs_descriptors: Table of full (or low) speed descriptors, using interface and
  *     string identifiers assigned during @bind().  If this pointer is null,
  *     the function will not be available at full speed (or at low speed).
  * @hs_descriptors: Table of high speed descriptors, using interface and
@@ -290,6 +290,7 @@ enum {
  *     after function notifications
  * @resume: Notifies configuration when the host restarts USB traffic,
  *     before function notifications
+ * @gadget_driver: Gadget driver controlling this driver
  *
  * Devices default to reporting self powered operation.  Devices which rely
  * on bus powered operation should report this in their @bind method.
index 0a78df5f6cfd23d616ecd4572b6079d1f8605dd2..59694b5e5e906821a873d52a1a33b9c5d67af5d4 100644 (file)
@@ -357,6 +357,7 @@ struct hc_driver {
                 */
        int     (*disable_usb3_lpm_timeout)(struct usb_hcd *,
                        struct usb_device *, enum usb3_link_state state);
+       int     (*find_raw_port_number)(struct usb_hcd *, int);
 };
 
 extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb);
@@ -396,6 +397,7 @@ extern int usb_hcd_is_primary_hcd(struct usb_hcd *hcd);
 extern int usb_add_hcd(struct usb_hcd *hcd,
                unsigned int irqnum, unsigned long irqflags);
 extern void usb_remove_hcd(struct usb_hcd *hcd);
+extern int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1);
 
 struct platform_device;
 extern void usb_hcd_platform_shutdown(struct platform_device *dev);
index 28884c7174112d7ede78d0283d9cba35802eddaa..148d35171aac622ab215bb6520f3dc3f0c0b431f 100644 (file)
@@ -5,6 +5,11 @@
 
 struct nop_usb_xceiv_platform_data {
        enum usb_phy_type type;
+       unsigned long clk_rate;
+
+       /* if set fails with -EPROBE_DEFER if can't get regulator */
+       unsigned int needs_vcc:1;
+       unsigned int needs_reset:1;
 };
 
 #if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE))
index ef9be7e1e1906ea05d1cfef7c6fe58f7ef4ceab3..1819b59aab2a697aa573cbf8fe4e1081292dc713 100644 (file)
@@ -66,6 +66,7 @@
  *     port.
  * @flags: usb serial port flags
  * @write_wait: a wait_queue_head_t used by the port.
+ * @delta_msr_wait: modem-status-change wait queue
  * @work: work queue entry for the line discipline waking up.
  * @throttled: nonzero if the read urb is inactive to throttle the device
  * @throttle_req: nonzero if the tty wants to throttle us
@@ -112,6 +113,7 @@ struct usb_serial_port {
 
        unsigned long           flags;
        wait_queue_head_t       write_wait;
+       wait_queue_head_t       delta_msr_wait;
        struct work_struct      work;
        char                    throttled;
        char                    throttle_req;
index 6f033a415ecb85caa0291a58940922b5d6304419..5c295c26ad37c8d743020ca4bab5996bc52f4df2 100644 (file)
 
 /*-------------------------------------------------------------------------*/
 
+#if IS_ENABLED(CONFIG_USB_ULPI)
 struct usb_phy *otg_ulpi_create(struct usb_phy_io_ops *ops,
                                        unsigned int flags);
+#else
+static inline struct usb_phy *otg_ulpi_create(struct usb_phy_io_ops *ops,
+                                             unsigned int flags)
+{
+       return NULL;
+}
+#endif
 
 #ifdef CONFIG_USB_ULPI_VIEWPORT
 /* access ops for controllers with a viewport register */
index 4ce009324933ebc2b048ebd5f834b0c1bf44e52d..b6b215f13b453091ff2be0fae11b37a5a51c0c84 100644 (file)
@@ -26,6 +26,8 @@ struct user_namespace {
        kuid_t                  owner;
        kgid_t                  group;
        unsigned int            proc_inum;
+       bool                    may_mount_sysfs;
+       bool                    may_mount_proc;
 };
 
 extern struct user_namespace init_user_ns;
@@ -82,4 +84,6 @@ static inline void put_user_ns(struct user_namespace *ns)
 
 #endif
 
+void update_mnt_policy(struct user_namespace *userns);
+
 #endif /* _LINUX_USER_H */
index 853cda11e518be98cbcf0d4bd5fa9270c804d2f5..1f8fd109e2254f10118929fe96e073bbceb13f5a 100644 (file)
@@ -413,13 +413,15 @@ static inline int dst_neigh_output(struct dst_entry *dst, struct neighbour *n,
 
 static inline struct neighbour *dst_neigh_lookup(const struct dst_entry *dst, const void *daddr)
 {
-       return dst->ops->neigh_lookup(dst, NULL, daddr);
+       struct neighbour *n = dst->ops->neigh_lookup(dst, NULL, daddr);
+       return IS_ERR(n) ? NULL : n;
 }
 
 static inline struct neighbour *dst_neigh_lookup_skb(const struct dst_entry *dst,
                                                     struct sk_buff *skb)
 {
-       return dst->ops->neigh_lookup(dst, skb, NULL);
+       struct neighbour *n =  dst->ops->neigh_lookup(dst, skb, NULL);
+       return IS_ERR(n) ? NULL : n;
 }
 
 static inline void dst_link_failure(struct sk_buff *skb)
index 80461c1ae9efcceea9875000629f62608c6e699e..bb8271d487b7bea10861c6548dde50d0964c4a20 100644 (file)
@@ -9,6 +9,7 @@ struct flow_keys {
                __be32 ports;
                __be16 port16[2];
        };
+       u16 thoff;
        u8 ip_proto;
 };
 
index 76c3fe5ecc2e6ed9fcf1b81be7dbd3d3dc258d73..0a1dcc2fa2f58c5be1f177f579fa4fa57c138dfd 100644 (file)
@@ -43,6 +43,13 @@ struct inet_frag_queue {
 
 #define INETFRAGS_HASHSZ               64
 
+/* averaged:
+ * max_depth = default ipfrag_high_thresh / INETFRAGS_HASHSZ /
+ *            rounded up (SKB_TRUELEN(0) + sizeof(struct ipq or
+ *            struct frag_queue))
+ */
+#define INETFRAGS_MAXDEPTH             128
+
 struct inet_frags {
        struct hlist_head       hash[INETFRAGS_HASHSZ];
        /* This rwlock is a global lock (seperate per IPv4, IPv6 and
@@ -76,6 +83,8 @@ int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force);
 struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
                struct inet_frags *f, void *key, unsigned int hash)
        __releases(&f->lock);
+void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
+                                  const char *prefix);
 
 static inline void inet_frag_put(struct inet_frag_queue *q, struct inet_frags *f)
 {
index 9497be1ad4c0c5cdf4fe2df49b79fa5f66a255f8..e49db91593a953422b0ce0a15c0eb0902ee33c56 100644 (file)
@@ -152,18 +152,16 @@ struct fib_result_nl {
 };
 
 #ifdef CONFIG_IP_ROUTE_MULTIPATH
-
 #define FIB_RES_NH(res)                ((res).fi->fib_nh[(res).nh_sel])
-
-#define FIB_TABLE_HASHSZ 2
-
 #else /* CONFIG_IP_ROUTE_MULTIPATH */
-
 #define FIB_RES_NH(res)                ((res).fi->fib_nh[0])
+#endif /* CONFIG_IP_ROUTE_MULTIPATH */
 
+#ifdef CONFIG_IP_MULTIPLE_TABLES
 #define FIB_TABLE_HASHSZ 256
-
-#endif /* CONFIG_IP_ROUTE_MULTIPATH */
+#else
+#define FIB_TABLE_HASHSZ 2
+#endif
 
 extern __be32 fib_info_update_nh_saddr(struct net *net, struct fib_nh *nh);
 
index 68c69d54d39281ee033d765a1b9b66567c55d06f..fce8e6b66d558d8ff8bb629c4da5e358113a675e 100644 (file)
@@ -976,6 +976,7 @@ struct netns_ipvs {
        int                     sysctl_sync_retries;
        int                     sysctl_nat_icmp_send;
        int                     sysctl_pmtu_disc;
+       int                     sysctl_backup_only;
 
        /* ip_vs_lblc */
        int                     sysctl_lblc_expiration;
@@ -1067,6 +1068,12 @@ static inline int sysctl_pmtu_disc(struct netns_ipvs *ipvs)
        return ipvs->sysctl_pmtu_disc;
 }
 
+static inline int sysctl_backup_only(struct netns_ipvs *ipvs)
+{
+       return ipvs->sync_state & IP_VS_STATE_BACKUP &&
+              ipvs->sysctl_backup_only;
+}
+
 #else
 
 static inline int sysctl_sync_threshold(struct netns_ipvs *ipvs)
@@ -1114,6 +1121,11 @@ static inline int sysctl_pmtu_disc(struct netns_ipvs *ipvs)
        return 1;
 }
 
+static inline int sysctl_backup_only(struct netns_ipvs *ipvs)
+{
+       return 0;
+}
+
 #endif
 
 /*
index fd19625ff99db290fd289b3caf18f32c9b72ffc3..982141c15200d1fc60b144a2ca6ba53c0d320200 100644 (file)
@@ -77,15 +77,11 @@ static inline void tunnel_ip_select_ident(struct sk_buff *skb,
 {
        struct iphdr *iph = ip_hdr(skb);
 
-       if (iph->frag_off & htons(IP_DF))
-               iph->id = 0;
-       else {
-               /* Use inner packet iph-id if possible. */
-               if (skb->protocol == htons(ETH_P_IP) && old_iph->id)
-                       iph->id = old_iph->id;
-               else
-                       __ip_select_ident(iph, dst,
-                                         (skb_shinfo(skb)->gso_segs ?: 1) - 1);
-       }
+       /* Use inner packet iph-id if possible. */
+       if (skb->protocol == htons(ETH_P_IP) && old_iph->id)
+               iph->id = old_iph->id;
+       else
+               __ip_select_ident(iph, dst,
+                                 (skb_shinfo(skb)->gso_segs ?: 1) - 1);
 }
 #endif
index 399162b50a8d3479e68183f63f8e227f8db5f6c5..e1379b4e8faf569c6f95131577bba6c4c392e2b0 100644 (file)
@@ -1074,7 +1074,8 @@ void fc_rport_terminate_io(struct fc_rport *);
 /*
  * DISCOVERY LAYER
  *****************************/
-int fc_disc_init(struct fc_lport *);
+void fc_disc_init(struct fc_lport *);
+void fc_disc_config(struct fc_lport *, void *);
 
 static inline struct fc_lport *fc_disc_lport(struct fc_disc *disc)
 {
old mode 100755 (executable)
new mode 100644 (file)
index e1ef63d4a5c453b17630b279d5780b32f1e722c3..44a30b1086835d1d1fcc2840bb5328d5a2ce19b2 100644 (file)
@@ -488,6 +488,7 @@ struct snd_soc_dapm_path {
        /* status */
        u32 connect:1;  /* source and sink widgets are connected */
        u32 walked:1;   /* path has been walked */
+       u32 walking:1;  /* path is in the process of being walked */
        u32 weak:1;     /* path ignored for power management */
 
        int (*connected)(struct snd_soc_dapm_widget *source,
index 11b6ca3e0873c4795fc3b8e8214e5503e6ba16d4..df2f9a0bba6ab78ad93f8ceb7aa240bf6cf329ec 100644 (file)
@@ -107,10 +107,12 @@ struct acct_v3
 #define ACORE          0x08    /* ... dumped core */
 #define AXSIG          0x10    /* ... was killed by a signal */
 
-#ifdef __BIG_ENDIAN
+#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __BIG_ENDIAN : defined(__BIG_ENDIAN)
 #define ACCT_BYTEORDER 0x80    /* accounting file is big endian */
-#else
+#elif defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
 #define ACCT_BYTEORDER 0x00    /* accounting file is little endian */
+#else
+#error unspecified endianness
 #endif
 
 #ifndef __KERNEL__
index 86fa7a71336a1cc2ea007c7410e3ede14807ec4c..bb2554f7fbd12a677015d48703ccf681357e84c6 100644 (file)
@@ -62,9 +62,9 @@ struct io_event {
        __s64           res2;           /* secondary result */
 };
 
-#if defined(__LITTLE_ENDIAN)
+#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
 #define PADDED(x,y)    x, y
-#elif defined(__BIG_ENDIAN)
+#elif defined(__BYTE_ORDER) ? __BYTE_ORDER == __BIG_ENDIAN : defined(__BIG_ENDIAN)
 #define PADDED(x,y)    y, x
 #else
 #error edit for your odd byteorder.
index 93f5fa94a431c167d70902ce6ded5a2275215b53..afafd703ad92b1595a5c7c326883fe89816f920f 100644 (file)
@@ -33,9 +33,11 @@ enum {
        PACKET_DIAG_TX_RING,
        PACKET_DIAG_FANOUT,
 
-       PACKET_DIAG_MAX,
+       __PACKET_DIAG_MAX,
 };
 
+#define PACKET_DIAG_MAX (__PACKET_DIAG_MAX - 1)
+
 struct packet_diag_info {
        __u32   pdi_index;
        __u32   pdi_version;
index ee753536ab7088350a147e1743805985a6b01ac0..fe1a5406d4d93cdf6012d11ab7315f014b552ede 100644 (file)
@@ -145,16 +145,18 @@ typedef struct mdp_superblock_s {
        __u32 failed_disks;     /*  4 Number of failed disks                  */
        __u32 spare_disks;      /*  5 Number of spare disks                   */
        __u32 sb_csum;          /*  6 checksum of the whole superblock        */
-#ifdef __BIG_ENDIAN
+#if defined(__BYTE_ORDER) ? __BYTE_ORDER == __BIG_ENDIAN : defined(__BIG_ENDIAN)
        __u32 events_hi;        /*  7 high-order of superblock update count   */
        __u32 events_lo;        /*  8 low-order of superblock update count    */
        __u32 cp_events_hi;     /*  9 high-order of checkpoint update count   */
        __u32 cp_events_lo;     /* 10 low-order of checkpoint update count    */
-#else
+#elif defined(__BYTE_ORDER) ? __BYTE_ORDER == __LITTLE_ENDIAN : defined(__LITTLE_ENDIAN)
        __u32 events_lo;        /*  7 low-order of superblock update count    */
        __u32 events_hi;        /*  8 high-order of superblock update count   */
        __u32 cp_events_lo;     /*  9 low-order of checkpoint update count    */
        __u32 cp_events_hi;     /* 10 high-order of checkpoint update count   */
+#else
+#error unspecified endianness
 #endif
        __u32 recovery_cp;      /* 11 recovery checkpoint sector count        */
        /* There are only valid for minor_version > 90 */
index b6a23a483d740d635f50bf2ab5261510396e5dff..74c2bf7211f85ed0a55f82987d690cd6bc9aad7c 100644 (file)
 #define PORT_8250_CIR  23      /* CIR infrared port, has its own driver */
 #define PORT_XR17V35X  24      /* Exar XR17V35x UARTs */
 #define PORT_BRCM_TRUMANAGE    25
-#define PORT_MAX_8250  25      /* max port ID */
+#define PORT_ALTR_16550_F32 26 /* Altera 16550 UART with 32 FIFOs */
+#define PORT_ALTR_16550_F64 27 /* Altera 16550 UART with 64 FIFOs */
+#define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */
+#define PORT_MAX_8250  28      /* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed
index b8a24941db21e82b11d80d0912c057a54bcf7742..b9e2a6a7446f077e528dd15fac8e8d97f0d9a232 100644 (file)
@@ -39,9 +39,11 @@ enum {
        UNIX_DIAG_MEMINFO,
        UNIX_DIAG_SHUTDOWN,
 
-       UNIX_DIAG_MAX,
+       __UNIX_DIAG_MAX,
 };
 
+#define UNIX_DIAG_MAX (__UNIX_DIAG_MAX - 1)
+
 struct unix_diag_vfs {
        __u32   udiag_vfs_ino;
        __u32   udiag_vfs_dev;
index 28447f1594fa3fcf5a3a337cf34b4671528a424f..0f5a2fc69af9971606a1b07185e6f366bf21fbec 100644 (file)
@@ -30,8 +30,8 @@
  */
 #define ATMEL_LCDC_WIRING_BGR  0
 #define ATMEL_LCDC_WIRING_RGB  1
-#define ATMEL_LCDC_WIRING_RGB555       2
 
+struct atmel_lcdfb_config;
 
  /* LCD Controller info data structure, stored in device platform_data */
 struct atmel_lcdfb_info {
@@ -62,6 +62,8 @@ struct atmel_lcdfb_info {
        void (*atmel_lcdfb_power_control)(int on);
        struct fb_monspecs      *default_monspecs;
        u32                     pseudo_palette[16];
+
+       struct atmel_lcdfb_config *config;
 };
 
 #define ATMEL_LCDC_DMABADDR1   0x00
index 01c3d62436ef8c44c4d0deffc3393bd2d02b8116..ffd4652de91ca390fff537f18f524300bf470246 100644 (file)
@@ -138,11 +138,21 @@ struct blkif_request_discard {
        uint8_t        _pad3;
 } __attribute__((__packed__));
 
+struct blkif_request_other {
+       uint8_t      _pad1;
+       blkif_vdev_t _pad2;        /* only for read/write requests         */
+#ifdef CONFIG_X86_64
+       uint32_t     _pad3;        /* offsetof(blkif_req..,u.other.id)==8*/
+#endif
+       uint64_t     id;           /* private guest value, echoed in resp  */
+} __attribute__((__packed__));
+
 struct blkif_request {
        uint8_t        operation;    /* BLKIF_OP_???                         */
        union {
                struct blkif_request_rw rw;
                struct blkif_request_discard discard;
+               struct blkif_request_other other;
        } u;
 } __attribute__((__packed__));
 
index 1844d31f45520fef57c93be90ba7e247e1a0b042..7000bb1f6e96fb018fcc5360cf6266d567f6121e 100644 (file)
@@ -251,6 +251,12 @@ struct physdev_pci_device_add {
 
 #define PHYSDEVOP_pci_device_remove     26
 #define PHYSDEVOP_restore_msi_ext       27
+/*
+ * Dom0 should use these two to announce MMIO resources assigned to
+ * MSI-X capable devices won't (prepare) or may (release) change.
+ */
+#define PHYSDEVOP_prepare_msix          30
+#define PHYSDEVOP_release_msix          31
 struct physdev_pci_device {
     /* IN */
     uint16_t seg;
index 22616cd434bc7d91d157074eb0cf9c9ce9b9f0f0..5341d7232c3ac083c2f87c8a3e1098a9c5e8d601 100644 (file)
@@ -28,10 +28,6 @@ config BUILDTIME_EXTABLE_SORT
 
 menu "General setup"
 
-config EXPERIMENTAL
-       bool
-       default y
-
 config BROKEN
        bool
 
index e5c4f609f22c2a902789e710756aa117f40cf5cc..e4e47f64744635bbebe26fda491ff64eda8e4161 100644 (file)
@@ -330,8 +330,16 @@ static struct dentry *mqueue_mount(struct file_system_type *fs_type,
                         int flags, const char *dev_name,
                         void *data)
 {
-       if (!(flags & MS_KERNMOUNT))
-               data = current->nsproxy->ipc_ns;
+       if (!(flags & MS_KERNMOUNT)) {
+               struct ipc_namespace *ns = current->nsproxy->ipc_ns;
+               /* Don't allow mounting unless the caller has CAP_SYS_ADMIN
+                * over the ipc namespace.
+                */
+               if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN))
+                       return ERR_PTR(-EPERM);
+
+               data = ns;
+       }
        return mount_ns(fs_type, flags, data, mqueue_fill_super);
 }
 
@@ -840,7 +848,8 @@ out_putfd:
                fd = error;
        }
        mutex_unlock(&root->d_inode->i_mutex);
-       mnt_drop_write(mnt);
+       if (!ro)
+               mnt_drop_write(mnt);
 out_putname:
        putname(name);
        return fd;
index 31cd1bf6af271771e67bdf6e29eb306371d3d130..fede1d06ef305cc59386bb4490c7e2e020b9f25d 100644 (file)
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -872,6 +872,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp,
                                                        goto out_unlock;
                                                break;
                                        }
+                                       msg = ERR_PTR(-EAGAIN);
                                } else
                                        break;
                                msg_counter++;
index b0cd86501c30db1a1320d284f2d52eb1ec499f2b..59412d037eed2a81163483b89fb38d9feb30623a 100644 (file)
@@ -4434,12 +4434,15 @@ static void perf_event_task_event(struct perf_task_event *task_event)
                        if (ctxn < 0)
                                goto next;
                        ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
+                       if (ctx)
+                               perf_event_task_ctx(ctx, task_event);
                }
-               if (ctx)
-                       perf_event_task_ctx(ctx, task_event);
 next:
                put_cpu_ptr(pmu->pmu_cpu_context);
        }
+       if (task_event->task_ctx)
+               perf_event_task_ctx(task_event->task_ctx, task_event);
+
        rcu_read_unlock();
 }
 
@@ -5647,6 +5650,7 @@ static void perf_swevent_init_hrtimer(struct perf_event *event)
                event->attr.sample_period = NSEC_PER_SEC / freq;
                hwc->sample_period = event->attr.sample_period;
                local64_set(&hwc->period_left, hwc->sample_period);
+               hwc->last_period = hwc->sample_period;
                event->attr.freq = 0;
        }
 }
index 51e485ca993560015dbb56701fd249637afc721c..60bc027c61c3a3be8d5bc26b024ffac0a79f1af9 100644 (file)
@@ -835,7 +835,7 @@ void do_exit(long code)
        /*
         * Make sure we are holding no locks:
         */
-       debug_check_no_locks_held();
+       debug_check_no_locks_held(tsk);
        /*
         * We can do this unlocked here. The futex code uses this flag
         * just to verify whether the pi state cleanup has been done
index 8d932b1c9056af738e2903bf813bcbd035ed3892..1766d324d5e35c38ca3910ea237857c0600d1a02 100644 (file)
@@ -1141,6 +1141,9 @@ static struct task_struct *copy_process(unsigned long clone_flags,
        if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
                return ERR_PTR(-EINVAL);
 
+       if ((clone_flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS))
+               return ERR_PTR(-EINVAL);
+
        /*
         * Thread groups must share signals as well, and detached threads
         * can only be started up within the thread group.
@@ -1807,7 +1810,7 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
         * If unsharing a user namespace must also unshare the thread.
         */
        if (unshare_flags & CLONE_NEWUSER)
-               unshare_flags |= CLONE_THREAD;
+               unshare_flags |= CLONE_THREAD | CLONE_FS;
        /*
         * If unsharing a pid namespace must also unshare the thread.
         */
index f0090a993dab1e3d43fd202e05bd904aefc05f2a..b26dcfc02c9489b3ca00bfd076f2208bb4964366 100644 (file)
@@ -223,7 +223,8 @@ static void drop_futex_key_refs(union futex_key *key)
  * @rw:                mapping needs to be read/write (values: VERIFY_READ,
  *              VERIFY_WRITE)
  *
- * Returns a negative error code or 0
+ * Return: a negative error code or 0
+ *
  * The key words are stored in *key on success.
  *
  * For shared mappings, it's (page->index, file_inode(vma->vm_file),
@@ -705,9 +706,9 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb,
  *                     be "current" except in the case of requeue pi.
  * @set_waiters:       force setting the FUTEX_WAITERS bit (1) or not (0)
  *
- * Returns:
- *  0 - ready to wait
- *  1 - acquired the lock
+ * Return:
+ *  0 - ready to wait;
+ *  1 - acquired the lock;
  * <0 - error
  *
  * The hb->lock and futex_key refs shall be held by the caller.
@@ -1191,9 +1192,9 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key,
  * then direct futex_lock_pi_atomic() to force setting the FUTEX_WAITERS bit.
  * hb1 and hb2 must be held by the caller.
  *
- * Returns:
- *  0 - failed to acquire the lock atomicly
- *  1 - acquired the lock
+ * Return:
+ *  0 - failed to acquire the lock atomically;
+ *  1 - acquired the lock;
  * <0 - error
  */
 static int futex_proxy_trylock_atomic(u32 __user *pifutex,
@@ -1254,8 +1255,8 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex,
  * Requeue waiters on uaddr1 to uaddr2. In the requeue_pi case, try to acquire
  * uaddr2 atomically on behalf of the top waiter.
  *
- * Returns:
- * >=0 - on success, the number of tasks requeued or woken
+ * Return:
+ * >=0 - on success, the number of tasks requeued or woken;
  *  <0 - on error
  */
 static int futex_requeue(u32 __user *uaddr1, unsigned int flags,
@@ -1536,8 +1537,8 @@ static inline void queue_me(struct futex_q *q, struct futex_hash_bucket *hb)
  * The q->lock_ptr must not be held by the caller. A call to unqueue_me() must
  * be paired with exactly one earlier call to queue_me().
  *
- * Returns:
- *   1 - if the futex_q was still queued (and we removed unqueued it)
+ * Return:
+ *   1 - if the futex_q was still queued (and we removed unqueued it);
  *   0 - if the futex_q was already removed by the waking thread
  */
 static int unqueue_me(struct futex_q *q)
@@ -1707,9 +1708,9 @@ static long futex_wait_restart(struct restart_block *restart);
  * the pi_state owner as well as handle race conditions that may allow us to
  * acquire the lock. Must be called with the hb lock held.
  *
- * Returns:
- *  1 - success, lock taken
- *  0 - success, lock not taken
+ * Return:
+ *  1 - success, lock taken;
+ *  0 - success, lock not taken;
  * <0 - on error (-EFAULT)
  */
 static int fixup_owner(u32 __user *uaddr, struct futex_q *q, int locked)
@@ -1824,8 +1825,8 @@ static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q,
  * Return with the hb lock held and a q.key reference on success, and unlocked
  * with no q.key reference on failure.
  *
- * Returns:
- *  0 - uaddr contains val and hb has been locked
+ * Return:
+ *  0 - uaddr contains val and hb has been locked;
  * <1 - -EFAULT or -EWOULDBLOCK (uaddr does not contain val) and hb is unlocked
  */
 static int futex_wait_setup(u32 __user *uaddr, u32 val, unsigned int flags,
@@ -2203,9 +2204,9 @@ pi_faulted:
  * the wakeup and return the appropriate error code to the caller.  Must be
  * called with the hb lock held.
  *
- * Returns
- *  0 - no early wakeup detected
- * <0 - -ETIMEDOUT or -ERESTARTNOINTR
+ * Return:
+ *  0 = no early wakeup detected;
+ * <0 = -ETIMEDOUT or -ERESTARTNOINTR
  */
 static inline
 int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
@@ -2247,7 +2248,6 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
  * @val:       the expected value of uaddr
  * @abs_time:  absolute timeout
  * @bitset:    32 bit wakeup bitset set by userspace, defaults to all
- * @clockrt:   whether to use CLOCK_REALTIME (1) or CLOCK_MONOTONIC (0)
  * @uaddr2:    the pi futex we will take prior to returning to user-space
  *
  * The caller will wait on uaddr and will be requeued by futex_requeue() to
@@ -2258,7 +2258,7 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
  * there was a need to.
  *
  * We call schedule in futex_wait_queue_me() when we enqueue and return there
- * via the following:
+ * via the following--
  * 1) wakeup on uaddr2 after an atomic lock acquisition by futex_requeue()
  * 2) wakeup on uaddr2 after a requeue
  * 3) signal
@@ -2276,8 +2276,8 @@ int handle_early_requeue_pi_wakeup(struct futex_hash_bucket *hb,
  *
  * If 4 or 7, we cleanup and return with -ETIMEDOUT.
  *
- * Returns:
- *  0 - On success
+ * Return:
+ *  0 - On success;
  * <0 - On error
  */
 static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags,
index 259db207b5d90806536da88963e7d1b469e1b943..8a0efac4f99de7c5d0711bea6792db1f385f66eb 100644 (file)
@@ -4088,7 +4088,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len)
 }
 EXPORT_SYMBOL_GPL(debug_check_no_locks_freed);
 
-static void print_held_locks_bug(void)
+static void print_held_locks_bug(struct task_struct *curr)
 {
        if (!debug_locks_off())
                return;
@@ -4097,21 +4097,22 @@ static void print_held_locks_bug(void)
 
        printk("\n");
        printk("=====================================\n");
-       printk("[ BUG: %s/%d still has locks held! ]\n",
-              current->comm, task_pid_nr(current));
+       printk("[ BUG: lock held at task exit time! ]\n");
        print_kernel_ident();
        printk("-------------------------------------\n");
-       lockdep_print_held_locks(current);
+       printk("%s/%d is exiting with locks still held!\n",
+               curr->comm, task_pid_nr(curr));
+       lockdep_print_held_locks(curr);
+
        printk("\nstack backtrace:\n");
        dump_stack();
 }
 
-void debug_check_no_locks_held(void)
+void debug_check_no_locks_held(struct task_struct *task)
 {
-       if (unlikely(current->lockdep_depth > 0))
-               print_held_locks_bug();
+       if (unlikely(task->lockdep_depth > 0))
+               print_held_locks_bug(task);
 }
-EXPORT_SYMBOL_GPL(debug_check_no_locks_held);
 
 void debug_show_all_locks(void)
 {
index c1c3dc1c60233f337a01ff13587f1a5a7f57f1cd..bea15bdf82b04c28d2f5d8c1a32a46b2621cb295 100644 (file)
@@ -181,6 +181,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
        int nr;
        int rc;
        struct task_struct *task, *me = current;
+       int init_pids = thread_group_leader(me) ? 1 : 2;
 
        /* Don't allow any more processes into the pid namespace */
        disable_pid_allocation(pid_ns);
@@ -230,7 +231,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
         */
        for (;;) {
                set_current_state(TASK_UNINTERRUPTIBLE);
-               if (pid_ns->nr_hashed == 1)
+               if (pid_ns->nr_hashed == init_pids)
                        break;
                schedule();
        }
index 0b31715f335a7a8ba1a846fe3b93fe71d97cd8d7..abbdd9e2ac82c423a3dc6c778632c37887241b41 100644 (file)
@@ -63,8 +63,6 @@ void asmlinkage __attribute__((weak)) early_printk(const char *fmt, ...)
 #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
 #define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
 
-DECLARE_WAIT_QUEUE_HEAD(log_wait);
-
 int console_printk[4] = {
        DEFAULT_CONSOLE_LOGLEVEL,       /* console_loglevel */
        DEFAULT_MESSAGE_LOGLEVEL,       /* default_message_loglevel */
@@ -224,6 +222,7 @@ struct log {
 static DEFINE_RAW_SPINLOCK(logbuf_lock);
 
 #ifdef CONFIG_PRINTK
+DECLARE_WAIT_QUEUE_HEAD(log_wait);
 /* the next printk record to read by syslog(READ) or /proc/kmsg */
 static u64 syslog_seq;
 static u32 syslog_idx;
@@ -1957,45 +1956,6 @@ int is_console_locked(void)
        return console_locked;
 }
 
-/*
- * Delayed printk version, for scheduler-internal messages:
- */
-#define PRINTK_BUF_SIZE                512
-
-#define PRINTK_PENDING_WAKEUP  0x01
-#define PRINTK_PENDING_SCHED   0x02
-
-static DEFINE_PER_CPU(int, printk_pending);
-static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf);
-
-static void wake_up_klogd_work_func(struct irq_work *irq_work)
-{
-       int pending = __this_cpu_xchg(printk_pending, 0);
-
-       if (pending & PRINTK_PENDING_SCHED) {
-               char *buf = __get_cpu_var(printk_sched_buf);
-               printk(KERN_WARNING "[sched_delayed] %s", buf);
-       }
-
-       if (pending & PRINTK_PENDING_WAKEUP)
-               wake_up_interruptible(&log_wait);
-}
-
-static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = {
-       .func = wake_up_klogd_work_func,
-       .flags = IRQ_WORK_LAZY,
-};
-
-void wake_up_klogd(void)
-{
-       preempt_disable();
-       if (waitqueue_active(&log_wait)) {
-               this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
-               irq_work_queue(&__get_cpu_var(wake_up_klogd_work));
-       }
-       preempt_enable();
-}
-
 static void console_cont_flush(char *text, size_t size)
 {
        unsigned long flags;
@@ -2458,6 +2418,44 @@ static int __init printk_late_init(void)
 late_initcall(printk_late_init);
 
 #if defined CONFIG_PRINTK
+/*
+ * Delayed printk version, for scheduler-internal messages:
+ */
+#define PRINTK_BUF_SIZE                512
+
+#define PRINTK_PENDING_WAKEUP  0x01
+#define PRINTK_PENDING_SCHED   0x02
+
+static DEFINE_PER_CPU(int, printk_pending);
+static DEFINE_PER_CPU(char [PRINTK_BUF_SIZE], printk_sched_buf);
+
+static void wake_up_klogd_work_func(struct irq_work *irq_work)
+{
+       int pending = __this_cpu_xchg(printk_pending, 0);
+
+       if (pending & PRINTK_PENDING_SCHED) {
+               char *buf = __get_cpu_var(printk_sched_buf);
+               printk(KERN_WARNING "[sched_delayed] %s", buf);
+       }
+
+       if (pending & PRINTK_PENDING_WAKEUP)
+               wake_up_interruptible(&log_wait);
+}
+
+static DEFINE_PER_CPU(struct irq_work, wake_up_klogd_work) = {
+       .func = wake_up_klogd_work_func,
+       .flags = IRQ_WORK_LAZY,
+};
+
+void wake_up_klogd(void)
+{
+       preempt_disable();
+       if (waitqueue_active(&log_wait)) {
+               this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP);
+               irq_work_queue(&__get_cpu_var(wake_up_klogd_work));
+       }
+       preempt_enable();
+}
 
 int printk_sched(const char *fmt, ...)
 {
index 2ec870a4c3c4faa2a6c30c0ee380d9fc9bd25de5..dd72567767d963ccb8ac2f3cfa4a824fa5f81b4e 100644 (file)
@@ -485,6 +485,9 @@ flush_signal_handlers(struct task_struct *t, int force_default)
                if (force_default || ka->sa.sa_handler != SIG_IGN)
                        ka->sa.sa_handler = SIG_DFL;
                ka->sa.sa_flags = 0;
+#ifdef __ARCH_HAS_SA_RESTORER
+               ka->sa.sa_restorer = NULL;
+#endif
                sigemptyset(&ka->sa.sa_mask);
                ka++;
        }
@@ -2682,7 +2685,7 @@ static int do_sigpending(void *set, unsigned long sigsetsize)
 /**
  *  sys_rt_sigpending - examine a pending signal that has been raised
  *                     while blocked
- *  @set: stores pending signals
+ *  @uset: stores pending signals
  *  @sigsetsize: size of sigset_t type or larger
  */
 SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize)
index 81f56445fba949790b34b7bf3f97383555134672..39c9c4a2949f3166b114f11534957ff2f6060565 100644 (file)
@@ -2185,9 +2185,8 @@ SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep,
 
 char poweroff_cmd[POWEROFF_CMD_PATH_LEN] = "/sbin/poweroff";
 
-static int __orderly_poweroff(void)
+static int __orderly_poweroff(bool force)
 {
-       int argc;
        char **argv;
        static char *envp[] = {
                "HOME=/",
@@ -2196,20 +2195,40 @@ static int __orderly_poweroff(void)
        };
        int ret;
 
-       argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc);
-       if (argv == NULL) {
+       argv = argv_split(GFP_KERNEL, poweroff_cmd, NULL);
+       if (argv) {
+               ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
+               argv_free(argv);
+       } else {
                printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n",
-                      __func__, poweroff_cmd);
-               return -ENOMEM;
+                                        __func__, poweroff_cmd);
+               ret = -ENOMEM;
        }
 
-       ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_WAIT_EXEC,
-                                     NULL, NULL, NULL);
-       argv_free(argv);
+       if (ret && force) {
+               printk(KERN_WARNING "Failed to start orderly shutdown: "
+                                       "forcing the issue\n");
+               /*
+                * I guess this should try to kick off some daemon to sync and
+                * poweroff asap.  Or not even bother syncing if we're doing an
+                * emergency shutdown?
+                */
+               emergency_sync();
+               kernel_power_off();
+       }
 
        return ret;
 }
 
+static bool poweroff_force;
+
+static void poweroff_work_func(struct work_struct *work)
+{
+       __orderly_poweroff(poweroff_force);
+}
+
+static DECLARE_WORK(poweroff_work, poweroff_work_func);
+
 /**
  * orderly_poweroff - Trigger an orderly system poweroff
  * @force: force poweroff if command execution fails
@@ -2219,21 +2238,9 @@ static int __orderly_poweroff(void)
  */
 int orderly_poweroff(bool force)
 {
-       int ret = __orderly_poweroff();
-
-       if (ret && force) {
-               printk(KERN_WARNING "Failed to start orderly shutdown: "
-                      "forcing the issue\n");
-
-               /*
-                * I guess this should try to kick off some daemon to sync and
-                * poweroff asap.  Or not even bother syncing if we're doing an
-                * emergency shutdown?
-                */
-               emergency_sync();
-               kernel_power_off();
-       }
-
-       return ret;
+       if (force) /* do not override the pending "true" */
+               poweroff_force = true;
+       schedule_work(&poweroff_work);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(orderly_poweroff);
index 2fb8cb88df8d0296e655f320bc7d5cbce1a858c8..7f32fe0e52cd46489c8d90e4b85f9d74204aab16 100644 (file)
@@ -67,7 +67,8 @@ static void tick_broadcast_start_periodic(struct clock_event_device *bc)
  */
 int tick_check_broadcast_device(struct clock_event_device *dev)
 {
-       if ((tick_broadcast_device.evtdev &&
+       if ((dev->features & CLOCK_EVT_FEAT_DUMMY) ||
+           (tick_broadcast_device.evtdev &&
             tick_broadcast_device.evtdev->rating >= dev->rating) ||
             (dev->features & CLOCK_EVT_FEAT_C3STOP))
                return 0;
index 192473b22799032c5cb013868f778ad4bc30626a..fc382d6e2765d4a454a85aa5591c8edc452dccfb 100644 (file)
@@ -414,24 +414,28 @@ config PROBE_EVENTS
        def_bool n
 
 config DYNAMIC_FTRACE
-       bool "enable/disable ftrace tracepoints dynamically"
+       bool "enable/disable function tracing dynamically"
        depends on FUNCTION_TRACER
        depends on HAVE_DYNAMIC_FTRACE
        default y
        help
-          This option will modify all the calls to ftrace dynamically
-         (will patch them out of the binary image and replace them
-         with a No-Op instruction) as they are called. A table is
-         created to dynamically enable them again.
+         This option will modify all the calls to function tracing
+         dynamically (will patch them out of the binary image and
+         replace them with a No-Op instruction) on boot up. During
+         compile time, a table is made of all the locations that ftrace
+         can function trace, and this table is linked into the kernel
+         image. When this is enabled, functions can be individually
+         enabled, and the functions not enabled will not affect
+         performance of the system.
+
+         See the files in /sys/kernel/debug/tracing:
+           available_filter_functions
+           set_ftrace_filter
+           set_ftrace_notrace
 
          This way a CONFIG_FUNCTION_TRACER kernel is slightly larger, but
          otherwise has native performance as long as no tracing is active.
 
-         The changes to the code are done by a kernel thread that
-         wakes up once a second and checks to see if any ftrace calls
-         were made. If so, it runs stop_machine (stops all CPUS)
-         and modifies the code to jump over the call to ftrace.
-
 config DYNAMIC_FTRACE_WITH_REGS
        def_bool y
        depends on DYNAMIC_FTRACE
index ab25b88aae56f4e22380766b02378669c8b05c57..6893d5a2bf086014f2919496ca7062c246935dad 100644 (file)
@@ -3104,8 +3104,8 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
                                        continue;
                        }
 
-                       hlist_del(&entry->node);
-                       call_rcu(&entry->rcu, ftrace_free_entry_rcu);
+                       hlist_del_rcu(&entry->node);
+                       call_rcu_sched(&entry->rcu, ftrace_free_entry_rcu);
                }
        }
        __disable_ftrace_function_probe();
index c2e2c23103742e3a3e53cf7b318aa0c804f5e1a8..4f1dade56981d6fe5d880e9f6caaf609ab1e9c02 100644 (file)
@@ -704,7 +704,7 @@ __update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
 void
 update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
 {
-       struct ring_buffer *buf = tr->buffer;
+       struct ring_buffer *buf;
 
        if (trace_stop_count)
                return;
@@ -719,6 +719,7 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu)
 
        arch_spin_lock(&ftrace_max_lock);
 
+       buf = tr->buffer;
        tr->buffer = max_tr.buffer;
        max_tr.buffer = buf;
 
@@ -2400,6 +2401,27 @@ static void test_ftrace_alive(struct seq_file *m)
        seq_printf(m, "#          MAY BE MISSING FUNCTION EVENTS\n");
 }
 
+#ifdef CONFIG_TRACER_MAX_TRACE
+static void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter)
+{
+       if (iter->trace->allocated_snapshot)
+               seq_printf(m, "#\n# * Snapshot is allocated *\n#\n");
+       else
+               seq_printf(m, "#\n# * Snapshot is freed *\n#\n");
+
+       seq_printf(m, "# Snapshot commands:\n");
+       seq_printf(m, "# echo 0 > snapshot : Clears and frees snapshot buffer\n");
+       seq_printf(m, "# echo 1 > snapshot : Allocates snapshot buffer, if not already allocated.\n");
+       seq_printf(m, "#                      Takes a snapshot of the main buffer.\n");
+       seq_printf(m, "# echo 2 > snapshot : Clears snapshot buffer (but does not allocate)\n");
+       seq_printf(m, "#                      (Doesn't have to be '2' works with any number that\n");
+       seq_printf(m, "#                       is not a '0' or '1')\n");
+}
+#else
+/* Should never be called */
+static inline void print_snapshot_help(struct seq_file *m, struct trace_iterator *iter) { }
+#endif
+
 static int s_show(struct seq_file *m, void *v)
 {
        struct trace_iterator *iter = v;
@@ -2411,7 +2433,9 @@ static int s_show(struct seq_file *m, void *v)
                        seq_puts(m, "#\n");
                        test_ftrace_alive(m);
                }
-               if (iter->trace && iter->trace->print_header)
+               if (iter->snapshot && trace_empty(iter))
+                       print_snapshot_help(m, iter);
+               else if (iter->trace && iter->trace->print_header)
                        iter->trace->print_header(m);
                else
                        trace_default_header(m);
@@ -2857,11 +2881,25 @@ static int set_tracer_option(struct tracer *trace, char *cmp, int neg)
        return -EINVAL;
 }
 
-static void set_tracer_flags(unsigned int mask, int enabled)
+/* Some tracers require overwrite to stay enabled */
+int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set)
+{
+       if (tracer->enabled && (mask & TRACE_ITER_OVERWRITE) && !set)
+               return -1;
+
+       return 0;
+}
+
+int set_tracer_flag(unsigned int mask, int enabled)
 {
        /* do nothing if flag is already set */
        if (!!(trace_flags & mask) == !!enabled)
-               return;
+               return 0;
+
+       /* Give the tracer a chance to approve the change */
+       if (current_trace->flag_changed)
+               if (current_trace->flag_changed(current_trace, mask, !!enabled))
+                       return -EINVAL;
 
        if (enabled)
                trace_flags |= mask;
@@ -2871,18 +2909,24 @@ static void set_tracer_flags(unsigned int mask, int enabled)
        if (mask == TRACE_ITER_RECORD_CMD)
                trace_event_enable_cmd_record(enabled);
 
-       if (mask == TRACE_ITER_OVERWRITE)
+       if (mask == TRACE_ITER_OVERWRITE) {
                ring_buffer_change_overwrite(global_trace.buffer, enabled);
+#ifdef CONFIG_TRACER_MAX_TRACE
+               ring_buffer_change_overwrite(max_tr.buffer, enabled);
+#endif
+       }
 
        if (mask == TRACE_ITER_PRINTK)
                trace_printk_start_stop_comm(enabled);
+
+       return 0;
 }
 
 static int trace_set_options(char *option)
 {
        char *cmp;
        int neg = 0;
-       int ret = 0;
+       int ret = -ENODEV;
        int i;
 
        cmp = strstrip(option);
@@ -2892,19 +2936,20 @@ static int trace_set_options(char *option)
                cmp += 2;
        }
 
+       mutex_lock(&trace_types_lock);
+
        for (i = 0; trace_options[i]; i++) {
                if (strcmp(cmp, trace_options[i]) == 0) {
-                       set_tracer_flags(1 << i, !neg);
+                       ret = set_tracer_flag(1 << i, !neg);
                        break;
                }
        }
 
        /* If no option could be set, test the specific tracer options */
-       if (!trace_options[i]) {
-               mutex_lock(&trace_types_lock);
+       if (!trace_options[i])
                ret = set_tracer_option(current_trace, cmp, neg);
-               mutex_unlock(&trace_types_lock);
-       }
+
+       mutex_unlock(&trace_types_lock);
 
        return ret;
 }
@@ -2914,6 +2959,7 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
                        size_t cnt, loff_t *ppos)
 {
        char buf[64];
+       int ret;
 
        if (cnt >= sizeof(buf))
                return -EINVAL;
@@ -2923,7 +2969,9 @@ tracing_trace_options_write(struct file *filp, const char __user *ubuf,
 
        buf[cnt] = 0;
 
-       trace_set_options(buf);
+       ret = trace_set_options(buf);
+       if (ret < 0)
+               return ret;
 
        *ppos += cnt;
 
@@ -3227,6 +3275,9 @@ static int tracing_set_tracer(const char *buf)
                goto out;
 
        trace_branch_disable();
+
+       current_trace->enabled = false;
+
        if (current_trace->reset)
                current_trace->reset(tr);
 
@@ -3271,6 +3322,7 @@ static int tracing_set_tracer(const char *buf)
        }
 
        current_trace = t;
+       current_trace->enabled = true;
        trace_branch_enable(tr);
  out:
        mutex_unlock(&trace_types_lock);
@@ -4144,8 +4196,6 @@ tracing_snapshot_write(struct file *filp, const char __user *ubuf, size_t cnt,
        default:
                if (current_trace->allocated_snapshot)
                        tracing_reset_online_cpus(&max_tr);
-               else
-                       ret = -EINVAL;
                break;
        }
 
@@ -4759,7 +4809,13 @@ trace_options_core_write(struct file *filp, const char __user *ubuf, size_t cnt,
 
        if (val != 0 && val != 1)
                return -EINVAL;
-       set_tracer_flags(1 << index, val);
+
+       mutex_lock(&trace_types_lock);
+       ret = set_tracer_flag(1 << index, val);
+       mutex_unlock(&trace_types_lock);
+
+       if (ret < 0)
+               return ret;
 
        *ppos += cnt;
 
index 57d7e5397d56da86f667e3139fb14703a99e8fcf..2081971367ea8e54d5b42e188c7aaaaee22c8f2a 100644 (file)
@@ -283,11 +283,15 @@ struct tracer {
        enum print_line_t       (*print_line)(struct trace_iterator *iter);
        /* If you handled the flag setting, return 0 */
        int                     (*set_flag)(u32 old_flags, u32 bit, int set);
+       /* Return 0 if OK with change, else return non-zero */
+       int                     (*flag_changed)(struct tracer *tracer,
+                                               u32 mask, int set);
        struct tracer           *next;
        struct tracer_flags     *flags;
        bool                    print_max;
        bool                    use_max_tr;
        bool                    allocated_snapshot;
+       bool                    enabled;
 };
 
 
@@ -943,6 +947,8 @@ extern const char *__stop___trace_bprintk_fmt[];
 
 void trace_printk_init_buffers(void);
 void trace_printk_start_comm(void);
+int trace_keep_overwrite(struct tracer *tracer, u32 mask, int set);
+int set_tracer_flag(unsigned int mask, int enabled);
 
 #undef FTRACE_ENTRY
 #define FTRACE_ENTRY(call, struct_name, id, tstruct, print, filter)    \
index 713a2cac48816461c0c0a5b11d5a854ea5c4b3d3..443b25b43b4f60f3b58102daab06c6150f01ad64 100644 (file)
@@ -32,7 +32,7 @@ enum {
 
 static int trace_type __read_mostly;
 
-static int save_lat_flag;
+static int save_flags;
 
 static void stop_irqsoff_tracer(struct trace_array *tr, int graph);
 static int start_irqsoff_tracer(struct trace_array *tr, int graph);
@@ -558,8 +558,11 @@ static void stop_irqsoff_tracer(struct trace_array *tr, int graph)
 
 static void __irqsoff_tracer_init(struct trace_array *tr)
 {
-       save_lat_flag = trace_flags & TRACE_ITER_LATENCY_FMT;
-       trace_flags |= TRACE_ITER_LATENCY_FMT;
+       save_flags = trace_flags;
+
+       /* non overwrite screws up the latency tracers */
+       set_tracer_flag(TRACE_ITER_OVERWRITE, 1);
+       set_tracer_flag(TRACE_ITER_LATENCY_FMT, 1);
 
        tracing_max_latency = 0;
        irqsoff_trace = tr;
@@ -573,10 +576,13 @@ static void __irqsoff_tracer_init(struct trace_array *tr)
 
 static void irqsoff_tracer_reset(struct trace_array *tr)
 {
+       int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT;
+       int overwrite_flag = save_flags & TRACE_ITER_OVERWRITE;
+
        stop_irqsoff_tracer(tr, is_graph());
 
-       if (!save_lat_flag)
-               trace_flags &= ~TRACE_ITER_LATENCY_FMT;
+       set_tracer_flag(TRACE_ITER_LATENCY_FMT, lat_flag);
+       set_tracer_flag(TRACE_ITER_OVERWRITE, overwrite_flag);
 }
 
 static void irqsoff_tracer_start(struct trace_array *tr)
@@ -609,6 +615,7 @@ static struct tracer irqsoff_tracer __read_mostly =
        .print_line     = irqsoff_print_line,
        .flags          = &tracer_flags,
        .set_flag       = irqsoff_set_flag,
+       .flag_changed   = trace_keep_overwrite,
 #ifdef CONFIG_FTRACE_SELFTEST
        .selftest    = trace_selftest_startup_irqsoff,
 #endif
@@ -642,6 +649,7 @@ static struct tracer preemptoff_tracer __read_mostly =
        .print_line     = irqsoff_print_line,
        .flags          = &tracer_flags,
        .set_flag       = irqsoff_set_flag,
+       .flag_changed   = trace_keep_overwrite,
 #ifdef CONFIG_FTRACE_SELFTEST
        .selftest    = trace_selftest_startup_preemptoff,
 #endif
@@ -677,6 +685,7 @@ static struct tracer preemptirqsoff_tracer __read_mostly =
        .print_line     = irqsoff_print_line,
        .flags          = &tracer_flags,
        .set_flag       = irqsoff_set_flag,
+       .flag_changed   = trace_keep_overwrite,
 #ifdef CONFIG_FTRACE_SELFTEST
        .selftest    = trace_selftest_startup_preemptirqsoff,
 #endif
index 75aa97fbe1a11120d93ed241e00ddbac5a51a55d..fde652c9a511c197d47822b66871ffb764f62539 100644 (file)
@@ -36,7 +36,7 @@ static void __wakeup_reset(struct trace_array *tr);
 static int wakeup_graph_entry(struct ftrace_graph_ent *trace);
 static void wakeup_graph_return(struct ftrace_graph_ret *trace);
 
-static int save_lat_flag;
+static int save_flags;
 
 #define TRACE_DISPLAY_GRAPH     1
 
@@ -540,8 +540,11 @@ static void stop_wakeup_tracer(struct trace_array *tr)
 
 static int __wakeup_tracer_init(struct trace_array *tr)
 {
-       save_lat_flag = trace_flags & TRACE_ITER_LATENCY_FMT;
-       trace_flags |= TRACE_ITER_LATENCY_FMT;
+       save_flags = trace_flags;
+
+       /* non overwrite screws up the latency tracers */
+       set_tracer_flag(TRACE_ITER_OVERWRITE, 1);
+       set_tracer_flag(TRACE_ITER_LATENCY_FMT, 1);
 
        tracing_max_latency = 0;
        wakeup_trace = tr;
@@ -563,12 +566,15 @@ static int wakeup_rt_tracer_init(struct trace_array *tr)
 
 static void wakeup_tracer_reset(struct trace_array *tr)
 {
+       int lat_flag = save_flags & TRACE_ITER_LATENCY_FMT;
+       int overwrite_flag = save_flags & TRACE_ITER_OVERWRITE;
+
        stop_wakeup_tracer(tr);
        /* make sure we put back any tasks we are tracing */
        wakeup_reset(tr);
 
-       if (!save_lat_flag)
-               trace_flags &= ~TRACE_ITER_LATENCY_FMT;
+       set_tracer_flag(TRACE_ITER_LATENCY_FMT, lat_flag);
+       set_tracer_flag(TRACE_ITER_OVERWRITE, overwrite_flag);
 }
 
 static void wakeup_tracer_start(struct trace_array *tr)
@@ -594,6 +600,7 @@ static struct tracer wakeup_tracer __read_mostly =
        .print_line     = wakeup_print_line,
        .flags          = &tracer_flags,
        .set_flag       = wakeup_set_flag,
+       .flag_changed   = trace_keep_overwrite,
 #ifdef CONFIG_FTRACE_SELFTEST
        .selftest    = trace_selftest_startup_wakeup,
 #endif
@@ -615,6 +622,7 @@ static struct tracer wakeup_rt_tracer __read_mostly =
        .print_line     = wakeup_print_line,
        .flags          = &tracer_flags,
        .set_flag       = wakeup_set_flag,
+       .flag_changed   = trace_keep_overwrite,
 #ifdef CONFIG_FTRACE_SELFTEST
        .selftest    = trace_selftest_startup_wakeup,
 #endif
index e81978e8c03b2b5f1a38d62248d8408fbfcd2d13..8e635a18ab521e48cfc4195cfb9f199de5e0c3b3 100644 (file)
@@ -51,6 +51,8 @@ struct user_namespace init_user_ns = {
        .owner = GLOBAL_ROOT_UID,
        .group = GLOBAL_ROOT_GID,
        .proc_inum = PROC_USER_INIT_INO,
+       .may_mount_sysfs = true,
+       .may_mount_proc = true,
 };
 EXPORT_SYMBOL_GPL(init_user_ns);
 
index 8b650837083e74f7c8bcac7b4f83081c448e36ed..a54f26f82eb250a60c7f24ecc651c6c1bbf8cc88 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/uaccess.h>
 #include <linux/ctype.h>
 #include <linux/projid.h>
+#include <linux/fs_struct.h>
 
 static struct kmem_cache *user_ns_cachep __read_mostly;
 
@@ -60,6 +61,15 @@ int create_user_ns(struct cred *new)
        kgid_t group = new->egid;
        int ret;
 
+       /*
+        * Verify that we can not violate the policy of which files
+        * may be accessed that is specified by the root directory,
+        * by verifing that the root directory is at the root of the
+        * mount namespace which allows all files to be accessed.
+        */
+       if (current_chrooted())
+               return -EPERM;
+
        /* The creator needs a mapping in the parent user namespace
         * or else we won't be able to reasonably tell userspace who
         * created a user_namespace.
@@ -86,6 +96,8 @@ int create_user_ns(struct cred *new)
 
        set_cred_user_ns(new, ns);
 
+       update_mnt_policy(ns);
+
        return 0;
 }
 
@@ -837,6 +849,9 @@ static int userns_install(struct nsproxy *nsproxy, void *ns)
        if (atomic_read(&current->mm->mm_users) > 1)
                return -EINVAL;
 
+       if (current->fs->users != 1)
+               return -EINVAL;
+
        if (!ns_capable(user_ns, CAP_SYS_ADMIN))
                return -EPERM;
 
index 81f2457811eb346915b8c17e4ce5ed44a5de8c10..b48cd597145dd007b503d22755c481256f48867e 100644 (file)
@@ -457,11 +457,12 @@ static int worker_pool_assign_id(struct worker_pool *pool)
        int ret;
 
        mutex_lock(&worker_pool_idr_mutex);
-       idr_pre_get(&worker_pool_idr, GFP_KERNEL);
-       ret = idr_get_new(&worker_pool_idr, pool, &pool->id);
+       ret = idr_alloc(&worker_pool_idr, pool, 0, 0, GFP_KERNEL);
+       if (ret >= 0)
+               pool->id = ret;
        mutex_unlock(&worker_pool_idr_mutex);
 
-       return ret;
+       return ret < 0 ? ret : 0;
 }
 
 /*
@@ -3446,28 +3447,34 @@ static void wq_unbind_fn(struct work_struct *work)
 
                spin_unlock_irq(&pool->lock);
                mutex_unlock(&pool->assoc_mutex);
-       }
 
-       /*
-        * Call schedule() so that we cross rq->lock and thus can guarantee
-        * sched callbacks see the %WORKER_UNBOUND flag.  This is necessary
-        * as scheduler callbacks may be invoked from other cpus.
-        */
-       schedule();
+               /*
+                * Call schedule() so that we cross rq->lock and thus can
+                * guarantee sched callbacks see the %WORKER_UNBOUND flag.
+                * This is necessary as scheduler callbacks may be invoked
+                * from other cpus.
+                */
+               schedule();
 
-       /*
-        * Sched callbacks are disabled now.  Zap nr_running.  After this,
-        * nr_running stays zero and need_more_worker() and keep_working()
-        * are always true as long as the worklist is not empty.  Pools on
-        * @cpu now behave as unbound (in terms of concurrency management)
-        * pools which are served by workers tied to the CPU.
-        *
-        * On return from this function, the current worker would trigger
-        * unbound chain execution of pending work items if other workers
-        * didn't already.
-        */
-       for_each_std_worker_pool(pool, cpu)
+               /*
+                * Sched callbacks are disabled now.  Zap nr_running.
+                * After this, nr_running stays zero and need_more_worker()
+                * and keep_working() are always true as long as the
+                * worklist is not empty.  This pool now behaves as an
+                * unbound (in terms of concurrency management) pool which
+                * are served by workers tied to the pool.
+                */
                atomic_set(&pool->nr_running, 0);
+
+               /*
+                * With concurrency management just turned off, a busy
+                * worker blocking could lead to lengthy stalls.  Kick off
+                * unbound chain execution of currently pending work items.
+                */
+               spin_lock_irq(&pool->lock);
+               wake_up_worker(pool);
+               spin_unlock_irq(&pool->lock);
+       }
 }
 
 /*
index 9681d54b95d127878405d5ff0afec6fcc575fbae..f8e0e536739832bdd05df68647e373788c060fda 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/printk.h>
 #include <linux/spinlock.h>
 #include <linux/tty.h>
 #include <linux/wait.h>
@@ -28,5 +29,3 @@ void __attribute__((weak)) bust_spinlocks(int yes)
                        wake_up_klogd();
        }
 }
-
-
index 5e396accd3d02a8dce6d06cc2d6020e311b308b0..d87a17a819d07a58bc8f1dd40f2d41ae499935c8 100644 (file)
@@ -862,17 +862,21 @@ static void check_unmap(struct dma_debug_entry *ref)
        entry = bucket_find_exact(bucket, ref);
 
        if (!entry) {
+               /* must drop lock before calling dma_mapping_error */
+               put_hash_bucket(bucket, &flags);
+
                if (dma_mapping_error(ref->dev, ref->dev_addr)) {
                        err_printk(ref->dev, NULL,
-                                  "DMA-API: device driver tries "
-                                  "to free an invalid DMA memory address\n");
-                       return;
+                                  "DMA-API: device driver tries to free an "
+                                  "invalid DMA memory address\n");
+               } else {
+                       err_printk(ref->dev, NULL,
+                                  "DMA-API: device driver tries to free DMA "
+                                  "memory it has not allocated [device "
+                                  "address=0x%016llx] [size=%llu bytes]\n",
+                                  ref->dev_addr, ref->size);
                }
-               err_printk(ref->dev, NULL, "DMA-API: device driver tries "
-                          "to free DMA memory it has not allocated "
-                          "[device address=0x%016llx] [size=%llu bytes]\n",
-                          ref->dev_addr, ref->size);
-               goto out;
+               return;
        }
 
        if (ref->size != entry->size) {
@@ -936,7 +940,6 @@ static void check_unmap(struct dma_debug_entry *ref)
        hash_bucket_del(entry);
        dma_entry_free(entry);
 
-out:
        put_hash_bucket(bucket, &flags);
 }
 
@@ -1082,13 +1085,27 @@ void debug_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
        ref.dev = dev;
        ref.dev_addr = dma_addr;
        bucket = get_hash_bucket(&ref, &flags);
-       entry = bucket_find_exact(bucket, &ref);
 
-       if (!entry)
-               goto out;
+       list_for_each_entry(entry, &bucket->list, list) {
+               if (!exact_match(&ref, entry))
+                       continue;
+
+               /*
+                * The same physical address can be mapped multiple
+                * times. Without a hardware IOMMU this results in the
+                * same device addresses being put into the dma-debug
+                * hash multiple times too. This can result in false
+                * positives being reported. Therefore we implement a
+                * best-fit algorithm here which updates the first entry
+                * from the hash which fits the reference value and is
+                * not currently listed as being checked.
+                */
+               if (entry->map_err_type == MAP_ERR_NOT_CHECKED) {
+                       entry->map_err_type = MAP_ERR_CHECKED;
+                       break;
+               }
+       }
 
-       entry->map_err_type = MAP_ERR_CHECKED;
-out:
        put_hash_bucket(bucket, &flags);
 }
 EXPORT_SYMBOL(debug_dma_mapping_error);
index 00739aaf95a2717536957f9cb08413621417a2f8..322e2816f2fb6fe67b512bb4329c49e7377c1591 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -106,8 +106,14 @@ static struct idr_layer *idr_layer_alloc(gfp_t gfp_mask, struct idr *layer_idr)
        if (layer_idr)
                return get_from_free_list(layer_idr);
 
-       /* try to allocate directly from kmem_cache */
-       new = kmem_cache_zalloc(idr_layer_cache, gfp_mask);
+       /*
+        * Try to allocate directly from kmem_cache.  We want to try this
+        * before preload buffer; otherwise, non-preloading idr_alloc()
+        * users will end up taking advantage of preloading ones.  As the
+        * following is allowed to fail for preloaded cases, suppress
+        * warning this time.
+        */
+       new = kmem_cache_zalloc(idr_layer_cache, gfp_mask | __GFP_NOWARN);
        if (new)
                return new;
 
@@ -115,18 +121,24 @@ static struct idr_layer *idr_layer_alloc(gfp_t gfp_mask, struct idr *layer_idr)
         * Try to fetch one from the per-cpu preload buffer if in process
         * context.  See idr_preload() for details.
         */
-       if (in_interrupt())
-               return NULL;
-
-       preempt_disable();
-       new = __this_cpu_read(idr_preload_head);
-       if (new) {
-               __this_cpu_write(idr_preload_head, new->ary[0]);
-               __this_cpu_dec(idr_preload_cnt);
-               new->ary[0] = NULL;
+       if (!in_interrupt()) {
+               preempt_disable();
+               new = __this_cpu_read(idr_preload_head);
+               if (new) {
+                       __this_cpu_write(idr_preload_head, new->ary[0]);
+                       __this_cpu_dec(idr_preload_cnt);
+                       new->ary[0] = NULL;
+               }
+               preempt_enable();
+               if (new)
+                       return new;
        }
-       preempt_enable();
-       return new;
+
+       /*
+        * Both failed.  Try kmem_cache again w/o adding __GFP_NOWARN so
+        * that memory allocation failure warning is printed as intended.
+        */
+       return kmem_cache_zalloc(idr_layer_cache, gfp_mask);
 }
 
 static void idr_layer_rcu_free(struct rcu_head *head)
@@ -184,20 +196,7 @@ static void idr_mark_full(struct idr_layer **pa, int id)
        }
 }
 
-/**
- * idr_pre_get - reserve resources for idr allocation
- * @idp:       idr handle
- * @gfp_mask:  memory allocation flags
- *
- * This function should be called prior to calling the idr_get_new* functions.
- * It preallocates enough memory to satisfy the worst possible allocation. The
- * caller should pass in GFP_KERNEL if possible.  This of course requires that
- * no spinning locks be held.
- *
- * If the system is REALLY out of memory this function returns %0,
- * otherwise %1.
- */
-int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
+int __idr_pre_get(struct idr *idp, gfp_t gfp_mask)
 {
        while (idp->id_free_cnt < MAX_IDR_FREE) {
                struct idr_layer *new;
@@ -208,13 +207,12 @@ int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
        }
        return 1;
 }
-EXPORT_SYMBOL(idr_pre_get);
+EXPORT_SYMBOL(__idr_pre_get);
 
 /**
  * sub_alloc - try to allocate an id without growing the tree depth
  * @idp: idr handle
  * @starting_id: id to start search at
- * @id: pointer to the allocated handle
  * @pa: idr_layer[MAX_IDR_LEVEL] used as backtrack buffer
  * @gfp_mask: allocation mask for idr_layer_alloc()
  * @layer_idr: optional idr passed to idr_layer_alloc()
@@ -376,25 +374,7 @@ static void idr_fill_slot(struct idr *idr, void *ptr, int id,
        idr_mark_full(pa, id);
 }
 
-/**
- * idr_get_new_above - allocate new idr entry above or equal to a start id
- * @idp: idr handle
- * @ptr: pointer you want associated with the id
- * @starting_id: id to start search at
- * @id: pointer to the allocated handle
- *
- * This is the allocate id function.  It should be called with any
- * required locks.
- *
- * If allocation from IDR's private freelist fails, idr_get_new_above() will
- * return %-EAGAIN.  The caller should retry the idr_pre_get() call to refill
- * IDR's preallocation and then retry the idr_get_new_above() call.
- *
- * If the idr is full idr_get_new_above() will return %-ENOSPC.
- *
- * @id returns a value in the range @starting_id ... %0x7fffffff
- */
-int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
+int __idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
 {
        struct idr_layer *pa[MAX_IDR_LEVEL + 1];
        int rv;
@@ -407,7 +387,7 @@ int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id)
        *id = rv;
        return 0;
 }
-EXPORT_SYMBOL(idr_get_new_above);
+EXPORT_SYMBOL(__idr_get_new_above);
 
 /**
  * idr_preload - preload for idr_alloc()
@@ -908,7 +888,7 @@ static void free_bitmap(struct ida *ida, struct ida_bitmap *bitmap)
 int ida_pre_get(struct ida *ida, gfp_t gfp_mask)
 {
        /* allocate idr_layers */
-       if (!idr_pre_get(&ida->idr, gfp_mask))
+       if (!__idr_pre_get(&ida->idr, gfp_mask))
                return 0;
 
        /* allocate free_bitmap */
index 82a04d7ba99ea317aca1888c103f3bee32590bbb..08837db52d94f16b39a45a80eaa4fef774ef8b7b 100644 (file)
@@ -15,7 +15,7 @@ config XZ_DEC_X86
 
 config XZ_DEC_POWERPC
        bool "PowerPC BCJ filter decoder"
-       default y if POWERPC
+       default y if PPC
        select XZ_DEC_BCJ
 
 config XZ_DEC_IA64
index ae55c1e04d105016cf7c780398552e56a498e65a..3bea74f1ccfe1f1f5c134fd5c98767d620553b60 100644 (file)
@@ -286,8 +286,12 @@ config NR_QUICK
        default "1"
 
 config VIRT_TO_BUS
-       def_bool y
-       depends on HAVE_VIRT_TO_BUS
+       bool
+       help
+         An architecture should select this if it implements the
+         deprecated interface virt_to_bus().  All new architectures
+         should probably not select this.
+
 
 config MMU_NOTIFIER
        bool
index 0cd4c11488edf8c8fd33346e9b94e28fb3272aa1..87da3590c61e20287b4854e8212c178f96cb73c6 100644 (file)
@@ -129,7 +129,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,
        struct vm_area_struct *vma;
        int err = -EINVAL;
        int has_write_lock = 0;
-       vm_flags_t vm_flags;
+       vm_flags_t vm_flags = 0;
 
        if (prot)
                return err;
@@ -204,10 +204,8 @@ get_write_lock:
                        unsigned long addr;
                        struct file *file = get_file(vma->vm_file);
 
-                       vm_flags = vma->vm_flags;
-                       if (!(flags & MAP_NONBLOCK))
-                               vm_flags |= VM_POPULATE;
-                       addr = mmap_region(file, start, size, vm_flags, pgoff);
+                       addr = mmap_region(file, start, size,
+                                       vma->vm_flags, pgoff);
                        fput(file);
                        if (IS_ERR_VALUE(addr)) {
                                err = addr;
@@ -226,12 +224,6 @@ get_write_lock:
                mutex_unlock(&mapping->i_mmap_mutex);
        }
 
-       if (!(flags & MAP_NONBLOCK) && !(vma->vm_flags & VM_POPULATE)) {
-               if (!has_write_lock)
-                       goto get_write_lock;
-               vma->vm_flags |= VM_POPULATE;
-       }
-
        if (vma->vm_flags & VM_LOCKED) {
                /*
                 * drop PG_Mlocked flag for over-mapped range
@@ -254,7 +246,8 @@ get_write_lock:
         */
 
 out:
-       vm_flags = vma->vm_flags;
+       if (vma)
+               vm_flags = vma->vm_flags;
        if (likely(!has_write_lock))
                up_read(&mm->mmap_sem);
        else
index 0a0be33bb1997f9b19d1800e906c97f7e5a18d38..ca9a7c6d7e973c5db4bbecd7e72139d5c9529b72 100644 (file)
@@ -2124,8 +2124,12 @@ int hugetlb_report_node_meminfo(int nid, char *buf)
 /* Return the number pages of memory we physically have, in PAGE_SIZE units. */
 unsigned long hugetlb_total_pages(void)
 {
-       struct hstate *h = &default_hstate;
-       return h->nr_huge_pages * pages_per_huge_page(h);
+       struct hstate *h;
+       unsigned long nr_total_pages = 0;
+
+       for_each_hstate(h)
+               nr_total_pages += h->nr_huge_pages * pages_per_huge_page(h);
+       return nr_total_pages;
 }
 
 static int hugetlb_acct_memory(struct hstate *h, long delta)
index b81a367b9f39bb056cc4127a674e8a3dd4d2567d..ee3765760818a6623f86e48a6d775d2d6c2a75a2 100644 (file)
@@ -1779,7 +1779,11 @@ void try_offline_node(int nid)
        for (i = 0; i < MAX_NR_ZONES; i++) {
                struct zone *zone = pgdat->node_zones + i;
 
-               if (zone->wait_table)
+               /*
+                * wait_table may be allocated from boot memory,
+                * here only free if it's allocated by vmalloc.
+                */
+               if (is_vmalloc_addr(zone->wait_table))
                        vfree(zone->wait_table);
        }
 
@@ -1801,7 +1805,7 @@ int __ref remove_memory(int nid, u64 start, u64 size)
        int retry = 1;
 
        start_pfn = PFN_DOWN(start);
-       end_pfn = start_pfn + PFN_DOWN(size);
+       end_pfn = PFN_UP(start + size - 1);
 
        /*
         * When CONFIG_MEMCG is on, one memory block may be used by other
index 1c5e33fce6391ec1ea7569b7d324fc76aa9fa288..79b7cf7d1bca72cee9babfb60e21a38799c8eba1 100644 (file)
@@ -358,7 +358,7 @@ static int do_mlock(unsigned long start, size_t len, int on)
 
                newflags = vma->vm_flags & ~VM_LOCKED;
                if (on)
-                       newflags |= VM_LOCKED | VM_POPULATE;
+                       newflags |= VM_LOCKED;
 
                tmp = vma->vm_end;
                if (tmp > end)
@@ -418,8 +418,7 @@ int __mm_populate(unsigned long start, unsigned long len, int ignore_errors)
                 * range with the first VMA. Also, skip undesirable VMA types.
                 */
                nend = min(end, vma->vm_end);
-               if ((vma->vm_flags & (VM_IO | VM_PFNMAP | VM_POPULATE)) !=
-                   VM_POPULATE)
+               if (vma->vm_flags & (VM_IO | VM_PFNMAP))
                        continue;
                if (nstart < vma->vm_start)
                        nstart = vma->vm_start;
@@ -492,9 +491,9 @@ static int do_mlockall(int flags)
        struct vm_area_struct * vma, * prev = NULL;
 
        if (flags & MCL_FUTURE)
-               current->mm->def_flags |= VM_LOCKED | VM_POPULATE;
+               current->mm->def_flags |= VM_LOCKED;
        else
-               current->mm->def_flags &= ~(VM_LOCKED | VM_POPULATE);
+               current->mm->def_flags &= ~VM_LOCKED;
        if (flags == MCL_FUTURE)
                goto out;
 
@@ -503,7 +502,7 @@ static int do_mlockall(int flags)
 
                newflags = vma->vm_flags & ~VM_LOCKED;
                if (flags & MCL_CURRENT)
-                       newflags |= VM_LOCKED | VM_POPULATE;
+                       newflags |= VM_LOCKED;
 
                /* Ignore errors */
                mlock_fixup(vma, &prev, vma->vm_start, vma->vm_end, newflags);
index 2664a47cec93721d6c73aafa85f32c11a5fb13e6..0db0de1c2fbee21e0e9919af66021b190d789731 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1306,7 +1306,9 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
        }
 
        addr = mmap_region(file, addr, len, vm_flags, pgoff);
-       if (!IS_ERR_VALUE(addr) && (vm_flags & VM_POPULATE))
+       if (!IS_ERR_VALUE(addr) &&
+           ((vm_flags & VM_LOCKED) ||
+            (flags & (MAP_POPULATE | MAP_NONBLOCK)) == MAP_POPULATE))
                *populate = len;
        return addr;
 }
@@ -1938,7 +1940,7 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
 
        /* Check the cache first. */
        /* (Cache hit rate is typically around 35%.) */
-       vma = mm->mmap_cache;
+       vma = ACCESS_ONCE(mm->mmap_cache);
        if (!(vma && vma->vm_end > addr && vma->vm_start <= addr)) {
                struct rb_node *rb_node;
 
index e19328087534af9f77371866c9afe30c70e3ff89..2f3ea749c3184057559cc06ef60960d39bb4bac2 100644 (file)
@@ -821,7 +821,7 @@ struct vm_area_struct *find_vma(struct mm_struct *mm, unsigned long addr)
        struct vm_area_struct *vma;
 
        /* check the cache first */
-       vma = mm->mmap_cache;
+       vma = ACCESS_ONCE(mm->mmap_cache);
        if (vma && vma->vm_start <= addr && vma->vm_end > addr)
                return vma;
 
index 926b466497492f3f8463ebc623adc4fbddf9547a..fd26d0433509e2b5885c74249a9eb04828285180 100644 (file)
@@ -429,12 +429,6 @@ compat_process_vm_rw(compat_pid_t pid,
        if (flags != 0)
                return -EINVAL;
 
-       if (!access_ok(VERIFY_READ, lvec, liovcnt * sizeof(*lvec)))
-               goto out;
-
-       if (!access_ok(VERIFY_READ, rvec, riovcnt * sizeof(*rvec)))
-               goto out;
-
        if (vm_write)
                rc = compat_rw_copy_check_uvector(WRITE, lvec, liovcnt,
                                                  UIO_FASTIOV, iovstack_l,
@@ -459,8 +453,6 @@ free_iovecs:
                kfree(iov_r);
        if (iov_l != iovstack_l)
                kfree(iov_l);
-
-out:
        return rc;
 }
 
index a18714469bf791299f0d60b1a38b9886fdf4dfff..85addcd9372b0d8abfbd277d332408900efdea1d 100644 (file)
@@ -86,13 +86,6 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
 
        grp = &vlan_info->grp;
 
-       /* Take it out of our own structures, but be sure to interlock with
-        * HW accelerating devices or SW vlan input packet processing if
-        * VLAN is not 0 (leave it there for 802.1p).
-        */
-       if (vlan_id)
-               vlan_vid_del(real_dev, vlan_id);
-
        grp->nr_vlan_devs--;
 
        if (vlan->flags & VLAN_FLAG_MVRP)
@@ -114,6 +107,13 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head)
                vlan_gvrp_uninit_applicant(real_dev);
        }
 
+       /* Take it out of our own structures, but be sure to interlock with
+        * HW accelerating devices or SW vlan input packet processing if
+        * VLAN is not 0 (leave it there for 802.1p).
+        */
+       if (vlan_id)
+               vlan_vid_del(real_dev, vlan_id);
+
        /* Get rid of the vlan's reference to real_dev */
        dev_put(real_dev);
 }
index a0b253ecadaf6805106e74c943ed726a81f172bb..a5bb0a769eb927efff0408fa7dd6afbffcdf2ec0 100644 (file)
@@ -1288,7 +1288,8 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
        batadv_ogm_packet = (struct batadv_ogm_packet *)packet_buff;
 
        /* unpack the aggregated packets and process them one by one */
-       do {
+       while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len,
+                                        batadv_ogm_packet->tt_num_changes)) {
                tt_buff = packet_buff + buff_pos + BATADV_OGM_HLEN;
 
                batadv_iv_ogm_process(ethhdr, batadv_ogm_packet, tt_buff,
@@ -1299,8 +1300,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
 
                packet_pos = packet_buff + buff_pos;
                batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos;
-       } while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len,
-                                          batadv_ogm_packet->tt_num_changes));
+       }
 
        kfree_skb(skb);
        return NET_RX_SUCCESS;
index 79d87d8d4f514f5529b57f1b89119a735d068f69..fad0302bdb325e5df700edf4fe323c6226216599 100644 (file)
@@ -359,6 +359,7 @@ static void __sco_sock_close(struct sock *sk)
                        sco_chan_del(sk, ECONNRESET);
                break;
 
+       case BT_CONNECT2:
        case BT_CONNECT:
        case BT_DISCONN:
                sco_chan_del(sk, ECONNRESET);
index d5f1d3fd4b28df39473446defcbad23928d4cb2d..314c73ed418fc43e977c7d47e4bce88ea1104b53 100644 (file)
@@ -66,7 +66,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
                        goto out;
                }
 
-               mdst = br_mdb_get(br, skb);
+               mdst = br_mdb_get(br, skb, vid);
                if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb))
                        br_multicast_deliver(mdst, skb);
                else
index b0812c91c0f0ea6d4010722990a044c72d93ba36..bab338e6270df4604efe792f40025a40d7682347 100644 (file)
@@ -423,7 +423,7 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source,
                        return 0;
                br_warn(br, "adding interface %s with same address "
                       "as a received packet\n",
-                      source->dev->name);
+                      source ? source->dev->name : br->dev->name);
                fdb_delete(br, fdb);
        }
 
index 480330151898486eee3a42382c28f327021d111b..828e2bcc1f525570809b652c98e1c011b2850940 100644 (file)
@@ -97,7 +97,7 @@ int br_handle_frame_finish(struct sk_buff *skb)
        if (is_broadcast_ether_addr(dest))
                skb2 = skb;
        else if (is_multicast_ether_addr(dest)) {
-               mdst = br_mdb_get(br, skb);
+               mdst = br_mdb_get(br, skb, vid);
                if (mdst || BR_INPUT_SKB_CB_MROUTERS_ONLY(skb)) {
                        if ((mdst && mdst->mglist) ||
                            br_multicast_is_router(br))
index 9f97b850fc65171cf87692cf87a3b2e29d906e0c..ee79f3f20383c9112ff2685ef10b6d69a1d40c97 100644 (file)
@@ -80,6 +80,7 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
                                port = p->port;
                                if (port) {
                                        struct br_mdb_entry e;
+                                       memset(&e, 0, sizeof(e));
                                        e.ifindex = port->dev->ifindex;
                                        e.state = p->state;
                                        if (p->addr.proto == htons(ETH_P_IP))
@@ -136,6 +137,7 @@ static int br_mdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
                                break;
 
                        bpm = nlmsg_data(nlh);
+                       memset(bpm, 0, sizeof(*bpm));
                        bpm->ifindex = dev->ifindex;
                        if (br_mdb_fill_info(skb, cb, dev) < 0)
                                goto out;
@@ -171,6 +173,7 @@ static int nlmsg_populate_mdb_fill(struct sk_buff *skb,
                return -EMSGSIZE;
 
        bpm = nlmsg_data(nlh);
+       memset(bpm, 0, sizeof(*bpm));
        bpm->family  = AF_BRIDGE;
        bpm->ifindex = dev->ifindex;
        nest = nla_nest_start(skb, MDBA_MDB);
@@ -228,6 +231,7 @@ void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
 {
        struct br_mdb_entry entry;
 
+       memset(&entry, 0, sizeof(entry));
        entry.ifindex = port->dev->ifindex;
        entry.addr.proto = group->proto;
        entry.addr.u.ip4 = group->u.ip4;
index 10e6fce1bb62abb0987a98c167bf653356e088ac..923fbeaf7afdbb957afb732fc226c4fb669e6a2e 100644 (file)
@@ -132,7 +132,7 @@ static struct net_bridge_mdb_entry *br_mdb_ip6_get(
 #endif
 
 struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
-                                       struct sk_buff *skb)
+                                       struct sk_buff *skb, u16 vid)
 {
        struct net_bridge_mdb_htable *mdb = rcu_dereference(br->mdb);
        struct br_ip ip;
@@ -144,6 +144,7 @@ struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
                return NULL;
 
        ip.proto = skb->protocol;
+       ip.vid = vid;
 
        switch (skb->protocol) {
        case htons(ETH_P_IP):
index 27aa3ee517ce56101e28fd37602356f1f43843ff..299fc5f40a26c12ef39786d8bc3885c0c96ca7be 100644 (file)
@@ -29,6 +29,7 @@ static inline size_t br_port_info_size(void)
                + nla_total_size(1)     /* IFLA_BRPORT_MODE */
                + nla_total_size(1)     /* IFLA_BRPORT_GUARD */
                + nla_total_size(1)     /* IFLA_BRPORT_PROTECT */
+               + nla_total_size(1)     /* IFLA_BRPORT_FAST_LEAVE */
                + 0;
 }
 
@@ -329,6 +330,7 @@ static int br_setport(struct net_bridge_port *p, struct nlattr *tb[])
        br_set_port_flag(p, tb, IFLA_BRPORT_MODE, BR_HAIRPIN_MODE);
        br_set_port_flag(p, tb, IFLA_BRPORT_GUARD, BR_BPDU_GUARD);
        br_set_port_flag(p, tb, IFLA_BRPORT_FAST_LEAVE, BR_MULTICAST_FAST_LEAVE);
+       br_set_port_flag(p, tb, IFLA_BRPORT_PROTECT, BR_ROOT_BLOCK);
 
        if (tb[IFLA_BRPORT_COST]) {
                err = br_stp_set_path_cost(p, nla_get_u32(tb[IFLA_BRPORT_COST]));
index 6d314c4e6bcbca8aa68da999e6117879cda9db12..3cbf5beb3d4be267fbea19a2fd81b7b09d3d6a0c 100644 (file)
@@ -442,7 +442,7 @@ extern int br_multicast_rcv(struct net_bridge *br,
                            struct net_bridge_port *port,
                            struct sk_buff *skb);
 extern struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
-                                              struct sk_buff *skb);
+                                              struct sk_buff *skb, u16 vid);
 extern void br_multicast_add_port(struct net_bridge_port *port);
 extern void br_multicast_del_port(struct net_bridge_port *port);
 extern void br_multicast_enable_port(struct net_bridge_port *port);
@@ -504,7 +504,7 @@ static inline int br_multicast_rcv(struct net_bridge *br,
 }
 
 static inline struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
-                                                     struct sk_buff *skb)
+                                                     struct sk_buff *skb, u16 vid)
 {
        return NULL;
 }
index 69bc4bf89e3e79bb47eddcac63367913a8645ef0..4543b9aba40ce1a9e4565824624bcecba6c298cb 100644 (file)
@@ -654,6 +654,24 @@ static int osdmap_set_max_osd(struct ceph_osdmap *map, int max)
        return 0;
 }
 
+static int __decode_pgid(void **p, void *end, struct ceph_pg *pg)
+{
+       u8 v;
+
+       ceph_decode_need(p, end, 1+8+4+4, bad);
+       v = ceph_decode_8(p);
+       if (v != 1)
+               goto bad;
+       pg->pool = ceph_decode_64(p);
+       pg->seed = ceph_decode_32(p);
+       *p += 4; /* skip preferred */
+       return 0;
+
+bad:
+       dout("error decoding pgid\n");
+       return -EINVAL;
+}
+
 /*
  * decode a full map.
  */
@@ -745,13 +763,12 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end)
        for (i = 0; i < len; i++) {
                int n, j;
                struct ceph_pg pgid;
-               struct ceph_pg_v1 pgid_v1;
                struct ceph_pg_mapping *pg;
 
-               ceph_decode_need(p, end, sizeof(u32) + sizeof(u64), bad);
-               ceph_decode_copy(p, &pgid_v1, sizeof(pgid_v1));
-               pgid.pool = le32_to_cpu(pgid_v1.pool);
-               pgid.seed = le16_to_cpu(pgid_v1.ps);
+               err = __decode_pgid(p, end, &pgid);
+               if (err)
+                       goto bad;
+               ceph_decode_need(p, end, sizeof(u32), bad);
                n = ceph_decode_32(p);
                err = -EINVAL;
                if (n > (UINT_MAX - sizeof(*pg)) / sizeof(u32))
@@ -818,8 +835,8 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
        u16 version;
 
        ceph_decode_16_safe(p, end, version, bad);
-       if (version > 6) {
-               pr_warning("got unknown v %d > %d of inc osdmap\n", version, 6);
+       if (version != 6) {
+               pr_warning("got unknown v %d != 6 of inc osdmap\n", version);
                goto bad;
        }
 
@@ -963,15 +980,14 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
        while (len--) {
                struct ceph_pg_mapping *pg;
                int j;
-               struct ceph_pg_v1 pgid_v1;
                struct ceph_pg pgid;
                u32 pglen;
-               ceph_decode_need(p, end, sizeof(u64) + sizeof(u32), bad);
-               ceph_decode_copy(p, &pgid_v1, sizeof(pgid_v1));
-               pgid.pool = le32_to_cpu(pgid_v1.pool);
-               pgid.seed = le16_to_cpu(pgid_v1.ps);
-               pglen = ceph_decode_32(p);
 
+               err = __decode_pgid(p, end, &pgid);
+               if (err)
+                       goto bad;
+               ceph_decode_need(p, end, sizeof(u32), bad);
+               pglen = ceph_decode_32(p);
                if (pglen) {
                        ceph_decode_need(p, end, pglen*sizeof(u32), bad);
 
index a06a7a58dd1181b4134adf7cd95d4b1b5512cda3..e7d68ed8aafe60f75233fcdc1ed68c39e755cda6 100644 (file)
@@ -1545,7 +1545,6 @@ void net_enable_timestamp(void)
                return;
        }
 #endif
-       WARN_ON(in_interrupt());
        static_key_slow_inc(&netstamp_needed);
 }
 EXPORT_SYMBOL(net_enable_timestamp);
@@ -1625,7 +1624,6 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
        }
 
        skb_orphan(skb);
-       nf_reset(skb);
 
        if (unlikely(!is_skb_forwardable(dev, skb))) {
                atomic_long_inc(&dev->rx_dropped);
@@ -1641,6 +1639,7 @@ int dev_forward_skb(struct net_device *dev, struct sk_buff *skb)
        skb->mark = 0;
        secpath_reset(skb);
        nf_reset(skb);
+       nf_reset_trace(skb);
        return netif_rx(skb);
 }
 EXPORT_SYMBOL_GPL(dev_forward_skb);
@@ -2219,9 +2218,9 @@ struct sk_buff *skb_mac_gso_segment(struct sk_buff *skb,
        struct sk_buff *segs = ERR_PTR(-EPROTONOSUPPORT);
        struct packet_offload *ptype;
        __be16 type = skb->protocol;
+       int vlan_depth = ETH_HLEN;
 
        while (type == htons(ETH_P_8021Q)) {
-               int vlan_depth = ETH_HLEN;
                struct vlan_hdr *vh;
 
                if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN)))
@@ -3315,6 +3314,7 @@ int netdev_rx_handler_register(struct net_device *dev,
        if (dev->rx_handler)
                return -EBUSY;
 
+       /* Note: rx_handler_data must be set before rx_handler */
        rcu_assign_pointer(dev->rx_handler_data, rx_handler_data);
        rcu_assign_pointer(dev->rx_handler, rx_handler);
 
@@ -3335,6 +3335,11 @@ void netdev_rx_handler_unregister(struct net_device *dev)
 
        ASSERT_RTNL();
        RCU_INIT_POINTER(dev->rx_handler, NULL);
+       /* a reader seeing a non NULL rx_handler in a rcu_read_lock()
+        * section has a guarantee to see a non NULL rx_handler_data
+        * as well.
+        */
+       synchronize_net();
        RCU_INIT_POINTER(dev->rx_handler_data, NULL);
 }
 EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister);
@@ -3444,6 +3449,7 @@ ncls:
                }
                switch (rx_handler(&skb)) {
                case RX_HANDLER_CONSUMED:
+                       ret = NET_RX_SUCCESS;
                        goto unlock;
                case RX_HANDLER_ANOTHER:
                        goto another_round;
@@ -4103,7 +4109,7 @@ static void net_rx_action(struct softirq_action *h)
                 * Allow this to run for 2 jiffies since which will allow
                 * an average latency of 1.5/HZ.
                 */
-               if (unlikely(budget <= 0 || time_after(jiffies, time_limit)))
+               if (unlikely(budget <= 0 || time_after_eq(jiffies, time_limit)))
                        goto softnet_break;
 
                local_irq_enable();
@@ -4780,7 +4786,7 @@ EXPORT_SYMBOL(dev_set_mac_address);
 /**
  *     dev_change_carrier - Change device carrier
  *     @dev: device
- *     @new_carries: new value
+ *     @new_carrier: new value
  *
  *     Change device carrier
  */
index bd2eb9d3e369c3ea0cdeac568600fd929c0b0d48..abdc9e6ef33e988ed3e2e00fada13b4ac3147143 100644 (file)
@@ -37,7 +37,7 @@ static int __hw_addr_create_ex(struct netdev_hw_addr_list *list,
        ha->type = addr_type;
        ha->refcount = 1;
        ha->global_use = global;
-       ha->synced = false;
+       ha->synced = 0;
        list_add_tail_rcu(&ha->list, &list->list);
        list->count++;
 
@@ -165,7 +165,7 @@ int __hw_addr_sync(struct netdev_hw_addr_list *to_list,
                                            addr_len, ha->type);
                        if (err)
                                break;
-                       ha->synced = true;
+                       ha->synced++;
                        ha->refcount++;
                } else if (ha->refcount == 1) {
                        __hw_addr_del(to_list, ha->addr, addr_len, ha->type);
@@ -186,7 +186,7 @@ void __hw_addr_unsync(struct netdev_hw_addr_list *to_list,
                if (ha->synced) {
                        __hw_addr_del(to_list, ha->addr,
                                      addr_len, ha->type);
-                       ha->synced = false;
+                       ha->synced--;
                        __hw_addr_del(from_list, ha->addr,
                                      addr_len, ha->type);
                }
index c56ea6f7f6c7c88acbe602a3470c979622345713..2bfd081c59f7706cbd9d8a5ba8a5780aaaae23d1 100644 (file)
@@ -328,7 +328,7 @@ static void flow_cache_flush_per_cpu(void *data)
        struct flow_flush_info *info = data;
        struct tasklet_struct *tasklet;
 
-       tasklet = this_cpu_ptr(&info->cache->percpu->flush_tasklet);
+       tasklet = &this_cpu_ptr(info->cache->percpu)->flush_tasklet;
        tasklet->data = (unsigned long)info;
        tasklet_schedule(tasklet);
 }
index 9d4c7201400d154ab2fd00ccfab4f22f8bddb5ff..e187bf06d673b0ec37d401a8389bba372a8fb3d9 100644 (file)
@@ -140,6 +140,8 @@ ipv6:
                        flow->ports = *ports;
        }
 
+       flow->thoff = (u16) nhoff;
+
        return true;
 }
 EXPORT_SYMBOL(skb_flow_dissect);
index b376410ff2590f3e10897488fd6c092df70faa4c..b65441da74abd85cc8deacc7650c583013e9dcfb 100644 (file)
@@ -496,8 +496,10 @@ static int rtnl_link_fill(struct sk_buff *skb, const struct net_device *dev)
        }
        if (ops->fill_info) {
                data = nla_nest_start(skb, IFLA_INFO_DATA);
-               if (data == NULL)
+               if (data == NULL) {
+                       err = -EMSGSIZE;
                        goto err_cancel_link;
+               }
                err = ops->fill_info(skb, dev);
                if (err < 0)
                        goto err_cancel_data;
@@ -979,6 +981,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                         * report anything.
                         */
                        ivi.spoofchk = -1;
+                       memset(ivi.mac, 0, sizeof(ivi.mac));
                        if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi))
                                break;
                        vf_mac.vf =
@@ -2620,7 +2623,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
                struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len);
 
                while (RTA_OK(attr, attrlen)) {
-                       unsigned int flavor = attr->rta_type;
+                       unsigned int flavor = attr->rta_type & NLA_TYPE_MASK;
                        if (flavor) {
                                if (flavor > rta_max[sz_idx])
                                        return -EINVAL;
index 905dcc6ad1e3b480c01f87df5157f4e37de112a1..2dc6cdaaae8abc5f31afa57a7ccf765cc978b6ac 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/interrupt.h>
 #include <linux/netdevice.h>
 #include <linux/security.h>
+#include <linux/pid_namespace.h>
 #include <linux/pid.h>
 #include <linux/nsproxy.h>
 #include <linux/slab.h>
@@ -52,7 +53,8 @@ static __inline__ int scm_check_creds(struct ucred *creds)
        if (!uid_valid(uid) || !gid_valid(gid))
                return -EINVAL;
 
-       if ((creds->pid == task_tgid_vnr(current) || nsown_capable(CAP_SYS_ADMIN)) &&
+       if ((creds->pid == task_tgid_vnr(current) ||
+            ns_capable(current->nsproxy->pid_ns->user_ns, CAP_SYS_ADMIN)) &&
            ((uid_eq(uid, cred->uid)   || uid_eq(uid, cred->euid) ||
              uid_eq(uid, cred->suid)) || nsown_capable(CAP_SETUID)) &&
            ((gid_eq(gid, cred->gid)   || gid_eq(gid, cred->egid) ||
index 1b588e23cf80b561632b9b5e16b851dff218a933..21291f1abcd6d0d228241b6771984d704bc1699e 100644 (file)
@@ -284,6 +284,7 @@ static int dcbnl_getperm_hwaddr(struct net_device *netdev, struct nlmsghdr *nlh,
        if (!netdev->dcbnl_ops->getpermhwaddr)
                return -EOPNOTSUPP;
 
+       memset(perm_addr, 0, sizeof(perm_addr));
        netdev->dcbnl_ops->getpermhwaddr(netdev, perm_addr);
 
        return nla_put(skb, DCB_ATTR_PERM_HWADDR, sizeof(perm_addr), perm_addr);
@@ -1042,6 +1043,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
 
        if (ops->ieee_getets) {
                struct ieee_ets ets;
+               memset(&ets, 0, sizeof(ets));
                err = ops->ieee_getets(netdev, &ets);
                if (!err &&
                    nla_put(skb, DCB_ATTR_IEEE_ETS, sizeof(ets), &ets))
@@ -1050,6 +1052,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
 
        if (ops->ieee_getmaxrate) {
                struct ieee_maxrate maxrate;
+               memset(&maxrate, 0, sizeof(maxrate));
                err = ops->ieee_getmaxrate(netdev, &maxrate);
                if (!err) {
                        err = nla_put(skb, DCB_ATTR_IEEE_MAXRATE,
@@ -1061,6 +1064,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
 
        if (ops->ieee_getpfc) {
                struct ieee_pfc pfc;
+               memset(&pfc, 0, sizeof(pfc));
                err = ops->ieee_getpfc(netdev, &pfc);
                if (!err &&
                    nla_put(skb, DCB_ATTR_IEEE_PFC, sizeof(pfc), &pfc))
@@ -1094,6 +1098,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
        /* get peer info if available */
        if (ops->ieee_peer_getets) {
                struct ieee_ets ets;
+               memset(&ets, 0, sizeof(ets));
                err = ops->ieee_peer_getets(netdev, &ets);
                if (!err &&
                    nla_put(skb, DCB_ATTR_IEEE_PEER_ETS, sizeof(ets), &ets))
@@ -1102,6 +1107,7 @@ static int dcbnl_ieee_fill(struct sk_buff *skb, struct net_device *netdev)
 
        if (ops->ieee_peer_getpfc) {
                struct ieee_pfc pfc;
+               memset(&pfc, 0, sizeof(pfc));
                err = ops->ieee_peer_getpfc(netdev, &pfc);
                if (!err &&
                    nla_put(skb, DCB_ATTR_IEEE_PEER_PFC, sizeof(pfc), &pfc))
@@ -1280,6 +1286,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
        /* peer info if available */
        if (ops->cee_peer_getpg) {
                struct cee_pg pg;
+               memset(&pg, 0, sizeof(pg));
                err = ops->cee_peer_getpg(netdev, &pg);
                if (!err &&
                    nla_put(skb, DCB_ATTR_CEE_PEER_PG, sizeof(pg), &pg))
@@ -1288,6 +1295,7 @@ static int dcbnl_cee_fill(struct sk_buff *skb, struct net_device *netdev)
 
        if (ops->cee_peer_getpfc) {
                struct cee_pfc pfc;
+               memset(&pfc, 0, sizeof(pfc));
                err = ops->cee_peer_getpfc(netdev, &pfc);
                if (!err &&
                    nla_put(skb, DCB_ATTR_CEE_PEER_PFC, sizeof(pfc), &pfc))
index 8c2251fb0a3fb5ba9347710e4682bdb273d49af9..bba5f8336317a178c5c7c073acd3bbfafde0e6b9 100644 (file)
@@ -84,7 +84,7 @@
        (memcmp(addr1, addr2, length >> 3) == 0)
 
 /* local link, i.e. FE80::/10 */
-#define is_addr_link_local(a) (((a)->s6_addr16[0]) == 0x80FE)
+#define is_addr_link_local(a) (((a)->s6_addr16[0]) == htons(0xFE80))
 
 /*
  * check whether we can compress the IID to 16 bits,
index 68f6a94f7661999095d9a02539aee956cd52e8cc..c929d9c1c4b60d719d60066f7ca06e4b7d296f59 100644 (file)
@@ -1333,8 +1333,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
                                iph->frag_off |= htons(IP_MF);
                        offset += (skb->len - skb->mac_len - iph->ihl * 4);
                } else  {
-                       if (!(iph->frag_off & htons(IP_DF)))
-                               iph->id = htons(id++);
+                       iph->id = htons(id++);
                }
                iph->tot_len = htons(skb->len - skb->mac_len);
                iph->check = 0;
index f678507bc8291f7df43108f470e41c3929af50e8..96083b7a436bc9efddd0b8b3473caa78286e5f02 100644 (file)
@@ -802,8 +802,10 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg
                if (nlh->nlmsg_flags & NLM_F_EXCL ||
                    !(nlh->nlmsg_flags & NLM_F_REPLACE))
                        return -EEXIST;
-
-               set_ifa_lifetime(ifa_existing, valid_lft, prefered_lft);
+               ifa = ifa_existing;
+               set_ifa_lifetime(ifa, valid_lft, prefered_lft);
+               rtmsg_ifa(RTM_NEWADDR, ifa, nlh, NETLINK_CB(skb).portid);
+               blocking_notifier_call_chain(&inetaddr_chain, NETDEV_UP, ifa);
        }
        return 0;
 }
index 7d1874be1df36282ca6c4d0ef3001d05686f335f..786d97aee751e2f2206b9e3b66398bc0995cc645 100644 (file)
@@ -735,6 +735,7 @@ EXPORT_SYMBOL(inet_csk_destroy_sock);
  * tcp/dccp_create_openreq_child().
  */
 void inet_csk_prepare_forced_close(struct sock *sk)
+       __releases(&sk->sk_lock.slock)
 {
        /* sk_clone_lock locked the socket and set refcnt to 2 */
        bh_unlock_sock(sk);
index 245ae078a07fa3d991d6bba6147aab7970f36c9a..f4fd23de9b13103b10351310aea08c47d0429d38 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/rtnetlink.h>
 #include <linux/slab.h>
 
+#include <net/sock.h>
 #include <net/inet_frag.h>
 
 static void inet_frag_secret_rebuild(unsigned long dummy)
@@ -277,6 +278,7 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
        __releases(&f->lock)
 {
        struct inet_frag_queue *q;
+       int depth = 0;
 
        hlist_for_each_entry(q, &f->hash[hash], list) {
                if (q->net == nf && f->match(q, key)) {
@@ -284,9 +286,25 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
                        read_unlock(&f->lock);
                        return q;
                }
+               depth++;
        }
        read_unlock(&f->lock);
 
-       return inet_frag_create(nf, f, key);
+       if (depth <= INETFRAGS_MAXDEPTH)
+               return inet_frag_create(nf, f, key);
+       else
+               return ERR_PTR(-ENOBUFS);
 }
 EXPORT_SYMBOL(inet_frag_find);
+
+void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
+                                  const char *prefix)
+{
+       static const char msg[] = "inet_frag_find: Fragment hash bucket"
+               " list length grew over limit " __stringify(INETFRAGS_MAXDEPTH)
+               ". Dropping fragment.\n";
+
+       if (PTR_ERR(q) == -ENOBUFS)
+               LIMIT_NETDEBUG(KERN_WARNING "%s%s", prefix, msg);
+}
+EXPORT_SYMBOL(inet_frag_maybe_warn_overflow);
index b6d30acb600c5e306ba825ed394c252e4fe27a8b..a6445b843ef40774f2bf5014e6800e1f4fd86b3e 100644 (file)
@@ -292,14 +292,11 @@ static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user)
        hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol);
 
        q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash);
-       if (q == NULL)
-               goto out_nomem;
-
+       if (IS_ERR_OR_NULL(q)) {
+               inet_frag_maybe_warn_overflow(q, pr_fmt());
+               return NULL;
+       }
        return container_of(q, struct ipq, q);
-
-out_nomem:
-       LIMIT_NETDEBUG(KERN_ERR pr_fmt("ip_frag_create: no memory left !\n"));
-       return NULL;
 }
 
 /* Is the fragment too far ahead to be part of ipq? */
index d0ef0e674ec5c083ad719bcd2b8201c82c1116d5..91d66dbde9c05cd05c4e8489a4abd317b378230e 100644 (file)
@@ -798,10 +798,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev
 
        if (dev->header_ops && dev->type == ARPHRD_IPGRE) {
                gre_hlen = 0;
-               if (skb->protocol == htons(ETH_P_IP))
-                       tiph = (const struct iphdr *)skb->data;
-               else
-                       tiph = &tunnel->parms.iph;
+               tiph = (const struct iphdr *)skb->data;
        } else {
                gre_hlen = tunnel->hlen;
                tiph = &tunnel->parms.iph;
index f6289bf6f3325edc2c78541eca88e546e5ec97c9..ec7264514a82e0a130bf15ee01a9030596880921 100644 (file)
@@ -370,7 +370,6 @@ int ip_options_compile(struct net *net,
                                }
                                switch (optptr[3]&0xF) {
                                      case IPOPT_TS_TSONLY:
-                                       opt->ts = optptr - iph;
                                        if (skb)
                                                timeptr = &optptr[optptr[2]-1];
                                        opt->ts_needtime = 1;
@@ -381,7 +380,6 @@ int ip_options_compile(struct net *net,
                                                pp_ptr = optptr + 2;
                                                goto error;
                                        }
-                                       opt->ts = optptr - iph;
                                        if (rt)  {
                                                spec_dst_fill(&spec_dst, skb);
                                                memcpy(&optptr[optptr[2]-1], &spec_dst, 4);
@@ -396,7 +394,6 @@ int ip_options_compile(struct net *net,
                                                pp_ptr = optptr + 2;
                                                goto error;
                                        }
-                                       opt->ts = optptr - iph;
                                        {
                                                __be32 addr;
                                                memcpy(&addr, &optptr[optptr[2]-1], 4);
@@ -423,18 +420,18 @@ int ip_options_compile(struct net *net,
                                        put_unaligned_be32(midtime, timeptr);
                                        opt->is_changed = 1;
                                }
-                       } else {
+                       } else if ((optptr[3]&0xF) != IPOPT_TS_PRESPEC) {
                                unsigned int overflow = optptr[3]>>4;
                                if (overflow == 15) {
                                        pp_ptr = optptr + 3;
                                        goto error;
                                }
-                               opt->ts = optptr - iph;
                                if (skb) {
                                        optptr[3] = (optptr[3]&0xF)|((overflow+1)<<4);
                                        opt->is_changed = 1;
                                }
                        }
+                       opt->ts = optptr - iph;
                        break;
                      case IPOPT_RA:
                        if (optlen < 4) {
index 98cbc6877019428f7d3400632c1e81e50145a814..bf6c5cf31aed27ccba4aa25c4d049f0cc037e3cb 100644 (file)
@@ -1522,7 +1522,8 @@ static int __init ip_auto_config(void)
                }
        for (i++; i < CONF_NAMESERVERS_MAX; i++)
                if (ic_nameservers[i] != NONE)
-                       pr_cont(", nameserver%u=%pI4\n", i, &ic_nameservers[i]);
+                       pr_cont(", nameserver%u=%pI4", i, &ic_nameservers[i]);
+       pr_cont("\n");
 #endif /* !SILENT */
 
        return 0;
index ce2d43e1f09f6b4983e6635e6c2b48ca56fcf18b..0d755c50994b2ca01438158e033c020810a3e8af 100644 (file)
@@ -36,19 +36,6 @@ config NF_CONNTRACK_PROC_COMPAT
 
          If unsure, say Y.
 
-config IP_NF_QUEUE
-       tristate "IP Userspace queueing via NETLINK (OBSOLETE)"
-       depends on NETFILTER_ADVANCED
-       help
-         Netfilter has the ability to queue packets to user space: the
-         netlink device can be used to access them using this driver.
-
-         This option enables the old IPv4-only "ip_queue" implementation
-         which has been obsoleted by the new "nfnetlink_queue" code (see
-         CONFIG_NETFILTER_NETLINK_QUEUE).
-
-         To compile it as a module, choose M here.  If unsure, say N.
-
 config IP_NF_IPTABLES
        tristate "IP tables support (required for filtering/masq/NAT)"
        default m if NETFILTER_ADVANCED=n
index 47e854fcae24dd8c108e93a2b5a22801a68d7232..e22020790709dbde58759c771f47a69e883892e4 100644 (file)
@@ -775,7 +775,7 @@ struct sk_buff *sk_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp)
                         * Make sure that we have exactly size bytes
                         * available to the caller, no more, no less.
                         */
-                       skb->avail_size = size;
+                       skb->reserved_tailroom = skb->end - skb->tail - size;
                        return skb;
                }
                __kfree_skb(skb);
index 0d9bdacce99f46a77982d89c86a7764fe9ef15f8..3bd55bad230ac7f822f4ea75eb280bc8ce0c07fc 100644 (file)
@@ -2059,11 +2059,8 @@ void tcp_enter_loss(struct sock *sk, int how)
        if (tcp_is_reno(tp))
                tcp_reset_reno_sack(tp);
 
-       if (!how) {
-               /* Push undo marker, if it was plain RTO and nothing
-                * was retransmitted. */
-               tp->undo_marker = tp->snd_una;
-       } else {
+       tp->undo_marker = tp->snd_una;
+       if (how) {
                tp->sacked_out = 0;
                tp->fackets_out = 0;
        }
index 4a8ec457310fbd57e6b62e0a0f8ae6c22f2463fa..d09203c63264d2d8c11f7b40d42200f82934213b 100644 (file)
@@ -274,13 +274,6 @@ static void tcp_v4_mtu_reduced(struct sock *sk)
        struct inet_sock *inet = inet_sk(sk);
        u32 mtu = tcp_sk(sk)->mtu_info;
 
-       /* We are not interested in TCP_LISTEN and open_requests (SYN-ACKs
-        * send out by Linux are always <576bytes so they should go through
-        * unfragmented).
-        */
-       if (sk->sk_state == TCP_LISTEN)
-               return;
-
        dst = inet_csk_update_pmtu(sk, mtu);
        if (!dst)
                return;
@@ -408,6 +401,13 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
                        goto out;
 
                if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */
+                       /* We are not interested in TCP_LISTEN and open_requests
+                        * (SYN-ACKs send out by Linux are always <576bytes so
+                        * they should go through unfragmented).
+                        */
+                       if (sk->sk_state == TCP_LISTEN)
+                               goto out;
+
                        tp->mtu_info = info;
                        if (!sock_owned_by_user(sk)) {
                                tcp_v4_mtu_reduced(sk);
index e2b4461074dab715af9c328fd1767f4a5caf8c97..5d0b4387cba6df401166a48f1e4cf3800d6ce6ff 100644 (file)
@@ -1298,7 +1298,6 @@ static void __pskb_trim_head(struct sk_buff *skb, int len)
        eat = min_t(int, len, skb_headlen(skb));
        if (eat) {
                __skb_pull(skb, eat);
-               skb->avail_size -= eat;
                len -= eat;
                if (!len)
                        return;
@@ -1810,8 +1809,11 @@ static bool tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb)
                        goto send_now;
        }
 
-       /* Ok, it looks like it is advisable to defer.  */
-       tp->tso_deferred = 1 | (jiffies << 1);
+       /* Ok, it looks like it is advisable to defer.
+        * Do not rearm the timer if already set to not break TCP ACK clocking.
+        */
+       if (!tp->tso_deferred)
+               tp->tso_deferred = 1 | (jiffies << 1);
 
        return true;
 
index 265c42cf963c30cce55016bbf4ef0a13f57e6ec5..0a073a263720c4eab823db2c09b1b18d7b510bcd 100644 (file)
@@ -1762,9 +1762,16 @@ int udp_rcv(struct sk_buff *skb)
 
 void udp_destroy_sock(struct sock *sk)
 {
+       struct udp_sock *up = udp_sk(sk);
        bool slow = lock_sock_fast(sk);
        udp_flush_pending_frames(sk);
        unlock_sock_fast(sk, slow);
+       if (static_key_false(&udp_encap_needed) && up->encap_type) {
+               void (*encap_destroy)(struct sock *sk);
+               encap_destroy = ACCESS_ONCE(up->encap_destroy);
+               if (encap_destroy)
+                       encap_destroy(sk);
+       }
 }
 
 /*
index f2c7e615f902d861d99529536ecebff35fbd7fd5..a459c4f5b76914e031798a4b90b3df1998f47a08 100644 (file)
@@ -2529,6 +2529,9 @@ static void sit_add_v4_addrs(struct inet6_dev *idev)
 static void init_loopback(struct net_device *dev)
 {
        struct inet6_dev  *idev;
+       struct net_device *sp_dev;
+       struct inet6_ifaddr *sp_ifa;
+       struct rt6_info *sp_rt;
 
        /* ::1 */
 
@@ -2540,6 +2543,30 @@ static void init_loopback(struct net_device *dev)
        }
 
        add_addr(idev, &in6addr_loopback, 128, IFA_HOST);
+
+       /* Add routes to other interface's IPv6 addresses */
+       for_each_netdev(dev_net(dev), sp_dev) {
+               if (!strcmp(sp_dev->name, dev->name))
+                       continue;
+
+               idev = __in6_dev_get(sp_dev);
+               if (!idev)
+                       continue;
+
+               read_lock_bh(&idev->lock);
+               list_for_each_entry(sp_ifa, &idev->addr_list, if_list) {
+
+                       if (sp_ifa->flags & (IFA_F_DADFAILED | IFA_F_TENTATIVE))
+                               continue;
+
+                       sp_rt = addrconf_dst_alloc(idev, &sp_ifa->addr, 0);
+
+                       /* Failure cases are ignored */
+                       if (!IS_ERR(sp_rt))
+                               ip6_ins_rt(sp_rt);
+               }
+               read_unlock_bh(&idev->lock);
+       }
 }
 
 static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr)
@@ -4784,26 +4811,20 @@ static void addrconf_sysctl_unregister(struct inet6_dev *idev)
 
 static int __net_init addrconf_init_net(struct net *net)
 {
-       int err;
+       int err = -ENOMEM;
        struct ipv6_devconf *all, *dflt;
 
-       err = -ENOMEM;
-       all = &ipv6_devconf;
-       dflt = &ipv6_devconf_dflt;
+       all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL);
+       if (all == NULL)
+               goto err_alloc_all;
 
-       if (!net_eq(net, &init_net)) {
-               all = kmemdup(all, sizeof(ipv6_devconf), GFP_KERNEL);
-               if (all == NULL)
-                       goto err_alloc_all;
+       dflt = kmemdup(&ipv6_devconf_dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL);
+       if (dflt == NULL)
+               goto err_alloc_dflt;
 
-               dflt = kmemdup(dflt, sizeof(ipv6_devconf_dflt), GFP_KERNEL);
-               if (dflt == NULL)
-                       goto err_alloc_dflt;
-       } else {
-               /* these will be inherited by all namespaces */
-               dflt->autoconf = ipv6_defaults.autoconf;
-               dflt->disable_ipv6 = ipv6_defaults.disable_ipv6;
-       }
+       /* these will be inherited by all namespaces */
+       dflt->autoconf = ipv6_defaults.autoconf;
+       dflt->disable_ipv6 = ipv6_defaults.disable_ipv6;
 
        net->ipv6.devconf_all = all;
        net->ipv6.devconf_dflt = dflt;
index b1876e52091e1ea2568b5b1acf9411df5986ef84..2bab2aa597450813ae4bd60d362998830a7e7e3b 100644 (file)
@@ -118,6 +118,18 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
            ipv6_addr_loopback(&hdr->daddr))
                goto err;
 
+       /* RFC4291 Errata ID: 3480
+        * Interface-Local scope spans only a single interface on a
+        * node and is useful only for loopback transmission of
+        * multicast.  Packets with interface-local scope received
+        * from another node must be discarded.
+        */
+       if (!(skb->pkt_type == PACKET_LOOPBACK ||
+             dev->flags & IFF_LOOPBACK) &&
+           ipv6_addr_is_multicast(&hdr->daddr) &&
+           IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1)
+               goto err;
+
        /* RFC4291 2.7
         * Nodes must not originate a packet to a multicast address whose scope
         * field contains the reserved value 0; if such a packet is received, it
@@ -281,7 +293,8 @@ int ip6_mc_input(struct sk_buff *skb)
         *      IPv6 multicast router mode is now supported ;)
         */
        if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding &&
-           !(ipv6_addr_type(&hdr->daddr) & IPV6_ADDR_LINKLOCAL) &&
+           !(ipv6_addr_type(&hdr->daddr) &
+             (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)) &&
            likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {
                /*
                 * Okay, we try to forward - split and duplicate
index 83acc1405a18dcef218625e8517431978393ac12..cb631143721c0afb13152121c74a9d49f51e99dc 100644 (file)
@@ -57,7 +57,7 @@ static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt,
                if (pfx_len - i >= 32)
                        mask = 0;
                else
-                       mask = htonl(~((1 << (pfx_len - i)) - 1));
+                       mask = htonl((1 << (i - pfx_len + 32)) - 1);
 
                idx = i / 32;
                addr->s6_addr32[idx] &= mask;
@@ -114,6 +114,7 @@ ip6t_dnpt_tg(struct sk_buff *skb, const struct xt_action_param *par)
 static struct xt_target ip6t_npt_target_reg[] __read_mostly = {
        {
                .name           = "SNPT",
+               .table          = "mangle",
                .target         = ip6t_snpt_tg,
                .targetsize     = sizeof(struct ip6t_npt_tginfo),
                .checkentry     = ip6t_npt_checkentry,
@@ -124,6 +125,7 @@ static struct xt_target ip6t_npt_target_reg[] __read_mostly = {
        },
        {
                .name           = "DNPT",
+               .table          = "mangle",
                .target         = ip6t_dnpt_tg,
                .targetsize     = sizeof(struct ip6t_npt_tginfo),
                .checkentry     = ip6t_npt_checkentry,
index 54087e96d7b8c5b45b52ce1f26fdd54a134506d2..6700069949ddc81b13f7f0c2bc2622258b6fb2a4 100644 (file)
@@ -14,6 +14,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#define pr_fmt(fmt) "IPv6-nf: " fmt
+
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -180,13 +182,11 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id,
 
        q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash);
        local_bh_enable();
-       if (q == NULL)
-               goto oom;
-
+       if (IS_ERR_OR_NULL(q)) {
+               inet_frag_maybe_warn_overflow(q, pr_fmt());
+               return NULL;
+       }
        return container_of(q, struct frag_queue, q);
-
-oom:
-       return NULL;
 }
 
 
index 3c6a77290c6e87573cb07d081d878d5c03f9760c..196ab9347ad1df2bab5a9c98720a51e81773985c 100644 (file)
@@ -26,6 +26,9 @@
  *     YOSHIFUJI,H. @USAGI     Always remove fragment header to
  *                             calculate ICV correctly.
  */
+
+#define pr_fmt(fmt) "IPv6: " fmt
+
 #include <linux/errno.h>
 #include <linux/types.h>
 #include <linux/string.h>
@@ -185,9 +188,10 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src, const struct in6
        hash = inet6_hash_frag(id, src, dst, ip6_frags.rnd);
 
        q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash);
-       if (q == NULL)
+       if (IS_ERR_OR_NULL(q)) {
+               inet_frag_maybe_warn_overflow(q, pr_fmt());
                return NULL;
-
+       }
        return container_of(q, struct frag_queue, q);
 }
 
index 9b6460055df5683d70dea9d3f09d24c325ee89e7..f6d629fd6aee152aaff674a03db7a3dd0f194134 100644 (file)
@@ -389,6 +389,13 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        }
 
        if (type == ICMPV6_PKT_TOOBIG) {
+               /* We are not interested in TCP_LISTEN and open_requests
+                * (SYN-ACKs send out by Linux are always <576bytes so
+                * they should go through unfragmented).
+                */
+               if (sk->sk_state == TCP_LISTEN)
+                       goto out;
+
                tp->mtu_info = ntohl(info);
                if (!sock_owned_by_user(sk))
                        tcp_v6_mtu_reduced(sk);
index 599e1ba6d1ceaa6766d53eda020a69a0aa234e5b..d8e5e852fc7a08b26879c81a4ecaad0be2cf2f90 100644 (file)
@@ -1285,10 +1285,18 @@ do_confirm:
 
 void udpv6_destroy_sock(struct sock *sk)
 {
+       struct udp_sock *up = udp_sk(sk);
        lock_sock(sk);
        udp_v6_flush_pending_frames(sk);
        release_sock(sk);
 
+       if (static_key_false(&udpv6_encap_needed) && up->encap_type) {
+               void (*encap_destroy)(struct sock *sk);
+               encap_destroy = ACCESS_ONCE(up->encap_destroy);
+               if (encap_destroy)
+                       encap_destroy(sk);
+       }
+
        inet6_destroy_sock(sk);
 }
 
index d07e3a626446b3cab44e68b019f7870619699f75..d28e7f014cc639779a4557203b4b2ba2f7e63927 100644 (file)
@@ -2583,8 +2583,10 @@ bed:
                                    NULL, NULL, NULL);
 
                /* Check if the we got some results */
-               if (!self->cachedaddr)
-                       return -EAGAIN;         /* Didn't find any devices */
+               if (!self->cachedaddr) {
+                       err = -EAGAIN;          /* Didn't find any devices */
+                       goto out;
+               }
                daddr = self->cachedaddr;
                /* Cleanup */
                self->cachedaddr = 0;
index 9a5fd3c3e530c5dc82c04ccf04abf0f93b0f3a28..362ba47968e41de822122f9c215e012ba566cd59 100644 (file)
@@ -280,7 +280,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
        struct tty_port *port = &self->port;
        DECLARE_WAITQUEUE(wait, current);
        int             retval;
-       int             do_clocal = 0, extra_count = 0;
+       int             do_clocal = 0;
        unsigned long   flags;
 
        IRDA_DEBUG(2, "%s()\n", __func__ );
@@ -289,8 +289,15 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
         * If non-blocking mode is set, or the port is not enabled,
         * then make the check up front and then exit.
         */
-       if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
-               /* nonblock mode is set or port is not enabled */
+       if (test_bit(TTY_IO_ERROR, &tty->flags)) {
+               port->flags |= ASYNC_NORMAL_ACTIVE;
+               return 0;
+       }
+
+       if (filp->f_flags & O_NONBLOCK) {
+               /* nonblock mode is set */
+               if (tty->termios.c_cflag & CBAUD)
+                       tty_port_raise_dtr_rts(port);
                port->flags |= ASYNC_NORMAL_ACTIVE;
                IRDA_DEBUG(1, "%s(), O_NONBLOCK requested!\n", __func__ );
                return 0;
@@ -315,18 +322,16 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
              __FILE__, __LINE__, tty->driver->name, port->count);
 
        spin_lock_irqsave(&port->lock, flags);
-       if (!tty_hung_up_p(filp)) {
-               extra_count = 1;
+       if (!tty_hung_up_p(filp))
                port->count--;
-       }
-       spin_unlock_irqrestore(&port->lock, flags);
        port->blocked_open++;
+       spin_unlock_irqrestore(&port->lock, flags);
 
        while (1) {
                if (tty->termios.c_cflag & CBAUD)
                        tty_port_raise_dtr_rts(port);
 
-               current->state = TASK_INTERRUPTIBLE;
+               set_current_state(TASK_INTERRUPTIBLE);
 
                if (tty_hung_up_p(filp) ||
                    !test_bit(ASYNCB_INITIALIZED, &port->flags)) {
@@ -361,13 +366,11 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self,
        __set_current_state(TASK_RUNNING);
        remove_wait_queue(&port->open_wait, &wait);
 
-       if (extra_count) {
-               /* ++ is not atomic, so this should be protected - Jean II */
-               spin_lock_irqsave(&port->lock, flags);
+       spin_lock_irqsave(&port->lock, flags);
+       if (!tty_hung_up_p(filp))
                port->count++;
-               spin_unlock_irqrestore(&port->lock, flags);
-       }
        port->blocked_open--;
+       spin_unlock_irqrestore(&port->lock, flags);
 
        IRDA_DEBUG(1, "%s(%d):block_til_ready after blocking on %s open_count=%d\n",
              __FILE__, __LINE__, tty->driver->name, port->count);
index 556fdafdd1ea3fb6d85b44c2e3efeb600b1839b8..5b1e5af257137e4c6a03a2c575f1adb5a949e25e 100644 (file)
@@ -2201,7 +2201,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_
                      XFRM_POLICY_BLOCK : XFRM_POLICY_ALLOW);
        xp->priority = pol->sadb_x_policy_priority;
 
-       sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
+       sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1];
        xp->family = pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.saddr);
        if (!xp->family) {
                err = -EINVAL;
@@ -2214,7 +2214,7 @@ static int pfkey_spdadd(struct sock *sk, struct sk_buff *skb, const struct sadb_
        if (xp->selector.sport)
                xp->selector.sport_mask = htons(0xffff);
 
-       sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1],
+       sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1];
        pfkey_sadb_addr2xfrm_addr(sa, &xp->selector.daddr);
        xp->selector.prefixlen_d = sa->sadb_address_prefixlen;
 
@@ -2315,7 +2315,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa
 
        memset(&sel, 0, sizeof(sel));
 
-       sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1],
+       sa = ext_hdrs[SADB_EXT_ADDRESS_SRC-1];
        sel.family = pfkey_sadb_addr2xfrm_addr(sa, &sel.saddr);
        sel.prefixlen_s = sa->sadb_address_prefixlen;
        sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
@@ -2323,7 +2323,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, const struct sa
        if (sel.sport)
                sel.sport_mask = htons(0xffff);
 
-       sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1],
+       sa = ext_hdrs[SADB_EXT_ADDRESS_DST-1];
        pfkey_sadb_addr2xfrm_addr(sa, &sel.daddr);
        sel.prefixlen_d = sa->sadb_address_prefixlen;
        sel.proto = pfkey_proto_to_xfrm(sa->sadb_address_proto);
@@ -2693,6 +2693,7 @@ static int key_notify_policy_flush(const struct km_event *c)
        hdr->sadb_msg_pid = c->portid;
        hdr->sadb_msg_version = PF_KEY_V2;
        hdr->sadb_msg_errno = (uint8_t) 0;
+       hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
        hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
        pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
        return 0;
index d36875f3427e82b7795012bebe8281318f983d22..8aecf5df66569a6ca0ae1b8921e20954d6812336 100644 (file)
@@ -114,7 +114,6 @@ struct l2tp_net {
 
 static void l2tp_session_set_header_len(struct l2tp_session *session, int version);
 static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel);
-static void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel);
 
 static inline struct l2tp_net *l2tp_pernet(struct net *net)
 {
@@ -192,6 +191,7 @@ struct sock *l2tp_tunnel_sock_lookup(struct l2tp_tunnel *tunnel)
        } else {
                /* Socket is owned by kernelspace */
                sk = tunnel->sock;
+               sock_hold(sk);
        }
 
 out:
@@ -210,6 +210,7 @@ void l2tp_tunnel_sock_put(struct sock *sk)
                }
                sock_put(sk);
        }
+       sock_put(sk);
 }
 EXPORT_SYMBOL_GPL(l2tp_tunnel_sock_put);
 
@@ -373,10 +374,8 @@ static void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *sk
        struct sk_buff *skbp;
        struct sk_buff *tmp;
        u32 ns = L2TP_SKB_CB(skb)->ns;
-       struct l2tp_stats *sstats;
 
        spin_lock_bh(&session->reorder_q.lock);
-       sstats = &session->stats;
        skb_queue_walk_safe(&session->reorder_q, skbp, tmp) {
                if (L2TP_SKB_CB(skbp)->ns > ns) {
                        __skb_queue_before(&session->reorder_q, skbp, skb);
@@ -384,9 +383,7 @@ static void l2tp_recv_queue_skb(struct l2tp_session *session, struct sk_buff *sk
                                 "%s: pkt %hu, inserted before %hu, reorder_q len=%d\n",
                                 session->name, ns, L2TP_SKB_CB(skbp)->ns,
                                 skb_queue_len(&session->reorder_q));
-                       u64_stats_update_begin(&sstats->syncp);
-                       sstats->rx_oos_packets++;
-                       u64_stats_update_end(&sstats->syncp);
+                       atomic_long_inc(&session->stats.rx_oos_packets);
                        goto out;
                }
        }
@@ -403,23 +400,16 @@ static void l2tp_recv_dequeue_skb(struct l2tp_session *session, struct sk_buff *
 {
        struct l2tp_tunnel *tunnel = session->tunnel;
        int length = L2TP_SKB_CB(skb)->length;
-       struct l2tp_stats *tstats, *sstats;
 
        /* We're about to requeue the skb, so return resources
         * to its current owner (a socket receive buffer).
         */
        skb_orphan(skb);
 
-       tstats = &tunnel->stats;
-       u64_stats_update_begin(&tstats->syncp);
-       sstats = &session->stats;
-       u64_stats_update_begin(&sstats->syncp);
-       tstats->rx_packets++;
-       tstats->rx_bytes += length;
-       sstats->rx_packets++;
-       sstats->rx_bytes += length;
-       u64_stats_update_end(&tstats->syncp);
-       u64_stats_update_end(&sstats->syncp);
+       atomic_long_inc(&tunnel->stats.rx_packets);
+       atomic_long_add(length, &tunnel->stats.rx_bytes);
+       atomic_long_inc(&session->stats.rx_packets);
+       atomic_long_add(length, &session->stats.rx_bytes);
 
        if (L2TP_SKB_CB(skb)->has_seq) {
                /* Bump our Nr */
@@ -450,7 +440,6 @@ static void l2tp_recv_dequeue(struct l2tp_session *session)
 {
        struct sk_buff *skb;
        struct sk_buff *tmp;
-       struct l2tp_stats *sstats;
 
        /* If the pkt at the head of the queue has the nr that we
         * expect to send up next, dequeue it and any other
@@ -458,13 +447,10 @@ static void l2tp_recv_dequeue(struct l2tp_session *session)
         */
 start:
        spin_lock_bh(&session->reorder_q.lock);
-       sstats = &session->stats;
        skb_queue_walk_safe(&session->reorder_q, skb, tmp) {
                if (time_after(jiffies, L2TP_SKB_CB(skb)->expires)) {
-                       u64_stats_update_begin(&sstats->syncp);
-                       sstats->rx_seq_discards++;
-                       sstats->rx_errors++;
-                       u64_stats_update_end(&sstats->syncp);
+                       atomic_long_inc(&session->stats.rx_seq_discards);
+                       atomic_long_inc(&session->stats.rx_errors);
                        l2tp_dbg(session, L2TP_MSG_SEQ,
                                 "%s: oos pkt %u len %d discarded (too old), waiting for %u, reorder_q_len=%d\n",
                                 session->name, L2TP_SKB_CB(skb)->ns,
@@ -623,7 +609,6 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
        struct l2tp_tunnel *tunnel = session->tunnel;
        int offset;
        u32 ns, nr;
-       struct l2tp_stats *sstats = &session->stats;
 
        /* The ref count is increased since we now hold a pointer to
         * the session. Take care to decrement the refcnt when exiting
@@ -640,9 +625,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
                                  "%s: cookie mismatch (%u/%u). Discarding.\n",
                                  tunnel->name, tunnel->tunnel_id,
                                  session->session_id);
-                       u64_stats_update_begin(&sstats->syncp);
-                       sstats->rx_cookie_discards++;
-                       u64_stats_update_end(&sstats->syncp);
+                       atomic_long_inc(&session->stats.rx_cookie_discards);
                        goto discard;
                }
                ptr += session->peer_cookie_len;
@@ -711,9 +694,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
                        l2tp_warn(session, L2TP_MSG_SEQ,
                                  "%s: recv data has no seq numbers when required. Discarding.\n",
                                  session->name);
-                       u64_stats_update_begin(&sstats->syncp);
-                       sstats->rx_seq_discards++;
-                       u64_stats_update_end(&sstats->syncp);
+                       atomic_long_inc(&session->stats.rx_seq_discards);
                        goto discard;
                }
 
@@ -732,9 +713,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
                        l2tp_warn(session, L2TP_MSG_SEQ,
                                  "%s: recv data has no seq numbers when required. Discarding.\n",
                                  session->name);
-                       u64_stats_update_begin(&sstats->syncp);
-                       sstats->rx_seq_discards++;
-                       u64_stats_update_end(&sstats->syncp);
+                       atomic_long_inc(&session->stats.rx_seq_discards);
                        goto discard;
                }
        }
@@ -788,9 +767,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
                         * packets
                         */
                        if (L2TP_SKB_CB(skb)->ns != session->nr) {
-                               u64_stats_update_begin(&sstats->syncp);
-                               sstats->rx_seq_discards++;
-                               u64_stats_update_end(&sstats->syncp);
+                               atomic_long_inc(&session->stats.rx_seq_discards);
                                l2tp_dbg(session, L2TP_MSG_SEQ,
                                         "%s: oos pkt %u len %d discarded, waiting for %u, reorder_q_len=%d\n",
                                         session->name, L2TP_SKB_CB(skb)->ns,
@@ -816,9 +793,7 @@ void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb,
        return;
 
 discard:
-       u64_stats_update_begin(&sstats->syncp);
-       sstats->rx_errors++;
-       u64_stats_update_end(&sstats->syncp);
+       atomic_long_inc(&session->stats.rx_errors);
        kfree_skb(skb);
 
        if (session->deref)
@@ -828,6 +803,23 @@ discard:
 }
 EXPORT_SYMBOL(l2tp_recv_common);
 
+/* Drop skbs from the session's reorder_q
+ */
+int l2tp_session_queue_purge(struct l2tp_session *session)
+{
+       struct sk_buff *skb = NULL;
+       BUG_ON(!session);
+       BUG_ON(session->magic != L2TP_SESSION_MAGIC);
+       while ((skb = skb_dequeue(&session->reorder_q))) {
+               atomic_long_inc(&session->stats.rx_errors);
+               kfree_skb(skb);
+               if (session->deref)
+                       (*session->deref)(session);
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(l2tp_session_queue_purge);
+
 /* Internal UDP receive frame. Do the real work of receiving an L2TP data frame
  * here. The skb is not on a list when we get here.
  * Returns 0 if the packet was a data packet and was successfully passed on.
@@ -843,7 +835,6 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
        u32 tunnel_id, session_id;
        u16 version;
        int length;
-       struct l2tp_stats *tstats;
 
        if (tunnel->sock && l2tp_verify_udp_checksum(tunnel->sock, skb))
                goto discard_bad_csum;
@@ -932,10 +923,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb,
 discard_bad_csum:
        LIMIT_NETDEBUG("%s: UDP: bad checksum\n", tunnel->name);
        UDP_INC_STATS_USER(tunnel->l2tp_net, UDP_MIB_INERRORS, 0);
-       tstats = &tunnel->stats;
-       u64_stats_update_begin(&tstats->syncp);
-       tstats->rx_errors++;
-       u64_stats_update_end(&tstats->syncp);
+       atomic_long_inc(&tunnel->stats.rx_errors);
        kfree_skb(skb);
 
        return 0;
@@ -1062,7 +1050,6 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,
        struct l2tp_tunnel *tunnel = session->tunnel;
        unsigned int len = skb->len;
        int error;
-       struct l2tp_stats *tstats, *sstats;
 
        /* Debug */
        if (session->send_seq)
@@ -1091,21 +1078,15 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb,
                error = ip_queue_xmit(skb, fl);
 
        /* Update stats */
-       tstats = &tunnel->stats;
-       u64_stats_update_begin(&tstats->syncp);
-       sstats = &session->stats;
-       u64_stats_update_begin(&sstats->syncp);
        if (error >= 0) {
-               tstats->tx_packets++;
-               tstats->tx_bytes += len;
-               sstats->tx_packets++;
-               sstats->tx_bytes += len;
+               atomic_long_inc(&tunnel->stats.tx_packets);
+               atomic_long_add(len, &tunnel->stats.tx_bytes);
+               atomic_long_inc(&session->stats.tx_packets);
+               atomic_long_add(len, &session->stats.tx_bytes);
        } else {
-               tstats->tx_errors++;
-               sstats->tx_errors++;
+               atomic_long_inc(&tunnel->stats.tx_errors);
+               atomic_long_inc(&session->stats.tx_errors);
        }
-       u64_stats_update_end(&tstats->syncp);
-       u64_stats_update_end(&sstats->syncp);
 
        return 0;
 }
@@ -1282,6 +1263,7 @@ static void l2tp_tunnel_destruct(struct sock *sk)
                /* No longer an encapsulation socket. See net/ipv4/udp.c */
                (udp_sk(sk))->encap_type = 0;
                (udp_sk(sk))->encap_rcv = NULL;
+               (udp_sk(sk))->encap_destroy = NULL;
                break;
        case L2TP_ENCAPTYPE_IP:
                break;
@@ -1311,7 +1293,7 @@ end:
 
 /* When the tunnel is closed, all the attached sessions need to go too.
  */
-static void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel)
+void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel)
 {
        int hash;
        struct hlist_node *walk;
@@ -1334,25 +1316,13 @@ again:
 
                        hlist_del_init(&session->hlist);
 
-                       /* Since we should hold the sock lock while
-                        * doing any unbinding, we need to release the
-                        * lock we're holding before taking that lock.
-                        * Hold a reference to the sock so it doesn't
-                        * disappear as we're jumping between locks.
-                        */
                        if (session->ref != NULL)
                                (*session->ref)(session);
 
                        write_unlock_bh(&tunnel->hlist_lock);
 
-                       if (tunnel->version != L2TP_HDR_VER_2) {
-                               struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net);
-
-                               spin_lock_bh(&pn->l2tp_session_hlist_lock);
-                               hlist_del_init_rcu(&session->global_hlist);
-                               spin_unlock_bh(&pn->l2tp_session_hlist_lock);
-                               synchronize_rcu();
-                       }
+                       __l2tp_session_unhash(session);
+                       l2tp_session_queue_purge(session);
 
                        if (session->session_close != NULL)
                                (*session->session_close)(session);
@@ -1360,6 +1330,8 @@ again:
                        if (session->deref != NULL)
                                (*session->deref)(session);
 
+                       l2tp_session_dec_refcount(session);
+
                        write_lock_bh(&tunnel->hlist_lock);
 
                        /* Now restart from the beginning of this hash
@@ -1372,6 +1344,17 @@ again:
        }
        write_unlock_bh(&tunnel->hlist_lock);
 }
+EXPORT_SYMBOL_GPL(l2tp_tunnel_closeall);
+
+/* Tunnel socket destroy hook for UDP encapsulation */
+static void l2tp_udp_encap_destroy(struct sock *sk)
+{
+       struct l2tp_tunnel *tunnel = l2tp_sock_to_tunnel(sk);
+       if (tunnel) {
+               l2tp_tunnel_closeall(tunnel);
+               sock_put(sk);
+       }
+}
 
 /* Really kill the tunnel.
  * Come here only when all sessions have been cleared from the tunnel.
@@ -1397,19 +1380,21 @@ static void l2tp_tunnel_del_work(struct work_struct *work)
                return;
 
        sock = sk->sk_socket;
-       BUG_ON(!sock);
 
-       /* If the tunnel socket was created directly by the kernel, use the
-        * sk_* API to release the socket now.  Otherwise go through the
-        * inet_* layer to shut the socket down, and let userspace close it.
+       /* If the tunnel socket was created by userspace, then go through the
+        * inet layer to shut the socket down, and let userspace close it.
+        * Otherwise, if we created the socket directly within the kernel, use
+        * the sk API to release it here.
         * In either case the tunnel resources are freed in the socket
         * destructor when the tunnel socket goes away.
         */
-       if (sock->file == NULL) {
-               kernel_sock_shutdown(sock, SHUT_RDWR);
-               sk_release_kernel(sk);
+       if (tunnel->fd >= 0) {
+               if (sock)
+                       inet_shutdown(sock, 2);
        } else {
-               inet_shutdown(sock, 2);
+               if (sock)
+                       kernel_sock_shutdown(sock, SHUT_RDWR);
+               sk_release_kernel(sk);
        }
 
        l2tp_tunnel_sock_put(sk);
@@ -1668,6 +1653,7 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
                /* Mark socket as an encapsulation socket. See net/ipv4/udp.c */
                udp_sk(sk)->encap_type = UDP_ENCAP_L2TPINUDP;
                udp_sk(sk)->encap_rcv = l2tp_udp_encap_recv;
+               udp_sk(sk)->encap_destroy = l2tp_udp_encap_destroy;
 #if IS_ENABLED(CONFIG_IPV6)
                if (sk->sk_family == PF_INET6)
                        udpv6_encap_enable();
@@ -1723,6 +1709,7 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_create);
  */
 int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel)
 {
+       l2tp_tunnel_closeall(tunnel);
        return (false == queue_work(l2tp_wq, &tunnel->del_work));
 }
 EXPORT_SYMBOL_GPL(l2tp_tunnel_delete);
@@ -1731,62 +1718,71 @@ EXPORT_SYMBOL_GPL(l2tp_tunnel_delete);
  */
 void l2tp_session_free(struct l2tp_session *session)
 {
-       struct l2tp_tunnel *tunnel;
+       struct l2tp_tunnel *tunnel = session->tunnel;
 
        BUG_ON(atomic_read(&session->ref_count) != 0);
 
-       tunnel = session->tunnel;
-       if (tunnel != NULL) {
+       if (tunnel) {
                BUG_ON(tunnel->magic != L2TP_TUNNEL_MAGIC);
+               if (session->session_id != 0)
+                       atomic_dec(&l2tp_session_count);
+               sock_put(tunnel->sock);
+               session->tunnel = NULL;
+               l2tp_tunnel_dec_refcount(tunnel);
+       }
+
+       kfree(session);
 
-               /* Delete the session from the hash */
+       return;
+}
+EXPORT_SYMBOL_GPL(l2tp_session_free);
+
+/* Remove an l2tp session from l2tp_core's hash lists.
+ * Provides a tidyup interface for pseudowire code which can't just route all
+ * shutdown via. l2tp_session_delete and a pseudowire-specific session_close
+ * callback.
+ */
+void __l2tp_session_unhash(struct l2tp_session *session)
+{
+       struct l2tp_tunnel *tunnel = session->tunnel;
+
+       /* Remove the session from core hashes */
+       if (tunnel) {
+               /* Remove from the per-tunnel hash */
                write_lock_bh(&tunnel->hlist_lock);
                hlist_del_init(&session->hlist);
                write_unlock_bh(&tunnel->hlist_lock);
 
-               /* Unlink from the global hash if not L2TPv2 */
+               /* For L2TPv3 we have a per-net hash: remove from there, too */
                if (tunnel->version != L2TP_HDR_VER_2) {
                        struct l2tp_net *pn = l2tp_pernet(tunnel->l2tp_net);
-
                        spin_lock_bh(&pn->l2tp_session_hlist_lock);
                        hlist_del_init_rcu(&session->global_hlist);
                        spin_unlock_bh(&pn->l2tp_session_hlist_lock);
                        synchronize_rcu();
                }
-
-               if (session->session_id != 0)
-                       atomic_dec(&l2tp_session_count);
-
-               sock_put(tunnel->sock);
-
-               /* This will delete the tunnel context if this
-                * is the last session on the tunnel.
-                */
-               session->tunnel = NULL;
-               l2tp_tunnel_dec_refcount(tunnel);
        }
-
-       kfree(session);
-
-       return;
 }
-EXPORT_SYMBOL_GPL(l2tp_session_free);
+EXPORT_SYMBOL_GPL(__l2tp_session_unhash);
 
 /* This function is used by the netlink SESSION_DELETE command and by
    pseudowire modules.
  */
 int l2tp_session_delete(struct l2tp_session *session)
 {
+       if (session->ref)
+               (*session->ref)(session);
+       __l2tp_session_unhash(session);
+       l2tp_session_queue_purge(session);
        if (session->session_close != NULL)
                (*session->session_close)(session);
-
+       if (session->deref)
+               (*session->ref)(session);
        l2tp_session_dec_refcount(session);
-
        return 0;
 }
 EXPORT_SYMBOL_GPL(l2tp_session_delete);
 
-
 /* We come here whenever a session's send_seq, cookie_len or
  * l2specific_len parameters are set.
  */
index 8eb8f1d47f3ac2d6ce32ae287e120a93aa931b40..485a490fd990eeb91a3577e65844c17d1350f720 100644 (file)
@@ -36,16 +36,15 @@ enum {
 struct sk_buff;
 
 struct l2tp_stats {
-       u64                     tx_packets;
-       u64                     tx_bytes;
-       u64                     tx_errors;
-       u64                     rx_packets;
-       u64                     rx_bytes;
-       u64                     rx_seq_discards;
-       u64                     rx_oos_packets;
-       u64                     rx_errors;
-       u64                     rx_cookie_discards;
-       struct u64_stats_sync   syncp;
+       atomic_long_t           tx_packets;
+       atomic_long_t           tx_bytes;
+       atomic_long_t           tx_errors;
+       atomic_long_t           rx_packets;
+       atomic_long_t           rx_bytes;
+       atomic_long_t           rx_seq_discards;
+       atomic_long_t           rx_oos_packets;
+       atomic_long_t           rx_errors;
+       atomic_long_t           rx_cookie_discards;
 };
 
 struct l2tp_tunnel;
@@ -240,11 +239,14 @@ extern struct l2tp_tunnel *l2tp_tunnel_find(struct net *net, u32 tunnel_id);
 extern struct l2tp_tunnel *l2tp_tunnel_find_nth(struct net *net, int nth);
 
 extern int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp);
+extern void l2tp_tunnel_closeall(struct l2tp_tunnel *tunnel);
 extern int l2tp_tunnel_delete(struct l2tp_tunnel *tunnel);
 extern struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunnel, u32 session_id, u32 peer_session_id, struct l2tp_session_cfg *cfg);
+extern void __l2tp_session_unhash(struct l2tp_session *session);
 extern int l2tp_session_delete(struct l2tp_session *session);
 extern void l2tp_session_free(struct l2tp_session *session);
 extern void l2tp_recv_common(struct l2tp_session *session, struct sk_buff *skb, unsigned char *ptr, unsigned char *optr, u16 hdrflags, int length, int (*payload_hook)(struct sk_buff *skb));
+extern int l2tp_session_queue_purge(struct l2tp_session *session);
 extern int l2tp_udp_encap_recv(struct sock *sk, struct sk_buff *skb);
 
 extern int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len);
index c3813bc84552cebc56691cae4eae3097b29d2160..072d7202e182ffa2125fe7de9c54c584626fdeb0 100644 (file)
@@ -146,14 +146,14 @@ static void l2tp_dfs_seq_tunnel_show(struct seq_file *m, void *v)
                   tunnel->sock ? atomic_read(&tunnel->sock->sk_refcnt) : 0,
                   atomic_read(&tunnel->ref_count));
 
-       seq_printf(m, " %08x rx %llu/%llu/%llu rx %llu/%llu/%llu\n",
+       seq_printf(m, " %08x rx %ld/%ld/%ld rx %ld/%ld/%ld\n",
                   tunnel->debug,
-                  (unsigned long long)tunnel->stats.tx_packets,
-                  (unsigned long long)tunnel->stats.tx_bytes,
-                  (unsigned long long)tunnel->stats.tx_errors,
-                  (unsigned long long)tunnel->stats.rx_packets,
-                  (unsigned long long)tunnel->stats.rx_bytes,
-                  (unsigned long long)tunnel->stats.rx_errors);
+                  atomic_long_read(&tunnel->stats.tx_packets),
+                  atomic_long_read(&tunnel->stats.tx_bytes),
+                  atomic_long_read(&tunnel->stats.tx_errors),
+                  atomic_long_read(&tunnel->stats.rx_packets),
+                  atomic_long_read(&tunnel->stats.rx_bytes),
+                  atomic_long_read(&tunnel->stats.rx_errors));
 
        if (tunnel->show != NULL)
                tunnel->show(m, tunnel);
@@ -203,14 +203,14 @@ static void l2tp_dfs_seq_session_show(struct seq_file *m, void *v)
                seq_printf(m, "\n");
        }
 
-       seq_printf(m, "   %hu/%hu tx %llu/%llu/%llu rx %llu/%llu/%llu\n",
+       seq_printf(m, "   %hu/%hu tx %ld/%ld/%ld rx %ld/%ld/%ld\n",
                   session->nr, session->ns,
-                  (unsigned long long)session->stats.tx_packets,
-                  (unsigned long long)session->stats.tx_bytes,
-                  (unsigned long long)session->stats.tx_errors,
-                  (unsigned long long)session->stats.rx_packets,
-                  (unsigned long long)session->stats.rx_bytes,
-                  (unsigned long long)session->stats.rx_errors);
+                  atomic_long_read(&session->stats.tx_packets),
+                  atomic_long_read(&session->stats.tx_bytes),
+                  atomic_long_read(&session->stats.tx_errors),
+                  atomic_long_read(&session->stats.rx_packets),
+                  atomic_long_read(&session->stats.rx_bytes),
+                  atomic_long_read(&session->stats.rx_errors));
 
        if (session->show != NULL)
                session->show(m, session);
index 7f41b7051269539efa0780b618be0b60e7788e76..571db8dd2292a7c5b1f2e940073edce370b13699 100644 (file)
@@ -228,10 +228,16 @@ static void l2tp_ip_close(struct sock *sk, long timeout)
 static void l2tp_ip_destroy_sock(struct sock *sk)
 {
        struct sk_buff *skb;
+       struct l2tp_tunnel *tunnel = l2tp_sock_to_tunnel(sk);
 
        while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL)
                kfree_skb(skb);
 
+       if (tunnel) {
+               l2tp_tunnel_closeall(tunnel);
+               sock_put(sk);
+       }
+
        sk_refcnt_debug_dec(sk);
 }
 
index 41f2f8126ebc720933638f67eb800f17797987e7..c74f5a91ff6a3213209c23ff488f0b475a552857 100644 (file)
@@ -241,10 +241,17 @@ static void l2tp_ip6_close(struct sock *sk, long timeout)
 
 static void l2tp_ip6_destroy_sock(struct sock *sk)
 {
+       struct l2tp_tunnel *tunnel = l2tp_sock_to_tunnel(sk);
+
        lock_sock(sk);
        ip6_flush_pending_frames(sk);
        release_sock(sk);
 
+       if (tunnel) {
+               l2tp_tunnel_closeall(tunnel);
+               sock_put(sk);
+       }
+
        inet6_destroy_sock(sk);
 }
 
index c1bab22db85e79765581079468a36231e5f3d608..0825ff26e113f3e2acdbbe2b88bd0f4fbfd92410 100644 (file)
@@ -246,8 +246,6 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq, int fla
 #if IS_ENABLED(CONFIG_IPV6)
        struct ipv6_pinfo *np = NULL;
 #endif
-       struct l2tp_stats stats;
-       unsigned int start;
 
        hdr = genlmsg_put(skb, portid, seq, &l2tp_nl_family, flags,
                          L2TP_CMD_TUNNEL_GET);
@@ -265,28 +263,22 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 portid, u32 seq, int fla
        if (nest == NULL)
                goto nla_put_failure;
 
-       do {
-               start = u64_stats_fetch_begin(&tunnel->stats.syncp);
-               stats.tx_packets = tunnel->stats.tx_packets;
-               stats.tx_bytes = tunnel->stats.tx_bytes;
-               stats.tx_errors = tunnel->stats.tx_errors;
-               stats.rx_packets = tunnel->stats.rx_packets;
-               stats.rx_bytes = tunnel->stats.rx_bytes;
-               stats.rx_errors = tunnel->stats.rx_errors;
-               stats.rx_seq_discards = tunnel->stats.rx_seq_discards;
-               stats.rx_oos_packets = tunnel->stats.rx_oos_packets;
-       } while (u64_stats_fetch_retry(&tunnel->stats.syncp, start));
-
-       if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, stats.tx_packets) ||
-           nla_put_u64(skb, L2TP_ATTR_TX_BYTES, stats.tx_bytes) ||
-           nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, stats.tx_errors) ||
-           nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, stats.rx_packets) ||
-           nla_put_u64(skb, L2TP_ATTR_RX_BYTES, stats.rx_bytes) ||
+       if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS,
+                   atomic_long_read(&tunnel->stats.tx_packets)) ||
+           nla_put_u64(skb, L2TP_ATTR_TX_BYTES,
+                   atomic_long_read(&tunnel->stats.tx_bytes)) ||
+           nla_put_u64(skb, L2TP_ATTR_TX_ERRORS,
+                   atomic_long_read(&tunnel->stats.tx_errors)) ||
+           nla_put_u64(skb, L2TP_ATTR_RX_PACKETS,
+                   atomic_long_read(&tunnel->stats.rx_packets)) ||
+           nla_put_u64(skb, L2TP_ATTR_RX_BYTES,
+                   atomic_long_read(&tunnel->stats.rx_bytes)) ||
            nla_put_u64(skb, L2TP_ATTR_RX_SEQ_DISCARDS,
-                       stats.rx_seq_discards) ||
+                   atomic_long_read(&tunnel->stats.rx_seq_discards)) ||
            nla_put_u64(skb, L2TP_ATTR_RX_OOS_PACKETS,
-                       stats.rx_oos_packets) ||
-           nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, stats.rx_errors))
+                   atomic_long_read(&tunnel->stats.rx_oos_packets)) ||
+           nla_put_u64(skb, L2TP_ATTR_RX_ERRORS,
+                   atomic_long_read(&tunnel->stats.rx_errors)))
                goto nla_put_failure;
        nla_nest_end(skb, nest);
 
@@ -612,8 +604,6 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int fl
        struct nlattr *nest;
        struct l2tp_tunnel *tunnel = session->tunnel;
        struct sock *sk = NULL;
-       struct l2tp_stats stats;
-       unsigned int start;
 
        sk = tunnel->sock;
 
@@ -656,28 +646,22 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 portid, u32 seq, int fl
        if (nest == NULL)
                goto nla_put_failure;
 
-       do {
-               start = u64_stats_fetch_begin(&session->stats.syncp);
-               stats.tx_packets = session->stats.tx_packets;
-               stats.tx_bytes = session->stats.tx_bytes;
-               stats.tx_errors = session->stats.tx_errors;
-               stats.rx_packets = session->stats.rx_packets;
-               stats.rx_bytes = session->stats.rx_bytes;
-               stats.rx_errors = session->stats.rx_errors;
-               stats.rx_seq_discards = session->stats.rx_seq_discards;
-               stats.rx_oos_packets = session->stats.rx_oos_packets;
-       } while (u64_stats_fetch_retry(&session->stats.syncp, start));
-
-       if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS, stats.tx_packets) ||
-           nla_put_u64(skb, L2TP_ATTR_TX_BYTES, stats.tx_bytes) ||
-           nla_put_u64(skb, L2TP_ATTR_TX_ERRORS, stats.tx_errors) ||
-           nla_put_u64(skb, L2TP_ATTR_RX_PACKETS, stats.rx_packets) ||
-           nla_put_u64(skb, L2TP_ATTR_RX_BYTES, stats.rx_bytes) ||
+       if (nla_put_u64(skb, L2TP_ATTR_TX_PACKETS,
+               atomic_long_read(&session->stats.tx_packets)) ||
+           nla_put_u64(skb, L2TP_ATTR_TX_BYTES,
+               atomic_long_read(&session->stats.tx_bytes)) ||
+           nla_put_u64(skb, L2TP_ATTR_TX_ERRORS,
+               atomic_long_read(&session->stats.tx_errors)) ||
+           nla_put_u64(skb, L2TP_ATTR_RX_PACKETS,
+               atomic_long_read(&session->stats.rx_packets)) ||
+           nla_put_u64(skb, L2TP_ATTR_RX_BYTES,
+               atomic_long_read(&session->stats.rx_bytes)) ||
            nla_put_u64(skb, L2TP_ATTR_RX_SEQ_DISCARDS,
-                       stats.rx_seq_discards) ||
+               atomic_long_read(&session->stats.rx_seq_discards)) ||
            nla_put_u64(skb, L2TP_ATTR_RX_OOS_PACKETS,
-                       stats.rx_oos_packets) ||
-           nla_put_u64(skb, L2TP_ATTR_RX_ERRORS, stats.rx_errors))
+               atomic_long_read(&session->stats.rx_oos_packets)) ||
+           nla_put_u64(skb, L2TP_ATTR_RX_ERRORS,
+               atomic_long_read(&session->stats.rx_errors)))
                goto nla_put_failure;
        nla_nest_end(skb, nest);
 
index 6a53371dba1f1b357f9cd4f34b7af166ed324eab..637a341c1e2d1a466c68efcb50d7fc201198a15b 100644 (file)
@@ -97,6 +97,7 @@
 #include <net/ip.h>
 #include <net/udp.h>
 #include <net/xfrm.h>
+#include <net/inet_common.h>
 
 #include <asm/byteorder.h>
 #include <linux/atomic.h>
@@ -259,7 +260,7 @@ static void pppol2tp_recv(struct l2tp_session *session, struct sk_buff *skb, int
                          session->name);
 
                /* Not bound. Nothing we can do, so discard. */
-               session->stats.rx_errors++;
+               atomic_long_inc(&session->stats.rx_errors);
                kfree_skb(skb);
        }
 
@@ -447,34 +448,16 @@ static void pppol2tp_session_close(struct l2tp_session *session)
 {
        struct pppol2tp_session *ps = l2tp_session_priv(session);
        struct sock *sk = ps->sock;
-       struct sk_buff *skb;
+       struct socket *sock = sk->sk_socket;
 
        BUG_ON(session->magic != L2TP_SESSION_MAGIC);
 
-       if (session->session_id == 0)
-               goto out;
-
-       if (sk != NULL) {
-               lock_sock(sk);
-
-               if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
-                       pppox_unbind_sock(sk);
-                       sk->sk_state = PPPOX_DEAD;
-                       sk->sk_state_change(sk);
-               }
-
-               /* Purge any queued data */
-               skb_queue_purge(&sk->sk_receive_queue);
-               skb_queue_purge(&sk->sk_write_queue);
-               while ((skb = skb_dequeue(&session->reorder_q))) {
-                       kfree_skb(skb);
-                       sock_put(sk);
-               }
 
-               release_sock(sk);
+       if (sock) {
+               inet_shutdown(sock, 2);
+               /* Don't let the session go away before our socket does */
+               l2tp_session_inc_refcount(session);
        }
-
-out:
        return;
 }
 
@@ -483,19 +466,12 @@ out:
  */
 static void pppol2tp_session_destruct(struct sock *sk)
 {
-       struct l2tp_session *session;
-
-       if (sk->sk_user_data != NULL) {
-               session = sk->sk_user_data;
-               if (session == NULL)
-                       goto out;
-
+       struct l2tp_session *session = sk->sk_user_data;
+       if (session) {
                sk->sk_user_data = NULL;
                BUG_ON(session->magic != L2TP_SESSION_MAGIC);
                l2tp_session_dec_refcount(session);
        }
-
-out:
        return;
 }
 
@@ -525,16 +501,13 @@ static int pppol2tp_release(struct socket *sock)
        session = pppol2tp_sock_to_session(sk);
 
        /* Purge any queued data */
-       skb_queue_purge(&sk->sk_receive_queue);
-       skb_queue_purge(&sk->sk_write_queue);
        if (session != NULL) {
-               struct sk_buff *skb;
-               while ((skb = skb_dequeue(&session->reorder_q))) {
-                       kfree_skb(skb);
-                       sock_put(sk);
-               }
+               __l2tp_session_unhash(session);
+               l2tp_session_queue_purge(session);
                sock_put(sk);
        }
+       skb_queue_purge(&sk->sk_receive_queue);
+       skb_queue_purge(&sk->sk_write_queue);
 
        release_sock(sk);
 
@@ -880,18 +853,6 @@ out:
        return error;
 }
 
-/* Called when deleting sessions via the netlink interface.
- */
-static int pppol2tp_session_delete(struct l2tp_session *session)
-{
-       struct pppol2tp_session *ps = l2tp_session_priv(session);
-
-       if (ps->sock == NULL)
-               l2tp_session_dec_refcount(session);
-
-       return 0;
-}
-
 #endif /* CONFIG_L2TP_V3 */
 
 /* getname() support.
@@ -1025,14 +986,14 @@ end:
 static void pppol2tp_copy_stats(struct pppol2tp_ioc_stats *dest,
                                struct l2tp_stats *stats)
 {
-       dest->tx_packets = stats->tx_packets;
-       dest->tx_bytes = stats->tx_bytes;
-       dest->tx_errors = stats->tx_errors;
-       dest->rx_packets = stats->rx_packets;
-       dest->rx_bytes = stats->rx_bytes;
-       dest->rx_seq_discards = stats->rx_seq_discards;
-       dest->rx_oos_packets = stats->rx_oos_packets;
-       dest->rx_errors = stats->rx_errors;
+       dest->tx_packets = atomic_long_read(&stats->tx_packets);
+       dest->tx_bytes = atomic_long_read(&stats->tx_bytes);
+       dest->tx_errors = atomic_long_read(&stats->tx_errors);
+       dest->rx_packets = atomic_long_read(&stats->rx_packets);
+       dest->rx_bytes = atomic_long_read(&stats->rx_bytes);
+       dest->rx_seq_discards = atomic_long_read(&stats->rx_seq_discards);
+       dest->rx_oos_packets = atomic_long_read(&stats->rx_oos_packets);
+       dest->rx_errors = atomic_long_read(&stats->rx_errors);
 }
 
 /* Session ioctl helper.
@@ -1666,14 +1627,14 @@ static void pppol2tp_seq_tunnel_show(struct seq_file *m, void *v)
                   tunnel->name,
                   (tunnel == tunnel->sock->sk_user_data) ? 'Y' : 'N',
                   atomic_read(&tunnel->ref_count) - 1);
-       seq_printf(m, " %08x %llu/%llu/%llu %llu/%llu/%llu\n",
+       seq_printf(m, " %08x %ld/%ld/%ld %ld/%ld/%ld\n",
                   tunnel->debug,
-                  (unsigned long long)tunnel->stats.tx_packets,
-                  (unsigned long long)tunnel->stats.tx_bytes,
-                  (unsigned long long)tunnel->stats.tx_errors,
-                  (unsigned long long)tunnel->stats.rx_packets,
-                  (unsigned long long)tunnel->stats.rx_bytes,
-                  (unsigned long long)tunnel->stats.rx_errors);
+                  atomic_long_read(&tunnel->stats.tx_packets),
+                  atomic_long_read(&tunnel->stats.tx_bytes),
+                  atomic_long_read(&tunnel->stats.tx_errors),
+                  atomic_long_read(&tunnel->stats.rx_packets),
+                  atomic_long_read(&tunnel->stats.rx_bytes),
+                  atomic_long_read(&tunnel->stats.rx_errors));
 }
 
 static void pppol2tp_seq_session_show(struct seq_file *m, void *v)
@@ -1708,14 +1669,14 @@ static void pppol2tp_seq_session_show(struct seq_file *m, void *v)
                   session->lns_mode ? "LNS" : "LAC",
                   session->debug,
                   jiffies_to_msecs(session->reorder_timeout));
-       seq_printf(m, "   %hu/%hu %llu/%llu/%llu %llu/%llu/%llu\n",
+       seq_printf(m, "   %hu/%hu %ld/%ld/%ld %ld/%ld/%ld\n",
                   session->nr, session->ns,
-                  (unsigned long long)session->stats.tx_packets,
-                  (unsigned long long)session->stats.tx_bytes,
-                  (unsigned long long)session->stats.tx_errors,
-                  (unsigned long long)session->stats.rx_packets,
-                  (unsigned long long)session->stats.rx_bytes,
-                  (unsigned long long)session->stats.rx_errors);
+                  atomic_long_read(&session->stats.tx_packets),
+                  atomic_long_read(&session->stats.tx_bytes),
+                  atomic_long_read(&session->stats.tx_errors),
+                  atomic_long_read(&session->stats.rx_packets),
+                  atomic_long_read(&session->stats.rx_bytes),
+                  atomic_long_read(&session->stats.rx_errors));
 
        if (po)
                seq_printf(m, "   interface %s\n", ppp_dev_name(&po->chan));
@@ -1839,7 +1800,7 @@ static const struct pppox_proto pppol2tp_proto = {
 
 static const struct l2tp_nl_cmd_ops pppol2tp_nl_cmd_ops = {
        .session_create = pppol2tp_session_create,
-       .session_delete = pppol2tp_session_delete,
+       .session_delete = l2tp_session_delete,
 };
 
 #endif /* CONFIG_L2TP_V3 */
index 808f5fcd1ced92127f8786700a759465e0708060..a6893602f87a753ebafeae0d0b8f449bdc7251f7 100644 (file)
@@ -2582,7 +2582,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
                        list_del(&dep->list);
                        mutex_unlock(&local->mtx);
 
-                       ieee80211_roc_notify_destroy(dep);
+                       ieee80211_roc_notify_destroy(dep, true);
                        return 0;
                }
 
@@ -2622,7 +2622,7 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
                        ieee80211_start_next_roc(local);
                mutex_unlock(&local->mtx);
 
-               ieee80211_roc_notify_destroy(found);
+               ieee80211_roc_notify_destroy(found, true);
        } else {
                /* work may be pending so use it all the time */
                found->abort = true;
@@ -2632,6 +2632,8 @@ static int ieee80211_cancel_roc(struct ieee80211_local *local,
 
                /* work will clean up etc */
                flush_delayed_work(&found->work);
+               WARN_ON(!found->to_be_freed);
+               kfree(found);
        }
 
        return 0;
@@ -3290,14 +3292,19 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
        int ret = -ENODATA;
 
        rcu_read_lock();
-       if (local->use_chanctx) {
-               chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
-               if (chanctx_conf) {
-                       *chandef = chanctx_conf->def;
-                       ret = 0;
-               }
-       } else if (local->open_count == local->monitors) {
-               *chandef = local->monitor_chandef;
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (chanctx_conf) {
+               *chandef = chanctx_conf->def;
+               ret = 0;
+       } else if (local->open_count > 0 &&
+                  local->open_count == local->monitors &&
+                  sdata->vif.type == NL80211_IFTYPE_MONITOR) {
+               if (local->use_chanctx)
+                       *chandef = local->monitor_chandef;
+               else
+                       cfg80211_chandef_create(chandef,
+                                               local->_oper_channel,
+                                               local->_oper_channel_type);
                ret = 0;
        }
        rcu_read_unlock();
index 78c0d90dd641e459dcec9972be0d97634d58a5c6..931be419ab5aece83990b530afa5979b2053294c 100644 (file)
@@ -63,6 +63,7 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
                      enum ieee80211_chanctx_mode mode)
 {
        struct ieee80211_chanctx *ctx;
+       u32 changed;
        int err;
 
        lockdep_assert_held(&local->chanctx_mtx);
@@ -76,6 +77,13 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
        ctx->conf.rx_chains_dynamic = 1;
        ctx->mode = mode;
 
+       /* acquire mutex to prevent idle from changing */
+       mutex_lock(&local->mtx);
+       /* turn idle off *before* setting channel -- some drivers need that */
+       changed = ieee80211_idle_off(local);
+       if (changed)
+               ieee80211_hw_config(local, changed);
+
        if (!local->use_chanctx) {
                local->_oper_channel_type =
                        cfg80211_get_chandef_type(chandef);
@@ -85,14 +93,17 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
                err = drv_add_chanctx(local, ctx);
                if (err) {
                        kfree(ctx);
-                       return ERR_PTR(err);
+                       ctx = ERR_PTR(err);
+
+                       ieee80211_recalc_idle(local);
+                       goto out;
                }
        }
 
+       /* and keep the mutex held until the new chanctx is on the list */
        list_add_rcu(&ctx->list, &local->chanctx_list);
 
-       mutex_lock(&local->mtx);
-       ieee80211_recalc_idle(local);
+ out:
        mutex_unlock(&local->mtx);
 
        return ctx;
index 388580a1badad2acec84893fe6ec652f8ce24b6c..5672533a083279ddc50fe98a09bbd4363a9fc731 100644 (file)
@@ -309,6 +309,7 @@ struct ieee80211_roc_work {
        struct ieee80211_channel *chan;
 
        bool started, abort, hw_begun, notified;
+       bool to_be_freed;
 
        unsigned long hw_start_time;
 
@@ -1347,7 +1348,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local);
 void ieee80211_roc_setup(struct ieee80211_local *local);
 void ieee80211_start_next_roc(struct ieee80211_local *local);
 void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata);
-void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc);
+void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free);
 void ieee80211_sw_roc_work(struct work_struct *work);
 void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
 
@@ -1361,6 +1362,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
                             enum nl80211_iftype type);
 void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata);
 void ieee80211_remove_interfaces(struct ieee80211_local *local);
+u32 ieee80211_idle_off(struct ieee80211_local *local);
 void ieee80211_recalc_idle(struct ieee80211_local *local);
 void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata,
                                    const int offset);
index 640afab304d7a02e50414a16f3df8e22c6ea4c30..58150f877ec3fe83f29adb2df4caf5bb617e3358 100644 (file)
@@ -78,7 +78,7 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata)
                ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER);
 }
 
-static u32 ieee80211_idle_off(struct ieee80211_local *local)
+u32 ieee80211_idle_off(struct ieee80211_local *local)
 {
        if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE))
                return 0;
@@ -349,21 +349,19 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
 static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
 {
        struct ieee80211_sub_if_data *sdata;
-       int ret = 0;
+       int ret;
 
        if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
                return 0;
 
-       mutex_lock(&local->iflist_mtx);
+       ASSERT_RTNL();
 
        if (local->monitor_sdata)
-               goto out_unlock;
+               return 0;
 
        sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
-       if (!sdata) {
-               ret = -ENOMEM;
-               goto out_unlock;
-       }
+       if (!sdata)
+               return -ENOMEM;
 
        /* set up data */
        sdata->local = local;
@@ -377,13 +375,13 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
        if (WARN_ON(ret)) {
                /* ok .. stupid driver, it asked for this! */
                kfree(sdata);
-               goto out_unlock;
+               return ret;
        }
 
        ret = ieee80211_check_queues(sdata);
        if (ret) {
                kfree(sdata);
-               goto out_unlock;
+               return ret;
        }
 
        ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef,
@@ -391,13 +389,14 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
        if (ret) {
                drv_remove_interface(local, sdata);
                kfree(sdata);
-               goto out_unlock;
+               return ret;
        }
 
+       mutex_lock(&local->iflist_mtx);
        rcu_assign_pointer(local->monitor_sdata, sdata);
- out_unlock:
        mutex_unlock(&local->iflist_mtx);
-       return ret;
+
+       return 0;
 }
 
 static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
@@ -407,14 +406,20 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
        if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
                return;
 
+       ASSERT_RTNL();
+
        mutex_lock(&local->iflist_mtx);
 
        sdata = rcu_dereference_protected(local->monitor_sdata,
                                          lockdep_is_held(&local->iflist_mtx));
-       if (!sdata)
-               goto out_unlock;
+       if (!sdata) {
+               mutex_unlock(&local->iflist_mtx);
+               return;
+       }
 
        rcu_assign_pointer(local->monitor_sdata, NULL);
+       mutex_unlock(&local->iflist_mtx);
+
        synchronize_net();
 
        ieee80211_vif_release_channel(sdata);
@@ -422,8 +427,6 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
        drv_remove_interface(local, sdata);
 
        kfree(sdata);
- out_unlock:
-       mutex_unlock(&local->iflist_mtx);
 }
 
 /*
@@ -541,6 +544,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
 
                ieee80211_adjust_monitor_flags(sdata, 1);
                ieee80211_configure_filter(local);
+               mutex_lock(&local->mtx);
+               ieee80211_recalc_idle(local);
+               mutex_unlock(&local->mtx);
 
                netif_carrier_on(dev);
                break;
@@ -812,6 +818,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
 
                ieee80211_adjust_monitor_flags(sdata, -1);
                ieee80211_configure_filter(local);
+               mutex_lock(&local->mtx);
+               ieee80211_recalc_idle(local);
+               mutex_unlock(&local->mtx);
                break;
        case NL80211_IFTYPE_P2P_DEVICE:
                /* relies on synchronize_rcu() below */
index 29ce2aa87e7b60fdd344f7fd8acb1148cbc477fd..4749b3858695e6c2aeae983146d6a055be562a28 100644 (file)
@@ -1060,7 +1060,8 @@ void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
 
        rcu_read_lock();
        list_for_each_entry_rcu(sdata, &local->interfaces, list)
-               if (ieee80211_vif_is_mesh(&sdata->vif))
+               if (ieee80211_vif_is_mesh(&sdata->vif) &&
+                   ieee80211_sdata_running(sdata))
                        ieee80211_queue_work(&local->hw, &sdata->work);
        rcu_read_unlock();
 }
index 9f6464f3e05f94e0025c4449b4a29e35bc185725..82cc30318a86f66c4a8f23341ea6ed3f6b62d578 100644 (file)
@@ -647,6 +647,9 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata,
                our_mcs = (le16_to_cpu(vht_cap.vht_mcs.rx_mcs_map) &
                                                                mask) >> shift;
 
+               if (our_mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED)
+                       continue;
+
                switch (ap_mcs) {
                default:
                        if (our_mcs <= ap_mcs)
@@ -3502,6 +3505,14 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
+       /*
+        * Stop timers before deleting work items, as timers
+        * could race and re-add the work-items. They will be
+        * re-established on connection.
+        */
+       del_timer_sync(&ifmgd->conn_mon_timer);
+       del_timer_sync(&ifmgd->bcn_mon_timer);
+
        /*
         * we need to use atomic bitops for the running bits
         * only because both timers might fire at the same
@@ -3516,13 +3527,9 @@ void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
        if (del_timer_sync(&ifmgd->timer))
                set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
 
-       cancel_work_sync(&ifmgd->chswitch_work);
        if (del_timer_sync(&ifmgd->chswitch_timer))
                set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
-
-       /* these will just be re-established on connection */
-       del_timer_sync(&ifmgd->conn_mon_timer);
-       del_timer_sync(&ifmgd->bcn_mon_timer);
+       cancel_work_sync(&ifmgd->chswitch_work);
 }
 
 void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
@@ -3601,8 +3608,10 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local)
 
        /* Restart STA timers */
        rcu_read_lock();
-       list_for_each_entry_rcu(sdata, &local->interfaces, list)
-               ieee80211_restart_sta_timer(sdata);
+       list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+               if (ieee80211_sdata_running(sdata))
+                       ieee80211_restart_sta_timer(sdata);
+       }
        rcu_read_unlock();
 }
 
@@ -4315,6 +4324,17 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
+       /*
+        * Make sure some work items will not run after this,
+        * they will not do anything but might not have been
+        * cancelled when disconnecting.
+        */
+       cancel_work_sync(&ifmgd->monitor_work);
+       cancel_work_sync(&ifmgd->beacon_connection_loss_work);
+       cancel_work_sync(&ifmgd->request_smps_work);
+       cancel_work_sync(&ifmgd->csa_connection_drop_work);
+       cancel_work_sync(&ifmgd->chswitch_work);
+
        mutex_lock(&ifmgd->mtx);
        if (ifmgd->assoc_data)
                ieee80211_destroy_assoc_data(sdata, false);
index cc79b4a2e821c9232c41135da3f4397dbba67b8d..430bd254e49693bf7e62744843fff8c10a2acb9a 100644 (file)
@@ -297,10 +297,13 @@ void ieee80211_start_next_roc(struct ieee80211_local *local)
        }
 }
 
-void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
+void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc, bool free)
 {
        struct ieee80211_roc_work *dep, *tmp;
 
+       if (WARN_ON(roc->to_be_freed))
+               return;
+
        /* was never transmitted */
        if (roc->frame) {
                cfg80211_mgmt_tx_status(&roc->sdata->wdev,
@@ -316,9 +319,12 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc)
                                                   GFP_KERNEL);
 
        list_for_each_entry_safe(dep, tmp, &roc->dependents, list)
-               ieee80211_roc_notify_destroy(dep);
+               ieee80211_roc_notify_destroy(dep, true);
 
-       kfree(roc);
+       if (free)
+               kfree(roc);
+       else
+               roc->to_be_freed = true;
 }
 
 void ieee80211_sw_roc_work(struct work_struct *work)
@@ -331,6 +337,9 @@ void ieee80211_sw_roc_work(struct work_struct *work)
 
        mutex_lock(&local->mtx);
 
+       if (roc->to_be_freed)
+               goto out_unlock;
+
        if (roc->abort)
                goto finish;
 
@@ -370,7 +379,7 @@ void ieee80211_sw_roc_work(struct work_struct *work)
  finish:
                list_del(&roc->list);
                started = roc->started;
-               ieee80211_roc_notify_destroy(roc);
+               ieee80211_roc_notify_destroy(roc, !roc->abort);
 
                if (started) {
                        drv_flush(local, false);
@@ -410,7 +419,7 @@ static void ieee80211_hw_roc_done(struct work_struct *work)
 
        list_del(&roc->list);
 
-       ieee80211_roc_notify_destroy(roc);
+       ieee80211_roc_notify_destroy(roc, true);
 
        /* if there's another roc, start it now */
        ieee80211_start_next_roc(local);
@@ -460,12 +469,14 @@ void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata)
        list_for_each_entry_safe(roc, tmp, &tmp_list, list) {
                if (local->ops->remain_on_channel) {
                        list_del(&roc->list);
-                       ieee80211_roc_notify_destroy(roc);
+                       ieee80211_roc_notify_destroy(roc, true);
                } else {
                        ieee80211_queue_delayed_work(&local->hw, &roc->work, 0);
 
                        /* work will clean up etc */
                        flush_delayed_work(&roc->work);
+                       WARN_ON(!roc->to_be_freed);
+                       kfree(roc);
                }
        }
 
index bb73ed2d20b90e8ece75bdd41a331fecb9c9d7ac..c6844ad080beee0123969c3aca15b7ca349eddda 100644 (file)
@@ -2675,7 +2675,19 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
 
                memset(nskb->cb, 0, sizeof(nskb->cb));
 
-               ieee80211_tx_skb(rx->sdata, nskb);
+               if (rx->sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) {
+                       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(nskb);
+
+                       info->flags = IEEE80211_TX_CTL_TX_OFFCHAN |
+                                     IEEE80211_TX_INTFL_OFFCHAN_TX_OK |
+                                     IEEE80211_TX_CTL_NO_CCK_RATE;
+                       if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
+                               info->hw_queue =
+                                       local->hw.offchannel_tx_hw_queue;
+               }
+
+               __ieee80211_tx_skb_tid_band(rx->sdata, nskb, 7,
+                                           status->band);
        }
        dev_kfree_skb(rx->skb);
        return RX_QUEUED;
index a79ce820cb50cf01e5cff62a47b974332c3fe8d6..238a0cca320e621dad86cbca1830e4867459cb6d 100644 (file)
@@ -766,6 +766,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
        struct ieee80211_local *local;
        struct ieee80211_sub_if_data *sdata;
        int ret, i;
+       bool have_key = false;
 
        might_sleep();
 
@@ -793,12 +794,19 @@ int __must_check __sta_info_destroy(struct sta_info *sta)
        list_del_rcu(&sta->list);
 
        mutex_lock(&local->key_mtx);
-       for (i = 0; i < NUM_DEFAULT_KEYS; i++)
+       for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
                __ieee80211_key_free(key_mtx_dereference(local, sta->gtk[i]));
-       if (sta->ptk)
+               have_key = true;
+       }
+       if (sta->ptk) {
                __ieee80211_key_free(key_mtx_dereference(local, sta->ptk));
+               have_key = true;
+       }
        mutex_unlock(&local->key_mtx);
 
+       if (!have_key)
+               synchronize_net();
+
        sta->dead = true;
 
        local->num_sta--;
index ce78d1149f1dc2e873eb4291ce9459b40a89b4db..8914d2d2881aab77c5741479d6dbf516db59e3b3 100644 (file)
@@ -2745,7 +2745,8 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw,
                                cpu_to_le16(IEEE80211_FCTL_MOREDATA);
                }
 
-               sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
+               if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+                       sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev);
                if (!ieee80211_tx_prepare(sdata, &tx, skb))
                        break;
                dev_kfree_skb_any(skb);
index 47edf5a40a5939d2401dc11baa89142b9bcd64b6..61f49d241712a77797829a294ee94fc10161306e 100644 (file)
@@ -1394,10 +1394,8 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum)
                        skb_reset_network_header(skb);
                        IP_VS_DBG(12, "ICMP for IPIP %pI4->%pI4: mtu=%u\n",
                                &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, mtu);
-                       rcu_read_lock();
                        ipv4_update_pmtu(skb, dev_net(skb->dev),
                                         mtu, 0, 0, 0, 0);
-                       rcu_read_unlock();
                        /* Client uses PMTUD? */
                        if (!(cih->frag_off & htons(IP_DF)))
                                goto ignore_ipip;
@@ -1577,7 +1575,8 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
        }
        /* ipvs enabled in this netns ? */
        net = skb_net(skb);
-       if (!net_ipvs(net)->enable)
+       ipvs = net_ipvs(net);
+       if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable))
                return NF_ACCEPT;
 
        ip_vs_fill_iph_skb(af, skb, &iph);
@@ -1654,7 +1653,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af)
        }
 
        IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet");
-       ipvs = net_ipvs(net);
        /* Check the server status */
        if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) {
                /* the destination server is not available */
@@ -1815,13 +1813,15 @@ ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb,
 {
        int r;
        struct net *net;
+       struct netns_ipvs *ipvs;
 
        if (ip_hdr(skb)->protocol != IPPROTO_ICMP)
                return NF_ACCEPT;
 
        /* ipvs enabled in this netns ? */
        net = skb_net(skb);
-       if (!net_ipvs(net)->enable)
+       ipvs = net_ipvs(net);
+       if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable))
                return NF_ACCEPT;
 
        return ip_vs_in_icmp(skb, &r, hooknum);
@@ -1835,6 +1835,7 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb,
 {
        int r;
        struct net *net;
+       struct netns_ipvs *ipvs;
        struct ip_vs_iphdr iphdr;
 
        ip_vs_fill_iph_skb(AF_INET6, skb, &iphdr);
@@ -1843,7 +1844,8 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb,
 
        /* ipvs enabled in this netns ? */
        net = skb_net(skb);
-       if (!net_ipvs(net)->enable)
+       ipvs = net_ipvs(net);
+       if (unlikely(sysctl_backup_only(ipvs) || !ipvs->enable))
                return NF_ACCEPT;
 
        return ip_vs_in_icmp_v6(skb, &r, hooknum, &iphdr);
index c68198bf9128abfb695571faed1e0390b036a4bb..9e2d1cccd1eb4c647b2ece3b2c3985edc0b5b32d 100644 (file)
@@ -1808,6 +1808,12 @@ static struct ctl_table vs_vars[] = {
                .mode           = 0644,
                .proc_handler   = proc_dointvec,
        },
+       {
+               .procname       = "backup_only",
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+       },
 #ifdef CONFIG_IP_VS_DEBUG
        {
                .procname       = "debug_level",
@@ -3741,6 +3747,7 @@ static int __net_init ip_vs_control_net_init_sysctl(struct net *net)
        tbl[idx++].data = &ipvs->sysctl_nat_icmp_send;
        ipvs->sysctl_pmtu_disc = 1;
        tbl[idx++].data = &ipvs->sysctl_pmtu_disc;
+       tbl[idx++].data = &ipvs->sysctl_backup_only;
 
 
        ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl);
index ae8ec6f2768888eec1fb8b8c68b4242eff033525..cd1d7298f7ba779de3e6654b85fafaf7cec58f8e 100644 (file)
@@ -906,7 +906,7 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
        sctp_chunkhdr_t _sctpch, *sch;
        unsigned char chunk_type;
        int event, next_state;
-       int ihl;
+       int ihl, cofs;
 
 #ifdef CONFIG_IP_VS_IPV6
        ihl = cp->af == AF_INET ? ip_hdrlen(skb) : sizeof(struct ipv6hdr);
@@ -914,8 +914,8 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
        ihl = ip_hdrlen(skb);
 #endif
 
-       sch = skb_header_pointer(skb, ihl + sizeof(sctp_sctphdr_t),
-                               sizeof(_sctpch), &_sctpch);
+       cofs = ihl + sizeof(sctp_sctphdr_t);
+       sch = skb_header_pointer(skb, cofs, sizeof(_sctpch), &_sctpch);
        if (sch == NULL)
                return;
 
@@ -933,10 +933,12 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
         */
        if ((sch->type == SCTP_CID_COOKIE_ECHO) ||
            (sch->type == SCTP_CID_COOKIE_ACK)) {
-               sch = skb_header_pointer(skb, (ihl + sizeof(sctp_sctphdr_t) +
-                               sch->length), sizeof(_sctpch), &_sctpch);
-               if (sch) {
-                       if (sch->type == SCTP_CID_ABORT)
+               int clen = ntohs(sch->length);
+
+               if (clen >= sizeof(sctp_chunkhdr_t)) {
+                       sch = skb_header_pointer(skb, cofs + ALIGN(clen, 4),
+                                                sizeof(_sctpch), &_sctpch);
+                       if (sch && sch->type == SCTP_CID_ABORT)
                                chunk_type = sch->type;
                }
        }
index a9740bd6fe543bc5d93a05296d9c0dd0260c340b..94b4b9853f60488a1aa9b12ff9e96cac3c90d4d2 100644 (file)
@@ -339,6 +339,13 @@ void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,
 {
        const struct nf_conn_help *help;
        const struct nf_conntrack_helper *helper;
+       struct va_format vaf;
+       va_list args;
+
+       va_start(args, fmt);
+
+       vaf.fmt = fmt;
+       vaf.va = &args;
 
        /* Called from the helper function, this call never fails */
        help = nfct_help(ct);
@@ -347,7 +354,9 @@ void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,
        helper = rcu_dereference(help->helper);
 
        nf_log_packet(nf_ct_l3num(ct), 0, skb, NULL, NULL, NULL,
-                     "nf_ct_%s: dropping packet: %s ", helper->name, fmt);
+                     "nf_ct_%s: dropping packet: %pV ", helper->name, &vaf);
+
+       va_end(args);
 }
 EXPORT_SYMBOL_GPL(nf_ct_helper_log);
 
index 432f95780003f2e36a4d0fb08aaa10b900e052ff..ba65b2041eb4b7f747f7df605a049e7922b32a55 100644 (file)
@@ -969,6 +969,10 @@ static int __init nf_conntrack_proto_dccp_init(void)
 {
        int ret;
 
+       ret = register_pernet_subsys(&dccp_net_ops);
+       if (ret < 0)
+               goto out_pernet;
+
        ret = nf_ct_l4proto_register(&dccp_proto4);
        if (ret < 0)
                goto out_dccp4;
@@ -977,16 +981,12 @@ static int __init nf_conntrack_proto_dccp_init(void)
        if (ret < 0)
                goto out_dccp6;
 
-       ret = register_pernet_subsys(&dccp_net_ops);
-       if (ret < 0)
-               goto out_pernet;
-
        return 0;
-out_pernet:
-       nf_ct_l4proto_unregister(&dccp_proto6);
 out_dccp6:
        nf_ct_l4proto_unregister(&dccp_proto4);
 out_dccp4:
+       unregister_pernet_subsys(&dccp_net_ops);
+out_pernet:
        return ret;
 }
 
index bd7d01d9c7e77d0e8a3a1e50116f854bb4925e14..155ce9f8a0db047d0e100b1d0283b8b36cd6e082 100644 (file)
@@ -420,18 +420,18 @@ static int __init nf_ct_proto_gre_init(void)
 {
        int ret;
 
-       ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_gre4);
-       if (ret < 0)
-               goto out_gre4;
-
        ret = register_pernet_subsys(&proto_gre_net_ops);
        if (ret < 0)
                goto out_pernet;
 
+       ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_gre4);
+       if (ret < 0)
+               goto out_gre4;
+
        return 0;
-out_pernet:
-       nf_ct_l4proto_unregister(&nf_conntrack_l4proto_gre4);
 out_gre4:
+       unregister_pernet_subsys(&proto_gre_net_ops);
+out_pernet:
        return ret;
 }
 
index 480f616d59361e0fff4abf182dc9f35974606187..ec83536def9ab89aca0678ac7b7e02a5509b4f01 100644 (file)
@@ -888,6 +888,10 @@ static int __init nf_conntrack_proto_sctp_init(void)
 {
        int ret;
 
+       ret = register_pernet_subsys(&sctp_net_ops);
+       if (ret < 0)
+               goto out_pernet;
+
        ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_sctp4);
        if (ret < 0)
                goto out_sctp4;
@@ -896,16 +900,12 @@ static int __init nf_conntrack_proto_sctp_init(void)
        if (ret < 0)
                goto out_sctp6;
 
-       ret = register_pernet_subsys(&sctp_net_ops);
-       if (ret < 0)
-               goto out_pernet;
-
        return 0;
-out_pernet:
-       nf_ct_l4proto_unregister(&nf_conntrack_l4proto_sctp6);
 out_sctp6:
        nf_ct_l4proto_unregister(&nf_conntrack_l4proto_sctp4);
 out_sctp4:
+       unregister_pernet_subsys(&sctp_net_ops);
+out_pernet:
        return ret;
 }
 
index 157489581c313b02456b18d0e3e886746a60671f..ca969f6273f77a58851858357c25285b9f22e10e 100644 (file)
@@ -371,6 +371,10 @@ static int __init nf_conntrack_proto_udplite_init(void)
 {
        int ret;
 
+       ret = register_pernet_subsys(&udplite_net_ops);
+       if (ret < 0)
+               goto out_pernet;
+
        ret = nf_ct_l4proto_register(&nf_conntrack_l4proto_udplite4);
        if (ret < 0)
                goto out_udplite4;
@@ -379,16 +383,12 @@ static int __init nf_conntrack_proto_udplite_init(void)
        if (ret < 0)
                goto out_udplite6;
 
-       ret = register_pernet_subsys(&udplite_net_ops);
-       if (ret < 0)
-               goto out_pernet;
-
        return 0;
-out_pernet:
-       nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udplite6);
 out_udplite6:
        nf_ct_l4proto_unregister(&nf_conntrack_l4proto_udplite4);
 out_udplite4:
+       unregister_pernet_subsys(&udplite_net_ops);
+out_pernet:
        return ret;
 }
 
index 6bcce401fd1c5ddfbc3fe00bb45ab87a72ab9fb2..fedee394366187cf35bfa242c9cd1584f0eb0108 100644 (file)
@@ -568,6 +568,7 @@ static int __init nf_conntrack_standalone_init(void)
                register_net_sysctl(&init_net, "net", nf_ct_netfilter_table);
        if (!nf_ct_netfilter_header) {
                pr_err("nf_conntrack: can't register to sysctl.\n");
+               ret = -ENOMEM;
                goto out_sysctl;
        }
 #endif
index d578ec251712b011be829e01aba8f379fb6babd7..0b1b32cda3072d2867edd82c3154538194f606d6 100644 (file)
@@ -62,11 +62,6 @@ void nfnl_unlock(__u8 subsys_id)
 }
 EXPORT_SYMBOL_GPL(nfnl_unlock);
 
-static struct mutex *nfnl_get_lock(__u8 subsys_id)
-{
-       return &table[subsys_id].mutex;
-}
-
 int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n)
 {
        nfnl_lock(n->subsys_id);
@@ -199,7 +194,7 @@ replay:
                        rcu_read_unlock();
                        nfnl_lock(subsys_id);
                        if (rcu_dereference_protected(table[subsys_id].subsys,
-                               lockdep_is_held(nfnl_get_lock(subsys_id))) != ss ||
+                               lockdep_is_held(&table[subsys_id].mutex)) != ss ||
                            nfnetlink_find_client(type, ss) != nc)
                                err = -EAGAIN;
                        else if (nc->call)
index 589d686f0b4cbe0f25b785790dfeba9bf1a13d98..dc3fd5d44464a3ca7cdc5ed68d52ec71256b0cc2 100644 (file)
@@ -49,6 +49,8 @@ nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb,
                return -EINVAL;
 
        acct_name = nla_data(tb[NFACCT_NAME]);
+       if (strlen(acct_name) == 0)
+               return -EINVAL;
 
        list_for_each_entry(nfacct, &nfnl_acct_list, head) {
                if (strncmp(nfacct->name, acct_name, NFACCT_NAME_MAX) != 0)
index 858fd52c10408393a901a9afb686226638f32f07..42680b2baa118d7d09697718077df29d994a10a3 100644 (file)
@@ -112,7 +112,7 @@ instance_create(u_int16_t queue_num, int portid)
        inst->queue_num = queue_num;
        inst->peer_portid = portid;
        inst->queue_maxlen = NFQNL_QMAX_DEFAULT;
-       inst->copy_range = 0xfffff;
+       inst->copy_range = 0xffff;
        inst->copy_mode = NFQNL_COPY_NONE;
        spin_lock_init(&inst->lock);
        INIT_LIST_HEAD(&inst->queue_list);
@@ -1062,8 +1062,10 @@ static int __init nfnetlink_queue_init(void)
 
 #ifdef CONFIG_PROC_FS
        if (!proc_create("nfnetlink_queue", 0440,
-                        proc_net_netfilter, &nfqnl_file_ops))
+                        proc_net_netfilter, &nfqnl_file_ops)) {
+               status = -ENOMEM;
                goto cleanup_subsys;
+       }
 #endif
 
        register_netdevice_notifier(&nfqnl_dev_notifier);
index ba92824086f3c3843c7158c5a5de86fe0db53dc4..3228d7f24eb4107ff717af4323e834af3e680797 100644 (file)
@@ -124,6 +124,9 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par)
        const struct xt_audit_info *info = par->targinfo;
        struct audit_buffer *ab;
 
+       if (audit_enabled == 0)
+               goto errout;
+
        ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
        if (ab == NULL)
                goto errout;
index 847d495cd4de0bee797f994fcaf491ed6efb30ce..8a6c6ea466d874dd34afd2013bef4f777a47db42 100644 (file)
@@ -1189,8 +1189,6 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
        struct netlbl_unlhsh_walk_arg cb_arg;
        u32 skip_bkt = cb->args[0];
        u32 skip_chain = cb->args[1];
-       u32 skip_addr4 = cb->args[2];
-       u32 skip_addr6 = cb->args[3];
        u32 iter_bkt;
        u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0;
        struct netlbl_unlhsh_iface *iface;
@@ -1215,7 +1213,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
                                continue;
                        netlbl_af4list_foreach_rcu(addr4,
                                                   &iface->addr4_list) {
-                               if (iter_addr4++ < skip_addr4)
+                               if (iter_addr4++ < cb->args[2])
                                        continue;
                                if (netlbl_unlabel_staticlist_gen(
                                              NLBL_UNLABEL_C_STATICLIST,
@@ -1231,7 +1229,7 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
 #if IS_ENABLED(CONFIG_IPV6)
                        netlbl_af6list_foreach_rcu(addr6,
                                                   &iface->addr6_list) {
-                               if (iter_addr6++ < skip_addr6)
+                               if (iter_addr6++ < cb->args[3])
                                        continue;
                                if (netlbl_unlabel_staticlist_gen(
                                              NLBL_UNLABEL_C_STATICLIST,
@@ -1250,10 +1248,10 @@ static int netlbl_unlabel_staticlist(struct sk_buff *skb,
 
 unlabel_staticlist_return:
        rcu_read_unlock();
-       cb->args[0] = skip_bkt;
-       cb->args[1] = skip_chain;
-       cb->args[2] = skip_addr4;
-       cb->args[3] = skip_addr6;
+       cb->args[0] = iter_bkt;
+       cb->args[1] = iter_chain;
+       cb->args[2] = iter_addr4;
+       cb->args[3] = iter_addr6;
        return skb->len;
 }
 
@@ -1273,12 +1271,9 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
 {
        struct netlbl_unlhsh_walk_arg cb_arg;
        struct netlbl_unlhsh_iface *iface;
-       u32 skip_addr4 = cb->args[0];
-       u32 skip_addr6 = cb->args[1];
-       u32 iter_addr4 = 0;
+       u32 iter_addr4 = 0, iter_addr6 = 0;
        struct netlbl_af4list *addr4;
 #if IS_ENABLED(CONFIG_IPV6)
-       u32 iter_addr6 = 0;
        struct netlbl_af6list *addr6;
 #endif
 
@@ -1292,7 +1287,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
                goto unlabel_staticlistdef_return;
 
        netlbl_af4list_foreach_rcu(addr4, &iface->addr4_list) {
-               if (iter_addr4++ < skip_addr4)
+               if (iter_addr4++ < cb->args[0])
                        continue;
                if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
                                              iface,
@@ -1305,7 +1300,7 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
        }
 #if IS_ENABLED(CONFIG_IPV6)
        netlbl_af6list_foreach_rcu(addr6, &iface->addr6_list) {
-               if (iter_addr6++ < skip_addr6)
+               if (iter_addr6++ < cb->args[1])
                        continue;
                if (netlbl_unlabel_staticlist_gen(NLBL_UNLABEL_C_STATICLISTDEF,
                                              iface,
@@ -1320,8 +1315,8 @@ static int netlbl_unlabel_staticlistdef(struct sk_buff *skb,
 
 unlabel_staticlistdef_return:
        rcu_read_unlock();
-       cb->args[0] = skip_addr4;
-       cb->args[1] = skip_addr6;
+       cb->args[0] = iter_addr4;
+       cb->args[1] = iter_addr6;
        return skb->len;
 }
 
index f2aabb6f410582439604d7a3c0f379a5cd798621..5a55be3f17a54aa2acac3ce109c412c86c652b36 100644 (file)
@@ -142,6 +142,7 @@ int genl_register_mc_group(struct genl_family *family,
        int err = 0;
 
        BUG_ON(grp->name[0] == '\0');
+       BUG_ON(memchr(grp->name, '\0', GENL_NAMSIZ) == NULL);
 
        genl_lock();
 
index 7f8266dd14cbc164a278aa3bbc0438c845fa0bf5..ee25f25f0cd638367cc4a6668c44e907945c9469 100644 (file)
@@ -68,7 +68,8 @@ static void nfc_llcp_socket_purge(struct nfc_llcp_sock *sock)
        }
 }
 
-static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
+static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen,
+                                   int err)
 {
        struct sock *sk;
        struct hlist_node *tmp;
@@ -100,11 +101,12 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
 
                                nfc_llcp_accept_unlink(accept_sk);
 
+                               if (err)
+                                       accept_sk->sk_err = err;
                                accept_sk->sk_state = LLCP_CLOSED;
+                               accept_sk->sk_state_change(sk);
 
                                bh_unlock_sock(accept_sk);
-
-                               sock_orphan(accept_sk);
                        }
 
                        if (listen == true) {
@@ -123,16 +125,45 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool listen)
                        continue;
                }
 
+               if (err)
+                       sk->sk_err = err;
                sk->sk_state = LLCP_CLOSED;
+               sk->sk_state_change(sk);
 
                bh_unlock_sock(sk);
 
-               sock_orphan(sk);
-
                sk_del_node_init(sk);
        }
 
        write_unlock(&local->sockets.lock);
+
+       /*
+        * If we want to keep the listening sockets alive,
+        * we don't touch the RAW ones.
+        */
+       if (listen == true)
+               return;
+
+       write_lock(&local->raw_sockets.lock);
+
+       sk_for_each_safe(sk, tmp, &local->raw_sockets.head) {
+               llcp_sock = nfc_llcp_sock(sk);
+
+               bh_lock_sock(sk);
+
+               nfc_llcp_socket_purge(llcp_sock);
+
+               if (err)
+                       sk->sk_err = err;
+               sk->sk_state = LLCP_CLOSED;
+               sk->sk_state_change(sk);
+
+               bh_unlock_sock(sk);
+
+               sk_del_node_init(sk);
+       }
+
+       write_unlock(&local->raw_sockets.lock);
 }
 
 struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
@@ -142,20 +173,25 @@ struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
        return local;
 }
 
-static void local_release(struct kref *ref)
+static void local_cleanup(struct nfc_llcp_local *local, bool listen)
 {
-       struct nfc_llcp_local *local;
-
-       local = container_of(ref, struct nfc_llcp_local, ref);
-
-       list_del(&local->list);
-       nfc_llcp_socket_release(local, false);
+       nfc_llcp_socket_release(local, listen, ENXIO);
        del_timer_sync(&local->link_timer);
        skb_queue_purge(&local->tx_queue);
        cancel_work_sync(&local->tx_work);
        cancel_work_sync(&local->rx_work);
        cancel_work_sync(&local->timeout_work);
        kfree_skb(local->rx_pending);
+}
+
+static void local_release(struct kref *ref)
+{
+       struct nfc_llcp_local *local;
+
+       local = container_of(ref, struct nfc_llcp_local, ref);
+
+       list_del(&local->list);
+       local_cleanup(local, false);
        kfree(local);
 }
 
@@ -785,7 +821,6 @@ static void nfc_llcp_recv_ui(struct nfc_llcp_local *local,
                skb_get(skb);
        } else {
                pr_err("Receive queue is full\n");
-               kfree_skb(skb);
        }
 
        nfc_llcp_sock_put(llcp_sock);
@@ -986,7 +1021,6 @@ static void nfc_llcp_recv_hdlc(struct nfc_llcp_local *local,
                        skb_get(skb);
                } else {
                        pr_err("Receive queue is full\n");
-                       kfree_skb(skb);
                }
        }
 
@@ -1348,7 +1382,7 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
                return;
 
        /* Close and purge all existing sockets */
-       nfc_llcp_socket_release(local, true);
+       nfc_llcp_socket_release(local, true, 0);
 }
 
 void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
@@ -1427,6 +1461,8 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev)
                return;
        }
 
+       local_cleanup(local, false);
+
        nfc_llcp_local_put(local);
 }
 
index 5332751943a9ec564befadda63a5a3749d7434c1..8f025746f3370b4296c8064c603e06085adcb42e 100644 (file)
@@ -270,7 +270,9 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
                }
 
                if (sk->sk_state == LLCP_CONNECTED || !newsock) {
-                       nfc_llcp_accept_unlink(sk);
+                       list_del_init(&lsk->accept_queue);
+                       sock_put(sk);
+
                        if (newsock)
                                sock_graft(sk, newsock);
 
@@ -278,6 +280,8 @@ struct sock *nfc_llcp_accept_dequeue(struct sock *parent,
 
                        pr_debug("Returning sk state %d\n", sk->sk_state);
 
+                       sk_acceptq_removed(parent);
+
                        return sk;
                }
 
@@ -462,8 +466,6 @@ static int llcp_sock_release(struct socket *sock)
                        nfc_llcp_accept_unlink(accept_sk);
 
                        release_sock(accept_sk);
-
-                       sock_orphan(accept_sk);
                }
        }
 
index ac2defeeba83ddbbb1ffcacb54deec0714fb85e0..d4d5363c7ba7868731cb9188ad9bc5ccd28b8304 100644 (file)
@@ -58,7 +58,7 @@ static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci)
 
        if (skb->ip_summed == CHECKSUM_COMPLETE)
                skb->csum = csum_sub(skb->csum, csum_partial(skb->data
-                                       + ETH_HLEN, VLAN_HLEN, 0));
+                                       + (2 * ETH_ALEN), VLAN_HLEN, 0));
 
        vhdr = (struct vlan_hdr *)(skb->data + ETH_HLEN);
        *current_tci = vhdr->h_vlan_TCI;
@@ -115,7 +115,7 @@ static int push_vlan(struct sk_buff *skb, const struct ovs_action_push_vlan *vla
 
                if (skb->ip_summed == CHECKSUM_COMPLETE)
                        skb->csum = csum_add(skb->csum, csum_partial(skb->data
-                                       + ETH_HLEN, VLAN_HLEN, 0));
+                                       + (2 * ETH_ALEN), VLAN_HLEN, 0));
 
        }
        __vlan_hwaccel_put_tag(skb, ntohs(vlan->vlan_tci) & ~VLAN_TAG_PRESENT);
index e87a26506dbaecc3e09af9cc5c75a767bb303e95..a4b724708a1ab0b7d4aedffc07606b8fbfdac0a9 100644 (file)
@@ -394,6 +394,7 @@ static int queue_userspace_packet(struct net *net, int dp_ifindex,
 
        skb_copy_and_csum_dev(skb, nla_data(nla));
 
+       genlmsg_end(user_skb, upcall);
        err = genlmsg_unicast(net, user_skb, upcall_info->portid);
 
 out:
@@ -1690,6 +1691,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info)
        if (IS_ERR(vport))
                goto exit_unlock;
 
+       err = 0;
        reply = ovs_vport_cmd_build_info(vport, info->snd_portid, info->snd_seq,
                                         OVS_VPORT_CMD_NEW);
        if (IS_ERR(reply)) {
@@ -1771,6 +1773,7 @@ static int ovs_vport_cmd_del(struct sk_buff *skb, struct genl_info *info)
        if (IS_ERR(reply))
                goto exit_unlock;
 
+       err = 0;
        ovs_dp_detach_port(vport);
 
        genl_notify(reply, genl_info_net(info), info->snd_portid,
index 20605ecf100bda104dd5fa7c536787149f0b2ea8..fe0e4215c73d6045469ba006722ef223d43ebd66 100644 (file)
@@ -482,7 +482,11 @@ static __be16 parse_ethertype(struct sk_buff *skb)
                return htons(ETH_P_802_2);
 
        __skb_pull(skb, sizeof(struct llc_snap_hdr));
-       return llc->ethertype;
+
+       if (ntohs(llc->ethertype) >= 1536)
+               return llc->ethertype;
+
+       return htons(ETH_P_802_2);
 }
 
 static int parse_icmpv6(struct sk_buff *skb, struct sw_flow_key *key,
index 670cbc3518ded5930f900eaca7e0677835cf750b..2130d61c384a227e0d7f5093e285054497e8fb40 100644 (file)
@@ -43,8 +43,7 @@ static void netdev_port_receive(struct vport *vport, struct sk_buff *skb)
 
        /* Make our own copy of the packet.  Otherwise we will mangle the
         * packet for anyone who came before us (e.g. tcpdump via AF_PACKET).
-        * (No one comes after us, since we tell handle_bridge() that we took
-        * the packet.) */
+        */
        skb = skb_share_check(skb, GFP_ATOMIC);
        if (unlikely(!skb))
                return;
index ba717cc038b3183fc24692e4b76cae8da6cbfbe4..f6b8132ce4cb7380a6bca860b4e50a2aa6756772 100644 (file)
@@ -325,8 +325,7 @@ int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb)
  * @skb: skb that was received
  *
  * Must be called with rcu_read_lock.  The packet cannot be shared and
- * skb->data should point to the Ethernet header.  The caller must have already
- * called compute_ip_summed() to initialize the checksumming fields.
+ * skb->data should point to the Ethernet header.
  */
 void ovs_vport_receive(struct vport *vport, struct sk_buff *skb)
 {
index 7be790d60b900d30053256b2f6cb1753056b0ba3..73be187d389ed044c886d22e4960905283d9de87 100644 (file)
@@ -87,6 +87,7 @@ void rds_stats_info_copy(struct rds_info_iterator *iter,
        for (i = 0; i < nr; i++) {
                BUG_ON(strlen(names[i]) >= sizeof(ctr.name));
                strncpy(ctr.name, names[i], sizeof(ctr.name) - 1);
+               ctr.name[sizeof(ctr.name) - 1] = '\0';
                ctr.value = values[i];
 
                rds_info_copy(iter, &ctr, sizeof(ctr));
index 13aa47aa2ffb48ea25990dce3762b83e775d7bcf..1bc210ffcba2a524750b3382d444a87db2c08c2c 100644 (file)
@@ -962,8 +962,11 @@ cbq_dequeue(struct Qdisc *sch)
                cbq_update(q);
                if ((incr -= incr2) < 0)
                        incr = 0;
+               q->now += incr;
+       } else {
+               if (now > q->now)
+                       q->now = now;
        }
-       q->now += incr;
        q->now_rt = now;
 
        for (;;) {
index 4e606fcb2534929a2470e807816ac1089d81b7b2..55786283a3dfe613ee6deac5756b4726a66925ee 100644 (file)
@@ -195,7 +195,7 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                flow->deficit = q->quantum;
                flow->dropped = 0;
        }
-       if (++sch->q.qlen < sch->limit)
+       if (++sch->q.qlen <= sch->limit)
                return NET_XMIT_SUCCESS;
 
        q->drop_overlimit++;
index ffad48109a228c66ccbd33124525dee83f9158df..eac7e0ee23c18708354e3cef8c237d289b81235f 100644 (file)
@@ -904,7 +904,7 @@ void psched_ratecfg_precompute(struct psched_ratecfg *r, u32 rate)
        u64 mult;
        int shift;
 
-       r->rate_bps = rate << 3;
+       r->rate_bps = (u64)rate << 3;
        r->shift = 0;
        r->mult = 1;
        /*
index e9a77f621c3dfc87d49ed534003a20ceb1d98f8d..d51852bba01c981c9f9834dad82cfbcfec904508 100644 (file)
@@ -298,6 +298,10 @@ static void qfq_update_agg(struct qfq_sched *q, struct qfq_aggregate *agg,
            new_num_classes == q->max_agg_classes - 1) /* agg no more full */
                hlist_add_head(&agg->nonfull_next, &q->nonfull_aggs);
 
+       /* The next assignment may let
+        * agg->initial_budget > agg->budgetmax
+        * hold, we will take it into account in charge_actual_service().
+        */
        agg->budgetmax = new_num_classes * agg->lmax;
        new_agg_weight = agg->class_weight * new_num_classes;
        agg->inv_w = ONE_FP/new_agg_weight;
@@ -817,7 +821,7 @@ static void qfq_make_eligible(struct qfq_sched *q)
        unsigned long old_vslot = q->oldV >> q->min_slot_shift;
 
        if (vslot != old_vslot) {
-               unsigned long mask = (1UL << fls(vslot ^ old_vslot)) - 1;
+               unsigned long mask = (1ULL << fls(vslot ^ old_vslot)) - 1;
                qfq_move_groups(q, mask, IR, ER);
                qfq_move_groups(q, mask, IB, EB);
        }
@@ -988,12 +992,23 @@ static inline struct sk_buff *qfq_peek_skb(struct qfq_aggregate *agg,
 /* Update F according to the actual service received by the aggregate. */
 static inline void charge_actual_service(struct qfq_aggregate *agg)
 {
-       /* compute the service received by the aggregate */
-       u32 service_received = agg->initial_budget - agg->budget;
+       /* Compute the service received by the aggregate, taking into
+        * account that, after decreasing the number of classes in
+        * agg, it may happen that
+        * agg->initial_budget - agg->budget > agg->bugdetmax
+        */
+       u32 service_received = min(agg->budgetmax,
+                                  agg->initial_budget - agg->budget);
 
        agg->F = agg->S + (u64)service_received * agg->inv_w;
 }
 
+static inline void qfq_update_agg_ts(struct qfq_sched *q,
+                                    struct qfq_aggregate *agg,
+                                    enum update_reason reason);
+
+static void qfq_schedule_agg(struct qfq_sched *q, struct qfq_aggregate *agg);
+
 static struct sk_buff *qfq_dequeue(struct Qdisc *sch)
 {
        struct qfq_sched *q = qdisc_priv(sch);
@@ -1021,7 +1036,7 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch)
                in_serv_agg->initial_budget = in_serv_agg->budget =
                        in_serv_agg->budgetmax;
 
-               if (!list_empty(&in_serv_agg->active))
+               if (!list_empty(&in_serv_agg->active)) {
                        /*
                         * Still active: reschedule for
                         * service. Possible optimization: if no other
@@ -1032,8 +1047,9 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch)
                         * handle it, we would need to maintain an
                         * extra num_active_aggs field.
                        */
-                       qfq_activate_agg(q, in_serv_agg, requeue);
-               else if (sch->q.qlen == 0) { /* no aggregate to serve */
+                       qfq_update_agg_ts(q, in_serv_agg, requeue);
+                       qfq_schedule_agg(q, in_serv_agg);
+               } else if (sch->q.qlen == 0) { /* no aggregate to serve */
                        q->in_serv_agg = NULL;
                        return NULL;
                }
@@ -1052,7 +1068,15 @@ static struct sk_buff *qfq_dequeue(struct Qdisc *sch)
        qdisc_bstats_update(sch, skb);
 
        agg_dequeue(in_serv_agg, cl, len);
-       in_serv_agg->budget -= len;
+       /* If lmax is lowered, through qfq_change_class, for a class
+        * owning pending packets with larger size than the new value
+        * of lmax, then the following condition may hold.
+        */
+       if (unlikely(in_serv_agg->budget < len))
+               in_serv_agg->budget = 0;
+       else
+               in_serv_agg->budget -= len;
+
        q->V += (u64)len * IWSUM;
        pr_debug("qfq dequeue: len %u F %lld now %lld\n",
                 len, (unsigned long long) in_serv_agg->F,
@@ -1217,17 +1241,11 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch)
        cl->deficit = agg->lmax;
        list_add_tail(&cl->alist, &agg->active);
 
-       if (list_first_entry(&agg->active, struct qfq_class, alist) != cl)
-               return err; /* aggregate was not empty, nothing else to do */
+       if (list_first_entry(&agg->active, struct qfq_class, alist) != cl ||
+           q->in_serv_agg == agg)
+               return err; /* non-empty or in service, nothing else to do */
 
-       /* recharge budget */
-       agg->initial_budget = agg->budget = agg->budgetmax;
-
-       qfq_update_agg_ts(q, agg, enqueue);
-       if (q->in_serv_agg == NULL)
-               q->in_serv_agg = agg;
-       else if (agg != q->in_serv_agg)
-               qfq_schedule_agg(q, agg);
+       qfq_activate_agg(q, agg, enqueue);
 
        return err;
 }
@@ -1261,7 +1279,8 @@ static void qfq_schedule_agg(struct qfq_sched *q, struct qfq_aggregate *agg)
                /* group was surely ineligible, remove */
                __clear_bit(grp->index, &q->bitmaps[IR]);
                __clear_bit(grp->index, &q->bitmaps[IB]);
-       } else if (!q->bitmaps[ER] && qfq_gt(roundedS, q->V))
+       } else if (!q->bitmaps[ER] && qfq_gt(roundedS, q->V) &&
+                  q->in_serv_agg == NULL)
                q->V = roundedS;
 
        grp->S = roundedS;
@@ -1284,8 +1303,15 @@ skip_update:
 static void qfq_activate_agg(struct qfq_sched *q, struct qfq_aggregate *agg,
                             enum update_reason reason)
 {
+       agg->initial_budget = agg->budget = agg->budgetmax; /* recharge budg. */
+
        qfq_update_agg_ts(q, agg, reason);
-       qfq_schedule_agg(q, agg);
+       if (q->in_serv_agg == NULL) { /* no aggr. in service or scheduled */
+               q->in_serv_agg = agg; /* start serving this aggregate */
+                /* update V: to be in service, agg must be eligible */
+               q->oldV = q->V = agg->S;
+       } else if (agg != q->in_serv_agg)
+               qfq_schedule_agg(q, agg);
 }
 
 static void qfq_slot_remove(struct qfq_sched *q, struct qfq_group *grp,
@@ -1357,8 +1383,6 @@ static void qfq_deactivate_agg(struct qfq_sched *q, struct qfq_aggregate *agg)
                        __set_bit(grp->index, &q->bitmaps[s]);
                }
        }
-
-       qfq_update_eligible(q);
 }
 
 static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg)
index 43cd0dd9149d42e2739985bd8bb4ea15c977de06..d2709e2b7be6642d47a691d27c983a937c7e8648 100644 (file)
@@ -1079,7 +1079,7 @@ struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *asoc,
                        transports) {
 
                if (transport == active)
-                       break;
+                       continue;
                list_for_each_entry(chunk, &transport->transmitted,
                                transmitted_list) {
                        if (key == chunk->subh.data_hdr->tsn) {
index 5131fcfedb03c0b09e8c7e451341cebd82e49692..de1a0138317f482c028ce583c335501b14d9f917 100644 (file)
@@ -2082,7 +2082,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(struct net *net,
        }
 
        /* Delete the tempory new association. */
-       sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc));
+       sctp_add_cmd_sf(commands, SCTP_CMD_SET_ASOC, SCTP_ASOC(new_asoc));
        sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL());
 
        /* Restore association pointer to provide SCTP command interpeter
index f7d34e7b6f818ba52bec46795b83062cbdf5a71e..5ead60550895f848ba2348bba3bbbfc50ddea7ea 100644 (file)
@@ -447,17 +447,21 @@ static int rsc_parse(struct cache_detail *cd,
        else {
                int N, i;
 
+               /*
+                * NOTE: we skip uid_valid()/gid_valid() checks here:
+                * instead, * -1 id's are later mapped to the
+                * (export-specific) anonymous id by nfsd_setuser.
+                *
+                * (But supplementary gid's get no such special
+                * treatment so are checked for validity here.)
+                */
                /* uid */
                rsci.cred.cr_uid = make_kuid(&init_user_ns, id);
-               if (!uid_valid(rsci.cred.cr_uid))
-                       goto out;
 
                /* gid */
                if (get_int(&mesg, &id))
                        goto out;
                rsci.cred.cr_gid = make_kgid(&init_user_ns, id);
-               if (!gid_valid(rsci.cred.cr_gid))
-                       goto out;
 
                /* number of additional gid's */
                if (get_int(&mesg, &N))
index a0f48a51e14e5e3b57a34970f0be204ec5c802ff..a9129f8d70706f5e33ac8f39cb3ea8a3e5825ca2 100644 (file)
@@ -1175,6 +1175,7 @@ static struct file_system_type rpc_pipe_fs_type = {
        .kill_sb        = rpc_kill_sb,
 };
 MODULE_ALIAS_FS("rpc_pipefs");
+MODULE_ALIAS("rpc_pipefs");
 
 static void
 init_once(void *foo)
index fb20f25ddec9b70c805ad65d675441d02b62055b..f8529fc8e54275c5b7b9809f0219f20608ffb472 100644 (file)
@@ -180,6 +180,8 @@ static void __rpc_add_wait_queue(struct rpc_wait_queue *queue,
                list_add_tail(&task->u.tk_wait.list, &queue->tasks[0]);
        task->tk_waitqueue = queue;
        queue->qlen++;
+       /* barrier matches the read in rpc_wake_up_task_queue_locked() */
+       smp_wmb();
        rpc_set_queued(task);
 
        dprintk("RPC: %5u added to queue %p \"%s\"\n",
@@ -430,8 +432,11 @@ static void __rpc_do_wake_up_task(struct rpc_wait_queue *queue, struct rpc_task
  */
 static void rpc_wake_up_task_queue_locked(struct rpc_wait_queue *queue, struct rpc_task *task)
 {
-       if (RPC_IS_QUEUED(task) && task->tk_waitqueue == queue)
-               __rpc_do_wake_up_task(queue, task);
+       if (RPC_IS_QUEUED(task)) {
+               smp_rmb();
+               if (task->tk_waitqueue == queue)
+                       __rpc_do_wake_up_task(queue, task);
+       }
 }
 
 /*
index c1d8476b76929b4300d967dd795aa6c2ce38f7a0..3d02130828da671066b40aa7dd769cf6a7bd4a74 100644 (file)
@@ -849,6 +849,14 @@ static void xs_tcp_close(struct rpc_xprt *xprt)
                xs_tcp_shutdown(xprt);
 }
 
+static void xs_local_destroy(struct rpc_xprt *xprt)
+{
+       xs_close(xprt);
+       xs_free_peer_addresses(xprt);
+       xprt_free(xprt);
+       module_put(THIS_MODULE);
+}
+
 /**
  * xs_destroy - prepare to shutdown a transport
  * @xprt: doomed transport
@@ -862,10 +870,7 @@ static void xs_destroy(struct rpc_xprt *xprt)
 
        cancel_delayed_work_sync(&transport->connect_worker);
 
-       xs_close(xprt);
-       xs_free_peer_addresses(xprt);
-       xprt_free(xprt);
-       module_put(THIS_MODULE);
+       xs_local_destroy(xprt);
 }
 
 static inline struct rpc_xprt *xprt_from_sock(struct sock *sk)
@@ -2482,7 +2487,7 @@ static struct rpc_xprt_ops xs_local_ops = {
        .send_request           = xs_local_send_request,
        .set_retrans_timeout    = xprt_set_retrans_timeout_def,
        .close                  = xs_close,
-       .destroy                = xs_destroy,
+       .destroy                = xs_local_destroy,
        .print_stats            = xs_local_print_stats,
 };
 
index 51be64f163ec166812660db8de26105b1c92eb46..2db702d82e7d16fea7a27a82cc7c5dc3d3d95726 100644 (file)
@@ -382,7 +382,7 @@ static void unix_sock_destructor(struct sock *sk)
 #endif
 }
 
-static int unix_release_sock(struct sock *sk, int embrion)
+static void unix_release_sock(struct sock *sk, int embrion)
 {
        struct unix_sock *u = unix_sk(sk);
        struct path path;
@@ -451,8 +451,6 @@ static int unix_release_sock(struct sock *sk, int embrion)
 
        if (unix_tot_inflight)
                unix_gc();              /* Garbage collect fds */
-
-       return 0;
 }
 
 static void init_peercred(struct sock *sk)
@@ -699,9 +697,10 @@ static int unix_release(struct socket *sock)
        if (!sk)
                return 0;
 
+       unix_release_sock(sk, 0);
        sock->sk = NULL;
 
-       return unix_release_sock(sk, 0);
+       return 0;
 }
 
 static int unix_autobind(struct socket *sock)
@@ -1994,7 +1993,7 @@ again:
                        if ((UNIXCB(skb).pid  != siocb->scm->pid) ||
                            (UNIXCB(skb).cred != siocb->scm->cred))
                                break;
-               } else {
+               } else if (test_bit(SOCK_PASSCRED, &sock->flags)) {
                        /* Copy credentials */
                        scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred);
                        check_creds = 1;
index ca511c4f388a56cf1fdaf110d31aff7d30b5d0fb..d8079daf1bdeaed0f341aaac673c8b9e1da7d96b 100644 (file)
@@ -207,7 +207,7 @@ static struct sock *__vsock_find_bound_socket(struct sockaddr_vm *addr)
        struct vsock_sock *vsk;
 
        list_for_each_entry(vsk, vsock_bound_sockets(addr), bound_table)
-               if (vsock_addr_equals_addr_any(addr, &vsk->local_addr))
+               if (addr->svm_port == vsk->local_addr.svm_port)
                        return sk_vsock(vsk);
 
        return NULL;
@@ -220,8 +220,8 @@ static struct sock *__vsock_find_connected_socket(struct sockaddr_vm *src,
 
        list_for_each_entry(vsk, vsock_connected_sockets(src, dst),
                            connected_table) {
-               if (vsock_addr_equals_addr(src, &vsk->remote_addr)
-                   && vsock_addr_equals_addr(dst, &vsk->local_addr)) {
+               if (vsock_addr_equals_addr(src, &vsk->remote_addr) &&
+                   dst->svm_port == vsk->local_addr.svm_port) {
                        return sk_vsock(vsk);
                }
        }
index a70ace83a1531232a2f11afc63c8b4ab1c4ea918..1f6508e249ae5934ce9257ebe5cc3e5941300ffa 100644 (file)
@@ -464,19 +464,16 @@ static struct sock *vmci_transport_get_pending(
        struct vsock_sock *vlistener;
        struct vsock_sock *vpending;
        struct sock *pending;
+       struct sockaddr_vm src;
+
+       vsock_addr_init(&src, pkt->dg.src.context, pkt->src_port);
 
        vlistener = vsock_sk(listener);
 
        list_for_each_entry(vpending, &vlistener->pending_links,
                            pending_links) {
-               struct sockaddr_vm src;
-               struct sockaddr_vm dst;
-
-               vsock_addr_init(&src, pkt->dg.src.context, pkt->src_port);
-               vsock_addr_init(&dst, pkt->dg.dst.context, pkt->dst_port);
-
                if (vsock_addr_equals_addr(&src, &vpending->remote_addr) &&
-                   vsock_addr_equals_addr(&dst, &vpending->local_addr)) {
+                   pkt->dst_port == vpending->local_addr.svm_port) {
                        pending = sk_vsock(vpending);
                        sock_hold(pending);
                        goto found;
@@ -739,10 +736,15 @@ static int vmci_transport_recv_stream_cb(void *data, struct vmci_datagram *dg)
         */
        bh_lock_sock(sk);
 
-       if (!sock_owned_by_user(sk) && sk->sk_state == SS_CONNECTED)
-               vmci_trans(vsk)->notify_ops->handle_notify_pkt(
-                               sk, pkt, true, &dst, &src,
-                               &bh_process_pkt);
+       if (!sock_owned_by_user(sk)) {
+               /* The local context ID may be out of date, update it. */
+               vsk->local_addr.svm_cid = dst.svm_cid;
+
+               if (sk->sk_state == SS_CONNECTED)
+                       vmci_trans(vsk)->notify_ops->handle_notify_pkt(
+                                       sk, pkt, true, &dst, &src,
+                                       &bh_process_pkt);
+       }
 
        bh_unlock_sock(sk);
 
@@ -902,6 +904,9 @@ static void vmci_transport_recv_pkt_work(struct work_struct *work)
 
        lock_sock(sk);
 
+       /* The local context ID may be out of date. */
+       vsock_sk(sk)->local_addr.svm_cid = pkt->dg.dst.context;
+
        switch (sk->sk_state) {
        case SS_LISTEN:
                vmci_transport_recv_listen(sk, pkt);
@@ -958,6 +963,10 @@ static int vmci_transport_recv_listen(struct sock *sk,
        pending = vmci_transport_get_pending(sk, pkt);
        if (pending) {
                lock_sock(pending);
+
+               /* The local context ID may be out of date. */
+               vsock_sk(pending)->local_addr.svm_cid = pkt->dg.dst.context;
+
                switch (pending->sk_state) {
                case SS_CONNECTING:
                        err = vmci_transport_recv_connecting_server(sk,
index b7df1aea7c59364b18f4e7a71b448909120a9b45..ec2611b4ea0ee4fc073926c9a33347ace8de9e4f 100644 (file)
@@ -64,16 +64,6 @@ bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
 }
 EXPORT_SYMBOL_GPL(vsock_addr_equals_addr);
 
-bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
-                               const struct sockaddr_vm *other)
-{
-       return (addr->svm_cid == VMADDR_CID_ANY ||
-               other->svm_cid == VMADDR_CID_ANY ||
-               addr->svm_cid == other->svm_cid) &&
-              addr->svm_port == other->svm_port;
-}
-EXPORT_SYMBOL_GPL(vsock_addr_equals_addr_any);
-
 int vsock_addr_cast(const struct sockaddr *addr,
                    size_t len, struct sockaddr_vm **out_addr)
 {
index cdfbcefdf84300f71fd598a782a8de66d6c095fb..9ccd5316eac09ddfeb7a07f030a9f4f993da7de2 100644 (file)
@@ -24,8 +24,6 @@ bool vsock_addr_bound(const struct sockaddr_vm *addr);
 void vsock_addr_unbind(struct sockaddr_vm *addr);
 bool vsock_addr_equals_addr(const struct sockaddr_vm *addr,
                            const struct sockaddr_vm *other);
-bool vsock_addr_equals_addr_any(const struct sockaddr_vm *addr,
-                               const struct sockaddr_vm *other);
 int vsock_addr_cast(const struct sockaddr *addr, size_t len,
                    struct sockaddr_vm **out_addr);
 
index 5ffff039b0174eefb8f3967dc6f5307ea7cb2f8c..6ddf74f0ae1e5ace4346f3c0cf6b4f1ce13fa580 100644 (file)
@@ -212,6 +212,39 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
        rdev_rfkill_poll(rdev);
 }
 
+void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
+                             struct wireless_dev *wdev)
+{
+       lockdep_assert_held(&rdev->devlist_mtx);
+       lockdep_assert_held(&rdev->sched_scan_mtx);
+
+       if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
+               return;
+
+       if (!wdev->p2p_started)
+               return;
+
+       rdev_stop_p2p_device(rdev, wdev);
+       wdev->p2p_started = false;
+
+       rdev->opencount--;
+
+       if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
+               bool busy = work_busy(&rdev->scan_done_wk);
+
+               /*
+                * If the work isn't pending or running (in which case it would
+                * be waiting for the lock we hold) the driver didn't properly
+                * cancel the scan when the interface was removed. In this case
+                * warn and leak the scan request object to not crash later.
+                */
+               WARN_ON(!busy);
+
+               rdev->scan_req->aborted = true;
+               ___cfg80211_scan_done(rdev, !busy);
+       }
+}
+
 static int cfg80211_rfkill_set_block(void *data, bool blocked)
 {
        struct cfg80211_registered_device *rdev = data;
@@ -221,7 +254,8 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
                return 0;
 
        rtnl_lock();
-       mutex_lock(&rdev->devlist_mtx);
+
+       /* read-only iteration need not hold the devlist_mtx */
 
        list_for_each_entry(wdev, &rdev->wdev_list, list) {
                if (wdev->netdev) {
@@ -231,18 +265,18 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
                /* otherwise, check iftype */
                switch (wdev->iftype) {
                case NL80211_IFTYPE_P2P_DEVICE:
-                       if (!wdev->p2p_started)
-                               break;
-                       rdev_stop_p2p_device(rdev, wdev);
-                       wdev->p2p_started = false;
-                       rdev->opencount--;
+                       /* but this requires it */
+                       mutex_lock(&rdev->devlist_mtx);
+                       mutex_lock(&rdev->sched_scan_mtx);
+                       cfg80211_stop_p2p_device(rdev, wdev);
+                       mutex_unlock(&rdev->sched_scan_mtx);
+                       mutex_unlock(&rdev->devlist_mtx);
                        break;
                default:
                        break;
                }
        }
 
-       mutex_unlock(&rdev->devlist_mtx);
        rtnl_unlock();
 
        return 0;
@@ -367,8 +401,7 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
        rdev->wiphy.rts_threshold = (u32) -1;
        rdev->wiphy.coverage_class = 0;
 
-       rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH |
-                              NL80211_FEATURE_ADVERTISE_CHAN_LIMITS;
+       rdev->wiphy.features = NL80211_FEATURE_SCAN_FLUSH;
 
        return &rdev->wiphy;
 }
@@ -746,17 +779,13 @@ static void wdev_cleanup_work(struct work_struct *work)
        wdev = container_of(work, struct wireless_dev, cleanup_work);
        rdev = wiphy_to_dev(wdev->wiphy);
 
-       cfg80211_lock_rdev(rdev);
+       mutex_lock(&rdev->sched_scan_mtx);
 
        if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
                rdev->scan_req->aborted = true;
                ___cfg80211_scan_done(rdev, true);
        }
 
-       cfg80211_unlock_rdev(rdev);
-
-       mutex_lock(&rdev->sched_scan_mtx);
-
        if (WARN_ON(rdev->sched_scan_req &&
                    rdev->sched_scan_req->dev == wdev->netdev)) {
                __cfg80211_stop_sched_scan(rdev, false);
@@ -782,21 +811,19 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
                return;
 
        mutex_lock(&rdev->devlist_mtx);
+       mutex_lock(&rdev->sched_scan_mtx);
        list_del_rcu(&wdev->list);
        rdev->devlist_generation++;
 
        switch (wdev->iftype) {
        case NL80211_IFTYPE_P2P_DEVICE:
-               if (!wdev->p2p_started)
-                       break;
-               rdev_stop_p2p_device(rdev, wdev);
-               wdev->p2p_started = false;
-               rdev->opencount--;
+               cfg80211_stop_p2p_device(rdev, wdev);
                break;
        default:
                WARN_ON_ONCE(1);
                break;
        }
+       mutex_unlock(&rdev->sched_scan_mtx);
        mutex_unlock(&rdev->devlist_mtx);
 }
 EXPORT_SYMBOL(cfg80211_unregister_wdev);
@@ -937,6 +964,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                cfg80211_update_iface_num(rdev, wdev->iftype, 1);
                cfg80211_lock_rdev(rdev);
                mutex_lock(&rdev->devlist_mtx);
+               mutex_lock(&rdev->sched_scan_mtx);
                wdev_lock(wdev);
                switch (wdev->iftype) {
 #ifdef CONFIG_CFG80211_WEXT
@@ -968,6 +996,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
                        break;
                }
                wdev_unlock(wdev);
+               mutex_unlock(&rdev->sched_scan_mtx);
                rdev->opencount++;
                mutex_unlock(&rdev->devlist_mtx);
                cfg80211_unlock_rdev(rdev);
index 3aec0e429d8adbf9d44c7fbc5bb7fa503e5b9818..5845c2b37aa832b444906ad4fb0e4e74f06c3ee3 100644 (file)
@@ -503,6 +503,9 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
 void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
                               enum nl80211_iftype iftype, int num);
 
+void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
+                             struct wireless_dev *wdev);
+
 #define CFG80211_MAX_NUM_DIFFERENT_CHANNELS 10
 
 #ifdef CONFIG_CFG80211_DEVELOPER_WARNINGS
index e652d05ff712714f597857b225b432aafea1c34c..58e13a8c95f90a7b880a9d65530799fc02451f1e 100644 (file)
@@ -557,18 +557,6 @@ static int nl80211_msg_put_channel(struct sk_buff *msg,
        if ((chan->flags & IEEE80211_CHAN_RADAR) &&
            nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
                goto nla_put_failure;
-       if ((chan->flags & IEEE80211_CHAN_NO_HT40MINUS) &&
-           nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_MINUS))
-               goto nla_put_failure;
-       if ((chan->flags & IEEE80211_CHAN_NO_HT40PLUS) &&
-           nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_HT40_PLUS))
-               goto nla_put_failure;
-       if ((chan->flags & IEEE80211_CHAN_NO_80MHZ) &&
-           nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_80MHZ))
-               goto nla_put_failure;
-       if ((chan->flags & IEEE80211_CHAN_NO_160MHZ) &&
-           nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_160MHZ))
-               goto nla_put_failure;
 
        if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_MAX_TX_POWER,
                        DBM_TO_MBM(chan->max_power)))
@@ -1310,15 +1298,6 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
                        dev->wiphy.max_acl_mac_addrs))
                goto nla_put_failure;
 
-       if (dev->wiphy.extended_capabilities &&
-           (nla_put(msg, NL80211_ATTR_EXT_CAPA,
-                    dev->wiphy.extended_capabilities_len,
-                    dev->wiphy.extended_capabilities) ||
-            nla_put(msg, NL80211_ATTR_EXT_CAPA_MASK,
-                    dev->wiphy.extended_capabilities_len,
-                    dev->wiphy.extended_capabilities_mask)))
-               goto nla_put_failure;
-
        return genlmsg_end(msg, hdr);
 
  nla_put_failure:
@@ -1328,7 +1307,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 portid, u32 seq, int flag
 
 static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
 {
-       int idx = 0;
+       int idx = 0, ret;
        int start = cb->args[0];
        struct cfg80211_registered_device *dev;
 
@@ -1338,9 +1317,29 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
                        continue;
                if (++idx <= start)
                        continue;
-               if (nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid,
-                                      cb->nlh->nlmsg_seq, NLM_F_MULTI,
-                                      dev) < 0) {
+               ret = nl80211_send_wiphy(skb, NETLINK_CB(cb->skb).portid,
+                                        cb->nlh->nlmsg_seq, NLM_F_MULTI,
+                                        dev);
+               if (ret < 0) {
+                       /*
+                        * If sending the wiphy data didn't fit (ENOBUFS or
+                        * EMSGSIZE returned), this SKB is still empty (so
+                        * it's not too big because another wiphy dataset is
+                        * already in the skb) and we've not tried to adjust
+                        * the dump allocation yet ... then adjust the alloc
+                        * size to be bigger, and return 1 but with the empty
+                        * skb. This results in an empty message being RX'ed
+                        * in userspace, but that is ignored.
+                        *
+                        * We can then retry with the larger buffer.
+                        */
+                       if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
+                           !skb->len &&
+                           cb->min_dump_alloc < 4096) {
+                               cb->min_dump_alloc = 4096;
+                               mutex_unlock(&cfg80211_mutex);
+                               return 1;
+                       }
                        idx--;
                        break;
                }
@@ -1357,7 +1356,7 @@ static int nl80211_get_wiphy(struct sk_buff *skb, struct genl_info *info)
        struct sk_buff *msg;
        struct cfg80211_registered_device *dev = info->user_ptr[0];
 
-       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
+       msg = nlmsg_new(4096, GFP_KERNEL);
        if (!msg)
                return -ENOMEM;
 
@@ -4703,14 +4702,19 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
        if (!rdev->ops->scan)
                return -EOPNOTSUPP;
 
-       if (rdev->scan_req)
-               return -EBUSY;
+       mutex_lock(&rdev->sched_scan_mtx);
+       if (rdev->scan_req) {
+               err = -EBUSY;
+               goto unlock;
+       }
 
        if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
                n_channels = validate_scan_freqs(
                                info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
-               if (!n_channels)
-                       return -EINVAL;
+               if (!n_channels) {
+                       err = -EINVAL;
+                       goto unlock;
+               }
        } else {
                enum ieee80211_band band;
                n_channels = 0;
@@ -4724,23 +4728,29 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
                        n_ssids++;
 
-       if (n_ssids > wiphy->max_scan_ssids)
-               return -EINVAL;
+       if (n_ssids > wiphy->max_scan_ssids) {
+               err = -EINVAL;
+               goto unlock;
+       }
 
        if (info->attrs[NL80211_ATTR_IE])
                ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
        else
                ie_len = 0;
 
-       if (ie_len > wiphy->max_scan_ie_len)
-               return -EINVAL;
+       if (ie_len > wiphy->max_scan_ie_len) {
+               err = -EINVAL;
+               goto unlock;
+       }
 
        request = kzalloc(sizeof(*request)
                        + sizeof(*request->ssids) * n_ssids
                        + sizeof(*request->channels) * n_channels
                        + ie_len, GFP_KERNEL);
-       if (!request)
-               return -ENOMEM;
+       if (!request) {
+               err = -ENOMEM;
+               goto unlock;
+       }
 
        if (n_ssids)
                request->ssids = (void *)&request->channels[n_channels];
@@ -4877,6 +4887,8 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
                kfree(request);
        }
 
+ unlock:
+       mutex_unlock(&rdev->sched_scan_mtx);
        return err;
 }
 
@@ -7750,20 +7762,9 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
        if (!rdev->ops->stop_p2p_device)
                return -EOPNOTSUPP;
 
-       if (!wdev->p2p_started)
-               return 0;
-
-       rdev_stop_p2p_device(rdev, wdev);
-       wdev->p2p_started = false;
-
-       mutex_lock(&rdev->devlist_mtx);
-       rdev->opencount--;
-       mutex_unlock(&rdev->devlist_mtx);
-
-       if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
-               rdev->scan_req->aborted = true;
-               ___cfg80211_scan_done(rdev, true);
-       }
+       mutex_lock(&rdev->sched_scan_mtx);
+       cfg80211_stop_p2p_device(rdev, wdev);
+       mutex_unlock(&rdev->sched_scan_mtx);
 
        return 0;
 }
@@ -8487,7 +8488,7 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
        struct nlattr *nest;
        int i;
 
-       ASSERT_RDEV_LOCK(rdev);
+       lockdep_assert_held(&rdev->sched_scan_mtx);
 
        if (WARN_ON(!req))
                return 0;
index 674aadca007982257b14b3c68abbafc39ee01461..fd99ea495b7e68cd9e5265542a6aa059d0ac7760 100644 (file)
@@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
        union iwreq_data wrqu;
 #endif
 
-       ASSERT_RDEV_LOCK(rdev);
+       lockdep_assert_held(&rdev->sched_scan_mtx);
 
        request = rdev->scan_req;
 
@@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
        rdev = container_of(wk, struct cfg80211_registered_device,
                            scan_done_wk);
 
-       cfg80211_lock_rdev(rdev);
+       mutex_lock(&rdev->sched_scan_mtx);
        ___cfg80211_scan_done(rdev, false);
-       cfg80211_unlock_rdev(rdev);
+       mutex_unlock(&rdev->sched_scan_mtx);
 }
 
 void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
@@ -698,11 +698,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
        found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR);
 
        if (found) {
-               found->pub.beacon_interval = tmp->pub.beacon_interval;
-               found->pub.signal = tmp->pub.signal;
-               found->pub.capability = tmp->pub.capability;
-               found->ts = tmp->ts;
-
                /* Update IEs */
                if (rcu_access_pointer(tmp->pub.proberesp_ies)) {
                        const struct cfg80211_bss_ies *old;
@@ -723,6 +718,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
 
                        if (found->pub.hidden_beacon_bss &&
                            !list_empty(&found->hidden_list)) {
+                               const struct cfg80211_bss_ies *f;
+
                                /*
                                 * The found BSS struct is one of the probe
                                 * response members of a group, but we're
@@ -732,6 +729,10 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
                                 * SSID to showing it, which is confusing so
                                 * drop this information.
                                 */
+
+                               f = rcu_access_pointer(tmp->pub.beacon_ies);
+                               kfree_rcu((struct cfg80211_bss_ies *)f,
+                                         rcu_head);
                                goto drop;
                        }
 
@@ -761,6 +762,11 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
                                kfree_rcu((struct cfg80211_bss_ies *)old,
                                          rcu_head);
                }
+
+               found->pub.beacon_interval = tmp->pub.beacon_interval;
+               found->pub.signal = tmp->pub.signal;
+               found->pub.capability = tmp->pub.capability;
+               found->ts = tmp->ts;
        } else {
                struct cfg80211_internal_bss *new;
                struct cfg80211_internal_bss *hidden;
@@ -1056,6 +1062,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
        if (IS_ERR(rdev))
                return PTR_ERR(rdev);
 
+       mutex_lock(&rdev->sched_scan_mtx);
        if (rdev->scan_req) {
                err = -EBUSY;
                goto out;
@@ -1162,6 +1169,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
                dev_hold(dev);
        }
  out:
+       mutex_unlock(&rdev->sched_scan_mtx);
        kfree(creq);
        cfg80211_unlock_rdev(rdev);
        return err;
index f432bd3755b19f0d865b1b2e9f2a132890f3b6a3..09d994d192ffa1c78b963933daad73e4240dfe4b 100644 (file)
@@ -85,6 +85,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
        ASSERT_RTNL();
        ASSERT_RDEV_LOCK(rdev);
        ASSERT_WDEV_LOCK(wdev);
+       lockdep_assert_held(&rdev->sched_scan_mtx);
 
        if (rdev->scan_req)
                return -EBUSY;
@@ -320,11 +321,9 @@ void cfg80211_sme_scan_done(struct net_device *dev)
 {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
 
-       mutex_lock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
        wdev_lock(wdev);
        __cfg80211_sme_scan_done(dev);
        wdev_unlock(wdev);
-       mutex_unlock(&wiphy_to_dev(wdev->wiphy)->devlist_mtx);
 }
 
 void cfg80211_sme_rx_auth(struct net_device *dev,
@@ -924,9 +923,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
        int err;
 
        mutex_lock(&rdev->devlist_mtx);
+       /* might request scan - scan_mtx -> wdev_mtx dependency */
+       mutex_lock(&rdev->sched_scan_mtx);
        wdev_lock(dev->ieee80211_ptr);
        err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
        wdev_unlock(dev->ieee80211_ptr);
+       mutex_unlock(&rdev->sched_scan_mtx);
        mutex_unlock(&rdev->devlist_mtx);
 
        return err;
index b7a531380e19d5bf879f2395eee1176a1abfac93..7586de77a2f8b57ebb9b832b76563ab66a59111a 100644 (file)
@@ -27,7 +27,8 @@
 #define WIPHY_PR_ARG   __entry->wiphy_name
 
 #define WDEV_ENTRY     __field(u32, id)
-#define WDEV_ASSIGN    (__entry->id) = (wdev ? wdev->identifier : 0)
+#define WDEV_ASSIGN    (__entry->id) = (!IS_ERR_OR_NULL(wdev)  \
+                                        ? wdev->identifier : 0)
 #define WDEV_PR_FMT    "wdev(%u)"
 #define WDEV_PR_ARG    (__entry->id)
 
@@ -1778,7 +1779,7 @@ TRACE_EVENT(rdev_set_mac_acl,
        ),
        TP_fast_assign(
                WIPHY_ASSIGN;
-               WIPHY_ASSIGN;
+               NETDEV_ASSIGN;
                __entry->acl_policy = params->acl_policy;
        ),
        TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", acl policy: %d",
index fb9622f6d99c4b6b6c87f8a8d8e2c88e4fb3705c..e79cb5c0655ad34ec0e8df85471e6c77ad856716 100644 (file)
@@ -89,6 +89,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
 
        cfg80211_lock_rdev(rdev);
        mutex_lock(&rdev->devlist_mtx);
+       mutex_lock(&rdev->sched_scan_mtx);
        wdev_lock(wdev);
 
        if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -135,6 +136,7 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
        err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
        wdev_unlock(wdev);
+       mutex_unlock(&rdev->sched_scan_mtx);
        mutex_unlock(&rdev->devlist_mtx);
        cfg80211_unlock_rdev(rdev);
        return err;
@@ -190,6 +192,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
 
        cfg80211_lock_rdev(rdev);
        mutex_lock(&rdev->devlist_mtx);
+       mutex_lock(&rdev->sched_scan_mtx);
        wdev_lock(wdev);
 
        err = 0;
@@ -223,6 +226,7 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
        err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
        wdev_unlock(wdev);
+       mutex_unlock(&rdev->sched_scan_mtx);
        mutex_unlock(&rdev->devlist_mtx);
        cfg80211_unlock_rdev(rdev);
        return err;
@@ -285,6 +289,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
 
        cfg80211_lock_rdev(rdev);
        mutex_lock(&rdev->devlist_mtx);
+       mutex_lock(&rdev->sched_scan_mtx);
        wdev_lock(wdev);
 
        if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -313,6 +318,7 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
        err = cfg80211_mgd_wext_connect(rdev, wdev);
  out:
        wdev_unlock(wdev);
+       mutex_unlock(&rdev->sched_scan_mtx);
        mutex_unlock(&rdev->devlist_mtx);
        cfg80211_unlock_rdev(rdev);
        return err;
index 35754cc8a9e5b9c51cdaf52693128ee2098718f7..8dafe6d3c6e41ebd20e5d0347d4ab9b0e6326a34 100644 (file)
@@ -334,6 +334,70 @@ static void xfrm_replay_notify_bmp(struct xfrm_state *x, int event)
                x->xflags &= ~XFRM_TIME_DEFER;
 }
 
+static void xfrm_replay_notify_esn(struct xfrm_state *x, int event)
+{
+       u32 seq_diff, oseq_diff;
+       struct km_event c;
+       struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
+       struct xfrm_replay_state_esn *preplay_esn = x->preplay_esn;
+
+       /* we send notify messages in case
+        *  1. we updated on of the sequence numbers, and the seqno difference
+        *     is at least x->replay_maxdiff, in this case we also update the
+        *     timeout of our timer function
+        *  2. if x->replay_maxage has elapsed since last update,
+        *     and there were changes
+        *
+        *  The state structure must be locked!
+        */
+
+       switch (event) {
+       case XFRM_REPLAY_UPDATE:
+               if (!x->replay_maxdiff)
+                       break;
+
+               if (replay_esn->seq_hi == preplay_esn->seq_hi)
+                       seq_diff = replay_esn->seq - preplay_esn->seq;
+               else
+                       seq_diff = ~preplay_esn->seq + replay_esn->seq + 1;
+
+               if (replay_esn->oseq_hi == preplay_esn->oseq_hi)
+                       oseq_diff = replay_esn->oseq - preplay_esn->oseq;
+               else
+                       oseq_diff = ~preplay_esn->oseq + replay_esn->oseq + 1;
+
+               if (seq_diff < x->replay_maxdiff &&
+                   oseq_diff < x->replay_maxdiff) {
+
+                       if (x->xflags & XFRM_TIME_DEFER)
+                               event = XFRM_REPLAY_TIMEOUT;
+                       else
+                               return;
+               }
+
+               break;
+
+       case XFRM_REPLAY_TIMEOUT:
+               if (memcmp(x->replay_esn, x->preplay_esn,
+                          xfrm_replay_state_esn_len(replay_esn)) == 0) {
+                       x->xflags |= XFRM_TIME_DEFER;
+                       return;
+               }
+
+               break;
+       }
+
+       memcpy(x->preplay_esn, x->replay_esn,
+              xfrm_replay_state_esn_len(replay_esn));
+       c.event = XFRM_MSG_NEWAE;
+       c.data.aevent = event;
+       km_state_notify(x, &c);
+
+       if (x->replay_maxage &&
+           !mod_timer(&x->rtimer, jiffies + x->replay_maxage))
+               x->xflags &= ~XFRM_TIME_DEFER;
+}
+
 static int xfrm_replay_overflow_esn(struct xfrm_state *x, struct sk_buff *skb)
 {
        int err = 0;
@@ -510,7 +574,7 @@ static struct xfrm_replay xfrm_replay_esn = {
        .advance        = xfrm_replay_advance_esn,
        .check          = xfrm_replay_check_esn,
        .recheck        = xfrm_replay_recheck_esn,
-       .notify         = xfrm_replay_notify_bmp,
+       .notify         = xfrm_replay_notify_esn,
        .overflow       = xfrm_replay_overflow_esn,
 };
 
index 25f216a841d5fcd734c4b234541aed998b561852..477d137c0557b8b70571d9e6e0873e2af221d53b 100644 (file)
@@ -14,7 +14,7 @@ kbuild-file := $(srctree)/$(obj)/Kbuild
 include $(kbuild-file)
 
 # called may set destination dir (when installing to asm/)
-_dst := $(or $(destination-y),$(dst),$(obj))
+_dst := $(if $(destination-y),$(destination-y),$(if $(dst),$(dst),$(obj)))
 
 old-kbuild-file := $(srctree)/$(subst uapi/,,$(obj))/Kbuild
 ifneq ($(wildcard $(old-kbuild-file)),)
@@ -48,13 +48,14 @@ all-files     := $(header-y) $(genhdr-y) $(wrapper-files)
 output-files  := $(addprefix $(installdir)/, $(all-files))
 
 input-files   := $(foreach hdr, $(header-y), \
-                  $(or \
+                  $(if $(wildcard $(srcdir)/$(hdr)), \
                        $(wildcard $(srcdir)/$(hdr)), \
-                       $(wildcard $(oldsrcdir)/$(hdr)), \
-                       $(error Missing UAPI file $(srcdir)/$(hdr)) \
+                       $(if $(wildcard $(oldsrcdir)/$(hdr)), \
+                               $(wildcard $(oldsrcdir)/$(hdr)), \
+                               $(error Missing UAPI file $(srcdir)/$(hdr))) \
                   )) \
                 $(foreach hdr, $(genhdr-y), \
-                  $(or \
+                  $(if $(wildcard $(gendir)/$(hdr)), \
                        $(wildcard $(gendir)/$(hdr)), \
                        $(error Missing generated UAPI file $(gendir)/$(hdr)) \
                   ))
index 1c261763f4799180432f2162a096579007243203..d65fa7fa29ba1a53b1ef4fb6d76c7aeafb7da65a 100644 (file)
@@ -40,12 +40,12 @@ static long compat_keyctl_instantiate_key_iov(
                                           ARRAY_SIZE(iovstack),
                                           iovstack, &iov);
        if (ret < 0)
-               return ret;
+               goto err;
        if (ret == 0)
                goto no_payload_free;
 
        ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid);
-
+err:
        if (iov != iovstack)
                kfree(iov);
        return ret;
index a571fad91010156aa7c532836b2a612e8e82e6fd..42defae1e161632e93b13b8194af1a30a09f2492 100644 (file)
@@ -57,7 +57,7 @@ int install_user_keyrings(void)
 
        kenter("%p{%u}", user, uid);
 
-       if (user->uid_keyring) {
+       if (user->uid_keyring && user->session_keyring) {
                kleave(" = 0 [exist]");
                return 0;
        }
index 48665ecd119715359cc4ffa624afee5c4332dd57..8ab2951545170e6e81fb71fc7ee1e8cad5c2dd72 100644 (file)
@@ -310,7 +310,7 @@ int selinux_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx,
 
        if (old_ctx) {
                new_ctx = kmalloc(sizeof(*old_ctx) + old_ctx->ctx_len,
-                                 GFP_KERNEL);
+                                 GFP_ATOMIC);
                if (!new_ctx)
                        return -ENOMEM;
 
index 23414b93771f30ec82ccf76b6cfb49fbed27edef..13c88fbcf0371cc32340791e335eeb0b4758f875 100644 (file)
@@ -347,10 +347,8 @@ int yama_ptrace_traceme(struct task_struct *parent)
        /* Only disallow PTRACE_TRACEME on more aggressive settings. */
        switch (ptrace_scope) {
        case YAMA_SCOPE_CAPABILITY:
-               rcu_read_lock();
-               if (!ns_capable(__task_cred(parent)->user_ns, CAP_SYS_PTRACE))
+               if (!has_ns_capability(parent, current_user_ns(), CAP_SYS_PTRACE))
                        rc = -EPERM;
-               rcu_read_unlock();
                break;
        case YAMA_SCOPE_NO_ATTACH:
                rc = -EPERM;
index 160b1bd0cd62262931896573953e990736e4da52..24d44b2f61acda72453e5be78958aae15b8afccf 100644 (file)
@@ -290,10 +290,10 @@ int snd_seq_timer_open(struct snd_seq_queue *q)
                        tid.device = SNDRV_TIMER_GLOBAL_SYSTEM;
                        err = snd_timer_open(&t, str, &tid, q->queue);
                }
-               if (err < 0) {
-                       snd_printk(KERN_ERR "seq fatal error: cannot create timer (%i)\n", err);
-                       return err;
-               }
+       }
+       if (err < 0) {
+               snd_printk(KERN_ERR "seq fatal error: cannot create timer (%i)\n", err);
+               return err;
        }
        t->callback = snd_seq_timer_interrupt;
        t->callback_data = q;
index 30bcfe470f8310fa7fa72cc1ddcf7ab4ba6a794c..4ff60a6427d9d8d3ea7cf095bc2766f2d49955fc 100644 (file)
@@ -545,6 +545,9 @@ static void seq_chn_common_event(unsigned char *event_rec)
                case MIDI_PGM_CHANGE:
                        if (seq_mode == SEQ_2)
                        {
+                               if (chn > 15)
+                                       break;
+
                                synth_devs[dev]->chn_info[chn].pgm_num = p1;
                                if ((int) dev >= num_synths)
                                        synth_devs[dev]->set_instr(dev, chn, p1);
@@ -596,6 +599,9 @@ static void seq_chn_common_event(unsigned char *event_rec)
                case MIDI_PITCH_BEND:
                        if (seq_mode == SEQ_2)
                        {
+                               if (chn > 15)
+                                       break;
+
                                synth_devs[dev]->chn_info[chn].bender_value = w14;
 
                                if ((int) dev < num_synths)
index 3536b076b529ab8c25edf1292a62e713e841b800..0aabfedeecbae241b6ab4e182713a3d2e85b82e8 100644 (file)
@@ -2549,7 +2549,7 @@ static int snd_asihpi_sampleclock_add(struct snd_card_asihpi *asihpi,
 
 static int snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
 {
-       struct snd_card *card = asihpi->card;
+       struct snd_card *card;
        unsigned int idx = 0;
        unsigned int subindex = 0;
        int err;
@@ -2557,6 +2557,7 @@ static int snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
 
        if (snd_BUG_ON(!asihpi))
                return -EINVAL;
+       card = asihpi->card;
        strcpy(card->mixername, "Asihpi Mixer");
 
        err =
index 97c68dd24ef5dfed33d340730371e4a40e34347d..4aba7646dd9c4999dafa488c7482ee4c65740167 100644 (file)
@@ -173,7 +173,7 @@ const char *snd_hda_get_jack_type(u32 cfg)
                "Line Out", "Speaker", "HP Out", "CD",
                "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
                "Line In", "Aux", "Mic", "Telephony",
-               "SPDIF In", "Digitial In", "Reserved", "Other"
+               "SPDIF In", "Digital In", "Reserved", "Other"
        };
 
        return jack_types[(cfg & AC_DEFCFG_DEVICE)
@@ -494,7 +494,7 @@ static unsigned int get_num_conns(struct hda_codec *codec, hda_nid_t nid)
 
 int snd_hda_get_num_raw_conns(struct hda_codec *codec, hda_nid_t nid)
 {
-       return get_num_conns(codec, nid) & AC_CLIST_LENGTH;
+       return snd_hda_get_raw_connections(codec, nid, NULL, 0);
 }
 
 /**
@@ -517,9 +517,6 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
        hda_nid_t prev_nid;
        int null_count = 0;
 
-       if (snd_BUG_ON(!conn_list || max_conns <= 0))
-               return -EINVAL;
-
        parm = get_num_conns(codec, nid);
        if (!parm)
                return 0;
@@ -545,7 +542,8 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
                                          AC_VERB_GET_CONNECT_LIST, 0);
                if (parm == -1 && codec->bus->rirb_error)
                        return -EIO;
-               conn_list[0] = parm & mask;
+               if (conn_list)
+                       conn_list[0] = parm & mask;
                return 1;
        }
 
@@ -580,14 +578,20 @@ int snd_hda_get_raw_connections(struct hda_codec *codec, hda_nid_t nid,
                                continue;
                        }
                        for (n = prev_nid + 1; n <= val; n++) {
+                               if (conn_list) {
+                                       if (conns >= max_conns)
+                                               return -ENOSPC;
+                                       conn_list[conns] = n;
+                               }
+                               conns++;
+                       }
+               } else {
+                       if (conn_list) {
                                if (conns >= max_conns)
                                        return -ENOSPC;
-                               conn_list[conns++] = n;
+                               conn_list[conns] = val;
                        }
-               } else {
-                       if (conns >= max_conns)
-                               return -ENOSPC;
-                       conn_list[conns++] = val;
+                       conns++;
                }
                prev_nid = val;
        }
@@ -3140,7 +3144,7 @@ static unsigned int convert_to_spdif_status(unsigned short val)
        if (val & AC_DIG1_PROFESSIONAL)
                sbits |= IEC958_AES0_PROFESSIONAL;
        if (sbits & IEC958_AES0_PROFESSIONAL) {
-               if (sbits & AC_DIG1_EMPHASIS)
+               if (val & AC_DIG1_EMPHASIS)
                        sbits |= IEC958_AES0_PRO_EMPHASIS_5015;
        } else {
                if (val & AC_DIG1_EMPHASIS)
index 7dd846380a5015bffdfe628182ba1d22168362c1..d0d7ac1e99d24cc606b441e6ec23470a75800dcd 100644 (file)
@@ -320,7 +320,7 @@ int snd_hdmi_get_eld(struct hda_codec *codec, hda_nid_t nid,
                     unsigned char *buf, int *eld_size)
 {
        int i;
-       int ret;
+       int ret = 0;
        int size;
 
        /*
index 78897d05d80f281d9bc8427a09a4da426f90dbe4..2dbe767be16bba7e84a3f3219ea1e9e98f52ef84 100644 (file)
@@ -740,7 +740,7 @@ EXPORT_SYMBOL_HDA(snd_hda_activate_path);
 static void path_power_down_sync(struct hda_codec *codec, struct nid_path *path)
 {
        struct hda_gen_spec *spec = codec->spec;
-       bool changed;
+       bool changed = false;
        int i;
 
        if (!spec->power_down_unused || path->active)
@@ -995,6 +995,8 @@ enum {
        BAD_NO_EXTRA_SURR_DAC = 0x101,
        /* Primary DAC shared with main surrounds */
        BAD_SHARED_SURROUND = 0x100,
+       /* No independent HP possible */
+       BAD_NO_INDEP_HP = 0x40,
        /* Primary DAC shared with main CLFE */
        BAD_SHARED_CLFE = 0x10,
        /* Primary DAC shared with extra surrounds */
@@ -1392,6 +1394,43 @@ static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
        return snd_hda_get_path_idx(codec, path);
 }
 
+/* check whether the independent HP is available with the current config */
+static bool indep_hp_possible(struct hda_codec *codec)
+{
+       struct hda_gen_spec *spec = codec->spec;
+       struct auto_pin_cfg *cfg = &spec->autocfg;
+       struct nid_path *path;
+       int i, idx;
+
+       if (cfg->line_out_type == AUTO_PIN_HP_OUT)
+               idx = spec->out_paths[0];
+       else
+               idx = spec->hp_paths[0];
+       path = snd_hda_get_path_from_idx(codec, idx);
+       if (!path)
+               return false;
+
+       /* assume no path conflicts unless aamix is involved */
+       if (!spec->mixer_nid || !is_nid_contained(path, spec->mixer_nid))
+               return true;
+
+       /* check whether output paths contain aamix */
+       for (i = 0; i < cfg->line_outs; i++) {
+               if (spec->out_paths[i] == idx)
+                       break;
+               path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]);
+               if (path && is_nid_contained(path, spec->mixer_nid))
+                       return false;
+       }
+       for (i = 0; i < cfg->speaker_outs; i++) {
+               path = snd_hda_get_path_from_idx(codec, spec->speaker_paths[i]);
+               if (path && is_nid_contained(path, spec->mixer_nid))
+                       return false;
+       }
+
+       return true;
+}
+
 /* fill the empty entries in the dac array for speaker/hp with the
  * shared dac pointed by the paths
  */
@@ -1545,6 +1584,9 @@ static int fill_and_eval_dacs(struct hda_codec *codec,
                badness += BAD_MULTI_IO;
        }
 
+       if (spec->indep_hp && !indep_hp_possible(codec))
+               badness += BAD_NO_INDEP_HP;
+
        /* re-fill the shared DAC for speaker / headphone */
        if (cfg->line_out_type != AUTO_PIN_HP_OUT)
                refill_shared_dacs(codec, cfg->hp_outs,
@@ -1758,6 +1800,10 @@ static int parse_output_paths(struct hda_codec *codec)
                                cfg->speaker_pins, val);
        }
 
+       /* clear indep_hp flag if not available */
+       if (spec->indep_hp && !indep_hp_possible(codec))
+               spec->indep_hp = 0;
+
        kfree(best_cfg);
        return 0;
 }
index 4cea6bb6fade09c1dfcfadd0ecd2cdab798a134a..bcd40ee488e35c85c880bc3d6764a2c7318cc5c2 100644 (file)
@@ -134,8 +134,8 @@ MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
  * this may give more power-saving, but will take longer time to
  * wake up.
  */
-static int power_save_controller = -1;
-module_param(power_save_controller, bint, 0644);
+static bool power_save_controller = 1;
+module_param(power_save_controller, bool, 0644);
 MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode.");
 #endif /* CONFIG_PM */
 
@@ -415,6 +415,8 @@ struct azx_dev {
        unsigned int opened :1;
        unsigned int running :1;
        unsigned int irq_pending :1;
+       unsigned int prepared:1;
+       unsigned int locked:1;
        /*
         * For VIA:
         *  A flag to ensure DMA position is 0
@@ -426,8 +428,25 @@ struct azx_dev {
 
        struct timecounter  azx_tc;
        struct cyclecounter azx_cc;
+
+#ifdef CONFIG_SND_HDA_DSP_LOADER
+       struct mutex dsp_mutex;
+#endif
 };
 
+/* DSP lock helpers */
+#ifdef CONFIG_SND_HDA_DSP_LOADER
+#define dsp_lock_init(dev)     mutex_init(&(dev)->dsp_mutex)
+#define dsp_lock(dev)          mutex_lock(&(dev)->dsp_mutex)
+#define dsp_unlock(dev)                mutex_unlock(&(dev)->dsp_mutex)
+#define dsp_is_locked(dev)     ((dev)->locked)
+#else
+#define dsp_lock_init(dev)     do {} while (0)
+#define dsp_lock(dev)          do {} while (0)
+#define dsp_unlock(dev)                do {} while (0)
+#define dsp_is_locked(dev)     0
+#endif
+
 /* CORB/RIRB */
 struct azx_rb {
        u32 *buf;               /* CORB/RIRB buffer
@@ -527,6 +546,10 @@ struct azx {
 
        /* card list (for power_save trigger) */
        struct list_head list;
+
+#ifdef CONFIG_SND_HDA_DSP_LOADER
+       struct azx_dev saved_azx_dev;
+#endif
 };
 
 #define CREATE_TRACE_POINTS
@@ -1793,15 +1816,25 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream)
                dev = chip->capture_index_offset;
                nums = chip->capture_streams;
        }
-       for (i = 0; i < nums; i++, dev++)
-               if (!chip->azx_dev[dev].opened) {
-                       res = &chip->azx_dev[dev];
-                       if (res->assigned_key == key)
-                               break;
+       for (i = 0; i < nums; i++, dev++) {
+               struct azx_dev *azx_dev = &chip->azx_dev[dev];
+               dsp_lock(azx_dev);
+               if (!azx_dev->opened && !dsp_is_locked(azx_dev)) {
+                       res = azx_dev;
+                       if (res->assigned_key == key) {
+                               res->opened = 1;
+                               res->assigned_key = key;
+                               dsp_unlock(azx_dev);
+                               return azx_dev;
+                       }
                }
+               dsp_unlock(azx_dev);
+       }
        if (res) {
+               dsp_lock(res);
                res->opened = 1;
                res->assigned_key = key;
+               dsp_unlock(res);
        }
        return res;
 }
@@ -2009,6 +2042,12 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
        struct azx_dev *azx_dev = get_azx_dev(substream);
        int ret;
 
+       dsp_lock(azx_dev);
+       if (dsp_is_locked(azx_dev)) {
+               ret = -EBUSY;
+               goto unlock;
+       }
+
        mark_runtime_wc(chip, azx_dev, substream, false);
        azx_dev->bufsize = 0;
        azx_dev->period_bytes = 0;
@@ -2016,8 +2055,10 @@ static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
        ret = snd_pcm_lib_malloc_pages(substream,
                                        params_buffer_bytes(hw_params));
        if (ret < 0)
-               return ret;
+               goto unlock;
        mark_runtime_wc(chip, azx_dev, substream, true);
+ unlock:
+       dsp_unlock(azx_dev);
        return ret;
 }
 
@@ -2029,16 +2070,21 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
        struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
 
        /* reset BDL address */
-       azx_sd_writel(azx_dev, SD_BDLPL, 0);
-       azx_sd_writel(azx_dev, SD_BDLPU, 0);
-       azx_sd_writel(azx_dev, SD_CTL, 0);
-       azx_dev->bufsize = 0;
-       azx_dev->period_bytes = 0;
-       azx_dev->format_val = 0;
+       dsp_lock(azx_dev);
+       if (!dsp_is_locked(azx_dev)) {
+               azx_sd_writel(azx_dev, SD_BDLPL, 0);
+               azx_sd_writel(azx_dev, SD_BDLPU, 0);
+               azx_sd_writel(azx_dev, SD_CTL, 0);
+               azx_dev->bufsize = 0;
+               azx_dev->period_bytes = 0;
+               azx_dev->format_val = 0;
+       }
 
        snd_hda_codec_cleanup(apcm->codec, hinfo, substream);
 
        mark_runtime_wc(chip, azx_dev, substream, false);
+       azx_dev->prepared = 0;
+       dsp_unlock(azx_dev);
        return snd_pcm_lib_free_pages(substream);
 }
 
@@ -2055,6 +2101,12 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
                snd_hda_spdif_out_of_nid(apcm->codec, hinfo->nid);
        unsigned short ctls = spdif ? spdif->ctls : 0;
 
+       dsp_lock(azx_dev);
+       if (dsp_is_locked(azx_dev)) {
+               err = -EBUSY;
+               goto unlock;
+       }
+
        azx_stream_reset(chip, azx_dev);
        format_val = snd_hda_calc_stream_format(runtime->rate,
                                                runtime->channels,
@@ -2065,7 +2117,8 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
                snd_printk(KERN_ERR SFX
                           "%s: invalid format_val, rate=%d, ch=%d, format=%d\n",
                           pci_name(chip->pci), runtime->rate, runtime->channels, runtime->format);
-               return -EINVAL;
+               err = -EINVAL;
+               goto unlock;
        }
 
        bufsize = snd_pcm_lib_buffer_bytes(substream);
@@ -2084,7 +2137,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
                azx_dev->no_period_wakeup = runtime->no_period_wakeup;
                err = azx_setup_periods(chip, substream, azx_dev);
                if (err < 0)
-                       return err;
+                       goto unlock;
        }
 
        /* wallclk has 24Mhz clock source */
@@ -2101,8 +2154,14 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream)
        if ((chip->driver_caps & AZX_DCAPS_CTX_WORKAROUND) &&
            stream_tag > chip->capture_streams)
                stream_tag -= chip->capture_streams;
-       return snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag,
+       err = snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag,
                                     azx_dev->format_val, substream);
+
+ unlock:
+       if (!err)
+               azx_dev->prepared = 1;
+       dsp_unlock(azx_dev);
+       return err;
 }
 
 static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
@@ -2117,6 +2176,9 @@ static int azx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
        azx_dev = get_azx_dev(substream);
        trace_azx_pcm_trigger(chip, azx_dev, cmd);
 
+       if (dsp_is_locked(azx_dev) || !azx_dev->prepared)
+               return -EPIPE;
+
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
                rstart = 1;
@@ -2621,17 +2683,27 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
        struct azx_dev *azx_dev;
        int err;
 
-       if (snd_hda_lock_devices(bus))
-               return -EBUSY;
+       azx_dev = azx_get_dsp_loader_dev(chip);
+
+       dsp_lock(azx_dev);
+       spin_lock_irq(&chip->reg_lock);
+       if (azx_dev->running || azx_dev->locked) {
+               spin_unlock_irq(&chip->reg_lock);
+               err = -EBUSY;
+               goto unlock;
+       }
+       azx_dev->prepared = 0;
+       chip->saved_azx_dev = *azx_dev;
+       azx_dev->locked = 1;
+       spin_unlock_irq(&chip->reg_lock);
 
        err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV_SG,
                                  snd_dma_pci_data(chip->pci),
                                  byte_size, bufp);
        if (err < 0)
-               goto unlock;
+               goto err_alloc;
 
        mark_pages_wc(chip, bufp, true);
-       azx_dev = azx_get_dsp_loader_dev(chip);
        azx_dev->bufsize = byte_size;
        azx_dev->period_bytes = byte_size;
        azx_dev->format_val = format;
@@ -2649,13 +2721,20 @@ static int azx_load_dsp_prepare(struct hda_bus *bus, unsigned int format,
                goto error;
 
        azx_setup_controller(chip, azx_dev);
+       dsp_unlock(azx_dev);
        return azx_dev->stream_tag;
 
  error:
        mark_pages_wc(chip, bufp, false);
        snd_dma_free_pages(bufp);
-unlock:
-       snd_hda_unlock_devices(bus);
+ err_alloc:
+       spin_lock_irq(&chip->reg_lock);
+       if (azx_dev->opened)
+               *azx_dev = chip->saved_azx_dev;
+       azx_dev->locked = 0;
+       spin_unlock_irq(&chip->reg_lock);
+ unlock:
+       dsp_unlock(azx_dev);
        return err;
 }
 
@@ -2677,9 +2756,10 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus,
        struct azx *chip = bus->private_data;
        struct azx_dev *azx_dev = azx_get_dsp_loader_dev(chip);
 
-       if (!dmab->area)
+       if (!dmab->area || !azx_dev->locked)
                return;
 
+       dsp_lock(azx_dev);
        /* reset BDL address */
        azx_sd_writel(azx_dev, SD_BDLPL, 0);
        azx_sd_writel(azx_dev, SD_BDLPU, 0);
@@ -2692,7 +2772,12 @@ static void azx_load_dsp_cleanup(struct hda_bus *bus,
        snd_dma_free_pages(dmab);
        dmab->area = NULL;
 
-       snd_hda_unlock_devices(bus);
+       spin_lock_irq(&chip->reg_lock);
+       if (azx_dev->opened)
+               *azx_dev = chip->saved_azx_dev;
+       azx_dev->locked = 0;
+       spin_unlock_irq(&chip->reg_lock);
+       dsp_unlock(azx_dev);
 }
 #endif /* CONFIG_SND_HDA_DSP_LOADER */
 
@@ -2846,8 +2931,6 @@ static int azx_runtime_idle(struct device *dev)
        struct snd_card *card = dev_get_drvdata(dev);
        struct azx *chip = card->private_data;
 
-       if (power_save_controller > 0)
-               return 0;
        if (!power_save_controller ||
            !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME))
                return -EBUSY;
@@ -3481,6 +3564,7 @@ static int azx_first_init(struct azx *chip)
        }
 
        for (i = 0; i < chip->num_streams; i++) {
+               dsp_lock_init(&chip->azx_dev[i]);
                /* allocate memory for the BDL for each stream */
                err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
                                          snd_dma_pci_data(chip->pci),
index eefc4563b2f946c440df969d063a403e09c37dc0..0792b5725f9c5e501886556ce68f1c383aef1460 100644 (file)
@@ -3239,7 +3239,7 @@ static int ca0132_set_vipsource(struct hda_codec *codec, int val)
        struct ca0132_spec *spec = codec->spec;
        unsigned int tmp;
 
-       if (!dspload_is_loaded(codec))
+       if (spec->dsp_state != DSP_DOWNLOADED)
                return 0;
 
        /* if CrystalVoice if off, vipsource should be 0 */
@@ -4267,11 +4267,12 @@ static void ca0132_refresh_widget_caps(struct hda_codec *codec)
  */
 static void ca0132_setup_defaults(struct hda_codec *codec)
 {
+       struct ca0132_spec *spec = codec->spec;
        unsigned int tmp;
        int num_fx;
        int idx, i;
 
-       if (!dspload_is_loaded(codec))
+       if (spec->dsp_state != DSP_DOWNLOADED)
                return;
 
        /* out, in effects + voicefx */
@@ -4351,12 +4352,16 @@ static bool ca0132_download_dsp_images(struct hda_codec *codec)
                return false;
 
        dsp_os_image = (struct dsp_image_seg *)(fw_entry->data);
-       dspload_image(codec, dsp_os_image, 0, 0, true, 0);
+       if (dspload_image(codec, dsp_os_image, 0, 0, true, 0)) {
+               pr_err("ca0132 dspload_image failed.\n");
+               goto exit_download;
+       }
+
        dsp_loaded = dspload_wait_loaded(codec);
 
+exit_download:
        release_firmware(fw_entry);
 
-
        return dsp_loaded;
 }
 
@@ -4367,16 +4372,13 @@ static void ca0132_download_dsp(struct hda_codec *codec)
 #ifndef CONFIG_SND_HDA_CODEC_CA0132_DSP
        return; /* NOP */
 #endif
-       spec->dsp_state = DSP_DOWNLOAD_INIT;
 
-       if (spec->dsp_state == DSP_DOWNLOAD_INIT) {
-               chipio_enable_clocks(codec);
-               spec->dsp_state = DSP_DOWNLOADING;
-               if (!ca0132_download_dsp_images(codec))
-                       spec->dsp_state = DSP_DOWNLOAD_FAILED;
-               else
-                       spec->dsp_state = DSP_DOWNLOADED;
-       }
+       chipio_enable_clocks(codec);
+       spec->dsp_state = DSP_DOWNLOADING;
+       if (!ca0132_download_dsp_images(codec))
+               spec->dsp_state = DSP_DOWNLOAD_FAILED;
+       else
+               spec->dsp_state = DSP_DOWNLOADED;
 
        if (spec->dsp_state == DSP_DOWNLOADED)
                ca0132_set_dsp_msr(codec, true);
index 72ebb8a36b135938593db795d255b27479a5231f..0d9c58f135606f8d422d5422d1742e76cf7f6572 100644 (file)
@@ -168,10 +168,10 @@ static void cs_automute(struct hda_codec *codec)
        snd_hda_gen_update_outputs(codec);
 
        if (spec->gpio_eapd_hp) {
-               unsigned int gpio = spec->gen.hp_jack_present ?
+               spec->gpio_data = spec->gen.hp_jack_present ?
                        spec->gpio_eapd_hp : spec->gpio_eapd_speaker;
                snd_hda_codec_write(codec, 0x01, 0,
-                                   AC_VERB_SET_GPIO_DATA, gpio);
+                                   AC_VERB_SET_GPIO_DATA, spec->gpio_data);
        }
 }
 
@@ -506,6 +506,8 @@ static int patch_cs420x(struct hda_codec *codec)
        if (!spec)
                return -ENOMEM;
 
+       spec->gen.automute_hook = cs_automute;
+
        snd_hda_pick_fixup(codec, cs420x_models, cs420x_fixup_tbl,
                           cs420x_fixups);
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
@@ -893,6 +895,8 @@ static int patch_cs4210(struct hda_codec *codec)
        if (!spec)
                return -ENOMEM;
 
+       spec->gen.automute_hook = cs_automute;
+
        snd_hda_pick_fixup(codec, cs421x_models, cs421x_fixup_tbl,
                           cs421x_fixups);
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
index 941bf6c766ecf5f6ff2aa35e28e33563066c58ef..2a89d1eefeb6059623a985fea7cdb464dc4c7390 100644 (file)
@@ -1142,7 +1142,7 @@ static int patch_cxt5045(struct hda_codec *codec)
        }
 
        if (spec->beep_amp)
-               snd_hda_attach_beep_device(codec, spec->beep_amp);
+               snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
 
        return 0;
 }
@@ -1921,7 +1921,7 @@ static int patch_cxt5051(struct hda_codec *codec)
        }
 
        if (spec->beep_amp)
-               snd_hda_attach_beep_device(codec, spec->beep_amp);
+               snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
 
        return 0;
 }
@@ -3099,7 +3099,7 @@ static int patch_cxt5066(struct hda_codec *codec)
        }
 
        if (spec->beep_amp)
-               snd_hda_attach_beep_device(codec, spec->beep_amp);
+               snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
 
        return 0;
 }
@@ -3191,11 +3191,17 @@ static int cx_auto_build_controls(struct hda_codec *codec)
        return 0;
 }
 
+static void cx_auto_free(struct hda_codec *codec)
+{
+       snd_hda_detach_beep_device(codec);
+       snd_hda_gen_free(codec);
+}
+
 static const struct hda_codec_ops cx_auto_patch_ops = {
        .build_controls = cx_auto_build_controls,
        .build_pcms = snd_hda_gen_build_pcms,
        .init = snd_hda_gen_init,
-       .free = snd_hda_gen_free,
+       .free = cx_auto_free,
        .unsol_event = snd_hda_jack_unsol_event,
 #ifdef CONFIG_PM
        .check_power_status = snd_hda_gen_check_power_status,
@@ -3391,7 +3397,7 @@ static int patch_conexant_auto(struct hda_codec *codec)
 
        codec->patch_ops = cx_auto_patch_ops;
        if (spec->beep_amp)
-               snd_hda_attach_beep_device(codec, spec->beep_amp);
+               snd_hda_attach_beep_device(codec, get_amp_nid_(spec->beep_amp));
 
        /* Some laptops with Conexant chips show stalls in S3 resume,
         * which falls into the single-cmd mode.
index 78e1827d0a956cd2ce9eaeb7fcc92d1f7ab3f6b2..de8ac5c07fd06628f971aed091b1668a697233d1 100644 (file)
@@ -1196,7 +1196,7 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
 
        _snd_printd(SND_PR_VERBOSE,
                "HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
-               codec->addr, pin_nid, eld->monitor_present, eld->eld_valid);
+               codec->addr, pin_nid, pin_eld->monitor_present, eld->eld_valid);
 
        if (eld->eld_valid) {
                if (snd_hdmi_get_eld(codec, pin_nid, eld->eld_buffer,
index 563c24df4d6f03f393def96afcd8340ee4538180..f15c36bde5403478513c5880e7ae65a9e1a42fe7 100644 (file)
@@ -3440,7 +3440,8 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
        const hda_nid_t *ssids;
 
        if (codec->vendor_id == 0x10ec0272 || codec->vendor_id == 0x10ec0663 ||
-           codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670)
+           codec->vendor_id == 0x10ec0665 || codec->vendor_id == 0x10ec0670 ||
+           codec->vendor_id == 0x10ec0671)
                ssids = alc663_ssids;
        else
                ssids = alc662_ssids;
@@ -3894,6 +3895,7 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
        { .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
        { .id = 0x10ec0668, .name = "ALC668", .patch = patch_alc662 },
        { .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
+       { .id = 0x10ec0671, .name = "ALC671", .patch = patch_alc662 },
        { .id = 0x10ec0680, .name = "ALC680", .patch = patch_alc680 },
        { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
        { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
index 83d5335ac348ee2c3b7a3f7e243f7d5ad8096045..dafe04ae8c72b6ba711d7f8dce4ac7878552b883 100644 (file)
@@ -815,6 +815,29 @@ static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity)
        return 0;
 }
 
+/* check whether a built-in speaker is included in parsed pins */
+static bool has_builtin_speaker(struct hda_codec *codec)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       hda_nid_t *nid_pin;
+       int nids, i;
+
+       if (spec->gen.autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) {
+               nid_pin = spec->gen.autocfg.line_out_pins;
+               nids = spec->gen.autocfg.line_outs;
+       } else {
+               nid_pin = spec->gen.autocfg.speaker_pins;
+               nids = spec->gen.autocfg.speaker_outs;
+       }
+
+       for (i = 0; i < nids; i++) {
+               unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid_pin[i]);
+               if (snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT)
+                       return true;
+       }
+       return false;
+}
+
 /*
  * PC beep controls
  */
@@ -3890,6 +3913,12 @@ static int patch_stac92hd73xx(struct hda_codec *codec)
                return err;
        }
 
+       /* Don't GPIO-mute speakers if there are no internal speakers, because
+        * the GPIO might be necessary for Headphone
+        */
+       if (spec->eapd_switch && !has_builtin_speaker(codec))
+               spec->eapd_switch = 0;
+
        codec->proc_widget_hook = stac92hd7x_proc_hook;
 
        snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PROBE);
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index f2d61a18783089a61632d43b27653e912b4eafa4..566ea3256e2d784c38745ea05972917e19b4021e 100644 (file)
@@ -159,6 +159,7 @@ static int si476x_codec_hw_params(struct snd_pcm_substream *substream,
        switch (params_format(params)) {
        case SNDRV_PCM_FORMAT_S8:
                width = SI476X_PCM_FORMAT_S8;
+               break;
        case SNDRV_PCM_FORMAT_S16_LE:
                width = SI476X_PCM_FORMAT_S16_LE;
                break;
index f3f7e75f86280ef5160facc2a7f3cfa7972c6b91..9af1bddc4c62734d95dde719f37a8d2797d084ae 100644 (file)
@@ -828,7 +828,8 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
                                                &buf_list);
                        if (!buf) {
                                adsp_err(dsp, "Out of memory\n");
-                               return -ENOMEM;
+                               ret = -ENOMEM;
+                               goto out_fw;
                        }
 
                        adsp_dbg(dsp, "%s.%d: Writing %d bytes at %x\n",
@@ -865,7 +866,7 @@ out_fw:
        wm_adsp_buf_free(&buf_list);
 out:
        kfree(file);
-       return 0;
+       return ret;
 }
 
 int wm_adsp1_init(struct wm_adsp *adsp)
index 55464a5b0706161fffd7c94bc3c524f4b3e40224..810c7eeb7b03998d39a69dde175f21a9c8fcee1c 100644 (file)
@@ -496,6 +496,8 @@ static void imx_ssi_ac97_reset(struct snd_ac97 *ac97)
 
        if (imx_ssi->ac97_reset)
                imx_ssi->ac97_reset(ac97);
+       /* First read sometimes fails, do a dummy read */
+       imx_ssi_ac97_read(ac97, 0);
 }
 
 static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97)
@@ -504,6 +506,9 @@ static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97)
 
        if (imx_ssi->ac97_warm_reset)
                imx_ssi->ac97_warm_reset(ac97);
+
+       /* First read sometimes fails, do a dummy read */
+       imx_ssi_ac97_read(ac97, 0);
 }
 
 struct snd_ac97_bus_ops soc_ac97_ops = {
index 8e52c1485df37bfdbe21cbbbc49e801663f4126c..eb4373840bb6e1ab2cbbb1e5e9220e1c8474cb29 100644 (file)
@@ -51,7 +51,7 @@ static struct snd_soc_card pcm030_card = {
        .num_links = ARRAY_SIZE(pcm030_fabric_dai),
 };
 
-static int __init pcm030_fabric_probe(struct platform_device *op)
+static int pcm030_fabric_probe(struct platform_device *op)
 {
        struct device_node *np = op->dev.of_node;
        struct device_node *platform_np;
index 19eff8fc4fdddda4a8ca47972a8c9700c7ea0af1..1a8b03e4b41b9c3f7ce38fcc79130307d757cb51 100644 (file)
@@ -342,8 +342,8 @@ static int camelot_pcm_new(struct snd_soc_pcm_runtime *rtd)
        return 0;
 }
 
-static struct snd_soc_platform sh7760_soc_platform = {
-       .pcm_ops        = &camelot_pcm_ops,
+static struct snd_soc_platform_driver sh7760_soc_platform = {
+       .ops            = &camelot_pcm_ops,
        .pcm_new        = camelot_pcm_new,
        .pcm_free       = camelot_pcm_free,
 };
index b7e84a7cd9ee70451e453f9ef8febb23f3ad05ab..507d251916af66ff81e0812714528ae02640d69e 100644 (file)
@@ -3140,7 +3140,7 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
        if (params->mask) {
                ret = regmap_read(codec->control_data, params->base, &val);
                if (ret != 0)
-                       return ret;
+                       goto out;
 
                val &= params->mask;
 
@@ -3158,13 +3158,15 @@ int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
                        ((u32 *)data)[0] |= cpu_to_be32(val);
                        break;
                default:
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto out;
                }
        }
 
        ret = regmap_raw_write(codec->control_data, params->base,
                               data, len);
 
+out:
        kfree(data);
 
        return ret;
@@ -4197,7 +4199,6 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
                        dev_err(card->dev,
                                "ASoC: Property '%s' index %d could not be read: %d\n",
                                propname, 2 * i, ret);
-                       kfree(routes);
                        return -EINVAL;
                }
                ret = of_property_read_string_index(np, propname,
@@ -4206,7 +4207,6 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
                        dev_err(card->dev,
                                "ASoC: Property '%s' index %d could not be read: %d\n",
                                propname, (2 * i) + 1, ret);
-                       kfree(routes);
                        return -EINVAL;
                }
        }
index 1d6a9b3ceb27cc0b9a6ea307faecaf5872d6b6c9..d6d9ba2e6916fe8f0ab263c03e3a0de2cd208232 100644 (file)
@@ -831,6 +831,9 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
                if (path->weak)
                        continue;
 
+               if (path->walking)
+                       return 1;
+
                if (path->walked)
                        continue;
 
@@ -838,6 +841,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
 
                if (path->sink && path->connect) {
                        path->walked = 1;
+                       path->walking = 1;
 
                        /* do we need to add this widget to the list ? */
                        if (list) {
@@ -847,11 +851,14 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
                                        dev_err(widget->dapm->dev,
                                                "ASoC: could not add widget %s\n",
                                                widget->name);
+                                       path->walking = 0;
                                        return con;
                                }
                        }
 
                        con += is_connected_output_ep(path->sink, list);
+
+                       path->walking = 0;
                }
        }
 
@@ -931,6 +938,9 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
                if (path->weak)
                        continue;
 
+               if (path->walking)
+                       return 1;
+
                if (path->walked)
                        continue;
 
@@ -938,6 +948,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
 
                if (path->source && path->connect) {
                        path->walked = 1;
+                       path->walking = 1;
 
                        /* do we need to add this widget to the list ? */
                        if (list) {
@@ -947,11 +958,14 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
                                        dev_err(widget->dapm->dev,
                                                "ASoC: could not add widget %s\n",
                                                widget->name);
+                                       path->walking = 0;
                                        return con;
                                }
                        }
 
                        con += is_connected_input_ep(path->source, list);
+
+                       path->walking = 0;
                }
        }
 
index 9b76cc5a114897613ed3d19e87b13b649037c4be..5e7aebe1e664bad240ded255bf03565f20670cc2 100644 (file)
@@ -149,9 +149,9 @@ static void spear_pcm_free(struct snd_pcm *pcm)
 
 static u64 spear_pcm_dmamask = DMA_BIT_MASK(32);
 
-static int spear_pcm_new(struct snd_card *card,
-               struct snd_soc_dai *dai, struct snd_pcm *pcm)
+static int spear_pcm_new(struct snd_soc_pcm_runtime *rtd)
 {
+       struct snd_card *card = rtd->card->snd_card;
        int ret;
 
        if (!card->dev->dma_mask)
@@ -159,16 +159,16 @@ static int spear_pcm_new(struct snd_card *card,
        if (!card->dev->coherent_dma_mask)
                card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
 
-       if (dai->driver->playback.channels_min) {
-               ret = spear_pcm_preallocate_dma_buffer(pcm,
+       if (rtd->cpu_dai->driver->playback.channels_min) {
+               ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
                                SNDRV_PCM_STREAM_PLAYBACK,
                                spear_pcm_hardware.buffer_bytes_max);
                if (ret)
                        return ret;
        }
 
-       if (dai->driver->capture.channels_min) {
-               ret = spear_pcm_preallocate_dma_buffer(pcm,
+       if (rtd->cpu_dai->driver->capture.channels_min) {
+               ret = spear_pcm_preallocate_dma_buffer(rtd->pcm,
                                SNDRV_PCM_STREAM_CAPTURE,
                                spear_pcm_hardware.buffer_bytes_max);
                if (ret)
index 803953a9bff338056795c888cecc9d7fb9c6daa2..2da8ad75fd96c7c0245dfca05c9997e5c3d355a1 100644 (file)
@@ -243,6 +243,21 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
                struct usb_interface_assoc_descriptor *assoc =
                        usb_ifnum_to_if(dev, ctrlif)->intf_assoc;
 
+               if (!assoc) {
+                       /*
+                        * Firmware writers cannot count to three.  So to find
+                        * the IAD on the NuForce UDH-100, also check the next
+                        * interface.
+                        */
+                       struct usb_interface *iface =
+                               usb_ifnum_to_if(dev, ctrlif + 1);
+                       if (iface &&
+                           iface->intf_assoc &&
+                           iface->intf_assoc->bFunctionClass == USB_CLASS_AUDIO &&
+                           iface->intf_assoc->bFunctionProtocol == UAC_VERSION_2)
+                               assoc = iface->intf_assoc;
+               }
+
                if (!assoc) {
                        snd_printk(KERN_ERR "Audio class v2 interfaces need an interface association\n");
                        return -EINVAL;
index 5e634a2eb2829461e9efea055a042384e3714b29..9e2703a2515630b82d5659200ae50d6da44c90e6 100644 (file)
@@ -253,7 +253,7 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
 {
        struct usb_device *dev = chip->dev;
        unsigned char data[4];
-       int err, crate;
+       int err, cur_rate, prev_rate;
        int clock = snd_usb_clock_find_source(chip, fmt->clock);
 
        if (clock < 0)
@@ -266,6 +266,19 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
                return -ENXIO;
        }
 
+       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
+                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+                             UAC2_CS_CONTROL_SAM_FREQ << 8,
+                             snd_usb_ctrl_intf(chip) | (clock << 8),
+                             data, sizeof(data));
+       if (err < 0) {
+               snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
+                          dev->devnum, iface, fmt->altsetting);
+               prev_rate = 0;
+       } else {
+               prev_rate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
+       }
+
        data[0] = rate;
        data[1] = rate >> 8;
        data[2] = rate >> 16;
@@ -280,19 +293,31 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
                return err;
        }
 
-       if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
-                                  USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-                                  UAC2_CS_CONTROL_SAM_FREQ << 8,
-                                  snd_usb_ctrl_intf(chip) | (clock << 8),
-                                  data, sizeof(data))) < 0) {
+       err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC2_CS_CUR,
+                             USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+                             UAC2_CS_CONTROL_SAM_FREQ << 8,
+                             snd_usb_ctrl_intf(chip) | (clock << 8),
+                             data, sizeof(data));
+       if (err < 0) {
                snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
                           dev->devnum, iface, fmt->altsetting);
-               return err;
+               cur_rate = 0;
+       } else {
+               cur_rate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
        }
 
-       crate = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
-       if (crate != rate)
-               snd_printd(KERN_WARNING "current rate %d is different from the runtime rate %d\n", crate, rate);
+       if (cur_rate != rate) {
+               snd_printd(KERN_WARNING
+                          "current rate %d is different from the runtime rate %d\n",
+                          cur_rate, rate);
+       }
+
+       /* Some devices doesn't respond to sample rate changes while the
+        * interface is active. */
+       if (rate != prev_rate) {
+               usb_set_interface(dev, iface, 0);
+               usb_set_interface(dev, iface, fmt->altsetting);
+       }
 
        return 0;
 }
index 638e7f738018bf155d55b8ffecc1af5f9a1fc15b..ca4739c3f65021fdef6d8493fb11225ad2746fb1 100644 (file)
@@ -715,8 +715,9 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
                case UAC2_CLOCK_SELECTOR: {
                        struct uac_selector_unit_descriptor *d = p1;
                        /* call recursively to retrieve the channel info */
-                       if (check_input_term(state, d->baSourceID[0], term) < 0)
-                               return -ENODEV;
+                       err = check_input_term(state, d->baSourceID[0], term);
+                       if (err < 0)
+                               return err;
                        term->type = d->bDescriptorSubtype << 16; /* virtual type */
                        term->id = id;
                        term->name = uac_selector_unit_iSelector(d);
@@ -725,7 +726,8 @@ static int check_input_term(struct mixer_build *state, int id, struct usb_audio_
                case UAC1_PROCESSING_UNIT:
                case UAC1_EXTENSION_UNIT:
                /* UAC2_PROCESSING_UNIT_V2 */
-               /* UAC2_EFFECT_UNIT */ {
+               /* UAC2_EFFECT_UNIT */
+               case UAC2_EXTENSION_UNIT_V2: {
                        struct uac_processing_unit_descriptor *d = p1;
 
                        if (state->mixer->protocol == UAC_VERSION_2 &&
@@ -1356,8 +1358,9 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
                return err;
 
        /* determine the input source type and name */
-       if (check_input_term(state, hdr->bSourceID, &iterm) < 0)
-               return -EINVAL;
+       err = check_input_term(state, hdr->bSourceID, &iterm);
+       if (err < 0)
+               return err;
 
        master_bits = snd_usb_combine_bytes(bmaControls, csize);
        /* master configuration quirks */
@@ -2052,6 +2055,8 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
                        return parse_audio_extension_unit(state, unitid, p1);
                else /* UAC_VERSION_2 */
                        return parse_audio_processing_unit(state, unitid, p1);
+       case UAC2_EXTENSION_UNIT_V2:
+               return parse_audio_extension_unit(state, unitid, p1);
        default:
                snd_printk(KERN_ERR "usbaudio: unit %u: unexpected type 0x%02x\n", unitid, p1[2]);
                return -EINVAL;
@@ -2118,7 +2123,7 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
                        state.oterm.type = le16_to_cpu(desc->wTerminalType);
                        state.oterm.name = desc->iTerminal;
                        err = parse_audio_unit(&state, desc->bSourceID);
-                       if (err < 0)
+                       if (err < 0 && err != -EINVAL)
                                return err;
                } else { /* UAC_VERSION_2 */
                        struct uac2_output_terminal_descriptor *desc = p;
@@ -2130,12 +2135,12 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
                        state.oterm.type = le16_to_cpu(desc->wTerminalType);
                        state.oterm.name = desc->iTerminal;
                        err = parse_audio_unit(&state, desc->bSourceID);
-                       if (err < 0)
+                       if (err < 0 && err != -EINVAL)
                                return err;
 
                        /* for UAC2, use the same approach to also add the clock selectors */
                        err = parse_audio_unit(&state, desc->bCSourceID);
-                       if (err < 0)
+                       if (err < 0 && err != -EINVAL)
                                return err;
                }
        }
index a20e32033431a38bc752e2d3476ecafe49e3c78f..0b0a90787db64b010277005c5a7980f60d8fbdbc 100644 (file)
@@ -122,7 +122,7 @@ export Q VERBOSE
 
 EVENT_PARSE_VERSION = $(EP_VERSION).$(EP_PATCHLEVEL).$(EP_EXTRAVERSION)
 
-INCLUDES = -I. -I/usr/local/include $(CONFIG_INCLUDES)
+INCLUDES = -I. $(CONFIG_INCLUDES)
 
 # Set compile option CFLAGS if not set elsewhere
 CFLAGS ?= -g -Wall
index a2108ca1cc17ad02e331aa02adf1870cc56a07ba..bb74c79cd16ed2ad02dbd33ee5f791fb9de2b3c2 100644 (file)
@@ -95,7 +95,7 @@ ifeq ("$(origin DEBUG)", "command line")
   PERF_DEBUG = $(DEBUG)
 endif
 ifndef PERF_DEBUG
-  CFLAGS_OPTIMIZE = -O6 -D_FORTIFY_SOURCE=2
+  CFLAGS_OPTIMIZE = -O6
 endif
 
 ifdef PARSER_DEBUG
@@ -180,6 +180,12 @@ ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -Werror -Wvolatile-register-var,-W
        CFLAGS := $(CFLAGS) -Wvolatile-register-var
 endif
 
+ifndef PERF_DEBUG
+       ifeq ($(call try-cc,$(SOURCE_HELLO),$(CFLAGS) -D_FORTIFY_SOURCE=2,-D_FORTIFY_SOURCE=2),y)
+               CFLAGS := $(CFLAGS) -D_FORTIFY_SOURCE=2
+       endif
+endif
+
 ### --- END CONFIGURATION SECTION ---
 
 ifeq ($(srctree),)
index a5223e6a7b432a0b04faf5ba5dfc130cd9ed150e..0fdc85269c4dc4c2bd72220526879a07e76679be 100644 (file)
@@ -1,6 +1,30 @@
 #ifndef BENCH_H
 #define BENCH_H
 
+/*
+ * The madvise transparent hugepage constants were added in glibc
+ * 2.13. For compatibility with older versions of glibc, define these
+ * tokens if they are not already defined.
+ *
+ * PA-RISC uses different madvise values from other architectures and
+ * needs to be special-cased.
+ */
+#ifdef __hppa__
+# ifndef MADV_HUGEPAGE
+#  define MADV_HUGEPAGE                67
+# endif
+# ifndef MADV_NOHUGEPAGE
+#  define MADV_NOHUGEPAGE      68
+# endif
+#else
+# ifndef MADV_HUGEPAGE
+#  define MADV_HUGEPAGE                14
+# endif
+# ifndef MADV_NOHUGEPAGE
+#  define MADV_NOHUGEPAGE      15
+# endif
+#endif
+
 extern int bench_numa(int argc, const char **argv, const char *prefix);
 extern int bench_sched_messaging(int argc, const char **argv, const char *prefix);
 extern int bench_sched_pipe(int argc, const char **argv, const char *prefix);
index 774c90713a53fe8a27f0561a8476d5c23748edab..f1a939ebc19c5d4aad0afbe1b96201aadbdb0511 100644 (file)
@@ -573,13 +573,15 @@ static int __cmd_record(struct perf_record *rec, int argc, const char **argv)
                                         perf_event__synthesize_guest_os, tool);
        }
 
-       if (!opts->target.system_wide)
+       if (perf_target__has_task(&opts->target))
                err = perf_event__synthesize_thread_map(tool, evsel_list->threads,
                                                  process_synthesized_event,
                                                  machine);
-       else
+       else if (perf_target__has_cpu(&opts->target))
                err = perf_event__synthesize_threads(tool, process_synthesized_event,
                                               machine);
+       else /* command specified */
+               err = 0;
 
        if (err != 0)
                goto out_delete_session;
index 38624686ee9a145ffaacbcfa063e5d985da750f0..226a4ae2f936ccaa228a5fad85bfd5318521ccd5 100644 (file)
@@ -208,8 +208,9 @@ static inline int script_browse(const char *script_opt __maybe_unused)
        return 0;
 }
 
-#define K_LEFT -1
-#define K_RIGHT -2
+#define K_LEFT  -1000
+#define K_RIGHT -2000
+#define K_SWITCH_INPUT_DATA -3000
 #endif
 
 #ifdef GTK2_SUPPORT
index 55433aa42c8f30cb8dbeeae537ce8ea0ad47965b..eabdce0a2daa0a0a2c5c882529617322ce6e8852 100644 (file)
@@ -143,7 +143,7 @@ struct strlist *strlist__new(bool dupstr, const char *list)
                slist->rblist.node_delete = strlist__node_delete;
 
                slist->dupstr    = dupstr;
-               if (slist && strlist__parse_list(slist, list) != 0)
+               if (list && strlist__parse_list(slist, list) != 0)
                        goto out_error;
        }
 
index 8674b9ec14f69882f2e64e689581284bdfeced4b..fe1e66b6ef40bbb1e490edcf2476645d81b66d3f 100644 (file)
@@ -38,7 +38,7 @@
 #include <unistd.h>
 #include <tools/le_byteshift.h>
 
-#include "../../include/linux/usb/functionfs.h"
+#include "../../include/uapi/linux/usb/functionfs.h"
 
 
 /******************** Little Endian Handling ********************************/
index ce82b940195843827be4d22e710942b0683a4618..5ba005c00e2f76998694d202eca68452600ee5bf 100644 (file)
@@ -74,9 +74,12 @@ static unsigned long ioapic_read_indirect(struct kvm_ioapic *ioapic,
                        u32 redir_index = (ioapic->ioregsel - 0x10) >> 1;
                        u64 redir_content;
 
-                       ASSERT(redir_index < IOAPIC_NUM_PINS);
+                       if (redir_index < IOAPIC_NUM_PINS)
+                               redir_content =
+                                       ioapic->redirtbl[redir_index].bits;
+                       else
+                               redir_content = ~0ULL;
 
-                       redir_content = ioapic->redirtbl[redir_index].bits;
                        result = (ioapic->ioregsel & 0x1) ?
                            (redir_content >> 32) & 0xffffffff :
                            redir_content & 0xffffffff;
index adc68feb5c5a338080ac8ca2385f73577ac6c29a..f18013f09e68423d68d4033d1e22fe1f8701886b 100644 (file)
@@ -1541,21 +1541,38 @@ int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data,
 }
 
 int kvm_gfn_to_hva_cache_init(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
-                             gpa_t gpa)
+                             gpa_t gpa, unsigned long len)
 {
        struct kvm_memslots *slots = kvm_memslots(kvm);
        int offset = offset_in_page(gpa);
-       gfn_t gfn = gpa >> PAGE_SHIFT;
+       gfn_t start_gfn = gpa >> PAGE_SHIFT;
+       gfn_t end_gfn = (gpa + len - 1) >> PAGE_SHIFT;
+       gfn_t nr_pages_needed = end_gfn - start_gfn + 1;
+       gfn_t nr_pages_avail;
 
        ghc->gpa = gpa;
        ghc->generation = slots->generation;
-       ghc->memslot = gfn_to_memslot(kvm, gfn);
-       ghc->hva = gfn_to_hva_many(ghc->memslot, gfn, NULL);
-       if (!kvm_is_error_hva(ghc->hva))
+       ghc->len = len;
+       ghc->memslot = gfn_to_memslot(kvm, start_gfn);
+       ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn, &nr_pages_avail);
+       if (!kvm_is_error_hva(ghc->hva) && nr_pages_avail >= nr_pages_needed) {
                ghc->hva += offset;
-       else
-               return -EFAULT;
-
+       } else {
+               /*
+                * If the requested region crosses two memslots, we still
+                * verify that the entire region is valid here.
+                */
+               while (start_gfn <= end_gfn) {
+                       ghc->memslot = gfn_to_memslot(kvm, start_gfn);
+                       ghc->hva = gfn_to_hva_many(ghc->memslot, start_gfn,
+                                                  &nr_pages_avail);
+                       if (kvm_is_error_hva(ghc->hva))
+                               return -EFAULT;
+                       start_gfn += nr_pages_avail;
+               }
+               /* Use the slow path for cross page reads and writes. */
+               ghc->memslot = NULL;
+       }
        return 0;
 }
 EXPORT_SYMBOL_GPL(kvm_gfn_to_hva_cache_init);
@@ -1566,8 +1583,13 @@ int kvm_write_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
        struct kvm_memslots *slots = kvm_memslots(kvm);
        int r;
 
+       BUG_ON(len > ghc->len);
+
        if (slots->generation != ghc->generation)
-               kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa);
+               kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
+
+       if (unlikely(!ghc->memslot))
+               return kvm_write_guest(kvm, ghc->gpa, data, len);
 
        if (kvm_is_error_hva(ghc->hva))
                return -EFAULT;
@@ -1587,8 +1609,13 @@ int kvm_read_guest_cached(struct kvm *kvm, struct gfn_to_hva_cache *ghc,
        struct kvm_memslots *slots = kvm_memslots(kvm);
        int r;
 
+       BUG_ON(len > ghc->len);
+
        if (slots->generation != ghc->generation)
-               kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa);
+               kvm_gfn_to_hva_cache_init(kvm, ghc, ghc->gpa, ghc->len);
+
+       if (unlikely(!ghc->memslot))
+               return kvm_read_guest(kvm, ghc->gpa, data, len);
 
        if (kvm_is_error_hva(ghc->hva))
                return -EFAULT;