Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 24 Jul 2012 17:01:50 +0000 (10:01 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 24 Jul 2012 17:01:50 +0000 (10:01 -0700)
Pull networking changes from David S Miller:

 1) Remove the ipv4 routing cache.  Now lookups go directly into the FIB
    trie and use prebuilt routes cached there.

    No more garbage collection, no more rDOS attacks on the routing
    cache.  Instead we now get predictable and consistent performance,
    no matter what the pattern of traffic we service.

    This has been almost 2 years in the making.  Special thanks to
    Julian Anastasov, Eric Dumazet, Steffen Klassert, and others who
    have helped along the way.

    I'm sure that with a change of this magnitude there will be some
    kind of fallout, but such things ought the be simple to fix at this
    point.  Luckily I'm not European so I'll be around all of August to
    fix things :-)

    The major stages of this work here are each fronted by a forced
    merge commit whose commit message contains a top-level description
    of the motivations and implementation issues.

 2) Pre-demux of established ipv4 TCP sockets, saves a route demux on
    input.

 3) TCP SYN/ACK performance tweaks from Eric Dumazet.

 4) Add namespace support for netfilter L4 conntrack helpers, from Gao
    Feng.

 5) Add config mechanism for Energy Efficient Ethernet to ethtool, from
    Yuval Mintz.

 6) Remove quadratic behavior from /proc/net/unix, from Eric Dumazet.

 7) Support for connection tracker helpers in userspace, from Pablo
    Neira Ayuso.

 8) Allow userspace driven TX load balancing functions in TEAM driver,
    from Jiri Pirko.

 9) Kill off NLMSG_PUT and RTA_PUT macros, more gross stuff with
    embedded gotos.

10) TCP Small Queues, essentially minimize the amount of TCP data queued
    up in the packet scheduler layer.  Whereas the existing BQL (Byte
    Queue Limits) limits the pkt_sched --> netdevice queuing levels,
    this controls the TCP --> pkt_sched queueing levels.

    From Eric Dumazet.

11) Reduce the number of get_page/put_page ops done on SKB fragments,
    from Alexander Duyck.

12) Implement protection against blind resets in TCP (RFC 5961), from
    Eric Dumazet.

13) Support the client side of TCP Fast Open, basically the ability to
    send data in the SYN exchange, from Yuchung Cheng.

    Basically, the sender queues up data with a sendmsg() call using
    MSG_FASTOPEN, then they do the connect() which emits the queued up
    fastopen data.

14) Avoid all the problems we get into in TCP when timers or PMTU events
    hit a locked socket.  The TCP Small Queues changes added a
    tcp_release_cb() that allows us to queue work up to the
    release_sock() caller, and that's what we use here too.  From Eric
    Dumazet.

15) Zero copy on TX support for TUN driver, from Michael S. Tsirkin.

* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next: (1870 commits)
  genetlink: define lockdep_genl_is_held() when CONFIG_LOCKDEP
  r8169: revert "add byte queue limit support".
  ipv4: Change rt->rt_iif encoding.
  net: Make skb->skb_iif always track skb->dev
  ipv4: Prepare for change of rt->rt_iif encoding.
  ipv4: Remove all RTCF_DIRECTSRC handliing.
  ipv4: Really ignore ICMP address requests/replies.
  decnet: Don't set RTCF_DIRECTSRC.
  net/ipv4/ip_vti.c: Fix __rcu warnings detected by sparse.
  ipv4: Remove redundant assignment
  rds: set correct msg_namelen
  openvswitch: potential NULL deref in sample()
  tcp: dont drop MTU reduction indications
  bnx2x: Add new 57840 device IDs
  tcp: avoid oops in tcp_metrics and reset tcpm_stamp
  niu: Change niu_rbr_fill() to use unlikely() to check niu_rbr_add_page() return value
  niu: Fix to check for dma mapping errors.
  net: Fix references to out-of-scope variables in put_cmsg_compat()
  net: ethernet: davinci_emac: add pm_runtime support
  net: ethernet: davinci_emac: Remove unnecessary #include
  ...

2070 files changed:
Documentation/ABI/testing/sysfs-power
Documentation/RCU/checklist.txt
Documentation/RCU/rcubarrier.txt
Documentation/RCU/torture.txt
Documentation/RCU/whatisRCU.txt
Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/armada-370-xp.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/atmel-aic.txt
Documentation/devicetree/bindings/arm/davinci/cp-intc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/mvebu-system-controller.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/olimex.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/omap/omap.txt
Documentation/devicetree/bindings/arm/tegra/emc.txt [deleted file]
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-mc.txt
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra30-mc.txt
Documentation/devicetree/bindings/fb/mxsfb.txt [new file with mode: 0644]
Documentation/devicetree/bindings/gpio/fsl-imx-gpio.txt
Documentation/devicetree/bindings/gpio/gpio-mxs.txt
Documentation/devicetree/bindings/gpio/gpio-nmk.txt
Documentation/devicetree/bindings/gpio/gpio_nvidia.txt [deleted file]
Documentation/devicetree/bindings/gpio/nvidia,tegra20-gpio.txt [new file with mode: 0644]
Documentation/devicetree/bindings/input/nvidia,tegra20-kbc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/input/tegra-kbc.txt [deleted file]
Documentation/devicetree/bindings/mfd/tps65910.txt
Documentation/devicetree/bindings/mmc/fsl-esdhc.txt
Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt
Documentation/devicetree/bindings/mmc/mmc.txt
Documentation/devicetree/bindings/mmc/mmci.txt
Documentation/devicetree/bindings/mmc/mxs-mmc.txt
Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt [deleted file]
Documentation/devicetree/bindings/mmc/sdhci-pxa.txt [new file with mode: 0644]
Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt
Documentation/devicetree/bindings/nvec/nvec_nvidia.txt [deleted file]
Documentation/devicetree/bindings/nvec/nvidia,nvec.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/fixed-regulator.txt
Documentation/devicetree/bindings/regulator/regulator.txt
Documentation/devicetree/bindings/regulator/tps65217.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/tps6586x.txt
Documentation/devicetree/bindings/regulator/twl-regulator.txt
Documentation/devicetree/bindings/rtc/dw-apb.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/nvidia,tegra-audio-trimslice.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/nvidia,tegra20-das.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/nvidia,tegra20-i2s.txt [new file with mode: 0644]
Documentation/devicetree/bindings/sound/tegra-audio-alc5632.txt [deleted file]
Documentation/devicetree/bindings/sound/tegra-audio-trimslice.txt [deleted file]
Documentation/devicetree/bindings/sound/tegra-audio-wm8753.txt [deleted file]
Documentation/devicetree/bindings/sound/tegra-audio-wm8903.txt [deleted file]
Documentation/devicetree/bindings/sound/tegra20-das.txt [deleted file]
Documentation/devicetree/bindings/sound/tegra20-i2s.txt [deleted file]
Documentation/devicetree/bindings/spi/nvidia,tegra20-spi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/spi-samsung.txt [new file with mode: 0644]
Documentation/devicetree/bindings/spi/spi_nvidia.txt [deleted file]
Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt [new file with mode: 0644]
Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt [new file with mode: 0644]
Documentation/devicetree/bindings/usb/tegra-usb.txt [deleted file]
Documentation/devicetree/bindings/watchdog/omap-wdt.txt [new file with mode: 0644]
Documentation/filesystems/Locking
Documentation/filesystems/porting
Documentation/filesystems/vfs.txt
Documentation/kernel-parameters.txt
Documentation/power/devices.txt
Documentation/power/swsusp.txt
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/dts/aks-cdu.dts [new file with mode: 0644]
arch/arm/boot/dts/am335x-bone.dts [new file with mode: 0644]
arch/arm/boot/dts/am335x-evm.dts [new file with mode: 0644]
arch/arm/boot/dts/am33xx.dtsi [new file with mode: 0644]
arch/arm/boot/dts/am3517-evm.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-370-db.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-370-xp.dtsi [new file with mode: 0644]
arch/arm/boot/dts/armada-370.dtsi [new file with mode: 0644]
arch/arm/boot/dts/armada-xp-db.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-xp.dtsi [new file with mode: 0644]
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9n12.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/db8500.dtsi
arch/arm/boot/dts/ea3250.dts [new file with mode: 0644]
arch/arm/boot/dts/evk-pro3.dts [new file with mode: 0644]
arch/arm/boot/dts/exynos4210-origen.dts
arch/arm/boot/dts/exynos4210-smdkv310.dts
arch/arm/boot/dts/exynos4210.dtsi
arch/arm/boot/dts/exynos5250-smdk5250.dts
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/ge863-pro3.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx23-evk.dts
arch/arm/boot/dts/imx23-olinuxino.dts [new file with mode: 0644]
arch/arm/boot/dts/imx23-stmp378x_devb.dts [new file with mode: 0644]
arch/arm/boot/dts/imx23.dtsi
arch/arm/boot/dts/imx27-3ds.dts [new file with mode: 0644]
arch/arm/boot/dts/imx27.dtsi
arch/arm/boot/dts/imx28-apx4devkit.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-cfa10036.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-evk.dts
arch/arm/boot/dts/imx28-m28evk.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-tx28.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/imx31-bug.dts [new file with mode: 0644]
arch/arm/boot/dts/imx31.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx51.dtsi
arch/arm/boot/dts/imx53.dtsi
arch/arm/boot/dts/imx6q-arm2.dts
arch/arm/boot/dts/imx6q-sabrelite.dts
arch/arm/boot/dts/imx6q.dtsi
arch/arm/boot/dts/lpc32xx.dtsi
arch/arm/boot/dts/omap2420-h4.dts [new file with mode: 0644]
arch/arm/boot/dts/omap3-beagle.dts
arch/arm/boot/dts/omap3-evm.dts
arch/arm/boot/dts/omap3.dtsi
arch/arm/boot/dts/omap4-panda.dts
arch/arm/boot/dts/omap4-pandaES.dts [new file with mode: 0644]
arch/arm/boot/dts/omap4-sdp.dts
arch/arm/boot/dts/omap4-var_som.dts [new file with mode: 0644]
arch/arm/boot/dts/omap4.dtsi
arch/arm/boot/dts/omap5-evm.dts [new file with mode: 0644]
arch/arm/boot/dts/omap5.dtsi [new file with mode: 0644]
arch/arm/boot/dts/phy3250.dts
arch/arm/boot/dts/snowball.dts
arch/arm/boot/dts/socfpga.dtsi [new file with mode: 0644]
arch/arm/boot/dts/socfpga_cyclone5.dts [new file with mode: 0644]
arch/arm/boot/dts/tegra-cardhu.dts [deleted file]
arch/arm/boot/dts/tegra-harmony.dts [deleted file]
arch/arm/boot/dts/tegra-paz00.dts [deleted file]
arch/arm/boot/dts/tegra-seaboard.dts [deleted file]
arch/arm/boot/dts/tegra-trimslice.dts [deleted file]
arch/arm/boot/dts/tegra-ventana.dts [deleted file]
arch/arm/boot/dts/tegra20-harmony.dts [new file with mode: 0644]
arch/arm/boot/dts/tegra20-paz00.dts [new file with mode: 0644]
arch/arm/boot/dts/tegra20-seaboard.dts [new file with mode: 0644]
arch/arm/boot/dts/tegra20-trimslice.dts [new file with mode: 0644]
arch/arm/boot/dts/tegra20-ventana.dts [new file with mode: 0644]
arch/arm/boot/dts/tegra20-whistler.dts [new file with mode: 0644]
arch/arm/boot/dts/tegra20.dtsi
arch/arm/boot/dts/tegra30-cardhu.dts [new file with mode: 0644]
arch/arm/boot/dts/tegra30.dtsi
arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
arch/arm/boot/dts/vexpress-v2m.dtsi
arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts [new file with mode: 0644]
arch/arm/configs/exynos_defconfig [new file with mode: 0644]
arch/arm/configs/imx_v4_v5_defconfig
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/lpc32xx_defconfig
arch/arm/configs/mvebu_defconfig [new file with mode: 0644]
arch/arm/configs/mxs_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/socfpga_defconfig [new file with mode: 0644]
arch/arm/configs/tegra_defconfig
arch/arm/include/asm/mach/irq.h
arch/arm/kernel/fiq.c
arch/arm/kernel/irq.c
arch/arm/mach-at91/Kconfig
arch/arm/mach-at91/Makefile.boot
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91rm9200_devices.c
arch/arm/mach-at91/at91sam9260.c
arch/arm/mach-at91/at91sam9260_devices.c
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/at91sam926x_time.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/at91sam9x5.c
arch/arm/mach-at91/at91x40.c
arch/arm/mach-at91/board-1arm.c
arch/arm/mach-at91/board-afeb-9260v1.c
arch/arm/mach-at91/board-cam60.c
arch/arm/mach-at91/board-carmeva.c
arch/arm/mach-at91/board-cpu9krea.c
arch/arm/mach-at91/board-cpuat91.c
arch/arm/mach-at91/board-csb337.c
arch/arm/mach-at91/board-csb637.c
arch/arm/mach-at91/board-dt.c
arch/arm/mach-at91/board-eb01.c
arch/arm/mach-at91/board-eb9200.c
arch/arm/mach-at91/board-ecbat91.c
arch/arm/mach-at91/board-eco920.c
arch/arm/mach-at91/board-flexibity.c
arch/arm/mach-at91/board-foxg20.c
arch/arm/mach-at91/board-gsia18s.c
arch/arm/mach-at91/board-kafa.c
arch/arm/mach-at91/board-kb9202.c
arch/arm/mach-at91/board-neocore926.c
arch/arm/mach-at91/board-pcontrol-g20.c
arch/arm/mach-at91/board-picotux200.c
arch/arm/mach-at91/board-qil-a9260.c
arch/arm/mach-at91/board-rm9200dk.c
arch/arm/mach-at91/board-rm9200ek.c
arch/arm/mach-at91/board-rsi-ews.c
arch/arm/mach-at91/board-sam9-l9260.c
arch/arm/mach-at91/board-sam9260ek.c
arch/arm/mach-at91/board-sam9261ek.c
arch/arm/mach-at91/board-sam9263ek.c
arch/arm/mach-at91/board-sam9g20ek.c
arch/arm/mach-at91/board-sam9m10g45ek.c
arch/arm/mach-at91/board-sam9rlek.c
arch/arm/mach-at91/board-snapper9260.c
arch/arm/mach-at91/board-stamp9g20.c
arch/arm/mach-at91/board-usb-a926x.c
arch/arm/mach-at91/board-yl-9200.c
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/gpio.c
arch/arm/mach-at91/include/mach/at91_aic.h
arch/arm/mach-at91/include/mach/at91_spi.h [deleted file]
arch/arm/mach-at91/include/mach/at91_ssc.h [deleted file]
arch/arm/mach-at91/include/mach/entry-macro.S [deleted file]
arch/arm/mach-at91/include/mach/irqs.h [deleted file]
arch/arm/mach-at91/irq.c
arch/arm/mach-at91/pm.c
arch/arm/mach-clps711x/common.c
arch/arm/mach-clps711x/include/mach/memory.h
arch/arm/mach-clps711x/p720t.c
arch/arm/mach-davinci/Kconfig
arch/arm/mach-davinci/Makefile
arch/arm/mach-davinci/cp_intc.c
arch/arm/mach-davinci/include/mach/cp_intc.h
arch/arm/mach-davinci/include/mach/dm365.h [deleted file]
arch/arm/mach-davinci/include/mach/dm646x.h [deleted file]
arch/arm/mach-davinci/include/mach/entry-macro.S
arch/arm/mach-davinci/pm_domain.c [new file with mode: 0644]
arch/arm/mach-ep93xx/core.c
arch/arm/mach-ep93xx/edb93xx.c
arch/arm/mach-ep93xx/include/mach/platform.h
arch/arm/mach-ep93xx/soc.h
arch/arm/mach-exynos/Kconfig
arch/arm/mach-exynos/clock-exynos4.c
arch/arm/mach-exynos/clock-exynos5.c
arch/arm/mach-exynos/common.c
arch/arm/mach-exynos/include/mach/irqs.h
arch/arm/mach-exynos/include/mach/map.h
arch/arm/mach-exynos/include/mach/regs-pmu.h
arch/arm/mach-exynos/include/mach/regs-usb-phy.h
arch/arm/mach-exynos/include/mach/spi-clocks.h [deleted file]
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/pmu.c
arch/arm/mach-exynos/setup-spi.c
arch/arm/mach-exynos/setup-usb-phy.c
arch/arm/mach-imx/Kconfig
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/clk-imx31.c
arch/arm/mach-imx/clk-imx51-imx53.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/devices-imx21.h
arch/arm/mach-imx/devices-imx25.h
arch/arm/mach-imx/devices-imx27.h
arch/arm/mach-imx/devices-imx31.h
arch/arm/mach-imx/devices-imx35.h
arch/arm/mach-imx/devices-imx51.h
arch/arm/mach-imx/devices-imx53.h
arch/arm/mach-imx/ehci-imx25.c
arch/arm/mach-imx/ehci-imx35.c
arch/arm/mach-imx/ehci-imx5.c
arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
arch/arm/mach-imx/eukrea_mbimxsd35-baseboard.c
arch/arm/mach-imx/imx27-dt.c
arch/arm/mach-imx/imx31-dt.c [new file with mode: 0644]
arch/arm/mach-imx/imx51-dt.c
arch/arm/mach-imx/imx53-dt.c
arch/arm/mach-imx/mach-apf9328.c
arch/arm/mach-imx/mach-armadillo5x0.c
arch/arm/mach-imx/mach-cpuimx27.c
arch/arm/mach-imx/mach-cpuimx35.c
arch/arm/mach-imx/mach-cpuimx51sd.c
arch/arm/mach-imx/mach-eukrea_cpuimx25.c
arch/arm/mach-imx/mach-imx27_visstrim_m10.c
arch/arm/mach-imx/mach-imx27ipcam.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-imx/mach-kzm_arm11_01.c
arch/arm/mach-imx/mach-mx1ads.c
arch/arm/mach-imx/mach-mx21ads.c
arch/arm/mach-imx/mach-mx25_3ds.c
arch/arm/mach-imx/mach-mx27_3ds.c
arch/arm/mach-imx/mach-mx27ads.c
arch/arm/mach-imx/mach-mx31_3ds.c
arch/arm/mach-imx/mach-mx31ads.c
arch/arm/mach-imx/mach-mx31lilly.c
arch/arm/mach-imx/mach-mx31lite.c
arch/arm/mach-imx/mach-mx31moboard.c
arch/arm/mach-imx/mach-mx35_3ds.c
arch/arm/mach-imx/mach-mx51_3ds.c
arch/arm/mach-imx/mach-mx51_babbage.c
arch/arm/mach-imx/mach-mx53_ard.c
arch/arm/mach-imx/mach-mx53_evk.c
arch/arm/mach-imx/mach-mx53_loco.c
arch/arm/mach-imx/mach-mx53_smd.c
arch/arm/mach-imx/mach-mxt_td60.c
arch/arm/mach-imx/mach-pca100.c
arch/arm/mach-imx/mach-pcm037.c
arch/arm/mach-imx/mach-pcm038.c
arch/arm/mach-imx/mach-pcm043.c
arch/arm/mach-imx/mach-qong.c
arch/arm/mach-imx/mach-scb9328.c
arch/arm/mach-imx/mach-vpr200.c
arch/arm/mach-imx/mm-imx1.c
arch/arm/mach-imx/mm-imx21.c
arch/arm/mach-imx/mm-imx25.c
arch/arm/mach-imx/mm-imx27.c
arch/arm/mach-imx/mm-imx3.c
arch/arm/mach-imx/mm-imx5.c
arch/arm/mach-imx/mx31lilly-db.c
arch/arm/mach-imx/mx31lite-db.c
arch/arm/mach-imx/mx51_efika.c
arch/arm/mach-imx/pcm970-baseboard.c
arch/arm/mach-imx/pm-imx5.c
arch/arm/mach-lpc32xx/Kconfig [deleted file]
arch/arm/mach-lpc32xx/Makefile.boot
arch/arm/mach-lpc32xx/clock.c
arch/arm/mach-lpc32xx/common.c
arch/arm/mach-lpc32xx/include/mach/gpio.h
arch/arm/mach-lpc32xx/include/mach/platform.h
arch/arm/mach-lpc32xx/phy3250.c
arch/arm/mach-lpc32xx/serial.c
arch/arm/mach-mvebu/Kconfig [new file with mode: 0644]
arch/arm/mach-mvebu/Makefile [new file with mode: 0644]
arch/arm/mach-mvebu/Makefile.boot [new file with mode: 0644]
arch/arm/mach-mvebu/armada-370-xp.c [new file with mode: 0644]
arch/arm/mach-mvebu/common.h [new file with mode: 0644]
arch/arm/mach-mvebu/include/mach/armada-370-xp.h [new file with mode: 0644]
arch/arm/mach-mvebu/include/mach/debug-macro.S [new file with mode: 0644]
arch/arm/mach-mvebu/include/mach/timex.h [new file with mode: 0644]
arch/arm/mach-mvebu/include/mach/uncompress.h [new file with mode: 0644]
arch/arm/mach-mvebu/irq-armada-370-xp.c [new file with mode: 0644]
arch/arm/mach-mvebu/system-controller.c [new file with mode: 0644]
arch/arm/mach-mxs/Kconfig
arch/arm/mach-mxs/Makefile.boot
arch/arm/mach-mxs/devices-mx23.h
arch/arm/mach-mxs/devices-mx28.h
arch/arm/mach-mxs/devices/platform-mxsfb.c
arch/arm/mach-mxs/include/mach/mxsfb.h [deleted file]
arch/arm/mach-mxs/mach-mxs.c
arch/arm/mach-mxs/module-tx28.c
arch/arm/mach-nomadik/Makefile
arch/arm/mach-nomadik/board-nhk8815.c
arch/arm/mach-nomadik/clock.c [deleted file]
arch/arm/mach-nomadik/clock.h [deleted file]
arch/arm/mach-nomadik/cpu-8815.c
arch/arm/mach-nomadik/i2c-8815nhk.c
arch/arm/mach-nomadik/include/mach/irqs.h
arch/arm/mach-omap1/board-ams-delta.c
arch/arm/mach-omap1/board-generic.c
arch/arm/mach-omap1/board-h2.c
arch/arm/mach-omap1/board-h3.c
arch/arm/mach-omap1/board-htcherald.c
arch/arm/mach-omap1/board-innovator.c
arch/arm/mach-omap1/board-nokia770.c
arch/arm/mach-omap1/board-osk.c
arch/arm/mach-omap1/board-palmte.c
arch/arm/mach-omap1/board-palmtt.c
arch/arm/mach-omap1/board-palmz71.c
arch/arm/mach-omap1/board-sx1.c
arch/arm/mach-omap1/board-voiceblue.c
arch/arm/mach-omap1/clock_data.c
arch/arm/mach-omap1/include/mach/usb.h [new file with mode: 0644]
arch/arm/mach-omap1/timer.c
arch/arm/mach-omap1/usb.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/am35xx-emac.c
arch/arm/mach-omap2/board-2430sdp.c
arch/arm/mach-omap2/board-4430sdp.c
arch/arm/mach-omap2/board-apollon.c
arch/arm/mach-omap2/board-cm-t35.c
arch/arm/mach-omap2/board-generic.c
arch/arm/mach-omap2/board-h4.c
arch/arm/mach-omap2/board-omap3beagle.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-omap3logic.c
arch/arm/mach-omap2/board-omap4panda.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock2420_data.c
arch/arm/mach-omap2/clock2430_data.c
arch/arm/mach-omap2/clock33xx_data.c [new file with mode: 0644]
arch/arm/mach-omap2/clock3xxx_data.c
arch/arm/mach-omap2/clock44xx_data.c
arch/arm/mach-omap2/clock_common_data.c
arch/arm/mach-omap2/clockdomain.h
arch/arm/mach-omap2/clockdomain33xx.c [new file with mode: 0644]
arch/arm/mach-omap2/clockdomain44xx.c
arch/arm/mach-omap2/clockdomains2420_data.c
arch/arm/mach-omap2/clockdomains2430_data.c
arch/arm/mach-omap2/clockdomains33xx_data.c [new file with mode: 0644]
arch/arm/mach-omap2/clockdomains3xxx_data.c
arch/arm/mach-omap2/clockdomains44xx_data.c
arch/arm/mach-omap2/clockdomains_common_data.c [deleted file]
arch/arm/mach-omap2/cm-regbits-33xx.h [new file with mode: 0644]
arch/arm/mach-omap2/cm-regbits-34xx.h
arch/arm/mach-omap2/cm33xx.c [new file with mode: 0644]
arch/arm/mach-omap2/cm33xx.h [new file with mode: 0644]
arch/arm/mach-omap2/cminst44xx.c
arch/arm/mach-omap2/cminst44xx.h
arch/arm/mach-omap2/common-board-devices.c
arch/arm/mach-omap2/common-board-devices.h
arch/arm/mach-omap2/common.c
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/control.c
arch/arm/mach-omap2/control.h
arch/arm/mach-omap2/cpuidle34xx.c
arch/arm/mach-omap2/cpuidle44xx.c
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/dpll3xxx.c
arch/arm/mach-omap2/drm.c [new file with mode: 0644]
arch/arm/mach-omap2/dsp.c
arch/arm/mach-omap2/gpmc.c
arch/arm/mach-omap2/hdq1w.c
arch/arm/mach-omap2/id.c
arch/arm/mach-omap2/include/mach/am35xx.h
arch/arm/mach-omap2/include/mach/ctrl_module_core_44xx.h
arch/arm/mach-omap2/include/mach/debug-macro.S
arch/arm/mach-omap2/include/mach/omap-wakeupgen.h
arch/arm/mach-omap2/io.c
arch/arm/mach-omap2/iomap.h
arch/arm/mach-omap2/irq.c
arch/arm/mach-omap2/mailbox.c
arch/arm/mach-omap2/msdi.c
arch/arm/mach-omap2/omap-headsmp.S
arch/arm/mach-omap2/omap-hotplug.c
arch/arm/mach-omap2/omap-iommu.c
arch/arm/mach-omap2/omap-mpuss-lowpower.c
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-omap2/omap-wakeupgen.c
arch/arm/mach-omap2/omap4-common.c
arch/arm/mach-omap2/omap4-sar-layout.h
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_2420_data.c
arch/arm/mach-omap2/omap_hwmod_2430_data.c
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_hwmod_common_data.c
arch/arm/mach-omap2/omap_l3_noc.h
arch/arm/mach-omap2/opp.c
arch/arm/mach-omap2/pm.h
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/powerdomain.c
arch/arm/mach-omap2/powerdomain.h
arch/arm/mach-omap2/powerdomain33xx.c [new file with mode: 0644]
arch/arm/mach-omap2/powerdomains33xx_data.c [new file with mode: 0644]
arch/arm/mach-omap2/powerdomains3xxx_data.c
arch/arm/mach-omap2/prcm-common.h
arch/arm/mach-omap2/prcm.c
arch/arm/mach-omap2/prm-regbits-33xx.h [new file with mode: 0644]
arch/arm/mach-omap2/prm2xxx_3xxx.c
arch/arm/mach-omap2/prm2xxx_3xxx.h
arch/arm/mach-omap2/prm33xx.c [new file with mode: 0644]
arch/arm/mach-omap2/prm33xx.h [new file with mode: 0644]
arch/arm/mach-omap2/prm44xx.c
arch/arm/mach-omap2/prm44xx.h
arch/arm/mach-omap2/prm_common.c
arch/arm/mach-omap2/smartreflex-class3.c
arch/arm/mach-omap2/smartreflex.c [deleted file]
arch/arm/mach-omap2/smartreflex.h [deleted file]
arch/arm/mach-omap2/sr_device.c
arch/arm/mach-omap2/timer.c
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-omap2/usb-fs.c [deleted file]
arch/arm/mach-omap2/voltage.h
arch/arm/mach-omap2/voltagedomains33xx_data.c [new file with mode: 0644]
arch/arm/mach-picoxcell/Makefile
arch/arm/mach-picoxcell/common.c
arch/arm/mach-picoxcell/common.h
arch/arm/mach-picoxcell/time.c [deleted file]
arch/arm/mach-prima2/include/mach/gpio.h [new file with mode: 0644]
arch/arm/mach-prima2/include/mach/irqs.h
arch/arm/mach-rpc/irq.c
arch/arm/mach-s3c24xx/clock-s3c2416.c
arch/arm/mach-s3c24xx/clock-s3c2443.c
arch/arm/mach-s3c24xx/common-s3c2443.c
arch/arm/mach-s3c24xx/common-smdk.c
arch/arm/mach-s3c24xx/common.c
arch/arm/mach-s3c24xx/include/mach/bast-pmu.h [deleted file]
arch/arm/mach-s3c24xx/include/mach/gpio-nrs.h
arch/arm/mach-s3c24xx/include/mach/gta02.h
arch/arm/mach-s3c24xx/include/mach/regs-gpio.h
arch/arm/mach-s3c24xx/include/mach/regs-gpioj.h [deleted file]
arch/arm/mach-s3c24xx/mach-gta02.c
arch/arm/mach-s3c24xx/mach-mini2440.c
arch/arm/mach-s3c24xx/mach-qt2410.c
arch/arm/mach-s3c24xx/mach-rx1950.c
arch/arm/mach-s3c24xx/pm-s3c2410.c
arch/arm/mach-s3c24xx/pm-s3c2412.c
arch/arm/mach-s3c24xx/s3c2412.c
arch/arm/mach-s3c24xx/s3c244x.c
arch/arm/mach-s3c24xx/setup-spi.c
arch/arm/mach-s3c24xx/setup-ts.c
arch/arm/mach-s3c64xx/clock.c
arch/arm/mach-s3c64xx/include/mach/crag6410.h
arch/arm/mach-s3c64xx/include/mach/dma.h
arch/arm/mach-s3c64xx/include/mach/spi-clocks.h [deleted file]
arch/arm/mach-s3c64xx/mach-crag6410-module.c
arch/arm/mach-s3c64xx/mach-crag6410.c
arch/arm/mach-s3c64xx/mach-smdk6410.c
arch/arm/mach-s3c64xx/setup-spi.c
arch/arm/mach-s5p64x0/clock-s5p6440.c
arch/arm/mach-s5p64x0/clock-s5p6450.c
arch/arm/mach-s5p64x0/dma.c
arch/arm/mach-s5p64x0/include/mach/spi-clocks.h [deleted file]
arch/arm/mach-s5p64x0/setup-spi.c
arch/arm/mach-s5pc100/clock.c
arch/arm/mach-s5pc100/dma.c
arch/arm/mach-s5pc100/include/mach/spi-clocks.h [deleted file]
arch/arm/mach-s5pc100/setup-spi.c
arch/arm/mach-s5pv210/Kconfig
arch/arm/mach-s5pv210/clock.c
arch/arm/mach-s5pv210/include/mach/spi-clocks.h [deleted file]
arch/arm/mach-s5pv210/mach-aquila.c
arch/arm/mach-s5pv210/mach-goni.c
arch/arm/mach-s5pv210/mach-smdkv210.c
arch/arm/mach-s5pv210/setup-spi.c
arch/arm/mach-socfpga/Makefile [new file with mode: 0644]
arch/arm/mach-socfpga/Makefile.boot [new file with mode: 0644]
arch/arm/mach-socfpga/include/mach/debug-macro.S [new file with mode: 0644]
arch/arm/mach-socfpga/include/mach/timex.h [new file with mode: 0644]
arch/arm/mach-socfpga/include/mach/uncompress.h [new file with mode: 0644]
arch/arm/mach-socfpga/socfpga.c [new file with mode: 0644]
arch/arm/mach-tegra/Kconfig
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/Makefile.boot
arch/arm/mach-tegra/apbio.c
arch/arm/mach-tegra/apbio.h
arch/arm/mach-tegra/board-dt-tegra20.c
arch/arm/mach-tegra/board-dt-tegra30.c
arch/arm/mach-tegra/board-harmony-pcie.c
arch/arm/mach-tegra/board-harmony-power.c
arch/arm/mach-tegra/board-paz00.c
arch/arm/mach-tegra/board-seaboard-pinmux.c [deleted file]
arch/arm/mach-tegra/board-seaboard.c [deleted file]
arch/arm/mach-tegra/board-seaboard.h [deleted file]
arch/arm/mach-tegra/board.h
arch/arm/mach-tegra/common.c
arch/arm/mach-tegra/cpu-tegra.c
arch/arm/mach-tegra/cpuidle.c
arch/arm/mach-tegra/dma.c
arch/arm/mach-tegra/pcie.c
arch/arm/mach-tegra/powergate.c
arch/arm/mach-tegra/sleep.S
arch/arm/mach-tegra/tegra2_clocks.c
arch/arm/mach-tegra/tegra30_clocks.c
arch/arm/mach-tegra/timer.c
arch/arm/mach-tegra/usb_phy.c
arch/arm/mach-ux500/Kconfig
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-vexpress/Kconfig
arch/arm/mach-vexpress/Makefile.boot
arch/arm/mach-vexpress/ct-ca9x4.c
arch/arm/mach-vexpress/include/mach/clkdev.h [deleted file]
arch/arm/mach-vexpress/include/mach/debug-macro.S
arch/arm/mach-vexpress/include/mach/motherboard.h
arch/arm/mach-vexpress/include/mach/uncompress.h
arch/arm/mach-vexpress/v2m.c
arch/arm/mach-vt8500/Makefile
arch/arm/mach-vt8500/bv07.c
arch/arm/mach-vt8500/include/mach/restart.h [new file with mode: 0644]
arch/arm/mach-vt8500/include/mach/system.h [deleted file]
arch/arm/mach-vt8500/restart.c [new file with mode: 0644]
arch/arm/mach-vt8500/wm8505_7in.c
arch/arm/plat-mxc/3ds_debugboard.c
arch/arm/plat-mxc/Makefile
arch/arm/plat-mxc/avic.c
arch/arm/plat-mxc/cpuidle.c [new file with mode: 0644]
arch/arm/plat-mxc/devices/platform-ipu-core.c
arch/arm/plat-mxc/devices/platform-mxc_rtc.c
arch/arm/plat-mxc/devices/platform-spi_imx.c
arch/arm/plat-mxc/include/mach/3ds_debugboard.h
arch/arm/plat-mxc/include/mach/common.h
arch/arm/plat-mxc/include/mach/cpuidle.h [new file with mode: 0644]
arch/arm/plat-mxc/include/mach/devices-common.h
arch/arm/plat-mxc/include/mach/hardware.h
arch/arm/plat-mxc/include/mach/iomux-mx3.h
arch/arm/plat-mxc/include/mach/iomux-mx51.h
arch/arm/plat-mxc/include/mach/iomux-v1.h
arch/arm/plat-mxc/include/mach/ipu.h
arch/arm/plat-mxc/include/mach/irqs.h
arch/arm/plat-mxc/include/mach/mx1.h
arch/arm/plat-mxc/include/mach/mx21.h
arch/arm/plat-mxc/include/mach/mx25.h
arch/arm/plat-mxc/include/mach/mx27.h
arch/arm/plat-mxc/include/mach/mx2x.h
arch/arm/plat-mxc/include/mach/mx31.h
arch/arm/plat-mxc/include/mach/mx35.h
arch/arm/plat-mxc/include/mach/mx3x.h
arch/arm/plat-mxc/include/mach/mx50.h
arch/arm/plat-mxc/include/mach/mx51.h
arch/arm/plat-mxc/include/mach/mx53.h
arch/arm/plat-mxc/include/mach/mxc_ehci.h
arch/arm/plat-mxc/time.c
arch/arm/plat-mxc/tzic.c
arch/arm/plat-omap/Kconfig
arch/arm/plat-omap/Makefile
arch/arm/plat-omap/common.c
arch/arm/plat-omap/counter_32k.c
arch/arm/plat-omap/dma.c
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/include/plat/board.h
arch/arm/plat-omap/include/plat/clkdev_omap.h
arch/arm/plat-omap/include/plat/clock.h
arch/arm/plat-omap/include/plat/cpu.h
arch/arm/plat-omap/include/plat/dmtimer.h
arch/arm/plat-omap/include/plat/dsp.h
arch/arm/plat-omap/include/plat/hardware.h
arch/arm/plat-omap/include/plat/multi.h
arch/arm/plat-omap/include/plat/mux.h
arch/arm/plat-omap/include/plat/omap-secure.h
arch/arm/plat-omap/include/plat/omap54xx.h [new file with mode: 0644]
arch/arm/plat-omap/include/plat/omap730.h [deleted file]
arch/arm/plat-omap/include/plat/omap850.h [deleted file]
arch/arm/plat-omap/include/plat/omap_hwmod.h
arch/arm/plat-omap/include/plat/sdrc.h
arch/arm/plat-omap/include/plat/serial.h
arch/arm/plat-omap/include/plat/uncompress.h
arch/arm/plat-omap/include/plat/usb.h
arch/arm/plat-omap/include/plat/voltage.h
arch/arm/plat-omap/mailbox.c
arch/arm/plat-omap/sram.c
arch/arm/plat-omap/usb.c [deleted file]
arch/arm/plat-s3c24xx/irq.c
arch/arm/plat-samsung/Kconfig
arch/arm/plat-samsung/Makefile
arch/arm/plat-samsung/devs.c
arch/arm/plat-samsung/dma-ops.c
arch/arm/plat-samsung/include/plat/cpu.h
arch/arm/plat-samsung/include/plat/devs.h
arch/arm/plat-samsung/include/plat/dma-ops.h
arch/arm/plat-samsung/include/plat/fb.h
arch/arm/plat-samsung/include/plat/pd.h [deleted file]
arch/arm/plat-samsung/include/plat/s3c64xx-spi.h
arch/arm/plat-samsung/pd.c [deleted file]
arch/arm/plat-samsung/pwm.c
arch/arm/plat-samsung/s3c-dma-ops.c
arch/arm/plat-versatile/Kconfig
arch/arm/plat-versatile/Makefile
arch/blackfin/Kconfig
arch/blackfin/configs/BF609-EZKIT_defconfig
arch/blackfin/include/asm/bfin-global.h
arch/blackfin/include/asm/bfin_crc.h
arch/blackfin/include/asm/bfin_serial.h
arch/blackfin/include/asm/bfin_simple_timer.h
arch/blackfin/include/asm/bfin_twi.h
arch/blackfin/include/asm/context.S
arch/blackfin/include/asm/dpmc.h
arch/blackfin/include/asm/gpio.h
arch/blackfin/include/asm/irq.h
arch/blackfin/include/asm/mem_init.h
arch/blackfin/include/asm/traps.h
arch/blackfin/kernel/bfin_dma.c
arch/blackfin/kernel/cplb-nompu/cplbinit.c
arch/blackfin/kernel/dma-mapping.c
arch/blackfin/mach-bf527/boards/ezkit.c
arch/blackfin/mach-bf548/boards/ezkit.c
arch/blackfin/mach-bf548/include/mach/gpio.h
arch/blackfin/mach-bf561/boards/ezkit.c
arch/blackfin/mach-bf609/Kconfig
arch/blackfin/mach-bf609/Makefile
arch/blackfin/mach-bf609/boards/ezkit.c
arch/blackfin/mach-bf609/clock.c
arch/blackfin/mach-bf609/dpm.S [new file with mode: 0644]
arch/blackfin/mach-bf609/hibernate.S [deleted file]
arch/blackfin/mach-bf609/include/mach/anomaly.h
arch/blackfin/mach-bf609/include/mach/defBF60x_base.h
arch/blackfin/mach-bf609/include/mach/gpio.h
arch/blackfin/mach-bf609/include/mach/irq.h
arch/blackfin/mach-bf609/include/mach/pm.h
arch/blackfin/mach-bf609/ints-priority.c [new file with mode: 0644]
arch/blackfin/mach-bf609/pm.c
arch/blackfin/mach-common/clocks-init.c
arch/blackfin/mach-common/cpufreq.c
arch/blackfin/mach-common/entry.S
arch/blackfin/mach-common/ints-priority.c
arch/blackfin/mach-common/pm.c
arch/c6x/boot/dts/evmc6678.dts [new file with mode: 0644]
arch/c6x/boot/dts/tms320c6678.dtsi [new file with mode: 0644]
arch/c6x/configs/evmc6678_defconfig [new file with mode: 0644]
arch/c6x/include/asm/irq.h
arch/c6x/kernel/irq.c
arch/c6x/kernel/setup.c
arch/c6x/kernel/signal.c
arch/c6x/platforms/Kconfig
arch/c6x/platforms/megamod-pic.c
arch/c6x/platforms/plldata.c
arch/hexagon/kernel/smp.c
arch/ia64/kernel/smpboot.c
arch/ia64/mm/fault.c
arch/m32r/include/asm/smp.h
arch/mips/Kconfig
arch/mips/bcm47xx/Kconfig
arch/mips/bcm63xx/dev-pcmcia.c
arch/mips/cavium-octeon/Kconfig
arch/mips/cavium-octeon/smp.c
arch/mips/include/asm/cmpxchg.h
arch/mips/include/asm/cpu.h
arch/mips/include/asm/gic.h
arch/mips/include/asm/inst.h
arch/mips/include/asm/irq.h
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
arch/mips/include/asm/mips-boards/maltaint.h
arch/mips/include/asm/mipsmtregs.h
arch/mips/include/asm/switch_to.h
arch/mips/include/asm/thread_info.h
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/mips_ksyms.c
arch/mips/kernel/octeon_switch.S
arch/mips/kernel/perf_event_mipsxx.c
arch/mips/kernel/r2300_switch.S
arch/mips/kernel/r4k_switch.S
arch/mips/kernel/smp-bmips.c
arch/mips/kernel/smp.c
arch/mips/kernel/smtc.c
arch/mips/kernel/sync-r4k.c
arch/mips/kernel/traps.c
arch/mips/kernel/vmlinux.lds.S
arch/mips/mm/Makefile
arch/mips/mm/c-r4k.c
arch/mips/mm/page-funcs.S [new file with mode: 0644]
arch/mips/mm/page.c
arch/mips/mm/tlbex.c
arch/mips/mti-malta/malta-pci.c
arch/mips/mti-malta/malta-setup.c
arch/mips/netlogic/xlp/setup.c
arch/mips/oprofile/common.c
arch/mips/oprofile/op_model_mipsxx.c
arch/mips/pci/fixup-fuloong2e.c
arch/mips/pci/fixup-lemote2f.c
arch/mips/pci/fixup-malta.c
arch/mips/pci/fixup-mpc30x.c
arch/mips/pci/fixup-sb1250.c
arch/mips/pci/ops-tx4927.c
arch/mips/pci/pci-ip27.c
arch/mips/pci/pci-xlr.c
arch/mips/pmc-sierra/yosemite/smp.c
arch/mips/powertv/asic/asic-calliope.c
arch/mips/powertv/asic/asic-cronus.c
arch/mips/powertv/asic/asic-gaia.c
arch/mips/powertv/asic/asic-zeus.c
arch/mips/txx9/generic/pci.c
arch/mn10300/kernel/smp.c
arch/parisc/kernel/smp.c
arch/powerpc/Kconfig
arch/powerpc/Kconfig.debug
arch/powerpc/boot/Makefile
arch/powerpc/boot/dts/bsc9131rdb.dts [new file with mode: 0644]
arch/powerpc/boot/dts/bsc9131rdb.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/bsc9131si-pre.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/fsl/p1021si-post.dtsi
arch/powerpc/boot/dts/fsl/p3060si-post.dtsi [deleted file]
arch/powerpc/boot/dts/fsl/p3060si-pre.dtsi [deleted file]
arch/powerpc/boot/dts/mgcoge.dts
arch/powerpc/boot/dts/mpc8536ds.dtsi
arch/powerpc/boot/dts/mpc8544ds.dtsi
arch/powerpc/boot/dts/mpc8572ds.dtsi
arch/powerpc/boot/dts/mpc8572ds_camp_core0.dts
arch/powerpc/boot/dts/mpc8572ds_camp_core1.dts
arch/powerpc/boot/dts/p1010rdb.dtsi
arch/powerpc/boot/dts/p1021rdb-pc.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/p1021rdb-pc_32b.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1021rdb-pc_36b.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1021rdb.dts [deleted file]
arch/powerpc/boot/dts/p1021rdb.dtsi [deleted file]
arch/powerpc/boot/dts/p1021rdb_36b.dts [deleted file]
arch/powerpc/boot/dts/p1022ds.dtsi
arch/powerpc/boot/dts/p1024rdb.dtsi [new file with mode: 0644]
arch/powerpc/boot/dts/p1024rdb_32b.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1024rdb_36b.dts [new file with mode: 0644]
arch/powerpc/boot/dts/p1025rdb.dtsi
arch/powerpc/boot/dts/p2020ds.dtsi
arch/powerpc/boot/dts/p2020rdb.dts
arch/powerpc/boot/dts/p2041rdb.dts
arch/powerpc/boot/dts/p3060qds.dts [deleted file]
arch/powerpc/boot/dts/sbc8560.dts [deleted file]
arch/powerpc/boot/flatdevtree_env.h [deleted file]
arch/powerpc/configs/83xx/kmeter1_defconfig
arch/powerpc/configs/85xx/sbc8560_defconfig [deleted file]
arch/powerpc/configs/corenet32_smp_defconfig
arch/powerpc/configs/corenet64_smp_defconfig
arch/powerpc/configs/mgcoge_defconfig
arch/powerpc/configs/mpc85xx_defconfig
arch/powerpc/configs/mpc85xx_smp_defconfig
arch/powerpc/configs/ppc64_defconfig
arch/powerpc/configs/pseries_defconfig
arch/powerpc/include/asm/asm-compat.h
arch/powerpc/include/asm/code-patching.h
arch/powerpc/include/asm/device.h
arch/powerpc/include/asm/exception-64s.h
arch/powerpc/include/asm/immap_qe.h
arch/powerpc/include/asm/io.h
arch/powerpc/include/asm/iommu.h
arch/powerpc/include/asm/kvm_book3s_asm.h
arch/powerpc/include/asm/mmu.h
arch/powerpc/include/asm/perf_event.h
arch/powerpc/include/asm/ppc-opcode.h
arch/powerpc/include/asm/ppc_asm.h
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/qe.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/thread_info.h
arch/powerpc/include/asm/trace.h
arch/powerpc/include/asm/vdso.h
arch/powerpc/include/asm/vio.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/cpu_setup_a2.S
arch/powerpc/kernel/dma.c
arch/powerpc/kernel/entry_32.S
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/exceptions-64e.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/fpu.S
arch/powerpc/kernel/ftrace.c
arch/powerpc/kernel/head_fsl_booke.S
arch/powerpc/kernel/hw_breakpoint.c
arch/powerpc/kernel/idle_6xx.S
arch/powerpc/kernel/idle_book3e.S
arch/powerpc/kernel/idle_e500.S
arch/powerpc/kernel/idle_power4.S
arch/powerpc/kernel/iommu.c
arch/powerpc/kernel/kvm.c
arch/powerpc/kernel/misc_32.S
arch/powerpc/kernel/misc_64.S
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/pci_of_scan.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/setup_32.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/vdso.c
arch/powerpc/kernel/vdso32/Makefile
arch/powerpc/kernel/vdso32/getcpu.S [new file with mode: 0644]
arch/powerpc/kernel/vdso32/vdso32.lds.S
arch/powerpc/kernel/vdso64/Makefile
arch/powerpc/kernel/vdso64/getcpu.S [new file with mode: 0644]
arch/powerpc/kernel/vdso64/vdso64.lds.S
arch/powerpc/kernel/vio.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_interrupts.S
arch/powerpc/kvm/book3s_rmhandlers.S
arch/powerpc/kvm/book3s_segment.S
arch/powerpc/kvm/booke_interrupts.S
arch/powerpc/kvm/bookehv_interrupts.S
arch/powerpc/lib/Makefile
arch/powerpc/lib/checksum_64.S
arch/powerpc/lib/code-patching.c
arch/powerpc/lib/copypage_64.S
arch/powerpc/lib/copypage_power7.S [new file with mode: 0644]
arch/powerpc/lib/copyuser_power7.S
arch/powerpc/lib/copyuser_power7_vmx.c [deleted file]
arch/powerpc/lib/crtsavres.S
arch/powerpc/lib/hweight_64.S
arch/powerpc/lib/ldstfp.S
arch/powerpc/lib/memcpy_64.S
arch/powerpc/lib/memcpy_power7.S [new file with mode: 0644]
arch/powerpc/lib/string.S
arch/powerpc/lib/string_64.S [new file with mode: 0644]
arch/powerpc/lib/vmx-helper.c [new file with mode: 0644]
arch/powerpc/mm/hash_low_32.S
arch/powerpc/mm/hash_low_64.S
arch/powerpc/mm/numa.c
arch/powerpc/mm/tlb_low_64e.S
arch/powerpc/mm/tlb_nohash_low.S
arch/powerpc/net/bpf_jit.h
arch/powerpc/net/bpf_jit_comp.c
arch/powerpc/perf/callchain.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/platforms/44x/currituck.c
arch/powerpc/platforms/82xx/km82xx.c
arch/powerpc/platforms/83xx/km83xx.c
arch/powerpc/platforms/85xx/Kconfig
arch/powerpc/platforms/85xx/Makefile
arch/powerpc/platforms/85xx/bsc913x_rdb.c [new file with mode: 0644]
arch/powerpc/platforms/85xx/corenet_ds.c
arch/powerpc/platforms/85xx/ge_imp3a.c
arch/powerpc/platforms/85xx/mpc8536_ds.c
arch/powerpc/platforms/85xx/mpc85xx_ds.c
arch/powerpc/platforms/85xx/mpc85xx_mds.c
arch/powerpc/platforms/85xx/mpc85xx_rdb.c
arch/powerpc/platforms/85xx/p1022_ds.c
arch/powerpc/platforms/85xx/p3060_qds.c [deleted file]
arch/powerpc/platforms/85xx/qemu_e500.c [new file with mode: 0644]
arch/powerpc/platforms/85xx/sbc8560.c [deleted file]
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
arch/powerpc/platforms/Kconfig.cputype
arch/powerpc/platforms/cell/beat_hvCall.S
arch/powerpc/platforms/cell/iommu.c
arch/powerpc/platforms/cell/spufs/inode.c
arch/powerpc/platforms/powernv/opal-takeover.S
arch/powerpc/platforms/pseries/eeh_event.c
arch/powerpc/platforms/pseries/eeh_pseries.c
arch/powerpc/platforms/pseries/hvCall.S
arch/powerpc/platforms/pseries/iommu.c
arch/powerpc/platforms/pseries/mobility.c
arch/powerpc/platforms/pseries/processor_idle.c
arch/powerpc/platforms/pseries/reconfig.c
arch/powerpc/platforms/pseries/smp.c
arch/powerpc/sysdev/6xx-suspend.S
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/fsl_pci.h
arch/powerpc/sysdev/mpic.c
arch/powerpc/sysdev/qe_lib/qe.c
arch/s390/appldata/appldata.h
arch/s390/appldata/appldata_base.c
arch/s390/appldata/appldata_mem.c
arch/s390/appldata/appldata_net_sum.c
arch/s390/appldata/appldata_os.c
arch/s390/crypto/aes_s390.c
arch/s390/crypto/crypt_s390.h
arch/s390/crypto/des_s390.c
arch/s390/crypto/prng.c
arch/s390/crypto/sha1_s390.c
arch/s390/crypto/sha256_s390.c
arch/s390/hypfs/hypfs.h
arch/s390/hypfs/hypfs_dbfs.c
arch/s390/hypfs/hypfs_diag.c
arch/s390/hypfs/hypfs_vm.c
arch/s390/hypfs/inode.c
arch/s390/include/asm/airq.h
arch/s390/include/asm/appldata.h
arch/s390/include/asm/atomic.h
arch/s390/include/asm/bitops.h
arch/s390/include/asm/bugs.h
arch/s390/include/asm/cache.h
arch/s390/include/asm/ccwdev.h
arch/s390/include/asm/ccwgroup.h
arch/s390/include/asm/checksum.h
arch/s390/include/asm/chpid.h
arch/s390/include/asm/chsc.h
arch/s390/include/asm/cio.h
arch/s390/include/asm/cpcmd.h
arch/s390/include/asm/cpu.h
arch/s390/include/asm/cputime.h
arch/s390/include/asm/crw.h
arch/s390/include/asm/current.h
arch/s390/include/asm/dasd.h
arch/s390/include/asm/debug.h
arch/s390/include/asm/delay.h
arch/s390/include/asm/dma.h
arch/s390/include/asm/ebcdic.h
arch/s390/include/asm/elf.h
arch/s390/include/asm/errno.h
arch/s390/include/asm/etr.h
arch/s390/include/asm/extmem.h
arch/s390/include/asm/hardirq.h
arch/s390/include/asm/idals.h
arch/s390/include/asm/io.h
arch/s390/include/asm/irqflags.h
arch/s390/include/asm/kexec.h
arch/s390/include/asm/kprobes.h
arch/s390/include/asm/kvm.h
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/kvm_para.h
arch/s390/include/asm/kvm_virtio.h
arch/s390/include/asm/lowcore.h
arch/s390/include/asm/mathemu.h
arch/s390/include/asm/mman.h
arch/s390/include/asm/mmu_context.h
arch/s390/include/asm/monwriter.h
arch/s390/include/asm/nmi.h
arch/s390/include/asm/page.h
arch/s390/include/asm/pgalloc.h
arch/s390/include/asm/pgtable.h
arch/s390/include/asm/posix_types.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/ptrace.h
arch/s390/include/asm/qdio.h
arch/s390/include/asm/qeth.h
arch/s390/include/asm/reset.h
arch/s390/include/asm/resource.h
arch/s390/include/asm/rwsem.h
arch/s390/include/asm/sclp.h
arch/s390/include/asm/scsw.h
arch/s390/include/asm/setup.h
arch/s390/include/asm/shmparam.h
arch/s390/include/asm/sigcontext.h
arch/s390/include/asm/siginfo.h
arch/s390/include/asm/signal.h
arch/s390/include/asm/sigp.h [new file with mode: 0644]
arch/s390/include/asm/smp.h
arch/s390/include/asm/socket.h
arch/s390/include/asm/spinlock.h
arch/s390/include/asm/stat.h
arch/s390/include/asm/statfs.h
arch/s390/include/asm/string.h
arch/s390/include/asm/swab.h
arch/s390/include/asm/sysinfo.h
arch/s390/include/asm/tape390.h
arch/s390/include/asm/termios.h
arch/s390/include/asm/thread_info.h
arch/s390/include/asm/timer.h [deleted file]
arch/s390/include/asm/timex.h
arch/s390/include/asm/types.h
arch/s390/include/asm/uaccess.h
arch/s390/include/asm/ucontext.h
arch/s390/include/asm/unistd.h
arch/s390/include/asm/user.h
arch/s390/include/asm/vtimer.h [new file with mode: 0644]
arch/s390/include/asm/vtoc.h
arch/s390/include/asm/zcrypt.h
arch/s390/kernel/asm-offsets.c
arch/s390/kernel/base.S
arch/s390/kernel/bitmap.c
arch/s390/kernel/compat_exec_domain.c
arch/s390/kernel/compat_linux.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/compat_wrapper.S
arch/s390/kernel/cpcmd.c
arch/s390/kernel/crash.c
arch/s390/kernel/debug.c
arch/s390/kernel/dis.c
arch/s390/kernel/early.c
arch/s390/kernel/ebcdic.c
arch/s390/kernel/entry.S
arch/s390/kernel/entry.h
arch/s390/kernel/entry64.S
arch/s390/kernel/head.S
arch/s390/kernel/head31.S
arch/s390/kernel/head64.S
arch/s390/kernel/head_kdump.S
arch/s390/kernel/ipl.c
arch/s390/kernel/irq.c
arch/s390/kernel/kprobes.c
arch/s390/kernel/lgr.c
arch/s390/kernel/machine_kexec.c
arch/s390/kernel/mcount.S
arch/s390/kernel/mcount64.S
arch/s390/kernel/module.c
arch/s390/kernel/nmi.c
arch/s390/kernel/os_info.c
arch/s390/kernel/process.c
arch/s390/kernel/processor.c
arch/s390/kernel/ptrace.c
arch/s390/kernel/reipl.S
arch/s390/kernel/reipl64.S
arch/s390/kernel/relocate_kernel.S
arch/s390/kernel/relocate_kernel64.S
arch/s390/kernel/sclp.S
arch/s390/kernel/setup.c
arch/s390/kernel/signal.c
arch/s390/kernel/smp.c
arch/s390/kernel/stacktrace.c
arch/s390/kernel/swsusp_asm64.S
arch/s390/kernel/sys_s390.c
arch/s390/kernel/time.c
arch/s390/kernel/topology.c
arch/s390/kernel/traps.c
arch/s390/kernel/vtime.c
arch/s390/kvm/diag.c
arch/s390/kvm/gaccess.h
arch/s390/kvm/intercept.c
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/kvm-s390.h
arch/s390/kvm/priv.c
arch/s390/kvm/sigp.c
arch/s390/lib/delay.c
arch/s390/lib/div64.c
arch/s390/lib/spinlock.c
arch/s390/lib/string.c
arch/s390/lib/uaccess.h
arch/s390/lib/uaccess_mvcos.c
arch/s390/lib/uaccess_pt.c
arch/s390/lib/uaccess_std.c
arch/s390/math-emu/math.c
arch/s390/mm/cmm.c
arch/s390/mm/extmem.c
arch/s390/mm/fault.c
arch/s390/mm/hugetlbpage.c
arch/s390/mm/init.c
arch/s390/mm/mmap.c
arch/s390/mm/pgtable.c
arch/s390/mm/vmem.c
arch/s390/oprofile/backtrace.c
arch/s390/oprofile/hwsampler.c
arch/s390/oprofile/init.c
arch/s390/oprofile/op_counter.h
arch/sh/Kconfig
arch/sh/boards/Kconfig
arch/sh/boards/mach-dreamcast/irq.c
arch/sh/boards/mach-se/7343/irq.c
arch/sh/boards/mach-se/7343/setup.c
arch/sh/boards/mach-se/7722/irq.c
arch/sh/boards/mach-se/7722/setup.c
arch/sh/boards/mach-se/7724/irq.c
arch/sh/boards/mach-x3proto/gpio.c
arch/sh/cchips/hd6446x/hd64461.c
arch/sh/include/asm/bug.h
arch/sh/include/asm/kdebug.h
arch/sh/include/mach-se/mach/se7343.h
arch/sh/include/mach-se/mach/se7722.h
arch/sh/kernel/cpu/sh5/unwind.c
arch/sh/kernel/dumpstack.c
arch/sh/kernel/irq.c
arch/sh/kernel/traps.c
arch/sh/kernel/traps_32.c
arch/sh/kernel/traps_64.c
arch/sh/lib64/Makefile
arch/sh/lib64/dbg.c [deleted file]
arch/sh/mm/tlb-sh5.c
arch/sparc/kernel/smp_64.c
arch/tile/Kconfig
arch/tile/Makefile
arch/tile/gxio/Kconfig [new file with mode: 0644]
arch/tile/gxio/Makefile [new file with mode: 0644]
arch/tile/gxio/dma_queue.c [new file with mode: 0644]
arch/tile/gxio/iorpc_globals.c [new file with mode: 0644]
arch/tile/gxio/iorpc_mpipe.c [new file with mode: 0644]
arch/tile/gxio/iorpc_mpipe_info.c [new file with mode: 0644]
arch/tile/gxio/iorpc_trio.c [new file with mode: 0644]
arch/tile/gxio/iorpc_usb_host.c [new file with mode: 0644]
arch/tile/gxio/kiorpc.c [new file with mode: 0644]
arch/tile/gxio/mpipe.c [new file with mode: 0644]
arch/tile/gxio/trio.c [new file with mode: 0644]
arch/tile/gxio/usb_host.c [new file with mode: 0644]
arch/tile/include/arch/mpipe.h [new file with mode: 0644]
arch/tile/include/arch/mpipe_constants.h [new file with mode: 0644]
arch/tile/include/arch/mpipe_def.h [new file with mode: 0644]
arch/tile/include/arch/mpipe_shm.h [new file with mode: 0644]
arch/tile/include/arch/mpipe_shm_def.h [new file with mode: 0644]
arch/tile/include/arch/trio.h [new file with mode: 0644]
arch/tile/include/arch/trio_constants.h [new file with mode: 0644]
arch/tile/include/arch/trio_def.h [new file with mode: 0644]
arch/tile/include/arch/trio_pcie_intfc.h [new file with mode: 0644]
arch/tile/include/arch/trio_pcie_intfc_def.h [new file with mode: 0644]
arch/tile/include/arch/trio_pcie_rc.h [new file with mode: 0644]
arch/tile/include/arch/trio_pcie_rc_def.h [new file with mode: 0644]
arch/tile/include/arch/trio_shm.h [new file with mode: 0644]
arch/tile/include/arch/trio_shm_def.h [new file with mode: 0644]
arch/tile/include/arch/usb_host.h [new file with mode: 0644]
arch/tile/include/arch/usb_host_def.h [new file with mode: 0644]
arch/tile/include/asm/Kbuild
arch/tile/include/asm/cache.h
arch/tile/include/asm/checksum.h
arch/tile/include/asm/device.h [new file with mode: 0644]
arch/tile/include/asm/dma-mapping.h
arch/tile/include/asm/fixmap.h
arch/tile/include/asm/homecache.h
arch/tile/include/asm/io.h
arch/tile/include/asm/memprof.h [deleted file]
arch/tile/include/asm/page.h
arch/tile/include/asm/pci.h
arch/tile/include/gxio/common.h [new file with mode: 0644]
arch/tile/include/gxio/dma_queue.h [new file with mode: 0644]
arch/tile/include/gxio/iorpc_globals.h [new file with mode: 0644]
arch/tile/include/gxio/iorpc_mpipe.h [new file with mode: 0644]
arch/tile/include/gxio/iorpc_mpipe_info.h [new file with mode: 0644]
arch/tile/include/gxio/iorpc_trio.h [new file with mode: 0644]
arch/tile/include/gxio/iorpc_usb_host.h [new file with mode: 0644]
arch/tile/include/gxio/kiorpc.h [new file with mode: 0644]
arch/tile/include/gxio/mpipe.h [new file with mode: 0644]
arch/tile/include/gxio/trio.h [new file with mode: 0644]
arch/tile/include/gxio/usb_host.h [new file with mode: 0644]
arch/tile/include/hv/drv_mpipe_intf.h [new file with mode: 0644]
arch/tile/include/hv/drv_trio_intf.h [new file with mode: 0644]
arch/tile/include/hv/drv_usb_host_intf.h [new file with mode: 0644]
arch/tile/include/hv/iorpc.h [new file with mode: 0644]
arch/tile/kernel/Makefile
arch/tile/kernel/pci-dma.c
arch/tile/kernel/pci_gx.c [new file with mode: 0644]
arch/tile/kernel/setup.c
arch/tile/kernel/smpboot.c
arch/tile/kernel/usb.c [new file with mode: 0644]
arch/tile/lib/checksum.c
arch/tile/mm/homecache.c
arch/tile/mm/init.c
arch/tile/mm/pgtable.c
arch/x86/Makefile
arch/x86/include/asm/alternative.h
arch/x86/include/asm/amd_nb.h
arch/x86/include/asm/apic.h
arch/x86/include/asm/emergency-restart.h
arch/x86/include/asm/floppy.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/msr.h
arch/x86/include/asm/nmi.h
arch/x86/include/asm/paravirt.h
arch/x86/include/asm/paravirt_types.h
arch/x86/include/asm/pci_x86.h
arch/x86/include/asm/perf_event.h
arch/x86/include/asm/pgtable-2level.h
arch/x86/include/asm/pgtable-3level.h
arch/x86/include/asm/pgtable_64.h
arch/x86/include/asm/realmode.h
arch/x86/include/asm/reboot.h
arch/x86/include/asm/smp.h
arch/x86/include/asm/uaccess_64.h
arch/x86/include/asm/uprobes.h
arch/x86/include/asm/uv/uv_bau.h
arch/x86/include/asm/x2apic.h
arch/x86/include/asm/x86_init.h
arch/x86/kernel/alternative.c
arch/x86/kernel/amd_nb.c
arch/x86/kernel/apic/apic.c
arch/x86/kernel/apic/apic_flat_64.c
arch/x86/kernel/apic/apic_noop.c
arch/x86/kernel/apic/apic_numachip.c
arch/x86/kernel/apic/bigsmp_32.c
arch/x86/kernel/apic/es7000_32.c
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/numaq_32.c
arch/x86/kernel/apic/probe_32.c
arch/x86/kernel/apic/probe_64.c
arch/x86/kernel/apic/summit_32.c
arch/x86/kernel/apic/x2apic_cluster.c
arch/x86/kernel/apic/x2apic_phys.c
arch/x86/kernel/apic/x2apic_uv_x.c
arch/x86/kernel/apm_32.c
arch/x86/kernel/cpu/Makefile
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/common.c
arch/x86/kernel/cpu/mcheck/mce.c
arch/x86/kernel/cpu/mcheck/mce_amd.c
arch/x86/kernel/cpu/mtrr/cleanup.c
arch/x86/kernel/cpu/mtrr/generic.c
arch/x86/kernel/cpu/perf_event.c
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_amd.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_ds.c
arch/x86/kernel/cpu/perf_event_intel_uncore.c [new file with mode: 0644]
arch/x86/kernel/cpu/perf_event_intel_uncore.h [new file with mode: 0644]
arch/x86/kernel/cpu/perf_event_p4.c
arch/x86/kernel/cpu/perf_event_p6.c
arch/x86/kernel/dumpstack.c
arch/x86/kernel/dumpstack_32.c
arch/x86/kernel/dumpstack_64.c
arch/x86/kernel/entry_64.S
arch/x86/kernel/irq.c
arch/x86/kernel/microcode_core.c
arch/x86/kernel/module.c
arch/x86/kernel/nmi.c
arch/x86/kernel/nmi_selftest.c
arch/x86/kernel/paravirt.c
arch/x86/kernel/pci-calgary_64.c
arch/x86/kernel/process.c
arch/x86/kernel/process_64.c
arch/x86/kernel/reboot.c
arch/x86/kernel/setup.c
arch/x86/kernel/signal.c
arch/x86/kernel/smpboot.c
arch/x86/kernel/traps.c
arch/x86/kernel/tsc.c
arch/x86/kernel/uprobes.c
arch/x86/kernel/vm86_32.c
arch/x86/kernel/vsmp_64.c
arch/x86/kernel/vsyscall_64.c
arch/x86/kernel/x8664_ksyms_64.c
arch/x86/kernel/x86_init.c
arch/x86/kernel/xsave.c
arch/x86/kvm/pmu.c
arch/x86/kvm/trace.h
arch/x86/lib/msr-reg-export.c
arch/x86/lib/msr-reg.S
arch/x86/mm/init.c
arch/x86/oprofile/op_model_amd.c
arch/x86/platform/olpc/olpc-xo15-sci.c
arch/x86/platform/uv/tlb_uv.c
arch/x86/platform/uv/uv_irq.c
arch/x86/realmode/rm/Makefile
arch/x86/realmode/rm/header.S
arch/x86/realmode/rm/reboot.S [new file with mode: 0644]
arch/x86/realmode/rm/reboot_32.S [deleted file]
arch/x86/vdso/vdso32-setup.c
arch/x86/xen/enlighten.c
arch/x86/xen/smp.c
drivers/acpi/ac.c
drivers/acpi/battery.c
drivers/acpi/button.c
drivers/acpi/fan.c
drivers/acpi/power.c
drivers/acpi/processor_driver.c
drivers/acpi/processor_idle.c
drivers/acpi/sbs.c
drivers/acpi/scan.c
drivers/acpi/thermal.c
drivers/amba/tegra-ahb.c
drivers/base/devtmpfs.c
drivers/base/power/domain.c
drivers/base/power/main.c
drivers/base/power/qos.c
drivers/base/power/sysfs.c
drivers/base/regmap/internal.h
drivers/base/regmap/regmap-irq.c
drivers/base/regmap/regmap-mmio.c
drivers/base/regmap/regmap.c
drivers/block/mg_disk.c
drivers/block/rbd.c
drivers/char/hw_random/omap-rng.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/mem.c
drivers/char/sonypi.c
drivers/char/tpm/tpm.c
drivers/char/tpm/tpm.h
drivers/char/tpm/tpm_atmel.c
drivers/char/tpm/tpm_infineon.c
drivers/char/tpm/tpm_nsc.c
drivers/char/tpm/tpm_tis.c
drivers/clk/Makefile
drivers/clk/clk-nomadik.c [new file with mode: 0644]
drivers/clk/socfpga/Makefile [new file with mode: 0644]
drivers/clk/socfpga/clk.c [new file with mode: 0644]
drivers/clocksource/Kconfig
drivers/clocksource/Makefile
drivers/clocksource/dw_apb_timer_of.c [new file with mode: 0644]
drivers/clocksource/time-armada-370-xp.c [new file with mode: 0644]
drivers/cpufreq/cpufreq.c
drivers/cpufreq/exynos-cpufreq.c
drivers/cpuidle/cpuidle.c
drivers/cpuidle/driver.c
drivers/cpuidle/governors/menu.c
drivers/cpuidle/sysfs.c
drivers/crypto/tegra-aes.c
drivers/crypto/ux500/cryp/cryp_core.c
drivers/crypto/ux500/hash/hash_core.c
drivers/dma/ipu/ipu_idmac.c
drivers/dma/ipu/ipu_irq.c
drivers/gpio/gpio-mxc.c
drivers/hwmon/acpi_power_meter.c
drivers/hwmon/k10temp.c
drivers/i2c/busses/i2c-imx.c
drivers/i2c/busses/i2c-nomadik.c
drivers/i2c/busses/i2c-powermac.c
drivers/i2c/busses/i2c-tegra.c
drivers/idle/intel_idle.c
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/input/keyboard/tegra-kbc.c
drivers/iommu/dmar.c
drivers/iommu/intel_irq_remapping.c
drivers/iommu/irq_remapping.c
drivers/iommu/irq_remapping.h
drivers/md/dm-raid1.c
drivers/md/dm-region-hash.c
drivers/md/dm-thin.c
drivers/media/video/mx1_camera.c
drivers/media/video/zoran/zoran.h
drivers/media/video/zoran/zoran_driver.c
drivers/mfd/tps65217.c
drivers/mmc/card/block.c
drivers/mmc/core/Makefile
drivers/mmc/core/cd-gpio.c [deleted file]
drivers/mmc/core/core.c
drivers/mmc/core/host.c
drivers/mmc/core/mmc.c
drivers/mmc/core/mmc_ops.c
drivers/mmc/core/sd.c
drivers/mmc/core/sdio.c
drivers/mmc/core/sdio_cis.c
drivers/mmc/core/slot-gpio.c [new file with mode: 0644]
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/mxs-mmc.c
drivers/mmc/host/omap_hsmmc.c
drivers/mmc/host/s3cmci.c
drivers/mmc/host/sdhci-dove.c
drivers/mmc/host/sdhci-esdhc-imx.c
drivers/mmc/host/sdhci-pci.c
drivers/mmc/host/sdhci-pxav2.c
drivers/mmc/host/sdhci-pxav3.c
drivers/mmc/host/sdhci-tegra.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h
drivers/mmc/host/sh_mmcif.c
drivers/mmc/host/sh_mobile_sdhi.c
drivers/mmc/host/tmio_mmc_pio.c
drivers/mtd/mtdsuper.c
drivers/mtd/ubi/Kconfig
drivers/mtd/ubi/cdev.c
drivers/mtd/ubi/misc.c
drivers/mtd/ubi/ubi.h
drivers/mtd/ubi/vmt.c
drivers/of/base.c
drivers/oprofile/oprofile_perf.c
drivers/pci/quirks.c
drivers/pinctrl/pinctrl-nomadik.c
drivers/pinctrl/pinctrl-sirf.c
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/classmate-laptop.c
drivers/platform/x86/fujitsu-tablet.c
drivers/platform/x86/hdaps.c
drivers/platform/x86/hp_accel.c
drivers/platform/x86/intel_ips.c
drivers/platform/x86/intel_mid_thermal.c
drivers/platform/x86/msi-laptop.c
drivers/platform/x86/panasonic-laptop.c
drivers/platform/x86/sony-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/platform/x86/toshiba_acpi.c
drivers/platform/x86/toshiba_bluetooth.c
drivers/platform/x86/xo15-ebook.c
drivers/power/Kconfig
drivers/power/Makefile
drivers/power/avs/Kconfig [new file with mode: 0644]
drivers/power/avs/Makefile [new file with mode: 0644]
drivers/power/avs/smartreflex.c [new file with mode: 0644]
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/aat2870-regulator.c
drivers/regulator/ab3100.c
drivers/regulator/ab8500.c
drivers/regulator/ad5398.c
drivers/regulator/anatop-regulator.c
drivers/regulator/arizona-ldo1.c [new file with mode: 0644]
drivers/regulator/arizona-micsupp.c [new file with mode: 0644]
drivers/regulator/core.c
drivers/regulator/da903x.c
drivers/regulator/da9052-regulator.c
drivers/regulator/fixed-helper.c
drivers/regulator/fixed.c
drivers/regulator/gpio-regulator.c
drivers/regulator/isl6271a-regulator.c
drivers/regulator/lp3971.c
drivers/regulator/lp3972.c
drivers/regulator/lp872x.c [new file with mode: 0644]
drivers/regulator/lp8788-buck.c [new file with mode: 0644]
drivers/regulator/lp8788-ldo.c [new file with mode: 0644]
drivers/regulator/max1586.c
drivers/regulator/max77686.c [new file with mode: 0644]
drivers/regulator/max8952.c
drivers/regulator/max8997.c
drivers/regulator/max8998.c
drivers/regulator/mc13783-regulator.c
drivers/regulator/mc13892-regulator.c
drivers/regulator/mc13xxx-regulator-core.c
drivers/regulator/mc13xxx.h
drivers/regulator/of_regulator.c
drivers/regulator/palmas-regulator.c
drivers/regulator/pcap-regulator.c
drivers/regulator/pcf50633-regulator.c
drivers/regulator/rc5t583-regulator.c
drivers/regulator/s2mps11.c [new file with mode: 0644]
drivers/regulator/s5m8767.c
drivers/regulator/tps6105x-regulator.c
drivers/regulator/tps62360-regulator.c
drivers/regulator/tps65023-regulator.c
drivers/regulator/tps6507x-regulator.c
drivers/regulator/tps65217-regulator.c
drivers/regulator/tps6524x-regulator.c
drivers/regulator/tps6586x-regulator.c
drivers/regulator/tps65910-regulator.c
drivers/regulator/twl-regulator.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-ldo.c
drivers/regulator/wm8350-regulator.c
drivers/regulator/wm8400-regulator.c
drivers/regulator/wm8994-regulator.c
drivers/rtc/rtc-at91rm9200.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-stmp3xxx.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_3990_erp.c
drivers/s390/block/dasd_alias.c
drivers/s390/block/dasd_devmap.c
drivers/s390/block/dasd_diag.c
drivers/s390/block/dasd_diag.h
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_eckd.h
drivers/s390/block/dasd_eer.c
drivers/s390/block/dasd_erp.c
drivers/s390/block/dasd_fba.c
drivers/s390/block/dasd_fba.h
drivers/s390/block/dasd_genhd.c
drivers/s390/block/dasd_int.h
drivers/s390/block/dasd_ioctl.c
drivers/s390/block/dasd_proc.c
drivers/s390/char/ctrlchar.c
drivers/s390/char/ctrlchar.h
drivers/s390/char/keyboard.c
drivers/s390/char/keyboard.h
drivers/s390/char/sclp_config.c
drivers/s390/char/sclp_cpi.c
drivers/s390/char/sclp_cpi_sys.c
drivers/s390/char/sclp_cpi_sys.h
drivers/s390/char/sclp_ocf.c
drivers/s390/char/sclp_quiesce.c
drivers/s390/char/sclp_sdias.c
drivers/s390/char/sclp_tty.c
drivers/s390/char/sclp_tty.h
drivers/s390/char/tape.h
drivers/s390/char/tape_34xx.c
drivers/s390/char/tape_3590.c
drivers/s390/char/tape_3590.h
drivers/s390/char/tape_char.c
drivers/s390/char/tape_class.c
drivers/s390/char/tape_class.h
drivers/s390/char/tape_core.c
drivers/s390/char/tape_proc.c
drivers/s390/char/tape_std.c
drivers/s390/char/tape_std.h
drivers/s390/char/tty3270.c
drivers/s390/char/tty3270.h
drivers/s390/char/vmcp.c
drivers/s390/char/vmcp.h
drivers/s390/char/vmlogrdr.c
drivers/s390/char/vmwatchdog.c
drivers/s390/char/zcore.c
drivers/s390/cio/airq.c
drivers/s390/cio/blacklist.c
drivers/s390/cio/chp.c
drivers/s390/cio/chp.h
drivers/s390/cio/chsc.c
drivers/s390/cio/cio.c
drivers/s390/cio/cmf.c
drivers/s390/cio/crw.c
drivers/s390/cio/device.c
drivers/s390/cio/device_fsm.c
drivers/s390/cio/device_id.c
drivers/s390/cio/device_pgid.c
drivers/s390/cio/device_status.c
drivers/s390/cio/idset.c
drivers/s390/cio/idset.h
drivers/s390/cio/qdio.h
drivers/s390/cio/qdio_debug.c
drivers/s390/cio/qdio_debug.h
drivers/s390/cio/qdio_main.c
drivers/s390/cio/qdio_setup.c
drivers/s390/cio/qdio_thinint.c
drivers/s390/crypto/ap_bus.c
drivers/s390/crypto/ap_bus.h
drivers/s390/crypto/zcrypt_api.c
drivers/s390/crypto/zcrypt_api.h
drivers/s390/crypto/zcrypt_cca_key.h
drivers/s390/crypto/zcrypt_cex2a.c
drivers/s390/crypto/zcrypt_cex2a.h
drivers/s390/crypto/zcrypt_error.h
drivers/s390/crypto/zcrypt_pcica.c
drivers/s390/crypto/zcrypt_pcica.h
drivers/s390/crypto/zcrypt_pcicc.c
drivers/s390/crypto/zcrypt_pcicc.h
drivers/s390/crypto/zcrypt_pcixcc.c
drivers/s390/crypto/zcrypt_pcixcc.h
drivers/s390/kvm/kvm_virtio.c
drivers/s390/net/claw.c
drivers/s390/net/ctcm_dbug.c
drivers/s390/net/ctcm_dbug.h
drivers/s390/net/ctcm_fsms.c
drivers/s390/net/ctcm_fsms.h
drivers/s390/net/ctcm_main.c
drivers/s390/net/ctcm_main.h
drivers/s390/net/ctcm_mpc.c
drivers/s390/net/ctcm_mpc.h
drivers/s390/net/ctcm_sysfs.c
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_core_mpc.c
drivers/s390/net/qeth_core_mpc.h
drivers/s390/net/qeth_core_sys.c
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3.h
drivers/s390/net/qeth_l3_main.c
drivers/s390/net/qeth_l3_sys.c
drivers/s390/net/smsgiucv.h
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_ccw.c
drivers/s390/scsi/zfcp_cfdc.c
drivers/s390/scsi/zfcp_dbf.c
drivers/s390/scsi/zfcp_def.h
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_ext.h
drivers/s390/scsi/zfcp_fc.c
drivers/s390/scsi/zfcp_fc.h
drivers/s390/scsi/zfcp_fsf.c
drivers/s390/scsi/zfcp_fsf.h
drivers/s390/scsi/zfcp_qdio.c
drivers/s390/scsi/zfcp_qdio.h
drivers/s390/scsi/zfcp_reqlist.h
drivers/s390/scsi/zfcp_scsi.c
drivers/s390/scsi/zfcp_sysfs.c
drivers/s390/scsi/zfcp_unit.c
drivers/scsi/qla2xxx/qla_target.c
drivers/scsi/qla2xxx/qla_target.h
drivers/scsi/qla2xxx/tcm_qla2xxx.c
drivers/sh/Kconfig
drivers/sh/Makefile
drivers/sh/clk/cpg.c
drivers/sh/intc/Makefile
drivers/sh/intc/dynamic.c [deleted file]
drivers/sh/intc/virq.c
drivers/sh/pfc.c [deleted file]
drivers/sh/pfc/Kconfig [new file with mode: 0644]
drivers/sh/pfc/Makefile [new file with mode: 0644]
drivers/sh/pfc/core.c [new file with mode: 0644]
drivers/sh/pfc/gpio.c [new file with mode: 0644]
drivers/sh/pfc/pinctrl.c [new file with mode: 0644]
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-tegra.c
drivers/staging/nvec/nvec.c
drivers/staging/omapdrm/omap_drv.h
drivers/staging/omapdrm/omap_priv.h [deleted file]
drivers/target/Makefile
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_core.h
drivers/target/iscsi/iscsi_target_erl1.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/iscsi/iscsi_target_parameters.c
drivers/target/iscsi/iscsi_target_tmr.c
drivers/target/iscsi/iscsi_target_tpg.c
drivers/target/loopback/tcm_loop.c
drivers/target/sbp/sbp_target.c
drivers/target/target_core_cdb.c [deleted file]
drivers/target/target_core_device.c
drivers/target/target_core_fabric_configfs.c
drivers/target/target_core_file.c
drivers/target/target_core_iblock.c
drivers/target/target_core_iblock.h
drivers/target/target_core_internal.h
drivers/target/target_core_pr.c
drivers/target/target_core_pscsi.c
drivers/target/target_core_rd.c
drivers/target/target_core_sbc.c [new file with mode: 0644]
drivers/target/target_core_spc.c [new file with mode: 0644]
drivers/target/target_core_tmr.c
drivers/target/target_core_tpg.c
drivers/target/target_core_transport.c
drivers/target/tcm_fc/tfc_cmd.c
drivers/target/tcm_fc/tfc_io.c
drivers/tty/serial/imx.c
drivers/tty/serial/mxs-auart.c
drivers/usb/gadget/Kconfig
drivers/usb/gadget/omap_udc.c
drivers/usb/gadget/tcm_usb_gadget.c
drivers/usb/host/Kconfig
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-tegra.c
drivers/usb/host/ehci-tilegx.c [new file with mode: 0644]
drivers/usb/host/ohci-hcd.c
drivers/usb/host/ohci-omap.c
drivers/usb/host/ohci-tilegx.c [new file with mode: 0644]
drivers/usb/otg/isp1301_omap.c
drivers/video/mxsfb.c
drivers/w1/masters/Kconfig
drivers/w1/masters/omap_hdq.c
drivers/watchdog/Kconfig
drivers/watchdog/booke_wdt.c
drivers/watchdog/omap_wdt.c
fs/9p/v9fs.h
fs/9p/vfs_dentry.c
fs/9p/vfs_inode.c
fs/9p/vfs_inode_dotl.c
fs/9p/vfs_super.c
fs/adfs/dir.c
fs/adfs/super.c
fs/affs/affs.h
fs/affs/amigaffs.c
fs/affs/bitmap.c
fs/affs/namei.c
fs/affs/super.c
fs/afs/dir.c
fs/afs/mntpt.c
fs/afs/super.c
fs/aio.c
fs/attr.c
fs/autofs4/dev-ioctl.c
fs/autofs4/root.c
fs/bad_inode.c
fs/befs/linuxvfs.c
fs/bfs/dir.c
fs/block_dev.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/super.c
fs/cachefiles/namei.c
fs/cachefiles/rdwr.c
fs/ceph/dir.c
fs/ceph/file.c
fs/ceph/super.c
fs/ceph/super.h
fs/cifs/cifsfs.c
fs/cifs/cifsfs.h
fs/cifs/dir.c
fs/cifs/inode.c
fs/coda/cache.c
fs/coda/dir.c
fs/configfs/dir.c
fs/cramfs/inode.c
fs/dcache.c
fs/debugfs/inode.c
fs/devpts/inode.c
fs/direct-io.c
fs/ecryptfs/dentry.c
fs/ecryptfs/ecryptfs_kernel.h
fs/ecryptfs/inode.c
fs/ecryptfs/kthread.c
fs/ecryptfs/main.c
fs/efs/efs.h
fs/efs/namei.c
fs/exofs/namei.c
fs/exofs/ore.c
fs/exofs/ore_raid.c
fs/exportfs/expfs.c
fs/ext2/namei.c
fs/ext2/super.c
fs/ext3/dir.c
fs/ext3/namei.c
fs/ext3/super.c
fs/ext4/dir.c
fs/ext4/file.c
fs/ext4/fsync.c
fs/ext4/ioctl.c
fs/ext4/namei.c
fs/ext4/super.c
fs/fat/namei_msdos.c
fs/fat/namei_vfat.c
fs/file_table.c
fs/freevxfs/vxfs_lookup.c
fs/fs-writeback.c
fs/fs_struct.c
fs/fuse/dir.c
fs/gfs2/dentry.c
fs/gfs2/inode.c
fs/gfs2/ops_fstype.c
fs/gfs2/quota.c
fs/gfs2/quota.h
fs/gfs2/super.c
fs/gfs2/sys.c
fs/hfs/dir.c
fs/hfs/extent.c
fs/hfs/hfs_fs.h
fs/hfs/inode.c
fs/hfs/mdb.c
fs/hfs/super.c
fs/hfs/sysdep.c
fs/hfsplus/bitmap.c
fs/hfsplus/dir.c
fs/hfsplus/hfsplus_fs.h
fs/hfsplus/inode.c
fs/hfsplus/super.c
fs/hostfs/hostfs_kern.c
fs/hpfs/dir.c
fs/hpfs/hpfs_fn.h
fs/hpfs/namei.c
fs/hppfs/hppfs.c
fs/hugetlbfs/inode.c
fs/inode.c
fs/internal.h
fs/isofs/isofs.h
fs/isofs/namei.c
fs/jffs2/dir.c
fs/jfs/namei.c
fs/jfs/super.c
fs/libfs.c
fs/locks.c
fs/logfs/dir.c
fs/logfs/super.c
fs/minix/namei.c
fs/mount.h
fs/namei.c
fs/namespace.c
fs/ncpfs/dir.c
fs/nfs/dir.c
fs/nfs/getroot.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4proc.c
fs/nfs/objlayout/objio_osd.c
fs/nfs/proc.c
fs/nfs/super.c
fs/nfsd/vfs.c
fs/nilfs2/namei.c
fs/nilfs2/super.c
fs/notify/fanotify/fanotify_user.c
fs/notify/fsnotify.c
fs/ntfs/namei.c
fs/ocfs2/dcache.c
fs/ocfs2/dlmfs/dlmfs.c
fs/ocfs2/namei.c
fs/omfs/dir.c
fs/open.c
fs/openpromfs/inode.c
fs/pnode.c
fs/proc/base.c
fs/proc/generic.c
fs/proc/internal.h
fs/proc/namespaces.c
fs/proc/proc_devtree.c
fs/proc/proc_net.c
fs/proc/proc_sysctl.c
fs/proc/root.c
fs/proc_namespace.c
fs/qnx4/namei.c
fs/qnx4/qnx4.h
fs/qnx6/inode.c
fs/qnx6/namei.c
fs/qnx6/qnx6.h
fs/quota/dquot.c
fs/quota/quota.c
fs/ramfs/inode.c
fs/read_write.c
fs/reiserfs/namei.c
fs/reiserfs/procfs.c
fs/reiserfs/super.c
fs/reiserfs/xattr.c
fs/romfs/super.c
fs/squashfs/namei.c
fs/super.c
fs/sync.c
fs/sysfs/dir.c
fs/sysfs/mount.c
fs/sysfs/sysfs.h
fs/sysv/inode.c
fs/sysv/namei.c
fs/sysv/sysv.h
fs/ubifs/debug.c
fs/ubifs/debug.h
fs/ubifs/dir.c
fs/ubifs/orphan.c
fs/ubifs/replay.c
fs/ubifs/sb.c
fs/ubifs/super.c
fs/udf/namei.c
fs/ufs/balloc.c
fs/ufs/ialloc.c
fs/ufs/namei.c
fs/ufs/super.c
fs/ufs/ufs.h
fs/ufs/ufs_fs.h
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_iops.c
include/acpi/acpi_bus.h
include/acpi/processor.h
include/linux/ceph/messenger.h
include/linux/cpuidle.h
include/linux/dcache.h
include/linux/dw_apb_timer.h
include/linux/file.h
include/linux/fs.h
include/linux/ftrace_event.h
include/linux/i2c/twl.h
include/linux/init_task.h
include/linux/intel-iommu.h
include/linux/io.h
include/linux/irq.h
include/linux/jump_label.h
include/linux/kernel.h
include/linux/key.h
include/linux/kmsg_dump.h
include/linux/mfd/s5m87xx/s5m-core.h
include/linux/mfd/tmio.h
include/linux/mfd/tps65217.h
include/linux/mfd/tps65910.h
include/linux/mm.h
include/linux/mmc/card.h
include/linux/mmc/cd-gpio.h [deleted file]
include/linux/mmc/host.h
include/linux/mmc/sdhci.h
include/linux/mmc/sh_mmcif.h
include/linux/mmc/sh_mobile_sdhi.h
include/linux/mmc/slot-gpio.h [new file with mode: 0644]
include/linux/mxsfb.h [new file with mode: 0644]
include/linux/namei.h
include/linux/nfs_xdr.h
include/linux/of.h
include/linux/pci_ids.h
include/linux/perf_event.h
include/linux/platform_data/clk-nomadik.h [new file with mode: 0644]
include/linux/platform_data/omap_drm.h [new file with mode: 0644]
include/linux/pm_domain.h
include/linux/pm_qos.h
include/linux/power/smartreflex.h [new file with mode: 0644]
include/linux/quota.h
include/linux/quotaops.h
include/linux/rcupdate.h
include/linux/regmap.h
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/linux/regulator/fixed.h
include/linux/regulator/lp872x.h [new file with mode: 0644]
include/linux/regulator/machine.h
include/linux/sched.h
include/linux/sh_clk.h
include/linux/sh_pfc.h
include/linux/smp.h
include/linux/suspend.h
include/linux/task_work.h
include/linux/tick.h
include/linux/time-armada-370-xp.h [new file with mode: 0644]
include/linux/tracehook.h
include/linux/tracepoint.h
include/linux/types.h
include/linux/usb/tilegx.h [new file with mode: 0644]
include/net/scm.h
include/target/target_core_backend.h
include/target/target_core_base.h
include/target/target_core_fabric.h
include/trace/events/rcu.h
include/trace/ftrace.h
init/main.c
ipc/mqueue.c
kernel/audit_tree.c
kernel/audit_watch.c
kernel/cgroup.c
kernel/debug/kdb/kdb_main.c
kernel/debug/kdb/kdb_private.h
kernel/events/core.c
kernel/events/uprobes.c
kernel/exit.c
kernel/fork.c
kernel/irq/manage.c
kernel/power/Kconfig
kernel/power/hibernate.c
kernel/power/main.c
kernel/power/power.h
kernel/power/suspend.c
kernel/power/swap.c
kernel/power/wakelock.c
kernel/printk.c
kernel/rcupdate.c
kernel/rcutiny.c
kernel/rcutiny_plugin.h
kernel/rcutorture.c
kernel/rcutree.c
kernel/rcutree.h
kernel/rcutree_plugin.h
kernel/rcutree_trace.c
kernel/signal.c
kernel/smp.c
kernel/smpboot.h
kernel/task_work.c
kernel/time/tick-sched.c
kernel/time/timekeeping.c
kernel/time/timer_list.c
kernel/timer.c
kernel/trace/ftrace.c
kernel/trace/ring_buffer.c
kernel/trace/trace.c
kernel/trace/trace.h
kernel/trace/trace_functions_graph.c
kernel/trace/trace_output.c
lib/Kconfig
lib/Kconfig.debug
lib/list_debug.c
lib/mpi/Makefile
lib/mpi/generic_mpi-asm-defs.h [deleted file]
lib/mpi/mpi-add.c [deleted file]
lib/mpi/mpi-bit.c
lib/mpi/mpi-cmp.c [deleted file]
lib/mpi/mpi-div.c [deleted file]
lib/mpi/mpi-gcd.c [deleted file]
lib/mpi/mpi-inline.c [deleted file]
lib/mpi/mpi-inv.c [deleted file]
lib/mpi/mpi-mpow.c [deleted file]
lib/mpi/mpi-mul.c [deleted file]
lib/mpi/mpi-scan.c [deleted file]
lib/mpi/mpicoder.c
lib/mpi/mpih-div.c
lib/mpi/mpih-mul.c
lib/mpi/mpiutil.c
mm/bounce.c
mm/memory-failure.c
mm/shmem.c
net/ceph/messenger.c
net/core/scm.c
samples/seccomp/.gitignore [new file with mode: 0644]
security/integrity/ima/Kconfig
security/integrity/ima/Makefile
security/integrity/ima/ima.h
security/integrity/ima/ima_api.c
security/integrity/ima/ima_audit.c
security/integrity/ima/ima_fs.c
security/integrity/ima/ima_init.c
security/integrity/ima/ima_main.c
security/integrity/ima/ima_policy.c
security/keys/compat.c
security/keys/internal.h
security/keys/keyctl.c
security/keys/keyring.c
security/keys/process_keys.c
security/selinux/hooks.c
security/selinux/include/security.h
security/selinux/selinuxfs.c
security/smack/smack.h
security/smack/smack_access.c
security/smack/smack_lsm.c
security/smack/smackfs.c
sound/aoa/codecs/onyx.c
sound/aoa/codecs/tas.c
sound/soc/fsl/imx-pcm-fiq.c
sound/soc/samsung/dma.c
sound/soc/tegra/Kconfig
sound/soc/tegra/tegra20_i2s.c
sound/soc/tegra/tegra20_spdif.c
sound/soc/tegra/tegra30_ahub.c
sound/soc/tegra/tegra30_i2s.c
sound/soc/tegra/tegra_asoc_utils.c
tools/lib/traceevent/Makefile
tools/lib/traceevent/event-parse.c
tools/lib/traceevent/event-parse.h
tools/lib/traceevent/parse-filter.c
tools/perf/Documentation/perf-bench.txt
tools/perf/Documentation/perf-report.txt
tools/perf/Documentation/perf-top.txt
tools/perf/Makefile
tools/perf/bench/mem-memcpy.c
tools/perf/bench/mem-memset.c
tools/perf/builtin-bench.c
tools/perf/builtin-evlist.c
tools/perf/builtin-kmem.c
tools/perf/builtin-lock.c
tools/perf/builtin-record.c
tools/perf/builtin-report.c
tools/perf/builtin-sched.c
tools/perf/builtin-script.c
tools/perf/builtin-stat.c
tools/perf/builtin-test.c
tools/perf/builtin-top.c
tools/perf/config/feature-tests.mak
tools/perf/ui/browsers/annotate.c
tools/perf/ui/browsers/hists.c
tools/perf/ui/gtk/browser.c
tools/perf/ui/gtk/gtk.h
tools/perf/ui/gtk/setup.c
tools/perf/ui/gtk/util.c [new file with mode: 0644]
tools/perf/ui/tui/setup.c
tools/perf/ui/tui/util.c [new file with mode: 0644]
tools/perf/ui/util.c
tools/perf/ui/util.h
tools/perf/util/debug.c
tools/perf/util/debug.h
tools/perf/util/evlist.c
tools/perf/util/evlist.h
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/header.c
tools/perf/util/hist.h
tools/perf/util/include/linux/kernel.h
tools/perf/util/map.h
tools/perf/util/parse-events-test.c
tools/perf/util/parse-events.c
tools/perf/util/parse-events.h
tools/perf/util/parse-events.l
tools/perf/util/parse-events.y
tools/perf/util/pmu.c
tools/perf/util/pmu.h
tools/perf/util/scripting-engines/trace-event-perl.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/session.c
tools/perf/util/session.h
tools/perf/util/sort.c
tools/perf/util/sort.h
tools/perf/util/string.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/top.c
tools/perf/util/trace-event-parse.c
tools/perf/util/trace-event-read.c
tools/perf/util/trace-event-scripting.c
tools/perf/util/trace-event.h
tools/perf/util/util.h

index 31725ffeeb3a3bc09bb4c712a3f88bfbe941aae8..217772615d0288f996e05cc128b98c9a40d95042 100644 (file)
@@ -231,3 +231,16 @@ Description:
                Reads from this file return a string consisting of the names of
                wakeup sources created with the help of /sys/power/wake_lock
                that are inactive at the moment, separated with spaces.
+
+What:          /sys/power/pm_print_times
+Date:          May 2012
+Contact:       Sameer Nanda <snanda@chromium.org>
+Description:
+               The /sys/power/pm_print_times file allows user space to
+               control whether the time taken by devices to suspend and
+               resume is printed.  These prints are useful for hunting down
+               devices that take too long to suspend or resume.
+
+               Writing a "1" enables this printing while writing a "0"
+               disables it.  The default value is "0".  Reading from this file
+               will display the current value.
index 5c8d74968090544ae570105b00a96561ea4acd6c..fc103d7a04740d338bf0490a2133674c25986d59 100644 (file)
@@ -162,9 +162,9 @@ over a rather long period of time, but improvements are always welcome!
                when publicizing a pointer to a structure that can
                be traversed by an RCU read-side critical section.
 
-5.     If call_rcu(), or a related primitive such as call_rcu_bh() or
-       call_rcu_sched(), is used, the callback function must be
-       written to be called from softirq context.  In particular,
+5.     If call_rcu(), or a related primitive such as call_rcu_bh(),
+       call_rcu_sched(), or call_srcu() is used, the callback function
+       must be written to be called from softirq context.  In particular,
        it cannot block.
 
 6.     Since synchronize_rcu() can block, it cannot be called from
@@ -202,11 +202,12 @@ over a rather long period of time, but improvements are always welcome!
        updater uses call_rcu_sched() or synchronize_sched(), then
        the corresponding readers must disable preemption, possibly
        by calling rcu_read_lock_sched() and rcu_read_unlock_sched().
-       If the updater uses synchronize_srcu(), the the corresponding
-       readers must use srcu_read_lock() and srcu_read_unlock(),
-       and with the same srcu_struct.  The rules for the expedited
-       primitives are the same as for their non-expedited counterparts.
-       Mixing things up will result in confusion and broken kernels.
+       If the updater uses synchronize_srcu() or call_srcu(),
+       the the corresponding readers must use srcu_read_lock() and
+       srcu_read_unlock(), and with the same srcu_struct.  The rules for
+       the expedited primitives are the same as for their non-expedited
+       counterparts.  Mixing things up will result in confusion and
+       broken kernels.
 
        One exception to this rule: rcu_read_lock() and rcu_read_unlock()
        may be substituted for rcu_read_lock_bh() and rcu_read_unlock_bh()
@@ -333,14 +334,14 @@ over a rather long period of time, but improvements are always welcome!
        victim CPU from ever going offline.)
 
 14.    SRCU (srcu_read_lock(), srcu_read_unlock(), srcu_dereference(),
-       synchronize_srcu(), and synchronize_srcu_expedited()) may only
-       be invoked from process context.  Unlike other forms of RCU, it
-       -is- permissible to block in an SRCU read-side critical section
-       (demarked by srcu_read_lock() and srcu_read_unlock()), hence the
-       "SRCU": "sleepable RCU".  Please note that if you don't need
-       to sleep in read-side critical sections, you should be using
-       RCU rather than SRCU, because RCU is almost always faster and
-       easier to use than is SRCU.
+       synchronize_srcu(), synchronize_srcu_expedited(), and call_srcu())
+       may only be invoked from process context.  Unlike other forms of
+       RCU, it -is- permissible to block in an SRCU read-side critical
+       section (demarked by srcu_read_lock() and srcu_read_unlock()),
+       hence the "SRCU": "sleepable RCU".  Please note that if you
+       don't need to sleep in read-side critical sections, you should be
+       using RCU rather than SRCU, because RCU is almost always faster
+       and easier to use than is SRCU.
 
        If you need to enter your read-side critical section in a
        hardirq or exception handler, and then exit that same read-side
@@ -353,8 +354,8 @@ over a rather long period of time, but improvements are always welcome!
        cleanup_srcu_struct().  These are passed a "struct srcu_struct"
        that defines the scope of a given SRCU domain.  Once initialized,
        the srcu_struct is passed to srcu_read_lock(), srcu_read_unlock()
-       synchronize_srcu(), and synchronize_srcu_expedited().  A given
-       synchronize_srcu() waits only for SRCU read-side critical
+       synchronize_srcu(), synchronize_srcu_expedited(), and call_srcu().
+       A given synchronize_srcu() waits only for SRCU read-side critical
        sections governed by srcu_read_lock() and srcu_read_unlock()
        calls that have been passed the same srcu_struct.  This property
        is what makes sleeping read-side critical sections tolerable --
@@ -374,7 +375,7 @@ over a rather long period of time, but improvements are always welcome!
        requiring SRCU's read-side deadlock immunity or low read-side
        realtime latency.
 
-       Note that, rcu_assign_pointer() relates to SRCU just as they do
+       Note that, rcu_assign_pointer() relates to SRCU just as it does
        to other forms of RCU.
 
 15.    The whole point of call_rcu(), synchronize_rcu(), and friends
index e439a0edee2263d554a53282aaa8512b0295a40c..38428c125135504de8737943088a4e0f3df6f213 100644 (file)
@@ -79,8 +79,6 @@ complete. Pseudo-code using rcu_barrier() is as follows:
    2. Execute rcu_barrier().
    3. Allow the module to be unloaded.
 
-Quick Quiz #1: Why is there no srcu_barrier()?
-
 The rcutorture module makes use of rcu_barrier in its exit function
 as follows:
 
@@ -162,7 +160,7 @@ for any pre-existing callbacks to complete.
 Then lines 55-62 print status and do operation-specific cleanup, and
 then return, permitting the module-unload operation to be completed.
 
-Quick Quiz #2: Is there any other situation where rcu_barrier() might
+Quick Quiz #1: Is there any other situation where rcu_barrier() might
        be required?
 
 Your module might have additional complications. For example, if your
@@ -242,7 +240,7 @@ reaches zero, as follows:
  4 complete(&rcu_barrier_completion);
  5 }
 
-Quick Quiz #3: What happens if CPU 0's rcu_barrier_func() executes
+Quick Quiz #2: What happens if CPU 0's rcu_barrier_func() executes
        immediately (thus incrementing rcu_barrier_cpu_count to the
        value one), but the other CPU's rcu_barrier_func() invocations
        are delayed for a full grace period? Couldn't this result in
@@ -259,12 +257,7 @@ so that your module may be safely unloaded.
 
 Answers to Quick Quizzes
 
-Quick Quiz #1: Why is there no srcu_barrier()?
-
-Answer: Since there is no call_srcu(), there can be no outstanding SRCU
-       callbacks. Therefore, there is no need to wait for them.
-
-Quick Quiz #2: Is there any other situation where rcu_barrier() might
+Quick Quiz #1: Is there any other situation where rcu_barrier() might
        be required?
 
 Answer: Interestingly enough, rcu_barrier() was not originally
@@ -278,7 +271,7 @@ Answer: Interestingly enough, rcu_barrier() was not originally
        implementing rcutorture, and found that rcu_barrier() solves
        this problem as well.
 
-Quick Quiz #3: What happens if CPU 0's rcu_barrier_func() executes
+Quick Quiz #2: What happens if CPU 0's rcu_barrier_func() executes
        immediately (thus incrementing rcu_barrier_cpu_count to the
        value one), but the other CPU's rcu_barrier_func() invocations
        are delayed for a full grace period? Couldn't this result in
index 4ddf3913fd8c0df7b91d2d29b17e3c69327907c7..7dce8a17eac269cdff475a57377bf49963c1216a 100644 (file)
@@ -174,11 +174,20 @@ torture_type      The type of RCU to test, with string values as follows:
                        and synchronize_rcu_bh_expedited().
 
                "srcu": srcu_read_lock(), srcu_read_unlock() and
+                       call_srcu().
+
+               "srcu_sync": srcu_read_lock(), srcu_read_unlock() and
                        synchronize_srcu().
 
                "srcu_expedited": srcu_read_lock(), srcu_read_unlock() and
                        synchronize_srcu_expedited().
 
+               "srcu_raw": srcu_read_lock_raw(), srcu_read_unlock_raw(),
+                       and call_srcu().
+
+               "srcu_raw_sync": srcu_read_lock_raw(), srcu_read_unlock_raw(),
+                       and synchronize_srcu().
+
                "sched": preempt_disable(), preempt_enable(), and
                        call_rcu_sched().
 
index 6bbe8dcdc3da94166160f3d27a96a6f2a622287f..69ee188515e7a9c907ec243dfff21852e55a9998 100644 (file)
@@ -833,9 +833,9 @@ sched:      Critical sections       Grace period            Barrier
 
 SRCU:  Critical sections       Grace period            Barrier
 
-       srcu_read_lock          synchronize_srcu        N/A
-       srcu_read_unlock        synchronize_srcu_expedited
-       srcu_read_lock_raw
+       srcu_read_lock          synchronize_srcu        srcu_barrier
+       srcu_read_unlock        call_srcu
+       srcu_read_lock_raw      synchronize_srcu_expedited
        srcu_read_unlock_raw
        srcu_dereference
 
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-mpic.txt
new file mode 100644 (file)
index 0000000..70c0dc5
--- /dev/null
@@ -0,0 +1,23 @@
+Marvell Armada 370 and Armada XP Interrupt Controller
+-----------------------------------------------------
+
+Required properties:
+- compatible: Should be "marvell,mpic"
+- interrupt-controller: Identifies the node as an interrupt controller.
+- #interrupt-cells: The number of cells to define the interrupts. Should be 1.
+  The cell is the IRQ number
+- reg: Should contain PMIC registers location and length. First pair
+  for the main interrupt registers, second pair for the per-CPU
+  interrupt registers
+
+Example:
+
+        mpic: interrupt-controller@d0020000 {
+              compatible = "marvell,mpic";
+              #interrupt-cells = <1>;
+              #address-cells = <1>;
+              #size-cells = <1>;
+              interrupt-controller;
+              reg = <0xd0020000 0x1000>,
+                    <0xd0021000 0x1000>;
+        };
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt b/Documentation/devicetree/bindings/arm/armada-370-xp-timer.txt
new file mode 100644 (file)
index 0000000..8b6ea22
--- /dev/null
@@ -0,0 +1,11 @@
+Marvell Armada 370 and Armada XP Global Timers
+----------------------------------------------
+
+Required properties:
+- compatible: Should be "marvell,armada-370-xp-timer"
+- interrupts: Should contain the list of Global Timer interrupts
+- reg: Should contain the base address of the Global Timer registers
+
+Optional properties:
+- marvell,timer-25Mhz: Tells whether the Global timer supports the 25
+  Mhz fixed mode (available on Armada XP and not on Armada 370)
diff --git a/Documentation/devicetree/bindings/arm/armada-370-xp.txt b/Documentation/devicetree/bindings/arm/armada-370-xp.txt
new file mode 100644 (file)
index 0000000..c6ed90e
--- /dev/null
@@ -0,0 +1,24 @@
+Marvell Armada 370 and Armada XP Platforms Device Tree Bindings
+---------------------------------------------------------------
+
+Boards with a SoC of the Marvell Armada 370 and Armada XP families
+shall have the following property:
+
+Required root node property:
+
+compatible: must contain "marvell,armada-370-xp"
+
+In addition, boards using the Marvell Armada 370 SoC shall have the
+following property:
+
+Required root node property:
+
+compatible: must contain "marvell,armada370"
+
+In addition, boards using the Marvell Armada XP SoC shall have the
+following property:
+
+Required root node property:
+
+compatible: must contain "marvell,armadaxp"
+
index aabca4f83402198c50893724a2d3dbcfb3d221d4..19078bf5cca82b22e5aba7882d592242d924fd48 100644 (file)
@@ -4,7 +4,7 @@ Required properties:
 - compatible: Should be "atmel,<chip>-aic"
 - interrupt-controller: Identifies the node as an interrupt controller.
 - interrupt-parent: For single AIC system, it is an empty property.
-- #interrupt-cells: The number of cells to define the interrupts. It sould be 2.
+- #interrupt-cells: The number of cells to define the interrupts. It sould be 3.
   The first cell is the IRQ number (aka "Peripheral IDentifier" on datasheet).
   The second cell is used to specify flags:
     bits[3:0] trigger type and level flags:
@@ -14,7 +14,10 @@ Required properties:
       8 = active low level-sensitive.
       Valid combinations are 1, 2, 3, 4, 8.
       Default flag for internal sources should be set to 4 (active high).
+  The third cell is used to specify the irq priority from 0 (lowest) to 7
+  (highest).
 - reg: Should contain AIC registers location and length
+- atmel,external-irqs: u32 array of external irqs.
 
 Examples:
        /*
@@ -24,7 +27,7 @@ Examples:
                compatible = "atmel,at91rm9200-aic";
                interrupt-controller;
                interrupt-parent;
-               #interrupt-cells = <2>;
+               #interrupt-cells = <3>;
                reg = <0xfffff000 0x200>;
        };
 
@@ -34,5 +37,5 @@ Examples:
        dma: dma-controller@ffffec00 {
                compatible = "atmel,at91sam9g45-dma";
                reg = <0xffffec00 0x200>;
-               interrupts = <21 4>;
+               interrupts = <21 4 5>;
        };
diff --git a/Documentation/devicetree/bindings/arm/davinci/cp-intc.txt b/Documentation/devicetree/bindings/arm/davinci/cp-intc.txt
new file mode 100644 (file)
index 0000000..597e8a0
--- /dev/null
@@ -0,0 +1,27 @@
+* TI Common Platform Interrupt Controller
+
+Common Platform Interrupt Controller (cp_intc) is used on
+OMAP-L1x SoCs and can support several configurable number
+of interrupts.
+
+Main node required properties:
+
+- compatible : should be:
+       "ti,cp-intc"
+- interrupt-controller : Identifies the node as an interrupt controller
+- #interrupt-cells : Specifies the number of cells needed to encode an
+  interrupt source. The type shall be a <u32> and the value shall be 1.
+
+  The cell contains the interrupt number in the range [0-128].
+- ti,intc-size: Number of interrupts handled by the interrupt controller.
+- reg: physical base address and size of the intc registers map.
+
+Example:
+
+       intc: interrupt-controller@1 {
+               compatible = "ti,cp-intc";
+               interrupt-controller;
+               #interrupt-cells = <1>;
+               ti,intc-size = <101>;
+               reg = <0xfffee000 0x2000>;
+       };
diff --git a/Documentation/devicetree/bindings/arm/mvebu-system-controller.txt b/Documentation/devicetree/bindings/arm/mvebu-system-controller.txt
new file mode 100644 (file)
index 0000000..081c6a7
--- /dev/null
@@ -0,0 +1,17 @@
+MVEBU System Controller
+-----------------------
+MVEBU (Marvell SOCs: Armada 370/XP, Dove, mv78xx0, Kirkwood, Orion5x)
+
+Required properties:
+
+- compatible: one of:
+       - "marvell,orion-system-controller"
+       - "marvell,armada-370-xp-system-controller"
+- reg: Should contain system controller registers location and length.
+
+Example:
+
+       system-controller@d0018200 {
+               compatible = "marvell,armada-370-xp-system-controller";
+               reg = <0xd0018200 0x500>;
+       };
diff --git a/Documentation/devicetree/bindings/arm/olimex.txt b/Documentation/devicetree/bindings/arm/olimex.txt
new file mode 100644 (file)
index 0000000..007fb5c
--- /dev/null
@@ -0,0 +1,6 @@
+Olimex i.MX Platforms Device Tree Bindings
+------------------------------------------
+
+i.MX23 Olinuxino Low Cost Board
+Required root node properties:
+    - compatible = "olimex,imx23-olinuxino", "fsl,imx23";
index e78e8bccac302ee2fb4ea8f1dfbf6e8c8be94ca8..ccdd0e53451fc916cd0bfe020fab31ccf52af84d 100644 (file)
@@ -47,3 +47,9 @@ Boards:
 
 - AM335X EVM : Software Developement Board for AM335x
   compatible = "ti,am335x-evm", "ti,am33xx", "ti,omap3"
+
+- AM335X Bone : Low cost community board
+  compatible = "ti,am335x-bone", "ti,am33xx", "ti,omap3"
+
+- OMAP5 EVM : Evaluation Module
+  compatible = "ti,omap5-evm", "ti,omap5"
diff --git a/Documentation/devicetree/bindings/arm/tegra/emc.txt b/Documentation/devicetree/bindings/arm/tegra/emc.txt
deleted file mode 100644 (file)
index 09335f8..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-Embedded Memory Controller
-
-Properties:
-- name : Should be emc
-- #address-cells : Should be 1
-- #size-cells : Should be 0
-- compatible : Should contain "nvidia,tegra20-emc".
-- reg : Offset and length of the register set for the device
-- nvidia,use-ram-code : If present, the sub-nodes will be addressed
-  and chosen using the ramcode board selector. If omitted, only one
-  set of tables can be present and said tables will be used
-  irrespective of ram-code configuration.
-
-Child device nodes describe the memory settings for different configurations and clock rates.
-
-Example:
-
-       emc@7000f400 {
-               #address-cells = < 1 >;
-               #size-cells = < 0 >;
-               compatible = "nvidia,tegra20-emc";
-               reg = <0x7000f4000 0x200>;
-       }
-
-
-Embedded Memory Controller ram-code table
-
-If the emc node has the nvidia,use-ram-code property present, then the
-next level of nodes below the emc table are used to specify which settings
-apply for which ram-code settings.
-
-If the emc node lacks the nvidia,use-ram-code property, this level is omitted
-and the tables are stored directly under the emc node (see below).
-
-Properties:
-
-- name : Should be emc-tables
-- nvidia,ram-code : the binary representation of the ram-code board strappings
-  for which this node (and children) are valid.
-
-
-
-Embedded Memory Controller configuration table
-
-This is a table containing the EMC register settings for the various
-operating speeds of the memory controller. They are always located as
-subnodes of the emc controller node.
-
-There are two ways of specifying which tables to use:
-
-* The simplest is if there is just one set of tables in the device tree,
-  and they will always be used (based on which frequency is used).
-  This is the preferred method, especially when firmware can fill in
-  this information based on the specific system information and just
-  pass it on to the kernel.
-
-* The slightly more complex one is when more than one memory configuration
-  might exist on the system.  The Tegra20 platform handles this during
-  early boot by selecting one out of possible 4 memory settings based
-  on a 2-pin "ram code" bootstrap setting on the board. The values of
-  these strappings can be read through a register in the SoC, and thus
-  used to select which tables to use.
-
-Properties:
-- name : Should be emc-table
-- compatible : Should contain "nvidia,tegra20-emc-table".
-- reg : either an opaque enumerator to tell different tables apart, or
-  the valid frequency for which the table should be used (in kHz).
-- clock-frequency : the clock frequency for the EMC at which this
-  table should be used (in kHz).
-- nvidia,emc-registers : a 46 word array of EMC registers to be programmed
-  for operation at the 'clock-frequency' setting.
-  The order and contents of the registers are:
-    RC, RFC, RAS, RP, R2W, W2R, R2P, W2P, RD_RCD, WR_RCD, RRD, REXT,
-    WDV, QUSE, QRST, QSAFE, RDV, REFRESH, BURST_REFRESH_NUM, PDEX2WR,
-    PDEX2RD, PCHG2PDEN, ACT2PDEN, AR2PDEN, RW2PDEN, TXSR, TCKE, TFAW,
-    TRPAB, TCLKSTABLE, TCLKSTOP, TREFBW, QUSE_EXTRA, FBIO_CFG6, ODT_WRITE,
-    ODT_READ, FBIO_CFG5, CFG_DIG_DLL, DLL_XFORM_DQS, DLL_XFORM_QUSE,
-    ZCAL_REF_CNT, ZCAL_WAIT_CNT, AUTO_CAL_INTERVAL, CFG_CLKTRIM_0,
-    CFG_CLKTRIM_1, CFG_CLKTRIM_2
-
-               emc-table@166000 {
-                       reg = <166000>;
-                       compatible = "nvidia,tegra20-emc-table";
-                       clock-frequency = < 166000 >;
-                       nvidia,emc-registers = < 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-                                                0 0 0 0 0 0 0 0 0 0 0 0 0 0
-                                                0 0 0 0 0 0 0 0 0 0 0 0 0 0
-                                                0 0 0 0 >;
-               };
-
-               emc-table@333000 {
-                       reg = <333000>;
-                       compatible = "nvidia,tegra20-emc-table";
-                       clock-frequency = < 333000 >;
-                       nvidia,emc-registers = < 0 0 0 0 0 0 0 0 0 0 0 0 0 0
-                                                0 0 0 0 0 0 0 0 0 0 0 0 0 0
-                                                0 0 0 0 0 0 0 0 0 0 0 0 0 0
-                                                0 0 0 0 >;
-               };
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-emc.txt
new file mode 100644 (file)
index 0000000..4c33b29
--- /dev/null
@@ -0,0 +1,100 @@
+Embedded Memory Controller
+
+Properties:
+- name : Should be emc
+- #address-cells : Should be 1
+- #size-cells : Should be 0
+- compatible : Should contain "nvidia,tegra20-emc".
+- reg : Offset and length of the register set for the device
+- nvidia,use-ram-code : If present, the sub-nodes will be addressed
+  and chosen using the ramcode board selector. If omitted, only one
+  set of tables can be present and said tables will be used
+  irrespective of ram-code configuration.
+
+Child device nodes describe the memory settings for different configurations and clock rates.
+
+Example:
+
+       memory-controller@7000f400 {
+               #address-cells = < 1 >;
+               #size-cells = < 0 >;
+               compatible = "nvidia,tegra20-emc";
+               reg = <0x7000f4000 0x200>;
+       }
+
+
+Embedded Memory Controller ram-code table
+
+If the emc node has the nvidia,use-ram-code property present, then the
+next level of nodes below the emc table are used to specify which settings
+apply for which ram-code settings.
+
+If the emc node lacks the nvidia,use-ram-code property, this level is omitted
+and the tables are stored directly under the emc node (see below).
+
+Properties:
+
+- name : Should be emc-tables
+- nvidia,ram-code : the binary representation of the ram-code board strappings
+  for which this node (and children) are valid.
+
+
+
+Embedded Memory Controller configuration table
+
+This is a table containing the EMC register settings for the various
+operating speeds of the memory controller. They are always located as
+subnodes of the emc controller node.
+
+There are two ways of specifying which tables to use:
+
+* The simplest is if there is just one set of tables in the device tree,
+  and they will always be used (based on which frequency is used).
+  This is the preferred method, especially when firmware can fill in
+  this information based on the specific system information and just
+  pass it on to the kernel.
+
+* The slightly more complex one is when more than one memory configuration
+  might exist on the system.  The Tegra20 platform handles this during
+  early boot by selecting one out of possible 4 memory settings based
+  on a 2-pin "ram code" bootstrap setting on the board. The values of
+  these strappings can be read through a register in the SoC, and thus
+  used to select which tables to use.
+
+Properties:
+- name : Should be emc-table
+- compatible : Should contain "nvidia,tegra20-emc-table".
+- reg : either an opaque enumerator to tell different tables apart, or
+  the valid frequency for which the table should be used (in kHz).
+- clock-frequency : the clock frequency for the EMC at which this
+  table should be used (in kHz).
+- nvidia,emc-registers : a 46 word array of EMC registers to be programmed
+  for operation at the 'clock-frequency' setting.
+  The order and contents of the registers are:
+    RC, RFC, RAS, RP, R2W, W2R, R2P, W2P, RD_RCD, WR_RCD, RRD, REXT,
+    WDV, QUSE, QRST, QSAFE, RDV, REFRESH, BURST_REFRESH_NUM, PDEX2WR,
+    PDEX2RD, PCHG2PDEN, ACT2PDEN, AR2PDEN, RW2PDEN, TXSR, TCKE, TFAW,
+    TRPAB, TCLKSTABLE, TCLKSTOP, TREFBW, QUSE_EXTRA, FBIO_CFG6, ODT_WRITE,
+    ODT_READ, FBIO_CFG5, CFG_DIG_DLL, DLL_XFORM_DQS, DLL_XFORM_QUSE,
+    ZCAL_REF_CNT, ZCAL_WAIT_CNT, AUTO_CAL_INTERVAL, CFG_CLKTRIM_0,
+    CFG_CLKTRIM_1, CFG_CLKTRIM_2
+
+               emc-table@166000 {
+                       reg = <166000>;
+                       compatible = "nvidia,tegra20-emc-table";
+                       clock-frequency = < 166000 >;
+                       nvidia,emc-registers = < 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+                                                0 0 0 0 0 0 0 0 0 0 0 0 0 0
+                                                0 0 0 0 0 0 0 0 0 0 0 0 0 0
+                                                0 0 0 0 >;
+               };
+
+               emc-table@333000 {
+                       reg = <333000>;
+                       compatible = "nvidia,tegra20-emc-table";
+                       clock-frequency = < 333000 >;
+                       nvidia,emc-registers = < 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+                                                0 0 0 0 0 0 0 0 0 0 0 0 0 0
+                                                0 0 0 0 0 0 0 0 0 0 0 0 0 0
+                                                0 0 0 0 >;
+               };
index c25a0a55151d900b612ffbe518d3605642cce5ac..866d93421eba20ba81fa66e905ecd58213636d95 100644 (file)
@@ -8,7 +8,7 @@ Required properties:
 - interrupts : Should contain MC General interrupt.
 
 Example:
-       mc {
+       memory-controller@0x7000f000 {
                compatible = "nvidia,tegra20-mc";
                reg = <0x7000f000 0x024
                       0x7000f03c 0x3c4>;
index e47e73f612f4b30e5cb47a2ee4736db84bf9ef9f..bdf1a612422bcb004a4c262648c422ec22fa9ea8 100644 (file)
@@ -8,7 +8,7 @@ Required properties:
 - interrupts : Should contain MC General interrupt.
 
 Example:
-       mc {
+       memory-controller {
                compatible = "nvidia,tegra30-mc";
                reg = <0x7000f000 0x010
                       0x7000f03c 0x1b4
diff --git a/Documentation/devicetree/bindings/fb/mxsfb.txt b/Documentation/devicetree/bindings/fb/mxsfb.txt
new file mode 100644 (file)
index 0000000..b41e5e5
--- /dev/null
@@ -0,0 +1,19 @@
+* Freescale MXS LCD Interface (LCDIF)
+
+Required properties:
+- compatible: Should be "fsl,<chip>-lcdif".  Supported chips include
+  imx23 and imx28.
+- reg: Address and length of the register set for lcdif
+- interrupts: Should contain lcdif interrupts
+
+Optional properties:
+- panel-enable-gpios : Should specify the gpio for panel enable
+
+Examples:
+
+lcdif@80030000 {
+       compatible = "fsl,imx28-lcdif";
+       reg = <0x80030000 2000>;
+       interrupts = <38 86>;
+       panel-enable-gpios = <&gpio3 30 0>;
+};
index 4363ae4b3c14741008b4d1e61db4b90a161ff0cc..4f3929713ae4d16df7f5f55dbb70459a8df02c76 100644 (file)
@@ -8,8 +8,16 @@ Required properties:
   by low 16 pins and the second one is for high 16 pins.
 - 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 (currently
-  unused).
+  the second cell is used to specify the gpio polarity:
+      0 = active high
+      1 = active low
+- interrupt-controller: Marks the device node as an interrupt controller.
+- #interrupt-cells : Should be 2.  The first cell is the GPIO number.
+  The second cell bits[3:0] is used to specify trigger type and level flags:
+      1 = low-to-high edge triggered.
+      2 = high-to-low edge triggered.
+      4 = active high level-sensitive.
+      8 = active low level-sensitive.
 
 Example:
 
@@ -19,4 +27,6 @@ gpio0: gpio@73f84000 {
        interrupts = <50 51>;
        gpio-controller;
        #gpio-cells = <2>;
+       interrupt-controller;
+       #interrupt-cells = <2>;
 };
index 0c35673f7a3ec16b8415ae1d8f2afa3abfbf3be2..1e677a47b83605ade43d6072711fa19b88e8a33f 100644 (file)
@@ -13,8 +13,9 @@ Required properties for GPIO node:
 - interrupts : Should be the port interrupt shared by all 32 pins.
 - 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 (currently
-  unused).
+  the second cell is used to specify the gpio polarity:
+      0 = active high
+      1 = active low
 - interrupt-controller: Marks the device node as an interrupt controller.
 - #interrupt-cells : Should be 2.  The first cell is the GPIO number.
   The second cell bits[3:0] is used to specify trigger type and level flags:
index ee87467ad8d684d33d43cbd1de95ed85699f3359..8315ac7780ef96429dd4b4dc421aa8ba98558081 100644 (file)
@@ -26,6 +26,6 @@ Example:
                         #gpio-cells = <2>;
                         gpio-controller;
                         interrupt-controller;
-                        supports-sleepmode;
+                        st,supports-sleepmode;
                         gpio-bank = <1>;
                 };
diff --git a/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt b/Documentation/devicetree/bindings/gpio/gpio_nvidia.txt
deleted file mode 100644 (file)
index 023c952..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-NVIDIA Tegra GPIO controller
-
-Required properties:
-- compatible : "nvidia,tegra<chip>-gpio"
-- reg : Physical base address and length of the controller's registers.
-- interrupts : The interrupt outputs from the controller. For Tegra20,
-  there should be 7 interrupts specified, and for Tegra30, there should
-  be 8 interrupts specified.
-- #gpio-cells : Should be two. The first cell is the pin number and the
-  second cell is used to specify optional parameters:
-  - bit 0 specifies polarity (0 for normal, 1 for inverted)
-- gpio-controller : Marks the device node as a GPIO controller.
-- #interrupt-cells : Should be 2.
-  The first cell is the GPIO number.
-  The second cell is used to specify flags:
-    bits[3:0] trigger type and level flags:
-      1 = low-to-high edge triggered.
-      2 = high-to-low edge triggered.
-      4 = active high level-sensitive.
-      8 = active low level-sensitive.
-      Valid combinations are 1, 2, 3, 4, 8.
-- interrupt-controller : Marks the device node as an interrupt controller.
-
-Example:
-
-gpio: gpio@6000d000 {
-       compatible = "nvidia,tegra20-gpio";
-       reg = < 0x6000d000 0x1000 >;
-       interrupts = < 0 32 0x04
-                      0 33 0x04
-                      0 34 0x04
-                      0 35 0x04
-                      0 55 0x04
-                      0 87 0x04
-                      0 89 0x04 >;
-       #gpio-cells = <2>;
-       gpio-controller;
-       #interrupt-cells = <2>;
-       interrupt-controller;
-};
diff --git a/Documentation/devicetree/bindings/gpio/nvidia,tegra20-gpio.txt b/Documentation/devicetree/bindings/gpio/nvidia,tegra20-gpio.txt
new file mode 100644 (file)
index 0000000..023c952
--- /dev/null
@@ -0,0 +1,40 @@
+NVIDIA Tegra GPIO controller
+
+Required properties:
+- compatible : "nvidia,tegra<chip>-gpio"
+- reg : Physical base address and length of the controller's registers.
+- interrupts : The interrupt outputs from the controller. For Tegra20,
+  there should be 7 interrupts specified, and for Tegra30, there should
+  be 8 interrupts specified.
+- #gpio-cells : Should be two. The first cell is the pin number and the
+  second cell is used to specify optional parameters:
+  - bit 0 specifies polarity (0 for normal, 1 for inverted)
+- gpio-controller : Marks the device node as a GPIO controller.
+- #interrupt-cells : Should be 2.
+  The first cell is the GPIO number.
+  The second cell is used to specify flags:
+    bits[3:0] trigger type and level flags:
+      1 = low-to-high edge triggered.
+      2 = high-to-low edge triggered.
+      4 = active high level-sensitive.
+      8 = active low level-sensitive.
+      Valid combinations are 1, 2, 3, 4, 8.
+- interrupt-controller : Marks the device node as an interrupt controller.
+
+Example:
+
+gpio: gpio@6000d000 {
+       compatible = "nvidia,tegra20-gpio";
+       reg = < 0x6000d000 0x1000 >;
+       interrupts = < 0 32 0x04
+                      0 33 0x04
+                      0 34 0x04
+                      0 35 0x04
+                      0 55 0x04
+                      0 87 0x04
+                      0 89 0x04 >;
+       #gpio-cells = <2>;
+       gpio-controller;
+       #interrupt-cells = <2>;
+       interrupt-controller;
+};
diff --git a/Documentation/devicetree/bindings/input/nvidia,tegra20-kbc.txt b/Documentation/devicetree/bindings/input/nvidia,tegra20-kbc.txt
new file mode 100644 (file)
index 0000000..72683be
--- /dev/null
@@ -0,0 +1,23 @@
+* Tegra keyboard controller
+
+Required properties:
+- compatible: "nvidia,tegra20-kbc"
+
+Optional properties, in addition to those specified by the shared
+matrix-keyboard bindings:
+
+- linux,fn-keymap: a second keymap, same specification as the
+  matrix-keyboard-controller spec but to be used when the KEY_FN modifier
+  key is pressed.
+- nvidia,debounce-delay-ms: delay in milliseconds per row scan for debouncing
+- nvidia,repeat-delay-ms: delay in milliseconds before repeat starts
+- nvidia,ghost-filter: enable ghost filtering for this device
+- nvidia,wakeup-source: configure keyboard as a wakeup source for suspend/resume
+
+Example:
+
+keyboard: keyboard {
+       compatible = "nvidia,tegra20-kbc";
+       reg = <0x7000e200 0x100>;
+       nvidia,ghost-filter;
+};
diff --git a/Documentation/devicetree/bindings/input/tegra-kbc.txt b/Documentation/devicetree/bindings/input/tegra-kbc.txt
deleted file mode 100644 (file)
index 72683be..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-* Tegra keyboard controller
-
-Required properties:
-- compatible: "nvidia,tegra20-kbc"
-
-Optional properties, in addition to those specified by the shared
-matrix-keyboard bindings:
-
-- linux,fn-keymap: a second keymap, same specification as the
-  matrix-keyboard-controller spec but to be used when the KEY_FN modifier
-  key is pressed.
-- nvidia,debounce-delay-ms: delay in milliseconds per row scan for debouncing
-- nvidia,repeat-delay-ms: delay in milliseconds before repeat starts
-- nvidia,ghost-filter: enable ghost filtering for this device
-- nvidia,wakeup-source: configure keyboard as a wakeup source for suspend/resume
-
-Example:
-
-keyboard: keyboard {
-       compatible = "nvidia,tegra20-kbc";
-       reg = <0x7000e200 0x100>;
-       nvidia,ghost-filter;
-};
index 645f5eaadb3f07dba8550f5a41acbc5f02899362..d2802d4717bcfe70c146c95a1bc430807feae514 100644 (file)
@@ -17,18 +17,46 @@ Required properties:
   device need to be present. The definition for each of these nodes is defined
   using the standard binding for regulators found at
   Documentation/devicetree/bindings/regulator/regulator.txt.
+  The regulator is matched with the regulator-compatible.
 
-  The valid names for regulators are:
+  The valid regulator-compatible values are:
   tps65910: vrtc, vio, vdd1, vdd2, vdd3, vdig1, vdig2, vpll, vdac, vaux1,
             vaux2, vaux33, vmmc
   tps65911: vrtc, vio, vdd1, vdd3, vddctrl, ldo1, ldo2, ldo3, ldo4, ldo5,
             ldo6, ldo7, ldo8
 
+- xxx-supply: Input voltage supply regulator.
+  These entries are require if regulators are enabled for a device. Missing of these
+  properties can cause the regulator registration fails.
+  If some of input supply is powered through battery or always-on supply then
+  also it is require to have these parameters with proper node handle of always
+  on power supply.
+  tps65910:
+       vcc1-supply: VDD1 input.
+       vcc2-supply: VDD2 input.
+       vcc3-supply: VAUX33 and VMMC input.
+       vcc4-supply: VAUX1 and VAUX2 input.
+       vcc5-supply: VPLL and VDAC input.
+       vcc6-supply: VDIG1 and VDIG2 input.
+       vcc7-supply: VRTC input.
+       vccio-supply: VIO input.
+  tps65911:
+       vcc1-supply: VDD1 input.
+       vcc2-supply: VDD2 input.
+       vcc3-supply: LDO6, LDO7 and LDO8 input.
+       vcc4-supply: LDO5 input.
+       vcc5-supply: LDO3 and LDO4 input.
+       vcc6-supply: LDO1 and LDO2 input.
+       vcc7-supply: VRTC input.
+       vccio-supply: VIO input.
+
 Optional properties:
 - ti,vmbch-threshold: (tps65911) main battery charged threshold
   comparator. (see VMBCH_VSEL in TPS65910 datasheet)
 - ti,vmbch2-threshold: (tps65911) main battery discharged threshold
   comparator. (see VMBCH_VSEL in TPS65910 datasheet)
+- ti,en-ck32k-xtal: enable external 32-kHz crystal oscillator (see CK32K_CTRL
+  in TPS6591X datasheet)
 - ti,en-gpio-sleep: enable sleep control for gpios
   There should be 9 entries here, one for each gpio.
 
@@ -56,74 +84,110 @@ Example:
 
                ti,en-gpio-sleep = <0 0 1 0 0 0 0 0 0>;
 
+               vcc1-supply = <&reg_parent>;
+               vcc2-supply = <&some_reg>;
+               vcc3-supply = <...>;
+               vcc4-supply = <...>;
+               vcc5-supply = <...>;
+               vcc6-supply = <...>;
+               vcc7-supply = <...>;
+               vccio-supply = <...>;
+
                regulators {
-                       vdd1_reg: vdd1 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       vdd1_reg: regulator@0 {
+                               regulator-compatible = "vdd1";
+                               reg = <0>;
                                regulator-min-microvolt = < 600000>;
                                regulator-max-microvolt = <1500000>;
                                regulator-always-on;
                                regulator-boot-on;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       vdd2_reg: vdd2 {
+                       vdd2_reg: regulator@1 {
+                               regulator-compatible = "vdd2";
+                               reg = <1>;
                                regulator-min-microvolt = < 600000>;
                                regulator-max-microvolt = <1500000>;
                                regulator-always-on;
                                regulator-boot-on;
                                ti,regulator-ext-sleep-control = <4>;
                        };
-                       vddctrl_reg: vddctrl {
+                       vddctrl_reg: regulator@2 {
+                               regulator-compatible = "vddctrl";
+                               reg = <2>;
                                regulator-min-microvolt = < 600000>;
                                regulator-max-microvolt = <1400000>;
                                regulator-always-on;
                                regulator-boot-on;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       vio_reg: vio {
+                       vio_reg: regulator@3 {
+                               regulator-compatible = "vio";
+                               reg = <3>;
                                regulator-min-microvolt = <1500000>;
                                regulator-max-microvolt = <1800000>;
                                regulator-always-on;
                                regulator-boot-on;
                                ti,regulator-ext-sleep-control = <1>;
                        };
-                       ldo1_reg: ldo1 {
+                       ldo1_reg: regulator@4 {
+                               regulator-compatible = "ldo1";
+                               reg = <4>;
                                regulator-min-microvolt = <1000000>;
                                regulator-max-microvolt = <3300000>;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       ldo2_reg: ldo2 {
+                       ldo2_reg: regulator@5 {
+                               regulator-compatible = "ldo2";
+                               reg = <5>;
                                regulator-min-microvolt = <1050000>;
                                regulator-max-microvolt = <1050000>;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       ldo3_reg: ldo3 {
+                       ldo3_reg: regulator@6 {
+                               regulator-compatible = "ldo3";
+                               reg = <6>;
                                regulator-min-microvolt = <1000000>;
                                regulator-max-microvolt = <3300000>;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       ldo4_reg: ldo4 {
+                       ldo4_reg: regulator@7 {
+                               regulator-compatible = "ldo4";
+                               reg = <7>;
                                regulator-min-microvolt = <1000000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-always-on;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       ldo5_reg: ldo5 {
+                       ldo5_reg: regulator@8 {
+                               regulator-compatible = "ldo5";
+                               reg = <8>;
                                regulator-min-microvolt = <1000000>;
                                regulator-max-microvolt = <3300000>;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       ldo6_reg: ldo6 {
+                       ldo6_reg: regulator@9 {
+                               regulator-compatible = "ldo6";
+                               reg = <9>;
                                regulator-min-microvolt = <1200000>;
                                regulator-max-microvolt = <1200000>;
                                ti,regulator-ext-sleep-control = <0>;
                        };
-                       ldo7_reg: ldo7 {
+                       ldo7_reg: regulator@10 {
+                               regulator-compatible = "ldo7";
+                               reg = <10>;
                                regulator-min-microvolt = <1200000>;
                                regulator-max-microvolt = <1200000>;
                                regulator-always-on;
                                regulator-boot-on;
                                ti,regulator-ext-sleep-control = <1>;
                        };
-                       ldo8_reg: ldo8 {
+                       ldo8_reg: regulator@11 {
+                               regulator-compatible = "ldo8";
+                               reg = <11>;
                                regulator-min-microvolt = <1000000>;
                                regulator-max-microvolt = <3300000>;
                                regulator-always-on;
index 0d93b4b0e0e3733f77d0b668f166f2a3ba983555..bd9be0b5bc2034279d628f07eece8a3d9c2b394d 100644 (file)
@@ -3,21 +3,22 @@
 The Enhanced Secure Digital Host Controller provides an interface
 for MMC, SD, and SDIO types of memory cards.
 
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the sdhci-esdhc driver.
+
 Required properties:
-  - compatible : should be
-    "fsl,<chip>-esdhc", "fsl,esdhc"
-  - reg : should contain eSDHC registers location and length.
-  - interrupts : should contain eSDHC interrupt.
   - interrupt-parent : interrupt source phandle.
   - clock-frequency : specifies eSDHC base clock frequency.
-  - sdhci,wp-inverted : (optional) specifies that eSDHC controller
-    reports inverted write-protect state; New devices should use
-    the generic "wp-inverted" property.
-  - sdhci,1-bit-only : (optional) specifies that a controller can
-    only handle 1-bit data transfers. New devices should use the
-    generic "bus-width = <1>" property.
-  - sdhci,auto-cmd12: (optional) specifies that a controller can
-    only handle auto CMD12.
+
+Optional properties:
+  - sdhci,wp-inverted : specifies that eSDHC controller reports
+    inverted write-protect state; New devices should use the generic
+    "wp-inverted" property.
+  - sdhci,1-bit-only : specifies that a controller can only handle
+    1-bit data transfers. New devices should use the generic
+    "bus-width = <1>" property.
+  - sdhci,auto-cmd12: specifies that a controller can only handle auto
+    CMD12.
 
 Example:
 
index fea541ee8b34a18fbf1aaef9276c17ef992db830..70cd49b1caa8c07e71b7d0855a9469fc989cb7f6 100644 (file)
@@ -3,17 +3,15 @@
 The Enhanced Secure Digital Host Controller on Freescale i.MX family
 provides an interface for MMC, SD, and SDIO types of memory cards.
 
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the sdhci-esdhc-imx driver.
+
 Required properties:
 - compatible : Should be "fsl,<chip>-esdhc"
-- reg : Should contain eSDHC registers location and length
-- interrupts : Should contain eSDHC interrupt
 
 Optional properties:
-- non-removable : Indicate the card is wired to host permanently
 - fsl,cd-internal : Indicate to use controller internal card detection
 - fsl,wp-internal : Indicate to use controller internal write protection
-- cd-gpios : Specify GPIOs for card detection
-- wp-gpios : Specify GPIOs for write protection
 
 Examples:
 
index d64aea5a42032414fa99d1fa43fb0dc20114c254..0e5e2ec4001dda10fe1b35b57d8ecbe976febf0a 100644 (file)
@@ -1,8 +1,9 @@
 MMC/SD/SDIO slot directly connected to a SPI bus
 
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the mmc_spi driver.
+
 Required properties:
-- compatible : should be "mmc-spi-slot".
-- reg : should specify SPI address (chip-select number).
 - spi-max-frequency : maximum frequency for this device (Hz).
 - voltage-ranges : two cells are required, first cell specifies minimum
   slot voltage (mV), second cell specifies maximum slot voltage (mV).
@@ -11,8 +12,7 @@ Required properties:
 Optional properties:
 - gpios : may specify GPIOs in this order: Card-Detect GPIO,
   Write-Protect GPIO. Note that this does not follow the
-  binding from mmc.txt, for historic reasons.
-- interrupts : the interrupt of a card detect interrupt.
+  binding from mmc.txt, for historical reasons.
 - interrupt-parent : the phandle for the interrupt controller that
   services interrupts for this device.
 
index 6e70dcde0a71e0f997abb0f5abdf10146aaaefb3..8a6811f4a02f5759e2a793506f1cef40b756e2d8 100644 (file)
@@ -2,13 +2,17 @@ These properties are common to multiple MMC host controllers. Any host
 that requires the respective functionality should implement them using
 these definitions.
 
+Interpreted by the OF core:
+- reg: Registers location and length.
+- interrupts: Interrupts used by the MMC controller.
+
 Required properties:
 - bus-width: Number of data lines, can be <1>, <4>, or <8>
 
 Optional properties:
-- cd-gpios : Specify GPIOs for card detection, see gpio binding
-- wp-gpios : Specify GPIOs for write protection, see gpio binding
-- cd-inverted: when present, polarity on the wp gpio line is inverted
+- cd-gpios: Specify GPIOs for card detection, see gpio binding
+- wp-gpios: Specify GPIOs for write protection, see gpio binding
+- cd-inverted: when present, polarity on the cd gpio line is inverted
 - wp-inverted: when present, polarity on the wp gpio line is inverted
 - non-removable: non-removable slot (like eMMC)
 - max-frequency: maximum operating clock frequency
index 14a81d5261182aa7f2775bc3ef543785122ae494..2b584cae352ae72f093c0e470ad436ada0b5598f 100644 (file)
@@ -1,19 +1,15 @@
 * ARM PrimeCell MultiMedia Card Interface (MMCI) PL180/1
 
-The ARM PrimeCell MMCI PL180 and PL181 provides and interface for
+The ARM PrimeCell MMCI PL180 and PL181 provides an interface for
 reading and writing to MultiMedia and SD cards alike.
 
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the mmci driver.
+
 Required properties:
 - compatible             : contains "arm,pl18x", "arm,primecell".
-- reg                    : contains pl18x registers and length.
-- interrupts             : contains the device IRQ(s).
 - arm,primecell-periphid : contains the PrimeCell Peripheral ID.
 
 Optional properties:
-- wp-gpios               : contains any write protect (ro) gpios
-- cd-gpios               : contains any card detection gpios
-- cd-inverted            : indicates whether the cd gpio is inverted
-- max-frequency          : contains the maximum operating frequency
-- bus-width              : number of data lines, can be <1>, <4>, or <8>
 - mmc-cap-mmc-highspeed  : indicates whether MMC is high speed capable
 - mmc-cap-sd-highspeed   : indicates whether SD is high speed capable
index 14d870a9e3db521c84311ac1fd80b57edd78f0a4..54949f6faedebf3ba54825bd62fb1a1ab254cf95 100644 (file)
@@ -3,16 +3,14 @@
 The Freescale MXS Synchronous Serial Ports (SSP) can act as a MMC controller
 to support MMC, SD, and SDIO types of memory cards.
 
+This file documents differences between the core properties in mmc.txt
+and the properties used by the mxsmmc driver.
+
 Required properties:
 - compatible: Should be "fsl,<chip>-mmc".  The supported chips include
   imx23 and imx28.
-- reg: Should contain registers location and length
 - interrupts: Should contain ERROR and DMA interrupts
 - fsl,ssp-dma-channel: APBH DMA channel for the SSP
-- bus-width: Number of data lines, can be <1>, <4>, or <8>
-
-Optional properties:
-- wp-gpios: Specify GPIOs for write protection
 
 Examples:
 
diff --git a/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt b/Documentation/devicetree/bindings/mmc/nvidia,tegra20-sdhci.txt
new file mode 100644 (file)
index 0000000..c6d7b11
--- /dev/null
@@ -0,0 +1,25 @@
+* NVIDIA Tegra Secure Digital Host Controller
+
+This controller on Tegra family SoCs provides an interface for MMC, SD,
+and SDIO types of memory cards.
+
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the sdhci-tegra driver.
+
+Required properties:
+- compatible : Should be "nvidia,<chip>-sdhci"
+
+Optional properties:
+- power-gpios : Specify GPIOs for power control
+
+Example:
+
+sdhci@c8000200 {
+       compatible = "nvidia,tegra20-sdhci";
+       reg = <0xc8000200 0x200>;
+       interrupts = <47>;
+       cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+       wp-gpios = <&gpio 57 0>; /* gpio PH1 */
+       power-gpios = <&gpio 155 0>; /* gpio PT3 */
+       bus-width = <8>;
+};
diff --git a/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt b/Documentation/devicetree/bindings/mmc/nvidia-sdhci.txt
deleted file mode 100644 (file)
index f77c303..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-* NVIDIA Tegra Secure Digital Host Controller
-
-This controller on Tegra family SoCs provides an interface for MMC, SD,
-and SDIO types of memory cards.
-
-Required properties:
-- compatible : Should be "nvidia,<chip>-sdhci"
-- reg : Should contain SD/MMC registers location and length
-- interrupts : Should contain SD/MMC interrupt
-- bus-width : Number of data lines, can be <1>, <4>, or <8>
-
-Optional properties:
-- cd-gpios : Specify GPIOs for card detection
-- wp-gpios : Specify GPIOs for write protection
-- power-gpios : Specify GPIOs for power control
-
-Example:
-
-sdhci@c8000200 {
-       compatible = "nvidia,tegra20-sdhci";
-       reg = <0xc8000200 0x200>;
-       interrupts = <47>;
-       cd-gpios = <&gpio 69 0>; /* gpio PI5 */
-       wp-gpios = <&gpio 57 0>; /* gpio PH1 */
-       power-gpios = <&gpio 155 0>; /* gpio PT3 */
-       bus-width = <8>;
-};
diff --git a/Documentation/devicetree/bindings/mmc/sdhci-pxa.txt b/Documentation/devicetree/bindings/mmc/sdhci-pxa.txt
new file mode 100644 (file)
index 0000000..dbe98a3
--- /dev/null
@@ -0,0 +1,21 @@
+* Marvell sdhci-pxa v2/v3 controller
+
+This file documents differences between the core properties in mmc.txt
+and the properties used by the sdhci-pxav2 and sdhci-pxav3 drivers.
+
+Required properties:
+- compatible: Should be "mrvl,pxav2-mmc" or "mrvl,pxav3-mmc".
+
+Optional properties:
+- mrvl,clk-delay-cycles: Specify a number of cycles to delay for tuning.
+
+Example:
+
+sdhci@d4280800 {
+       compatible = "mrvl,pxav3-mmc";
+       reg = <0xd4280800 0x800>;
+       bus-width = <8>;
+       interrupts = <27>;
+       non-removable;
+       mrvl,clk-delay-cycles = <31>;
+};
index 8a53958c9a9f50e71073daa1b8aa0650308ea13c..be76a23b34c408133bb1d397c2c3395cac59c66a 100644 (file)
@@ -3,21 +3,20 @@
 The Highspeed MMC Host Controller on TI OMAP family
 provides an interface for MMC, SD, and SDIO types of memory cards.
 
+This file documents differences between the core properties described
+by mmc.txt and the properties used by the omap_hsmmc driver.
+
 Required properties:
 - compatible:
  Should be "ti,omap2-hsmmc", for OMAP2 controllers
  Should be "ti,omap3-hsmmc", for OMAP3 controllers
  Should be "ti,omap4-hsmmc", for OMAP4 controllers
 - ti,hwmods: Must be "mmc<n>", n is controller instance starting 1
-- reg : should contain hsmmc registers location and length
 
 Optional properties:
 ti,dual-volt: boolean, supports dual voltage cards
 <supply-name>-supply: phandle to the regulator device tree node
 "supply-name" examples are "vmmc", "vmmc_aux" etc
-bus-width: Number of data lines, default assumed is 1 if the property is missing.
-cd-gpios: GPIOs for card detection
-wp-gpios: GPIOs for write protection
 ti,non-removable: non-removable slot (like eMMC)
 ti,needs-special-reset: Requires a special softreset sequence
 
diff --git a/Documentation/devicetree/bindings/nvec/nvec_nvidia.txt b/Documentation/devicetree/bindings/nvec/nvec_nvidia.txt
deleted file mode 100644 (file)
index 5aeee53..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-NVIDIA compliant embedded controller
-
-Required properties:
-- compatible : should be "nvidia,nvec".
-- reg : the iomem of the i2c slave controller
-- interrupts : the interrupt line of the i2c slave controller
-- clock-frequency : the frequency of the i2c bus
-- gpios : the gpio used for ec request
-- slave-addr: the i2c address of the slave controller
diff --git a/Documentation/devicetree/bindings/nvec/nvidia,nvec.txt b/Documentation/devicetree/bindings/nvec/nvidia,nvec.txt
new file mode 100644 (file)
index 0000000..5aeee53
--- /dev/null
@@ -0,0 +1,9 @@
+NVIDIA compliant embedded controller
+
+Required properties:
+- compatible : should be "nvidia,nvec".
+- reg : the iomem of the i2c slave controller
+- interrupts : the interrupt line of the i2c slave controller
+- clock-frequency : the frequency of the i2c bus
+- gpios : the gpio used for ec request
+- slave-addr: the i2c address of the slave controller
index 2f5b6b1ba15f9c97c64b483fc1ad8f1a31ee6053..4fae41d547984297d0f427d22baa672a1ffedea2 100644 (file)
@@ -10,6 +10,7 @@ Optional properties:
 If this property is missing, the default assumed is Active low.
 - gpio-open-drain: GPIO is open drain type.
   If this property is missing then default assumption is false.
+-vin-supply: Input supply name.
 
 Any property defined as part of the core regulator
 binding, defined in regulator.txt, can also be used.
@@ -29,4 +30,5 @@ Example:
                enable-active-high;
                regulator-boot-on;
                gpio-open-drain;
+               vin-supply = <&parent_reg>;
        };
index 5b7a408acdaa2ddd09aacab5d8ab402f52f00389..66ece3f87bbc09d755973b7580944fea3cb60971 100644 (file)
@@ -10,6 +10,11 @@ Optional properties:
 - regulator-always-on: boolean, regulator should never be disabled
 - regulator-boot-on: bootloader/firmware enabled regulator
 - <name>-supply: phandle to the parent supply/regulator node
+- regulator-ramp-delay: ramp delay for regulator(in uV/uS)
+- regulator-compatible: If a regulator chip contains multiple
+  regulators, and if the chip's binding contains a child node that
+  describes each regulator, then this property indicates which regulator
+  this child node is intended to configure.
 
 Example:
 
diff --git a/Documentation/devicetree/bindings/regulator/tps65217.txt b/Documentation/devicetree/bindings/regulator/tps65217.txt
new file mode 100644 (file)
index 0000000..0487e96
--- /dev/null
@@ -0,0 +1,91 @@
+TPS65217 family of regulators
+
+Required properties:
+- compatible: "ti,tps65217"
+- reg: I2C slave address
+- regulators: list of regulators provided by this controller, must be named
+  after their hardware counterparts: dcdc[1-3] and ldo[1-4]
+- regulators: This is the list of child nodes that specify the regulator
+  initialization data for defined regulators. Not all regulators for the given
+  device need to be present. The definition for each of these nodes is defined
+  using the standard binding for regulators found at
+  Documentation/devicetree/bindings/regulator/regulator.txt.
+
+  The valid names for regulators are:
+  tps65217: dcdc1, dcdc2, dcdc3, ldo1, ldo2, ldo3 and ldo4
+
+Each regulator is defined using the standard binding for regulators.
+
+Example:
+
+       tps: tps@24 {
+               compatible = "ti,tps65217";
+
+               regulators {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       dcdc1_reg: regulator@0 {
+                               reg = <0>;
+                               regulator-compatible = "dcdc1";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       dcdc2_reg: regulator@1 {
+                               reg = <1>;
+                               regulator-compatible = "dcdc2";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       dcdc3_reg: regulator@2 {
+                               reg = <2>;
+                               regulator-compatible = "dcdc3";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo1_reg: regulator@3 {
+                               reg = <3>;
+                               regulator-compatible = "ldo1";
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo2_reg: regulator@4 {
+                               reg = <4>;
+                               regulator-compatible = "ldo2";
+                               regulator-min-microvolt = <900000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo3_reg: regulator@5 {
+                               reg = <5>;
+                               regulator-compatible = "ldo3";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       ldo4_reg: regulator@6 {
+                               reg = <6>;
+                               regulator-compatible = "ldo4";
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+               };
+       };
index 0fcabaa3baa344fa9a2ec676bfec2ab999a38891..d156e1b5db1233c5ffdb2c0f54e1f5bd6234da34 100644 (file)
@@ -6,8 +6,17 @@ Required properties:
 - interrupts: the interrupt outputs of the controller
 - #gpio-cells: number of cells to describe a GPIO
 - gpio-controller: mark the device as a GPIO controller
-- regulators: list of regulators provided by this controller, must be named
-  after their hardware counterparts: sm[0-2], ldo[0-9] and ldo_rtc
+- regulators: list of regulators provided by this controller, must have
+  property "regulator-compatible" to match their hardware counterparts:
+  sm[0-2], ldo[0-9] and ldo_rtc
+- sm0-supply: The input supply for the SM0.
+- sm1-supply: The input supply for the SM1.
+- sm2-supply: The input supply for the SM2.
+- vinldo01-supply: The input supply for the LDO1 and LDO2
+- vinldo23-supply: The input supply for the LDO2 and LDO3
+- vinldo4-supply: The input supply for the LDO4
+- vinldo678-supply: The input supply for the LDO6, LDO7 and LDO8
+- vinldo9-supply: The input supply for the LDO9
 
 Each regulator is defined using the standard binding for regulators.
 
@@ -21,75 +30,113 @@ Example:
                #gpio-cells = <2>;
                gpio-controller;
 
+               sm0-supply = <&some_reg>;
+               sm1-supply = <&some_reg>;
+               sm2-supply = <&some_reg>;
+               vinldo01-supply = <...>;
+               vinldo23-supply = <...>;
+               vinldo4-supply = <...>;
+               vinldo678-supply = <...>;
+               vinldo9-supply = <...>;
+
                regulators {
-                       sm0_reg: sm0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       sm0_reg: regulator@0 {
+                               reg = <0>;
+                               regulator-compatible = "sm0";
                                regulator-min-microvolt = < 725000>;
                                regulator-max-microvolt = <1500000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
 
-                       sm1_reg: sm1 {
+                       sm1_reg: regulator@1 {
+                               reg = <1>;
+                               regulator-compatible = "sm1";
                                regulator-min-microvolt = < 725000>;
                                regulator-max-microvolt = <1500000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
 
-                       sm2_reg: sm2 {
+                       sm2_reg: regulator@2 {
+                               reg = <2>;
+                               regulator-compatible = "sm2";
                                regulator-min-microvolt = <3000000>;
                                regulator-max-microvolt = <4550000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
 
-                       ldo0_reg: ldo0 {
+                       ldo0_reg: regulator@3 {
+                               reg = <3>;
+                               regulator-compatible = "ldo0";
                                regulator-name = "PCIE CLK";
                                regulator-min-microvolt = <3300000>;
                                regulator-max-microvolt = <3300000>;
                        };
 
-                       ldo1_reg: ldo1 {
+                       ldo1_reg: regulator@4 {
+                               reg = <4>;
+                               regulator-compatible = "ldo1";
                                regulator-min-microvolt = < 725000>;
                                regulator-max-microvolt = <1500000>;
                        };
 
-                       ldo2_reg: ldo2 {
+                       ldo2_reg: regulator@5 {
+                               reg = <5>;
+                               regulator-compatible = "ldo2";
                                regulator-min-microvolt = < 725000>;
                                regulator-max-microvolt = <1500000>;
                        };
 
-                       ldo3_reg: ldo3 {
+                       ldo3_reg: regulator@6 {
+                               reg = <6>;
+                               regulator-compatible = "ldo3";
                                regulator-min-microvolt = <1250000>;
                                regulator-max-microvolt = <3300000>;
                        };
 
-                       ldo4_reg: ldo4 {
+                       ldo4_reg: regulator@7 {
+                               reg = <7>;
+                               regulator-compatible = "ldo4";
                                regulator-min-microvolt = <1700000>;
                                regulator-max-microvolt = <2475000>;
                        };
 
-                       ldo5_reg: ldo5 {
+                       ldo5_reg: regulator@8 {
+                               reg = <8>;
+                               regulator-compatible = "ldo5";
                                regulator-min-microvolt = <1250000>;
                                regulator-max-microvolt = <3300000>;
                        };
 
-                       ldo6_reg: ldo6 {
+                       ldo6_reg: regulator@9 {
+                               reg = <9>;
+                               regulator-compatible = "ldo6";
                                regulator-min-microvolt = <1250000>;
                                regulator-max-microvolt = <3300000>;
                        };
 
-                       ldo7_reg: ldo7 {
+                       ldo7_reg: regulator@10 {
+                               reg = <10>;
+                               regulator-compatible = "ldo7";
                                regulator-min-microvolt = <1250000>;
                                regulator-max-microvolt = <3300000>;
                        };
 
-                       ldo8_reg: ldo8 {
+                       ldo8_reg: regulator@11 {
+                               reg = <11>;
+                               regulator-compatible = "ldo8";
                                regulator-min-microvolt = <1250000>;
                                regulator-max-microvolt = <3300000>;
                        };
 
-                       ldo9_reg: ldo9 {
+                       ldo9_reg: regulator@12 {
+                               reg = <12>;
+                               regulator-compatible = "ldo9";
                                regulator-min-microvolt = <1250000>;
                                regulator-max-microvolt = <3300000>;
                        };
index 0c3395d55ac19afde8c334fc096dc937a1e9ca19..658749b90b970e0d309c656d3c389d9730f81a1b 100644 (file)
@@ -15,7 +15,6 @@ For twl6030 regulators/LDOs
   - "ti,twl6030-vusb" for VUSB LDO
   - "ti,twl6030-v1v8" for V1V8 LDO
   - "ti,twl6030-v2v1" for V2V1 LDO
-  - "ti,twl6030-clk32kg" for CLK32KG RESOURCE
   - "ti,twl6030-vdd1" for VDD1 SMPS
   - "ti,twl6030-vdd2" for VDD2 SMPS
   - "ti,twl6030-vdd3" for VDD3 SMPS
diff --git a/Documentation/devicetree/bindings/rtc/dw-apb.txt b/Documentation/devicetree/bindings/rtc/dw-apb.txt
new file mode 100644 (file)
index 0000000..93e2b0f
--- /dev/null
@@ -0,0 +1,25 @@
+* Designware APB timer
+
+Required properties:
+- compatible: "snps,dw-apb-timer-sp" or "snps,dw-apb-timer-osc"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- interrupts: IRQ line for the timer.
+- clock-frequency: The frequency in HZ of the timer.
+- clock-freq: For backwards compatibility with picoxcell
+
+Example:
+
+               timer1: timer@ffc09000 {
+                               compatible = "snps,dw-apb-timer-sp";
+                               interrupts = <0 168 4>;
+                               clock-frequency = <200000000>;
+                               reg = <0xffc09000 0x1000>;
+                       };
+
+               timer2: timer@ffd00000 {
+                               compatible = "snps,dw-apb-timer-osc";
+                               interrupts = <0 169 4>;
+                               clock-frequency = <200000000>;
+                               reg = <0xffd00000 0x1000>;
+                       };
diff --git a/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt b/Documentation/devicetree/bindings/rtc/stmp3xxx-rtc.txt
new file mode 100644 (file)
index 0000000..b800070
--- /dev/null
@@ -0,0 +1,16 @@
+* STMP3xxx/i.MX28 Time Clock controller
+
+Required properties:
+- compatible: should be one of the following.
+    * "fsl,stmp3xxx-rtc"
+- reg: physical base address of the controller and length of memory mapped
+  region.
+- interrupts: rtc alarm interrupt
+
+Example:
+
+rtc@80056000 {
+       compatible = "fsl,imx28-rtc", "fsl,stmp3xxx-rtc";
+       reg = <0x80056000 2000>;
+       interrupts = <29>;
+};
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-alc5632.txt
new file mode 100644 (file)
index 0000000..b77a97c
--- /dev/null
@@ -0,0 +1,59 @@
+NVIDIA Tegra audio complex
+
+Required properties:
+- compatible : "nvidia,tegra-audio-alc5632"
+- nvidia,model : The user-visible name of this sound complex.
+- nvidia,audio-routing : A list of the connections between audio components.
+  Each entry is a pair of strings, the first being the connection's sink,
+  the second being the connection's source. Valid names for sources and
+  sinks are the ALC5632's pins:
+
+  ALC5632 pins:
+
+  * SPK_OUTP
+  * SPK_OUTN
+  * HP_OUT_L
+  * HP_OUT_R
+  * AUX_OUT_P
+  * AUX_OUT_N
+  * LINE_IN_L
+  * LINE_IN_R
+  * PHONE_P
+  * PHONE_N
+  * MIC1_P
+  * MIC1_N
+  * MIC2_P
+  * MIC2_N
+  * MICBIAS1
+  * DMICDAT
+
+  Board connectors:
+
+  * Headset Stereophone
+  * Int Spk
+  * Headset Mic
+  * Digital Mic
+
+- nvidia,i2s-controller : The phandle of the Tegra I2S controller
+- nvidia,audio-codec : The phandle of the ALC5632 audio codec
+
+Example:
+
+sound {
+       compatible = "nvidia,tegra-audio-alc5632-paz00",
+                                "nvidia,tegra-audio-alc5632";
+
+       nvidia,model = "Compal PAZ00";
+
+       nvidia,audio-routing =
+                               "Int Spk", "SPK_OUTP",
+                               "Int Spk", "SPK_OUTN",
+                               "Headset Mic","MICBIAS1",
+                               "MIC1_N", "Headset Mic",
+                               "MIC1_P", "Headset Mic",
+                               "Headset Stereophone", "HP_OUT_R",
+                               "Headset Stereophone", "HP_OUT_L";
+
+       nvidia,i2s-controller = <&tegra_i2s1>;
+       nvidia,audio-codec = <&alc5632>;
+};
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-trimslice.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-trimslice.txt
new file mode 100644 (file)
index 0000000..04b14cf
--- /dev/null
@@ -0,0 +1,14 @@
+NVIDIA Tegra audio complex for TrimSlice
+
+Required properties:
+- compatible : "nvidia,tegra-audio-trimslice"
+- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
+- nvidia,audio-codec : The phandle of the WM8903 audio codec
+
+Example:
+
+sound {
+       compatible = "nvidia,tegra-audio-trimslice";
+       nvidia,i2s-controller = <&tegra_i2s1>;
+       nvidia,audio-codec = <&codec>;
+};
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8753.txt
new file mode 100644 (file)
index 0000000..c4dd39c
--- /dev/null
@@ -0,0 +1,54 @@
+NVIDIA Tegra audio complex
+
+Required properties:
+- compatible : "nvidia,tegra-audio-wm8753"
+- nvidia,model : The user-visible name of this sound complex.
+- nvidia,audio-routing : A list of the connections between audio components.
+  Each entry is a pair of strings, the first being the connection's sink,
+  the second being the connection's source. Valid names for sources and
+  sinks are the WM8753's pins, and the jacks on the board:
+
+  WM8753 pins:
+
+  * LOUT1
+  * LOUT2
+  * ROUT1
+  * ROUT2
+  * MONO1
+  * MONO2
+  * OUT3
+  * OUT4
+  * LINE1
+  * LINE2
+  * RXP
+  * RXN
+  * ACIN
+  * ACOP
+  * MIC1N
+  * MIC1
+  * MIC2N
+  * MIC2
+  * Mic Bias
+
+  Board connectors:
+
+  * Headphone Jack
+  * Mic Jack
+
+- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
+- nvidia,audio-codec : The phandle of the WM8753 audio codec
+Example:
+
+sound {
+       compatible = "nvidia,tegra-audio-wm8753-whistler",
+                    "nvidia,tegra-audio-wm8753"
+       nvidia,model = "tegra-wm8753-harmony";
+
+       nvidia,audio-routing =
+               "Headphone Jack", "LOUT1",
+               "Headphone Jack", "ROUT1";
+
+       nvidia,i2s-controller = <&i2s1>;
+       nvidia,audio-codec = <&wm8753>;
+};
+
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra-audio-wm8903.txt
new file mode 100644 (file)
index 0000000..d5b0da8
--- /dev/null
@@ -0,0 +1,71 @@
+NVIDIA Tegra audio complex
+
+Required properties:
+- compatible : "nvidia,tegra-audio-wm8903"
+- nvidia,model : The user-visible name of this sound complex.
+- nvidia,audio-routing : A list of the connections between audio components.
+  Each entry is a pair of strings, the first being the connection's sink,
+  the second being the connection's source. Valid names for sources and
+  sinks are the WM8903's pins, and the jacks on the board:
+
+  WM8903 pins:
+
+  * IN1L
+  * IN1R
+  * IN2L
+  * IN2R
+  * IN3L
+  * IN3R
+  * DMICDAT
+  * HPOUTL
+  * HPOUTR
+  * LINEOUTL
+  * LINEOUTR
+  * LOP
+  * LON
+  * ROP
+  * RON
+  * MICBIAS
+
+  Board connectors:
+
+  * Headphone Jack
+  * Int Spk
+  * Mic Jack
+
+- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
+- nvidia,audio-codec : The phandle of the WM8903 audio codec
+
+Optional properties:
+- nvidia,spkr-en-gpios : The GPIO that enables the speakers
+- nvidia,hp-mute-gpios : The GPIO that mutes the headphones
+- nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in
+- nvidia,int-mic-en-gpios : The GPIO that enables the internal microphone
+- nvidia,ext-mic-en-gpios : The GPIO that enables the external microphone
+
+Example:
+
+sound {
+       compatible = "nvidia,tegra-audio-wm8903-harmony",
+                    "nvidia,tegra-audio-wm8903"
+       nvidia,model = "tegra-wm8903-harmony";
+
+       nvidia,audio-routing =
+               "Headphone Jack", "HPOUTR",
+               "Headphone Jack", "HPOUTL",
+               "Int Spk", "ROP",
+               "Int Spk", "RON",
+               "Int Spk", "LOP",
+               "Int Spk", "LON",
+               "Mic Jack", "MICBIAS",
+               "IN1L", "Mic Jack";
+
+       nvidia,i2s-controller = <&i2s1>;
+       nvidia,audio-codec = <&wm8903>;
+
+       nvidia,spkr-en-gpios = <&codec 2 0>;
+       nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+       nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */
+       nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
+};
+
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra20-das.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra20-das.txt
new file mode 100644 (file)
index 0000000..6de3a7e
--- /dev/null
@@ -0,0 +1,12 @@
+NVIDIA Tegra 20 DAS (Digital Audio Switch) controller
+
+Required properties:
+- compatible : "nvidia,tegra20-das"
+- reg : Should contain DAS registers location and length
+
+Example:
+
+das@70000c00 {
+       compatible = "nvidia,tegra20-das";
+       reg = <0x70000c00 0x80>;
+};
diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra20-i2s.txt b/Documentation/devicetree/bindings/sound/nvidia,tegra20-i2s.txt
new file mode 100644 (file)
index 0000000..0df2b5c
--- /dev/null
@@ -0,0 +1,17 @@
+NVIDIA Tegra 20 I2S controller
+
+Required properties:
+- compatible : "nvidia,tegra20-i2s"
+- reg : Should contain I2S registers location and length
+- interrupts : Should contain I2S interrupt
+- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
+  request selector for this I2S controller
+
+Example:
+
+i2s@70002800 {
+       compatible = "nvidia,tegra20-i2s";
+       reg = <0x70002800 0x200>;
+       interrupts = < 45 >;
+       nvidia,dma-request-selector = < &apbdma 2 >;
+};
diff --git a/Documentation/devicetree/bindings/sound/tegra-audio-alc5632.txt b/Documentation/devicetree/bindings/sound/tegra-audio-alc5632.txt
deleted file mode 100644 (file)
index b77a97c..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-NVIDIA Tegra audio complex
-
-Required properties:
-- compatible : "nvidia,tegra-audio-alc5632"
-- nvidia,model : The user-visible name of this sound complex.
-- nvidia,audio-routing : A list of the connections between audio components.
-  Each entry is a pair of strings, the first being the connection's sink,
-  the second being the connection's source. Valid names for sources and
-  sinks are the ALC5632's pins:
-
-  ALC5632 pins:
-
-  * SPK_OUTP
-  * SPK_OUTN
-  * HP_OUT_L
-  * HP_OUT_R
-  * AUX_OUT_P
-  * AUX_OUT_N
-  * LINE_IN_L
-  * LINE_IN_R
-  * PHONE_P
-  * PHONE_N
-  * MIC1_P
-  * MIC1_N
-  * MIC2_P
-  * MIC2_N
-  * MICBIAS1
-  * DMICDAT
-
-  Board connectors:
-
-  * Headset Stereophone
-  * Int Spk
-  * Headset Mic
-  * Digital Mic
-
-- nvidia,i2s-controller : The phandle of the Tegra I2S controller
-- nvidia,audio-codec : The phandle of the ALC5632 audio codec
-
-Example:
-
-sound {
-       compatible = "nvidia,tegra-audio-alc5632-paz00",
-                                "nvidia,tegra-audio-alc5632";
-
-       nvidia,model = "Compal PAZ00";
-
-       nvidia,audio-routing =
-                               "Int Spk", "SPK_OUTP",
-                               "Int Spk", "SPK_OUTN",
-                               "Headset Mic","MICBIAS1",
-                               "MIC1_N", "Headset Mic",
-                               "MIC1_P", "Headset Mic",
-                               "Headset Stereophone", "HP_OUT_R",
-                               "Headset Stereophone", "HP_OUT_L";
-
-       nvidia,i2s-controller = <&tegra_i2s1>;
-       nvidia,audio-codec = <&alc5632>;
-};
diff --git a/Documentation/devicetree/bindings/sound/tegra-audio-trimslice.txt b/Documentation/devicetree/bindings/sound/tegra-audio-trimslice.txt
deleted file mode 100644 (file)
index 04b14cf..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-NVIDIA Tegra audio complex for TrimSlice
-
-Required properties:
-- compatible : "nvidia,tegra-audio-trimslice"
-- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
-- nvidia,audio-codec : The phandle of the WM8903 audio codec
-
-Example:
-
-sound {
-       compatible = "nvidia,tegra-audio-trimslice";
-       nvidia,i2s-controller = <&tegra_i2s1>;
-       nvidia,audio-codec = <&codec>;
-};
diff --git a/Documentation/devicetree/bindings/sound/tegra-audio-wm8753.txt b/Documentation/devicetree/bindings/sound/tegra-audio-wm8753.txt
deleted file mode 100644 (file)
index c4dd39c..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-NVIDIA Tegra audio complex
-
-Required properties:
-- compatible : "nvidia,tegra-audio-wm8753"
-- nvidia,model : The user-visible name of this sound complex.
-- nvidia,audio-routing : A list of the connections between audio components.
-  Each entry is a pair of strings, the first being the connection's sink,
-  the second being the connection's source. Valid names for sources and
-  sinks are the WM8753's pins, and the jacks on the board:
-
-  WM8753 pins:
-
-  * LOUT1
-  * LOUT2
-  * ROUT1
-  * ROUT2
-  * MONO1
-  * MONO2
-  * OUT3
-  * OUT4
-  * LINE1
-  * LINE2
-  * RXP
-  * RXN
-  * ACIN
-  * ACOP
-  * MIC1N
-  * MIC1
-  * MIC2N
-  * MIC2
-  * Mic Bias
-
-  Board connectors:
-
-  * Headphone Jack
-  * Mic Jack
-
-- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
-- nvidia,audio-codec : The phandle of the WM8753 audio codec
-Example:
-
-sound {
-       compatible = "nvidia,tegra-audio-wm8753-whistler",
-                    "nvidia,tegra-audio-wm8753"
-       nvidia,model = "tegra-wm8753-harmony";
-
-       nvidia,audio-routing =
-               "Headphone Jack", "LOUT1",
-               "Headphone Jack", "ROUT1";
-
-       nvidia,i2s-controller = <&i2s1>;
-       nvidia,audio-codec = <&wm8753>;
-};
-
diff --git a/Documentation/devicetree/bindings/sound/tegra-audio-wm8903.txt b/Documentation/devicetree/bindings/sound/tegra-audio-wm8903.txt
deleted file mode 100644 (file)
index d5b0da8..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-NVIDIA Tegra audio complex
-
-Required properties:
-- compatible : "nvidia,tegra-audio-wm8903"
-- nvidia,model : The user-visible name of this sound complex.
-- nvidia,audio-routing : A list of the connections between audio components.
-  Each entry is a pair of strings, the first being the connection's sink,
-  the second being the connection's source. Valid names for sources and
-  sinks are the WM8903's pins, and the jacks on the board:
-
-  WM8903 pins:
-
-  * IN1L
-  * IN1R
-  * IN2L
-  * IN2R
-  * IN3L
-  * IN3R
-  * DMICDAT
-  * HPOUTL
-  * HPOUTR
-  * LINEOUTL
-  * LINEOUTR
-  * LOP
-  * LON
-  * ROP
-  * RON
-  * MICBIAS
-
-  Board connectors:
-
-  * Headphone Jack
-  * Int Spk
-  * Mic Jack
-
-- nvidia,i2s-controller : The phandle of the Tegra I2S1 controller
-- nvidia,audio-codec : The phandle of the WM8903 audio codec
-
-Optional properties:
-- nvidia,spkr-en-gpios : The GPIO that enables the speakers
-- nvidia,hp-mute-gpios : The GPIO that mutes the headphones
-- nvidia,hp-det-gpios : The GPIO that detect headphones are plugged in
-- nvidia,int-mic-en-gpios : The GPIO that enables the internal microphone
-- nvidia,ext-mic-en-gpios : The GPIO that enables the external microphone
-
-Example:
-
-sound {
-       compatible = "nvidia,tegra-audio-wm8903-harmony",
-                    "nvidia,tegra-audio-wm8903"
-       nvidia,model = "tegra-wm8903-harmony";
-
-       nvidia,audio-routing =
-               "Headphone Jack", "HPOUTR",
-               "Headphone Jack", "HPOUTL",
-               "Int Spk", "ROP",
-               "Int Spk", "RON",
-               "Int Spk", "LOP",
-               "Int Spk", "LON",
-               "Mic Jack", "MICBIAS",
-               "IN1L", "Mic Jack";
-
-       nvidia,i2s-controller = <&i2s1>;
-       nvidia,audio-codec = <&wm8903>;
-
-       nvidia,spkr-en-gpios = <&codec 2 0>;
-       nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
-       nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */
-       nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
-};
-
diff --git a/Documentation/devicetree/bindings/sound/tegra20-das.txt b/Documentation/devicetree/bindings/sound/tegra20-das.txt
deleted file mode 100644 (file)
index 6de3a7e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-NVIDIA Tegra 20 DAS (Digital Audio Switch) controller
-
-Required properties:
-- compatible : "nvidia,tegra20-das"
-- reg : Should contain DAS registers location and length
-
-Example:
-
-das@70000c00 {
-       compatible = "nvidia,tegra20-das";
-       reg = <0x70000c00 0x80>;
-};
diff --git a/Documentation/devicetree/bindings/sound/tegra20-i2s.txt b/Documentation/devicetree/bindings/sound/tegra20-i2s.txt
deleted file mode 100644 (file)
index 0df2b5c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-NVIDIA Tegra 20 I2S controller
-
-Required properties:
-- compatible : "nvidia,tegra20-i2s"
-- reg : Should contain I2S registers location and length
-- interrupts : Should contain I2S interrupt
-- nvidia,dma-request-selector : The Tegra DMA controller's phandle and
-  request selector for this I2S controller
-
-Example:
-
-i2s@70002800 {
-       compatible = "nvidia,tegra20-i2s";
-       reg = <0x70002800 0x200>;
-       interrupts = < 45 >;
-       nvidia,dma-request-selector = < &apbdma 2 >;
-};
diff --git a/Documentation/devicetree/bindings/spi/nvidia,tegra20-spi.txt b/Documentation/devicetree/bindings/spi/nvidia,tegra20-spi.txt
new file mode 100644 (file)
index 0000000..6b9e518
--- /dev/null
@@ -0,0 +1,5 @@
+NVIDIA Tegra 2 SPI device
+
+Required properties:
+- compatible : should be "nvidia,tegra20-spi".
+- gpios : should specify GPIOs used for chipselect.
diff --git a/Documentation/devicetree/bindings/spi/spi-samsung.txt b/Documentation/devicetree/bindings/spi/spi-samsung.txt
new file mode 100644 (file)
index 0000000..a15ffed
--- /dev/null
@@ -0,0 +1,116 @@
+* Samsung SPI Controller
+
+The Samsung SPI controller is used to interface with various devices such as flash
+and display controllers using the SPI communication interface.
+
+Required SoC Specific Properties:
+
+- compatible: should be one of the following.
+    - samsung,s3c2443-spi: for s3c2443, s3c2416 and s3c2450 platforms
+    - samsung,s3c6410-spi: for s3c6410 platforms
+    - samsung,s5p6440-spi: for s5p6440 and s5p6450 platforms
+    - samsung,s5pv210-spi: for s5pv210 and s5pc110 platforms
+    - samsung,exynos4210-spi: for exynos4 and exynos5 platforms
+
+- reg: physical base address of the controller and length of memory mapped
+  region.
+
+- interrupts: The interrupt number to the cpu. The interrupt specifier format
+  depends on the interrupt controller.
+
+[PRELIMINARY: the dma channel allocation will change once there are
+official DMA bindings]
+
+- tx-dma-channel: The dma channel specifier for tx operations. The format of
+  the dma specifier depends on the dma controller.
+
+- rx-dma-channel: The dma channel specifier for rx operations. The format of
+  the dma specifier depends on the dma controller.
+
+Required Board Specific Properties:
+
+- #address-cells: should be 1.
+- #size-cells: should be 0.
+- gpios: The gpio specifier for clock, mosi and miso interface lines (in the
+  order specified). The format of the gpio specifier depends on the gpio
+  controller.
+
+Optional Board Specific Properties:
+
+- samsung,spi-src-clk: If the spi controller includes a internal clock mux to
+  select the clock source for the spi bus clock, this property can be used to
+  indicate the clock to be used for driving the spi bus clock. If not specified,
+  the clock number 0 is used as default.
+
+- num-cs: Specifies the number of chip select lines supported. If
+  not specified, the default number of chip select lines is set to 1.
+
+SPI Controller specific data in SPI slave nodes:
+
+- The spi slave nodes should provide the following information which is required
+  by the spi controller.
+
+  - cs-gpio: A gpio specifier that specifies the gpio line used as
+    the slave select line by the spi controller. The format of the gpio
+    specifier depends on the gpio controller.
+
+  - samsung,spi-feedback-delay: The sampling phase shift to be applied on the
+    miso line (to account for any lag in the miso line). The following are the
+    valid values.
+
+      - 0: No phase shift.
+      - 1: 90 degree phase shift sampling.
+      - 2: 180 degree phase shift sampling.
+      - 3: 270 degree phase shift sampling.
+
+Aliases:
+
+- All the SPI controller nodes should be represented in the aliases node using
+  the following format 'spi{n}' where n is a unique number for the alias.
+
+
+Example:
+
+- SoC Specific Portion:
+
+       spi_0: spi@12d20000 {
+               compatible = "samsung,exynos4210-spi";
+               reg = <0x12d20000 0x100>;
+               interrupts = <0 66 0>;
+               tx-dma-channel = <&pdma0 5>;
+               rx-dma-channel = <&pdma0 4>;
+       };
+
+- Board Specific Portion:
+
+       spi_0: spi@12d20000 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               gpios = <&gpa2 4 2 3 0>,
+                       <&gpa2 6 2 3 0>,
+                       <&gpa2 7 2 3 0>;
+
+               w25q80bw@0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "w25x80";
+                       reg = <0>;
+                       spi-max-frequency = <10000>;
+
+                       controller-data {
+                               cs-gpio = <&gpa2 5 1 0 3>;
+                               samsung,spi-feedback-delay = <0>;
+                       };
+
+                       partition@0 {
+                               label = "U-Boot";
+                               reg = <0x0 0x40000>;
+                               read-only;
+                       };
+
+                       partition@40000 {
+                               label = "Kernel";
+                               reg = <0x40000 0xc0000>;
+                       };
+               };
+       };
diff --git a/Documentation/devicetree/bindings/spi/spi_nvidia.txt b/Documentation/devicetree/bindings/spi/spi_nvidia.txt
deleted file mode 100644 (file)
index 6b9e518..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-NVIDIA Tegra 2 SPI device
-
-Required properties:
-- compatible : should be "nvidia,tegra20-spi".
-- gpios : should specify GPIOs used for chipselect.
diff --git a/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt b/Documentation/devicetree/bindings/tty/serial/fsl-mxs-auart.txt
new file mode 100644 (file)
index 0000000..2ee903f
--- /dev/null
@@ -0,0 +1,27 @@
+* Freescale MXS Application UART (AUART)
+
+Required properties:
+- compatible : Should be "fsl,<soc>-auart". The supported SoCs include
+  imx23 and imx28.
+- reg : Address and length of the register set for the device
+- interrupts : Should contain the auart interrupt numbers
+
+Example:
+auart0: serial@8006a000 {
+       compatible = "fsl,imx28-auart", "fsl,imx23-auart";
+       reg = <0x8006a000 0x2000>;
+       interrupts = <112 70 71>;
+};
+
+Note: Each auart port should have an alias correctly numbered in "aliases"
+node.
+
+Example:
+
+aliases {
+       serial0 = &auart0;
+       serial1 = &auart1;
+       serial2 = &auart2;
+       serial3 = &auart3;
+       serial4 = &auart4;
+};
diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt
new file mode 100644 (file)
index 0000000..e9b005d
--- /dev/null
@@ -0,0 +1,29 @@
+Tegra SOC USB controllers
+
+The device node for a USB controller that is part of a Tegra
+SOC is as described in the document "Open Firmware Recommended
+Practice : Universal Serial Bus" with the following modifications
+and additions :
+
+Required properties :
+ - compatible : Should be "nvidia,tegra20-ehci" for USB controllers
+   used in host mode.
+ - phy_type : Should be one of "ulpi" or "utmi".
+ - nvidia,vbus-gpio : If present, specifies a gpio that needs to be
+   activated for the bus to be powered.
+
+Required properties for phy_type == ulpi:
+  - nvidia,phy-reset-gpio : The GPIO used to reset the PHY.
+
+Optional properties:
+  - dr_mode : dual role mode. Indicates the working mode for
+   nvidia,tegra20-ehci compatible controllers.  Can be "host", "peripheral",
+   or "otg".  Default to "host" if not defined for backward compatibility.
+      host means this is a host controller
+      peripheral means it is device controller
+      otg means it can operate as either ("on the go")
+  - nvidia,has-legacy-mode : boolean indicates whether this controller can
+    operate in legacy mode (as APX 2500 / 2600). In legacy mode some
+    registers are accessed through the APB_MISC base address instead of
+    the USB controller. Since this is a legacy issue it probably does not
+    warrant a compatible string of its own.
diff --git a/Documentation/devicetree/bindings/usb/tegra-usb.txt b/Documentation/devicetree/bindings/usb/tegra-usb.txt
deleted file mode 100644 (file)
index e9b005d..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-Tegra SOC USB controllers
-
-The device node for a USB controller that is part of a Tegra
-SOC is as described in the document "Open Firmware Recommended
-Practice : Universal Serial Bus" with the following modifications
-and additions :
-
-Required properties :
- - compatible : Should be "nvidia,tegra20-ehci" for USB controllers
-   used in host mode.
- - phy_type : Should be one of "ulpi" or "utmi".
- - nvidia,vbus-gpio : If present, specifies a gpio that needs to be
-   activated for the bus to be powered.
-
-Required properties for phy_type == ulpi:
-  - nvidia,phy-reset-gpio : The GPIO used to reset the PHY.
-
-Optional properties:
-  - dr_mode : dual role mode. Indicates the working mode for
-   nvidia,tegra20-ehci compatible controllers.  Can be "host", "peripheral",
-   or "otg".  Default to "host" if not defined for backward compatibility.
-      host means this is a host controller
-      peripheral means it is device controller
-      otg means it can operate as either ("on the go")
-  - nvidia,has-legacy-mode : boolean indicates whether this controller can
-    operate in legacy mode (as APX 2500 / 2600). In legacy mode some
-    registers are accessed through the APB_MISC base address instead of
-    the USB controller. Since this is a legacy issue it probably does not
-    warrant a compatible string of its own.
diff --git a/Documentation/devicetree/bindings/watchdog/omap-wdt.txt b/Documentation/devicetree/bindings/watchdog/omap-wdt.txt
new file mode 100644 (file)
index 0000000..c227970
--- /dev/null
@@ -0,0 +1,14 @@
+TI Watchdog Timer (WDT) Controller for OMAP
+
+Required properties:
+compatible:
+- "ti,omap3-wdt" for OMAP3
+- "ti,omap4-wdt" for OMAP4
+- ti,hwmods: Name of the hwmod associated to the WDT
+
+Examples:
+
+wdt2: wdt@4a314000 {
+       compatible = "ti,omap4-wdt", "ti,omap3-wdt";
+       ti,hwmods = "wd_timer2";
+};
index 8e2da1e06e3b2371eb82ef07105e63ad97d224b6..e0cce2a5f820a6327f9ea1558717434c490e8aae 100644 (file)
@@ -9,7 +9,7 @@ be able to use diff(1).
 
 --------------------------- dentry_operations --------------------------
 prototypes:
-       int (*d_revalidate)(struct dentry *, struct nameidata *);
+       int (*d_revalidate)(struct dentry *, unsigned int);
        int (*d_hash)(const struct dentry *, const struct inode *,
                        struct qstr *);
        int (*d_compare)(const struct dentry *, const struct inode *,
@@ -37,9 +37,8 @@ d_manage:     no              no              yes (ref-walk)  maybe
 
 --------------------------- inode_operations --------------------------- 
 prototypes:
-       int (*create) (struct inode *,struct dentry *,umode_t, struct nameidata *);
-       struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameid
-ata *);
+       int (*create) (struct inode *,struct dentry *,umode_t, bool);
+       struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
        int (*link) (struct dentry *,struct inode *,struct dentry *);
        int (*unlink) (struct inode *,struct dentry *);
        int (*symlink) (struct inode *,struct dentry *,const char *);
@@ -62,6 +61,9 @@ ata *);
        int (*removexattr) (struct dentry *, const char *);
        int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len);
        void (*update_time)(struct inode *, struct timespec *, int);
+       int (*atomic_open)(struct inode *, struct dentry *,
+                               struct file *, unsigned open_flag,
+                               umode_t create_mode, int *opened);
 
 locking rules:
        all may block
@@ -89,6 +91,7 @@ listxattr:    no
 removexattr:   yes
 fiemap:                no
 update_time:   no
+atomic_open:   yes
 
        Additionally, ->rmdir(), ->unlink() and ->rename() have ->i_mutex on
 victim.
index 8c91d1057d9a141f77c0c64614eb17024d45256f..2bef2b3843d1d4e09ead99fed121de4b2ab92db2 100644 (file)
@@ -355,12 +355,10 @@ protects *all* the dcache state of a given dentry.
 via rcu-walk path walk (basically, if the file can have had a path name in the
 vfs namespace).
 
-       i_dentry and i_rcu share storage in a union, and the vfs expects
-i_dentry to be reinitialized before it is freed, so an:
-
-  INIT_LIST_HEAD(&inode->i_dentry);
-
-must be done in the RCU callback.
+       Even though i_dentry and i_rcu share storage in a union, we will
+initialize the former in inode_init_always(), so just leave it alone in
+the callback.  It used to be necessary to clean it there, but not anymore
+(starting at 3.2).
 
 --
 [recommended]
@@ -433,3 +431,14 @@ release it yourself.
        d_alloc_root() is gone, along with a lot of bugs caused by code
 misusing it.  Replacement: d_make_root(inode).  The difference is,
 d_make_root() drops the reference to inode if dentry allocation fails.  
+
+--
+[mandatory]
+       The witch is dead!  Well, 2/3 of it, anyway.  ->d_revalidate() and
+->lookup() do *not* take struct nameidata anymore; just the flags.
+--
+[mandatory]
+       ->create() doesn't take struct nameidata *; unlike the previous
+two, it gets "is it an O_EXCL or equivalent?" boolean argument.  Note that
+local filesystems can ignore tha argument - they are guaranteed that the
+object doesn't exist.  It's remote/distributed ones that might care...
index efd23f4817044ac9d55932bd9476d309a02918dc..aa754e01464e1c71f55869da9d5222ef763518d7 100644 (file)
@@ -341,8 +341,8 @@ This describes how the VFS can manipulate an inode in your
 filesystem. As of kernel 2.6.22, the following members are defined:
 
 struct inode_operations {
-       int (*create) (struct inode *,struct dentry *, umode_t, struct nameidata *);
-       struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
+       int (*create) (struct inode *,struct dentry *, umode_t, bool);
+       struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
        int (*link) (struct dentry *,struct inode *,struct dentry *);
        int (*unlink) (struct inode *,struct dentry *);
        int (*symlink) (struct inode *,struct dentry *,const char *);
@@ -364,6 +364,9 @@ struct inode_operations {
        ssize_t (*listxattr) (struct dentry *, char *, size_t);
        int (*removexattr) (struct dentry *, const char *);
        void (*update_time)(struct inode *, struct timespec *, int);
+       int (*atomic_open)(struct inode *, struct dentry *,
+                               struct file *, unsigned open_flag,
+                               umode_t create_mode, int *opened);
 };
 
 Again, all methods are called without any locks being held, unless
@@ -476,6 +479,14 @@ otherwise noted.
        an inode.  If this is not defined the VFS will update the inode itself
        and call mark_inode_dirty_sync.
 
+  atomic_open: called on the last component of an open.  Using this optional
+       method the filesystem can look up, possibly create and open the file in
+       one atomic operation.  If it cannot perform this (e.g. the file type
+       turned out to be wrong) it may signal this by returning 1 instead of
+       usual 0 or -ve .  This method is only called if the last
+       component is negative or needs lookup.  Cached positive dentries are
+       still handled by f_op->open().
+
 The Address Space Object
 ========================
 
@@ -891,7 +902,7 @@ the VFS uses a default. As of kernel 2.6.22, the following members are
 defined:
 
 struct dentry_operations {
-       int (*d_revalidate)(struct dentry *, struct nameidata *);
+       int (*d_revalidate)(struct dentry *, unsigned int);
        int (*d_hash)(const struct dentry *, const struct inode *,
                        struct qstr *);
        int (*d_compare)(const struct dentry *, const struct inode *,
@@ -910,11 +921,11 @@ struct dentry_operations {
        dcache. Most filesystems leave this as NULL, because all their
        dentries in the dcache are valid
 
-       d_revalidate may be called in rcu-walk mode (nd->flags & LOOKUP_RCU).
+       d_revalidate may be called in rcu-walk mode (flags & LOOKUP_RCU).
        If in rcu-walk mode, the filesystem must revalidate the dentry without
        blocking or storing to the dentry, d_parent and d_inode should not be
-       used without care (because they can go NULL), instead nd->inode should
-       be used.
+       used without care (because they can change and, in d_inode case, even
+       become NULL under us).
 
        If a situation is encountered that rcu-walk cannot handle, return
        -ECHILD and it will be called again in ref-walk mode.
index a92c5ebf373e2bf4bea68072b58fbc0471ad9c13..12783fa833c38041c94fb02cff34bc011b4d184d 100644 (file)
@@ -2367,6 +2367,11 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
                        Set maximum number of finished RCU callbacks to process
                        in one batch.
 
+       rcutree.fanout_leaf=    [KNL,BOOT]
+                       Increase the number of CPUs assigned to each
+                       leaf rcu_node structure.  Useful for very large
+                       systems.
+
        rcutree.qhimark=        [KNL,BOOT]
                        Set threshold of queued
                        RCU callbacks over which batch limiting is disabled.
index 872815cd41d30bcc8e57df31b6b283a4872a2690..504dfe4d52eba3541cfa6330d52595d37265a0b7 100644 (file)
@@ -583,9 +583,10 @@ for the given device during all power transitions, instead of the respective
 subsystem-level callbacks.  Specifically, if a device's pm_domain pointer is
 not NULL, the ->suspend() callback from the object pointed to by it will be
 executed instead of its subsystem's (e.g. bus type's) ->suspend() callback and
-anlogously for all of the remaining callbacks.  In other words, power management
-domain callbacks, if defined for the given device, always take precedence over
-the callbacks provided by the device's subsystem (e.g. bus type).
+analogously for all of the remaining callbacks.  In other words, power
+management domain callbacks, if defined for the given device, always take
+precedence over the callbacks provided by the device's subsystem (e.g. bus
+type).
 
 The support for device power management domains is only relevant to platforms
 needing to use the same device driver power management callbacks in many
@@ -598,7 +599,7 @@ it into account in any way.
 Device Low Power (suspend) States
 ---------------------------------
 Device low-power states aren't standard.  One device might only handle
-"on" and "off, while another might support a dozen different versions of
+"on" and "off", while another might support a dozen different versions of
 "on" (how many engines are active?), plus a state that gets back to "on"
 faster than from a full "off".
 
index ac190cf1963e05e310edf6a96df2466f01eb1355..92341b84250dfaf137b89376c115597a4bd9c222 100644 (file)
@@ -33,6 +33,11 @@ echo shutdown > /sys/power/disk; echo disk > /sys/power/state
 
 echo platform > /sys/power/disk; echo disk > /sys/power/state
 
+. If you would like to write hibernation image to swap and then suspend
+to RAM (provided your platform supports it), you can try
+
+echo suspend > /sys/power/disk; echo disk > /sys/power/state
+
 . If you have SATA disks, you'll need recent kernels with SATA suspend
 support. For suspend and resume to work, make sure your disk drivers
 are built into kernel -- not modules. [There's way to make
index fe5795020e6ef5519c0c1f1fde429ad920f10eef..7316ab62e5af3c0857acfbeff154e0bfaa0eb05e 100644 (file)
@@ -894,6 +894,14 @@ ARM/MAGICIAN MACHINE SUPPORT
 M:     Philipp Zabel <philipp.zabel@gmail.com>
 S:     Maintained
 
+ARM/Marvell Armada 370 and Armada XP SOC support
+M:     Jason Cooper <jason@lakedaemon.net>
+M:     Andrew Lunn <andrew@lunn.ch>
+M:     Gregory Clement <gregory.clement@free-electrons.com>
+L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+S:     Maintained
+F:     arch/arm/mach-mvebu/
+
 ARM/Marvell Dove/Kirkwood/MV78xx0/Orion SOC support
 M:     Jason Cooper <jason@lakedaemon.net>
 M:     Andrew Lunn <andrew@lunn.ch>
@@ -1103,6 +1111,16 @@ S:       Supported
 F:     arch/arm/mach-shmobile/
 F:     drivers/sh/
 
+ARM/SOCFPGA ARCHITECTURE
+M:     Dinh Nguyen <dinguyen@altera.com>
+S:     Maintained
+F:     arch/arm/mach-socfpga/
+
+ARM/SOCFPGA CLOCK FRAMEWORK SUPPORT
+M:     Dinh Nguyen <dinguyen@altera.com>
+S:     Maintained
+F:     drivers/clk/socfpga/
+
 ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
 M:     Lennert Buytenhek <kernel@wantstofly.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -6202,6 +6220,15 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/paulmck/linux-rcu.git
 F:     include/linux/srcu*
 F:     kernel/srcu*
 
+SMACK SECURITY MODULE
+M:     Casey Schaufler <casey@schaufler-ca.com>
+L:     linux-security-module@vger.kernel.org
+W:     http://schaufler-ca.com
+T:     git git://git.gitorious.org/smack-next/kernel.git
+S:     Maintained
+F:     Documentation/security/Smack.txt
+F:     security/smack/
+
 SMC91x ETHERNET DRIVER
 M:     Nicolas Pitre <nico@fluxnic.net>
 S:     Odd Fixes
@@ -6834,10 +6861,11 @@ F:      include/linux/shmem_fs.h
 F:     mm/shmem.c
 
 TPM DEVICE DRIVER
-M:     Debora Velarde <debora@linux.vnet.ibm.com>
-M:     Rajiv Andrade <srajiv@linux.vnet.ibm.com>
+M:     Kent Yoder <key@linux.vnet.ibm.com>
+M:     Rajiv Andrade <mail@srajiv.net>
 W:     http://tpmdd.sourceforge.net
-M:     Marcel Selhorst <m.selhorst@sirrix.com>
+M:     Marcel Selhorst <tpmdd@selhorst.net>
+M:     Sirrix AG <tpmdd@sirrix.com>
 W:     http://www.sirrix.com
 L:     tpmdd-devel@lists.sourceforge.net (moderated for non-subscribers)
 S:     Maintained
index aa8e315f26ef9b3aaef3509cf82489280bba382e..4bb09e1b1230d33d9328c2a67ba32aff22ebde7d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
 PATCHLEVEL = 5
 SUBLEVEL = 0
-EXTRAVERSION = -rc7
+EXTRAVERSION =
 NAME = Saber-toothed Squirrel
 
 # *DOCUMENTATION*
index a91009c6187062253579d0324292ade00ea2241c..c7e6d208fa8dd4d48f4bef05afcbd03539e9daee 100644 (file)
@@ -250,6 +250,25 @@ choice
        prompt "ARM system type"
        default ARCH_VERSATILE
 
+config ARCH_SOCFPGA
+       bool "Altera SOCFPGA family"
+       select ARCH_WANT_OPTIONAL_GPIOLIB
+       select ARM_AMBA
+       select ARM_GIC
+       select CACHE_L2X0
+       select CLKDEV_LOOKUP
+       select COMMON_CLK
+       select CPU_V7
+       select DW_APB_TIMER
+       select DW_APB_TIMER_OF
+       select GENERIC_CLOCKEVENTS
+       select GPIO_PL061 if GPIOLIB
+       select HAVE_ARM_SCU
+       select SPARSE_IRQ
+       select USE_OF
+       help
+         This enables support for Altera SOCFPGA Cyclone V platform
+
 config ARCH_INTEGRATOR
        bool "ARM Ltd. Integrator family"
        select ARM_AMBA
@@ -260,6 +279,7 @@ config ARCH_INTEGRATOR
        select ICST
        select GENERIC_CLOCKEVENTS
        select PLAT_VERSATILE
+       select PLAT_VERSATILE_CLOCK
        select PLAT_VERSATILE_FPGA_IRQ
        select NEED_MACH_IO_H
        select NEED_MACH_MEMORY_H
@@ -277,6 +297,7 @@ config ARCH_REALVIEW
        select GENERIC_CLOCKEVENTS
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select PLAT_VERSATILE
+       select PLAT_VERSATILE_CLOCK
        select PLAT_VERSATILE_CLCD
        select ARM_TIMER_SP804
        select GPIO_PL061 if GPIOLIB
@@ -295,6 +316,7 @@ config ARCH_VERSATILE
        select ARCH_WANT_OPTIONAL_GPIOLIB
        select NEED_MACH_IO_H if PCI
        select PLAT_VERSATILE
+       select PLAT_VERSATILE_CLOCK
        select PLAT_VERSATILE_CLCD
        select PLAT_VERSATILE_FPGA_IRQ
        select ARM_TIMER_SP804
@@ -307,7 +329,7 @@ config ARCH_VEXPRESS
        select ARM_AMBA
        select ARM_TIMER_SP804
        select CLKDEV_LOOKUP
-       select HAVE_MACH_CLKDEV
+       select COMMON_CLK
        select GENERIC_CLOCKEVENTS
        select HAVE_CLK
        select HAVE_PATA_PLATFORM
@@ -315,6 +337,7 @@ config ARCH_VEXPRESS
        select NO_IOPORT
        select PLAT_VERSATILE
        select PLAT_VERSATILE_CLCD
+       select REGULATOR_FIXED_VOLTAGE if REGULATOR
        help
          This enables support for the ARM Ltd Versatile Express boards.
 
@@ -389,6 +412,7 @@ config ARCH_PRIMA2
        bool "CSR SiRFSoC PRIMA2 ARM Cortex A9 Platform"
        select CPU_V7
        select NO_IOPORT
+       select ARCH_REQUIRE_GPIOLIB
        select GENERIC_CLOCKEVENTS
        select CLKDEV_LOOKUP
        select GENERIC_IRQ_CHIP
@@ -447,6 +471,8 @@ config ARCH_MXC
        select CLKSRC_MMIO
        select GENERIC_IRQ_CHIP
        select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
+       select USE_OF
        help
          Support for Freescale MXC/iMX-based family of processors
 
@@ -533,6 +559,18 @@ config ARCH_IXP4XX
        help
          Support for Intel's IXP4XX (XScale) family of processors.
 
+config ARCH_MVEBU
+       bool "Marvell SOCs with Device Tree support"
+       select GENERIC_CLOCKEVENTS
+       select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
+       select CLKSRC_MMIO
+       select GENERIC_IRQ_CHIP
+       select IRQ_DOMAIN
+       select COMMON_CLK
+       help
+         Support for the Marvell SoC Family with device tree support
+
 config ARCH_DOVE
        bool "Marvell Dove"
        select CPU_V7
@@ -567,6 +605,7 @@ config ARCH_LPC32XX
        select CLKDEV_LOOKUP
        select GENERIC_CLOCKEVENTS
        select USE_OF
+       select HAVE_PWM
        help
          Support for the NXP LPC32XX family of processors
 
@@ -647,6 +686,7 @@ config ARCH_TEGRA
        select MIGHT_HAVE_CACHE_L2X0
        select NEED_MACH_IO_H if PCI
        select ARCH_HAS_CPUFREQ
+       select USE_OF
        help
          This enables support for NVIDIA Tegra based systems (Tegra APX,
          Tegra 6xx and Tegra 2 series).
@@ -658,6 +698,7 @@ config ARCH_PICOXCELL
        select ARM_VIC
        select CPU_V6K
        select DW_APB_TIMER
+       select DW_APB_TIMER_OF
        select GENERIC_CLOCKEVENTS
        select GENERIC_GPIO
        select HAVE_TCM
@@ -913,7 +954,7 @@ config ARCH_NOMADIK
        select ARM_AMBA
        select ARM_VIC
        select CPU_ARM926T
-       select CLKDEV_LOOKUP
+       select COMMON_CLK
        select GENERIC_CLOCKEVENTS
        select PINCTRL
        select MIGHT_HAVE_CACHE_L2X0
@@ -936,6 +977,7 @@ config ARCH_DAVINCI
 
 config ARCH_OMAP
        bool "TI OMAP"
+       depends on MMU
        select HAVE_CLK
        select ARCH_REQUIRE_GPIOLIB
        select ARCH_HAS_CPUFREQ
@@ -987,6 +1029,8 @@ endchoice
 # Kconfigs may be included either alphabetically (according to the
 # plat- suffix) or along side the corresponding mach-* source.
 #
+source "arch/arm/mach-mvebu/Kconfig"
+
 source "arch/arm/mach-at91/Kconfig"
 
 source "arch/arm/mach-bcmring/Kconfig"
@@ -1021,8 +1065,6 @@ source "arch/arm/mach-kirkwood/Kconfig"
 
 source "arch/arm/mach-ks8695/Kconfig"
 
-source "arch/arm/mach-lpc32xx/Kconfig"
-
 source "arch/arm/mach-msm/Kconfig"
 
 source "arch/arm/mach-mv78xx0/Kconfig"
@@ -1581,6 +1623,7 @@ config ARCH_NR_GPIO
        default 1024 if ARCH_SHMOBILE || ARCH_TEGRA
        default 355 if ARCH_U8500
        default 264 if MACH_H4700
+       default 512 if SOC_OMAP5
        default 0
        help
          Maximum number of GPIOs in the system.
index 01a134141216a1a02f5fec43defa8768ad72fa26..a03b5a7059e2d059a34d7655fc6be7fe57ba1676 100644 (file)
@@ -310,6 +310,32 @@ choice
                  The uncompressor code port configuration is now handled
                  by CONFIG_S3C_LOWLEVEL_UART_PORT.
 
+       config DEBUG_VEXPRESS_UART0_DETECT
+               bool "Autodetect UART0 on Versatile Express Cortex-A core tiles"
+               depends on ARCH_VEXPRESS && CPU_CP15_MMU
+               help
+                 This option enables a simple heuristic which tries to determine
+                 the motherboard's memory map variant (original or RS1) and then
+                 choose the relevant UART0 base address.
+
+                 Note that this will only work with standard A-class core tiles,
+                 and may fail with non-standard SMM or custom software models.
+
+       config DEBUG_VEXPRESS_UART0_CA9
+               bool "Use PL011 UART0 at 0x10009000 (V2P-CA9 core tile)"
+               depends on ARCH_VEXPRESS
+               help
+                 This option selects UART0 at 0x10009000. Except for custom models,
+                 this applies only to the V2P-CA9 tile.
+
+       config DEBUG_VEXPRESS_UART0_RS1
+               bool "Use PL011 UART0 at 0x1c090000 (RS1 complaint tiles)"
+               depends on ARCH_VEXPRESS
+               help
+                 This option selects UART0 at 0x1c090000. This applies to most
+                 of the tiles using the RS1 memory map, including all new A-class
+                 core tiles, FPGA-based SMMs and software models.
+
        config DEBUG_LL_UART_NONE
                bool "No low-level debugging UART"
                help
index 0298b00fe2413a1964cd899b9834136c3166136a..4d6d31115cf2df07b0df8ebe790cf51c94aa65b9 100644 (file)
@@ -157,6 +157,7 @@ machine-$(CONFIG_ARCH_MV78XX0)              := mv78xx0
 machine-$(CONFIG_ARCH_IMX_V4_V5)       := imx
 machine-$(CONFIG_ARCH_IMX_V6_V7)       := imx
 machine-$(CONFIG_ARCH_MXS)             := mxs
+machine-$(CONFIG_ARCH_MVEBU)           := mvebu
 machine-$(CONFIG_ARCH_NETX)            := netx
 machine-$(CONFIG_ARCH_NOMADIK)         := nomadik
 machine-$(CONFIG_ARCH_OMAP1)           := omap1
@@ -186,6 +187,7 @@ machine-$(CONFIG_ARCH_VEXPRESS)             := vexpress
 machine-$(CONFIG_ARCH_VT8500)          := vt8500
 machine-$(CONFIG_ARCH_W90X900)         := w90x900
 machine-$(CONFIG_FOOTBRIDGE)           := footbridge
+machine-$(CONFIG_ARCH_SOCFPGA)         := socfpga
 machine-$(CONFIG_MACH_SPEAR1310)       := spear13xx
 machine-$(CONFIG_MACH_SPEAR1340)       := spear13xx
 machine-$(CONFIG_MACH_SPEAR300)                := spear3xx
diff --git a/arch/arm/boot/dts/aks-cdu.dts b/arch/arm/boot/dts/aks-cdu.dts
new file mode 100644 (file)
index 0000000..29b9f15
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * aks-cdu.dts - Device Tree file for AK signal CDU
+ *
+ * Copyright (C) 2012 AK signal Brno a.s.
+ *               2012 Jiri Prchal <jiri.prchal@aksignal.cz>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/dts-v1/;
+
+/include/ "ge863-pro3.dtsi"
+
+/ {
+       chosen {
+               bootargs = "console=ttyS0,115200 ubi.mtd=4 root=ubi0:rootfs rootfstype=ubifs";
+       };
+
+       ahb {
+               apb {
+                       usart0: serial@fffb0000 {
+                               status = "okay";
+                       };
+
+                       usart1: serial@fffb4000 {
+                               status = "okay";
+                               linux,rs485-enabled-at-boot-time;
+                               rs485-rts-delay = <0 0>;
+                               };
+
+                       usart2: serial@fffb8000 {
+                               status = "okay";
+                               linux,rs485-enabled-at-boot-time;
+                               rs485-rts-delay = <0 0>;
+                       };
+
+                       usart3: serial@fffd0000 {
+                               status = "okay";
+                               linux,rs485-enabled-at-boot-time;
+                               rs485-rts-delay = <0 0>;
+                       };
+
+                       macb0: ethernet@fffc4000 {
+                               phy-mode = "rmii";
+                               status = "okay";
+                       };
+
+                       usb1: gadget@fffa4000 {
+                               atmel,vbus-gpio = <&pioC 15 0>;
+                               status = "okay";
+                       };
+               };
+
+               usb0: ohci@00500000 {
+                       num-ports = <2>;
+                       status = "okay";
+               };
+
+               nand0: nand@40000000 {
+                       nand-bus-width = <8>;
+                       nand-ecc-mode = "soft";
+                       nand-on-flash-bbt;
+                       status = "okay";
+
+                       bootstrap@0 {
+                               label = "bootstrap";
+                               reg = <0x0 0x40000>;
+                       };
+
+                       uboot@40000 {
+                               label = "uboot";
+                               reg = <0x40000 0x80000>;
+                       };
+                       ubootenv@c0000 {
+                               label = "ubootenv";
+                               reg = <0xc0000 0x40000>;
+                       };
+                       kernel@100000 {
+                               label = "kernel";
+                               reg = <0x100000 0x400000>;
+                       };
+                       rootfs@500000 {
+                               label = "rootfs";
+                               reg = <0x500000 0x7b00000>;
+                       };
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               red {
+                       gpios = <&pioC 10 0>;
+                       linux,default-trigger = "none";
+               };
+
+               green {
+                       gpios = <&pioA 5 1>;
+                       linux,default-trigger = "none";
+                       default-state = "on";
+               };
+
+               yellow {
+                       gpios = <&pioB 20 1>;
+                       linux,default-trigger = "none";
+               };
+
+               blue {
+                       gpios = <&pioB 21 1>;
+                       linux,default-trigger = "none";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts
new file mode 100644 (file)
index 0000000..a9af4db
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "am33xx.dtsi"
+
+/ {
+       model = "TI AM335x BeagleBone";
+       compatible = "ti,am335x-bone", "ti,am33xx";
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x10000000>; /* 256 MB */
+       };
+};
diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts
new file mode 100644 (file)
index 0000000..d6a97d9
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "am33xx.dtsi"
+
+/ {
+       model = "TI AM335x EVM";
+       compatible = "ti,am335x-evm", "ti,am33xx";
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x10000000>; /* 256 MB */
+       };
+};
diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi
new file mode 100644 (file)
index 0000000..59509c4
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Device Tree Source for AM33XX SoC
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+       compatible = "ti,am33xx";
+
+       aliases {
+               serial0 = &uart1;
+               serial1 = &uart2;
+               serial2 = &uart3;
+               serial3 = &uart4;
+               serial4 = &uart5;
+               serial5 = &uart6;
+       };
+
+       cpus {
+               cpu@0 {
+                       compatible = "arm,cortex-a8";
+               };
+       };
+
+       /*
+        * The soc node represents the soc top level view. It is uses for IPs
+        * that are not memory mapped in the MPU view or for the MPU itself.
+        */
+       soc {
+               compatible = "ti,omap-infra";
+               mpu {
+                       compatible = "ti,omap3-mpu";
+                       ti,hwmods = "mpu";
+               };
+       };
+
+       /*
+        * XXX: Use a flat representation of the AM33XX interconnect.
+        * The real AM33XX interconnect network is quite complex.Since
+        * that will not bring real advantage to represent that in DT
+        * for the moment, just use a fake OCP bus entry to represent
+        * the whole bus hierarchy.
+        */
+       ocp {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+               ti,hwmods = "l3_main";
+
+               intc: interrupt-controller@48200000 {
+                       compatible = "ti,omap2-intc";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+                       ti,intc-size = <128>;
+                       reg = <0x48200000 0x1000>;
+               };
+
+               gpio1: gpio@44e07000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio1";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio2: gpio@4804C000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio2";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio3: gpio@481AC000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio3";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio4: gpio@481AE000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio4";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               uart1: serial@44E09000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart1";
+                       clock-frequency = <48000000>;
+               };
+
+               uart2: serial@48022000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart2";
+                       clock-frequency = <48000000>;
+               };
+
+               uart3: serial@48024000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart3";
+                       clock-frequency = <48000000>;
+               };
+
+               uart4: serial@481A6000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart4";
+                       clock-frequency = <48000000>;
+               };
+
+               uart5: serial@481A8000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart5";
+                       clock-frequency = <48000000>;
+               };
+
+               uart6: serial@481AA000 {
+                       compatible = "ti,omap3-uart";
+                       ti,hwmods = "uart6";
+                       clock-frequency = <48000000>;
+               };
+
+               i2c1: i2c@44E0B000 {
+                       compatible = "ti,omap4-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       ti,hwmods = "i2c1";
+               };
+
+               i2c2: i2c@4802A000 {
+                       compatible = "ti,omap4-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       ti,hwmods = "i2c2";
+               };
+
+               i2c3: i2c@4819C000 {
+                       compatible = "ti,omap4-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       ti,hwmods = "i2c3";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/am3517-evm.dts b/arch/arm/boot/dts/am3517-evm.dts
new file mode 100644 (file)
index 0000000..474f760
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap3.dtsi"
+
+/ {
+       model = "TI AM3517 EVM (AM3517/05)";
+       compatible = "ti,am3517-evm", "ti,omap3";
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x10000000>; /* 256 MB */
+       };
+};
+
+&i2c1 {
+       clock-frequency = <400000>;
+};
+
+&i2c2 {
+       clock-frequency = <400000>;
+};
+
+&i2c3 {
+       clock-frequency = <400000>;
+};
diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts
new file mode 100644 (file)
index 0000000..fffd5c2
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Device Tree file for Marvell Armada 370 evaluation board
+ * (DB-88F6710-BP-DDR3)
+ *
+ *  Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/dts-v1/;
+/include/ "armada-370.dtsi"
+
+/ {
+       model = "Marvell Armada 370 Evaluation Board";
+       compatible = "marvell,a370-db", "marvell,armada370", "marvell,armada-370-xp";
+
+       chosen {
+               bootargs = "console=ttyS0,115200 earlyprintk";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x20000000>; /* 512 MB */
+       };
+
+       soc {
+               serial@d0012000 {
+                       clock-frequency = <200000000>;
+                       status = "okay";
+               };
+               timer@d0020300 {
+                       clock-frequency = <600000000>;
+                       status = "okay";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/armada-370-xp.dtsi b/arch/arm/boot/dts/armada-370-xp.dtsi
new file mode 100644 (file)
index 0000000..6b6b932
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * Device Tree Include file for Marvell Armada 370 and Armada XP SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ * Ben Dooks <ben.dooks@codethink.co.uk>
+ *
+ * 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.
+ *
+ * This file contains the definitions that are common to the Armada
+ * 370 and Armada XP SoC.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+       model = "Marvell Armada 370 and XP SoC";
+       compatible = "marvell,armada_370_xp";
+
+       cpus {
+               cpu@0 {
+                       compatible = "marvell,sheeva-v7";
+               };
+       };
+
+       mpic: interrupt-controller@d0020000 {
+             compatible = "marvell,mpic";
+             #interrupt-cells = <1>;
+             #address-cells = <1>;
+             #size-cells = <1>;
+             interrupt-controller;
+       };
+
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "simple-bus";
+               interrupt-parent = <&mpic>;
+               ranges;
+
+               serial@d0012000 {
+                               compatible = "ns16550";
+                               reg = <0xd0012000 0x100>;
+                               reg-shift = <2>;
+                               interrupts = <41>;
+                               status = "disabled";
+               };
+               serial@d0012100 {
+                               compatible = "ns16550";
+                               reg = <0xd0012100 0x100>;
+                               reg-shift = <2>;
+                               interrupts = <42>;
+                               status = "disabled";
+               };
+
+               timer@d0020300 {
+                              compatible = "marvell,armada-370-xp-timer";
+                              reg = <0xd0020300 0x30>;
+                              interrupts = <37>, <38>, <39>, <40>;
+               };
+       };
+};
+
diff --git a/arch/arm/boot/dts/armada-370.dtsi b/arch/arm/boot/dts/armada-370.dtsi
new file mode 100644 (file)
index 0000000..3228ccc
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Device Tree Include file for Marvell Armada 370 family SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Contains definitions specific to the Armada 370 SoC that are not
+ * common to all Armada SoCs.
+ */
+
+/include/ "armada-370-xp.dtsi"
+
+/ {
+       model = "Marvell Armada 370 family SoC";
+       compatible = "marvell,armada370", "marvell,armada-370-xp";
+
+       mpic: interrupt-controller@d0020000 {
+             reg = <0xd0020a00 0x1d0>,
+                   <0xd0021870 0x58>;
+       };
+
+       soc {
+               system-controller@d0018200 {
+                               compatible = "marvell,armada-370-xp-system-controller";
+                               reg = <0xd0018200 0x100>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/armada-xp-db.dts b/arch/arm/boot/dts/armada-xp-db.dts
new file mode 100644 (file)
index 0000000..f97040d
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Device Tree file for Marvell Armada XP evaluation board
+ * (DB-78460-BP)
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+/dts-v1/;
+/include/ "armada-xp.dtsi"
+
+/ {
+       model = "Marvell Armada XP Evaluation Board";
+       compatible = "marvell,axp-db", "marvell,armadaxp", "marvell,armada-370-xp";
+
+       chosen {
+               bootargs = "console=ttyS0,115200 earlyprintk";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x80000000>; /* 2 GB */
+       };
+
+       soc {
+               serial@d0012000 {
+                       clock-frequency = <250000000>;
+                       status = "okay";
+               };
+               serial@d0012100 {
+                       clock-frequency = <250000000>;
+                       status = "okay";
+               };
+               serial@d0012200 {
+                       clock-frequency = <250000000>;
+                       status = "okay";
+               };
+               serial@d0012300 {
+                       clock-frequency = <250000000>;
+                       status = "okay";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/armada-xp.dtsi b/arch/arm/boot/dts/armada-xp.dtsi
new file mode 100644 (file)
index 0000000..e1fa7e6
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Device Tree Include file for Marvell Armada XP family SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ * Ben Dooks <ben.dooks@codethink.co.uk>
+ *
+ * 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.
+ *
+ * Contains definitions specific to the Armada 370 SoC that are not
+ * common to all Armada SoCs.
+ */
+
+/include/ "armada-370-xp.dtsi"
+
+/ {
+       model = "Marvell Armada XP family SoC";
+       compatible = "marvell,armadaxp", "marvell,armada-370-xp";
+
+       mpic: interrupt-controller@d0020000 {
+             reg = <0xd0020a00 0x1d0>,
+                   <0xd0021870 0x58>;
+       };
+
+       soc {
+               serial@d0012200 {
+                               compatible = "ns16550";
+                               reg = <0xd0012200 0x100>;
+                               reg-shift = <2>;
+                               interrupts = <43>;
+                               status = "disabled";
+               };
+               serial@d0012300 {
+                               compatible = "ns16550";
+                               reg = <0xd0012300 0x100>;
+                               reg-shift = <2>;
+                               interrupts = <44>;
+                               status = "disabled";
+               };
+
+               timer@d0020300 {
+                               marvell,timer-25Mhz;
+               };
+
+               system-controller@d0018200 {
+                               compatible = "marvell,armada-370-xp-system-controller";
+                               reg = <0xd0018200 0x500>;
+               };
+       };
+};
index f449efc9825fd711d485b57318adf02b47e01f3e..66389c1c6f6297e50c8ae3b944d7311dcbb26b6c 100644 (file)
                        ranges;
 
                        aic: interrupt-controller@fffff000 {
-                               #interrupt-cells = <2>;
+                               #interrupt-cells = <3>;
                                compatible = "atmel,at91rm9200-aic";
                                interrupt-controller;
                                reg = <0xfffff000 0x200>;
+                               atmel,external-irqs = <29 30 31>;
                        };
 
                        ramc0: ramc@ffffea00 {
                        pit: timer@fffffd30 {
                                compatible = "atmel,at91sam9260-pit";
                                reg = <0xfffffd30 0xf>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                        };
 
                        tcb0: timer@fffa0000 {
                                compatible = "atmel,at91rm9200-tcb";
                                reg = <0xfffa0000 0x100>;
-                               interrupts = <17 4 18 4 19 4>;
+                               interrupts = <17 4 0 18 4 0 19 4 0>;
                        };
 
                        tcb1: timer@fffdc000 {
                                compatible = "atmel,at91rm9200-tcb";
                                reg = <0xfffdc000 0x100>;
-                               interrupts = <26 4 27 4 28 4>;
+                               interrupts = <26 4 0 27 4 0 28 4 0>;
                        };
 
                        pioA: gpio@fffff400 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff400 0x100>;
-                               interrupts = <2 4>;
+                               interrupts = <2 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioB: gpio@fffff600 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff600 0x100>;
-                               interrupts = <3 4>;
+                               interrupts = <3 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioC: gpio@fffff800 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff800 0x100>;
-                               interrupts = <4 4>;
+                               interrupts = <4 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        dbgu: serial@fffff200 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                                status = "disabled";
                        };
 
                        usart0: serial@fffb0000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffb0000 0x200>;
-                               interrupts = <6 4>;
+                               interrupts = <6 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart1: serial@fffb4000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffb4000 0x200>;
-                               interrupts = <7 4>;
+                               interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart2: serial@fffb8000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffb8000 0x200>;
-                               interrupts = <8 4>;
+                               interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart3: serial@fffd0000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffd0000 0x200>;
-                               interrupts = <23 4>;
+                               interrupts = <23 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart4: serial@fffd4000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffd4000 0x200>;
-                               interrupts = <24 4>;
+                               interrupts = <24 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart5: serial@fffd8000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffd8000 0x200>;
-                               interrupts = <25 4>;
+                               interrupts = <25 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        macb0: ethernet@fffc4000 {
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xfffc4000 0x100>;
-                               interrupts = <21 4>;
+                               interrupts = <21 4 3>;
                                status = "disabled";
                        };
 
                        usb1: gadget@fffa4000 {
                                compatible = "atmel,at91rm9200-udc";
                                reg = <0xfffa4000 0x4000>;
-                               interrupts = <10 4>;
+                               interrupts = <10 4 2>;
                                status = "disabled";
                        };
 
                        adc0: adc@fffe0000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xfffe0000 0x100>;
-                               interrupts = <5 4>;
+                               interrupts = <5 4 0>;
                                atmel,adc-use-external-triggers;
                                atmel,adc-channels-used = <0xf>;
                                atmel,adc-vref = <3300>;
                usb0: ohci@00500000 {
                        compatible = "atmel,at91rm9200-ohci", "usb-ohci";
                        reg = <0x00500000 0x100000>;
-                       interrupts = <20 4>;
+                       interrupts = <20 4 2>;
                        status = "disabled";
                };
        };
index 0209913a65a2001dafea2bacda1ce741fa227872..b460d6ce9eb592da5191871b40b2d3433156bcef 100644 (file)
                        ranges;
 
                        aic: interrupt-controller@fffff000 {
-                               #interrupt-cells = <2>;
+                               #interrupt-cells = <3>;
                                compatible = "atmel,at91rm9200-aic";
                                interrupt-controller;
                                reg = <0xfffff000 0x200>;
+                               atmel,external-irqs = <30 31>;
                        };
 
                        pmc: pmc@fffffc00 {
                        pit: timer@fffffd30 {
                                compatible = "atmel,at91sam9260-pit";
                                reg = <0xfffffd30 0xf>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                        };
 
                        tcb0: timer@fff7c000 {
                                compatible = "atmel,at91rm9200-tcb";
                                reg = <0xfff7c000 0x100>;
-                               interrupts = <19 4>;
+                               interrupts = <19 4 0>;
                        };
 
                        rstc@fffffd00 {
@@ -90,7 +91,7 @@
                        pioA: gpio@fffff200 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff200 0x100>;
-                               interrupts = <2 4>;
+                               interrupts = <2 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioB: gpio@fffff400 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff400 0x100>;
-                               interrupts = <3 4>;
+                               interrupts = <3 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioC: gpio@fffff600 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff600 0x100>;
-                               interrupts = <4 4>;
+                               interrupts = <4 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioD: gpio@fffff800 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff800 0x100>;
-                               interrupts = <4 4>;
+                               interrupts = <4 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioE: gpio@fffffa00 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffffa00 0x100>;
-                               interrupts = <4 4>;
+                               interrupts = <4 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        dbgu: serial@ffffee00 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xffffee00 0x200>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                                status = "disabled";
                        };
 
                        usart0: serial@fff8c000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfff8c000 0x200>;
-                               interrupts = <7 4>;
+                               interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart1: serial@fff90000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfff90000 0x200>;
-                               interrupts = <8 4>;
+                               interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart2: serial@fff94000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfff94000 0x200>;
-                               interrupts = <9 4>;
+                               interrupts = <9 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        macb0: ethernet@fffbc000 {
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xfffbc000 0x100>;
-                               interrupts = <21 4>;
+                               interrupts = <21 4 3>;
                                status = "disabled";
                        };
 
                        usb1: gadget@fff78000 {
                                compatible = "atmel,at91rm9200-udc";
                                reg = <0xfff78000 0x4000>;
-                               interrupts = <24 4>;
+                               interrupts = <24 4 2>;
                                status = "disabled";
                        };
                };
                usb0: ohci@00a00000 {
                        compatible = "atmel,at91rm9200-ohci", "usb-ohci";
                        reg = <0x00a00000 0x100000>;
-                       interrupts = <29 4>;
+                       interrupts = <29 4 2>;
                        status = "disabled";
                };
        };
index 7dbccaf199f7e0844bdeb3ee8cf789d8543f0a6f..bafa8806fc17293e3bddc28aff5b4829f677c178 100644 (file)
                        ranges;
 
                        aic: interrupt-controller@fffff000 {
-                               #interrupt-cells = <2>;
+                               #interrupt-cells = <3>;
                                compatible = "atmel,at91rm9200-aic";
                                interrupt-controller;
                                reg = <0xfffff000 0x200>;
+                               atmel,external-irqs = <31>;
                        };
 
                        ramc0: ramc@ffffe400 {
@@ -78,7 +79,7 @@
                        pit: timer@fffffd30 {
                                compatible = "atmel,at91sam9260-pit";
                                reg = <0xfffffd30 0xf>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                        };
 
 
                        tcb0: timer@fff7c000 {
                                compatible = "atmel,at91rm9200-tcb";
                                reg = <0xfff7c000 0x100>;
-                               interrupts = <18 4>;
+                               interrupts = <18 4 0>;
                        };
 
                        tcb1: timer@fffd4000 {
                                compatible = "atmel,at91rm9200-tcb";
                                reg = <0xfffd4000 0x100>;
-                               interrupts = <18 4>;
+                               interrupts = <18 4 0>;
                        };
 
                        dma: dma-controller@ffffec00 {
                                compatible = "atmel,at91sam9g45-dma";
                                reg = <0xffffec00 0x200>;
-                               interrupts = <21 4>;
+                               interrupts = <21 4 0>;
                        };
 
                        pioA: gpio@fffff200 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff200 0x100>;
-                               interrupts = <2 4>;
+                               interrupts = <2 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioB: gpio@fffff400 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff400 0x100>;
-                               interrupts = <3 4>;
+                               interrupts = <3 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioC: gpio@fffff600 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff600 0x100>;
-                               interrupts = <4 4>;
+                               interrupts = <4 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioD: gpio@fffff800 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffff800 0x100>;
-                               interrupts = <5 4>;
+                               interrupts = <5 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioE: gpio@fffffa00 {
                                compatible = "atmel,at91rm9200-gpio";
                                reg = <0xfffffa00 0x100>;
-                               interrupts = <5 4>;
+                               interrupts = <5 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        dbgu: serial@ffffee00 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xffffee00 0x200>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                                status = "disabled";
                        };
 
                        usart0: serial@fff8c000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfff8c000 0x200>;
-                               interrupts = <7 4>;
+                               interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart1: serial@fff90000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfff90000 0x200>;
-                               interrupts = <8 4>;
+                               interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart2: serial@fff94000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfff94000 0x200>;
-                               interrupts = <9 4>;
+                               interrupts = <9 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart3: serial@fff98000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfff98000 0x200>;
-                               interrupts = <10 4>;
+                               interrupts = <10 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        macb0: ethernet@fffbc000 {
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xfffbc000 0x100>;
-                               interrupts = <25 4>;
+                               interrupts = <25 4 3>;
                                status = "disabled";
                        };
 
                        adc0: adc@fffb0000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xfffb0000 0x100>;
-                               interrupts = <20 4>;
+                               interrupts = <20 4 0>;
                                atmel,adc-use-external-triggers;
                                atmel,adc-channels-used = <0xff>;
                                atmel,adc-vref = <3300>;
                usb0: ohci@00700000 {
                        compatible = "atmel,at91rm9200-ohci", "usb-ohci";
                        reg = <0x00700000 0x100000>;
-                       interrupts = <22 4>;
+                       interrupts = <22 4 2>;
                        status = "disabled";
                };
 
                usb1: ehci@00800000 {
                        compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
                        reg = <0x00800000 0x100000>;
-                       interrupts = <22 4>;
+                       interrupts = <22 4 2>;
                        status = "disabled";
                };
        };
index cb84de791b5ab9906e66e9664fcc80b4ae314b6e..bfac0dfc332c7d10bc3fe2f87458ec728c48b885 100644 (file)
@@ -50,7 +50,7 @@
                        ranges;
 
                        aic: interrupt-controller@fffff000 {
-                               #interrupt-cells = <2>;
+                               #interrupt-cells = <3>;
                                compatible = "atmel,at91rm9200-aic";
                                interrupt-controller;
                                reg = <0xfffff000 0x200>;
@@ -74,7 +74,7 @@
                        pit: timer@fffffe30 {
                                compatible = "atmel,at91sam9260-pit";
                                reg = <0xfffffe30 0xf>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                        };
 
                        shdwc@fffffe10 {
                        tcb0: timer@f8008000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf8008000 0x100>;
-                               interrupts = <17 4>;
+                               interrupts = <17 4 0>;
                        };
 
                        tcb1: timer@f800c000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf800c000 0x100>;
-                               interrupts = <17 4>;
+                               interrupts = <17 4 0>;
                        };
 
                        dma: dma-controller@ffffec00 {
                                compatible = "atmel,at91sam9g45-dma";
                                reg = <0xffffec00 0x200>;
-                               interrupts = <20 4>;
+                               interrupts = <20 4 0>;
                        };
 
                        pioA: gpio@fffff400 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffff400 0x100>;
-                               interrupts = <2 4>;
+                               interrupts = <2 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioB: gpio@fffff600 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffff600 0x100>;
-                               interrupts = <2 4>;
+                               interrupts = <2 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioC: gpio@fffff800 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffff800 0x100>;
-                               interrupts = <3 4>;
+                               interrupts = <3 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioD: gpio@fffffa00 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffffa00 0x100>;
-                               interrupts = <3 4>;
+                               interrupts = <3 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        dbgu: serial@fffff200 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                                status = "disabled";
                        };
 
                        usart0: serial@f801c000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf801c000 0x4000>;
-                               interrupts = <5 4>;
+                               interrupts = <5 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart1: serial@f8020000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf8020000 0x4000>;
-                               interrupts = <6 4>;
+                               interrupts = <6 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart2: serial@f8024000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf8024000 0x4000>;
-                               interrupts = <7 4>;
+                               interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart3: serial@f8028000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf8028000 0x4000>;
-                               interrupts = <8 4>;
+                               interrupts = <8 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                usb0: ohci@00500000 {
                        compatible = "atmel,at91rm9200-ohci", "usb-ohci";
                        reg = <0x00500000 0x00100000>;
-                       interrupts = <22 4>;
+                       interrupts = <22 4 2>;
                        status = "disabled";
                };
        };
index 6b3ef4339ae7030eff85882a89f04d29ea346c21..4a18c393b1360f490c9796f3c598d349338ed2f5 100644 (file)
                        ranges;
 
                        aic: interrupt-controller@fffff000 {
-                               #interrupt-cells = <2>;
+                               #interrupt-cells = <3>;
                                compatible = "atmel,at91rm9200-aic";
                                interrupt-controller;
                                reg = <0xfffff000 0x200>;
+                               atmel,external-irqs = <31>;
                        };
 
                        ramc0: ramc@ffffe800 {
                        pit: timer@fffffe30 {
                                compatible = "atmel,at91sam9260-pit";
                                reg = <0xfffffe30 0xf>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                        };
 
                        tcb0: timer@f8008000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf8008000 0x100>;
-                               interrupts = <17 4>;
+                               interrupts = <17 4 0>;
                        };
 
                        tcb1: timer@f800c000 {
                                compatible = "atmel,at91sam9x5-tcb";
                                reg = <0xf800c000 0x100>;
-                               interrupts = <17 4>;
+                               interrupts = <17 4 0>;
                        };
 
                        dma0: dma-controller@ffffec00 {
                                compatible = "atmel,at91sam9g45-dma";
                                reg = <0xffffec00 0x200>;
-                               interrupts = <20 4>;
+                               interrupts = <20 4 0>;
                        };
 
                        dma1: dma-controller@ffffee00 {
                                compatible = "atmel,at91sam9g45-dma";
                                reg = <0xffffee00 0x200>;
-                               interrupts = <21 4>;
+                               interrupts = <21 4 0>;
                        };
 
                        pioA: gpio@fffff400 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffff400 0x100>;
-                               interrupts = <2 4>;
+                               interrupts = <2 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioB: gpio@fffff600 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffff600 0x100>;
-                               interrupts = <2 4>;
+                               interrupts = <2 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioC: gpio@fffff800 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffff800 0x100>;
-                               interrupts = <3 4>;
+                               interrupts = <3 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        pioD: gpio@fffffa00 {
                                compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
                                reg = <0xfffffa00 0x100>;
-                               interrupts = <3 4>;
+                               interrupts = <3 4 1>;
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
                        dbgu: serial@fffff200 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xfffff200 0x200>;
-                               interrupts = <1 4>;
+                               interrupts = <1 4 7>;
                                status = "disabled";
                        };
 
                        usart0: serial@f801c000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf801c000 0x200>;
-                               interrupts = <5 4>;
+                               interrupts = <5 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart1: serial@f8020000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf8020000 0x200>;
-                               interrupts = <6 4>;
+                               interrupts = <6 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        usart2: serial@f8024000 {
                                compatible = "atmel,at91sam9260-usart";
                                reg = <0xf8024000 0x200>;
-                               interrupts = <7 4>;
+                               interrupts = <7 4 5>;
                                atmel,use-dma-rx;
                                atmel,use-dma-tx;
                                status = "disabled";
                        macb0: ethernet@f802c000 {
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xf802c000 0x100>;
-                               interrupts = <24 4>;
+                               interrupts = <24 4 3>;
                                status = "disabled";
                        };
 
                        macb1: ethernet@f8030000 {
                                compatible = "cdns,at32ap7000-macb", "cdns,macb";
                                reg = <0xf8030000 0x100>;
-                               interrupts = <27 4>;
+                               interrupts = <27 4 3>;
                                status = "disabled";
                        };
 
                        adc0: adc@f804c000 {
                                compatible = "atmel,at91sam9260-adc";
                                reg = <0xf804c000 0x100>;
-                               interrupts = <19 4>;
+                               interrupts = <19 4 0>;
                                atmel,adc-use-external;
                                atmel,adc-channels-used = <0xffff>;
                                atmel,adc-vref = <3300>;
                usb0: ohci@00600000 {
                        compatible = "atmel,at91rm9200-ohci", "usb-ohci";
                        reg = <0x00600000 0x100000>;
-                       interrupts = <22 4>;
+                       interrupts = <22 4 2>;
                        status = "disabled";
                };
 
                usb1: ehci@00700000 {
                        compatible = "atmel,at91sam9g45-ehci", "usb-ehci";
                        reg = <0x00700000 0x100000>;
-                       interrupts = <22 4>;
+                       interrupts = <22 4 2>;
                        status = "disabled";
                };
        };
index 4ad5160018cb522922201b3dfebf9c0462b6ef85..3180a9c588b921d21ac9cea8b28e1c91b634686b 100644 (file)
@@ -48,7 +48,7 @@
                };
 
                rtc@80154000 {
-                       compatible = "stericsson,db8500-rtc";
+                       compatible = "arm,rtc-pl031", "arm,primecell";
                        reg = <0x80154000 0x1000>;
                        interrupts = <0 18 0x4>;
                };
@@ -60,7 +60,7 @@
                        interrupts = <0 119 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <0>;
@@ -73,7 +73,7 @@
                        interrupts = <0 120 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <1>;
@@ -86,7 +86,7 @@
                        interrupts = <0 121 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <2>;
@@ -99,7 +99,7 @@
                        interrupts = <0 122 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <3>;
                        interrupts = <0 123 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <4>;
                        interrupts = <0 124 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <5>;
                        interrupts = <0 125 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <6>;
                        interrupts = <0 126 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <7>;
                        interrupts = <0 127 0x4>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
-                       supports-sleepmode;
+                       st,supports-sleepmode;
                        gpio-controller;
                        #gpio-cells = <2>;
                        gpio-bank = <8>;
 
                                // DB8500_REGULATOR_VAPE
                                db8500_vape_reg: db8500_vape {
+                                       regulator-compatible = "db8500_vape";
                                        regulator-name = "db8500-vape";
                                        regulator-always-on;
                                };
 
                                // DB8500_REGULATOR_VARM
                                db8500_varm_reg: db8500_varm {
+                                       regulator-compatible = "db8500_varm";
                                        regulator-name = "db8500-varm";
                                };
 
                                // DB8500_REGULATOR_VMODEM
                                db8500_vmodem_reg: db8500_vmodem {
+                                       regulator-compatible = "db8500_vmodem";
                                        regulator-name = "db8500-vmodem";
                                };
 
                                // DB8500_REGULATOR_VPLL
                                db8500_vpll_reg: db8500_vpll {
+                                       regulator-compatible = "db8500_vpll";
                                        regulator-name = "db8500-vpll";
                                };
 
                                // DB8500_REGULATOR_VSMPS1
                                db8500_vsmps1_reg: db8500_vsmps1 {
+                                       regulator-compatible = "db8500_vsmps1";
                                        regulator-name = "db8500-vsmps1";
                                };
 
                                // DB8500_REGULATOR_VSMPS2
                                db8500_vsmps2_reg: db8500_vsmps2 {
+                                       regulator-compatible = "db8500_vsmps2";
                                        regulator-name = "db8500-vsmps2";
                                };
 
                                // DB8500_REGULATOR_VSMPS3
                                db8500_vsmps3_reg: db8500_vsmps3 {
+                                       regulator-compatible = "db8500_vsmps3";
                                        regulator-name = "db8500-vsmps3";
                                };
 
                                // DB8500_REGULATOR_VRF1
                                db8500_vrf1_reg: db8500_vrf1 {
+                                       regulator-compatible = "db8500_vrf1";
                                        regulator-name = "db8500-vrf1";
                                };
 
                                // DB8500_REGULATOR_SWITCH_SVAMMDSP
                                db8500_sva_mmdsp_reg: db8500_sva_mmdsp {
+                                       regulator-compatible = "db8500_sva_mmdsp";
                                        regulator-name = "db8500-sva-mmdsp";
                                };
 
                                // DB8500_REGULATOR_SWITCH_SVAMMDSPRET
                                db8500_sva_mmdsp_ret_reg: db8500_sva_mmdsp_ret {
+                                       regulator-compatible = "db8500_sva_mmdsp_ret";
                                        regulator-name = "db8500-sva-mmdsp-ret";
                                };
 
                                // DB8500_REGULATOR_SWITCH_SVAPIPE
                                db8500_sva_pipe_reg: db8500_sva_pipe {
+                                       regulator-compatible = "db8500_sva_pipe";
                                        regulator-name = "db8500_sva_pipe";
                                };
 
                                // DB8500_REGULATOR_SWITCH_SIAMMDSP
                                db8500_sia_mmdsp_reg: db8500_sia_mmdsp {
+                                       regulator-compatible = "db8500_sia_mmdsp";
                                        regulator-name = "db8500_sia_mmdsp";
                                };
 
 
                                // DB8500_REGULATOR_SWITCH_SIAPIPE
                                db8500_sia_pipe_reg: db8500_sia_pipe {
+                                       regulator-compatible = "db8500_sia_pipe";
                                        regulator-name = "db8500-sia-pipe";
                                };
 
                                // DB8500_REGULATOR_SWITCH_SGA
                                db8500_sga_reg: db8500_sga {
+                                       regulator-compatible = "db8500_sga";
                                        regulator-name = "db8500-sga";
                                        vin-supply = <&db8500_vape_reg>;
                                };
 
                                // DB8500_REGULATOR_SWITCH_B2R2_MCDE
                                db8500_b2r2_mcde_reg: db8500_b2r2_mcde {
+                                       regulator-compatible = "db8500_b2r2_mcde";
                                        regulator-name = "db8500-b2r2-mcde";
                                        vin-supply = <&db8500_vape_reg>;
                                };
 
                                // DB8500_REGULATOR_SWITCH_ESRAM12
                                db8500_esram12_reg: db8500_esram12 {
+                                       regulator-compatible = "db8500_esram12";
                                        regulator-name = "db8500-esram12";
                                };
 
                                // DB8500_REGULATOR_SWITCH_ESRAM12RET
                                db8500_esram12_ret_reg: db8500_esram12_ret {
+                                       regulator-compatible = "db8500_esram12_ret";
                                        regulator-name = "db8500-esram12-ret";
                                };
 
                                // DB8500_REGULATOR_SWITCH_ESRAM34
                                db8500_esram34_reg: db8500_esram34 {
+                                       regulator-compatible = "db8500_esram34";
                                        regulator-name = "db8500-esram34";
                                };
 
                                // DB8500_REGULATOR_SWITCH_ESRAM34RET
                                db8500_esram34_ret_reg: db8500_esram34_ret {
+                                       regulator-compatible = "db8500_esram34_ret";
                                        regulator-name = "db8500-esram34-ret";
                                };
                        };
                                compatible = "stericsson,ab8500";
                                reg = <5>; /* mailbox 5 is i2c */
                                interrupts = <0 40 0x4>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+
+                               ab8500-rtc {
+                                       compatible = "stericsson,ab8500-rtc";
+                                       interrupts = <17 0x4
+                                                     18 0x4>;
+                                       interrupt-names = "60S", "ALARM";
+                               };
+
+                               ab8500-gpadc {
+                                       compatible = "stericsson,ab8500-gpadc";
+                                       interrupts = <32 0x4
+                                                     39 0x4>;
+                                       interrupt-names = "HW_CONV_END", "SW_CONV_END";
+                                       vddadc-supply = <&ab8500_ldo_tvout_reg>;
+                               };
+
+                               ab8500-usb {
+                                       compatible = "stericsson,ab8500-usb";
+                                       interrupts = < 90 0x4
+                                                      96 0x4
+                                                      14 0x4
+                                                      15 0x4
+                                                      79 0x4
+                                                      74 0x4
+                                                      75 0x4>;
+                                       interrupt-names = "ID_WAKEUP_R",
+                                                         "ID_WAKEUP_F",
+                                                         "VBUS_DET_F",
+                                                         "VBUS_DET_R",
+                                                         "USB_LINK_STATUS",
+                                                         "USB_ADP_PROBE_PLUG",
+                                                         "USB_ADP_PROBE_UNPLUG";
+                                       vddulpivio18-supply = <&ab8500_ldo_initcore_reg>;
+                                       v-ape-supply = <&db8500_vape_reg>;
+                                       musb_1v8-supply = <&db8500_vsmps2_reg>;
+                               };
+
+                               ab8500-ponkey {
+                                       compatible = "stericsson,ab8500-ponkey";
+                                       interrupts = <6 0x4
+                                                     7 0x4>;
+                                       interrupt-names = "ONKEY_DBF", "ONKEY_DBR";
+                               };
+
+                               ab8500-sysctrl {
+                                       compatible = "stericsson,ab8500-sysctrl";
+                               };
+
+                               ab8500-pwm {
+                                       compatible = "stericsson,ab8500-pwm";
+                               };
+
+                               ab8500-debugfs {
+                                       compatible = "stericsson,ab8500-debug";
+                               };
 
                                ab8500-regulators {
                                        compatible = "stericsson,ab8500-regulator";
 
                                        // supplies to the display/camera
                                        ab8500_ldo_aux1_reg: ab8500_ldo_aux1 {
+                                               regulator-compatible = "ab8500_ldo_aux1";
                                                regulator-name = "V-DISPLAY";
                                                regulator-min-microvolt = <2500000>;
                                                regulator-max-microvolt = <2900000>;
 
                                        // supplies to the on-board eMMC
                                        ab8500_ldo_aux2_reg: ab8500_ldo_aux2 {
+                                               regulator-compatible = "ab8500_ldo_aux2";
                                                regulator-name = "V-eMMC1";
                                                regulator-min-microvolt = <1100000>;
                                                regulator-max-microvolt = <3300000>;
 
                                        // supply for VAUX3; SDcard slots
                                        ab8500_ldo_aux3_reg: ab8500_ldo_aux3 {
+                                               regulator-compatible = "ab8500_ldo_aux3";
                                                regulator-name = "V-MMC-SD";
                                                regulator-min-microvolt = <1100000>;
                                                regulator-max-microvolt = <3300000>;
 
                                        // supply for v-intcore12; VINTCORE12 LDO
                                        ab8500_ldo_initcore_reg: ab8500_ldo_initcore {
+                                               regulator-compatible = "ab8500_ldo_initcore";
                                                regulator-name = "V-INTCORE";
                                        };
 
                                        // supply for tvout; gpadc; TVOUT LDO
                                        ab8500_ldo_tvout_reg: ab8500_ldo_tvout {
+                                               regulator-compatible = "ab8500_ldo_tvout";
                                                regulator-name = "V-TVOUT";
                                        };
 
                                        // supply for ab8500-usb; USB LDO
                                        ab8500_ldo_usb_reg: ab8500_ldo_usb {
+                                               regulator-compatible = "ab8500_ldo_usb";
                                                regulator-name = "dummy";
                                        };
 
                                        // supply for ab8500-vaudio; VAUDIO LDO
                                        ab8500_ldo_audio_reg: ab8500_ldo_audio {
+                                               regulator-compatible = "ab8500_ldo_audio";
                                                regulator-name = "V-AUD";
                                        };
 
                                        // supply for v-anamic1 VAMic1-LDO
                                        ab8500_ldo_anamic1_reg: ab8500_ldo_anamic1 {
+                                               regulator-compatible = "ab8500_ldo_anamic1";
                                                regulator-name = "V-AMIC1";
                                        };
 
                                        // supply for v-amic2; VAMIC2 LDO; reuse constants for AMIC1
                                        ab8500_ldo_amamic2_reg: ab8500_ldo_amamic2 {
+                                               regulator-compatible = "ab8500_ldo_amamic2";
                                                regulator-name = "V-AMIC2";
                                        };
 
                                        // supply for v-dmic; VDMIC LDO
                                        ab8500_ldo_dmic_reg: ab8500_ldo_dmic {
+                                               regulator-compatible = "ab8500_ldo_dmic";
                                                regulator-name = "V-DMIC";
                                        };
 
                                        // supply for U8500 CSI/DSI; VANA LDO
                                        ab8500_ldo_ana_reg: ab8500_ldo_ana {
+                                               regulator-compatible = "ab8500_ldo_ana";
                                                regulator-name = "V-CSI/DSI";
                                        };
                                };
diff --git a/arch/arm/boot/dts/ea3250.dts b/arch/arm/boot/dts/ea3250.dts
new file mode 100644 (file)
index 0000000..d79b28d
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ * Embedded Artists LPC3250 board
+ *
+ * Copyright 2012 Roland Stigge <stigge@antcom.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "lpc32xx.dtsi"
+
+/ {
+       model = "Embedded Artists LPC3250 board based on NXP LPC3250";
+       compatible = "ea,ea3250", "nxp,lpc3250";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory {
+               device_type = "memory";
+               reg = <0 0x4000000>;
+       };
+
+       ahb {
+               mac: ethernet@31060000 {
+                       phy-mode = "rmii";
+                       use-iram;
+               };
+
+               /* Here, choose exactly one from: ohci, usbd */
+               ohci@31020000 {
+                       transceiver = <&isp1301>;
+                       status = "okay";
+               };
+
+/*
+               usbd@31020000 {
+                       transceiver = <&isp1301>;
+                       status = "okay";
+               };
+*/
+
+               /* 128MB Flash via SLC NAND controller */
+               slc: flash@20020000 {
+                       status = "okay";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       nxp,wdr-clks = <14>;
+                       nxp,wwidth = <260000000>;
+                       nxp,whold = <104000000>;
+                       nxp,wsetup = <200000000>;
+                       nxp,rdr-clks = <14>;
+                       nxp,rwidth = <34666666>;
+                       nxp,rhold = <104000000>;
+                       nxp,rsetup = <200000000>;
+                       nand-on-flash-bbt;
+                       gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */
+
+                       mtd0@00000000 {
+                               label = "ea3250-boot";
+                               reg = <0x00000000 0x00080000>;
+                               read-only;
+                       };
+
+                       mtd1@00080000 {
+                               label = "ea3250-uboot";
+                               reg = <0x00080000 0x000c0000>;
+                               read-only;
+                       };
+
+                       mtd2@00140000 {
+                               label = "ea3250-kernel";
+                               reg = <0x00140000 0x00400000>;
+                       };
+
+                       mtd3@00540000 {
+                               label = "ea3250-rootfs";
+                               reg = <0x00540000 0x07ac0000>;
+                       };
+               };
+
+               apb {
+                       uart5: serial@40090000 {
+                               status = "okay";
+                       };
+
+                       uart3: serial@40080000 {
+                               status = "okay";
+                       };
+
+                       uart6: serial@40098000 {
+                               status = "okay";
+                       };
+
+                       i2c1: i2c@400A0000 {
+                               clock-frequency = <100000>;
+
+                               eeprom@50 {
+                                       compatible = "at,24c256";
+                                       reg = <0x50>;
+                               };
+
+                               eeprom@57 {
+                                       compatible = "at,24c64";
+                                       reg = <0x57>;
+                               };
+
+                               uda1380: uda1380@18 {
+                                       compatible = "nxp,uda1380";
+                                       reg = <0x18>;
+                                       power-gpio = <&gpio 0x59 0>;
+                                       reset-gpio = <&gpio 0x51 0>;
+                                       dac-clk = "wspll";
+                               };
+
+                               pca9532: pca9532@60 {
+                                       compatible = "nxp,pca9532";
+                                       gpio-controller;
+                                       #gpio-cells = <2>;
+                                       reg = <0x60>;
+                               };
+                       };
+
+                       i2c2: i2c@400A8000 {
+                               clock-frequency = <100000>;
+                       };
+
+                       i2cusb: i2c@31020300 {
+                               clock-frequency = <100000>;
+
+                               isp1301: usb-transceiver@2d {
+                                       compatible = "nxp,isp1301";
+                                       reg = <0x2d>;
+                               };
+                       };
+
+                       sd@20098000 {
+                               wp-gpios = <&pca9532 5 0>;
+                               cd-gpios = <&pca9532 4 0>;
+                               cd-inverted;
+                               bus-width = <4>;
+                               status = "okay";
+                       };
+               };
+
+               fab {
+                       uart1: serial@40014000 {
+                               status = "okay";
+                       };
+
+                       /* 3-axis accelerometer X,Y,Z (or AD-IN instead of Z) */
+                       adc@40048000 {
+                               status = "okay";
+                       };
+               };
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               autorepeat;
+               button@21 {
+                       label = "GPIO Key UP";
+                       linux,code = <103>;
+                       gpios = <&gpio 4 1 0>; /* GPI_P3 1 */
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/evk-pro3.dts b/arch/arm/boot/dts/evk-pro3.dts
new file mode 100644 (file)
index 0000000..b7354e6
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * evk-pro3.dts - Device Tree file for Telit EVK-PRO3 with Telit GE863-PRO3
+ *
+ * Copyright (C) 2012 Telit,
+ *               2012 Fabio Porcedda <fabio.porcedda@gmail.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/dts-v1/;
+
+/include/ "ge863-pro3.dtsi"
+
+/ {
+       model = "Telit EVK-PRO3 for Telit GE863-PRO3";
+       compatible = "telit,evk-pro3", "atmel,at91sam9260", "atmel,at91sam9";
+
+       ahb {
+               apb {
+                       macb0: ethernet@fffc4000 {
+                               phy-mode = "rmii";
+                               status = "okay";
+                       };
+
+                       usb1: gadget@fffa4000 {
+                               atmel,vbus-gpio = <&pioC 5 0>;
+                               status = "okay";
+                       };
+               };
+
+               usb0: ohci@00500000 {
+                       num-ports = <2>;
+                       status = "okay";
+               };
+       };
+
+       i2c@0 {
+               status = "okay";
+       };
+
+};
\ No newline at end of file
index b8c476384eef92d8ec7d44eac1d5e275a84e4de1..0c49caa099786b4c247831da4b539da7a32711ab 100644 (file)
        i2c@138D0000 {
                status = "disabled";
        };
+
+       spi_0: spi@13920000 {
+               status = "disabled";
+       };
+
+       spi_1: spi@13930000 {
+               status = "disabled";
+       };
+
+       spi_2: spi@13940000 {
+               status = "disabled";
+       };
 };
index 27afc8e535ca69618de7a10c9fabb5a35983f2a4..1beccc8f14ff948c622a6af681141221139ba021 100644 (file)
        i2c@138D0000 {
                status = "disabled";
        };
+
+       spi_0: spi@13920000 {
+               status = "disabled";
+       };
+
+       spi_1: spi@13930000 {
+               status = "disabled";
+       };
+
+       spi_2: spi@13940000 {
+               gpios = <&gpc1 1 5 3 0>,
+                       <&gpc1 3 5 3 0>,
+                       <&gpc1 4 5 3 0>;
+
+               w25x80@0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "w25x80";
+                       reg = <0>;
+                       spi-max-frequency = <1000000>;
+
+                       controller-data {
+                               cs-gpio = <&gpc1 2 1 0 3>;
+                               samsung,spi-feedback-delay = <0>;
+                       };
+
+                       partition@0 {
+                               label = "U-Boot";
+                               reg = <0x0 0x40000>;
+                               read-only;
+                       };
+
+                       partition@40000 {
+                               label = "Kernel";
+                               reg = <0x40000 0xc0000>;
+                       };
+               };
+       };
 };
index a1dd2ee83753d0740c4d774dd03b556b2614f309..02891fe876e43bbbdb947aae28840baa7f9fa860 100644 (file)
        compatible = "samsung,exynos4210";
        interrupt-parent = <&gic>;
 
+       aliases {
+               spi0 = &spi_0;
+               spi1 = &spi_1;
+               spi2 = &spi_2;
+       };
+
        gic:interrupt-controller@10490000 {
                compatible = "arm,cortex-a9-gic";
                #interrupt-cells = <3>;
                reg = <0x10490000 0x1000>, <0x10480000 0x100>;
        };
 
+       combiner:interrupt-controller@10440000 {
+               compatible = "samsung,exynos4210-combiner";
+               #interrupt-cells = <2>;
+               interrupt-controller;
+               reg = <0x10440000 0x1000>;
+               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>;
+       };
+
        watchdog@10060000 {
                compatible = "samsung,s3c2410-wdt";
                reg = <0x10060000 0x100>;
                interrupts = <0 65 0>;
        };
 
+       spi_0: spi@13920000 {
+               compatible = "samsung,exynos4210-spi";
+               reg = <0x13920000 0x100>;
+               interrupts = <0 66 0>;
+               tx-dma-channel = <&pdma0 7>; /* preliminary */
+               rx-dma-channel = <&pdma0 6>; /* preliminary */
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       spi_1: spi@13930000 {
+               compatible = "samsung,exynos4210-spi";
+               reg = <0x13930000 0x100>;
+               interrupts = <0 67 0>;
+               tx-dma-channel = <&pdma1 7>; /* preliminary */
+               rx-dma-channel = <&pdma1 6>; /* preliminary */
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       spi_2: spi@13940000 {
+               compatible = "samsung,exynos4210-spi";
+               reg = <0x13940000 0x100>;
+               interrupts = <0 68 0>;
+               tx-dma-channel = <&pdma0 9>; /* preliminary */
+               rx-dma-channel = <&pdma0 8>; /* preliminary */
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
        amba {
                #address-cells = <1>;
                #size-cells = <1>;
index 49945cc1bc7df3795b71812c67f98c3ec88e5e72..8a5e348793c765e8caf189004f8c04848378206d 100644 (file)
        i2c@12CD0000 {
                status = "disabled";
        };
+
+       spi_0: spi@12d20000 {
+               status = "disabled";
+       };
+
+       spi_1: spi@12d30000 {
+               gpios = <&gpa2 4 2 3 0>,
+                       <&gpa2 6 2 3 0>,
+                       <&gpa2 7 2 3 0>;
+
+               w25q80bw@0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "w25x80";
+                       reg = <0>;
+                       spi-max-frequency = <1000000>;
+
+                       controller-data {
+                               cs-gpio = <&gpa2 5 1 0 3>;
+                               samsung,spi-feedback-delay = <0>;
+                       };
+
+                       partition@0 {
+                               label = "U-Boot";
+                               reg = <0x0 0x40000>;
+                               read-only;
+                       };
+
+                       partition@40000 {
+                               label = "Kernel";
+                               reg = <0x40000 0xc0000>;
+                       };
+               };
+       };
+
+       spi_2: spi@12d40000 {
+               status = "disabled";
+       };
 };
index 4272b2949228ba2e4ea9d7ebb7bc2285fd9bb19b..004aaa8d123cd66fed607c7c45ebc5827cd018dd 100644 (file)
        compatible = "samsung,exynos5250";
        interrupt-parent = <&gic>;
 
+       aliases {
+               spi0 = &spi_0;
+               spi1 = &spi_1;
+               spi2 = &spi_2;
+       };
+
        gic:interrupt-controller@10481000 {
                compatible = "arm,cortex-a9-gic";
                #interrupt-cells = <3>;
                #size-cells = <0>;
        };
 
+       spi_0: spi@12d20000 {
+               compatible = "samsung,exynos4210-spi";
+               reg = <0x12d20000 0x100>;
+               interrupts = <0 66 0>;
+               tx-dma-channel = <&pdma0 5>; /* preliminary */
+               rx-dma-channel = <&pdma0 4>; /* preliminary */
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       spi_1: spi@12d30000 {
+               compatible = "samsung,exynos4210-spi";
+               reg = <0x12d30000 0x100>;
+               interrupts = <0 67 0>;
+               tx-dma-channel = <&pdma1 5>; /* preliminary */
+               rx-dma-channel = <&pdma1 4>; /* preliminary */
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       spi_2: spi@12d40000 {
+               compatible = "samsung,exynos4210-spi";
+               reg = <0x12d40000 0x100>;
+               interrupts = <0 68 0>;
+               tx-dma-channel = <&pdma0 7>; /* preliminary */
+               rx-dma-channel = <&pdma0 6>; /* preliminary */
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
        amba {
                #address-cells = <1>;
                #size-cells = <1>;
diff --git a/arch/arm/boot/dts/ge863-pro3.dtsi b/arch/arm/boot/dts/ge863-pro3.dtsi
new file mode 100644 (file)
index 0000000..17136fc
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * ge863_pro3.dtsi - Device Tree file for Telit GE863-PRO3
+ *
+ * Copyright (C) 2012 Telit,
+ *               2012 Fabio Porcedda <fabio.porcedda@gmail.com>
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "at91sam9260.dtsi"
+
+/ {
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               main_clock: clock@0 {
+                       compatible = "atmel,osc", "fixed-clock";
+                       clock-frequency = <6000000>;
+               };
+       };
+
+       ahb {
+               apb {
+                       dbgu: serial@fffff200 {
+                               status = "okay";
+                       };
+               };
+
+               nand0: nand@40000000 {
+                       nand-bus-width = <8>;
+                       nand-ecc-mode = "soft";
+                       nand-on-flash-bbt;
+                       status = "okay";
+
+                       boot@0 {
+                               label = "boot";
+                               reg = <0x0 0x7c0000>;
+                       };
+
+                       root@07c0000 {
+                               label = "root";
+                               reg = <0x7c0000 0x7840000>;
+                       };
+               };
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200 root=ubi0:rootfs ubi.mtd=1 rootfstype=ubifs";
+       };
+};
index 70bffa929b659b43ab67de96d00663475ed89a4a..e3486f486b405cfb74cb1dcbe41f808a49f5e658 100644 (file)
 
        apb@80000000 {
                apbh@80000000 {
+                       gpmi-nand@8000c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&gpmi_pins_a &gpmi_pins_fixup>;
+                               status = "okay";
+                       };
+
                        ssp0: ssp@80010000 {
                                compatible = "fsl,imx23-mmc";
                                pinctrl-names = "default";
-                               pinctrl-0 = <&mmc0_8bit_pins_a &mmc0_pins_fixup>;
-                               bus-width = <8>;
+                               pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>;
+                               bus-width = <4>;
                                wp-gpios = <&gpio1 30 0>;
+                               vmmc-supply = <&reg_vddio_sd0>;
+                               status = "okay";
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog-gpios@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x1123 /* MX23_PAD_LCD_RESET__GPIO_1_18 */
+                                               0x11d3 /* MX23_PAD_PWM3__GPIO_1_29 */
+                                               0x11e3 /* MX23_PAD_PWM4__GPIO_1_30 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+                       };
+
+                       lcdif@80030000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&lcdif_24bit_pins_a>;
+                               panel-enable-gpios = <&gpio1 18 0>;
                                status = "okay";
                        };
                };
 
                apbx@80040000 {
+                       pwm: pwm@80064000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pwm2_pins_a>;
+                               status = "okay";
+                       };
+
+                       auart0: serial@8006c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_pins_a>;
+                               status = "okay";
+                       };
+
                        duart: serial@80070000 {
                                pinctrl-names = "default";
                                pinctrl-0 = <&duart_pins_a>;
                        };
                };
        };
+
+       regulators {
+               compatible = "simple-bus";
+
+               reg_vddio_sd0: vddio-sd0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "vddio-sd0";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       gpio = <&gpio1 29 0>;
+               };
+       };
+
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm 2 5000000>;
+               brightness-levels = <0 4 8 16 32 64 128 255>;
+               default-brightness-level = <6>;
+       };
 };
diff --git a/arch/arm/boot/dts/imx23-olinuxino.dts b/arch/arm/boot/dts/imx23-olinuxino.dts
new file mode 100644 (file)
index 0000000..20912b1
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * Author: Fabio Estevam <fabio.estevam@freescale.com>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx23.dtsi"
+
+/ {
+       model = "i.MX23 Olinuxino Low Cost Board";
+       compatible = "olimex,imx23-olinuxino", "fsl,imx23";
+
+       memory {
+               reg = <0x40000000 0x04000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx23-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>;
+                               bus-width = <4>;
+                               status = "okay";
+                       };
+               };
+
+               apbx@80040000 {
+                       duart: serial@80070000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_a>;
+                               status = "okay";
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/imx23-stmp378x_devb.dts b/arch/arm/boot/dts/imx23-stmp378x_devb.dts
new file mode 100644 (file)
index 0000000..757a327
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx23.dtsi"
+
+/ {
+       model = "Freescale STMP378x Development Board";
+       compatible = "fsl,stmp378x-devb", "fsl,imx23";
+
+       memory {
+               reg = <0x40000000 0x04000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx23-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_pins_fixup>;
+                               bus-width = <4>;
+                               wp-gpios = <&gpio1 30 0>;
+                               vmmc-supply = <&reg_vddio_sd0>;
+                               status = "okay";
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog-gpios@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x11d3 /* MX23_PAD_PWM3__GPIO_1_29 */
+                                               0x11e3 /* MX23_PAD_PWM4__GPIO_1_30 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+                       };
+               };
+
+               apbx@80040000 {
+                       auart0: serial@8006c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_pins_a>;
+                               status = "okay";
+                       };
+
+                       duart: serial@80070000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_a>;
+                               status = "okay";
+                       };
+               };
+       };
+
+       regulators {
+               compatible = "simple-bus";
+
+               reg_vddio_sd0: vddio-sd0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "vddio-sd0";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       gpio = <&gpio1 29 0>;
+               };
+       };
+};
index 8c5f9994f3fc226265c83e3d6fe44952319b1725..a874dbfb5ae69da5d6771c75d9605ca3bbbcbcaa 100644 (file)
@@ -18,6 +18,8 @@
                gpio0 = &gpio0;
                gpio1 = &gpio1;
                gpio2 = &gpio2;
+               serial0 = &auart0;
+               serial1 = &auart1;
        };
 
        cpus {
                                status = "disabled";
                        };
 
-                       bch@8000a000 {
-                               reg = <0x8000a000 2000>;
-                               status = "disabled";
-                       };
-
-                       gpmi@8000c000 {
-                               reg = <0x8000c000 2000>;
+                       gpmi-nand@8000c000 {
+                               compatible = "fsl,imx23-gpmi-nand";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0x8000c000 2000>, <0x8000a000 2000>;
+                               reg-names = "gpmi-nand", "bch";
+                               interrupts = <13>, <56>;
+                               interrupt-names = "gpmi-dma", "bch";
+                               fsl,gpmi-dma-channel = <4>;
                                status = "disabled";
                        };
 
 
                                duart_pins_a: duart@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x11a2 0x11b2>;
+                                       fsl,pinmux-ids = <
+                                               0x11a2 /* MX23_PAD_PWM0__DUART_RX */
+                                               0x11b2 /* MX23_PAD_PWM1__DUART_TX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               auart0_pins_a: auart0@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x01c0 /* MX23_PAD_AUART1_RX__AUART1_RX */
+                                               0x01d0 /* MX23_PAD_AUART1_TX__AUART1_TX */
+                                               0x01a0 /* MX23_PAD_AUART1_CTS__AUART1_CTS */
+                                               0x01b0 /* MX23_PAD_AUART1_RTS__AUART1_RTS */
+                                       >;
                                        fsl,drive-strength = <0>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <0>;
                                };
 
+                               gpmi_pins_a: gpmi-nand@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x0000 /* MX23_PAD_GPMI_D00__GPMI_D00 */
+                                               0x0010 /* MX23_PAD_GPMI_D01__GPMI_D01 */
+                                               0x0020 /* MX23_PAD_GPMI_D02__GPMI_D02 */
+                                               0x0030 /* MX23_PAD_GPMI_D03__GPMI_D03 */
+                                               0x0040 /* MX23_PAD_GPMI_D04__GPMI_D04 */
+                                               0x0050 /* MX23_PAD_GPMI_D05__GPMI_D05 */
+                                               0x0060 /* MX23_PAD_GPMI_D06__GPMI_D06 */
+                                               0x0070 /* MX23_PAD_GPMI_D07__GPMI_D07 */
+                                               0x0100 /* MX23_PAD_GPMI_CLE__GPMI_CLE */
+                                               0x0110 /* MX23_PAD_GPMI_ALE__GPMI_ALE */
+                                               0x0130 /* MX23_PAD_GPMI_RDY0__GPMI_RDY0 */
+                                               0x0140 /* MX23_PAD_GPMI_RDY1__GPMI_RDY1 */
+                                               0x0170 /* MX23_PAD_GPMI_WPN__GPMI_WPN */
+                                               0x0180 /* MX23_PAD_GPMI_WRN__GPMI_WRN */
+                                               0x0190 /* MX23_PAD_GPMI_RDN__GPMI_RDN */
+                                               0x21b0 /* MX23_PAD_GPMI_CE1N__GPMI_CE1N */
+                                               0x21c0 /* MX23_PAD_GPMI_CE0N__GPMI_CE0N */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               gpmi_pins_fixup: gpmi-pins-fixup {
+                                       fsl,pinmux-ids = <
+                                               0x0170 /* MX23_PAD_GPMI_WPN__GPMI_WPN */
+                                               0x0180 /* MX23_PAD_GPMI_WRN__GPMI_WRN */
+                                               0x0190 /* MX23_PAD_GPMI_RDN__GPMI_RDN */
+                                       >;
+                                       fsl,drive-strength = <2>;
+                               };
+
+                               mmc0_4bit_pins_a: mmc0-4bit@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x2020 /* MX23_PAD_SSP1_DATA0__SSP1_DATA0 */
+                                               0x2030 /* MX23_PAD_SSP1_DATA1__SSP1_DATA1 */
+                                               0x2040 /* MX23_PAD_SSP1_DATA2__SSP1_DATA2 */
+                                               0x2050 /* MX23_PAD_SSP1_DATA3__SSP1_DATA3 */
+                                               0x2000 /* MX23_PAD_SSP1_CMD__SSP1_CMD */
+                                               0x2010 /* MX23_PAD_SSP1_DETECT__SSP1_DETECT */
+                                               0x2060 /* MX23_PAD_SSP1_SCK__SSP1_SCK */
+                                       >;
+                                       fsl,drive-strength = <1>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <1>;
+                               };
+
                                mmc0_8bit_pins_a: mmc0-8bit@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x2020 0x2030 0x2040
-                                               0x2050 0x0082 0x0092 0x00a2
-                                               0x00b2 0x2000 0x2010 0x2060>;
+                                       fsl,pinmux-ids = <
+                                               0x2020 /* MX23_PAD_SSP1_DATA0__SSP1_DATA0 */
+                                               0x2030 /* MX23_PAD_SSP1_DATA1__SSP1_DATA1 */
+                                               0x2040 /* MX23_PAD_SSP1_DATA2__SSP1_DATA2 */
+                                               0x2050 /* MX23_PAD_SSP1_DATA3__SSP1_DATA3 */
+                                               0x0082 /* MX23_PAD_GPMI_D08__SSP1_DATA4 */
+                                               0x0092 /* MX23_PAD_GPMI_D09__SSP1_DATA5 */
+                                               0x00a2 /* MX23_PAD_GPMI_D10__SSP1_DATA6 */
+                                               0x00b2 /* MX23_PAD_GPMI_D11__SSP1_DATA7 */
+                                               0x2000 /* MX23_PAD_SSP1_CMD__SSP1_CMD */
+                                               0x2010 /* MX23_PAD_SSP1_DETECT__SSP1_DETECT */
+                                               0x2060 /* MX23_PAD_SSP1_SCK__SSP1_SCK */
+                                       >;
                                        fsl,drive-strength = <1>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <1>;
                                };
 
                                mmc0_pins_fixup: mmc0-pins-fixup {
-                                       fsl,pinmux-ids = <0x2010 0x2060>;
+                                       fsl,pinmux-ids = <
+                                               0x2010 /* MX23_PAD_SSP1_DETECT__SSP1_DETECT */
+                                               0x2060 /* MX23_PAD_SSP1_SCK__SSP1_SCK */
+                                       >;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               pwm2_pins_a: pwm2@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x11c0 /* MX23_PAD_PWM2__PWM2 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               lcdif_24bit_pins_a: lcdif-24bit@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x1000 /* MX23_PAD_LCD_D00__LCD_D0 */
+                                               0x1010 /* MX23_PAD_LCD_D01__LCD_D1 */
+                                               0x1020 /* MX23_PAD_LCD_D02__LCD_D2 */
+                                               0x1030 /* MX23_PAD_LCD_D03__LCD_D3 */
+                                               0x1040 /* MX23_PAD_LCD_D04__LCD_D4 */
+                                               0x1050 /* MX23_PAD_LCD_D05__LCD_D5 */
+                                               0x1060 /* MX23_PAD_LCD_D06__LCD_D6 */
+                                               0x1070 /* MX23_PAD_LCD_D07__LCD_D7 */
+                                               0x1080 /* MX23_PAD_LCD_D08__LCD_D8 */
+                                               0x1090 /* MX23_PAD_LCD_D09__LCD_D9 */
+                                               0x10a0 /* MX23_PAD_LCD_D10__LCD_D10 */
+                                               0x10b0 /* MX23_PAD_LCD_D11__LCD_D11 */
+                                               0x10c0 /* MX23_PAD_LCD_D12__LCD_D12 */
+                                               0x10d0 /* MX23_PAD_LCD_D13__LCD_D13 */
+                                               0x10e0 /* MX23_PAD_LCD_D14__LCD_D14 */
+                                               0x10f0 /* MX23_PAD_LCD_D15__LCD_D15 */
+                                               0x1100 /* MX23_PAD_LCD_D16__LCD_D16 */
+                                               0x1110 /* MX23_PAD_LCD_D17__LCD_D17 */
+                                               0x0081 /* MX23_PAD_GPMI_D08__LCD_D18 */
+                                               0x0091 /* MX23_PAD_GPMI_D09__LCD_D19 */
+                                               0x00a1 /* MX23_PAD_GPMI_D10__LCD_D20 */
+                                               0x00b1 /* MX23_PAD_GPMI_D11__LCD_D21 */
+                                               0x00c1 /* MX23_PAD_GPMI_D12__LCD_D22 */
+                                               0x00d1 /* MX23_PAD_GPMI_D13__LCD_D23 */
+                                               0x1160 /* MX23_PAD_LCD_DOTCK__LCD_DOTCK */
+                                               0x1170 /* MX23_PAD_LCD_ENABLE__LCD_ENABLE */
+                                               0x1180 /* MX23_PAD_LCD_HSYNC__LCD_HSYNC */
+                                               0x1190 /* MX23_PAD_LCD_VSYNC__LCD_VSYNC */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
                                        fsl,pull-up = <0>;
                                };
                        };
                        };
 
                        lcdif@80030000 {
+                               compatible = "fsl,imx23-lcdif";
                                reg = <0x80030000 2000>;
+                               interrupts = <46 45>;
                                status = "disabled";
                        };
 
                        };
 
                        rtc@8005c000 {
+                               compatible = "fsl,imx23-rtc", "fsl,stmp3xxx-rtc";
                                reg = <0x8005c000 2000>;
-                               status = "disabled";
+                               interrupts = <22>;
                        };
 
-                       pwm@80064000 {
+                       pwm: pwm@80064000 {
+                               compatible = "fsl,imx23-pwm";
                                reg = <0x80064000 2000>;
+                               #pwm-cells = <2>;
+                               fsl,pwm-number = <5>;
                                status = "disabled";
                        };
 
                        };
 
                        auart0: serial@8006c000 {
+                               compatible = "fsl,imx23-auart";
                                reg = <0x8006c000 0x2000>;
+                               interrupts = <24 25 23>;
                                status = "disabled";
                        };
 
                        auart1: serial@8006e000 {
+                               compatible = "fsl,imx23-auart";
                                reg = <0x8006e000 0x2000>;
+                               interrupts = <59 60 58>;
                                status = "disabled";
                        };
 
diff --git a/arch/arm/boot/dts/imx27-3ds.dts b/arch/arm/boot/dts/imx27-3ds.dts
new file mode 100644 (file)
index 0000000..d3f8296
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx27.dtsi"
+
+/ {
+       model = "mx27_3ds";
+       compatible = "freescale,imx27-3ds", "fsl,imx27";
+
+       memory {
+               reg = <0x0 0x0>;
+       };
+
+       soc {
+               aipi@10000000 { /* aipi */
+
+                       wdog@10002000 {
+                               status = "okay";
+                       };
+
+                       uart@1000a000 {
+                               fsl,uart-has-rtscts;
+                               status = "okay";
+                       };
+
+                       fec@1002b000 {
+                               status = "okay";
+                       };
+               };
+       };
+
+};
index 386c769c38d179dcb090bba33af5aeb6ec2f0a0a..00bae3aad5ab601f7a21adf4da8539aa48880781 100644 (file)
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio2: gpio@10015100 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio3: gpio@10015200 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio4: gpio@10015300 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio5: gpio@10015400 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio6: gpio@10015500 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        cspi3: cspi@10017000 {
diff --git a/arch/arm/boot/dts/imx28-apx4devkit.dts b/arch/arm/boot/dts/imx28-apx4devkit.dts
new file mode 100644 (file)
index 0000000..b383417
--- /dev/null
@@ -0,0 +1,198 @@
+/dts-v1/;
+/include/ "imx28.dtsi"
+
+/ {
+       model = "Bluegiga APX4 Development Kit";
+       compatible = "bluegiga,apx4devkit", "fsl,imx28";
+
+       memory {
+               reg = <0x40000000 0x04000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       gpmi-nand@8000c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
+                               status = "okay";
+                       };
+
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_4bit_pins_a &mmc0_sck_cfg>;
+                               bus-width = <4>;
+                               status = "okay";
+                       };
+
+                       ssp2: ssp@80014000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc2_4bit_pins_apx4 &mmc2_sck_cfg_apx4>;
+                               bus-width = <4>;
+                               status = "okay";
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog-gpios@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x0113 /* MX28_PAD_GPMI_CE1N__GPIO_0_17 */
+                                               0x0153 /* MX28_PAD_GPMI_RDY1__GPIO_0_21 */
+                                               0x2123 /* MX28_PAD_SSP2_MISO__GPIO_2_18 */
+                                               0x2131 /* MX28_PAD_SSP2_SS0__GPIO_2_19 */
+                                               0x31c3 /* MX28_PAD_PWM3__GPIO_3_28 */
+                                               0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
+                                               0x4143 /* MX28_PAD_JTAG_RTCK__GPIO_4_20 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               lcdif_pins_apx4: lcdif-apx4@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
+                                               0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
+                                               0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
+                                               0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               mmc2_4bit_pins_apx4: mmc2-4bit-apx4@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x2041 /* MX28_PAD_SSP0_DATA4__SSP2_D0 */
+                                               0x2051 /* MX28_PAD_SSP0_DATA5__SSP2_D3 */
+                                               0x2061 /* MX28_PAD_SSP0_DATA6__SSP2_CMD */
+                                               0x2071 /* MX28_PAD_SSP0_DATA7__SSP2_SCK */
+                                               0x2141 /* MX28_PAD_SSP2_SS1__SSP2_D1 */
+                                               0x2151 /* MX28_PAD_SSP2_SS2__SSP2_D2 */
+                                       >;
+                                       fsl,drive-strength = <1>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <1>;
+                               };
+
+                               mmc2_sck_cfg_apx4: mmc2-sck-cfg-apx4 {
+                                       fsl,pinmux-ids = <
+                                               0x2071 /* MX28_PAD_SSP0_DATA7__SSP2_SCK */
+                                       >;
+                                       fsl,drive-strength = <2>;
+                                       fsl,pull-up = <0>;
+                               };
+                       };
+
+                       lcdif@80030000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&lcdif_24bit_pins_a
+                                            &lcdif_pins_apx4>;
+                               status = "okay";
+                       };
+               };
+
+               apbx@80040000 {
+                       saif0: saif@80042000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&saif0_pins_a>;
+                               status = "okay";
+                       };
+
+                       saif1: saif@80046000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&saif1_pins_a>;
+                               fsl,saif-master = <&saif0>;
+                               status = "okay";
+                       };
+
+                       i2c0: i2c@80058000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&i2c0_pins_a>;
+                               status = "okay";
+
+                               sgtl5000: codec@0a {
+                                       compatible = "fsl,sgtl5000";
+                                       reg = <0x0a>;
+                                       VDDA-supply = <&reg_3p3v>;
+                                       VDDIO-supply = <&reg_3p3v>;
+
+                               };
+
+                               pcf8563: rtc@51 {
+                                       compatible = "phg,pcf8563";
+                                       reg = <0x51>;
+                               };
+                       };
+
+                       duart: serial@80074000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_a>;
+                               status = "okay";
+                       };
+
+                       auart0: serial@8006a000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_pins_a>;
+                               status = "okay";
+                       };
+
+                       auart1: serial@8006c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart1_2pins_a>;
+                               status = "okay";
+                       };
+
+                       auart2: serial@8006e000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart2_2pins_a>;
+                               status = "okay";
+                       };
+               };
+       };
+
+       ahb@80080000 {
+               mac0: ethernet@800f0000 {
+                       phy-mode = "rmii";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mac0_pins_a>;
+                       status = "okay";
+               };
+       };
+
+       regulators {
+               compatible = "simple-bus";
+
+               reg_3p3v: 3p3v {
+                       compatible = "regulator-fixed";
+                       regulator-name = "3P3V";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+       };
+
+       sound {
+               compatible = "bluegiga,apx4devkit-sgtl5000",
+                            "fsl,mxs-audio-sgtl5000";
+               model = "apx4devkit-sgtl5000";
+               saif-controllers = <&saif0 &saif1>;
+               audio-codec = <&sgtl5000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               user {
+                       label = "Heartbeat";
+                       gpios = <&gpio3 28 0>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/imx28-cfa10036.dts b/arch/arm/boot/dts/imx28-cfa10036.dts
new file mode 100644 (file)
index 0000000..c03a577
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2012 Free Electrons
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx28.dtsi"
+
+/ {
+       model = "Crystalfontz CFA-10036 Board";
+       compatible = "crystalfontz,cfa10036", "fsl,imx28";
+
+       memory {
+               reg = <0x40000000 0x08000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_4bit_pins_a
+                                       &mmc0_cd_cfg &mmc0_sck_cfg>;
+                               bus-width = <4>;
+                               status = "okay";
+                       };
+               };
+
+               apbx@80040000 {
+                       duart: serial@80074000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_b>;
+                               status = "okay";
+                       };
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               power {
+                       gpios = <&gpio3 4 1>;
+                       default-state = "on";
+               };
+       };
+};
index ee520a529cb4a6406385b72a3717d00c8c791fbf..773c0e84d1fb54cb1724c03e0101b0053d483bee 100644 (file)
 
        apb@80000000 {
                apbh@80000000 {
+                       gpmi-nand@8000c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg
+                                            &gpmi_pins_evk>;
+                               status = "okay";
+                       };
+
                        ssp0: ssp@80010000 {
                                compatible = "fsl,imx28-mmc";
                                pinctrl-names = "default";
@@ -29,6 +36,7 @@
                                        &mmc0_cd_cfg &mmc0_sck_cfg>;
                                bus-width = <8>;
                                wp-gpios = <&gpio2 12 0>;
+                               vmmc-supply = <&reg_vddio_sd0>;
                                status = "okay";
                        };
 
                                compatible = "fsl,imx28-mmc";
                                bus-width = <8>;
                                wp-gpios = <&gpio0 28 0>;
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog-gpios@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x20d3 /* MX28_PAD_SSP1_CMD__GPIO_2_13 */
+                                               0x20f3 /* MX28_PAD_SSP1_DATA3__GPIO_2_15 */
+                                               0x40d3 /* MX28_PAD_ENET0_RX_CLK__GPIO_4_13 */
+                                               0x20c3 /* MX28_PAD_SSP1_SCK__GPIO_2_12 */
+                                               0x31c3 /* MX28_PAD_PWM3__GPIO_3_28 */
+                                               0x31e3 /* MX28_PAD_LCD_RESET__GPIO_3_30 */
+                                               0x3053 /* MX28_PAD_AUART1_TX__GPIO_3_5 */
+                                               0x3083 /* MX28_PAD_AUART2_RX__GPIO_3_8 */
+                                               0x3093 /* MX28_PAD_AUART2_TX__GPIO_3_9 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               gpmi_pins_evk: gpmi-nand-evk@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x0110 /* MX28_PAD_GPMI_CE1N__GPMI_CE1N */
+                                               0x0150 /* MX28_PAD_GPMI_RDY1__GPMI_READY1 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               lcdif_pins_evk: lcdif-evk@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x1181 /* MX28_PAD_LCD_RD_E__LCD_VSYNC */
+                                               0x1191 /* MX28_PAD_LCD_WR_RWN__LCD_HSYNC */
+                                               0x11a1 /* MX28_PAD_LCD_RS__LCD_DOTCLK */
+                                               0x11b1 /* MX28_PAD_LCD_CS__LCD_ENABLE */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+                       };
+
+                       lcdif@80030000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&lcdif_24bit_pins_a
+                                            &lcdif_pins_evk>;
+                               panel-enable-gpios = <&gpio3 30 0>;
+                               status = "okay";
+                       };
+
+                       can0: can@80032000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&can0_pins_a>;
+                               status = "okay";
+                       };
+
+                       can1: can@80034000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&can1_pins_a>;
                                status = "okay";
                        };
                };
                                };
                        };
 
+                       pwm: pwm@80064000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pwm2_pins_a>;
+                               status = "okay";
+                       };
+
                        duart: serial@80074000 {
                                pinctrl-names = "default";
                                pinctrl-0 = <&duart_pins_a>;
                                status = "okay";
                        };
+
+                       auart0: serial@8006a000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_pins_a>;
+                               status = "okay";
+                       };
+
+                       auart3: serial@80070000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart3_pins_a>;
+                               status = "okay";
+                       };
+
+                       usbphy0: usbphy@8007c000 {
+                               status = "okay";
+                       };
+
+                       usbphy1: usbphy@8007e000 {
+                               status = "okay";
+                       };
                };
        };
 
        ahb@80080000 {
+               usb0: usb@80080000 {
+                       vbus-supply = <&reg_usb0_vbus>;
+                       status = "okay";
+               };
+
+               usb1: usb@80090000 {
+                       vbus-supply = <&reg_usb1_vbus>;
+                       status = "okay";
+               };
+
                mac0: ethernet@800f0000 {
                        phy-mode = "rmii";
                        pinctrl-names = "default";
                        pinctrl-0 = <&mac0_pins_a>;
+                       phy-supply = <&reg_fec_3v3>;
+                       phy-reset-gpios = <&gpio4 13 0>;
+                       phy-reset-duration = <100>;
                        status = "okay";
                };
 
                        regulator-max-microvolt = <3300000>;
                        regulator-always-on;
                };
+
+               reg_vddio_sd0: vddio-sd0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "vddio-sd0";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       gpio = <&gpio3 28 0>;
+               };
+
+               reg_fec_3v3: fec-3v3 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "fec-3v3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       gpio = <&gpio2 15 0>;
+               };
+
+               reg_usb0_vbus: usb0_vbus {
+                       compatible = "regulator-fixed";
+                       regulator-name = "usb0_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio3 9 0>;
+                       enable-active-high;
+               };
+
+               reg_usb1_vbus: usb1_vbus {
+                       compatible = "regulator-fixed";
+                       regulator-name = "usb1_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio3 8 0>;
+                       enable-active-high;
+               };
        };
 
        sound {
                saif-controllers = <&saif0 &saif1>;
                audio-codec = <&sgtl5000>;
        };
+
+       leds {
+               compatible = "gpio-leds";
+
+               user {
+                       label = "Heartbeat";
+                       gpios = <&gpio3 5 0>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm 2 5000000>;
+               brightness-levels = <0 4 8 16 32 64 128 255>;
+               default-brightness-level = <6>;
+       };
 };
diff --git a/arch/arm/boot/dts/imx28-m28evk.dts b/arch/arm/boot/dts/imx28-m28evk.dts
new file mode 100644 (file)
index 0000000..183a3fd
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2012 Marek Vasut <marex@denx.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx28.dtsi"
+
+/ {
+       model = "DENX M28EVK";
+       compatible = "denx,m28evk", "fsl,imx28";
+
+       memory {
+               reg = <0x40000000 0x08000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       gpmi-nand@8000c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&gpmi_pins_a &gpmi_status_cfg>;
+                               status = "okay";
+
+                               partition@0 {
+                                       label = "bootloader";
+                                       reg = <0x00000000 0x00300000>;
+                                       read-only;
+                               };
+
+                               partition@1 {
+                                       label = "environment";
+                                       reg = <0x00300000 0x00080000>;
+                               };
+
+                               partition@2 {
+                                       label = "redundant-environment";
+                                       reg = <0x00380000 0x00080000>;
+                               };
+
+                               partition@3 {
+                                       label = "kernel";
+                                       reg = <0x00400000 0x00400000>;
+                               };
+
+                               partition@4 {
+                                       label = "filesystem";
+                                       reg = <0x00800000 0x0f800000>;
+                               };
+                       };
+
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_8bit_pins_a
+                                            &mmc0_cd_cfg
+                                            &mmc0_sck_cfg>;
+                               bus-width = <8>;
+                               wp-gpios = <&gpio3 10 1>;
+                               status = "okay";
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog-gpios@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x30a3 /* MX28_PAD_AUART2_CTS__GPIO_3_10 */
+                                               0x30b3 /* MX28_PAD_AUART2_RTS__GPIO_3_11 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               lcdif_pins_m28: lcdif-m28@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x11e0 /* MX28_PAD_LCD_DOTCLK__LCD_DOTCLK */
+                                               0x11f0 /* MX28_PAD_LCD_ENABLE__LCD_ENABLE */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+                       };
+
+                       lcdif@80030000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&lcdif_24bit_pins_a
+                                            &lcdif_pins_m28>;
+                               status = "okay";
+                       };
+
+                       can0: can@80032000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&can0_pins_a>;
+                               status = "okay";
+                       };
+
+                       can1: can@80034000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&can1_pins_a>;
+                               status = "okay";
+                       };
+               };
+
+               apbx@80040000 {
+                       saif0: saif@80042000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&saif0_pins_a>;
+                               status = "okay";
+                       };
+
+                       saif1: saif@80046000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&saif1_pins_a>;
+                               fsl,saif-master = <&saif0>;
+                               status = "okay";
+                       };
+
+                       i2c0: i2c@80058000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&i2c0_pins_a>;
+                               status = "okay";
+
+                               sgtl5000: codec@0a {
+                                       compatible = "fsl,sgtl5000";
+                                       reg = <0x0a>;
+                                       VDDA-supply = <&reg_3p3v>;
+                                       VDDIO-supply = <&reg_3p3v>;
+
+                               };
+
+                               eeprom: eeprom@51 {
+                                       compatible = "atmel,24c128";
+                                       reg = <0x51>;
+                                       pagesize = <32>;
+                               };
+
+                               rtc: rtc@68 {
+                                       compatible = "stm,mt41t62";
+                                       reg = <0x68>;
+                               };
+                       };
+
+                       duart: serial@80074000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_a>;
+                               status = "okay";
+                       };
+
+                       auart0: serial@8006a000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_2pins_a>;
+                               status = "okay";
+                       };
+
+                       auart3: serial@80070000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart3_pins_a>;
+                               status = "okay";
+                       };
+               };
+       };
+
+       ahb@80080000 {
+               mac0: ethernet@800f0000 {
+                       phy-mode = "rmii";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mac0_pins_a>;
+                       phy-reset-gpios = <&gpio3 11 0>;
+                       status = "okay";
+               };
+
+               mac1: ethernet@800f4000 {
+                       phy-mode = "rmii";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mac1_pins_a>;
+                       status = "okay";
+               };
+       };
+
+       regulators {
+               compatible = "simple-bus";
+
+               reg_3p3v: 3p3v {
+                       compatible = "regulator-fixed";
+                       regulator-name = "3P3V";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
+       };
+
+       sound {
+               compatible = "denx,m28evk-sgtl5000",
+                            "fsl,mxs-audio-sgtl5000";
+               model = "m28evk-sgtl5000";
+               saif-controllers = <&saif0 &saif1>;
+               audio-codec = <&sgtl5000>;
+       };
+};
diff --git a/arch/arm/boot/dts/imx28-tx28.dts b/arch/arm/boot/dts/imx28-tx28.dts
new file mode 100644 (file)
index 0000000..62bf767
--- /dev/null
@@ -0,0 +1,97 @@
+/dts-v1/;
+/include/ "imx28.dtsi"
+
+/ {
+       model = "Ka-Ro electronics TX28 module";
+       compatible = "karo,tx28", "fsl,imx28";
+
+       memory {
+               reg = <0x40000000 0x08000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_4bit_pins_a
+                                            &mmc0_cd_cfg
+                                            &mmc0_sck_cfg>;
+                               bus-width = <4>;
+                               status = "okay";
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog-gpios@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x40a3 /* MX28_PAD_ENET0_RXD3__GPIO_4_10 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+                       };
+               };
+
+               apbx@80040000 {
+                       i2c0: i2c@80058000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&i2c0_pins_a>;
+                               status = "okay";
+
+                               ds1339: rtc@68 {
+                                       compatible = "mxim,ds1339";
+                                       reg = <0x68>;
+                               };
+                       };
+
+                       pwm: pwm@80064000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pwm0_pins_a>;
+                               status = "okay";
+                       };
+
+                       duart: serial@80074000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_4pins_a>;
+                               status = "okay";
+                       };
+
+                       auart1: serial@8006c000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart1_pins_a>;
+                               status = "okay";
+                       };
+               };
+       };
+
+       ahb@80080000 {
+               mac0: ethernet@800f0000 {
+                       phy-mode = "rmii";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mac0_pins_a>;
+                       status = "okay";
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               user {
+                       label = "Heartbeat";
+                       gpios = <&gpio4 10 0>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm 0 5000000>;
+               brightness-levels = <0 4 8 16 32 64 128 255>;
+               default-brightness-level = <6>;
+       };
+};
index 4634cb861a597d115b5f6dab784da3a616c81b01..915db89e364431450347e69e93c9e73bb6b59108 100644 (file)
                gpio4 = &gpio4;
                saif0 = &saif0;
                saif1 = &saif1;
+               serial0 = &auart0;
+               serial1 = &auart1;
+               serial2 = &auart2;
+               serial3 = &auart3;
+               serial4 = &auart4;
        };
 
        cpus {
                                status = "disabled";
                        };
 
-                       bch@8000a000 {
-                               reg = <0x8000a000 2000>;
-                               interrupts = <41>;
-                               status = "disabled";
-                       };
-
-                       gpmi@8000c000 {
-                               reg = <0x8000c000 2000>;
-                               interrupts = <42 88>;
+                       gpmi-nand@8000c000 {
+                               compatible = "fsl,imx28-gpmi-nand";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0x8000c000 2000>, <0x8000a000 2000>;
+                               reg-names = "gpmi-nand", "bch";
+                               interrupts = <88>, <41>;
+                               interrupt-names = "gpmi-dma", "bch";
+                               fsl,gpmi-dma-channel = <4>;
                                status = "disabled";
                        };
 
 
                                duart_pins_a: duart@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x3102 0x3112>;
+                                       fsl,pinmux-ids = <
+                                               0x3102 /* MX28_PAD_PWM0__DUART_RX */
+                                               0x3112 /* MX28_PAD_PWM1__DUART_TX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               duart_pins_b: duart@1 {
+                                       reg = <1>;
+                                       fsl,pinmux-ids = <
+                                               0x3022 /* MX28_PAD_AUART0_CTS__DUART_RX */
+                                               0x3032 /* MX28_PAD_AUART0_RTS__DUART_TX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               duart_4pins_a: duart-4pins@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x3022 /* MX28_PAD_AUART0_CTS__DUART_RX */
+                                               0x3032 /* MX28_PAD_AUART0_RTS__DUART_TX */
+                                               0x3002 /* MX28_PAD_AUART0_RX__DUART_CTS */
+                                               0x3012 /* MX28_PAD_AUART0_TX__DUART_RTS */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               gpmi_pins_a: gpmi-nand@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x0000 /* MX28_PAD_GPMI_D00__GPMI_D0 */
+                                               0x0010 /* MX28_PAD_GPMI_D01__GPMI_D1 */
+                                               0x0020 /* MX28_PAD_GPMI_D02__GPMI_D2 */
+                                               0x0030 /* MX28_PAD_GPMI_D03__GPMI_D3 */
+                                               0x0040 /* MX28_PAD_GPMI_D04__GPMI_D4 */
+                                               0x0050 /* MX28_PAD_GPMI_D05__GPMI_D5 */
+                                               0x0060 /* MX28_PAD_GPMI_D06__GPMI_D6 */
+                                               0x0070 /* MX28_PAD_GPMI_D07__GPMI_D7 */
+                                               0x0100 /* MX28_PAD_GPMI_CE0N__GPMI_CE0N */
+                                               0x0140 /* MX28_PAD_GPMI_RDY0__GPMI_READY0 */
+                                               0x0180 /* MX28_PAD_GPMI_RDN__GPMI_RDN */
+                                               0x0190 /* MX28_PAD_GPMI_WRN__GPMI_WRN */
+                                               0x01a0 /* MX28_PAD_GPMI_ALE__GPMI_ALE */
+                                               0x01b0 /* MX28_PAD_GPMI_CLE__GPMI_CLE */
+                                               0x01c0 /* MX28_PAD_GPMI_RESETN__GPMI_RESETN */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               gpmi_status_cfg: gpmi-status-cfg {
+                                       fsl,pinmux-ids = <
+                                               0x0180 /* MX28_PAD_GPMI_RDN__GPMI_RDN */
+                                               0x0190 /* MX28_PAD_GPMI_WRN__GPMI_WRN */
+                                               0x01c0 /* MX28_PAD_GPMI_RESETN__GPMI_RESETN */
+                                       >;
+                                       fsl,drive-strength = <2>;
+                               };
+
+                               auart0_pins_a: auart0@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x3000 /* MX28_PAD_AUART0_RX__AUART0_RX */
+                                               0x3010 /* MX28_PAD_AUART0_TX__AUART0_TX */
+                                               0x3020 /* MX28_PAD_AUART0_CTS__AUART0_CTS */
+                                               0x3030 /* MX28_PAD_AUART0_RTS__AUART0_RTS */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               auart0_2pins_a: auart0-2pins@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x3000 /* MX28_PAD_AUART0_RX__AUART0_RX */
+                                               0x3010 /* MX28_PAD_AUART0_TX__AUART0_TX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               auart1_pins_a: auart1@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x3040 /* MX28_PAD_AUART1_RX__AUART1_RX */
+                                               0x3050 /* MX28_PAD_AUART1_TX__AUART1_TX */
+                                               0x3060 /* MX28_PAD_AUART1_CTS__AUART1_CTS */
+                                               0x3070 /* MX28_PAD_AUART1_RTS__AUART1_RTS */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               auart1_2pins_a: auart1-2pins@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x3040 /* MX28_PAD_AUART1_RX__AUART1_RX */
+                                               0x3050 /* MX28_PAD_AUART1_TX__AUART1_TX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               auart2_2pins_a: auart2-2pins@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x2101 /* MX28_PAD_SSP2_SCK__AUART2_RX */
+                                               0x2111 /* MX28_PAD_SSP2_MOSI__AUART2_TX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               auart3_pins_a: auart3@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x30c0 /* MX28_PAD_AUART3_RX__AUART3_RX */
+                                               0x30d0 /* MX28_PAD_AUART3_TX__AUART3_TX */
+                                               0x30e0 /* MX28_PAD_AUART3_CTS__AUART3_CTS */
+                                               0x30f0 /* MX28_PAD_AUART3_RTS__AUART3_RTS */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               auart3_2pins_a: auart3-2pins@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x2121 /* MX28_PAD_SSP2_MISO__AUART3_RX */
+                                               0x2131 /* MX28_PAD_SSP2_SS0__AUART3_TX */
+                                       >;
                                        fsl,drive-strength = <0>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <0>;
 
                                mac0_pins_a: mac0@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x4000 0x4010 0x4020
-                                               0x4030 0x4040 0x4060 0x4070
-                                               0x4080 0x4100>;
+                                       fsl,pinmux-ids = <
+                                               0x4000 /* MX28_PAD_ENET0_MDC__ENET0_MDC */
+                                               0x4010 /* MX28_PAD_ENET0_MDIO__ENET0_MDIO */
+                                               0x4020 /* MX28_PAD_ENET0_RX_EN__ENET0_RX_EN */
+                                               0x4030 /* MX28_PAD_ENET0_RXD0__ENET0_RXD0 */
+                                               0x4040 /* MX28_PAD_ENET0_RXD1__ENET0_RXD1 */
+                                               0x4060 /* MX28_PAD_ENET0_TX_EN__ENET0_TX_EN */
+                                               0x4070 /* MX28_PAD_ENET0_TXD0__ENET0_TXD0 */
+                                               0x4080 /* MX28_PAD_ENET0_TXD1__ENET0_TXD1 */
+                                               0x4100 /* MX28_PAD_ENET_CLK__CLKCTRL_ENET */
+                                       >;
                                        fsl,drive-strength = <1>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <1>;
 
                                mac1_pins_a: mac1@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x40f1 0x4091 0x40a1
-                                               0x40e1 0x40b1 0x40c1>;
+                                       fsl,pinmux-ids = <
+                                               0x40f1 /* MX28_PAD_ENET0_CRS__ENET1_RX_EN */
+                                               0x4091 /* MX28_PAD_ENET0_RXD2__ENET1_RXD0 */
+                                               0x40a1 /* MX28_PAD_ENET0_RXD3__ENET1_RXD1 */
+                                               0x40e1 /* MX28_PAD_ENET0_COL__ENET1_TX_EN */
+                                               0x40b1 /* MX28_PAD_ENET0_TXD2__ENET1_TXD0 */
+                                               0x40c1 /* MX28_PAD_ENET0_TXD3__ENET1_TXD1 */
+                                       >;
                                        fsl,drive-strength = <1>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <1>;
 
                                mmc0_8bit_pins_a: mmc0-8bit@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x2000 0x2010 0x2020
-                                               0x2030 0x2040 0x2050 0x2060
-                                               0x2070 0x2080 0x2090 0x20a0>;
+                                       fsl,pinmux-ids = <
+                                               0x2000 /* MX28_PAD_SSP0_DATA0__SSP0_D0 */
+                                               0x2010 /* MX28_PAD_SSP0_DATA1__SSP0_D1 */
+                                               0x2020 /* MX28_PAD_SSP0_DATA2__SSP0_D2 */
+                                               0x2030 /* MX28_PAD_SSP0_DATA3__SSP0_D3 */
+                                               0x2040 /* MX28_PAD_SSP0_DATA4__SSP0_D4 */
+                                               0x2050 /* MX28_PAD_SSP0_DATA5__SSP0_D5 */
+                                               0x2060 /* MX28_PAD_SSP0_DATA6__SSP0_D6 */
+                                               0x2070 /* MX28_PAD_SSP0_DATA7__SSP0_D7 */
+                                               0x2080 /* MX28_PAD_SSP0_CMD__SSP0_CMD */
+                                               0x2090 /* MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT */
+                                               0x20a0 /* MX28_PAD_SSP0_SCK__SSP0_SCK */
+                                       >;
+                                       fsl,drive-strength = <1>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <1>;
+                               };
+
+                               mmc0_4bit_pins_a: mmc0-4bit@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x2000 /* MX28_PAD_SSP0_DATA0__SSP0_D0 */
+                                               0x2010 /* MX28_PAD_SSP0_DATA1__SSP0_D1 */
+                                               0x2020 /* MX28_PAD_SSP0_DATA2__SSP0_D2 */
+                                               0x2030 /* MX28_PAD_SSP0_DATA3__SSP0_D3 */
+                                               0x2080 /* MX28_PAD_SSP0_CMD__SSP0_CMD */
+                                               0x2090 /* MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT */
+                                               0x20a0 /* MX28_PAD_SSP0_SCK__SSP0_SCK */
+                                       >;
                                        fsl,drive-strength = <1>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <1>;
                                };
 
                                mmc0_cd_cfg: mmc0-cd-cfg {
-                                       fsl,pinmux-ids = <0x2090>;
+                                       fsl,pinmux-ids = <
+                                               0x2090 /* MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT */
+                                       >;
                                        fsl,pull-up = <0>;
                                };
 
                                mmc0_sck_cfg: mmc0-sck-cfg {
-                                       fsl,pinmux-ids = <0x20a0>;
+                                       fsl,pinmux-ids = <
+                                               0x20a0 /* MX28_PAD_SSP0_SCK__SSP0_SCK */
+                                       >;
                                        fsl,drive-strength = <2>;
                                        fsl,pull-up = <0>;
                                };
 
                                i2c0_pins_a: i2c0@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x3180 0x3190>;
+                                       fsl,pinmux-ids = <
+                                               0x3180 /* MX28_PAD_I2C0_SCL__I2C0_SCL */
+                                               0x3190 /* MX28_PAD_I2C0_SDA__I2C0_SDA */
+                                       >;
                                        fsl,drive-strength = <1>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <1>;
 
                                saif0_pins_a: saif0@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids =
-                                               <0x3140 0x3150 0x3160 0x3170>;
+                                       fsl,pinmux-ids = <
+                                               0x3140 /* MX28_PAD_SAIF0_MCLK__SAIF0_MCLK */
+                                               0x3150 /* MX28_PAD_SAIF0_LRCLK__SAIF0_LRCLK */
+                                               0x3160 /* MX28_PAD_SAIF0_BITCLK__SAIF0_BITCLK */
+                                               0x3170 /* MX28_PAD_SAIF0_SDATA0__SAIF0_SDATA0 */
+                                       >;
                                        fsl,drive-strength = <2>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <1>;
 
                                saif1_pins_a: saif1@0 {
                                        reg = <0>;
-                                       fsl,pinmux-ids = <0x31a0>;
+                                       fsl,pinmux-ids = <
+                                               0x31a0 /* MX28_PAD_SAIF1_SDATA0__SAIF1_SDATA0 */
+                                       >;
                                        fsl,drive-strength = <2>;
                                        fsl,voltage = <1>;
                                        fsl,pull-up = <1>;
                                };
+
+                               pwm0_pins_a: pwm0@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x3100 /* MX28_PAD_PWM0__PWM_0 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               pwm2_pins_a: pwm2@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x3120 /* MX28_PAD_PWM2__PWM_2 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               lcdif_24bit_pins_a: lcdif-24bit@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x1000 /* MX28_PAD_LCD_D00__LCD_D0 */
+                                               0x1010 /* MX28_PAD_LCD_D01__LCD_D1 */
+                                               0x1020 /* MX28_PAD_LCD_D02__LCD_D2 */
+                                               0x1030 /* MX28_PAD_LCD_D03__LCD_D3 */
+                                               0x1040 /* MX28_PAD_LCD_D04__LCD_D4 */
+                                               0x1050 /* MX28_PAD_LCD_D05__LCD_D5 */
+                                               0x1060 /* MX28_PAD_LCD_D06__LCD_D6 */
+                                               0x1070 /* MX28_PAD_LCD_D07__LCD_D7 */
+                                               0x1080 /* MX28_PAD_LCD_D08__LCD_D8 */
+                                               0x1090 /* MX28_PAD_LCD_D09__LCD_D9 */
+                                               0x10a0 /* MX28_PAD_LCD_D10__LCD_D10 */
+                                               0x10b0 /* MX28_PAD_LCD_D11__LCD_D11 */
+                                               0x10c0 /* MX28_PAD_LCD_D12__LCD_D12 */
+                                               0x10d0 /* MX28_PAD_LCD_D13__LCD_D13 */
+                                               0x10e0 /* MX28_PAD_LCD_D14__LCD_D14 */
+                                               0x10f0 /* MX28_PAD_LCD_D15__LCD_D15 */
+                                               0x1100 /* MX28_PAD_LCD_D16__LCD_D16 */
+                                               0x1110 /* MX28_PAD_LCD_D17__LCD_D17 */
+                                               0x1120 /* MX28_PAD_LCD_D18__LCD_D18 */
+                                               0x1130 /* MX28_PAD_LCD_D19__LCD_D19 */
+                                               0x1140 /* MX28_PAD_LCD_D20__LCD_D20 */
+                                               0x1150 /* MX28_PAD_LCD_D21__LCD_D21 */
+                                               0x1160 /* MX28_PAD_LCD_D22__LCD_D22 */
+                                               0x1170 /* MX28_PAD_LCD_D23__LCD_D23 */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               can0_pins_a: can0@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x0161 /* MX28_PAD_GPMI_RDY2__CAN0_TX */
+                                               0x0171 /* MX28_PAD_GPMI_RDY3__CAN0_RX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
+
+                               can1_pins_a: can1@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               0x0121 /* MX28_PAD_GPMI_CE2N__CAN1_TX */
+                                               0x0131 /* MX28_PAD_GPMI_CE3N__CAN1_RX */
+                                       >;
+                                       fsl,drive-strength = <0>;
+                                       fsl,voltage = <1>;
+                                       fsl,pull-up = <0>;
+                               };
                        };
 
                        digctl@8001c000 {
                        };
 
                        lcdif@80030000 {
+                               compatible = "fsl,imx28-lcdif";
                                reg = <0x80030000 2000>;
                                interrupts = <38 86>;
                                status = "disabled";
                        };
 
                        can0: can@80032000 {
+                               compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan";
                                reg = <0x80032000 2000>;
                                interrupts = <8>;
                                status = "disabled";
                        };
 
                        can1: can@80034000 {
+                               compatible = "fsl,imx28-flexcan", "fsl,p1010-flexcan";
                                reg = <0x80034000 2000>;
                                interrupts = <9>;
                                status = "disabled";
                        };
 
                        rtc@80056000 {
+                               compatible = "fsl,imx28-rtc", "fsl,stmp3xxx-rtc";
                                reg = <0x80056000 2000>;
-                               interrupts = <28 29>;
-                               status = "disabled";
+                               interrupts = <29>;
                        };
 
                        i2c0: i2c@80058000 {
                                status = "disabled";
                        };
 
-                       pwm@80064000 {
+                       pwm: pwm@80064000 {
+                               compatible = "fsl,imx28-pwm", "fsl,imx23-pwm";
                                reg = <0x80064000 2000>;
+                               #pwm-cells = <2>;
+                               fsl,pwm-number = <8>;
                                status = "disabled";
                        };
 
                        };
 
                        auart0: serial@8006a000 {
+                               compatible = "fsl,imx28-auart", "fsl,imx23-auart";
                                reg = <0x8006a000 0x2000>;
                                interrupts = <112 70 71>;
                                status = "disabled";
                        };
 
                        auart1: serial@8006c000 {
+                               compatible = "fsl,imx28-auart", "fsl,imx23-auart";
                                reg = <0x8006c000 0x2000>;
                                interrupts = <113 72 73>;
                                status = "disabled";
                        };
 
                        auart2: serial@8006e000 {
+                               compatible = "fsl,imx28-auart", "fsl,imx23-auart";
                                reg = <0x8006e000 0x2000>;
                                interrupts = <114 74 75>;
                                status = "disabled";
                        };
 
                        auart3: serial@80070000 {
+                               compatible = "fsl,imx28-auart", "fsl,imx23-auart";
                                reg = <0x80070000 0x2000>;
                                interrupts = <115 76 77>;
                                status = "disabled";
                        };
 
                        auart4: serial@80072000 {
+                               compatible = "fsl,imx28-auart", "fsl,imx23-auart";
                                reg = <0x80072000 0x2000>;
                                interrupts = <116 78 79>;
                                status = "disabled";
                        };
 
                        usbphy0: usbphy@8007c000 {
+                               compatible = "fsl,imx28-usbphy", "fsl,imx23-usbphy";
                                reg = <0x8007c000 0x2000>;
                                status = "disabled";
                        };
 
                        usbphy1: usbphy@8007e000 {
+                               compatible = "fsl,imx28-usbphy", "fsl,imx23-usbphy";
                                reg = <0x8007e000 0x2000>;
                                status = "disabled";
                        };
                reg = <0x80080000 0x80000>;
                ranges;
 
-               usbctrl0: usbctrl@80080000 {
+               usb0: usb@80080000 {
+                       compatible = "fsl,imx28-usb", "fsl,imx27-usb";
                        reg = <0x80080000 0x10000>;
+                       interrupts = <93>;
+                       fsl,usbphy = <&usbphy0>;
                        status = "disabled";
                };
 
-               usbctrl1: usbctrl@80090000 {
+               usb1: usb@80090000 {
+                       compatible = "fsl,imx28-usb", "fsl,imx27-usb";
                        reg = <0x80090000 0x10000>;
+                       interrupts = <92>;
+                       fsl,usbphy = <&usbphy1>;
                        status = "disabled";
                };
 
diff --git a/arch/arm/boot/dts/imx31-bug.dts b/arch/arm/boot/dts/imx31-bug.dts
new file mode 100644 (file)
index 0000000..24731cb
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2012 Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+/include/ "imx31.dtsi"
+
+/ {
+       model = "Buglabs i.MX31 Bug 1.x";
+       compatible = "fsl,imx31-bug", "fsl,imx31";
+
+       memory {
+               reg = <0x80000000 0x8000000>; /* 128M */
+       };
+
+       soc {
+               aips@43f00000 { /* AIPS1 */
+                       uart5: serial@43fb4000 {
+                               fsl,uart-has-rtscts;
+                               status = "okay";
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/imx31.dtsi b/arch/arm/boot/dts/imx31.dtsi
new file mode 100644 (file)
index 0000000..eef7099
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2012 Denis 'GNUtoo' Carikli <GNUtoo@no-log.org>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+       aliases {
+               serial0 = &uart1;
+               serial1 = &uart2;
+               serial2 = &uart3;
+               serial3 = &uart4;
+               serial4 = &uart5;
+       };
+
+       avic: avic-interrupt-controller@60000000 {
+               compatible = "fsl,imx31-avic", "fsl,avic";
+               interrupt-controller;
+               #interrupt-cells = <1>;
+               reg = <0x60000000 0x100000>;
+       };
+
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "simple-bus";
+               interrupt-parent = <&avic>;
+               ranges;
+
+               aips@43f00000 { /* AIPS1 */
+                       compatible = "fsl,aips-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x43f00000 0x100000>;
+                       ranges;
+
+                       uart1: serial@43f90000 {
+                               compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+                               reg = <0x43f90000 0x4000>;
+                               interrupts = <45>;
+                               status = "disabled";
+                       };
+
+                       uart2: serial@43f94000 {
+                               compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+                               reg = <0x43f94000 0x4000>;
+                               interrupts = <32>;
+                               status = "disabled";
+                       };
+
+                       uart4: serial@43fb0000 {
+                               compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+                               reg = <0x43fb0000 0x4000>;
+                               interrupts = <46>;
+                               status = "disabled";
+                       };
+
+                       uart5: serial@43fb4000 {
+                               compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+                               reg = <0x43fb4000 0x4000>;
+                               interrupts = <47>;
+                               status = "disabled";
+                       };
+               };
+
+               spba@50000000 {
+                       compatible = "fsl,spba-bus", "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x50000000 0x100000>;
+                       ranges;
+
+                       uart3: serial@5000c000 {
+                               compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+                               reg = <0x5000c000 0x4000>;
+                               interrupts = <18>;
+                               status = "disabled";
+                       };
+               };
+       };
+};
index bfa65abe8ef29444f4a56ca88c7fa1fd05591a47..922adefdd29120d14e5c7456ddbf3d6144b26f11 100644 (file)
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio2: gpio@73f88000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio3: gpio@73f8c000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio4: gpio@73f90000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        wdog@73f98000 { /* WDOG1 */
index e3e869470cd3e4f6dc5f56daf2645f85bf6f14bc..4e735edc78ed7b4f9b6e2389091a759330e5b18c 100644 (file)
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio2: gpio@53f88000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio3: gpio@53f8c000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio4: gpio@53f90000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        wdog@53f98000 { /* WDOG1 */
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio6: gpio@53fe0000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio7: gpio@53fe4000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        i2c@53fec000 { /* I2C3 */
index db4c6096c562eaea2415570934b4cd7fad4a981a..d792581672cc0ca1710ffaa232f9837f29e722b6 100644 (file)
        };
 
        soc {
+               gpmi-nand@00112000 {
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_gpmi_nand_1>;
+                       status = "disabled"; /* gpmi nand conflicts with SD */
+               };
+
                aips-bus@02100000 { /* AIPS2 */
                        ethernet@02188000 {
                                phy-mode = "rgmii";
index e0ec92973e7e7d253e560cb4f66fb72800be2ad9..d42e851ceb97e423fd785e3cd357ba6d70b23d8c 100644 (file)
@@ -27,6 +27,8 @@
                                ecspi@02008000 { /* eCSPI1 */
                                        fsl,spi-num-chipselects = <1>;
                                        cs-gpios = <&gpio3 19 0>;
+                                       pinctrl-names = "default";
+                                       pinctrl-0 = <&pinctrl_ecspi1_1>;
                                        status = "okay";
 
                                        flash: m25p80@0 {
                                };
                        };
 
+                       iomuxc@020e0000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&pinctrl_gpio_hog>;
+
+                               gpios {
+                                       pinctrl_gpio_hog: gpiohog {
+                                               fsl,pins = <
+                                                          144  0x80000000      /* MX6Q_PAD_EIM_D22__GPIO_3_22 */
+                                                          121  0x80000000      /* MX6Q_PAD_EIM_D19__GPIO_3_19 */
+                                                          >;
+                                       };
+                               };
+                       };
                };
 
                aips-bus@02100000 { /* AIPS2 */
+                       usb@02184000 { /* USB OTG */
+                               vbus-supply = <&reg_usb_otg_vbus>;
+                               status = "okay";
+                       };
+
+                       usb@02184200 { /* USB1 */
+                               status = "okay";
+                       };
+
                        ethernet@02188000 {
                                phy-mode = "rgmii";
                                phy-reset-gpios = <&gpio3 23 0>;
                        regulator-max-microvolt = <3300000>;
                        regulator-always-on;
                };
+
+               reg_usb_otg_vbus: usb_otg_vbus {
+                       compatible = "regulator-fixed";
+                       regulator-name = "usb_otg_vbus";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       gpio = <&gpio3 22 0>;
+                       enable-active-high;
+               };
        };
 
        sound {
index 8c90cbac945f1d2392e590bdbb725e7154f317e5..c25d49584814aade377b4c57f964967ec1f71a09 100644 (file)
                interrupt-parent = <&intc>;
                ranges;
 
+               dma-apbh@00110000 {
+                       compatible = "fsl,imx6q-dma-apbh", "fsl,imx28-dma-apbh";
+                       reg = <0x00110000 0x2000>;
+               };
+
+               gpmi-nand@00112000 {
+                      compatible = "fsl,imx6q-gpmi-nand";
+                      #address-cells = <1>;
+                      #size-cells = <1>;
+                      reg = <0x00112000 0x2000>, <0x00114000 0x2000>;
+                      reg-names = "gpmi-nand", "bch";
+                      interrupts = <0 13 0x04>, <0 15 0x04>;
+                      interrupt-names = "gpmi-dma", "bch";
+                      fsl,gpmi-dma-channel = <0>;
+                      status = "disabled";
+               };
+
                timer@00a00600 {
                        compatible = "arm,cortex-a9-twd-timer";
                        reg = <0x00a00600 0x20>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio2: gpio@020a0000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio3: gpio@020a4000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio4: gpio@020a8000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio5: gpio@020ac000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio6: gpio@020b0000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        gpio7: gpio@020b4000 {
                                gpio-controller;
                                #gpio-cells = <2>;
                                interrupt-controller;
-                               #interrupt-cells = <1>;
+                               #interrupt-cells = <2>;
                        };
 
                        kpp@020b8000 {
                                };
                        };
 
-                       usbphy@020c9000 { /* USBPHY1 */
+                       usbphy1: usbphy@020c9000 {
+                               compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
                                reg = <0x020c9000 0x1000>;
                                interrupts = <0 44 0x04>;
                        };
 
-                       usbphy@020ca000 { /* USBPHY2 */
+                       usbphy2: usbphy@020ca000 {
+                               compatible = "fsl,imx6q-usbphy", "fsl,imx23-usbphy";
                                reg = <0x020ca000 0x1000>;
                                interrupts = <0 45 0x04>;
                        };
                                        };
                                };
 
+                               gpmi-nand {
+                                       pinctrl_gpmi_nand_1: gpmi-nand-1 {
+                                               fsl,pins = <1328 0xb0b1         /* MX6Q_PAD_NANDF_CLE__RAWNAND_CLE */
+                                                           1336 0xb0b1         /* MX6Q_PAD_NANDF_ALE__RAWNAND_ALE */
+                                                           1344 0xb0b1         /* MX6Q_PAD_NANDF_WP_B__RAWNAND_RESETN */
+                                                           1352 0xb000         /* MX6Q_PAD_NANDF_RB0__RAWNAND_READY0 */
+                                                           1360 0xb0b1         /* MX6Q_PAD_NANDF_CS0__RAWNAND_CE0N */
+                                                           1365 0xb0b1         /* MX6Q_PAD_NANDF_CS1__RAWNAND_CE1N */
+                                                           1371 0xb0b1         /* MX6Q_PAD_NANDF_CS2__RAWNAND_CE2N */
+                                                           1378 0xb0b1         /* MX6Q_PAD_NANDF_CS3__RAWNAND_CE3N */
+                                                           1387 0xb0b1         /* MX6Q_PAD_SD4_CMD__RAWNAND_RDN */
+                                                           1393 0xb0b1         /* MX6Q_PAD_SD4_CLK__RAWNAND_WRN */
+                                                           1397 0xb0b1         /* MX6Q_PAD_NANDF_D0__RAWNAND_D0 */
+                                                           1405 0xb0b1         /* MX6Q_PAD_NANDF_D1__RAWNAND_D1 */
+                                                           1413 0xb0b1         /* MX6Q_PAD_NANDF_D2__RAWNAND_D2 */
+                                                           1421 0xb0b1         /* MX6Q_PAD_NANDF_D3__RAWNAND_D3 */
+                                                           1429 0xb0b1         /* MX6Q_PAD_NANDF_D4__RAWNAND_D4 */
+                                                           1437 0xb0b1         /* MX6Q_PAD_NANDF_D5__RAWNAND_D5 */
+                                                           1445 0xb0b1         /* MX6Q_PAD_NANDF_D6__RAWNAND_D6 */
+                                                           1453 0xb0b1         /* MX6Q_PAD_NANDF_D7__RAWNAND_D7 */
+                                                           1463 0x00b1>;       /* MX6Q_PAD_SD4_DAT0__RAWNAND_DQS */
+                                       };
+                               };
+
                                i2c1 {
                                        pinctrl_i2c1_1: i2c1grp-1 {
                                                fsl,pins = <137 0x4001b8b1      /* MX6Q_PAD_EIM_D21__I2C1_SCL */
                                                            1517 0x17059>;      /* MX6Q_PAD_SD4_DAT7__USDHC4_DAT7 */
                                        };
                                };
+
+                               ecspi1 {
+                                       pinctrl_ecspi1_1: ecspi1grp-1 {
+                                               fsl,pins = <101 0x100b1         /* MX6Q_PAD_EIM_D17__ECSPI1_MISO */
+                                                           109 0x100b1         /* MX6Q_PAD_EIM_D18__ECSPI1_MOSI */
+                                                           94  0x100b1>;       /* MX6Q_PAD_EIM_D16__ECSPI1_SCLK */
+                                       };
+                               };
                        };
 
                        dcic@020e4000 { /* DCIC1 */
                                reg = <0x0217c000 0x4000>;
                        };
 
+                       usb@02184000 { /* USB OTG */
+                               compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+                               reg = <0x02184000 0x200>;
+                               interrupts = <0 43 0x04>;
+                               fsl,usbphy = <&usbphy1>;
+                               status = "disabled";
+                       };
+
+                       usb@02184200 { /* USB1 */
+                               compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+                               reg = <0x02184200 0x200>;
+                               interrupts = <0 40 0x04>;
+                               fsl,usbphy = <&usbphy2>;
+                               status = "disabled";
+                       };
+
+                       usb@02184400 { /* USB2 */
+                               compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+                               reg = <0x02184400 0x200>;
+                               interrupts = <0 41 0x04>;
+                               status = "disabled";
+                       };
+
+                       usb@02184600 { /* USB3 */
+                               compatible = "fsl,imx6q-usb", "fsl,imx27-usb";
+                               reg = <0x02184600 0x200>;
+                               interrupts = <0 42 0x04>;
+                               status = "disabled";
+                       };
+
                        ethernet@02188000 {
                                compatible = "fsl,imx6q-fec";
                                reg = <0x02188000 0x4000>;
index 3f5dad801a9806ad3173a0d06dedc0c4a37e8388..e5ffe960dbf3e43181d28e7519b35911c3f95f2c 100644 (file)
                slc: flash@20020000 {
                        compatible = "nxp,lpc3220-slc";
                        reg = <0x20020000 0x1000>;
-                       status = "disable";
+                       status = "disabled";
                };
 
-               mlc: flash@200B0000 {
+               mlc: flash@200a8000 {
                        compatible = "nxp,lpc3220-mlc";
-                       reg = <0x200B0000 0x1000>;
-                       status = "disable";
+                       reg = <0x200a8000 0x11000>;
+                       interrupts = <11 0>;
+                       status = "disabled";
                };
 
                dma@31000000 {
                        compatible = "nxp,ohci-nxp", "usb-ohci";
                        reg = <0x31020000 0x300>;
                        interrupts = <0x3b 0>;
-                       status = "disable";
+                       status = "disabled";
                };
 
                usbd@31020000 {
                        compatible = "nxp,lpc3220-udc";
                        reg = <0x31020000 0x300>;
                        interrupts = <0x3d 0>, <0x3e 0>, <0x3c 0>, <0x3a 0>;
-                       status = "disable";
+                       status = "disabled";
                };
 
                clcd@31040000 {
                        compatible = "arm,pl110", "arm,primecell";
                        reg = <0x31040000 0x1000>;
                        interrupts = <0x0e 0>;
-                       status = "disable";
+                       status = "disabled";
                };
 
                mac: ethernet@31060000 {
                        };
 
                        sd@20098000 {
-                               compatible = "arm,pl180", "arm,primecell";
+                               compatible = "arm,pl18x", "arm,primecell";
                                reg = <0x20098000 0x1000>;
                                interrupts = <0x0f 0>, <0x0d 0>;
+                               status = "disabled";
                        };
 
                        i2s1: i2s@2009C000 {
                                reg = <0x2009C000 0x1000>;
                        };
 
+                       /* UART5 first since it is the default console, ttyS0 */
+                       uart5: serial@40090000 {
+                               /* actually, ns16550a w/ 64 byte fifos! */
+                               compatible = "nxp,lpc3220-uart";
+                               reg = <0x40090000 0x1000>;
+                               interrupts = <9 0>;
+                               clock-frequency = <13000000>;
+                               reg-shift = <2>;
+                               status = "disabled";
+                       };
+
                        uart3: serial@40080000 {
-                               compatible = "nxp,serial";
+                               compatible = "nxp,lpc3220-uart";
                                reg = <0x40080000 0x1000>;
+                               interrupts = <7 0>;
+                               clock-frequency = <13000000>;
+                               reg-shift = <2>;
+                               status = "disabled";
                        };
 
                        uart4: serial@40088000 {
-                               compatible = "nxp,serial";
+                               compatible = "nxp,lpc3220-uart";
                                reg = <0x40088000 0x1000>;
-                       };
-
-                       uart5: serial@40090000 {
-                               compatible = "nxp,serial";
-                               reg = <0x40090000 0x1000>;
+                               interrupts = <8 0>;
+                               clock-frequency = <13000000>;
+                               reg-shift = <2>;
+                               status = "disabled";
                        };
 
                        uart6: serial@40098000 {
-                               compatible = "nxp,serial";
+                               compatible = "nxp,lpc3220-uart";
                                reg = <0x40098000 0x1000>;
+                               interrupts = <10 0>;
+                               clock-frequency = <13000000>;
+                               reg-shift = <2>;
+                               status = "disabled";
                        };
 
                        i2c1: i2c@400A0000 {
                        };
 
                        uart1: serial@40014000 {
-                               compatible = "nxp,serial";
+                               compatible = "nxp,lpc3220-hsuart";
                                reg = <0x40014000 0x1000>;
+                               interrupts = <26 0>;
+                               status = "disabled";
                        };
 
                        uart2: serial@40018000 {
-                               compatible = "nxp,serial";
+                               compatible = "nxp,lpc3220-hsuart";
                                reg = <0x40018000 0x1000>;
+                               interrupts = <25 0>;
+                               status = "disabled";
                        };
 
-                       uart7: serial@4001C000 {
-                               compatible = "nxp,serial";
-                               reg = <0x4001C000 0x1000>;
+                       uart7: serial@4001c000 {
+                               compatible = "nxp,lpc3220-hsuart";
+                               reg = <0x4001c000 0x1000>;
+                               interrupts = <24 0>;
+                               status = "disabled";
                        };
 
                        rtc@40024000 {
                                compatible = "nxp,lpc3220-adc";
                                reg = <0x40048000 0x1000>;
                                interrupts = <0x27 0>;
-                               status = "disable";
+                               status = "disabled";
                        };
 
                        tsc@40048000 {
                                compatible = "nxp,lpc3220-tsc";
                                reg = <0x40048000 0x1000>;
                                interrupts = <0x27 0>;
-                               status = "disable";
+                               status = "disabled";
                        };
 
                        key@40050000 {
                                compatible = "nxp,lpc3220-key";
                                reg = <0x40050000 0x1000>;
+                               interrupts = <54 0>;
+                               status = "disabled";
                        };
 
+                       pwm: pwm@4005C000 {
+                               compatible = "nxp,lpc3220-pwm";
+                               reg = <0x4005C000 0x8>;
+                               status = "disabled";
+                       };
                };
        };
 };
diff --git a/arch/arm/boot/dts/omap2420-h4.dts b/arch/arm/boot/dts/omap2420-h4.dts
new file mode 100644 (file)
index 0000000..25b50b7
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap2.dtsi"
+
+/ {
+       model = "TI OMAP2420 H4 board";
+       compatible = "ti,omap2420-h4", "ti,omap2420", "ti,omap2";
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x84000000>; /* 64 MB */
+       };
+};
index 5b4506c0a8c47d7e1ef506db75cbad9da303b3ec..cdcb98c7e0753b055c3388bd5f170950ba2964a2 100644 (file)
@@ -61,9 +61,9 @@
 };
 
 &mmc2 {
-       status = "disable";
+       status = "disabled";
 };
 
 &mmc3 {
-       status = "disable";
+       status = "disabled";
 };
index 2eee16ec59b472ad8a4c6bff23601105adabbcf8..f349ee9182ce6b12390f74718c9a978b84acd817 100644 (file)
                reg = <0x80000000 0x10000000>; /* 256 MB */
        };
 };
+
+&i2c1 {
+       clock-frequency = <2600000>;
+
+       twl: twl@48 {
+               reg = <0x48>;
+               interrupts = <7>; /* SYS_NIRQ cascaded to intc */
+               interrupt-parent = <&intc>;
+       };
+};
+
+/include/ "twl4030.dtsi"
+
+&i2c2 {
+       clock-frequency = <400000>;
+};
+
+&i2c3 {
+       clock-frequency = <400000>;
+
+       /*
+        * TVP5146 Video decoder-in for analog input support.
+        */
+       tvp5146@5c {
+               compatible = "ti,tvp5146m2";
+               reg = <0x5c>;
+       };
+};
index 99474fa5fac4aa65585625cb77b19338fcdb84cf..810947198208c1fc8b476522b873ccb4136d4e6e 100644 (file)
                        compatible = "ti,omap3-hsmmc";
                        ti,hwmods = "mmc3";
                };
+
+               wdt2: wdt@48314000 {
+                       compatible = "ti,omap3-wdt";
+                       ti,hwmods = "wd_timer2";
+               };
        };
 };
index 1efe0c5879855ebbc4165d09f21403eb86ed9be6..9880c12877b3f5347ef4d5c84cdfadeb028a67d1 100644 (file)
                        linux,default-trigger = "mmc0";
                };
        };
+
+       sound: sound {
+               compatible = "ti,abe-twl6040";
+               ti,model = "PandaBoard";
+
+               ti,mclk-freq = <38400000>;
+
+               ti,mcpdm = <&mcpdm>;
+
+               ti,twl6040 = <&twl6040>;
+
+               /* Audio routing */
+               ti,audio-routing =
+                       "Headset Stereophone", "HSOL",
+                       "Headset Stereophone", "HSOR",
+                       "Ext Spk", "HFL",
+                       "Ext Spk", "HFR",
+                       "Line Out", "AUXL",
+                       "Line Out", "AUXR",
+                       "HSMIC", "Headset Mic",
+                       "Headset Mic", "Headset Mic Bias",
+                       "AFML", "Line In",
+                       "AFMR", "Line In";
+       };
 };
 
 &i2c1 {
                interrupts = <0 7 4>; /* IRQ_SYS_1N cascaded to gic */
                interrupt-parent = <&gic>;
        };
+
+       twl6040: twl@4b {
+               compatible = "ti,twl6040";
+               reg = <0x4b>;
+               /* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */
+               interrupts = <0 119 4>; /* IRQ_SYS_2N cascaded to gic */
+               interrupt-parent = <&gic>;
+               ti,audpwron-gpio = <&gpio4 31 0>;  /* gpio line 127 */
+
+               vio-supply = <&v1v8>;
+               v2v1-supply = <&v2v1>;
+               enable-active-high;
+       };
 };
 
 /include/ "twl6030.dtsi"
 };
 
 &mmc2 {
-       status = "disable";
+       status = "disabled";
 };
 
 &mmc3 {
-       status = "disable";
+       status = "disabled";
 };
 
 &mmc4 {
-       status = "disable";
+       status = "disabled";
 };
 
 &mmc5 {
diff --git a/arch/arm/boot/dts/omap4-pandaES.dts b/arch/arm/boot/dts/omap4-pandaES.dts
new file mode 100644 (file)
index 0000000..d4ba43a
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/include/ "omap4-panda.dts"
+
+/* Audio routing is differnet between PandaBoard4430 and PandaBoardES */
+&sound {
+       ti,model = "PandaBoardES";
+
+       /* Audio routing */
+       ti,audio-routing =
+               "Headset Stereophone", "HSOL",
+               "Headset Stereophone", "HSOR",
+               "Ext Spk", "HFL",
+               "Ext Spk", "HFR",
+               "Line Out", "AUXL",
+               "Line Out", "AUXR",
+               "AFML", "Line In",
+               "AFMR", "Line In";
+};
index d08c4d1372800a0f944489ace4495db188c499c7..72216e932fc0c7c8d5632a0df5173d7bfe05bbe8 100644 (file)
                regulator-boot-on;
        };
 
+       vbat: fixedregulator@2 {
+               compatible = "regulator-fixed";
+               regulator-name = "VBAT";
+               regulator-min-microvolt = <3750000>;
+               regulator-max-microvolt = <3750000>;
+               regulator-boot-on;
+       };
+
        leds {
                compatible = "gpio-leds";
                debug0 {
                        gpios = <&gpio5 11 0>; /* 139 */
                };
        };
+
+       sound {
+               compatible = "ti,abe-twl6040";
+               ti,model = "SDP4430";
+
+               ti,jack-detection = <1>;
+               ti,mclk-freq = <38400000>;
+
+               ti,mcpdm = <&mcpdm>;
+               ti,dmic = <&dmic>;
+
+               ti,twl6040 = <&twl6040>;
+
+               /* Audio routing */
+               ti,audio-routing =
+                       "Headset Stereophone", "HSOL",
+                       "Headset Stereophone", "HSOR",
+                       "Earphone Spk", "EP",
+                       "Ext Spk", "HFL",
+                       "Ext Spk", "HFR",
+                       "Line Out", "AUXL",
+                       "Line Out", "AUXR",
+                       "Vibrator", "VIBRAL",
+                       "Vibrator", "VIBRAR",
+                       "HSMIC", "Headset Mic",
+                       "Headset Mic", "Headset Mic Bias",
+                       "MAINMIC", "Main Handset Mic",
+                       "Main Handset Mic", "Main Mic Bias",
+                       "SUBMIC", "Sub Handset Mic",
+                       "Sub Handset Mic", "Main Mic Bias",
+                       "AFML", "Line In",
+                       "AFMR", "Line In",
+                       "DMic", "Digital Mic",
+                       "Digital Mic", "Digital Mic1 Bias";
+       };
 };
 
 &i2c1 {
                interrupts = <0 7 4>; /* IRQ_SYS_1N cascaded to gic */
                interrupt-parent = <&gic>;
        };
+
+       twl6040: twl@4b {
+               compatible = "ti,twl6040";
+               reg = <0x4b>;
+               /* SPI = 0, IRQ# = 119, 4 = active high level-sensitive */
+               interrupts = <0 119 4>; /* IRQ_SYS_2N cascaded to gic */
+               interrupt-parent = <&gic>;
+               ti,audpwron-gpio = <&gpio4 31 0>;  /* gpio line 127 */
+
+               vio-supply = <&v1v8>;
+               v2v1-supply = <&v2v1>;
+               enable-active-high;
+
+               /* regulators for vibra motor */
+               vddvibl-supply = <&vbat>;
+               vddvibr-supply = <&vbat>;
+
+               vibra {
+                       /* Vibra driver, motor resistance parameters */
+                       ti,vibldrv-res = <8>;
+                       ti,vibrdrv-res = <3>;
+                       ti,viblmotor-res = <10>;
+                       ti,vibrmotor-res = <10>;
+               };
+       };
 };
 
 /include/ "twl6030.dtsi"
 };
 
 &mmc3 {
-       status = "disable";
+       status = "disabled";
 };
 
 &mmc4 {
-       status = "disable";
+       status = "disabled";
 };
 
 &mmc5 {
diff --git a/arch/arm/boot/dts/omap4-var_som.dts b/arch/arm/boot/dts/omap4-var_som.dts
new file mode 100644 (file)
index 0000000..6601e6a
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2012 Variscite Ltd. - http://www.variscite.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap4.dtsi"
+
+/ {
+       model = "Variscite OMAP4 SOM";
+       compatible = "var,omap4-var_som", "ti,omap4430", "ti,omap4";
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x40000000>; /* 1 GB */
+       };
+
+       vdd_eth: fixedregulator@0 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDD_ETH";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               enable-active-high;
+               regulator-boot-on;
+       };
+};
+
+&i2c1 {
+       clock-frequency = <400000>;
+
+       twl: twl@48 {
+               reg = <0x48>;
+               /* SPI = 0, IRQ# = 7, 4 = active high level-sensitive */
+               interrupts = <0 7 4>; /* IRQ_SYS_1N cascaded to gic */
+               interrupt-parent = <&gic>;
+       };
+};
+
+/include/ "twl6030.dtsi"
+
+&i2c2 {
+       clock-frequency = <400000>;
+};
+
+&i2c3 {
+       clock-frequency = <400000>;
+
+       /*
+        * Temperature Sensor
+        * http://www.ti.com/lit/ds/symlink/tmp105.pdf
+        */
+       tmp105@49 {
+               compatible = "ti,tmp105";
+               reg = <0x49>;
+       };
+};
+
+&i2c4 {
+       clock-frequency = <400000>;
+};
+
+&mcspi1 {
+       eth@0 {
+               compatible = "ks8851";
+               spi-max-frequency = <24000000>;
+               reg = <0>;
+               interrupt-parent = <&gpio6>;
+               interrupts = <11>; /* gpio line 171 */
+               vdd-supply = <&vdd_eth>;
+       };
+};
+
+&mmc1 {
+       vmmc-supply = <&vmmc>;
+       ti,bus-width = <8>;
+       ti,non-removable;
+};
+
+&mmc2 {
+       status = "disabled";
+};
+
+&mmc3 {
+       status = "disabled";
+};
+
+&mmc4 {
+       status = "disabled";
+};
+
+&mmc5 {
+       ti,bus-width = <4>;
+};
index 359c4979c8aab6fcc7e0ec40ed1e69ec9b3d8802..04cbbcb6ff91796ac78dfd2e15035ad32a9c89e1 100644 (file)
                        ti,hwmods = "mmc5";
                        ti,needs-special-reset;
                };
+
+               wdt2: wdt@4a314000 {
+                       compatible = "ti,omap4-wdt", "ti,omap3-wdt";
+                       ti,hwmods = "wd_timer2";
+               };
+
+               mcpdm: mcpdm@40132000 {
+                       compatible = "ti,omap4-mcpdm";
+                       reg = <0x40132000 0x7f>, /* MPU private access */
+                             <0x49032000 0x7f>; /* L3 Interconnect */
+                       interrupts = <0 112 0x4>;
+                       interrupt-parent = <&gic>;
+                       ti,hwmods = "mcpdm";
+               };
+
+               dmic: dmic@4012e000 {
+                       compatible = "ti,omap4-dmic";
+                       reg = <0x4012e000 0x7f>, /* MPU private access */
+                             <0x4902e000 0x7f>; /* L3 Interconnect */
+                       interrupts = <0 114 0x4>;
+                       interrupt-parent = <&gic>;
+                       ti,hwmods = "dmic";
+               };
        };
 };
diff --git a/arch/arm/boot/dts/omap5-evm.dts b/arch/arm/boot/dts/omap5-evm.dts
new file mode 100644 (file)
index 0000000..200c39a
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+/dts-v1/;
+
+/include/ "omap5.dtsi"
+
+/ {
+       model = "TI OMAP5 EVM board";
+       compatible = "ti,omap5-evm", "ti,omap5";
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x40000000>; /* 1 GB */
+       };
+};
diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi
new file mode 100644 (file)
index 0000000..57e5270
--- /dev/null
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ * Based on "omap4.dtsi"
+ */
+
+/*
+ * Carveout for multimedia usecases
+ * It should be the last 48MB of the first 512MB memory part
+ * In theory, it should not even exist. That zone should be reserved
+ * dynamically during the .reserve callback.
+ */
+/memreserve/ 0x9d000000 0x03000000;
+
+/include/ "skeleton.dtsi"
+
+/ {
+       compatible = "ti,omap5";
+       interrupt-parent = <&gic>;
+
+       aliases {
+               serial0 = &uart1;
+               serial1 = &uart2;
+               serial2 = &uart3;
+               serial3 = &uart4;
+               serial4 = &uart5;
+               serial5 = &uart6;
+       };
+
+       cpus {
+               cpu@0 {
+                       compatible = "arm,cortex-a15";
+               };
+               cpu@1 {
+                       compatible = "arm,cortex-a15";
+               };
+       };
+
+       /*
+        * The soc node represents the soc top level view. It is uses for IPs
+        * that are not memory mapped in the MPU view or for the MPU itself.
+        */
+       soc {
+               compatible = "ti,omap-infra";
+               mpu {
+                       compatible = "ti,omap5-mpu";
+                       ti,hwmods = "mpu";
+               };
+       };
+
+       /*
+        * XXX: Use a flat representation of the OMAP3 interconnect.
+        * The real OMAP interconnect network is quite complex.
+        * Since that will not bring real advantage to represent that in DT for
+        * the moment, just use a fake OCP bus entry to represent the whole bus
+        * hierarchy.
+        */
+       ocp {
+               compatible = "ti,omap4-l3-noc", "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+               ti,hwmods = "l3_main_1", "l3_main_2", "l3_main_3";
+
+               gic: interrupt-controller@48211000 {
+                       compatible = "arm,cortex-a15-gic";
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       reg = <0x48211000 0x1000>,
+                             <0x48212000 0x1000>;
+               };
+
+               gpio1: gpio@4ae10000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio1";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio2: gpio@48055000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio2";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio3: gpio@48057000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio3";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio4: gpio@48059000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio4";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio5: gpio@4805b000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio5";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio6: gpio@4805d000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio6";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio7: gpio@48051000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio7";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               gpio8: gpio@48053000 {
+                       compatible = "ti,omap4-gpio";
+                       ti,hwmods = "gpio8";
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               uart1: serial@4806a000 {
+                       compatible = "ti,omap4-uart";
+                       ti,hwmods = "uart1";
+                       clock-frequency = <48000000>;
+               };
+
+               uart2: serial@4806c000 {
+                       compatible = "ti,omap4-uart";
+                       ti,hwmods = "uart2";
+                       clock-frequency = <48000000>;
+               };
+
+               uart3: serial@48020000 {
+                       compatible = "ti,omap4-uart";
+                       ti,hwmods = "uart3";
+                       clock-frequency = <48000000>;
+               };
+
+               uart4: serial@4806e000 {
+                       compatible = "ti,omap4-uart";
+                       ti,hwmods = "uart4";
+                       clock-frequency = <48000000>;
+               };
+
+               uart5: serial@48066000 {
+                       compatible = "ti,omap5-uart";
+                       ti,hwmods = "uart5";
+                       clock-frequency = <48000000>;
+               };
+
+               uart6: serial@48068000 {
+                       compatible = "ti,omap6-uart";
+                       ti,hwmods = "uart6";
+                       clock-frequency = <48000000>;
+               };
+       };
+};
index c4ff6d1a018bbee575fd99432c518d0ed530e769..802ec5b2fd00d0d40977624a9ae382b55e416b76 100644 (file)
                        #address-cells = <1>;
                        #size-cells = <1>;
 
+                       nxp,wdr-clks = <14>;
+                       nxp,wwidth = <40000000>;
+                       nxp,whold = <100000000>;
+                       nxp,wsetup = <100000000>;
+                       nxp,rdr-clks = <14>;
+                       nxp,rwidth = <40000000>;
+                       nxp,rhold = <66666666>;
+                       nxp,rsetup = <100000000>;
+                       nand-on-flash-bbt;
+                       gpios = <&gpio 5 19 1>; /* GPO_P3 19, active low */
+
                        mtd0@00000000 {
                                label = "phy3250-boot";
                                reg = <0x00000000 0x00064000>;
                };
 
                apb {
+                       uart5: serial@40090000 {
+                               status = "okay";
+                       };
+
+                       uart3: serial@40080000 {
+                               status = "okay";
+                       };
+
                        i2c1: i2c@400A0000 {
                                clock-frequency = <100000>;
 
                        };
 
                        ssp0: ssp@20084000 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               pl022,num-chipselects = <1>;
+                               cs-gpios = <&gpio 3 5 0>;
+
                                eeprom: at25@0 {
+                                       pl022,hierarchy = <0>;
+                                       pl022,interface = <0>;
+                                       pl022,slave-tx-disable = <0>;
+                                       pl022,com-mode = <0>;
+                                       pl022,rx-level-trig = <1>;
+                                       pl022,tx-level-trig = <1>;
+                                       pl022,ctrl-len = <11>;
+                                       pl022,wait-state = <0>;
+                                       pl022,duplex = <0>;
+
+                                       at25,byte-len = <0x8000>;
+                                       at25,addr-mode = <2>;
+                                       at25,page-size = <64>;
+
                                        compatible = "atmel,at25";
+                                       reg = <0>;
+                                       spi-max-frequency = <5000000>;
                                };
                        };
+
+                       sd@20098000 {
+                               wp-gpios = <&gpio 3 0 0>;
+                               cd-gpios = <&gpio 3 1 0>;
+                               cd-inverted;
+                               bus-width = <4>;
+                               status = "okay";
+                       };
                };
 
                fab {
+                       uart2: serial@40018000 {
+                               status = "okay";
+                       };
+
                        tsc@40048000 {
                                status = "okay";
                        };
+
+                       key@40050000 {
+                               status = "okay";
+                               keypad,num-rows = <1>;
+                               keypad,num-columns = <1>;
+                               nxp,debounce-delay-ms = <3>;
+                               nxp,scan-delay-ms = <34>;
+                               linux,keymap = <0x00000002>;
+                       };
                };
        };
 
index ec3c339751104c43594062c30a47f2601b02b731..7e334d4cae217c8584032666b4301325944786ed 100644 (file)
@@ -77,6 +77,8 @@
                used-led {
                        label = "user_led";
                        gpios = <&gpio4 14 0x4>;
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
                };
        };
 
                        };
                };
 
+               // External Micro SD slot
                sdi@80126000 {
-                       status = "enabled";
+                       arm,primecell-periphid = <0x10480180>;
+                       max-frequency = <50000000>;
+                       bus-width = <8>;
+                       mmc-cap-mmc-highspeed;
                        vmmc-supply = <&ab8500_ldo_aux3_reg>;
+
+                       #gpio-cells = <1>;
                        cd-gpios  = <&gpio6 26 0x4>; // 218
+                       cd-inverted;
+
+                       status = "okay";
                };
 
+               // On-board eMMC
                sdi@80114000 {
-                       status = "enabled";
+                       arm,primecell-periphid = <0x10480180>;
+                       max-frequency = <50000000>;
+                       bus-width = <8>;
+                       mmc-cap-mmc-highspeed;
                        vmmc-supply = <&ab8500_ldo_aux2_reg>;
+
+                       status = "okay";
                };
 
                uart@80120000 {
diff --git a/arch/arm/boot/dts/socfpga.dtsi b/arch/arm/boot/dts/socfpga.dtsi
new file mode 100644 (file)
index 0000000..0772f57
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ *  Copyright (C) 2012 Altera <www.altera.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       aliases {
+               ethernet0 = &gmac0;
+               serial0 = &uart0;
+               serial1 = &uart1;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       compatible = "arm,cortex-a9";
+                       device_type = "cpu";
+                       reg = <0>;
+                       next-level-cache = <&L2>;
+               };
+               cpu@1 {
+                       compatible = "arm,cortex-a9";
+                       device_type = "cpu";
+                       reg = <1>;
+                       next-level-cache = <&L2>;
+               };
+       };
+
+       intc: intc@fffed000 {
+               compatible = "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               reg = <0xfffed000 0x1000>,
+                     <0xfffec100 0x100>;
+       };
+
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "simple-bus";
+               device_type = "soc";
+               interrupt-parent = <&intc>;
+               ranges;
+
+               amba {
+                       compatible = "arm,amba-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       pdma: pdma@ffe01000 {
+                               compatible = "arm,pl330", "arm,primecell";
+                               reg = <0xffe01000 0x1000>;
+                               interrupts = <0 180 4>;
+                       };
+               };
+
+               gmac0: stmmac@ff700000 {
+                       compatible = "altr,socfpga-stmmac", "snps,dwmac-3.70a", "snps,dwmac";
+                       reg = <0xff700000 0x2000>;
+                       interrupts = <0 115 4>;
+                       interrupt-names = "macirq";
+                       mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */
+                       phy-mode = "gmii";
+               };
+
+               L2: l2-cache@fffef000 {
+                       compatible = "arm,pl310-cache";
+                       reg = <0xfffef000 0x1000>;
+                       interrupts = <0 38 0x04>;
+                       cache-unified;
+                       cache-level = <2>;
+               };
+
+               /* Local timer */
+               timer@fffec600 {
+                       compatible = "arm,cortex-a9-twd-timer";
+                       reg = <0xfffec600 0x100>;
+                       interrupts = <1 13 0xf04>;
+               };
+
+               timer0: timer@ffc08000 {
+                       compatible = "snps,dw-apb-timer-sp";
+                       interrupts = <0 167 4>;
+                       clock-frequency = <200000000>;
+                       reg = <0xffc08000 0x1000>;
+               };
+
+               timer1: timer@ffc09000 {
+                       compatible = "snps,dw-apb-timer-sp";
+                       interrupts = <0 168 4>;
+                       clock-frequency = <200000000>;
+                       reg = <0xffc09000 0x1000>;
+               };
+
+               timer2: timer@ffd00000 {
+                       compatible = "snps,dw-apb-timer-osc";
+                       interrupts = <0 169 4>;
+                       clock-frequency = <200000000>;
+                       reg = <0xffd00000 0x1000>;
+               };
+
+               timer3: timer@ffd01000 {
+                       compatible = "snps,dw-apb-timer-osc";
+                       interrupts = <0 170 4>;
+                       clock-frequency = <200000000>;
+                       reg = <0xffd01000 0x1000>;
+               };
+
+               uart0: uart@ffc02000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0xffc02000 0x1000>;
+                       clock-frequency = <7372800>;
+                       interrupts = <0 162 4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+
+               uart1: uart@ffc03000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0xffc03000 0x1000>;
+                       clock-frequency = <7372800>;
+                       interrupts = <0 163 4>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/socfpga_cyclone5.dts b/arch/arm/boot/dts/socfpga_cyclone5.dts
new file mode 100644 (file)
index 0000000..ab7e4a9
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ *  Copyright (C) 2012 Altera Corporation <www.altera.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/dts-v1/;
+/include/ "socfpga.dtsi"
+
+/ {
+       model = "Altera SOCFPGA Cyclone V";
+       compatible = "altr,socfpga-cyclone5";
+
+       chosen {
+               bootargs = "console=ttyS0,57600";
+       };
+
+       memory {
+               name = "memory";
+               device_type = "memory";
+               reg = <0x0 0x10000000>; /* 256MB */
+       };
+};
diff --git a/arch/arm/boot/dts/tegra-cardhu.dts b/arch/arm/boot/dts/tegra-cardhu.dts
deleted file mode 100644 (file)
index 36321bc..0000000
+++ /dev/null
@@ -1,172 +0,0 @@
-/dts-v1/;
-
-/include/ "tegra30.dtsi"
-
-/ {
-       model = "NVIDIA Tegra30 Cardhu evaluation board";
-       compatible = "nvidia,cardhu", "nvidia,tegra30";
-
-       memory {
-               reg = <0x80000000 0x40000000>;
-       };
-
-       pinmux {
-               pinctrl-names = "default";
-               pinctrl-0 = <&state_default>;
-
-               state_default: pinmux {
-                       sdmmc1_clk_pz0 {
-                               nvidia,pins = "sdmmc1_clk_pz0";
-                               nvidia,function = "sdmmc1";
-                               nvidia,pull = <0>;
-                               nvidia,tristate = <0>;
-                       };
-                       sdmmc1_cmd_pz1 {
-                               nvidia,pins =   "sdmmc1_cmd_pz1",
-                                               "sdmmc1_dat0_py7",
-                                               "sdmmc1_dat1_py6",
-                                               "sdmmc1_dat2_py5",
-                                               "sdmmc1_dat3_py4";
-                               nvidia,function = "sdmmc1";
-                               nvidia,pull = <2>;
-                               nvidia,tristate = <0>;
-                       };
-                       sdmmc4_clk_pcc4 {
-                               nvidia,pins =   "sdmmc4_clk_pcc4",
-                                               "sdmmc4_rst_n_pcc3";
-                               nvidia,function = "sdmmc4";
-                               nvidia,pull = <0>;
-                               nvidia,tristate = <0>;
-                       };
-                       sdmmc4_dat0_paa0 {
-                               nvidia,pins =   "sdmmc4_dat0_paa0",
-                                               "sdmmc4_dat1_paa1",
-                                               "sdmmc4_dat2_paa2",
-                                               "sdmmc4_dat3_paa3",
-                                               "sdmmc4_dat4_paa4",
-                                               "sdmmc4_dat5_paa5",
-                                               "sdmmc4_dat6_paa6",
-                                               "sdmmc4_dat7_paa7";
-                               nvidia,function = "sdmmc4";
-                               nvidia,pull = <2>;
-                               nvidia,tristate = <0>;
-                       };
-                       dap2_fs_pa2 {
-                               nvidia,pins =   "dap2_fs_pa2",
-                                               "dap2_sclk_pa3",
-                                               "dap2_din_pa4",
-                                               "dap2_dout_pa5";
-                               nvidia,function = "i2s1";
-                               nvidia,pull = <0>;
-                               nvidia,tristate = <0>;
-                       };
-               };
-       };
-
-       serial@70006000 {
-               status = "okay";
-               clock-frequency = <408000000>;
-       };
-
-       i2c@7000c000 {
-               status = "okay";
-               clock-frequency = <100000>;
-       };
-
-       i2c@7000c400 {
-               status = "okay";
-               clock-frequency = <100000>;
-       };
-
-       i2c@7000c500 {
-               status = "okay";
-               clock-frequency = <100000>;
-
-               /* ALS and Proximity sensor */
-               isl29028@44 {
-                       compatible = "isil,isl29028";
-                       reg = <0x44>;
-                       interrupt-parent = <&gpio>;
-                       interrupts = <88 0x04>; /*gpio PL0 */
-               };
-       };
-
-       i2c@7000c700 {
-               status = "okay";
-               clock-frequency = <100000>;
-       };
-
-       i2c@7000d000 {
-               status = "okay";
-               clock-frequency = <100000>;
-
-               wm8903: wm8903@1a {
-                       compatible = "wlf,wm8903";
-                       reg = <0x1a>;
-                       interrupt-parent = <&gpio>;
-                       interrupts = <179 0x04>; /* gpio PW3 */
-
-                       gpio-controller;
-                       #gpio-cells = <2>;
-
-                       micdet-cfg = <0>;
-                       micdet-delay = <100>;
-                       gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>;
-               };
-
-               tps62361 {
-                       compatible = "ti,tps62361";
-                       reg = <0x60>;
-
-                       regulator-name = "tps62361-vout";
-                       regulator-min-microvolt = <500000>;
-                       regulator-max-microvolt = <1500000>;
-                       regulator-boot-on;
-                       regulator-always-on;
-                       ti,vsel0-state-high;
-                       ti,vsel1-state-high;
-               };
-       };
-
-       ahub {
-               i2s@70080400 {
-                       status = "okay";
-               };
-       };
-
-       sdhci@78000000 {
-               status = "okay";
-               cd-gpios = <&gpio 69 0>; /* gpio PI5 */
-               wp-gpios = <&gpio 155 0>; /* gpio PT3 */
-               power-gpios = <&gpio 31 0>; /* gpio PD7 */
-               bus-width = <4>;
-       };
-
-       sdhci@78000600 {
-               status = "okay";
-               support-8bit;
-               bus-width = <8>;
-       };
-
-       sound {
-               compatible = "nvidia,tegra-audio-wm8903-cardhu",
-                            "nvidia,tegra-audio-wm8903";
-               nvidia,model = "NVIDIA Tegra Cardhu";
-
-               nvidia,audio-routing =
-                       "Headphone Jack", "HPOUTR",
-                       "Headphone Jack", "HPOUTL",
-                       "Int Spk", "ROP",
-                       "Int Spk", "RON",
-                       "Int Spk", "LOP",
-                       "Int Spk", "LON",
-                       "Mic Jack", "MICBIAS",
-                       "IN1L", "Mic Jack";
-
-               nvidia,i2s-controller = <&tegra_i2s1>;
-               nvidia,audio-codec = <&wm8903>;
-
-               nvidia,spkr-en-gpios = <&wm8903 2 0>;
-               nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
-       };
-};
diff --git a/arch/arm/boot/dts/tegra-harmony.dts b/arch/arm/boot/dts/tegra-harmony.dts
deleted file mode 100644 (file)
index 7de7013..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-/dts-v1/;
-
-/include/ "tegra20.dtsi"
-
-/ {
-       model = "NVIDIA Tegra2 Harmony evaluation board";
-       compatible = "nvidia,harmony", "nvidia,tegra20";
-
-       memory {
-               reg = <0x00000000 0x40000000>;
-       };
-
-       pinmux {
-               pinctrl-names = "default";
-               pinctrl-0 = <&state_default>;
-
-               state_default: pinmux {
-                       ata {
-                               nvidia,pins = "ata";
-                               nvidia,function = "ide";
-                       };
-                       atb {
-                               nvidia,pins = "atb", "gma", "gme";
-                               nvidia,function = "sdio4";
-                       };
-                       atc {
-                               nvidia,pins = "atc";
-                               nvidia,function = "nand";
-                       };
-                       atd {
-                               nvidia,pins = "atd", "ate", "gmb", "gmd", "gpu",
-                                       "spia", "spib", "spic";
-                               nvidia,function = "gmi";
-                       };
-                       cdev1 {
-                               nvidia,pins = "cdev1";
-                               nvidia,function = "plla_out";
-                       };
-                       cdev2 {
-                               nvidia,pins = "cdev2";
-                               nvidia,function = "pllp_out4";
-                       };
-                       crtp {
-                               nvidia,pins = "crtp";
-                               nvidia,function = "crt";
-                       };
-                       csus {
-                               nvidia,pins = "csus";
-                               nvidia,function = "vi_sensor_clk";
-                       };
-                       dap1 {
-                               nvidia,pins = "dap1";
-                               nvidia,function = "dap1";
-                       };
-                       dap2 {
-                               nvidia,pins = "dap2";
-                               nvidia,function = "dap2";
-                       };
-                       dap3 {
-                               nvidia,pins = "dap3";
-                               nvidia,function = "dap3";
-                       };
-                       dap4 {
-                               nvidia,pins = "dap4";
-                               nvidia,function = "dap4";
-                       };
-                       ddc {
-                               nvidia,pins = "ddc";
-                               nvidia,function = "i2c2";
-                       };
-                       dta {
-                               nvidia,pins = "dta", "dtd";
-                               nvidia,function = "sdio2";
-                       };
-                       dtb {
-                               nvidia,pins = "dtb", "dtc", "dte";
-                               nvidia,function = "rsvd1";
-                       };
-                       dtf {
-                               nvidia,pins = "dtf";
-                               nvidia,function = "i2c3";
-                       };
-                       gmc {
-                               nvidia,pins = "gmc";
-                               nvidia,function = "uartd";
-                       };
-                       gpu7 {
-                               nvidia,pins = "gpu7";
-                               nvidia,function = "rtck";
-                       };
-                       gpv {
-                               nvidia,pins = "gpv", "slxa", "slxk";
-                               nvidia,function = "pcie";
-                       };
-                       hdint {
-                               nvidia,pins = "hdint", "pta";
-                               nvidia,function = "hdmi";
-                       };
-                       i2cp {
-                               nvidia,pins = "i2cp";
-                               nvidia,function = "i2cp";
-                       };
-                       irrx {
-                               nvidia,pins = "irrx", "irtx";
-                               nvidia,function = "uarta";
-                       };
-                       kbca {
-                               nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
-                                       "kbce", "kbcf";
-                               nvidia,function = "kbc";
-                       };
-                       lcsn {
-                               nvidia,pins = "lcsn", "ld0", "ld1", "ld2",
-                                       "ld3", "ld4", "ld5", "ld6", "ld7",
-                                       "ld8", "ld9", "ld10", "ld11", "ld12",
-                                       "ld13", "ld14", "ld15", "ld16", "ld17",
-                                       "ldc", "ldi", "lhp0", "lhp1", "lhp2",
-                                       "lhs", "lm0", "lm1", "lpp", "lpw0",
-                                       "lpw1", "lpw2", "lsc0", "lsc1", "lsck",
-                                       "lsda", "lsdi", "lspi", "lvp0", "lvp1",
-                                       "lvs";
-                               nvidia,function = "displaya";
-                       };
-                       owc {
-                               nvidia,pins = "owc", "spdi", "spdo", "uac";
-                               nvidia,function = "rsvd2";
-                       };
-                       pmc {
-                               nvidia,pins = "pmc";
-                               nvidia,function = "pwr_on";
-                       };
-                       rm {
-                               nvidia,pins = "rm";
-                               nvidia,function = "i2c1";
-                       };
-                       sdb {
-                               nvidia,pins = "sdb", "sdc", "sdd";
-                               nvidia,function = "pwm";
-                       };
-                       sdio1 {
-                               nvidia,pins = "sdio1";
-                               nvidia,function = "sdio1";
-                       };
-                       slxc {
-                               nvidia,pins = "slxc", "slxd";
-                               nvidia,function = "spdif";
-                       };
-                       spid {
-                               nvidia,pins = "spid", "spie", "spif";
-                               nvidia,function = "spi1";
-                       };
-                       spig {
-                               nvidia,pins = "spig", "spih";
-                               nvidia,function = "spi2_alt";
-                       };
-                       uaa {
-                               nvidia,pins = "uaa", "uab", "uda";
-                               nvidia,function = "ulpi";
-                       };
-                       uad {
-                               nvidia,pins = "uad";
-                               nvidia,function = "irda";
-                       };
-                       uca {
-                               nvidia,pins = "uca", "ucb";
-                               nvidia,function = "uartc";
-                       };
-                       conf_ata {
-                               nvidia,pins = "ata", "atb", "atc", "atd", "ate",
-                                       "cdev1", "cdev2", "dap1", "dtb", "gma",
-                                       "gmb", "gmc", "gmd", "gme", "gpu7",
-                                       "gpv", "i2cp", "pta", "rm", "slxa",
-                                       "slxk", "spia", "spib", "uac";
-                               nvidia,pull = <0>;
-                               nvidia,tristate = <0>;
-                       };
-                       conf_ck32 {
-                               nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
-                                       "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
-                               nvidia,pull = <0>;
-                       };
-                       conf_csus {
-                               nvidia,pins = "csus", "spid", "spif";
-                               nvidia,pull = <1>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_crtp {
-                               nvidia,pins = "crtp", "dap2", "dap3", "dap4",
-                                       "dtc", "dte", "dtf", "gpu", "sdio1",
-                                       "slxc", "slxd", "spdi", "spdo", "spig",
-                                       "uda";
-                               nvidia,pull = <0>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_ddc {
-                               nvidia,pins = "ddc", "dta", "dtd", "kbca",
-                                       "kbcb", "kbcc", "kbcd", "kbce", "kbcf",
-                                       "sdc";
-                               nvidia,pull = <2>;
-                               nvidia,tristate = <0>;
-                       };
-                       conf_hdint {
-                               nvidia,pins = "hdint", "lcsn", "ldc", "lm1",
-                                       "lpw1", "lsc1", "lsck", "lsda", "lsdi",
-                                       "lvp0", "owc", "sdb";
-                               nvidia,tristate = <1>;
-                       };
-                       conf_irrx {
-                               nvidia,pins = "irrx", "irtx", "sdd", "spic",
-                                       "spie", "spih", "uaa", "uab", "uad",
-                                       "uca", "ucb";
-                               nvidia,pull = <2>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_lc {
-                               nvidia,pins = "lc", "ls";
-                               nvidia,pull = <2>;
-                       };
-                       conf_ld0 {
-                               nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
-                                       "ld5", "ld6", "ld7", "ld8", "ld9",
-                                       "ld10", "ld11", "ld12", "ld13", "ld14",
-                                       "ld15", "ld16", "ld17", "ldi", "lhp0",
-                                       "lhp1", "lhp2", "lhs", "lm0", "lpp",
-                                       "lpw0", "lpw2", "lsc0", "lspi", "lvp1",
-                                       "lvs", "pmc";
-                               nvidia,tristate = <0>;
-                       };
-                       conf_ld17_0 {
-                               nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
-                                       "ld23_22";
-                               nvidia,pull = <1>;
-                       };
-               };
-       };
-
-       i2s@70002800 {
-               status = "okay";
-       };
-
-       serial@70006300 {
-               status = "okay";
-               clock-frequency = <216000000>;
-       };
-
-       i2c@7000c000 {
-               status = "okay";
-               clock-frequency = <400000>;
-
-               wm8903: wm8903@1a {
-                       compatible = "wlf,wm8903";
-                       reg = <0x1a>;
-                       interrupt-parent = <&gpio>;
-                       interrupts = <187 0x04>;
-
-                       gpio-controller;
-                       #gpio-cells = <2>;
-
-                       micdet-cfg = <0>;
-                       micdet-delay = <100>;
-                       gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>;
-               };
-       };
-
-       i2c@7000c400 {
-               status = "okay";
-               clock-frequency = <400000>;
-       };
-
-       i2c@7000c500 {
-               status = "okay";
-               clock-frequency = <400000>;
-       };
-
-       i2c@7000d000 {
-               status = "okay";
-               clock-frequency = <400000>;
-       };
-
-       pmc {
-               nvidia,invert-interrupt;
-       };
-
-       usb@c5000000 {
-               status = "okay";
-       };
-
-       usb@c5004000 {
-               status = "okay";
-               nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
-       };
-
-       usb@c5008000 {
-               status = "okay";
-       };
-
-       sdhci@c8000200 {
-               status = "okay";
-               cd-gpios = <&gpio 69 0>; /* 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 */
-               wp-gpios = <&gpio 59 0>; /* gpio PH3 */
-               power-gpios = <&gpio 70 0>; /* gpio PI6 */
-               support-8bit;
-               bus-width = <8>;
-       };
-
-       sound {
-               compatible = "nvidia,tegra-audio-wm8903-harmony",
-                            "nvidia,tegra-audio-wm8903";
-               nvidia,model = "NVIDIA Tegra Harmony";
-
-               nvidia,audio-routing =
-                       "Headphone Jack", "HPOUTR",
-                       "Headphone Jack", "HPOUTL",
-                       "Int Spk", "ROP",
-                       "Int Spk", "RON",
-                       "Int Spk", "LOP",
-                       "Int Spk", "LON",
-                       "Mic Jack", "MICBIAS",
-                       "IN1L", "Mic Jack";
-
-               nvidia,i2s-controller = <&tegra_i2s1>;
-               nvidia,audio-codec = <&wm8903>;
-
-               nvidia,spkr-en-gpios = <&wm8903 2 0>;
-               nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
-               nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */
-               nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
-       };
-};
diff --git a/arch/arm/boot/dts/tegra-paz00.dts b/arch/arm/boot/dts/tegra-paz00.dts
deleted file mode 100644 (file)
index bfeb117..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-/dts-v1/;
-
-/include/ "tegra20.dtsi"
-
-/ {
-       model = "Toshiba AC100 / Dynabook AZ";
-       compatible = "compal,paz00", "nvidia,tegra20";
-
-       memory {
-               reg = <0x00000000 0x20000000>;
-       };
-
-       pinmux {
-               pinctrl-names = "default";
-               pinctrl-0 = <&state_default>;
-
-               state_default: pinmux {
-                       ata {
-                               nvidia,pins = "ata", "atc", "atd", "ate",
-                                       "dap2", "gmb", "gmc", "gmd", "spia",
-                                       "spib", "spic", "spid", "spie";
-                               nvidia,function = "gmi";
-                       };
-                       atb {
-                               nvidia,pins = "atb", "gma", "gme";
-                               nvidia,function = "sdio4";
-                       };
-                       cdev1 {
-                               nvidia,pins = "cdev1";
-                               nvidia,function = "plla_out";
-                       };
-                       cdev2 {
-                               nvidia,pins = "cdev2";
-                               nvidia,function = "pllp_out4";
-                       };
-                       crtp {
-                               nvidia,pins = "crtp";
-                               nvidia,function = "crt";
-                       };
-                       csus {
-                               nvidia,pins = "csus";
-                               nvidia,function = "pllc_out1";
-                       };
-                       dap1 {
-                               nvidia,pins = "dap1";
-                               nvidia,function = "dap1";
-                       };
-                       dap3 {
-                               nvidia,pins = "dap3";
-                               nvidia,function = "dap3";
-                       };
-                       dap4 {
-                               nvidia,pins = "dap4";
-                               nvidia,function = "dap4";
-                       };
-                       ddc {
-                               nvidia,pins = "ddc";
-                               nvidia,function = "i2c2";
-                       };
-                       dta {
-                               nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
-                               nvidia,function = "rsvd1";
-                       };
-                       dtf {
-                               nvidia,pins = "dtf";
-                               nvidia,function = "i2c3";
-                       };
-                       gpu {
-                               nvidia,pins = "gpu", "sdb", "sdd";
-                               nvidia,function = "pwm";
-                       };
-                       gpu7 {
-                               nvidia,pins = "gpu7";
-                               nvidia,function = "rtck";
-                       };
-                       gpv {
-                               nvidia,pins = "gpv", "slxa", "slxk";
-                               nvidia,function = "pcie";
-                       };
-                       hdint {
-                               nvidia,pins = "hdint", "pta";
-                               nvidia,function = "hdmi";
-                       };
-                       i2cp {
-                               nvidia,pins = "i2cp";
-                               nvidia,function = "i2cp";
-                       };
-                       irrx {
-                               nvidia,pins = "irrx", "irtx";
-                               nvidia,function = "uarta";
-                       };
-                       kbca {
-                               nvidia,pins = "kbca", "kbcc", "kbce", "kbcf";
-                               nvidia,function = "kbc";
-                       };
-                       kbcb {
-                               nvidia,pins = "kbcb", "kbcd";
-                               nvidia,function = "sdio2";
-                       };
-                       lcsn {
-                               nvidia,pins = "lcsn", "ld0", "ld1", "ld2",
-                                       "ld3", "ld4", "ld5", "ld6", "ld7",
-                                       "ld8", "ld9", "ld10", "ld11", "ld12",
-                                       "ld13", "ld14", "ld15", "ld16", "ld17",
-                                       "ldc", "ldi", "lhp0", "lhp1", "lhp2",
-                                       "lhs", "lm0", "lm1", "lpp", "lpw0",
-                                       "lpw1", "lpw2", "lsc0", "lsc1", "lsck",
-                                       "lsda", "lsdi", "lspi", "lvp0", "lvp1",
-                                       "lvs";
-                               nvidia,function = "displaya";
-                       };
-                       owc {
-                               nvidia,pins = "owc";
-                               nvidia,function = "owr";
-                       };
-                       pmc {
-                               nvidia,pins = "pmc";
-                               nvidia,function = "pwr_on";
-                       };
-                       rm {
-                               nvidia,pins = "rm";
-                               nvidia,function = "i2c1";
-                       };
-                       sdc {
-                               nvidia,pins = "sdc";
-                               nvidia,function = "twc";
-                       };
-                       sdio1 {
-                               nvidia,pins = "sdio1";
-                               nvidia,function = "sdio1";
-                       };
-                       slxc {
-                               nvidia,pins = "slxc", "slxd";
-                               nvidia,function = "spi4";
-                       };
-                       spdi {
-                               nvidia,pins = "spdi", "spdo";
-                               nvidia,function = "rsvd2";
-                       };
-                       spif {
-                               nvidia,pins = "spif", "uac";
-                               nvidia,function = "rsvd4";
-                       };
-                       spig {
-                               nvidia,pins = "spig", "spih";
-                               nvidia,function = "spi2_alt";
-                       };
-                       uaa {
-                               nvidia,pins = "uaa", "uab", "uda";
-                               nvidia,function = "ulpi";
-                       };
-                       uad {
-                               nvidia,pins = "uad";
-                               nvidia,function = "spdif";
-                       };
-                       uca {
-                               nvidia,pins = "uca", "ucb";
-                               nvidia,function = "uartc";
-                       };
-                       conf_ata {
-                               nvidia,pins = "ata", "atb", "atc", "atd", "ate",
-                                       "cdev1", "cdev2", "dap1", "dap2", "dtf",
-                                       "gma", "gmb", "gmc", "gmd", "gme",
-                                       "gpu", "gpu7", "gpv", "i2cp", "pta",
-                                       "rm", "sdio1", "slxk", "spdo", "uac",
-                                       "uda";
-                               nvidia,pull = <0>;
-                               nvidia,tristate = <0>;
-                       };
-                       conf_ck32 {
-                               nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
-                                       "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
-                               nvidia,pull = <0>;
-                       };
-                       conf_crtp {
-                               nvidia,pins = "crtp", "dap3", "dap4", "dtb",
-                                       "dtc", "dte", "slxa", "slxc", "slxd",
-                                       "spdi";
-                               nvidia,pull = <0>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_csus {
-                               nvidia,pins = "csus", "spia", "spib", "spid",
-                                       "spif";
-                               nvidia,pull = <1>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_ddc {
-                               nvidia,pins = "ddc", "irrx", "irtx", "kbca",
-                                       "kbcb", "kbcc", "kbcd", "kbce", "kbcf",
-                                       "spic", "spig", "uaa", "uab";
-                               nvidia,pull = <2>;
-                               nvidia,tristate = <0>;
-                       };
-                       conf_dta {
-                               nvidia,pins = "dta", "dtd", "owc", "sdc", "sdd",
-                                       "spie", "spih", "uad", "uca", "ucb";
-                               nvidia,pull = <2>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_hdint {
-                               nvidia,pins = "hdint", "ld0", "ld1", "ld2",
-                                       "ld3", "ld4", "ld5", "ld6", "ld7",
-                                       "ld8", "ld9", "ld10", "ld11", "ld12",
-                                       "ld13", "ld14", "ld15", "ld16", "ld17",
-                                       "ldc", "ldi", "lhs", "lsc0", "lspi",
-                                       "lvs", "pmc";
-                               nvidia,tristate = <0>;
-                       };
-                       conf_lc {
-                               nvidia,pins = "lc", "ls";
-                               nvidia,pull = <2>;
-                       };
-                       conf_lcsn {
-                               nvidia,pins = "lcsn", "lhp0", "lhp1", "lhp2",
-                                       "lm0", "lm1", "lpp", "lpw0", "lpw1",
-                                       "lpw2", "lsc1", "lsck", "lsda", "lsdi",
-                                       "lvp0", "lvp1", "sdb";
-                               nvidia,tristate = <1>;
-                       };
-                       conf_ld17_0 {
-                               nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
-                                       "ld23_22";
-                               nvidia,pull = <1>;
-                       };
-               };
-       };
-
-       i2s@70002800 {
-               status = "okay";
-       };
-
-       serial@70006000 {
-               status = "okay";
-               clock-frequency = <216000000>;
-       };
-
-       serial@70006200 {
-               status = "okay";
-               clock-frequency = <216000000>;
-       };
-
-       i2c@7000c000 {
-               status = "okay";
-               clock-frequency = <400000>;
-
-               alc5632: alc5632@1e {
-                       compatible = "realtek,alc5632";
-                       reg = <0x1e>;
-                       gpio-controller;
-                       #gpio-cells = <2>;
-               };
-       };
-
-       i2c@7000c400 {
-               status = "okay";
-               clock-frequency = <400000>;
-       };
-
-       nvec {
-               compatible = "nvidia,nvec";
-               reg = <0x7000c500 0x100>;
-               interrupts = <0 92 0x04>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-               clock-frequency = <80000>;
-               request-gpios = <&gpio 170 0>; /* gpio PV2 */
-               slave-addr = <138>;
-       };
-
-       i2c@7000d000 {
-               status = "okay";
-               clock-frequency = <400000>;
-
-               adt7461@4c {
-                       compatible = "adi,adt7461";
-                       reg = <0x4c>;
-               };
-       };
-
-       usb@c5000000 {
-               status = "okay";
-       };
-
-       usb@c5004000 {
-               status = "okay";
-               nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
-       };
-
-       usb@c5008000 {
-               status = "okay";
-       };
-
-       sdhci@c8000000 {
-               status = "okay";
-               cd-gpios = <&gpio 173 0>; /* gpio PV5 */
-               wp-gpios = <&gpio 57 0>;  /* gpio PH1 */
-               power-gpios = <&gpio 169 0>; /* gpio PV1 */
-               bus-width = <4>;
-       };
-
-       sdhci@c8000600 {
-               status = "okay";
-               support-8bit;
-               bus-width = <8>;
-       };
-
-       gpio-keys {
-               compatible = "gpio-keys";
-
-               power {
-                       label = "Power";
-                       gpios = <&gpio 79 1>; /* gpio PJ7, active low */
-                       linux,code = <116>; /* KEY_POWER */
-                       gpio-key,wakeup;
-               };
-       };
-
-       gpio-leds {
-               compatible = "gpio-leds";
-
-               wifi {
-                       label = "wifi-led";
-                       gpios = <&gpio 24 0>; /* gpio PD0 */
-                       linux,default-trigger = "rfkill0";
-               };
-       };
-
-       sound {
-               compatible = "nvidia,tegra-audio-alc5632-paz00",
-                       "nvidia,tegra-audio-alc5632";
-
-               nvidia,model = "Compal PAZ00";
-
-               nvidia,audio-routing =
-                       "Int Spk", "SPKOUT",
-                       "Int Spk", "SPKOUTN",
-                       "Headset Mic", "MICBIAS1",
-                       "MIC1", "Headset Mic",
-                       "Headset Stereophone", "HPR",
-                       "Headset Stereophone", "HPL",
-                       "DMICDAT", "Digital Mic";
-
-               nvidia,audio-codec = <&alc5632>;
-               nvidia,i2s-controller = <&tegra_i2s1>;
-               nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
-       };
-};
diff --git a/arch/arm/boot/dts/tegra-seaboard.dts b/arch/arm/boot/dts/tegra-seaboard.dts
deleted file mode 100644 (file)
index 89cb7f2..0000000
+++ /dev/null
@@ -1,445 +0,0 @@
-/dts-v1/;
-
-/include/ "tegra20.dtsi"
-
-/ {
-       model = "NVIDIA Seaboard";
-       compatible = "nvidia,seaboard", "nvidia,tegra20";
-
-       memory {
-               reg = <0x00000000 0x40000000>;
-       };
-
-       pinmux {
-               pinctrl-names = "default";
-               pinctrl-0 = <&state_default>;
-
-               state_default: pinmux {
-                       ata {
-                               nvidia,pins = "ata";
-                               nvidia,function = "ide";
-                       };
-                       atb {
-                               nvidia,pins = "atb", "gma", "gme";
-                               nvidia,function = "sdio4";
-                       };
-                       atc {
-                               nvidia,pins = "atc";
-                               nvidia,function = "nand";
-                       };
-                       atd {
-                               nvidia,pins = "atd", "ate", "gmb", "spia",
-                                       "spib", "spic";
-                               nvidia,function = "gmi";
-                       };
-                       cdev1 {
-                               nvidia,pins = "cdev1";
-                               nvidia,function = "plla_out";
-                       };
-                       cdev2 {
-                               nvidia,pins = "cdev2";
-                               nvidia,function = "pllp_out4";
-                       };
-                       crtp {
-                               nvidia,pins = "crtp", "lm1";
-                               nvidia,function = "crt";
-                       };
-                       csus {
-                               nvidia,pins = "csus";
-                               nvidia,function = "vi_sensor_clk";
-                       };
-                       dap1 {
-                               nvidia,pins = "dap1";
-                               nvidia,function = "dap1";
-                       };
-                       dap2 {
-                               nvidia,pins = "dap2";
-                               nvidia,function = "dap2";
-                       };
-                       dap3 {
-                               nvidia,pins = "dap3";
-                               nvidia,function = "dap3";
-                       };
-                       dap4 {
-                               nvidia,pins = "dap4";
-                               nvidia,function = "dap4";
-                       };
-                       ddc {
-                               nvidia,pins = "ddc", "owc", "spdi", "spdo",
-                                       "uac";
-                               nvidia,function = "rsvd2";
-                       };
-                       dta {
-                               nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
-                               nvidia,function = "vi";
-                       };
-                       dtf {
-                               nvidia,pins = "dtf";
-                               nvidia,function = "i2c3";
-                       };
-                       gmc {
-                               nvidia,pins = "gmc";
-                               nvidia,function = "uartd";
-                       };
-                       gmd {
-                               nvidia,pins = "gmd";
-                               nvidia,function = "sflash";
-                       };
-                       gpu {
-                               nvidia,pins = "gpu";
-                               nvidia,function = "pwm";
-                       };
-                       gpu7 {
-                               nvidia,pins = "gpu7";
-                               nvidia,function = "rtck";
-                       };
-                       gpv {
-                               nvidia,pins = "gpv", "slxa", "slxk";
-                               nvidia,function = "pcie";
-                       };
-                       hdint {
-                               nvidia,pins = "hdint", "lpw0", "lpw2", "lsc1",
-                                       "lsck", "lsda";
-                               nvidia,function = "hdmi";
-                       };
-                       i2cp {
-                               nvidia,pins = "i2cp";
-                               nvidia,function = "i2cp";
-                       };
-                       irrx {
-                               nvidia,pins = "irrx", "irtx";
-                               nvidia,function = "uartb";
-                       };
-                       kbca {
-                               nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
-                                       "kbce", "kbcf";
-                               nvidia,function = "kbc";
-                       };
-                       lcsn {
-                               nvidia,pins = "lcsn", "ldc", "lm0", "lpw1",
-                                       "lsdi", "lvp0";
-                               nvidia,function = "rsvd4";
-                       };
-                       ld0 {
-                               nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
-                                       "ld5", "ld6", "ld7", "ld8", "ld9",
-                                       "ld10", "ld11", "ld12", "ld13", "ld14",
-                                       "ld15", "ld16", "ld17", "ldi", "lhp0",
-                                       "lhp1", "lhp2", "lhs", "lpp", "lsc0",
-                                       "lspi", "lvp1", "lvs";
-                               nvidia,function = "displaya";
-                       };
-                       pmc {
-                               nvidia,pins = "pmc";
-                               nvidia,function = "pwr_on";
-                       };
-                       pta {
-                               nvidia,pins = "pta";
-                               nvidia,function = "i2c2";
-                       };
-                       rm {
-                               nvidia,pins = "rm";
-                               nvidia,function = "i2c1";
-                       };
-                       sdb {
-                               nvidia,pins = "sdb", "sdc", "sdd";
-                               nvidia,function = "sdio3";
-                       };
-                       sdio1 {
-                               nvidia,pins = "sdio1";
-                               nvidia,function = "sdio1";
-                       };
-                       slxc {
-                               nvidia,pins = "slxc", "slxd";
-                               nvidia,function = "spdif";
-                       };
-                       spid {
-                               nvidia,pins = "spid", "spie", "spif";
-                               nvidia,function = "spi1";
-                       };
-                       spig {
-                               nvidia,pins = "spig", "spih";
-                               nvidia,function = "spi2_alt";
-                       };
-                       uaa {
-                               nvidia,pins = "uaa", "uab", "uda";
-                               nvidia,function = "ulpi";
-                       };
-                       uad {
-                               nvidia,pins = "uad";
-                               nvidia,function = "irda";
-                       };
-                       uca {
-                               nvidia,pins = "uca", "ucb";
-                               nvidia,function = "uartc";
-                       };
-                       conf_ata {
-                               nvidia,pins = "ata", "atb", "atc", "atd",
-                                       "cdev1", "cdev2", "dap1", "dap2",
-                                       "dap4", "dtf", "gma", "gmc", "gmd",
-                                       "gme", "gpu", "gpu7", "i2cp", "irrx",
-                                       "irtx", "pta", "rm", "sdc", "sdd",
-                                       "slxd", "slxk", "spdi", "spdo", "uac",
-                                       "uad", "uca", "ucb", "uda";
-                               nvidia,pull = <0>;
-                               nvidia,tristate = <0>;
-                       };
-                       conf_ate {
-                               nvidia,pins = "ate", "csus", "dap3", "ddc",
-                                       "gpv", "owc", "slxc", "spib", "spid",
-                                       "spie";
-                               nvidia,pull = <0>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_ck32 {
-                               nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
-                                       "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
-                               nvidia,pull = <0>;
-                       };
-                       conf_crtp {
-                               nvidia,pins = "crtp", "gmb", "slxa", "spia",
-                                       "spig", "spih";
-                               nvidia,pull = <2>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_dta {
-                               nvidia,pins = "dta", "dtb", "dtc", "dtd";
-                               nvidia,pull = <1>;
-                               nvidia,tristate = <0>;
-                       };
-                       conf_dte {
-                               nvidia,pins = "dte", "spif";
-                               nvidia,pull = <1>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_hdint {
-                               nvidia,pins = "hdint", "lcsn", "ldc", "lm1",
-                                       "lpw1", "lsc1", "lsck", "lsda", "lsdi",
-                                       "lvp0";
-                               nvidia,tristate = <1>;
-                       };
-                       conf_kbca {
-                               nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
-                                       "kbce", "kbcf", "sdio1", "spic", "uaa",
-                                       "uab";
-                               nvidia,pull = <2>;
-                               nvidia,tristate = <0>;
-                       };
-                       conf_lc {
-                               nvidia,pins = "lc", "ls";
-                               nvidia,pull = <2>;
-                       };
-                       conf_ld0 {
-                               nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
-                                       "ld5", "ld6", "ld7", "ld8", "ld9",
-                                       "ld10", "ld11", "ld12", "ld13", "ld14",
-                                       "ld15", "ld16", "ld17", "ldi", "lhp0",
-                                       "lhp1", "lhp2", "lhs", "lm0", "lpp",
-                                       "lpw0", "lpw2", "lsc0", "lspi", "lvp1",
-                                       "lvs", "pmc", "sdb";
-                               nvidia,tristate = <0>;
-                       };
-                       conf_ld17_0 {
-                               nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
-                                       "ld23_22";
-                               nvidia,pull = <1>;
-                       };
-                       drive_sdio1 {
-                               nvidia,pins = "drive_sdio1";
-                               nvidia,high-speed-mode = <0>;
-                               nvidia,schmitt = <0>;
-                               nvidia,low-power-mode = <3>;
-                               nvidia,pull-down-strength = <31>;
-                               nvidia,pull-up-strength = <31>;
-                               nvidia,slew-rate-rising = <3>;
-                               nvidia,slew-rate-falling = <3>;
-                       };
-               };
-       };
-
-       i2s@70002800 {
-               status = "okay";
-       };
-
-       serial@70006300 {
-               status = "okay";
-               clock-frequency = <216000000>;
-       };
-
-       i2c@7000c000 {
-               status = "okay";
-               clock-frequency = <400000>;
-
-               wm8903: wm8903@1a {
-                       compatible = "wlf,wm8903";
-                       reg = <0x1a>;
-                       interrupt-parent = <&gpio>;
-                       interrupts = <187 0x04>;
-
-                       gpio-controller;
-                       #gpio-cells = <2>;
-
-                       micdet-cfg = <0>;
-                       micdet-delay = <100>;
-                       gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>;
-               };
-
-               /* ALS and proximity sensor */
-               isl29018@44 {
-                       compatible = "isil,isl29018";
-                       reg = <0x44>;
-                       interrupt-parent = <&gpio>;
-                       interrupts = <202 0x04>; /* GPIO PZ2 */
-               };
-
-               gyrometer@68 {
-                       compatible = "invn,mpu3050";
-                       reg = <0x68>;
-                       interrupt-parent = <&gpio>;
-                       interrupts = <204 0x04>; /* gpio PZ4 */
-               };
-       };
-
-       i2c@7000c400 {
-               status = "okay";
-               clock-frequency = <100000>;
-
-               smart-battery@b {
-                       compatible = "ti,bq20z75", "smart-battery-1.1";
-                       reg = <0xb>;
-                       ti,i2c-retry-count = <2>;
-                       ti,poll-retry-count = <10>;
-               };
-       };
-
-       i2c@7000c500 {
-               status = "okay";
-               clock-frequency = <400000>;
-       };
-
-       i2c@7000d000 {
-               status = "okay";
-               clock-frequency = <400000>;
-
-               temperature-sensor@4c {
-                       compatible = "nct1008";
-                       reg = <0x4c>;
-               };
-
-               magnetometer@c {
-                       compatible = "ak8975";
-                       reg = <0xc>;
-                       interrupt-parent = <&gpio>;
-                       interrupts = <109 0x04>; /* gpio PN5 */
-               };
-       };
-
-       emc {
-               emc-table@190000 {
-                       reg = <190000>;
-                       compatible = "nvidia,tegra20-emc-table";
-                       clock-frequency = <190000>;
-                       nvidia,emc-registers = <0x0000000c 0x00000026
-                               0x00000009 0x00000003 0x00000004 0x00000004
-                               0x00000002 0x0000000c 0x00000003 0x00000003
-                               0x00000002 0x00000001 0x00000004 0x00000005
-                               0x00000004 0x00000009 0x0000000d 0x0000059f
-                               0x00000000 0x00000003 0x00000003 0x00000003
-                               0x00000003 0x00000001 0x0000000b 0x000000c8
-                               0x00000003 0x00000007 0x00000004 0x0000000f
-                               0x00000002 0x00000000 0x00000000 0x00000002
-                               0x00000000 0x00000000 0x00000083 0xa06204ae
-                               0x007dc010 0x00000000 0x00000000 0x00000000
-                               0x00000000 0x00000000 0x00000000 0x00000000>;
-               };
-
-               emc-table@380000 {
-                       reg = <380000>;
-                       compatible = "nvidia,tegra20-emc-table";
-                       clock-frequency = <380000>;
-                       nvidia,emc-registers = <0x00000017 0x0000004b
-                               0x00000012 0x00000006 0x00000004 0x00000005
-                               0x00000003 0x0000000c 0x00000006 0x00000006
-                               0x00000003 0x00000001 0x00000004 0x00000005
-                               0x00000004 0x00000009 0x0000000d 0x00000b5f
-                               0x00000000 0x00000003 0x00000003 0x00000006
-                               0x00000006 0x00000001 0x00000011 0x000000c8
-                               0x00000003 0x0000000e 0x00000007 0x0000000f
-                               0x00000002 0x00000000 0x00000000 0x00000002
-                               0x00000000 0x00000000 0x00000083 0xe044048b
-                               0x007d8010 0x00000000 0x00000000 0x00000000
-                               0x00000000 0x00000000 0x00000000 0x00000000>;
-               };
-       };
-
-       usb@c5000000 {
-               status = "okay";
-               nvidia,vbus-gpio = <&gpio 24 0>; /* PD0 */
-               dr_mode = "otg";
-       };
-
-       usb@c5004000 {
-               status = "okay";
-               nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
-       };
-
-       usb@c5008000 {
-               status = "okay";
-       };
-
-       sdhci@c8000400 {
-               status = "okay";
-               cd-gpios = <&gpio 69 0>; /* gpio PI5 */
-               wp-gpios = <&gpio 57 0>; /* gpio PH1 */
-               power-gpios = <&gpio 70 0>; /* gpio PI6 */
-               bus-width = <4>;
-       };
-
-       sdhci@c8000600 {
-               status = "okay";
-               support-8bit;
-               bus-width = <8>;
-       };
-
-       gpio-keys {
-               compatible = "gpio-keys";
-
-               power {
-                       label = "Power";
-                       gpios = <&gpio 170 1>; /* gpio PV2, active low */
-                       linux,code = <116>; /* KEY_POWER */
-                       gpio-key,wakeup;
-               };
-
-               lid {
-                       label = "Lid";
-                       gpios = <&gpio 23 0>; /* gpio PC7 */
-                       linux,input-type = <5>; /* EV_SW */
-                       linux,code = <0>; /* SW_LID */
-                       debounce-interval = <1>;
-                       gpio-key,wakeup;
-               };
-       };
-
-       sound {
-               compatible = "nvidia,tegra-audio-wm8903-seaboard",
-                            "nvidia,tegra-audio-wm8903";
-               nvidia,model = "NVIDIA Tegra Seaboard";
-
-               nvidia,audio-routing =
-                       "Headphone Jack", "HPOUTR",
-                       "Headphone Jack", "HPOUTL",
-                       "Int Spk", "ROP",
-                       "Int Spk", "RON",
-                       "Int Spk", "LOP",
-                       "Int Spk", "LON",
-                       "Mic Jack", "MICBIAS",
-                       "IN1R", "Mic Jack";
-
-               nvidia,i2s-controller = <&tegra_i2s1>;
-               nvidia,audio-codec = <&wm8903>;
-
-               nvidia,spkr-en-gpios = <&wm8903 2 0>;
-               nvidia,hp-det-gpios = <&gpio 185 0>; /* gpio PX1 */
-       };
-};
diff --git a/arch/arm/boot/dts/tegra-trimslice.dts b/arch/arm/boot/dts/tegra-trimslice.dts
deleted file mode 100644 (file)
index 9de5636..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/dts-v1/;
-
-/include/ "tegra20.dtsi"
-
-/ {
-       model = "Compulab TrimSlice board";
-       compatible = "compulab,trimslice", "nvidia,tegra20";
-
-       memory {
-               reg = <0x00000000 0x40000000>;
-       };
-
-       pinmux {
-               pinctrl-names = "default";
-               pinctrl-0 = <&state_default>;
-
-               state_default: pinmux {
-                       ata {
-                               nvidia,pins = "ata";
-                               nvidia,function = "ide";
-                       };
-                       atb {
-                               nvidia,pins = "atb", "gma";
-                               nvidia,function = "sdio4";
-                       };
-                       atc {
-                               nvidia,pins = "atc", "gmb";
-                               nvidia,function = "nand";
-                       };
-                       atd {
-                               nvidia,pins = "atd", "ate", "gme", "pta";
-                               nvidia,function = "gmi";
-                       };
-                       cdev1 {
-                               nvidia,pins = "cdev1";
-                               nvidia,function = "plla_out";
-                       };
-                       cdev2 {
-                               nvidia,pins = "cdev2";
-                               nvidia,function = "pllp_out4";
-                       };
-                       crtp {
-                               nvidia,pins = "crtp";
-                               nvidia,function = "crt";
-                       };
-                       csus {
-                               nvidia,pins = "csus";
-                               nvidia,function = "vi_sensor_clk";
-                       };
-                       dap1 {
-                               nvidia,pins = "dap1";
-                               nvidia,function = "dap1";
-                       };
-                       dap2 {
-                               nvidia,pins = "dap2";
-                               nvidia,function = "dap2";
-                       };
-                       dap3 {
-                               nvidia,pins = "dap3";
-                               nvidia,function = "dap3";
-                       };
-                       dap4 {
-                               nvidia,pins = "dap4";
-                               nvidia,function = "dap4";
-                       };
-                       ddc {
-                               nvidia,pins = "ddc";
-                               nvidia,function = "i2c2";
-                       };
-                       dta {
-                               nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
-                               nvidia,function = "vi";
-                       };
-                       dtf {
-                               nvidia,pins = "dtf";
-                               nvidia,function = "i2c3";
-                       };
-                       gmc {
-                               nvidia,pins = "gmc", "gmd";
-                               nvidia,function = "sflash";
-                       };
-                       gpu {
-                               nvidia,pins = "gpu";
-                               nvidia,function = "uarta";
-                       };
-                       gpu7 {
-                               nvidia,pins = "gpu7";
-                               nvidia,function = "rtck";
-                       };
-                       gpv {
-                               nvidia,pins = "gpv", "slxa", "slxk";
-                               nvidia,function = "pcie";
-                       };
-                       hdint {
-                               nvidia,pins = "hdint";
-                               nvidia,function = "hdmi";
-                       };
-                       i2cp {
-                               nvidia,pins = "i2cp";
-                               nvidia,function = "i2cp";
-                       };
-                       irrx {
-                               nvidia,pins = "irrx", "irtx";
-                               nvidia,function = "uartb";
-                       };
-                       kbca {
-                               nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
-                                       "kbce", "kbcf";
-                               nvidia,function = "kbc";
-                       };
-                       lcsn {
-                               nvidia,pins = "lcsn", "ld0", "ld1", "ld2",
-                                       "ld3", "ld4", "ld5", "ld6", "ld7",
-                                       "ld8", "ld9", "ld10", "ld11", "ld12",
-                                       "ld13", "ld14", "ld15", "ld16", "ld17",
-                                       "ldc", "ldi", "lhp0", "lhp1", "lhp2",
-                                       "lhs", "lm0", "lm1", "lpp", "lpw0",
-                                       "lpw1", "lpw2", "lsc0", "lsc1", "lsck",
-                                       "lsda", "lsdi", "lspi", "lvp0", "lvp1",
-                                       "lvs";
-                               nvidia,function = "displaya";
-                       };
-                       owc {
-                               nvidia,pins = "owc", "uac";
-                               nvidia,function = "rsvd2";
-                       };
-                       pmc {
-                               nvidia,pins = "pmc";
-                               nvidia,function = "pwr_on";
-                       };
-                       rm {
-                               nvidia,pins = "rm";
-                               nvidia,function = "i2c1";
-                       };
-                       sdb {
-                               nvidia,pins = "sdb", "sdc", "sdd";
-                               nvidia,function = "pwm";
-                       };
-                       sdio1 {
-                               nvidia,pins = "sdio1";
-                               nvidia,function = "sdio1";
-                       };
-                       slxc {
-                               nvidia,pins = "slxc", "slxd";
-                               nvidia,function = "sdio3";
-                       };
-                       spdi {
-                               nvidia,pins = "spdi", "spdo";
-                               nvidia,function = "spdif";
-                       };
-                       spia {
-                               nvidia,pins = "spia", "spib", "spic";
-                               nvidia,function = "spi2";
-                       };
-                       spid {
-                               nvidia,pins = "spid", "spie", "spif";
-                               nvidia,function = "spi1";
-                       };
-                       spig {
-                               nvidia,pins = "spig", "spih";
-                               nvidia,function = "spi2_alt";
-                       };
-                       uaa {
-                               nvidia,pins = "uaa", "uab", "uda";
-                               nvidia,function = "ulpi";
-                       };
-                       uad {
-                               nvidia,pins = "uad";
-                               nvidia,function = "irda";
-                       };
-                       uca {
-                               nvidia,pins = "uca", "ucb";
-                               nvidia,function = "uartc";
-                       };
-                       conf_ata {
-                               nvidia,pins = "ata", "atc", "atd", "ate",
-                                       "crtp", "dap2", "dap3", "dap4", "dta",
-                                       "dtb", "dtc", "dtd", "dte", "gmb",
-                                       "gme", "i2cp", "pta", "slxc", "slxd",
-                                       "spdi", "spdo", "uda";
-                               nvidia,pull = <0>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_atb {
-                               nvidia,pins = "atb", "cdev1", "cdev2", "dap1",
-                                       "gma", "gmc", "gmd", "gpu", "gpu7",
-                                       "gpv", "sdio1", "slxa", "slxk", "uac";
-                               nvidia,pull = <0>;
-                               nvidia,tristate = <0>;
-                       };
-                       conf_ck32 {
-                               nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
-                                       "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
-                               nvidia,pull = <0>;
-                       };
-                       conf_csus {
-                               nvidia,pins = "csus", "spia", "spib",
-                                       "spid", "spif";
-                               nvidia,pull = <1>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_ddc {
-                               nvidia,pins = "ddc", "dtf", "rm", "sdc", "sdd";
-                               nvidia,pull = <2>;
-                               nvidia,tristate = <0>;
-                       };
-                       conf_hdint {
-                               nvidia,pins = "hdint", "lcsn", "ldc", "lm1",
-                                       "lpw1", "lsc1", "lsck", "lsda", "lsdi",
-                                       "lvp0", "pmc";
-                               nvidia,tristate = <1>;
-                       };
-                       conf_irrx {
-                               nvidia,pins = "irrx", "irtx", "kbca", "kbcb",
-                                       "kbcc", "kbcd", "kbce", "kbcf", "owc",
-                                       "spic", "spie", "spig", "spih", "uaa",
-                                       "uab", "uad", "uca", "ucb";
-                               nvidia,pull = <2>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_lc {
-                               nvidia,pins = "lc", "ls";
-                               nvidia,pull = <2>;
-                       };
-                       conf_ld0 {
-                               nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
-                                       "ld5", "ld6", "ld7", "ld8", "ld9",
-                                       "ld10", "ld11", "ld12", "ld13", "ld14",
-                                       "ld15", "ld16", "ld17", "ldi", "lhp0",
-                                       "lhp1", "lhp2", "lhs", "lm0", "lpp",
-                                       "lpw0", "lpw2", "lsc0", "lspi", "lvp1",
-                                       "lvs", "sdb";
-                               nvidia,tristate = <0>;
-                       };
-                       conf_ld17_0 {
-                               nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
-                                       "ld23_22";
-                               nvidia,pull = <1>;
-                       };
-               };
-       };
-
-       i2s@70002800 {
-               status = "okay";
-       };
-
-       serial@70006000 {
-               status = "okay";
-               clock-frequency = <216000000>;
-       };
-
-       i2c@7000c000 {
-               status = "okay";
-               clock-frequency = <400000>;
-       };
-
-       i2c@7000c400 {
-               status = "okay";
-               clock-frequency = <400000>;
-       };
-
-       i2c@7000c500 {
-               status = "okay";
-               clock-frequency = <400000>;
-
-               codec: codec@1a {
-                       compatible = "ti,tlv320aic23";
-                       reg = <0x1a>;
-               };
-
-               rtc@56 {
-                       compatible = "emmicro,em3027";
-                       reg = <0x56>;
-               };
-       };
-
-       usb@c5000000 {
-               status = "okay";
-       };
-
-       usb@c5004000 {
-               nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
-       };
-
-       usb@c5008000 {
-               status = "okay";
-       };
-
-       sdhci@c8000000 {
-               status = "okay";
-               bus-width = <4>;
-       };
-
-       sdhci@c8000600 {
-               status = "okay";
-               cd-gpios = <&gpio 121 0>; /* gpio PP1 */
-               wp-gpios = <&gpio 122 0>; /* gpio PP2 */
-               bus-width = <4>;
-       };
-
-       sound {
-               compatible = "nvidia,tegra-audio-trimslice";
-               nvidia,i2s-controller = <&tegra_i2s1>;
-               nvidia,audio-codec = <&codec>;
-       };
-};
diff --git a/arch/arm/boot/dts/tegra-ventana.dts b/arch/arm/boot/dts/tegra-ventana.dts
deleted file mode 100644 (file)
index 445343b..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-/dts-v1/;
-
-/include/ "tegra20.dtsi"
-
-/ {
-       model = "NVIDIA Tegra2 Ventana evaluation board";
-       compatible = "nvidia,ventana", "nvidia,tegra20";
-
-       memory {
-               reg = <0x00000000 0x40000000>;
-       };
-
-       pinmux {
-               pinctrl-names = "default";
-               pinctrl-0 = <&state_default>;
-
-               state_default: pinmux {
-                       ata {
-                               nvidia,pins = "ata";
-                               nvidia,function = "ide";
-                       };
-                       atb {
-                               nvidia,pins = "atb", "gma", "gme";
-                               nvidia,function = "sdio4";
-                       };
-                       atc {
-                               nvidia,pins = "atc";
-                               nvidia,function = "nand";
-                       };
-                       atd {
-                               nvidia,pins = "atd", "ate", "gmb", "spia",
-                                       "spib", "spic";
-                               nvidia,function = "gmi";
-                       };
-                       cdev1 {
-                               nvidia,pins = "cdev1";
-                               nvidia,function = "plla_out";
-                       };
-                       cdev2 {
-                               nvidia,pins = "cdev2";
-                               nvidia,function = "pllp_out4";
-                       };
-                       crtp {
-                               nvidia,pins = "crtp", "lm1";
-                               nvidia,function = "crt";
-                       };
-                       csus {
-                               nvidia,pins = "csus";
-                               nvidia,function = "vi_sensor_clk";
-                       };
-                       dap1 {
-                               nvidia,pins = "dap1";
-                               nvidia,function = "dap1";
-                       };
-                       dap2 {
-                               nvidia,pins = "dap2";
-                               nvidia,function = "dap2";
-                       };
-                       dap3 {
-                               nvidia,pins = "dap3";
-                               nvidia,function = "dap3";
-                       };
-                       dap4 {
-                               nvidia,pins = "dap4";
-                               nvidia,function = "dap4";
-                       };
-                       ddc {
-                               nvidia,pins = "ddc", "owc", "spdi", "spdo",
-                                       "uac";
-                               nvidia,function = "rsvd2";
-                       };
-                       dta {
-                               nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
-                               nvidia,function = "vi";
-                       };
-                       dtf {
-                               nvidia,pins = "dtf";
-                               nvidia,function = "i2c3";
-                       };
-                       gmc {
-                               nvidia,pins = "gmc";
-                               nvidia,function = "uartd";
-                       };
-                       gmd {
-                               nvidia,pins = "gmd";
-                               nvidia,function = "sflash";
-                       };
-                       gpu {
-                               nvidia,pins = "gpu";
-                               nvidia,function = "pwm";
-                       };
-                       gpu7 {
-                               nvidia,pins = "gpu7";
-                               nvidia,function = "rtck";
-                       };
-                       gpv {
-                               nvidia,pins = "gpv", "slxa", "slxk";
-                               nvidia,function = "pcie";
-                       };
-                       hdint {
-                               nvidia,pins = "hdint", "pta";
-                               nvidia,function = "hdmi";
-                       };
-                       i2cp {
-                               nvidia,pins = "i2cp";
-                               nvidia,function = "i2cp";
-                       };
-                       irrx {
-                               nvidia,pins = "irrx", "irtx";
-                               nvidia,function = "uartb";
-                       };
-                       kbca {
-                               nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
-                                       "kbce", "kbcf";
-                               nvidia,function = "kbc";
-                       };
-                       lcsn {
-                               nvidia,pins = "lcsn", "ldc", "lm0", "lpw1",
-                                       "lsdi", "lvp0";
-                               nvidia,function = "rsvd4";
-                       };
-                       ld0 {
-                               nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
-                                       "ld5", "ld6", "ld7", "ld8", "ld9",
-                                       "ld10", "ld11", "ld12", "ld13", "ld14",
-                                       "ld15", "ld16", "ld17", "ldi", "lhp0",
-                                       "lhp1", "lhp2", "lhs", "lpp", "lpw0",
-                                       "lpw2", "lsc0", "lsc1", "lsck", "lsda",
-                                       "lspi", "lvp1", "lvs";
-                               nvidia,function = "displaya";
-                       };
-                       pmc {
-                               nvidia,pins = "pmc";
-                               nvidia,function = "pwr_on";
-                       };
-                       rm {
-                               nvidia,pins = "rm";
-                               nvidia,function = "i2c1";
-                       };
-                       sdb {
-                               nvidia,pins = "sdb", "sdc", "sdd", "slxc";
-                               nvidia,function = "sdio3";
-                       };
-                       sdio1 {
-                               nvidia,pins = "sdio1";
-                               nvidia,function = "sdio1";
-                       };
-                       slxd {
-                               nvidia,pins = "slxd";
-                               nvidia,function = "spdif";
-                       };
-                       spid {
-                               nvidia,pins = "spid", "spie", "spif";
-                               nvidia,function = "spi1";
-                       };
-                       spig {
-                               nvidia,pins = "spig", "spih";
-                               nvidia,function = "spi2_alt";
-                       };
-                       uaa {
-                               nvidia,pins = "uaa", "uab", "uda";
-                               nvidia,function = "ulpi";
-                       };
-                       uad {
-                               nvidia,pins = "uad";
-                               nvidia,function = "irda";
-                       };
-                       uca {
-                               nvidia,pins = "uca", "ucb";
-                               nvidia,function = "uartc";
-                       };
-                       conf_ata {
-                               nvidia,pins = "ata", "atb", "atc", "atd",
-                                       "cdev1", "cdev2", "dap1", "dap2",
-                                       "dap4", "ddc", "dtf", "gma", "gmc",
-                                       "gme", "gpu", "gpu7", "i2cp", "irrx",
-                                       "irtx", "pta", "rm", "sdc", "sdd",
-                                       "slxc", "slxd", "slxk", "spdi", "spdo",
-                                       "uac", "uad", "uca", "ucb", "uda";
-                               nvidia,pull = <0>;
-                               nvidia,tristate = <0>;
-                       };
-                       conf_ate {
-                               nvidia,pins = "ate", "csus", "dap3", "gmd",
-                                       "gpv", "owc", "spia", "spib", "spic",
-                                       "spid", "spie", "spig";
-                               nvidia,pull = <0>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_ck32 {
-                               nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
-                                       "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
-                               nvidia,pull = <0>;
-                       };
-                       conf_crtp {
-                               nvidia,pins = "crtp", "gmb", "slxa", "spih";
-                               nvidia,pull = <2>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_dta {
-                               nvidia,pins = "dta", "dtb", "dtc", "dtd";
-                               nvidia,pull = <1>;
-                               nvidia,tristate = <0>;
-                       };
-                       conf_dte {
-                               nvidia,pins = "dte", "spif";
-                               nvidia,pull = <1>;
-                               nvidia,tristate = <1>;
-                       };
-                       conf_hdint {
-                               nvidia,pins = "hdint", "lcsn", "ldc", "lm1",
-                                       "lpw1", "lsck", "lsda", "lsdi", "lvp0";
-                               nvidia,tristate = <1>;
-                       };
-                       conf_kbca {
-                               nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
-                                       "kbce", "kbcf", "sdio1", "uaa", "uab";
-                               nvidia,pull = <2>;
-                               nvidia,tristate = <0>;
-                       };
-                       conf_lc {
-                               nvidia,pins = "lc", "ls";
-                               nvidia,pull = <2>;
-                       };
-                       conf_ld0 {
-                               nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
-                                       "ld5", "ld6", "ld7", "ld8", "ld9",
-                                       "ld10", "ld11", "ld12", "ld13", "ld14",
-                                       "ld15", "ld16", "ld17", "ldi", "lhp0",
-                                       "lhp1", "lhp2", "lhs", "lm0", "lpp",
-                                       "lpw0", "lpw2", "lsc0", "lsc1", "lspi",
-                                       "lvp1", "lvs", "pmc", "sdb";
-                               nvidia,tristate = <0>;
-                       };
-                       conf_ld17_0 {
-                               nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
-                                       "ld23_22";
-                               nvidia,pull = <1>;
-                       };
-               };
-       };
-
-       i2s@70002800 {
-               status = "okay";
-       };
-
-       serial@70006300 {
-               status = "okay";
-               clock-frequency = <216000000>;
-       };
-
-       i2c@7000c000 {
-               status = "okay";
-               clock-frequency = <400000>;
-
-               wm8903: wm8903@1a {
-                       compatible = "wlf,wm8903";
-                       reg = <0x1a>;
-                       interrupt-parent = <&gpio>;
-                       interrupts = <187 0x04>;
-
-                       gpio-controller;
-                       #gpio-cells = <2>;
-
-                       micdet-cfg = <0>;
-                       micdet-delay = <100>;
-                       gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>;
-               };
-
-               /* ALS and proximity sensor */
-               isl29018@44 {
-                       compatible = "isil,isl29018";
-                       reg = <0x44>;
-                       interrupt-parent = <&gpio>;
-                       interrupts = <202 0x04>; /*gpio PZ2 */
-               };
-       };
-
-       i2c@7000c400 {
-               status = "okay";
-               clock-frequency = <400000>;
-       };
-
-       i2c@7000c500 {
-               status = "okay";
-               clock-frequency = <400000>;
-       };
-
-       i2c@7000d000 {
-               status = "okay";
-               clock-frequency = <400000>;
-       };
-
-       usb@c5000000 {
-               status = "okay";
-       };
-
-       usb@c5004000 {
-               status = "okay";
-               nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
-       };
-
-       usb@c5008000 {
-               status = "okay";
-       };
-
-       sdhci@c8000400 {
-               status = "okay";
-               cd-gpios = <&gpio 69 0>; /* gpio PI5 */
-               wp-gpios = <&gpio 57 0>; /* gpio PH1 */
-               power-gpios = <&gpio 70 0>; /* gpio PI6 */
-               bus-width = <4>;
-       };
-
-       sdhci@c8000600 {
-               status = "okay";
-               support-8bit;
-               bus-width = <8>;
-       };
-
-       sound {
-               compatible = "nvidia,tegra-audio-wm8903-ventana",
-                            "nvidia,tegra-audio-wm8903";
-               nvidia,model = "NVIDIA Tegra Ventana";
-
-               nvidia,audio-routing =
-                       "Headphone Jack", "HPOUTR",
-                       "Headphone Jack", "HPOUTL",
-                       "Int Spk", "ROP",
-                       "Int Spk", "RON",
-                       "Int Spk", "LOP",
-                       "Int Spk", "LON",
-                       "Mic Jack", "MICBIAS",
-                       "IN1L", "Mic Jack";
-
-               nvidia,i2s-controller = <&tegra_i2s1>;
-               nvidia,audio-codec = <&wm8903>;
-
-               nvidia,spkr-en-gpios = <&wm8903 2 0>;
-               nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
-               nvidia,int-mic-en-gpios = <&gpio 184 0>; /* gpio PX0 */
-               nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
-       };
-};
diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts
new file mode 100644 (file)
index 0000000..f146dbf
--- /dev/null
@@ -0,0 +1,336 @@
+/dts-v1/;
+
+/include/ "tegra20.dtsi"
+
+/ {
+       model = "NVIDIA Tegra2 Harmony evaluation board";
+       compatible = "nvidia,harmony", "nvidia,tegra20";
+
+       memory {
+               reg = <0x00000000 0x40000000>;
+       };
+
+       pinmux {
+               pinctrl-names = "default";
+               pinctrl-0 = <&state_default>;
+
+               state_default: pinmux {
+                       ata {
+                               nvidia,pins = "ata";
+                               nvidia,function = "ide";
+                       };
+                       atb {
+                               nvidia,pins = "atb", "gma", "gme";
+                               nvidia,function = "sdio4";
+                       };
+                       atc {
+                               nvidia,pins = "atc";
+                               nvidia,function = "nand";
+                       };
+                       atd {
+                               nvidia,pins = "atd", "ate", "gmb", "gmd", "gpu",
+                                       "spia", "spib", "spic";
+                               nvidia,function = "gmi";
+                       };
+                       cdev1 {
+                               nvidia,pins = "cdev1";
+                               nvidia,function = "plla_out";
+                       };
+                       cdev2 {
+                               nvidia,pins = "cdev2";
+                               nvidia,function = "pllp_out4";
+                       };
+                       crtp {
+                               nvidia,pins = "crtp";
+                               nvidia,function = "crt";
+                       };
+                       csus {
+                               nvidia,pins = "csus";
+                               nvidia,function = "vi_sensor_clk";
+                       };
+                       dap1 {
+                               nvidia,pins = "dap1";
+                               nvidia,function = "dap1";
+                       };
+                       dap2 {
+                               nvidia,pins = "dap2";
+                               nvidia,function = "dap2";
+                       };
+                       dap3 {
+                               nvidia,pins = "dap3";
+                               nvidia,function = "dap3";
+                       };
+                       dap4 {
+                               nvidia,pins = "dap4";
+                               nvidia,function = "dap4";
+                       };
+                       ddc {
+                               nvidia,pins = "ddc";
+                               nvidia,function = "i2c2";
+                       };
+                       dta {
+                               nvidia,pins = "dta", "dtd";
+                               nvidia,function = "sdio2";
+                       };
+                       dtb {
+                               nvidia,pins = "dtb", "dtc", "dte";
+                               nvidia,function = "rsvd1";
+                       };
+                       dtf {
+                               nvidia,pins = "dtf";
+                               nvidia,function = "i2c3";
+                       };
+                       gmc {
+                               nvidia,pins = "gmc";
+                               nvidia,function = "uartd";
+                       };
+                       gpu7 {
+                               nvidia,pins = "gpu7";
+                               nvidia,function = "rtck";
+                       };
+                       gpv {
+                               nvidia,pins = "gpv", "slxa", "slxk";
+                               nvidia,function = "pcie";
+                       };
+                       hdint {
+                               nvidia,pins = "hdint", "pta";
+                               nvidia,function = "hdmi";
+                       };
+                       i2cp {
+                               nvidia,pins = "i2cp";
+                               nvidia,function = "i2cp";
+                       };
+                       irrx {
+                               nvidia,pins = "irrx", "irtx";
+                               nvidia,function = "uarta";
+                       };
+                       kbca {
+                               nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
+                                       "kbce", "kbcf";
+                               nvidia,function = "kbc";
+                       };
+                       lcsn {
+                               nvidia,pins = "lcsn", "ld0", "ld1", "ld2",
+                                       "ld3", "ld4", "ld5", "ld6", "ld7",
+                                       "ld8", "ld9", "ld10", "ld11", "ld12",
+                                       "ld13", "ld14", "ld15", "ld16", "ld17",
+                                       "ldc", "ldi", "lhp0", "lhp1", "lhp2",
+                                       "lhs", "lm0", "lm1", "lpp", "lpw0",
+                                       "lpw1", "lpw2", "lsc0", "lsc1", "lsck",
+                                       "lsda", "lsdi", "lspi", "lvp0", "lvp1",
+                                       "lvs";
+                               nvidia,function = "displaya";
+                       };
+                       owc {
+                               nvidia,pins = "owc", "spdi", "spdo", "uac";
+                               nvidia,function = "rsvd2";
+                       };
+                       pmc {
+                               nvidia,pins = "pmc";
+                               nvidia,function = "pwr_on";
+                       };
+                       rm {
+                               nvidia,pins = "rm";
+                               nvidia,function = "i2c1";
+                       };
+                       sdb {
+                               nvidia,pins = "sdb", "sdc", "sdd";
+                               nvidia,function = "pwm";
+                       };
+                       sdio1 {
+                               nvidia,pins = "sdio1";
+                               nvidia,function = "sdio1";
+                       };
+                       slxc {
+                               nvidia,pins = "slxc", "slxd";
+                               nvidia,function = "spdif";
+                       };
+                       spid {
+                               nvidia,pins = "spid", "spie", "spif";
+                               nvidia,function = "spi1";
+                       };
+                       spig {
+                               nvidia,pins = "spig", "spih";
+                               nvidia,function = "spi2_alt";
+                       };
+                       uaa {
+                               nvidia,pins = "uaa", "uab", "uda";
+                               nvidia,function = "ulpi";
+                       };
+                       uad {
+                               nvidia,pins = "uad";
+                               nvidia,function = "irda";
+                       };
+                       uca {
+                               nvidia,pins = "uca", "ucb";
+                               nvidia,function = "uartc";
+                       };
+                       conf_ata {
+                               nvidia,pins = "ata", "atb", "atc", "atd", "ate",
+                                       "cdev1", "cdev2", "dap1", "dtb", "gma",
+                                       "gmb", "gmc", "gmd", "gme", "gpu7",
+                                       "gpv", "i2cp", "pta", "rm", "slxa",
+                                       "slxk", "spia", "spib", "uac";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_ck32 {
+                               nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
+                                       "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
+                               nvidia,pull = <0>;
+                       };
+                       conf_csus {
+                               nvidia,pins = "csus", "spid", "spif";
+                               nvidia,pull = <1>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_crtp {
+                               nvidia,pins = "crtp", "dap2", "dap3", "dap4",
+                                       "dtc", "dte", "dtf", "gpu", "sdio1",
+                                       "slxc", "slxd", "spdi", "spdo", "spig",
+                                       "uda";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_ddc {
+                               nvidia,pins = "ddc", "dta", "dtd", "kbca",
+                                       "kbcb", "kbcc", "kbcd", "kbce", "kbcf",
+                                       "sdc";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_hdint {
+                               nvidia,pins = "hdint", "lcsn", "ldc", "lm1",
+                                       "lpw1", "lsc1", "lsck", "lsda", "lsdi",
+                                       "lvp0", "owc", "sdb";
+                               nvidia,tristate = <1>;
+                       };
+                       conf_irrx {
+                               nvidia,pins = "irrx", "irtx", "sdd", "spic",
+                                       "spie", "spih", "uaa", "uab", "uad",
+                                       "uca", "ucb";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_lc {
+                               nvidia,pins = "lc", "ls";
+                               nvidia,pull = <2>;
+                       };
+                       conf_ld0 {
+                               nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+                                       "ld5", "ld6", "ld7", "ld8", "ld9",
+                                       "ld10", "ld11", "ld12", "ld13", "ld14",
+                                       "ld15", "ld16", "ld17", "ldi", "lhp0",
+                                       "lhp1", "lhp2", "lhs", "lm0", "lpp",
+                                       "lpw0", "lpw2", "lsc0", "lspi", "lvp1",
+                                       "lvs", "pmc";
+                               nvidia,tristate = <0>;
+                       };
+                       conf_ld17_0 {
+                               nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
+                                       "ld23_22";
+                               nvidia,pull = <1>;
+                       };
+               };
+       };
+
+       i2s@70002800 {
+               status = "okay";
+       };
+
+       serial@70006300 {
+               status = "okay";
+               clock-frequency = <216000000>;
+       };
+
+       i2c@7000c000 {
+               status = "okay";
+               clock-frequency = <400000>;
+
+               wm8903: wm8903@1a {
+                       compatible = "wlf,wm8903";
+                       reg = <0x1a>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <187 0x04>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       micdet-cfg = <0>;
+                       micdet-delay = <100>;
+                       gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>;
+               };
+       };
+
+       i2c@7000c400 {
+               status = "okay";
+               clock-frequency = <400000>;
+       };
+
+       i2c@7000c500 {
+               status = "okay";
+               clock-frequency = <400000>;
+       };
+
+       i2c@7000d000 {
+               status = "okay";
+               clock-frequency = <400000>;
+       };
+
+       pmc {
+               nvidia,invert-interrupt;
+       };
+
+       usb@c5000000 {
+               status = "okay";
+       };
+
+       usb@c5004000 {
+               status = "okay";
+               nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+       };
+
+       usb@c5008000 {
+               status = "okay";
+       };
+
+       sdhci@c8000200 {
+               status = "okay";
+               cd-gpios = <&gpio 69 0>; /* 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 */
+               wp-gpios = <&gpio 59 0>; /* gpio PH3 */
+               power-gpios = <&gpio 70 0>; /* gpio PI6 */
+               bus-width = <8>;
+       };
+
+       sound {
+               compatible = "nvidia,tegra-audio-wm8903-harmony",
+                            "nvidia,tegra-audio-wm8903";
+               nvidia,model = "NVIDIA Tegra Harmony";
+
+               nvidia,audio-routing =
+                       "Headphone Jack", "HPOUTR",
+                       "Headphone Jack", "HPOUTL",
+                       "Int Spk", "ROP",
+                       "Int Spk", "RON",
+                       "Int Spk", "LOP",
+                       "Int Spk", "LON",
+                       "Mic Jack", "MICBIAS",
+                       "IN1L", "Mic Jack";
+
+               nvidia,i2s-controller = <&tegra_i2s1>;
+               nvidia,audio-codec = <&wm8903>;
+
+               nvidia,spkr-en-gpios = <&wm8903 2 0>;
+               nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+               nvidia,int-mic-en-gpios = <&gpio 184 0>; /*gpio PX0 */
+               nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
+       };
+};
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts
new file mode 100644 (file)
index 0000000..684a9e1
--- /dev/null
@@ -0,0 +1,347 @@
+/dts-v1/;
+
+/include/ "tegra20.dtsi"
+
+/ {
+       model = "Toshiba AC100 / Dynabook AZ";
+       compatible = "compal,paz00", "nvidia,tegra20";
+
+       memory {
+               reg = <0x00000000 0x20000000>;
+       };
+
+       pinmux {
+               pinctrl-names = "default";
+               pinctrl-0 = <&state_default>;
+
+               state_default: pinmux {
+                       ata {
+                               nvidia,pins = "ata", "atc", "atd", "ate",
+                                       "dap2", "gmb", "gmc", "gmd", "spia",
+                                       "spib", "spic", "spid", "spie";
+                               nvidia,function = "gmi";
+                       };
+                       atb {
+                               nvidia,pins = "atb", "gma", "gme";
+                               nvidia,function = "sdio4";
+                       };
+                       cdev1 {
+                               nvidia,pins = "cdev1";
+                               nvidia,function = "plla_out";
+                       };
+                       cdev2 {
+                               nvidia,pins = "cdev2";
+                               nvidia,function = "pllp_out4";
+                       };
+                       crtp {
+                               nvidia,pins = "crtp";
+                               nvidia,function = "crt";
+                       };
+                       csus {
+                               nvidia,pins = "csus";
+                               nvidia,function = "pllc_out1";
+                       };
+                       dap1 {
+                               nvidia,pins = "dap1";
+                               nvidia,function = "dap1";
+                       };
+                       dap3 {
+                               nvidia,pins = "dap3";
+                               nvidia,function = "dap3";
+                       };
+                       dap4 {
+                               nvidia,pins = "dap4";
+                               nvidia,function = "dap4";
+                       };
+                       ddc {
+                               nvidia,pins = "ddc";
+                               nvidia,function = "i2c2";
+                       };
+                       dta {
+                               nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
+                               nvidia,function = "rsvd1";
+                       };
+                       dtf {
+                               nvidia,pins = "dtf";
+                               nvidia,function = "i2c3";
+                       };
+                       gpu {
+                               nvidia,pins = "gpu", "sdb", "sdd";
+                               nvidia,function = "pwm";
+                       };
+                       gpu7 {
+                               nvidia,pins = "gpu7";
+                               nvidia,function = "rtck";
+                       };
+                       gpv {
+                               nvidia,pins = "gpv", "slxa", "slxk";
+                               nvidia,function = "pcie";
+                       };
+                       hdint {
+                               nvidia,pins = "hdint", "pta";
+                               nvidia,function = "hdmi";
+                       };
+                       i2cp {
+                               nvidia,pins = "i2cp";
+                               nvidia,function = "i2cp";
+                       };
+                       irrx {
+                               nvidia,pins = "irrx", "irtx";
+                               nvidia,function = "uarta";
+                       };
+                       kbca {
+                               nvidia,pins = "kbca", "kbcc", "kbce", "kbcf";
+                               nvidia,function = "kbc";
+                       };
+                       kbcb {
+                               nvidia,pins = "kbcb", "kbcd";
+                               nvidia,function = "sdio2";
+                       };
+                       lcsn {
+                               nvidia,pins = "lcsn", "ld0", "ld1", "ld2",
+                                       "ld3", "ld4", "ld5", "ld6", "ld7",
+                                       "ld8", "ld9", "ld10", "ld11", "ld12",
+                                       "ld13", "ld14", "ld15", "ld16", "ld17",
+                                       "ldc", "ldi", "lhp0", "lhp1", "lhp2",
+                                       "lhs", "lm0", "lm1", "lpp", "lpw0",
+                                       "lpw1", "lpw2", "lsc0", "lsc1", "lsck",
+                                       "lsda", "lsdi", "lspi", "lvp0", "lvp1",
+                                       "lvs";
+                               nvidia,function = "displaya";
+                       };
+                       owc {
+                               nvidia,pins = "owc";
+                               nvidia,function = "owr";
+                       };
+                       pmc {
+                               nvidia,pins = "pmc";
+                               nvidia,function = "pwr_on";
+                       };
+                       rm {
+                               nvidia,pins = "rm";
+                               nvidia,function = "i2c1";
+                       };
+                       sdc {
+                               nvidia,pins = "sdc";
+                               nvidia,function = "twc";
+                       };
+                       sdio1 {
+                               nvidia,pins = "sdio1";
+                               nvidia,function = "sdio1";
+                       };
+                       slxc {
+                               nvidia,pins = "slxc", "slxd";
+                               nvidia,function = "spi4";
+                       };
+                       spdi {
+                               nvidia,pins = "spdi", "spdo";
+                               nvidia,function = "rsvd2";
+                       };
+                       spif {
+                               nvidia,pins = "spif", "uac";
+                               nvidia,function = "rsvd4";
+                       };
+                       spig {
+                               nvidia,pins = "spig", "spih";
+                               nvidia,function = "spi2_alt";
+                       };
+                       uaa {
+                               nvidia,pins = "uaa", "uab", "uda";
+                               nvidia,function = "ulpi";
+                       };
+                       uad {
+                               nvidia,pins = "uad";
+                               nvidia,function = "spdif";
+                       };
+                       uca {
+                               nvidia,pins = "uca", "ucb";
+                               nvidia,function = "uartc";
+                       };
+                       conf_ata {
+                               nvidia,pins = "ata", "atb", "atc", "atd", "ate",
+                                       "cdev1", "cdev2", "dap1", "dap2", "dtf",
+                                       "gma", "gmb", "gmc", "gmd", "gme",
+                                       "gpu", "gpu7", "gpv", "i2cp", "pta",
+                                       "rm", "sdio1", "slxk", "spdo", "uac",
+                                       "uda";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_ck32 {
+                               nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
+                                       "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
+                               nvidia,pull = <0>;
+                       };
+                       conf_crtp {
+                               nvidia,pins = "crtp", "dap3", "dap4", "dtb",
+                                       "dtc", "dte", "slxa", "slxc", "slxd",
+                                       "spdi";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_csus {
+                               nvidia,pins = "csus", "spia", "spib", "spid",
+                                       "spif";
+                               nvidia,pull = <1>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_ddc {
+                               nvidia,pins = "ddc", "irrx", "irtx", "kbca",
+                                       "kbcb", "kbcc", "kbcd", "kbce", "kbcf",
+                                       "spic", "spig", "uaa", "uab";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_dta {
+                               nvidia,pins = "dta", "dtd", "owc", "sdc", "sdd",
+                                       "spie", "spih", "uad", "uca", "ucb";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_hdint {
+                               nvidia,pins = "hdint", "ld0", "ld1", "ld2",
+                                       "ld3", "ld4", "ld5", "ld6", "ld7",
+                                       "ld8", "ld9", "ld10", "ld11", "ld12",
+                                       "ld13", "ld14", "ld15", "ld16", "ld17",
+                                       "ldc", "ldi", "lhs", "lsc0", "lspi",
+                                       "lvs", "pmc";
+                               nvidia,tristate = <0>;
+                       };
+                       conf_lc {
+                               nvidia,pins = "lc", "ls";
+                               nvidia,pull = <2>;
+                       };
+                       conf_lcsn {
+                               nvidia,pins = "lcsn", "lhp0", "lhp1", "lhp2",
+                                       "lm0", "lm1", "lpp", "lpw0", "lpw1",
+                                       "lpw2", "lsc1", "lsck", "lsda", "lsdi",
+                                       "lvp0", "lvp1", "sdb";
+                               nvidia,tristate = <1>;
+                       };
+                       conf_ld17_0 {
+                               nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
+                                       "ld23_22";
+                               nvidia,pull = <1>;
+                       };
+               };
+       };
+
+       i2s@70002800 {
+               status = "okay";
+       };
+
+       serial@70006000 {
+               status = "okay";
+               clock-frequency = <216000000>;
+       };
+
+       serial@70006200 {
+               status = "okay";
+               clock-frequency = <216000000>;
+       };
+
+       i2c@7000c000 {
+               status = "okay";
+               clock-frequency = <400000>;
+
+               alc5632: alc5632@1e {
+                       compatible = "realtek,alc5632";
+                       reg = <0x1e>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+       };
+
+       i2c@7000c400 {
+               status = "okay";
+               clock-frequency = <400000>;
+       };
+
+       nvec {
+               compatible = "nvidia,nvec";
+               reg = <0x7000c500 0x100>;
+               interrupts = <0 92 0x04>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clock-frequency = <80000>;
+               request-gpios = <&gpio 170 0>; /* gpio PV2 */
+               slave-addr = <138>;
+       };
+
+       i2c@7000d000 {
+               status = "okay";
+               clock-frequency = <400000>;
+
+               adt7461@4c {
+                       compatible = "adi,adt7461";
+                       reg = <0x4c>;
+               };
+       };
+
+       usb@c5000000 {
+               status = "okay";
+       };
+
+       usb@c5004000 {
+               status = "okay";
+               nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
+       };
+
+       usb@c5008000 {
+               status = "okay";
+       };
+
+       sdhci@c8000000 {
+               status = "okay";
+               cd-gpios = <&gpio 173 0>; /* gpio PV5 */
+               wp-gpios = <&gpio 57 0>;  /* gpio PH1 */
+               power-gpios = <&gpio 169 0>; /* gpio PV1 */
+               bus-width = <4>;
+       };
+
+       sdhci@c8000600 {
+               status = "okay";
+               bus-width = <8>;
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               power {
+                       label = "Power";
+                       gpios = <&gpio 79 1>; /* gpio PJ7, active low */
+                       linux,code = <116>; /* KEY_POWER */
+                       gpio-key,wakeup;
+               };
+       };
+
+       gpio-leds {
+               compatible = "gpio-leds";
+
+               wifi {
+                       label = "wifi-led";
+                       gpios = <&gpio 24 0>; /* gpio PD0 */
+                       linux,default-trigger = "rfkill0";
+               };
+       };
+
+       sound {
+               compatible = "nvidia,tegra-audio-alc5632-paz00",
+                       "nvidia,tegra-audio-alc5632";
+
+               nvidia,model = "Compal PAZ00";
+
+               nvidia,audio-routing =
+                       "Int Spk", "SPKOUT",
+                       "Int Spk", "SPKOUTN",
+                       "Headset Mic", "MICBIAS1",
+                       "MIC1", "Headset Mic",
+                       "Headset Stereophone", "HPR",
+                       "Headset Stereophone", "HPL",
+                       "DMICDAT", "Digital Mic";
+
+               nvidia,audio-codec = <&alc5632>;
+               nvidia,i2s-controller = <&tegra_i2s1>;
+               nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+       };
+};
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
new file mode 100644 (file)
index 0000000..85e621a
--- /dev/null
@@ -0,0 +1,497 @@
+/dts-v1/;
+
+/include/ "tegra20.dtsi"
+
+/ {
+       model = "NVIDIA Seaboard";
+       compatible = "nvidia,seaboard", "nvidia,tegra20";
+
+       memory {
+               reg = <0x00000000 0x40000000>;
+       };
+
+       pinmux {
+               pinctrl-names = "default";
+               pinctrl-0 = <&state_default>;
+
+               state_default: pinmux {
+                       ata {
+                               nvidia,pins = "ata";
+                               nvidia,function = "ide";
+                       };
+                       atb {
+                               nvidia,pins = "atb", "gma", "gme";
+                               nvidia,function = "sdio4";
+                       };
+                       atc {
+                               nvidia,pins = "atc";
+                               nvidia,function = "nand";
+                       };
+                       atd {
+                               nvidia,pins = "atd", "ate", "gmb", "spia",
+                                       "spib", "spic";
+                               nvidia,function = "gmi";
+                       };
+                       cdev1 {
+                               nvidia,pins = "cdev1";
+                               nvidia,function = "plla_out";
+                       };
+                       cdev2 {
+                               nvidia,pins = "cdev2";
+                               nvidia,function = "pllp_out4";
+                       };
+                       crtp {
+                               nvidia,pins = "crtp", "lm1";
+                               nvidia,function = "crt";
+                       };
+                       csus {
+                               nvidia,pins = "csus";
+                               nvidia,function = "vi_sensor_clk";
+                       };
+                       dap1 {
+                               nvidia,pins = "dap1";
+                               nvidia,function = "dap1";
+                       };
+                       dap2 {
+                               nvidia,pins = "dap2";
+                               nvidia,function = "dap2";
+                       };
+                       dap3 {
+                               nvidia,pins = "dap3";
+                               nvidia,function = "dap3";
+                       };
+                       dap4 {
+                               nvidia,pins = "dap4";
+                               nvidia,function = "dap4";
+                       };
+                       dta {
+                               nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
+                               nvidia,function = "vi";
+                       };
+                       dtf {
+                               nvidia,pins = "dtf";
+                               nvidia,function = "i2c3";
+                       };
+                       gmc {
+                               nvidia,pins = "gmc";
+                               nvidia,function = "uartd";
+                       };
+                       gmd {
+                               nvidia,pins = "gmd";
+                               nvidia,function = "sflash";
+                       };
+                       gpu {
+                               nvidia,pins = "gpu";
+                               nvidia,function = "pwm";
+                       };
+                       gpu7 {
+                               nvidia,pins = "gpu7";
+                               nvidia,function = "rtck";
+                       };
+                       gpv {
+                               nvidia,pins = "gpv", "slxa", "slxk";
+                               nvidia,function = "pcie";
+                       };
+                       hdint {
+                               nvidia,pins = "hdint", "lpw0", "lpw2", "lsc1",
+                                       "lsck", "lsda";
+                               nvidia,function = "hdmi";
+                       };
+                       i2cp {
+                               nvidia,pins = "i2cp";
+                               nvidia,function = "i2cp";
+                       };
+                       irrx {
+                               nvidia,pins = "irrx", "irtx";
+                               nvidia,function = "uartb";
+                       };
+                       kbca {
+                               nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
+                                       "kbce", "kbcf";
+                               nvidia,function = "kbc";
+                       };
+                       lcsn {
+                               nvidia,pins = "lcsn", "ldc", "lm0", "lpw1",
+                                       "lsdi", "lvp0";
+                               nvidia,function = "rsvd4";
+                       };
+                       ld0 {
+                               nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+                                       "ld5", "ld6", "ld7", "ld8", "ld9",
+                                       "ld10", "ld11", "ld12", "ld13", "ld14",
+                                       "ld15", "ld16", "ld17", "ldi", "lhp0",
+                                       "lhp1", "lhp2", "lhs", "lpp", "lsc0",
+                                       "lspi", "lvp1", "lvs";
+                               nvidia,function = "displaya";
+                       };
+                       owc {
+                               nvidia,pins = "owc", "spdi", "spdo", "uac";
+                               nvidia,function = "rsvd2";
+                       };
+                       pmc {
+                               nvidia,pins = "pmc";
+                               nvidia,function = "pwr_on";
+                       };
+                       rm {
+                               nvidia,pins = "rm";
+                               nvidia,function = "i2c1";
+                       };
+                       sdb {
+                               nvidia,pins = "sdb", "sdc", "sdd";
+                               nvidia,function = "sdio3";
+                       };
+                       sdio1 {
+                               nvidia,pins = "sdio1";
+                               nvidia,function = "sdio1";
+                       };
+                       slxc {
+                               nvidia,pins = "slxc", "slxd";
+                               nvidia,function = "spdif";
+                       };
+                       spid {
+                               nvidia,pins = "spid", "spie", "spif";
+                               nvidia,function = "spi1";
+                       };
+                       spig {
+                               nvidia,pins = "spig", "spih";
+                               nvidia,function = "spi2_alt";
+                       };
+                       uaa {
+                               nvidia,pins = "uaa", "uab", "uda";
+                               nvidia,function = "ulpi";
+                       };
+                       uad {
+                               nvidia,pins = "uad";
+                               nvidia,function = "irda";
+                       };
+                       uca {
+                               nvidia,pins = "uca", "ucb";
+                               nvidia,function = "uartc";
+                       };
+                       conf_ata {
+                               nvidia,pins = "ata", "atb", "atc", "atd",
+                                       "cdev1", "cdev2", "dap1", "dap2",
+                                       "dap4", "ddc", "dtf", "gma", "gmc", "gmd",
+                                       "gme", "gpu", "gpu7", "i2cp", "irrx",
+                                       "irtx", "pta", "rm", "sdc", "sdd",
+                                       "slxd", "slxk", "spdi", "spdo", "uac",
+                                       "uad", "uca", "ucb", "uda";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_ate {
+                               nvidia,pins = "ate", "csus", "dap3",
+                                       "gpv", "owc", "slxc", "spib", "spid",
+                                       "spie";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_ck32 {
+                               nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
+                                       "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
+                               nvidia,pull = <0>;
+                       };
+                       conf_crtp {
+                               nvidia,pins = "crtp", "gmb", "slxa", "spia",
+                                       "spig", "spih";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_dta {
+                               nvidia,pins = "dta", "dtb", "dtc", "dtd";
+                               nvidia,pull = <1>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_dte {
+                               nvidia,pins = "dte", "spif";
+                               nvidia,pull = <1>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_hdint {
+                               nvidia,pins = "hdint", "lcsn", "ldc", "lm1",
+                                       "lpw1", "lsc1", "lsck", "lsda", "lsdi",
+                                       "lvp0";
+                               nvidia,tristate = <1>;
+                       };
+                       conf_kbca {
+                               nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
+                                       "kbce", "kbcf", "sdio1", "spic", "uaa",
+                                       "uab";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_lc {
+                               nvidia,pins = "lc", "ls";
+                               nvidia,pull = <2>;
+                       };
+                       conf_ld0 {
+                               nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+                                       "ld5", "ld6", "ld7", "ld8", "ld9",
+                                       "ld10", "ld11", "ld12", "ld13", "ld14",
+                                       "ld15", "ld16", "ld17", "ldi", "lhp0",
+                                       "lhp1", "lhp2", "lhs", "lm0", "lpp",
+                                       "lpw0", "lpw2", "lsc0", "lspi", "lvp1",
+                                       "lvs", "pmc", "sdb";
+                               nvidia,tristate = <0>;
+                       };
+                       conf_ld17_0 {
+                               nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
+                                       "ld23_22";
+                               nvidia,pull = <1>;
+                       };
+                       drive_sdio1 {
+                               nvidia,pins = "drive_sdio1";
+                               nvidia,high-speed-mode = <0>;
+                               nvidia,schmitt = <0>;
+                               nvidia,low-power-mode = <3>;
+                               nvidia,pull-down-strength = <31>;
+                               nvidia,pull-up-strength = <31>;
+                               nvidia,slew-rate-rising = <3>;
+                               nvidia,slew-rate-falling = <3>;
+                       };
+               };
+
+               state_i2cmux_ddc: pinmux_i2cmux_ddc {
+                       ddc {
+                               nvidia,pins = "ddc";
+                               nvidia,function = "i2c2";
+                       };
+                       pta {
+                               nvidia,pins = "pta";
+                               nvidia,function = "rsvd4";
+                       };
+               };
+
+               state_i2cmux_pta: pinmux_i2cmux_pta {
+                       ddc {
+                               nvidia,pins = "ddc";
+                               nvidia,function = "rsvd4";
+                       };
+                       pta {
+                               nvidia,pins = "pta";
+                               nvidia,function = "i2c2";
+                       };
+               };
+
+               state_i2cmux_idle: pinmux_i2cmux_idle {
+                       ddc {
+                               nvidia,pins = "ddc";
+                               nvidia,function = "rsvd4";
+                       };
+                       pta {
+                               nvidia,pins = "pta";
+                               nvidia,function = "rsvd4";
+                       };
+               };
+       };
+
+       i2s@70002800 {
+               status = "okay";
+       };
+
+       serial@70006300 {
+               status = "okay";
+               clock-frequency = <216000000>;
+       };
+
+       i2c@7000c000 {
+               status = "okay";
+               clock-frequency = <400000>;
+
+               wm8903: wm8903@1a {
+                       compatible = "wlf,wm8903";
+                       reg = <0x1a>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <187 0x04>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       micdet-cfg = <0>;
+                       micdet-delay = <100>;
+                       gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>;
+               };
+
+               /* ALS and proximity sensor */
+               isl29018@44 {
+                       compatible = "isil,isl29018";
+                       reg = <0x44>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <202 0x04>; /* GPIO PZ2 */
+               };
+
+               gyrometer@68 {
+                       compatible = "invn,mpu3050";
+                       reg = <0x68>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <204 0x04>; /* gpio PZ4 */
+               };
+       };
+
+       i2c@7000c400 {
+               status = "okay";
+               clock-frequency = <100000>;
+       };
+
+       i2cmux {
+               compatible = "i2c-mux-pinctrl";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               i2c-parent = <&{/i2c@7000c400}>;
+
+               pinctrl-names = "ddc", "pta", "idle";
+               pinctrl-0 = <&state_i2cmux_ddc>;
+               pinctrl-1 = <&state_i2cmux_pta>;
+               pinctrl-2 = <&state_i2cmux_idle>;
+
+               i2c@0 {
+                       reg = <0>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               i2c@1 {
+                       reg = <1>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       smart-battery@b {
+                               compatible = "ti,bq20z75", "smart-battery-1.1";
+                               reg = <0xb>;
+                               ti,i2c-retry-count = <2>;
+                               ti,poll-retry-count = <10>;
+                       };
+               };
+       };
+
+       i2c@7000c500 {
+               status = "okay";
+               clock-frequency = <400000>;
+       };
+
+       i2c@7000d000 {
+               status = "okay";
+               clock-frequency = <400000>;
+
+               temperature-sensor@4c {
+                       compatible = "nct1008";
+                       reg = <0x4c>;
+               };
+
+               magnetometer@c {
+                       compatible = "ak8975";
+                       reg = <0xc>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <109 0x04>; /* gpio PN5 */
+               };
+       };
+
+       memory-controller@0x7000f400 {
+               emc-table@190000 {
+                       reg = <190000>;
+                       compatible = "nvidia,tegra20-emc-table";
+                       clock-frequency = <190000>;
+                       nvidia,emc-registers = <0x0000000c 0x00000026
+                               0x00000009 0x00000003 0x00000004 0x00000004
+                               0x00000002 0x0000000c 0x00000003 0x00000003
+                               0x00000002 0x00000001 0x00000004 0x00000005
+                               0x00000004 0x00000009 0x0000000d 0x0000059f
+                               0x00000000 0x00000003 0x00000003 0x00000003
+                               0x00000003 0x00000001 0x0000000b 0x000000c8
+                               0x00000003 0x00000007 0x00000004 0x0000000f
+                               0x00000002 0x00000000 0x00000000 0x00000002
+                               0x00000000 0x00000000 0x00000083 0xa06204ae
+                               0x007dc010 0x00000000 0x00000000 0x00000000
+                               0x00000000 0x00000000 0x00000000 0x00000000>;
+               };
+
+               emc-table@380000 {
+                       reg = <380000>;
+                       compatible = "nvidia,tegra20-emc-table";
+                       clock-frequency = <380000>;
+                       nvidia,emc-registers = <0x00000017 0x0000004b
+                               0x00000012 0x00000006 0x00000004 0x00000005
+                               0x00000003 0x0000000c 0x00000006 0x00000006
+                               0x00000003 0x00000001 0x00000004 0x00000005
+                               0x00000004 0x00000009 0x0000000d 0x00000b5f
+                               0x00000000 0x00000003 0x00000003 0x00000006
+                               0x00000006 0x00000001 0x00000011 0x000000c8
+                               0x00000003 0x0000000e 0x00000007 0x0000000f
+                               0x00000002 0x00000000 0x00000000 0x00000002
+                               0x00000000 0x00000000 0x00000083 0xe044048b
+                               0x007d8010 0x00000000 0x00000000 0x00000000
+                               0x00000000 0x00000000 0x00000000 0x00000000>;
+               };
+       };
+
+       usb@c5000000 {
+               status = "okay";
+               nvidia,vbus-gpio = <&gpio 24 0>; /* PD0 */
+               dr_mode = "otg";
+       };
+
+       usb@c5004000 {
+               status = "okay";
+               nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+       };
+
+       usb@c5008000 {
+               status = "okay";
+       };
+
+       sdhci@c8000400 {
+               status = "okay";
+               cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+               wp-gpios = <&gpio 57 0>; /* gpio PH1 */
+               power-gpios = <&gpio 70 0>; /* gpio PI6 */
+               bus-width = <4>;
+       };
+
+       sdhci@c8000600 {
+               status = "okay";
+               bus-width = <8>;
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               power {
+                       label = "Power";
+                       gpios = <&gpio 170 1>; /* gpio PV2, active low */
+                       linux,code = <116>; /* KEY_POWER */
+                       gpio-key,wakeup;
+               };
+
+               lid {
+                       label = "Lid";
+                       gpios = <&gpio 23 0>; /* gpio PC7 */
+                       linux,input-type = <5>; /* EV_SW */
+                       linux,code = <0>; /* SW_LID */
+                       debounce-interval = <1>;
+                       gpio-key,wakeup;
+               };
+       };
+
+       sound {
+               compatible = "nvidia,tegra-audio-wm8903-seaboard",
+                            "nvidia,tegra-audio-wm8903";
+               nvidia,model = "NVIDIA Tegra Seaboard";
+
+               nvidia,audio-routing =
+                       "Headphone Jack", "HPOUTR",
+                       "Headphone Jack", "HPOUTL",
+                       "Int Spk", "ROP",
+                       "Int Spk", "RON",
+                       "Int Spk", "LOP",
+                       "Int Spk", "LON",
+                       "Mic Jack", "MICBIAS",
+                       "IN1R", "Mic Jack";
+
+               nvidia,i2s-controller = <&tegra_i2s1>;
+               nvidia,audio-codec = <&wm8903>;
+
+               nvidia,spkr-en-gpios = <&wm8903 2 0>;
+               nvidia,hp-det-gpios = <&gpio 185 0>; /* gpio PX1 */
+       };
+};
diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts
new file mode 100644 (file)
index 0000000..9de5636
--- /dev/null
@@ -0,0 +1,306 @@
+/dts-v1/;
+
+/include/ "tegra20.dtsi"
+
+/ {
+       model = "Compulab TrimSlice board";
+       compatible = "compulab,trimslice", "nvidia,tegra20";
+
+       memory {
+               reg = <0x00000000 0x40000000>;
+       };
+
+       pinmux {
+               pinctrl-names = "default";
+               pinctrl-0 = <&state_default>;
+
+               state_default: pinmux {
+                       ata {
+                               nvidia,pins = "ata";
+                               nvidia,function = "ide";
+                       };
+                       atb {
+                               nvidia,pins = "atb", "gma";
+                               nvidia,function = "sdio4";
+                       };
+                       atc {
+                               nvidia,pins = "atc", "gmb";
+                               nvidia,function = "nand";
+                       };
+                       atd {
+                               nvidia,pins = "atd", "ate", "gme", "pta";
+                               nvidia,function = "gmi";
+                       };
+                       cdev1 {
+                               nvidia,pins = "cdev1";
+                               nvidia,function = "plla_out";
+                       };
+                       cdev2 {
+                               nvidia,pins = "cdev2";
+                               nvidia,function = "pllp_out4";
+                       };
+                       crtp {
+                               nvidia,pins = "crtp";
+                               nvidia,function = "crt";
+                       };
+                       csus {
+                               nvidia,pins = "csus";
+                               nvidia,function = "vi_sensor_clk";
+                       };
+                       dap1 {
+                               nvidia,pins = "dap1";
+                               nvidia,function = "dap1";
+                       };
+                       dap2 {
+                               nvidia,pins = "dap2";
+                               nvidia,function = "dap2";
+                       };
+                       dap3 {
+                               nvidia,pins = "dap3";
+                               nvidia,function = "dap3";
+                       };
+                       dap4 {
+                               nvidia,pins = "dap4";
+                               nvidia,function = "dap4";
+                       };
+                       ddc {
+                               nvidia,pins = "ddc";
+                               nvidia,function = "i2c2";
+                       };
+                       dta {
+                               nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
+                               nvidia,function = "vi";
+                       };
+                       dtf {
+                               nvidia,pins = "dtf";
+                               nvidia,function = "i2c3";
+                       };
+                       gmc {
+                               nvidia,pins = "gmc", "gmd";
+                               nvidia,function = "sflash";
+                       };
+                       gpu {
+                               nvidia,pins = "gpu";
+                               nvidia,function = "uarta";
+                       };
+                       gpu7 {
+                               nvidia,pins = "gpu7";
+                               nvidia,function = "rtck";
+                       };
+                       gpv {
+                               nvidia,pins = "gpv", "slxa", "slxk";
+                               nvidia,function = "pcie";
+                       };
+                       hdint {
+                               nvidia,pins = "hdint";
+                               nvidia,function = "hdmi";
+                       };
+                       i2cp {
+                               nvidia,pins = "i2cp";
+                               nvidia,function = "i2cp";
+                       };
+                       irrx {
+                               nvidia,pins = "irrx", "irtx";
+                               nvidia,function = "uartb";
+                       };
+                       kbca {
+                               nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
+                                       "kbce", "kbcf";
+                               nvidia,function = "kbc";
+                       };
+                       lcsn {
+                               nvidia,pins = "lcsn", "ld0", "ld1", "ld2",
+                                       "ld3", "ld4", "ld5", "ld6", "ld7",
+                                       "ld8", "ld9", "ld10", "ld11", "ld12",
+                                       "ld13", "ld14", "ld15", "ld16", "ld17",
+                                       "ldc", "ldi", "lhp0", "lhp1", "lhp2",
+                                       "lhs", "lm0", "lm1", "lpp", "lpw0",
+                                       "lpw1", "lpw2", "lsc0", "lsc1", "lsck",
+                                       "lsda", "lsdi", "lspi", "lvp0", "lvp1",
+                                       "lvs";
+                               nvidia,function = "displaya";
+                       };
+                       owc {
+                               nvidia,pins = "owc", "uac";
+                               nvidia,function = "rsvd2";
+                       };
+                       pmc {
+                               nvidia,pins = "pmc";
+                               nvidia,function = "pwr_on";
+                       };
+                       rm {
+                               nvidia,pins = "rm";
+                               nvidia,function = "i2c1";
+                       };
+                       sdb {
+                               nvidia,pins = "sdb", "sdc", "sdd";
+                               nvidia,function = "pwm";
+                       };
+                       sdio1 {
+                               nvidia,pins = "sdio1";
+                               nvidia,function = "sdio1";
+                       };
+                       slxc {
+                               nvidia,pins = "slxc", "slxd";
+                               nvidia,function = "sdio3";
+                       };
+                       spdi {
+                               nvidia,pins = "spdi", "spdo";
+                               nvidia,function = "spdif";
+                       };
+                       spia {
+                               nvidia,pins = "spia", "spib", "spic";
+                               nvidia,function = "spi2";
+                       };
+                       spid {
+                               nvidia,pins = "spid", "spie", "spif";
+                               nvidia,function = "spi1";
+                       };
+                       spig {
+                               nvidia,pins = "spig", "spih";
+                               nvidia,function = "spi2_alt";
+                       };
+                       uaa {
+                               nvidia,pins = "uaa", "uab", "uda";
+                               nvidia,function = "ulpi";
+                       };
+                       uad {
+                               nvidia,pins = "uad";
+                               nvidia,function = "irda";
+                       };
+                       uca {
+                               nvidia,pins = "uca", "ucb";
+                               nvidia,function = "uartc";
+                       };
+                       conf_ata {
+                               nvidia,pins = "ata", "atc", "atd", "ate",
+                                       "crtp", "dap2", "dap3", "dap4", "dta",
+                                       "dtb", "dtc", "dtd", "dte", "gmb",
+                                       "gme", "i2cp", "pta", "slxc", "slxd",
+                                       "spdi", "spdo", "uda";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_atb {
+                               nvidia,pins = "atb", "cdev1", "cdev2", "dap1",
+                                       "gma", "gmc", "gmd", "gpu", "gpu7",
+                                       "gpv", "sdio1", "slxa", "slxk", "uac";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_ck32 {
+                               nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
+                                       "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
+                               nvidia,pull = <0>;
+                       };
+                       conf_csus {
+                               nvidia,pins = "csus", "spia", "spib",
+                                       "spid", "spif";
+                               nvidia,pull = <1>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_ddc {
+                               nvidia,pins = "ddc", "dtf", "rm", "sdc", "sdd";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_hdint {
+                               nvidia,pins = "hdint", "lcsn", "ldc", "lm1",
+                                       "lpw1", "lsc1", "lsck", "lsda", "lsdi",
+                                       "lvp0", "pmc";
+                               nvidia,tristate = <1>;
+                       };
+                       conf_irrx {
+                               nvidia,pins = "irrx", "irtx", "kbca", "kbcb",
+                                       "kbcc", "kbcd", "kbce", "kbcf", "owc",
+                                       "spic", "spie", "spig", "spih", "uaa",
+                                       "uab", "uad", "uca", "ucb";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_lc {
+                               nvidia,pins = "lc", "ls";
+                               nvidia,pull = <2>;
+                       };
+                       conf_ld0 {
+                               nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+                                       "ld5", "ld6", "ld7", "ld8", "ld9",
+                                       "ld10", "ld11", "ld12", "ld13", "ld14",
+                                       "ld15", "ld16", "ld17", "ldi", "lhp0",
+                                       "lhp1", "lhp2", "lhs", "lm0", "lpp",
+                                       "lpw0", "lpw2", "lsc0", "lspi", "lvp1",
+                                       "lvs", "sdb";
+                               nvidia,tristate = <0>;
+                       };
+                       conf_ld17_0 {
+                               nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
+                                       "ld23_22";
+                               nvidia,pull = <1>;
+                       };
+               };
+       };
+
+       i2s@70002800 {
+               status = "okay";
+       };
+
+       serial@70006000 {
+               status = "okay";
+               clock-frequency = <216000000>;
+       };
+
+       i2c@7000c000 {
+               status = "okay";
+               clock-frequency = <400000>;
+       };
+
+       i2c@7000c400 {
+               status = "okay";
+               clock-frequency = <400000>;
+       };
+
+       i2c@7000c500 {
+               status = "okay";
+               clock-frequency = <400000>;
+
+               codec: codec@1a {
+                       compatible = "ti,tlv320aic23";
+                       reg = <0x1a>;
+               };
+
+               rtc@56 {
+                       compatible = "emmicro,em3027";
+                       reg = <0x56>;
+               };
+       };
+
+       usb@c5000000 {
+               status = "okay";
+       };
+
+       usb@c5004000 {
+               nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
+       };
+
+       usb@c5008000 {
+               status = "okay";
+       };
+
+       sdhci@c8000000 {
+               status = "okay";
+               bus-width = <4>;
+       };
+
+       sdhci@c8000600 {
+               status = "okay";
+               cd-gpios = <&gpio 121 0>; /* gpio PP1 */
+               wp-gpios = <&gpio 122 0>; /* gpio PP2 */
+               bus-width = <4>;
+       };
+
+       sound {
+               compatible = "nvidia,tegra-audio-trimslice";
+               nvidia,i2s-controller = <&tegra_i2s1>;
+               nvidia,audio-codec = <&codec>;
+       };
+};
diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
new file mode 100644 (file)
index 0000000..be90544
--- /dev/null
@@ -0,0 +1,343 @@
+/dts-v1/;
+
+/include/ "tegra20.dtsi"
+
+/ {
+       model = "NVIDIA Tegra2 Ventana evaluation board";
+       compatible = "nvidia,ventana", "nvidia,tegra20";
+
+       memory {
+               reg = <0x00000000 0x40000000>;
+       };
+
+       pinmux {
+               pinctrl-names = "default";
+               pinctrl-0 = <&state_default>;
+
+               state_default: pinmux {
+                       ata {
+                               nvidia,pins = "ata";
+                               nvidia,function = "ide";
+                       };
+                       atb {
+                               nvidia,pins = "atb", "gma", "gme";
+                               nvidia,function = "sdio4";
+                       };
+                       atc {
+                               nvidia,pins = "atc";
+                               nvidia,function = "nand";
+                       };
+                       atd {
+                               nvidia,pins = "atd", "ate", "gmb", "spia",
+                                       "spib", "spic";
+                               nvidia,function = "gmi";
+                       };
+                       cdev1 {
+                               nvidia,pins = "cdev1";
+                               nvidia,function = "plla_out";
+                       };
+                       cdev2 {
+                               nvidia,pins = "cdev2";
+                               nvidia,function = "pllp_out4";
+                       };
+                       crtp {
+                               nvidia,pins = "crtp", "lm1";
+                               nvidia,function = "crt";
+                       };
+                       csus {
+                               nvidia,pins = "csus";
+                               nvidia,function = "vi_sensor_clk";
+                       };
+                       dap1 {
+                               nvidia,pins = "dap1";
+                               nvidia,function = "dap1";
+                       };
+                       dap2 {
+                               nvidia,pins = "dap2";
+                               nvidia,function = "dap2";
+                       };
+                       dap3 {
+                               nvidia,pins = "dap3";
+                               nvidia,function = "dap3";
+                       };
+                       dap4 {
+                               nvidia,pins = "dap4";
+                               nvidia,function = "dap4";
+                       };
+                       ddc {
+                               nvidia,pins = "ddc", "owc", "spdi", "spdo",
+                                       "uac";
+                               nvidia,function = "rsvd2";
+                       };
+                       dta {
+                               nvidia,pins = "dta", "dtb", "dtc", "dtd", "dte";
+                               nvidia,function = "vi";
+                       };
+                       dtf {
+                               nvidia,pins = "dtf";
+                               nvidia,function = "i2c3";
+                       };
+                       gmc {
+                               nvidia,pins = "gmc";
+                               nvidia,function = "uartd";
+                       };
+                       gmd {
+                               nvidia,pins = "gmd";
+                               nvidia,function = "sflash";
+                       };
+                       gpu {
+                               nvidia,pins = "gpu";
+                               nvidia,function = "pwm";
+                       };
+                       gpu7 {
+                               nvidia,pins = "gpu7";
+                               nvidia,function = "rtck";
+                       };
+                       gpv {
+                               nvidia,pins = "gpv", "slxa", "slxk";
+                               nvidia,function = "pcie";
+                       };
+                       hdint {
+                               nvidia,pins = "hdint", "pta";
+                               nvidia,function = "hdmi";
+                       };
+                       i2cp {
+                               nvidia,pins = "i2cp";
+                               nvidia,function = "i2cp";
+                       };
+                       irrx {
+                               nvidia,pins = "irrx", "irtx";
+                               nvidia,function = "uartb";
+                       };
+                       kbca {
+                               nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
+                                       "kbce", "kbcf";
+                               nvidia,function = "kbc";
+                       };
+                       lcsn {
+                               nvidia,pins = "lcsn", "ldc", "lm0", "lpw1",
+                                       "lsdi", "lvp0";
+                               nvidia,function = "rsvd4";
+                       };
+                       ld0 {
+                               nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+                                       "ld5", "ld6", "ld7", "ld8", "ld9",
+                                       "ld10", "ld11", "ld12", "ld13", "ld14",
+                                       "ld15", "ld16", "ld17", "ldi", "lhp0",
+                                       "lhp1", "lhp2", "lhs", "lpp", "lpw0",
+                                       "lpw2", "lsc0", "lsc1", "lsck", "lsda",
+                                       "lspi", "lvp1", "lvs";
+                               nvidia,function = "displaya";
+                       };
+                       pmc {
+                               nvidia,pins = "pmc";
+                               nvidia,function = "pwr_on";
+                       };
+                       rm {
+                               nvidia,pins = "rm";
+                               nvidia,function = "i2c1";
+                       };
+                       sdb {
+                               nvidia,pins = "sdb", "sdc", "sdd", "slxc";
+                               nvidia,function = "sdio3";
+                       };
+                       sdio1 {
+                               nvidia,pins = "sdio1";
+                               nvidia,function = "sdio1";
+                       };
+                       slxd {
+                               nvidia,pins = "slxd";
+                               nvidia,function = "spdif";
+                       };
+                       spid {
+                               nvidia,pins = "spid", "spie", "spif";
+                               nvidia,function = "spi1";
+                       };
+                       spig {
+                               nvidia,pins = "spig", "spih";
+                               nvidia,function = "spi2_alt";
+                       };
+                       uaa {
+                               nvidia,pins = "uaa", "uab", "uda";
+                               nvidia,function = "ulpi";
+                       };
+                       uad {
+                               nvidia,pins = "uad";
+                               nvidia,function = "irda";
+                       };
+                       uca {
+                               nvidia,pins = "uca", "ucb";
+                               nvidia,function = "uartc";
+                       };
+                       conf_ata {
+                               nvidia,pins = "ata", "atb", "atc", "atd",
+                                       "cdev1", "cdev2", "dap1", "dap2",
+                                       "dap4", "ddc", "dtf", "gma", "gmc",
+                                       "gme", "gpu", "gpu7", "i2cp", "irrx",
+                                       "irtx", "pta", "rm", "sdc", "sdd",
+                                       "slxc", "slxd", "slxk", "spdi", "spdo",
+                                       "uac", "uad", "uca", "ucb", "uda";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_ate {
+                               nvidia,pins = "ate", "csus", "dap3", "gmd",
+                                       "gpv", "owc", "spia", "spib", "spic",
+                                       "spid", "spie", "spig";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_ck32 {
+                               nvidia,pins = "ck32", "ddrc", "pmca", "pmcb",
+                                       "pmcc", "pmcd", "pmce", "xm2c", "xm2d";
+                               nvidia,pull = <0>;
+                       };
+                       conf_crtp {
+                               nvidia,pins = "crtp", "gmb", "slxa", "spih";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_dta {
+                               nvidia,pins = "dta", "dtb", "dtc", "dtd";
+                               nvidia,pull = <1>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_dte {
+                               nvidia,pins = "dte", "spif";
+                               nvidia,pull = <1>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_hdint {
+                               nvidia,pins = "hdint", "lcsn", "ldc", "lm1",
+                                       "lpw1", "lsck", "lsda", "lsdi", "lvp0";
+                               nvidia,tristate = <1>;
+                       };
+                       conf_kbca {
+                               nvidia,pins = "kbca", "kbcb", "kbcc", "kbcd",
+                                       "kbce", "kbcf", "sdio1", "uaa", "uab";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_lc {
+                               nvidia,pins = "lc", "ls";
+                               nvidia,pull = <2>;
+                       };
+                       conf_ld0 {
+                               nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+                                       "ld5", "ld6", "ld7", "ld8", "ld9",
+                                       "ld10", "ld11", "ld12", "ld13", "ld14",
+                                       "ld15", "ld16", "ld17", "ldi", "lhp0",
+                                       "lhp1", "lhp2", "lhs", "lm0", "lpp",
+                                       "lpw0", "lpw2", "lsc0", "lsc1", "lspi",
+                                       "lvp1", "lvs", "pmc", "sdb";
+                               nvidia,tristate = <0>;
+                       };
+                       conf_ld17_0 {
+                               nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
+                                       "ld23_22";
+                               nvidia,pull = <1>;
+                       };
+               };
+       };
+
+       i2s@70002800 {
+               status = "okay";
+       };
+
+       serial@70006300 {
+               status = "okay";
+               clock-frequency = <216000000>;
+       };
+
+       i2c@7000c000 {
+               status = "okay";
+               clock-frequency = <400000>;
+
+               wm8903: wm8903@1a {
+                       compatible = "wlf,wm8903";
+                       reg = <0x1a>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <187 0x04>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       micdet-cfg = <0>;
+                       micdet-delay = <100>;
+                       gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>;
+               };
+
+               /* ALS and proximity sensor */
+               isl29018@44 {
+                       compatible = "isil,isl29018";
+                       reg = <0x44>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <202 0x04>; /*gpio PZ2 */
+               };
+       };
+
+       i2c@7000c400 {
+               status = "okay";
+               clock-frequency = <400000>;
+       };
+
+       i2c@7000c500 {
+               status = "okay";
+               clock-frequency = <400000>;
+       };
+
+       i2c@7000d000 {
+               status = "okay";
+               clock-frequency = <400000>;
+       };
+
+       usb@c5000000 {
+               status = "okay";
+       };
+
+       usb@c5004000 {
+               status = "okay";
+               nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+       };
+
+       usb@c5008000 {
+               status = "okay";
+       };
+
+       sdhci@c8000400 {
+               status = "okay";
+               cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+               wp-gpios = <&gpio 57 0>; /* gpio PH1 */
+               power-gpios = <&gpio 70 0>; /* gpio PI6 */
+               bus-width = <4>;
+       };
+
+       sdhci@c8000600 {
+               status = "okay";
+               bus-width = <8>;
+       };
+
+       sound {
+               compatible = "nvidia,tegra-audio-wm8903-ventana",
+                            "nvidia,tegra-audio-wm8903";
+               nvidia,model = "NVIDIA Tegra Ventana";
+
+               nvidia,audio-routing =
+                       "Headphone Jack", "HPOUTR",
+                       "Headphone Jack", "HPOUTL",
+                       "Int Spk", "ROP",
+                       "Int Spk", "RON",
+                       "Int Spk", "LOP",
+                       "Int Spk", "LON",
+                       "Mic Jack", "MICBIAS",
+                       "IN1L", "Mic Jack";
+
+               nvidia,i2s-controller = <&tegra_i2s1>;
+               nvidia,audio-codec = <&wm8903>;
+
+               nvidia,spkr-en-gpios = <&wm8903 2 0>;
+               nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+               nvidia,int-mic-en-gpios = <&gpio 184 0>; /* gpio PX0 */
+               nvidia,ext-mic-en-gpios = <&gpio 185 0>; /* gpio PX1 */
+       };
+};
diff --git a/arch/arm/boot/dts/tegra20-whistler.dts b/arch/arm/boot/dts/tegra20-whistler.dts
new file mode 100644 (file)
index 0000000..6916310
--- /dev/null
@@ -0,0 +1,301 @@
+/dts-v1/;
+
+/include/ "tegra20.dtsi"
+
+/ {
+       model = "NVIDIA Tegra2 Whistler evaluation board";
+       compatible = "nvidia,whistler", "nvidia,tegra20";
+
+       memory {
+               reg = <0x00000000 0x20000000>;
+       };
+
+       pinmux {
+               pinctrl-names = "default";
+               pinctrl-0 = <&state_default>;
+
+               state_default: pinmux {
+                       ata {
+                               nvidia,pins = "ata", "atb", "ate", "gma", "gmb",
+                                       "gmc", "gmd", "gpu";
+                               nvidia,function = "gmi";
+                       };
+                       atc {
+                               nvidia,pins = "atc", "atd";
+                               nvidia,function = "sdio4";
+                       };
+                       cdev1 {
+                               nvidia,pins = "cdev1";
+                               nvidia,function = "plla_out";
+                       };
+                       cdev2 {
+                               nvidia,pins = "cdev2";
+                               nvidia,function = "osc";
+                       };
+                       crtp {
+                               nvidia,pins = "crtp";
+                               nvidia,function = "crt";
+                       };
+                       csus {
+                               nvidia,pins = "csus";
+                               nvidia,function = "vi_sensor_clk";
+                       };
+                       dap1 {
+                               nvidia,pins = "dap1";
+                               nvidia,function = "dap1";
+                       };
+                       dap2 {
+                               nvidia,pins = "dap2";
+                               nvidia,function = "dap2";
+                       };
+                       dap3 {
+                               nvidia,pins = "dap3";
+                               nvidia,function = "dap3";
+                       };
+                       dap4 {
+                               nvidia,pins = "dap4";
+                               nvidia,function = "dap4";
+                       };
+                       ddc {
+                               nvidia,pins = "ddc";
+                               nvidia,function = "i2c2";
+                       };
+                       dta {
+                               nvidia,pins = "dta", "dtb", "dtc", "dtd";
+                               nvidia,function = "vi";
+                       };
+                       dte {
+                               nvidia,pins = "dte";
+                               nvidia,function = "rsvd1";
+                       };
+                       dtf {
+                               nvidia,pins = "dtf";
+                               nvidia,function = "i2c3";
+                       };
+                       gme {
+                               nvidia,pins = "gme";
+                               nvidia,function = "dap5";
+                       };
+                       gpu7 {
+                               nvidia,pins = "gpu7";
+                               nvidia,function = "rtck";
+                       };
+                       gpv {
+                               nvidia,pins = "gpv";
+                               nvidia,function = "pcie";
+                       };
+                       hdint {
+                               nvidia,pins = "hdint", "pta";
+                               nvidia,function = "hdmi";
+                       };
+                       i2cp {
+                               nvidia,pins = "i2cp";
+                               nvidia,function = "i2cp";
+                       };
+                       irrx {
+                               nvidia,pins = "irrx", "irtx";
+                               nvidia,function = "uartb";
+                       };
+                       kbca {
+                               nvidia,pins = "kbca", "kbcc", "kbce", "kbcf";
+                               nvidia,function = "kbc";
+                       };
+                       kbcb {
+                               nvidia,pins = "kbcb", "kbcd";
+                               nvidia,function = "sdio2";
+                       };
+                       lcsn {
+                               nvidia,pins = "lcsn", "lsck", "lsda", "lsdi",
+                                       "spia", "spib", "spic";
+                               nvidia,function = "spi3";
+                       };
+                       ld0 {
+                               nvidia,pins = "ld0", "ld1", "ld2", "ld3", "ld4",
+                                       "ld5", "ld6", "ld7", "ld8", "ld9",
+                                       "ld10", "ld11", "ld12", "ld13", "ld14",
+                                       "ld15", "ld16", "ld17", "ldc", "ldi",
+                                       "lhp0", "lhp1", "lhp2", "lhs", "lm0",
+                                       "lm1", "lpp", "lpw0", "lpw1", "lpw2",
+                                       "lsc0", "lsc1", "lspi", "lvp0", "lvp1",
+                                       "lvs";
+                               nvidia,function = "displaya";
+                       };
+                       owc {
+                               nvidia,pins = "owc", "uac";
+                               nvidia,function = "owr";
+                       };
+                       pmc {
+                               nvidia,pins = "pmc";
+                               nvidia,function = "pwr_on";
+                       };
+                       rm {
+                               nvidia,pins = "rm";
+                               nvidia,function = "i2c1";
+                       };
+                       sdb {
+                               nvidia,pins = "sdb", "sdc", "sdd", "slxa",
+                                       "slxc", "slxd", "slxk";
+                               nvidia,function = "sdio3";
+                       };
+                       sdio1 {
+                               nvidia,pins = "sdio1";
+                               nvidia,function = "sdio1";
+                       };
+                       spdi {
+                               nvidia,pins = "spdi", "spdo";
+                               nvidia,function = "rsvd2";
+                       };
+                       spid {
+                               nvidia,pins = "spid", "spie", "spig", "spih";
+                               nvidia,function = "spi2_alt";
+                       };
+                       spif {
+                               nvidia,pins = "spif";
+                               nvidia,function = "spi2";
+                       };
+                       uaa {
+                               nvidia,pins = "uaa", "uab";
+                               nvidia,function = "uarta";
+                       };
+                       uad {
+                               nvidia,pins = "uad";
+                               nvidia,function = "irda";
+                       };
+                       uca {
+                               nvidia,pins = "uca", "ucb";
+                               nvidia,function = "uartc";
+                       };
+                       uda {
+                               nvidia,pins = "uda";
+                               nvidia,function = "spi1";
+                       };
+                       conf_ata {
+                               nvidia,pins = "ata", "atb", "atc", "ddc", "gma",
+                                       "gmb", "gmc", "gmd", "irrx", "irtx",
+                                       "kbca", "kbcb", "kbcc", "kbcd", "kbce",
+                                       "kbcf", "sdc", "sdd", "spie", "spig",
+                                       "spih", "uaa", "uab", "uad", "uca",
+                                       "ucb";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_atd {
+                               nvidia,pins = "atd", "ate", "cdev1", "csus",
+                                       "dap1", "dap2", "dap3", "dap4", "dte",
+                                       "dtf", "gpu", "gpu7", "gpv", "i2cp",
+                                       "rm", "sdio1", "slxa", "slxc", "slxd",
+                                       "slxk", "spdi", "spdo", "uac", "uda";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_cdev2 {
+                               nvidia,pins = "cdev2", "spia", "spib";
+                               nvidia,pull = <1>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_ck32 {
+                               nvidia,pins = "ck32", "ddrc", "lc", "pmca",
+                                       "pmcb", "pmcc", "pmcd", "xm2c",
+                                       "xm2d";
+                               nvidia,pull = <0>;
+                       };
+                       conf_crtp {
+                               nvidia,pins = "crtp";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_dta {
+                               nvidia,pins = "dta", "dtb", "dtc", "dtd",
+                                       "spid", "spif";
+                               nvidia,pull = <1>;
+                               nvidia,tristate = <0>;
+                       };
+                       conf_gme {
+                               nvidia,pins = "gme", "owc", "pta", "spic";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <1>;
+                       };
+                       conf_ld17_0 {
+                               nvidia,pins = "ld17_0", "ld19_18", "ld21_20",
+                                       "ld23_22";
+                               nvidia,pull = <1>;
+                       };
+                       conf_ls {
+                               nvidia,pins = "ls", "pmce";
+                               nvidia,pull = <2>;
+                       };
+                       drive_dap1 {
+                               nvidia,pins = "drive_dap1";
+                               nvidia,high-speed-mode = <0>;
+                               nvidia,schmitt = <1>;
+                               nvidia,low-power-mode = <0>;
+                               nvidia,pull-down-strength = <0>;
+                               nvidia,pull-up-strength = <0>;
+                               nvidia,slew-rate-rising = <0>;
+                               nvidia,slew-rate-falling = <0>;
+                       };
+               };
+       };
+
+       i2s@70002800 {
+               status = "okay";
+       };
+
+       serial@70006000 {
+               status = "okay";
+               clock-frequency = <216000000>;
+       };
+
+       i2c@7000d000 {
+               status = "okay";
+               clock-frequency = <100000>;
+
+               codec: codec@1a {
+                       compatible = "wlf,wm8753";
+                       reg = <0x1a>;
+               };
+
+               tca6416: gpio@20 {
+                       compatible = "ti,tca6416";
+                       reg = <0x20>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+               };
+       };
+
+       usb@c5000000 {
+               status = "okay";
+               nvidia,vbus-gpio = <&tca6416 0 0>; /* GPIO_PMU0 */
+       };
+
+       usb@c5008000 {
+               status = "okay";
+               nvidia,vbus-gpio = <&tca6416 1 0>; /* GPIO_PMU1 */
+       };
+
+       sdhci@c8000400 {
+               status = "okay";
+               wp-gpios = <&gpio 173 0>; /* gpio PV5 */
+               bus-width = <8>;
+       };
+
+       sdhci@c8000600 {
+               status = "okay";
+               bus-width = <8>;
+       };
+
+       sound {
+               compatible = "nvidia,tegra-audio-wm8753-whistler",
+                            "nvidia,tegra-audio-wm8753";
+               nvidia,model = "NVIDIA Tegra Whistler";
+
+               nvidia,audio-routing =
+                       "Headphone Jack", "LOUT1",
+                       "Headphone Jack", "ROUT1",
+                       "MIC2", "Mic Jack",
+                       "MIC2N", "Mic Jack";
+
+               nvidia,i2s-controller = <&tegra_i2s1>;
+               nvidia,audio-codec = <&codec>;
+       };
+};
index c417d67e902755df968f812a9fe4f94101cbb796..9f1921634eb7b8ab19c671fc2de17f0d44a50fc4 100644 (file)
@@ -72,7 +72,7 @@
                reg = <0x70002800 0x200>;
                interrupts = <0 13 0x04>;
                nvidia,dma-request-selector = <&apbdma 2>;
-               status = "disable";
+               status = "disabled";
        };
 
        tegra_i2s2: i2s@70002a00 {
@@ -80,7 +80,7 @@
                reg = <0x70002a00 0x200>;
                interrupts = <0 3 0x04>;
                nvidia,dma-request-selector = <&apbdma 1>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006000 {
@@ -88,7 +88,7 @@
                reg = <0x70006000 0x40>;
                reg-shift = <2>;
                interrupts = <0 36 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006040 {
@@ -96,7 +96,7 @@
                reg = <0x70006040 0x40>;
                reg-shift = <2>;
                interrupts = <0 37 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006200 {
                reg = <0x70006200 0x100>;
                reg-shift = <2>;
                interrupts = <0 46 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006300 {
                reg = <0x70006300 0x100>;
                reg-shift = <2>;
                interrupts = <0 90 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006400 {
                reg = <0x70006400 0x100>;
                reg-shift = <2>;
                interrupts = <0 91 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000c000 {
                interrupts = <0 38 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000c400 {
                interrupts = <0 84 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000c500 {
                interrupts = <0 92 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000d000 {
                interrupts = <0 53 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        pmc {
                reg = <0x7000e400 0x400>;
        };
 
-       mc {
+       memory-controller@0x7000f000 {
                compatible = "nvidia,tegra20-mc";
                reg = <0x7000f000 0x024
                       0x7000f03c 0x3c4>;
                       0x58000000 0x02000000>;  /* GART aperture */
        };
 
-       emc {
+       memory-controller@0x7000f400 {
                compatible = "nvidia,tegra20-emc";
                reg = <0x7000f400 0x200>;
                #address-cells = <1>;
                interrupts = <0 20 0x04>;
                phy_type = "utmi";
                nvidia,has-legacy-mode;
-               status = "disable";
+               status = "disabled";
        };
 
        usb@c5004000 {
                reg = <0xc5004000 0x4000>;
                interrupts = <0 21 0x04>;
                phy_type = "ulpi";
-               status = "disable";
+               status = "disabled";
        };
 
        usb@c5008000 {
                reg = <0xc5008000 0x4000>;
                interrupts = <0 97 0x04>;
                phy_type = "utmi";
-               status = "disable";
+               status = "disabled";
        };
 
        sdhci@c8000000 {
                compatible = "nvidia,tegra20-sdhci";
                reg = <0xc8000000 0x200>;
                interrupts = <0 14 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        sdhci@c8000200 {
                compatible = "nvidia,tegra20-sdhci";
                reg = <0xc8000200 0x200>;
                interrupts = <0 15 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        sdhci@c8000400 {
                compatible = "nvidia,tegra20-sdhci";
                reg = <0xc8000400 0x200>;
                interrupts = <0 19 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        sdhci@c8000600 {
                compatible = "nvidia,tegra20-sdhci";
                reg = <0xc8000600 0x200>;
                interrupts = <0 31 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        pmu {
diff --git a/arch/arm/boot/dts/tegra30-cardhu.dts b/arch/arm/boot/dts/tegra30-cardhu.dts
new file mode 100644 (file)
index 0000000..c169bce
--- /dev/null
@@ -0,0 +1,171 @@
+/dts-v1/;
+
+/include/ "tegra30.dtsi"
+
+/ {
+       model = "NVIDIA Tegra30 Cardhu evaluation board";
+       compatible = "nvidia,cardhu", "nvidia,tegra30";
+
+       memory {
+               reg = <0x80000000 0x40000000>;
+       };
+
+       pinmux {
+               pinctrl-names = "default";
+               pinctrl-0 = <&state_default>;
+
+               state_default: pinmux {
+                       sdmmc1_clk_pz0 {
+                               nvidia,pins = "sdmmc1_clk_pz0";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <0>;
+                       };
+                       sdmmc1_cmd_pz1 {
+                               nvidia,pins =   "sdmmc1_cmd_pz1",
+                                               "sdmmc1_dat0_py7",
+                                               "sdmmc1_dat1_py6",
+                                               "sdmmc1_dat2_py5",
+                                               "sdmmc1_dat3_py4";
+                               nvidia,function = "sdmmc1";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <0>;
+                       };
+                       sdmmc4_clk_pcc4 {
+                               nvidia,pins =   "sdmmc4_clk_pcc4",
+                                               "sdmmc4_rst_n_pcc3";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <0>;
+                       };
+                       sdmmc4_dat0_paa0 {
+                               nvidia,pins =   "sdmmc4_dat0_paa0",
+                                               "sdmmc4_dat1_paa1",
+                                               "sdmmc4_dat2_paa2",
+                                               "sdmmc4_dat3_paa3",
+                                               "sdmmc4_dat4_paa4",
+                                               "sdmmc4_dat5_paa5",
+                                               "sdmmc4_dat6_paa6",
+                                               "sdmmc4_dat7_paa7";
+                               nvidia,function = "sdmmc4";
+                               nvidia,pull = <2>;
+                               nvidia,tristate = <0>;
+                       };
+                       dap2_fs_pa2 {
+                               nvidia,pins =   "dap2_fs_pa2",
+                                               "dap2_sclk_pa3",
+                                               "dap2_din_pa4",
+                                               "dap2_dout_pa5";
+                               nvidia,function = "i2s1";
+                               nvidia,pull = <0>;
+                               nvidia,tristate = <0>;
+                       };
+               };
+       };
+
+       serial@70006000 {
+               status = "okay";
+               clock-frequency = <408000000>;
+       };
+
+       i2c@7000c000 {
+               status = "okay";
+               clock-frequency = <100000>;
+       };
+
+       i2c@7000c400 {
+               status = "okay";
+               clock-frequency = <100000>;
+       };
+
+       i2c@7000c500 {
+               status = "okay";
+               clock-frequency = <100000>;
+
+               /* ALS and Proximity sensor */
+               isl29028@44 {
+                       compatible = "isil,isl29028";
+                       reg = <0x44>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <88 0x04>; /*gpio PL0 */
+               };
+       };
+
+       i2c@7000c700 {
+               status = "okay";
+               clock-frequency = <100000>;
+       };
+
+       i2c@7000d000 {
+               status = "okay";
+               clock-frequency = <100000>;
+
+               wm8903: wm8903@1a {
+                       compatible = "wlf,wm8903";
+                       reg = <0x1a>;
+                       interrupt-parent = <&gpio>;
+                       interrupts = <179 0x04>; /* gpio PW3 */
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       micdet-cfg = <0>;
+                       micdet-delay = <100>;
+                       gpio-cfg = <0xffffffff 0xffffffff 0 0xffffffff 0xffffffff>;
+               };
+
+               tps62361 {
+                       compatible = "ti,tps62361";
+                       reg = <0x60>;
+
+                       regulator-name = "tps62361-vout";
+                       regulator-min-microvolt = <500000>;
+                       regulator-max-microvolt = <1500000>;
+                       regulator-boot-on;
+                       regulator-always-on;
+                       ti,vsel0-state-high;
+                       ti,vsel1-state-high;
+               };
+       };
+
+       ahub {
+               i2s@70080400 {
+                       status = "okay";
+               };
+       };
+
+       sdhci@78000000 {
+               status = "okay";
+               cd-gpios = <&gpio 69 0>; /* gpio PI5 */
+               wp-gpios = <&gpio 155 0>; /* gpio PT3 */
+               power-gpios = <&gpio 31 0>; /* gpio PD7 */
+               bus-width = <4>;
+       };
+
+       sdhci@78000600 {
+               status = "okay";
+               bus-width = <8>;
+       };
+
+       sound {
+               compatible = "nvidia,tegra-audio-wm8903-cardhu",
+                            "nvidia,tegra-audio-wm8903";
+               nvidia,model = "NVIDIA Tegra Cardhu";
+
+               nvidia,audio-routing =
+                       "Headphone Jack", "HPOUTR",
+                       "Headphone Jack", "HPOUTL",
+                       "Int Spk", "ROP",
+                       "Int Spk", "RON",
+                       "Int Spk", "LOP",
+                       "Int Spk", "LON",
+                       "Mic Jack", "MICBIAS",
+                       "IN1L", "Mic Jack";
+
+               nvidia,i2s-controller = <&tegra_i2s1>;
+               nvidia,audio-codec = <&wm8903>;
+
+               nvidia,spkr-en-gpios = <&wm8903 2 0>;
+               nvidia,hp-det-gpios = <&gpio 178 0>; /* gpio PW2 */
+       };
+};
index 2dcc09e784b58713cb514fe89044cd821c6a82e3..da740191771f8493f1734636a88244869be5abff 100644 (file)
@@ -82,7 +82,7 @@
                reg = <0x70006000 0x40>;
                reg-shift = <2>;
                interrupts = <0 36 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006040 {
@@ -90,7 +90,7 @@
                reg = <0x70006040 0x40>;
                reg-shift = <2>;
                interrupts = <0 37 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006200 {
@@ -98,7 +98,7 @@
                reg = <0x70006200 0x100>;
                reg-shift = <2>;
                interrupts = <0 46 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006300 {
                reg = <0x70006300 0x100>;
                reg-shift = <2>;
                interrupts = <0 90 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        serial@70006400 {
                reg = <0x70006400 0x100>;
                reg-shift = <2>;
                interrupts = <0 91 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000c000 {
                interrupts = <0 38 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000c400 {
                interrupts = <0 84 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000c500 {
                interrupts = <0 92 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000c700 {
                interrupts = <0 120 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        i2c@7000d000 {
                interrupts = <0 53 0x04>;
                #address-cells = <1>;
                #size-cells = <0>;
-               status = "disable";
+               status = "disabled";
        };
 
        pmc {
                reg = <0x7000e400 0x400>;
        };
 
-       mc {
+       memory-controller {
                compatible = "nvidia,tegra30-mc";
                reg = <0x7000f000 0x010
                       0x7000f03c 0x1b4
                        compatible = "nvidia,tegra30-i2s";
                        reg = <0x70080300 0x100>;
                        nvidia,ahub-cif-ids = <4 4>;
-                       status = "disable";
+                       status = "disabled";
                };
 
                tegra_i2s1: i2s@70080400 {
                        compatible = "nvidia,tegra30-i2s";
                        reg = <0x70080400 0x100>;
                        nvidia,ahub-cif-ids = <5 5>;
-                       status = "disable";
+                       status = "disabled";
                };
 
                tegra_i2s2: i2s@70080500 {
                        compatible = "nvidia,tegra30-i2s";
                        reg = <0x70080500 0x100>;
                        nvidia,ahub-cif-ids = <6 6>;
-                       status = "disable";
+                       status = "disabled";
                };
 
                tegra_i2s3: i2s@70080600 {
                        compatible = "nvidia,tegra30-i2s";
                        reg = <0x70080600 0x100>;
                        nvidia,ahub-cif-ids = <7 7>;
-                       status = "disable";
+                       status = "disabled";
                };
 
                tegra_i2s4: i2s@70080700 {
                        compatible = "nvidia,tegra30-i2s";
                        reg = <0x70080700 0x100>;
                        nvidia,ahub-cif-ids = <8 8>;
-                       status = "disable";
+                       status = "disabled";
                };
        };
 
                compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
                reg = <0x78000000 0x200>;
                interrupts = <0 14 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        sdhci@78000200 {
                compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
                reg = <0x78000200 0x200>;
                interrupts = <0 15 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        sdhci@78000400 {
                compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
                reg = <0x78000400 0x200>;
                interrupts = <0 19 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        sdhci@78000600 {
                compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
                reg = <0x78000600 0x200>;
                interrupts = <0 31 0x04>;
-               status = "disable";
+               status = "disabled";
        };
 
        pmu {
index 16076e2d093410b25dd3f8e1f43e38ef57f8ffd7..d8a827bd2bf3728984621d1c45d90b640e8373db 100644 (file)
@@ -55,6 +55,8 @@
                        reg-io-width = <4>;
                        smsc,irq-active-high;
                        smsc,irq-push-pull;
+                       vdd33a-supply = <&v2m_fixed_3v3>;
+                       vddvario-supply = <&v2m_fixed_3v3>;
                };
 
                usb@2,03000000 {
                        v2m_timer23: timer@120000 {
                                compatible = "arm,sp804", "arm,primecell";
                                reg = <0x120000 0x1000>;
+                               interrupts = <3>;
                        };
 
                        /* DVI I2C bus */
                                interrupts = <14>;
                        };
                };
+
+               v2m_fixed_3v3: fixedregulator@0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "3V3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
        };
 };
index a6c9c7c82d5357aee7640b6176dc71789003e364..dba53fd026bb3692ecf33d69d237a2f9356c4bd1 100644 (file)
@@ -54,6 +54,8 @@
                        reg-io-width = <4>;
                        smsc,irq-active-high;
                        smsc,irq-push-pull;
+                       vdd33a-supply = <&v2m_fixed_3v3>;
+                       vddvario-supply = <&v2m_fixed_3v3>;
                };
 
                usb@3,03000000 {
                        v2m_timer23: timer@12000 {
                                compatible = "arm,sp804", "arm,primecell";
                                reg = <0x12000 0x1000>;
+                               interrupts = <3>;
                        };
 
                        /* DVI I2C bus */
                                interrupts = <14>;
                        };
                };
+
+               v2m_fixed_3v3: fixedregulator@0 {
+                       compatible = "regulator-fixed";
+                       regulator-name = "3V3";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+                       regulator-always-on;
+               };
        };
 };
index 7e1091d91af8b9d999b795414ebf0110c42b65c0..d12b34ca05685fd04b0c500088c74740bcacfc84 100644 (file)
@@ -14,8 +14,8 @@
        arm,hbi = <0x237>;
        compatible = "arm,vexpress,v2p-ca15,tc1", "arm,vexpress,v2p-ca15", "arm,vexpress";
        interrupt-parent = <&gic>;
-       #address-cells = <1>;
-       #size-cells = <1>;
+       #address-cells = <2>;
+       #size-cells = <2>;
 
        chosen { };
 
 
        memory@80000000 {
                device_type = "memory";
-               reg = <0x80000000 0x40000000>;
+               reg = <0 0x80000000 0 0x40000000>;
        };
 
        hdlcd@2b000000 {
                compatible = "arm,hdlcd";
-               reg = <0x2b000000 0x1000>;
+               reg = <0 0x2b000000 0 0x1000>;
                interrupts = <0 85 4>;
        };
 
        memory-controller@2b0a0000 {
                compatible = "arm,pl341", "arm,primecell";
-               reg = <0x2b0a0000 0x1000>;
+               reg = <0 0x2b0a0000 0 0x1000>;
        };
 
        wdt@2b060000 {
                compatible = "arm,sp805", "arm,primecell";
-               reg = <0x2b060000 0x1000>;
+               reg = <0 0x2b060000 0 0x1000>;
                interrupts = <98>;
        };
 
                #interrupt-cells = <3>;
                #address-cells = <0>;
                interrupt-controller;
-               reg = <0x2c001000 0x1000>,
-                     <0x2c002000 0x1000>,
-                     <0x2c004000 0x2000>,
-                     <0x2c006000 0x2000>;
+               reg = <0 0x2c001000 0 0x1000>,
+                     <0 0x2c002000 0 0x1000>,
+                     <0 0x2c004000 0 0x2000>,
+                     <0 0x2c006000 0 0x2000>;
                interrupts = <1 9 0xf04>;
        };
 
        memory-controller@7ffd0000 {
                compatible = "arm,pl354", "arm,primecell";
-               reg = <0x7ffd0000 0x1000>;
+               reg = <0 0x7ffd0000 0 0x1000>;
                interrupts = <0 86 4>,
                             <0 87 4>;
        };
 
        dma@7ffb0000 {
                compatible = "arm,pl330", "arm,primecell";
-               reg = <0x7ffb0000 0x1000>;
+               reg = <0 0x7ffb0000 0 0x1000>;
                interrupts = <0 92 4>,
                             <0 88 4>,
                             <0 89 4>,
        };
 
        motherboard {
-               ranges = <0 0 0x08000000 0x04000000>,
-                        <1 0 0x14000000 0x04000000>,
-                        <2 0 0x18000000 0x04000000>,
-                        <3 0 0x1c000000 0x04000000>,
-                        <4 0 0x0c000000 0x04000000>,
-                        <5 0 0x10000000 0x04000000>;
+               ranges = <0 0 0 0x08000000 0x04000000>,
+                        <1 0 0 0x14000000 0x04000000>,
+                        <2 0 0 0x18000000 0x04000000>,
+                        <3 0 0 0x1c000000 0x04000000>,
+                        <4 0 0 0x0c000000 0x04000000>,
+                        <5 0 0 0x10000000 0x04000000>;
 
                interrupt-map-mask = <0 0 63>;
                interrupt-map = <0 0  0 &gic 0  0 4>,
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
new file mode 100644 (file)
index 0000000..4890a81
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * ARM Ltd. Versatile Express
+ *
+ * CoreTile Express A15x2 A7x3
+ * Cortex-A15_A7 MPCore (V2P-CA15_A7)
+ *
+ * HBI-0249A
+ */
+
+/dts-v1/;
+
+/ {
+       model = "V2P-CA15_CA7";
+       arm,hbi = <0x249>;
+       compatible = "arm,vexpress,v2p-ca15_a7", "arm,vexpress";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       chosen { };
+
+       aliases {
+               serial0 = &v2m_serial0;
+               serial1 = &v2m_serial1;
+               serial2 = &v2m_serial2;
+               serial3 = &v2m_serial3;
+               i2c0 = &v2m_i2c_dvi;
+               i2c1 = &v2m_i2c_pcie;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu0: cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a15";
+                       reg = <0>;
+               };
+
+               cpu1: cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a15";
+                       reg = <1>;
+               };
+
+/* A7s disabled till big.LITTLE patches are available...
+               cpu2: cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x100>;
+               };
+
+               cpu3: cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x101>;
+               };
+
+               cpu4: cpu@4 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a7";
+                       reg = <0x102>;
+               };
+*/
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0 0x80000000 0 0x40000000>;
+       };
+
+       wdt@2a490000 {
+               compatible = "arm,sp805", "arm,primecell";
+               reg = <0 0x2a490000 0 0x1000>;
+               interrupts = <98>;
+       };
+
+       hdlcd@2b000000 {
+               compatible = "arm,hdlcd";
+               reg = <0 0x2b000000 0 0x1000>;
+               interrupts = <0 85 4>;
+       };
+
+       memory-controller@2b0a0000 {
+               compatible = "arm,pl341", "arm,primecell";
+               reg = <0 0x2b0a0000 0 0x1000>;
+       };
+
+       gic: interrupt-controller@2c001000 {
+               compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic";
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               interrupt-controller;
+               reg = <0 0x2c001000 0 0x1000>,
+                     <0 0x2c002000 0 0x1000>,
+                     <0 0x2c004000 0 0x2000>,
+                     <0 0x2c006000 0 0x2000>;
+               interrupts = <1 9 0xf04>;
+       };
+
+       memory-controller@7ffd0000 {
+               compatible = "arm,pl354", "arm,primecell";
+               reg = <0 0x7ffd0000 0 0x1000>;
+               interrupts = <0 86 4>,
+                            <0 87 4>;
+       };
+
+       dma@7ff00000 {
+               compatible = "arm,pl330", "arm,primecell";
+               reg = <0 0x7ff00000 0 0x1000>;
+               interrupts = <0 92 4>,
+                            <0 88 4>,
+                            <0 89 4>,
+                            <0 90 4>,
+                            <0 91 4>;
+       };
+
+       timer {
+               compatible = "arm,armv7-timer";
+               interrupts = <1 13 0xf08>,
+                            <1 14 0xf08>,
+                            <1 11 0xf08>,
+                            <1 10 0xf08>;
+       };
+
+       pmu {
+               compatible = "arm,cortex-a15-pmu", "arm,cortex-a9-pmu";
+               interrupts = <0 68 4>,
+                            <0 69 4>;
+       };
+
+       motherboard {
+               ranges = <0 0 0 0x08000000 0x04000000>,
+                        <1 0 0 0x14000000 0x04000000>,
+                        <2 0 0 0x18000000 0x04000000>,
+                        <3 0 0 0x1c000000 0x04000000>,
+                        <4 0 0 0x0c000000 0x04000000>,
+                        <5 0 0 0x10000000 0x04000000>;
+
+               interrupt-map-mask = <0 0 63>;
+               interrupt-map = <0 0  0 &gic 0  0 4>,
+                               <0 0  1 &gic 0  1 4>,
+                               <0 0  2 &gic 0  2 4>,
+                               <0 0  3 &gic 0  3 4>,
+                               <0 0  4 &gic 0  4 4>,
+                               <0 0  5 &gic 0  5 4>,
+                               <0 0  6 &gic 0  6 4>,
+                               <0 0  7 &gic 0  7 4>,
+                               <0 0  8 &gic 0  8 4>,
+                               <0 0  9 &gic 0  9 4>,
+                               <0 0 10 &gic 0 10 4>,
+                               <0 0 11 &gic 0 11 4>,
+                               <0 0 12 &gic 0 12 4>,
+                               <0 0 13 &gic 0 13 4>,
+                               <0 0 14 &gic 0 14 4>,
+                               <0 0 15 &gic 0 15 4>,
+                               <0 0 16 &gic 0 16 4>,
+                               <0 0 17 &gic 0 17 4>,
+                               <0 0 18 &gic 0 18 4>,
+                               <0 0 19 &gic 0 19 4>,
+                               <0 0 20 &gic 0 20 4>,
+                               <0 0 21 &gic 0 21 4>,
+                               <0 0 22 &gic 0 22 4>,
+                               <0 0 23 &gic 0 23 4>,
+                               <0 0 24 &gic 0 24 4>,
+                               <0 0 25 &gic 0 25 4>,
+                               <0 0 26 &gic 0 26 4>,
+                               <0 0 27 &gic 0 27 4>,
+                               <0 0 28 &gic 0 28 4>,
+                               <0 0 29 &gic 0 29 4>,
+                               <0 0 30 &gic 0 30 4>,
+                               <0 0 31 &gic 0 31 4>,
+                               <0 0 32 &gic 0 32 4>,
+                               <0 0 33 &gic 0 33 4>,
+                               <0 0 34 &gic 0 34 4>,
+                               <0 0 35 &gic 0 35 4>,
+                               <0 0 36 &gic 0 36 4>,
+                               <0 0 37 &gic 0 37 4>,
+                               <0 0 38 &gic 0 38 4>,
+                               <0 0 39 &gic 0 39 4>,
+                               <0 0 40 &gic 0 40 4>,
+                               <0 0 41 &gic 0 41 4>,
+                               <0 0 42 &gic 0 42 4>;
+       };
+};
+
+/include/ "vexpress-v2m-rs1.dtsi"
diff --git a/arch/arm/configs/exynos_defconfig b/arch/arm/configs/exynos_defconfig
new file mode 100644 (file)
index 0000000..e40b435
--- /dev/null
@@ -0,0 +1,92 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_ARCH_EXYNOS=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=1
+CONFIG_S3C24XX_PWM=y
+CONFIG_ARCH_EXYNOS5=y
+CONFIG_MACH_EXYNOS4_DT=y
+CONFIG_MACH_EXYNOS5_DT=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_ARM_ATAG_DTB_COMPAT=y
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc mem=256M"
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_RFKILL_REGULATOR=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_NETDEVICES=y
+CONFIG_SMSC911X=y
+CONFIG_USB_USBNET=y
+CONFIG_USB_NET_SMSC75XX=y
+CONFIG_USB_NET_SMSC95XX=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+# CONFIG_HWMON is not set
+CONFIG_MFD_TPS65090=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_TPS65090=y
+CONFIG_FB=y
+CONFIG_EXYNOS_VIDEO=y
+CONFIG_EXYNOS_MIPI_DSI=y
+CONFIG_EXYNOS_DP=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_7x14=y
+CONFIG_LOGO=y
+CONFIG_USB=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CRC_CCITT=y
index e05a2f1665a78c1b6929271aed7b69a054247ef3..78ed575feb1abac028168ab3ab847694165c68c2 100644 (file)
@@ -2,7 +2,10 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
 CONFIG_EXPERT=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
@@ -36,8 +39,6 @@ CONFIG_MACH_IMX27IPCAM=y
 CONFIG_MACH_IMX27_DT=y
 CONFIG_MXC_IRQ_PRIOR=y
 CONFIG_MXC_PWM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -46,7 +47,6 @@ CONFIG_FPE_NWFPE=y
 CONFIG_FPE_NWFPE_XP=y
 CONFIG_PM_DEBUG=y
 CONFIG_NET=y
-CONFIG_SMSC911X=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
@@ -70,31 +70,31 @@ CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_ADV_OPTIONS=y
 CONFIG_MTD_CFI_GEOMETRY=y
 # CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
 # CONFIG_MTD_CFI_I2 is not set
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_MXC=y
 CONFIG_MTD_UBI=y
-CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT24=y
 CONFIG_EEPROM_AT25=y
+CONFIG_ATA=y
+CONFIG_PATA_IMX=y
 CONFIG_NETDEVICES=y
 CONFIG_CS89x0=y
 CONFIG_CS89x0_PLATFORM=y
 CONFIG_DM9000=y
 CONFIG_SMC91X=y
 CONFIG_SMC911X=y
+CONFIG_SMSC911X=y
 CONFIG_SMSC_PHY=y
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
+CONFIG_KEYBOARD_IMX=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ADS7846=m
-CONFIG_TOUCHSCREEN_MC13783=m
-# CONFIG_SERIO is not set
+CONFIG_TOUCHSCREEN_MC13783=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_8250=m
 CONFIG_SERIAL_IMX=y
@@ -113,31 +113,23 @@ CONFIG_HWMON=m
 CONFIG_SENSORS_MC13783_ADC=m
 CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
-CONFIG_MFD_MC13XXX=y
+CONFIG_MFD_MC13XXX_SPI=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_MC13783=y
 CONFIG_REGULATOR_MC13892=y
-CONFIG_FB=y
-CONFIG_FB_IMX=y
-CONFIG_BACKLIGHT_LCD_SUPPORT=y
-CONFIG_LCD_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_LCD_L4F00242T03=y
 CONFIG_MEDIA_SUPPORT=y
 CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L2_COMMON=y
-CONFIG_VIDEO_MEDIA=y
-CONFIG_VIDEO_V4L2=y
-CONFIG_VIDEOBUF_GEN=y
-CONFIG_VIDEOBUF_DMA_CONTIG=y
-CONFIG_VIDEOBUF2_CORE=y
-CONFIG_VIDEO_CAPTURE_DRIVERS=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_OV2640=y
-CONFIG_VIDEO_MX2_HOSTSUPPORT=y
 CONFIG_VIDEO_MX2=y
+CONFIG_FB=y
+CONFIG_FB_IMX=y
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_L4F00242T03=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_BACKLIGHT_PWM=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FONTS=y
@@ -152,13 +144,17 @@ CONFIG_SND_IMX_SOC=y
 CONFIG_SND_SOC_MX27VIS_AIC32X4=y
 CONFIG_SND_SOC_PHYCORE_AC97=y
 CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_SND_SOC_IMX_SGTL5000=y
+CONFIG_SND_SOC_IMX_MC13783=y
 CONFIG_USB_HID=m
 CONFIG_USB=y
-# CONFIG_USB_DEVICE_CLASS is not set
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
 CONFIG_USB_ULPI=y
 CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_ESDHC_IMX=y
 CONFIG_MMC_MXC=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
@@ -173,22 +169,25 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_PCF8563=y
 CONFIG_RTC_DRV_IMXDI=y
+CONFIG_RTC_DRV_MC13XXX=y
 CONFIG_RTC_DRV_MXC=y
 CONFIG_DMADEVICES=y
 CONFIG_IMX_SDMA=y
 CONFIG_IMX_DMA=y
+CONFIG_COMMON_CLK_DEBUG=y
 # CONFIG_IOMMU_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
 # CONFIG_DNOTIFY is not set
 # CONFIG_PROC_PAGE_MONITOR is not set
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_UBIFS_FS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=m
 CONFIG_NLS_CODEPAGE_850=m
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_15=m
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
index b1d3675df72cd2c8abb336e05cd01854b9fe7918..f725b9637b3374a4079c17ca50823f064ea0bb6d 100644 (file)
@@ -2,6 +2,8 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_KERNEL_LZO=y
 CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_LOG_BUF_SHIFT=18
 CONFIG_CGROUPS=y
 CONFIG_RELAY=y
@@ -29,15 +31,12 @@ CONFIG_MACH_MX35_3DS=y
 CONFIG_MACH_VPR200=y
 CONFIG_MACH_IMX51_DT=y
 CONFIG_MACH_MX51_3DS=y
-CONFIG_MACH_EUKREA_CPUIMX51=y
 CONFIG_MACH_EUKREA_CPUIMX51SD=y
 CONFIG_MACH_MX51_EFIKAMX=y
 CONFIG_MACH_MX51_EFIKASB=y
 CONFIG_MACH_IMX53_DT=y
 CONFIG_SOC_IMX6Q=y
 CONFIG_MXC_PWM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_VMSPLIT_2G=y
 CONFIG_PREEMPT_VOLUNTARY=y
@@ -64,17 +63,29 @@ CONFIG_IPV6=y
 # CONFIG_WIRELESS is not set
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
+# CONFIG_STANDALONE is not set
+CONFIG_CONNECTOR=y
 CONFIG_MTD=y
-CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
 CONFIG_MTD_DATAFLASH=y
 CONFIG_MTD_M25P80=y
 CONFIG_MTD_SST25L=y
-# CONFIG_STANDALONE is not set
-CONFIG_CONNECTOR=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_GPMI_NAND=y
+CONFIG_MTD_NAND_MXC=y
+CONFIG_MTD_UBI=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
+CONFIG_EEPROM_AT24=y
+CONFIG_EEPROM_AT25=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_MULTI_LUN=y
@@ -105,8 +116,11 @@ CONFIG_SMSC911X=y
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_IMX=y
 CONFIG_MOUSE_PS2=m
 CONFIG_MOUSE_PS2_ELANTECH=y
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_MC13783=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MMA8450=y
 CONFIG_SERIO_SERPORT=m
@@ -116,6 +130,7 @@ CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_SERIAL_IMX=y
 CONFIG_SERIAL_IMX_CONSOLE=y
 CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_MXC_RNGA=y
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
 CONFIG_I2C_CHARDEV=y
@@ -130,42 +145,37 @@ CONFIG_GPIO_SYSFS=y
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_IMX2_WDT=y
-CONFIG_MFD_MC13XXX=y
+CONFIG_MFD_MC13XXX_SPI=y
+CONFIG_MFD_MC13XXX_I2C=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_MC13783=y
 CONFIG_REGULATOR_MC13892=y
 CONFIG_MEDIA_SUPPORT=y
-CONFIG_VIDEO_V4L2=y
 CONFIG_VIDEO_DEV=y
-CONFIG_VIDEO_V4L2_COMMON=y
-CONFIG_VIDEOBUF_GEN=y
-CONFIG_VIDEOBUF2_CORE=y
-CONFIG_VIDEOBUF2_MEMOPS=y
-CONFIG_VIDEOBUF2_DMA_CONTIG=y
-CONFIG_VIDEO_CAPTURE_DRIVERS=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
 CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_OV2640=y
-CONFIG_MX3_VIDEO=y
 CONFIG_VIDEO_MX3=y
 CONFIG_FB=y
-CONFIG_FB_MX3=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_L4F00242T03=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
-CONFIG_BACKLIGHT_GENERIC=y
-CONFIG_DUMMY_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
 CONFIG_FONTS=y
 CONFIG_FONT_8x8=y
 CONFIG_FONT_8x16=y
 CONFIG_LOGO=y
-CONFIG_LOGO_LINUX_MONO=y
-CONFIG_LOGO_LINUX_VGA16=y
-CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_SOC=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_PHYCORE_AC97=y
+CONFIG_SND_SOC_EUKREA_TLV320=y
+CONFIG_SND_SOC_IMX_SGTL5000=y
+CONFIG_SND_SOC_IMX_MC13783=y
 CONFIG_USB=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MXC=y
@@ -178,9 +188,12 @@ CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
+CONFIG_RTC_DRV_MC13XXX=y
 CONFIG_RTC_DRV_MXC=y
 CONFIG_DMADEVICES=y
 CONFIG_IMX_SDMA=y
+CONFIG_COMMON_CLK_DEBUG=y
+# CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
@@ -204,8 +217,9 @@ CONFIG_MSDOS_FS=m
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_CONFIGFS_FS=m
+CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
@@ -216,14 +230,11 @@ CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_UTF8=y
 CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_FS=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_BUGVERBOSE is not set
 # CONFIG_FTRACE is not set
 # CONFIG_ARM_UNWIND is not set
 CONFIG_SECURITYFS=y
-CONFIG_CRYPTO_DEFLATE=m
-CONFIG_CRYPTO_LZO=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_CCITT=m
index 4fa60547494ad7f160d5b512de2edbe17cd43a77..e42a0e3d4c3a6466375e492eaf5759c0cc0bff30 100644 (file)
@@ -1,5 +1,7 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=16
@@ -16,8 +18,7 @@ CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARCH_LPC32XX=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
+CONFIG_KEYBOARD_GPIO_POLLED=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -52,13 +53,17 @@ CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
+CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_MUSEUM_IDS=y
+CONFIG_MTD_NAND_SLC_LPC32XX=y
+CONFIG_MTD_NAND_MLC_LPC32XX=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=1
 CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_EEPROM_AT24=y
 CONFIG_EEPROM_AT25=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
@@ -79,16 +84,23 @@ CONFIG_LPC_ENET=y
 # CONFIG_NET_VENDOR_STMICRO is not set
 CONFIG_SMSC_PHY=y
 # CONFIG_WLAN is not set
+CONFIG_INPUT_MATRIXKMAP=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_MOUSEDEV_SCREEN_X=240
 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=320
 CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_LPC32XX=y
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_LPC32XX=y
+CONFIG_SERIO_LIBPS2=y
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_HS_LPC32XX=y
+CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -96,7 +108,8 @@ CONFIG_I2C_PNX=y
 CONFIG_SPI=y
 CONFIG_SPI_PL022=y
 CONFIG_GPIO_SYSFS=y
-# CONFIG_HWMON is not set
+CONFIG_SENSORS_DS620=y
+CONFIG_SENSORS_MAX6639=y
 CONFIG_WATCHDOG=y
 CONFIG_PNX4008_WATCHDOG=y
 CONFIG_FB=y
@@ -133,6 +146,8 @@ CONFIG_MMC=y
 CONFIG_MMC_ARMMMCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_PCA9532=y
+CONFIG_LEDS_PCA9532_GPIO=y
 CONFIG_LEDS_GPIO=y
 CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_TIMER=y
@@ -146,10 +161,10 @@ CONFIG_RTC_DRV_DS1374=y
 CONFIG_RTC_DRV_PCF8563=y
 CONFIG_RTC_DRV_LPC32XX=y
 CONFIG_DMADEVICES=y
-CONFIG_AMBA_PL08X=y
 CONFIG_STAGING=y
-CONFIG_IIO=y
 CONFIG_LPC32XX_ADC=y
+CONFIG_MAX517=y
+CONFIG_IIO=y
 CONFIG_EXT2_FS=y
 CONFIG_AUTOFS4_FS=y
 CONFIG_MSDOS_FS=y
@@ -159,7 +174,6 @@ CONFIG_JFFS2_FS=y
 CONFIG_JFFS2_FS_WBUF_VERIFY=y
 CONFIG_CRAMFS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig
new file mode 100644 (file)
index 0000000..2e86b31
--- /dev/null
@@ -0,0 +1,46 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EXPERT=y
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_ARCH_MVEBU=y
+CONFIG_MACH_ARMADA_370_XP=y
+CONFIG_AEABI=y
+CONFIG_HIGHMEM=y
+CONFIG_USE_OF=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_ARM_APPENDED_DTB=y
+CONFIG_VFP=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_CODEPAGE_850=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+CONFIG_NLS_UTF8=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_BUGVERBOSE is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
index 5406c23a02e3b2dafa323300222690094f38326d..ccdb6357fb74065e017d44527a27e8c2c7a3f46d 100644 (file)
@@ -28,6 +28,7 @@ CONFIG_MACH_MX28EVK=y
 CONFIG_MACH_STMP378X_DEVB=y
 CONFIG_MACH_TX28=y
 CONFIG_MACH_M28EVK=y
+CONFIG_MACH_APX4DEVKIT=y
 # CONFIG_ARM_THUMB is not set
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -58,6 +59,9 @@ CONFIG_CAN_FLEXCAN=m
 CONFIG_DEVTMPFS=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 # CONFIG_BLK_DEV is not set
+CONFIG_MTD=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_GPMI_NAND=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
 CONFIG_ENC28J60=y
@@ -77,6 +81,7 @@ CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_MXS_AUART=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
@@ -109,8 +114,10 @@ CONFIG_MMC=y
 CONFIG_MMC_MXS=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=m
+CONFIG_RTC_DRV_STMP=y
 CONFIG_DMADEVICES=y
 CONFIG_MXS_DMA=y
+CONFIG_COMMON_CLK_DEBUG=y
 CONFIG_EXT3_FS=y
 # CONFIG_DNOTIFY is not set
 CONFIG_FSCACHE=m
index 11828e632532accb5ab386ac9a0ffe173c6b9fdf..b152de79fd95373e2f6fd8e34e66a4c360463c3b 100644 (file)
@@ -196,6 +196,7 @@ CONFIG_RTC_DRV_TWL4030=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
 CONFIG_QUOTA=y
 CONFIG_QFMT_V2=y
 CONFIG_MSDOS_FS=y
@@ -235,3 +236,4 @@ CONFIG_CRC_T10DIF=y
 CONFIG_CRC_ITU_T=y
 CONFIG_CRC7=y
 CONFIG_LIBCRC32C=y
+CONFIG_SOC_OMAP5=y
diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
new file mode 100644 (file)
index 0000000..0ac1293
--- /dev/null
@@ -0,0 +1,83 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_CPUSETS=y
+CONFIG_NAMESPACES=y
+CONFIG_EMBEDDED=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_SOCFPGA=y
+CONFIG_MACH_SOCFPGA_CYCLONE5=y
+CONFIG_ARM_THUMBEE=y
+# CONFIG_CACHE_L2X0 is not set
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_NR_CPUS=2
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_NET_KEY_MIGRATE=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=2
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_NETDEVICES=y
+CONFIG_STMMAC_ETH=y
+# CONFIG_STMMAC_PHY_ID_ZERO_WORKAROUND is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_AMBAKMI=y
+CONFIG_LEGACY_PTY_COUNT=16
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+CONFIG_SERIAL_8250_DW=y
+# CONFIG_RTC_HCTOSYS is not set
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+# CONFIG_DNOTIFY is not set
+# CONFIG_INOTIFY_USER is not set
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
+CONFIG_NTFS_RW=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_INFO=y
+CONFIG_ENABLE_DEFAULT_TRACERS=y
+CONFIG_DEBUG_USER=y
+CONFIG_XZ_DEC=y
index 1198dd61c7c49e6b1035082db78f77d09846bbbf..4be9c1e80ee63aac2c5d8239222ec1dcf147e683 100644 (file)
@@ -1,4 +1,6 @@
 CONFIG_EXPERIMENTAL=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CGROUPS=y
@@ -25,14 +27,9 @@ CONFIG_ARCH_TEGRA=y
 CONFIG_ARCH_TEGRA_2x_SOC=y
 CONFIG_ARCH_TEGRA_3x_SOC=y
 CONFIG_MACH_HARMONY=y
-CONFIG_MACH_KAEN=y
 CONFIG_MACH_PAZ00=y
 CONFIG_MACH_TRIMSLICE=y
-CONFIG_MACH_WARIO=y
-CONFIG_MACH_VENTANA=y
 CONFIG_TEGRA_EMC_SCALING_ENABLE=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
@@ -103,19 +100,24 @@ CONFIG_SERIAL_OF_PLATFORM=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_I2C=y
 # CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_PINCTRL=y
 CONFIG_I2C_TEGRA=y
 CONFIG_SPI=y
 CONFIG_SPI_TEGRA=y
+CONFIG_GPIO_TPS65910=y
 CONFIG_POWER_SUPPLY=y
 CONFIG_BATTERY_SBS=y
 CONFIG_SENSORS_LM90=y
 CONFIG_MFD_TPS6586X=y
+CONFIG_MFD_TPS65910=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_VIRTUAL_CONSUMER=y
 CONFIG_REGULATOR_GPIO=y
 CONFIG_REGULATOR_TPS62360=y
 CONFIG_REGULATOR_TPS6586X=y
+CONFIG_REGULATOR_TPS65910=y
 CONFIG_SOUND=y
 CONFIG_SND=y
 # CONFIG_SND_SUPPORT_OLD_API is not set
@@ -126,6 +128,7 @@ CONFIG_SND=y
 # CONFIG_SND_USB is not set
 CONFIG_SND_SOC=y
 CONFIG_SND_SOC_TEGRA=y
+CONFIG_SND_SOC_TEGRA_WM8753=y
 CONFIG_SND_SOC_TEGRA_WM8903=y
 CONFIG_SND_SOC_TEGRA_TRIMSLICE=y
 CONFIG_SND_SOC_TEGRA_ALC5632=y
index febe495d0c6e15777b9e393a50cc08d7fbdd917c..15cb035309f754ca4c5b3e4c4fa718e6a27252ac 100644 (file)
@@ -17,7 +17,7 @@ struct seq_file;
 /*
  * This is internal.  Do not use it.
  */
-extern void init_FIQ(void);
+extern void init_FIQ(int);
 extern int show_fiq_list(struct seq_file *, int);
 
 #ifdef CONFIG_MULTI_IRQ_HANDLER
index c32f8456aa094115b8c28a92df83fc643a15188c..2adda11f712fe02fa2fdaa63e944e17199bd3748 100644 (file)
@@ -122,14 +122,16 @@ void release_fiq(struct fiq_handler *f)
        while (current_fiq->fiq_op(current_fiq->dev_id, 0));
 }
 
+static int fiq_start;
+
 void enable_fiq(int fiq)
 {
-       enable_irq(fiq + FIQ_START);
+       enable_irq(fiq + fiq_start);
 }
 
 void disable_fiq(int fiq)
 {
-       disable_irq(fiq + FIQ_START);
+       disable_irq(fiq + fiq_start);
 }
 
 EXPORT_SYMBOL(set_fiq_handler);
@@ -140,7 +142,8 @@ EXPORT_SYMBOL(release_fiq);
 EXPORT_SYMBOL(enable_fiq);
 EXPORT_SYMBOL(disable_fiq);
 
-void __init init_FIQ(void)
+void __init init_FIQ(int start)
 {
        no_fiq_insn = *(unsigned long *)0xffff001c;
+       fiq_start = start;
 }
index 8349d4e97e2b8b9b7bb5672b2cf974c2cdb74fd0..16cedb42c0c39c0169008e45488b279cd9b32821 100644 (file)
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
-/*
- * No architecture-specific irq_finish function defined in arm/arch/irqs.h.
- */
-#ifndef irq_finish
-#define irq_finish(irq) do { } while (0)
-#endif
-
 unsigned long irq_err_count;
 
 int arch_show_interrupts(struct seq_file *p, int prec)
@@ -85,9 +78,6 @@ void handle_IRQ(unsigned int irq, struct pt_regs *regs)
                generic_handle_irq(irq);
        }
 
-       /* AT91 specific workaround */
-       irq_finish(irq);
-
        irq_exit();
        set_irq_regs(old_regs);
 }
index 19505c0a3f018225dcdc4935e089024e8d03d670..c8050b14e615ef0df3adbee08598b7aaf30a60ff 100644 (file)
@@ -29,12 +29,16 @@ comment "Atmel AT91 Processor"
 config SOC_AT91SAM9
        bool
        select CPU_ARM926T
+       select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
        select AT91_SAM9_TIME
        select AT91_SAM9_SMC
 
 config SOC_AT91RM9200
        bool "AT91RM9200"
        select CPU_ARM920T
+       select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
        select GENERIC_CLOCKEVENTS
        select HAVE_AT91_DBGU0
 
@@ -140,6 +144,8 @@ config ARCH_AT91SAM9G45
 config ARCH_AT91X40
        bool "AT91x40"
        depends on !MMU
+       select MULTI_IRQ_HANDLER
+       select SPARSE_IRQ
        select ARCH_USES_GETTIMEOFFSET
 
 endchoice
index 9e84fe4f2aaa00b2c23107f1e58a949afa7e68bb..30bb7332e30b99a8d45a7c20ed10d9f26ce4e9f2 100644 (file)
@@ -15,7 +15,9 @@ endif
 
 # Keep dtb files sorted alphabetically for each SoC
 # sam9260
+dtb-$(CONFIG_MACH_AT91SAM_DT) += aks-cdu.dtb
 dtb-$(CONFIG_MACH_AT91SAM_DT) += ethernut5.dtb
+dtb-$(CONFIG_MACH_AT91SAM_DT) += evk-pro3.dtb
 dtb-$(CONFIG_MACH_AT91SAM_DT) += tny_a9260.dtb
 dtb-$(CONFIG_MACH_AT91SAM_DT) += usb_a9260.dtb
 # sam9263
index 26917687fc30fd6b981181b79d8d338719d95305..6f50c6722276dcc73f8607b51132bfe40dd077b9 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/at91rm9200.h>
+#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_st.h>
 #include <mach/cpu.h>
index e6b7d0533dd75dad4f6cee4f3458a2a6ddda6581..01fb7325fecce0ef9a015835ff846655b3b4af11 100644 (file)
@@ -41,8 +41,8 @@ static struct resource usbh_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_UHP,
-               .end    = AT91RM9200_ID_UHP,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_UHP,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_UHP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -94,8 +94,8 @@ static struct resource udc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_UDP,
-               .end    = AT91RM9200_ID_UDP,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_UDP,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_UDP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -145,8 +145,8 @@ static struct resource eth_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_EMAC,
-               .end    = AT91RM9200_ID_EMAC,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_EMAC,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_EMAC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -305,8 +305,8 @@ static struct resource mmc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_MCI,
-               .end    = AT91RM9200_ID_MCI,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_MCI,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_MCI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -488,8 +488,8 @@ static struct resource twi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_TWI,
-               .end    = AT91RM9200_ID_TWI,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TWI,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TWI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -532,8 +532,8 @@ static struct resource spi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_SPI,
-               .end    = AT91RM9200_ID_SPI,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_SPI,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_SPI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -598,18 +598,18 @@ static struct resource tcb0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_TC0,
-               .end    = AT91RM9200_ID_TC0,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC0,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC0,
                .flags  = IORESOURCE_IRQ,
        },
        [2] = {
-               .start  = AT91RM9200_ID_TC1,
-               .end    = AT91RM9200_ID_TC1,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC1,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC1,
                .flags  = IORESOURCE_IRQ,
        },
        [3] = {
-               .start  = AT91RM9200_ID_TC2,
-               .end    = AT91RM9200_ID_TC2,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC2,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -628,18 +628,18 @@ static struct resource tcb1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_TC3,
-               .end    = AT91RM9200_ID_TC3,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC3,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC3,
                .flags  = IORESOURCE_IRQ,
        },
        [2] = {
-               .start  = AT91RM9200_ID_TC4,
-               .end    = AT91RM9200_ID_TC4,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC4,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC4,
                .flags  = IORESOURCE_IRQ,
        },
        [3] = {
-               .start  = AT91RM9200_ID_TC5,
-               .end    = AT91RM9200_ID_TC5,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_TC5,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_TC5,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -673,8 +673,8 @@ static struct resource rtc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -729,8 +729,8 @@ static struct resource ssc0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_SSC0,
-               .end    = AT91RM9200_ID_SSC0,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_SSC0,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_SSC0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -771,8 +771,8 @@ static struct resource ssc1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_SSC1,
-               .end    = AT91RM9200_ID_SSC1,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_SSC1,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_SSC1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -813,8 +813,8 @@ static struct resource ssc2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_SSC2,
-               .end    = AT91RM9200_ID_SSC2,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_SSC2,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_SSC2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -897,8 +897,8 @@ static struct resource dbgu_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -935,8 +935,8 @@ static struct resource uart0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_US0,
-               .end    = AT91RM9200_ID_US0,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_US0,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_US0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -984,8 +984,8 @@ static struct resource uart1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_US1,
-               .end    = AT91RM9200_ID_US1,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_US1,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_US1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1035,8 +1035,8 @@ static struct resource uart2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_US2,
-               .end    = AT91RM9200_ID_US2,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_US2,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_US2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1078,8 +1078,8 @@ static struct resource uart3_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91RM9200_ID_US3,
-               .end    = AT91RM9200_ID_US3,
+               .start  = NR_IRQS_LEGACY + AT91RM9200_ID_US3,
+               .end    = NR_IRQS_LEGACY + AT91RM9200_ID_US3,
                .flags  = IORESOURCE_IRQ,
        },
 };
index 2b1e438ed87869320362678421486dc0caa058fd..30c7f26a4668c34e3739955a782ef3ec2befb978 100644 (file)
@@ -20,6 +20,7 @@
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91sam9260.h>
+#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_rstc.h>
 
index 0ded951f785af1f31c7cba305f191a5f137ea096..7b9c2ba396edb854cfd78ddef676250a751e60bc 100644 (file)
@@ -45,8 +45,8 @@ static struct resource usbh_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_UHP,
-               .end    = AT91SAM9260_ID_UHP,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_UHP,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_UHP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -98,8 +98,8 @@ static struct resource udc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_UDP,
-               .end    = AT91SAM9260_ID_UDP,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_UDP,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_UDP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -149,8 +149,8 @@ static struct resource eth_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_EMAC,
-               .end    = AT91SAM9260_ID_EMAC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_EMAC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_EMAC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -223,8 +223,8 @@ static struct resource mmc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_MCI,
-               .end    = AT91SAM9260_ID_MCI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -305,8 +305,8 @@ static struct resource mmc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_MCI,
-               .end    = AT91SAM9260_ID_MCI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_MCI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -496,8 +496,8 @@ static struct resource twi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_TWI,
-               .end    = AT91SAM9260_ID_TWI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TWI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TWI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -540,8 +540,8 @@ static struct resource spi0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_SPI0,
-               .end    = AT91SAM9260_ID_SPI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -566,8 +566,8 @@ static struct resource spi1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_SPI1,
-               .end    = AT91SAM9260_ID_SPI1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_SPI1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -652,18 +652,18 @@ static struct resource tcb0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_TC0,
-               .end    = AT91SAM9260_ID_TC0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC0,
                .flags  = IORESOURCE_IRQ,
        },
        [2] = {
-               .start  = AT91SAM9260_ID_TC1,
-               .end    = AT91SAM9260_ID_TC1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC1,
                .flags  = IORESOURCE_IRQ,
        },
        [3] = {
-               .start  = AT91SAM9260_ID_TC2,
-               .end    = AT91SAM9260_ID_TC2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -682,18 +682,18 @@ static struct resource tcb1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_TC3,
-               .end    = AT91SAM9260_ID_TC3,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC3,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC3,
                .flags  = IORESOURCE_IRQ,
        },
        [2] = {
-               .start  = AT91SAM9260_ID_TC4,
-               .end    = AT91SAM9260_ID_TC4,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC4,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC4,
                .flags  = IORESOURCE_IRQ,
        },
        [3] = {
-               .start  = AT91SAM9260_ID_TC5,
-               .end    = AT91SAM9260_ID_TC5,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_TC5,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_TC5,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -807,8 +807,8 @@ static struct resource ssc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_SSC,
-               .end    = AT91SAM9260_ID_SSC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_SSC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_SSC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -882,8 +882,8 @@ static struct resource dbgu_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -920,8 +920,8 @@ static struct resource uart0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_US0,
-               .end    = AT91SAM9260_ID_US0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -971,8 +971,8 @@ static struct resource uart1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_US1,
-               .end    = AT91SAM9260_ID_US1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1014,8 +1014,8 @@ static struct resource uart2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_US2,
-               .end    = AT91SAM9260_ID_US2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1057,8 +1057,8 @@ static struct resource uart3_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_US3,
-               .end    = AT91SAM9260_ID_US3,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US3,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US3,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1100,8 +1100,8 @@ static struct resource uart4_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_US4,
-               .end    = AT91SAM9260_ID_US4,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US4,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US4,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1138,8 +1138,8 @@ static struct resource uart5_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_US5,
-               .end    = AT91SAM9260_ID_US5,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_US5,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_US5,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1357,8 +1357,8 @@ static struct resource adc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9260_ID_ADC,
-               .end    = AT91SAM9260_ID_ADC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9260_ID_ADC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9260_ID_ADC,
                .flags  = IORESOURCE_IRQ,
        },
 };
index c77d503d09d1c2546a8e73a5ddccb246acb4ddcb..f40762c5fedee898fb836b24556f50499ee2858e 100644 (file)
@@ -19,6 +19,7 @@
 #include <asm/system_misc.h>
 #include <mach/cpu.h>
 #include <mach/at91sam9261.h>
+#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_rstc.h>
 
index 9295e90b08ff523fa93817ca9121eb15d9d5a2bb..8df5c1bdff92f1d1194fa9d64da61e2aa9bc2598 100644 (file)
@@ -45,8 +45,8 @@ static struct resource usbh_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_UHP,
-               .end    = AT91SAM9261_ID_UHP,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_UHP,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_UHP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -98,8 +98,8 @@ static struct resource udc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_UDP,
-               .end    = AT91SAM9261_ID_UDP,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_UDP,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_UDP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -148,8 +148,8 @@ static struct resource mmc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_MCI,
-               .end    = AT91SAM9261_ID_MCI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_MCI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_MCI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -310,8 +310,8 @@ static struct resource twi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_TWI,
-               .end    = AT91SAM9261_ID_TWI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_TWI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_TWI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -354,8 +354,8 @@ static struct resource spi0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_SPI0,
-               .end    = AT91SAM9261_ID_SPI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -380,8 +380,8 @@ static struct resource spi1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_SPI1,
-               .end    = AT91SAM9261_ID_SPI1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SPI1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -468,8 +468,8 @@ static struct resource lcdc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_LCDC,
-               .end    = AT91SAM9261_ID_LCDC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_LCDC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_LCDC,
                .flags  = IORESOURCE_IRQ,
        },
 #if defined(CONFIG_FB_INTSRAM)
@@ -566,18 +566,18 @@ static struct resource tcb_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_TC0,
-               .end    = AT91SAM9261_ID_TC0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_TC0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_TC0,
                .flags  = IORESOURCE_IRQ,
        },
        [2] = {
-               .start  = AT91SAM9261_ID_TC1,
-               .end    = AT91SAM9261_ID_TC1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_TC1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_TC1,
                .flags  = IORESOURCE_IRQ,
        },
        [3] = {
-               .start  = AT91SAM9261_ID_TC2,
-               .end    = AT91SAM9261_ID_TC2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_TC2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_TC2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -689,8 +689,8 @@ static struct resource ssc0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_SSC0,
-               .end    = AT91SAM9261_ID_SSC0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -731,8 +731,8 @@ static struct resource ssc1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_SSC1,
-               .end    = AT91SAM9261_ID_SSC1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -773,8 +773,8 @@ static struct resource ssc2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_SSC2,
-               .end    = AT91SAM9261_ID_SSC2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_SSC2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -857,8 +857,8 @@ static struct resource dbgu_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -895,8 +895,8 @@ static struct resource uart0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_US0,
-               .end    = AT91SAM9261_ID_US0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_US0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_US0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -938,8 +938,8 @@ static struct resource uart1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_US1,
-               .end    = AT91SAM9261_ID_US1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_US1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_US1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -981,8 +981,8 @@ static struct resource uart2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9261_ID_US2,
-               .end    = AT91SAM9261_ID_US2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9261_ID_US2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9261_ID_US2,
                .flags  = IORESOURCE_IRQ,
        },
 };
index ed91c7e9f7c20312ccc9f25564187c84f8e118af..84b38105231e91a52df082f3828f2042c1178201 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/at91sam9263.h>
+#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_rstc.h>
 
index 175e0009eaa9b886a90694dcf5cb1d880e2e38ad..eb6bbf86fb9f597cc7424a52b459bb04ecff2326 100644 (file)
@@ -44,8 +44,8 @@ static struct resource usbh_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_UHP,
-               .end    = AT91SAM9263_ID_UHP,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_UHP,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_UHP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -104,8 +104,8 @@ static struct resource udc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_UDP,
-               .end    = AT91SAM9263_ID_UDP,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_UDP,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_UDP,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -155,8 +155,8 @@ static struct resource eth_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_EMAC,
-               .end    = AT91SAM9263_ID_EMAC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_EMAC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_EMAC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -229,8 +229,8 @@ static struct resource mmc0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_MCI0,
-               .end    = AT91SAM9263_ID_MCI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -254,8 +254,8 @@ static struct resource mmc1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_MCI1,
-               .end    = AT91SAM9263_ID_MCI1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_MCI1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -567,8 +567,8 @@ static struct resource twi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_TWI,
-               .end    = AT91SAM9263_ID_TWI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_TWI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_TWI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -611,8 +611,8 @@ static struct resource spi0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_SPI0,
-               .end    = AT91SAM9263_ID_SPI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -637,8 +637,8 @@ static struct resource spi1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_SPI1,
-               .end    = AT91SAM9263_ID_SPI1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_SPI1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -725,8 +725,8 @@ static struct resource ac97_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_AC97C,
-               .end    = AT91SAM9263_ID_AC97C,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_AC97C,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_AC97C,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -776,8 +776,8 @@ static struct resource can_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_CAN,
-               .end    = AT91SAM9263_ID_CAN,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_CAN,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_CAN,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -816,8 +816,8 @@ static struct resource lcdc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_LCDC,
-               .end    = AT91SAM9263_ID_LCDC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_LCDC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_LCDC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -883,8 +883,8 @@ struct resource isi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_ISI,
-               .end    = AT91SAM9263_ID_ISI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_ISI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_ISI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -940,8 +940,8 @@ static struct resource tcb_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_TCB,
-               .end    = AT91SAM9263_ID_TCB,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_TCB,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_TCB,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1108,8 +1108,8 @@ static struct resource pwm_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_PWMC,
-               .end    = AT91SAM9263_ID_PWMC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_PWMC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_PWMC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1161,8 +1161,8 @@ static struct resource ssc0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_SSC0,
-               .end    = AT91SAM9263_ID_SSC0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1203,8 +1203,8 @@ static struct resource ssc1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_SSC1,
-               .end    = AT91SAM9263_ID_SSC1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_SSC1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1284,8 +1284,8 @@ static struct resource dbgu_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1322,8 +1322,8 @@ static struct resource uart0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_US0,
-               .end    = AT91SAM9263_ID_US0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_US0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_US0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1365,8 +1365,8 @@ static struct resource uart1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_US1,
-               .end    = AT91SAM9263_ID_US1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_US1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_US1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1408,8 +1408,8 @@ static struct resource uart2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9263_ID_US2,
-               .end    = AT91SAM9263_ID_US2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9263_ID_US2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9263_ID_US2,
                .flags  = IORESOURCE_IRQ,
        },
 };
index a94758b42737a3d33a3cdce0bee439103ea8f7ab..ffc0957d7623ebe91319ab6a5810c0642ab328df 100644 (file)
@@ -137,7 +137,7 @@ static struct irqaction at91sam926x_pit_irq = {
        .name           = "at91_tick",
        .flags          = IRQF_SHARED | IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
        .handler        = at91sam926x_pit_interrupt,
-       .irq            = AT91_ID_SYS,
+       .irq            = NR_IRQS_LEGACY + AT91_ID_SYS,
 };
 
 static void at91sam926x_pit_reset(void)
index 4792682d52b9962df1d227a3deb4370244260476..977127368a7dbd10d3785d4383840be2b72f840d 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/mach/map.h>
 #include <asm/system_misc.h>
 #include <mach/at91sam9g45.h>
+#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/cpu.h>
 
index 933fc9afe7d091db78f5484d4ca331a50cb50716..40fb79df2de0b0ebb19c2d4eb4258490d9839cc9 100644 (file)
@@ -53,8 +53,8 @@ static struct resource hdmac_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_DMA,
-               .end    = AT91SAM9G45_ID_DMA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_DMA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_DMA,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -94,8 +94,8 @@ static struct resource usbh_ohci_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_UHPHS,
-               .end    = AT91SAM9G45_ID_UHPHS,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -156,8 +156,8 @@ static struct resource usbh_ehci_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_UHPHS,
-               .end    = AT91SAM9G45_ID_UHPHS,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_UHPHS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -213,8 +213,8 @@ static struct resource usba_udc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [2] = {
-               .start  = AT91SAM9G45_ID_UDPHS,
-               .end    = AT91SAM9G45_ID_UDPHS,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_UDPHS,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_UDPHS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -296,8 +296,8 @@ static struct resource eth_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_EMAC,
-               .end    = AT91SAM9G45_ID_EMAC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_EMAC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_EMAC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -370,8 +370,8 @@ static struct resource mmc0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_MCI0,
-               .end    = AT91SAM9G45_ID_MCI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -395,8 +395,8 @@ static struct resource mmc1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_MCI1,
-               .end    = AT91SAM9G45_ID_MCI1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_MCI1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -645,8 +645,8 @@ static struct resource twi0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_TWI0,
-               .end    = AT91SAM9G45_ID_TWI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -665,8 +665,8 @@ static struct resource twi1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_TWI1,
-               .end    = AT91SAM9G45_ID_TWI1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TWI1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -720,8 +720,8 @@ static struct resource spi0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_SPI0,
-               .end    = AT91SAM9G45_ID_SPI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -746,8 +746,8 @@ static struct resource spi1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_SPI1,
-               .end    = AT91SAM9G45_ID_SPI1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_SPI1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -834,8 +834,8 @@ static struct resource ac97_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_AC97C,
-               .end    = AT91SAM9G45_ID_AC97C,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_AC97C,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_AC97C,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -887,8 +887,8 @@ struct resource isi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_ISI,
-               .end    = AT91SAM9G45_ID_ISI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_ISI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_ISI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -979,8 +979,8 @@ static struct resource lcdc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_LCDC,
-               .end    = AT91SAM9G45_ID_LCDC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_LCDC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_LCDC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1054,8 +1054,8 @@ static struct resource tcb0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_TCB,
-               .end    = AT91SAM9G45_ID_TCB,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1075,8 +1075,8 @@ static struct resource tcb1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_TCB,
-               .end    = AT91SAM9G45_ID_TCB,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TCB,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1110,8 +1110,8 @@ static struct resource rtc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1147,8 +1147,8 @@ static struct resource tsadcc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_TSC,
-               .end    = AT91SAM9G45_ID_TSC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TSC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TSC,
                .flags  = IORESOURCE_IRQ,
        }
 };
@@ -1197,8 +1197,8 @@ static struct resource adc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_TSC,
-               .end    = AT91SAM9G45_ID_TSC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_TSC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_TSC,
                .flags  = IORESOURCE_IRQ,
        }
 };
@@ -1400,8 +1400,8 @@ static struct resource pwm_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_PWMC,
-               .end    = AT91SAM9G45_ID_PWMC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_PWMC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_PWMC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1453,8 +1453,8 @@ static struct resource ssc0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_SSC0,
-               .end    = AT91SAM9G45_ID_SSC0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1495,8 +1495,8 @@ static struct resource ssc1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_SSC1,
-               .end    = AT91SAM9G45_ID_SSC1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_SSC1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1575,8 +1575,8 @@ static struct resource dbgu_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1613,8 +1613,8 @@ static struct resource uart0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_US0,
-               .end    = AT91SAM9G45_ID_US0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_US0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_US0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1656,8 +1656,8 @@ static struct resource uart1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_US1,
-               .end    = AT91SAM9G45_ID_US1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_US1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_US1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1699,8 +1699,8 @@ static struct resource uart2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_US2,
-               .end    = AT91SAM9G45_ID_US2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_US2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_US2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1742,8 +1742,8 @@ static struct resource uart3_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9G45_ID_US3,
-               .end    = AT91SAM9G45_ID_US3,
+               .start  = NR_IRQS_LEGACY + AT91SAM9G45_ID_US3,
+               .end    = NR_IRQS_LEGACY + AT91SAM9G45_ID_US3,
                .flags  = IORESOURCE_IRQ,
        },
 };
index e420085a57effa34a373b3aeeaca91185f248109..72ce50a50de5a278e21535422c1572bb95837a36 100644 (file)
@@ -19,6 +19,7 @@
 #include <mach/cpu.h>
 #include <mach/at91_dbgu.h>
 #include <mach/at91sam9rl.h>
+#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/at91_rstc.h>
 
index 9c0b1481a9a70c5d3ac6ebfc199c5d2e77ba1f46..f09fff932172ffec238c10714331d7c8970a53e1 100644 (file)
@@ -41,8 +41,8 @@ static struct resource hdmac_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [2] = {
-               .start  = AT91SAM9RL_ID_DMA,
-               .end    = AT91SAM9RL_ID_DMA,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_DMA,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_DMA,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -84,8 +84,8 @@ static struct resource usba_udc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [2] = {
-               .start  = AT91SAM9RL_ID_UDPHS,
-               .end    = AT91SAM9RL_ID_UDPHS,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_UDPHS,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_UDPHS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -172,8 +172,8 @@ static struct resource mmc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_MCI,
-               .end    = AT91SAM9RL_ID_MCI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_MCI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_MCI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -339,8 +339,8 @@ static struct resource twi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_TWI0,
-               .end    = AT91SAM9RL_ID_TWI0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TWI0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TWI0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -383,8 +383,8 @@ static struct resource spi_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_SPI,
-               .end    = AT91SAM9RL_ID_SPI,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_SPI,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_SPI,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -452,8 +452,8 @@ static struct resource ac97_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_AC97C,
-               .end    = AT91SAM9RL_ID_AC97C,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_AC97C,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_AC97C,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -507,8 +507,8 @@ static struct resource lcdc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_LCDC,
-               .end    = AT91SAM9RL_ID_LCDC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_LCDC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_LCDC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -574,18 +574,18 @@ static struct resource tcb_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_TC0,
-               .end    = AT91SAM9RL_ID_TC0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC0,
                .flags  = IORESOURCE_IRQ,
        },
        [2] = {
-               .start  = AT91SAM9RL_ID_TC1,
-               .end    = AT91SAM9RL_ID_TC1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC1,
                .flags  = IORESOURCE_IRQ,
        },
        [3] = {
-               .start  = AT91SAM9RL_ID_TC2,
-               .end    = AT91SAM9RL_ID_TC2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TC2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -621,8 +621,8 @@ static struct resource tsadcc_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_TSC,
-               .end    = AT91SAM9RL_ID_TSC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_TSC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_TSC,
                .flags  = IORESOURCE_IRQ,
        }
 };
@@ -768,8 +768,8 @@ static struct resource pwm_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_PWMC,
-               .end    = AT91SAM9RL_ID_PWMC,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_PWMC,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_PWMC,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -821,8 +821,8 @@ static struct resource ssc0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_SSC0,
-               .end    = AT91SAM9RL_ID_SSC0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -863,8 +863,8 @@ static struct resource ssc1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_SSC1,
-               .end    = AT91SAM9RL_ID_SSC1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_SSC1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -943,8 +943,8 @@ static struct resource dbgu_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91_ID_SYS,
-               .end    = AT91_ID_SYS,
+               .start  = NR_IRQS_LEGACY + AT91_ID_SYS,
+               .end    = NR_IRQS_LEGACY + AT91_ID_SYS,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -981,8 +981,8 @@ static struct resource uart0_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_US0,
-               .end    = AT91SAM9RL_ID_US0,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_US0,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_US0,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1032,8 +1032,8 @@ static struct resource uart1_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_US1,
-               .end    = AT91SAM9RL_ID_US1,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_US1,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_US1,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1075,8 +1075,8 @@ static struct resource uart2_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_US2,
-               .end    = AT91SAM9RL_ID_US2,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_US2,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_US2,
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -1118,8 +1118,8 @@ static struct resource uart3_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = AT91SAM9RL_ID_US3,
-               .end    = AT91SAM9RL_ID_US3,
+               .start  = NR_IRQS_LEGACY + AT91SAM9RL_ID_US3,
+               .end    = NR_IRQS_LEGACY + AT91SAM9RL_ID_US3,
                .flags  = IORESOURCE_IRQ,
        },
 };
index 1b144b4d3ce19da1ef7a580d2bbde299100eaa5f..477cf9d06672c7259cca0dab641bcb099de8e6b5 100644 (file)
@@ -312,8 +312,6 @@ static void __init at91sam9x5_map_io(void)
 
 void __init at91sam9x5_initialize(void)
 {
-       at91_extern_irq = (1 << AT91SAM9X5_ID_IRQ0);
-
        /* Register GPIO subsystem (using DT) */
        at91_gpio_init(NULL, 0);
 }
@@ -321,47 +319,9 @@ void __init at91sam9x5_initialize(void)
 /* --------------------------------------------------------------------
  *  Interrupt initialization
  * -------------------------------------------------------------------- */
-/*
- * The default interrupt priority levels (0 = lowest, 7 = highest).
- */
-static unsigned int at91sam9x5_default_irq_priority[NR_AIC_IRQS] __initdata = {
-       7,      /* Advanced Interrupt Controller (FIQ) */
-       7,      /* System Peripherals */
-       1,      /* Parallel IO Controller A and B */
-       1,      /* Parallel IO Controller C and D */
-       4,      /* Soft Modem */
-       5,      /* USART 0 */
-       5,      /* USART 1 */
-       5,      /* USART 2 */
-       5,      /* USART 3 */
-       6,      /* Two-Wire Interface 0 */
-       6,      /* Two-Wire Interface 1 */
-       6,      /* Two-Wire Interface 2 */
-       0,      /* Multimedia Card Interface 0 */
-       5,      /* Serial Peripheral Interface 0 */
-       5,      /* Serial Peripheral Interface 1 */
-       5,      /* UART 0 */
-       5,      /* UART 1 */
-       0,      /* Timer Counter 0, 1, 2, 3, 4 and 5 */
-       0,      /* Pulse Width Modulation Controller */
-       0,      /* ADC Controller */
-       0,      /* DMA Controller 0 */
-       0,      /* DMA Controller 1 */
-       2,      /* USB Host High Speed port */
-       2,      /* USB Device High speed port */
-       3,      /* Ethernet MAC 0 */
-       3,      /* LDC Controller or Image Sensor Interface */
-       0,      /* Multimedia Card Interface 1 */
-       3,      /* Ethernet MAC 1 */
-       4,      /* Synchronous Serial Interface */
-       4,      /* CAN Controller 0 */
-       4,      /* CAN Controller 1 */
-       0,      /* Advanced Interrupt Controller (IRQ0) */
-};
 
 struct at91_init_soc __initdata at91sam9x5_soc = {
        .map_io = at91sam9x5_map_io,
-       .default_irq_priority = at91sam9x5_default_irq_priority,
        .register_clocks = at91sam9x5_register_clocks,
        .init = at91sam9x5_initialize,
 };
index d62fe090d814c4860403984e470d2f6ad919a79f..46090e642d8eb00b7fe93e05b70c9ea62dc9c8c3 100644 (file)
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/io.h>
 #include <asm/proc-fns.h>
 #include <asm/system_misc.h>
 #include <asm/mach/arch.h>
 #include <mach/at91x40.h>
+#include <mach/at91_aic.h>
 #include <mach/at91_st.h>
 #include <mach/timex.h>
 #include "generic.h"
index 271f994314a469807f2d328f4c75418534d699dc..22d8856094f19a0b0c7512edc135de7425db4501 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <mach/board.h>
 #include <mach/cpu.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -91,6 +92,7 @@ MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
        /* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = onearm_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = onearm_board_init,
index b7d8aa7b81e64baa60d6ea772a74a52c471d5228..de7be193181795cb210e5865df30e6fb8babb0d8 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -212,6 +213,7 @@ MACHINE_START(AFEB9260, "Custom afeb9260 board")
        /* Maintainer: Sergey Lapin <slapin@ossfans.org> */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = afeb9260_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = afeb9260_board_init,
index 29d3ef0a50fb9901ed71d6c27f7dd6de819950e8..477e708497bcfc47e4a225d189d767b07561d210 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -188,6 +189,7 @@ MACHINE_START(CAM60, "KwikByte CAM60")
        /* Maintainer: KwikByte */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = cam60_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = cam60_board_init,
index 44328a6d46095027b75f903a11b7ec611c9043f5..a5b002f32a6162e98e6ae5335fcdbec2eb911332 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -158,6 +159,7 @@ MACHINE_START(CARMEVA, "Carmeva")
        /* Maintainer: Conitec Datasystems */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = carmeva_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = carmeva_board_init,
index 69951ec7dbf310dd5a4d800c90d9ae5dcc6adcff..ecbc13b594de05ed2877d27eab08b91db16cf475 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91sam9260_matrix.h>
 #include <mach/at91_matrix.h>
@@ -376,6 +377,7 @@ MACHINE_START(CPUAT9G20, "Eukrea CPU9G20")
        /* Maintainer: Eric Benard - EUKREA Electromatique */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = cpu9krea_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = cpu9krea_board_init,
index 895cf2dba612fe3a6c1ec0212ce7d1c45ff127cb..2e6d043c82f202e352b426e0ac699a74b15fbdcd 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 #include <mach/cpu.h>
@@ -178,6 +179,7 @@ MACHINE_START(CPUAT91, "Eukrea")
        /* Maintainer: Eric Benard - EUKREA Electromatique */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = cpuat91_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = cpuat91_board_init,
index cd813361cd26be2d61a49de0f536f3be0ac1059d..462bc319cbc589b2bc86d80c4ebcce642ac7bc33 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -252,6 +253,7 @@ MACHINE_START(CSB337, "Cogent CSB337")
        /* Maintainer: Bill Gatliff */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = csb337_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = csb337_board_init,
index 7c8b05a57d7f5f9460e436f338b23668fe7ec577..872871ab11605e37dd35df90a85a7a8f8cb762c7 100644 (file)
@@ -36,6 +36,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -133,6 +134,7 @@ MACHINE_START(CSB637, "Cogent CSB637")
        /* Maintainer: Bill Gatliff */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = csb637_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = csb637_board_init,
index a1fce05aa7a5f7b64e8889f348934d3f75e5ee8a..e8f45c4e0ea8f01affd71c486d50ea1f42228e4c 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/of_platform.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include <asm/setup.h>
 #include <asm/irq.h>
@@ -53,6 +54,7 @@ DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = at91_dt_initialize,
        .init_irq       = at91_dt_init_irq,
        .init_machine   = at91_dt_device_init,
index d2023f27c65254f83113588a105d221ccfabf705..01f66e99ece73a875b3aa97b79c1af0ca54da58d 100644 (file)
@@ -28,6 +28,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include "generic.h"
 
 static void __init at91eb01_init_irq(void)
@@ -43,6 +44,7 @@ static void __init at91eb01_init_early(void)
 MACHINE_START(AT91EB01, "Atmel AT91 EB01")
        /* Maintainer: Greg Ungerer <gerg@snapgear.com> */
        .timer          = &at91x40_timer,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = at91eb01_init_early,
        .init_irq       = at91eb01_init_irq,
 MACHINE_END
index bd10172979891c1aab6b139496b068500eedc30b..d1e1f3fc0a47a06d912eddc622048b0663c8be8d 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -118,6 +119,7 @@ static void __init eb9200_board_init(void)
 MACHINE_START(ATEB9200, "Embest ATEB9200")
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = eb9200_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = eb9200_board_init,
index 89cc3726a9ce1f3b57f5c589b5d495d1a6c5d4db..9c24cb25707c61dae73275d31c4c669af20528cd 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <mach/board.h>
 #include <mach/cpu.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -170,6 +171,7 @@ MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
        /* Maintainer: emQbit.com */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = ecb_at91init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = ecb_at91board_init,
index 558546cf63f492bf46d5b290b389e019f428244a..82bdfde3405f52d0ef1fd34507b12bd4bfe56466 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/mach/map.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 #include <mach/cpu.h>
@@ -132,6 +133,7 @@ MACHINE_START(ECO920, "eco920")
        /* Maintainer: Sascha Hauer */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = eco920_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = eco920_board_init,
index 47658f78105db41fad698b7d438444f60c8f6cbf..6cc83a87d77cf9422e958f9526720842de343cb9 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include "generic.h"
 
@@ -160,6 +161,7 @@ MACHINE_START(FLEXIBITY, "Flexibity Connect")
        /* Maintainer: Maxim Osipov */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = flexibity_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = flexibity_board_init,
index 33411e6ecb1f1747f7431721003e4b722218bf57..69ab1247ef81263fb430de41d5c025263de5cb9e 100644 (file)
@@ -42,6 +42,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -262,6 +263,7 @@ MACHINE_START(ACMENETUSFOXG20, "Acme Systems srl FOX Board G20")
        /* Maintainer: Sergio Tanzilli */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = foxg20_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = foxg20_board_init,
index 3e0dfa643a86e1714ad627638667a9df713375a7..a9d5e78118c5475a763bfb310a22b588d2c9ddc8 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/mach/arch.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/gsia18s.h>
 #include <mach/stamp9g20.h>
@@ -575,6 +576,7 @@ static void __init gsia18s_board_init(void)
 MACHINE_START(GSIA18S, "GS_IA18_S")
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = gsia18s_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = gsia18s_board_init,
index f260657f32bcf5881b3d2aa98fa9d442f992a4df..64c1dbf88a07bfe602f9c8c29071bff1ba5db774 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/cpu.h>
 
 #include "generic.h"
@@ -93,6 +94,7 @@ MACHINE_START(KAFA, "Sperry-Sun KAFA")
        /* Maintainer: Sergei Sharonov */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = kafa_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = kafa_board_init,
index ba39db5482b955617689e7f65adb39e245915738..5d96cb85175f9a6bce00c7b30ce12fa5d46b5821 100644 (file)
@@ -37,6 +37,7 @@
 
 #include <mach/board.h>
 #include <mach/cpu.h>
+#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
@@ -133,6 +134,7 @@ MACHINE_START(KB9200, "KB920x")
        /* Maintainer: KwikByte, Inc. */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = kb9202_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = kb9202_board_init,
index d2f4cc1617669e9d92729c47dde9d6c1bc84a0cf..18103c5d993ce24c148887d5bfc60331f4cb556d 100644 (file)
@@ -45,6 +45,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -378,6 +379,7 @@ MACHINE_START(NEOCORE926, "ADENEO NEOCORE 926")
        /* Maintainer: ADENEO */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = neocore926_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = neocore926_board_init,
index 7fe6383424213a173a9f5553077f3c468aff8945..9ca3e32c54cbb3b52acc0224625c5c83b8cecad3 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/mach/arch.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/stamp9g20.h>
 
@@ -218,6 +219,7 @@ MACHINE_START(PCONTROL_G20, "PControl G20")
        /* Maintainer: pgsellmann@portner-elektronik.at */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = pcontrol_g20_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = pcontrol_g20_board_init,
index b45c0a5d5ca7649c745d4718a329d0ee65fbdf20..127065504508c8fd5bffd4f00d778339fe497788 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
@@ -120,6 +121,7 @@ MACHINE_START(PICOTUX2XX, "picotux 200")
        /* Maintainer: Kleinhenz Elektronik GmbH */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = picotux200_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = picotux200_board_init,
index 0c61bf0d272c3b02215da56a7cfbdf7c2ce6a0fd..bf351e285422684cc71644e090ea428c766c556b 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 
@@ -258,6 +259,7 @@ MACHINE_START(QIL_A9260, "CALAO QIL_A9260")
        /* Maintainer: calao-systems */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
index afd7a4713766cec538c1736daf0895f691d6ebf3..cc2bf9796073bcb096883059c7cced4153287a91 100644 (file)
@@ -40,6 +40,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
@@ -223,6 +224,7 @@ MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
        /* Maintainer: SAN People/Atmel */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = dk_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = dk_board_init,
index 2b15b8adec4ccb9c671fab7e2423a59f2860ad89..62e19e64c9d3f52dc0d5ca8e2470dfe9cfc1918e 100644 (file)
@@ -40,6 +40,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 
@@ -190,6 +191,7 @@ MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
        /* Maintainer: SAN People/Atmel */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
index 24ab9be7510fbe5f6cdd3296be794fd7affa8cdc..c3b43aefdb7597d2f71dc5e8e40e054019b891f6 100644 (file)
@@ -26,6 +26,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 
 #include <linux/gpio.h>
 
@@ -225,6 +226,7 @@ MACHINE_START(RSI_EWS, "RSI EWS")
        /* Maintainer: Josef Holzmayr <holzmayr@rsi-elektrotechnik.de> */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = rsi_ews_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = rsi_ews_board_init,
index cdd21f2595d2220de8fc828f636d240e0d0b1476..7bf6da70d7d56bbe735156f5c72add8a5441338b 100644 (file)
@@ -38,6 +38,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -202,6 +203,7 @@ MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
        /* Maintainer: Olimex */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
index 7b3c3913551a53ccc7a08eef94b5a18b7bba428b..889c1bf71eb596d2efd28fc76d086f2d87a42b9d 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -344,6 +345,7 @@ MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
index 2736453821b0d55e9782d065107c176102ca4c35..2269be5fa3841075539fd106746ce7c7cc88776d 100644 (file)
@@ -46,6 +46,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -615,6 +616,7 @@ MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
index 983cb98d2465c7253b2c9c2900de5379e2636979..82adf581afc2eb48868ea1d3198685bff22d457a 100644 (file)
@@ -45,6 +45,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -443,6 +444,7 @@ MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
index 6860d3451100321a8bfd8930c6d5bc96e5fc3b9e..4ea4ee00364b44fd2fe1ef693d72e08e57a734e9 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/system_rev.h>
 
@@ -413,6 +414,7 @@ MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
@@ -422,6 +424,7 @@ MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
index 63163dc7df46c4b416fadf21031c393716861fcc..3d48ec15468594f6b3fde5654f4f709eb4a4abea 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/mach/irq.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 #include <mach/system_rev.h>
@@ -503,6 +504,7 @@ MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
index be3239f13daa64341598d1b5f33041ff44058eab..e7dc3ead7045f3f938c65729263a71be5050dafb 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 
@@ -319,6 +320,7 @@ MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK")
        /* Maintainer: Atmel */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
index 9d446f1bb45fe6fcc91d78a35932bb56823e685e..a4e031a039fd50c0fd407ffc34d6ae9240070301 100644 (file)
@@ -33,6 +33,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -178,6 +179,7 @@ static void __init snapper9260_board_init(void)
 MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module")
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = snapper9260_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = snapper9260_board_init,
index ee86f9d7ee72ed87bf408e273858be3dbe4586e1..29eae1626bf79ffa1ca4c4bf562d6ef255b81f82 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/mach/arch.h>
 
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 
 #include "sam9_smc.h"
@@ -287,6 +288,7 @@ MACHINE_START(PORTUXG20, "taskit PortuxG20")
        /* Maintainer: taskit GmbH */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = stamp9g20_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = portuxg20_board_init,
@@ -296,6 +298,7 @@ MACHINE_START(STAMP9G20, "taskit Stamp9G20")
        /* Maintainer: taskit GmbH */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = stamp9g20_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = stamp9g20evb_board_init,
index 95393fcaf199c9664bc6cafa8fafe17e826e5d92..c1476b9fe7b91a98ef279e4be2ecd250300bb1fc 100644 (file)
@@ -42,6 +42,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91sam9_smc.h>
 #include <mach/at91_shdwc.h>
 
@@ -358,6 +359,7 @@ MACHINE_START(USB_A9263, "CALAO USB_A9263")
        /* Maintainer: calao-systems */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
@@ -367,6 +369,7 @@ MACHINE_START(USB_A9260, "CALAO USB_A9260")
        /* Maintainer: calao-systems */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
@@ -376,6 +379,7 @@ MACHINE_START(USB_A9G20, "CALAO USB_A92G0")
        /* Maintainer: Jean-Christophe PLAGNIOL-VILLARD */
        .timer          = &at91sam926x_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = ek_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = ek_board_init,
index d56665ea4b55d3a8259228d8801fe20a547b9bab..516d340549d8db4c4ffe0a5ff461aee9cb7e6175 100644 (file)
@@ -44,6 +44,7 @@
 
 #include <mach/hardware.h>
 #include <mach/board.h>
+#include <mach/at91_aic.h>
 #include <mach/at91rm9200_mc.h>
 #include <mach/at91_ramc.h>
 #include <mach/cpu.h>
@@ -590,6 +591,7 @@ MACHINE_START(YL9200, "uCdragon YL-9200")
        /* Maintainer: S.Birtles */
        .timer          = &at91rm9200_timer,
        .map_io         = at91_map_io,
+       .handle_irq     = at91_aic_handle_irq,
        .init_early     = yl9200_init_early,
        .init_irq       = at91_init_irq_default,
        .init_machine   = yl9200_board_init,
index 0a60bf837037dd67382163c30f3290ed30acb9ae..f49650677653a0f0488e6c64346fcf07e46ae555 100644 (file)
@@ -29,6 +29,8 @@ extern void __init at91x40_init_interrupts(unsigned int priority[]);
 extern void __init at91_aic_init(unsigned int priority[]);
 extern int  __init at91_aic_of_init(struct device_node *node,
                                    struct device_node *parent);
+extern int  __init at91_aic5_of_init(struct device_node *node,
+                                   struct device_node *parent);
 
 
  /* Timer */
index 325837a264c930fdbe1787d3ed2e61d3f75d1772..be42cf0e74bddd39ded6e1b54d7f17d351a24bc1 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/of_irq.h>
 #include <linux/of_gpio.h>
 
+#include <asm/mach/irq.h>
+
 #include <mach/hardware.h>
 #include <mach/at91_pio.h>
 
@@ -585,15 +587,14 @@ static struct irq_chip gpio_irqchip = {
 
 static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
+       struct irq_chip *chip = irq_desc_get_chip(desc);
        struct irq_data *idata = irq_desc_get_irq_data(desc);
-       struct irq_chip *chip = irq_data_get_irq_chip(idata);
        struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
        void __iomem    *pio = at91_gpio->regbase;
        unsigned long   isr;
        int             n;
 
-       /* temporarily mask (level sensitive) parent IRQ */
-       chip->irq_ack(idata);
+       chained_irq_enter(chip, desc);
        for (;;) {
                /* Reading ISR acks pending (edge triggered) GPIO interrupts.
                 * When there none are pending, we're finished unless we need
@@ -614,7 +615,7 @@ static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
                        n = find_next_bit(&isr, BITS_PER_LONG, n + 1);
                }
        }
-       chip->irq_unmask(idata);
+       chained_irq_exit(chip, desc);
        /* now it may re-trigger */
 }
 
index 3045781c473f5d427e84e9ad83e51592c5e3d3da..eaea66197fa17f606e8f5d2228b5efa61e936c86 100644 (file)
@@ -23,12 +23,23 @@ extern void __iomem *at91_aic_base;
        __raw_readl(at91_aic_base + field)
 
 #define at91_aic_write(field, value) \
-       __raw_writel(value, at91_aic_base + field);
+       __raw_writel(value, at91_aic_base + field)
 #else
 .extern at91_aic_base
 #endif
 
+/* Number of irq lines managed by AIC */
+#define NR_AIC_IRQS    32
+#define NR_AIC5_IRQS   128
+
+#define AT91_AIC5_SSR          0x0                     /* Source Select Register [AIC5] */
+#define        AT91_AIC5_INTSEL_MSK    (0x7f << 0)             /* Interrupt Line Selection Mask */
+
+#define AT91_AIC_IRQ_MIN_PRIORITY      0
+#define AT91_AIC_IRQ_MAX_PRIORITY      7
+
 #define AT91_AIC_SMR(n)                ((n) * 4)               /* Source Mode Registers 0-31 */
+#define AT91_AIC5_SMR          0x4                     /* Source Mode Register [AIC5] */
 #define                AT91_AIC_PRIOR          (7 << 0)                /* Priority Level */
 #define                AT91_AIC_SRCTYPE        (3 << 5)                /* Interrupt Source Type */
 #define                        AT91_AIC_SRCTYPE_LOW            (0 << 5)
@@ -37,29 +48,52 @@ extern void __iomem *at91_aic_base;
 #define                        AT91_AIC_SRCTYPE_RISING         (3 << 5)
 
 #define AT91_AIC_SVR(n)                (0x80 + ((n) * 4))      /* Source Vector Registers 0-31 */
+#define AT91_AIC5_SVR          0x8                     /* Source Vector Register [AIC5] */
 #define AT91_AIC_IVR           0x100                   /* Interrupt Vector Register */
+#define AT91_AIC5_IVR          0x10                    /* Interrupt Vector Register [AIC5] */
 #define AT91_AIC_FVR           0x104                   /* Fast Interrupt Vector Register */
+#define AT91_AIC5_FVR          0x14                    /* Fast Interrupt Vector Register [AIC5] */
 #define AT91_AIC_ISR           0x108                   /* Interrupt Status Register */
+#define AT91_AIC5_ISR          0x18                    /* Interrupt Status Register [AIC5] */
 #define                AT91_AIC_IRQID          (0x1f << 0)             /* Current Interrupt Identifier */
 
 #define AT91_AIC_IPR           0x10c                   /* Interrupt Pending Register */
+#define AT91_AIC5_IPR0         0x20                    /* Interrupt Pending Register 0 [AIC5] */
+#define AT91_AIC5_IPR1         0x24                    /* Interrupt Pending Register 1 [AIC5] */
+#define AT91_AIC5_IPR2         0x28                    /* Interrupt Pending Register 2 [AIC5] */
+#define AT91_AIC5_IPR3         0x2c                    /* Interrupt Pending Register 3 [AIC5] */
 #define AT91_AIC_IMR           0x110                   /* Interrupt Mask Register */
+#define AT91_AIC5_IMR          0x30                    /* Interrupt Mask Register [AIC5] */
 #define AT91_AIC_CISR          0x114                   /* Core Interrupt Status Register */
+#define AT91_AIC5_CISR         0x34                    /* Core Interrupt Status Register [AIC5] */
 #define                AT91_AIC_NFIQ           (1 << 0)                /* nFIQ Status */
 #define                AT91_AIC_NIRQ           (1 << 1)                /* nIRQ Status */
 
 #define AT91_AIC_IECR          0x120                   /* Interrupt Enable Command Register */
+#define AT91_AIC5_IECR         0x40                    /* Interrupt Enable Command Register [AIC5] */
 #define AT91_AIC_IDCR          0x124                   /* Interrupt Disable Command Register */
+#define AT91_AIC5_IDCR         0x44                    /* Interrupt Disable Command Register [AIC5] */
 #define AT91_AIC_ICCR          0x128                   /* Interrupt Clear Command Register */
+#define AT91_AIC5_ICCR         0x48                    /* Interrupt Clear Command Register [AIC5] */
 #define AT91_AIC_ISCR          0x12c                   /* Interrupt Set Command Register */
+#define AT91_AIC5_ISCR         0x4c                    /* Interrupt Set Command Register [AIC5] */
 #define AT91_AIC_EOICR         0x130                   /* End of Interrupt Command Register */
+#define AT91_AIC5_EOICR                0x38                    /* End of Interrupt Command Register [AIC5] */
 #define AT91_AIC_SPU           0x134                   /* Spurious Interrupt Vector Register */
+#define AT91_AIC5_SPU          0x3c                    /* Spurious Interrupt Vector Register [AIC5] */
 #define AT91_AIC_DCR           0x138                   /* Debug Control Register */
+#define AT91_AIC5_DCR          0x6c                    /* Debug Control Register [AIC5] */
 #define                AT91_AIC_DCR_PROT       (1 << 0)                /* Protection Mode */
 #define                AT91_AIC_DCR_GMSK       (1 << 1)                /* General Mask */
 
 #define AT91_AIC_FFER          0x140                   /* Fast Forcing Enable Register [SAM9 only] */
+#define AT91_AIC5_FFER         0x50                    /* Fast Forcing Enable Register [AIC5] */
 #define AT91_AIC_FFDR          0x144                   /* Fast Forcing Disable Register [SAM9 only] */
+#define AT91_AIC5_FFDR         0x54                    /* Fast Forcing Disable Register [AIC5] */
 #define AT91_AIC_FFSR          0x148                   /* Fast Forcing Status Register [SAM9 only] */
+#define AT91_AIC5_FFSR         0x58                    /* Fast Forcing Status Register [AIC5] */
+
+void at91_aic_handle_irq(struct pt_regs *regs);
+void at91_aic5_handle_irq(struct pt_regs *regs);
 
 #endif
diff --git a/arch/arm/mach-at91/include/mach/at91_spi.h b/arch/arm/mach-at91/include/mach/at91_spi.h
deleted file mode 100644 (file)
index 2f6ba0c..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_spi.h
- *
- * Copyright (C) 2005 Ivan Kokshaysky
- * Copyright (C) SAN People
- *
- * Serial Peripheral Interface (SPI) registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91_SPI_H
-#define AT91_SPI_H
-
-#define AT91_SPI_CR                    0x00            /* Control Register */
-#define                AT91_SPI_SPIEN          (1 <<  0)               /* SPI Enable */
-#define                AT91_SPI_SPIDIS         (1 <<  1)               /* SPI Disable */
-#define                AT91_SPI_SWRST          (1 <<  7)               /* SPI Software Reset */
-#define                AT91_SPI_LASTXFER       (1 << 24)               /* Last Transfer [SAM9261 only] */
-
-#define AT91_SPI_MR                    0x04            /* Mode Register */
-#define                AT91_SPI_MSTR           (1    <<  0)            /* Master/Slave Mode */
-#define                AT91_SPI_PS             (1    <<  1)            /* Peripheral Select */
-#define                        AT91_SPI_PS_FIXED       (0 << 1)
-#define                        AT91_SPI_PS_VARIABLE    (1 << 1)
-#define                AT91_SPI_PCSDEC         (1    <<  2)            /* Chip Select Decode */
-#define                AT91_SPI_DIV32          (1    <<  3)            /* Clock Selection [AT91RM9200 only] */
-#define                AT91_SPI_MODFDIS        (1    <<  4)            /* Mode Fault Detection */
-#define                AT91_SPI_LLB            (1    <<  7)            /* Local Loopback Enable */
-#define                AT91_SPI_PCS            (0xf  << 16)            /* Peripheral Chip Select */
-#define                AT91_SPI_DLYBCS         (0xff << 24)            /* Delay Between Chip Selects */
-
-#define AT91_SPI_RDR           0x08                    /* Receive Data Register */
-#define                AT91_SPI_RD             (0xffff <<  0)          /* Receive Data */
-#define                AT91_SPI_PCS            (0xf    << 16)          /* Peripheral Chip Select */
-
-#define AT91_SPI_TDR           0x0c                    /* Transmit Data Register */
-#define                AT91_SPI_TD             (0xffff <<  0)          /* Transmit Data */
-#define                AT91_SPI_PCS            (0xf    << 16)          /* Peripheral Chip Select */
-#define                AT91_SPI_LASTXFER       (1      << 24)          /* Last Transfer [SAM9261 only] */
-
-#define AT91_SPI_SR            0x10                    /* Status Register */
-#define                AT91_SPI_RDRF           (1 <<  0)               /* Receive Data Register Full */
-#define                AT91_SPI_TDRE           (1 <<  1)               /* Transmit Data Register Full */
-#define                AT91_SPI_MODF           (1 <<  2)               /* Mode Fault Error */
-#define                AT91_SPI_OVRES          (1 <<  3)               /* Overrun Error Status */
-#define                AT91_SPI_ENDRX          (1 <<  4)               /* End of RX buffer */
-#define                AT91_SPI_ENDTX          (1 <<  5)               /* End of TX buffer */
-#define                AT91_SPI_RXBUFF         (1 <<  6)               /* RX Buffer Full */
-#define                AT91_SPI_TXBUFE         (1 <<  7)               /* TX Buffer Empty */
-#define                AT91_SPI_NSSR           (1 <<  8)               /* NSS Rising [SAM9261 only] */
-#define                AT91_SPI_TXEMPTY        (1 <<  9)               /* Transmission Register Empty [SAM9261 only] */
-#define                AT91_SPI_SPIENS         (1 << 16)               /* SPI Enable Status */
-
-#define AT91_SPI_IER           0x14                    /* Interrupt Enable Register */
-#define AT91_SPI_IDR           0x18                    /* Interrupt Disable Register */
-#define AT91_SPI_IMR           0x1c                    /* Interrupt Mask Register */
-
-#define AT91_SPI_CSR(n)                (0x30 + ((n) * 4))      /* Chip Select Registers 0-3 */
-#define                AT91_SPI_CPOL           (1    <<  0)            /* Clock Polarity */
-#define                AT91_SPI_NCPHA          (1    <<  1)            /* Clock Phase */
-#define                AT91_SPI_CSAAT          (1    <<  3)            /* Chip Select Active After Transfer [SAM9261 only] */
-#define                AT91_SPI_BITS           (0xf  <<  4)            /* Bits Per Transfer */
-#define                        AT91_SPI_BITS_8         (0 << 4)
-#define                        AT91_SPI_BITS_9         (1 << 4)
-#define                        AT91_SPI_BITS_10        (2 << 4)
-#define                        AT91_SPI_BITS_11        (3 << 4)
-#define                        AT91_SPI_BITS_12        (4 << 4)
-#define                        AT91_SPI_BITS_13        (5 << 4)
-#define                        AT91_SPI_BITS_14        (6 << 4)
-#define                        AT91_SPI_BITS_15        (7 << 4)
-#define                        AT91_SPI_BITS_16        (8 << 4)
-#define                AT91_SPI_SCBR           (0xff <<  8)            /* Serial Clock Baud Rate */
-#define                AT91_SPI_DLYBS          (0xff << 16)            /* Delay before SPCK */
-#define                AT91_SPI_DLYBCT         (0xff << 24)            /* Delay between Consecutive Transfers */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/at91_ssc.h b/arch/arm/mach-at91/include/mach/at91_ssc.h
deleted file mode 100644 (file)
index a81114c..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/at91_ssc.h
- *
- * Copyright (C) SAN People
- *
- * Serial Synchronous Controller (SSC) registers.
- * Based on AT91RM9200 datasheet revision E.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef AT91_SSC_H
-#define AT91_SSC_H
-
-#define AT91_SSC_CR            0x00    /* Control Register */
-#define                AT91_SSC_RXEN           (1 <<  0)       /* Receive Enable */
-#define                AT91_SSC_RXDIS          (1 <<  1)       /* Receive Disable */
-#define                AT91_SSC_TXEN           (1 <<  8)       /* Transmit Enable */
-#define                AT91_SSC_TXDIS          (1 <<  9)       /* Transmit Disable */
-#define                AT91_SSC_SWRST          (1 << 15)       /* Software Reset */
-
-#define AT91_SSC_CMR           0x04    /* Clock Mode Register */
-#define                AT91_SSC_CMR_DIV        (0xfff << 0)    /* Clock Divider */
-
-#define AT91_SSC_RCMR          0x10    /* Receive Clock Mode Register */
-#define                AT91_SSC_CKS            (3    <<  0)    /* Clock Selection */
-#define                        AT91_SSC_CKS_DIV                (0 << 0)
-#define                        AT91_SSC_CKS_CLOCK              (1 << 0)
-#define                        AT91_SSC_CKS_PIN                (2 << 0)
-#define                AT91_SSC_CKO            (7    <<  2)    /* Clock Output Mode Selection */
-#define                        AT91_SSC_CKO_NONE               (0 << 2)
-#define                        AT91_SSC_CKO_CONTINUOUS         (1 << 2)
-#define                AT91_SSC_CKI            (1    <<  5)    /* Clock Inversion */
-#define                        AT91_SSC_CKI_FALLING            (0 << 5)
-#define                        AT91_SSC_CK_RISING              (1 << 5)
-#define                AT91_SSC_CKG            (1    <<  6)    /* Receive Clock Gating Selection [AT91SAM9261 only] */
-#define                        AT91_SSC_CKG_NONE               (0 << 6)
-#define                        AT91_SSC_CKG_RFLOW              (1 << 6)
-#define                        AT91_SSC_CKG_RFHIGH             (2 << 6)
-#define                AT91_SSC_START          (0xf  <<  8)    /* Start Selection */
-#define                        AT91_SSC_START_CONTINUOUS       (0 << 8)
-#define                        AT91_SSC_START_TX_RX            (1 << 8)
-#define                        AT91_SSC_START_LOW_RF           (2 << 8)
-#define                        AT91_SSC_START_HIGH_RF          (3 << 8)
-#define                        AT91_SSC_START_FALLING_RF       (4 << 8)
-#define                        AT91_SSC_START_RISING_RF        (5 << 8)
-#define                        AT91_SSC_START_LEVEL_RF         (6 << 8)
-#define                        AT91_SSC_START_EDGE_RF          (7 << 8)
-#define                AT91_SSC_STOP           (1    << 12)    /* Receive Stop Selection [AT91SAM9261 only] */
-#define                AT91_SSC_STTDLY         (0xff << 16)    /* Start Delay */
-#define                AT91_SSC_PERIOD         (0xff << 24)    /* Period Divider Selection */
-
-#define AT91_SSC_RFMR          0x14    /* Receive Frame Mode Register */
-#define                AT91_SSC_DATALEN        (0x1f <<  0)    /* Data Length */
-#define                AT91_SSC_LOOP           (1    <<  5)    /* Loop Mode */
-#define                AT91_SSC_MSBF           (1    <<  7)    /* Most Significant Bit First */
-#define                AT91_SSC_DATNB          (0xf  <<  8)    /* Data Number per Frame */
-#define                AT91_SSC_FSLEN          (0xf  << 16)    /* Frame Sync Length */
-#define                AT91_SSC_FSOS           (7    << 20)    /* Frame Sync Output Selection */
-#define                        AT91_SSC_FSOS_NONE              (0 << 20)
-#define                        AT91_SSC_FSOS_NEGATIVE          (1 << 20)
-#define                        AT91_SSC_FSOS_POSITIVE          (2 << 20)
-#define                        AT91_SSC_FSOS_LOW               (3 << 20)
-#define                        AT91_SSC_FSOS_HIGH              (4 << 20)
-#define                        AT91_SSC_FSOS_TOGGLE            (5 << 20)
-#define                AT91_SSC_FSEDGE         (1    << 24)    /* Frame Sync Edge Detection */
-#define                        AT91_SSC_FSEDGE_POSITIVE        (0 << 24)
-#define                        AT91_SSC_FSEDGE_NEGATIVE        (1 << 24)
-
-#define AT91_SSC_TCMR          0x18    /* Transmit Clock Mode Register */
-#define AT91_SSC_TFMR          0x1c    /* Transmit Fram Mode Register */
-#define                AT91_SSC_DATDEF         (1 <<  5)       /* Data Default Value */
-#define                AT91_SSC_FSDEN          (1 << 23)       /* Frame Sync Data Enable */
-
-#define AT91_SSC_RHR           0x20    /* Receive Holding Register */
-#define AT91_SSC_THR           0x24    /* Transmit Holding Register */
-#define AT91_SSC_RSHR          0x30    /* Receive Sync Holding Register */
-#define AT91_SSC_TSHR          0x34    /* Transmit Sync Holding Register */
-
-#define AT91_SSC_RC0R          0x38    /* Receive Compare 0 Register [AT91SAM9261 only] */
-#define AT91_SSC_RC1R          0x3c    /* Receive Compare 1 Register [AT91SAM9261 only] */
-
-#define AT91_SSC_SR            0x40    /* Status Register */
-#define                AT91_SSC_TXRDY          (1 <<  0)       /* Transmit Ready */
-#define                AT91_SSC_TXEMPTY        (1 <<  1)       /* Transmit Empty */
-#define                AT91_SSC_ENDTX          (1 <<  2)       /* End of Transmission */
-#define                AT91_SSC_TXBUFE         (1 <<  3)       /* Transmit Buffer Empty */
-#define                AT91_SSC_RXRDY          (1 <<  4)       /* Receive Ready */
-#define                AT91_SSC_OVRUN          (1 <<  5)       /* Receive Overrun */
-#define                AT91_SSC_ENDRX          (1 <<  6)       /* End of Reception */
-#define                AT91_SSC_RXBUFF         (1 <<  7)       /* Receive Buffer Full */
-#define                AT91_SSC_CP0            (1 <<  8)       /* Compare 0 [AT91SAM9261 only] */
-#define                AT91_SSC_CP1            (1 <<  9)       /* Compare 1 [AT91SAM9261 only] */
-#define                AT91_SSC_TXSYN          (1 << 10)       /* Transmit Sync */
-#define                AT91_SSC_RXSYN          (1 << 11)       /* Receive Sync */
-#define                AT91_SSC_TXENA          (1 << 16)       /* Transmit Enable */
-#define                AT91_SSC_RXENA          (1 << 17)       /* Receive Enable */
-
-#define AT91_SSC_IER           0x44    /* Interrupt Enable Register */
-#define AT91_SSC_IDR           0x48    /* Interrupt Disable Register */
-#define AT91_SSC_IMR           0x4c    /* Interrupt Mask Register */
-
-#endif
diff --git a/arch/arm/mach-at91/include/mach/entry-macro.S b/arch/arm/mach-at91/include/mach/entry-macro.S
deleted file mode 100644 (file)
index 903bf20..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/entry-macro.S
- *
- *  Copyright (C) 2003-2005 SAN People
- *
- * Low-level IRQ helper macros for AT91RM9200 platforms
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-
-#include <mach/hardware.h>
-#include <mach/at91_aic.h>
-
-       .macro  get_irqnr_preamble, base, tmp
-       ldr     \base, =at91_aic_base           @ base virtual address of AIC peripheral
-       ldr     \base, [\base]
-       .endm
-
-       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-       ldr     \irqnr, [\base, #AT91_AIC_IVR]          @ read IRQ vector register: de-asserts nIRQ to processor (and clears interrupt)
-       ldr     \irqstat, [\base, #AT91_AIC_ISR]        @ read interrupt source number
-       teq     \irqstat, #0                            @ ISR is 0 when no current interrupt, or spurious interrupt
-       streq   \tmp, [\base, #AT91_AIC_EOICR]          @ not going to be handled further, then ACK it now.
-       .endm
-
diff --git a/arch/arm/mach-at91/include/mach/irqs.h b/arch/arm/mach-at91/include/mach/irqs.h
deleted file mode 100644 (file)
index ac8b7df..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * arch/arm/mach-at91/include/mach/irqs.h
- *
- *  Copyright (C) 2004 SAN People
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-#include <linux/io.h>
-#include <mach/at91_aic.h>
-
-#define NR_AIC_IRQS 32
-
-
-/*
- * Acknowledge interrupt with AIC after interrupt has been handled.
- *   (by kernel/irq.c)
- */
-#define irq_finish(irq) do { at91_aic_write(AT91_AIC_EOICR, 0); } while (0)
-
-
-/*
- * IRQ interrupt symbols are the AT91xxx_ID_* symbols
- * for IRQs handled directly through the AIC, or else the AT91_PIN_*
- * symbols in gpio.h for ones handled indirectly as GPIOs.
- * We make provision for 5 banks of GPIO.
- */
-#define        NR_IRQS         (NR_AIC_IRQS + (5 * 32))
-
-/* FIQ is AIC source 0. */
-#define FIQ_START AT91_ID_FIQ
-
-#endif
index cfcfcbe362699d1ed04be46e2d9680bc89917e58..1e02c0e49dccb76949be0fc9d855a5a3bb3504bc 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/bitmap.h>
 #include <linux/types.h>
 #include <linux/irq.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/irqdomain.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/setup.h>
 
+#include <asm/exception.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
 
+#include <mach/at91_aic.h>
+
 void __iomem *at91_aic_base;
 static struct irq_domain *at91_aic_domain;
 static struct device_node *at91_aic_np;
+static unsigned int n_irqs = NR_AIC_IRQS;
+static unsigned long at91_aic_caps = 0;
+
+/* AIC5 introduces a Source Select Register */
+#define AT91_AIC_CAP_AIC5      (1 << 0)
+#define has_aic5()             (at91_aic_caps & AT91_AIC_CAP_AIC5)
+
+#ifdef CONFIG_PM
+
+static unsigned long *wakeups;
+static unsigned long *backups;
+
+#define set_backup(bit) set_bit(bit, backups)
+#define clear_backup(bit) clear_bit(bit, backups)
+
+static int at91_aic_pm_init(void)
+{
+       backups = kzalloc(BITS_TO_LONGS(n_irqs) * sizeof(*backups), GFP_KERNEL);
+       if (!backups)
+               return -ENOMEM;
+
+       wakeups = kzalloc(BITS_TO_LONGS(n_irqs) * sizeof(*backups), GFP_KERNEL);
+       if (!wakeups) {
+               kfree(backups);
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int at91_aic_set_wake(struct irq_data *d, unsigned value)
+{
+       if (unlikely(d->hwirq >= n_irqs))
+               return -EINVAL;
+
+       if (value)
+               set_bit(d->hwirq, wakeups);
+       else
+               clear_bit(d->hwirq, wakeups);
+
+       return 0;
+}
+
+void at91_irq_suspend(void)
+{
+       int i = 0, bit;
+
+       if (has_aic5()) {
+               /* disable enabled irqs */
+               while ((bit = find_next_bit(backups, n_irqs, i)) < 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) {
+                       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);
+               at91_aic_write(AT91_AIC_IECR, *wakeups);
+       }
+}
+
+void at91_irq_resume(void)
+{
+       int i = 0, bit;
+
+       if (has_aic5()) {
+               /* disable wakeup irqs */
+               while ((bit = find_next_bit(wakeups, n_irqs, i)) < 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) {
+                       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);
+               at91_aic_write(AT91_AIC_IECR, *backups);
+       }
+}
+
+#else
+static inline int at91_aic_pm_init(void)
+{
+       return 0;
+}
+
+#define set_backup(bit)
+#define clear_backup(bit)
+#define at91_aic_set_wake      NULL
+
+#endif /* CONFIG_PM */
+
+asmlinkage void __exception_irq_entry
+at91_aic_handle_irq(struct pt_regs *regs)
+{
+       u32 irqnr;
+       u32 irqstat;
+
+       irqnr = at91_aic_read(AT91_AIC_IVR);
+       irqstat = at91_aic_read(AT91_AIC_ISR);
+
+       /*
+        * ISR value is 0 when there is no current interrupt or when there is
+        * a spurious interrupt
+        */
+       if (!irqstat)
+               at91_aic_write(AT91_AIC_EOICR, 0);
+       else
+               handle_IRQ(irqnr, regs);
+}
+
+asmlinkage void __exception_irq_entry
+at91_aic5_handle_irq(struct pt_regs *regs)
+{
+       u32 irqnr;
+       u32 irqstat;
+
+       irqnr = at91_aic_read(AT91_AIC5_IVR);
+       irqstat = at91_aic_read(AT91_AIC5_ISR);
+
+       if (!irqstat)
+               at91_aic_write(AT91_AIC5_EOICR, 0);
+       else
+               handle_IRQ(irqnr, regs);
+}
 
 static void at91_aic_mask_irq(struct irq_data *d)
 {
        /* Disable interrupt on AIC */
        at91_aic_write(AT91_AIC_IDCR, 1 << d->hwirq);
+       /* Update ISR cache */
+       clear_backup(d->hwirq);
+}
+
+static void __maybe_unused at91_aic5_mask_irq(struct irq_data *d)
+{
+       /* Disable interrupt on AIC5 */
+       at91_aic_write(AT91_AIC5_SSR, d->hwirq & AT91_AIC5_INTSEL_MSK);
+       at91_aic_write(AT91_AIC5_IDCR, 1);
+       /* Update ISR cache */
+       clear_backup(d->hwirq);
 }
 
 static void at91_aic_unmask_irq(struct irq_data *d)
 {
        /* Enable interrupt on AIC */
        at91_aic_write(AT91_AIC_IECR, 1 << d->hwirq);
+       /* Update ISR cache */
+       set_backup(d->hwirq);
+}
+
+static void __maybe_unused at91_aic5_unmask_irq(struct irq_data *d)
+{
+       /* Enable interrupt on AIC5 */
+       at91_aic_write(AT91_AIC5_SSR, d->hwirq & AT91_AIC5_INTSEL_MSK);
+       at91_aic_write(AT91_AIC5_IECR, 1);
+       /* Update ISR cache */
+       set_backup(d->hwirq);
 }
 
-unsigned int at91_extern_irq;
+static void at91_aic_eoi(struct irq_data *d)
+{
+       /*
+        * Mark end-of-interrupt on AIC, the controller doesn't care about
+        * the value written. Moreover it's a write-only register.
+        */
+       at91_aic_write(AT91_AIC_EOICR, 0);
+}
+
+static void __maybe_unused at91_aic5_eoi(struct irq_data *d)
+{
+       at91_aic_write(AT91_AIC5_EOICR, 0);
+}
 
-#define is_extern_irq(hwirq) ((1 << (hwirq)) & at91_extern_irq)
+unsigned long *at91_extern_irq;
 
-static int at91_aic_set_type(struct irq_data *d, unsigned type)
+#define is_extern_irq(hwirq) test_bit(hwirq, at91_extern_irq)
+
+static int at91_aic_compute_srctype(struct irq_data *d, unsigned type)
 {
-       unsigned int smr, srctype;
+       int srctype;
 
        switch (type) {
        case IRQ_TYPE_LEVEL_HIGH:
@@ -74,65 +255,51 @@ static int at91_aic_set_type(struct irq_data *d, unsigned type)
                if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq))               /* only supported on external interrupts */
                        srctype = AT91_AIC_SRCTYPE_LOW;
                else
-                       return -EINVAL;
+                       srctype = -EINVAL;
                break;
        case IRQ_TYPE_EDGE_FALLING:
                if ((d->hwirq == AT91_ID_FIQ) || is_extern_irq(d->hwirq))               /* only supported on external interrupts */
                        srctype = AT91_AIC_SRCTYPE_FALLING;
                else
-                       return -EINVAL;
+                       srctype = -EINVAL;
                break;
        default:
-               return -EINVAL;
+               srctype = -EINVAL;
        }
 
-       smr = at91_aic_read(AT91_AIC_SMR(d->hwirq)) & ~AT91_AIC_SRCTYPE;
-       at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype);
-       return 0;
+       return srctype;
 }
 
-#ifdef CONFIG_PM
-
-static u32 wakeups;
-static u32 backups;
-
-static int at91_aic_set_wake(struct irq_data *d, unsigned value)
+static int at91_aic_set_type(struct irq_data *d, unsigned type)
 {
-       if (unlikely(d->hwirq >= NR_AIC_IRQS))
-               return -EINVAL;
-
-       if (value)
-               wakeups |= (1 << d->hwirq);
-       else
-               wakeups &= ~(1 << d->hwirq);
+       unsigned int smr;
+       int srctype;
+
+       srctype = at91_aic_compute_srctype(d, type);
+       if (srctype < 0)
+               return srctype;
+
+       if (has_aic5()) {
+               at91_aic_write(AT91_AIC5_SSR,
+                              d->hwirq & AT91_AIC5_INTSEL_MSK);
+               smr = at91_aic_read(AT91_AIC5_SMR) & ~AT91_AIC_SRCTYPE;
+               at91_aic_write(AT91_AIC5_SMR, smr | srctype);
+       } else {
+               smr = at91_aic_read(AT91_AIC_SMR(d->hwirq))
+                     & ~AT91_AIC_SRCTYPE;
+               at91_aic_write(AT91_AIC_SMR(d->hwirq), smr | srctype);
+       }
 
        return 0;
 }
 
-void at91_irq_suspend(void)
-{
-       backups = at91_aic_read(AT91_AIC_IMR);
-       at91_aic_write(AT91_AIC_IDCR, backups);
-       at91_aic_write(AT91_AIC_IECR, wakeups);
-}
-
-void at91_irq_resume(void)
-{
-       at91_aic_write(AT91_AIC_IDCR, wakeups);
-       at91_aic_write(AT91_AIC_IECR, backups);
-}
-
-#else
-#define at91_aic_set_wake      NULL
-#endif
-
 static struct irq_chip at91_aic_chip = {
        .name           = "AIC",
-       .irq_ack        = at91_aic_mask_irq,
        .irq_mask       = at91_aic_mask_irq,
        .irq_unmask     = at91_aic_unmask_irq,
        .irq_set_type   = at91_aic_set_type,
        .irq_set_wake   = at91_aic_set_wake,
+       .irq_eoi        = at91_aic_eoi,
 };
 
 static void __init at91_aic_hw_init(unsigned int spu_vector)
@@ -161,41 +328,172 @@ static void __init at91_aic_hw_init(unsigned int spu_vector)
        at91_aic_write(AT91_AIC_ICCR, 0xFFFFFFFF);
 }
 
+static void __init __maybe_unused at91_aic5_hw_init(unsigned int spu_vector)
+{
+       int i;
+
+       /*
+        * Perform 8 End Of Interrupt Command to make sure AIC
+        * will not Lock out nIRQ
+        */
+       for (i = 0; i < 8; i++)
+               at91_aic_write(AT91_AIC5_EOICR, 0);
+
+       /*
+        * Spurious Interrupt ID in Spurious Vector Register.
+        * When there is no current interrupt, the IRQ Vector Register
+        * reads the value stored in AIC_SPU
+        */
+       at91_aic_write(AT91_AIC5_SPU, spu_vector);
+
+       /* No debugging in AIC: Debug (Protect) Control Register */
+       at91_aic_write(AT91_AIC5_DCR, 0);
+
+       /* Disable and clear all interrupts initially */
+       for (i = 0; i < n_irqs; i++) {
+               at91_aic_write(AT91_AIC5_SSR, i & AT91_AIC5_INTSEL_MSK);
+               at91_aic_write(AT91_AIC5_IDCR, 1);
+               at91_aic_write(AT91_AIC5_ICCR, 1);
+       }
+}
+
 #if defined(CONFIG_OF)
+static unsigned int *at91_aic_irq_priorities;
+
 static int at91_aic_irq_map(struct irq_domain *h, unsigned int virq,
                                                        irq_hw_number_t hw)
 {
        /* Put virq number in Source Vector Register */
        at91_aic_write(AT91_AIC_SVR(hw), virq);
 
-       /* Active Low interrupt, without priority */
-       at91_aic_write(AT91_AIC_SMR(hw), AT91_AIC_SRCTYPE_LOW);
+       /* Active Low interrupt, with priority */
+       at91_aic_write(AT91_AIC_SMR(hw),
+                      AT91_AIC_SRCTYPE_LOW | at91_aic_irq_priorities[hw]);
 
-       irq_set_chip_and_handler(virq, &at91_aic_chip, handle_level_irq);
+       irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq);
        set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
 
        return 0;
 }
 
+static int at91_aic5_irq_map(struct irq_domain *h, unsigned int virq,
+               irq_hw_number_t hw)
+{
+       at91_aic_write(AT91_AIC5_SSR, hw & AT91_AIC5_INTSEL_MSK);
+
+       /* Put virq number in Source Vector Register */
+       at91_aic_write(AT91_AIC5_SVR, virq);
+
+       /* Active Low interrupt, with priority */
+       at91_aic_write(AT91_AIC5_SMR,
+                      AT91_AIC_SRCTYPE_LOW | at91_aic_irq_priorities[hw]);
+
+       irq_set_chip_and_handler(virq, &at91_aic_chip, handle_fasteoi_irq);
+       set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
+
+       return 0;
+}
+
+static int at91_aic_irq_domain_xlate(struct irq_domain *d, struct device_node *ctrlr,
+                               const u32 *intspec, unsigned int intsize,
+                               irq_hw_number_t *out_hwirq, unsigned int *out_type)
+{
+       if (WARN_ON(intsize < 3))
+               return -EINVAL;
+       if (WARN_ON(intspec[0] >= n_irqs))
+               return -EINVAL;
+       if (WARN_ON((intspec[2] < AT91_AIC_IRQ_MIN_PRIORITY)
+                   || (intspec[2] > AT91_AIC_IRQ_MAX_PRIORITY)))
+               return -EINVAL;
+
+       *out_hwirq = intspec[0];
+       *out_type = intspec[1] & IRQ_TYPE_SENSE_MASK;
+       at91_aic_irq_priorities[*out_hwirq] = intspec[2];
+
+       return 0;
+}
+
 static struct irq_domain_ops at91_aic_irq_ops = {
        .map    = at91_aic_irq_map,
-       .xlate  = irq_domain_xlate_twocell,
+       .xlate  = at91_aic_irq_domain_xlate,
 };
 
-int __init at91_aic_of_init(struct device_node *node,
-                                    struct device_node *parent)
+int __init at91_aic_of_common_init(struct device_node *node,
+                                   struct device_node *parent)
 {
+       struct property *prop;
+       const __be32 *p;
+       u32 val;
+
+       at91_extern_irq = kzalloc(BITS_TO_LONGS(n_irqs)
+                                 * sizeof(*at91_extern_irq), GFP_KERNEL);
+       if (!at91_extern_irq)
+               return -ENOMEM;
+
+       if (at91_aic_pm_init()) {
+               kfree(at91_extern_irq);
+               return -ENOMEM;
+       }
+
+       at91_aic_irq_priorities = kzalloc(n_irqs
+                                         * sizeof(*at91_aic_irq_priorities),
+                                         GFP_KERNEL);
+       if (!at91_aic_irq_priorities)
+               return -ENOMEM;
+
        at91_aic_base = of_iomap(node, 0);
        at91_aic_np = node;
 
-       at91_aic_domain = irq_domain_add_linear(at91_aic_np, NR_AIC_IRQS,
+       at91_aic_domain = irq_domain_add_linear(at91_aic_np, n_irqs,
                                                &at91_aic_irq_ops, NULL);
        if (!at91_aic_domain)
                panic("Unable to add AIC irq domain (DT)\n");
 
+       of_property_for_each_u32(node, "atmel,external-irqs", prop, p, val) {
+               if (val >= n_irqs)
+                       pr_warn("AIC: external irq %d >= %d skip it\n",
+                               val, n_irqs);
+               else
+                       set_bit(val, at91_extern_irq);
+       }
+
        irq_set_default_host(at91_aic_domain);
 
-       at91_aic_hw_init(NR_AIC_IRQS);
+       return 0;
+}
+
+int __init at91_aic_of_init(struct device_node *node,
+                                    struct device_node *parent)
+{
+       int err;
+
+       err = at91_aic_of_common_init(node, parent);
+       if (err)
+               return err;
+
+       at91_aic_hw_init(n_irqs);
+
+       return 0;
+}
+
+int __init at91_aic5_of_init(struct device_node *node,
+                                    struct device_node *parent)
+{
+       int err;
+
+       at91_aic_caps |= AT91_AIC_CAP_AIC5;
+       n_irqs = NR_AIC5_IRQS;
+       at91_aic_chip.irq_ack           = at91_aic5_mask_irq;
+       at91_aic_chip.irq_mask          = at91_aic5_mask_irq;
+       at91_aic_chip.irq_unmask        = at91_aic5_unmask_irq;
+       at91_aic_chip.irq_eoi           = at91_aic5_eoi;
+       at91_aic_irq_ops.map            = at91_aic5_irq_map;
+
+       err = at91_aic_of_common_init(node, parent);
+       if (err)
+               return err;
+
+       at91_aic5_hw_init(n_irqs);
 
        return 0;
 }
@@ -204,22 +502,25 @@ int __init at91_aic_of_init(struct device_node *node,
 /*
  * Initialize the AIC interrupt controller.
  */
-void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
+void __init at91_aic_init(unsigned int *priority)
 {
        unsigned int i;
        int irq_base;
 
+       if (at91_aic_pm_init())
+               panic("Unable to allocate bit maps\n");
+
        at91_aic_base = ioremap(AT91_AIC, 512);
        if (!at91_aic_base)
                panic("Unable to ioremap AIC registers\n");
 
        /* Add irq domain for AIC */
-       irq_base = irq_alloc_descs(-1, 0, NR_AIC_IRQS, 0);
+       irq_base = irq_alloc_descs(-1, 0, n_irqs, 0);
        if (irq_base < 0) {
                WARN(1, "Cannot allocate irq_descs, assuming pre-allocated\n");
                irq_base = 0;
        }
-       at91_aic_domain = irq_domain_add_legacy(at91_aic_np, NR_AIC_IRQS,
+       at91_aic_domain = irq_domain_add_legacy(at91_aic_np, n_irqs,
                                                irq_base, 0,
                                                &irq_domain_simple_ops, NULL);
 
@@ -232,15 +533,14 @@ void __init at91_aic_init(unsigned int priority[NR_AIC_IRQS])
         * The IVR is used by macro get_irqnr_and_base to read and verify.
         * The irq number is NR_AIC_IRQS when a spurious interrupt has occurred.
         */
-       for (i = 0; i < NR_AIC_IRQS; i++) {
+       for (i = 0; i < n_irqs; i++) {
                /* Put hardware irq number in Source Vector Register: */
-               at91_aic_write(AT91_AIC_SVR(i), i);
+               at91_aic_write(AT91_AIC_SVR(i), NR_IRQS_LEGACY + i);
                /* Active Low interrupt, with the specified priority */
                at91_aic_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
-
-               irq_set_chip_and_handler(i, &at91_aic_chip, handle_level_irq);
+               irq_set_chip_and_handler(NR_IRQS_LEGACY + i, &at91_aic_chip, handle_fasteoi_irq);
                set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
        }
 
-       at91_aic_hw_init(NR_AIC_IRQS);
+       at91_aic_hw_init(n_irqs);
 }
index 1bfaad628731b262c474bc23217a30f4119eece3..2c2d86505a541fe1964f3f717d7e81c04f9e6a30 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
 
+#include <mach/at91_aic.h>
 #include <mach/at91_pmc.h>
 #include <mach/cpu.h>
 
index c965fd8eb31a14de7478eaaea8a395ab3816bbc8..f15293bd797437805dd7fcf20a6ac062512144ec 100644 (file)
@@ -26,7 +26,6 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/sched.h>
-#include <linux/timex.h>
 
 #include <asm/sizes.h>
 #include <mach/hardware.h>
@@ -188,7 +187,6 @@ static struct irqaction clps711x_timer_irq = {
 
 static void __init clps711x_timer_init(void)
 {
-       struct timespec tv;
        unsigned int syscon;
 
        syscon = clps_readl(SYSCON1);
@@ -198,10 +196,6 @@ static void __init clps711x_timer_init(void)
        clps_writel(LATCH-1, TC2D); /* 512kHz / 100Hz - 1 */
 
        setup_irq(IRQ_TC2OI, &clps711x_timer_irq);
-
-       tv.tv_nsec = 0;
-       tv.tv_sec = clps_readl(RTCDR);
-       do_settimeofday(&tv);
 }
 
 struct sys_timer clps711x_timer = {
index 3a032a67725c0d0179ddf84102c9d7ebbcbb7127..fc0e028d9405c53cfc9d20e9a726dae59bbe90b6 100644 (file)
  */
 #define PLAT_PHYS_OFFSET       UL(0xc0000000)
 
-#if !defined(CONFIG_ARCH_CDB89712) && !defined (CONFIG_ARCH_AUTCPU12)
-
-#define __virt_to_bus(x)       ((x) - PAGE_OFFSET)
-#define __bus_to_virt(x)       ((x) + PAGE_OFFSET)
-#define __pfn_to_bus(x)                (__pfn_to_phys(x) - PHYS_OFFSET)
-#define __bus_to_pfn(x)                __phys_to_pfn((x) + PHYS_OFFSET)
-
-#endif
-
-
-/*
- * Like the SA1100, the EDB7211 has a large gap between physical RAM
- * banks.  In 2.2, the Psion (CL-PS7110) port added custom support for
- * discontiguous physical memory.  In 2.4, we can use the standard
- * Linux NUMA support.
- *
- * This is not necessary for EP7211 implementations with only one used
- * memory bank.  For those systems, simply undefine CONFIG_DISCONTIGMEM.
- */
-
 /*
  * The PS7211 allows up to 256MB max per DRAM bank, but the EDB7211
  * uses only one of the two banks (bank #1).  However, even within
  * them, so we use 24 for the node max shift to get 16MB node sizes.
  */
 
-/*
- * Because of the wide memory address space between physical RAM banks on the 
- * SA1100, it's much more convenient to use Linux's NUMA support to implement
- * our memory map representation.  Assuming all memory nodes have equal access 
- * characteristics, we then have generic discontiguous memory support.
- *
- * Of course, all this isn't mandatory for SA1100 implementations with only
- * one used memory bank.  For those, simply undefine CONFIG_DISCONTIGMEM.
- *
- * The nodes are matched with the physical memory bank addresses which are 
- * incidentally the same as virtual addresses.
- * 
- *     node 0:  0xc0000000 - 0xc7ffffff
- *     node 1:  0xc8000000 - 0xcfffffff
- *     node 2:  0xd0000000 - 0xd7ffffff
- *     node 3:  0xd8000000 - 0xdfffffff
- */
 #define SECTION_SIZE_BITS      24
 #define MAX_PHYSMEM_BITS       32
 
index 42ee8f33eafbaf7421c6db5b5dd0630971fc660b..f266d90b9efc0e8a4cc79b92b8ece9214c31c2e7 100644 (file)
@@ -86,17 +86,7 @@ static void __init p720t_map_io(void)
        iotable_init(p720t_io_desc, ARRAY_SIZE(p720t_io_desc));
 }
 
-MACHINE_START(P720T, "ARM-Prospector720T")
-       /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-       .atag_offset    = 0x100,
-       .fixup          = fixup_p720t,
-       .map_io         = p720t_map_io,
-       .init_irq       = clps711x_init_irq,
-       .timer          = &clps711x_timer,
-       .restart        = clps711x_restart,
-MACHINE_END
-
-static int p720t_hw_init(void)
+static void __init p720t_init_early(void)
 {
        /*
         * Power down as much as possible in case we don't
@@ -111,13 +101,19 @@ static int p720t_hw_init(void)
        PLD_CODEC = 0;
        PLD_TCH   = 0;
        PLD_SPI   = 0;
-#ifndef CONFIG_DEBUG_LL
-       PLD_COM2  = 0;
-       PLD_COM1  = 0;
-#endif
-
-       return 0;
+       if (!IS_ENABLED(CONFIG_DEBUG_LL)) {
+               PLD_COM2 = 0;
+               PLD_COM1 = 0;
+       }
 }
 
-__initcall(p720t_hw_init);
-
+MACHINE_START(P720T, "ARM-Prospector720T")
+       /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
+       .atag_offset    = 0x100,
+       .fixup          = fixup_p720t,
+       .init_early     = p720t_init_early,
+       .map_io         = p720t_map_io,
+       .init_irq       = clps711x_init_irq,
+       .timer          = &clps711x_timer,
+       .restart        = clps711x_restart,
+MACHINE_END
index 32d837d8eab97ded50f9d861faee3b16f3fb0dd0..2ce1ef07c13d63c52edea705c655ea2f8ef3469f 100644 (file)
@@ -4,6 +4,7 @@ config AINTC
        bool
 
 config CP_INTC
+       select IRQ_DOMAIN
        bool
 
 config ARCH_DAVINCI_DMx
index 2db78bd5c835dbda436faf7184fc837b8eed8f0e..2227effcb0e98bdea4968b95617e06cf3c0b5f39 100644 (file)
@@ -39,3 +39,4 @@ obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD) += board-omapl138-hawk.o
 obj-$(CONFIG_CPU_FREQ)                 += cpufreq.o
 obj-$(CONFIG_CPU_IDLE)                 += cpuidle.o
 obj-$(CONFIG_SUSPEND)                  += pm.o sleep.o
+obj-$(CONFIG_HAVE_CLK)                 += pm_domain.o
index f83152d643c5d58921a7b91a826a1790b7bbe4f9..006dae8dfe443b3474ae6df73b5c97cf93502f33 100644 (file)
@@ -9,9 +9,14 @@
  * kind, whether express or implied.
  */
 
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <mach/common.h>
 #include <mach/cp_intc.h>
@@ -28,7 +33,7 @@ static inline void cp_intc_write(unsigned long value, unsigned offset)
 
 static void cp_intc_ack_irq(struct irq_data *d)
 {
-       cp_intc_write(d->irq, CP_INTC_SYS_STAT_IDX_CLR);
+       cp_intc_write(d->hwirq, CP_INTC_SYS_STAT_IDX_CLR);
 }
 
 /* Disable interrupt */
@@ -36,20 +41,20 @@ static void cp_intc_mask_irq(struct irq_data *d)
 {
        /* XXX don't know why we need to disable nIRQ here... */
        cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_CLR);
-       cp_intc_write(d->irq, CP_INTC_SYS_ENABLE_IDX_CLR);
+       cp_intc_write(d->hwirq, CP_INTC_SYS_ENABLE_IDX_CLR);
        cp_intc_write(1, CP_INTC_HOST_ENABLE_IDX_SET);
 }
 
 /* Enable interrupt */
 static void cp_intc_unmask_irq(struct irq_data *d)
 {
-       cp_intc_write(d->irq, CP_INTC_SYS_ENABLE_IDX_SET);
+       cp_intc_write(d->hwirq, CP_INTC_SYS_ENABLE_IDX_SET);
 }
 
 static int cp_intc_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-       unsigned reg            = BIT_WORD(d->irq);
-       unsigned mask           = BIT_MASK(d->irq);
+       unsigned reg            = BIT_WORD(d->hwirq);
+       unsigned mask           = BIT_MASK(d->hwirq);
        unsigned polarity       = cp_intc_read(CP_INTC_SYS_POLARITY(reg));
        unsigned type           = cp_intc_read(CP_INTC_SYS_TYPE(reg));
 
@@ -99,18 +104,43 @@ static struct irq_chip cp_intc_irq_chip = {
        .irq_set_wake   = cp_intc_set_wake,
 };
 
-void __init cp_intc_init(void)
+static struct irq_domain *cp_intc_domain;
+
+static int cp_intc_host_map(struct irq_domain *h, unsigned int virq,
+                         irq_hw_number_t hw)
 {
-       unsigned long num_irq   = davinci_soc_info.intc_irq_num;
+       pr_debug("cp_intc_host_map(%d, 0x%lx)\n", virq, hw);
+
+       irq_set_chip(virq, &cp_intc_irq_chip);
+       set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
+       irq_set_handler(virq, handle_edge_irq);
+       return 0;
+}
+
+static const struct irq_domain_ops cp_intc_host_ops = {
+       .map = cp_intc_host_map,
+       .xlate = irq_domain_xlate_onetwocell,
+};
+
+int __init cp_intc_of_init(struct device_node *node, struct device_node *parent)
+{
+       u32 num_irq             = davinci_soc_info.intc_irq_num;
        u8 *irq_prio            = davinci_soc_info.intc_irq_prios;
        u32 *host_map           = davinci_soc_info.intc_host_map;
        unsigned num_reg        = BITS_TO_LONGS(num_irq);
-       int i;
+       int i, irq_base;
 
        davinci_intc_type = DAVINCI_INTC_TYPE_CP_INTC;
-       davinci_intc_base = ioremap(davinci_soc_info.intc_base, SZ_8K);
+       if (node) {
+               davinci_intc_base = of_iomap(node, 0);
+               if (of_property_read_u32(node, "ti,intc-size", &num_irq))
+                       pr_warn("unable to get intc-size, default to %d\n",
+                               num_irq);
+       } else {
+               davinci_intc_base = ioremap(davinci_soc_info.intc_base, SZ_8K);
+       }
        if (WARN_ON(!davinci_intc_base))
-               return;
+               return -EINVAL;
 
        cp_intc_write(0, CP_INTC_GLOBAL_ENABLE);
 
@@ -165,13 +195,28 @@ void __init cp_intc_init(void)
                for (i = 0; host_map[i] != -1; i++)
                        cp_intc_write(host_map[i], CP_INTC_HOST_MAP(i));
 
-       /* Set up genirq dispatching for cp_intc */
-       for (i = 0; i < num_irq; i++) {
-               irq_set_chip(i, &cp_intc_irq_chip);
-               set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-               irq_set_handler(i, handle_edge_irq);
+       irq_base = irq_alloc_descs(-1, 0, num_irq, 0);
+       if (irq_base < 0) {
+               pr_warn("Couldn't allocate IRQ numbers\n");
+               irq_base = 0;
+       }
+
+       /* create a legacy host */
+       cp_intc_domain = irq_domain_add_legacy(node, num_irq,
+                                       irq_base, 0, &cp_intc_host_ops, NULL);
+
+       if (!cp_intc_domain) {
+               pr_err("cp_intc: failed to allocate irq host!\n");
+               return -EINVAL;
        }
 
        /* Enable global interrupt */
        cp_intc_write(1, CP_INTC_GLOBAL_ENABLE);
+
+       return 0;
+}
+
+void __init cp_intc_init(void)
+{
+       cp_intc_of_init(NULL, NULL);
 }
index 4e8190eed673dca87281134821ab5fa06ac477f7..d13d8dfa2b0d6c6d871c80a5ebdbb19f237476b7 100644 (file)
@@ -52,5 +52,6 @@
 #define CP_INTC_VECTOR_ADDR(n)         (0x2000 + (n << 2))
 
 void __init cp_intc_init(void);
+int __init cp_intc_of_init(struct device_node *, struct device_node *);
 
 #endif /* __ASM_HARDWARE_CP_INTC_H */
diff --git a/arch/arm/mach-davinci/include/mach/dm365.h b/arch/arm/mach-davinci/include/mach/dm365.h
deleted file mode 100644 (file)
index b9bf3d6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/* empty, remove once unused */
diff --git a/arch/arm/mach-davinci/include/mach/dm646x.h b/arch/arm/mach-davinci/include/mach/dm646x.h
deleted file mode 100644 (file)
index b9bf3d6..0000000
+++ /dev/null
@@ -1 +0,0 @@
-/* empty, remove once unused */
index 768b3c0602140e789286b7182bb07e2b31336282..cf5f573eb5fd713c6d407bb752a870e7abbc0992 100644 (file)
 #endif
 #if defined(CONFIG_CP_INTC)
 1001:          ldr \irqnr, [\base, #0x80] /* get irq number */
+               mov \tmp, \irqnr, lsr #31
                and \irqnr, \irqnr, #0xff  /* irq is in bits 0-9 */
-               mov \tmp, \irqnr, lsr #3
-               and \tmp, \tmp, #0xfc
-               add \tmp, \tmp, #0x280 /* get the register offset */
-               ldr \irqstat, [\base, \tmp] /* get the intc status */
-               cmp \irqstat, #0x0
+               and \tmp, \tmp, #0x1
+               cmp \tmp, #0x1
 #endif
 1002:
                .endm
diff --git a/arch/arm/mach-davinci/pm_domain.c b/arch/arm/mach-davinci/pm_domain.c
new file mode 100644 (file)
index 0000000..00946e2
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Runtime PM support code for DaVinci
+ *
+ * Author: Kevin Hilman
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+#include <linux/init.h>
+#include <linux/pm_runtime.h>
+#include <linux/pm_clock.h>
+#include <linux/platform_device.h>
+
+#ifdef CONFIG_PM_RUNTIME
+static int davinci_pm_runtime_suspend(struct device *dev)
+{
+       int ret;
+
+       dev_dbg(dev, "%s\n", __func__);
+
+       ret = pm_generic_runtime_suspend(dev);
+       if (ret)
+               return ret;
+
+       ret = pm_clk_suspend(dev);
+       if (ret) {
+               pm_generic_runtime_resume(dev);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int davinci_pm_runtime_resume(struct device *dev)
+{
+       dev_dbg(dev, "%s\n", __func__);
+
+       pm_clk_resume(dev);
+       return pm_generic_runtime_resume(dev);
+}
+#endif
+
+static struct dev_pm_domain davinci_pm_domain = {
+       .ops = {
+               SET_RUNTIME_PM_OPS(davinci_pm_runtime_suspend,
+                                  davinci_pm_runtime_resume, NULL)
+               USE_PLATFORM_PM_SLEEP_OPS
+       },
+};
+
+static struct pm_clk_notifier_block platform_bus_notifier = {
+       .pm_domain = &davinci_pm_domain,
+};
+
+static int __init davinci_pm_runtime_init(void)
+{
+       pm_clk_add_notifier(&platform_bus_type, &platform_bus_notifier);
+
+       return 0;
+}
+core_initcall(davinci_pm_runtime_init);
index 4dd07a0e3604a19498cf4fa507b544a666e2d8a5..4afe52aaaff3573e97e6d46ba479b56303445f89 100644 (file)
@@ -797,6 +797,102 @@ static struct platform_device ep93xx_wdt_device = {
        .resource       = ep93xx_wdt_resources,
 };
 
+/*************************************************************************
+ * EP93xx IDE
+ *************************************************************************/
+static struct resource ep93xx_ide_resources[] = {
+       DEFINE_RES_MEM(EP93XX_IDE_PHYS_BASE, 0x38),
+       DEFINE_RES_IRQ(IRQ_EP93XX_EXT3),
+};
+
+static struct platform_device ep93xx_ide_device = {
+       .name           = "ep93xx-ide",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &ep93xx_ide_device.dev.coherent_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .num_resources  = ARRAY_SIZE(ep93xx_ide_resources),
+       .resource       = ep93xx_ide_resources,
+};
+
+void __init ep93xx_register_ide(void)
+{
+       platform_device_register(&ep93xx_ide_device);
+}
+
+int ep93xx_ide_acquire_gpio(struct platform_device *pdev)
+{
+       int err;
+       int i;
+
+       err = gpio_request(EP93XX_GPIO_LINE_EGPIO2, dev_name(&pdev->dev));
+       if (err)
+               return err;
+       err = gpio_request(EP93XX_GPIO_LINE_EGPIO15, dev_name(&pdev->dev));
+       if (err)
+               goto fail_egpio15;
+       for (i = 2; i < 8; i++) {
+               err = gpio_request(EP93XX_GPIO_LINE_E(i), dev_name(&pdev->dev));
+               if (err)
+                       goto fail_gpio_e;
+       }
+       for (i = 4; i < 8; i++) {
+               err = gpio_request(EP93XX_GPIO_LINE_G(i), dev_name(&pdev->dev));
+               if (err)
+                       goto fail_gpio_g;
+       }
+       for (i = 0; i < 8; i++) {
+               err = gpio_request(EP93XX_GPIO_LINE_H(i), dev_name(&pdev->dev));
+               if (err)
+                       goto fail_gpio_h;
+       }
+
+       /* GPIO ports E[7:2], G[7:4] and H used by IDE */
+       ep93xx_devcfg_clear_bits(EP93XX_SYSCON_DEVCFG_EONIDE |
+                                EP93XX_SYSCON_DEVCFG_GONIDE |
+                                EP93XX_SYSCON_DEVCFG_HONIDE);
+       return 0;
+
+fail_gpio_h:
+       for (--i; i >= 0; --i)
+               gpio_free(EP93XX_GPIO_LINE_H(i));
+       i = 8;
+fail_gpio_g:
+       for (--i; i >= 4; --i)
+               gpio_free(EP93XX_GPIO_LINE_G(i));
+       i = 8;
+fail_gpio_e:
+       for (--i; i >= 2; --i)
+               gpio_free(EP93XX_GPIO_LINE_E(i));
+       gpio_free(EP93XX_GPIO_LINE_EGPIO15);
+fail_egpio15:
+       gpio_free(EP93XX_GPIO_LINE_EGPIO2);
+       return err;
+}
+EXPORT_SYMBOL(ep93xx_ide_acquire_gpio);
+
+void ep93xx_ide_release_gpio(struct platform_device *pdev)
+{
+       int i;
+
+       for (i = 2; i < 8; i++)
+               gpio_free(EP93XX_GPIO_LINE_E(i));
+       for (i = 4; i < 8; i++)
+               gpio_free(EP93XX_GPIO_LINE_G(i));
+       for (i = 0; i < 8; i++)
+               gpio_free(EP93XX_GPIO_LINE_H(i));
+       gpio_free(EP93XX_GPIO_LINE_EGPIO15);
+       gpio_free(EP93XX_GPIO_LINE_EGPIO2);
+
+
+       /* GPIO ports E[7:2], G[7:4] and H used by GPIO */
+       ep93xx_devcfg_set_bits(EP93XX_SYSCON_DEVCFG_EONIDE |
+                              EP93XX_SYSCON_DEVCFG_GONIDE |
+                              EP93XX_SYSCON_DEVCFG_HONIDE);
+}
+EXPORT_SYMBOL(ep93xx_ide_release_gpio);
+
 void __init ep93xx_init_devices(void)
 {
        /* Disallow access to MaverickCrunch initially */
index d74c5cddb98b654972ae986489f90c0e700aa190..337ab7cf4c16fc81391883c435e2be66d1f44298 100644 (file)
@@ -91,8 +91,8 @@ static void __init edb93xx_register_i2c(void)
                ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
                                    edb93xxa_i2c_board_info,
                                    ARRAY_SIZE(edb93xxa_i2c_board_info));
-       } else if (machine_is_edb9307() || machine_is_edb9312() ||
-                  machine_is_edb9315()) {
+       } else if (machine_is_edb9302() || machine_is_edb9307()
+               || machine_is_edb9312() || machine_is_edb9315()) {
                ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
                                    edb93xx_i2c_board_info,
                                    ARRAY_SIZE(edb93xx_i2c_board_info));
@@ -233,6 +233,29 @@ static void __init edb93xx_register_fb(void)
 }
 
 
+/*************************************************************************
+ * EDB93xx IDE
+ *************************************************************************/
+static int __init edb93xx_has_ide(void)
+{
+       /*
+        * Although EDB9312 and EDB9315 do have IDE capability, they have
+        * INTRQ line wired as pull-up, which makes using IDE interface
+        * problematic.
+        */
+       return machine_is_edb9312() || machine_is_edb9315() ||
+              machine_is_edb9315a();
+}
+
+static void __init edb93xx_register_ide(void)
+{
+       if (!edb93xx_has_ide())
+               return;
+
+       ep93xx_register_ide();
+}
+
+
 static void __init edb93xx_init_machine(void)
 {
        ep93xx_init_devices();
@@ -243,6 +266,7 @@ static void __init edb93xx_init_machine(void)
        edb93xx_register_i2s();
        edb93xx_register_pwm();
        edb93xx_register_fb();
+       edb93xx_register_ide();
 }
 
 
index 1ecb040d98bf7f3e390f76473ec85c7c50e377a3..33a5122c6dc8bac0954655a5d5795b12a0d0df85 100644 (file)
@@ -48,6 +48,9 @@ void ep93xx_register_i2s(void);
 int ep93xx_i2s_acquire(void);
 void ep93xx_i2s_release(void);
 void ep93xx_register_ac97(void);
+void ep93xx_register_ide(void);
+int ep93xx_ide_acquire_gpio(struct platform_device *pdev);
+void ep93xx_ide_release_gpio(struct platform_device *pdev);
 
 void ep93xx_init_devices(void);
 extern struct sys_timer ep93xx_timer;
index 979fba72292628e8bddd22ba7660df9514bb2ebb..7bf7ff8beae73f28aec97693a9cda48c6a8212bf 100644 (file)
@@ -69,6 +69,7 @@
 
 #define EP93XX_BOOT_ROM_BASE           EP93XX_AHB_IOMEM(0x00090000)
 
+#define EP93XX_IDE_PHYS_BASE           EP93XX_AHB_PHYS(0x000a0000)
 #define EP93XX_IDE_BASE                        EP93XX_AHB_IOMEM(0x000a0000)
 
 #define EP93XX_VIC1_BASE               EP93XX_AHB_IOMEM(0x000b0000)
index 6f6d13f91e4ca1fc65448ee4b4f950ea0eeeeebc..b5b4c8c9db11adfe4a78d642a910207846abffbe 100644 (file)
@@ -207,6 +207,7 @@ config MACH_SMDKV310
        select S3C_DEV_HSMMC1
        select S3C_DEV_HSMMC2
        select S3C_DEV_HSMMC3
+       select S3C_DEV_USB_HSOTG
        select SAMSUNG_DEV_BACKLIGHT
        select EXYNOS_DEV_DRM
        select EXYNOS_DEV_SYSMMU
@@ -326,6 +327,7 @@ config MACH_ORIGEN
        select S3C_DEV_WDT
        select S3C_DEV_HSMMC
        select S3C_DEV_HSMMC2
+       select S3C_DEV_USB_HSOTG
        select S5P_DEV_FIMC0
        select S5P_DEV_FIMC1
        select S5P_DEV_FIMC2
@@ -360,22 +362,27 @@ config MACH_SMDK4212
        select S3C_DEV_I2C3
        select S3C_DEV_I2C7
        select S3C_DEV_RTC
+       select S3C_DEV_USB_HSOTG
        select S3C_DEV_WDT
        select S5P_DEV_FIMC0
        select S5P_DEV_FIMC1
        select S5P_DEV_FIMC2
        select S5P_DEV_FIMC3
+       select S5P_DEV_FIMD0
        select S5P_DEV_MFC
        select SAMSUNG_DEV_BACKLIGHT
        select SAMSUNG_DEV_KEYPAD
        select SAMSUNG_DEV_PWM
        select EXYNOS_DEV_SYSMMU
        select EXYNOS_DEV_DMA
+       select EXYNOS_DEV_DRM
+       select EXYNOS4_SETUP_FIMD0
        select EXYNOS4_SETUP_I2C1
        select EXYNOS4_SETUP_I2C3
        select EXYNOS4_SETUP_I2C7
        select EXYNOS4_SETUP_KEYPAD
        select EXYNOS4_SETUP_SDHCI
+       select EXYNOS4_SETUP_USB_PHY
        help
          Machine support for Samsung SMDK4212
 
index bcb7db45314599cd975a6ad904d199c881c4e6cf..26fe9de35ecb8ca715f73a4cee3955591b1e2b2a 100644 (file)
@@ -586,17 +586,17 @@ static struct clk exynos4_init_clocks_off[] = {
                .ctrlbit        = (1 << 13),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "exynos4210-spi.0",
                .enable         = exynos4_clk_ip_peril_ctrl,
                .ctrlbit        = (1 << 16),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "exynos4210-spi.1",
                .enable         = exynos4_clk_ip_peril_ctrl,
                .ctrlbit        = (1 << 17),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.2",
+               .devname        = "exynos4210-spi.2",
                .enable         = exynos4_clk_ip_peril_ctrl,
                .ctrlbit        = (1 << 18),
        }, {
@@ -1242,40 +1242,67 @@ static struct clksrc_clk exynos4_clk_sclk_mmc3 = {
        .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        = "s3c64xx-spi.0",
+               .devname        = "exynos4210-spi.0",
+               .parent         = &exynos4_clk_mdout_spi0.clk,
                .enable         = exynos4_clksrc_mask_peril1_ctrl,
                .ctrlbit        = (1 << 16),
        },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 16, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 0, .size = 4 },
+       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 8, .size = 8 },
 };
 
 static struct clksrc_clk exynos4_clk_sclk_spi1 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "exynos4210-spi.1",
+               .parent         = &exynos4_clk_mdout_spi1.clk,
                .enable         = exynos4_clksrc_mask_peril1_ctrl,
                .ctrlbit        = (1 << 20),
        },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 20, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 16, .size = 4 },
+       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL1, .shift = 24, .size = 8 },
 };
 
 static struct clksrc_clk exynos4_clk_sclk_spi2 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.2",
+               .devname        = "exynos4210-spi.2",
+               .parent         = &exynos4_clk_mdout_spi2.clk,
                .enable         = exynos4_clksrc_mask_peril1_ctrl,
                .ctrlbit        = (1 << 24),
        },
-       .sources = &exynos4_clkset_group,
-       .reg_src = { .reg = EXYNOS4_CLKSRC_PERIL1, .shift = 24, .size = 4 },
-       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 0, .size = 4 },
+       .reg_div = { .reg = EXYNOS4_CLKDIV_PERIL2, .shift = 8, .size = 8 },
 };
 
 /* Clock initialization code */
@@ -1331,7 +1358,9 @@ static struct clksrc_clk *exynos4_clksrc_cdev[] = {
        &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[] = {
@@ -1347,9 +1376,9 @@ static struct clk_lookup exynos4_clk_lookup[] = {
        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("s3c64xx-spi.0", "spi_busclk0", &exynos4_clk_sclk_spi0.clk),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk0", &exynos4_clk_sclk_spi1.clk),
-       CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk0", &exynos4_clk_sclk_spi2.clk),
+       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;
index fefa336be2b4baf8d841a809766be3bdf9338f83..774533c670667c1a7a8e16986e7ababa841ee48e 100644 (file)
@@ -131,6 +131,11 @@ 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);
@@ -740,6 +745,24 @@ static struct clk exynos5_init_clocks_off[] = {
                .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           = SYSMMU_CLOCK_NAME,
                .devname        = SYSMMU_CLOCK_DEVNAME(mfc_l, 0),
@@ -1034,6 +1057,69 @@ static struct clksrc_clk exynos5_clk_sclk_mmc3 = {
        .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_clksrcs[] = {
        {
                .clk    = {
@@ -1148,6 +1234,12 @@ static struct clksrc_clk *exynos5_sysclks[] = {
        &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,
 };
 
 static struct clk *exynos5_clk_cdev[] = {
@@ -1176,6 +1268,9 @@ static struct clk_lookup exynos5_clk_lookup[] = {
        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),
index 742edd3bbec34b14f9c6e1817029b9c81f602c03..4eb39cdf75eab7b524ab090af5179315797107ce 100644 (file)
@@ -540,7 +540,8 @@ 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 void __init combiner_init(void __iomem *combiner_base,
+                                struct device_node *np)
 {
        int i, irq, irq_base;
        unsigned int max_nr, nr_irq;
@@ -712,31 +713,6 @@ static int __init exynos4_l2x0_cache_init(void)
 early_initcall(exynos4_l2x0_cache_init);
 #endif
 
-static int __init exynos5_l2_cache_init(void)
-{
-       unsigned int val;
-
-       if (!soc_is_exynos5250())
-               return 0;
-
-       asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
-                    "bic %0, %0, #(1 << 2)\n"  /* cache disable */
-                    "mcr p15, 0, %0, c1, c0, 0\n"
-                    "mrc p15, 1, %0, c9, c0, 2\n"
-                    : "=r"(val));
-
-       val |= (1 << 9) | (1 << 5) | (2 << 6) | (2 << 0);
-
-       asm volatile("mcr p15, 1, %0, c9, c0, 2\n" : : "r"(val));
-       asm volatile("mrc p15, 0, %0, c1, c0, 0\n"
-                    "orr %0, %0, #(1 << 2)\n"  /* cache enable */
-                    "mcr p15, 0, %0, c1, c0, 0\n"
-                    : : "r"(val));
-
-       return 0;
-}
-early_initcall(exynos5_l2_cache_init);
-
 static int __init exynos_init(void)
 {
        printk(KERN_INFO "EXYNOS: Initializing architecture\n");
index 7a4b4789eb7288205fcfcd555dcf50ffdb962753..35bced6f9092141920152664267362a54cdf8161 100644 (file)
 #define IRQ_IIC6                       EXYNOS4_IRQ_IIC6
 #define IRQ_IIC7                       EXYNOS4_IRQ_IIC7
 
+#define IRQ_SPI0                       EXYNOS4_IRQ_SPI0
+#define IRQ_SPI1                       EXYNOS4_IRQ_SPI1
+#define IRQ_SPI2                       EXYNOS4_IRQ_SPI2
+
 #define IRQ_USB_HOST                   EXYNOS4_IRQ_USB_HOST
 #define IRQ_OTG                                EXYNOS4_IRQ_USB_HSOTG
 
index ca4aa89aa46b357fe5ff04710bd9ffdf4caf361b..c72b675b3e4b98f07dd26353d1dcbb3ee7ae12e6 100644 (file)
 #define EXYNOS4_PA_SPI0                        0x13920000
 #define EXYNOS4_PA_SPI1                        0x13930000
 #define EXYNOS4_PA_SPI2                        0x13940000
+#define EXYNOS5_PA_SPI0                        0x12D20000
+#define EXYNOS5_PA_SPI1                        0x12D30000
+#define EXYNOS5_PA_SPI2                        0x12D40000
 
 #define EXYNOS4_PA_GPIO1               0x11400000
 #define EXYNOS4_PA_GPIO2               0x11000000
index 43a99e6f56ab68e638621f8fb9e6b23c910005b3..d4e392b811a315d6a477f677b4462359ed9c8f6f 100644 (file)
 
 #define EXYNOS5_USB_CFG                                                S5P_PMUREG(0x0230)
 
+#define EXYNOS5_AUTO_WDTRESET_DISABLE                          S5P_PMUREG(0x0408)
+#define EXYNOS5_MASK_WDTRESET_REQUEST                          S5P_PMUREG(0x040C)
+
+#define EXYNOS5_SYS_WDTRESET                                   (1 << 20)
+
 #define EXYNOS5_ARM_CORE0_SYS_PWR_REG                          S5P_PMUREG(0x1000)
 #define EXYNOS5_DIS_IRQ_ARM_CORE0_LOCAL_SYS_PWR_REG            S5P_PMUREG(0x1004)
 #define EXYNOS5_DIS_IRQ_ARM_CORE0_CENTRAL_SYS_PWR_REG          S5P_PMUREG(0x1008)
index c337cf3a71bf35e39bf4780f481a36a1c54db9aa..07277735252e39b3437e8cdb2fddeaf44e1c3cd9 100644 (file)
 #define PHY1_COMMON_ON_N               (1 << 7)
 #define PHY0_COMMON_ON_N               (1 << 4)
 #define PHY0_ID_PULLUP                 (1 << 2)
-#define CLKSEL_MASK                    (0x3 << 0)
-#define CLKSEL_SHIFT                   (0)
-#define CLKSEL_48M                     (0x0 << 0)
-#define CLKSEL_12M                     (0x2 << 0)
-#define CLKSEL_24M                     (0x3 << 0)
+
+#define EXYNOS4_CLKSEL_SHIFT           (0)
+
+#define EXYNOS4210_CLKSEL_MASK         (0x3 << 0)
+#define EXYNOS4210_CLKSEL_48M          (0x0 << 0)
+#define EXYNOS4210_CLKSEL_12M          (0x2 << 0)
+#define EXYNOS4210_CLKSEL_24M          (0x3 << 0)
+
+#define EXYNOS4X12_CLKSEL_MASK         (0x7 << 0)
+#define EXYNOS4X12_CLKSEL_9600K                (0x0 << 0)
+#define EXYNOS4X12_CLKSEL_10M          (0x1 << 0)
+#define EXYNOS4X12_CLKSEL_12M          (0x2 << 0)
+#define EXYNOS4X12_CLKSEL_19200K       (0x3 << 0)
+#define EXYNOS4X12_CLKSEL_20M          (0x4 << 0)
+#define EXYNOS4X12_CLKSEL_24M          (0x5 << 0)
 
 #define EXYNOS4_RSTCON                 EXYNOS4_HSOTG_PHYREG(0x08)
 #define HOST_LINK_PORT_SWRST_MASK      (0xf << 6)
diff --git a/arch/arm/mach-exynos/include/mach/spi-clocks.h b/arch/arm/mach-exynos/include/mach/spi-clocks.h
deleted file mode 100644 (file)
index c71a5fb..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/* linux/arch/arm/mach-exynos4/include/mach/spi-clocks.h
- *
- * Copyright (C) 2011 Samsung Electronics Co. Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARCH_SPI_CLKS_H
-#define __ASM_ARCH_SPI_CLKS_H __FILE__
-
-/* Must source from SCLK_SPI */
-#define EXYNOS_SPI_SRCCLK_SCLK         0
-
-#endif /* __ASM_ARCH_SPI_CLKS_H */
index e7e9743543acd6384f38f5cfcfcd7b4760872225..b2b5d5faa74854adea983f3b2b1b085b6d133540 100644 (file)
@@ -55,6 +55,12 @@ static const struct of_dev_auxdata exynos4210_auxdata_lookup[] __initconst = {
                                "exynos4-sdhci.3", NULL),
        OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS4_PA_IIC(0),
                                "s3c2440-i2c.0", 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),
        {},
index 7b1e11a228cce49776135f140316c83182f4d440..ef770bc2318fcbd074387a6c5278a007f169773d 100644 (file)
@@ -47,6 +47,12 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
                                "s3c2440-i2c.0", NULL),
        OF_DEV_AUXDATA("samsung,s3c2440-i2c", EXYNOS5_PA_IIC(1),
                                "s3c2440-i2c.1", 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("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),
index 656f8fc9addd3b67ecaafbe9207f279da01b3b70..f98a83a81ce73ed0cd89f364bfa87956802e7be8 100644 (file)
@@ -50,7 +50,6 @@
 #include <plat/gpio-cfg.h>
 #include <plat/iic.h>
 #include <plat/mfc.h>
-#include <plat/pd.h>
 #include <plat/fimc-core.h>
 #include <plat/camport.h>
 #include <plat/mipi_csis.h>
@@ -1342,9 +1341,8 @@ static struct platform_device *nuri_devices[] __initdata = {
 
 static void __init nuri_map_io(void)
 {
-       clk_xusbxti.rate = 24000000;
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(24000000);
+       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
 }
 
index f5572be9d7bf38480f931618d27507738aaf1ad6..5a12dc26f496a7e2ef3552f1728d66ea11f09ef8 100644 (file)
@@ -9,6 +9,7 @@
 */
 
 #include <linux/serial_core.h>
+#include <linux/leds.h>
 #include <linux/gpio.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
@@ -21,6 +22,7 @@
 #include <linux/mfd/max8997.h>
 #include <linux/lcd.h>
 #include <linux/rfkill-gpio.h>
+#include <linux/platform_data/s3c-hsotg.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -38,7 +40,6 @@
 #include <plat/clock.h>
 #include <plat/gpio-cfg.h>
 #include <plat/backlight.h>
-#include <plat/pd.h>
 #include <plat/fb.h>
 #include <plat/mfc.h>
 
@@ -499,6 +500,37 @@ static void __init origen_ohci_init(void)
        exynos4_ohci_set_platdata(pdata);
 }
 
+/* USB OTG */
+static struct s3c_hsotg_plat origen_hsotg_pdata;
+
+static struct gpio_led origen_gpio_leds[] = {
+       {
+               .name                   = "origen::status1",
+               .default_trigger        = "heartbeat",
+               .gpio                   = EXYNOS4_GPX1(3),
+               .active_low             = 1,
+       },
+       {
+               .name                   = "origen::status2",
+               .default_trigger        = "mmc0",
+               .gpio                   = EXYNOS4_GPX1(4),
+               .active_low             = 1,
+       },
+};
+
+static struct gpio_led_platform_data origen_gpio_led_info = {
+       .leds           = origen_gpio_leds,
+       .num_leds       = ARRAY_SIZE(origen_gpio_leds),
+};
+
+static struct platform_device origen_leds_gpio = {
+       .name   = "leds-gpio",
+       .id     = -1,
+       .dev    = {
+               .platform_data  = &origen_gpio_led_info,
+       },
+};
+
 static struct gpio_keys_button origen_gpio_keys_table[] = {
        {
                .code                   = KEY_MENU,
@@ -655,6 +687,7 @@ static struct platform_device *origen_devices[] __initdata = {
        &s3c_device_hsmmc0,
        &s3c_device_i2c0,
        &s3c_device_rtc,
+       &s3c_device_usb_hsotg,
        &s3c_device_wdt,
        &s5p_device_ehci,
        &s5p_device_fimc0,
@@ -677,6 +710,7 @@ static struct platform_device *origen_devices[] __initdata = {
        &exynos4_device_ohci,
        &origen_device_gpiokeys,
        &origen_lcd_hv070wsa,
+       &origen_leds_gpio,
        &origen_device_bluetooth,
 };
 
@@ -712,7 +746,7 @@ static void s5p_tv_setup(void)
 static void __init origen_map_io(void)
 {
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(24000000);
+       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(origen_uartcfgs, ARRAY_SIZE(origen_uartcfgs));
 }
 
@@ -744,7 +778,7 @@ static void __init origen_machine_init(void)
 
        origen_ehci_init();
        origen_ohci_init();
-       clk_xusbxti.rate = 24000000;
+       s3c_hsotg_set_platdata(&origen_hsotg_pdata);
 
        s5p_tv_setup();
        s5p_i2c_hdmiphy_set_platdata(NULL);
index fb09c70e195af8a61e3399fb0db0926222905a66..b26beb13ebef40ff03bb524a6a8a9e8733e7efe9 100644 (file)
 #include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/io.h>
+#include <linux/lcd.h>
 #include <linux/mfd/max8997.h>
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
 #include <linux/pwm_backlight.h>
 #include <linux/regulator/machine.h>
 #include <linux/serial_core.h>
+#include <linux/platform_data/s3c-hsotg.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
 #include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/devs.h>
+#include <plat/fb.h>
 #include <plat/gpio-cfg.h>
 #include <plat/iic.h>
 #include <plat/keypad.h>
 #include <plat/mfc.h>
+#include <plat/regs-fb.h>
 #include <plat/regs-serial.h>
 #include <plat/sdhci.h>
 
 #include <mach/map.h>
 
+#include <drm/exynos_drm.h>
 #include "common.h"
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
@@ -219,8 +224,10 @@ static struct platform_pwm_backlight_data smdk4x12_bl_data = {
 
 static uint32_t smdk4x12_keymap[] __initdata = {
        /* KEY(row, col, keycode) */
-       KEY(1, 0, KEY_D), KEY(1, 1, KEY_A), KEY(1, 2, KEY_B),
-       KEY(1, 3, KEY_E), KEY(1, 4, KEY_C)
+       KEY(1, 3, KEY_1), KEY(1, 4, KEY_2), KEY(1, 5, KEY_3),
+       KEY(1, 6, KEY_4), KEY(1, 7, KEY_5),
+       KEY(2, 5, KEY_D), KEY(2, 6, KEY_A), KEY(2, 7, KEY_B),
+       KEY(0, 7, KEY_E), KEY(0, 5, KEY_C)
 };
 
 static struct matrix_keymap_data smdk4x12_keymap_data __initdata = {
@@ -230,10 +237,62 @@ static struct matrix_keymap_data smdk4x12_keymap_data __initdata = {
 
 static struct samsung_keypad_platdata smdk4x12_keypad_data __initdata = {
        .keymap_data    = &smdk4x12_keymap_data,
-       .rows           = 2,
-       .cols           = 5,
+       .rows           = 3,
+       .cols           = 8,
 };
 
+#ifdef CONFIG_DRM_EXYNOS
+static struct exynos_drm_fimd_pdata drm_fimd_pdata = {
+       .panel  = {
+               .timing = {
+                       .left_margin    = 8,
+                       .right_margin   = 8,
+                       .upper_margin   = 6,
+                       .lower_margin   = 6,
+                       .hsync_len      = 6,
+                       .vsync_len      = 4,
+                       .xres           = 480,
+                       .yres           = 800,
+               },
+       },
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .default_win    = 0,
+       .bpp            = 32,
+};
+#else
+static struct s3c_fb_pd_win smdk4x12_fb_win0 = {
+       .xres           = 480,
+       .yres           = 800,
+       .virtual_x      = 480,
+       .virtual_y      = 800 * 2,
+       .max_bpp        = 32,
+       .default_bpp    = 24,
+};
+
+static struct fb_videomode smdk4x12_lcd_timing = {
+       .left_margin    = 8,
+       .right_margin   = 8,
+       .upper_margin   = 6,
+       .lower_margin   = 6,
+       .hsync_len      = 6,
+       .vsync_len      = 4,
+       .xres           = 480,
+       .yres           = 800,
+};
+
+static struct s3c_fb_platdata smdk4x12_lcd_pdata __initdata = {
+       .win[0]         = &smdk4x12_fb_win0,
+       .vtiming        = &smdk4x12_lcd_timing,
+       .vidcon0        = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
+       .vidcon1        = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
+       .setup_gpio     = exynos4_fimd0_gpio_setup_24bpp,
+};
+#endif
+
+/* USB OTG */
+static struct s3c_hsotg_plat smdk4x12_hsotg_pdata;
+
 static struct platform_device *smdk4x12_devices[] __initdata = {
        &s3c_device_hsmmc2,
        &s3c_device_hsmmc3,
@@ -242,22 +301,25 @@ static struct platform_device *smdk4x12_devices[] __initdata = {
        &s3c_device_i2c3,
        &s3c_device_i2c7,
        &s3c_device_rtc,
+       &s3c_device_usb_hsotg,
        &s3c_device_wdt,
        &s5p_device_fimc0,
        &s5p_device_fimc1,
        &s5p_device_fimc2,
        &s5p_device_fimc3,
        &s5p_device_fimc_md,
+       &s5p_device_fimd0,
        &s5p_device_mfc,
        &s5p_device_mfc_l,
        &s5p_device_mfc_r,
+#ifdef CONFIG_DRM_EXYNOS
+       &exynos_device_drm,
+#endif
        &samsung_device_keypad,
 };
 
 static void __init smdk4x12_map_io(void)
 {
-       clk_xusbxti.rate = 24000000;
-
        exynos_init_io(NULL, 0);
        s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(smdk4x12_uartcfgs, ARRAY_SIZE(smdk4x12_uartcfgs));
@@ -293,6 +355,15 @@ static void __init smdk4x12_machine_init(void)
        s3c_sdhci2_set_platdata(&smdk4x12_hsmmc2_pdata);
        s3c_sdhci3_set_platdata(&smdk4x12_hsmmc3_pdata);
 
+       s3c_hsotg_set_platdata(&smdk4x12_hsotg_pdata);
+
+#ifdef CONFIG_DRM_EXYNOS
+       s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata;
+       exynos4_fimd0_gpio_setup_24bpp();
+#else
+       s5p_fimd0_set_platdata(&smdk4x12_lcd_pdata);
+#endif
+
        platform_add_devices(smdk4x12_devices, ARRAY_SIZE(smdk4x12_devices));
 }
 
index 262e9e446a96a62934f58b978c81dcdd98e1c1a3..3cfa688d274a8bda5b5657924509d9d0726f41f6 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/i2c.h>
 #include <linux/input.h>
 #include <linux/pwm_backlight.h>
+#include <linux/platform_data/s3c-hsotg.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/gic.h>
@@ -34,7 +35,6 @@
 #include <plat/keypad.h>
 #include <plat/sdhci.h>
 #include <plat/iic.h>
-#include <plat/pd.h>
 #include <plat/gpio-cfg.h>
 #include <plat/backlight.h>
 #include <plat/mfc.h>
@@ -271,6 +271,15 @@ static void __init smdkv310_ohci_init(void)
        exynos4_ohci_set_platdata(pdata);
 }
 
+/* USB OTG */
+static struct s3c_hsotg_plat smdkv310_hsotg_pdata;
+
+/* Audio device */
+static struct platform_device smdkv310_device_audio = {
+       .name = "smdk-audio",
+       .id = -1,
+};
+
 static struct platform_device *smdkv310_devices[] __initdata = {
        &s3c_device_hsmmc0,
        &s3c_device_hsmmc1,
@@ -279,6 +288,7 @@ static struct platform_device *smdkv310_devices[] __initdata = {
        &s3c_device_i2c1,
        &s5p_device_i2c_hdmiphy,
        &s3c_device_rtc,
+       &s3c_device_usb_hsotg,
        &s3c_device_wdt,
        &s5p_device_ehci,
        &s5p_device_fimc0,
@@ -302,6 +312,7 @@ static struct platform_device *smdkv310_devices[] __initdata = {
        &samsung_asoc_dma,
        &samsung_asoc_idma,
        &s5p_device_fimd0,
+       &smdkv310_device_audio,
        &smdkv310_lcd_lte480wv,
        &smdkv310_smsc911x,
        &exynos4_device_ahci,
@@ -354,7 +365,7 @@ static void s5p_tv_setup(void)
 static void __init smdkv310_map_io(void)
 {
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(24000000);
+       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
 }
 
@@ -390,7 +401,7 @@ static void __init smdkv310_machine_init(void)
 
        smdkv310_ehci_init();
        smdkv310_ohci_init();
-       clk_xusbxti.rate = 24000000;
+       s3c_hsotg_set_platdata(&smdkv310_hsotg_pdata);
 
        platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
 }
@@ -417,5 +428,6 @@ MACHINE_START(SMDKC210, "SMDKC210")
        .init_machine   = smdkv310_machine_init,
        .init_late      = exynos_init_late,
        .timer          = &exynos4_timer,
+       .reserve        = &smdkv310_reserve,
        .restart        = exynos4_restart,
 MACHINE_END
index cd92fa86ba41248da1d8de5e8f122edca102d290..4d1f40d44ed19686f129113e5903a9f137e139e6 100644 (file)
@@ -39,7 +39,6 @@
 #include <plat/fb.h>
 #include <plat/mfc.h>
 #include <plat/sdhci.h>
-#include <plat/pd.h>
 #include <plat/regs-fb-v4.h>
 #include <plat/fimc-core.h>
 #include <plat/s5p-time.h>
@@ -1100,9 +1099,8 @@ static struct platform_device *universal_devices[] __initdata = {
 
 static void __init universal_map_io(void)
 {
-       clk_xusbxti.rate = 24000000;
        exynos_init_io(NULL, 0);
-       s3c24xx_init_clocks(24000000);
+       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
        s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
 }
index 4aacb66f71618da5d865a04a868878ef380aebea..3a48c852be6c1a1e97117b96512d6e4e1ca452c5 100644 (file)
@@ -315,7 +315,7 @@ static struct exynos_pmu_conf exynos5250_pmu_config[] = {
        { PMU_TABLE_END,},
 };
 
-void __iomem *exynos5_list_both_cnt_feed[] = {
+static void __iomem *exynos5_list_both_cnt_feed[] = {
        EXYNOS5_ARM_CORE0_OPTION,
        EXYNOS5_ARM_CORE1_OPTION,
        EXYNOS5_ARM_COMMON_OPTION,
@@ -329,7 +329,7 @@ void __iomem *exynos5_list_both_cnt_feed[] = {
        EXYNOS5_TOP_PWR_SYSMEM_OPTION,
 };
 
-void __iomem *exynos5_list_diable_wfi_wfe[] = {
+static void __iomem *exynos5_list_diable_wfi_wfe[] = {
        EXYNOS5_ARM_CORE1_OPTION,
        EXYNOS5_FSYS_ARM_OPTION,
        EXYNOS5_ISP_ARM_OPTION,
@@ -390,6 +390,8 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
 
 static int __init exynos_pmu_init(void)
 {
+       unsigned int value;
+
        exynos_pmu_config = exynos4210_pmu_config;
 
        if (soc_is_exynos4210()) {
@@ -399,6 +401,18 @@ static int __init exynos_pmu_init(void)
                exynos_pmu_config = exynos4x12_pmu_config;
                pr_info("EXYNOS4x12 PMU Initialize\n");
        } else if (soc_is_exynos5250()) {
+               /*
+                * When SYS_WDTRESET is set, watchdog timer reset request
+                * is ignored by power management unit.
+                */
+               value = __raw_readl(EXYNOS5_AUTO_WDTRESET_DISABLE);
+               value &= ~EXYNOS5_SYS_WDTRESET;
+               __raw_writel(value, EXYNOS5_AUTO_WDTRESET_DISABLE);
+
+               value = __raw_readl(EXYNOS5_MASK_WDTRESET_REQUEST);
+               value &= ~EXYNOS5_SYS_WDTRESET;
+               __raw_writel(value, EXYNOS5_MASK_WDTRESET_REQUEST);
+
                exynos_pmu_config = exynos5250_pmu_config;
                pr_info("EXYNOS5250 PMU Initialize\n");
        } else {
index 833ff40ee0e8943cd5f711c884f2307df4a52f2d..4999829d1c6eb176f028a4f5959a9af90ac3d66e 100644 (file)
@@ -9,21 +9,10 @@
  */
 
 #include <linux/gpio.h>
-#include <linux/platform_device.h>
-
 #include <plat/gpio-cfg.h>
-#include <plat/s3c64xx-spi.h>
 
 #ifdef CONFIG_S3C64XX_DEV_SPI0
-struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = {
-       .fifo_lvl_mask  = 0x1ff,
-       .rx_lvl_offset  = 15,
-       .high_speed     = 1,
-       .clk_from_cmu   = true,
-       .tx_st_done     = 25,
-};
-
-int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi0_cfg_gpio(void)
 {
        s3c_gpio_cfgpin(EXYNOS4_GPB(0), S3C_GPIO_SFN(2));
        s3c_gpio_setpull(EXYNOS4_GPB(0), S3C_GPIO_PULL_UP);
@@ -34,15 +23,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
 #endif
 
 #ifdef CONFIG_S3C64XX_DEV_SPI1
-struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 15,
-       .high_speed     = 1,
-       .clk_from_cmu   = true,
-       .tx_st_done     = 25,
-};
-
-int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi1_cfg_gpio(void)
 {
        s3c_gpio_cfgpin(EXYNOS4_GPB(4), S3C_GPIO_SFN(2));
        s3c_gpio_setpull(EXYNOS4_GPB(4), S3C_GPIO_PULL_UP);
@@ -53,15 +34,7 @@ int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
 #endif
 
 #ifdef CONFIG_S3C64XX_DEV_SPI2
-struct s3c64xx_spi_info s3c64xx_spi2_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 15,
-       .high_speed     = 1,
-       .clk_from_cmu   = true,
-       .tx_st_done     = 25,
-};
-
-int s3c64xx_spi2_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi2_cfg_gpio(void)
 {
        s3c_gpio_cfgpin(EXYNOS4_GPC1(1), S3C_GPIO_SFN(5));
        s3c_gpio_setpull(EXYNOS4_GPC1(1), S3C_GPIO_PULL_UP);
index 1af0a7f44e002af1c82fec2aee0d2b2cdecba595..b81cc569a8ddab4e7a247752297b1b4fac732542 100644 (file)
@@ -31,27 +31,55 @@ static void exynos4210_usb_phy_clkset(struct platform_device *pdev)
        struct clk *xusbxti_clk;
        u32 phyclk;
 
-       /* set clock frequency for PLL */
-       phyclk = readl(EXYNOS4_PHYCLK) & ~CLKSEL_MASK;
-
        xusbxti_clk = clk_get(&pdev->dev, "xusbxti");
        if (xusbxti_clk && !IS_ERR(xusbxti_clk)) {
-               switch (clk_get_rate(xusbxti_clk)) {
-               case 12 * MHZ:
-                       phyclk |= CLKSEL_12M;
-                       break;
-               case 24 * MHZ:
-                       phyclk |= CLKSEL_24M;
-                       break;
-               default:
-               case 48 * MHZ:
-                       /* default reference clock */
-                       break;
+               if (soc_is_exynos4210()) {
+                       /* set clock frequency for PLL */
+                       phyclk = readl(EXYNOS4_PHYCLK) & ~EXYNOS4210_CLKSEL_MASK;
+
+                       switch (clk_get_rate(xusbxti_clk)) {
+                       case 12 * MHZ:
+                               phyclk |= EXYNOS4210_CLKSEL_12M;
+                               break;
+                       case 48 * MHZ:
+                               phyclk |= EXYNOS4210_CLKSEL_48M;
+                               break;
+                       default:
+                       case 24 * MHZ:
+                               phyclk |= EXYNOS4210_CLKSEL_24M;
+                               break;
+                       }
+                       writel(phyclk, EXYNOS4_PHYCLK);
+               } else if (soc_is_exynos4212() || soc_is_exynos4412()) {
+                       /* set clock frequency for PLL */
+                       phyclk = readl(EXYNOS4_PHYCLK) & ~EXYNOS4X12_CLKSEL_MASK;
+
+                       switch (clk_get_rate(xusbxti_clk)) {
+                       case 9600 * KHZ:
+                               phyclk |= EXYNOS4X12_CLKSEL_9600K;
+                               break;
+                       case 10 * MHZ:
+                               phyclk |= EXYNOS4X12_CLKSEL_10M;
+                               break;
+                       case 12 * MHZ:
+                               phyclk |= EXYNOS4X12_CLKSEL_12M;
+                               break;
+                       case 19200 * KHZ:
+                               phyclk |= EXYNOS4X12_CLKSEL_19200K;
+                               break;
+                       case 20 * MHZ:
+                               phyclk |= EXYNOS4X12_CLKSEL_20M;
+                               break;
+                       default:
+                       case 24 * MHZ:
+                               /* default reference clock */
+                               phyclk |= EXYNOS4X12_CLKSEL_24M;
+                               break;
+                       }
+                       writel(phyclk, EXYNOS4_PHYCLK);
                }
                clk_put(xusbxti_clk);
        }
-
-       writel(phyclk, EXYNOS4_PHYCLK);
 }
 
 static int exynos4210_usb_phy0_init(struct platform_device *pdev)
index eff4db5de0ddb8abbfde826cc14c16b9432c5373..afd542ad6f97d97cca788c4604a10e69d4625540 100644 (file)
@@ -52,6 +52,7 @@ config SOC_IMX25
        select ARCH_MX25
        select COMMON_CLK
        select CPU_ARM926T
+       select HAVE_CAN_FLEXCAN if CAN
        select ARCH_MXC_IOMUX_V3
        select MXC_AVIC
 
@@ -73,12 +74,13 @@ config SOC_IMX31
 
 config SOC_IMX35
        bool
-       select CPU_V6
+       select CPU_V6K
        select ARCH_MXC_IOMUX_V3
        select COMMON_CLK
        select HAVE_EPIT
        select MXC_AVIC
        select SMP_ON_UP if SMP
+       select HAVE_CAN_FLEXCAN if CAN
 
 config SOC_IMX5
        select CPU_V7
@@ -105,6 +107,7 @@ config      SOC_IMX53
        select SOC_IMX5
        select ARCH_MX5
        select ARCH_MX53
+       select HAVE_CAN_FLEXCAN if CAN
 
 if ARCH_IMX_V4_V5
 
@@ -158,7 +161,6 @@ config MACH_MX25_3DS
        select IMX_HAVE_PLATFORM_IMX2_WDT
        select IMX_HAVE_PLATFORM_IMXDI_RTC
        select IMX_HAVE_PLATFORM_IMX_I2C
-       select IMX_HAVE_PLATFORM_IMX_SSI
        select IMX_HAVE_PLATFORM_IMX_FB
        select IMX_HAVE_PLATFORM_IMX_KEYPAD
        select IMX_HAVE_PLATFORM_IMX_UART
@@ -380,7 +382,6 @@ config MACH_IMX27IPCAM
 config MACH_IMX27_DT
        bool "Support i.MX27 platforms from device tree"
        select SOC_IMX27
-       select USE_OF
        help
          Include support for Freescale i.MX27 based platforms
          using the device tree for discovery
@@ -557,6 +558,14 @@ config MACH_BUG
          Include support for BUGBase 1.3 platform. This includes specific
          configurations for the board and its peripherals.
 
+config MACH_IMX31_DT
+       bool "Support i.MX31 platforms from device tree"
+       select SOC_IMX31
+       select USE_OF
+       help
+         Include support for Freescale i.MX31 based platforms
+         using the device tree for discovery.
+
 comment "MX35 platforms:"
 
 config MACH_PCM043
@@ -589,6 +598,7 @@ config MACH_MX35_3DS
        select IMX_HAVE_PLATFORM_IPU_CORE
        select IMX_HAVE_PLATFORM_MXC_EHCI
        select IMX_HAVE_PLATFORM_MXC_NAND
+       select IMX_HAVE_PLATFORM_MXC_RTC
        select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
        help
          Include support for MX35PDK platform. This includes specific
@@ -663,7 +673,6 @@ comment "i.MX51 machines:"
 config MACH_IMX51_DT
        bool "Support i.MX51 platforms from device tree"
        select SOC_IMX51
-       select USE_OF
        select MACH_MX51_BABBAGE
        help
          Include support for Freescale i.MX51 based platforms
@@ -759,7 +768,6 @@ comment "i.MX53 machines:"
 config MACH_IMX53_DT
        bool "Support i.MX53 platforms from device tree"
        select SOC_IMX53
-       select USE_OF
        select MACH_MX53_ARD
        select MACH_MX53_EVK
        select MACH_MX53_LOCO
@@ -826,13 +834,14 @@ config SOC_IMX6Q
        select COMMON_CLK
        select CPU_V7
        select HAVE_ARM_SCU
+       select HAVE_CAN_FLEXCAN if CAN
        select HAVE_IMX_GPC
        select HAVE_IMX_MMDC
        select HAVE_IMX_SRC
        select HAVE_SMP
+       select MFD_ANATOP
        select PINCTRL
        select PINCTRL_IMX6Q
-       select USE_OF
 
        help
          This enables support for Freescale i.MX6 Quad processor.
index ff29421414f24262e5e4b66c74270f58fa401798..07f7c226e4cfe6eec6181e5e506655223c2f1e1a 100644 (file)
@@ -57,6 +57,7 @@ obj-$(CONFIG_MACH_QONG) += mach-qong.o
 obj-$(CONFIG_MACH_ARMADILLO5X0) += mach-armadillo5x0.o
 obj-$(CONFIG_MACH_KZM_ARM11_01) += mach-kzm_arm11_01.o
 obj-$(CONFIG_MACH_BUG) += mach-bug.o
+obj-$(CONFIG_MACH_IMX31_DT) += imx31-dt.o
 
 # i.MX35 based machines
 obj-$(CONFIG_MACH_PCM043) += mach-pcm043.o
index 295cbd7c08dcd9df383b8fd7eb5a1843083e895a..7aa6313fb1671bbf975d6cf6407aad3ecee66498 100644 (file)
@@ -256,7 +256,7 @@ int __init mx27_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[gpio_ipg_gate], "gpio", NULL);
        clk_register_clkdev(clk[brom_ahb_gate], "brom", NULL);
        clk_register_clkdev(clk[ata_ahb_gate], "ata", NULL);
-       clk_register_clkdev(clk[rtc_ipg_gate], "rtc", NULL);
+       clk_register_clkdev(clk[rtc_ipg_gate], NULL, "mxc_rtc");
        clk_register_clkdev(clk[scc_ipg_gate], "scc", NULL);
        clk_register_clkdev(clk[cpu_div], "cpu", NULL);
        clk_register_clkdev(clk[emi_ahb_gate], "emi_ahb" , NULL);
@@ -267,6 +267,8 @@ int __init mx27_clocks_init(unsigned long fref)
 
        clk_prepare_enable(clk[emi_ahb_gate]);
 
+       imx_print_silicon_rev("i.MX27", mx27_revision());
+
        return 0;
 }
 
index c9a06d800f8ef7a0a7d96e015cd87754afd09a25..8e19e70f90f97f121b6379945ebeadc2ae2284ab 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/clkdev.h>
 #include <linux/io.h>
 #include <linux/err.h>
+#include <linux/of.h>
 
 #include <mach/hardware.h>
 #include <mach/mx31.h>
@@ -123,7 +124,7 @@ int __init mx31_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[cspi3_gate], NULL, "imx31-cspi.2");
        clk_register_clkdev(clk[pwm_gate], "pwm", NULL);
        clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
-       clk_register_clkdev(clk[rtc_gate], "rtc", NULL);
+       clk_register_clkdev(clk[rtc_gate], NULL, "mxc_rtc");
        clk_register_clkdev(clk[epit1_gate], "epit", NULL);
        clk_register_clkdev(clk[epit2_gate], "epit", NULL);
        clk_register_clkdev(clk[nfc], NULL, "mxc_nand.0");
@@ -165,7 +166,7 @@ int __init mx31_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[firi_gate], "firi", NULL);
        clk_register_clkdev(clk[ata_gate], NULL, "pata_imx");
        clk_register_clkdev(clk[rtic_gate], "rtic", NULL);
-       clk_register_clkdev(clk[rng_gate], "rng", NULL);
+       clk_register_clkdev(clk[rng_gate], NULL, "mxc_rnga");
        clk_register_clkdev(clk[sdma_gate], NULL, "imx31-sdma");
        clk_register_clkdev(clk[iim_gate], "iim", NULL);
 
@@ -179,3 +180,21 @@ int __init mx31_clocks_init(unsigned long fref)
 
        return 0;
 }
+
+#ifdef CONFIG_OF
+int __init mx31_clocks_init_dt(void)
+{
+       struct device_node *np;
+       u32 fref = 26000000; /* default */
+
+       for_each_compatible_node(np, NULL, "fixed-clock") {
+               if (!of_device_is_compatible(np, "fsl,imx-osc26m"))
+                       continue;
+
+               if (!of_property_read_u32(np, "clock-frequency", &fref))
+                       break;
+       }
+
+       return mx31_clocks_init(fref);
+}
+#endif
index a2200c77bf70dcdc09c44d642fe09656f36f0fcb..f6086693ebd2aa665e29fc7a5d5623caeb0d3d53 100644 (file)
@@ -58,7 +58,7 @@ enum imx5_clks {
        tve_s, uart1_ipg_gate, uart1_per_gate, uart2_ipg_gate,
        uart2_per_gate, uart3_ipg_gate, uart3_per_gate, i2c1_gate, i2c2_gate,
        gpt_ipg_gate, pwm1_ipg_gate, pwm1_hf_gate, pwm2_ipg_gate, pwm2_hf_gate,
-       gpt_gate, fec_gate, usboh3_per_gate, esdhc1_ipg_gate, esdhc2_ipg_gate,
+       gpt_hf_gate, fec_gate, usboh3_per_gate, esdhc1_ipg_gate, esdhc2_ipg_gate,
        esdhc3_ipg_gate, esdhc4_ipg_gate, ssi1_ipg_gate, ssi2_ipg_gate,
        ssi3_ipg_gate, ecspi1_ipg_gate, ecspi1_per_gate, ecspi2_ipg_gate,
        ecspi2_per_gate, cspi_ipg_gate, sdma_gate, emi_slow_gate, ipu_s,
@@ -81,6 +81,7 @@ enum imx5_clks {
        ssi1_root_podf, ssi2_root_pred, ssi2_root_podf, ssi_ext1_pred,
        ssi_ext1_podf, ssi_ext2_pred, ssi_ext2_podf, ssi1_root_gate,
        ssi2_root_gate, ssi3_root_gate, ssi_ext1_gate, ssi_ext2_gate,
+       epit1_ipg_gate, epit1_hf_gate, epit2_ipg_gate, epit2_hf_gate,
        clk_max
 };
 
@@ -167,12 +168,12 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
        clk[uart3_per_gate] = imx_clk_gate2("uart3_per_gate", "uart_root", MXC_CCM_CCGR1, 16);
        clk[i2c1_gate] = imx_clk_gate2("i2c1_gate", "per_root", MXC_CCM_CCGR1, 18);
        clk[i2c2_gate] = imx_clk_gate2("i2c2_gate", "per_root", MXC_CCM_CCGR1, 20);
-       clk[gpt_ipg_gate] = imx_clk_gate2("gpt_ipg_gate", "ipg", MXC_CCM_CCGR2, 20);
        clk[pwm1_ipg_gate] = imx_clk_gate2("pwm1_ipg_gate", "ipg", MXC_CCM_CCGR2, 10);
-       clk[pwm1_hf_gate] = imx_clk_gate2("pwm1_hf_gate", "ipg", MXC_CCM_CCGR2, 12);
+       clk[pwm1_hf_gate] = imx_clk_gate2("pwm1_hf_gate", "per_root", MXC_CCM_CCGR2, 12);
        clk[pwm2_ipg_gate] = imx_clk_gate2("pwm2_ipg_gate", "ipg", MXC_CCM_CCGR2, 14);
-       clk[pwm2_hf_gate] = imx_clk_gate2("pwm2_hf_gate", "ipg", MXC_CCM_CCGR2, 16);
-       clk[gpt_gate] = imx_clk_gate2("gpt_gate", "per_root", MXC_CCM_CCGR2, 18);
+       clk[pwm2_hf_gate] = imx_clk_gate2("pwm2_hf_gate", "per_root", MXC_CCM_CCGR2, 16);
+       clk[gpt_ipg_gate] = imx_clk_gate2("gpt_ipg_gate", "ipg", MXC_CCM_CCGR2, 18);
+       clk[gpt_hf_gate] = imx_clk_gate2("gpt_hf_gate", "per_root", MXC_CCM_CCGR2, 20);
        clk[fec_gate] = imx_clk_gate2("fec_gate", "ipg", MXC_CCM_CCGR2, 24);
        clk[usboh3_gate] = imx_clk_gate2("usboh3_gate", "ipg", MXC_CCM_CCGR2, 26);
        clk[usboh3_per_gate] = imx_clk_gate2("usboh3_per_gate", "usboh3_podf", MXC_CCM_CCGR2, 28);
@@ -226,13 +227,17 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
        clk[ssi3_root_gate] = imx_clk_gate2("ssi3_root_gate", "ssi3_root_sel", MXC_CCM_CCGR3, 26);
        clk[ssi_ext1_gate] = imx_clk_gate2("ssi_ext1_gate", "ssi_ext1_com_sel", MXC_CCM_CCGR3, 28);
        clk[ssi_ext2_gate] = imx_clk_gate2("ssi_ext2_gate", "ssi_ext2_com_sel", MXC_CCM_CCGR3, 30);
+       clk[epit1_ipg_gate] = imx_clk_gate2("epit1_ipg_gate", "ipg", MXC_CCM_CCGR2, 2);
+       clk[epit1_hf_gate] = imx_clk_gate2("epit1_hf_gate", "per_root", MXC_CCM_CCGR2, 4);
+       clk[epit2_ipg_gate] = imx_clk_gate2("epit2_ipg_gate", "ipg", MXC_CCM_CCGR2, 6);
+       clk[epit2_hf_gate] = imx_clk_gate2("epit2_hf_gate", "per_root", MXC_CCM_CCGR2, 8);
 
        for (i = 0; i < ARRAY_SIZE(clk); i++)
                if (IS_ERR(clk[i]))
                        pr_err("i.MX5 clk %d: register failed with %ld\n",
                                i, PTR_ERR(clk[i]));
        
-       clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0");
+       clk_register_clkdev(clk[gpt_hf_gate], "per", "imx-gpt.0");
        clk_register_clkdev(clk[gpt_ipg_gate], "ipg", "imx-gpt.0");
        clk_register_clkdev(clk[uart1_per_gate], "per", "imx21-uart.0");
        clk_register_clkdev(clk[uart1_ipg_gate], "ipg", "imx21-uart.0");
@@ -248,7 +253,7 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
        clk_register_clkdev(clk[ecspi1_ipg_gate], "ipg", "imx51-ecspi.0");
        clk_register_clkdev(clk[ecspi2_per_gate], "per", "imx51-ecspi.1");
        clk_register_clkdev(clk[ecspi2_ipg_gate], "ipg", "imx51-ecspi.1");
-       clk_register_clkdev(clk[cspi_ipg_gate], NULL, "imx51-cspi.0");
+       clk_register_clkdev(clk[cspi_ipg_gate], NULL, "imx35-cspi.2");
        clk_register_clkdev(clk[pwm1_ipg_gate], "pwm", "mxc_pwm.0");
        clk_register_clkdev(clk[pwm2_ipg_gate], "pwm", "mxc_pwm.1");
        clk_register_clkdev(clk[i2c1_gate], NULL, "imx-i2c.0");
@@ -279,6 +284,11 @@ static void __init mx5_clocks_common_init(unsigned long rate_ckil,
        clk_register_clkdev(clk[dummy], NULL, "imx-keypad");
        clk_register_clkdev(clk[tve_gate], NULL, "imx-tve.0");
        clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx-tve.0");
+       clk_register_clkdev(clk[gpc_dvfs], "gpc_dvfs", NULL);
+       clk_register_clkdev(clk[epit1_ipg_gate], "ipg", "imx-epit.0");
+       clk_register_clkdev(clk[epit1_hf_gate], "per", "imx-epit.0");
+       clk_register_clkdev(clk[epit2_ipg_gate], "ipg", "imx-epit.1");
+       clk_register_clkdev(clk[epit2_hf_gate], "per", "imx-epit.1");
 
        /* Set SDHC parents to be PLL2 */
        clk_set_parent(clk[esdhc_a_sel], clk[pll2_sw]);
@@ -336,7 +346,6 @@ int __init mx51_clocks_init(unsigned long rate_ckil, unsigned long rate_osc,
        clk_register_clkdev(clk[mx51_mipi], "mipi_hsp", NULL);
        clk_register_clkdev(clk[vpu_gate], NULL, "imx51-vpu.0");
        clk_register_clkdev(clk[fec_gate], NULL, "imx27-fec.0");
-       clk_register_clkdev(clk[gpc_dvfs], "gpc_dvfs", NULL);
        clk_register_clkdev(clk[ipu_gate], "bus", "imx51-ipu");
        clk_register_clkdev(clk[ipu_di0_gate], "di0", "imx51-ipu");
        clk_register_clkdev(clk[ipu_di1_gate], "di1", "imx51-ipu");
index e1a17ac7b3b48419a8ff1f9dadfa5de03f5fd852..ea89520b6e223fd3ab4db3227574c7299605e265 100644 (file)
@@ -147,12 +147,12 @@ enum mx6q_clks {
        esai, gpt_ipg, gpt_ipg_per, gpu2d_core, gpu3d_core, hdmi_iahb,
        hdmi_isfr, i2c1, i2c2, i2c3, iim, enfc, ipu1, ipu1_di0, ipu1_di1, ipu2,
        ipu2_di0, ldb_di0, ldb_di1, ipu2_di1, hsi_tx, mlb, mmdc_ch0_axi,
-       mmdc_ch1_axi, ocram, openvg_axi, pcie_axi, pwm1, pwm2, pwm3, pwm4,
+       mmdc_ch1_axi, ocram, openvg_axi, pcie_axi, pwm1, pwm2, pwm3, pwm4, per1_bch,
        gpmi_bch_apb, gpmi_bch, gpmi_io, gpmi_apb, sata, sdma, spba, ssi1,
        ssi2, ssi3, uart_ipg, uart_serial, usboh3, usdhc1, usdhc2, usdhc3,
        usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg,
        pll4_audio, pll5_video, pll6_mlb, pll7_usb_host, pll8_enet, ssi1_ipg,
-       ssi2_ipg, ssi3_ipg, rom,
+       ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2,
        clk_max
 };
 
@@ -198,6 +198,9 @@ int __init mx6q_clocks_init(void)
        clk[pll7_usb_host] = imx_clk_pllv3(IMX_PLLV3_USB,       "pll7_usb_host","osc", base + 0x20, 0x2000,   0x3);
        clk[pll8_enet]     = imx_clk_pllv3(IMX_PLLV3_ENET,      "pll8_enet",    "osc", base + 0xe0, 0x182000, 0x3);
 
+       clk[usbphy1] = imx_clk_gate("usbphy1", "pll3_usb_otg", base + 0x10, 6);
+       clk[usbphy2] = imx_clk_gate("usbphy2", "pll7_usb_host", base + 0x20, 6);
+
        /*                                name              parent_name        reg       idx */
        clk[pll2_pfd0_352m] = imx_clk_pfd("pll2_pfd0_352m", "pll2_bus",     base + 0x100, 0);
        clk[pll2_pfd1_594m] = imx_clk_pfd("pll2_pfd1_594m", "pll2_bus",     base + 0x100, 1);
@@ -318,7 +321,7 @@ int __init mx6q_clocks_init(void)
        clk[ahb]               = imx_clk_busy_divider("ahb",               "periph",      base + 0x14, 10,  3,   base + 0x48, 1);
 
        /*                                name             parent_name          reg         shift */
-       clk[apbh_dma]     = imx_clk_gate2("apbh_dma",      "ahb",               base + 0x68, 4);
+       clk[apbh_dma]     = imx_clk_gate2("apbh_dma",      "usdhc3",            base + 0x68, 4);
        clk[asrc]         = imx_clk_gate2("asrc",          "asrc_podf",         base + 0x68, 6);
        clk[can1_ipg]     = imx_clk_gate2("can1_ipg",      "ipg",               base + 0x68, 14);
        clk[can1_serial]  = imx_clk_gate2("can1_serial",   "can_root",          base + 0x68, 16);
@@ -357,6 +360,7 @@ int __init mx6q_clocks_init(void)
        clk[ocram]        = imx_clk_gate2("ocram",         "ahb",               base + 0x74, 28);
        clk[openvg_axi]   = imx_clk_gate2("openvg_axi",    "axi",               base + 0x74, 30);
        clk[pcie_axi]     = imx_clk_gate2("pcie_axi",      "pcie_axi_sel",      base + 0x78, 0);
+       clk[per1_bch]     = imx_clk_gate2("per1_bch",      "usdhc3",            base + 0x78, 12);
        clk[pwm1]         = imx_clk_gate2("pwm1",          "ipg_per",           base + 0x78, 16);
        clk[pwm2]         = imx_clk_gate2("pwm2",          "ipg_per",           base + 0x78, 18);
        clk[pwm3]         = imx_clk_gate2("pwm3",          "ipg_per",           base + 0x78, 20);
@@ -388,12 +392,21 @@ int __init mx6q_clocks_init(void)
                        pr_err("i.MX6q clk %d: register failed with %ld\n",
                                i, PTR_ERR(clk[i]));
 
-       clk_register_clkdev(clk[mmdc_ch0_axi], NULL, "mmdc_ch0_axi");
-       clk_register_clkdev(clk[mmdc_ch1_axi], NULL, "mmdc_ch1_axi");
        clk_register_clkdev(clk[gpt_ipg], "ipg", "imx-gpt.0");
        clk_register_clkdev(clk[gpt_ipg_per], "per", "imx-gpt.0");
        clk_register_clkdev(clk[twd], NULL, "smp_twd");
-       clk_register_clkdev(clk[usboh3], NULL, "usboh3");
+       clk_register_clkdev(clk[apbh_dma], NULL, "110000.dma-apbh");
+       clk_register_clkdev(clk[per1_bch], "per1_bch", "112000.gpmi-nand");
+       clk_register_clkdev(clk[gpmi_bch_apb], "gpmi_bch_apb", "112000.gpmi-nand");
+       clk_register_clkdev(clk[gpmi_bch], "gpmi_bch", "112000.gpmi-nand");
+       clk_register_clkdev(clk[gpmi_apb], "gpmi_apb", "112000.gpmi-nand");
+       clk_register_clkdev(clk[gpmi_io], "gpmi_io", "112000.gpmi-nand");
+       clk_register_clkdev(clk[usboh3], NULL, "2184000.usb");
+       clk_register_clkdev(clk[usboh3], NULL, "2184200.usb");
+       clk_register_clkdev(clk[usboh3], NULL, "2184400.usb");
+       clk_register_clkdev(clk[usboh3], NULL, "2184600.usb");
+       clk_register_clkdev(clk[usbphy1], NULL, "20c9000.usbphy");
+       clk_register_clkdev(clk[usbphy2], NULL, "20ca000.usbphy");
        clk_register_clkdev(clk[uart_serial], "per", "2020000.serial");
        clk_register_clkdev(clk[uart_ipg], "ipg", "2020000.serial");
        clk_register_clkdev(clk[uart_serial], "per", "21e8000.serial");
index 2628e0c474dc2538f6a5b8c486a80fbabda738c7..93ece55f75dfbf3014039968a6a740d7cecd1900 100644 (file)
@@ -14,7 +14,7 @@ extern const struct imx_imx21_hcd_data imx21_imx21_hcd_data;
        imx_add_imx21_hcd(&imx21_imx21_hcd_data, pdata)
 
 extern const struct imx_imx2_wdt_data imx21_imx2_wdt_data;
-#define imx21_add_imx2_wdt(pdata)      \
+#define imx21_add_imx2_wdt()   \
        imx_add_imx2_wdt(&imx21_imx2_wdt_data)
 
 extern const struct imx_imx_fb_data imx21_imx_fb_data;
@@ -50,7 +50,7 @@ extern const struct imx_mxc_nand_data imx21_mxc_nand_data;
        imx_add_mxc_nand(&imx21_mxc_nand_data, pdata)
 
 extern const struct imx_mxc_w1_data imx21_mxc_w1_data;
-#define imx21_add_mxc_w1(pdata)        \
+#define imx21_add_mxc_w1()     \
        imx_add_mxc_w1(&imx21_mxc_w1_data)
 
 extern const struct imx_spi_imx_data imx21_cspi_data[];
index efa0761c508d7707ddba2f33b6d52f7cffb46cd9..f8e03dd1f116f16a8f175403c6e6cd62756caa2d 100644 (file)
@@ -24,11 +24,11 @@ extern const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data;
        imx_add_fsl_usb2_udc(&imx25_fsl_usb2_udc_data, pdata)
 
 extern struct imx_imxdi_rtc_data imx25_imxdi_rtc_data;
-#define imx25_add_imxdi_rtc(pdata)     \
+#define imx25_add_imxdi_rtc()  \
        imx_add_imxdi_rtc(&imx25_imxdi_rtc_data)
 
 extern const struct imx_imx2_wdt_data imx25_imx2_wdt_data;
-#define imx25_add_imx2_wdt(pdata)      \
+#define imx25_add_imx2_wdt()   \
        imx_add_imx2_wdt(&imx25_imx2_wdt_data)
 
 extern const struct imx_imx_fb_data imx25_imx_fb_data;
index 28537a5d904801a1c38a8d5bac171bbd2104e9cf..436c5720fe6a40255a2c3bc5ab05378c23855e02 100644 (file)
@@ -18,7 +18,7 @@ extern const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data;
        imx_add_fsl_usb2_udc(&imx27_fsl_usb2_udc_data, pdata)
 
 extern const struct imx_imx2_wdt_data imx27_imx2_wdt_data;
-#define imx27_add_imx2_wdt(pdata)      \
+#define imx27_add_imx2_wdt()   \
        imx_add_imx2_wdt(&imx27_imx2_wdt_data)
 
 extern const struct imx_imx_fb_data imx27_imx_fb_data;
@@ -50,7 +50,7 @@ extern const struct imx_imx_uart_1irq_data imx27_imx_uart_data[];
 extern const struct imx_mx2_camera_data imx27_mx2_camera_data;
 #define imx27_add_mx2_camera(pdata)    \
        imx_add_mx2_camera(&imx27_mx2_camera_data, pdata)
-#define imx27_add_mx2_emmaprp(pdata)   \
+#define imx27_add_mx2_emmaprp()        \
        imx_add_mx2_emmaprp(&imx27_mx2_camera_data)
 
 extern const struct imx_mxc_ehci_data imx27_mxc_ehci_otg_data;
@@ -69,7 +69,7 @@ extern const struct imx_mxc_nand_data imx27_mxc_nand_data;
        imx_add_mxc_nand(&imx27_mxc_nand_data, pdata)
 
 extern const struct imx_mxc_w1_data imx27_mxc_w1_data;
-#define imx27_add_mxc_w1(pdata)        \
+#define imx27_add_mxc_w1()     \
        imx_add_mxc_w1(&imx27_mxc_w1_data)
 
 extern const struct imx_spi_imx_data imx27_cspi_data[];
index 488e241a6db638b90f2da3ca38108cb0eea42a8b..8b2ceb45bb8344223dae53b974e345237c707479 100644 (file)
@@ -14,7 +14,7 @@ extern const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data;
        imx_add_fsl_usb2_udc(&imx31_fsl_usb2_udc_data, pdata)
 
 extern const struct imx_imx2_wdt_data imx31_imx2_wdt_data;
-#define imx31_add_imx2_wdt(pdata)       \
+#define imx31_add_imx2_wdt()       \
        imx_add_imx2_wdt(&imx31_imx2_wdt_data)
 
 extern const struct imx_imx_i2c_data imx31_imx_i2c_data[];
@@ -42,8 +42,8 @@ extern const struct imx_imx_uart_1irq_data imx31_imx_uart_data[];
 #define imx31_add_imx_uart4(pdata)     imx31_add_imx_uart(4, pdata)
 
 extern const struct imx_ipu_core_data imx31_ipu_core_data;
-#define imx31_add_ipu_core(pdata)      \
-       imx_add_ipu_core(&imx31_ipu_core_data, pdata)
+#define imx31_add_ipu_core()           \
+       imx_add_ipu_core(&imx31_ipu_core_data)
 #define imx31_alloc_mx3_camera(pdata)  \
        imx_alloc_mx3_camera(&imx31_ipu_core_data, pdata)
 #define imx31_add_mx3_sdc_fb(pdata)    \
@@ -65,11 +65,11 @@ extern const struct imx_mxc_nand_data imx31_mxc_nand_data;
        imx_add_mxc_nand(&imx31_mxc_nand_data, pdata)
 
 extern const struct imx_mxc_rtc_data imx31_mxc_rtc_data;
-#define imx31_add_mxc_rtc(pdata)       \
+#define imx31_add_mxc_rtc()    \
        imx_add_mxc_rtc(&imx31_mxc_rtc_data)
 
 extern const struct imx_mxc_w1_data imx31_mxc_w1_data;
-#define imx31_add_mxc_w1(pdata)        \
+#define imx31_add_mxc_w1()     \
        imx_add_mxc_w1(&imx31_mxc_w1_data)
 
 extern const struct imx_spi_imx_data imx31_cspi_data[];
index 7b99ef0bb50111f24fb97a0aca09a3a3517cabc3..c3e9f206ac2bdfdff093b2a082dbddd168aa4d05 100644 (file)
@@ -24,7 +24,7 @@ extern const struct imx_flexcan_data imx35_flexcan_data[];
 #define imx35_add_flexcan1(pdata)      imx35_add_flexcan(1, pdata)
 
 extern const struct imx_imx2_wdt_data imx35_imx2_wdt_data;
-#define imx35_add_imx2_wdt(pdata)       \
+#define imx35_add_imx2_wdt()       \
        imx_add_imx2_wdt(&imx35_imx2_wdt_data)
 
 extern const struct imx_imx_i2c_data imx35_imx_i2c_data[];
@@ -50,8 +50,8 @@ extern const struct imx_imx_uart_1irq_data imx35_imx_uart_data[];
 #define imx35_add_imx_uart2(pdata)     imx35_add_imx_uart(2, pdata)
 
 extern const struct imx_ipu_core_data imx35_ipu_core_data;
-#define imx35_add_ipu_core(pdata)      \
-       imx_add_ipu_core(&imx35_ipu_core_data, pdata)
+#define imx35_add_ipu_core()           \
+       imx_add_ipu_core(&imx35_ipu_core_data)
 #define imx35_alloc_mx3_camera(pdata)  \
        imx_alloc_mx3_camera(&imx35_ipu_core_data, pdata)
 #define imx35_add_mx3_sdc_fb(pdata)    \
@@ -68,8 +68,12 @@ extern const struct imx_mxc_nand_data imx35_mxc_nand_data;
 #define imx35_add_mxc_nand(pdata)      \
        imx_add_mxc_nand(&imx35_mxc_nand_data, pdata)
 
+extern const struct imx_mxc_rtc_data imx35_mxc_rtc_data;
+#define imx35_add_mxc_rtc()    \
+       imx_add_mxc_rtc(&imx35_mxc_rtc_data)
+
 extern const struct imx_mxc_w1_data imx35_mxc_w1_data;
-#define imx35_add_mxc_w1(pdata)        \
+#define imx35_add_mxc_w1()     \
        imx_add_mxc_w1(&imx35_mxc_w1_data)
 
 extern const struct imx_sdhci_esdhc_imx_data imx35_sdhci_esdhc_imx_data[];
index af488bc0e2256df020b37c770f534bcc0cde01e1..9f1718725195414e0798a40d49c932838f7b4235 100644 (file)
@@ -55,7 +55,7 @@ extern const struct imx_spi_imx_data imx51_ecspi_data[];
        imx_add_spi_imx(&imx51_ecspi_data[id], pdata)
 
 extern const struct imx_imx2_wdt_data imx51_imx2_wdt_data[];
-#define imx51_add_imx2_wdt(id, pdata)  \
+#define imx51_add_imx2_wdt(id) \
        imx_add_imx2_wdt(&imx51_imx2_wdt_data[id])
 
 extern const struct imx_mxc_pwm_data imx51_mxc_pwm_data[];
index 6e1e5d1f8c3a9886cd40f47c29e768431d5b416d..77e0db96c4483c4592099fb7639678a180f84190 100644 (file)
@@ -30,7 +30,7 @@ extern const struct imx_spi_imx_data imx53_ecspi_data[];
        imx_add_spi_imx(&imx53_ecspi_data[id], pdata)
 
 extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[];
-#define imx53_add_imx2_wdt(id, pdata)  \
+#define imx53_add_imx2_wdt(id) \
        imx_add_imx2_wdt(&imx53_imx2_wdt_data[id])
 
 extern const struct imx_imx_ssi_data imx53_imx_ssi_data[];
index 865daf0b09e97e0dfa50721096a30dbe1ec0358d..05bb41d99728b3911ea6cfb8203a08cece9bdba7 100644 (file)
 #define MX25_OTG_SIC_SHIFT     29
 #define MX25_OTG_SIC_MASK      (0x3 << MX25_OTG_SIC_SHIFT)
 #define MX25_OTG_PM_BIT                (1 << 24)
+#define MX25_OTG_PP_BIT                (1 << 11)
+#define MX25_OTG_OCPOL_BIT     (1 << 3)
 
 #define MX25_H1_SIC_SHIFT      21
 #define MX25_H1_SIC_MASK       (0x3 << MX25_H1_SIC_SHIFT)
+#define MX25_H1_PP_BIT         (1 << 18)
 #define MX25_H1_PM_BIT         (1 << 8)
 #define MX25_H1_IPPUE_UP_BIT   (1 << 7)
 #define MX25_H1_IPPUE_DOWN_BIT (1 << 6)
 #define MX25_H1_TLL_BIT                (1 << 5)
 #define MX25_H1_USBTE_BIT      (1 << 4)
+#define MX25_H1_OCPOL_BIT      (1 << 2)
 
 int mx25_initialize_usb_hw(int port, unsigned int flags)
 {
@@ -41,21 +45,35 @@ int mx25_initialize_usb_hw(int port, unsigned int flags)
 
        switch (port) {
        case 0: /* OTG port */
-               v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT);
+               v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT | MX25_OTG_PP_BIT |
+                       MX25_OTG_OCPOL_BIT);
                v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
 
                if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
                        v |= MX25_OTG_PM_BIT;
 
+               if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
+                       v |= MX25_OTG_PP_BIT;
+
+               if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW))
+                       v |= MX25_OTG_OCPOL_BIT;
+
                break;
        case 1: /* H1 port */
-               v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_TLL_BIT |
-                       MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT | MX25_H1_IPPUE_UP_BIT);
+               v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_PP_BIT |
+                       MX25_H1_OCPOL_BIT | MX25_H1_TLL_BIT | MX25_H1_USBTE_BIT |
+                       MX25_H1_IPPUE_DOWN_BIT | MX25_H1_IPPUE_UP_BIT);
                v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
 
                if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
                        v |= MX25_H1_PM_BIT;
 
+               if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
+                       v |= MX25_H1_PP_BIT;
+
+               if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW))
+                       v |= MX25_H1_OCPOL_BIT;
+
                if (!(flags & MXC_EHCI_TTL_ENABLED))
                        v |= MX25_H1_TLL_BIT;
 
index 001ec3971f5da93de19c7e2db9153a32f4347348..73574c30cf50ca97c337eaa4ec9bd58d7a2c9dab 100644 (file)
 #define MX35_OTG_SIC_SHIFT     29
 #define MX35_OTG_SIC_MASK      (0x3 << MX35_OTG_SIC_SHIFT)
 #define MX35_OTG_PM_BIT                (1 << 24)
+#define MX35_OTG_PP_BIT                (1 << 11)
+#define MX35_OTG_OCPOL_BIT     (1 << 3)
 
 #define MX35_H1_SIC_SHIFT      21
 #define MX35_H1_SIC_MASK       (0x3 << MX35_H1_SIC_SHIFT)
+#define MX35_H1_PP_BIT         (1 << 18)
 #define MX35_H1_PM_BIT         (1 << 8)
 #define MX35_H1_IPPUE_UP_BIT   (1 << 7)
 #define MX35_H1_IPPUE_DOWN_BIT (1 << 6)
 #define MX35_H1_TLL_BIT                (1 << 5)
 #define MX35_H1_USBTE_BIT      (1 << 4)
+#define MX35_H1_OCPOL_BIT      (1 << 2)
 
 int mx35_initialize_usb_hw(int port, unsigned int flags)
 {
@@ -41,21 +45,35 @@ int mx35_initialize_usb_hw(int port, unsigned int flags)
 
        switch (port) {
        case 0: /* OTG port */
-               v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
+               v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT | MX35_OTG_PP_BIT |
+                       MX35_OTG_OCPOL_BIT);
                v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_OTG_SIC_SHIFT;
 
                if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
                        v |= MX35_OTG_PM_BIT;
 
+               if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
+                       v |= MX35_OTG_PP_BIT;
+
+               if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW))
+                       v |= MX35_OTG_OCPOL_BIT;
+
                break;
        case 1: /* H1 port */
-               v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
-                       MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
+               v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_PP_BIT |
+                       MX35_H1_OCPOL_BIT | MX35_H1_TLL_BIT | MX35_H1_USBTE_BIT |
+                       MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
                v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_H1_SIC_SHIFT;
 
                if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
                        v |= MX35_H1_PM_BIT;
 
+               if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
+                       v |= MX35_H1_PP_BIT;
+
+               if (!(flags & MXC_EHCI_OC_PIN_ACTIVE_LOW))
+                       v |= MX35_H1_OCPOL_BIT;
+
                if (!(flags & MXC_EHCI_TTL_ENABLED))
                        v |= MX35_H1_TLL_BIT;
 
index c17fa131728b227dcbc44a3ede131e58a12919ee..a6a4afb0ad62d8a6738d70cc81137b5a2f014571 100644 (file)
 #define MXC_OTG_UCTRL_OPM_BIT          (1 << 24)       /* OTG power mask */
 #define MXC_H1_UCTRL_H1UIE_BIT         (1 << 12)       /* Host1 ULPI interrupt enable */
 #define MXC_H1_UCTRL_H1WIE_BIT         (1 << 11)       /* HOST1 wakeup intr enable */
-#define MXC_H1_UCTRL_H1PM_BIT          (1 <<  8)               /* HOST1 power mask */
+#define MXC_H1_UCTRL_H1PM_BIT          (1 <<  8)       /* HOST1 power mask */
 
 /* USB_PHY_CTRL_FUNC */
+#define MXC_OTG_PHYCTRL_OC_POL_BIT     (1 << 9)        /* OTG Polarity of Overcurrent */
 #define MXC_OTG_PHYCTRL_OC_DIS_BIT     (1 << 8)        /* OTG Disable Overcurrent Event */
+#define MXC_H1_OC_POL_BIT              (1 << 6)        /* UH1 Polarity of Overcurrent */
 #define MXC_H1_OC_DIS_BIT              (1 << 5)        /* UH1 Disable Overcurrent Event */
+#define MXC_OTG_PHYCTRL_PWR_POL_BIT    (1 << 3)        /* OTG Power Pin Polarity */
 
 /* USBH2CTRL */
 #define MXC_H2_UCTRL_H2UIE_BIT         (1 << 8)
@@ -80,13 +83,21 @@ int mx51_initialize_usb_hw(int port, unsigned int flags)
                if (flags & MXC_EHCI_INTERNAL_PHY) {
                        v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
 
+                       if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)
+                               v |= MXC_OTG_PHYCTRL_OC_POL_BIT;
+                       else
+                               v &= ~MXC_OTG_PHYCTRL_OC_POL_BIT;
                        if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
-                               /* OC/USBPWR is not used */
-                               v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
-                       } else {
                                /* OC/USBPWR is used */
                                v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
+                       } else {
+                               /* OC/USBPWR is not used */
+                               v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
                        }
+                       if (flags & MXC_EHCI_PWR_PIN_ACTIVE_HIGH)
+                               v |= MXC_OTG_PHYCTRL_PWR_POL_BIT;
+                       else
+                               v &= ~MXC_OTG_PHYCTRL_PWR_POL_BIT;
                        __raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
 
                        v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
@@ -95,9 +106,9 @@ int mx51_initialize_usb_hw(int port, unsigned int flags)
                        else
                                v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
                        if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-                               v |= MXC_OTG_UCTRL_OPM_BIT;
-                       else
                                v &= ~MXC_OTG_UCTRL_OPM_BIT;
+                       else
+                               v |= MXC_OTG_UCTRL_OPM_BIT;
                        __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
                }
                break;
@@ -113,12 +124,16 @@ int mx51_initialize_usb_hw(int port, unsigned int flags)
                }
 
                if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-                       v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
+                       v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask unused*/
                else
                        v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
                __raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
 
                v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+               if (flags & MXC_EHCI_OC_PIN_ACTIVE_LOW)
+                       v |= MXC_H1_OC_POL_BIT;
+               else
+                       v &= ~MXC_H1_OC_POL_BIT;
                if (flags & MXC_EHCI_POWER_PINS_ENABLED)
                        v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
                else
@@ -142,7 +157,7 @@ int mx51_initialize_usb_hw(int port, unsigned int flags)
                }
 
                if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-                       v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+                       v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask unused*/
                else
                        v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
                __raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
index b46cab0ced5383976aee183f0a49ac4f283ab83b..fd3177f9e79ad2be616fb4d70b1f71f48daf9fdf 100644 (file)
@@ -266,7 +266,7 @@ static struct spi_board_info __maybe_unused
                .bus_num        = 0,
                .chip_select    = 0,
                .max_speed_hz   = 1500000,
-               .irq            = IRQ_GPIOD(25),
+               /* irq number is run-time assigned */
                .platform_data  = &ads7846_config,
                .mode           = SPI_MODE_2,
        },
@@ -329,6 +329,7 @@ void __init eukrea_mbimx27_baseboard_init(void)
        /* SPI_CS0 init */
        mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_OUT);
        imx27_add_spi_imx0(&eukrea_mbimx27_spi0_data);
+       eukrea_mbimx27_spi_board_info[0].irq = gpio_to_irq(IMX_GPIO_NR(4, 25));
        spi_register_board_info(eukrea_mbimx27_spi_board_info,
                        ARRAY_SIZE(eukrea_mbimx27_spi_board_info));
 
index 557f6c4860535f7bef1d7860acd0f57e54bda7a1..6e9dd12a6961cf8bf7e6fc8cf8053a12ca13fd32 100644 (file)
@@ -95,10 +95,6 @@ static const struct fb_videomode fb_modedb[] = {
        },
 };
 
-static const struct ipu_platform_data mx3_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct mx3fb_platform_data mx3fb_pdata __initdata = {
        .name           = "CMO-QVGA",
        .mode           = fb_modedb,
@@ -287,7 +283,7 @@ void __init eukrea_mbimxsd35_baseboard_init(void)
                printk(KERN_ERR "error setting mbimxsd pads !\n");
 
        imx35_add_imx_uart1(&uart_pdata);
-       imx35_add_ipu_core(&mx3_ipu_data);
+       imx35_add_ipu_core();
        imx35_add_mx3_sdc_fb(&mx3fb_pdata);
 
        imx35_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
index eee0cc8d92a43e84300723b05e6e9bb86bcb84f1..e80d5235dac0201346aeac09ab9045608bfbe9b5 100644 (file)
@@ -10,7 +10,6 @@
  */
 
 #include <linux/irq.h>
-#include <linux/irqdomain.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <asm/mach/arch.h>
@@ -33,35 +32,8 @@ static const struct of_dev_auxdata imx27_auxdata_lookup[] __initconst = {
        { /* sentinel */ }
 };
 
-static int __init imx27_avic_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       irq_domain_add_legacy(np, 64, 0, 0, &irq_domain_simple_ops, NULL);
-       return 0;
-}
-
-static int __init imx27_gpio_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
-
-       gpio_irq_base -= 32;
-       irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops,
-                               NULL);
-
-       return 0;
-}
-
-static const struct of_device_id imx27_irq_match[] __initconst = {
-       { .compatible = "fsl,imx27-avic", .data = imx27_avic_add_irq_domain, },
-       { .compatible = "fsl,imx27-gpio", .data = imx27_gpio_add_irq_domain, },
-       { /* sentinel */ }
-};
-
 static void __init imx27_dt_init(void)
 {
-       of_irq_init(imx27_irq_match);
-
        of_platform_populate(NULL, of_default_bus_match_table,
                             imx27_auxdata_lookup, NULL);
 }
@@ -75,7 +47,7 @@ static struct sys_timer imx27_timer = {
        .init = imx27_timer_init,
 };
 
-static const char *imx27_dt_board_compat[] __initdata = {
+static const char * const imx27_dt_board_compat[] __initconst = {
        "fsl,imx27",
        NULL
 };
diff --git a/arch/arm/mach-imx/imx31-dt.c b/arch/arm/mach-imx/imx31-dt.c
new file mode 100644 (file)
index 0000000..a68ba20
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2012 Sascha Hauer, Pengutronix
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/irq.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/mx31.h>
+
+static const struct of_dev_auxdata imx31_auxdata_lookup[] __initconst = {
+       OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART1_BASE_ADDR,
+                       "imx21-uart.0", NULL),
+       OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART2_BASE_ADDR,
+                       "imx21-uart.1", NULL),
+       OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART3_BASE_ADDR,
+                       "imx21-uart.2", NULL),
+       OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART4_BASE_ADDR,
+                       "imx21-uart.3", NULL),
+       OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART5_BASE_ADDR,
+                       "imx21-uart.4", NULL),
+       { /* sentinel */ }
+};
+
+static void __init imx31_dt_init(void)
+{
+       of_platform_populate(NULL, of_default_bus_match_table,
+                            imx31_auxdata_lookup, NULL);
+}
+
+static void __init imx31_timer_init(void)
+{
+       mx31_clocks_init_dt();
+}
+
+static struct sys_timer imx31_timer = {
+       .init = imx31_timer_init,
+};
+
+static const char *imx31_dt_board_compat[] __initdata = {
+       "fsl,imx31",
+       NULL
+};
+
+DT_MACHINE_START(IMX31_DT, "Freescale i.MX31 (Device Tree Support)")
+       .map_io         = mx31_map_io,
+       .init_early     = imx31_init_early,
+       .init_irq       = mx31_init_irq,
+       .handle_irq     = imx31_handle_irq,
+       .timer          = &imx31_timer,
+       .init_machine   = imx31_dt_init,
+       .dt_compat      = imx31_dt_board_compat,
+       .restart        = mxc_restart,
+MACHINE_END
index 18e78dba4298ad90aebc7f0a86e44e723d413924..d4067fe363575955739c22d2f59ef142d97f6669 100644 (file)
@@ -11,7 +11,6 @@
  */
 
 #include <linux/irq.h>
-#include <linux/irqdomain.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/pinctrl/machine.h>
@@ -45,30 +44,6 @@ static const struct of_dev_auxdata imx51_auxdata_lookup[] __initconst = {
        { /* sentinel */ }
 };
 
-static int __init imx51_tzic_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       irq_domain_add_legacy(np, 128, 0, 0, &irq_domain_simple_ops, NULL);
-       return 0;
-}
-
-static int __init imx51_gpio_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
-
-       gpio_irq_base -= 32;
-       irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, NULL);
-
-       return 0;
-}
-
-static const struct of_device_id imx51_irq_match[] __initconst = {
-       { .compatible = "fsl,imx51-tzic", .data = imx51_tzic_add_irq_domain, },
-       { .compatible = "fsl,imx51-gpio", .data = imx51_gpio_add_irq_domain, },
-       { /* sentinel */ }
-};
-
 static const struct of_device_id imx51_iomuxc_of_match[] __initconst = {
        { .compatible = "fsl,imx51-iomuxc-babbage", .data = imx51_babbage_common_init, },
        { /* sentinel */ }
@@ -80,8 +55,6 @@ static void __init imx51_dt_init(void)
        const struct of_device_id *of_id;
        void (*func)(void);
 
-       of_irq_init(imx51_irq_match);
-
        pinctrl_provide_dummies();
 
        node = of_find_matching_node(NULL, imx51_iomuxc_of_match);
index eb04b6248e48ee9a93751ede8c6cafee15904896..1b7a2fc36591e1806af4345be6f00fbec9bd70a8 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/irq.h>
-#include <linux/irqdomain.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/pinctrl/machine.h>
@@ -52,30 +51,6 @@ static const struct of_dev_auxdata imx53_auxdata_lookup[] __initconst = {
        { /* sentinel */ }
 };
 
-static int __init imx53_tzic_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       irq_domain_add_legacy(np, 128, 0, 0, &irq_domain_simple_ops, NULL);
-       return 0;
-}
-
-static int __init imx53_gpio_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
-
-       gpio_irq_base -= 32;
-       irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops, NULL);
-
-       return 0;
-}
-
-static const struct of_device_id imx53_irq_match[] __initconst = {
-       { .compatible = "fsl,imx53-tzic", .data = imx53_tzic_add_irq_domain, },
-       { .compatible = "fsl,imx53-gpio", .data = imx53_gpio_add_irq_domain, },
-       { /* sentinel */ }
-};
-
 static const struct of_device_id imx53_iomuxc_of_match[] __initconst = {
        { .compatible = "fsl,imx53-iomuxc-ard", .data = imx53_ard_common_init, },
        { .compatible = "fsl,imx53-iomuxc-evk", .data = imx53_evk_common_init, },
@@ -103,8 +78,6 @@ static void __init imx53_dt_init(void)
        const struct of_device_id *of_id;
        void (*func)(void);
 
-       of_irq_init(imx53_irq_match);
-
        pinctrl_provide_dummies();
 
        node = of_find_matching_node(NULL, imx53_iomuxc_of_match);
@@ -147,6 +120,7 @@ DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
        .handle_irq     = imx53_handle_irq,
        .timer          = &imx53_timer,
        .init_machine   = imx53_dt_init,
+       .init_late      = imx53_init_late,
        .dt_compat      = imx53_dt_board_compat,
        .restart        = mxc_restart,
 MACHINE_END
index f4a63ee9e2174010f02aad2ca51123c48c02f38e..7b99a79722b6fbe638829ad8946877f11eb5c353 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
 #include <linux/dm9000.h>
+#include <linux/gpio.h>
 #include <linux/i2c.h>
 
 #include <asm/mach-types.h>
@@ -26,7 +27,6 @@
 
 #include <mach/common.h>
 #include <mach/hardware.h>
-#include <mach/irqs.h>
 #include <mach/iomux-mx1.h>
 
 #include "devices-imx1.h"
@@ -87,8 +87,7 @@ static struct resource dm9000_resources[] = {
                .end    = MX1_CS4_PHYS + 0x00C00003,
                .flags  = IORESOURCE_MEM,
        }, {
-               .start  = IRQ_GPIOB(14),
-               .end    = IRQ_GPIOB(14),
+               /* irq number is run-time assigned */
                .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
        },
 };
@@ -129,6 +128,8 @@ static void __init apf9328_init(void)
 
        imx1_add_imx_i2c(&apf9328_i2c_data);
 
+       dm9000_resources[2].start = gpio_to_irq(IMX_GPIO_NR(2, 14));
+       dm9000_resources[2].end = gpio_to_irq(IMX_GPIO_NR(2, 14));
        platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
index c650145d1646e6dbdfbe65ec4c96c7c56d611cd5..2c6ab3273f9e4d4a419e54a4f7cde417fdb213a6 100644 (file)
@@ -367,10 +367,6 @@ static const struct fb_videomode fb_modedb[] = {
        },
 };
 
-static const struct ipu_platform_data mx3_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct mx3fb_platform_data mx3fb_pdata __initdata = {
        .name           = "CRT-VGA",
        .mode           = fb_modedb,
@@ -408,7 +404,8 @@ static int armadillo5x0_sdhc1_init(struct device *dev,
        gpio_direction_input(gpio_wp);
 
        /* When supported the trigger type have to be BOTH */
-       ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_ATA_DMACK), detect_irq,
+       ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK)),
+                         detect_irq,
                          IRQF_DISABLED | IRQF_TRIGGER_FALLING,
                          "sdhc-detect", data);
 
@@ -429,7 +426,7 @@ err_gpio_free:
 
 static void armadillo5x0_sdhc1_exit(struct device *dev, void *data)
 {
-       free_irq(IOMUX_TO_IRQ(MX31_PIN_ATA_DMACK), data);
+       free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK)), data);
        gpio_free(IOMUX_TO_GPIO(MX31_PIN_ATA_DMACK));
        gpio_free(IOMUX_TO_GPIO(MX31_PIN_ATA_RESET_B));
 }
@@ -450,8 +447,7 @@ static struct resource armadillo5x0_smc911x_resources[] = {
                .end    = MX31_CS3_BASE_ADDR + SZ_32M - 1,
                .flags  = IORESOURCE_MEM,
        }, {
-               .start  = IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
-               .end    = IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
+               /* irq number is run-time assigned */
                .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
        },
 };
@@ -498,6 +494,10 @@ static void __init armadillo5x0_init(void)
 
        regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 
+       armadillo5x0_smc911x_resources[1].start =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_0));
+       armadillo5x0_smc911x_resources[1].end =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_0));
        platform_add_devices(devices, ARRAY_SIZE(devices));
        imx_add_gpio_keys(&armadillo5x0_button_data);
        imx31_add_imx_i2c1(NULL);
@@ -513,7 +513,7 @@ static void __init armadillo5x0_init(void)
        imx31_add_mxc_mmc(0, &sdhc_pdata);
 
        /* Register FB */
-       imx31_add_ipu_core(&mx3_ipu_data);
+       imx31_add_ipu_core();
        imx31_add_mx3_sdc_fb(&mx3fb_pdata);
 
        /* Register NOR Flash */
index d085aea087095e4750e104a54aaee02c7312b0cf..2bb9e18d9ee134a078c664c966c2de6d2d4342f5 100644 (file)
@@ -169,28 +169,28 @@ static struct i2c_board_info eukrea_cpuimx27_i2c_devices[] = {
 static struct plat_serial8250_port serial_platform_data[] = {
        {
                .mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x200000),
-               .irq = IRQ_GPIOB(23),
+               /* irq number is run-time assigned */
                .uartclk = 14745600,
                .regshift = 1,
                .iotype = UPIO_MEM,
                .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
        }, {
                .mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x400000),
-               .irq = IRQ_GPIOB(22),
+               /* irq number is run-time assigned */
                .uartclk = 14745600,
                .regshift = 1,
                .iotype = UPIO_MEM,
                .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
        }, {
                .mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x800000),
-               .irq = IRQ_GPIOB(27),
+               /* irq number is run-time assigned */
                .uartclk = 14745600,
                .regshift = 1,
                .iotype = UPIO_MEM,
                .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_IOREMAP,
        }, {
                .mapbase = (unsigned long)(MX27_CS3_BASE_ADDR + 0x1000000),
-               .irq = IRQ_GPIOB(30),
+               /* irq number is run-time assigned */
                .uartclk = 14745600,
                .regshift = 1,
                .iotype = UPIO_MEM,
@@ -233,18 +233,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .phy_mode       = FSL_USB2_PHY_ULPI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init eukrea_cpuimx27_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", eukrea_cpuimx27_otg_mode);
 
@@ -266,8 +266,8 @@ static void __init eukrea_cpuimx27_init(void)
 
        imx27_add_fec(NULL);
        platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-       imx27_add_imx2_wdt(NULL);
-       imx27_add_mxc_w1(NULL);
+       imx27_add_imx2_wdt();
+       imx27_add_mxc_w1();
 
 #if defined(CONFIG_MACH_EUKREA_CPUIMX27_USESDHC2)
        /* SDHC2 can be used for Wifi */
@@ -279,6 +279,10 @@ static void __init eukrea_cpuimx27_init(void)
 #endif
 
 #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
+       serial_platform_data[0].irq = IMX_GPIO_NR(2, 23);
+       serial_platform_data[1].irq = IMX_GPIO_NR(2, 22);
+       serial_platform_data[2].irq = IMX_GPIO_NR(2, 27);
+       serial_platform_data[3].irq = IMX_GPIO_NR(2, 30);
        platform_device_register(&serial_device);
 #endif
 
index 6450303f1a7ac01e701adf8b886248a981c54856..d49b0ec6bdec839953f15775a03adb5546c17b6a 100644 (file)
@@ -71,7 +71,7 @@ static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
        }, {
                I2C_BOARD_INFO("tsc2007", 0x48),
                .platform_data  = &tsc2007_info,
-               .irq            = IMX_GPIO_TO_IRQ(TSC2007_IRQGPIO),
+               /* irq number is run-time assigned */
        },
 };
 
@@ -141,18 +141,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .workaround     = FLS_USB2_WORKAROUND_ENGCM09152,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init eukrea_cpuimx35_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", eukrea_cpuimx35_otg_mode);
 
@@ -167,11 +167,12 @@ static void __init eukrea_cpuimx35_init(void)
                        ARRAY_SIZE(eukrea_cpuimx35_pads));
 
        imx35_add_fec(NULL);
-       imx35_add_imx2_wdt(NULL);
+       imx35_add_imx2_wdt();
 
        imx35_add_imx_uart0(&uart_pdata);
        imx35_add_mxc_nand(&eukrea_cpuimx35_nand_board_info);
 
+       eukrea_cpuimx35_i2c_devices[1].irq = gpio_to_irq(TSC2007_IRQGPIO);
        i2c_register_board_info(0, eukrea_cpuimx35_i2c_devices,
                        ARRAY_SIZE(eukrea_cpuimx35_i2c_devices));
        imx35_add_imx_i2c0(&eukrea_cpuimx35_i2c0_data);
index 1e09de50cbcdc9292ad762d6228c7663fbfcc4a2..b87cc49ab1e8ec67e6504f54335115de95c3223d 100644 (file)
@@ -217,18 +217,18 @@ static const struct mxc_usbh_platform_data usbh1_config __initconst = {
        .portsc = MXC_EHCI_MODE_ULPI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init eukrea_cpuimx51sd_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", eukrea_cpuimx51sd_otg_mode);
 
@@ -258,7 +258,7 @@ static struct spi_board_info cpuimx51sd_spi_device[] = {
                .mode           = SPI_MODE_0,
                .chip_select     = 0,
                .platform_data   = &mcp251x_info,
-               .irq             = IMX_GPIO_TO_IRQ(CAN_IRQGPIO)
+               /* irq number is run-time assigned */
        },
 };
 
@@ -292,7 +292,7 @@ static void __init eukrea_cpuimx51sd_init(void)
 
        imx51_add_imx_uart(0, &uart_pdata);
        imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);
-       imx51_add_imx2_wdt(0, NULL);
+       imx51_add_imx2_wdt(0);
 
        gpio_request(ETH_RST, "eth_rst");
        gpio_set_value(ETH_RST, 1);
@@ -309,6 +309,7 @@ static void __init eukrea_cpuimx51sd_init(void)
        msleep(20);
        gpio_set_value(CAN_RST, 1);
        imx51_add_ecspi(0, &cpuimx51sd_ecspi1_pdata);
+       cpuimx51sd_spi_device[0].irq = gpio_to_irq(CAN_IRQGPIO);
        spi_register_board_info(cpuimx51sd_spi_device,
                                ARRAY_SIZE(cpuimx51sd_spi_device));
 
index d1e04e676e33b0cb4c516560d72c61030c64a5bd..017bbb70ea415b3b75c050dbf0952aa46374680c 100644 (file)
@@ -109,18 +109,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .workaround     = FLS_USB2_WORKAROUND_ENGCM09152,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init eukrea_cpuimx25_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", eukrea_cpuimx25_otg_mode);
 
@@ -134,9 +134,9 @@ static void __init eukrea_cpuimx25_init(void)
 
        imx25_add_imx_uart0(&uart_pdata);
        imx25_add_mxc_nand(&eukrea_cpuimx25_nand_board_info);
-       imx25_add_imxdi_rtc(NULL);
+       imx25_add_imxdi_rtc();
        imx25_add_fec(&mx25_fec_pdata);
-       imx25_add_imx2_wdt(NULL);
+       imx25_add_imx2_wdt();
 
        i2c_register_board_info(0, eukrea_cpuimx25_i2c_devices,
                                ARRAY_SIZE(eukrea_cpuimx25_i2c_devices));
index ba09552fe5feee5b6720e3b294449e6d46bfeddf..f264ddddd47c395404203cdebf43b7dc2206abb0 100644 (file)
@@ -40,6 +40,7 @@
 #include <asm/mach/time.h>
 #include <asm/system_info.h>
 #include <mach/common.h>
+#include <mach/hardware.h>
 #include <mach/iomux-mx27.h>
 
 #include "devices-imx27.h"
@@ -47,7 +48,7 @@
 #define TVP5150_RSTN (GPIO_PORTC + 18)
 #define TVP5150_PWDN (GPIO_PORTC + 19)
 #define OTG_PHY_CS_GPIO (GPIO_PORTF + 17)
-#define SDHC1_IRQ IRQ_GPIOB(25)
+#define SDHC1_IRQ_GPIO IMX_GPIO_NR(2, 25)
 
 #define MOTHERBOARD_BIT2       (GPIO_PORTD + 31)
 #define MOTHERBOARD_BIT1       (GPIO_PORTD + 30)
@@ -307,14 +308,14 @@ static int visstrim_m10_sdhc1_init(struct device *dev,
 {
        int ret;
 
-       ret = request_irq(SDHC1_IRQ, detect_irq, IRQF_TRIGGER_FALLING,
-                               "mmc-detect", data);
+       ret = request_irq(gpio_to_irq(SDHC1_IRQ_GPIO), detect_irq,
+                         IRQF_TRIGGER_FALLING, "mmc-detect", data);
        return ret;
 }
 
 static void visstrim_m10_sdhc1_exit(struct device *dev, void *data)
 {
-       free_irq(SDHC1_IRQ, data);
+       free_irq(gpio_to_irq(SDHC1_IRQ_GPIO), data);
 }
 
 static const struct imxmmc_platform_data visstrim_m10_sdhc_pdata __initconst = {
index c9d350c5dcc83a590ea36774887eb7fd8461e72b..7381387a890558909ae69b3fd2fbeb621118e61c 100644 (file)
@@ -57,7 +57,7 @@ static void __init mx27ipcam_init(void)
 
        imx27_add_imx_uart0(NULL);
        imx27_add_fec(NULL);
-       imx27_add_imx2_wdt(NULL);
+       imx27_add_imx2_wdt();
 }
 
 static void __init mx27ipcam_timer_init(void)
index b47e98b7d539fc9bce4cd4f0060004f086d528c4..5ec0608f2a764a9be584ea1bebbe1339f981a259 100644 (file)
 
 #include <linux/clk.h>
 #include <linux/clkdev.h>
+#include <linux/cpuidle.h>
 #include <linux/delay.h>
+#include <linux/export.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/irq.h>
-#include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -24,6 +25,8 @@
 #include <linux/pinctrl/machine.h>
 #include <linux/phy.h>
 #include <linux/micrel_phy.h>
+#include <linux/mfd/anatop.h>
+#include <asm/cpuidle.h>
 #include <asm/smp_twd.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
 #include <asm/mach/time.h>
 #include <asm/system_misc.h>
 #include <mach/common.h>
+#include <mach/cpuidle.h>
 #include <mach/hardware.h>
 
+
 void imx6q_restart(char mode, const char *cmd)
 {
        struct device_node *np;
@@ -113,6 +118,45 @@ static void __init imx6q_sabrelite_init(void)
        imx6q_sabrelite_cko1_setup();
 }
 
+static void __init imx6q_usb_init(void)
+{
+       struct device_node *np;
+       struct platform_device *pdev = NULL;
+       struct anatop *adata = NULL;
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
+       if (np)
+               pdev = of_find_device_by_node(np);
+       if (pdev)
+               adata = platform_get_drvdata(pdev);
+       if (!adata) {
+               if (np)
+                       of_node_put(np);
+               return;
+       }
+
+#define HW_ANADIG_USB1_CHRG_DETECT             0x000001b0
+#define HW_ANADIG_USB2_CHRG_DETECT             0x00000210
+
+#define BM_ANADIG_USB_CHRG_DETECT_EN_B         0x00100000
+#define BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B   0x00080000
+
+       /*
+        * The external charger detector needs to be disabled,
+        * or the signal at DP will be poor
+        */
+       anatop_write_reg(adata, HW_ANADIG_USB1_CHRG_DETECT,
+                       BM_ANADIG_USB_CHRG_DETECT_EN_B
+                       | BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B,
+                       ~0);
+       anatop_write_reg(adata, HW_ANADIG_USB2_CHRG_DETECT,
+                       BM_ANADIG_USB_CHRG_DETECT_EN_B |
+                       BM_ANADIG_USB_CHRG_DETECT_CHK_CHRG_B,
+                       ~0);
+
+       of_node_put(np);
+}
+
 static void __init imx6q_init_machine(void)
 {
        /*
@@ -127,6 +171,20 @@ static void __init imx6q_init_machine(void)
        of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 
        imx6q_pm_init();
+       imx6q_usb_init();
+}
+
+static struct cpuidle_driver imx6q_cpuidle_driver = {
+       .name                   = "imx6q_cpuidle",
+       .owner                  = THIS_MODULE,
+       .en_core_tk_irqen       = 1,
+       .states[0]              = ARM_CPUIDLE_WFI_STATE,
+       .state_count            = 1,
+};
+
+static void __init imx6q_init_late(void)
+{
+       imx_cpuidle_init(&imx6q_cpuidle_driver);
 }
 
 static void __init imx6q_map_io(void)
@@ -136,21 +194,8 @@ static void __init imx6q_map_io(void)
        imx6q_clock_map_io();
 }
 
-static int __init imx6q_gpio_add_irq_domain(struct device_node *np,
-                               struct device_node *interrupt_parent)
-{
-       static int gpio_irq_base = MXC_GPIO_IRQ_START + ARCH_NR_GPIOS;
-
-       gpio_irq_base -= 32;
-       irq_domain_add_legacy(np, 32, gpio_irq_base, 0, &irq_domain_simple_ops,
-                             NULL);
-
-       return 0;
-}
-
 static const struct of_device_id imx6q_irq_match[] __initconst = {
        { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-       { .compatible = "fsl,imx6q-gpio", .data = imx6q_gpio_add_irq_domain, },
        { /* sentinel */ }
 };
 
@@ -186,6 +231,7 @@ DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad (Device Tree)")
        .handle_irq     = imx6q_handle_irq,
        .timer          = &imx6q_timer,
        .init_machine   = imx6q_init_machine,
+       .init_late      = imx6q_init_late,
        .dt_compat      = imx6q_dt_compat,
        .restart        = imx6q_restart,
 MACHINE_END
index 15a26e90826032d987775a16223e5e49e023b864..5d08533ab2c77d50109c670dc071063c9c0da34c 100644 (file)
@@ -73,7 +73,7 @@ static struct plat_serial8250_port serial_platform_data[] = {
        {
                .membase        = KZM_ARM11_IO_ADDRESS(KZM_ARM11_16550),
                .mapbase        = KZM_ARM11_16550,
-               .irq            = IOMUX_TO_IRQ(MX31_PIN_GPIO1_1),
+               /* irq number is run-time assigned */
                .irqflags       = IRQ_TYPE_EDGE_RISING,
                .uartclk        = 14745600,
                .regshift       = 0,
@@ -91,8 +91,7 @@ static struct resource serial8250_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        {
-               .start  = IOMUX_TO_IRQ(MX31_PIN_GPIO1_1),
-               .end    = IOMUX_TO_IRQ(MX31_PIN_GPIO1_1),
+               /* irq number is run-time assigned */
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -125,6 +124,13 @@ static int __init kzm_init_ext_uart(void)
        tmp |= 0x2;
        __raw_writeb(tmp, KZM_ARM11_IO_ADDRESS(KZM_ARM11_CTL1));
 
+       serial_platform_data[0].irq =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1));
+       serial8250_resources[1].start =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1));
+       serial8250_resources[1].end =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1));
+
        return platform_device_register(&serial_device);
 }
 #else
@@ -152,8 +158,7 @@ static struct resource kzm_smsc9118_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        {
-               .start  = IOMUX_TO_IRQ(MX31_PIN_GPIO1_2),
-               .end    = IOMUX_TO_IRQ(MX31_PIN_GPIO1_2),
+               /* irq number is run-time assigned */
                .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
        },
 };
@@ -184,6 +189,11 @@ static int __init kzm_init_smsc9118(void)
 
        regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 
+       kzm_smsc9118_resources[1].start =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2));
+       kzm_smsc9118_resources[1].end =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_2));
+
        return platform_device_register(&kzm_smsc9118_device);
 }
 #else
index 7274e7928136a67d366175329830d4146fb7d08b..667f359a2e8b037e8d6a08933cf20435195e849d 100644 (file)
@@ -26,7 +26,6 @@
 #include <mach/common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-mx1.h>
-#include <mach/irqs.h>
 
 #include "devices-imx1.h"
 
index 3e7401fca76c7e18860261a7541449e3c75b5c9d..ed22e3fe6ec888d08840d9b6cbc839c9ccfdf4d6 100644 (file)
@@ -38,7 +38,7 @@
                (MX21ADS_MMIO_BASE_ADDR + (offset))
 
 #define MX21ADS_CS8900A_MMIO_SIZE   0x200000
-#define MX21ADS_CS8900A_IRQ         IRQ_GPIOE(11)
+#define MX21ADS_CS8900A_IRQ_GPIO    IMX_GPIO_NR(5, 11)
 #define MX21ADS_ST16C255_IOBASE_REG MX21ADS_REG_ADDR(0x200000)
 #define MX21ADS_VERSION_REG         MX21ADS_REG_ADDR(0x400000)
 #define MX21ADS_IO_REG              MX21ADS_REG_ADDR(0x800000)
@@ -159,9 +159,10 @@ static struct platform_device mx21ads_nor_mtd_device = {
        .resource = &mx21ads_flash_resource,
 };
 
-static const struct resource mx21ads_cs8900_resources[] __initconst = {
+static struct resource mx21ads_cs8900_resources[] __initdata = {
        DEFINE_RES_MEM(MX21_CS1_BASE_ADDR, MX21ADS_CS8900A_MMIO_SIZE),
-       DEFINE_RES_IRQ(MX21ADS_CS8900A_IRQ),
+       /* irq number is run-time assigned */
+       DEFINE_RES_IRQ(-1),
 };
 
 static const struct platform_device_info mx21ads_cs8900_devinfo __initconst = {
@@ -241,13 +242,13 @@ static int mx21ads_sdhc_get_ro(struct device *dev)
 static int mx21ads_sdhc_init(struct device *dev, irq_handler_t detect_irq,
        void *data)
 {
-       return request_irq(IRQ_GPIOD(25), detect_irq,
+       return request_irq(gpio_to_irq(IMX_GPIO_NR(4, 25)), detect_irq,
                IRQF_TRIGGER_FALLING, "mmc-detect", data);
 }
 
 static void mx21ads_sdhc_exit(struct device *dev, void *data)
 {
-       free_irq(IRQ_GPIOD(25), data);
+       free_irq(gpio_to_irq(IMX_GPIO_NR(4, 25)), data);
 }
 
 static const struct imxmmc_platform_data mx21ads_sdhc_pdata __initconst = {
@@ -304,6 +305,11 @@ static void __init mx21ads_board_init(void)
        imx21_add_mxc_nand(&mx21ads_nand_board_info);
 
        platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
+
+       mx21ads_cs8900_resources[1].start =
+                       gpio_to_irq(MX21ADS_CS8900A_IRQ_GPIO);
+       mx21ads_cs8900_resources[1].end =
+                       gpio_to_irq(MX21ADS_CS8900A_IRQ_GPIO);
        platform_device_register_full(&mx21ads_cs8900_devinfo);
 }
 
index f26734298aa629d52c94faea8f7e7ea2a0694230..ce247fd1269ae094a57dc95065ba2256effb7e65 100644 (file)
@@ -237,9 +237,9 @@ static void __init mx25pdk_init(void)
        imx25_add_fsl_usb2_udc(&otg_device_pdata);
        imx25_add_mxc_ehci_hs(&usbh2_pdata);
        imx25_add_mxc_nand(&mx25pdk_nand_board_info);
-       imx25_add_imxdi_rtc(NULL);
+       imx25_add_imxdi_rtc();
        imx25_add_imx_fb(&mx25pdk_fb_pdata);
-       imx25_add_imx2_wdt(NULL);
+       imx25_add_imx2_wdt();
 
        mx25pdk_fec_reset();
        imx25_add_fec(&mx25_fec_pdata);
index c6d385c522576f1052eeb474fc2d69a86faa7a0e..58c24c1a7ab70ac26e47db241e882800a2cf9cc5 100644 (file)
@@ -40,7 +40,6 @@
 #include <mach/common.h>
 #include <mach/iomux-mx27.h>
 #include <mach/ulpi.h>
-#include <mach/irqs.h>
 #include <mach/3ds_debugboard.h>
 
 #include "devices-imx27.h"
@@ -48,7 +47,6 @@
 #define SD1_EN_GPIO            IMX_GPIO_NR(2, 25)
 #define OTG_PHY_RESET_GPIO     IMX_GPIO_NR(2, 23)
 #define SPI2_SS0               IMX_GPIO_NR(4, 21)
-#define EXPIO_PARENT_INT       gpio_to_irq(IMX_GPIO_NR(3, 28))
 #define PMIC_INT               IMX_GPIO_NR(3, 14)
 #define SPI1_SS0               IMX_GPIO_NR(4, 28)
 #define SD1_CD                 IMX_GPIO_NR(2, 26)
@@ -241,18 +239,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .phy_mode       = FSL_USB2_PHY_ULPI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init mx27_3ds_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", mx27_3ds_otg_mode);
 
@@ -445,7 +443,7 @@ static struct spi_board_info mx27_3ds_spi_devs[] __initdata = {
                .bus_num        = 1,
                .chip_select    = 0, /* SS0 */
                .platform_data  = &mc13783_pdata,
-               .irq = IMX_GPIO_TO_IRQ(PMIC_INT),
+               /* irq number is run-time assigned */
                .mode = SPI_CS_HIGH,
        }, {
                .modalias       = "l4f00242t03",
@@ -480,7 +478,7 @@ static void __init mx27pdk_init(void)
        imx27_add_fec(NULL);
        imx27_add_imx_keypad(&mx27_3ds_keymap_data);
        imx27_add_mxc_mmc(0, &sdhc1_pdata);
-       imx27_add_imx2_wdt(NULL);
+       imx27_add_imx2_wdt();
        otg_phy_init();
 
        if (otg_mode_host) {
@@ -496,10 +494,11 @@ static void __init mx27pdk_init(void)
 
        imx27_add_spi_imx1(&spi2_pdata);
        imx27_add_spi_imx0(&spi1_pdata);
+       mx27_3ds_spi_devs[0].irq = gpio_to_irq(PMIC_INT);
        spi_register_board_info(mx27_3ds_spi_devs,
                                                ARRAY_SIZE(mx27_3ds_spi_devs));
 
-       if (mxc_expio_init(MX27_CS5_BASE_ADDR, EXPIO_PARENT_INT))
+       if (mxc_expio_init(MX27_CS5_BASE_ADDR, IMX_GPIO_NR(3, 28)))
                pr_warn("Init of the debugboard failed, all devices on the debugboard are unusable.\n");
        imx27_add_imx_i2c(0, &mx27_3ds_i2c0_data);
        platform_add_devices(devices, ARRAY_SIZE(devices));
index 0228d2e07fe05ed641b6f24988b0730b9eae86ed..7dc59bac0e55cf8e30e1151064622a53cf172205 100644 (file)
@@ -246,25 +246,25 @@ static const struct imx_fb_platform_data mx27ads_fb_data __initconst = {
 static int mx27ads_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
                              void *data)
 {
-       return request_irq(IRQ_GPIOE(21), detect_irq, IRQF_TRIGGER_RISING,
-                          "sdhc1-card-detect", data);
+       return request_irq(gpio_to_irq(IMX_GPIO_NR(5, 21)), detect_irq,
+                          IRQF_TRIGGER_RISING, "sdhc1-card-detect", data);
 }
 
 static int mx27ads_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
                              void *data)
 {
-       return request_irq(IRQ_GPIOB(7), detect_irq, IRQF_TRIGGER_RISING,
-                          "sdhc2-card-detect", data);
+       return request_irq(gpio_to_irq(IMX_GPIO_NR(2, 7)), detect_irq,
+                          IRQF_TRIGGER_RISING, "sdhc2-card-detect", data);
 }
 
 static void mx27ads_sdhc1_exit(struct device *dev, void *data)
 {
-       free_irq(IRQ_GPIOE(21), data);
+       free_irq(gpio_to_irq(IMX_GPIO_NR(5, 21)), data);
 }
 
 static void mx27ads_sdhc2_exit(struct device *dev, void *data)
 {
-       free_irq(IRQ_GPIOB(7), data);
+       free_irq(gpio_to_irq(IMX_GPIO_NR(2, 7)), data);
 }
 
 static const struct imxmmc_platform_data sdhc1_pdata __initconst = {
@@ -310,7 +310,7 @@ static void __init mx27ads_board_init(void)
 
        imx27_add_fec(NULL);
        platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-       imx27_add_mxc_w1(NULL);
+       imx27_add_mxc_w1();
 }
 
 static void __init mx27ads_timer_init(void)
index 4eafdf275ea28864d6dacf6667be7221cf2a9a22..8915f937b7d54e00735bf2de1dd4c03730d2d5f9 100644 (file)
@@ -44,9 +44,6 @@
 
 #include "devices-imx31.h"
 
-/* CPLD IRQ line for external uart, external ethernet etc */
-#define EXPIO_PARENT_INT       IOMUX_TO_IRQ(MX31_PIN_GPIO1_1)
-
 static int mx31_3ds_pins[] = {
        /* UART1 */
        MX31_PIN_CTS1__CTS1,
@@ -277,10 +274,6 @@ static const struct fb_videomode fb_modedb[] = {
        },
 };
 
-static struct ipu_platform_data mx3_ipu_data = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct mx3fb_platform_data mx3fb_pdata __initdata = {
        .name           = "Epson-VGA",
        .mode           = fb_modedb,
@@ -317,7 +310,7 @@ static int mx31_3ds_sdhc1_init(struct device *dev,
                return ret;
        }
 
-       ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO3_1),
+       ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)),
                          detect_irq, IRQF_DISABLED |
                          IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
                          "sdhc1-detect", data);
@@ -336,7 +329,7 @@ gpio_free:
 
 static void mx31_3ds_sdhc1_exit(struct device *dev, void *data)
 {
-       free_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO3_1), data);
+       free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)), data);
        gpio_free_array(mx31_3ds_sdhc1_gpios,
                         ARRAY_SIZE(mx31_3ds_sdhc1_gpios));
 }
@@ -539,7 +532,7 @@ static struct spi_board_info mx31_3ds_spi_devs[] __initdata = {
                .bus_num        = 1,
                .chip_select    = 1, /* SS2 */
                .platform_data  = &mc13783_pdata,
-               .irq            = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+               /* irq number is run-time assigned */
                .mode = SPI_CS_HIGH,
        }, {
                .modalias       = "l4f00242t03",
@@ -671,18 +664,18 @@ static const struct fsl_usb2_platform_data usbotg_pdata __initconst = {
        .phy_mode       = FSL_USB2_PHY_ULPI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init mx31_3ds_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", mx31_3ds_otg_mode);
 
@@ -714,6 +707,7 @@ static void __init mx31_3ds_init(void)
        imx31_add_mxc_nand(&mx31_3ds_nand_board_info);
 
        imx31_add_spi_imx1(&spi1_pdata);
+       mx31_3ds_spi_devs[0].irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
        spi_register_board_info(mx31_3ds_spi_devs,
                                                ARRAY_SIZE(mx31_3ds_spi_devs));
 
@@ -736,15 +730,15 @@ static void __init mx31_3ds_init(void)
        if (!otg_mode_host)
                imx31_add_fsl_usb2_udc(&usbotg_pdata);
 
-       if (mxc_expio_init(MX31_CS5_BASE_ADDR, EXPIO_PARENT_INT))
+       if (mxc_expio_init(MX31_CS5_BASE_ADDR, IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)))
                printk(KERN_WARNING "Init of the debug board failed, all "
                                    "devices on the debug board are unusable.\n");
-       imx31_add_imx2_wdt(NULL);
+       imx31_add_imx2_wdt();
        imx31_add_imx_i2c0(&mx31_3ds_i2c0_data);
        imx31_add_mxc_mmc(0, &sdhc1_pdata);
 
        imx31_add_spi_imx0(&spi0_pdata);
-       imx31_add_ipu_core(&mx3_ipu_data);
+       imx31_add_ipu_core();
        imx31_add_mx3_sdc_fb(&mx3fb_pdata);
 
        /* CSI */
index 4518e544822731c19b941927067265184c59ff0b..d37f4809c5565abacb594f7693991ce726412092 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #define PBC_INTSTATUS_REG      (PBC_INTSTATUS + PBC_BASE_ADDRESS)
 #define PBC_INTMASK_SET_REG    (PBC_INTMASK_SET + PBC_BASE_ADDRESS)
 #define PBC_INTMASK_CLEAR_REG  (PBC_INTMASK_CLEAR + PBC_BASE_ADDRESS)
-#define EXPIO_PARENT_INT       IOMUX_TO_IRQ(MX31_PIN_GPIO1_4)
 
-#define MXC_EXP_IO_BASE                MXC_BOARD_IRQ_START
-#define MXC_IRQ_TO_EXPIO(irq)  ((irq) - MXC_EXP_IO_BASE)
-
-#define EXPIO_INT_XUART_INTA   (MXC_EXP_IO_BASE + 10)
-#define EXPIO_INT_XUART_INTB   (MXC_EXP_IO_BASE + 11)
+#define EXPIO_INT_XUART_INTA   10
+#define EXPIO_INT_XUART_INTB   11
 
 #define MXC_MAX_EXP_IO_LINES   16
 
 /* CS8900 */
-#define EXPIO_INT_ENET_INT     (MXC_EXP_IO_BASE + 8)
+#define EXPIO_INT_ENET_INT     8
 #define CS4_CS8900_MMIO_START  0x20000
 
+static struct irq_domain *domain;
+
 /*
  * The serial port definition structure.
  */
@@ -83,7 +82,6 @@ static struct plat_serial8250_port serial_platform_data[] = {
        {
                .membase  = (void *)(PBC_BASE_ADDRESS + PBC_SC16C652_UARTA),
                .mapbase  = (unsigned long)(MX31_CS4_BASE_ADDR + PBC_SC16C652_UARTA),
-               .irq      = EXPIO_INT_XUART_INTA,
                .uartclk  = 14745600,
                .regshift = 0,
                .iotype   = UPIO_MEM,
@@ -91,7 +89,6 @@ static struct plat_serial8250_port serial_platform_data[] = {
        }, {
                .membase  = (void *)(PBC_BASE_ADDRESS + PBC_SC16C652_UARTB),
                .mapbase  = (unsigned long)(MX31_CS4_BASE_ADDR + PBC_SC16C652_UARTB),
-               .irq      = EXPIO_INT_XUART_INTB,
                .uartclk  = 14745600,
                .regshift = 0,
                .iotype   = UPIO_MEM,
@@ -108,9 +105,9 @@ static struct platform_device serial_device = {
        },
 };
 
-static const struct resource mx31ads_cs8900_resources[] __initconst = {
+static struct resource mx31ads_cs8900_resources[] __initdata = {
        DEFINE_RES_MEM(MX31_CS4_BASE_ADDR + CS4_CS8900_MMIO_START, SZ_64K),
-       DEFINE_RES_IRQ(EXPIO_INT_ENET_INT),
+       DEFINE_RES_IRQ(-1),
 };
 
 static const struct platform_device_info mx31ads_cs8900_devinfo __initconst = {
@@ -122,11 +119,19 @@ static const struct platform_device_info mx31ads_cs8900_devinfo __initconst = {
 
 static int __init mxc_init_extuart(void)
 {
+       serial_platform_data[0].irq = irq_find_mapping(domain,
+                                                      EXPIO_INT_XUART_INTA);
+       serial_platform_data[1].irq = irq_find_mapping(domain,
+                                                      EXPIO_INT_XUART_INTB);
        return platform_device_register(&serial_device);
 }
 
 static void __init mxc_init_ext_ethernet(void)
 {
+       mx31ads_cs8900_resources[1].start =
+                       irq_find_mapping(domain, EXPIO_INT_ENET_INT);
+       mx31ads_cs8900_resources[1].end =
+                       irq_find_mapping(domain, EXPIO_INT_ENET_INT);
        platform_device_register_full(
                (struct platform_device_info *)&mx31ads_cs8900_devinfo);
 }
@@ -157,12 +162,12 @@ static void mx31ads_expio_irq_handler(u32 irq, struct irq_desc *desc)
        imr_val = __raw_readw(PBC_INTMASK_SET_REG);
        int_valid = __raw_readw(PBC_INTSTATUS_REG) & imr_val;
 
-       expio_irq = MXC_EXP_IO_BASE;
+       expio_irq = 0;
        for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
                if ((int_valid & 1) == 0)
                        continue;
 
-               generic_handle_irq(expio_irq);
+               generic_handle_irq(irq_find_mapping(domain, expio_irq));
        }
 }
 
@@ -172,7 +177,7 @@ static void mx31ads_expio_irq_handler(u32 irq, struct irq_desc *desc)
  */
 static void expio_mask_irq(struct irq_data *d)
 {
-       u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
+       u32 expio = d->hwirq;
        /* mask the interrupt */
        __raw_writew(1 << expio, PBC_INTMASK_CLEAR_REG);
        __raw_readw(PBC_INTMASK_CLEAR_REG);
@@ -184,7 +189,7 @@ static void expio_mask_irq(struct irq_data *d)
  */
 static void expio_ack_irq(struct irq_data *d)
 {
-       u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
+       u32 expio = d->hwirq;
        /* clear the interrupt status */
        __raw_writew(1 << expio, PBC_INTSTATUS_REG);
 }
@@ -195,7 +200,7 @@ static void expio_ack_irq(struct irq_data *d)
  */
 static void expio_unmask_irq(struct irq_data *d)
 {
-       u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
+       u32 expio = d->hwirq;
        /* unmask the interrupt */
        __raw_writew(1 << expio, PBC_INTMASK_SET_REG);
 }
@@ -209,7 +214,8 @@ static struct irq_chip expio_irq_chip = {
 
 static void __init mx31ads_init_expio(void)
 {
-       int i;
+       int irq_base;
+       int i, irq;
 
        printk(KERN_INFO "MX31ADS EXPIO(CPLD) hardware\n");
 
@@ -221,13 +227,21 @@ static void __init mx31ads_init_expio(void)
        /* disable the interrupt and clear the status */
        __raw_writew(0xFFFF, PBC_INTMASK_CLEAR_REG);
        __raw_writew(0xFFFF, PBC_INTSTATUS_REG);
-       for (i = MXC_EXP_IO_BASE; i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES);
-            i++) {
+
+       irq_base = irq_alloc_descs(-1, 0, MXC_MAX_EXP_IO_LINES, numa_node_id());
+       WARN_ON(irq_base < 0);
+
+       domain = irq_domain_add_legacy(NULL, MXC_MAX_EXP_IO_LINES, irq_base, 0,
+                                      &irq_domain_simple_ops, NULL);
+       WARN_ON(!domain);
+
+       for (i = irq_base; i < irq_base + MXC_MAX_EXP_IO_LINES; i++) {
                irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
-       irq_set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_HIGH);
-       irq_set_chained_handler(EXPIO_PARENT_INT, mx31ads_expio_irq_handler);
+       irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_4));
+       irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+       irq_set_chained_handler(irq, mx31ads_expio_irq_handler);
 }
 
 #ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
@@ -479,7 +493,6 @@ static int mx31_wm8350_init(struct wm8350 *wm8350)
 
 static struct wm8350_platform_data __initdata mx31_wm8350_pdata = {
        .init = mx31_wm8350_init,
-       .irq_base = MXC_BOARD_IRQ_START + MXC_MAX_EXP_IO_LINES,
 };
 #endif
 
@@ -488,13 +501,17 @@ static struct i2c_board_info __initdata mx31ads_i2c1_devices[] = {
        {
                I2C_BOARD_INFO("wm8350", 0x1a),
                .platform_data = &mx31_wm8350_pdata,
-               .irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+               /* irq number is run-time assigned */
        },
 #endif
 };
 
 static void __init mxc_init_i2c(void)
 {
+#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
+       mx31ads_i2c1_devices[0].irq =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
+#endif
        i2c_register_board_info(1, mx31ads_i2c1_devices,
                                ARRAY_SIZE(mx31ads_i2c1_devices));
 
index 83714b0cc290a25202e1e5122f3490ea426339c7..34b9bf075daff783eb332ab652347ac1e159b84f 100644 (file)
@@ -65,8 +65,7 @@ static struct resource smsc91x_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        {
-               .start  = IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
-               .end    = IOMUX_TO_IRQ(MX31_PIN_GPIO1_0),
+               /* irq number is run-time assigned */
                .flags  = IORESOURCE_IRQ | IRQF_TRIGGER_FALLING,
        }
 };
@@ -233,7 +232,7 @@ static struct spi_board_info mc13783_dev __initdata = {
        .bus_num        = 1,
        .chip_select    = 0,
        .platform_data  = &mc13783_pdata,
-       .irq            = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+       /* irq number is run-time assigned */
 };
 
 static struct platform_device *devices[] __initdata = {
@@ -285,10 +284,15 @@ static void __init mx31lilly_board_init(void)
 
        imx31_add_spi_imx0(&spi0_pdata);
        imx31_add_spi_imx1(&spi1_pdata);
+       mc13783_dev.irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
        spi_register_board_info(&mc13783_dev, 1);
 
        regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
 
+       smsc91x_resources[1].start =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_0));
+       smsc91x_resources[1].end =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_0));
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
        /* USB */
index 686c605879800614656aeeac2d60515a4c2d3536..c8785b39eaed20432166db3a0d24b49a4f416bc0 100644 (file)
@@ -43,7 +43,6 @@
 #include <mach/common.h>
 #include <mach/board-mx31lite.h>
 #include <mach/iomux-mx3.h>
-#include <mach/irqs.h>
 #include <mach/ulpi.h>
 
 #include "devices-imx31.h"
@@ -83,8 +82,7 @@ static struct resource smsc911x_resources[] = {
                .end            = MX31_CS4_BASE_ADDR + 0x100,
                .flags          = IORESOURCE_MEM,
        }, {
-               .start          = IOMUX_TO_IRQ(MX31_PIN_SFS6),
-               .end            = IOMUX_TO_IRQ(MX31_PIN_SFS6),
+               /* irq number is run-time assigned */
                .flags          = IORESOURCE_IRQ,
        },
 };
@@ -124,7 +122,7 @@ static struct spi_board_info mc13783_spi_dev __initdata = {
        .bus_num        = 1,
        .chip_select    = 0,
        .platform_data  = &mc13783_pdata,
-       .irq            = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+       /* irq number is run-time assigned */
 };
 
 /*
@@ -258,6 +256,7 @@ static void __init mx31lite_init(void)
        imx31_add_mxc_nand(&mx31lite_nand_board_info);
 
        imx31_add_spi_imx1(&spi1_pdata);
+       mc13783_spi_dev.irq = gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
        spi_register_board_info(&mc13783_spi_dev, 1);
 
        /* USB */
@@ -274,6 +273,10 @@ static void __init mx31lite_init(void)
                pr_warning("could not get LAN irq gpio\n");
        else {
                gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_SFS6));
+               smsc911x_resources[1].start =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SFS6));
+               smsc911x_resources[1].end =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SFS6));
                platform_device_register(&smsc911x_device);
        }
 }
index 016791f038b0a75e918077cecf4ecaff5452cabf..d46290b288eda7a6d6b0f26d5ed3f89c8f9195b6 100644 (file)
@@ -303,7 +303,7 @@ static struct imx_ssi_platform_data moboard_ssi_pdata = {
 static struct spi_board_info moboard_spi_board_info[] __initdata = {
        {
                .modalias = "mc13783",
-               .irq = IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
+               /* irq number is run-time assigned */
                .max_speed_hz = 300000,
                .bus_num = 1,
                .chip_select = 0,
@@ -473,10 +473,6 @@ static const struct gpio_led_platform_data mx31moboard_led_pdata __initconst = {
        .leds           = mx31moboard_leds,
 };
 
-static const struct ipu_platform_data mx3_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct platform_device *devices[] __initdata = {
        &mx31moboard_flash,
 };
@@ -494,7 +490,7 @@ static int __init mx31moboard_init_cam(void)
        int dma, ret = -ENOMEM;
        struct platform_device *pdev;
 
-       imx31_add_ipu_core(&mx3_ipu_data);
+       imx31_add_ipu_core();
 
        pdev = imx31_alloc_mx3_camera(&camera_pdata);
        if (IS_ERR(pdev))
@@ -544,7 +540,7 @@ static void __init mx31moboard_init(void)
        platform_add_devices(devices, ARRAY_SIZE(devices));
        gpio_led_register_device(-1, &mx31moboard_led_pdata);
 
-       imx31_add_imx2_wdt(NULL);
+       imx31_add_imx2_wdt();
 
        imx31_add_imx_uart0(&uart0_pdata);
        imx31_add_imx_uart4(&uart4_pdata);
@@ -557,6 +553,8 @@ static void __init mx31moboard_init(void)
 
        gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3), "pmic-irq");
        gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
+       moboard_spi_board_info[0].irq =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_3));
        spi_register_board_info(moboard_spi_board_info,
                ARRAY_SIZE(moboard_spi_board_info));
 
index 28aa19476de73dc47ea40eaec323e71e1623b7e7..504983c68aa8309bc8971ddbb18d8e35fb270505 100644 (file)
@@ -46,7 +46,6 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-mx35.h>
-#include <mach/irqs.h>
 #include <mach/3ds_debugboard.h>
 #include <video/platform_lcd.h>
 
@@ -80,10 +79,6 @@ static const struct fb_videomode fb_modedb[] = {
         },
 };
 
-static const struct ipu_platform_data mx3_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct mx3fb_platform_data mx3fb_pdata __initdata = {
        .name = "Ceramate-CLAA070VC01",
        .mode = fb_modedb,
@@ -136,8 +131,6 @@ static struct platform_device mx35_3ds_lcd = {
        .dev.platform_data = &mx35_3ds_lcd_data,
 };
 
-#define EXPIO_PARENT_INT       gpio_to_irq(IMX_GPIO_NR(1, 1))
-
 static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
@@ -297,10 +290,6 @@ err:
        return ret;
 }
 
-static const struct ipu_platform_data mx35_3ds_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct i2c_board_info mx35_3ds_i2c_camera = {
        I2C_BOARD_INFO("ov2640", 0x30),
 };
@@ -492,7 +481,7 @@ static struct i2c_board_info mx35_3ds_i2c_mc13892 = {
 
        I2C_BOARD_INFO("mc13892", 0x08),
        .platform_data = &mx35_3ds_mc13892_data,
-       .irq = IMX_GPIO_TO_IRQ(GPIO_PMIC_INT),
+       /* irq number is run-time assigned */
 };
 
 static void __init imx35_3ds_init_mc13892(void)
@@ -504,6 +493,7 @@ static void __init imx35_3ds_init_mc13892(void)
                return;
        }
 
+       mx35_3ds_i2c_mc13892.irq = gpio_to_irq(GPIO_PMIC_INT);
        i2c_register_board_info(0, &mx35_3ds_i2c_mc13892, 1);
 }
 
@@ -540,18 +530,18 @@ static const struct mxc_usbh_platform_data usb_host_pdata __initconst = {
        .portsc         = MXC_EHCI_MODE_SERIAL,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init mx35_3ds_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", mx35_3ds_otg_mode);
 
@@ -571,7 +561,8 @@ static void __init mx35_3ds_init(void)
        mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));
 
        imx35_add_fec(NULL);
-       imx35_add_imx2_wdt(NULL);
+       imx35_add_imx2_wdt();
+       imx35_add_mxc_rtc();
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
        imx35_add_imx_uart0(&uart_pdata);
@@ -587,7 +578,7 @@ static void __init mx35_3ds_init(void)
        imx35_add_mxc_nand(&mx35pdk_nand_board_info);
        imx35_add_sdhci_esdhc_imx(0, NULL);
 
-       if (mxc_expio_init(MX35_CS5_BASE_ADDR, EXPIO_PARENT_INT))
+       if (mxc_expio_init(MX35_CS5_BASE_ADDR, IMX_GPIO_NR(1, 1)))
                pr_warn("Init of the debugboard failed, all "
                                "devices on the debugboard are unusable.\n");
        imx35_add_imx_i2c0(&mx35_3ds_i2c0_data);
@@ -595,7 +586,7 @@ static void __init mx35_3ds_init(void)
        i2c_register_board_info(
                0, i2c_devices_3ds, ARRAY_SIZE(i2c_devices_3ds));
 
-       imx35_add_ipu_core(&mx35_3ds_ipu_data);
+       imx35_add_ipu_core();
        platform_device_register(&mx35_3ds_ov2640);
        imx35_3ds_init_camera();
 
index 3c5b163923f63e4b20ab311fee76a70bb431d666..9ee84a4af63931c915a1d297a22a68ccaf1e688b 100644 (file)
@@ -26,7 +26,6 @@
 
 #include "devices-imx51.h"
 
-#define EXPIO_PARENT_INT       gpio_to_irq(IMX_GPIO_NR(1, 6))
 #define MX51_3DS_ECSPI2_CS     (GPIO_PORTC + 28)
 
 static iomux_v3_cfg_t mx51_3ds_pads[] = {
@@ -148,13 +147,13 @@ static void __init mx51_3ds_init(void)
        spi_register_board_info(mx51_3ds_spi_nor_device,
                                ARRAY_SIZE(mx51_3ds_spi_nor_device));
 
-       if (mxc_expio_init(MX51_CS5_BASE_ADDR, EXPIO_PARENT_INT))
+       if (mxc_expio_init(MX51_CS5_BASE_ADDR, IMX_GPIO_NR(1, 6)))
                printk(KERN_WARNING "Init of the debugboard failed, all "
                                    "devices on the board are unusable.\n");
 
        imx51_add_sdhci_esdhc_imx(0, NULL);
        imx51_add_imx_keypad(&mx51_3ds_map_data);
-       imx51_add_imx2_wdt(0, NULL);
+       imx51_add_imx2_wdt(0);
 }
 
 static void __init mx51_3ds_timer_init(void)
index dde397014d4b709d2cd2026d8ea879676f3b35b8..7b31cbde8775409312da8d8b749c293c3ced850f 100644 (file)
@@ -307,18 +307,18 @@ static const struct mxc_usbh_platform_data usbh1_config __initconst = {
        .portsc = MXC_EHCI_MODE_ULPI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init babbage_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", babbage_otg_mode);
 
@@ -411,7 +411,7 @@ static void __init mx51_babbage_init(void)
        spi_register_board_info(mx51_babbage_spi_board_info,
                ARRAY_SIZE(mx51_babbage_spi_board_info));
        imx51_add_ecspi(0, &mx51_babbage_spi_pdata);
-       imx51_add_imx2_wdt(0, NULL);
+       imx51_add_imx2_wdt(0);
 }
 
 static void __init mx51_babbage_timer_init(void)
index 05641980dc5e7c86ede296ef01129be70fea653b..6c28e65f424d012ad4217793c8c04c31e4aacc14 100644 (file)
@@ -135,8 +135,7 @@ static struct resource ard_smsc911x_resources[] = {
                .flags = IORESOURCE_MEM,
        },
        {
-               .start =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
-               .end =  IMX_GPIO_TO_IRQ(ARD_ETHERNET_INT_B),
+               /* irq number is run-time assigned */
                .flags = IORESOURCE_IRQ,
        },
 };
@@ -240,10 +239,12 @@ static void __init mx53_ard_board_init(void)
        imx53_ard_common_init();
        mx53_ard_io_init();
        regulator_register_fixed(0, dummy_supplies, ARRAY_SIZE(dummy_supplies));
+       ard_smsc911x_resources[1].start = gpio_to_irq(ARD_ETHERNET_INT_B);
+       ard_smsc911x_resources[1].end = gpio_to_irq(ARD_ETHERNET_INT_B);
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
        imx53_add_sdhci_esdhc_imx(0, &mx53_ard_sd1_data);
-       imx53_add_imx2_wdt(0, NULL);
+       imx53_add_imx2_wdt(0);
        imx53_add_imx_i2c(1, &mx53_ard_i2c2_data);
        imx53_add_imx_i2c(2, &mx53_ard_i2c3_data);
        imx_add_gpio_keys(&ard_button_data);
@@ -266,5 +267,6 @@ MACHINE_START(MX53_ARD, "Freescale MX53 ARD Board")
        .handle_irq = imx53_handle_irq,
        .timer = &mx53_ard_timer,
        .init_machine = mx53_ard_board_init,
+       .init_late      = imx53_init_late,
        .restart        = mxc_restart,
 MACHINE_END
index 5a72188b9cdb6e3ba8479a7b473c04a77d92080d..09fe2197b4919e51cc5016e4f44a4049342816b3 100644 (file)
@@ -154,7 +154,7 @@ static void __init mx53_evk_board_init(void)
        spi_register_board_info(mx53_evk_spi_board_info,
                ARRAY_SIZE(mx53_evk_spi_board_info));
        imx53_add_ecspi(0, &mx53_evk_spi_data);
-       imx53_add_imx2_wdt(0, NULL);
+       imx53_add_imx2_wdt(0);
        gpio_led_register_device(-1, &mx53evk_leds_data);
 }
 
@@ -174,5 +174,6 @@ MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
        .handle_irq = imx53_handle_irq,
        .timer = &mx53_evk_timer,
        .init_machine = mx53_evk_board_init,
+       .init_late      = imx53_init_late,
        .restart        = mxc_restart,
 MACHINE_END
index 37f67cac15a4daad2d803266503f6b2dfa81d4d0..8abe23c1d3c893fc191110717fd8131eea10ab41 100644 (file)
@@ -283,7 +283,7 @@ static void __init mx53_loco_board_init(void)
        imx53_add_imx_uart(0, NULL);
        mx53_loco_fec_reset();
        imx53_add_fec(&mx53_loco_fec_data);
-       imx53_add_imx2_wdt(0, NULL);
+       imx53_add_imx2_wdt(0);
 
        ret = gpio_request_one(LOCO_ACCEL_EN, GPIOF_OUT_INIT_HIGH, "accel_en");
        if (ret)
@@ -316,5 +316,6 @@ MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
        .handle_irq = imx53_handle_irq,
        .timer = &mx53_loco_timer,
        .init_machine = mx53_loco_board_init,
+       .init_late      = imx53_init_late,
        .restart        = mxc_restart,
 MACHINE_END
index 8e972c5c3e138bfebe6244b3da450937d1ede945..b15d6a6d3b6873c77e13283ba9103f4da3e62091 100644 (file)
@@ -138,7 +138,7 @@ static void __init mx53_smd_board_init(void)
        mx53_smd_init_uart();
        mx53_smd_fec_reset();
        imx53_add_fec(&mx53_smd_fec_data);
-       imx53_add_imx2_wdt(0, NULL);
+       imx53_add_imx2_wdt(0);
        imx53_add_imx_i2c(0, &mx53_smd_i2c_data);
        imx53_add_sdhci_esdhc_imx(0, NULL);
        imx53_add_sdhci_esdhc_imx(1, NULL);
@@ -163,5 +163,6 @@ MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
        .handle_irq = imx53_handle_irq,
        .timer = &mx53_smd_timer,
        .init_machine = mx53_smd_board_init,
+       .init_late      = imx53_init_late,
        .restart        = mxc_restart,
 MACHINE_END
index 8b3d3f07d894ab72f30d5d21de495c991a2ecca2..0bf6d30aa32d71de42f0068c6c7663a2ffb4ac01 100644 (file)
@@ -213,13 +213,13 @@ static const struct imx_fb_platform_data mxt_td60_fb_data __initconst = {
 static int mxt_td60_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
                                void *data)
 {
-       return request_irq(IRQ_GPIOF(8), detect_irq, IRQF_TRIGGER_FALLING,
-                               "sdhc1-card-detect", data);
+       return request_irq(gpio_to_irq(IMX_GPIO_NR(6, 8)), detect_irq,
+                          IRQF_TRIGGER_FALLING, "sdhc1-card-detect", data);
 }
 
 static void mxt_td60_sdhc1_exit(struct device *dev, void *data)
 {
-       free_irq(IRQ_GPIOF(8), data);
+       free_irq(gpio_to_irq(IMX_GPIO_NR(6, 8)), data);
 }
 
 static const struct imxmmc_platform_data sdhc1_pdata __initconst = {
index 541152e450c420bbf2cd65ca6061bee935957191..de8516b7d69f36a77c51f44dcc224077f05d021e 100644 (file)
@@ -36,7 +36,6 @@
 #include <mach/hardware.h>
 #include <mach/iomux-mx27.h>
 #include <asm/mach/time.h>
-#include <mach/irqs.h>
 #include <mach/ulpi.h>
 
 #include "devices-imx27.h"
@@ -245,7 +244,7 @@ static int pca100_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
 {
        int ret;
 
-       ret = request_irq(IRQ_GPIOC(29), detect_irq,
+       ret = request_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), detect_irq,
                          IRQF_DISABLED | IRQF_TRIGGER_FALLING,
                          "imx-mmc-detect", data);
        if (ret)
@@ -257,7 +256,7 @@ static int pca100_sdhc2_init(struct device *dev, irq_handler_t detect_irq,
 
 static void pca100_sdhc2_exit(struct device *dev, void *data)
 {
-       free_irq(IRQ_GPIOC(29), data);
+       free_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), data);
 }
 
 static const struct imxmmc_platform_data sdhc_pdata __initconst = {
@@ -298,18 +297,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .phy_mode       = FSL_USB2_PHY_ULPI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init pca100_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", pca100_otg_mode);
 
@@ -408,8 +407,8 @@ static void __init pca100_init(void)
        imx27_add_imx_fb(&pca100_fb_data);
 
        imx27_add_fec(NULL);
-       imx27_add_imx2_wdt(NULL);
-       imx27_add_mxc_w1(NULL);
+       imx27_add_imx2_wdt();
+       imx27_add_mxc_w1();
 }
 
 static void __init pca100_timer_init(void)
index 0a40004154f234e4afba7f20477a902509bb6637..e3c45130fb3cc8bad1929bdcd68b6227b2cc298f 100644 (file)
@@ -225,8 +225,7 @@ static struct resource smsc911x_resources[] = {
                .end            = MX31_CS1_BASE_ADDR + 0x300 + SZ_64K - 1,
                .flags          = IORESOURCE_MEM,
        }, {
-               .start          = IOMUX_TO_IRQ(MX31_PIN_GPIO3_1),
-               .end            = IOMUX_TO_IRQ(MX31_PIN_GPIO3_1),
+               /* irq number is run-time assigned */
                .flags          = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
        },
 };
@@ -371,7 +370,7 @@ static int pcm970_sdhc1_init(struct device *dev, irq_handler_t detect_irq,
        gpio_direction_input(SDHC1_GPIO_WP);
 #endif
 
-       ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_SCK6), detect_irq,
+       ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SCK6)), detect_irq,
                        IRQF_DISABLED | IRQF_TRIGGER_FALLING,
                                "sdhc-detect", data);
        if (ret)
@@ -391,7 +390,7 @@ err_gpio_free:
 
 static void pcm970_sdhc1_exit(struct device *dev, void *data)
 {
-       free_irq(IOMUX_TO_IRQ(MX31_PIN_SCK6), data);
+       free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_SCK6)), data);
        gpio_free(SDHC1_GPIO_DET);
        gpio_free(SDHC1_GPIO_WP);
 }
@@ -442,10 +441,6 @@ static struct platform_device *devices[] __initdata = {
        &pcm037_mt9v022,
 };
 
-static const struct ipu_platform_data mx3_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static const struct fb_videomode fb_modedb[] = {
        {
                /* 240x320 @ 60 Hz Sharp */
@@ -511,8 +506,7 @@ static struct resource pcm970_sja1000_resources[] = {
                .end     = MX31_CS5_BASE_ADDR + 0x100 - 1,
                .flags   = IORESOURCE_MEM,
        }, {
-               .start   = IOMUX_TO_IRQ(IOMUX_PIN(48, 105)),
-               .end     = IOMUX_TO_IRQ(IOMUX_PIN(48, 105)),
+               /* irq number is run-time assigned */
                .flags   = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
        },
 };
@@ -557,18 +551,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .phy_mode       = FSL_USB2_PHY_ULPI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init pcm037_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", pcm037_otg_mode);
 
@@ -619,13 +613,13 @@ static void __init pcm037_init(void)
 
        platform_add_devices(devices, ARRAY_SIZE(devices));
 
-       imx31_add_imx2_wdt(NULL);
+       imx31_add_imx2_wdt();
        imx31_add_imx_uart0(&uart_pdata);
        /* XXX: should't this have .flags = 0 (i.e. no RTSCTS) on PCM037_EET? */
        imx31_add_imx_uart1(&uart_pdata);
        imx31_add_imx_uart2(&uart_pdata);
 
-       imx31_add_mxc_w1(NULL);
+       imx31_add_mxc_w1();
 
        /* LAN9217 IRQ pin */
        ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1), "lan9217-irq");
@@ -633,6 +627,10 @@ static void __init pcm037_init(void)
                pr_warning("could not get LAN irq gpio\n");
        else {
                gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1));
+               smsc911x_resources[1].start =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1));
+               smsc911x_resources[1].end =
+                       gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO3_1));
                platform_device_register(&pcm037_eth);
        }
 
@@ -646,7 +644,7 @@ static void __init pcm037_init(void)
 
        imx31_add_mxc_nand(&pcm037_nand_board_info);
        imx31_add_mxc_mmc(0, &sdhc_pdata);
-       imx31_add_ipu_core(&mx3_ipu_data);
+       imx31_add_ipu_core();
        imx31_add_mx3_sdc_fb(&mx3fb_pdata);
 
        /* CSI */
@@ -659,6 +657,10 @@ static void __init pcm037_init(void)
 
        pcm037_init_camera();
 
+       pcm970_sja1000_resources[1].start =
+                       gpio_to_irq(IOMUX_TO_GPIO(IOMUX_PIN(48, 105)));
+       pcm970_sja1000_resources[1].end =
+                       gpio_to_irq(IOMUX_TO_GPIO(IOMUX_PIN(48, 105)));
        platform_device_register(&pcm970_sja1000);
 
        if (otg_mode_host) {
index 2f3debe2a11335f60de6f2913cb4ba9452127567..95f49d936fd3bd442e6b806ac5945d62050a3ba8 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/mfd/mc13783.h>
 #include <linux/spi/spi.h>
 #include <linux/irq.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -274,7 +275,7 @@ static struct mc13xxx_platform_data pcm038_pmic = {
 static struct spi_board_info pcm038_spi_board_info[] __initdata = {
        {
                .modalias = "mc13783",
-               .irq = IRQ_GPIOB(23),
+               /* irq number is run-time assigned */
                .max_speed_hz = 300000,
                .bus_num = 0,
                .chip_select = 0,
@@ -325,6 +326,7 @@ static void __init pcm038_init(void)
        mxc_gpio_mode(GPIO_PORTB | 23 | GPIO_GPIO | GPIO_IN);
 
        imx27_add_spi_imx0(&pcm038_spi0_data);
+       pcm038_spi_board_info[0].irq = gpio_to_irq(IMX_GPIO_NR(2, 23));
        spi_register_board_info(pcm038_spi_board_info,
                                ARRAY_SIZE(pcm038_spi_board_info));
 
@@ -332,8 +334,8 @@ static void __init pcm038_init(void)
 
        imx27_add_fec(NULL);
        platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
-       imx27_add_imx2_wdt(NULL);
-       imx27_add_mxc_w1(NULL);
+       imx27_add_imx2_wdt();
+       imx27_add_mxc_w1();
 
 #ifdef CONFIG_MACH_PCM970_BASEBOARD
        pcm970_baseboard_init();
index 73585f55cca0c6b804351064511a69b678fc1a63..e4bd4387e344e653394a3b203ca91cbb7ec5cda0 100644 (file)
@@ -76,10 +76,6 @@ static const struct fb_videomode fb_modedb[] = {
        },
 };
 
-static const struct ipu_platform_data mx3_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct mx3fb_platform_data mx3fb_pdata __initdata = {
        .name           = "Sharp-LQ035Q7",
        .mode           = fb_modedb,
@@ -330,18 +326,18 @@ static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
        .phy_mode       = FSL_USB2_PHY_UTMI,
 };
 
-static int otg_mode_host;
+static bool otg_mode_host __initdata;
 
 static int __init pcm043_otg_mode(char *options)
 {
        if (!strcmp(options, "host"))
-               otg_mode_host = 1;
+               otg_mode_host = true;
        else if (!strcmp(options, "device"))
-               otg_mode_host = 0;
+               otg_mode_host = false;
        else
                pr_info("otg_mode neither \"host\" nor \"device\". "
                        "Defaulting to device\n");
-       return 0;
+       return 1;
 }
 __setup("otg_mode=", pcm043_otg_mode);
 
@@ -363,7 +359,7 @@ static void __init pcm043_init(void)
 
        imx35_add_fec(NULL);
        platform_add_devices(devices, ARRAY_SIZE(devices));
-       imx35_add_imx2_wdt(NULL);
+       imx35_add_imx2_wdt();
 
        imx35_add_imx_uart0(&uart_pdata);
        imx35_add_mxc_nand(&pcm037_nand_board_info);
@@ -376,7 +372,7 @@ static void __init pcm043_init(void)
 
        imx35_add_imx_i2c0(&pcm043_i2c0_data);
 
-       imx35_add_ipu_core(&mx3_ipu_data);
+       imx35_add_ipu_core();
        imx35_add_mx3_sdc_fb(&mx3fb_pdata);
 
        if (otg_mode_host) {
index 260621055b6be1edfe9ef4ce8eca2f391d3edb86..fb25fbd3122633baae6bc964cbfac7779acd014f 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/gpio.h>
 
 #include <mach/hardware.h>
-#include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
@@ -51,8 +50,6 @@
        (QONG_FPGA_BASEADDR + QONG_DNET_ID * QONG_FPGA_PERIPH_SIZE)
 #define QONG_DNET_SIZE         0x00001000
 
-#define QONG_FPGA_IRQ          IOMUX_TO_IRQ(MX31_PIN_DTR_DCE1)
-
 static const struct imxuart_platform_data uart_pdata __initconst = {
        .flags = IMXUART_HAVE_RTSCTS,
 };
@@ -78,8 +75,7 @@ static struct resource dnet_resources[] = {
                .end    = QONG_DNET_BASEADDR + QONG_DNET_SIZE - 1,
                .flags  = IORESOURCE_MEM,
        }, {
-               .start  = QONG_FPGA_IRQ,
-               .end    = QONG_FPGA_IRQ,
+               /* irq number is run-time assigned */
                .flags  = IORESOURCE_IRQ,
        },
 };
@@ -95,6 +91,10 @@ static int __init qong_init_dnet(void)
 {
        int ret;
 
+       dnet_resources[1].start =
+               gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1));
+       dnet_resources[1].end =
+               gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1));
        ret = platform_device_register(&dnet_device);
        return ret;
 }
@@ -252,7 +252,7 @@ static void __init qong_init(void)
        mxc_init_imx_uart();
        qong_init_nor_mtd();
        qong_init_fpga();
-       imx31_add_imx2_wdt(NULL);
+       imx31_add_imx2_wdt();
 }
 
 static void __init qong_timer_init(void)
index cb9ceae2f648dbd8f6a838c9c42ddb48b76dcea2..67ff38e9a3ca3434e9b16b4daba6f908eec77715 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/mtd/physmap.h>
 #include <linux/interrupt.h>
 #include <linux/dm9000.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -21,7 +22,6 @@
 
 #include <mach/common.h>
 #include <mach/hardware.h>
-#include <mach/irqs.h>
 #include <mach/iomux-mx1.h>
 
 #include "devices-imx1.h"
@@ -78,8 +78,7 @@ static struct resource dm9000x_resources[] = {
                .end    = MX1_CS5_PHYS + 5,
                .flags  = IORESOURCE_MEM,       /* data access */
        }, {
-               .start  = IRQ_GPIOC(3),
-               .end    = IRQ_GPIOC(3),
+               /* irq number is run-time assigned */
                .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL,
        },
 };
@@ -123,6 +122,8 @@ static void __init scb9328_init(void)
        imx1_add_imx_uart0(&uart_pdata);
 
        printk(KERN_INFO"Scb9328: Adding devices\n");
+       dm9000x_resources[2].start = gpio_to_irq(IMX_GPIO_NR(3, 3));
+       dm9000x_resources[2].end = gpio_to_irq(IMX_GPIO_NR(3, 3));
        platform_add_devices(devices, ARRAY_SIZE(devices));
 }
 
index add8c69c6c1ade1e8c020d03166d25365cf7e532..39eb7960e2a425a7ff604427b23e337fb697caed 100644 (file)
@@ -31,7 +31,6 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-mx35.h>
-#include <mach/irqs.h>
 
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
@@ -87,10 +86,6 @@ static const struct fb_videomode fb_modedb[] = {
        }
 };
 
-static const struct ipu_platform_data mx3_ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static struct mx3fb_platform_data mx3fb_pdata __initdata = {
        .name           = "PT0708048",
        .mode           = fb_modedb,
@@ -162,7 +157,7 @@ static struct i2c_board_info vpr200_i2c_devices[] = {
        }, {
                I2C_BOARD_INFO("mc13892", 0x08),
                .platform_data = &vpr200_pmic,
-               .irq = IMX_GPIO_TO_IRQ(GPIO_PMIC_INT),
+               /* irq number is run-time assigned */
        }
 };
 
@@ -272,7 +267,7 @@ static void __init vpr200_board_init(void)
        mxc_iomux_v3_setup_multiple_pads(vpr200_pads, ARRAY_SIZE(vpr200_pads));
 
        imx35_add_fec(NULL);
-       imx35_add_imx2_wdt(NULL);
+       imx35_add_imx2_wdt();
        imx_add_gpio_keys(&vpr200_gpio_keys_data);
 
        platform_add_devices(devices, ARRAY_SIZE(devices));
@@ -290,7 +285,7 @@ static void __init vpr200_board_init(void)
        imx35_add_imx_uart0(NULL);
        imx35_add_imx_uart2(NULL);
 
-       imx35_add_ipu_core(&mx3_ipu_data);
+       imx35_add_ipu_core();
        imx35_add_mx3_sdc_fb(&mx3fb_pdata);
 
        imx35_add_fsl_usb2_udc(&otg_device_pdata);
@@ -299,6 +294,7 @@ static void __init vpr200_board_init(void)
        imx35_add_mxc_nand(&vpr200_nand_board_info);
        imx35_add_sdhci_esdhc_imx(0, NULL);
 
+       vpr200_i2c_devices[1].irq = gpio_to_irq(GPIO_PMIC_INT);
        i2c_register_board_info(0, vpr200_i2c_devices,
                        ARRAY_SIZE(vpr200_i2c_devices));
 
index fcafd3dafb8cbef72a27a3b6389beded233ba396..6d60d51868bc83932667cd7488a364e0b3f9efb6 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <mach/common.h>
 #include <mach/hardware.h>
-#include <mach/irqs.h>
 #include <mach/iomux-v1.h>
 
 static struct map_desc imx_io_desc[] __initdata = {
index 5f43905e5290571a3aec938033213b24d8442571..d056dad0940dd3688d785fb721d7ed13939afbe0 100644 (file)
@@ -26,7 +26,6 @@
 #include <mach/devices-common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
-#include <mach/irqs.h>
 #include <mach/iomux-v1.h>
 
 /* MX21 memory map definition */
index 6ff37140a4f86c54445133ce187ef675fd2c4b92..388928fdb11a0008ee85dfd3ad598a4668ac48c1 100644 (file)
@@ -29,7 +29,6 @@
 #include <mach/hardware.h>
 #include <mach/mx25.h>
 #include <mach/iomux-v3.h>
-#include <mach/irqs.h>
 
 /*
  * This table defines static virtual address mappings for I/O regions.
index 25662558e018b27af567b2c79c3ebd94fe7e15aa..e7e24afc45edb6f83a7fbc9de56a13568a6d348a 100644 (file)
@@ -26,7 +26,6 @@
 #include <mach/devices-common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
-#include <mach/irqs.h>
 #include <mach/iomux-v1.h>
 
 /* MX27 memory map definition */
index a8983b9778d1b7873dd850076718eabd690ca6f1..fe96105109b323844dc4bc688d9df9d4f0bf2047 100644 (file)
@@ -30,7 +30,6 @@
 #include <mach/devices-common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-v3.h>
-#include <mach/irqs.h>
 
 #include "crmregs-imx3.h"
 
index 1d003053d5621bd45341030b9f58db08f78990ac..f19d604e1b2aea6e89ab7c86fc6c6917e57ce48a 100644 (file)
@@ -16,7 +16,6 @@
 #include <linux/clk.h>
 #include <linux/pinctrl/machine.h>
 
-#include <asm/system_misc.h>
 #include <asm/mach/map.h>
 
 #include <mach/hardware.h>
 #include <mach/devices-common.h>
 #include <mach/iomux-v3.h>
 
-static struct clk *gpc_dvfs_clk;
-
-static void imx5_idle(void)
-{
-       /* gpc clock is needed for SRPG */
-       if (gpc_dvfs_clk == NULL) {
-               gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
-               if (IS_ERR(gpc_dvfs_clk))
-                       return;
-               clk_prepare(gpc_dvfs_clk);
-       }
-       clk_enable(gpc_dvfs_clk);
-       mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
-       if (!tzic_enable_wake())
-               cpu_do_idle();
-       clk_disable(gpc_dvfs_clk);
-}
-
 /*
  * Define the MX50 memory map.
  */
@@ -105,7 +86,6 @@ void __init imx51_init_early(void)
        mxc_set_cpu_type(MXC_CPU_MX51);
        mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
        mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
-       arm_pm_idle = imx5_idle;
 }
 
 void __init imx53_init_early(void)
@@ -243,4 +223,10 @@ void __init imx53_soc_init(void)
 void __init imx51_init_late(void)
 {
        mx51_neon_fixup();
+       imx51_pm_init();
+}
+
+void __init imx53_init_late(void)
+{
+       imx53_pm_init();
 }
index 7d26f766a4ee8988c919bec7269c3366ff8185bd..29e890f92055ef697f72f0b32b3fb7009a9a1c68 100644 (file)
@@ -130,7 +130,8 @@ static int mxc_mmc1_init(struct device *dev,
        gpio_direction_input(gpio_det);
        gpio_direction_input(gpio_wp);
 
-       ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO1_1), detect_irq,
+       ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)),
+                         detect_irq,
                          IRQF_DISABLED | IRQF_TRIGGER_FALLING,
                          "MMC detect", data);
        if (ret)
@@ -151,7 +152,7 @@ static void mxc_mmc1_exit(struct device *dev, void *data)
 {
        gpio_free(gpio_det);
        gpio_free(gpio_wp);
-       free_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO1_1), data);
+       free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)), data);
 }
 
 static const struct imxmmc_platform_data mmc_pdata __initconst = {
@@ -161,10 +162,6 @@ static const struct imxmmc_platform_data mmc_pdata __initconst = {
 };
 
 /* Framebuffer support */
-static const struct ipu_platform_data ipu_data __initconst = {
-       .irq_base = MXC_IPU_IRQ_START,
-};
-
 static const struct fb_videomode fb_modedb = {
        /* 640x480 TFT panel (IPS-056T) */
        .name           = "CRT-VGA",
@@ -198,7 +195,7 @@ static void __init mx31lilly_init_fb(void)
                return;
        }
 
-       imx31_add_ipu_core(&ipu_data);
+       imx31_add_ipu_core();
        imx31_add_mx3_sdc_fb(&fb_pdata);
        gpio_direction_output(LCD_VCC_EN_GPIO, 1);
 }
index bf0fb87946ba40fbd1a0ee5222572034177ccc68..83d17d9e0bc8677fd62ef31949ef55c0b64e72e4 100644 (file)
@@ -116,7 +116,8 @@ static int mxc_mmc1_init(struct device *dev,
        gpio_direction_input(gpio_det);
        gpio_direction_input(gpio_wp);
 
-       ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_DCD_DCE1), detect_irq,
+       ret = request_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1)),
+                         detect_irq,
                          IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
                          "MMC detect", data);
        if (ret)
@@ -137,7 +138,7 @@ static void mxc_mmc1_exit(struct device *dev, void *data)
 {
        gpio_free(gpio_det);
        gpio_free(gpio_wp);
-       free_irq(IOMUX_TO_IRQ(MX31_PIN_DCD_DCE1), data);
+       free_irq(gpio_to_irq(IOMUX_TO_GPIO(MX31_PIN_DCD_DCE1)), data);
 }
 
 static const struct imxmmc_platform_data mmc_pdata __initconst = {
@@ -191,6 +192,6 @@ void __init mx31lite_db_init(void)
        imx31_add_mxc_mmc(0, &mmc_pdata);
        imx31_add_spi_imx0(&spi0_pdata);
        gpio_led_register_device(-1, &litekit_led_platform_data);
-       imx31_add_imx2_wdt(NULL);
-       imx31_add_mxc_rtc(NULL);
+       imx31_add_imx2_wdt();
+       imx31_add_mxc_rtc();
 }
index ec6ca91b299b629039ff3ac13ed7942494b3b830..ee870c49bc636c5f95f3aa01bd6cc1602fb6d1c5 100644 (file)
@@ -587,7 +587,7 @@ static struct spi_board_info mx51_efika_spi_board_info[] __initdata = {
                .bus_num = 0,
                .chip_select = 0,
                .platform_data = &mx51_efika_mc13892_data,
-               .irq = IMX_GPIO_TO_IRQ(EFIKAMX_PMIC),
+               /* irq number is run-time assigned */
        },
 };
 
@@ -620,6 +620,7 @@ void __init efika_board_common_init(void)
 
        gpio_request(EFIKAMX_PMIC, "pmic irq");
        gpio_direction_input(EFIKAMX_PMIC);
+       mx51_efika_spi_board_info[1].irq = gpio_to_irq(EFIKAMX_PMIC);
        spi_register_board_info(mx51_efika_spi_board_info,
                ARRAY_SIZE(mx51_efika_spi_board_info));
        imx51_add_ecspi(0, &mx51_efika_spi_pdata);
index 99afbc3f43a3f539ea858227e844e02cf77bc3c9..9917e2ff51da9bdd6cf74823044dfcd985faba02 100644 (file)
@@ -95,14 +95,14 @@ static int pcm970_sdhc2_init(struct device *dev, irq_handler_t detect_irq, void
 {
        int ret;
 
-       ret = request_irq(IRQ_GPIOC(29), detect_irq, IRQF_TRIGGER_FALLING,
-                               "imx-mmc-detect", data);
+       ret = request_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), detect_irq,
+                         IRQF_TRIGGER_FALLING, "imx-mmc-detect", data);
        if (ret)
                return ret;
 
        ret = gpio_request(GPIO_PORTC + 28, "imx-mmc-ro");
        if (ret) {
-               free_irq(IRQ_GPIOC(29), data);
+               free_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), data);
                return ret;
        }
 
@@ -113,7 +113,7 @@ static int pcm970_sdhc2_init(struct device *dev, irq_handler_t detect_irq, void
 
 static void pcm970_sdhc2_exit(struct device *dev, void *data)
 {
-       free_irq(IRQ_GPIOC(29), data);
+       free_irq(gpio_to_irq(IMX_GPIO_NR(3, 29)), data);
        gpio_free(GPIO_PORTC + 28);
 }
 
@@ -192,8 +192,7 @@ static struct resource pcm970_sja1000_resources[] = {
                .end     = MX27_CS4_BASE_ADDR + 0x100 - 1,
                .flags   = IORESOURCE_MEM,
        }, {
-               .start   = IRQ_GPIOE(19),
-               .end     = IRQ_GPIOE(19),
+               /* irq number is run-time assigned */
                .flags   = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE,
        },
 };
@@ -227,5 +226,7 @@ void __init pcm970_baseboard_init(void)
        imx27_add_imx_fb(&pcm038_fb_data);
        mxc_gpio_mode(GPIO_PORTC | 28 | GPIO_GPIO | GPIO_IN);
        imx27_add_mxc_mmc(1, &sdhc_pdata);
+       pcm970_sja1000_resources[1].start = gpio_to_irq(IMX_GPIO_NR(5, 19));
+       pcm970_sja1000_resources[1].end = gpio_to_irq(IMX_GPIO_NR(5, 19));
        platform_device_register(&pcm970_sja1000);
 }
index e26a9cb05ed811098e25244e58349b094ba0dc7b..19621ed1ffa5852900e2ab285e3ea1c2b4c1c357 100644 (file)
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/err.h>
+#include <linux/export.h>
 #include <asm/cacheflush.h>
+#include <asm/system_misc.h>
 #include <asm/tlbflush.h>
 #include <mach/common.h>
+#include <mach/cpuidle.h>
 #include <mach/hardware.h>
 #include "crm-regs-imx5.h"
 
-static struct clk *gpc_dvfs_clk;
+/*
+ * The WAIT_UNCLOCKED_POWER_OFF state only requires <= 500ns to exit.
+ * This is also the lowest power state possible without affecting
+ * non-cpu parts of the system.  For these reasons, imx5 should default
+ * to always using this state for cpu idling.  The PM_SUSPEND_STANDBY also
+ * uses this state and needs to take no action when registers remain confgiured
+ * for this state.
+ */
+#define IMX5_DEFAULT_CPU_IDLE_STATE WAIT_UNCLOCKED_POWER_OFF
 
 /*
  * set cpu low power mode before WFI instruction. This function is called
  * mx5 because it can be used for mx50, mx51, and mx53.
  */
-void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
+static void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
 {
        u32 plat_lpc, arm_srpgcr, ccm_clpcr;
        u32 empgc0, empgc1;
@@ -87,11 +98,6 @@ void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
        }
 }
 
-static int mx5_suspend_prepare(void)
-{
-       return clk_prepare_enable(gpc_dvfs_clk);
-}
-
 static int mx5_suspend_enter(suspend_state_t state)
 {
        switch (state) {
@@ -99,7 +105,7 @@ static int mx5_suspend_enter(suspend_state_t state)
                mx5_cpu_lp_set(STOP_POWER_OFF);
                break;
        case PM_SUSPEND_STANDBY:
-               mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+               /* DEFAULT_IDLE_STATE already configured */
                break;
        default:
                return -EINVAL;
@@ -114,12 +120,10 @@ static int mx5_suspend_enter(suspend_state_t state)
                __raw_writel(0, MXC_SRPG_EMPGC1_SRPGCR);
        }
        cpu_do_idle();
-       return 0;
-}
 
-static void mx5_suspend_finish(void)
-{
-       clk_disable_unprepare(gpc_dvfs_clk);
+       /* return registers to default idle state */
+       mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE);
+       return 0;
 }
 
 static int mx5_pm_valid(suspend_state_t state)
@@ -129,25 +133,80 @@ static int mx5_pm_valid(suspend_state_t state)
 
 static const struct platform_suspend_ops mx5_suspend_ops = {
        .valid = mx5_pm_valid,
-       .prepare = mx5_suspend_prepare,
        .enter = mx5_suspend_enter,
-       .finish = mx5_suspend_finish,
 };
 
-static int __init mx5_pm_init(void)
+static inline int imx5_cpu_do_idle(void)
+{
+       int ret = tzic_enable_wake();
+
+       if (likely(!ret))
+               cpu_do_idle();
+
+       return ret;
+}
+
+static void imx5_pm_idle(void)
+{
+       imx5_cpu_do_idle();
+}
+
+static int imx5_cpuidle_enter(struct cpuidle_device *dev,
+                               struct cpuidle_driver *drv, int idx)
+{
+       int ret;
+
+       ret = imx5_cpu_do_idle();
+       if (ret < 0)
+               return ret;
+
+       return idx;
+}
+
+static struct cpuidle_driver imx5_cpuidle_driver = {
+       .name                   = "imx5_cpuidle",
+       .owner                  = THIS_MODULE,
+       .en_core_tk_irqen       = 1,
+       .states[0]      = {
+               .enter                  = imx5_cpuidle_enter,
+               .exit_latency           = 2,
+               .target_residency       = 1,
+               .flags                  = CPUIDLE_FLAG_TIME_VALID,
+               .name                   = "IMX5 SRPG",
+               .desc                   = "CPU state retained,powered off",
+       },
+       .state_count            = 1,
+};
+
+static int __init imx5_pm_common_init(void)
 {
-       if (!cpu_is_mx51() && !cpu_is_mx53())
-               return 0;
+       int ret;
+       struct clk *gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
 
-       if (gpc_dvfs_clk == NULL)
-               gpc_dvfs_clk = clk_get(NULL, "gpc_dvfs");
+       if (IS_ERR(gpc_dvfs_clk))
+               return PTR_ERR(gpc_dvfs_clk);
 
-       if (!IS_ERR(gpc_dvfs_clk)) {
-               if (cpu_is_mx51())
-                       suspend_set_ops(&mx5_suspend_ops);
-       } else
-               return -EPERM;
+       ret = clk_prepare_enable(gpc_dvfs_clk);
+       if (ret)
+               return ret;
 
+       arm_pm_idle = imx5_pm_idle;
+
+       /* Set the registers to the default cpu idle state. */
+       mx5_cpu_lp_set(IMX5_DEFAULT_CPU_IDLE_STATE);
+
+       imx_cpuidle_init(&imx5_cpuidle_driver);
        return 0;
 }
-device_initcall(mx5_pm_init);
+
+void __init imx51_pm_init(void)
+{
+       int ret = imx5_pm_common_init();
+       if (!ret)
+               suspend_set_ops(&mx5_suspend_ops);
+}
+
+void __init imx53_pm_init(void)
+{
+       imx5_pm_common_init();
+}
diff --git a/arch/arm/mach-lpc32xx/Kconfig b/arch/arm/mach-lpc32xx/Kconfig
deleted file mode 100644 (file)
index e0b3eee..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-if ARCH_LPC32XX
-
-menu "Individual UART enable selections"
-
-config ARCH_LPC32XX_UART3_SELECT
-       bool "Add support for standard UART3"
-       help
-        Adds support for standard UART 3 when the 8250 serial support
-        is enabled.
-
-config ARCH_LPC32XX_UART4_SELECT
-       bool "Add support for standard UART4"
-       help
-        Adds support for standard UART 4 when the 8250 serial support
-        is enabled.
-
-config ARCH_LPC32XX_UART5_SELECT
-       bool "Add support for standard UART5"
-       default y
-       help
-        Adds support for standard UART 5 when the 8250 serial support
-        is enabled.
-
-config ARCH_LPC32XX_UART6_SELECT
-       bool "Add support for standard UART6"
-       help
-        Adds support for standard UART 6 when the 8250 serial support
-        is enabled.
-
-endmenu
-
-endif
index 2cfe0ee635c55ba844e93aedb64a477d2572d25a..697323b5f92d4033d3a48bfcca542b21428f12be 100644 (file)
@@ -2,3 +2,4 @@
 params_phys-y  := 0x80000100
 initrd_phys-y  := 0x82000000
 
+dtb-$(CONFIG_ARCH_LPC32XX) += ea3250.dtb phy3250.dtb
index f6a3ffec1f4bbaa28eb742a1e47582a6dcdbe802..f48c2e961b84d0abe335167882455c928c4340f7 100644 (file)
@@ -607,6 +607,19 @@ static struct clk clk_dma = {
        .get_rate       = local_return_parent_rate,
 };
 
+static struct clk clk_pwm = {
+       .parent         = &clk_pclk,
+       .enable         = local_onoff_enable,
+       .enable_reg     = LPC32XX_CLKPWR_PWM_CLK_CTRL,
+       .enable_mask    = LPC32XX_CLKPWR_PWMCLK_PWM1CLK_EN |
+                         LPC32XX_CLKPWR_PWMCLK_PWM1SEL_PCLK |
+                         LPC32XX_CLKPWR_PWMCLK_PWM1_DIV(1) |
+                         LPC32XX_CLKPWR_PWMCLK_PWM2CLK_EN |
+                         LPC32XX_CLKPWR_PWMCLK_PWM2SEL_PCLK |
+                         LPC32XX_CLKPWR_PWMCLK_PWM2_DIV(1),
+       .get_rate       = local_return_parent_rate,
+};
+
 static struct clk clk_uart3 = {
        .parent         = &clk_pclk,
        .enable         = local_onoff_enable,
@@ -691,10 +704,21 @@ static struct clk clk_nand = {
        .parent         = &clk_hclk,
        .enable         = local_onoff_enable,
        .enable_reg     = LPC32XX_CLKPWR_NAND_CLK_CTRL,
-       .enable_mask    = LPC32XX_CLKPWR_NANDCLK_SLCCLK_EN,
+       .enable_mask    = LPC32XX_CLKPWR_NANDCLK_SLCCLK_EN |
+                         LPC32XX_CLKPWR_NANDCLK_SEL_SLC,
        .get_rate       = local_return_parent_rate,
 };
 
+static struct clk clk_nand_mlc = {
+       .parent         = &clk_hclk,
+       .enable         = local_onoff_enable,
+       .enable_reg     = LPC32XX_CLKPWR_NAND_CLK_CTRL,
+       .enable_mask    = LPC32XX_CLKPWR_NANDCLK_MLCCLK_EN |
+                         LPC32XX_CLKPWR_NANDCLK_DMA_INT |
+                         LPC32XX_CLKPWR_NANDCLK_INTSEL_MLC,
+       .get_rate       = local_return_parent_rate,
+};
+
 static struct clk clk_i2s0 = {
        .parent         = &clk_hclk,
        .enable         = local_onoff_enable,
@@ -707,7 +731,8 @@ static struct clk clk_i2s1 = {
        .parent         = &clk_hclk,
        .enable         = local_onoff_enable,
        .enable_reg     = LPC32XX_CLKPWR_I2S_CLK_CTRL,
-       .enable_mask    = LPC32XX_CLKPWR_I2SCTRL_I2SCLK1_EN,
+       .enable_mask    = LPC32XX_CLKPWR_I2SCTRL_I2SCLK1_EN |
+                         LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA,
        .get_rate       = local_return_parent_rate,
 };
 
@@ -727,14 +752,77 @@ static struct clk clk_rtc = {
        .get_rate       = local_return_parent_rate,
 };
 
+static int local_usb_enable(struct clk *clk, int enable)
+{
+       u32 tmp;
+
+       if (enable) {
+               /* Set up I2C pull levels */
+               tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL);
+               tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE;
+               __raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL);
+       }
+
+       return local_onoff_enable(clk, enable);
+}
+
 static struct clk clk_usbd = {
        .parent         = &clk_usbpll,
-       .enable         = local_onoff_enable,
+       .enable         = local_usb_enable,
        .enable_reg     = LPC32XX_CLKPWR_USB_CTRL,
        .enable_mask    = LPC32XX_CLKPWR_USBCTRL_HCLK_EN,
        .get_rate       = local_return_parent_rate,
 };
 
+#define OTG_ALWAYS_MASK                (LPC32XX_USB_OTG_OTG_CLOCK_ON | \
+                                LPC32XX_USB_OTG_I2C_CLOCK_ON)
+
+static int local_usb_otg_enable(struct clk *clk, int enable)
+{
+       int to = 1000;
+
+       if (enable) {
+               __raw_writel(clk->enable_mask, clk->enable_reg);
+
+               while (((__raw_readl(LPC32XX_USB_OTG_CLK_STAT) &
+                       clk->enable_mask) != clk->enable_mask) && (to > 0))
+                       to--;
+       } else {
+               __raw_writel(OTG_ALWAYS_MASK, clk->enable_reg);
+
+               while (((__raw_readl(LPC32XX_USB_OTG_CLK_STAT) &
+                       OTG_ALWAYS_MASK) != OTG_ALWAYS_MASK) && (to > 0))
+                       to--;
+       }
+
+       if (to)
+               return 0;
+       else
+               return -1;
+}
+
+static struct clk clk_usb_otg_dev = {
+       .parent         = &clk_usbpll,
+       .enable         = local_usb_otg_enable,
+       .enable_reg     = LPC32XX_USB_OTG_CLK_CTRL,
+       .enable_mask    = LPC32XX_USB_OTG_AHB_M_CLOCK_ON |
+                         LPC32XX_USB_OTG_OTG_CLOCK_ON |
+                         LPC32XX_USB_OTG_DEV_CLOCK_ON |
+                         LPC32XX_USB_OTG_I2C_CLOCK_ON,
+       .get_rate       = local_return_parent_rate,
+};
+
+static struct clk clk_usb_otg_host = {
+       .parent         = &clk_usbpll,
+       .enable         = local_usb_otg_enable,
+       .enable_reg     = LPC32XX_USB_OTG_CLK_CTRL,
+       .enable_mask    = LPC32XX_USB_OTG_AHB_M_CLOCK_ON |
+                         LPC32XX_USB_OTG_OTG_CLOCK_ON |
+                         LPC32XX_USB_OTG_HOST_CLOCK_ON |
+                         LPC32XX_USB_OTG_I2C_CLOCK_ON,
+       .get_rate       = local_return_parent_rate,
+};
+
 static int tsc_onoff_enable(struct clk *clk, int enable)
 {
        u32 tmp;
@@ -800,11 +888,17 @@ static int mmc_onoff_enable(struct clk *clk, int enable)
        u32 tmp;
 
        tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL) &
-               ~LPC32XX_CLKPWR_MSCARD_SDCARD_EN;
+               ~(LPC32XX_CLKPWR_MSCARD_SDCARD_EN |
+                 LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN |
+                 LPC32XX_CLKPWR_MSCARD_MSDIO_PIN_DIS |
+                 LPC32XX_CLKPWR_MSCARD_MSDIO0_DIS |
+                 LPC32XX_CLKPWR_MSCARD_MSDIO1_DIS |
+                 LPC32XX_CLKPWR_MSCARD_MSDIO23_DIS);
 
        /* If rate is 0, disable clock */
        if (enable != 0)
-               tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN;
+               tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN |
+                       LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN;
 
        __raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
 
@@ -853,7 +947,7 @@ static unsigned long mmc_round_rate(struct clk *clk, unsigned long rate)
 
 static int mmc_set_rate(struct clk *clk, unsigned long rate)
 {
-       u32 oldclk, tmp;
+       u32 tmp;
        unsigned long prate, div, crate = mmc_round_rate(clk, rate);
 
        prate = clk->parent->get_rate(clk->parent);
@@ -861,16 +955,12 @@ static int mmc_set_rate(struct clk *clk, unsigned long rate)
        div = prate / crate;
 
        /* The MMC clock must be on when accessing an MMC register */
-       oldclk = __raw_readl(LPC32XX_CLKPWR_MS_CTRL);
-       __raw_writel(oldclk | LPC32XX_CLKPWR_MSCARD_SDCARD_EN,
-               LPC32XX_CLKPWR_MS_CTRL);
        tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL) &
                ~LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(0xf);
-       tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(div);
+       tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_DIV(div) |
+               LPC32XX_CLKPWR_MSCARD_SDCARD_EN;
        __raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
 
-       __raw_writel(oldclk, LPC32XX_CLKPWR_MS_CTRL);
-
        return 0;
 }
 
@@ -1111,6 +1201,7 @@ static struct clk_lookup lookups[] = {
        CLKDEV_INIT(NULL, "vfp9_ck", &clk_vfp9),
        CLKDEV_INIT("pl08xdmac", NULL, &clk_dma),
        CLKDEV_INIT("4003c000.watchdog", NULL, &clk_wdt),
+       CLKDEV_INIT("4005c000.pwm", NULL, &clk_pwm),
        CLKDEV_INIT(NULL, "uart3_ck", &clk_uart3),
        CLKDEV_INIT(NULL, "uart4_ck", &clk_uart4),
        CLKDEV_INIT(NULL, "uart5_ck", &clk_uart5),
@@ -1120,8 +1211,9 @@ static struct clk_lookup lookups[] = {
        CLKDEV_INIT("31020300.i2c", NULL, &clk_i2c2),
        CLKDEV_INIT("dev:ssp0", NULL, &clk_ssp0),
        CLKDEV_INIT("dev:ssp1", NULL, &clk_ssp1),
-       CLKDEV_INIT("lpc32xx_keys.0", NULL, &clk_kscan),
-       CLKDEV_INIT("lpc32xx-nand.0", "nand_ck", &clk_nand),
+       CLKDEV_INIT("40050000.key", NULL, &clk_kscan),
+       CLKDEV_INIT("20020000.flash", NULL, &clk_nand),
+       CLKDEV_INIT("200a8000.flash", NULL, &clk_nand_mlc),
        CLKDEV_INIT("40048000.adc", NULL, &clk_adc),
        CLKDEV_INIT(NULL, "i2s0_ck", &clk_i2s0),
        CLKDEV_INIT(NULL, "i2s1_ck", &clk_i2s1),
@@ -1130,6 +1222,9 @@ static struct clk_lookup lookups[] = {
        CLKDEV_INIT("31060000.ethernet", NULL, &clk_net),
        CLKDEV_INIT("dev:clcd", NULL, &clk_lcd),
        CLKDEV_INIT("31020000.usbd", "ck_usbd", &clk_usbd),
+       CLKDEV_INIT("31020000.ohci", "ck_usbd", &clk_usbd),
+       CLKDEV_INIT("31020000.usbd", "ck_usb_otg", &clk_usb_otg_dev),
+       CLKDEV_INIT("31020000.ohci", "ck_usb_otg", &clk_usb_otg_host),
        CLKDEV_INIT("lpc32xx_rtc", NULL, &clk_rtc),
 };
 
index 5c96057b6d78e2a864863a87e38e91a03086a62d..a48dc2dec4859a43be83a93d482469e19d8ced5d 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/io.h>
 
 #include <asm/mach/map.h>
+#include <asm/system_info.h>
 
 #include <mach/hardware.h>
 #include <mach/platform.h>
@@ -224,7 +225,7 @@ void lpc23xx_restart(char mode, const char *cmd)
                ;
 }
 
-static int __init lpc32xx_display_uid(void)
+static int __init lpc32xx_check_uid(void)
 {
        u32 uid[4];
 
@@ -233,6 +234,11 @@ static int __init lpc32xx_display_uid(void)
        printk(KERN_INFO "LPC32XX unique ID: %08x%08x%08x%08x\n",
                uid[3], uid[2], uid[1], uid[0]);
 
+       if (!system_serial_low && !system_serial_high) {
+               system_serial_low = uid[0];
+               system_serial_high = uid[1];
+       }
+
        return 1;
 }
-arch_initcall(lpc32xx_display_uid);
+arch_initcall(lpc32xx_check_uid);
index 2ba6ca412bef3e06245853dfdeb5904ae54e3fbd..0052e7a761798acd1fef17aa5cf2a68ed8b43d29 100644 (file)
@@ -3,6 +3,4 @@
 
 #include "gpio-lpc32xx.h"
 
-#define ARCH_NR_GPIOS (LPC32XX_GPO_P3_GRP + LPC32XX_GPO_P3_MAX)
-
 #endif /* __MACH_GPIO_H */
index c584f5bb164fe5d8cedf6bb9cc3d05767c8faac3..acc4aabf1c7b090eae3cd64fc6a176aabbbf9542 100644 (file)
 #define LPC32XX_GPIO_P2_MUX_CLR                        _GPREG(0x02C)
 #define LPC32XX_GPIO_P2_MUX_STATE              _GPREG(0x030)
 
+/*
+ * USB Otg Registers
+ */
+#define _OTGREG(x)                     io_p2v(LPC32XX_USB_OTG_BASE + (x))
+#define LPC32XX_USB_OTG_CLK_CTRL       _OTGREG(0xFF4)
+#define LPC32XX_USB_OTG_CLK_STAT       _OTGREG(0xFF8)
+
+/* USB OTG CLK CTRL bit defines */
+#define LPC32XX_USB_OTG_AHB_M_CLOCK_ON _BIT(4)
+#define LPC32XX_USB_OTG_OTG_CLOCK_ON   _BIT(3)
+#define LPC32XX_USB_OTG_I2C_CLOCK_ON   _BIT(2)
+#define LPC32XX_USB_OTG_DEV_CLOCK_ON   _BIT(1)
+#define LPC32XX_USB_OTG_HOST_CLOCK_ON  _BIT(0)
+
 #endif
index 540106cdb9ec42658c404b92be618d8766570adf..b07dcc90829d7c3b2227bca72594d0381263ca1e 100644 (file)
 #include <linux/amba/bus.h>
 #include <linux/amba/clcd.h>
 #include <linux/amba/pl022.h>
+#include <linux/amba/pl08x.h>
+#include <linux/amba/mmci.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/clk.h>
-#include <linux/amba/pl08x.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -50,9 +51,9 @@
 /*
  * Mapped GPIOLIB GPIOs
  */
-#define SPI0_CS_GPIO   LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
-#define LCD_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 0)
-#define BKL_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 4)
+#define LCD_POWER_GPIO         LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 0)
+#define BKL_POWER_GPIO         LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 4)
+#define MMC_PWR_ENABLE_GPIO    LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 5)
 
 /*
  * AMBA LCD controller
@@ -158,24 +159,6 @@ static struct clcd_board lpc32xx_clcd_data = {
 /*
  * AMBA SSP (SPI)
  */
-static void phy3250_spi_cs_set(u32 control)
-{
-       gpio_set_value(SPI0_CS_GPIO, (int) control);
-}
-
-static struct pl022_config_chip spi0_chip_info = {
-       .com_mode               = INTERRUPT_TRANSFER,
-       .iface                  = SSP_INTERFACE_MOTOROLA_SPI,
-       .hierarchy              = SSP_MASTER,
-       .slave_tx_disable       = 0,
-       .rx_lev_trig            = SSP_RX_4_OR_MORE_ELEM,
-       .tx_lev_trig            = SSP_TX_4_OR_MORE_EMPTY_LOC,
-       .ctrl_len               = SSP_BITS_8,
-       .wait_state             = SSP_MWIRE_WAIT_ZERO,
-       .duplex                 = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
-       .cs_control             = phy3250_spi_cs_set,
-};
-
 static struct pl022_ssp_controller lpc32xx_ssp0_data = {
        .bus_id                 = 0,
        .num_chipselect         = 1,
@@ -188,45 +171,56 @@ static struct pl022_ssp_controller lpc32xx_ssp1_data = {
        .enable_dma             = 0,
 };
 
-/* AT25 driver registration */
-static int __init phy3250_spi_board_register(void)
+static struct pl08x_channel_data pl08x_slave_channels[] = {
+       {
+               .bus_id = "nand-slc",
+               .min_signal = 1, /* SLC NAND Flash */
+               .max_signal = 1,
+               .periph_buses = PL08X_AHB1,
+       },
+       {
+               .bus_id = "nand-mlc",
+               .min_signal = 12, /* MLC NAND Flash */
+               .max_signal = 12,
+               .periph_buses = PL08X_AHB1,
+       },
+};
+
+static int pl08x_get_signal(const struct pl08x_channel_data *cd)
+{
+       return cd->min_signal;
+}
+
+static void pl08x_put_signal(const struct pl08x_channel_data *cd, int ch)
 {
-#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
-       static struct spi_board_info info[] = {
-               {
-                       .modalias = "spidev",
-                       .max_speed_hz = 5000000,
-                       .bus_num = 0,
-                       .chip_select = 0,
-                       .controller_data = &spi0_chip_info,
-               },
-       };
-
-#else
-       static struct spi_eeprom eeprom = {
-               .name = "at25256a",
-               .byte_len = 0x8000,
-               .page_size = 64,
-               .flags = EE_ADDR2,
-       };
-
-       static struct spi_board_info info[] = {
-               {
-                       .modalias = "at25",
-                       .max_speed_hz = 5000000,
-                       .bus_num = 0,
-                       .chip_select = 0,
-                       .mode = SPI_MODE_0,
-                       .platform_data = &eeprom,
-                       .controller_data = &spi0_chip_info,
-               },
-       };
-#endif
-       return spi_register_board_info(info, ARRAY_SIZE(info));
 }
-arch_initcall(phy3250_spi_board_register);
 
 static struct pl08x_platform_data pl08x_pd = {
+       .slave_channels = &pl08x_slave_channels[0],
+       .num_slave_channels = ARRAY_SIZE(pl08x_slave_channels),
+       .get_signal = pl08x_get_signal,
+       .put_signal = pl08x_put_signal,
+       .lli_buses = PL08X_AHB1,
+       .mem_buses = PL08X_AHB1,
+};
+
+static int mmc_handle_ios(struct device *dev, struct mmc_ios *ios)
+{
+       /* Only on and off are supported */
+       if (ios->power_mode == MMC_POWER_OFF)
+               gpio_set_value(MMC_PWR_ENABLE_GPIO, 0);
+       else
+               gpio_set_value(MMC_PWR_ENABLE_GPIO, 1);
+       return 0;
+}
+
+static struct mmci_platform_data lpc32xx_mmci_data = {
+       .ocr_mask       = MMC_VDD_30_31 | MMC_VDD_31_32 |
+                         MMC_VDD_32_33 | MMC_VDD_33_34,
+       .ios_handler    = mmc_handle_ios,
+       .dma_filter     = NULL,
+       /* No DMA for now since AMBA PL080 dmaengine driver only does scatter
+        * gather, and the MMCI driver doesn't do it this way */
 };
 
 static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = {
@@ -234,6 +228,8 @@ static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = {
        OF_DEV_AUXDATA("arm,pl022", 0x2008C000, "dev:ssp1", &lpc32xx_ssp1_data),
        OF_DEV_AUXDATA("arm,pl110", 0x31040000, "dev:clcd", &lpc32xx_clcd_data),
        OF_DEV_AUXDATA("arm,pl080", 0x31000000, "pl08xdmac", &pl08x_pd),
+       OF_DEV_AUXDATA("arm,pl18x", 0x20098000, "20098000.sd",
+                      &lpc32xx_mmci_data),
        { }
 };
 
@@ -241,10 +237,6 @@ static void __init lpc3250_machine_init(void)
 {
        u32 tmp;
 
-       /* Setup SLC NAND controller muxing */
-       __raw_writel(LPC32XX_CLKPWR_NANDCLK_SEL_SLC,
-               LPC32XX_CLKPWR_NAND_CLK_CTRL);
-
        /* Setup LCD muxing to RGB565 */
        tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) &
                ~(LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK |
@@ -252,47 +244,8 @@ static void __init lpc3250_machine_init(void)
        tmp |= LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16;
        __raw_writel(tmp, LPC32XX_CLKPWR_LCDCLK_CTRL);
 
-       /* Set up USB power */
-       tmp = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
-       tmp |= LPC32XX_CLKPWR_USBCTRL_HCLK_EN |
-               LPC32XX_CLKPWR_USBCTRL_USBI2C_EN;
-       __raw_writel(tmp, LPC32XX_CLKPWR_USB_CTRL);
-
-       /* Set up I2C pull levels */
-       tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL);
-       tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE |
-               LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE;
-       __raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL);
-
-       /* Disable IrDA pulsing support on UART6 */
-       tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
-       tmp |= LPC32XX_UART_UART6_IRDAMOD_BYPASS;
-       __raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
-
-       /* Enable DMA for I2S1 channel */
-       tmp = __raw_readl(LPC32XX_CLKPWR_I2S_CLK_CTRL);
-       tmp = LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA;
-       __raw_writel(tmp, LPC32XX_CLKPWR_I2S_CLK_CTRL);
-
        lpc32xx_serial_init();
 
-       /*
-        * AMBA peripheral clocks need to be enabled prior to AMBA device
-        * detection or a data fault will occur, so enable the clocks
-        * here.
-        */
-       tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
-       __raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN),
-               LPC32XX_CLKPWR_LCDCLK_CTRL);
-
-       tmp = __raw_readl(LPC32XX_CLKPWR_SSP_CLK_CTRL);
-       __raw_writel((tmp | LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN),
-               LPC32XX_CLKPWR_SSP_CLK_CTRL);
-
-       tmp = __raw_readl(LPC32XX_CLKPWR_DMA_CLK_CTRL);
-       __raw_writel((tmp | LPC32XX_CLKPWR_DMACLKCTRL_CLK_EN),
-                    LPC32XX_CLKPWR_DMA_CLK_CTRL);
-
        /* Test clock needed for UDA1380 initial init */
        __raw_writel(LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC |
                LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN,
@@ -302,12 +255,10 @@ static void __init lpc3250_machine_init(void)
                             lpc32xx_auxdata_lookup, NULL);
 
        /* Register GPIOs used on this board */
-       if (gpio_request(SPI0_CS_GPIO, "spi0 cs"))
-               printk(KERN_ERR "Error requesting gpio %u",
-                       SPI0_CS_GPIO);
-       else if (gpio_direction_output(SPI0_CS_GPIO, 1))
-               printk(KERN_ERR "Error setting gpio %u to output",
-                       SPI0_CS_GPIO);
+       if (gpio_request(MMC_PWR_ENABLE_GPIO, "mmc_power_en"))
+               pr_err("Error requesting gpio %u", MMC_PWR_ENABLE_GPIO);
+       else if (gpio_direction_output(MMC_PWR_ENABLE_GPIO, 1))
+               pr_err("Error setting gpio %u to output", MMC_PWR_ENABLE_GPIO);
 }
 
 static char const *lpc32xx_dt_compat[] __initdata = {
index f2735281616a1d8a9e008c09d7483fa637a314cf..05621a29fba22cb5a1754f525d90817c9eaf3c57 100644 (file)
 
 #define LPC32XX_SUART_FIFO_SIZE        64
 
-/* Standard 8250/16550 compatible serial ports */
-static struct plat_serial8250_port serial_std_platform_data[] = {
-#ifdef CONFIG_ARCH_LPC32XX_UART5_SELECT
-       {
-               .membase        = io_p2v(LPC32XX_UART5_BASE),
-               .mapbase        = LPC32XX_UART5_BASE,
-               .irq            = IRQ_LPC32XX_UART_IIR5,
-               .uartclk        = LPC32XX_MAIN_OSC_FREQ,
-               .regshift       = 2,
-               .iotype         = UPIO_MEM32,
-               .flags          = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
-                                       UPF_SKIP_TEST,
-       },
-#endif
-#ifdef CONFIG_ARCH_LPC32XX_UART3_SELECT
-       {
-               .membase        = io_p2v(LPC32XX_UART3_BASE),
-               .mapbase        = LPC32XX_UART3_BASE,
-               .irq            = IRQ_LPC32XX_UART_IIR3,
-               .uartclk        = LPC32XX_MAIN_OSC_FREQ,
-               .regshift       = 2,
-               .iotype         = UPIO_MEM32,
-               .flags          = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
-                                       UPF_SKIP_TEST,
-       },
-#endif
-#ifdef CONFIG_ARCH_LPC32XX_UART4_SELECT
-       {
-               .membase        = io_p2v(LPC32XX_UART4_BASE),
-               .mapbase        = LPC32XX_UART4_BASE,
-               .irq            = IRQ_LPC32XX_UART_IIR4,
-               .uartclk        = LPC32XX_MAIN_OSC_FREQ,
-               .regshift       = 2,
-               .iotype         = UPIO_MEM32,
-               .flags          = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
-                                       UPF_SKIP_TEST,
-       },
-#endif
-#ifdef CONFIG_ARCH_LPC32XX_UART6_SELECT
-       {
-               .membase        = io_p2v(LPC32XX_UART6_BASE),
-               .mapbase        = LPC32XX_UART6_BASE,
-               .irq            = IRQ_LPC32XX_UART_IIR6,
-               .uartclk        = LPC32XX_MAIN_OSC_FREQ,
-               .regshift       = 2,
-               .iotype         = UPIO_MEM32,
-               .flags          = UPF_BOOT_AUTOCONF | UPF_BUGGY_UART |
-                                       UPF_SKIP_TEST,
-       },
-#endif
-       { },
-};
-
 struct uartinit {
        char *uart_ck_name;
        u32 ck_mode_mask;
@@ -92,7 +39,6 @@ struct uartinit {
 };
 
 static struct uartinit uartinit_data[] __initdata = {
-#ifdef CONFIG_ARCH_LPC32XX_UART5_SELECT
        {
                .uart_ck_name = "uart5_ck",
                .ck_mode_mask =
@@ -100,8 +46,6 @@ static struct uartinit uartinit_data[] __initdata = {
                .pdiv_clk_reg = LPC32XX_CLKPWR_UART5_CLK_CTRL,
                .mapbase = LPC32XX_UART5_BASE,
        },
-#endif
-#ifdef CONFIG_ARCH_LPC32XX_UART3_SELECT
        {
                .uart_ck_name = "uart3_ck",
                .ck_mode_mask =
@@ -109,8 +53,6 @@ static struct uartinit uartinit_data[] __initdata = {
                .pdiv_clk_reg = LPC32XX_CLKPWR_UART3_CLK_CTRL,
                .mapbase = LPC32XX_UART3_BASE,
        },
-#endif
-#ifdef CONFIG_ARCH_LPC32XX_UART4_SELECT
        {
                .uart_ck_name = "uart4_ck",
                .ck_mode_mask =
@@ -118,8 +60,6 @@ static struct uartinit uartinit_data[] __initdata = {
                .pdiv_clk_reg = LPC32XX_CLKPWR_UART4_CLK_CTRL,
                .mapbase = LPC32XX_UART4_BASE,
        },
-#endif
-#ifdef CONFIG_ARCH_LPC32XX_UART6_SELECT
        {
                .uart_ck_name = "uart6_ck",
                .ck_mode_mask =
@@ -127,19 +67,6 @@ static struct uartinit uartinit_data[] __initdata = {
                .pdiv_clk_reg = LPC32XX_CLKPWR_UART6_CLK_CTRL,
                .mapbase = LPC32XX_UART6_BASE,
        },
-#endif
-};
-
-static struct platform_device serial_std_platform_device = {
-       .name                   = "serial8250",
-       .id                     = 0,
-       .dev                    = {
-               .platform_data  = serial_std_platform_data,
-       },
-};
-
-static struct platform_device *lpc32xx_serial_devs[] __initdata = {
-       &serial_std_platform_device,
 };
 
 void __init lpc32xx_serial_init(void)
@@ -156,15 +83,8 @@ void __init lpc32xx_serial_init(void)
                clk = clk_get(NULL, uartinit_data[i].uart_ck_name);
                if (!IS_ERR(clk)) {
                        clk_enable(clk);
-                       serial_std_platform_data[i].uartclk =
-                               clk_get_rate(clk);
                }
 
-               /* Fall back on main osc rate if clock rate return fails */
-               if (serial_std_platform_data[i].uartclk == 0)
-                       serial_std_platform_data[i].uartclk =
-                               LPC32XX_MAIN_OSC_FREQ;
-
                /* Setup UART clock modes for all UARTs, disable autoclock */
                clkmodes |= uartinit_data[i].ck_mode_mask;
 
@@ -189,7 +109,7 @@ void __init lpc32xx_serial_init(void)
        __raw_writel(clkmodes, LPC32XX_UARTCTL_CLKMODE);
        for (i = 0; i < ARRAY_SIZE(uartinit_data); i++) {
                /* Force a flush of the RX FIFOs to work around a HW bug */
-               puart = serial_std_platform_data[i].mapbase;
+               puart = uartinit_data[i].mapbase;
                __raw_writel(0xC1, LPC32XX_UART_IIR_FCR(puart));
                __raw_writel(0x00, LPC32XX_UART_DLL_FIFO(puart));
                j = LPC32XX_SUART_FIFO_SIZE;
@@ -198,11 +118,13 @@ void __init lpc32xx_serial_init(void)
                __raw_writel(0, LPC32XX_UART_IIR_FCR(puart));
        }
 
+       /* Disable IrDA pulsing support on UART6 */
+       tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
+       tmp |= LPC32XX_UART_UART6_IRDAMOD_BYPASS;
+       __raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
+
        /* Disable UART5->USB transparent mode or USB won't work */
        tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
        tmp &= ~LPC32XX_UART_U5_ROUTE_TO_USB;
        __raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
-
-       platform_add_devices(lpc32xx_serial_devs,
-               ARRAY_SIZE(lpc32xx_serial_devs));
 }
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
new file mode 100644 (file)
index 0000000..caa2c5e
--- /dev/null
@@ -0,0 +1,16 @@
+if ARCH_MVEBU
+
+menu "Marvell SOC with device tree"
+
+config MACH_ARMADA_370_XP
+       bool "Marvell Armada 370 and Aramada XP boards"
+       select ARMADA_370_XP_TIMER
+       select CPU_V7
+       help
+
+         Say 'Y' here if you want your kernel to support boards based on
+         Marvell Armada 370 or Armada XP with device tree.
+
+endmenu
+
+endif
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
new file mode 100644 (file)
index 0000000..e61d2b8
--- /dev/null
@@ -0,0 +1,2 @@
+obj-y += system-controller.o
+obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o
diff --git a/arch/arm/mach-mvebu/Makefile.boot b/arch/arm/mach-mvebu/Makefile.boot
new file mode 100644 (file)
index 0000000..2579a2f
--- /dev/null
@@ -0,0 +1,3 @@
+zreladdr-y := 0x00008000
+dtb-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-db.dtb
+dtb-$(CONFIG_MACH_ARMADA_370_XP) += armada-xp-db.dtb
diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
new file mode 100644 (file)
index 0000000..4ef923b
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Device Tree support for Armada 370 and XP platforms.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of_platform.h>
+#include <linux/io.h>
+#include <linux/time-armada-370-xp.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/time.h>
+#include <mach/armada-370-xp.h>
+#include "common.h"
+
+static struct map_desc armada_370_xp_io_desc[] __initdata = {
+       {
+               .virtual        = ARMADA_370_XP_REGS_VIRT_BASE,
+               .pfn            = __phys_to_pfn(ARMADA_370_XP_REGS_PHYS_BASE),
+               .length         = ARMADA_370_XP_REGS_SIZE,
+               .type           = MT_DEVICE,
+       },
+};
+
+void __init armada_370_xp_map_io(void)
+{
+       iotable_init(armada_370_xp_io_desc, ARRAY_SIZE(armada_370_xp_io_desc));
+}
+
+struct sys_timer armada_370_xp_timer = {
+       .init           = armada_370_xp_timer_init,
+};
+
+static void __init armada_370_xp_dt_init(void)
+{
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char * const armada_370_xp_dt_board_dt_compat[] = {
+       "marvell,a370-db",
+       "marvell,axp-db",
+       NULL,
+};
+
+DT_MACHINE_START(ARMADA_XP_DT, "Marvell Aramada 370/XP (Device Tree)")
+       .init_machine   = armada_370_xp_dt_init,
+       .map_io         = armada_370_xp_map_io,
+       .init_irq       = armada_370_xp_init_irq,
+       .handle_irq     = armada_370_xp_handle_irq,
+       .timer          = &armada_370_xp_timer,
+       .restart        = mvebu_restart,
+       .dt_compat      = armada_370_xp_dt_board_dt_compat,
+MACHINE_END
diff --git a/arch/arm/mach-mvebu/common.h b/arch/arm/mach-mvebu/common.h
new file mode 100644 (file)
index 0000000..02f89ea
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Core functions for Marvell System On Chip
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __ARCH_MVEBU_COMMON_H
+#define __ARCH_MVEBU_COMMON_H
+
+void mvebu_restart(char mode, const char *cmd);
+
+void armada_370_xp_init_irq(void);
+void armada_370_xp_handle_irq(struct pt_regs *regs);
+
+#endif
diff --git a/arch/arm/mach-mvebu/include/mach/armada-370-xp.h b/arch/arm/mach-mvebu/include/mach/armada-370-xp.h
new file mode 100644 (file)
index 0000000..25f0ca8
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Generic definitions for Marvell Armada_370_XP SoCs
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MACH_ARMADA_370_XP_H
+#define __MACH_ARMADA_370_XP_H
+
+#define ARMADA_370_XP_REGS_PHYS_BASE   0xd0000000
+#define ARMADA_370_XP_REGS_VIRT_BASE   0xfeb00000
+#define ARMADA_370_XP_REGS_SIZE                SZ_1M
+
+#endif /* __MACH_ARMADA_370_XP_H */
diff --git a/arch/arm/mach-mvebu/include/mach/debug-macro.S b/arch/arm/mach-mvebu/include/mach/debug-macro.S
new file mode 100644 (file)
index 0000000..2282576
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Early serial output macro for Marvell  SoC
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory Clement <gregory.clement@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 version 2 as
+ * published by the Free Software Foundation.
+*/
+
+#include <mach/armada-370-xp.h>
+
+       .macro  addruart, rp, rv, tmp
+       ldr     \rp, =ARMADA_370_XP_REGS_PHYS_BASE
+       ldr     \rv, =ARMADA_370_XP_REGS_VIRT_BASE
+       orr     \rp, \rp, #0x00012000
+       orr     \rv, \rv, #0x00012000
+       .endm
+
+#define UART_SHIFT     2
+#include <asm/hardware/debug-8250.S>
diff --git a/arch/arm/mach-mvebu/include/mach/timex.h b/arch/arm/mach-mvebu/include/mach/timex.h
new file mode 100644 (file)
index 0000000..ab324a3
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * Marvell Armada SoC time definitions
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#define CLOCK_TICK_RATE                (100 * HZ)
diff --git a/arch/arm/mach-mvebu/include/mach/uncompress.h b/arch/arm/mach-mvebu/include/mach/uncompress.h
new file mode 100644 (file)
index 0000000..d6a100c
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Marvell Armada SoC kernel uncompression UART routines
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <mach/armada-370-xp.h>
+
+#define UART_THR ((volatile unsigned char *)(ARMADA_370_XP_REGS_PHYS_BASE\
+                                                               + 0x12000))
+#define UART_LSR ((volatile unsigned char *)(ARMADA_370_XP_REGS_PHYS_BASE\
+                                                               + 0x12014))
+
+#define LSR_THRE       0x20
+
+static void putc(const char c)
+{
+       int i;
+
+       for (i = 0; i < 0x1000; i++) {
+               /* Transmit fifo not full? */
+               if (*UART_LSR & LSR_THRE)
+                       break;
+       }
+
+       *UART_THR = c;
+}
+
+static void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff --git a/arch/arm/mach-mvebu/irq-armada-370-xp.c b/arch/arm/mach-mvebu/irq-armada-370-xp.c
new file mode 100644 (file)
index 0000000..5f5f939
--- /dev/null
@@ -0,0 +1,133 @@
+/*
+ * Marvell Armada 370 and Armada XP SoC IRQ handling
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ * Ben Dooks <ben.dooks@codethink.co.uk>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/irqdomain.h>
+#include <asm/mach/arch.h>
+#include <asm/exception.h>
+
+/* Interrupt Controller Registers Map */
+#define ARMADA_370_XP_INT_SET_MASK_OFFS                (0x48)
+#define ARMADA_370_XP_INT_CLEAR_MASK_OFFS      (0x4C)
+
+#define ARMADA_370_XP_INT_CONTROL              (0x00)
+#define ARMADA_370_XP_INT_SET_ENABLE_OFFS      (0x30)
+#define ARMADA_370_XP_INT_CLEAR_ENABLE_OFFS    (0x34)
+
+#define ARMADA_370_XP_CPU_INTACK_OFFS          (0x44)
+
+static void __iomem *per_cpu_int_base;
+static void __iomem *main_int_base;
+static struct irq_domain *armada_370_xp_mpic_domain;
+
+static void armada_370_xp_irq_mask(struct irq_data *d)
+{
+       writel(irqd_to_hwirq(d),
+              per_cpu_int_base + ARMADA_370_XP_INT_SET_MASK_OFFS);
+}
+
+static void armada_370_xp_irq_unmask(struct irq_data *d)
+{
+       writel(irqd_to_hwirq(d),
+              per_cpu_int_base + ARMADA_370_XP_INT_CLEAR_MASK_OFFS);
+}
+
+static struct irq_chip armada_370_xp_irq_chip = {
+       .name           = "armada_370_xp_irq",
+       .irq_mask       = armada_370_xp_irq_mask,
+       .irq_mask_ack   = armada_370_xp_irq_mask,
+       .irq_unmask     = armada_370_xp_irq_unmask,
+};
+
+static int armada_370_xp_mpic_irq_map(struct irq_domain *h,
+                                     unsigned int virq, irq_hw_number_t hw)
+{
+       armada_370_xp_irq_mask(irq_get_irq_data(virq));
+       writel(hw, main_int_base + ARMADA_370_XP_INT_SET_ENABLE_OFFS);
+
+       irq_set_chip_and_handler(virq, &armada_370_xp_irq_chip,
+                                handle_level_irq);
+       irq_set_status_flags(virq, IRQ_LEVEL);
+       set_irq_flags(virq, IRQF_VALID | IRQF_PROBE);
+
+       return 0;
+}
+
+static struct irq_domain_ops armada_370_xp_mpic_irq_ops = {
+       .map = armada_370_xp_mpic_irq_map,
+       .xlate = irq_domain_xlate_onecell,
+};
+
+static int __init armada_370_xp_mpic_of_init(struct device_node *node,
+                                            struct device_node *parent)
+{
+       u32 control;
+
+       main_int_base = of_iomap(node, 0);
+       per_cpu_int_base = of_iomap(node, 1);
+
+       BUG_ON(!main_int_base);
+       BUG_ON(!per_cpu_int_base);
+
+       control = readl(main_int_base + ARMADA_370_XP_INT_CONTROL);
+
+       armada_370_xp_mpic_domain =
+           irq_domain_add_linear(node, (control >> 2) & 0x3ff,
+                                 &armada_370_xp_mpic_irq_ops, NULL);
+
+       if (!armada_370_xp_mpic_domain)
+               panic("Unable to add Armada_370_Xp MPIC irq domain (DT)\n");
+
+       irq_set_default_host(armada_370_xp_mpic_domain);
+       return 0;
+}
+
+asmlinkage void __exception_irq_entry armada_370_xp_handle_irq(struct pt_regs
+                                                              *regs)
+{
+       u32 irqstat, irqnr;
+
+       do {
+               irqstat = readl_relaxed(per_cpu_int_base +
+                                       ARMADA_370_XP_CPU_INTACK_OFFS);
+               irqnr = irqstat & 0x3FF;
+
+               if (irqnr < 1023) {
+                       irqnr =
+                           irq_find_mapping(armada_370_xp_mpic_domain, irqnr);
+                       handle_IRQ(irqnr, regs);
+                       continue;
+               }
+
+               break;
+       } while (1);
+}
+
+static const struct of_device_id mpic_of_match[] __initconst = {
+       {.compatible = "marvell,mpic", .data = armada_370_xp_mpic_of_init},
+       {},
+};
+
+void __init armada_370_xp_init_irq(void)
+{
+       of_irq_init(mpic_of_match);
+}
diff --git a/arch/arm/mach-mvebu/system-controller.c b/arch/arm/mach-mvebu/system-controller.c
new file mode 100644 (file)
index 0000000..b8079df
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * System controller support for Armada 370 and XP platforms.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * The Armada 370 and Armada XP SoCs both have a range of
+ * miscellaneous registers, that do not belong to a particular device,
+ * but rather provide system-level features. This basic
+ * system-controller driver provides a device tree binding for those
+ * registers, and implements utility functions offering various
+ * features related to those registers.
+ *
+ * For now, the feature set is limited to restarting the platform by a
+ * soft-reset, but it might be extended in the future.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+static void __iomem *system_controller_base;
+
+struct mvebu_system_controller {
+       u32 rstoutn_mask_offset;
+       u32 system_soft_reset_offset;
+
+       u32 rstoutn_mask_reset_out_en;
+       u32 system_soft_reset;
+};
+static struct mvebu_system_controller *mvebu_sc;
+
+const struct mvebu_system_controller armada_370_xp_system_controller = {
+       .rstoutn_mask_offset = 0x60,
+       .system_soft_reset_offset = 0x64,
+       .rstoutn_mask_reset_out_en = 0x1,
+       .system_soft_reset = 0x1,
+};
+
+const struct mvebu_system_controller orion_system_controller = {
+       .rstoutn_mask_offset = 0x108,
+       .system_soft_reset_offset = 0x10c,
+       .rstoutn_mask_reset_out_en = 0x4,
+       .system_soft_reset = 0x1,
+};
+
+static struct of_device_id of_system_controller_table[] = {
+       {
+               .compatible = "marvell,orion-system-controller",
+               .data = (void *) &orion_system_controller,
+       }, {
+               .compatible = "marvell,armada-370-xp-system-controller",
+               .data = (void *) &armada_370_xp_system_controller,
+       },
+       { /* end of list */ },
+};
+
+void mvebu_restart(char mode, const char *cmd)
+{
+       if (!system_controller_base) {
+               pr_err("Cannot restart, system-controller not available: check the device tree\n");
+       } else {
+               /*
+                * Enable soft reset to assert RSTOUTn.
+                */
+               writel(mvebu_sc->rstoutn_mask_reset_out_en,
+                       system_controller_base +
+                       mvebu_sc->rstoutn_mask_offset);
+               /*
+                * Assert soft reset.
+                */
+               writel(mvebu_sc->system_soft_reset,
+                       system_controller_base +
+                       mvebu_sc->system_soft_reset_offset);
+       }
+
+       while (1)
+               ;
+}
+
+static int __init mvebu_system_controller_init(void)
+{
+       struct device_node *np;
+
+       np = of_find_matching_node(NULL, of_system_controller_table);
+       if (np) {
+               const struct of_device_id *match =
+                   of_match_node(of_system_controller_table, np);
+               BUG_ON(!match);
+               system_controller_base = of_iomap(np, 0);
+               mvebu_sc = (struct mvebu_system_controller *)match->data;
+       }
+
+       return 0;
+}
+
+arch_initcall(mvebu_system_controller_init);
index 91cf0625819c2f62639cff7216e6563b9813e585..ccdf83b17cf16030612bdf62c43711f7f926baa6 100644 (file)
@@ -16,6 +16,7 @@ config SOC_IMX28
        bool
        select ARM_AMBA
        select CPU_ARM926T
+       select HAVE_CAN_FLEXCAN if CAN
        select HAVE_PWM
        select PINCTRL_IMX28
 
index 07b11fe6453f525bc43fc15cf32694388188f0c7..4582999cf0805ec1b79ce888a224d8669695f562 100644 (file)
@@ -1 +1,10 @@
 zreladdr-y += 0x40008000
+
+dtb-y += imx23-evk.dtb \
+        imx23-olinuxino.dtb \
+        imx23-stmp378x_devb.dtb \
+        imx28-apx4devkit.dtb \
+        imx28-cfa10036.dtb \
+        imx28-evk.dtb \
+        imx28-m28evk.dtb \
+        imx28-tx28.dtb \
index 9acdd6387047dd89663b90ab1cb80cca3245260d..9ee5cede3d42f5d646cac069888ebb563aefe163 100644 (file)
@@ -10,7 +10,7 @@
  */
 #include <mach/mx23.h>
 #include <mach/devices-common.h>
-#include <mach/mxsfb.h>
+#include <linux/mxsfb.h>
 #include <linux/amba/bus.h>
 
 static inline int mx23_add_duart(void)
index 84b2960df117f56920a481253b6596ad1eb37356..fcab431060f486e7da61eaa07f2d46f62a31e0b6 100644 (file)
@@ -10,7 +10,7 @@
  */
 #include <mach/mx28.h>
 #include <mach/devices-common.h>
-#include <mach/mxsfb.h>
+#include <linux/mxsfb.h>
 #include <linux/amba/bus.h>
 
 static inline int mx28_add_duart(void)
index 5a75b7180f74b616939b30c0aeeaa7c3f987f847..76b53f73418e695a6b0826e8ea8b4f03d8b78910 100644 (file)
@@ -10,7 +10,7 @@
 #include <mach/mx23.h>
 #include <mach/mx28.h>
 #include <mach/devices-common.h>
-#include <mach/mxsfb.h>
+#include <linux/mxsfb.h>
 
 #ifdef CONFIG_SOC_IMX23
 struct platform_device *__init mx23_add_mxsfb(
diff --git a/arch/arm/mach-mxs/include/mach/mxsfb.h b/arch/arm/mach-mxs/include/mach/mxsfb.h
deleted file mode 100644 (file)
index e4d7979..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA.
- */
-
-#ifndef __MACH_FB_H
-#define __MACH_FB_H
-
-#include <linux/fb.h>
-
-#define STMLCDIF_8BIT 1        /** pixel data bus to the display is of 8 bit width */
-#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
-#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 */
-
-struct mxsfb_platform_data {
-       struct fb_videomode *mode_list;
-       unsigned mode_count;
-
-       unsigned default_bpp;
-
-       unsigned dotclk_delay;  /* refer manual HW_LCDIF_VDCTRL4 register */
-       unsigned ld_intf_width; /* refer STMLCDIF_* macros */
-
-       unsigned fb_size;       /* Size of the video memory. If zero a
-                                * default will be used
-                                */
-       unsigned long fb_phys;  /* physical address for the video memory. If
-                                * zero the framebuffer memory will be dynamically
-                                * allocated. If specified,fb_size must also be specified.
-                                * fb_phys must be unused by Linux.
-                                */
-};
-
-#endif /* __MACH_FB_H */
index 8cac94b33020c64fb1a3f2efc80a3af5b5fbba21..648bdd05d38bb95006401378af9540580501970a 100644 (file)
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/irqdomain.h>
+#include <linux/micrel_phy.h>
+#include <linux/mxsfb.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/phy.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <mach/common.h>
 
+static struct fb_videomode mx23evk_video_modes[] = {
+       {
+               .name           = "Samsung-LMS430HF02",
+               .refresh        = 60,
+               .xres           = 480,
+               .yres           = 272,
+               .pixclock       = 108096, /* picosecond (9.2 MHz) */
+               .left_margin    = 15,
+               .right_margin   = 8,
+               .upper_margin   = 12,
+               .lower_margin   = 4,
+               .hsync_len      = 1,
+               .vsync_len      = 1,
+               .sync           = FB_SYNC_DATA_ENABLE_HIGH_ACT |
+                                 FB_SYNC_DOTCLK_FAILING_ACT,
+       },
+};
+
+static struct fb_videomode mx28evk_video_modes[] = {
+       {
+               .name           = "Seiko-43WVF1G",
+               .refresh        = 60,
+               .xres           = 800,
+               .yres           = 480,
+               .pixclock       = 29851, /* picosecond (33.5 MHz) */
+               .left_margin    = 89,
+               .right_margin   = 164,
+               .upper_margin   = 23,
+               .lower_margin   = 10,
+               .hsync_len      = 10,
+               .vsync_len      = 10,
+               .sync           = FB_SYNC_DATA_ENABLE_HIGH_ACT |
+                                 FB_SYNC_DOTCLK_FAILING_ACT,
+       },
+};
+
+static struct fb_videomode m28evk_video_modes[] = {
+       {
+               .name           = "Ampire AM-800480R2TMQW-T01H",
+               .refresh        = 60,
+               .xres           = 800,
+               .yres           = 480,
+               .pixclock       = 30066, /* picosecond (33.26 MHz) */
+               .left_margin    = 0,
+               .right_margin   = 256,
+               .upper_margin   = 0,
+               .lower_margin   = 45,
+               .hsync_len      = 1,
+               .vsync_len      = 1,
+               .sync           = FB_SYNC_DATA_ENABLE_HIGH_ACT,
+       },
+};
+
+static struct fb_videomode apx4devkit_video_modes[] = {
+       {
+               .name           = "HannStar PJ70112A",
+               .refresh        = 60,
+               .xres           = 800,
+               .yres           = 480,
+               .pixclock       = 33333, /* picosecond (30.00 MHz) */
+               .left_margin    = 88,
+               .right_margin   = 40,
+               .upper_margin   = 32,
+               .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,
+       },
+};
+
+static struct mxsfb_platform_data mxsfb_pdata __initdata;
+
+static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = {
+       OF_DEV_AUXDATA("fsl,imx23-lcdif", 0x80030000, NULL, &mxsfb_pdata),
+       OF_DEV_AUXDATA("fsl,imx28-lcdif", 0x80030000, NULL, &mxsfb_pdata),
+       { /* sentinel */ }
+};
+
 static int __init mxs_icoll_add_irq_domain(struct device_node *np,
                                struct device_node *interrupt_parent)
 {
@@ -71,33 +154,155 @@ static struct sys_timer imx28_timer = {
        .init = imx28_timer_init,
 };
 
-static void __init imx28_evk_init(void)
+enum mac_oui {
+       OUI_FSL,
+       OUI_DENX,
+};
+
+static void __init update_fec_mac_prop(enum mac_oui oui)
+{
+       struct device_node *np, *from = NULL;
+       struct property *oldmac, *newmac;
+       const u32 *ocotp = mxs_get_ocotp();
+       u8 *macaddr;
+       u32 val;
+       int i;
+
+       for (i = 0; i < 2; i++) {
+               np = of_find_compatible_node(from, NULL, "fsl,imx28-fec");
+               if (!np)
+                       return;
+               from = np;
+
+               newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL);
+               if (!newmac)
+                       return;
+               newmac->value = newmac + 1;
+               newmac->length = 6;
+
+               newmac->name = kstrdup("local-mac-address", GFP_KERNEL);
+               if (!newmac->name) {
+                       kfree(newmac);
+                       return;
+               }
+
+               /*
+                * OCOTP only stores the last 4 octets for each mac address,
+                * so hard-code OUI here.
+                */
+               macaddr = newmac->value;
+               switch (oui) {
+               case OUI_FSL:
+                       macaddr[0] = 0x00;
+                       macaddr[1] = 0x04;
+                       macaddr[2] = 0x9f;
+                       break;
+               case OUI_DENX:
+                       macaddr[0] = 0xc0;
+                       macaddr[1] = 0xe5;
+                       macaddr[2] = 0x4e;
+                       break;
+               }
+               val = ocotp[i];
+               macaddr[3] = (val >> 16) & 0xff;
+               macaddr[4] = (val >> 8) & 0xff;
+               macaddr[5] = (val >> 0) & 0xff;
+
+               oldmac = of_find_property(np, newmac->name, NULL);
+               if (oldmac)
+                       prom_update_property(np, newmac, oldmac);
+               else
+                       prom_add_property(np, newmac);
+       }
+}
+
+static void __init imx23_evk_init(void)
+{
+       mxsfb_pdata.mode_list = mx23evk_video_modes;
+       mxsfb_pdata.mode_count = ARRAY_SIZE(mx23evk_video_modes);
+       mxsfb_pdata.default_bpp = 32;
+       mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT;
+}
+
+static inline void enable_clk_enet_out(void)
 {
-       struct clk *clk;
+       struct clk *clk = clk_get_sys("enet_out", NULL);
 
-       /* Enable fec phy clock */
-       clk = clk_get_sys("enet_out", NULL);
        if (!IS_ERR(clk))
                clk_prepare_enable(clk);
 }
 
+static void __init imx28_evk_init(void)
+{
+       enable_clk_enet_out();
+       update_fec_mac_prop(OUI_FSL);
+
+       mxsfb_pdata.mode_list = mx28evk_video_modes;
+       mxsfb_pdata.mode_count = ARRAY_SIZE(mx28evk_video_modes);
+       mxsfb_pdata.default_bpp = 32;
+       mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT;
+}
+
+static void __init m28evk_init(void)
+{
+       enable_clk_enet_out();
+       update_fec_mac_prop(OUI_DENX);
+
+       mxsfb_pdata.mode_list = m28evk_video_modes;
+       mxsfb_pdata.mode_count = ARRAY_SIZE(m28evk_video_modes);
+       mxsfb_pdata.default_bpp = 16;
+       mxsfb_pdata.ld_intf_width = STMLCDIF_18BIT;
+}
+
+static int apx4devkit_phy_fixup(struct phy_device *phy)
+{
+       phy->dev_flags |= MICREL_PHY_50MHZ_CLK;
+       return 0;
+}
+
+static void __init apx4devkit_init(void)
+{
+       enable_clk_enet_out();
+
+       if (IS_BUILTIN(CONFIG_PHYLIB))
+               phy_register_fixup_for_uid(PHY_ID_KS8051, MICREL_PHY_ID_MASK,
+                                          apx4devkit_phy_fixup);
+
+       mxsfb_pdata.mode_list = apx4devkit_video_modes;
+       mxsfb_pdata.mode_count = ARRAY_SIZE(apx4devkit_video_modes);
+       mxsfb_pdata.default_bpp = 32;
+       mxsfb_pdata.ld_intf_width = STMLCDIF_24BIT;
+}
+
 static void __init mxs_machine_init(void)
 {
        if (of_machine_is_compatible("fsl,imx28-evk"))
                imx28_evk_init();
+       else if (of_machine_is_compatible("fsl,imx23-evk"))
+               imx23_evk_init();
+       else if (of_machine_is_compatible("denx,m28evk"))
+               m28evk_init();
+       else if (of_machine_is_compatible("bluegiga,apx4devkit"))
+               apx4devkit_init();
 
        of_platform_populate(NULL, of_default_bus_match_table,
-                               NULL, NULL);
+                            mxs_auxdata_lookup, NULL);
 }
 
 static const char *imx23_dt_compat[] __initdata = {
        "fsl,imx23-evk",
+       "fsl,stmp378x_devb"
+       "olimex,imx23-olinuxino",
        "fsl,imx23",
        NULL,
 };
 
 static const char *imx28_dt_compat[] __initdata = {
+       "bluegiga,apx4devkit",
+       "crystalfontz,cfa10036",
+       "denx,m28evk",
        "fsl,imx28-evk",
+       "karo,tx28",
        "fsl,imx28",
        NULL,
 };
index 9a7b08b2a92559caf1028df076040c5e5dc798ae..0f71f82101cc00bcf20e831d8e61dc780f276448 100644 (file)
@@ -11,7 +11,7 @@
 #include <linux/gpio.h>
 
 #include <mach/iomux-mx28.h>
-#include "../devices-mx28.h"
+#include "devices-mx28.h"
 
 #include "module-tx28.h"
 
index a6bbd1a7b4e7d1c4d053b462386afe5a432dffad..a42c9a33d3bf54472ae101ddef035e58ca873463 100644 (file)
@@ -7,8 +7,6 @@
 
 # Object file lists.
 
-obj-y                  += clock.o
-
 # Cpu revision
 obj-$(CONFIG_NOMADIK_8815) += cpu-8815.o
 
index 2e8d3e176bc70b7216b5b8aa818b648ae63ebee0..f4535a7dadf537d7ffc0a691598db24103ba4ab1 100644 (file)
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
+#include <linux/amba/mmci.h>
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/onenand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/i2c.h>
 #include <linux/io.h>
 #include <asm/hardware/vic.h>
 #include <asm/sizes.h>
@@ -185,16 +187,28 @@ static void __init nhk8815_onenand_init(void)
 #endif
 }
 
-static AMBA_APB_DEVICE(uart0, "uart0", 0, NOMADIK_UART0_BASE,
-       { IRQ_UART0 }, NULL);
+static struct mmci_platform_data mmcsd_plat_data = {
+       .ocr_mask = MMC_VDD_29_30,
+       .f_max = 48000000,
+       .gpio_wp = -1,
+       .gpio_cd = 111,
+       .cd_invert = true,
+       .capabilities = MMC_CAP_MMC_HIGHSPEED |
+       MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA,
+};
 
-static AMBA_APB_DEVICE(uart1, "uart1", 0, NOMADIK_UART1_BASE,
-       { IRQ_UART1 }, NULL);
+static int __init nhk8815_mmcsd_init(void)
+{
+       int ret;
 
-static struct amba_device *amba_devs[] __initdata = {
-       &uart0_device,
-       &uart1_device,
-};
+       ret = gpio_request(112, "card detect bias");
+       if (ret)
+               return ret;
+       gpio_direction_output(112, 0);
+       amba_apb_device_add(NULL, "mmci", NOMADIK_SDI_BASE, SZ_4K, IRQ_SDMMC, 0, &mmcsd_plat_data, 0x10180180);
+       return 0;
+}
+module_init(nhk8815_mmcsd_init);
 
 static struct resource nhk8815_eth_resources[] = {
        {
@@ -253,17 +267,46 @@ static struct sys_timer nomadik_timer = {
        .init   = nomadik_timer_init,
 };
 
+static struct i2c_board_info __initdata nhk8815_i2c0_devices[] = {
+       {
+               I2C_BOARD_INFO("stw4811", 0x2d),
+       },
+};
+
+static struct i2c_board_info __initdata nhk8815_i2c1_devices[] = {
+       {
+               I2C_BOARD_INFO("camera", 0x10),
+       },
+       {
+               I2C_BOARD_INFO("stw5095", 0x1a),
+       },
+       {
+               I2C_BOARD_INFO("lis3lv02dl", 0x1d),
+       },
+};
+
+static struct i2c_board_info __initdata nhk8815_i2c2_devices[] = {
+       {
+               I2C_BOARD_INFO("stw4811-usb", 0x2d),
+       },
+};
+
 static void __init nhk8815_platform_init(void)
 {
-       int i;
-
        cpu8815_platform_init();
        nhk8815_onenand_init();
        platform_add_devices(nhk8815_platform_devices,
                             ARRAY_SIZE(nhk8815_platform_devices));
 
-       for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
-               amba_device_register(amba_devs[i], &iomem_resource);
+       amba_apb_device_add(NULL, "uart0", NOMADIK_UART0_BASE, SZ_4K, IRQ_UART0, 0, NULL, 0);
+       amba_apb_device_add(NULL, "uart1", NOMADIK_UART1_BASE, SZ_4K, IRQ_UART1, 0, NULL, 0);
+
+       i2c_register_board_info(0, nhk8815_i2c0_devices,
+                               ARRAY_SIZE(nhk8815_i2c0_devices));
+       i2c_register_board_info(1, nhk8815_i2c1_devices,
+                               ARRAY_SIZE(nhk8815_i2c1_devices));
+       i2c_register_board_info(2, nhk8815_i2c2_devices,
+                               ARRAY_SIZE(nhk8815_i2c2_devices));
 }
 
 MACHINE_START(NOMADIK, "NHK8815")
diff --git a/arch/arm/mach-nomadik/clock.c b/arch/arm/mach-nomadik/clock.c
deleted file mode 100644 (file)
index 48a59f2..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- *  linux/arch/arm/mach-nomadik/clock.c
- *
- *  Copyright (C) 2009 Alessandro Rubini
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
-#include "clock.h"
-
-/*
- * The nomadik board uses generic clocks, but the serial pl011 file
- * calls clk_enable(), clk_disable(), clk_get_rate(), so we provide them
- */
-unsigned long clk_get_rate(struct clk *clk)
-{
-       return clk->rate;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-/* enable and disable do nothing */
-int clk_enable(struct clk *clk)
-{
-       return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_disable);
-
-static struct clk clk_24 = {
-       .rate = 2400000,
-};
-
-static struct clk clk_48 = {
-       .rate = 48 * 1000 * 1000,
-};
-
-/*
- * Catch-all default clock to satisfy drivers using the clk API.  We don't
- * model the actual hardware clocks yet.
- */
-static struct clk clk_default;
-
-#define CLK(_clk, dev)                         \
-       {                                       \
-               .clk            = _clk,         \
-               .dev_id         = dev,          \
-       }
-
-static struct clk_lookup lookups[] = {
-       {
-               .con_id         = "apb_pclk",
-               .clk            = &clk_default,
-       },
-       CLK(&clk_24, "mtu0"),
-       CLK(&clk_24, "mtu1"),
-       CLK(&clk_48, "uart0"),
-       CLK(&clk_48, "uart1"),
-       CLK(&clk_default, "gpio.0"),
-       CLK(&clk_default, "gpio.1"),
-       CLK(&clk_default, "gpio.2"),
-       CLK(&clk_default, "gpio.3"),
-       CLK(&clk_default, "rng"),
-};
-
-int __init clk_init(void)
-{
-       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-       return 0;
-}
diff --git a/arch/arm/mach-nomadik/clock.h b/arch/arm/mach-nomadik/clock.h
deleted file mode 100644 (file)
index 78da2e7..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-
-/*
- *  linux/arch/arm/mach-nomadik/clock.h
- *
- *  Copyright (C) 2009 Alessandro Rubini
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-struct clk {
-       unsigned long           rate;
-};
-
-int __init clk_init(void);
index 27f43a46985ee15c33551ab582bafb45f5783fdd..6fd8e46567a4e602fc15bed22f97f8661e7dc1c5 100644 (file)
 #include <linux/amba/bus.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_data/clk-nomadik.h>
 
 #include <plat/gpio-nomadik.h>
 #include <mach/hardware.h>
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
 
-#include "clock.h"
 #include "cpu-8815.h"
 
-#define __MEM_4K_RESOURCE(x) \
-       .res = {.start = (x), .end = (x) + SZ_4K - 1, .flags = IORESOURCE_MEM}
-
 /* The 8815 has 4 GPIO blocks, let's register them immediately */
-
-#define GPIO_RESOURCE(block)                                           \
-       {                                                               \
-               .start  = NOMADIK_GPIO##block##_BASE,                   \
-               .end    = NOMADIK_GPIO##block##_BASE + SZ_4K - 1,       \
-               .flags  = IORESOURCE_MEM,                               \
-       },                                                              \
-       {                                                               \
-               .start  = IRQ_GPIO##block,                              \
-               .end    = IRQ_GPIO##block,                              \
-               .flags  = IORESOURCE_IRQ,                               \
-       }
-
-#define GPIO_DEVICE(block)                                             \
-       {                                                               \
-               .name           = "gpio",                               \
-               .id             = block,                                \
-               .num_resources  = 2,                                    \
-               .resource       = &cpu8815_gpio_resources[block * 2],   \
-               .dev = {                                                \
-                       .platform_data = &cpu8815_gpio[block],          \
-               },                                                      \
-       }
-
-static struct nmk_gpio_platform_data cpu8815_gpio[] = {
-       {
-               .name = "GPIO-0-31",
-               .first_gpio = 0,
-               .first_irq = NOMADIK_GPIO_TO_IRQ(0),
-       }, {
-               .name = "GPIO-32-63",
-               .first_gpio = 32,
-               .first_irq = NOMADIK_GPIO_TO_IRQ(32),
-       }, {
-               .name = "GPIO-64-95",
-               .first_gpio = 64,
-               .first_irq = NOMADIK_GPIO_TO_IRQ(64),
-       }, {
-               .name = "GPIO-96-127", /* 124..127 not routed to pin */
-               .first_gpio = 96,
-               .first_irq = NOMADIK_GPIO_TO_IRQ(96),
-       }
+static resource_size_t __initdata cpu8815_gpio_base[] = {
+       NOMADIK_GPIO0_BASE,
+       NOMADIK_GPIO1_BASE,
+       NOMADIK_GPIO2_BASE,
+       NOMADIK_GPIO3_BASE,
 };
 
-static struct resource cpu8815_gpio_resources[] = {
-       GPIO_RESOURCE(0),
-       GPIO_RESOURCE(1),
-       GPIO_RESOURCE(2),
-       GPIO_RESOURCE(3),
-};
-
-static struct platform_device cpu8815_platform_gpio[] = {
-       GPIO_DEVICE(0),
-       GPIO_DEVICE(1),
-       GPIO_DEVICE(2),
-       GPIO_DEVICE(3),
-};
+static struct platform_device *
+cpu8815_add_gpio(int id, resource_size_t addr, int irq,
+                struct nmk_gpio_platform_data *pdata)
+{
+       struct resource resources[] = {
+               {
+                       .start  = addr,
+                       .end    = addr + 127,
+                       .flags  = IORESOURCE_MEM,
+               },
+               {
+                       .start  = irq,
+                       .end    = irq,
+                       .flags  = IORESOURCE_IRQ,
+               }
+       };
+
+       return platform_device_register_resndata(NULL, "gpio", id,
+                               resources, ARRAY_SIZE(resources),
+                               pdata, sizeof(*pdata));
+}
 
-static AMBA_APB_DEVICE(cpu8815_amba_rng, "rng", 0, NOMADIK_RNG_BASE, { }, NULL);
+void cpu8815_add_gpios(resource_size_t *base, int num, int irq,
+                      struct nmk_gpio_platform_data *pdata)
+{
+       int first = 0;
+       int i;
 
-static struct platform_device *platform_devs[] __initdata = {
-       cpu8815_platform_gpio + 0,
-       cpu8815_platform_gpio + 1,
-       cpu8815_platform_gpio + 2,
-       cpu8815_platform_gpio + 3,
-};
+       for (i = 0; i < num; i++, first += 32, irq++) {
+               pdata->first_gpio = first;
+               pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first);
+               pdata->num_gpio = 32;
 
-static struct amba_device *amba_devs[] __initdata = {
-       &cpu8815_amba_rng_device
-};
+               cpu8815_add_gpio(i, base[i], irq, pdata);
+       }
+}
 
 static int __init cpu8815_init(void)
 {
-       int i;
-
-       platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
-       for (i = 0; i < ARRAY_SIZE(amba_devs); i++)
-               amba_device_register(amba_devs[i], &iomem_resource);
+       struct nmk_gpio_platform_data pdata = {
+               /* No custom data yet */
+       };
+
+       cpu8815_add_gpios(cpu8815_gpio_base, ARRAY_SIZE(cpu8815_gpio_base),
+                         IRQ_GPIO0, &pdata);
+       amba_apb_device_add(NULL, "rng", NOMADIK_RNG_BASE, SZ_4K, 0, 0, NULL, 0);
+       amba_apb_device_add(NULL, "rtc-pl031", NOMADIK_RTC_BASE, SZ_4K, IRQ_RTC_RTT, 0, NULL, 0);
        return 0;
 }
 arch_initcall(cpu8815_init);
@@ -147,7 +123,7 @@ void __init cpu8815_init_irq(void)
         * Init clocks here so that they are available for system timer
         * initialization.
         */
-       clk_init();
+       nomadik_clk_init();
 }
 
 /*
index 0fc2f6f1cc979097cf83de13a924c7fb05a105f1..6d14454d46094fc4bdd00c66cabff3a0abb800f9 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/i2c-gpio.h>
 #include <linux/platform_device.h>
 #include <plat/gpio-nomadik.h>
+#include <plat/pincfg.h>
 
 /*
  * There are two busses in the 8815NHK.
  * use bit-bang through GPIO by now, to keep things simple
  */
 
+/* I2C0 connected to the STw4811 power management chip */
 static struct i2c_gpio_platform_data nhk8815_i2c_data0 = {
        /* keep defaults for timeouts; pins are push-pull bidirectional */
        .scl_pin = 62,
        .sda_pin = 63,
 };
 
+/* I2C1 connected to various sensors */
 static struct i2c_gpio_platform_data nhk8815_i2c_data1 = {
        /* keep defaults for timeouts; pins are push-pull bidirectional */
        .scl_pin = 53,
        .sda_pin = 54,
 };
 
-/* first bus: GPIO XX and YY */
+/* I2C2 connected to the USB portions of the STw4811 only */
+static struct i2c_gpio_platform_data nhk8815_i2c_data2 = {
+       /* keep defaults for timeouts; pins are push-pull bidirectional */
+       .scl_pin = 73,
+       .sda_pin = 74,
+};
+
 static struct platform_device nhk8815_i2c_dev0 = {
        .name   = "i2c-gpio",
        .id     = 0,
@@ -32,7 +41,7 @@ static struct platform_device nhk8815_i2c_dev0 = {
                .platform_data = &nhk8815_i2c_data0,
        },
 };
-/* second bus: GPIO XX and YY */
+
 static struct platform_device nhk8815_i2c_dev1 = {
        .name   = "i2c-gpio",
        .id     = 1,
@@ -41,15 +50,29 @@ static struct platform_device nhk8815_i2c_dev1 = {
        },
 };
 
+static struct platform_device nhk8815_i2c_dev2 = {
+       .name   = "i2c-gpio",
+       .id     = 2,
+       .dev    = {
+               .platform_data = &nhk8815_i2c_data2,
+       },
+};
+
+static pin_cfg_t cpu8815_pins_i2c[] = {
+       PIN_CFG_INPUT(62, GPIO, PULLUP),
+       PIN_CFG_INPUT(63, GPIO, PULLUP),
+       PIN_CFG_INPUT(53, GPIO, PULLUP),
+       PIN_CFG_INPUT(54, GPIO, PULLUP),
+       PIN_CFG_INPUT(73, GPIO, PULLUP),
+       PIN_CFG_INPUT(74, GPIO, PULLUP),
+};
+
 static int __init nhk8815_i2c_init(void)
 {
-       nmk_gpio_set_mode(nhk8815_i2c_data0.scl_pin, NMK_GPIO_ALT_GPIO);
-       nmk_gpio_set_mode(nhk8815_i2c_data0.sda_pin, NMK_GPIO_ALT_GPIO);
+       nmk_config_pins(cpu8815_pins_i2c, ARRAY_SIZE(cpu8815_pins_i2c));
        platform_device_register(&nhk8815_i2c_dev0);
-
-       nmk_gpio_set_mode(nhk8815_i2c_data1.scl_pin, NMK_GPIO_ALT_GPIO);
-       nmk_gpio_set_mode(nhk8815_i2c_data1.sda_pin, NMK_GPIO_ALT_GPIO);
        platform_device_register(&nhk8815_i2c_dev1);
+       platform_device_register(&nhk8815_i2c_dev2);
 
        return 0;
 }
@@ -58,6 +81,7 @@ static void __exit nhk8815_i2c_exit(void)
 {
        platform_device_unregister(&nhk8815_i2c_dev0);
        platform_device_unregister(&nhk8815_i2c_dev1);
+       platform_device_unregister(&nhk8815_i2c_dev2);
        return;
 }
 
index 8faabc5603987bed9237c2f8c2a8d9e0c5aeb6b6..a118e615f8650a81b100348abbbae3bc30b7c0ea 100644 (file)
 
 #include <mach/hardware.h>
 
-#define IRQ_VIC_START          0       /* first VIC interrupt is 0 */
+#define IRQ_VIC_START          1       /* first VIC interrupt is 1 */
 
 /*
  * Interrupt numbers generic for all Nomadik Chip cuts
  */
-#define IRQ_WATCHDOG                   0
-#define IRQ_SOFTINT                    1
-#define IRQ_CRYPTO                     2
-#define IRQ_OWM                                3
-#define IRQ_MTU0                       4
-#define IRQ_MTU1                       5
-#define IRQ_GPIO0                      6
-#define IRQ_GPIO1                      7
-#define IRQ_GPIO2                      8
-#define IRQ_GPIO3                      9
-#define IRQ_RTC_RTT                    10
-#define IRQ_SSP                                11
-#define IRQ_UART0                      12
-#define IRQ_DMA1                       13
-#define IRQ_CLCD_MDIF                  14
-#define IRQ_DMA0                       15
-#define IRQ_PWRFAIL                    16
-#define IRQ_UART1                      17
-#define IRQ_FIRDA                      18
-#define IRQ_MSP0                       19
-#define IRQ_I2C0                       20
-#define IRQ_I2C1                       21
-#define IRQ_SDMMC                      22
-#define IRQ_USBOTG                     23
-#define IRQ_SVA_IT0                    24
-#define IRQ_SVA_IT1                    25
-#define IRQ_SAA_IT0                    26
-#define IRQ_SAA_IT1                    27
-#define IRQ_UART2                      28
-#define IRQ_MSP2                       31
-#define IRQ_L2CC                       48
-#define IRQ_HPI                                49
-#define IRQ_SKE                                50
-#define IRQ_KP                         51
-#define IRQ_MEMST                      54
-#define IRQ_SGA_IT                     58
-#define IRQ_USBM                       60
-#define IRQ_MSP1                       62
+#define IRQ_WATCHDOG                   1
+#define IRQ_SOFTINT                    2
+#define IRQ_CRYPTO                     3
+#define IRQ_OWM                                4
+#define IRQ_MTU0                       5
+#define IRQ_MTU1                       6
+#define IRQ_GPIO0                      7
+#define IRQ_GPIO1                      8
+#define IRQ_GPIO2                      9
+#define IRQ_GPIO3                      10
+#define IRQ_RTC_RTT                    11
+#define IRQ_SSP                                12
+#define IRQ_UART0                      13
+#define IRQ_DMA1                       14
+#define IRQ_CLCD_MDIF                  15
+#define IRQ_DMA0                       16
+#define IRQ_PWRFAIL                    17
+#define IRQ_UART1                      18
+#define IRQ_FIRDA                      19
+#define IRQ_MSP0                       20
+#define IRQ_I2C0                       21
+#define IRQ_I2C1                       22
+#define IRQ_SDMMC                      23
+#define IRQ_USBOTG                     24
+#define IRQ_SVA_IT0                    25
+#define IRQ_SVA_IT1                    26
+#define IRQ_SAA_IT0                    27
+#define IRQ_SAA_IT1                    28
+#define IRQ_UART2                      29
+#define IRQ_MSP2                       30
+#define IRQ_L2CC                       49
+#define IRQ_HPI                                50
+#define IRQ_SKE                                51
+#define IRQ_KP                         52
+#define IRQ_MEMST                      55
+#define IRQ_SGA_IT                     59
+#define IRQ_USBM                       61
+#define IRQ_MSP1                       63
 
-#define NOMADIK_SOC_NR_IRQS            64
+#define NOMADIK_GPIO_OFFSET            (IRQ_VIC_START+64)
 
 /* After chip-specific IRQ numbers we have the GPIO ones */
 #define NOMADIK_NR_GPIO                        128 /* last 4 not wired to pins */
-#define NOMADIK_GPIO_TO_IRQ(gpio)      ((gpio) + NOMADIK_SOC_NR_IRQS)
-#define NOMADIK_IRQ_TO_GPIO(irq)       ((irq) - NOMADIK_SOC_NR_IRQS)
+#define NOMADIK_GPIO_TO_IRQ(gpio)      ((gpio) + NOMADIK_GPIO_OFFSET)
+#define NOMADIK_IRQ_TO_GPIO(irq)       ((irq) - NOMADIK_GPIO_OFFSET)
 #define NR_IRQS                                NOMADIK_GPIO_TO_IRQ(NOMADIK_NR_GPIO)
 
 /* Following two are used by entry_macro.S, to access our dual-vic */
@@ -79,4 +79,3 @@
 #define VIC_REG_IRQSR1         0x20
 
 #endif /* __ASM_ARCH_IRQS_H */
-
index f2f8a58470182c5d1d783b1a3496833f1b1dfbc7..c53469802c03cf0e79640e5b7af53ee7df83abbe 100644 (file)
 #include <plat/board-ams-delta.h>
 #include <plat/keypad.h>
 #include <plat/mux.h>
-#include <plat/usb.h>
 #include <plat/board.h>
 
 #include <mach/hardware.h>
 #include <mach/ams-delta-fiq.h>
 #include <mach/camera.h>
+#include <mach/usb.h>
 
 #include "iomap.h"
 #include "common.h"
index e75e2d55a2d72ba133c5e923389c03512058461e..6ec385e2b98e93553de87814452eacb95de775fb 100644 (file)
 #include <asm/mach/map.h>
 
 #include <plat/mux.h>
-#include <plat/usb.h>
 #include <plat/board.h>
+
+#include <mach/usb.h>
+
 #include "common.h"
 
 /* assume no Mini-AB port */
index a28e989a63f4369f94cd0081e11cb4f28f407215..44a4ab195fbc54ec0537d24328fed150216d8e3b 100644 (file)
 #include <plat/dma.h>
 #include <plat/tc.h>
 #include <plat/irda.h>
-#include <plat/usb.h>
 #include <plat/keypad.h>
 #include <plat/flash.h>
 
 #include <mach/hardware.h>
+#include <mach/usb.h>
 
 #include "common.h"
 #include "board-h2.h"
index 108a8640fc6f04c2c42c0accc0d6602716831ef0..86cb5a04a404e2ea3b8c89f5fb3051ab1d3583ec 100644 (file)
 
 #include <plat/mux.h>
 #include <plat/tc.h>
-#include <plat/usb.h>
 #include <plat/keypad.h>
 #include <plat/dma.h>
 #include <plat/flash.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
+#include <mach/usb.h>
 
 #include "common.h"
 #include "board-h3.h"
index 118a9d4a4c54a56b2bad8b261c60335b3f3a3f82..b3f6e943e6616ca8f82874e56fbe408c49de086f 100644 (file)
 #include <plat/omap7xx.h>
 #include <plat/board.h>
 #include <plat/keypad.h>
-#include <plat/usb.h>
 #include <plat/mmc.h>
 
 #include <mach/irqs.h>
+#include <mach/usb.h>
 
 #include "common.h"
 
index 7970223a559d552d270953905a2107e3dfb2446f..f21c2966daad7f4cd820ed1594e64a13756bf3a9 100644 (file)
 #include <plat/flash.h>
 #include <plat/fpga.h>
 #include <plat/tc.h>
-#include <plat/usb.h>
 #include <plat/keypad.h>
 #include <plat/mmc.h>
 
 #include <mach/hardware.h>
+#include <mach/usb.h>
 
 #include "iomap.h"
 #include "common.h"
index 7212ae97f44acfc1ff508fbca348a3ff26702a8a..4007a372481b9a9bfac27c9fa8d55d2ed672fa27 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/mach/map.h>
 
 #include <plat/mux.h>
-#include <plat/usb.h>
 #include <plat/board.h>
 #include <plat/keypad.h>
 #include <plat/lcd_mipid.h>
@@ -34,6 +33,7 @@
 #include <plat/clock.h>
 
 #include <mach/hardware.h>
+#include <mach/usb.h>
 
 #include "common.h"
 
index da8d872d3d1cddf00bdab9c3bdec4684ec585989..8784705edb60135aac86a8bc660b02a8e1f284f5 100644 (file)
 #include <asm/mach/map.h>
 
 #include <plat/flash.h>
-#include <plat/usb.h>
 #include <plat/mux.h>
 #include <plat/tc.h>
 
 #include <mach/hardware.h>
+#include <mach/usb.h>
 
 #include "common.h"
 
index 949b62a736931b0a74158727ca2ca2ecf488c6e8..26bcb9defcdc830ff7ae97d8667cef70b956b598 100644 (file)
@@ -35,7 +35,6 @@
 
 #include <plat/flash.h>
 #include <plat/mux.h>
-#include <plat/usb.h>
 #include <plat/tc.h>
 #include <plat/dma.h>
 #include <plat/board.h>
@@ -43,6 +42,7 @@
 #include <plat/keypad.h>
 
 #include <mach/hardware.h>
+#include <mach/usb.h>
 
 #include "common.h"
 
index 7f1e1cf2bf46a47e525338ff47398b2226ea997f..4d099446dfa888e1898227d35eb260e9ee8b203f 100644 (file)
@@ -35,7 +35,6 @@
 #include <plat/led.h>
 #include <plat/flash.h>
 #include <plat/mux.h>
-#include <plat/usb.h>
 #include <plat/dma.h>
 #include <plat/tc.h>
 #include <plat/board.h>
@@ -43,6 +42,7 @@
 #include <plat/keypad.h>
 
 #include <mach/hardware.h>
+#include <mach/usb.h>
 
 #include "common.h"
 
index 3c71c6bace2cd09489b358d6569c2652471040aa..cc71a26723efb0937294bfe777b10aa9a59ed746 100644 (file)
@@ -37,7 +37,6 @@
 
 #include <plat/flash.h>
 #include <plat/mux.h>
-#include <plat/usb.h>
 #include <plat/dma.h>
 #include <plat/tc.h>
 #include <plat/board.h>
@@ -45,6 +44,7 @@
 #include <plat/keypad.h>
 
 #include <mach/hardware.h>
+#include <mach/usb.h>
 
 #include "common.h"
 
index 3b7b82b136840ac05fcedaa1e9ba3da1617df96b..8c665bd16ac20b38195fa126ae4e21a7595d31d1 100644 (file)
 #include <plat/mux.h>
 #include <plat/dma.h>
 #include <plat/irda.h>
-#include <plat/usb.h>
 #include <plat/tc.h>
 #include <plat/board.h>
 #include <plat/keypad.h>
 #include <plat/board-sx1.h>
 
 #include <mach/hardware.h>
+#include <mach/usb.h>
 
 #include "common.h"
 
index afd67f0ec495160d4c5f996f8f81b6832b03e1c2..3497769eb353965adc1aa435c599b0bab252fb12 100644 (file)
 #include <plat/flash.h>
 #include <plat/mux.h>
 #include <plat/tc.h>
-#include <plat/usb.h>
+#include <plat/board.h>
 
 #include <mach/hardware.h>
+#include <mach/usb.h>
 
 #include "common.h"
 
index c6ce93f71d08d5bb1bb1d546024dfdb2f363d1d0..c007d80dfb6244396606dfd38281b7d8b6c1bfbf 100644 (file)
 #include <plat/clock.h>
 #include <plat/cpu.h>
 #include <plat/clkdev_omap.h>
+#include <plat/board.h>
 #include <plat/sram.h> /* for omap_sram_reprogram_clock() */
-#include <plat/usb.h>   /* for OTG_BASE */
 
 #include <mach/hardware.h>
+#include <mach/usb.h>   /* for OTG_BASE */
 
 #include "iomap.h"
 #include "clock.h"
diff --git a/arch/arm/mach-omap1/include/mach/usb.h b/arch/arm/mach-omap1/include/mach/usb.h
new file mode 100644 (file)
index 0000000..753cd5c
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * FIXME correct answer depends on hmc_mode,
+ * as does (on omap1) any nonzero value for config->otg port number
+ */
+#ifdef CONFIG_USB_GADGET_OMAP
+#define        is_usb0_device(config)  1
+#else
+#define        is_usb0_device(config)  0
+#endif
+
+struct omap_usb_config {
+       /* Configure drivers according to the connectors on your board:
+        *  - "A" connector (rectagular)
+        *      ... for host/OHCI use, set "register_host".
+        *  - "B" connector (squarish) or "Mini-B"
+        *      ... for device/gadget use, set "register_dev".
+        *  - "Mini-AB" connector (very similar to Mini-B)
+        *      ... for OTG use as device OR host, initialize "otg"
+        */
+       unsigned        register_host:1;
+       unsigned        register_dev:1;
+       u8              otg;    /* port number, 1-based:  usb1 == 2 */
+
+       u8              hmc_mode;
+
+       /* implicitly true if otg:  host supports remote wakeup? */
+       u8              rwc;
+
+       /* signaling pins used to talk to transceiver on usbN:
+        *  0 == usbN unused
+        *  2 == usb0-only, using internal transceiver
+        *  3 == 3 wire bidirectional
+        *  4 == 4 wire bidirectional
+        *  6 == 6 wire unidirectional (or TLL)
+        */
+       u8              pins[3];
+
+       struct platform_device *udc_device;
+       struct platform_device *ohci_device;
+       struct platform_device *otg_device;
+
+       u32 (*usb0_init)(unsigned nwires, unsigned is_device);
+       u32 (*usb1_init)(unsigned nwires);
+       u32 (*usb2_init)(unsigned nwires, unsigned alt_pingroup);
+
+       int (*ocpi_enable)(void);
+};
+
+void omap_otg_init(struct omap_usb_config *config);
+
+#if defined(CONFIG_USB) || defined(CONFIG_USB_MODULE)
+void omap1_usb_init(struct omap_usb_config *pdata);
+#else
+static inline void omap1_usb_init(struct omap_usb_config *pdata)
+{
+}
+#endif
+
+#define OMAP1_OTG_BASE                 0xfffb0400
+#define OMAP1_UDC_BASE                 0xfffb4000
+#define OMAP1_OHCI_BASE                        0xfffba000
+
+#define OMAP2_OHCI_BASE                        0x4805e000
+#define OMAP2_UDC_BASE                 0x4805e200
+#define OMAP2_OTG_BASE                 0x4805e300
+#define OTG_BASE                       OMAP1_OTG_BASE
+#define UDC_BASE                       OMAP1_UDC_BASE
+#define OMAP_OHCI_BASE                 OMAP1_OHCI_BASE
+
+/*
+ * OTG and transceiver registers, for OMAPs starting with ARM926
+ */
+#define OTG_REV                                (OTG_BASE + 0x00)
+#define OTG_SYSCON_1                   (OTG_BASE + 0x04)
+#      define   USB2_TRX_MODE(w)       (((w)>>24)&0x07)
+#      define   USB1_TRX_MODE(w)       (((w)>>20)&0x07)
+#      define   USB0_TRX_MODE(w)       (((w)>>16)&0x07)
+#      define   OTG_IDLE_EN            (1 << 15)
+#      define   HST_IDLE_EN            (1 << 14)
+#      define   DEV_IDLE_EN            (1 << 13)
+#      define   OTG_RESET_DONE         (1 << 2)
+#      define   OTG_SOFT_RESET         (1 << 1)
+#define OTG_SYSCON_2                   (OTG_BASE + 0x08)
+#      define   OTG_EN                 (1 << 31)
+#      define   USBX_SYNCHRO           (1 << 30)
+#      define   OTG_MST16              (1 << 29)
+#      define   SRP_GPDATA             (1 << 28)
+#      define   SRP_GPDVBUS            (1 << 27)
+#      define   SRP_GPUVBUS(w)         (((w)>>24)&0x07)
+#      define   A_WAIT_VRISE(w)        (((w)>>20)&0x07)
+#      define   B_ASE_BRST(w)          (((w)>>16)&0x07)
+#      define   SRP_DPW                (1 << 14)
+#      define   SRP_DATA               (1 << 13)
+#      define   SRP_VBUS               (1 << 12)
+#      define   OTG_PADEN              (1 << 10)
+#      define   HMC_PADEN              (1 << 9)
+#      define   UHOST_EN               (1 << 8)
+#      define   HMC_TLLSPEED           (1 << 7)
+#      define   HMC_TLLATTACH          (1 << 6)
+#      define   OTG_HMC(w)             (((w)>>0)&0x3f)
+#define OTG_CTRL                       (OTG_BASE + 0x0c)
+#      define   OTG_USB2_EN            (1 << 29)
+#      define   OTG_USB2_DP            (1 << 28)
+#      define   OTG_USB2_DM            (1 << 27)
+#      define   OTG_USB1_EN            (1 << 26)
+#      define   OTG_USB1_DP            (1 << 25)
+#      define   OTG_USB1_DM            (1 << 24)
+#      define   OTG_USB0_EN            (1 << 23)
+#      define   OTG_USB0_DP            (1 << 22)
+#      define   OTG_USB0_DM            (1 << 21)
+#      define   OTG_ASESSVLD           (1 << 20)
+#      define   OTG_BSESSEND           (1 << 19)
+#      define   OTG_BSESSVLD           (1 << 18)
+#      define   OTG_VBUSVLD            (1 << 17)
+#      define   OTG_ID                 (1 << 16)
+#      define   OTG_DRIVER_SEL         (1 << 15)
+#      define   OTG_A_SETB_HNPEN       (1 << 12)
+#      define   OTG_A_BUSREQ           (1 << 11)
+#      define   OTG_B_HNPEN            (1 << 9)
+#      define   OTG_B_BUSREQ           (1 << 8)
+#      define   OTG_BUSDROP            (1 << 7)
+#      define   OTG_PULLDOWN           (1 << 5)
+#      define   OTG_PULLUP             (1 << 4)
+#      define   OTG_DRV_VBUS           (1 << 3)
+#      define   OTG_PD_VBUS            (1 << 2)
+#      define   OTG_PU_VBUS            (1 << 1)
+#      define   OTG_PU_ID              (1 << 0)
+#define OTG_IRQ_EN                     (OTG_BASE + 0x10)       /* 16-bit */
+#      define   DRIVER_SWITCH          (1 << 15)
+#      define   A_VBUS_ERR             (1 << 13)
+#      define   A_REQ_TMROUT           (1 << 12)
+#      define   A_SRP_DETECT           (1 << 11)
+#      define   B_HNP_FAIL             (1 << 10)
+#      define   B_SRP_TMROUT           (1 << 9)
+#      define   B_SRP_DONE             (1 << 8)
+#      define   B_SRP_STARTED          (1 << 7)
+#      define   OPRT_CHG               (1 << 0)
+#define OTG_IRQ_SRC                    (OTG_BASE + 0x14)       /* 16-bit */
+       // same bits as in IRQ_EN
+#define OTG_OUTCTRL                    (OTG_BASE + 0x18)       /* 16-bit */
+#      define   OTGVPD                 (1 << 14)
+#      define   OTGVPU                 (1 << 13)
+#      define   OTGPUID                (1 << 12)
+#      define   USB2VDR                (1 << 10)
+#      define   USB2PDEN               (1 << 9)
+#      define   USB2PUEN               (1 << 8)
+#      define   USB1VDR                (1 << 6)
+#      define   USB1PDEN               (1 << 5)
+#      define   USB1PUEN               (1 << 4)
+#      define   USB0VDR                (1 << 2)
+#      define   USB0PDEN               (1 << 1)
+#      define   USB0PUEN               (1 << 0)
+#define OTG_TEST                       (OTG_BASE + 0x20)       /* 16-bit */
+#define OTG_VENDOR_CODE                        (OTG_BASE + 0xfc)       /* 16-bit */
+
+/*-------------------------------------------------------------------------*/
+
+/* OMAP1 */
+#define        USB_TRANSCEIVER_CTRL            (0xfffe1000 + 0x0064)
+#      define  CONF_USB2_UNI_R         (1 << 8)
+#      define  CONF_USB1_UNI_R         (1 << 7)
+#      define  CONF_USB_PORT0_R(x)     (((x)>>4)&0x7)
+#      define  CONF_USB0_ISOLATE_R     (1 << 3)
+#      define  CONF_USB_PWRDN_DM_R     (1 << 2)
+#      define  CONF_USB_PWRDN_DP_R     (1 << 1)
index 64c65bcb2d67574af11b0af2c64e8374317b7419..aa81593db1af9f054058f2c1ed87d295e15bbafd 100644 (file)
@@ -140,7 +140,8 @@ static int __init omap1_dm_timer_init(void)
                }
 
                pdata->set_timer_src = omap1_dm_timer_set_src;
-               pdata->needs_manual_reset = 1;
+               pdata->timer_capability = OMAP_TIMER_ALWON |
+                               OMAP_TIMER_NEEDS_RESET;
 
                ret = platform_device_add_data(pdev, pdata, sizeof(*pdata));
                if (ret) {
index e61afd9227662f123620a3243ed0a92d89cbe30b..65f88176fba87288a154e708979b6c0c9f98196c 100644 (file)
@@ -27,7 +27,8 @@
 #include <asm/irq.h>
 
 #include <plat/mux.h>
-#include <plat/usb.h>
+
+#include <mach/usb.h>
 
 #include "common.h"
 
 #define INT_USB_IRQ_HGEN       INT_USB_HHC_1
 #define INT_USB_IRQ_OTG                IH2_BASE + 8
 
+#ifdef CONFIG_ARCH_OMAP_OTG
+
+void __init
+omap_otg_init(struct omap_usb_config *config)
+{
+       u32             syscon;
+       int             alt_pingroup = 0;
+
+       /* NOTE:  no bus or clock setup (yet?) */
+
+       syscon = omap_readl(OTG_SYSCON_1) & 0xffff;
+       if (!(syscon & OTG_RESET_DONE))
+               pr_debug("USB resets not complete?\n");
+
+       //omap_writew(0, OTG_IRQ_EN);
+
+       /* pin muxing and transceiver pinouts */
+       if (config->pins[0] > 2)        /* alt pingroup 2 */
+               alt_pingroup = 1;
+       syscon |= config->usb0_init(config->pins[0], is_usb0_device(config));
+       syscon |= config->usb1_init(config->pins[1]);
+       syscon |= config->usb2_init(config->pins[2], alt_pingroup);
+       pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1));
+       omap_writel(syscon, OTG_SYSCON_1);
+
+       syscon = config->hmc_mode;
+       syscon |= USBX_SYNCHRO | (4 << 16) /* B_ASE0_BRST */;
+#ifdef CONFIG_USB_OTG
+       if (config->otg)
+               syscon |= OTG_EN;
+#endif
+       if (cpu_class_is_omap1())
+               pr_debug("USB_TRANSCEIVER_CTRL = %03x\n",
+                        omap_readl(USB_TRANSCEIVER_CTRL));
+       pr_debug("OTG_SYSCON_2 = %08x\n", omap_readl(OTG_SYSCON_2));
+       omap_writel(syscon, OTG_SYSCON_2);
+
+       printk("USB: hmc %d", config->hmc_mode);
+       if (!alt_pingroup)
+               printk(", usb2 alt %d wires", config->pins[2]);
+       else if (config->pins[0])
+               printk(", usb0 %d wires%s", config->pins[0],
+                       is_usb0_device(config) ? " (dev)" : "");
+       if (config->pins[1])
+               printk(", usb1 %d wires", config->pins[1]);
+       if (!alt_pingroup && config->pins[2])
+               printk(", usb2 %d wires", config->pins[2]);
+       if (config->otg)
+               printk(", Mini-AB on usb%d", config->otg - 1);
+       printk("\n");
+
+       if (cpu_class_is_omap1()) {
+               u16 w;
+
+               /* leave USB clocks/controllers off until needed */
+               w = omap_readw(ULPD_SOFT_REQ);
+               w &= ~SOFT_USB_CLK_REQ;
+               omap_writew(w, ULPD_SOFT_REQ);
+
+               w = omap_readw(ULPD_CLOCK_CTRL);
+               w &= ~USB_MCLK_EN;
+               w |= DIS_USB_PVCI_CLK;
+               omap_writew(w, ULPD_CLOCK_CTRL);
+       }
+       syscon = omap_readl(OTG_SYSCON_1);
+       syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN;
+
+#ifdef CONFIG_USB_GADGET_OMAP
+       if (config->otg || config->register_dev) {
+               struct platform_device *udc_device = config->udc_device;
+               int status;
+
+               syscon &= ~DEV_IDLE_EN;
+               udc_device->dev.platform_data = config;
+               status = platform_device_register(udc_device);
+               if (status)
+                       pr_debug("can't register UDC device, %d\n", status);
+       }
+#endif
+
+#if    defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
+       if (config->otg || config->register_host) {
+               struct platform_device *ohci_device = config->ohci_device;
+               int status;
+
+               syscon &= ~HST_IDLE_EN;
+               ohci_device->dev.platform_data = config;
+               status = platform_device_register(ohci_device);
+               if (status)
+                       pr_debug("can't register OHCI device, %d\n", status);
+       }
+#endif
+
+#ifdef CONFIG_USB_OTG
+       if (config->otg) {
+               struct platform_device *otg_device = config->otg_device;
+               int status;
+
+               syscon &= ~OTG_IDLE_EN;
+               otg_device->dev.platform_data = config;
+               status = platform_device_register(otg_device);
+               if (status)
+                       pr_debug("can't register OTG device, %d\n", status);
+       }
+#endif
+       pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1));
+       omap_writel(syscon, OTG_SYSCON_1);
+}
+
+#else
+void omap_otg_init(struct omap_usb_config *config) {}
+#endif
+
 #ifdef CONFIG_USB_GADGET_OMAP
 
 static struct resource udc_resources[] = {
index 4cf5142f22ccd9543f6795f491a24a64bc3d12a9..dd0fbf76ac793d87580c1d750bad8983a25ef62e 100644 (file)
@@ -9,7 +9,7 @@ config ARCH_OMAP2PLUS_TYPICAL
        select REGULATOR
        select PM_RUNTIME
        select VFP
-       select NEON if ARCH_OMAP3 || ARCH_OMAP4
+       select NEON if ARCH_OMAP3 || ARCH_OMAP4 || SOC_OMAP5
        select SERIAL_OMAP
        select SERIAL_OMAP_CONSOLE
        select I2C
@@ -21,12 +21,16 @@ config ARCH_OMAP2PLUS_TYPICAL
        help
          Compile a kernel suitable for booting most boards
 
+config SOC_HAS_OMAP2_SDRC
+       bool "OMAP2 SDRAM Controller support"
+
 config ARCH_OMAP2
        bool "TI OMAP2"
        depends on ARCH_OMAP2PLUS
        default y
        select CPU_V6
        select MULTI_IRQ_HANDLER
+       select SOC_HAS_OMAP2_SDRC
 
 config ARCH_OMAP3
        bool "TI OMAP3"
@@ -35,9 +39,11 @@ config ARCH_OMAP3
        select CPU_V7
        select USB_ARCH_HAS_EHCI if USB_SUPPORT
        select ARCH_HAS_OPP
+       select PM_RUNTIME if CPU_IDLE
        select PM_OPP if PM
        select ARM_CPU_SUSPEND if PM
        select MULTI_IRQ_HANDLER
+       select SOC_HAS_OMAP2_SDRC
 
 config ARCH_OMAP4
        bool "TI OMAP4"
@@ -52,10 +58,17 @@ config ARCH_OMAP4
        select PL310_ERRATA_727915
        select ARM_ERRATA_720789
        select ARCH_HAS_OPP
+       select PM_RUNTIME if CPU_IDLE
        select PM_OPP if PM
        select USB_ARCH_HAS_EHCI if USB_SUPPORT
        select ARM_CPU_SUSPEND if PM
 
+config SOC_OMAP5
+       bool "TI OMAP5"
+       select CPU_V7
+       select ARM_GIC
+       select HAVE_SMP
+
 comment "OMAP Core Type"
        depends on ARCH_OMAP2
 
@@ -64,19 +77,19 @@ config SOC_OMAP2420
        depends on ARCH_OMAP2
        default y
        select OMAP_DM_TIMER
-       select ARCH_OMAP_OTG
+       select SOC_HAS_OMAP2_SDRC
 
 config SOC_OMAP2430
        bool "OMAP2430 support"
        depends on ARCH_OMAP2
        default y
-       select ARCH_OMAP_OTG
+       select SOC_HAS_OMAP2_SDRC
 
 config SOC_OMAP3430
        bool "OMAP3430 support"
        depends on ARCH_OMAP3
        default y
-       select ARCH_OMAP_OTG
+       select SOC_HAS_OMAP2_SDRC
 
 config SOC_TI81XX
        bool "TI81XX support"
@@ -85,8 +98,10 @@ config SOC_TI81XX
 
 config SOC_AM33XX
        bool "AM33XX support"
-       depends on ARCH_OMAP3
        default y
+       select CPU_V7
+       select ARM_CPU_SUSPEND if PM
+       select MULTI_IRQ_HANDLER
 
 config OMAP_PACKAGE_ZAF
        bool
index fa742f3c262947313f23df2b65e8b36521cf71d9..f6a24b3f9c4f7b4dd3e381eb3ff7823444d99e70 100644 (file)
@@ -6,7 +6,7 @@
 obj-y := id.o io.o control.o mux.o devices.o serial.o gpmc.o timer.o pm.o \
         common.o gpio.o dma.o wd_timer.o display.o i2c.o hdq1w.o
 
-omap-2-3-common                                = irq.o sdrc.o
+omap-2-3-common                                = irq.o
 hwmod-common                           = omap_hwmod.o \
                                          omap_hwmod_common_data.o
 clock-common                           = clock.o clock_common_data.o \
@@ -16,19 +16,24 @@ secure-common                               = omap-smc.o omap-secure.o
 obj-$(CONFIG_ARCH_OMAP2) += $(omap-2-3-common) $(hwmod-common)
 obj-$(CONFIG_ARCH_OMAP3) += $(omap-2-3-common) $(hwmod-common) $(secure-common)
 obj-$(CONFIG_ARCH_OMAP4) += prm44xx.o $(hwmod-common) $(secure-common)
+obj-$(CONFIG_SOC_AM33XX) += irq.o $(hwmod-common)
+obj-$(CONFIG_SOC_OMAP5)         += prm44xx.o $(hwmod-common) $(secure-common)
 
 ifneq ($(CONFIG_SND_OMAP_SOC_MCBSP),)
 obj-y += mcbsp.o
 endif
 
 obj-$(CONFIG_TWL4030_CORE) += omap_twl.o
+obj-$(CONFIG_SOC_HAS_OMAP2_SDRC)       += sdrc.o
 
 # SMP support ONLY available for OMAP4
 
 obj-$(CONFIG_SMP)                      += omap-smp.o omap-headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)              += omap-hotplug.o
-obj-$(CONFIG_ARCH_OMAP4)               += omap4-common.o omap-wakeupgen.o
-obj-$(CONFIG_ARCH_OMAP4)               += sleep44xx.o
+omap-4-5-common                                =  omap4-common.o omap-wakeupgen.o \
+                                          sleep44xx.o
+obj-$(CONFIG_ARCH_OMAP4)               += $(omap-4-5-common)
+obj-$(CONFIG_SOC_OMAP5)                        += $(omap-4-5-common)
 
 plus_sec := $(call as-instr,.arch_extension sec,+sec)
 AFLAGS_omap-headsmp.o                  :=-Wa,-march=armv7-a$(plus_sec)
@@ -66,12 +71,12 @@ ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)               += pm24xx.o
 obj-$(CONFIG_ARCH_OMAP2)               += sleep24xx.o
 obj-$(CONFIG_ARCH_OMAP3)               += pm34xx.o sleep34xx.o
-obj-$(CONFIG_ARCH_OMAP3)               += cpuidle34xx.o
 obj-$(CONFIG_ARCH_OMAP4)               += pm44xx.o omap-mpuss-lowpower.o
-obj-$(CONFIG_ARCH_OMAP4)               += cpuidle44xx.o
+obj-$(CONFIG_SOC_OMAP5)                        += omap-mpuss-lowpower.o
 obj-$(CONFIG_PM_DEBUG)                 += pm-debug.o
-obj-$(CONFIG_OMAP_SMARTREFLEX)          += sr_device.o smartreflex.o
-obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3)  += smartreflex-class3.o
+
+obj-$(CONFIG_POWER_AVS_OMAP)           += sr_device.o
+obj-$(CONFIG_POWER_AVS_OMAP_CLASS3)    += smartreflex-class3.o
 
 AFLAGS_sleep24xx.o                     :=-Wa,-march=armv6
 AFLAGS_sleep34xx.o                     :=-Wa,-march=armv7-a$(plus_sec)
@@ -82,14 +87,22 @@ endif
 
 endif
 
+ifeq ($(CONFIG_CPU_IDLE),y)
+obj-$(CONFIG_ARCH_OMAP3)                += cpuidle34xx.o
+obj-$(CONFIG_ARCH_OMAP4)                += cpuidle44xx.o
+endif
+
 # PRCM
+omap-prcm-4-5-common                   =  prcm.o cminst44xx.o cm44xx.o \
+                                          prcm_mpu44xx.o prminst44xx.o \
+                                          vc44xx_data.o vp44xx_data.o
 obj-y                                  += prm_common.o
 obj-$(CONFIG_ARCH_OMAP2)               += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
 obj-$(CONFIG_ARCH_OMAP3)               += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
 obj-$(CONFIG_ARCH_OMAP3)               += vc3xxx_data.o vp3xxx_data.o
-obj-$(CONFIG_ARCH_OMAP4)               += prcm.o cminst44xx.o cm44xx.o
-obj-$(CONFIG_ARCH_OMAP4)               += prcm_mpu44xx.o prminst44xx.o
-obj-$(CONFIG_ARCH_OMAP4)               += vc44xx_data.o vp44xx_data.o prm44xx.o
+obj-$(CONFIG_SOC_AM33XX)               += prcm.o prm33xx.o cm33xx.o
+obj-$(CONFIG_ARCH_OMAP4)               += $(omap-prcm-4-5-common) prm44xx.o
+obj-$(CONFIG_SOC_OMAP5)                        += $(omap-prcm-4-5-common)
 
 # OMAP voltage domains
 voltagedomain-common                   := voltage.o vc.o vp.o
@@ -99,6 +112,9 @@ obj-$(CONFIG_ARCH_OMAP3)             += $(voltagedomain-common)
 obj-$(CONFIG_ARCH_OMAP3)               += voltagedomains3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP4)               += $(voltagedomain-common)
 obj-$(CONFIG_ARCH_OMAP4)               += voltagedomains44xx_data.o
+obj-$(CONFIG_SOC_AM33XX)               += $(voltagedomain-common)
+obj-$(CONFIG_SOC_AM33XX)                += voltagedomains33xx_data.o
+obj-$(CONFIG_SOC_OMAP5)                        += $(voltagedomain-common)
 
 # OMAP powerdomain framework
 powerdomain-common                     += powerdomain.o powerdomain-common.o
@@ -113,10 +129,14 @@ obj-$(CONFIG_ARCH_OMAP3)          += powerdomains2xxx_3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP4)               += $(powerdomain-common)
 obj-$(CONFIG_ARCH_OMAP4)               += powerdomain44xx.o
 obj-$(CONFIG_ARCH_OMAP4)               += powerdomains44xx_data.o
+obj-$(CONFIG_SOC_AM33XX)               += $(powerdomain-common)
+obj-$(CONFIG_SOC_AM33XX)               += powerdomain33xx.o
+obj-$(CONFIG_SOC_AM33XX)               += powerdomains33xx_data.o
+obj-$(CONFIG_SOC_OMAP5)                        += $(powerdomain-common)
+obj-$(CONFIG_SOC_OMAP5)                        += powerdomain44xx.o
 
 # PRCM clockdomain control
 clockdomain-common                     += clockdomain.o
-clockdomain-common                     += clockdomains_common_data.o
 obj-$(CONFIG_ARCH_OMAP2)               += $(clockdomain-common)
 obj-$(CONFIG_ARCH_OMAP2)               += clockdomain2xxx_3xxx.o
 obj-$(CONFIG_ARCH_OMAP2)               += clockdomains2xxx_3xxx_data.o
@@ -129,6 +149,11 @@ obj-$(CONFIG_ARCH_OMAP3)           += clockdomains3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP4)               += $(clockdomain-common)
 obj-$(CONFIG_ARCH_OMAP4)               += clockdomain44xx.o
 obj-$(CONFIG_ARCH_OMAP4)               += clockdomains44xx_data.o
+obj-$(CONFIG_SOC_AM33XX)               += $(clockdomain-common)
+obj-$(CONFIG_SOC_AM33XX)               += clockdomain33xx.o
+obj-$(CONFIG_SOC_AM33XX)               += clockdomains33xx_data.o
+obj-$(CONFIG_SOC_OMAP5)                        += $(clockdomain-common)
+obj-$(CONFIG_SOC_OMAP5)                        += clockdomain44xx.o
 
 # Clock framework
 obj-$(CONFIG_ARCH_OMAP2)               += $(clock-common) clock2xxx.o
@@ -146,6 +171,10 @@ obj-$(CONFIG_ARCH_OMAP3)           += dpll3xxx.o clock3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)               += clkt_iclk.o
 obj-$(CONFIG_ARCH_OMAP4)               += $(clock-common) clock44xx_data.o
 obj-$(CONFIG_ARCH_OMAP4)               += dpll3xxx.o dpll44xx.o
+obj-$(CONFIG_SOC_AM33XX)               += $(clock-common) dpll3xxx.o
+obj-$(CONFIG_SOC_AM33XX)               += clock33xx_data.o
+obj-$(CONFIG_SOC_OMAP5)                        += $(clock-common)
+obj-$(CONFIG_SOC_OMAP5)                        += dpll3xxx.o dpll44xx.o
 
 # OMAP2 clock rate set data (old "OPP" data)
 obj-$(CONFIG_SOC_OMAP2420)             += opp2420_data.o
@@ -173,6 +202,7 @@ obj-$(CONFIG_OMAP3_EMU)                     += emu.o
 # L3 interconnect
 obj-$(CONFIG_ARCH_OMAP3)               += omap_l3_smx.o
 obj-$(CONFIG_ARCH_OMAP4)               += omap_l3_noc.o
+obj-$(CONFIG_SOC_OMAP5)                        += omap_l3_noc.o
 
 obj-$(CONFIG_OMAP_MBOX_FWK)            += mailbox_mach.o
 mailbox_mach-objs                      := mailbox.o
@@ -189,6 +219,10 @@ endif
 # OMAP2420 MSDI controller integration support ("MMC")
 obj-$(CONFIG_SOC_OMAP2420)             += msdi.o
 
+ifneq ($(CONFIG_DRM_OMAP),)
+obj-y                                  += drm.o
+endif
+
 # Specific board support
 obj-$(CONFIG_MACH_OMAP_GENERIC)                += board-generic.o
 obj-$(CONFIG_MACH_OMAP_H4)             += board-h4.o
@@ -244,9 +278,6 @@ obj-y                                       += $(omap-flash-y) $(omap-flash-m)
 omap-hsmmc-$(CONFIG_MMC_OMAP_HS)       := hsmmc.o
 obj-y                                  += $(omap-hsmmc-m) $(omap-hsmmc-y)
 
-
-usbfs-$(CONFIG_ARCH_OMAP_OTG)          := usb-fs.o
-obj-y                                  += $(usbfs-m) $(usbfs-y)
 obj-y                                  += usb-musb.o
 obj-y                                  += omap_phy_internal.o
 
index 447682c4e11cccad255241f2f32240d41c1f1423..2c90ac6866868ac97b1dc22c519a12ef2553255c 100644 (file)
  * General Public License for more details.
  */
 
-#include <linux/clk.h>
+#include <linux/err.h>
 #include <linux/davinci_emac.h>
-#include <linux/platform_device.h>
-#include <plat/irqs.h>
+#include <asm/system.h>
+#include <plat/omap_device.h>
 #include <mach/am35xx.h>
-
 #include "control.h"
-
-static struct mdio_platform_data am35xx_emac_mdio_pdata;
-
-static struct resource am35xx_emac_mdio_resources[] = {
-       DEFINE_RES_MEM(AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET, SZ_4K),
-};
-
-static struct platform_device am35xx_emac_mdio_device = {
-       .name           = "davinci_mdio",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(am35xx_emac_mdio_resources),
-       .resource       = am35xx_emac_mdio_resources,
-       .dev.platform_data = &am35xx_emac_mdio_pdata,
-};
+#include "am35xx-emac.h"
 
 static void am35xx_enable_emac_int(void)
 {
@@ -69,41 +55,57 @@ static struct emac_platform_data am35xx_emac_pdata = {
        .interrupt_disable      = am35xx_disable_emac_int,
 };
 
-static struct resource am35xx_emac_resources[] = {
-       DEFINE_RES_MEM(AM35XX_IPSS_EMAC_BASE, 0x30000),
-       DEFINE_RES_IRQ(INT_35XX_EMAC_C0_RXTHRESH_IRQ),
-       DEFINE_RES_IRQ(INT_35XX_EMAC_C0_RX_PULSE_IRQ),
-       DEFINE_RES_IRQ(INT_35XX_EMAC_C0_TX_PULSE_IRQ),
-       DEFINE_RES_IRQ(INT_35XX_EMAC_C0_MISC_PULSE_IRQ),
-};
+static struct mdio_platform_data am35xx_mdio_pdata;
 
-static struct platform_device am35xx_emac_device = {
-       .name           = "davinci_emac",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(am35xx_emac_resources),
-       .resource       = am35xx_emac_resources,
-       .dev            = {
-               .platform_data  = &am35xx_emac_pdata,
-       },
-};
+static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh,
+               void *pdata, int pdata_len)
+{
+       struct platform_device *pdev;
+
+       pdev = omap_device_build(oh->class->name, 0, oh, pdata, pdata_len,
+                                NULL, 0, false);
+       if (IS_ERR(pdev)) {
+               WARN(1, "Can't build omap_device for %s:%s.\n",
+                    oh->class->name, oh->name);
+               return PTR_ERR(pdev);
+       }
+
+       return 0;
+}
 
 void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en)
 {
+       struct omap_hwmod *oh;
        u32 v;
-       int err;
+       int ret;
 
-       am35xx_emac_pdata.rmii_en = rmii_en;
-       am35xx_emac_mdio_pdata.bus_freq = mdio_bus_freq;
-       err = platform_device_register(&am35xx_emac_device);
-       if (err) {
-               pr_err("AM35x: failed registering EMAC device: %d\n", err);
+       oh = omap_hwmod_lookup("davinci_mdio");
+       if (!oh) {
+               pr_err("Could not find davinci_mdio hwmod\n");
+               return;
+       }
+
+       am35xx_mdio_pdata.bus_freq = mdio_bus_freq;
+
+       ret = omap_davinci_emac_dev_init(oh, &am35xx_mdio_pdata,
+                                        sizeof(am35xx_mdio_pdata));
+       if (ret) {
+               pr_err("Could not build davinci_mdio hwmod device\n");
                return;
        }
 
-       err = platform_device_register(&am35xx_emac_mdio_device);
-       if (err) {
-               pr_err("AM35x: failed registering EMAC MDIO device: %d\n", err);
-               platform_device_unregister(&am35xx_emac_device);
+       oh = omap_hwmod_lookup("davinci_emac");
+       if (!oh) {
+               pr_err("Could not find davinci_emac hwmod\n");
+               return;
+       }
+
+       am35xx_emac_pdata.rmii_en = rmii_en;
+
+       ret = omap_davinci_emac_dev_init(oh, &am35xx_emac_pdata,
+                                        sizeof(am35xx_emac_pdata));
+       if (ret) {
+               pr_err("Could not build davinci_emac hwmod device\n");
                return;
        }
 
index 99ca6bad5c30c210c0a6e19d5eae570ef862d632..9511584fdc4fd75bccd809e33ed354aedc8b791a 100644 (file)
@@ -218,9 +218,6 @@ static struct twl4030_gpio_platform_data sdp2430_gpio_data = {
 };
 
 static struct twl4030_platform_data sdp2430_twldata = {
-       .irq_base       = TWL4030_IRQ_BASE,
-       .irq_end        = TWL4030_IRQ_END,
-
        /* platform_data for children goes here */
        .gpio           = &sdp2430_gpio_data,
        .vmmc1          = &sdp2430_vmmc1,
@@ -254,16 +251,6 @@ static struct omap2_hsmmc_info mmc[] __initdata = {
        {}      /* Terminator */
 };
 
-static struct omap_usb_config sdp2430_usb_config __initdata = {
-       .otg            = 1,
-#ifdef  CONFIG_USB_GADGET_OMAP
-       .hmc_mode       = 0x0,
-#elif   defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-       .hmc_mode       = 0x1,
-#endif
-       .pins[0]        = 3,
-};
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
        { .reg_offset = OMAP_MUX_TERMINATOR },
@@ -280,7 +267,6 @@ static void __init omap_2430sdp_init(void)
        omap_serial_init();
        omap_sdrc_init(NULL, NULL);
        omap_hsmmc_init(mmc);
-       omap2_usbfs_init(&sdp2430_usb_config);
 
        omap_mux_init_signal("usb0hs_stp", OMAP_PULL_ENA | OMAP_PULL_UP);
        usb_musb_init(NULL);
index 8e17284a803ff0cae6ae473aced0a9793418c059..ad8a7d94afcd4b5c43f09ed3ad6e4cc02c08ea01 100644 (file)
@@ -821,6 +821,9 @@ static void __init omap_4430sdp_display_init(void)
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
        OMAP4_MUX(USBB2_ULPITLL_CLK, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+       /* NIRQ2 for twl6040 */
+       OMAP4_MUX(SYS_NIRQ2, OMAP_MUX_MODE0 |
+                 OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE),
        { .reg_offset = OMAP_MUX_TERMINATOR },
 };
 
index 502c31e123be0308f46b44bb4c40dadb88ef6e4c..519bcd3079e888857ee5401a5500ad9efc9e0e2b 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/mach/flash.h>
 
 #include <plat/led.h>
-#include <plat/usb.h>
 #include <plat/board.h>
 #include "common.h"
 #include <plat/gpmc.h>
@@ -253,13 +252,6 @@ out:
        clk_put(gpmc_fck);
 }
 
-static struct omap_usb_config apollon_usb_config __initdata = {
-       .register_dev   = 1,
-       .hmc_mode       = 0x14, /* 0:dev 1:host1 2:disable */
-
-       .pins[0]        = 6,
-};
-
 static struct panel_generic_dpi_data apollon_panel_data = {
        .name                   = "apollon",
 };
@@ -297,15 +289,6 @@ static void __init apollon_led_init(void)
        gpio_request_array(apollon_gpio_leds, ARRAY_SIZE(apollon_gpio_leds));
 }
 
-static void __init apollon_usb_init(void)
-{
-       /* USB device */
-       /* DEVICE_SUSPEND */
-       omap_mux_init_signal("mcbsp2_clkx.gpio_12", 0);
-       gpio_request_one(12, GPIOF_OUT_INIT_LOW, "USB suspend");
-       omap2_usbfs_init(&apollon_usb_config);
-}
-
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
        { .reg_offset = OMAP_MUX_TERMINATOR },
@@ -321,7 +304,6 @@ static void __init omap_apollon_init(void)
        apollon_init_smc91x();
        apollon_led_init();
        apollon_flash_init();
-       apollon_usb_init();
 
        /* REVISIT: where's the correct place */
        omap_mux_init_signal("sys_nirq", OMAP_PULL_ENA | OMAP_PULL_UP);
index ded100c80a91cb55f50245a924efcca310cee621..97d719047af382ca3aa5b5484310a427c1748b0d 100644 (file)
@@ -490,6 +490,71 @@ static struct twl4030_platform_data cm_t35_twldata = {
        .power          = &cm_t35_power_data,
 };
 
+#if defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
+#include <media/omap3isp.h>
+#include "devices.h"
+
+static struct i2c_board_info cm_t35_isp_i2c_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("mt9t001", 0x5d),
+       },
+       {
+               I2C_BOARD_INFO("tvp5150", 0x5c),
+       },
+};
+
+static struct isp_subdev_i2c_board_info cm_t35_isp_primary_subdevs[] = {
+       {
+               .board_info = &cm_t35_isp_i2c_boardinfo[0],
+               .i2c_adapter_id = 3,
+       },
+       { NULL, 0, },
+};
+
+static struct isp_subdev_i2c_board_info cm_t35_isp_secondary_subdevs[] = {
+       {
+               .board_info = &cm_t35_isp_i2c_boardinfo[1],
+               .i2c_adapter_id = 3,
+       },
+       { NULL, 0, },
+};
+
+static struct isp_v4l2_subdevs_group cm_t35_isp_subdevs[] = {
+       {
+               .subdevs = cm_t35_isp_primary_subdevs,
+               .interface = ISP_INTERFACE_PARALLEL,
+               .bus = {
+                       .parallel = {
+                               .clk_pol = 1,
+                       },
+               },
+       },
+       {
+               .subdevs = cm_t35_isp_secondary_subdevs,
+               .interface = ISP_INTERFACE_PARALLEL,
+               .bus = {
+                       .parallel = {
+                               .clk_pol = 0,
+                       },
+               },
+       },
+       { NULL, 0, },
+};
+
+static struct isp_platform_data cm_t35_isp_pdata = {
+       .subdevs = cm_t35_isp_subdevs,
+};
+
+static void __init cm_t35_init_camera(void)
+{
+       if (omap3_init_camera(&cm_t35_isp_pdata) < 0)
+               pr_warn("CM-T3x: Failed registering camera device!\n");
+}
+
+#else
+static inline void cm_t35_init_camera(void) {}
+#endif /* CONFIG_VIDEO_OMAP3 */
+
 static void __init cm_t35_init_i2c(void)
 {
        omap3_pmic_get_config(&cm_t35_twldata, TWL_COMMON_PDATA_USB,
@@ -497,6 +562,8 @@ static void __init cm_t35_init_i2c(void)
                              TWL_COMMON_PDATA_AUDIO);
 
        omap3_pmic_init("tps65930", &cm_t35_twldata);
+
+       omap_register_i2c_bus(3, 400, NULL, 0);
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -574,6 +641,27 @@ static struct omap_board_mux board_mux[] __initdata = {
        OMAP3_MUX(DSS_DATA16, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
        OMAP3_MUX(DSS_DATA17, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
 
+       /* Camera */
+       OMAP3_MUX(CAM_HS, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_VS, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_XCLKA, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_PCLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_FLD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D4, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D5, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D6, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D7, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+       OMAP3_MUX(CAM_D8, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP3_MUX(CAM_D9, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP3_MUX(CAM_STROBE, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
+
+       OMAP3_MUX(CAM_D10, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLDOWN),
+       OMAP3_MUX(CAM_D11, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLDOWN),
+
        /* display controls */
        OMAP3_MUX(MCBSP1_FSR, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
        OMAP3_MUX(GPMC_NCS7, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
@@ -646,6 +734,7 @@ static void __init cm_t3x_common_init(void)
 
        usb_musb_init(NULL);
        cm_t35_init_usbh();
+       cm_t35_init_camera();
 }
 
 static void __init cm_t35_init(void)
index 20293465786701f8650e1377ea070c6eee536673..6f93a20536eaabe60fba031726422685f2624331 100644 (file)
 #include "common-board-devices.h"
 
 #if !(defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3))
-#define omap_intc_of_init      NULL
+#define intc_of_init   NULL
 #endif
 #ifndef CONFIG_ARCH_OMAP4
 #define gic_of_init            NULL
 #endif
 
-static struct of_device_id irq_match[] __initdata = {
-       { .compatible = "ti,omap2-intc", .data = omap_intc_of_init, },
-       { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-       { }
-};
-
-static void __init omap_init_irq(void)
-{
-       of_irq_init(irq_match);
-}
-
 static struct of_device_id omap_dt_match_table[] __initdata = {
        { .compatible = "simple-bus", },
        { .compatible = "ti,omap-infra", },
@@ -65,7 +54,7 @@ DT_MACHINE_START(OMAP242X_DT, "Generic OMAP2420 (Flattened Device Tree)")
        .reserve        = omap_reserve,
        .map_io         = omap242x_map_io,
        .init_early     = omap2420_init_early,
-       .init_irq       = omap_init_irq,
+       .init_irq       = omap_intc_of_init,
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = omap_generic_init,
        .timer          = &omap2_timer,
@@ -84,7 +73,7 @@ DT_MACHINE_START(OMAP243X_DT, "Generic OMAP2430 (Flattened Device Tree)")
        .reserve        = omap_reserve,
        .map_io         = omap243x_map_io,
        .init_early     = omap2430_init_early,
-       .init_irq       = omap_init_irq,
+       .init_irq       = omap_intc_of_init,
        .handle_irq     = omap2_intc_handle_irq,
        .init_machine   = omap_generic_init,
        .timer          = &omap2_timer,
@@ -103,7 +92,7 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
        .reserve        = omap_reserve,
        .map_io         = omap3_map_io,
        .init_early     = omap3430_init_early,
-       .init_irq       = omap_init_irq,
+       .init_irq       = omap_intc_of_init,
        .handle_irq     = omap3_intc_handle_irq,
        .init_machine   = omap_generic_init,
        .timer          = &omap3_timer,
@@ -112,6 +101,24 @@ DT_MACHINE_START(OMAP3_DT, "Generic OMAP3 (Flattened Device Tree)")
 MACHINE_END
 #endif
 
+#ifdef CONFIG_SOC_AM33XX
+static const char *am33xx_boards_compat[] __initdata = {
+       "ti,am33xx",
+       NULL,
+};
+
+DT_MACHINE_START(AM33XX_DT, "Generic AM33XX (Flattened Device Tree)")
+       .reserve        = omap_reserve,
+       .map_io         = am33xx_map_io,
+       .init_early     = am33xx_init_early,
+       .init_irq       = omap_intc_of_init,
+       .handle_irq     = omap3_intc_handle_irq,
+       .init_machine   = omap_generic_init,
+       .timer          = &omap3_am33xx_timer,
+       .dt_compat      = am33xx_boards_compat,
+MACHINE_END
+#endif
+
 #ifdef CONFIG_ARCH_OMAP4
 static const char *omap4_boards_compat[] __initdata = {
        "ti,omap4",
@@ -122,7 +129,7 @@ DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)")
        .reserve        = omap_reserve,
        .map_io         = omap4_map_io,
        .init_early     = omap4430_init_early,
-       .init_irq       = omap_init_irq,
+       .init_irq       = omap_gic_of_init,
        .handle_irq     = gic_handle_irq,
        .init_machine   = omap_generic_init,
        .init_late      = omap4430_init_late,
@@ -131,3 +138,22 @@ DT_MACHINE_START(OMAP4_DT, "Generic OMAP4 (Flattened Device Tree)")
        .restart        = omap_prcm_restart,
 MACHINE_END
 #endif
+
+#ifdef CONFIG_SOC_OMAP5
+static const char *omap5_boards_compat[] __initdata = {
+       "ti,omap5",
+       NULL,
+};
+
+DT_MACHINE_START(OMAP5_DT, "Generic OMAP5 (Flattened Device Tree)")
+       .reserve        = omap_reserve,
+       .map_io         = omap5_map_io,
+       .init_early     = omap5_init_early,
+       .init_irq       = omap_gic_of_init,
+       .handle_irq     = gic_handle_irq,
+       .init_machine   = omap_generic_init,
+       .timer          = &omap5_timer,
+       .dt_compat      = omap5_boards_compat,
+       .restart        = omap_prcm_restart,
+MACHINE_END
+#endif
index 876becf8205a475ad6e168c5ca5ac513f737a49f..ace20482e3e1901eb4fedb311fa9e0ae55fa34b5 100644 (file)
@@ -32,7 +32,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/usb.h>
 #include <plat/board.h>
 #include "common.h"
 #include <plat/menelaus.h>
@@ -329,17 +328,6 @@ static void __init h4_init_flash(void)
        h4_flash_resource.end   = base + SZ_64M - 1;
 }
 
-static struct omap_usb_config h4_usb_config __initdata = {
-       /* S1.10 OFF -- usb "download port"
-        * usb0 switched to Mini-B port and isp1105 transceiver;
-        * S2.POS3 = ON, S2.POS4 = OFF ... to enable battery charging
-        */
-       .register_dev   = 1,
-       .pins[0]        = 3,
-/*     .hmc_mode       = 0x14,*/       /* 0:dev 1:host 2:disable */
-       .hmc_mode       = 0x00,         /* 0:dev|otg 1:disable 2:disable */
-};
-
 static struct at24_platform_data m24c01 = {
        .byte_len       = SZ_1K / 8,
        .page_size      = 16,
@@ -381,7 +369,6 @@ static void __init omap_h4_init(void)
                        ARRAY_SIZE(h4_i2c_board_info));
 
        platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
-       omap2_usbfs_init(&h4_usb_config);
        omap_serial_init();
        omap_sdrc_init(NULL, NULL);
        h4_init_flash();
index 580fd17208dacc24dd51bbff63507763c0612730..6202fc76e490f108e9ae238ae8499eab6cf1126a 100644 (file)
@@ -433,7 +433,7 @@ static struct platform_device *omap3_beagle_devices[] __initdata = {
 
 static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 
-       .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+       .port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
        .port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
        .port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
index 639bd07ea38a1cca473ac4c6fa5da29024ad9d77..ef230a0eb5eb13e5cedde6f0a6c540f6a348eae6 100644 (file)
 #include <linux/leds.h>
 #include <linux/interrupt.h>
 
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/i2c/twl.h>
@@ -43,6 +47,7 @@
 
 #include <plat/board.h>
 #include <plat/usb.h>
+#include <plat/nand.h>
 #include "common.h"
 #include <plat/mcspi.h>
 #include <video/omapdss.h>
@@ -53,7 +58,6 @@
 #include "hsmmc.h"
 #include "common-board-devices.h"
 
-#define OMAP3_EVM_TS_GPIO      175
 #define OMAP3_EVM_EHCI_VBUS    22
 #define OMAP3_EVM_EHCI_SELECT  61
 
@@ -355,6 +359,19 @@ static int omap3evm_twl_gpio_setup(struct device *dev,
 
        platform_device_register(&leds_gpio);
 
+       /* Enable VBUS switch by setting TWL4030.GPIO2DIR as output
+        * for starting USB tranceiver
+        */
+#ifdef CONFIG_TWL4030_CORE
+       if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) {
+               u8 val;
+
+               twl_i2c_read_u8(TWL4030_MODULE_GPIO, &val, REG_GPIODATADIR1);
+               val |= 0x04; /* TWL4030.GPIO2DIR BIT at GPIODATADIR1(0x9B) */
+               twl_i2c_write_u8(TWL4030_MODULE_GPIO, val, REG_GPIODATADIR1);
+       }
+#endif
+
        return 0;
 }
 
@@ -461,6 +478,28 @@ struct wl12xx_platform_data omap3evm_wlan_data __initdata = {
 };
 #endif
 
+/* VAUX2 for USB */
+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("vaux2", NULL),
+};
+
+static struct regulator_init_data omap3evm_vaux2 = {
+       .constraints = {
+               .min_uV         = 2800000,
+               .max_uV         = 2800000,
+               .apply_uV       = true,
+               .valid_modes_mask       = REGULATOR_MODE_NORMAL
+                                       | REGULATOR_MODE_STANDBY,
+               .valid_ops_mask         = REGULATOR_CHANGE_MODE
+                                       | REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies          = ARRAY_SIZE(omap3evm_vaux2_supplies),
+       .consumer_supplies              = omap3evm_vaux2_supplies,
+};
+
 static struct twl4030_platform_data omap3evm_twldata = {
        /* platform_data for children goes here */
        .keypad         = &omap3evm_kp_data,
@@ -607,6 +646,37 @@ static struct regulator_consumer_supply dummy_supplies[] = {
        REGULATOR_SUPPLY("vdd33a", "smsc911x.0"),
 };
 
+static struct mtd_partition omap3evm_nand_partitions[] = {
+       /* All the partition sizes are listed in terms of NAND block size */
+       {
+               .name           = "X-Loader",
+               .offset         = 0,
+               .size           = 4*(SZ_128K),
+               .mask_flags     = MTD_WRITEABLE
+       },
+       {
+               .name           = "U-Boot",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 14*(SZ_128K),
+               .mask_flags     = MTD_WRITEABLE
+       },
+       {
+               .name           = "U-Boot Env",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 2*(SZ_128K)
+       },
+       {
+               .name           = "Kernel",
+               .offset         = MTDPART_OFS_APPEND,
+               .size           = 40*(SZ_128K)
+       },
+       {
+               .name           = "File system",
+               .size           = MTDPART_SIZ_FULL,
+               .offset         = MTDPART_OFS_APPEND,
+       },
+};
+
 static void __init omap3_evm_init(void)
 {
        struct omap_board_mux *obm;
@@ -623,6 +693,9 @@ static void __init omap3_evm_init(void)
        omap_mux_init_gpio(63, OMAP_PIN_INPUT);
        omap_hsmmc_init(mmc);
 
+       if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2)
+               omap3evm_twldata.vaux2 = &omap3evm_vaux2;
+
        omap3_evm_i2c_init();
 
        omap_display_init(&omap3_evm_dss_data);
@@ -656,6 +729,9 @@ static void __init omap3_evm_init(void)
        }
        usb_musb_init(&musb_board_data);
        usbhs_init(&usbhs_bdata);
+       omap_nand_flash_init(NAND_BUSWIDTH_16, omap3evm_nand_partitions,
+                            ARRAY_SIZE(omap3evm_nand_partitions));
+
        omap_ads7846_init(1, OMAP3_EVM_TS_GPIO, 310, NULL);
        omap3evm_init_smsc911x();
        omap3_evm_display_init();
index 932e1778aff94187c4ff2056c11f489747061c27..fca93d1afd43536a5ffca0d62248ac85f8f804c7 100644 (file)
@@ -93,9 +93,6 @@ static struct twl4030_usb_data omap3logic_usb_data = {
 
 
 static struct twl4030_platform_data omap3logic_twldata = {
-       .irq_base       = TWL4030_IRQ_BASE,
-       .irq_end        = TWL4030_IRQ_END,
-
        /* platform_data for children goes here */
        .gpio           = &omap3logic_gpio_data,
        .vmmc1          = &omap3logic_vmmc1,
index 982fb2622ab83063840b61d867098b8ebf700df5..b627cdc12b84bbc15218a614cfd288abe312520e 100644 (file)
@@ -379,6 +379,9 @@ static struct omap_board_mux board_mux[] __initdata = {
        OMAP4_MUX(DPM_EMU18, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
        /* dispc2_data0 */
        OMAP4_MUX(DPM_EMU19, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+       /* NIRQ2 for twl6040 */
+       OMAP4_MUX(SYS_NIRQ2, OMAP_MUX_MODE0 |
+                 OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE),
        { .reg_offset = OMAP_MUX_TERMINATOR },
 };
 
index 5c4e66542169f0a260487c1c7cd985a1698bd87d..ea3f565ba1a44863926492611d493fdc6f081da6 100644 (file)
@@ -398,24 +398,6 @@ int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent)
        return omap2_clksel_set_parent(clk, new_parent);
 }
 
-/* OMAP3/4 non-CORE DPLL clkops */
-
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-
-const struct clkops clkops_omap3_noncore_dpll_ops = {
-       .enable         = omap3_noncore_dpll_enable,
-       .disable        = omap3_noncore_dpll_disable,
-       .allow_idle     = omap3_dpll_allow_idle,
-       .deny_idle      = omap3_dpll_deny_idle,
-};
-
-const struct clkops clkops_omap3_core_dpll_ops = {
-       .allow_idle     = omap3_dpll_allow_idle,
-       .deny_idle      = omap3_dpll_deny_idle,
-};
-
-#endif
-
 /*
  * OMAP2+ clock reset and init functions
  */
index a1bb23a23351262600d242873d71536c9e4de134..35ec5f3d9a7361ee0b60647002a2a5251880580f 100644 (file)
@@ -155,4 +155,18 @@ extern const struct clkops clkops_omap3_noncore_dpll_ops;
 extern const struct clkops clkops_omap3_core_dpll_ops;
 extern const struct clkops clkops_omap4_dpllmx_ops;
 
+/* clksel_rate blocks shared between OMAP44xx and AM33xx */
+extern const struct clksel_rate div_1_0_rates[];
+extern const struct clksel_rate div_1_1_rates[];
+extern const struct clksel_rate div_1_2_rates[];
+extern const struct clksel_rate div_1_3_rates[];
+extern const struct clksel_rate div_1_4_rates[];
+extern const struct clksel_rate div31_1to31_rates[];
+
+/* clocks shared between various OMAP SoCs */
+extern struct clk virt_19200000_ck;
+extern struct clk virt_26000000_ck;
+
+extern int am33xx_clk_init(void);
+
 #endif
index bace9308a4db89616b780f310738f35c6cee5644..002745181ad6e334bdbe961b8257f63b0f7c75b0 100644 (file)
@@ -1774,8 +1774,6 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "osc_ck",       &osc_ck,        CK_242X),
        CLK(NULL,       "sys_ck",       &sys_ck,        CK_242X),
        CLK(NULL,       "alt_ck",       &alt_ck,        CK_242X),
-       CLK("omap-mcbsp.1",     "pad_fck",      &mcbsp_clks,    CK_242X),
-       CLK("omap-mcbsp.2",     "pad_fck",      &mcbsp_clks,    CK_242X),
        CLK(NULL,       "mcbsp_clks",   &mcbsp_clks,    CK_242X),
        /* internal analog sources */
        CLK(NULL,       "dpll_ck",      &dpll_ck,       CK_242X),
@@ -1784,8 +1782,6 @@ static struct omap_clk omap2420_clks[] = {
        /* internal prcm root sources */
        CLK(NULL,       "func_54m_ck",  &func_54m_ck,   CK_242X),
        CLK(NULL,       "core_ck",      &core_ck,       CK_242X),
-       CLK("omap-mcbsp.1",     "prcm_fck",     &func_96m_ck,   CK_242X),
-       CLK("omap-mcbsp.2",     "prcm_fck",     &func_96m_ck,   CK_242X),
        CLK(NULL,       "func_96m_ck",  &func_96m_ck,   CK_242X),
        CLK(NULL,       "func_48m_ck",  &func_48m_ck,   CK_242X),
        CLK(NULL,       "func_12m_ck",  &func_12m_ck,   CK_242X),
@@ -1901,42 +1897,9 @@ static struct omap_clk omap2420_clks[] = {
        CLK(NULL,       "pka_ick",      &pka_ick,       CK_242X),
        CLK(NULL,       "usb_fck",      &usb_fck,       CK_242X),
        CLK("musb-hdrc",        "fck",  &osc_ck,        CK_242X),
-       CLK("omap_timer.1",     "32k_ck",       &func_32k_ck,   CK_243X),
-       CLK("omap_timer.2",     "32k_ck",       &func_32k_ck,   CK_243X),
-       CLK("omap_timer.3",     "32k_ck",       &func_32k_ck,   CK_243X),
-       CLK("omap_timer.4",     "32k_ck",       &func_32k_ck,   CK_243X),
-       CLK("omap_timer.5",     "32k_ck",       &func_32k_ck,   CK_243X),
-       CLK("omap_timer.6",     "32k_ck",       &func_32k_ck,   CK_243X),
-       CLK("omap_timer.7",     "32k_ck",       &func_32k_ck,   CK_243X),
-       CLK("omap_timer.8",     "32k_ck",       &func_32k_ck,   CK_243X),
-       CLK("omap_timer.9",     "32k_ck",       &func_32k_ck,   CK_243X),
-       CLK("omap_timer.10",    "32k_ck",       &func_32k_ck,   CK_243X),
-       CLK("omap_timer.11",    "32k_ck",       &func_32k_ck,   CK_243X),
-       CLK("omap_timer.12",    "32k_ck",       &func_32k_ck,   CK_243X),
-       CLK("omap_timer.1",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.2",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.3",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.4",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.5",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.6",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.7",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.8",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.9",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.10",    "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.11",    "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.12",    "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.1",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.2",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.3",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.4",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.5",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.6",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.7",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.8",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.9",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.10",    "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.11",    "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.12",    "alt_ck",       &alt_ck,        CK_243X),
+       CLK(NULL,       "timer_32k_ck", &func_32k_ck,   CK_243X),
+       CLK(NULL,       "timer_sys_ck", &sys_ck,        CK_243X),
+       CLK(NULL,       "timer_ext_ck", &alt_ck,        CK_243X),
 };
 
 /*
index 3b4d09a5039905687b2723adbad0d76add914221..cacabb070e22b546126e82c61ce7824505755c19 100644 (file)
@@ -1858,11 +1858,6 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "osc_ck",       &osc_ck,        CK_243X),
        CLK(NULL,       "sys_ck",       &sys_ck,        CK_243X),
        CLK(NULL,       "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap-mcbsp.1",     "pad_fck",      &mcbsp_clks,    CK_243X),
-       CLK("omap-mcbsp.2",     "pad_fck",      &mcbsp_clks,    CK_243X),
-       CLK("omap-mcbsp.3",     "pad_fck",      &mcbsp_clks,    CK_243X),
-       CLK("omap-mcbsp.4",     "pad_fck",      &mcbsp_clks,    CK_243X),
-       CLK("omap-mcbsp.5",     "pad_fck",      &mcbsp_clks,    CK_243X),
        CLK(NULL,       "mcbsp_clks",   &mcbsp_clks,    CK_243X),
        /* internal analog sources */
        CLK(NULL,       "dpll_ck",      &dpll_ck,       CK_243X),
@@ -1871,11 +1866,6 @@ static struct omap_clk omap2430_clks[] = {
        /* internal prcm root sources */
        CLK(NULL,       "func_54m_ck",  &func_54m_ck,   CK_243X),
        CLK(NULL,       "core_ck",      &core_ck,       CK_243X),
-       CLK("omap-mcbsp.1",     "prcm_fck",     &func_96m_ck,   CK_243X),
-       CLK("omap-mcbsp.2",     "prcm_fck",     &func_96m_ck,   CK_243X),
-       CLK("omap-mcbsp.3",     "prcm_fck",     &func_96m_ck,   CK_243X),
-       CLK("omap-mcbsp.4",     "prcm_fck",     &func_96m_ck,   CK_243X),
-       CLK("omap-mcbsp.5",     "prcm_fck",     &func_96m_ck,   CK_243X),
        CLK(NULL,       "func_96m_ck",  &func_96m_ck,   CK_243X),
        CLK(NULL,       "func_48m_ck",  &func_48m_ck,   CK_243X),
        CLK(NULL,       "func_12m_ck",  &func_12m_ck,   CK_243X),
@@ -2000,42 +1990,9 @@ static struct omap_clk omap2430_clks[] = {
        CLK(NULL,       "mdm_intc_ick", &mdm_intc_ick,  CK_243X),
        CLK("omap_hsmmc.0", "mmchsdb_fck",      &mmchsdb1_fck,  CK_243X),
        CLK("omap_hsmmc.1", "mmchsdb_fck",      &mmchsdb2_fck,  CK_243X),
-       CLK("omap_timer.1",     "32k_ck",  &func_32k_ck,   CK_243X),
-       CLK("omap_timer.2",     "32k_ck",  &func_32k_ck,   CK_243X),
-       CLK("omap_timer.3",     "32k_ck",  &func_32k_ck,   CK_243X),
-       CLK("omap_timer.4",     "32k_ck",  &func_32k_ck,   CK_243X),
-       CLK("omap_timer.5",     "32k_ck",  &func_32k_ck,   CK_243X),
-       CLK("omap_timer.6",     "32k_ck",  &func_32k_ck,   CK_243X),
-       CLK("omap_timer.7",     "32k_ck",  &func_32k_ck,   CK_243X),
-       CLK("omap_timer.8",     "32k_ck",  &func_32k_ck,   CK_243X),
-       CLK("omap_timer.9",     "32k_ck",  &func_32k_ck,   CK_243X),
-       CLK("omap_timer.10",    "32k_ck",  &func_32k_ck,   CK_243X),
-       CLK("omap_timer.11",    "32k_ck",  &func_32k_ck,   CK_243X),
-       CLK("omap_timer.12",    "32k_ck",  &func_32k_ck,   CK_243X),
-       CLK("omap_timer.1",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.2",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.3",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.4",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.5",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.6",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.7",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.8",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.9",     "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.10",    "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.11",    "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.12",    "sys_ck",       &sys_ck,        CK_243X),
-       CLK("omap_timer.1",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.2",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.3",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.4",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.5",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.6",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.7",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.8",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.9",     "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.10",    "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.11",    "alt_ck",       &alt_ck,        CK_243X),
-       CLK("omap_timer.12",    "alt_ck",       &alt_ck,        CK_243X),
+       CLK(NULL,       "timer_32k_ck",  &func_32k_ck,   CK_243X),
+       CLK(NULL,       "timer_sys_ck", &sys_ck,        CK_243X),
+       CLK(NULL,       "timer_ext_ck", &alt_ck,        CK_243X),
 };
 
 /*
diff --git a/arch/arm/mach-omap2/clock33xx_data.c b/arch/arm/mach-omap2/clock33xx_data.c
new file mode 100644 (file)
index 0000000..25bbcc7
--- /dev/null
@@ -0,0 +1,1105 @@
+/*
+ * AM33XX Clock data
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Vaibhav Hiremath <hvaibhav@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/clk.h>
+#include <plat/clkdev_omap.h>
+#include <plat/am33xx.h>
+
+#include "iomap.h"
+#include "control.h"
+#include "clock.h"
+#include "cm.h"
+#include "cm33xx.h"
+#include "cm-regbits-33xx.h"
+#include "prm.h"
+
+/* Maximum DPLL multiplier, divider values for AM33XX */
+#define AM33XX_MAX_DPLL_MULT           2047
+#define AM33XX_MAX_DPLL_DIV            128
+
+/* Modulemode control */
+#define AM33XX_MODULEMODE_HWCTRL       0
+#define AM33XX_MODULEMODE_SWCTRL       1
+
+/* TRM ERRATA: Timer 3 & 6 default parent (TCLKIN) may not be always
+ *    physically present, in such a case HWMOD enabling of
+ *    clock would be failure with default parent. And timer
+ *    probe thinks clock is already enabled, this leads to
+ *    crash upon accessing timer 3 & 6 registers in probe.
+ *    Fix by setting parent of both these timers to master
+ *    oscillator clock.
+ */
+static inline void am33xx_init_timer_parent(struct clk *clk)
+{
+       omap2_clksel_set_parent(clk, clk->parent);
+}
+
+/* Root clocks */
+
+/* RTC 32k */
+static struct clk clk_32768_ck = {
+       .name           = "clk_32768_ck",
+       .clkdm_name     = "l4_rtc_clkdm",
+       .rate           = 32768,
+       .ops            = &clkops_null,
+};
+
+/* On-Chip 32KHz RC OSC */
+static struct clk clk_rc32k_ck = {
+       .name           = "clk_rc32k_ck",
+       .rate           = 32000,
+       .ops            = &clkops_null,
+};
+
+/* Crystal input clks */
+static struct clk virt_24000000_ck = {
+       .name           = "virt_24000000_ck",
+       .rate           = 24000000,
+       .ops            = &clkops_null,
+};
+
+static struct clk virt_25000000_ck = {
+       .name           = "virt_25000000_ck",
+       .rate           = 25000000,
+       .ops            = &clkops_null,
+};
+
+/* Oscillator clock */
+/* 19.2, 24, 25 or 26 MHz */
+static const struct clksel sys_clkin_sel[] = {
+       { .parent = &virt_19200000_ck, .rates = div_1_0_rates },
+       { .parent = &virt_24000000_ck, .rates = div_1_1_rates },
+       { .parent = &virt_25000000_ck, .rates = div_1_2_rates },
+       { .parent = &virt_26000000_ck, .rates = div_1_3_rates },
+       { .parent = NULL },
+};
+
+/* External clock - 12 MHz */
+static struct clk tclkin_ck = {
+       .name           = "tclkin_ck",
+       .rate           = 12000000,
+       .ops            = &clkops_null,
+};
+
+/*
+ * sys_clk in: input to the dpll and also used as funtional clock for,
+ *   adc_tsc, smartreflex0-1, timer1-7, mcasp0-1, dcan0-1, cefuse
+ *
+ */
+static struct clk sys_clkin_ck = {
+       .name           = "sys_clkin_ck",
+       .parent         = &virt_24000000_ck,
+       .init           = &omap2_init_clksel_parent,
+       .clksel_reg     = AM33XX_CTRL_REGADDR(AM33XX_CONTROL_STATUS),
+       .clksel_mask    = AM33XX_CONTROL_STATUS_SYSBOOT1_MASK,
+       .clksel         = sys_clkin_sel,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+/* DPLL_CORE */
+static struct dpll_data dpll_core_dd = {
+       .mult_div1_reg  = AM33XX_CM_CLKSEL_DPLL_CORE,
+       .clk_bypass     = &sys_clkin_ck,
+       .clk_ref        = &sys_clkin_ck,
+       .control_reg    = AM33XX_CM_CLKMODE_DPLL_CORE,
+       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       .idlest_reg     = AM33XX_CM_IDLEST_DPLL_CORE,
+       .mult_mask      = AM33XX_DPLL_MULT_MASK,
+       .div1_mask      = AM33XX_DPLL_DIV_MASK,
+       .enable_mask    = AM33XX_DPLL_EN_MASK,
+       .idlest_mask    = AM33XX_ST_DPLL_CLK_MASK,
+       .max_multiplier = AM33XX_MAX_DPLL_MULT,
+       .max_divider    = AM33XX_MAX_DPLL_DIV,
+       .min_divider    = 1,
+};
+
+/* CLKDCOLDO output */
+static struct clk dpll_core_ck = {
+       .name           = "dpll_core_ck",
+       .parent         = &sys_clkin_ck,
+       .dpll_data      = &dpll_core_dd,
+       .init           = &omap2_init_dpll_parent,
+       .ops            = &clkops_omap3_core_dpll_ops,
+       .recalc         = &omap3_dpll_recalc,
+};
+
+static struct clk dpll_core_x2_ck = {
+       .name           = "dpll_core_x2_ck",
+       .parent         = &dpll_core_ck,
+       .flags          = CLOCK_CLKOUTX2,
+       .ops            = &clkops_null,
+       .recalc         = &omap3_clkoutx2_recalc,
+};
+
+
+static const struct clksel dpll_core_m4_div[] = {
+       { .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
+       { .parent = NULL },
+};
+
+static struct clk dpll_core_m4_ck = {
+       .name           = "dpll_core_m4_ck",
+       .parent         = &dpll_core_x2_ck,
+       .init           = &omap2_init_clksel_parent,
+       .clksel         = dpll_core_m4_div,
+       .clksel_reg     = AM33XX_CM_DIV_M4_DPLL_CORE,
+       .clksel_mask    = AM33XX_HSDIVIDER_CLKOUT1_DIV_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
+static const struct clksel dpll_core_m5_div[] = {
+       { .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
+       { .parent = NULL },
+};
+
+static struct clk dpll_core_m5_ck = {
+       .name           = "dpll_core_m5_ck",
+       .parent         = &dpll_core_x2_ck,
+       .init           = &omap2_init_clksel_parent,
+       .clksel         = dpll_core_m5_div,
+       .clksel_reg     = AM33XX_CM_DIV_M5_DPLL_CORE,
+       .clksel_mask    = AM33XX_HSDIVIDER_CLKOUT2_DIV_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
+static const struct clksel dpll_core_m6_div[] = {
+       { .parent = &dpll_core_x2_ck, .rates = div31_1to31_rates },
+       { .parent = NULL },
+};
+
+static struct clk dpll_core_m6_ck = {
+       .name           = "dpll_core_m6_ck",
+       .parent         = &dpll_core_x2_ck,
+       .init           = &omap2_init_clksel_parent,
+       .clksel         = dpll_core_m6_div,
+       .clksel_reg     = AM33XX_CM_DIV_M6_DPLL_CORE,
+       .clksel_mask    = AM33XX_HSDIVIDER_CLKOUT3_DIV_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
+/* DPLL_MPU */
+static struct dpll_data dpll_mpu_dd = {
+       .mult_div1_reg  = AM33XX_CM_CLKSEL_DPLL_MPU,
+       .clk_bypass     = &sys_clkin_ck,
+       .clk_ref        = &sys_clkin_ck,
+       .control_reg    = AM33XX_CM_CLKMODE_DPLL_MPU,
+       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       .idlest_reg     = AM33XX_CM_IDLEST_DPLL_MPU,
+       .mult_mask      = AM33XX_DPLL_MULT_MASK,
+       .div1_mask      = AM33XX_DPLL_DIV_MASK,
+       .enable_mask    = AM33XX_DPLL_EN_MASK,
+       .idlest_mask    = AM33XX_ST_DPLL_CLK_MASK,
+       .max_multiplier = AM33XX_MAX_DPLL_MULT,
+       .max_divider    = AM33XX_MAX_DPLL_DIV,
+       .min_divider    = 1,
+};
+
+/* CLKOUT: fdpll/M2 */
+static struct clk dpll_mpu_ck = {
+       .name           = "dpll_mpu_ck",
+       .parent         = &sys_clkin_ck,
+       .dpll_data      = &dpll_mpu_dd,
+       .init           = &omap2_init_dpll_parent,
+       .ops            = &clkops_omap3_noncore_dpll_ops,
+       .recalc         = &omap3_dpll_recalc,
+       .round_rate     = &omap2_dpll_round_rate,
+       .set_rate       = &omap3_noncore_dpll_set_rate,
+};
+
+/*
+ * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
+ * and ALT_CLK1/2)
+ */
+static const struct clksel dpll_mpu_m2_div[] = {
+       { .parent = &dpll_mpu_ck, .rates = div31_1to31_rates },
+       { .parent = NULL },
+};
+
+static struct clk dpll_mpu_m2_ck = {
+       .name           = "dpll_mpu_m2_ck",
+       .clkdm_name     = "mpu_clkdm",
+       .parent         = &dpll_mpu_ck,
+       .clksel         = dpll_mpu_m2_div,
+       .clksel_reg     = AM33XX_CM_DIV_M2_DPLL_MPU,
+       .clksel_mask    = AM33XX_DPLL_CLKOUT_DIV_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
+/* DPLL_DDR */
+static struct dpll_data dpll_ddr_dd = {
+       .mult_div1_reg  = AM33XX_CM_CLKSEL_DPLL_DDR,
+       .clk_bypass     = &sys_clkin_ck,
+       .clk_ref        = &sys_clkin_ck,
+       .control_reg    = AM33XX_CM_CLKMODE_DPLL_DDR,
+       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       .idlest_reg     = AM33XX_CM_IDLEST_DPLL_DDR,
+       .mult_mask      = AM33XX_DPLL_MULT_MASK,
+       .div1_mask      = AM33XX_DPLL_DIV_MASK,
+       .enable_mask    = AM33XX_DPLL_EN_MASK,
+       .idlest_mask    = AM33XX_ST_DPLL_CLK_MASK,
+       .max_multiplier = AM33XX_MAX_DPLL_MULT,
+       .max_divider    = AM33XX_MAX_DPLL_DIV,
+       .min_divider    = 1,
+};
+
+/* CLKOUT: fdpll/M2 */
+static struct clk dpll_ddr_ck = {
+       .name           = "dpll_ddr_ck",
+       .parent         = &sys_clkin_ck,
+       .dpll_data      = &dpll_ddr_dd,
+       .init           = &omap2_init_dpll_parent,
+       .ops            = &clkops_null,
+       .recalc         = &omap3_dpll_recalc,
+};
+
+/*
+ * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
+ * and ALT_CLK1/2)
+ */
+static const struct clksel dpll_ddr_m2_div[] = {
+       { .parent = &dpll_ddr_ck, .rates = div31_1to31_rates },
+       { .parent = NULL },
+};
+
+static struct clk dpll_ddr_m2_ck = {
+       .name           = "dpll_ddr_m2_ck",
+       .parent         = &dpll_ddr_ck,
+       .clksel         = dpll_ddr_m2_div,
+       .clksel_reg     = AM33XX_CM_DIV_M2_DPLL_DDR,
+       .clksel_mask    = AM33XX_DPLL_CLKOUT_DIV_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
+/* emif_fck functional clock */
+static struct clk dpll_ddr_m2_div2_ck = {
+       .name           = "dpll_ddr_m2_div2_ck",
+       .clkdm_name     = "l3_clkdm",
+       .parent         = &dpll_ddr_m2_ck,
+       .ops            = &clkops_null,
+       .fixed_div      = 2,
+       .recalc         = &omap_fixed_divisor_recalc,
+};
+
+/* DPLL_DISP */
+static struct dpll_data dpll_disp_dd = {
+       .mult_div1_reg  = AM33XX_CM_CLKSEL_DPLL_DISP,
+       .clk_bypass     = &sys_clkin_ck,
+       .clk_ref        = &sys_clkin_ck,
+       .control_reg    = AM33XX_CM_CLKMODE_DPLL_DISP,
+       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       .idlest_reg     = AM33XX_CM_IDLEST_DPLL_DISP,
+       .mult_mask      = AM33XX_DPLL_MULT_MASK,
+       .div1_mask      = AM33XX_DPLL_DIV_MASK,
+       .enable_mask    = AM33XX_DPLL_EN_MASK,
+       .idlest_mask    = AM33XX_ST_DPLL_CLK_MASK,
+       .max_multiplier = AM33XX_MAX_DPLL_MULT,
+       .max_divider    = AM33XX_MAX_DPLL_DIV,
+       .min_divider    = 1,
+};
+
+/* CLKOUT: fdpll/M2 */
+static struct clk dpll_disp_ck = {
+       .name           = "dpll_disp_ck",
+       .parent         = &sys_clkin_ck,
+       .dpll_data      = &dpll_disp_dd,
+       .init           = &omap2_init_dpll_parent,
+       .ops            = &clkops_null,
+       .recalc         = &omap3_dpll_recalc,
+       .round_rate     = &omap2_dpll_round_rate,
+       .set_rate       = &omap3_noncore_dpll_set_rate,
+};
+
+/*
+ * TODO: Add clksel here (sys_clkin, CORE_CLKOUTM6, PER_CLKOUTM2
+ * and ALT_CLK1/2)
+ */
+static const struct clksel dpll_disp_m2_div[] = {
+       { .parent = &dpll_disp_ck, .rates = div31_1to31_rates },
+       { .parent = NULL },
+};
+
+static struct clk dpll_disp_m2_ck = {
+       .name           = "dpll_disp_m2_ck",
+       .parent         = &dpll_disp_ck,
+       .clksel         = dpll_disp_m2_div,
+       .clksel_reg     = AM33XX_CM_DIV_M2_DPLL_DISP,
+       .clksel_mask    = AM33XX_DPLL_CLKOUT_DIV_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
+/* DPLL_PER */
+static struct dpll_data dpll_per_dd = {
+       .mult_div1_reg  = AM33XX_CM_CLKSEL_DPLL_PERIPH,
+       .clk_bypass     = &sys_clkin_ck,
+       .clk_ref        = &sys_clkin_ck,
+       .control_reg    = AM33XX_CM_CLKMODE_DPLL_PER,
+       .modes          = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       .idlest_reg     = AM33XX_CM_IDLEST_DPLL_PER,
+       .mult_mask      = AM33XX_DPLL_MULT_PERIPH_MASK,
+       .div1_mask      = AM33XX_DPLL_PER_DIV_MASK,
+       .enable_mask    = AM33XX_DPLL_EN_MASK,
+       .idlest_mask    = AM33XX_ST_DPLL_CLK_MASK,
+       .max_multiplier = AM33XX_MAX_DPLL_MULT,
+       .max_divider    = AM33XX_MAX_DPLL_DIV,
+       .min_divider    = 1,
+       .flags          = DPLL_J_TYPE,
+};
+
+/* CLKDCOLDO */
+static struct clk dpll_per_ck = {
+       .name           = "dpll_per_ck",
+       .parent         = &sys_clkin_ck,
+       .dpll_data      = &dpll_per_dd,
+       .init           = &omap2_init_dpll_parent,
+       .ops            = &clkops_null,
+       .recalc         = &omap3_dpll_recalc,
+       .round_rate     = &omap2_dpll_round_rate,
+       .set_rate       = &omap3_noncore_dpll_set_rate,
+};
+
+/* CLKOUT: fdpll/M2 */
+static const struct clksel dpll_per_m2_div[] = {
+       { .parent = &dpll_per_ck, .rates = div31_1to31_rates },
+       { .parent = NULL },
+};
+
+static struct clk dpll_per_m2_ck = {
+       .name           = "dpll_per_m2_ck",
+       .parent         = &dpll_per_ck,
+       .clksel         = dpll_per_m2_div,
+       .clksel_reg     = AM33XX_CM_DIV_M2_DPLL_PER,
+       .clksel_mask    = AM33XX_DPLL_CLKOUT_DIV_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
+static struct clk dpll_per_m2_div4_wkupdm_ck = {
+       .name           = "dpll_per_m2_div4_wkupdm_ck",
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &dpll_per_m2_ck,
+       .fixed_div      = 4,
+       .ops            = &clkops_null,
+       .recalc         = &omap_fixed_divisor_recalc,
+};
+
+static struct clk dpll_per_m2_div4_ck = {
+       .name           = "dpll_per_m2_div4_ck",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &dpll_per_m2_ck,
+       .fixed_div      = 4,
+       .ops            = &clkops_null,
+       .recalc         = &omap_fixed_divisor_recalc,
+};
+
+static struct clk l3_gclk = {
+       .name           = "l3_gclk",
+       .clkdm_name     = "l3_clkdm",
+       .parent         = &dpll_core_m4_ck,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk dpll_core_m4_div2_ck = {
+       .name           = "dpll_core_m4_div2_ck",
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &dpll_core_m4_ck,
+       .ops            = &clkops_null,
+       .fixed_div      = 2,
+       .recalc         = &omap_fixed_divisor_recalc,
+};
+
+static struct clk l4_rtc_gclk = {
+       .name           = "l4_rtc_gclk",
+       .parent         = &dpll_core_m4_ck,
+       .ops            = &clkops_null,
+       .fixed_div      = 2,
+       .recalc         = &omap_fixed_divisor_recalc,
+};
+
+static struct clk clk_24mhz = {
+       .name           = "clk_24mhz",
+       .parent         = &dpll_per_m2_ck,
+       .fixed_div      = 8,
+       .ops            = &clkops_null,
+       .recalc         = &omap_fixed_divisor_recalc,
+};
+
+/*
+ * Below clock nodes describes clockdomains derived out
+ * of core clock.
+ */
+static struct clk l4hs_gclk = {
+       .name           = "l4hs_gclk",
+       .clkdm_name     = "l4hs_clkdm",
+       .parent         = &dpll_core_m4_ck,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk l3s_gclk = {
+       .name           = "l3s_gclk",
+       .clkdm_name     = "l3s_clkdm",
+       .parent         = &dpll_core_m4_div2_ck,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk l4fw_gclk = {
+       .name           = "l4fw_gclk",
+       .clkdm_name     = "l4fw_clkdm",
+       .parent         = &dpll_core_m4_div2_ck,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk l4ls_gclk = {
+       .name           = "l4ls_gclk",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &dpll_core_m4_div2_ck,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk sysclk_div_ck = {
+       .name           = "sysclk_div_ck",
+       .parent         = &dpll_core_m4_ck,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+/*
+ * In order to match the clock domain with hwmod clockdomain entry,
+ * separate clock nodes is required for the modules which are
+ * directly getting their funtioncal clock from sys_clkin.
+ */
+static struct clk adc_tsc_fck = {
+       .name           = "adc_tsc_fck",
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &sys_clkin_ck,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk dcan0_fck = {
+       .name           = "dcan0_fck",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &sys_clkin_ck,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk dcan1_fck = {
+       .name           = "dcan1_fck",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &sys_clkin_ck,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk mcasp0_fck = {
+       .name           = "mcasp0_fck",
+       .clkdm_name     = "l3s_clkdm",
+       .parent         = &sys_clkin_ck,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk mcasp1_fck = {
+       .name           = "mcasp1_fck",
+       .clkdm_name     = "l3s_clkdm",
+       .parent         = &sys_clkin_ck,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk smartreflex0_fck = {
+       .name           = "smartreflex0_fck",
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &sys_clkin_ck,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk smartreflex1_fck = {
+       .name           = "smartreflex1_fck",
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &sys_clkin_ck,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+/*
+ * Modules clock nodes
+ *
+ * The following clock leaf nodes are added for the moment because:
+ *
+ *  - hwmod data is not present for these modules, either hwmod
+ *    control is not required or its not populated.
+ *  - Driver code is not yet migrated to use hwmod/runtime pm
+ *  - Modules outside kernel access (to disable them by default)
+ *
+ *     - debugss
+ *     - mmu (gfx domain)
+ *     - cefuse
+ *     - usbotg_fck (its additional clock and not really a modulemode)
+ *     - ieee5000
+ */
+static struct clk debugss_ick = {
+       .name           = "debugss_ick",
+       .clkdm_name     = "l3_aon_clkdm",
+       .parent         = &dpll_core_m4_ck,
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = AM33XX_CM_WKUP_DEBUGSS_CLKCTRL,
+       .enable_bit     = AM33XX_MODULEMODE_SWCTRL,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk mmu_fck = {
+       .name           = "mmu_fck",
+       .clkdm_name     = "gfx_l3_clkdm",
+       .parent         = &dpll_core_m4_ck,
+       .ops            = &clkops_omap2_dflt,
+       .enable_reg     = AM33XX_CM_GFX_MMUDATA_CLKCTRL,
+       .enable_bit     = AM33XX_MODULEMODE_SWCTRL,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk cefuse_fck = {
+       .name           = "cefuse_fck",
+       .clkdm_name     = "l4_cefuse_clkdm",
+       .parent         = &sys_clkin_ck,
+       .enable_reg     = AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL,
+       .enable_bit     = AM33XX_MODULEMODE_SWCTRL,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &followparent_recalc,
+};
+
+/*
+ * clkdiv32 is generated from fixed division of 732.4219
+ */
+static struct clk clkdiv32k_ick = {
+       .name           = "clkdiv32k_ick",
+       .clkdm_name     = "clk_24mhz_clkdm",
+       .rate           = 32768,
+       .parent         = &clk_24mhz,
+       .enable_reg     = AM33XX_CM_PER_CLKDIV32K_CLKCTRL,
+       .enable_bit     = AM33XX_MODULEMODE_SWCTRL,
+       .ops            = &clkops_omap2_dflt,
+};
+
+static struct clk usbotg_fck = {
+       .name           = "usbotg_fck",
+       .clkdm_name     = "l3s_clkdm",
+       .parent         = &dpll_per_ck,
+       .enable_reg     = AM33XX_CM_CLKDCOLDO_DPLL_PER,
+       .enable_bit     = AM33XX_ST_DPLL_CLKDCOLDO_SHIFT,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk ieee5000_fck = {
+       .name           = "ieee5000_fck",
+       .clkdm_name     = "l3s_clkdm",
+       .parent         = &dpll_core_m4_div2_ck,
+       .enable_reg     = AM33XX_CM_PER_IEEE5000_CLKCTRL,
+       .enable_bit     = AM33XX_MODULEMODE_SWCTRL,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &followparent_recalc,
+};
+
+/* Timers */
+static const struct clksel timer1_clkmux_sel[] = {
+       { .parent = &sys_clkin_ck, .rates = div_1_0_rates },
+       { .parent = &clkdiv32k_ick, .rates = div_1_1_rates },
+       { .parent = &tclkin_ck, .rates = div_1_2_rates },
+       { .parent = &clk_rc32k_ck, .rates = div_1_3_rates },
+       { .parent = &clk_32768_ck, .rates = div_1_4_rates },
+       { .parent = NULL },
+};
+
+static struct clk timer1_fck = {
+       .name           = "timer1_fck",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &sys_clkin_ck,
+       .init           = &omap2_init_clksel_parent,
+       .clksel         = timer1_clkmux_sel,
+       .clksel_reg     = AM33XX_CLKSEL_TIMER1MS_CLK,
+       .clksel_mask    = AM33XX_CLKSEL_0_2_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static const struct clksel timer2_to_7_clk_sel[] = {
+       { .parent = &tclkin_ck, .rates = div_1_0_rates },
+       { .parent = &sys_clkin_ck, .rates = div_1_1_rates },
+       { .parent = &clkdiv32k_ick, .rates = div_1_2_rates },
+       { .parent = NULL },
+};
+
+static struct clk timer2_fck = {
+       .name           = "timer2_fck",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &sys_clkin_ck,
+       .init           = &omap2_init_clksel_parent,
+       .clksel         = timer2_to_7_clk_sel,
+       .clksel_reg     = AM33XX_CLKSEL_TIMER2_CLK,
+       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk timer3_fck = {
+       .name           = "timer3_fck",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &sys_clkin_ck,
+       .init           = &am33xx_init_timer_parent,
+       .clksel         = timer2_to_7_clk_sel,
+       .clksel_reg     = AM33XX_CLKSEL_TIMER3_CLK,
+       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk timer4_fck = {
+       .name           = "timer4_fck",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &sys_clkin_ck,
+       .init           = &omap2_init_clksel_parent,
+       .clksel         = timer2_to_7_clk_sel,
+       .clksel_reg     = AM33XX_CLKSEL_TIMER4_CLK,
+       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk timer5_fck = {
+       .name           = "timer5_fck",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &sys_clkin_ck,
+       .init           = &omap2_init_clksel_parent,
+       .clksel         = timer2_to_7_clk_sel,
+       .clksel_reg     = AM33XX_CLKSEL_TIMER5_CLK,
+       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk timer6_fck = {
+       .name           = "timer6_fck",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &sys_clkin_ck,
+       .init           = &am33xx_init_timer_parent,
+       .clksel         = timer2_to_7_clk_sel,
+       .clksel_reg     = AM33XX_CLKSEL_TIMER6_CLK,
+       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk timer7_fck = {
+       .name           = "timer7_fck",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &sys_clkin_ck,
+       .init           = &omap2_init_clksel_parent,
+       .clksel         = timer2_to_7_clk_sel,
+       .clksel_reg     = AM33XX_CLKSEL_TIMER7_CLK,
+       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk cpsw_125mhz_gclk = {
+       .name           = "cpsw_125mhz_gclk",
+       .clkdm_name     = "cpsw_125mhz_clkdm",
+       .parent         = &dpll_core_m5_ck,
+       .ops            = &clkops_null,
+       .fixed_div      = 2,
+       .recalc         = &omap_fixed_divisor_recalc,
+};
+
+static const struct clksel cpsw_cpts_rft_clkmux_sel[] = {
+       { .parent = &dpll_core_m5_ck, .rates = div_1_0_rates },
+       { .parent = &dpll_core_m4_ck, .rates = div_1_1_rates },
+       { .parent = NULL },
+};
+
+static struct clk cpsw_cpts_rft_clk = {
+       .name           = "cpsw_cpts_rft_clk",
+       .clkdm_name     = "cpsw_125mhz_clkdm",
+       .parent         = &dpll_core_m5_ck,
+       .clksel         = cpsw_cpts_rft_clkmux_sel,
+       .clksel_reg     = AM33XX_CM_CPTS_RFT_CLKSEL,
+       .clksel_mask    = AM33XX_CLKSEL_0_0_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+/* gpio */
+static const struct clksel gpio0_dbclk_mux_sel[] = {
+       { .parent = &clk_rc32k_ck, .rates = div_1_0_rates },
+       { .parent = &clk_32768_ck, .rates = div_1_1_rates },
+       { .parent = &clkdiv32k_ick, .rates = div_1_2_rates },
+       { .parent = NULL },
+};
+
+static struct clk gpio0_dbclk_mux_ck = {
+       .name           = "gpio0_dbclk_mux_ck",
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &clk_rc32k_ck,
+       .init           = &omap2_init_clksel_parent,
+       .clksel         = gpio0_dbclk_mux_sel,
+       .clksel_reg     = AM33XX_CLKSEL_GPIO0_DBCLK,
+       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static struct clk gpio0_dbclk = {
+       .name           = "gpio0_dbclk",
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &gpio0_dbclk_mux_ck,
+       .enable_reg     = AM33XX_CM_WKUP_GPIO0_CLKCTRL,
+       .enable_bit     = AM33XX_OPTFCLKEN_GPIO0_GDBCLK_SHIFT,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk gpio1_dbclk = {
+       .name           = "gpio1_dbclk",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &clkdiv32k_ick,
+       .enable_reg     = AM33XX_CM_PER_GPIO1_CLKCTRL,
+       .enable_bit     = AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_SHIFT,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk gpio2_dbclk = {
+       .name           = "gpio2_dbclk",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &clkdiv32k_ick,
+       .enable_reg     = AM33XX_CM_PER_GPIO2_CLKCTRL,
+       .enable_bit     = AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_SHIFT,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk gpio3_dbclk = {
+       .name           = "gpio3_dbclk",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &clkdiv32k_ick,
+       .enable_reg     = AM33XX_CM_PER_GPIO3_CLKCTRL,
+       .enable_bit     = AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_SHIFT,
+       .ops            = &clkops_omap2_dflt,
+       .recalc         = &followparent_recalc,
+};
+
+static const struct clksel pruss_ocp_clk_mux_sel[] = {
+       { .parent = &l3_gclk, .rates = div_1_0_rates },
+       { .parent = &dpll_disp_m2_ck, .rates = div_1_1_rates },
+       { .parent = NULL },
+};
+
+static struct clk pruss_ocp_gclk = {
+       .name           = "pruss_ocp_gclk",
+       .clkdm_name     = "pruss_ocp_clkdm",
+       .parent         = &l3_gclk,
+       .init           = &omap2_init_clksel_parent,
+       .clksel         = pruss_ocp_clk_mux_sel,
+       .clksel_reg     = AM33XX_CLKSEL_PRUSS_OCP_CLK,
+       .clksel_mask    = AM33XX_CLKSEL_0_0_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+static const struct clksel lcd_clk_mux_sel[] = {
+       { .parent = &dpll_disp_m2_ck, .rates = div_1_0_rates },
+       { .parent = &dpll_core_m5_ck, .rates = div_1_1_rates },
+       { .parent = &dpll_per_m2_ck, .rates = div_1_2_rates },
+       { .parent = NULL },
+};
+
+static struct clk lcd_gclk = {
+       .name           = "lcd_gclk",
+       .clkdm_name     = "lcdc_clkdm",
+       .parent         = &dpll_disp_m2_ck,
+       .init           = &omap2_init_clksel_parent,
+       .clksel         = lcd_clk_mux_sel,
+       .clksel_reg     = AM33XX_CLKSEL_LCDC_PIXEL_CLK,
+       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+static struct clk mmc_clk = {
+       .name           = "mmc_clk",
+       .clkdm_name     = "l4ls_clkdm",
+       .parent         = &dpll_per_m2_ck,
+       .ops            = &clkops_null,
+       .fixed_div      = 2,
+       .recalc         = &omap_fixed_divisor_recalc,
+};
+
+static struct clk mmc2_fck = {
+       .name           = "mmc2_fck",
+       .clkdm_name     = "l3s_clkdm",
+       .parent         = &mmc_clk,
+       .ops            = &clkops_null,
+       .recalc         = &followparent_recalc,
+};
+
+static const struct clksel gfx_clksel_sel[] = {
+       { .parent = &dpll_core_m4_ck, .rates = div_1_0_rates },
+       { .parent = &dpll_per_m2_ck, .rates = div_1_1_rates },
+       { .parent = NULL },
+};
+
+static struct clk gfx_fclk_clksel_ck = {
+       .name           = "gfx_fclk_clksel_ck",
+       .parent         = &dpll_core_m4_ck,
+       .clksel         = gfx_clksel_sel,
+       .ops            = &clkops_null,
+       .clksel_reg     = AM33XX_CLKSEL_GFX_FCLK,
+       .clksel_mask    = AM33XX_CLKSEL_GFX_FCLK_MASK,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+static const struct clksel_rate div_1_0_2_1_rates[] = {
+       { .div = 1, .val = 0, .flags = RATE_IN_AM33XX },
+       { .div = 2, .val = 1, .flags = RATE_IN_AM33XX },
+       { .div = 0 },
+};
+
+static const struct clksel gfx_div_sel[] = {
+       { .parent = &gfx_fclk_clksel_ck, .rates = div_1_0_2_1_rates },
+       { .parent = NULL },
+};
+
+static struct clk gfx_fck_div_ck = {
+       .name           = "gfx_fck_div_ck",
+       .clkdm_name     = "gfx_l3_clkdm",
+       .parent         = &gfx_fclk_clksel_ck,
+       .init           = &omap2_init_clksel_parent,
+       .clksel         = gfx_div_sel,
+       .clksel_reg     = AM33XX_CLKSEL_GFX_FCLK,
+       .clksel_mask    = AM33XX_CLKSEL_0_0_MASK,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+       .ops            = &clkops_null,
+};
+
+static const struct clksel sysclkout_pre_sel[] = {
+       { .parent = &clk_32768_ck, .rates = div_1_0_rates },
+       { .parent = &l3_gclk, .rates = div_1_1_rates },
+       { .parent = &dpll_ddr_m2_ck, .rates = div_1_2_rates },
+       { .parent = &dpll_per_m2_ck, .rates = div_1_3_rates },
+       { .parent = &lcd_gclk, .rates = div_1_4_rates },
+       { .parent = NULL },
+};
+
+static struct clk sysclkout_pre_ck = {
+       .name           = "sysclkout_pre_ck",
+       .parent         = &clk_32768_ck,
+       .init           = &omap2_init_clksel_parent,
+       .clksel         = sysclkout_pre_sel,
+       .clksel_reg     = AM33XX_CM_CLKOUT_CTRL,
+       .clksel_mask    = AM33XX_CLKOUT2SOURCE_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+/* Divide by 8 clock rates with default clock is 1/1*/
+static const struct clksel_rate div8_rates[] = {
+       { .div = 1, .val = 0, .flags = RATE_IN_AM33XX },
+       { .div = 2, .val = 1, .flags = RATE_IN_AM33XX },
+       { .div = 3, .val = 2, .flags = RATE_IN_AM33XX },
+       { .div = 4, .val = 3, .flags = RATE_IN_AM33XX },
+       { .div = 5, .val = 4, .flags = RATE_IN_AM33XX },
+       { .div = 6, .val = 5, .flags = RATE_IN_AM33XX },
+       { .div = 7, .val = 6, .flags = RATE_IN_AM33XX },
+       { .div = 8, .val = 7, .flags = RATE_IN_AM33XX },
+       { .div = 0 },
+};
+
+static const struct clksel clkout2_div[] = {
+       { .parent = &sysclkout_pre_ck, .rates = div8_rates },
+       { .parent = NULL },
+};
+
+static struct clk clkout2_ck = {
+       .name           = "clkout2_ck",
+       .parent         = &sysclkout_pre_ck,
+       .ops            = &clkops_omap2_dflt,
+       .clksel         = clkout2_div,
+       .clksel_reg     = AM33XX_CM_CLKOUT_CTRL,
+       .clksel_mask    = AM33XX_CLKOUT2DIV_MASK,
+       .enable_reg     = AM33XX_CM_CLKOUT_CTRL,
+       .enable_bit     = AM33XX_CLKOUT2EN_SHIFT,
+       .recalc         = &omap2_clksel_recalc,
+       .round_rate     = &omap2_clksel_round_rate,
+       .set_rate       = &omap2_clksel_set_rate,
+};
+
+static const struct clksel wdt_clkmux_sel[] = {
+       { .parent = &clk_rc32k_ck, .rates = div_1_0_rates },
+       { .parent = &clkdiv32k_ick, .rates = div_1_1_rates },
+       { .parent = NULL },
+};
+
+static struct clk wdt1_fck = {
+       .name           = "wdt1_fck",
+       .clkdm_name     = "l4_wkup_clkdm",
+       .parent         = &clk_rc32k_ck,
+       .init           = &omap2_init_clksel_parent,
+       .clksel         = wdt_clkmux_sel,
+       .clksel_reg     = AM33XX_CLKSEL_WDT1_CLK,
+       .clksel_mask    = AM33XX_CLKSEL_0_1_MASK,
+       .ops            = &clkops_null,
+       .recalc         = &omap2_clksel_recalc,
+};
+
+/*
+ * clkdev
+ */
+static struct omap_clk am33xx_clks[] = {
+       CLK(NULL,       "clk_32768_ck",         &clk_32768_ck,  CK_AM33XX),
+       CLK(NULL,       "clk_rc32k_ck",         &clk_rc32k_ck,  CK_AM33XX),
+       CLK(NULL,       "virt_19200000_ck",     &virt_19200000_ck,      CK_AM33XX),
+       CLK(NULL,       "virt_24000000_ck",     &virt_24000000_ck,      CK_AM33XX),
+       CLK(NULL,       "virt_25000000_ck",     &virt_25000000_ck,      CK_AM33XX),
+       CLK(NULL,       "virt_26000000_ck",     &virt_26000000_ck,      CK_AM33XX),
+       CLK(NULL,       "sys_clkin_ck",         &sys_clkin_ck,  CK_AM33XX),
+       CLK(NULL,       "tclkin_ck",            &tclkin_ck,     CK_AM33XX),
+       CLK(NULL,       "dpll_core_ck",         &dpll_core_ck,  CK_AM33XX),
+       CLK(NULL,       "dpll_core_x2_ck",      &dpll_core_x2_ck,       CK_AM33XX),
+       CLK(NULL,       "dpll_core_m4_ck",      &dpll_core_m4_ck,       CK_AM33XX),
+       CLK(NULL,       "dpll_core_m5_ck",      &dpll_core_m5_ck,       CK_AM33XX),
+       CLK(NULL,       "dpll_core_m6_ck",      &dpll_core_m6_ck,       CK_AM33XX),
+       CLK(NULL,       "dpll_mpu_ck",          &dpll_mpu_ck,   CK_AM33XX),
+       CLK(NULL,       "dpll_mpu_m2_ck",       &dpll_mpu_m2_ck,        CK_AM33XX),
+       CLK(NULL,       "dpll_ddr_ck",          &dpll_ddr_ck,   CK_AM33XX),
+       CLK(NULL,       "dpll_ddr_m2_ck",       &dpll_ddr_m2_ck,        CK_AM33XX),
+       CLK(NULL,       "dpll_ddr_m2_div2_ck",  &dpll_ddr_m2_div2_ck,   CK_AM33XX),
+       CLK(NULL,       "dpll_disp_ck",         &dpll_disp_ck,  CK_AM33XX),
+       CLK(NULL,       "dpll_disp_m2_ck",      &dpll_disp_m2_ck,       CK_AM33XX),
+       CLK(NULL,       "dpll_per_ck",          &dpll_per_ck,   CK_AM33XX),
+       CLK(NULL,       "dpll_per_m2_ck",       &dpll_per_m2_ck,        CK_AM33XX),
+       CLK(NULL,       "dpll_per_m2_div4_wkupdm_ck",   &dpll_per_m2_div4_wkupdm_ck,    CK_AM33XX),
+       CLK(NULL,       "dpll_per_m2_div4_ck",  &dpll_per_m2_div4_ck,   CK_AM33XX),
+       CLK(NULL,       "adc_tsc_fck",          &adc_tsc_fck,   CK_AM33XX),
+       CLK(NULL,       "cefuse_fck",           &cefuse_fck,    CK_AM33XX),
+       CLK(NULL,       "clkdiv32k_ick",        &clkdiv32k_ick, CK_AM33XX),
+       CLK(NULL,       "dcan0_fck",            &dcan0_fck,     CK_AM33XX),
+       CLK(NULL,       "dcan1_fck",            &dcan1_fck,     CK_AM33XX),
+       CLK(NULL,       "debugss_ick",          &debugss_ick,   CK_AM33XX),
+       CLK(NULL,       "pruss_ocp_gclk",       &pruss_ocp_gclk,        CK_AM33XX),
+       CLK("davinci-mcasp.0",  NULL,           &mcasp0_fck,    CK_AM33XX),
+       CLK("davinci-mcasp.1",  NULL,           &mcasp1_fck,    CK_AM33XX),
+       CLK("NULL",     "mmc2_fck",             &mmc2_fck,      CK_AM33XX),
+       CLK(NULL,       "mmu_fck",              &mmu_fck,       CK_AM33XX),
+       CLK(NULL,       "smartreflex0_fck",     &smartreflex0_fck,      CK_AM33XX),
+       CLK(NULL,       "smartreflex1_fck",     &smartreflex1_fck,      CK_AM33XX),
+       CLK(NULL,       "gpt1_fck",             &timer1_fck,    CK_AM33XX),
+       CLK(NULL,       "gpt2_fck",             &timer2_fck,    CK_AM33XX),
+       CLK(NULL,       "gpt3_fck",             &timer3_fck,    CK_AM33XX),
+       CLK(NULL,       "gpt4_fck",             &timer4_fck,    CK_AM33XX),
+       CLK(NULL,       "gpt5_fck",             &timer5_fck,    CK_AM33XX),
+       CLK(NULL,       "gpt6_fck",             &timer6_fck,    CK_AM33XX),
+       CLK(NULL,       "gpt7_fck",             &timer7_fck,    CK_AM33XX),
+       CLK(NULL,       "usbotg_fck",           &usbotg_fck,    CK_AM33XX),
+       CLK(NULL,       "ieee5000_fck",         &ieee5000_fck,  CK_AM33XX),
+       CLK(NULL,       "wdt1_fck",             &wdt1_fck,      CK_AM33XX),
+       CLK(NULL,       "l4_rtc_gclk",          &l4_rtc_gclk,   CK_AM33XX),
+       CLK(NULL,       "l3_gclk",              &l3_gclk,       CK_AM33XX),
+       CLK(NULL,       "dpll_core_m4_div2_ck", &dpll_core_m4_div2_ck,  CK_AM33XX),
+       CLK(NULL,       "l4hs_gclk",            &l4hs_gclk,     CK_AM33XX),
+       CLK(NULL,       "l3s_gclk",             &l3s_gclk,      CK_AM33XX),
+       CLK(NULL,       "l4fw_gclk",            &l4fw_gclk,     CK_AM33XX),
+       CLK(NULL,       "l4ls_gclk",            &l4ls_gclk,     CK_AM33XX),
+       CLK(NULL,       "clk_24mhz",            &clk_24mhz,     CK_AM33XX),
+       CLK(NULL,       "sysclk_div_ck",        &sysclk_div_ck, CK_AM33XX),
+       CLK(NULL,       "cpsw_125mhz_gclk",     &cpsw_125mhz_gclk,      CK_AM33XX),
+       CLK(NULL,       "cpsw_cpts_rft_clk",    &cpsw_cpts_rft_clk,     CK_AM33XX),
+       CLK(NULL,       "gpio0_dbclk_mux_ck",   &gpio0_dbclk_mux_ck,    CK_AM33XX),
+       CLK(NULL,       "gpio0_dbclk",          &gpio0_dbclk,   CK_AM33XX),
+       CLK(NULL,       "gpio1_dbclk",          &gpio1_dbclk,   CK_AM33XX),
+       CLK(NULL,       "gpio2_dbclk",          &gpio2_dbclk,   CK_AM33XX),
+       CLK(NULL,       "gpio3_dbclk",          &gpio3_dbclk,   CK_AM33XX),
+       CLK(NULL,       "lcd_gclk",             &lcd_gclk,      CK_AM33XX),
+       CLK(NULL,       "mmc_clk",              &mmc_clk,       CK_AM33XX),
+       CLK(NULL,       "gfx_fclk_clksel_ck",   &gfx_fclk_clksel_ck,    CK_AM33XX),
+       CLK(NULL,       "gfx_fck_div_ck",       &gfx_fck_div_ck,        CK_AM33XX),
+       CLK(NULL,       "sysclkout_pre_ck",     &sysclkout_pre_ck,      CK_AM33XX),
+       CLK(NULL,       "clkout2_ck",           &clkout2_ck,    CK_AM33XX),
+};
+
+int __init am33xx_clk_init(void)
+{
+       struct omap_clk *c;
+       u32 cpu_clkflg;
+
+       if (soc_is_am33xx()) {
+               cpu_mask = RATE_IN_AM33XX;
+               cpu_clkflg = CK_AM33XX;
+       }
+
+       clk_init(&omap2_clk_functions);
+
+       for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++)
+               clk_preinit(c->lk.clk);
+
+       for (c = am33xx_clks; c < am33xx_clks + ARRAY_SIZE(am33xx_clks); c++) {
+               if (c->cpu & cpu_clkflg) {
+                       clkdev_add(&c->lk);
+                       clk_register(c->lk.clk);
+                       omap2_init_clk_clkdm(c->lk.clk);
+               }
+       }
+
+       recalculate_root_clocks();
+
+       /*
+        * Only enable those clocks we will need, let the drivers
+        * enable other clocks as necessary
+        */
+       clk_enable_init_clocks();
+
+       return 0;
+}
index 1efdec236ae89dac6671bbd8f09d7cffb2067deb..91b3d5c60bfe31952e4b91d98a55b597471e6462 100644 (file)
@@ -93,18 +93,6 @@ static struct clk virt_16_8m_ck = {
        .rate           = 16800000,
 };
 
-static struct clk virt_19_2m_ck = {
-       .name           = "virt_19_2m_ck",
-       .ops            = &clkops_null,
-       .rate           = 19200000,
-};
-
-static struct clk virt_26m_ck = {
-       .name           = "virt_26m_ck",
-       .ops            = &clkops_null,
-       .rate           = 26000000,
-};
-
 static struct clk virt_38_4m_ck = {
        .name           = "virt_38_4m_ck",
        .ops            = &clkops_null,
@@ -145,8 +133,8 @@ static const struct clksel osc_sys_clksel[] = {
        { .parent = &virt_12m_ck,   .rates = osc_sys_12m_rates },
        { .parent = &virt_13m_ck,   .rates = osc_sys_13m_rates },
        { .parent = &virt_16_8m_ck, .rates = osc_sys_16_8m_rates },
-       { .parent = &virt_19_2m_ck, .rates = osc_sys_19_2m_rates },
-       { .parent = &virt_26m_ck,   .rates = osc_sys_26m_rates },
+       { .parent = &virt_19200000_ck, .rates = osc_sys_19_2m_rates },
+       { .parent = &virt_26000000_ck,   .rates = osc_sys_26m_rates },
        { .parent = &virt_38_4m_ck, .rates = osc_sys_38_4m_rates },
        { .parent = NULL },
 };
@@ -2490,13 +2478,13 @@ static struct clk uart4_fck = {
 };
 
 static struct clk uart4_fck_am35xx = {
-       .name           = "uart4_fck",
-       .ops            = &clkops_omap2_dflt_wait,
-       .parent         = &per_48m_fck,
-       .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
-       .enable_bit     = OMAP3430_EN_UART4_SHIFT,
-       .clkdm_name     = "core_l4_clkdm",
-       .recalc         = &followparent_recalc,
+       .name           = "uart4_fck",
+       .ops            = &clkops_omap2_dflt_wait,
+       .parent         = &core_48m_fck,
+       .enable_reg     = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
+       .enable_bit     = AM35XX_EN_UART4_SHIFT,
+       .clkdm_name     = "core_l4_clkdm",
+       .recalc         = &followparent_recalc,
 };
 
 static struct clk gpt2_fck = {
@@ -3201,8 +3189,12 @@ static struct clk vpfe_fck = {
 };
 
 /*
- * The UART1/2 functional clock acts as the functional
- * clock for UART4. No separate fclk control available.
+ * The UART1/2 functional clock acts as the functional clock for
+ * UART4. No separate fclk control available.  XXX Well now we have a
+ * uart4_fck that is apparently used as the UART4 functional clock,
+ * but it also seems that uart1_fck or uart2_fck are still needed, at
+ * least for UART4 softresets to complete.  This really needs
+ * clarification.
  */
 static struct clk uart4_ick_am35xx = {
        .name           = "uart4_ick",
@@ -3230,17 +3222,12 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "virt_12m_ck",  &virt_12m_ck,   CK_3XXX),
        CLK(NULL,       "virt_13m_ck",  &virt_13m_ck,   CK_3XXX),
        CLK(NULL,       "virt_16_8m_ck", &virt_16_8m_ck, CK_3430ES2PLUS | CK_AM35XX  | CK_36XX),
-       CLK(NULL,       "virt_19_2m_ck", &virt_19_2m_ck, CK_3XXX),
-       CLK(NULL,       "virt_26m_ck",  &virt_26m_ck,   CK_3XXX),
+       CLK(NULL,       "virt_19200000_ck", &virt_19200000_ck, CK_3XXX),
+       CLK(NULL,       "virt_26000000_ck",     &virt_26000000_ck,      CK_3XXX),
        CLK(NULL,       "virt_38_4m_ck", &virt_38_4m_ck, CK_3XXX),
        CLK(NULL,       "osc_sys_ck",   &osc_sys_ck,    CK_3XXX),
        CLK(NULL,       "sys_ck",       &sys_ck,        CK_3XXX),
        CLK(NULL,       "sys_altclk",   &sys_altclk,    CK_3XXX),
-       CLK("omap-mcbsp.1",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
-       CLK("omap-mcbsp.2",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
-       CLK("omap-mcbsp.3",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
-       CLK("omap-mcbsp.4",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
-       CLK("omap-mcbsp.5",     "pad_fck",      &mcbsp_clks,    CK_3XXX),
        CLK(NULL,       "mcbsp_clks",   &mcbsp_clks,    CK_3XXX),
        CLK(NULL,       "sys_clkout1",  &sys_clkout1,   CK_3XXX),
        CLK(NULL,       "dpll1_ck",     &dpll1_ck,      CK_3XXX),
@@ -3307,8 +3294,6 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "ts_fck",       &ts_fck,        CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
        CLK(NULL,       "usbtll_fck",   &usbtll_fck,    CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
        CLK("usbhs_omap",       "usbtll_fck",   &usbtll_fck,    CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-       CLK("omap-mcbsp.1",     "prcm_fck",     &core_96m_fck,  CK_3XXX),
-       CLK("omap-mcbsp.5",     "prcm_fck",     &core_96m_fck,  CK_3XXX),
        CLK(NULL,       "core_96m_fck", &core_96m_fck,  CK_3XXX),
        CLK(NULL,       "mmchs3_fck",   &mmchs3_fck,    CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
        CLK(NULL,       "mmchs2_fck",   &mmchs2_fck,    CK_3XXX),
@@ -3413,9 +3398,6 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "omap_32ksync_ick", &omap_32ksync_ick, CK_3XXX),
        CLK(NULL,       "gpt12_ick",    &gpt12_ick,     CK_3XXX),
        CLK(NULL,       "gpt1_ick",     &gpt1_ick,      CK_3XXX),
-       CLK("omap-mcbsp.2",     "prcm_fck",     &per_96m_fck,   CK_3XXX),
-       CLK("omap-mcbsp.3",     "prcm_fck",     &per_96m_fck,   CK_3XXX),
-       CLK("omap-mcbsp.4",     "prcm_fck",     &per_96m_fck,   CK_3XXX),
        CLK(NULL,       "per_96m_fck",  &per_96m_fck,   CK_3XXX),
        CLK(NULL,       "per_48m_fck",  &per_48m_fck,   CK_3XXX),
        CLK(NULL,       "uart3_fck",    &uart3_fck,     CK_3XXX),
@@ -3474,38 +3456,16 @@ static struct omap_clk omap3xxx_clks[] = {
        CLK(NULL,       "ipss_ick",     &ipss_ick,      CK_AM35XX),
        CLK(NULL,       "rmii_ck",      &rmii_ck,       CK_AM35XX),
        CLK(NULL,       "pclk_ck",      &pclk_ck,       CK_AM35XX),
-       CLK("davinci_emac",     NULL,   &emac_ick,      CK_AM35XX),
+       CLK("davinci_emac.0",   NULL,   &emac_ick,      CK_AM35XX),
        CLK("davinci_mdio.0",   NULL,   &emac_fck,      CK_AM35XX),
        CLK("vpfe-capture",     "master",       &vpfe_ick,      CK_AM35XX),
        CLK("vpfe-capture",     "slave",        &vpfe_fck,      CK_AM35XX),
-       CLK("musb-am35x",       "ick",          &hsotgusb_ick_am35xx,   CK_AM35XX),
-       CLK("musb-am35x",       "fck",          &hsotgusb_fck_am35xx,   CK_AM35XX),
+       CLK(NULL,       "hsotgusb_ick",         &hsotgusb_ick_am35xx,   CK_AM35XX),
+       CLK(NULL,       "hsotgusb_fck",         &hsotgusb_fck_am35xx,   CK_AM35XX),
        CLK(NULL,       "hecc_ck",      &hecc_ck,       CK_AM35XX),
        CLK(NULL,       "uart4_ick",    &uart4_ick_am35xx,      CK_AM35XX),
-       CLK("omap_timer.1",     "32k_ck",       &omap_32k_fck,  CK_3XXX),
-       CLK("omap_timer.2",     "32k_ck",       &omap_32k_fck,  CK_3XXX),
-       CLK("omap_timer.3",     "32k_ck",       &omap_32k_fck,  CK_3XXX),
-       CLK("omap_timer.4",     "32k_ck",       &omap_32k_fck,  CK_3XXX),
-       CLK("omap_timer.5",     "32k_ck",       &omap_32k_fck,  CK_3XXX),
-       CLK("omap_timer.6",     "32k_ck",       &omap_32k_fck,  CK_3XXX),
-       CLK("omap_timer.7",     "32k_ck",       &omap_32k_fck,  CK_3XXX),
-       CLK("omap_timer.8",     "32k_ck",       &omap_32k_fck,  CK_3XXX),
-       CLK("omap_timer.9",     "32k_ck",       &omap_32k_fck,  CK_3XXX),
-       CLK("omap_timer.10",    "32k_ck",       &omap_32k_fck,  CK_3XXX),
-       CLK("omap_timer.11",    "32k_ck",       &omap_32k_fck,  CK_3XXX),
-       CLK("omap_timer.12",    "32k_ck",       &omap_32k_fck,  CK_3XXX),
-       CLK("omap_timer.1",     "sys_ck",       &sys_ck,        CK_3XXX),
-       CLK("omap_timer.2",     "sys_ck",       &sys_ck,        CK_3XXX),
-       CLK("omap_timer.3",     "sys_ck",       &sys_ck,        CK_3XXX),
-       CLK("omap_timer.4",     "sys_ck",       &sys_ck,        CK_3XXX),
-       CLK("omap_timer.5",     "sys_ck",       &sys_ck,        CK_3XXX),
-       CLK("omap_timer.6",     "sys_ck",       &sys_ck,        CK_3XXX),
-       CLK("omap_timer.7",     "sys_ck",       &sys_ck,        CK_3XXX),
-       CLK("omap_timer.8",     "sys_ck",       &sys_ck,        CK_3XXX),
-       CLK("omap_timer.9",     "sys_ck",       &sys_ck,        CK_3XXX),
-       CLK("omap_timer.10",    "sys_ck",       &sys_ck,        CK_3XXX),
-       CLK("omap_timer.11",    "sys_ck",       &sys_ck,        CK_3XXX),
-       CLK("omap_timer.12",    "sys_ck",       &sys_ck,        CK_3XXX),
+       CLK(NULL,       "timer_32k_ck", &omap_32k_fck,  CK_3XXX),
+       CLK(NULL,       "timer_sys_ck", &sys_ck,        CK_3XXX),
 };
 
 
@@ -3523,7 +3483,7 @@ int __init omap3xxx_clk_init(void)
        } else if (cpu_is_ti816x()) {
                cpu_mask = RATE_IN_TI816X;
                cpu_clkflg = CK_TI816X;
-       } else if (cpu_is_am33xx()) {
+       } else if (soc_is_am33xx()) {
                cpu_mask = RATE_IN_AM33XX;
        } else if (cpu_is_ti814x()) {
                cpu_mask = RATE_IN_TI814X;
index ba6f9a0a43e9096776963ea1285eea34fb1a24f8..d7f55e43b76189537ee84e32d5c0965f9e79f487 100644 (file)
@@ -107,18 +107,6 @@ static struct clk virt_16800000_ck = {
        .rate           = 16800000,
 };
 
-static struct clk virt_19200000_ck = {
-       .name           = "virt_19200000_ck",
-       .ops            = &clkops_null,
-       .rate           = 19200000,
-};
-
-static struct clk virt_26000000_ck = {
-       .name           = "virt_26000000_ck",
-       .ops            = &clkops_null,
-       .rate           = 26000000,
-};
-
 static struct clk virt_27000000_ck = {
        .name           = "virt_27000000_ck",
        .ops            = &clkops_null,
@@ -131,31 +119,6 @@ static struct clk virt_38400000_ck = {
        .rate           = 38400000,
 };
 
-static const struct clksel_rate div_1_0_rates[] = {
-       { .div = 1, .val = 0, .flags = RATE_IN_4430 },
-       { .div = 0 },
-};
-
-static const struct clksel_rate div_1_1_rates[] = {
-       { .div = 1, .val = 1, .flags = RATE_IN_4430 },
-       { .div = 0 },
-};
-
-static const struct clksel_rate div_1_2_rates[] = {
-       { .div = 1, .val = 2, .flags = RATE_IN_4430 },
-       { .div = 0 },
-};
-
-static const struct clksel_rate div_1_3_rates[] = {
-       { .div = 1, .val = 3, .flags = RATE_IN_4430 },
-       { .div = 0 },
-};
-
-static const struct clksel_rate div_1_4_rates[] = {
-       { .div = 1, .val = 4, .flags = RATE_IN_4430 },
-       { .div = 0 },
-};
-
 static const struct clksel_rate div_1_5_rates[] = {
        { .div = 1, .val = 5, .flags = RATE_IN_4430 },
        { .div = 0 },
@@ -289,41 +252,6 @@ static struct clk dpll_abe_x2_ck = {
        .recalc         = &omap3_clkoutx2_recalc,
 };
 
-static const struct clksel_rate div31_1to31_rates[] = {
-       { .div = 1, .val = 1, .flags = RATE_IN_4430 },
-       { .div = 2, .val = 2, .flags = RATE_IN_4430 },
-       { .div = 3, .val = 3, .flags = RATE_IN_4430 },
-       { .div = 4, .val = 4, .flags = RATE_IN_4430 },
-       { .div = 5, .val = 5, .flags = RATE_IN_4430 },
-       { .div = 6, .val = 6, .flags = RATE_IN_4430 },
-       { .div = 7, .val = 7, .flags = RATE_IN_4430 },
-       { .div = 8, .val = 8, .flags = RATE_IN_4430 },
-       { .div = 9, .val = 9, .flags = RATE_IN_4430 },
-       { .div = 10, .val = 10, .flags = RATE_IN_4430 },
-       { .div = 11, .val = 11, .flags = RATE_IN_4430 },
-       { .div = 12, .val = 12, .flags = RATE_IN_4430 },
-       { .div = 13, .val = 13, .flags = RATE_IN_4430 },
-       { .div = 14, .val = 14, .flags = RATE_IN_4430 },
-       { .div = 15, .val = 15, .flags = RATE_IN_4430 },
-       { .div = 16, .val = 16, .flags = RATE_IN_4430 },
-       { .div = 17, .val = 17, .flags = RATE_IN_4430 },
-       { .div = 18, .val = 18, .flags = RATE_IN_4430 },
-       { .div = 19, .val = 19, .flags = RATE_IN_4430 },
-       { .div = 20, .val = 20, .flags = RATE_IN_4430 },
-       { .div = 21, .val = 21, .flags = RATE_IN_4430 },
-       { .div = 22, .val = 22, .flags = RATE_IN_4430 },
-       { .div = 23, .val = 23, .flags = RATE_IN_4430 },
-       { .div = 24, .val = 24, .flags = RATE_IN_4430 },
-       { .div = 25, .val = 25, .flags = RATE_IN_4430 },
-       { .div = 26, .val = 26, .flags = RATE_IN_4430 },
-       { .div = 27, .val = 27, .flags = RATE_IN_4430 },
-       { .div = 28, .val = 28, .flags = RATE_IN_4430 },
-       { .div = 29, .val = 29, .flags = RATE_IN_4430 },
-       { .div = 30, .val = 30, .flags = RATE_IN_4430 },
-       { .div = 31, .val = 31, .flags = RATE_IN_4430 },
-       { .div = 0 },
-};
-
 static const struct clksel dpll_abe_m2x2_div[] = {
        { .parent = &dpll_abe_x2_ck, .rates = div31_1to31_rates },
        { .parent = NULL },
@@ -3299,17 +3227,17 @@ static struct omap_clk omap44xx_clks[] = {
        CLK(NULL,       "smartreflex_core_fck",         &smartreflex_core_fck,  CK_443X),
        CLK(NULL,       "smartreflex_iva_fck",          &smartreflex_iva_fck,   CK_443X),
        CLK(NULL,       "smartreflex_mpu_fck",          &smartreflex_mpu_fck,   CK_443X),
-       CLK(NULL,       "gpt1_fck",                     &timer1_fck,    CK_443X),
-       CLK(NULL,       "gpt10_fck",                    &timer10_fck,   CK_443X),
-       CLK(NULL,       "gpt11_fck",                    &timer11_fck,   CK_443X),
-       CLK(NULL,       "gpt2_fck",                     &timer2_fck,    CK_443X),
-       CLK(NULL,       "gpt3_fck",                     &timer3_fck,    CK_443X),
-       CLK(NULL,       "gpt4_fck",                     &timer4_fck,    CK_443X),
-       CLK(NULL,       "gpt5_fck",                     &timer5_fck,    CK_443X),
-       CLK(NULL,       "gpt6_fck",                     &timer6_fck,    CK_443X),
-       CLK(NULL,       "gpt7_fck",                     &timer7_fck,    CK_443X),
-       CLK(NULL,       "gpt8_fck",                     &timer8_fck,    CK_443X),
-       CLK(NULL,       "gpt9_fck",                     &timer9_fck,    CK_443X),
+       CLK(NULL,       "timer1_fck",                   &timer1_fck,    CK_443X),
+       CLK(NULL,       "timer10_fck",                  &timer10_fck,   CK_443X),
+       CLK(NULL,       "timer11_fck",                  &timer11_fck,   CK_443X),
+       CLK(NULL,       "timer2_fck",                   &timer2_fck,    CK_443X),
+       CLK(NULL,       "timer3_fck",                   &timer3_fck,    CK_443X),
+       CLK(NULL,       "timer4_fck",                   &timer4_fck,    CK_443X),
+       CLK(NULL,       "timer5_fck",                   &timer5_fck,    CK_443X),
+       CLK(NULL,       "timer6_fck",                   &timer6_fck,    CK_443X),
+       CLK(NULL,       "timer7_fck",                   &timer7_fck,    CK_443X),
+       CLK(NULL,       "timer8_fck",                   &timer8_fck,    CK_443X),
+       CLK(NULL,       "timer9_fck",                   &timer9_fck,    CK_443X),
        CLK(NULL,       "uart1_fck",                    &uart1_fck,     CK_443X),
        CLK(NULL,       "uart2_fck",                    &uart2_fck,     CK_443X),
        CLK(NULL,       "uart3_fck",                    &uart3_fck,     CK_443X),
@@ -3385,28 +3313,18 @@ static struct omap_clk omap44xx_clks[] = {
        CLK("usbhs_omap",       "usbhost_ick",          &dummy_ck,              CK_443X),
        CLK("usbhs_omap",       "usbtll_fck",           &dummy_ck,      CK_443X),
        CLK("omap_wdt", "ick",                          &dummy_ck,      CK_443X),
-       CLK("omap_timer.1",     "32k_ck",       &sys_32k_ck,    CK_443X),
-       CLK("omap_timer.2",     "32k_ck",       &sys_32k_ck,    CK_443X),
-       CLK("omap_timer.3",     "32k_ck",       &sys_32k_ck,    CK_443X),
-       CLK("omap_timer.4",     "32k_ck",       &sys_32k_ck,    CK_443X),
-       CLK("omap_timer.5",     "32k_ck",       &sys_32k_ck,    CK_443X),
-       CLK("omap_timer.6",     "32k_ck",       &sys_32k_ck,    CK_443X),
-       CLK("omap_timer.7",     "32k_ck",       &sys_32k_ck,    CK_443X),
-       CLK("omap_timer.8",     "32k_ck",       &sys_32k_ck,    CK_443X),
-       CLK("omap_timer.9",     "32k_ck",       &sys_32k_ck,    CK_443X),
-       CLK("omap_timer.10",    "32k_ck",       &sys_32k_ck,    CK_443X),
-       CLK("omap_timer.11",    "32k_ck",       &sys_32k_ck,    CK_443X),
-       CLK("omap_timer.1",     "sys_ck",       &sys_clkin_ck,  CK_443X),
-       CLK("omap_timer.2",     "sys_ck",       &sys_clkin_ck,  CK_443X),
-       CLK("omap_timer.3",     "sys_ck",       &sys_clkin_ck,  CK_443X),
-       CLK("omap_timer.4",     "sys_ck",       &sys_clkin_ck,  CK_443X),
-       CLK("omap_timer.9",     "sys_ck",       &sys_clkin_ck,  CK_443X),
-       CLK("omap_timer.10",    "sys_ck",       &sys_clkin_ck,  CK_443X),
-       CLK("omap_timer.11",    "sys_ck",       &sys_clkin_ck,  CK_443X),
-       CLK("omap_timer.5",     "sys_ck",       &syc_clk_div_ck,        CK_443X),
-       CLK("omap_timer.6",     "sys_ck",       &syc_clk_div_ck,        CK_443X),
-       CLK("omap_timer.7",     "sys_ck",       &syc_clk_div_ck,        CK_443X),
-       CLK("omap_timer.8",     "sys_ck",       &syc_clk_div_ck,        CK_443X),
+       CLK(NULL,       "timer_32k_ck", &sys_32k_ck,    CK_443X),
+       CLK("omap_timer.1",     "timer_sys_ck", &sys_clkin_ck,  CK_443X),
+       CLK("omap_timer.2",     "timer_sys_ck", &sys_clkin_ck,  CK_443X),
+       CLK("omap_timer.3",     "timer_sys_ck", &sys_clkin_ck,  CK_443X),
+       CLK("omap_timer.4",     "timer_sys_ck", &sys_clkin_ck,  CK_443X),
+       CLK("omap_timer.9",     "timer_sys_ck", &sys_clkin_ck,  CK_443X),
+       CLK("omap_timer.10",    "timer_sys_ck", &sys_clkin_ck,  CK_443X),
+       CLK("omap_timer.11",    "timer_sys_ck", &sys_clkin_ck,  CK_443X),
+       CLK("omap_timer.5",     "timer_sys_ck", &syc_clk_div_ck,        CK_443X),
+       CLK("omap_timer.6",     "timer_sys_ck", &syc_clk_div_ck,        CK_443X),
+       CLK("omap_timer.7",     "timer_sys_ck", &syc_clk_div_ck,        CK_443X),
+       CLK("omap_timer.8",     "timer_sys_ck", &syc_clk_div_ck,        CK_443X),
 };
 
 int __init omap4xxx_clk_init(void)
index 6424d46be14a69b7fa255df9ec3e1b5c410c6a71..b9f3ba68148c793d368f51174ca164c4a1081c4f 100644 (file)
@@ -43,3 +43,80 @@ const struct clksel_rate dsp_ick_rates[] = {
        { .div = 3, .val = 3, .flags = RATE_IN_243X },
        { .div = 0 },
 };
+
+
+/* clksel_rate blocks shared between OMAP44xx and AM33xx */
+
+const struct clksel_rate div_1_0_rates[] = {
+       { .div = 1, .val = 0, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 0 },
+};
+
+const struct clksel_rate div_1_1_rates[] = {
+       { .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 0 },
+};
+
+const struct clksel_rate div_1_2_rates[] = {
+       { .div = 1, .val = 2, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 0 },
+};
+
+const struct clksel_rate div_1_3_rates[] = {
+       { .div = 1, .val = 3, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 0 },
+};
+
+const struct clksel_rate div_1_4_rates[] = {
+       { .div = 1, .val = 4, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 0 },
+};
+
+const struct clksel_rate div31_1to31_rates[] = {
+       { .div = 1, .val = 1, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 2, .val = 2, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 3, .val = 3, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 4, .val = 4, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 5, .val = 5, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 6, .val = 6, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 7, .val = 7, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 8, .val = 8, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 9, .val = 9, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 10, .val = 10, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 11, .val = 11, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 12, .val = 12, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 13, .val = 13, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 14, .val = 14, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 15, .val = 15, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 16, .val = 16, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 17, .val = 17, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 18, .val = 18, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 19, .val = 19, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 20, .val = 20, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 21, .val = 21, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 22, .val = 22, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 23, .val = 23, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 24, .val = 24, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 25, .val = 25, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 26, .val = 26, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 27, .val = 27, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 28, .val = 28, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 29, .val = 29, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 30, .val = 30, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 31, .val = 31, .flags = RATE_IN_4430 | RATE_IN_AM33XX },
+       { .div = 0 },
+};
+
+/* Clocks shared between various OMAP SoCs */
+
+struct clk virt_19200000_ck = {
+       .name           = "virt_19200000_ck",
+       .ops            = &clkops_null,
+       .rate           = 19200000,
+};
+
+struct clk virt_26000000_ck = {
+       .name           = "virt_26000000_ck",
+       .ops            = &clkops_null,
+       .rate           = 26000000,
+};
index 6227e9505c2db6858c44bf2b9f30e0abe7ec0023..5601dc13785ed606f0ce1bdf562472270489811a 100644 (file)
@@ -199,6 +199,7 @@ int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh);
 extern void __init omap242x_clockdomains_init(void);
 extern void __init omap243x_clockdomains_init(void);
 extern void __init omap3xxx_clockdomains_init(void);
+extern void __init am33xx_clockdomains_init(void);
 extern void __init omap44xx_clockdomains_init(void);
 extern void _clkdm_add_autodeps(struct clockdomain *clkdm);
 extern void _clkdm_del_autodeps(struct clockdomain *clkdm);
@@ -206,11 +207,10 @@ extern void _clkdm_del_autodeps(struct clockdomain *clkdm);
 extern struct clkdm_ops omap2_clkdm_operations;
 extern struct clkdm_ops omap3_clkdm_operations;
 extern struct clkdm_ops omap4_clkdm_operations;
+extern struct clkdm_ops am33xx_clkdm_operations;
 
 extern struct clkdm_dep gfx_24xx_wkdeps[];
 extern struct clkdm_dep dsp_24xx_wkdeps[];
 extern struct clockdomain wkup_common_clkdm;
-extern struct clockdomain prm_common_clkdm;
-extern struct clockdomain cm_common_clkdm;
 
 #endif
diff --git a/arch/arm/mach-omap2/clockdomain33xx.c b/arch/arm/mach-omap2/clockdomain33xx.c
new file mode 100644 (file)
index 0000000..aca6388
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * AM33XX clockdomain control
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Vaibhav Hiremath <hvaibhav@ti.com>
+ *
+ * Derived from mach-omap2/clockdomain44xx.c written by Rajendra Nayak
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+
+#include "clockdomain.h"
+#include "cm33xx.h"
+
+
+static int am33xx_clkdm_sleep(struct clockdomain *clkdm)
+{
+       am33xx_cm_clkdm_force_sleep(clkdm->cm_inst, clkdm->clkdm_offs);
+       return 0;
+}
+
+static int am33xx_clkdm_wakeup(struct clockdomain *clkdm)
+{
+       am33xx_cm_clkdm_force_wakeup(clkdm->cm_inst, clkdm->clkdm_offs);
+       return 0;
+}
+
+static void am33xx_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+       am33xx_cm_clkdm_enable_hwsup(clkdm->cm_inst, clkdm->clkdm_offs);
+}
+
+static void am33xx_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+       am33xx_cm_clkdm_disable_hwsup(clkdm->cm_inst, clkdm->clkdm_offs);
+}
+
+static int am33xx_clkdm_clk_enable(struct clockdomain *clkdm)
+{
+       if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+               return am33xx_clkdm_wakeup(clkdm);
+
+       return 0;
+}
+
+static int am33xx_clkdm_clk_disable(struct clockdomain *clkdm)
+{
+       bool hwsup = false;
+
+       hwsup = am33xx_cm_is_clkdm_in_hwsup(clkdm->cm_inst, clkdm->clkdm_offs);
+
+       if (!hwsup && (clkdm->flags & CLKDM_CAN_FORCE_SLEEP))
+               am33xx_clkdm_sleep(clkdm);
+
+       return 0;
+}
+
+struct clkdm_ops am33xx_clkdm_operations = {
+       .clkdm_sleep            = am33xx_clkdm_sleep,
+       .clkdm_wakeup           = am33xx_clkdm_wakeup,
+       .clkdm_allow_idle       = am33xx_clkdm_allow_idle,
+       .clkdm_deny_idle        = am33xx_clkdm_deny_idle,
+       .clkdm_clk_enable       = am33xx_clkdm_clk_enable,
+       .clkdm_clk_disable      = am33xx_clkdm_clk_disable,
+};
index 4f04dd11d65570b5cd1a22d7fa8faae90c1bb058..762f2cc542cec0badf1316a5ae9144426892a54b 100644 (file)
@@ -70,7 +70,7 @@ static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
 
 static int omap4_clkdm_sleep(struct clockdomain *clkdm)
 {
-       omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition,
+       omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
                                        clkdm->cm_inst, clkdm->clkdm_offs);
        return 0;
 }
@@ -90,8 +90,12 @@ static void omap4_clkdm_allow_idle(struct clockdomain *clkdm)
 
 static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
 {
-       omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
-                                       clkdm->cm_inst, clkdm->clkdm_offs);
+       if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+               omap4_clkdm_wakeup(clkdm);
+       else
+               omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
+                                                clkdm->cm_inst,
+                                                clkdm->clkdm_offs);
 }
 
 static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
index 0ab8e46d5b2b04d431dd97cfec4345ff98d169a4..5c741852fac0294748d9f417ce9b73494eb25f32 100644 (file)
@@ -131,8 +131,6 @@ static struct clockdomain dss_2420_clkdm = {
 
 static struct clockdomain *clockdomains_omap242x[] __initdata = {
        &wkup_common_clkdm,
-       &cm_common_clkdm,
-       &prm_common_clkdm,
        &mpu_2420_clkdm,
        &iva1_2420_clkdm,
        &dsp_2420_clkdm,
index 3645ed04489042d5ff32b89a73988dcabf7403f7..f09617555e15d7da642621a1f076e2cdf8690bc5 100644 (file)
@@ -157,8 +157,6 @@ static struct clockdomain dss_2430_clkdm = {
 
 static struct clockdomain *clockdomains_omap243x[] __initdata = {
        &wkup_common_clkdm,
-       &cm_common_clkdm,
-       &prm_common_clkdm,
        &mpu_2430_clkdm,
        &mdm_clkdm,
        &dsp_2430_clkdm,
diff --git a/arch/arm/mach-omap2/clockdomains33xx_data.c b/arch/arm/mach-omap2/clockdomains33xx_data.c
new file mode 100644 (file)
index 0000000..32c90fd
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * AM33XX Clock Domain data.
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Vaibhav Hiremath <hvaibhav@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include "clockdomain.h"
+#include "cm.h"
+#include "cm33xx.h"
+#include "cm-regbits-33xx.h"
+
+static struct clockdomain l4ls_am33xx_clkdm = {
+       .name           = "l4ls_clkdm",
+       .pwrdm          = { .name = "per_pwrdm" },
+       .cm_inst        = AM33XX_CM_PER_MOD,
+       .clkdm_offs     = AM33XX_CM_PER_L4LS_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l3s_am33xx_clkdm = {
+       .name           = "l3s_clkdm",
+       .pwrdm          = { .name = "per_pwrdm" },
+       .cm_inst        = AM33XX_CM_PER_MOD,
+       .clkdm_offs     = AM33XX_CM_PER_L3S_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l4fw_am33xx_clkdm = {
+       .name           = "l4fw_clkdm",
+       .pwrdm          = { .name = "per_pwrdm" },
+       .cm_inst        = AM33XX_CM_PER_MOD,
+       .clkdm_offs     = AM33XX_CM_PER_L4FW_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l3_am33xx_clkdm = {
+       .name           = "l3_clkdm",
+       .pwrdm          = { .name = "per_pwrdm" },
+       .cm_inst        = AM33XX_CM_PER_MOD,
+       .clkdm_offs     = AM33XX_CM_PER_L3_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l4hs_am33xx_clkdm = {
+       .name           = "l4hs_clkdm",
+       .pwrdm          = { .name = "per_pwrdm" },
+       .cm_inst        = AM33XX_CM_PER_MOD,
+       .clkdm_offs     = AM33XX_CM_PER_L4HS_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain ocpwp_l3_am33xx_clkdm = {
+       .name           = "ocpwp_l3_clkdm",
+       .pwrdm          = { .name = "per_pwrdm" },
+       .cm_inst        = AM33XX_CM_PER_MOD,
+       .clkdm_offs     = AM33XX_CM_PER_OCPWP_L3_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain pruss_ocp_am33xx_clkdm = {
+       .name           = "pruss_ocp_clkdm",
+       .pwrdm          = { .name = "per_pwrdm" },
+       .cm_inst        = AM33XX_CM_PER_MOD,
+       .clkdm_offs     = AM33XX_CM_PER_PRUSS_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain cpsw_125mhz_am33xx_clkdm = {
+       .name           = "cpsw_125mhz_clkdm",
+       .pwrdm          = { .name = "per_pwrdm" },
+       .cm_inst        = AM33XX_CM_PER_MOD,
+       .clkdm_offs     = AM33XX_CM_PER_CPSW_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain lcdc_am33xx_clkdm = {
+       .name           = "lcdc_clkdm",
+       .pwrdm          = { .name = "per_pwrdm" },
+       .cm_inst        = AM33XX_CM_PER_MOD,
+       .clkdm_offs     = AM33XX_CM_PER_LCDC_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain clk_24mhz_am33xx_clkdm = {
+       .name           = "clk_24mhz_clkdm",
+       .pwrdm          = { .name = "per_pwrdm" },
+       .cm_inst        = AM33XX_CM_PER_MOD,
+       .clkdm_offs     = AM33XX_CM_PER_CLK_24MHZ_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l4_wkup_am33xx_clkdm = {
+       .name           = "l4_wkup_clkdm",
+       .pwrdm          = { .name = "wkup_pwrdm" },
+       .cm_inst        = AM33XX_CM_WKUP_MOD,
+       .clkdm_offs     = AM33XX_CM_WKUP_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l3_aon_am33xx_clkdm = {
+       .name           = "l3_aon_clkdm",
+       .pwrdm          = { .name = "wkup_pwrdm" },
+       .cm_inst        = AM33XX_CM_WKUP_MOD,
+       .clkdm_offs     = AM33XX_CM_L3_AON_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l4_wkup_aon_am33xx_clkdm = {
+       .name           = "l4_wkup_aon_clkdm",
+       .pwrdm          = { .name = "wkup_pwrdm" },
+       .cm_inst        = AM33XX_CM_WKUP_MOD,
+       .clkdm_offs     = AM33XX_CM_L4_WKUP_AON_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain mpu_am33xx_clkdm = {
+       .name           = "mpu_clkdm",
+       .pwrdm          = { .name = "mpu_pwrdm" },
+       .cm_inst        = AM33XX_CM_MPU_MOD,
+       .clkdm_offs     = AM33XX_CM_MPU_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l4_rtc_am33xx_clkdm = {
+       .name           = "l4_rtc_clkdm",
+       .pwrdm          = { .name = "rtc_pwrdm" },
+       .cm_inst        = AM33XX_CM_RTC_MOD,
+       .clkdm_offs     = AM33XX_CM_RTC_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain gfx_l3_am33xx_clkdm = {
+       .name           = "gfx_l3_clkdm",
+       .pwrdm          = { .name = "gfx_pwrdm" },
+       .cm_inst        = AM33XX_CM_GFX_MOD,
+       .clkdm_offs     = AM33XX_CM_GFX_L3_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain gfx_l4ls_gfx_am33xx_clkdm = {
+       .name           = "gfx_l4ls_gfx_clkdm",
+       .pwrdm          = { .name = "gfx_pwrdm" },
+       .cm_inst        = AM33XX_CM_GFX_MOD,
+       .clkdm_offs     = AM33XX_CM_GFX_L4LS_GFX_CLKSTCTRL__1_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain l4_cefuse_am33xx_clkdm = {
+       .name           = "l4_cefuse_clkdm",
+       .pwrdm          = { .name = "cefuse_pwrdm" },
+       .cm_inst        = AM33XX_CM_CEFUSE_MOD,
+       .clkdm_offs     = AM33XX_CM_CEFUSE_CLKSTCTRL_OFFSET,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
+static struct clockdomain *clockdomains_am33xx[] __initdata = {
+       &l4ls_am33xx_clkdm,
+       &l3s_am33xx_clkdm,
+       &l4fw_am33xx_clkdm,
+       &l3_am33xx_clkdm,
+       &l4hs_am33xx_clkdm,
+       &ocpwp_l3_am33xx_clkdm,
+       &pruss_ocp_am33xx_clkdm,
+       &cpsw_125mhz_am33xx_clkdm,
+       &lcdc_am33xx_clkdm,
+       &clk_24mhz_am33xx_clkdm,
+       &l4_wkup_am33xx_clkdm,
+       &l3_aon_am33xx_clkdm,
+       &l4_wkup_aon_am33xx_clkdm,
+       &mpu_am33xx_clkdm,
+       &l4_rtc_am33xx_clkdm,
+       &gfx_l3_am33xx_clkdm,
+       &gfx_l4ls_gfx_am33xx_clkdm,
+       &l4_cefuse_am33xx_clkdm,
+       NULL,
+};
+
+void __init am33xx_clockdomains_init(void)
+{
+       clkdm_register_platform_funcs(&am33xx_clkdm_operations);
+       clkdm_register_clkdms(clockdomains_am33xx);
+       clkdm_complete_init();
+}
index 6038adb977108f6440ea0f002dcba63beefb9b29..56089c49142a9e810a11ca0e60bbcf62f0fae7da 100644 (file)
@@ -59,6 +59,12 @@ static struct clkdm_dep gfx_sgx_3xxx_wkdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep gfx_sgx_am35x_wkdeps[] = {
+       { .clkdm_name = "mpu_clkdm" },
+       { .clkdm_name = "wkup_clkdm" },
+       { NULL },
+};
+
 /* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */
 static struct clkdm_dep per_wkdeps[] = {
        { .clkdm_name = "core_l3_clkdm" },
@@ -69,6 +75,14 @@ static struct clkdm_dep per_wkdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep per_am35x_wkdeps[] = {
+       { .clkdm_name = "core_l3_clkdm" },
+       { .clkdm_name = "core_l4_clkdm" },
+       { .clkdm_name = "mpu_clkdm" },
+       { .clkdm_name = "wkup_clkdm" },
+       { NULL },
+};
+
 /* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */
 static struct clkdm_dep usbhost_wkdeps[] = {
        { .clkdm_name = "core_l3_clkdm" },
@@ -79,6 +93,14 @@ static struct clkdm_dep usbhost_wkdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep usbhost_am35x_wkdeps[] = {
+       { .clkdm_name = "core_l3_clkdm" },
+       { .clkdm_name = "core_l4_clkdm" },
+       { .clkdm_name = "mpu_clkdm" },
+       { .clkdm_name = "wkup_clkdm" },
+       { NULL },
+};
+
 /* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */
 static struct clkdm_dep mpu_3xxx_wkdeps[] = {
        { .clkdm_name = "core_l3_clkdm" },
@@ -89,6 +111,14 @@ static struct clkdm_dep mpu_3xxx_wkdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep mpu_am35x_wkdeps[] = {
+       { .clkdm_name = "core_l3_clkdm" },
+       { .clkdm_name = "core_l4_clkdm" },
+       { .clkdm_name = "dss_clkdm" },
+       { .clkdm_name = "per_clkdm" },
+       { NULL },
+};
+
 /* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */
 static struct clkdm_dep iva2_wkdeps[] = {
        { .clkdm_name = "core_l3_clkdm" },
@@ -116,6 +146,12 @@ static struct clkdm_dep dss_wkdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep dss_am35x_wkdeps[] = {
+       { .clkdm_name = "mpu_clkdm" },
+       { .clkdm_name = "wkup_clkdm" },
+       { NULL },
+};
+
 /* 3430: PM_WKDEP_NEON: MPU */
 static struct clkdm_dep neon_wkdeps[] = {
        { .clkdm_name = "mpu_clkdm" },
@@ -131,6 +167,11 @@ static struct clkdm_dep dss_sleepdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep dss_am35x_sleepdeps[] = {
+       { .clkdm_name = "mpu_clkdm" },
+       { NULL },
+};
+
 /* 3430: CM_SLEEPDEP_PER: MPU, IVA */
 static struct clkdm_dep per_sleepdeps[] = {
        { .clkdm_name = "mpu_clkdm" },
@@ -138,6 +179,11 @@ static struct clkdm_dep per_sleepdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep per_am35x_sleepdeps[] = {
+       { .clkdm_name = "mpu_clkdm" },
+       { NULL },
+};
+
 /* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */
 static struct clkdm_dep usbhost_sleepdeps[] = {
        { .clkdm_name = "mpu_clkdm" },
@@ -145,6 +191,11 @@ static struct clkdm_dep usbhost_sleepdeps[] = {
        { NULL },
 };
 
+static struct clkdm_dep usbhost_am35x_sleepdeps[] = {
+       { .clkdm_name = "mpu_clkdm" },
+       { NULL },
+};
+
 /* 3430: CM_SLEEPDEP_CAM: MPU */
 static struct clkdm_dep cam_sleepdeps[] = {
        { .clkdm_name = "mpu_clkdm" },
@@ -175,6 +226,15 @@ static struct clockdomain mpu_3xxx_clkdm = {
        .clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
 };
 
+static struct clockdomain mpu_am35x_clkdm = {
+       .name           = "mpu_clkdm",
+       .pwrdm          = { .name = "mpu_pwrdm" },
+       .flags          = CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
+       .dep_bit        = OMAP3430_EN_MPU_SHIFT,
+       .wkdep_srcs     = mpu_am35x_wkdeps,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
+};
+
 static struct clockdomain neon_clkdm = {
        .name           = "neon_clkdm",
        .pwrdm          = { .name = "neon_pwrdm" },
@@ -210,6 +270,15 @@ static struct clockdomain sgx_clkdm = {
        .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
 };
 
+static struct clockdomain sgx_am35x_clkdm = {
+       .name           = "sgx_clkdm",
+       .pwrdm          = { .name = "sgx_pwrdm" },
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .wkdep_srcs     = gfx_sgx_am35x_wkdeps,
+       .sleepdep_srcs  = gfx_sgx_sleepdeps,
+       .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
+};
+
 /*
  * The die-to-die clockdomain was documented in the 34xx ES1 TRM, but
  * then that information was removed from the 34xx ES2+ TRM.  It is
@@ -261,6 +330,16 @@ static struct clockdomain dss_3xxx_clkdm = {
        .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
 };
 
+static struct clockdomain dss_am35x_clkdm = {
+       .name           = "dss_clkdm",
+       .pwrdm          = { .name = "dss_pwrdm" },
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .dep_bit        = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
+       .wkdep_srcs     = dss_am35x_wkdeps,
+       .sleepdep_srcs  = dss_am35x_sleepdeps,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
+};
+
 static struct clockdomain cam_clkdm = {
        .name           = "cam_clkdm",
        .pwrdm          = { .name = "cam_pwrdm" },
@@ -279,6 +358,15 @@ static struct clockdomain usbhost_clkdm = {
        .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
 };
 
+static struct clockdomain usbhost_am35x_clkdm = {
+       .name           = "usbhost_clkdm",
+       .pwrdm          = { .name = "core_pwrdm" },
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .wkdep_srcs     = usbhost_am35x_wkdeps,
+       .sleepdep_srcs  = usbhost_am35x_sleepdeps,
+       .clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
+};
+
 static struct clockdomain per_clkdm = {
        .name           = "per_clkdm",
        .pwrdm          = { .name = "per_pwrdm" },
@@ -289,6 +377,16 @@ static struct clockdomain per_clkdm = {
        .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
 };
 
+static struct clockdomain per_am35x_clkdm = {
+       .name           = "per_clkdm",
+       .pwrdm          = { .name = "per_pwrdm" },
+       .flags          = CLKDM_CAN_HWSUP_SWSUP,
+       .dep_bit        = OMAP3430_EN_PER_SHIFT,
+       .wkdep_srcs     = per_am35x_wkdeps,
+       .sleepdep_srcs  = per_am35x_sleepdeps,
+       .clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
+};
+
 /*
  * Disable hw supervised mode for emu_clkdm, because emu_pwrdm is
  * switched of even if sdti is in use
@@ -341,31 +439,42 @@ static struct clkdm_autodep clkdm_autodeps[] = {
        }
 };
 
+static struct clkdm_autodep clkdm_am35x_autodeps[] = {
+       {
+               .clkdm = { .name = "mpu_clkdm" },
+       },
+       {
+               .clkdm = { .name = NULL },
+       }
+};
+
 /*
  *
  */
 
-static struct clockdomain *clockdomains_omap3430_common[] __initdata = {
+static struct clockdomain *clockdomains_common[] __initdata = {
        &wkup_common_clkdm,
-       &cm_common_clkdm,
-       &prm_common_clkdm,
-       &mpu_3xxx_clkdm,
        &neon_clkdm,
-       &iva2_clkdm,
-       &d2d_clkdm,
        &core_l3_3xxx_clkdm,
        &core_l4_3xxx_clkdm,
-       &dss_3xxx_clkdm,
-       &cam_clkdm,
-       &per_clkdm,
        &emu_clkdm,
        &dpll1_clkdm,
-       &dpll2_clkdm,
        &dpll3_clkdm,
        &dpll4_clkdm,
        NULL
 };
 
+static struct clockdomain *clockdomains_omap3430[] __initdata = {
+       &mpu_3xxx_clkdm,
+       &iva2_clkdm,
+       &d2d_clkdm,
+       &dss_3xxx_clkdm,
+       &cam_clkdm,
+       &per_clkdm,
+       &dpll2_clkdm,
+       NULL
+};
+
 static struct clockdomain *clockdomains_omap3430es1[] __initdata = {
        &gfx_3430es1_clkdm,
        NULL,
@@ -378,21 +487,41 @@ static struct clockdomain *clockdomains_omap3430es2plus[] __initdata = {
        NULL,
 };
 
+static struct clockdomain *clockdomains_am35x[] __initdata = {
+       &mpu_am35x_clkdm,
+       &sgx_am35x_clkdm,
+       &dss_am35x_clkdm,
+       &per_am35x_clkdm,
+       &usbhost_am35x_clkdm,
+       &dpll5_clkdm,
+       NULL
+};
+
 void __init omap3xxx_clockdomains_init(void)
 {
        struct clockdomain **sc;
+       unsigned int rev;
 
        if (!cpu_is_omap34xx())
                return;
 
        clkdm_register_platform_funcs(&omap3_clkdm_operations);
-       clkdm_register_clkdms(clockdomains_omap3430_common);
+       clkdm_register_clkdms(clockdomains_common);
 
-       sc = (omap_rev() == OMAP3430_REV_ES1_0) ? clockdomains_omap3430es1 :
-               clockdomains_omap3430es2plus;
+       rev = omap_rev();
 
-       clkdm_register_clkdms(sc);
+       if (rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1) {
+               clkdm_register_clkdms(clockdomains_am35x);
+               clkdm_register_autodeps(clkdm_am35x_autodeps);
+       } else {
+               clkdm_register_clkdms(clockdomains_omap3430);
+
+               sc = (rev == OMAP3430_REV_ES1_0) ?
+                       clockdomains_omap3430es1 : clockdomains_omap3430es2plus;
+
+               clkdm_register_clkdms(sc);
+               clkdm_register_autodeps(clkdm_autodeps);
+       }
 
-       clkdm_register_autodeps(clkdm_autodeps);
        clkdm_complete_init();
 }
index 7f2133abe7d36e601c322fcec0a8f6217b500b46..63d60a773d3b2e51e7e65bd6131a207871daa0dc 100644 (file)
@@ -430,8 +430,6 @@ static struct clockdomain *clockdomains_omap44xx[] __initdata = {
        &l4_wkup_44xx_clkdm,
        &emu_sys_44xx_clkdm,
        &l3_dma_44xx_clkdm,
-       &prm_common_clkdm,
-       &cm_common_clkdm,
        NULL
 };
 
diff --git a/arch/arm/mach-omap2/clockdomains_common_data.c b/arch/arm/mach-omap2/clockdomains_common_data.c
deleted file mode 100644 (file)
index 615b1f0..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * OMAP2+-common clockdomain data
- *
- * Copyright (C) 2008-2012 Texas Instruments, Inc.
- * Copyright (C) 2008-2010 Nokia Corporation
- *
- * Paul Walmsley, Jouni Högander
- */
-
-#include <linux/kernel.h>
-#include <linux/io.h>
-
-#include "clockdomain.h"
-
-/* These are implicit clockdomains - they are never defined as such in TRM */
-struct clockdomain prm_common_clkdm = {
-       .name           = "prm_clkdm",
-       .pwrdm          = { .name = "wkup_pwrdm" },
-};
-
-struct clockdomain cm_common_clkdm = {
-       .name           = "cm_clkdm",
-       .pwrdm          = { .name = "core_pwrdm" },
-};
diff --git a/arch/arm/mach-omap2/cm-regbits-33xx.h b/arch/arm/mach-omap2/cm-regbits-33xx.h
new file mode 100644 (file)
index 0000000..532027e
--- /dev/null
@@ -0,0 +1,687 @@
+/*
+ * AM33XX Power Management register bits
+ *
+ * This file is automatically generated from the AM33XX hardware databases.
+ * Vaibhav Hiremath <hvaibhav@ti.com>
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CM_REGBITS_33XX_H
+#define __ARCH_ARM_MACH_OMAP2_CM_REGBITS_33XX_H
+
+/*
+ * Used by CM_AUTOIDLE_DPLL_CORE, CM_AUTOIDLE_DPLL_DDR, CM_AUTOIDLE_DPLL_DISP,
+ * CM_AUTOIDLE_DPLL_MPU, CM_AUTOIDLE_DPLL_PER
+ */
+#define AM33XX_AUTO_DPLL_MODE_SHIFT                    0
+#define AM33XX_AUTO_DPLL_MODE_MASK                     (0x7 << 0)
+
+/* Used by CM_WKUP_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_ADC_FCLK_SHIFT              14
+#define AM33XX_CLKACTIVITY_ADC_FCLK_MASK               (1 << 16)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_CAN_CLK_SHIFT               11
+#define AM33XX_CLKACTIVITY_CAN_CLK_MASK                        (1 << 11)
+
+/* Used by CM_PER_CLK_24MHZ_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_CLK_24MHZ_GCLK_SHIFT                4
+#define AM33XX_CLKACTIVITY_CLK_24MHZ_GCLK_MASK         (1 << 4)
+
+/* Used by CM_PER_CPSW_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_CPSW_125MHZ_GCLK_SHIFT      4
+#define AM33XX_CLKACTIVITY_CPSW_125MHZ_GCLK_MASK       (1 << 4)
+
+/* Used by CM_PER_L4HS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_CPSW_250MHZ_GCLK_SHIFT      4
+#define AM33XX_CLKACTIVITY_CPSW_250MHZ_GCLK_MASK       (1 << 4)
+
+/* Used by CM_PER_L4HS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_CPSW_50MHZ_GCLK_SHIFT       5
+#define AM33XX_CLKACTIVITY_CPSW_50MHZ_GCLK_MASK                (1 << 5)
+
+/* Used by CM_PER_L4HS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_CPSW_5MHZ_GCLK_SHIFT                6
+#define AM33XX_CLKACTIVITY_CPSW_5MHZ_GCLK_MASK         (1 << 6)
+
+/* Used by CM_PER_L3_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_CPTS_RFT_GCLK_SHIFT         6
+#define AM33XX_CLKACTIVITY_CPTS_RFT_GCLK_MASK          (1 << 6)
+
+/* Used by CM_CEFUSE_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_CUST_EFUSE_SYS_CLK_SHIFT    9
+#define AM33XX_CLKACTIVITY_CUST_EFUSE_SYS_CLK_MASK     (1 << 9)
+
+/* Used by CM_L3_AON_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_DBGSYSCLK_SHIFT             2
+#define AM33XX_CLKACTIVITY_DBGSYSCLK_MASK              (1 << 2)
+
+/* Used by CM_L3_AON_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_DEBUG_CLKA_SHIFT            4
+#define AM33XX_CLKACTIVITY_DEBUG_CLKA_MASK             (1 << 4)
+
+/* Used by CM_PER_L3_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_EMIF_GCLK_SHIFT             2
+#define AM33XX_CLKACTIVITY_EMIF_GCLK_MASK              (1 << 2)
+
+/* Used by CM_GFX_L3_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_GFX_FCLK_SHIFT              9
+#define AM33XX_CLKACTIVITY_GFX_FCLK_MASK               (1 << 9)
+
+/* Used by CM_GFX_L3_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_GFX_L3_GCLK_SHIFT           8
+#define AM33XX_CLKACTIVITY_GFX_L3_GCLK_MASK            (1 << 8)
+
+/* Used by CM_WKUP_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_GPIO0_GDBCLK_SHIFT          8
+#define AM33XX_CLKACTIVITY_GPIO0_GDBCLK_MASK           (1 << 8)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_GPIO_1_GDBCLK_SHIFT         19
+#define AM33XX_CLKACTIVITY_GPIO_1_GDBCLK_MASK          (1 << 19)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_GPIO_2_GDBCLK_SHIFT         20
+#define AM33XX_CLKACTIVITY_GPIO_2_GDBCLK_MASK          (1 << 20)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_GPIO_3_GDBCLK_SHIFT         21
+#define AM33XX_CLKACTIVITY_GPIO_3_GDBCLK_MASK          (1 << 21)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_GPIO_4_GDBCLK_SHIFT         22
+#define AM33XX_CLKACTIVITY_GPIO_4_GDBCLK_MASK          (1 << 22)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_GPIO_5_GDBCLK_SHIFT         26
+#define AM33XX_CLKACTIVITY_GPIO_5_GDBCLK_MASK          (1 << 26)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_GPIO_6_GDBCLK_SHIFT         18
+#define AM33XX_CLKACTIVITY_GPIO_6_GDBCLK_MASK          (1 << 18)
+
+/* Used by CM_WKUP_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_I2C0_GFCLK_SHIFT            11
+#define AM33XX_CLKACTIVITY_I2C0_GFCLK_MASK             (1 << 11)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_I2C_FCLK_SHIFT              24
+#define AM33XX_CLKACTIVITY_I2C_FCLK_MASK               (1 << 24)
+
+/* Used by CM_PER_PRUSS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_PRUSS_IEP_GCLK_SHIFT                5
+#define AM33XX_CLKACTIVITY_PRUSS_IEP_GCLK_MASK         (1 << 5)
+
+/* Used by CM_PER_PRUSS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_PRUSS_OCP_GCLK_SHIFT                4
+#define AM33XX_CLKACTIVITY_PRUSS_OCP_GCLK_MASK         (1 << 4)
+
+/* Used by CM_PER_PRUSS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_PRUSS_UART_GCLK_SHIFT       6
+#define AM33XX_CLKACTIVITY_PRUSS_UART_GCLK_MASK                (1 << 6)
+
+/* Used by CM_PER_L3S_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_L3S_GCLK_SHIFT              3
+#define AM33XX_CLKACTIVITY_L3S_GCLK_MASK               (1 << 3)
+
+/* Used by CM_L3_AON_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_L3_AON_GCLK_SHIFT           3
+#define AM33XX_CLKACTIVITY_L3_AON_GCLK_MASK            (1 << 3)
+
+/* Used by CM_PER_L3_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_L3_GCLK_SHIFT               4
+#define AM33XX_CLKACTIVITY_L3_GCLK_MASK                        (1 << 4)
+
+/* Used by CM_PER_L4FW_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_L4FW_GCLK_SHIFT             8
+#define AM33XX_CLKACTIVITY_L4FW_GCLK_MASK              (1 << 8)
+
+/* Used by CM_PER_L4HS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_L4HS_GCLK_SHIFT             3
+#define AM33XX_CLKACTIVITY_L4HS_GCLK_MASK              (1 << 3)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_L4LS_GCLK_SHIFT             8
+#define AM33XX_CLKACTIVITY_L4LS_GCLK_MASK              (1 << 8)
+
+/* Used by CM_GFX_L4LS_GFX_CLKSTCTRL__1 */
+#define AM33XX_CLKACTIVITY_L4LS_GFX_GCLK_SHIFT         8
+#define AM33XX_CLKACTIVITY_L4LS_GFX_GCLK_MASK          (1 << 8)
+
+/* Used by CM_CEFUSE_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_L4_CEFUSE_GICLK_SHIFT       8
+#define AM33XX_CLKACTIVITY_L4_CEFUSE_GICLK_MASK                (1 << 8)
+
+/* Used by CM_RTC_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_L4_RTC_GCLK_SHIFT           8
+#define AM33XX_CLKACTIVITY_L4_RTC_GCLK_MASK            (1 << 8)
+
+/* Used by CM_L4_WKUP_AON_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_L4_WKUP_AON_GCLK_SHIFT      2
+#define AM33XX_CLKACTIVITY_L4_WKUP_AON_GCLK_MASK       (1 << 2)
+
+/* Used by CM_WKUP_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_L4_WKUP_GCLK_SHIFT          2
+#define AM33XX_CLKACTIVITY_L4_WKUP_GCLK_MASK           (1 << 2)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_LCDC_GCLK_SHIFT             17
+#define AM33XX_CLKACTIVITY_LCDC_GCLK_MASK              (1 << 17)
+
+/* Used by CM_PER_LCDC_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_LCDC_L3_OCP_GCLK_SHIFT      4
+#define AM33XX_CLKACTIVITY_LCDC_L3_OCP_GCLK_MASK       (1 << 4)
+
+/* Used by CM_PER_LCDC_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_LCDC_L4_OCP_GCLK_SHIFT      5
+#define AM33XX_CLKACTIVITY_LCDC_L4_OCP_GCLK_MASK       (1 << 5)
+
+/* Used by CM_PER_L3_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_MCASP_GCLK_SHIFT            7
+#define AM33XX_CLKACTIVITY_MCASP_GCLK_MASK             (1 << 7)
+
+/* Used by CM_PER_L3_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_MMC_FCLK_SHIFT              3
+#define AM33XX_CLKACTIVITY_MMC_FCLK_MASK               (1 << 3)
+
+/* Used by CM_MPU_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_MPU_CLK_SHIFT               2
+#define AM33XX_CLKACTIVITY_MPU_CLK_MASK                        (1 << 2)
+
+/* Used by CM_PER_OCPWP_L3_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_OCPWP_L3_GCLK_SHIFT         4
+#define AM33XX_CLKACTIVITY_OCPWP_L3_GCLK_MASK          (1 << 4)
+
+/* Used by CM_PER_OCPWP_L3_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_OCPWP_L4_GCLK_SHIFT         5
+#define AM33XX_CLKACTIVITY_OCPWP_L4_GCLK_MASK          (1 << 5)
+
+/* Used by CM_RTC_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_RTC_32KCLK_SHIFT            9
+#define AM33XX_CLKACTIVITY_RTC_32KCLK_MASK             (1 << 9)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_SPI_GCLK_SHIFT              25
+#define AM33XX_CLKACTIVITY_SPI_GCLK_MASK               (1 << 25)
+
+/* Used by CM_WKUP_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_SR_SYSCLK_SHIFT             3
+#define AM33XX_CLKACTIVITY_SR_SYSCLK_MASK              (1 << 3)
+
+/* Used by CM_WKUP_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_TIMER0_GCLK_SHIFT           10
+#define AM33XX_CLKACTIVITY_TIMER0_GCLK_MASK            (1 << 10)
+
+/* Used by CM_WKUP_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_TIMER1_GCLK_SHIFT           13
+#define AM33XX_CLKACTIVITY_TIMER1_GCLK_MASK            (1 << 13)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_TIMER2_GCLK_SHIFT           14
+#define AM33XX_CLKACTIVITY_TIMER2_GCLK_MASK            (1 << 14)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_TIMER3_GCLK_SHIFT           15
+#define AM33XX_CLKACTIVITY_TIMER3_GCLK_MASK            (1 << 15)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_TIMER4_GCLK_SHIFT           16
+#define AM33XX_CLKACTIVITY_TIMER4_GCLK_MASK            (1 << 16)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_TIMER5_GCLK_SHIFT           27
+#define AM33XX_CLKACTIVITY_TIMER5_GCLK_MASK            (1 << 27)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_TIMER6_GCLK_SHIFT           28
+#define AM33XX_CLKACTIVITY_TIMER6_GCLK_MASK            (1 << 28)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_TIMER7_GCLK_SHIFT           13
+#define AM33XX_CLKACTIVITY_TIMER7_GCLK_MASK            (1 << 13)
+
+/* Used by CM_WKUP_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_UART0_GFCLK_SHIFT           12
+#define AM33XX_CLKACTIVITY_UART0_GFCLK_MASK            (1 << 12)
+
+/* Used by CM_PER_L4LS_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_UART_GFCLK_SHIFT            10
+#define AM33XX_CLKACTIVITY_UART_GFCLK_MASK             (1 << 10)
+
+/* Used by CM_WKUP_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_WDT0_GCLK_SHIFT             9
+#define AM33XX_CLKACTIVITY_WDT0_GCLK_MASK              (1 << 9)
+
+/* Used by CM_WKUP_CLKSTCTRL */
+#define AM33XX_CLKACTIVITY_WDT1_GCLK_SHIFT             4
+#define AM33XX_CLKACTIVITY_WDT1_GCLK_MASK              (1 << 4)
+
+/* Used by CLKSEL_GFX_FCLK */
+#define AM33XX_CLKDIV_SEL_GFX_FCLK_SHIFT               0
+#define AM33XX_CLKDIV_SEL_GFX_FCLK_MASK                        (1 << 0)
+
+/* Used by CM_CLKOUT_CTRL */
+#define AM33XX_CLKOUT2DIV_SHIFT                                3
+#define AM33XX_CLKOUT2DIV_MASK                         (0x05 << 3)
+
+/* Used by CM_CLKOUT_CTRL */
+#define AM33XX_CLKOUT2EN_SHIFT                         7
+#define AM33XX_CLKOUT2EN_MASK                          (1 << 7)
+
+/* Used by CM_CLKOUT_CTRL */
+#define AM33XX_CLKOUT2SOURCE_SHIFT                     0
+#define AM33XX_CLKOUT2SOURCE_MASK                      (0x02 << 0)
+
+/*
+ * Used by CLKSEL_GPIO0_DBCLK, CLKSEL_LCDC_PIXEL_CLK, CLKSEL_TIMER2_CLK,
+ * CLKSEL_TIMER3_CLK, CLKSEL_TIMER4_CLK, CLKSEL_TIMER5_CLK, CLKSEL_TIMER6_CLK,
+ * CLKSEL_TIMER7_CLK
+ */
+#define AM33XX_CLKSEL_SHIFT                            0
+#define AM33XX_CLKSEL_MASK                             (0x01 << 0)
+
+/*
+ * Renamed from CLKSEL Used by CLKSEL_PRUSS_OCP_CLK, CLKSEL_WDT1_CLK,
+ * CM_CPTS_RFT_CLKSEL
+ */
+#define AM33XX_CLKSEL_0_0_SHIFT                                0
+#define AM33XX_CLKSEL_0_0_MASK                         (1 << 0)
+
+#define AM33XX_CLKSEL_0_1_SHIFT                                0
+#define AM33XX_CLKSEL_0_1_MASK                         (3 << 0)
+
+/* Renamed from CLKSEL Used by CLKSEL_TIMER1MS_CLK */
+#define AM33XX_CLKSEL_0_2_SHIFT                                0
+#define AM33XX_CLKSEL_0_2_MASK                         (7 << 0)
+
+/* Used by CLKSEL_GFX_FCLK */
+#define AM33XX_CLKSEL_GFX_FCLK_SHIFT                   1
+#define AM33XX_CLKSEL_GFX_FCLK_MASK                    (1 << 1)
+
+/*
+ * Used by CM_MPU_CLKSTCTRL, CM_RTC_CLKSTCTRL, CM_PER_CLK_24MHZ_CLKSTCTRL,
+ * CM_PER_CPSW_CLKSTCTRL, CM_PER_PRUSS_CLKSTCTRL, CM_PER_L3S_CLKSTCTRL,
+ * CM_PER_L3_CLKSTCTRL, CM_PER_L4FW_CLKSTCTRL, CM_PER_L4HS_CLKSTCTRL,
+ * CM_PER_L4LS_CLKSTCTRL, CM_PER_LCDC_CLKSTCTRL, CM_PER_OCPWP_L3_CLKSTCTRL,
+ * CM_L3_AON_CLKSTCTRL, CM_L4_WKUP_AON_CLKSTCTRL, CM_WKUP_CLKSTCTRL,
+ * CM_GFX_L3_CLKSTCTRL, CM_GFX_L4LS_GFX_CLKSTCTRL__1, CM_CEFUSE_CLKSTCTRL
+ */
+#define AM33XX_CLKTRCTRL_SHIFT                         0
+#define AM33XX_CLKTRCTRL_MASK                          (0x3 << 0)
+
+/*
+ * Used by CM_SSC_DELTAMSTEP_DPLL_CORE, CM_SSC_DELTAMSTEP_DPLL_DDR,
+ * CM_SSC_DELTAMSTEP_DPLL_DISP, CM_SSC_DELTAMSTEP_DPLL_MPU,
+ * CM_SSC_DELTAMSTEP_DPLL_PER
+ */
+#define AM33XX_DELTAMSTEP_SHIFT                                0
+#define AM33XX_DELTAMSTEP_MASK                         (0x19 << 0)
+
+/* Used by CM_CLKSEL_DPLL_DDR, CM_CLKSEL_DPLL_DISP, CM_CLKSEL_DPLL_MPU */
+#define AM33XX_DPLL_BYP_CLKSEL_SHIFT                   23
+#define AM33XX_DPLL_BYP_CLKSEL_MASK                    (1 << 23)
+
+/* Used by CM_CLKDCOLDO_DPLL_PER */
+#define AM33XX_DPLL_CLKDCOLDO_GATE_CTRL_SHIFT          8
+#define AM33XX_DPLL_CLKDCOLDO_GATE_CTRL_MASK           (1 << 8)
+
+/* Used by CM_CLKDCOLDO_DPLL_PER */
+#define AM33XX_DPLL_CLKDCOLDO_PWDN_SHIFT               12
+#define AM33XX_DPLL_CLKDCOLDO_PWDN_MASK                        (1 << 12)
+
+/* Used by CM_DIV_M2_DPLL_DDR, CM_DIV_M2_DPLL_DISP, CM_DIV_M2_DPLL_MPU */
+#define AM33XX_DPLL_CLKOUT_DIV_SHIFT                   0
+#define AM33XX_DPLL_CLKOUT_DIV_MASK                    (0x1f << 0)
+
+/* Renamed from DPLL_CLKOUT_DIV Used by CM_DIV_M2_DPLL_PER */
+#define AM33XX_DPLL_CLKOUT_DIV_0_6_SHIFT               0
+#define AM33XX_DPLL_CLKOUT_DIV_0_6_MASK                        (0x06 << 0)
+
+/* Used by CM_DIV_M2_DPLL_DDR, CM_DIV_M2_DPLL_DISP, CM_DIV_M2_DPLL_MPU */
+#define AM33XX_DPLL_CLKOUT_DIVCHACK_SHIFT              5
+#define AM33XX_DPLL_CLKOUT_DIVCHACK_MASK               (1 << 5)
+
+/* Renamed from DPLL_CLKOUT_DIVCHACK Used by CM_DIV_M2_DPLL_PER */
+#define AM33XX_DPLL_CLKOUT_DIVCHACK_M2_PER_SHIFT       7
+#define AM33XX_DPLL_CLKOUT_DIVCHACK_M2_PER_MASK                (1 << 7)
+
+/*
+ * Used by CM_DIV_M2_DPLL_DDR, CM_DIV_M2_DPLL_DISP, CM_DIV_M2_DPLL_MPU,
+ * CM_DIV_M2_DPLL_PER
+ */
+#define AM33XX_DPLL_CLKOUT_GATE_CTRL_SHIFT             8
+#define AM33XX_DPLL_CLKOUT_GATE_CTRL_MASK              (1 << 8)
+
+/*
+ * Used by CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_DDR, CM_CLKSEL_DPLL_DISP,
+ * CM_CLKSEL_DPLL_MPU
+ */
+#define AM33XX_DPLL_DIV_SHIFT                          0
+#define AM33XX_DPLL_DIV_MASK                           (0x7f << 0)
+
+#define AM33XX_DPLL_PER_DIV_MASK                       (0xff << 0)
+
+/* Renamed from DPLL_DIV Used by CM_CLKSEL_DPLL_PERIPH */
+#define AM33XX_DPLL_DIV_0_7_SHIFT                      0
+#define AM33XX_DPLL_DIV_0_7_MASK                       (0x07 << 0)
+
+/*
+ * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP,
+ * CM_CLKMODE_DPLL_MPU
+ */
+#define AM33XX_DPLL_DRIFTGUARD_EN_SHIFT                        8
+#define AM33XX_DPLL_DRIFTGUARD_EN_MASK                 (1 << 8)
+
+/*
+ * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
+ */
+#define AM33XX_DPLL_EN_SHIFT                           0
+#define AM33XX_DPLL_EN_MASK                            (0x7 << 0)
+
+/*
+ * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP,
+ * CM_CLKMODE_DPLL_MPU
+ */
+#define AM33XX_DPLL_LPMODE_EN_SHIFT                    10
+#define AM33XX_DPLL_LPMODE_EN_MASK                     (1 << 10)
+
+/*
+ * Used by CM_CLKSEL_DPLL_CORE, CM_CLKSEL_DPLL_DDR, CM_CLKSEL_DPLL_DISP,
+ * CM_CLKSEL_DPLL_MPU
+ */
+#define AM33XX_DPLL_MULT_SHIFT                         8
+#define AM33XX_DPLL_MULT_MASK                          (0x7ff << 8)
+
+/* Renamed from DPLL_MULT Used by CM_CLKSEL_DPLL_PERIPH */
+#define AM33XX_DPLL_MULT_PERIPH_SHIFT                  8
+#define AM33XX_DPLL_MULT_PERIPH_MASK                   (0xfff << 8)
+
+/*
+ * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP,
+ * CM_CLKMODE_DPLL_MPU
+ */
+#define AM33XX_DPLL_REGM4XEN_SHIFT                     11
+#define AM33XX_DPLL_REGM4XEN_MASK                      (1 << 11)
+
+/* Used by CM_CLKSEL_DPLL_PERIPH */
+#define AM33XX_DPLL_SD_DIV_SHIFT                       24
+#define AM33XX_DPLL_SD_DIV_MASK                                (24, 31)
+
+/*
+ * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
+ */
+#define AM33XX_DPLL_SSC_ACK_SHIFT                      13
+#define AM33XX_DPLL_SSC_ACK_MASK                       (1 << 13)
+
+/*
+ * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
+ */
+#define AM33XX_DPLL_SSC_DOWNSPREAD_SHIFT               14
+#define AM33XX_DPLL_SSC_DOWNSPREAD_MASK                        (1 << 14)
+
+/*
+ * Used by CM_CLKMODE_DPLL_CORE, CM_CLKMODE_DPLL_DDR, CM_CLKMODE_DPLL_DISP,
+ * CM_CLKMODE_DPLL_MPU, CM_CLKMODE_DPLL_PER
+ */
+#define AM33XX_DPLL_SSC_EN_SHIFT                       12
+#define AM33XX_DPLL_SSC_EN_MASK                                (1 << 12)
+
+/* Used by CM_DIV_M4_DPLL_CORE */
+#define AM33XX_HSDIVIDER_CLKOUT1_DIV_SHIFT             0
+#define AM33XX_HSDIVIDER_CLKOUT1_DIV_MASK              (0x1f << 0)
+
+/* Used by CM_DIV_M4_DPLL_CORE */
+#define AM33XX_HSDIVIDER_CLKOUT1_DIVCHACK_SHIFT                5
+#define AM33XX_HSDIVIDER_CLKOUT1_DIVCHACK_MASK         (1 << 5)
+
+/* Used by CM_DIV_M4_DPLL_CORE */
+#define AM33XX_HSDIVIDER_CLKOUT1_GATE_CTRL_SHIFT       8
+#define AM33XX_HSDIVIDER_CLKOUT1_GATE_CTRL_MASK                (1 << 8)
+
+/* Used by CM_DIV_M4_DPLL_CORE */
+#define AM33XX_HSDIVIDER_CLKOUT1_PWDN_SHIFT            12
+#define AM33XX_HSDIVIDER_CLKOUT1_PWDN_MASK             (1 << 12)
+
+/* Used by CM_DIV_M5_DPLL_CORE */
+#define AM33XX_HSDIVIDER_CLKOUT2_DIV_SHIFT             0
+#define AM33XX_HSDIVIDER_CLKOUT2_DIV_MASK              (0x1f << 0)
+
+/* Used by CM_DIV_M5_DPLL_CORE */
+#define AM33XX_HSDIVIDER_CLKOUT2_DIVCHACK_SHIFT                5
+#define AM33XX_HSDIVIDER_CLKOUT2_DIVCHACK_MASK         (1 << 5)
+
+/* Used by CM_DIV_M5_DPLL_CORE */
+#define AM33XX_HSDIVIDER_CLKOUT2_GATE_CTRL_SHIFT       8
+#define AM33XX_HSDIVIDER_CLKOUT2_GATE_CTRL_MASK                (1 << 8)
+
+/* Used by CM_DIV_M5_DPLL_CORE */
+#define AM33XX_HSDIVIDER_CLKOUT2_PWDN_SHIFT            12
+#define AM33XX_HSDIVIDER_CLKOUT2_PWDN_MASK             (1 << 12)
+
+/* Used by CM_DIV_M6_DPLL_CORE */
+#define AM33XX_HSDIVIDER_CLKOUT3_DIV_SHIFT             0
+#define AM33XX_HSDIVIDER_CLKOUT3_DIV_MASK              (0x04 << 0)
+
+/* Used by CM_DIV_M6_DPLL_CORE */
+#define AM33XX_HSDIVIDER_CLKOUT3_DIVCHACK_SHIFT                5
+#define AM33XX_HSDIVIDER_CLKOUT3_DIVCHACK_MASK         (1 << 5)
+
+/* Used by CM_DIV_M6_DPLL_CORE */
+#define AM33XX_HSDIVIDER_CLKOUT3_GATE_CTRL_SHIFT       8
+#define AM33XX_HSDIVIDER_CLKOUT3_GATE_CTRL_MASK                (1 << 8)
+
+/* Used by CM_DIV_M6_DPLL_CORE */
+#define AM33XX_HSDIVIDER_CLKOUT3_PWDN_SHIFT            12
+#define AM33XX_HSDIVIDER_CLKOUT3_PWDN_MASK             (1 << 12)
+
+/*
+ * Used by CM_MPU_MPU_CLKCTRL, CM_RTC_RTC_CLKCTRL, CM_PER_AES0_CLKCTRL,
+ * CM_PER_AES1_CLKCTRL, CM_PER_CLKDIV32K_CLKCTRL, CM_PER_CPGMAC0_CLKCTRL,
+ * CM_PER_DCAN0_CLKCTRL, CM_PER_DCAN1_CLKCTRL, CM_PER_DES_CLKCTRL,
+ * CM_PER_ELM_CLKCTRL, CM_PER_EMIF_CLKCTRL, CM_PER_EMIF_FW_CLKCTRL,
+ * CM_PER_EPWMSS0_CLKCTRL, CM_PER_EPWMSS1_CLKCTRL, CM_PER_EPWMSS2_CLKCTRL,
+ * CM_PER_GPIO1_CLKCTRL, CM_PER_GPIO2_CLKCTRL, CM_PER_GPIO3_CLKCTRL,
+ * CM_PER_GPIO4_CLKCTRL, CM_PER_GPIO5_CLKCTRL, CM_PER_GPIO6_CLKCTRL,
+ * CM_PER_GPMC_CLKCTRL, CM_PER_I2C1_CLKCTRL, CM_PER_I2C2_CLKCTRL,
+ * CM_PER_PRUSS_CLKCTRL, CM_PER_IEEE5000_CLKCTRL, CM_PER_L3_CLKCTRL,
+ * CM_PER_L3_INSTR_CLKCTRL, CM_PER_L4FW_CLKCTRL, CM_PER_L4HS_CLKCTRL,
+ * CM_PER_L4LS_CLKCTRL, CM_PER_LCDC_CLKCTRL, CM_PER_MAILBOX0_CLKCTRL,
+ * CM_PER_MAILBOX1_CLKCTRL, CM_PER_MCASP0_CLKCTRL, CM_PER_MCASP1_CLKCTRL,
+ * CM_PER_MCASP2_CLKCTRL, CM_PER_MLB_CLKCTRL, CM_PER_MMC0_CLKCTRL,
+ * CM_PER_MMC1_CLKCTRL, CM_PER_MMC2_CLKCTRL, CM_PER_MSTR_EXPS_CLKCTRL,
+ * CM_PER_OCMCRAM_CLKCTRL, CM_PER_OCPWP_CLKCTRL, CM_PER_PCIE_CLKCTRL,
+ * CM_PER_PKA_CLKCTRL, CM_PER_RNG_CLKCTRL, CM_PER_SHA0_CLKCTRL,
+ * CM_PER_SLV_EXPS_CLKCTRL, CM_PER_SPARE0_CLKCTRL, CM_PER_SPARE1_CLKCTRL,
+ * CM_PER_SPARE_CLKCTRL, CM_PER_SPI0_CLKCTRL, CM_PER_SPI1_CLKCTRL,
+ * CM_PER_SPI2_CLKCTRL, CM_PER_SPI3_CLKCTRL, CM_PER_SPINLOCK_CLKCTRL,
+ * CM_PER_TIMER2_CLKCTRL, CM_PER_TIMER3_CLKCTRL, CM_PER_TIMER4_CLKCTRL,
+ * CM_PER_TIMER5_CLKCTRL, CM_PER_TIMER6_CLKCTRL, CM_PER_TIMER7_CLKCTRL,
+ * CM_PER_TPCC_CLKCTRL, CM_PER_TPTC0_CLKCTRL, CM_PER_TPTC1_CLKCTRL,
+ * CM_PER_TPTC2_CLKCTRL, CM_PER_UART1_CLKCTRL, CM_PER_UART2_CLKCTRL,
+ * CM_PER_UART3_CLKCTRL, CM_PER_UART4_CLKCTRL, CM_PER_UART5_CLKCTRL,
+ * CM_PER_USB0_CLKCTRL, CM_WKUP_ADC_TSC_CLKCTRL, CM_WKUP_CONTROL_CLKCTRL,
+ * CM_WKUP_DEBUGSS_CLKCTRL, CM_WKUP_GPIO0_CLKCTRL, CM_WKUP_I2C0_CLKCTRL,
+ * CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_SMARTREFLEX0_CLKCTRL,
+ * CM_WKUP_SMARTREFLEX1_CLKCTRL, CM_WKUP_TIMER0_CLKCTRL,
+ * CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_UART0_CLKCTRL, CM_WKUP_WDT0_CLKCTRL,
+ * CM_WKUP_WDT1_CLKCTRL, CM_GFX_BITBLT_CLKCTRL, CM_GFX_GFX_CLKCTRL,
+ * CM_GFX_MMUCFG_CLKCTRL, CM_GFX_MMUDATA_CLKCTRL, CM_CEFUSE_CEFUSE_CLKCTRL
+ */
+#define AM33XX_IDLEST_SHIFT                            16
+#define AM33XX_IDLEST_MASK                             (0x3 << 16)
+#define AM33XX_IDLEST_VAL                              0x3
+
+/* Used by CM_MAC_CLKSEL */
+#define AM33XX_MII_CLK_SEL_SHIFT                       2
+#define AM33XX_MII_CLK_SEL_MASK                                (1 << 2)
+
+/*
+ * Used by CM_SSC_MODFREQDIV_DPLL_CORE, CM_SSC_MODFREQDIV_DPLL_DDR,
+ * CM_SSC_MODFREQDIV_DPLL_DISP, CM_SSC_MODFREQDIV_DPLL_MPU,
+ * CM_SSC_MODFREQDIV_DPLL_PER
+ */
+#define AM33XX_MODFREQDIV_EXPONENT_SHIFT               8
+#define AM33XX_MODFREQDIV_EXPONENT_MASK                        (0x10 << 8)
+
+/*
+ * Used by CM_SSC_MODFREQDIV_DPLL_CORE, CM_SSC_MODFREQDIV_DPLL_DDR,
+ * CM_SSC_MODFREQDIV_DPLL_DISP, CM_SSC_MODFREQDIV_DPLL_MPU,
+ * CM_SSC_MODFREQDIV_DPLL_PER
+ */
+#define AM33XX_MODFREQDIV_MANTISSA_SHIFT               0
+#define AM33XX_MODFREQDIV_MANTISSA_MASK                        (0x06 << 0)
+
+/*
+ * Used by CM_MPU_MPU_CLKCTRL, CM_RTC_RTC_CLKCTRL, CM_PER_AES0_CLKCTRL,
+ * CM_PER_AES1_CLKCTRL, CM_PER_CLKDIV32K_CLKCTRL, CM_PER_CPGMAC0_CLKCTRL,
+ * CM_PER_DCAN0_CLKCTRL, CM_PER_DCAN1_CLKCTRL, CM_PER_DES_CLKCTRL,
+ * CM_PER_ELM_CLKCTRL, CM_PER_EMIF_CLKCTRL, CM_PER_EMIF_FW_CLKCTRL,
+ * CM_PER_EPWMSS0_CLKCTRL, CM_PER_EPWMSS1_CLKCTRL, CM_PER_EPWMSS2_CLKCTRL,
+ * CM_PER_GPIO1_CLKCTRL, CM_PER_GPIO2_CLKCTRL, CM_PER_GPIO3_CLKCTRL,
+ * CM_PER_GPIO4_CLKCTRL, CM_PER_GPIO5_CLKCTRL, CM_PER_GPIO6_CLKCTRL,
+ * CM_PER_GPMC_CLKCTRL, CM_PER_I2C1_CLKCTRL, CM_PER_I2C2_CLKCTRL,
+ * CM_PER_PRUSS_CLKCTRL, CM_PER_IEEE5000_CLKCTRL, CM_PER_L3_CLKCTRL,
+ * CM_PER_L3_INSTR_CLKCTRL, CM_PER_L4FW_CLKCTRL, CM_PER_L4HS_CLKCTRL,
+ * CM_PER_L4LS_CLKCTRL, CM_PER_LCDC_CLKCTRL, CM_PER_MAILBOX0_CLKCTRL,
+ * CM_PER_MAILBOX1_CLKCTRL, CM_PER_MCASP0_CLKCTRL, CM_PER_MCASP1_CLKCTRL,
+ * CM_PER_MCASP2_CLKCTRL, CM_PER_MLB_CLKCTRL, CM_PER_MMC0_CLKCTRL,
+ * CM_PER_MMC1_CLKCTRL, CM_PER_MMC2_CLKCTRL, CM_PER_MSTR_EXPS_CLKCTRL,
+ * CM_PER_OCMCRAM_CLKCTRL, CM_PER_OCPWP_CLKCTRL, CM_PER_PCIE_CLKCTRL,
+ * CM_PER_PKA_CLKCTRL, CM_PER_RNG_CLKCTRL, CM_PER_SHA0_CLKCTRL,
+ * CM_PER_SLV_EXPS_CLKCTRL, CM_PER_SPARE0_CLKCTRL, CM_PER_SPARE1_CLKCTRL,
+ * CM_PER_SPARE_CLKCTRL, CM_PER_SPI0_CLKCTRL, CM_PER_SPI1_CLKCTRL,
+ * CM_PER_SPI2_CLKCTRL, CM_PER_SPI3_CLKCTRL, CM_PER_SPINLOCK_CLKCTRL,
+ * CM_PER_TIMER2_CLKCTRL, CM_PER_TIMER3_CLKCTRL, CM_PER_TIMER4_CLKCTRL,
+ * CM_PER_TIMER5_CLKCTRL, CM_PER_TIMER6_CLKCTRL, CM_PER_TIMER7_CLKCTRL,
+ * CM_PER_TPCC_CLKCTRL, CM_PER_TPTC0_CLKCTRL, CM_PER_TPTC1_CLKCTRL,
+ * CM_PER_TPTC2_CLKCTRL, CM_PER_UART1_CLKCTRL, CM_PER_UART2_CLKCTRL,
+ * CM_PER_UART3_CLKCTRL, CM_PER_UART4_CLKCTRL, CM_PER_UART5_CLKCTRL,
+ * CM_PER_USB0_CLKCTRL, CM_WKUP_ADC_TSC_CLKCTRL, CM_WKUP_CONTROL_CLKCTRL,
+ * CM_WKUP_DEBUGSS_CLKCTRL, CM_WKUP_GPIO0_CLKCTRL, CM_WKUP_I2C0_CLKCTRL,
+ * CM_WKUP_L4WKUP_CLKCTRL, CM_WKUP_SMARTREFLEX0_CLKCTRL,
+ * CM_WKUP_SMARTREFLEX1_CLKCTRL, CM_WKUP_TIMER0_CLKCTRL,
+ * CM_WKUP_TIMER1_CLKCTRL, CM_WKUP_UART0_CLKCTRL, CM_WKUP_WDT0_CLKCTRL,
+ * CM_WKUP_WDT1_CLKCTRL, CM_WKUP_WKUP_M3_CLKCTRL, CM_GFX_BITBLT_CLKCTRL,
+ * CM_GFX_GFX_CLKCTRL, CM_GFX_MMUCFG_CLKCTRL, CM_GFX_MMUDATA_CLKCTRL,
+ * CM_CEFUSE_CEFUSE_CLKCTRL
+ */
+#define AM33XX_MODULEMODE_SHIFT                                0
+#define AM33XX_MODULEMODE_MASK                         (0x3 << 0)
+
+/* Used by CM_WKUP_DEBUGSS_CLKCTRL */
+#define AM33XX_OPTCLK_DEBUG_CLKA_SHIFT                 30
+#define AM33XX_OPTCLK_DEBUG_CLKA_MASK                  (1 << 30)
+
+/* Used by CM_WKUP_DEBUGSS_CLKCTRL */
+#define AM33XX_OPTFCLKEN_DBGSYSCLK_SHIFT               19
+#define AM33XX_OPTFCLKEN_DBGSYSCLK_MASK                        (1 << 19)
+
+/* Used by CM_WKUP_GPIO0_CLKCTRL */
+#define AM33XX_OPTFCLKEN_GPIO0_GDBCLK_SHIFT            18
+#define AM33XX_OPTFCLKEN_GPIO0_GDBCLK_MASK             (1 << 18)
+
+/* Used by CM_PER_GPIO1_CLKCTRL */
+#define AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_SHIFT           18
+#define AM33XX_OPTFCLKEN_GPIO_1_GDBCLK_MASK            (1 << 18)
+
+/* Used by CM_PER_GPIO2_CLKCTRL */
+#define AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_SHIFT           18
+#define AM33XX_OPTFCLKEN_GPIO_2_GDBCLK_MASK            (1 << 18)
+
+/* Used by CM_PER_GPIO3_CLKCTRL */
+#define AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_SHIFT           18
+#define AM33XX_OPTFCLKEN_GPIO_3_GDBCLK_MASK            (1 << 18)
+
+/* Used by CM_PER_GPIO4_CLKCTRL */
+#define AM33XX_OPTFCLKEN_GPIO_4_GDBCLK_SHIFT           18
+#define AM33XX_OPTFCLKEN_GPIO_4_GDBCLK_MASK            (1 << 18)
+
+/* Used by CM_PER_GPIO5_CLKCTRL */
+#define AM33XX_OPTFCLKEN_GPIO_5_GDBCLK_SHIFT           18
+#define AM33XX_OPTFCLKEN_GPIO_5_GDBCLK_MASK            (1 << 18)
+
+/* Used by CM_PER_GPIO6_CLKCTRL */
+#define AM33XX_OPTFCLKEN_GPIO_6_GDBCLK_SHIFT           18
+#define AM33XX_OPTFCLKEN_GPIO_6_GDBCLK_MASK            (1 << 18)
+
+/*
+ * Used by CM_MPU_MPU_CLKCTRL, CM_PER_CPGMAC0_CLKCTRL, CM_PER_PRUSS_CLKCTRL,
+ * CM_PER_IEEE5000_CLKCTRL, CM_PER_LCDC_CLKCTRL, CM_PER_MLB_CLKCTRL,
+ * CM_PER_MSTR_EXPS_CLKCTRL, CM_PER_OCPWP_CLKCTRL, CM_PER_PCIE_CLKCTRL,
+ * CM_PER_SPARE_CLKCTRL, CM_PER_TPTC0_CLKCTRL, CM_PER_TPTC1_CLKCTRL,
+ * CM_PER_TPTC2_CLKCTRL, CM_PER_USB0_CLKCTRL, CM_WKUP_DEBUGSS_CLKCTRL,
+ * CM_WKUP_WKUP_M3_CLKCTRL, CM_GFX_BITBLT_CLKCTRL, CM_GFX_GFX_CLKCTRL
+ */
+#define AM33XX_STBYST_SHIFT                            18
+#define AM33XX_STBYST_MASK                             (1 << 18)
+
+/* Used by CM_WKUP_DEBUGSS_CLKCTRL */
+#define AM33XX_STM_PMD_CLKDIVSEL_SHIFT                 27
+#define AM33XX_STM_PMD_CLKDIVSEL_MASK                  (0x29 << 27)
+
+/* Used by CM_WKUP_DEBUGSS_CLKCTRL */
+#define AM33XX_STM_PMD_CLKSEL_SHIFT                    22
+#define AM33XX_STM_PMD_CLKSEL_MASK                     (0x23 << 22)
+
+/*
+ * Used by CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDR, CM_IDLEST_DPLL_DISP,
+ * CM_IDLEST_DPLL_MPU, CM_IDLEST_DPLL_PER
+ */
+#define AM33XX_ST_DPLL_CLK_SHIFT                       0
+#define AM33XX_ST_DPLL_CLK_MASK                                (1 << 0)
+
+/* Used by CM_CLKDCOLDO_DPLL_PER */
+#define AM33XX_ST_DPLL_CLKDCOLDO_SHIFT                 8
+#define AM33XX_ST_DPLL_CLKDCOLDO_MASK                  (1 << 8)
+
+/*
+ * Used by CM_DIV_M2_DPLL_DDR, CM_DIV_M2_DPLL_DISP, CM_DIV_M2_DPLL_MPU,
+ * CM_DIV_M2_DPLL_PER
+ */
+#define AM33XX_ST_DPLL_CLKOUT_SHIFT                    9
+#define AM33XX_ST_DPLL_CLKOUT_MASK                     (1 << 9)
+
+/* Used by CM_DIV_M4_DPLL_CORE */
+#define AM33XX_ST_HSDIVIDER_CLKOUT1_SHIFT              9
+#define AM33XX_ST_HSDIVIDER_CLKOUT1_MASK               (1 << 9)
+
+/* Used by CM_DIV_M5_DPLL_CORE */
+#define AM33XX_ST_HSDIVIDER_CLKOUT2_SHIFT              9
+#define AM33XX_ST_HSDIVIDER_CLKOUT2_MASK               (1 << 9)
+
+/* Used by CM_DIV_M6_DPLL_CORE */
+#define AM33XX_ST_HSDIVIDER_CLKOUT3_SHIFT              9
+#define AM33XX_ST_HSDIVIDER_CLKOUT3_MASK               (1 << 9)
+
+/*
+ * Used by CM_IDLEST_DPLL_CORE, CM_IDLEST_DPLL_DDR, CM_IDLEST_DPLL_DISP,
+ * CM_IDLEST_DPLL_MPU, CM_IDLEST_DPLL_PER
+ */
+#define AM33XX_ST_MN_BYPASS_SHIFT                      8
+#define AM33XX_ST_MN_BYPASS_MASK                       (1 << 8)
+
+/* Used by CM_WKUP_DEBUGSS_CLKCTRL */
+#define AM33XX_TRC_PMD_CLKDIVSEL_SHIFT                 24
+#define AM33XX_TRC_PMD_CLKDIVSEL_MASK                  (0x26 << 24)
+
+/* Used by CM_WKUP_DEBUGSS_CLKCTRL */
+#define AM33XX_TRC_PMD_CLKSEL_SHIFT                    20
+#define AM33XX_TRC_PMD_CLKSEL_MASK                     (0x21 << 20)
+
+/* Used by CONTROL_SEC_CLK_CTRL */
+#define AM33XX_TIMER0_CLKSEL_MASK                      (0x3 << 4)
+#endif
index 8083a8cdc55f074aad48a88e8a2c2f7605c8f333..766338fe4d347746ee04eb3961452a7b3f8f6aa9 100644 (file)
 /* AM35XX specific CM_ICLKEN1_CORE bits */
 #define AM35XX_EN_IPSS_MASK                            (1 << 4)
 #define AM35XX_EN_IPSS_SHIFT                           4
-#define AM35XX_EN_UART4_MASK                           (1 << 23)
-#define AM35XX_EN_UART4_SHIFT                          23
 
 /* CM_ICLKEN2_CORE */
 #define OMAP3430_EN_PKA_MASK                           (1 << 4)
 #define OMAP3430_ST_DES2_MASK                          (1 << 26)
 #define OMAP3430_ST_MSPRO_SHIFT                                23
 #define OMAP3430_ST_MSPRO_MASK                         (1 << 23)
+#define AM35XX_ST_UART4_SHIFT                          23
+#define AM35XX_ST_UART4_MASK                           (1 << 23)
 #define OMAP3430_ST_HDQ_SHIFT                          22
 #define OMAP3430_ST_HDQ_MASK                           (1 << 22)
 #define OMAP3430ES1_ST_FAC_SHIFT                       8
diff --git a/arch/arm/mach-omap2/cm33xx.c b/arch/arm/mach-omap2/cm33xx.c
new file mode 100644 (file)
index 0000000..13f56ea
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+ * AM33XX CM functions
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Vaibhav Hiremath <hvaibhav@ti.com>
+ *
+ * Reference taken from from OMAP4 cminst44xx.c
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+
+#include "cm.h"
+#include "cm33xx.h"
+#include "cm-regbits-34xx.h"
+#include "cm-regbits-33xx.h"
+#include "prm33xx.h"
+
+/*
+ * CLKCTRL_IDLEST_*: possible values for the CM_*_CLKCTRL.IDLEST bitfield:
+ *
+ *   0x0 func:     Module is fully functional, including OCP
+ *   0x1 trans:    Module is performing transition: wakeup, or sleep, or sleep
+ *                 abortion
+ *   0x2 idle:     Module is in Idle mode (only OCP part). It is functional if
+ *                 using separate functional clock
+ *   0x3 disabled: Module is disabled and cannot be accessed
+ *
+ */
+#define CLKCTRL_IDLEST_FUNCTIONAL              0x0
+#define CLKCTRL_IDLEST_INTRANSITION            0x1
+#define CLKCTRL_IDLEST_INTERFACE_IDLE          0x2
+#define CLKCTRL_IDLEST_DISABLED                        0x3
+
+/* Private functions */
+
+/* Read a register in a CM instance */
+static inline u32 am33xx_cm_read_reg(s16 inst, u16 idx)
+{
+       return __raw_readl(cm_base + inst + idx);
+}
+
+/* Write into a register in a CM */
+static inline void am33xx_cm_write_reg(u32 val, s16 inst, u16 idx)
+{
+       __raw_writel(val, cm_base + inst + idx);
+}
+
+/* Read-modify-write a register in CM */
+static inline u32 am33xx_cm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx)
+{
+       u32 v;
+
+       v = am33xx_cm_read_reg(inst, idx);
+       v &= ~mask;
+       v |= bits;
+       am33xx_cm_write_reg(v, inst, idx);
+
+       return v;
+}
+
+static inline u32 am33xx_cm_set_reg_bits(u32 bits, s16 inst, s16 idx)
+{
+       return am33xx_cm_rmw_reg_bits(bits, bits, inst, idx);
+}
+
+static inline u32 am33xx_cm_clear_reg_bits(u32 bits, s16 inst, s16 idx)
+{
+       return am33xx_cm_rmw_reg_bits(bits, 0x0, inst, idx);
+}
+
+static inline u32 am33xx_cm_read_reg_bits(u16 inst, s16 idx, u32 mask)
+{
+       u32 v;
+
+       v = am33xx_cm_read_reg(inst, idx);
+       v &= mask;
+       v >>= __ffs(mask);
+
+       return v;
+}
+
+/**
+ * _clkctrl_idlest - read a CM_*_CLKCTRL register; mask & shift IDLEST bitfield
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * Return the IDLEST bitfield of a CM_*_CLKCTRL register, shifted down to
+ * bit 0.
+ */
+static u32 _clkctrl_idlest(u16 inst, s16 cdoffs, u16 clkctrl_offs)
+{
+       u32 v = am33xx_cm_read_reg(inst, clkctrl_offs);
+       v &= AM33XX_IDLEST_MASK;
+       v >>= AM33XX_IDLEST_SHIFT;
+       return v;
+}
+
+/**
+ * _is_module_ready - can module registers be accessed without causing an abort?
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * Returns true if the module's CM_*_CLKCTRL.IDLEST bitfield is either
+ * *FUNCTIONAL or *INTERFACE_IDLE; false otherwise.
+ */
+static bool _is_module_ready(u16 inst, s16 cdoffs, u16 clkctrl_offs)
+{
+       u32 v;
+
+       v = _clkctrl_idlest(inst, cdoffs, clkctrl_offs);
+
+       return (v == CLKCTRL_IDLEST_FUNCTIONAL ||
+               v == CLKCTRL_IDLEST_INTERFACE_IDLE) ? true : false;
+}
+
+/**
+ * _clktrctrl_write - write @c to a CM_CLKSTCTRL.CLKTRCTRL register bitfield
+ * @c: CLKTRCTRL register bitfield (LSB = bit 0, i.e., unshifted)
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ *
+ * @c must be the unshifted value for CLKTRCTRL - i.e., this function
+ * will handle the shift itself.
+ */
+static void _clktrctrl_write(u8 c, s16 inst, u16 cdoffs)
+{
+       u32 v;
+
+       v = am33xx_cm_read_reg(inst, cdoffs);
+       v &= ~AM33XX_CLKTRCTRL_MASK;
+       v |= c << AM33XX_CLKTRCTRL_SHIFT;
+       am33xx_cm_write_reg(v, inst, cdoffs);
+}
+
+/* Public functions */
+
+/**
+ * am33xx_cm_is_clkdm_in_hwsup - is a clockdomain in hwsup idle mode?
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ *
+ * Returns true if the clockdomain referred to by (@inst, @cdoffs)
+ * is in hardware-supervised idle mode, or 0 otherwise.
+ */
+bool am33xx_cm_is_clkdm_in_hwsup(s16 inst, u16 cdoffs)
+{
+       u32 v;
+
+       v = am33xx_cm_read_reg(inst, cdoffs);
+       v &= AM33XX_CLKTRCTRL_MASK;
+       v >>= AM33XX_CLKTRCTRL_SHIFT;
+
+       return (v == OMAP34XX_CLKSTCTRL_ENABLE_AUTO) ? true : false;
+}
+
+/**
+ * am33xx_cm_clkdm_enable_hwsup - put a clockdomain in hwsup-idle mode
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ *
+ * Put a clockdomain referred to by (@inst, @cdoffs) into
+ * hardware-supervised idle mode.  No return value.
+ */
+void am33xx_cm_clkdm_enable_hwsup(s16 inst, u16 cdoffs)
+{
+       _clktrctrl_write(OMAP34XX_CLKSTCTRL_ENABLE_AUTO, inst, cdoffs);
+}
+
+/**
+ * am33xx_cm_clkdm_disable_hwsup - put a clockdomain in swsup-idle mode
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ *
+ * Put a clockdomain referred to by (@inst, @cdoffs) into
+ * software-supervised idle mode, i.e., controlled manually by the
+ * Linux OMAP clockdomain code.  No return value.
+ */
+void am33xx_cm_clkdm_disable_hwsup(s16 inst, u16 cdoffs)
+{
+       _clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, inst, cdoffs);
+}
+
+/**
+ * am33xx_cm_clkdm_force_sleep - try to put a clockdomain into idle
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ *
+ * Put a clockdomain referred to by (@inst, @cdoffs) into idle
+ * No return value.
+ */
+void am33xx_cm_clkdm_force_sleep(s16 inst, u16 cdoffs)
+{
+       _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, inst, cdoffs);
+}
+
+/**
+ * am33xx_cm_clkdm_force_wakeup - try to take a clockdomain out of idle
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ *
+ * Take a clockdomain referred to by (@inst, @cdoffs) out of idle,
+ * waking it up.  No return value.
+ */
+void am33xx_cm_clkdm_force_wakeup(s16 inst, u16 cdoffs)
+{
+       _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, inst, cdoffs);
+}
+
+/*
+ *
+ */
+
+/**
+ * am33xx_cm_wait_module_ready - wait for a module to be in 'func' state
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * Wait for the module IDLEST to be functional. If the idle state is in any
+ * the non functional state (trans, idle or disabled), module and thus the
+ * sysconfig cannot be accessed and will probably lead to an "imprecise
+ * external abort"
+ */
+int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs, u16 clkctrl_offs)
+{
+       int i = 0;
+
+       if (!clkctrl_offs)
+               return 0;
+
+       omap_test_timeout(_is_module_ready(inst, cdoffs, clkctrl_offs),
+                         MAX_MODULE_READY_TIME, i);
+
+       return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
+}
+
+/**
+ * am33xx_cm_wait_module_idle - wait for a module to be in 'disabled'
+ * state
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * Wait for the module IDLEST to be disabled. Some PRCM transition,
+ * like reset assertion or parent clock de-activation must wait the
+ * module to be fully disabled.
+ */
+int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs, u16 clkctrl_offs)
+{
+       int i = 0;
+
+       if (!clkctrl_offs)
+               return 0;
+
+       omap_test_timeout((_clkctrl_idlest(inst, cdoffs, clkctrl_offs) ==
+                               CLKCTRL_IDLEST_DISABLED),
+                               MAX_MODULE_READY_TIME, i);
+
+       return (i < MAX_MODULE_READY_TIME) ? 0 : -EBUSY;
+}
+
+/**
+ * am33xx_cm_module_enable - Enable the modulemode inside CLKCTRL
+ * @mode: Module mode (SW or HW)
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * No return value.
+ */
+void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs, u16 clkctrl_offs)
+{
+       u32 v;
+
+       v = am33xx_cm_read_reg(inst, clkctrl_offs);
+       v &= ~AM33XX_MODULEMODE_MASK;
+       v |= mode << AM33XX_MODULEMODE_SHIFT;
+       am33xx_cm_write_reg(v, inst, clkctrl_offs);
+}
+
+/**
+ * am33xx_cm_module_disable - Disable the module inside CLKCTRL
+ * @inst: CM instance register offset (*_INST macro)
+ * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
+ * @clkctrl_offs: Module clock control register offset (*_CLKCTRL macro)
+ *
+ * No return value.
+ */
+void am33xx_cm_module_disable(u16 inst, s16 cdoffs, u16 clkctrl_offs)
+{
+       u32 v;
+
+       v = am33xx_cm_read_reg(inst, clkctrl_offs);
+       v &= ~AM33XX_MODULEMODE_MASK;
+       am33xx_cm_write_reg(v, inst, clkctrl_offs);
+}
diff --git a/arch/arm/mach-omap2/cm33xx.h b/arch/arm/mach-omap2/cm33xx.h
new file mode 100644 (file)
index 0000000..5fa0b62
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+ * AM33XX CM offset macros
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ * Vaibhav Hiremath <hvaibhav@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_CM_33XX_H
+#define __ARCH_ARM_MACH_OMAP2_CM_33XX_H
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include "common.h"
+
+#include "cm.h"
+#include "cm-regbits-33xx.h"
+#include "cm33xx.h"
+
+/* CM base address */
+#define AM33XX_CM_BASE         0x44e00000
+
+#define AM33XX_CM_REGADDR(inst, reg)                           \
+       AM33XX_L4_WK_IO_ADDRESS(AM33XX_CM_BASE + (inst) + (reg))
+
+/* CM instances */
+#define AM33XX_CM_PER_MOD              0x0000
+#define AM33XX_CM_WKUP_MOD             0x0400
+#define AM33XX_CM_DPLL_MOD             0x0500
+#define AM33XX_CM_MPU_MOD              0x0600
+#define AM33XX_CM_DEVICE_MOD           0x0700
+#define AM33XX_CM_RTC_MOD              0x0800
+#define AM33XX_CM_GFX_MOD              0x0900
+#define AM33XX_CM_CEFUSE_MOD           0x0A00
+
+/* CM */
+
+/* CM.PER_CM register offsets */
+#define AM33XX_CM_PER_L4LS_CLKSTCTRL_OFFSET            0x0000
+#define AM33XX_CM_PER_L4LS_CLKSTCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0000)
+#define AM33XX_CM_PER_L3S_CLKSTCTRL_OFFSET             0x0004
+#define AM33XX_CM_PER_L3S_CLKSTCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0004)
+#define AM33XX_CM_PER_L4FW_CLKSTCTRL_OFFSET            0x0008
+#define AM33XX_CM_PER_L4FW_CLKSTCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0008)
+#define AM33XX_CM_PER_L3_CLKSTCTRL_OFFSET              0x000c
+#define AM33XX_CM_PER_L3_CLKSTCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x000c)
+#define AM33XX_CM_PER_CPGMAC0_CLKCTRL_OFFSET           0x0014
+#define AM33XX_CM_PER_CPGMAC0_CLKCTRL                  AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0014)
+#define AM33XX_CM_PER_LCDC_CLKCTRL_OFFSET              0x0018
+#define AM33XX_CM_PER_LCDC_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0018)
+#define AM33XX_CM_PER_USB0_CLKCTRL_OFFSET              0x001c
+#define AM33XX_CM_PER_USB0_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x001c)
+#define AM33XX_CM_PER_MLB_CLKCTRL_OFFSET               0x0020
+#define AM33XX_CM_PER_MLB_CLKCTRL                      AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0020)
+#define AM33XX_CM_PER_TPTC0_CLKCTRL_OFFSET             0x0024
+#define AM33XX_CM_PER_TPTC0_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0024)
+#define AM33XX_CM_PER_EMIF_CLKCTRL_OFFSET              0x0028
+#define AM33XX_CM_PER_EMIF_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0028)
+#define AM33XX_CM_PER_OCMCRAM_CLKCTRL_OFFSET           0x002c
+#define AM33XX_CM_PER_OCMCRAM_CLKCTRL                  AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x002c)
+#define AM33XX_CM_PER_GPMC_CLKCTRL_OFFSET              0x0030
+#define AM33XX_CM_PER_GPMC_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0030)
+#define AM33XX_CM_PER_MCASP0_CLKCTRL_OFFSET            0x0034
+#define AM33XX_CM_PER_MCASP0_CLKCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0034)
+#define AM33XX_CM_PER_UART5_CLKCTRL_OFFSET             0x0038
+#define AM33XX_CM_PER_UART5_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0038)
+#define AM33XX_CM_PER_MMC0_CLKCTRL_OFFSET              0x003c
+#define AM33XX_CM_PER_MMC0_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x003c)
+#define AM33XX_CM_PER_ELM_CLKCTRL_OFFSET               0x0040
+#define AM33XX_CM_PER_ELM_CLKCTRL                      AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0040)
+#define AM33XX_CM_PER_I2C2_CLKCTRL_OFFSET              0x0044
+#define AM33XX_CM_PER_I2C2_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0044)
+#define AM33XX_CM_PER_I2C1_CLKCTRL_OFFSET              0x0048
+#define AM33XX_CM_PER_I2C1_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0048)
+#define AM33XX_CM_PER_SPI0_CLKCTRL_OFFSET              0x004c
+#define AM33XX_CM_PER_SPI0_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x004c)
+#define AM33XX_CM_PER_SPI1_CLKCTRL_OFFSET              0x0050
+#define AM33XX_CM_PER_SPI1_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0050)
+#define AM33XX_CM_PER_SPI2_CLKCTRL_OFFSET              0x0054
+#define AM33XX_CM_PER_SPI2_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0054)
+#define AM33XX_CM_PER_SPI3_CLKCTRL_OFFSET              0x0058
+#define AM33XX_CM_PER_SPI3_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0058)
+#define AM33XX_CM_PER_L4LS_CLKCTRL_OFFSET              0x0060
+#define AM33XX_CM_PER_L4LS_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0060)
+#define AM33XX_CM_PER_L4FW_CLKCTRL_OFFSET              0x0064
+#define AM33XX_CM_PER_L4FW_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0064)
+#define AM33XX_CM_PER_MCASP1_CLKCTRL_OFFSET            0x0068
+#define AM33XX_CM_PER_MCASP1_CLKCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0068)
+#define AM33XX_CM_PER_UART1_CLKCTRL_OFFSET             0x006c
+#define AM33XX_CM_PER_UART1_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x006c)
+#define AM33XX_CM_PER_UART2_CLKCTRL_OFFSET             0x0070
+#define AM33XX_CM_PER_UART2_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0070)
+#define AM33XX_CM_PER_UART3_CLKCTRL_OFFSET             0x0074
+#define AM33XX_CM_PER_UART3_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0074)
+#define AM33XX_CM_PER_UART4_CLKCTRL_OFFSET             0x0078
+#define AM33XX_CM_PER_UART4_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0078)
+#define AM33XX_CM_PER_TIMER7_CLKCTRL_OFFSET            0x007c
+#define AM33XX_CM_PER_TIMER7_CLKCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x007c)
+#define AM33XX_CM_PER_TIMER2_CLKCTRL_OFFSET            0x0080
+#define AM33XX_CM_PER_TIMER2_CLKCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0080)
+#define AM33XX_CM_PER_TIMER3_CLKCTRL_OFFSET            0x0084
+#define AM33XX_CM_PER_TIMER3_CLKCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0084)
+#define AM33XX_CM_PER_TIMER4_CLKCTRL_OFFSET            0x0088
+#define AM33XX_CM_PER_TIMER4_CLKCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0088)
+#define AM33XX_CM_PER_MCASP2_CLKCTRL_OFFSET            0x008c
+#define AM33XX_CM_PER_MCASP2_CLKCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x008c)
+#define AM33XX_CM_PER_RNG_CLKCTRL_OFFSET               0x0090
+#define AM33XX_CM_PER_RNG_CLKCTRL                      AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0090)
+#define AM33XX_CM_PER_AES0_CLKCTRL_OFFSET              0x0094
+#define AM33XX_CM_PER_AES0_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0094)
+#define AM33XX_CM_PER_AES1_CLKCTRL_OFFSET              0x0098
+#define AM33XX_CM_PER_AES1_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0098)
+#define AM33XX_CM_PER_DES_CLKCTRL_OFFSET               0x009c
+#define AM33XX_CM_PER_DES_CLKCTRL                      AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x009c)
+#define AM33XX_CM_PER_SHA0_CLKCTRL_OFFSET              0x00a0
+#define AM33XX_CM_PER_SHA0_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00a0)
+#define AM33XX_CM_PER_PKA_CLKCTRL_OFFSET               0x00a4
+#define AM33XX_CM_PER_PKA_CLKCTRL                      AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00a4)
+#define AM33XX_CM_PER_GPIO6_CLKCTRL_OFFSET             0x00a8
+#define AM33XX_CM_PER_GPIO6_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00a8)
+#define AM33XX_CM_PER_GPIO1_CLKCTRL_OFFSET             0x00ac
+#define AM33XX_CM_PER_GPIO1_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00ac)
+#define AM33XX_CM_PER_GPIO2_CLKCTRL_OFFSET             0x00b0
+#define AM33XX_CM_PER_GPIO2_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00b0)
+#define AM33XX_CM_PER_GPIO3_CLKCTRL_OFFSET             0x00b4
+#define AM33XX_CM_PER_GPIO3_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00b4)
+#define AM33XX_CM_PER_GPIO4_CLKCTRL_OFFSET             0x00b8
+#define AM33XX_CM_PER_GPIO4_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00b8)
+#define AM33XX_CM_PER_TPCC_CLKCTRL_OFFSET              0x00bc
+#define AM33XX_CM_PER_TPCC_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00bc)
+#define AM33XX_CM_PER_DCAN0_CLKCTRL_OFFSET             0x00c0
+#define AM33XX_CM_PER_DCAN0_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00c0)
+#define AM33XX_CM_PER_DCAN1_CLKCTRL_OFFSET             0x00c4
+#define AM33XX_CM_PER_DCAN1_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00c4)
+#define AM33XX_CM_PER_EPWMSS1_CLKCTRL_OFFSET           0x00cc
+#define AM33XX_CM_PER_EPWMSS1_CLKCTRL                  AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00cc)
+#define AM33XX_CM_PER_EMIF_FW_CLKCTRL_OFFSET           0x00d0
+#define AM33XX_CM_PER_EMIF_FW_CLKCTRL                  AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00d0)
+#define AM33XX_CM_PER_EPWMSS0_CLKCTRL_OFFSET           0x00d4
+#define AM33XX_CM_PER_EPWMSS0_CLKCTRL                  AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00d4)
+#define AM33XX_CM_PER_EPWMSS2_CLKCTRL_OFFSET           0x00d8
+#define AM33XX_CM_PER_EPWMSS2_CLKCTRL                  AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00d8)
+#define AM33XX_CM_PER_L3_INSTR_CLKCTRL_OFFSET          0x00dc
+#define AM33XX_CM_PER_L3_INSTR_CLKCTRL                 AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00dc)
+#define AM33XX_CM_PER_L3_CLKCTRL_OFFSET                        0x00e0
+#define AM33XX_CM_PER_L3_CLKCTRL                       AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00e0)
+#define AM33XX_CM_PER_IEEE5000_CLKCTRL_OFFSET          0x00e4
+#define AM33XX_CM_PER_IEEE5000_CLKCTRL                 AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00e4)
+#define AM33XX_CM_PER_PRUSS_CLKCTRL_OFFSET             0x00e8
+#define AM33XX_CM_PER_PRUSS_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00e8)
+#define AM33XX_CM_PER_TIMER5_CLKCTRL_OFFSET            0x00ec
+#define AM33XX_CM_PER_TIMER5_CLKCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00ec)
+#define AM33XX_CM_PER_TIMER6_CLKCTRL_OFFSET            0x00f0
+#define AM33XX_CM_PER_TIMER6_CLKCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00f0)
+#define AM33XX_CM_PER_MMC1_CLKCTRL_OFFSET              0x00f4
+#define AM33XX_CM_PER_MMC1_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00f4)
+#define AM33XX_CM_PER_MMC2_CLKCTRL_OFFSET              0x00f8
+#define AM33XX_CM_PER_MMC2_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00f8)
+#define AM33XX_CM_PER_TPTC1_CLKCTRL_OFFSET             0x00fc
+#define AM33XX_CM_PER_TPTC1_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x00fc)
+#define AM33XX_CM_PER_TPTC2_CLKCTRL_OFFSET             0x0100
+#define AM33XX_CM_PER_TPTC2_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0100)
+#define AM33XX_CM_PER_GPIO5_CLKCTRL_OFFSET             0x0104
+#define AM33XX_CM_PER_GPIO5_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0104)
+#define AM33XX_CM_PER_SPINLOCK_CLKCTRL_OFFSET          0x010c
+#define AM33XX_CM_PER_SPINLOCK_CLKCTRL                 AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x010c)
+#define AM33XX_CM_PER_MAILBOX0_CLKCTRL_OFFSET          0x0110
+#define AM33XX_CM_PER_MAILBOX0_CLKCTRL                 AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0110)
+#define AM33XX_CM_PER_L4HS_CLKSTCTRL_OFFSET            0x011c
+#define AM33XX_CM_PER_L4HS_CLKSTCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x011c)
+#define AM33XX_CM_PER_L4HS_CLKCTRL_OFFSET              0x0120
+#define AM33XX_CM_PER_L4HS_CLKCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0120)
+#define AM33XX_CM_PER_MSTR_EXPS_CLKCTRL_OFFSET         0x0124
+#define AM33XX_CM_PER_MSTR_EXPS_CLKCTRL                        AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0124)
+#define AM33XX_CM_PER_SLV_EXPS_CLKCTRL_OFFSET          0x0128
+#define AM33XX_CM_PER_SLV_EXPS_CLKCTRL                 AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0128)
+#define AM33XX_CM_PER_OCPWP_L3_CLKSTCTRL_OFFSET                0x012c
+#define AM33XX_CM_PER_OCPWP_L3_CLKSTCTRL               AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x012c)
+#define AM33XX_CM_PER_OCPWP_CLKCTRL_OFFSET             0x0130
+#define AM33XX_CM_PER_OCPWP_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0130)
+#define AM33XX_CM_PER_MAILBOX1_CLKCTRL_OFFSET          0x0134
+#define AM33XX_CM_PER_MAILBOX1_CLKCTRL                 AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0134)
+#define AM33XX_CM_PER_PRUSS_CLKSTCTRL_OFFSET           0x0140
+#define AM33XX_CM_PER_PRUSS_CLKSTCTRL                  AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0140)
+#define AM33XX_CM_PER_CPSW_CLKSTCTRL_OFFSET            0x0144
+#define AM33XX_CM_PER_CPSW_CLKSTCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0144)
+#define AM33XX_CM_PER_LCDC_CLKSTCTRL_OFFSET            0x0148
+#define AM33XX_CM_PER_LCDC_CLKSTCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0148)
+#define AM33XX_CM_PER_CLKDIV32K_CLKCTRL_OFFSET         0x014c
+#define AM33XX_CM_PER_CLKDIV32K_CLKCTRL                        AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x014c)
+#define AM33XX_CM_PER_CLK_24MHZ_CLKSTCTRL_OFFSET       0x0150
+#define AM33XX_CM_PER_CLK_24MHZ_CLKSTCTRL              AM33XX_CM_REGADDR(AM33XX_CM_PER_MOD, 0x0150)
+
+/* CM.WKUP_CM register offsets */
+#define AM33XX_CM_WKUP_CLKSTCTRL_OFFSET                        0x0000
+#define AM33XX_CM_WKUP_CLKSTCTRL                       AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0000)
+#define AM33XX_CM_WKUP_CONTROL_CLKCTRL_OFFSET          0x0004
+#define AM33XX_CM_WKUP_CONTROL_CLKCTRL                 AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0004)
+#define AM33XX_CM_WKUP_GPIO0_CLKCTRL_OFFSET            0x0008
+#define AM33XX_CM_WKUP_GPIO0_CLKCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0008)
+#define AM33XX_CM_WKUP_L4WKUP_CLKCTRL_OFFSET           0x000c
+#define AM33XX_CM_WKUP_L4WKUP_CLKCTRL                  AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x000c)
+#define AM33XX_CM_WKUP_TIMER0_CLKCTRL_OFFSET           0x0010
+#define AM33XX_CM_WKUP_TIMER0_CLKCTRL                  AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0010)
+#define AM33XX_CM_WKUP_DEBUGSS_CLKCTRL_OFFSET          0x0014
+#define AM33XX_CM_WKUP_DEBUGSS_CLKCTRL                 AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0014)
+#define AM33XX_CM_L3_AON_CLKSTCTRL_OFFSET              0x0018
+#define AM33XX_CM_L3_AON_CLKSTCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0018)
+#define AM33XX_CM_AUTOIDLE_DPLL_MPU_OFFSET             0x001c
+#define AM33XX_CM_AUTOIDLE_DPLL_MPU                    AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x001c)
+#define AM33XX_CM_IDLEST_DPLL_MPU_OFFSET               0x0020
+#define AM33XX_CM_IDLEST_DPLL_MPU                      AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0020)
+#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_MPU_OFFSET       0x0024
+#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_MPU              AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0024)
+#define AM33XX_CM_SSC_MODFREQDIV_DPLL_MPU_OFFSET       0x0028
+#define AM33XX_CM_SSC_MODFREQDIV_DPLL_MPU              AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0028)
+#define AM33XX_CM_CLKSEL_DPLL_MPU_OFFSET               0x002c
+#define AM33XX_CM_CLKSEL_DPLL_MPU                      AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x002c)
+#define AM33XX_CM_AUTOIDLE_DPLL_DDR_OFFSET             0x0030
+#define AM33XX_CM_AUTOIDLE_DPLL_DDR                    AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0030)
+#define AM33XX_CM_IDLEST_DPLL_DDR_OFFSET               0x0034
+#define AM33XX_CM_IDLEST_DPLL_DDR                      AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0034)
+#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_DDR_OFFSET       0x0038
+#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_DDR              AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0038)
+#define AM33XX_CM_SSC_MODFREQDIV_DPLL_DDR_OFFSET       0x003c
+#define AM33XX_CM_SSC_MODFREQDIV_DPLL_DDR              AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x003c)
+#define AM33XX_CM_CLKSEL_DPLL_DDR_OFFSET               0x0040
+#define AM33XX_CM_CLKSEL_DPLL_DDR                      AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0040)
+#define AM33XX_CM_AUTOIDLE_DPLL_DISP_OFFSET            0x0044
+#define AM33XX_CM_AUTOIDLE_DPLL_DISP                   AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0044)
+#define AM33XX_CM_IDLEST_DPLL_DISP_OFFSET              0x0048
+#define AM33XX_CM_IDLEST_DPLL_DISP                     AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0048)
+#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_DISP_OFFSET      0x004c
+#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_DISP             AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x004c)
+#define AM33XX_CM_SSC_MODFREQDIV_DPLL_DISP_OFFSET      0x0050
+#define AM33XX_CM_SSC_MODFREQDIV_DPLL_DISP             AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0050)
+#define AM33XX_CM_CLKSEL_DPLL_DISP_OFFSET              0x0054
+#define AM33XX_CM_CLKSEL_DPLL_DISP                     AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0054)
+#define AM33XX_CM_AUTOIDLE_DPLL_CORE_OFFSET            0x0058
+#define AM33XX_CM_AUTOIDLE_DPLL_CORE                   AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0058)
+#define AM33XX_CM_IDLEST_DPLL_CORE_OFFSET              0x005c
+#define AM33XX_CM_IDLEST_DPLL_CORE                     AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x005c)
+#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_CORE_OFFSET      0x0060
+#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_CORE             AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0060)
+#define AM33XX_CM_SSC_MODFREQDIV_DPLL_CORE_OFFSET      0x0064
+#define AM33XX_CM_SSC_MODFREQDIV_DPLL_CORE             AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0064)
+#define AM33XX_CM_CLKSEL_DPLL_CORE_OFFSET              0x0068
+#define AM33XX_CM_CLKSEL_DPLL_CORE                     AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0068)
+#define AM33XX_CM_AUTOIDLE_DPLL_PER_OFFSET             0x006c
+#define AM33XX_CM_AUTOIDLE_DPLL_PER                    AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x006c)
+#define AM33XX_CM_IDLEST_DPLL_PER_OFFSET               0x0070
+#define AM33XX_CM_IDLEST_DPLL_PER                      AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0070)
+#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_PER_OFFSET       0x0074
+#define AM33XX_CM_SSC_DELTAMSTEP_DPLL_PER              AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0074)
+#define AM33XX_CM_SSC_MODFREQDIV_DPLL_PER_OFFSET       0x0078
+#define AM33XX_CM_SSC_MODFREQDIV_DPLL_PER              AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0078)
+#define AM33XX_CM_CLKDCOLDO_DPLL_PER_OFFSET            0x007c
+#define AM33XX_CM_CLKDCOLDO_DPLL_PER                   AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x007c)
+#define AM33XX_CM_DIV_M4_DPLL_CORE_OFFSET              0x0080
+#define AM33XX_CM_DIV_M4_DPLL_CORE                     AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0080)
+#define AM33XX_CM_DIV_M5_DPLL_CORE_OFFSET              0x0084
+#define AM33XX_CM_DIV_M5_DPLL_CORE                     AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0084)
+#define AM33XX_CM_CLKMODE_DPLL_MPU_OFFSET              0x0088
+#define AM33XX_CM_CLKMODE_DPLL_MPU                     AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0088)
+#define AM33XX_CM_CLKMODE_DPLL_PER_OFFSET              0x008c
+#define AM33XX_CM_CLKMODE_DPLL_PER                     AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x008c)
+#define AM33XX_CM_CLKMODE_DPLL_CORE_OFFSET             0x0090
+#define AM33XX_CM_CLKMODE_DPLL_CORE                    AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0090)
+#define AM33XX_CM_CLKMODE_DPLL_DDR_OFFSET              0x0094
+#define AM33XX_CM_CLKMODE_DPLL_DDR                     AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0094)
+#define AM33XX_CM_CLKMODE_DPLL_DISP_OFFSET             0x0098
+#define AM33XX_CM_CLKMODE_DPLL_DISP                    AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x0098)
+#define AM33XX_CM_CLKSEL_DPLL_PERIPH_OFFSET            0x009c
+#define AM33XX_CM_CLKSEL_DPLL_PERIPH                   AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x009c)
+#define AM33XX_CM_DIV_M2_DPLL_DDR_OFFSET               0x00a0
+#define AM33XX_CM_DIV_M2_DPLL_DDR                      AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00a0)
+#define AM33XX_CM_DIV_M2_DPLL_DISP_OFFSET              0x00a4
+#define AM33XX_CM_DIV_M2_DPLL_DISP                     AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00a4)
+#define AM33XX_CM_DIV_M2_DPLL_MPU_OFFSET               0x00a8
+#define AM33XX_CM_DIV_M2_DPLL_MPU                      AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00a8)
+#define AM33XX_CM_DIV_M2_DPLL_PER_OFFSET               0x00ac
+#define AM33XX_CM_DIV_M2_DPLL_PER                      AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00ac)
+#define AM33XX_CM_WKUP_WKUP_M3_CLKCTRL_OFFSET          0x00b0
+#define AM33XX_CM_WKUP_WKUP_M3_CLKCTRL                 AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00b0)
+#define AM33XX_CM_WKUP_UART0_CLKCTRL_OFFSET            0x00b4
+#define AM33XX_CM_WKUP_UART0_CLKCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00b4)
+#define AM33XX_CM_WKUP_I2C0_CLKCTRL_OFFSET             0x00b8
+#define AM33XX_CM_WKUP_I2C0_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00b8)
+#define AM33XX_CM_WKUP_ADC_TSC_CLKCTRL_OFFSET          0x00bc
+#define AM33XX_CM_WKUP_ADC_TSC_CLKCTRL                 AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00bc)
+#define AM33XX_CM_WKUP_SMARTREFLEX0_CLKCTRL_OFFSET     0x00c0
+#define AM33XX_CM_WKUP_SMARTREFLEX0_CLKCTRL            AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00c0)
+#define AM33XX_CM_WKUP_TIMER1_CLKCTRL_OFFSET           0x00c4
+#define AM33XX_CM_WKUP_TIMER1_CLKCTRL                  AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00c4)
+#define AM33XX_CM_WKUP_SMARTREFLEX1_CLKCTRL_OFFSET     0x00c8
+#define AM33XX_CM_WKUP_SMARTREFLEX1_CLKCTRL            AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00c8)
+#define AM33XX_CM_L4_WKUP_AON_CLKSTCTRL_OFFSET         0x00cc
+#define AM33XX_CM_L4_WKUP_AON_CLKSTCTRL                        AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00cc)
+#define AM33XX_CM_WKUP_WDT0_CLKCTRL_OFFSET             0x00d0
+#define AM33XX_CM_WKUP_WDT0_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00d0)
+#define AM33XX_CM_WKUP_WDT1_CLKCTRL_OFFSET             0x00d4
+#define AM33XX_CM_WKUP_WDT1_CLKCTRL                    AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00d4)
+#define AM33XX_CM_DIV_M6_DPLL_CORE_OFFSET              0x00d8
+#define AM33XX_CM_DIV_M6_DPLL_CORE                     AM33XX_CM_REGADDR(AM33XX_CM_WKUP_MOD, 0x00d8)
+
+/* CM.DPLL_CM register offsets */
+#define AM33XX_CLKSEL_TIMER7_CLK_OFFSET                        0x0004
+#define AM33XX_CLKSEL_TIMER7_CLK                       AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0004)
+#define AM33XX_CLKSEL_TIMER2_CLK_OFFSET                        0x0008
+#define AM33XX_CLKSEL_TIMER2_CLK                       AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0008)
+#define AM33XX_CLKSEL_TIMER3_CLK_OFFSET                        0x000c
+#define AM33XX_CLKSEL_TIMER3_CLK                       AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x000c)
+#define AM33XX_CLKSEL_TIMER4_CLK_OFFSET                        0x0010
+#define AM33XX_CLKSEL_TIMER4_CLK                       AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0010)
+#define AM33XX_CM_MAC_CLKSEL_OFFSET                    0x0014
+#define AM33XX_CM_MAC_CLKSEL                           AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0014)
+#define AM33XX_CLKSEL_TIMER5_CLK_OFFSET                        0x0018
+#define AM33XX_CLKSEL_TIMER5_CLK                       AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0018)
+#define AM33XX_CLKSEL_TIMER6_CLK_OFFSET                        0x001c
+#define AM33XX_CLKSEL_TIMER6_CLK                       AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x001c)
+#define AM33XX_CM_CPTS_RFT_CLKSEL_OFFSET               0x0020
+#define AM33XX_CM_CPTS_RFT_CLKSEL                      AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0020)
+#define AM33XX_CLKSEL_TIMER1MS_CLK_OFFSET              0x0028
+#define AM33XX_CLKSEL_TIMER1MS_CLK                     AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0028)
+#define AM33XX_CLKSEL_GFX_FCLK_OFFSET                  0x002c
+#define AM33XX_CLKSEL_GFX_FCLK                         AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x002c)
+#define AM33XX_CLKSEL_PRUSS_OCP_CLK_OFFSET             0x0030
+#define AM33XX_CLKSEL_PRUSS_OCP_CLK                    AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0030)
+#define AM33XX_CLKSEL_LCDC_PIXEL_CLK_OFFSET            0x0034
+#define AM33XX_CLKSEL_LCDC_PIXEL_CLK                   AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0034)
+#define AM33XX_CLKSEL_WDT1_CLK_OFFSET                  0x0038
+#define AM33XX_CLKSEL_WDT1_CLK                         AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x0038)
+#define AM33XX_CLKSEL_GPIO0_DBCLK_OFFSET               0x003c
+#define AM33XX_CLKSEL_GPIO0_DBCLK                      AM33XX_CM_REGADDR(AM33XX_CM_DPLL_MOD, 0x003c)
+
+/* CM.MPU_CM register offsets */
+#define AM33XX_CM_MPU_CLKSTCTRL_OFFSET                 0x0000
+#define AM33XX_CM_MPU_CLKSTCTRL                                AM33XX_CM_REGADDR(AM33XX_CM_MPU_MOD, 0x0000)
+#define AM33XX_CM_MPU_MPU_CLKCTRL_OFFSET               0x0004
+#define AM33XX_CM_MPU_MPU_CLKCTRL                      AM33XX_CM_REGADDR(AM33XX_CM_MPU_MOD, 0x0004)
+
+/* CM.DEVICE_CM register offsets */
+#define AM33XX_CM_CLKOUT_CTRL_OFFSET                   0x0000
+#define AM33XX_CM_CLKOUT_CTRL                          AM33XX_CM_REGADDR(AM33XX_CM_DEVICE_MOD, 0x0000)
+
+/* CM.RTC_CM register offsets */
+#define AM33XX_CM_RTC_RTC_CLKCTRL_OFFSET               0x0000
+#define AM33XX_CM_RTC_RTC_CLKCTRL                      AM33XX_CM_REGADDR(AM33XX_CM_RTC_MOD, 0x0000)
+#define AM33XX_CM_RTC_CLKSTCTRL_OFFSET                 0x0004
+#define AM33XX_CM_RTC_CLKSTCTRL                                AM33XX_CM_REGADDR(AM33XX_CM_RTC_MOD, 0x0004)
+
+/* CM.GFX_CM register offsets */
+#define AM33XX_CM_GFX_L3_CLKSTCTRL_OFFSET              0x0000
+#define AM33XX_CM_GFX_L3_CLKSTCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_GFX_MOD, 0x0000)
+#define AM33XX_CM_GFX_GFX_CLKCTRL_OFFSET               0x0004
+#define AM33XX_CM_GFX_GFX_CLKCTRL                      AM33XX_CM_REGADDR(AM33XX_CM_GFX_MOD, 0x0004)
+#define AM33XX_CM_GFX_BITBLT_CLKCTRL_OFFSET            0x0008
+#define AM33XX_CM_GFX_BITBLT_CLKCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_GFX_MOD, 0x0008)
+#define AM33XX_CM_GFX_L4LS_GFX_CLKSTCTRL__1_OFFSET     0x000c
+#define AM33XX_CM_GFX_L4LS_GFX_CLKSTCTRL__1            AM33XX_CM_REGADDR(AM33XX_CM_GFX_MOD, 0x000c)
+#define AM33XX_CM_GFX_MMUCFG_CLKCTRL_OFFSET            0x0010
+#define AM33XX_CM_GFX_MMUCFG_CLKCTRL                   AM33XX_CM_REGADDR(AM33XX_CM_GFX_MOD, 0x0010)
+#define AM33XX_CM_GFX_MMUDATA_CLKCTRL_OFFSET           0x0014
+#define AM33XX_CM_GFX_MMUDATA_CLKCTRL                  AM33XX_CM_REGADDR(AM33XX_CM_GFX_MOD, 0x0014)
+
+/* CM.CEFUSE_CM register offsets */
+#define AM33XX_CM_CEFUSE_CLKSTCTRL_OFFSET              0x0000
+#define AM33XX_CM_CEFUSE_CLKSTCTRL                     AM33XX_CM_REGADDR(AM33XX_CM_CEFUSE_MOD, 0x0000)
+#define AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL_OFFSET         0x0020
+#define AM33XX_CM_CEFUSE_CEFUSE_CLKCTRL                        AM33XX_CM_REGADDR(AM33XX_CM_CEFUSE_MOD, 0x0020)
+
+
+extern bool am33xx_cm_is_clkdm_in_hwsup(s16 inst, u16 cdoffs);
+extern void am33xx_cm_clkdm_enable_hwsup(s16 inst, u16 cdoffs);
+extern void am33xx_cm_clkdm_disable_hwsup(s16 inst, u16 cdoffs);
+extern void am33xx_cm_clkdm_force_sleep(s16 inst, u16 cdoffs);
+extern void am33xx_cm_clkdm_force_wakeup(s16 inst, u16 cdoffs);
+
+#ifdef CONFIG_SOC_AM33XX
+extern int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs,
+                                       u16 clkctrl_offs);
+extern void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs,
+                                       u16 clkctrl_offs);
+extern void am33xx_cm_module_disable(u16 inst, s16 cdoffs,
+                                       u16 clkctrl_offs);
+extern int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs,
+                                       u16 clkctrl_offs);
+#else
+static inline int am33xx_cm_wait_module_idle(u16 inst, s16 cdoffs,
+                                       u16 clkctrl_offs)
+{
+       return 0;
+}
+static inline void am33xx_cm_module_enable(u8 mode, u16 inst, s16 cdoffs,
+                                       u16 clkctrl_offs)
+{
+}
+static inline void am33xx_cm_module_disable(u16 inst, s16 cdoffs,
+                                       u16 clkctrl_offs)
+{
+}
+static inline int am33xx_cm_wait_module_ready(u16 inst, s16 cdoffs,
+                                       u16 clkctrl_offs)
+{
+       return 0;
+}
+#endif
+
+#endif
index 1a39945d9ff81fd5ed9a78f785c6fe08d3f1f939..1894015ff04b3faf33312058e34dbca92f756b5d 100644 (file)
@@ -234,20 +234,6 @@ void omap4_cminst_clkdm_disable_hwsup(u8 part, s16 inst, u16 cdoffs)
        _clktrctrl_write(OMAP34XX_CLKSTCTRL_DISABLE_AUTO, part, inst, cdoffs);
 }
 
-/**
- * omap4_cminst_clkdm_force_sleep - try to put a clockdomain into idle
- * @part: PRCM partition ID that the clockdomain registers exist in
- * @inst: CM instance register offset (*_INST macro)
- * @cdoffs: Clockdomain register offset (*_CDOFFS macro)
- *
- * Put a clockdomain referred to by (@part, @inst, @cdoffs) into idle
- * No return value.
- */
-void omap4_cminst_clkdm_force_sleep(u8 part, s16 inst, u16 cdoffs)
-{
-       _clktrctrl_write(OMAP34XX_CLKSTCTRL_FORCE_SLEEP, part, inst, cdoffs);
-}
-
 /**
  * omap4_cminst_clkdm_force_sleep - try to take a clockdomain out of idle
  * @part: PRCM partition ID that the clockdomain registers exist in
index a018a7327879daba08da25f7376db36d8b5a4985..d69fdefef9858addee526adee078a94816216af9 100644 (file)
@@ -16,38 +16,13 @@ extern void omap4_cminst_clkdm_enable_hwsup(u8 part, s16 inst, u16 cdoffs);
 extern void omap4_cminst_clkdm_disable_hwsup(u8 part, s16 inst, u16 cdoffs);
 extern void omap4_cminst_clkdm_force_sleep(u8 part, s16 inst, u16 cdoffs);
 extern void omap4_cminst_clkdm_force_wakeup(u8 part, s16 inst, u16 cdoffs);
-
 extern int omap4_cminst_wait_module_ready(u8 part, u16 inst, s16 cdoffs, u16 clkctrl_offs);
-
-# ifdef CONFIG_ARCH_OMAP4
 extern int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs,
                                         u16 clkctrl_offs);
-
 extern void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst, s16 cdoffs,
                                       u16 clkctrl_offs);
 extern void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
                                        u16 clkctrl_offs);
-
-# else
-
-static inline int omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs,
-                                       u16 clkctrl_offs)
-{
-       return 0;
-}
-
-static inline void omap4_cminst_module_enable(u8 mode, u8 part, u16 inst,
-                               s16 cdoffs, u16 clkctrl_offs)
-{
-}
-
-static inline void omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
-                                u16 clkctrl_offs)
-{
-}
-
-# endif
-
 /*
  * In an ideal world, we would not export these low-level functions,
  * but this will probably take some time to fix properly
index 1706ebcec08d79c08ea23191b949266613c9406e..14734746457c2bd8bdfcabd1ea4681dc4edab36e 100644 (file)
@@ -35,6 +35,16 @@ static struct omap2_mcspi_device_config ads7846_mcspi_config = {
        .turbo_mode     = 0,
 };
 
+/*
+ * ADS7846 driver maybe request a gpio according to the value
+ * of pdata->get_pendown_state, but we have done this. So set
+ * get_pendown_state to avoid twice gpio requesting.
+ */
+static int omap3_get_pendown_state(void)
+{
+       return !gpio_get_value(OMAP3_EVM_TS_GPIO);
+}
+
 static struct ads7846_platform_data ads7846_config = {
        .x_max                  = 0x0fff,
        .y_max                  = 0x0fff,
@@ -45,6 +55,7 @@ static struct ads7846_platform_data ads7846_config = {
        .debounce_rep           = 1,
        .gpio_pendown           = -EINVAL,
        .keep_vref_on           = 1,
+       .get_pendown_state      = &omap3_get_pendown_state,
 };
 
 static struct spi_board_info ads7846_spi_board_info __initdata = {
@@ -63,28 +74,30 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
        struct spi_board_info *spi_bi = &ads7846_spi_board_info;
        int err;
 
-       if (board_pdata && board_pdata->get_pendown_state) {
-               err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
-               if (err) {
-                       pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
-                       return;
-               }
-               gpio_export(gpio_pendown, 0);
-
-               if (gpio_debounce)
-                       gpio_set_debounce(gpio_pendown, gpio_debounce);
+       err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
+       if (err) {
+               pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
+               return;
        }
 
+       if (gpio_debounce)
+               gpio_set_debounce(gpio_pendown, gpio_debounce);
+
        spi_bi->bus_num = bus_num;
        spi_bi->irq     = gpio_to_irq(gpio_pendown);
 
        if (board_pdata) {
                board_pdata->gpio_pendown = gpio_pendown;
                spi_bi->platform_data = board_pdata;
+               if (board_pdata->get_pendown_state)
+                       gpio_export(gpio_pendown, 0);
        } else {
                ads7846_config.gpio_pendown = gpio_pendown;
        }
 
+       if (!board_pdata || (board_pdata && !board_pdata->get_pendown_state))
+               gpio_free(gpio_pendown);
+
        spi_register_board_info(&ads7846_spi_board_info, 1);
 }
 #else
index a0b4a42836ab9f7a29f1757ee410e37a237af00c..4c4ef6a6166ba28b768ee46580b7f35dbafb7885 100644 (file)
@@ -4,6 +4,7 @@
 #include "twl-common.h"
 
 #define NAND_BLOCK_SIZE        SZ_128K
+#define OMAP3_EVM_TS_GPIO      175
 
 struct mtd_partition;
 struct ads7846_platform_data;
index 8a6953a34fe2b01d159ba40a296a343818236a76..069f9725b1c3edd879bbc689af17ed70542deaae 100644 (file)
@@ -29,8 +29,6 @@
 
 /* Global address base setup code */
 
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
-
 static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
 {
        omap2_set_globals_tap(omap2_globals);
@@ -39,8 +37,6 @@ static void __init __omap2_set_globals(struct omap_globals *omap2_globals)
        omap2_set_globals_prcm(omap2_globals);
 }
 
-#endif
-
 #if defined(CONFIG_SOC_OMAP2420)
 
 static struct omap_globals omap242x_globals = {
@@ -134,7 +130,9 @@ void __init ti81xx_map_io(void)
 {
        omapti81xx_map_common_io();
 }
+#endif
 
+#if defined(CONFIG_SOC_AM33XX)
 #define AM33XX_TAP_BASE                (AM33XX_CTRL_BASE + \
                                TI81XX_CONTROL_DEVICE_ID - 0x204)
 
@@ -171,9 +169,7 @@ static struct omap_globals omap4_globals = {
 
 void __init omap2_set_globals_443x(void)
 {
-       omap2_set_globals_tap(&omap4_globals);
-       omap2_set_globals_control(&omap4_globals);
-       omap2_set_globals_prcm(&omap4_globals);
+       __omap2_set_globals(&omap4_globals);
 }
 
 void __init omap4_map_io(void)
@@ -182,3 +178,27 @@ void __init omap4_map_io(void)
 }
 #endif
 
+#if defined(CONFIG_SOC_OMAP5)
+static struct omap_globals omap5_globals = {
+       .class  = OMAP54XX_CLASS,
+       .tap    = OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE),
+       .ctrl   = OMAP2_L4_IO_ADDRESS(OMAP54XX_SCM_BASE),
+       .ctrl_pad       = OMAP2_L4_IO_ADDRESS(OMAP54XX_CTRL_BASE),
+       .prm    = OMAP2_L4_IO_ADDRESS(OMAP54XX_PRM_BASE),
+       .cm     = OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_AON_BASE),
+       .cm2    = OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_BASE),
+       .prcm_mpu = OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE),
+};
+
+void __init omap2_set_globals_5xxx(void)
+{
+       omap2_set_globals_tap(&omap5_globals);
+       omap2_set_globals_control(&omap5_globals);
+       omap2_set_globals_prcm(&omap5_globals);
+}
+
+void __init omap5_map_io(void)
+{
+       omap5_map_common_io();
+}
+#endif
index be9dfd1abe603f247c089f7c0feab81bb3402223..1f65b1871c231eb35abd289b1b1e4457367dad42 100644 (file)
@@ -115,12 +115,22 @@ static inline int omap_mux_late_init(void)
 }
 #endif
 
+#ifdef CONFIG_SOC_OMAP5
+extern void omap5_map_common_io(void);
+#else
+static inline void omap5_map_common_io(void)
+{
+}
+#endif
+
 extern void omap2_init_common_infrastructure(void);
 
 extern struct sys_timer omap2_timer;
 extern struct sys_timer omap3_timer;
 extern struct sys_timer omap3_secure_timer;
+extern struct sys_timer omap3_am33xx_timer;
 extern struct sys_timer omap4_timer;
+extern struct sys_timer omap5_timer;
 
 void omap2420_init_early(void);
 void omap2430_init_early(void);
@@ -128,9 +138,12 @@ void omap3430_init_early(void);
 void omap35xx_init_early(void);
 void omap3630_init_early(void);
 void omap3_init_early(void);   /* Do not use this one */
+void am33xx_init_early(void);
 void am35xx_init_early(void);
 void ti81xx_init_early(void);
+void am33xx_init_early(void);
 void omap4430_init_early(void);
+void omap5_init_early(void);
 void omap3_init_late(void);    /* Do not use this one */
 void omap4430_init_late(void);
 void omap2420_init_late(void);
@@ -166,12 +179,18 @@ void omap2_set_globals_242x(void);
 void omap2_set_globals_243x(void);
 void omap2_set_globals_3xxx(void);
 void omap2_set_globals_443x(void);
+void omap2_set_globals_5xxx(void);
 void omap2_set_globals_ti81xx(void);
 void omap2_set_globals_am33xx(void);
 
 /* These get called from omap2_set_globals_xxxx(), do not call these */
 void omap2_set_globals_tap(struct omap_globals *);
+#if defined(CONFIG_SOC_HAS_OMAP2_SDRC)
 void omap2_set_globals_sdrc(struct omap_globals *);
+#else
+static inline void omap2_set_globals_sdrc(struct omap_globals *omap2_globals)
+{ }
+#endif
 void omap2_set_globals_control(struct omap_globals *);
 void omap2_set_globals_prcm(struct omap_globals *);
 
@@ -180,6 +199,7 @@ void omap243x_map_io(void);
 void omap3_map_io(void);
 void am33xx_map_io(void);
 void omap4_map_io(void);
+void omap5_map_io(void);
 void ti81xx_map_io(void);
 void omap_barriers_init(void);
 
@@ -219,6 +239,8 @@ void omap3_intc_prepare_idle(void);
 void omap3_intc_resume_idle(void);
 void omap2_intc_handle_irq(struct pt_regs *regs);
 void omap3_intc_handle_irq(struct pt_regs *regs);
+void omap_intc_of_init(void);
+void omap_gic_of_init(void);
 
 #ifdef CONFIG_CACHE_L2X0
 extern void __iomem *omap4_get_l2cache_base(void);
@@ -226,10 +248,10 @@ extern void __iomem *omap4_get_l2cache_base(void);
 
 struct device_node;
 #ifdef CONFIG_OF
-int __init omap_intc_of_init(struct device_node *node,
+int __init intc_of_init(struct device_node *node,
                             struct device_node *parent);
 #else
-int __init omap_intc_of_init(struct device_node *node,
+int __init intc_of_init(struct device_node *node,
                             struct device_node *parent)
 {
        return 0;
@@ -256,6 +278,7 @@ extern void omap_secondary_startup(void);
 extern u32 omap_modify_auxcoreboot0(u32 set_mask, u32 clear_mask);
 extern void omap_auxcoreboot_addr(u32 cpu_addr);
 extern u32 omap_read_auxcoreboot0(void);
+extern void omap5_secondary_startup(void);
 #endif
 
 #if defined(CONFIG_SMP) && defined(CONFIG_PM)
index 08e674bb04171c2e6b81d97be51a7cab6e697d0c..3223b81e75327afb3af4ca47f88e69a744ac372e 100644 (file)
@@ -241,6 +241,49 @@ void omap3_ctrl_write_boot_mode(u8 bootmode)
 
 #endif
 
+/**
+ * omap_ctrl_write_dsp_boot_addr - set boot address for a remote processor
+ * @bootaddr: physical address of the boot loader
+ *
+ * Set boot address for the boot loader of a supported processor
+ * when a power ON sequence occurs.
+ */
+void omap_ctrl_write_dsp_boot_addr(u32 bootaddr)
+{
+       u32 offset = cpu_is_omap243x() ? OMAP243X_CONTROL_IVA2_BOOTADDR :
+                    cpu_is_omap34xx() ? OMAP343X_CONTROL_IVA2_BOOTADDR :
+                    cpu_is_omap44xx() ? OMAP4_CTRL_MODULE_CORE_DSP_BOOTADDR :
+                    0;
+
+       if (!offset) {
+               pr_err("%s: unsupported omap type\n", __func__);
+               return;
+       }
+
+       omap_ctrl_writel(bootaddr, offset);
+}
+
+/**
+ * omap_ctrl_write_dsp_boot_mode - set boot mode for a remote processor
+ * @bootmode: 8-bit value to pass to some boot code
+ *
+ * Sets boot mode for the boot loader of a supported processor
+ * when a power ON sequence occurs.
+ */
+void omap_ctrl_write_dsp_boot_mode(u8 bootmode)
+{
+       u32 offset = cpu_is_omap243x() ? OMAP243X_CONTROL_IVA2_BOOTMOD :
+                    cpu_is_omap34xx() ? OMAP343X_CONTROL_IVA2_BOOTMOD :
+                    0;
+
+       if (!offset) {
+               pr_err("%s: unsupported omap type\n", __func__);
+               return;
+       }
+
+       omap_ctrl_writel(bootmode, offset);
+}
+
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
 /*
  * Clears the scratchpad contents in case of cold boot-
index a406fd045ce13e18649b488a663cc21c6520a415..b8cdc8531b607dabd6a755b7ed21fba201f248bc 100644 (file)
@@ -21,6 +21,8 @@
 #include <mach/ctrl_module_pad_core_44xx.h>
 #include <mach/ctrl_module_pad_wkup_44xx.h>
 
+#include <plat/am33xx.h>
+
 #ifndef __ASSEMBLY__
 #define OMAP242X_CTRL_REGADDR(reg)                                     \
                OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
@@ -28,6 +30,8 @@
                OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
 #define OMAP343X_CTRL_REGADDR(reg)                                     \
                OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
+#define AM33XX_CTRL_REGADDR(reg)                                       \
+               AM33XX_L4_WK_IO_ADDRESS(AM33XX_SCM_BASE + (reg))
 #else
 #define OMAP242X_CTRL_REGADDR(reg)                                     \
                OMAP2_L4_IO_ADDRESS(OMAP242X_CTRL_BASE + (reg))
@@ -35,6 +39,8 @@
                OMAP2_L4_IO_ADDRESS(OMAP243X_CTRL_BASE + (reg))
 #define OMAP343X_CTRL_REGADDR(reg)                                     \
                OMAP2_L4_IO_ADDRESS(OMAP343X_CTRL_BASE + (reg))
+#define AM33XX_CTRL_REGADDR(reg)                                       \
+               AM33XX_L4_WK_IO_ADDRESS(AM33XX_SCM_BASE + (reg))
 #endif /* __ASSEMBLY__ */
 
 /*
 #define OMAP3630_CONTROL_FUSE_OPP120_VDD1       (OMAP2_CONTROL_GENERAL + 0x0120)
 #define OMAP3630_CONTROL_FUSE_OPP50_VDD2        (OMAP2_CONTROL_GENERAL + 0x0128)
 #define OMAP3630_CONTROL_FUSE_OPP100_VDD2       (OMAP2_CONTROL_GENERAL + 0x012C)
+#define OMAP3630_CONTROL_CAMERA_PHY_CTRL       (OMAP2_CONTROL_GENERAL + 0x02f0)
 
 /* OMAP44xx control efuse offsets */
 #define OMAP44XX_CONTROL_FUSE_IVA_OPP50                0x22C
 /* TI81XX CONTROL_DEVCONF register offsets */
 #define TI81XX_CONTROL_DEVICE_ID       (TI81XX_CONTROL_DEVCONF + 0x000)
 
+/* OMAP54XX CONTROL STATUS register */
+#define OMAP5XXX_CONTROL_STATUS                0x134
+#define OMAP5_DEVICETYPE_MASK          (0x7 << 6)
+
 /*
  * REVISIT: This list of registers is not comprehensive - there are more
  * that should be added.
                                                OMAP343X_SCRATCHPAD + reg)
 
 /* AM35XX_CONTROL_IPSS_CLK_CTRL bits */
-#define AM35XX_USBOTG_VBUSP_CLK_SHIFT   0
-#define AM35XX_CPGMAC_VBUSP_CLK_SHIFT   1
-#define AM35XX_VPFE_VBUSP_CLK_SHIFT     2
-#define AM35XX_HECC_VBUSP_CLK_SHIFT     3
-#define AM35XX_USBOTG_FCLK_SHIFT        8
-#define AM35XX_CPGMAC_FCLK_SHIFT        9
-#define AM35XX_VPFE_FCLK_SHIFT          10
-
-/*AM35XX CONTROL_LVL_INTR_CLEAR bits*/
+#define AM35XX_USBOTG_VBUSP_CLK_SHIFT  0
+#define AM35XX_CPGMAC_VBUSP_CLK_SHIFT  1
+#define AM35XX_VPFE_VBUSP_CLK_SHIFT    2
+#define AM35XX_HECC_VBUSP_CLK_SHIFT    3
+#define AM35XX_USBOTG_FCLK_SHIFT       8
+#define AM35XX_CPGMAC_FCLK_SHIFT       9
+#define AM35XX_VPFE_FCLK_SHIFT         10
+
+/* AM35XX CONTROL_LVL_INTR_CLEAR bits */
 #define AM35XX_CPGMAC_C0_MISC_PULSE_CLR        BIT(0)
 #define AM35XX_CPGMAC_C0_RX_PULSE_CLR  BIT(1)
 #define AM35XX_CPGMAC_C0_RX_THRESH_CLR BIT(2)
 #define AM35XX_VPFE_CCDC_VD1_INT_CLR   BIT(6)
 #define AM35XX_VPFE_CCDC_VD2_INT_CLR   BIT(7)
 
-/*AM35XX CONTROL_IP_SW_RESET bits*/
+/* AM35XX CONTROL_IP_SW_RESET bits */
 #define AM35XX_USBOTGSS_SW_RST         BIT(0)
 #define AM35XX_CPGMACSS_SW_RST         BIT(1)
 #define AM35XX_VPFE_VBUSP_SW_RST       BIT(2)
 #define AM35XX_HECC_SW_RST             BIT(3)
 #define AM35XX_VPFE_PCLK_SW_RST                BIT(4)
 
-/*
- * CONTROL AM33XX STATUS register
- */
+/* AM33XX CONTROL_STATUS register */
 #define AM33XX_CONTROL_STATUS          0x040
+#define AM33XX_CONTROL_SEC_CLK_CTRL    0x1bc
 
-/*
- * CONTROL OMAP STATUS register to identify OMAP3 features
- */
+/* AM33XX CONTROL_STATUS bitfields (partial) */
+#define AM33XX_CONTROL_STATUS_SYSBOOT1_SHIFT           22
+#define AM33XX_CONTROL_STATUS_SYSBOOT1_MASK            (0x3 << 22)
+
+/* CONTROL OMAP STATUS register to identify OMAP3 features */
 #define OMAP3_CONTROL_OMAP_STATUS      0x044c
 
 #define OMAP3_SGX_SHIFT                        13
@@ -397,6 +409,8 @@ extern u32 omap3_arm_context[128];
 extern void omap3_control_save_context(void);
 extern void omap3_control_restore_context(void);
 extern void omap3_ctrl_write_boot_mode(u8 bootmode);
+extern void omap_ctrl_write_dsp_boot_addr(u32 bootaddr);
+extern void omap_ctrl_write_dsp_boot_mode(u8 bootmode);
 extern void omap3630_ctrl_disable_rta(void);
 extern int omap3_ctrl_save_padconf(void);
 #else
index 207bc1c7759f1bb66b986d0ff1dbadd8c2b01925..f2a49a48ef5992bada3566f8e2ab00581a3e6b4d 100644 (file)
@@ -36,8 +36,6 @@
 #include "control.h"
 #include "common.h"
 
-#ifdef CONFIG_CPU_IDLE
-
 /* Mach specific information to be recorded in the C-state driver_data */
 struct omap3_idle_statedata {
        u32 mpu_state;
@@ -77,20 +75,6 @@ static struct omap3_idle_statedata omap3_idle_data[] = {
 
 static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
 
-static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
-                               struct clockdomain *clkdm)
-{
-       clkdm_allow_idle(clkdm);
-       return 0;
-}
-
-static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
-                               struct clockdomain *clkdm)
-{
-       clkdm_deny_idle(clkdm);
-       return 0;
-}
-
 static int __omap3_enter_idle(struct cpuidle_device *dev,
                                struct cpuidle_driver *drv,
                                int index)
@@ -108,8 +92,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 
        /* Deny idle for C1 */
        if (index == 0) {
-               pwrdm_for_each_clkdm(mpu_pd, _cpuidle_deny_idle);
-               pwrdm_for_each_clkdm(core_pd, _cpuidle_deny_idle);
+               clkdm_deny_idle(mpu_pd->pwrdm_clkdms[0]);
+               clkdm_deny_idle(core_pd->pwrdm_clkdms[0]);
        }
 
        /*
@@ -131,8 +115,8 @@ static int __omap3_enter_idle(struct cpuidle_device *dev,
 
        /* Re-allow idle for C1 */
        if (index == 0) {
-               pwrdm_for_each_clkdm(mpu_pd, _cpuidle_allow_idle);
-               pwrdm_for_each_clkdm(core_pd, _cpuidle_allow_idle);
+               clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]);
+               clkdm_allow_idle(core_pd->pwrdm_clkdms[0]);
        }
 
 return_sleep_time:
@@ -178,7 +162,7 @@ static int next_valid_state(struct cpuidle_device *dev,
        u32 mpu_deepest_state = PWRDM_POWER_RET;
        u32 core_deepest_state = PWRDM_POWER_RET;
        int idx;
-       int next_index = -1;
+       int next_index = 0; /* C1 is the default value */
 
        if (enable_off_mode) {
                mpu_deepest_state = PWRDM_POWER_OFF;
@@ -209,12 +193,6 @@ static int next_valid_state(struct cpuidle_device *dev,
                }
        }
 
-       /*
-        * C1 is always valid.
-        * So, no need to check for 'next_index == -1' outside
-        * this loop.
-        */
-
        return next_index;
 }
 
@@ -228,23 +206,22 @@ static int next_valid_state(struct cpuidle_device *dev,
  * the device to the specified or a safer state.
  */
 static int omap3_enter_idle_bm(struct cpuidle_device *dev,
-                               struct cpuidle_driver *drv,
+                              struct cpuidle_driver *drv,
                               int index)
 {
        int new_state_idx;
-       u32 core_next_state, per_next_state = 0, per_saved_state = 0, cam_state;
+       u32 core_next_state, per_next_state = 0, per_saved_state = 0;
        struct omap3_idle_statedata *cx;
        int ret;
 
        /*
-        * Prevent idle completely if CAM is active.
+        * Use only C1 if CAM is active.
         * CAM does not have wakeup capability in OMAP3.
         */
-       cam_state = pwrdm_read_pwrst(cam_pd);
-       if (cam_state == PWRDM_POWER_ON) {
+       if (pwrdm_read_pwrst(cam_pd) == PWRDM_POWER_ON)
                new_state_idx = drv->safe_state_index;
-               goto select_state;
-       }
+       else
+               new_state_idx = next_valid_state(dev, drv, index);
 
        /*
         * FIXME: we currently manage device-specific idle states
@@ -254,24 +231,28 @@ static int omap3_enter_idle_bm(struct cpuidle_device *dev,
         *        its own code.
         */
 
-       /*
-        * Prevent PER off if CORE is not in retention or off as this
-        * would disable PER wakeups completely.
-        */
-       cx = &omap3_idle_data[index];
+       /* Program PER state */
+       cx = &omap3_idle_data[new_state_idx];
        core_next_state = cx->core_state;
        per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
-       if ((per_next_state == PWRDM_POWER_OFF) &&
-           (core_next_state > PWRDM_POWER_RET))
-               per_next_state = PWRDM_POWER_RET;
+       if (new_state_idx == 0) {
+               /* In C1 do not allow PER state lower than CORE state */
+               if (per_next_state < core_next_state)
+                       per_next_state = core_next_state;
+       } else {
+               /*
+                * Prevent PER OFF if CORE is not in RETention or OFF as this
+                * would disable PER wakeups completely.
+                */
+               if ((per_next_state == PWRDM_POWER_OFF) &&
+                   (core_next_state > PWRDM_POWER_RET))
+                       per_next_state = PWRDM_POWER_RET;
+       }
 
        /* Are we changing PER target state? */
        if (per_next_state != per_saved_state)
                pwrdm_set_next_pwrst(per_pd, per_next_state);
 
-       new_state_idx = next_valid_state(dev, drv, index);
-
-select_state:
        ret = omap3_enter_idle(dev, drv, new_state_idx);
 
        /* Restore original PER state if it was modified */
@@ -288,7 +269,7 @@ struct cpuidle_driver omap3_idle_driver = {
        .owner =        THIS_MODULE,
        .states = {
                {
-                       .enter            = omap3_enter_idle,
+                       .enter            = omap3_enter_idle_bm,
                        .exit_latency     = 2 + 2,
                        .target_residency = 5,
                        .flags            = CPUIDLE_FLAG_TIME_VALID,
@@ -379,9 +360,3 @@ int __init omap3_idle_init(void)
 
        return 0;
 }
-#else
-int __init omap3_idle_init(void)
-{
-       return 0;
-}
-#endif /* CONFIG_CPU_IDLE */
index be1617ca84bd022092e7c06849a3ece28e64052f..02d15bbd4e35c2eb4d90cf892085d143d0334e81 100644 (file)
@@ -22,8 +22,6 @@
 #include "pm.h"
 #include "prm.h"
 
-#ifdef CONFIG_CPU_IDLE
-
 /* Machine specific information */
 struct omap4_idle_statedata {
        u32 cpu_state;
@@ -199,9 +197,3 @@ int __init omap4_idle_init(void)
 
        return 0;
 }
-#else
-int __init omap4_idle_init(void)
-{
-       return 0;
-}
-#endif /* CONFIG_CPU_IDLE */
index 7b4b9327e54332e1edc3bacec2a35269169fd6b2..c00c68961bb848d16a68802003a4ee6402cf4710 100644 (file)
@@ -27,7 +27,6 @@
 
 #include "iomap.h"
 #include <plat/board.h>
-#include <plat/mmc.h>
 #include <plat/dma.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
@@ -84,7 +83,7 @@ static int __init omap4_l3_init(void)
         * To avoid code running on other OMAPs in
         * multi-omap builds
         */
-       if (!(cpu_is_omap44xx()))
+       if (!cpu_is_omap44xx() && !soc_is_omap54xx())
                return -ENODEV;
 
        for (i = 0; i < L3_MODULES; i++) {
@@ -603,112 +602,6 @@ static inline void omap_init_aes(void) { }
 
 /*-------------------------------------------------------------------------*/
 
-#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
-
-static inline void omap242x_mmc_mux(struct omap_mmc_platform_data
-                                                       *mmc_controller)
-{
-       if ((mmc_controller->slots[0].switch_pin > 0) && \
-               (mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES))
-               omap_mux_init_gpio(mmc_controller->slots[0].switch_pin,
-                                       OMAP_PIN_INPUT_PULLUP);
-       if ((mmc_controller->slots[0].gpio_wp > 0) && \
-               (mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES))
-               omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp,
-                                       OMAP_PIN_INPUT_PULLUP);
-
-       omap_mux_init_signal("sdmmc_cmd", 0);
-       omap_mux_init_signal("sdmmc_clki", 0);
-       omap_mux_init_signal("sdmmc_clko", 0);
-       omap_mux_init_signal("sdmmc_dat0", 0);
-       omap_mux_init_signal("sdmmc_dat_dir0", 0);
-       omap_mux_init_signal("sdmmc_cmd_dir", 0);
-       if (mmc_controller->slots[0].caps & MMC_CAP_4_BIT_DATA) {
-               omap_mux_init_signal("sdmmc_dat1", 0);
-               omap_mux_init_signal("sdmmc_dat2", 0);
-               omap_mux_init_signal("sdmmc_dat3", 0);
-               omap_mux_init_signal("sdmmc_dat_dir1", 0);
-               omap_mux_init_signal("sdmmc_dat_dir2", 0);
-               omap_mux_init_signal("sdmmc_dat_dir3", 0);
-       }
-
-       /*
-        * Use internal loop-back in MMC/SDIO Module Input Clock
-        * selection
-        */
-       if (mmc_controller->slots[0].internal_clock) {
-               u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-               v |= (1 << 24);
-               omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
-       }
-}
-
-void __init omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data)
-{
-       struct platform_device *pdev;
-       struct omap_hwmod *oh;
-       int id = 0;
-       char *oh_name = "msdi1";
-       char *dev_name = "mmci-omap";
-
-       if (!mmc_data[0]) {
-               pr_err("%s fails: Incomplete platform data\n", __func__);
-               return;
-       }
-
-       omap242x_mmc_mux(mmc_data[0]);
-
-       oh = omap_hwmod_lookup(oh_name);
-       if (!oh) {
-               pr_err("Could not look up %s\n", oh_name);
-               return;
-       }
-       pdev = omap_device_build(dev_name, id, oh, mmc_data[0],
-                                sizeof(struct omap_mmc_platform_data), NULL, 0, 0);
-       if (IS_ERR(pdev))
-               WARN(1, "Can'd build omap_device for %s:%s.\n",
-                                       dev_name, oh->name);
-}
-
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-#if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE)
-#define OMAP_HDQ_BASE  0x480B2000
-static struct resource omap_hdq_resources[] = {
-       {
-               .start          = OMAP_HDQ_BASE,
-               .end            = OMAP_HDQ_BASE + 0x1C,
-               .flags          = IORESOURCE_MEM,
-       },
-       {
-               .start          = INT_24XX_HDQ_IRQ,
-               .flags          = IORESOURCE_IRQ,
-       },
-};
-static struct platform_device omap_hdq_dev = {
-       .name = "omap_hdq",
-       .id = 0,
-       .dev = {
-               .platform_data = NULL,
-       },
-       .num_resources  = ARRAY_SIZE(omap_hdq_resources),
-       .resource       = omap_hdq_resources,
-};
-static inline void omap_hdq_init(void)
-{
-       if (cpu_is_omap2420())
-               return;
-
-       platform_device_register(&omap_hdq_dev);
-}
-#else
-static inline void omap_hdq_init(void) {}
-#endif
-
-/*---------------------------------------------------------------------------*/
-
 #if defined(CONFIG_VIDEO_OMAP2_VOUT) || \
        defined(CONFIG_VIDEO_OMAP2_VOUT_MODULE)
 #if defined(CONFIG_FB_OMAP2) || defined(CONFIG_FB_OMAP2_MODULE)
@@ -753,7 +646,6 @@ static int __init omap2_init_devices(void)
                omap_init_mcspi();
        }
        omap_init_pmu();
-       omap_hdq_init();
        omap_init_sti();
        omap_init_sham();
        omap_init_aes();
@@ -772,7 +664,7 @@ static int __init omap_init_wdt(void)
        char *oh_name = "wd_timer2";
        char *dev_name = "omap_wdt";
 
-       if (!cpu_class_is_omap2())
+       if (!cpu_class_is_omap2() || of_have_populated_dt())
                return 0;
 
        oh = omap_hwmod_lookup(oh_name);
index f0f10beeffe8ec77fe8d77b9a81934e83bd92bb1..b9c8d2f6a81fb166c8fa9822a6e01f81317cdc0b 100644 (file)
@@ -135,11 +135,20 @@ static u16 _omap3_dpll_compute_freqsel(struct clk *clk, u8 n)
  */
 static int _omap3_noncore_dpll_lock(struct clk *clk)
 {
+       const struct dpll_data *dd;
        u8 ai;
-       int r;
+       u8 state = 1;
+       int r = 0;
 
        pr_debug("clock: locking DPLL %s\n", clk->name);
 
+       dd = clk->dpll_data;
+       state <<= __ffs(dd->idlest_mask);
+
+       /* Check if already locked */
+       if ((__raw_readl(dd->idlest_reg) & dd->idlest_mask) == state)
+               goto done;
+
        ai = omap3_dpll_autoidle_read(clk);
 
        if (ai)
@@ -152,6 +161,7 @@ static int _omap3_noncore_dpll_lock(struct clk *clk)
        if (ai)
                omap3_dpll_allow_idle(clk);
 
+done:
        return r;
 }
 
@@ -628,3 +638,17 @@ unsigned long omap3_clkoutx2_recalc(struct clk *clk)
                rate = clk->parent->rate * 2;
        return rate;
 }
+
+/* OMAP3/4 non-CORE DPLL clkops */
+
+const struct clkops clkops_omap3_noncore_dpll_ops = {
+       .enable         = omap3_noncore_dpll_enable,
+       .disable        = omap3_noncore_dpll_disable,
+       .allow_idle     = omap3_dpll_allow_idle,
+       .deny_idle      = omap3_dpll_deny_idle,
+};
+
+const struct clkops clkops_omap3_core_dpll_ops = {
+       .allow_idle     = omap3_dpll_allow_idle,
+       .deny_idle      = omap3_dpll_deny_idle,
+};
diff --git a/arch/arm/mach-omap2/drm.c b/arch/arm/mach-omap2/drm.c
new file mode 100644 (file)
index 0000000..72e0f01
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * DRM/KMS device registration for TI OMAP platforms
+ *
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <rob.clark@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <plat/omap_device.h>
+#include <plat/omap_hwmod.h>
+
+#if defined(CONFIG_DRM_OMAP) || (CONFIG_DRM_OMAP_MODULE)
+
+static struct platform_device omap_drm_device = {
+       .dev = {
+               .coherent_dma_mask = DMA_BIT_MASK(32),
+       },
+       .name = "omapdrm",
+       .id = 0,
+};
+
+static int __init omap_init_drm(void)
+{
+       struct omap_hwmod *oh = NULL;
+       struct platform_device *pdev;
+
+       /* lookup and populate the DMM information, if present - OMAP4+ */
+       oh = omap_hwmod_lookup("dmm");
+
+       if (oh) {
+               pdev = omap_device_build(oh->name, -1, oh, NULL, 0, NULL, 0,
+                                       false);
+               WARN(IS_ERR(pdev), "Could not build omap_device for %s\n",
+                       oh->name);
+       }
+
+       return platform_device_register(&omap_drm_device);
+
+}
+
+arch_initcall(omap_init_drm);
+
+#endif
index 88ffa1e645cd948614afe61c17502533c64650a7..a636ebc16b3975f8ae49cc9c18bd676920baf4df 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <asm/memblock.h>
 
+#include "control.h"
 #include "cm2xxx_3xxx.h"
 #include "prm2xxx_3xxx.h"
 #ifdef CONFIG_BRIDGE_DVFS
@@ -46,6 +47,9 @@ static struct omap_dsp_platform_data omap_dsp_pdata __initdata = {
        .dsp_cm_read = omap2_cm_read_mod_reg,
        .dsp_cm_write = omap2_cm_write_mod_reg,
        .dsp_cm_rmw_bits = omap2_cm_rmw_mod_reg_bits,
+
+       .set_bootaddr = omap_ctrl_write_dsp_boot_addr,
+       .set_bootmode = omap_ctrl_write_dsp_boot_mode,
 };
 
 static phys_addr_t omap_dsp_phys_mempool_base;
index 2286410671e7e6ecded10796c3d268ea92863b8c..b2b5759ab0fec1ce1cb2641752ac14294ff25bf6 100644 (file)
@@ -727,7 +727,8 @@ static int __init gpmc_init(void)
                ck = "gpmc_fck";
                l = OMAP34XX_GPMC_BASE;
                gpmc_irq = INT_34XX_GPMC_IRQ;
-       } else if (cpu_is_omap44xx()) {
+       } else if (cpu_is_omap44xx() || soc_is_omap54xx()) {
+               /* Base address and irq number are same for OMAP4/5 */
                ck = "gpmc_ck";
                l = OMAP44XX_GPMC_BASE;
                gpmc_irq = OMAP44XX_IRQ_GPMC;
index 297ebe03f09c136fe52f1e83c4ac92d4396ff25c..cdd6dda03828fc6126331c1c560b1d5361a12730 100644 (file)
  * 02110-1301 USA
  */
 
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
 #include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 #include <plat/hdq1w.h>
 
 #include "common.h"
@@ -70,3 +76,23 @@ int omap_hdq1w_reset(struct omap_hwmod *oh)
 
        return 0;
 }
+
+static int __init omap_init_hdq(void)
+{
+       int id = -1;
+       struct platform_device *pdev;
+       struct omap_hwmod *oh;
+       char *oh_name = "hdq1w";
+       char *devname = "omap_hdq";
+
+       oh = omap_hwmod_lookup(oh_name);
+       if (!oh)
+               return 0;
+
+       pdev = omap_device_build(devname, id, oh, NULL, 0, NULL, 0, 0);
+       WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
+            devname, oh->name);
+
+       return 0;
+}
+arch_initcall(omap_init_hdq);
index 00486a8564fdace3131b4a8309bdeb067a16cece..40373db649aa3e8fc16fcb57b0002777e9e277c3 100644 (file)
@@ -44,12 +44,17 @@ int omap_type(void)
 
        if (cpu_is_omap24xx()) {
                val = omap_ctrl_readl(OMAP24XX_CONTROL_STATUS);
-       } else if (cpu_is_am33xx()) {
+       } else if (soc_is_am33xx()) {
                val = omap_ctrl_readl(AM33XX_CONTROL_STATUS);
        } else if (cpu_is_omap34xx()) {
                val = omap_ctrl_readl(OMAP343X_CONTROL_STATUS);
        } else if (cpu_is_omap44xx()) {
                val = omap_ctrl_readl(OMAP4_CTRL_MODULE_CORE_STATUS);
+       } else if (soc_is_omap54xx()) {
+               val = omap_ctrl_readl(OMAP5XXX_CONTROL_STATUS);
+               val &= OMAP5_DEVICETYPE_MASK;
+               val >>= 6;
+               goto out;
        } else {
                pr_err("Cannot detect omap type!\n");
                goto out;
@@ -100,7 +105,7 @@ static u16 tap_prod_id;
 
 void omap_get_die_id(struct omap_die_id *odi)
 {
-       if (cpu_is_omap44xx()) {
+       if (cpu_is_omap44xx() || soc_is_omap54xx()) {
                odi->id_0 = read_tap_reg(OMAP_TAP_DIE_ID_44XX_0);
                odi->id_1 = read_tap_reg(OMAP_TAP_DIE_ID_44XX_1);
                odi->id_2 = read_tap_reg(OMAP_TAP_DIE_ID_44XX_2);
@@ -189,7 +194,7 @@ static void __init omap3_cpuinfo(void)
                cpu_name = (omap3_has_sgx()) ? "AM3517" : "AM3505";
        } else if (cpu_is_ti816x()) {
                cpu_name = "TI816X";
-       } else if (cpu_is_am335x()) {
+       } else if (soc_is_am335x()) {
                cpu_name =  "AM335X";
        } else if (cpu_is_ti814x()) {
                cpu_name = "TI814X";
@@ -513,6 +518,41 @@ void __init omap4xxx_check_revision(void)
                ((omap_rev() >> 12) & 0xf), ((omap_rev() >> 8) & 0xf));
 }
 
+void __init omap5xxx_check_revision(void)
+{
+       u32 idcode;
+       u16 hawkeye;
+       u8 rev;
+
+       idcode = read_tap_reg(OMAP_TAP_IDCODE);
+       hawkeye = (idcode >> 12) & 0xffff;
+       rev = (idcode >> 28) & 0xff;
+       switch (hawkeye) {
+       case 0xb942:
+               switch (rev) {
+               case 0:
+               default:
+                       omap_revision = OMAP5430_REV_ES1_0;
+               }
+               break;
+
+       case 0xb998:
+               switch (rev) {
+               case 0:
+               default:
+                       omap_revision = OMAP5432_REV_ES1_0;
+               }
+               break;
+
+       default:
+               /* Unknown default to latest silicon rev as default*/
+               omap_revision = OMAP5430_REV_ES1_0;
+       }
+
+       pr_info("OMAP%04x ES%d.0\n",
+                       omap_rev() >> 16, ((omap_rev() >> 12) & 0xf));
+}
+
 /*
  * Set up things for map_io and processor detection later on. Gets called
  * pretty much first thing from board init. For multi-omap, this gets
index f1e13d1ca5e7360b30878de8b69c5dd6c2a3adf3..95594495fcf6481f5568c8ed43787eb977d1a2ab 100644 (file)
@@ -36,6 +36,8 @@
 #define AM35XX_EMAC_CNTRL_MOD_OFFSET   (0x0)
 #define AM35XX_EMAC_CNTRL_RAM_OFFSET   (0x20000)
 #define AM35XX_EMAC_MDIO_OFFSET                (0x30000)
+#define AM35XX_IPSS_MDIO_BASE          (AM35XX_IPSS_EMAC_BASE + \
+                                               AM35XX_EMAC_MDIO_OFFSET)
 #define AM35XX_EMAC_CNTRL_RAM_SIZE     (0x2000)
 #define AM35XX_EMAC_RAM_ADDR           (AM3517_EMAC_BASE + \
                                                AM3517_EMAC_CNTRL_RAM_OFFSET)
index 2f7ac70a20d8f8ae8df8094ee75f818d0bf596e5..01970824e0e5d7a7773b49fd321b406d42c971dd 100644 (file)
@@ -42,6 +42,7 @@
 #define OMAP4_CTRL_MODULE_CORE_STD_FUSE_OPP_DPLL_1             0x0268
 #define OMAP4_CTRL_MODULE_CORE_STATUS                          0x02c4
 #define OMAP4_CTRL_MODULE_CORE_DEV_CONF                                0x0300
+#define OMAP4_CTRL_MODULE_CORE_DSP_BOOTADDR                    0x0304
 #define OMAP4_CTRL_MODULE_CORE_LDOVBB_IVA_VOLTAGE_CTRL         0x0314
 #define OMAP4_CTRL_MODULE_CORE_LDOVBB_MPU_VOLTAGE_CTRL         0x0318
 #define OMAP4_CTRL_MODULE_CORE_LDOSRAM_IVA_VOLTAGE_CTRL                0x0320
index cdfc2a1f0e75778bcbe549b8b86dae212bed25ba..93d10de7129fc550bea299921a3a0f3a62239630 100644 (file)
@@ -60,18 +60,20 @@ omap_uart_lsr:      .word   0
                beq     23f                     @ configure OMAP2UART3
                cmp     \rp, #OMAP3UART3        @ only on 34xx
                beq     33f                     @ configure OMAP3UART3
-               cmp     \rp, #OMAP4UART3        @ only on 44xx
-               beq     43f                     @ configure OMAP4UART3
+               cmp     \rp, #OMAP4UART3        @ only on 44xx/54xx
+               beq     43f                     @ configure OMAP4/5UART3
                cmp     \rp, #OMAP3UART4        @ only on 36xx
                beq     34f                     @ configure OMAP3UART4
-               cmp     \rp, #OMAP4UART4        @ only on 44xx
-               beq     44f                     @ configure OMAP4UART4
+               cmp     \rp, #OMAP4UART4        @ only on 44xx/54xx
+               beq     44f                     @ configure OMAP4/5UART4
                cmp     \rp, #TI81XXUART1       @ ti81Xx UART offsets different
                beq     81f                     @ configure UART1
                cmp     \rp, #TI81XXUART2       @ ti81Xx UART offsets different
                beq     82f                     @ configure UART2
                cmp     \rp, #TI81XXUART3       @ ti81Xx UART offsets different
                beq     83f                     @ configure UART3
+               cmp     \rp, #AM33XXUART1       @ AM33XX UART offsets different
+               beq     84f                     @ configure UART1
                cmp     \rp, #ZOOM_UART         @ only on zoom2/3
                beq     95f                     @ configure ZOOM_UART
 
@@ -100,7 +102,9 @@ omap_uart_lsr:      .word   0
                b       98f
 83:            mov     \rp, #UART_OFFSET(TI81XX_UART3_BASE)
                b       98f
-
+84:            ldr     \rp, =AM33XX_UART1_BASE
+               and     \rp, \rp, #0x00ffffff
+               b       97f
 95:            ldr     \rp, =ZOOM_UART_BASE
                str     \rp, [\tmp, #0]         @ omap_uart_phys
                ldr     \rp, =ZOOM_UART_VIRT
@@ -109,6 +113,17 @@ omap_uart_lsr:     .word   0
                str     \rp, [\tmp, #8]         @ omap_uart_lsr
                b       10b
 
+               /* AM33XX: Store both phys and virt address for the uart */
+97:            add     \rp, \rp, #0x44000000   @ phys base
+               str     \rp, [\tmp, #0]         @ omap_uart_phys
+               sub     \rp, \rp, #0x44000000   @ phys base
+               add     \rp, \rp, #0xf9000000   @ virt base
+               str     \rp, [\tmp, #4]         @ omap_uart_virt
+               mov     \rp, #(UART_LSR << OMAP_PORT_SHIFT)
+               str     \rp, [\tmp, #8]         @ omap_uart_lsr
+
+               b       10b
+
                /* Store both phys and virt address for the uart */
 98:            add     \rp, \rp, #0x48000000   @ phys base
                str     \rp, [\tmp, #0]         @ omap_uart_phys
index 548de90b58c2c76de55ea0a6b12382f1e897ee4c..b0fd16f5c3912a8ed9addba17f58d73a52b338bb 100644 (file)
 #ifndef OMAP_ARCH_WAKEUPGEN_H
 #define OMAP_ARCH_WAKEUPGEN_H
 
+/* OMAP4 and OMAP5 has same base address */
+#define OMAP_WKUPGEN_BASE                      0x48281000
+
 #define OMAP_WKG_CONTROL_0                     0x00
 #define OMAP_WKG_ENB_A_0                       0x10
 #define OMAP_WKG_ENB_B_0                       0x14
 #define OMAP_WKG_ENB_C_0                       0x18
 #define OMAP_WKG_ENB_D_0                       0x1c
+#define OMAP_WKG_ENB_E_0                       0x20
 #define OMAP_WKG_ENB_A_1                       0x410
 #define OMAP_WKG_ENB_B_1                       0x414
 #define OMAP_WKG_ENB_C_1                       0x418
 #define OMAP_WKG_ENB_D_1                       0x41c
+#define OMAP_WKG_ENB_E_1                       0x420
 #define OMAP_AUX_CORE_BOOT_0                   0x800
 #define OMAP_AUX_CORE_BOOT_1                   0x804
 #define OMAP_PTMSYNCREQ_MASK                   0xc00
@@ -28,4 +33,6 @@
 #define OMAP_TIMESTAMPCYCLEHI                  0xc0c
 
 extern int __init omap_wakeupgen_init(void);
+extern void __iomem *omap_get_wakeupgen_base(void);
+extern int omap_secure_apis_support(void);
 #endif
index 8d014ba04abcc7fe0fe0416db50dcb212458bb94..4d2d981ff5c50839d35714ea7e94cb48d6001ad7 100644 (file)
@@ -38,6 +38,7 @@
 #include "powerdomain.h"
 #include "clockdomain.h"
 #include "common.h"
+#include "clock.h"
 #include "clock2xxx.h"
 #include "clock3xxx.h"
 #include "clock44xx.h"
@@ -233,6 +234,35 @@ static struct map_desc omap44xx_io_desc[] __initdata = {
 };
 #endif
 
+#ifdef CONFIG_SOC_OMAP5
+static struct map_desc omap54xx_io_desc[] __initdata = {
+       {
+               .virtual        = L3_54XX_VIRT,
+               .pfn            = __phys_to_pfn(L3_54XX_PHYS),
+               .length         = L3_54XX_SIZE,
+               .type           = MT_DEVICE,
+       },
+       {
+               .virtual        = L4_54XX_VIRT,
+               .pfn            = __phys_to_pfn(L4_54XX_PHYS),
+               .length         = L4_54XX_SIZE,
+               .type           = MT_DEVICE,
+       },
+       {
+               .virtual        = L4_WK_54XX_VIRT,
+               .pfn            = __phys_to_pfn(L4_WK_54XX_PHYS),
+               .length         = L4_WK_54XX_SIZE,
+               .type           = MT_DEVICE,
+       },
+       {
+               .virtual        = L4_PER_54XX_VIRT,
+               .pfn            = __phys_to_pfn(L4_PER_54XX_PHYS),
+               .length         = L4_PER_54XX_SIZE,
+               .type           = MT_DEVICE,
+       },
+};
+#endif
+
 #ifdef CONFIG_SOC_OMAP2420
 void __init omap242x_map_common_io(void)
 {
@@ -278,6 +308,12 @@ void __init omap44xx_map_common_io(void)
 }
 #endif
 
+#ifdef CONFIG_SOC_OMAP5
+void __init omap5_map_common_io(void)
+{
+       iotable_init(omap54xx_io_desc, ARRAY_SIZE(omap54xx_io_desc));
+}
+#endif
 /*
  * omap2_init_reprogram_sdrc - reprogram SDRC timing parameters
  *
@@ -477,6 +513,20 @@ void __init ti81xx_init_late(void)
 }
 #endif
 
+#ifdef CONFIG_SOC_AM33XX
+void __init am33xx_init_early(void)
+{
+       omap2_set_globals_am33xx();
+       omap3xxx_check_revision();
+       ti81xx_check_features();
+       omap_common_init_early();
+       am33xx_voltagedomains_init();
+       am33xx_powerdomains_init();
+       am33xx_clockdomains_init();
+       am33xx_clk_init();
+}
+#endif
+
 #ifdef CONFIG_ARCH_OMAP4
 void __init omap4430_init_early(void)
 {
@@ -500,6 +550,15 @@ void __init omap4430_init_late(void)
 }
 #endif
 
+#ifdef CONFIG_SOC_OMAP5
+void __init omap5_init_early(void)
+{
+       omap2_set_globals_5xxx();
+       omap5xxx_check_revision();
+       omap_common_init_early();
+}
+#endif
+
 void __init omap_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
                                      struct omap_sdrc_params *sdrc_cs1)
 {
index 80b88921faba9cad422f0644847da0433697cd52..cce2b65039f1205fd13eda489b63921ade872783 100644 (file)
@@ -1,6 +1,14 @@
 /*
  * IO mappings for OMAP2+
  *
+ * IO definitions for TI OMAP processors and boards
+ *
+ * Copied from arch/arm/mach-sa1100/include/mach/io.h
+ * Copyright (C) 1997-1999 Russell King
+ *
+ * Copyright (C) 2009-2012 Texas Instruments
+ * Added OMAP4/5 support - Santosh Shilimkar <santosh.shilimkar@ti.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
                                                /* 0x49000000 --> 0xfb000000 */
 #define L4_ABE_44XX_VIRT       (L4_ABE_44XX_PHYS + OMAP2_L4_IO_OFFSET)
 #define L4_ABE_44XX_SIZE       SZ_1M
+/*
+ * ----------------------------------------------------------------------------
+ * Omap5 specific IO mapping
+ * ----------------------------------------------------------------------------
+ */
+#define L3_54XX_PHYS           L3_54XX_BASE    /* 0x44000000 --> 0xf8000000 */
+#define L3_54XX_VIRT           (L3_54XX_PHYS + OMAP4_L3_IO_OFFSET)
+#define L3_54XX_SIZE           SZ_1M
+
+#define L4_54XX_PHYS           L4_54XX_BASE    /* 0x4a000000 --> 0xfc000000 */
+#define L4_54XX_VIRT           (L4_54XX_PHYS + OMAP2_L4_IO_OFFSET)
+#define L4_54XX_SIZE           SZ_4M
+
+#define L4_WK_54XX_PHYS                L4_WK_54XX_BASE /* 0x4ae00000 --> 0xfce00000 */
+#define L4_WK_54XX_VIRT                (L4_WK_54XX_PHYS + OMAP2_L4_IO_OFFSET)
+#define L4_WK_54XX_SIZE                SZ_2M
 
+#define L4_PER_54XX_PHYS       L4_PER_54XX_BASE /* 0x48000000 --> 0xfa000000 */
+#define L4_PER_54XX_VIRT       (L4_PER_54XX_PHYS + OMAP2_L4_IO_OFFSET)
+#define L4_PER_54XX_SIZE       SZ_4M
index 6038a8c84b743af0ed1f205af643f3a8a0013b63..bcd83db41bbce706062a9116d5aa1fb25472089e 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <mach/hardware.h>
 
@@ -258,11 +259,11 @@ asmlinkage void __exception_irq_entry omap2_intc_handle_irq(struct pt_regs *regs
        omap_intc_handle_irq(base_addr, regs);
 }
 
-int __init omap_intc_of_init(struct device_node *node,
+int __init intc_of_init(struct device_node *node,
                             struct device_node *parent)
 {
        struct resource res;
-       u32 nr_irqs = 96;
+       u32 nr_irq = 96;
 
        if (WARN_ON(!node))
                return -ENODEV;
@@ -272,15 +273,25 @@ int __init omap_intc_of_init(struct device_node *node,
                return -EINVAL;
        }
 
-       if (of_property_read_u32(node, "ti,intc-size", &nr_irqs))
-               pr_warn("unable to get intc-size, default to %d\n", nr_irqs);
+       if (of_property_read_u32(node, "ti,intc-size", &nr_irq))
+               pr_warn("unable to get intc-size, default to %d\n", nr_irq);
 
-       omap_init_irq(res.start, nr_irqs, of_node_get(node));
+       omap_init_irq(res.start, nr_irq, of_node_get(node));
 
        return 0;
 }
 
-#ifdef CONFIG_ARCH_OMAP3
+static struct of_device_id irq_match[] __initdata = {
+       { .compatible = "ti,omap2-intc", .data = intc_of_init, },
+       { }
+};
+
+void __init omap_intc_of_init(void)
+{
+       of_irq_init(irq_match);
+}
+
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_SOC_AM33XX)
 static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)];
 
 void omap_intc_save_context(void)
index 19b8b6774862dce41d3b837db885573b0d9d26e0..6875be837d9f9632cb3ffbd0c3fcbd64b5dcfddc 100644 (file)
@@ -83,8 +83,6 @@ static int omap2_mbox_startup(struct omap_mbox *mbox)
        l = mbox_read_reg(MAILBOX_REVISION);
        pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
 
-       omap2_mbox_enable_irq(mbox, IRQ_RX);
-
        return 0;
 }
 
index ef2a6924731a69be7e7e92e5afdfe201e0e8cee0..fb5bc6cf3773a531417d6f8da1293c5d351f543e 100644 (file)
  */
 
 #include <linux/kernel.h>
+#include <linux/err.h>
 
 #include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
 #include <plat/mmc.h>
 
 #include "common.h"
+#include "control.h"
+#include "mux.h"
 
 /*
  * MSDI_CON_OFFSET: offset in bytes of the MSDI IP block's CON register
@@ -86,3 +90,72 @@ int omap_msdi_reset(struct omap_hwmod *oh)
 
        return 0;
 }
+
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
+
+static inline void omap242x_mmc_mux(struct omap_mmc_platform_data
+                                   *mmc_controller)
+{
+       if ((mmc_controller->slots[0].switch_pin > 0) && \
+               (mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES))
+               omap_mux_init_gpio(mmc_controller->slots[0].switch_pin,
+                                       OMAP_PIN_INPUT_PULLUP);
+       if ((mmc_controller->slots[0].gpio_wp > 0) && \
+               (mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES))
+               omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp,
+                                       OMAP_PIN_INPUT_PULLUP);
+
+       omap_mux_init_signal("sdmmc_cmd", 0);
+       omap_mux_init_signal("sdmmc_clki", 0);
+       omap_mux_init_signal("sdmmc_clko", 0);
+       omap_mux_init_signal("sdmmc_dat0", 0);
+       omap_mux_init_signal("sdmmc_dat_dir0", 0);
+       omap_mux_init_signal("sdmmc_cmd_dir", 0);
+       if (mmc_controller->slots[0].caps & MMC_CAP_4_BIT_DATA) {
+               omap_mux_init_signal("sdmmc_dat1", 0);
+               omap_mux_init_signal("sdmmc_dat2", 0);
+               omap_mux_init_signal("sdmmc_dat3", 0);
+               omap_mux_init_signal("sdmmc_dat_dir1", 0);
+               omap_mux_init_signal("sdmmc_dat_dir2", 0);
+               omap_mux_init_signal("sdmmc_dat_dir3", 0);
+       }
+
+       /*
+        * Use internal loop-back in MMC/SDIO Module Input Clock
+        * selection
+        */
+       if (mmc_controller->slots[0].internal_clock) {
+               u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
+               v |= (1 << 24);
+               omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
+       }
+}
+
+void __init omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data)
+{
+       struct platform_device *pdev;
+       struct omap_hwmod *oh;
+       int id = 0;
+       char *oh_name = "msdi1";
+       char *dev_name = "mmci-omap";
+
+       if (!mmc_data[0]) {
+               pr_err("%s fails: Incomplete platform data\n", __func__);
+               return;
+       }
+
+       omap242x_mmc_mux(mmc_data[0]);
+
+       oh = omap_hwmod_lookup(oh_name);
+       if (!oh) {
+               pr_err("Could not look up %s\n", oh_name);
+               return;
+       }
+       pdev = omap_device_build(dev_name, id, oh, mmc_data[0],
+                                sizeof(struct omap_mmc_platform_data), NULL, 0, 0);
+       if (IS_ERR(pdev))
+               WARN(1, "Can'd build omap_device for %s:%s.\n",
+                                       dev_name, oh->name);
+}
+
+#endif
index 503ac777a2ba8682b35f0798eccd80f3f8621763..502e3135aad3a7ca4ea41f848ec449447307be0c 100644 (file)
 #include <linux/init.h>
 
        __CPUINIT
+
+/* Physical address needed since MMU not enabled yet on secondary core */
+#define AUX_CORE_BOOT0_PA                      0x48281800
+
+/*
+ * OMAP5 specific entry point for secondary CPU to jump from ROM
+ * code.  This routine also provides a holding flag into which
+ * secondary core is held until we're ready for it to initialise.
+ * The primary core will update this flag using a hardware
++ * register AuxCoreBoot0.
+ */
+ENTRY(omap5_secondary_startup)
+wait:  ldr     r2, =AUX_CORE_BOOT0_PA  @ read from AuxCoreBoot0
+       ldr     r0, [r2]
+       mov     r0, r0, lsr #5
+       mrc     p15, 0, r4, c0, c0, 5
+       and     r4, r4, #0x0f
+       cmp     r0, r4
+       bne     wait
+       b       secondary_startup
+END(omap5_secondary_startup)
 /*
  * OMAP4 specific entry point for secondary CPU to jump from ROM
  * code.  This routine also provides a holding flag into which
index 56c345b8b931b1d00b926152ea1459390884c500..414083b427df7a4abff4ed98c2ae11e3a715f0a4 100644 (file)
 #include <linux/kernel.h>
 #include <linux/errno.h>
 #include <linux/smp.h>
+#include <linux/io.h>
 
 #include <asm/cacheflush.h>
+#include <mach/omap-wakeupgen.h>
 
 #include "common.h"
 
@@ -35,7 +37,8 @@ int platform_cpu_kill(unsigned int cpu)
  */
 void __ref platform_cpu_die(unsigned int cpu)
 {
-       unsigned int this_cpu;
+       unsigned int boot_cpu = 0;
+       void __iomem *base = omap_get_wakeupgen_base();
 
        flush_cache_all();
        dsb();
@@ -43,16 +46,27 @@ void __ref platform_cpu_die(unsigned int cpu)
        /*
         * we're ready for shutdown now, so do it
         */
-       if (omap_modify_auxcoreboot0(0x0, 0x200) != 0x0)
-               pr_err("Secure clear status failed\n");
+       if (omap_secure_apis_support()) {
+               if (omap_modify_auxcoreboot0(0x0, 0x200) != 0x0)
+                       pr_err("Secure clear status failed\n");
+       } else {
+               __raw_writel(0, base + OMAP_AUX_CORE_BOOT_0);
+       }
+
 
        for (;;) {
                /*
                 * Enter into low power state
                 */
                omap4_hotplug_cpu(cpu, PWRDM_POWER_OFF);
-               this_cpu = smp_processor_id();
-               if (omap_read_auxcoreboot0() == this_cpu) {
+
+               if (omap_secure_apis_support())
+                       boot_cpu = omap_read_auxcoreboot0();
+               else
+                       boot_cpu =
+                               __raw_readl(base + OMAP_AUX_CORE_BOOT_0) >> 5;
+
+               if (boot_cpu == smp_processor_id()) {
                        /*
                         * OK, proper wakeup, we're done
                         */
index ac49384d028521deceb8e11355b46fbd4a2ec1b9..1be8bcb52e9307cdacffea26857db68a762927cd 100644 (file)
@@ -73,19 +73,17 @@ static struct iommu_device omap4_devices[] = {
                        .da_end = 0xFFFFF000,
                },
        },
-#if defined(CONFIG_MPU_TESLA_IOMMU)
        {
                .base = OMAP4_MMU2_BASE,
-               .irq = INT_44XX_DSP_MMU,
+               .irq = OMAP44XX_IRQ_TESLA_MMU,
                .pdata = {
                        .name = "tesla",
                        .nr_tlb_entries = 32,
-                       .clk_name = "tesla_ick",
+                       .clk_name = "dsp_fck",
                        .da_start = 0x0,
                        .da_end = 0xFFFFF000,
                },
        },
-#endif
 };
 #define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices)
 static struct platform_device *omap4_iommu_pdev[NR_OMAP4_IOMMU_DEVICES];
index 13670aa84e58707ba0fdd284afbcee10a995b5e7..e35a86bf4e1dcdde5e5ffe850575cb60635ce5c3 100644 (file)
@@ -255,7 +255,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
                return -ENXIO;
        }
 
-       pwrdm_pre_transition();
+       pwrdm_pre_transition(NULL);
 
        /*
         * Check MPUSS next state and save interrupt controller if needed.
@@ -287,7 +287,7 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
        wakeup_cpu = smp_processor_id();
        set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
 
-       pwrdm_post_transition();
+       pwrdm_post_transition(NULL);
 
        return 0;
 }
index deffbf1c9627f8baa0acfa2890954263237fc899..7d118b9bdd5f1205938f05d26d446b7249298da1 100644 (file)
 
 #include <mach/hardware.h>
 #include <mach/omap-secure.h>
+#include <mach/omap-wakeupgen.h>
+#include <asm/cputype.h>
 
 #include "iomap.h"
 #include "common.h"
 #include "clockdomain.h"
 
+#define CPU_MASK               0xff0ffff0
+#define CPU_CORTEX_A9          0x410FC090
+#define CPU_CORTEX_A15         0x410FC0F0
+
+#define OMAP5_CORE_COUNT       0x2
+
 /* SCU base address */
 static void __iomem *scu_base;
 
@@ -73,6 +81,8 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
        static struct clockdomain *cpu1_clkdm;
        static bool booted;
+       void __iomem *base = omap_get_wakeupgen_base();
+
        /*
         * Set synchronisation state between this boot processor
         * and the secondary one
@@ -85,7 +95,11 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
         * the AuxCoreBoot1 register is updated with cpu state
         * A barrier is added to ensure that write buffer is drained
         */
-       omap_modify_auxcoreboot0(0x200, 0xfffffdff);
+       if (omap_secure_apis_support())
+               omap_modify_auxcoreboot0(0x200, 0xfffffdff);
+       else
+               __raw_writel(0x20, base + OMAP_AUX_CORE_BOOT_0);
+
        flush_cache_all();
        smp_wmb();
 
@@ -124,13 +138,19 @@ int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 
 static void __init wakeup_secondary(void)
 {
+       void __iomem *base = omap_get_wakeupgen_base();
        /*
         * Write the address of secondary startup routine into the
         * AuxCoreBoot1 where ROM code will jump and start executing
         * on secondary core once out of WFE
         * A barrier is added to ensure that write buffer is drained
         */
-       omap_auxcoreboot_addr(virt_to_phys(omap_secondary_startup));
+       if (omap_secure_apis_support())
+               omap_auxcoreboot_addr(virt_to_phys(omap_secondary_startup));
+       else
+               __raw_writel(virt_to_phys(omap5_secondary_startup),
+                                               base + OMAP_AUX_CORE_BOOT_1);
+
        smp_wmb();
 
        /*
@@ -147,16 +167,21 @@ static void __init wakeup_secondary(void)
  */
 void __init smp_init_cpus(void)
 {
-       unsigned int i, ncores;
-
-       /*
-        * Currently we can't call ioremap here because
-        * SoC detection won't work until after init_early.
-        */
-       scu_base =  OMAP2_L4_IO_ADDRESS(OMAP44XX_SCU_BASE);
-       BUG_ON(!scu_base);
-
-       ncores = scu_get_core_count(scu_base);
+       unsigned int i = 0, ncores = 1, cpu_id;
+
+       /* Use ARM cpuid check here, as SoC detection will not work so early */
+       cpu_id = read_cpuid(CPUID_ID) & CPU_MASK;
+       if (cpu_id == CPU_CORTEX_A9) {
+               /*
+                * Currently we can't call ioremap here because
+                * SoC detection won't work until after init_early.
+                */
+               scu_base =  OMAP2_L4_IO_ADDRESS(OMAP44XX_SCU_BASE);
+               BUG_ON(!scu_base);
+               ncores = scu_get_core_count(scu_base);
+       } else if (cpu_id == CPU_CORTEX_A15) {
+               ncores = OMAP5_CORE_COUNT;
+       }
 
        /* sanity check */
        if (ncores > nr_cpu_ids) {
@@ -178,6 +203,7 @@ void __init platform_smp_prepare_cpus(unsigned int max_cpus)
         * Initialise the SCU and wake up the secondary core using
         * wakeup_secondary().
         */
-       scu_enable(scu_base);
+       if (scu_base)
+               scu_enable(scu_base);
        wakeup_secondary();
 }
index d811c7790350d9deded0e7ed53636e3a74430219..05fdebfaa195b0e5fc87e33217f24ce1b5c09822 100644 (file)
 #include "omap4-sar-layout.h"
 #include "common.h"
 
-#define NR_REG_BANKS           4
-#define MAX_IRQS               128
+#define MAX_NR_REG_BANKS       5
+#define MAX_IRQS               160
 #define WKG_MASK_ALL           0x00000000
 #define WKG_UNMASK_ALL         0xffffffff
 #define CPU_ENA_OFFSET         0x400
 #define CPU0_ID                        0x0
 #define CPU1_ID                        0x1
+#define OMAP4_NR_BANKS         4
+#define OMAP4_NR_IRQS          128
 
 static void __iomem *wakeupgen_base;
 static void __iomem *sar_base;
 static DEFINE_SPINLOCK(wakeupgen_lock);
 static unsigned int irq_target_cpu[NR_IRQS];
+static unsigned int irq_banks = MAX_NR_REG_BANKS;
+static unsigned int max_irqs = MAX_IRQS;
+static unsigned int omap_secure_apis;
 
 /*
  * Static helper functions.
@@ -146,13 +151,13 @@ static void wakeupgen_unmask(struct irq_data *d)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-static DEFINE_PER_CPU(u32 [NR_REG_BANKS], irqmasks);
+static DEFINE_PER_CPU(u32 [MAX_NR_REG_BANKS], irqmasks);
 
 static void _wakeupgen_save_masks(unsigned int cpu)
 {
        u8 i;
 
-       for (i = 0; i < NR_REG_BANKS; i++)
+       for (i = 0; i < irq_banks; i++)
                per_cpu(irqmasks, cpu)[i] = wakeupgen_readl(i, cpu);
 }
 
@@ -160,7 +165,7 @@ static void _wakeupgen_restore_masks(unsigned int cpu)
 {
        u8 i;
 
-       for (i = 0; i < NR_REG_BANKS; i++)
+       for (i = 0; i < irq_banks; i++)
                wakeupgen_writel(per_cpu(irqmasks, cpu)[i], i, cpu);
 }
 
@@ -168,7 +173,7 @@ static void _wakeupgen_set_all(unsigned int cpu, unsigned int reg)
 {
        u8 i;
 
-       for (i = 0; i < NR_REG_BANKS; i++)
+       for (i = 0; i < irq_banks; i++)
                wakeupgen_writel(reg, i, cpu);
 }
 
@@ -196,25 +201,14 @@ static void wakeupgen_irqmask_all(unsigned int cpu, unsigned int set)
 #endif
 
 #ifdef CONFIG_CPU_PM
-/*
- * Save WakeupGen interrupt context in SAR BANK3. Restore is done by
- * ROM code. WakeupGen IP is integrated along with GIC to manage the
- * interrupt wakeups from CPU low power states. It manages
- * masking/unmasking of Shared peripheral interrupts(SPI). So the
- * interrupt enable/disable control should be in sync and consistent
- * at WakeupGen and GIC so that interrupts are not lost.
- */
-static void irq_save_context(void)
+static inline void omap4_irq_save_context(void)
 {
        u32 i, val;
 
        if (omap_rev() == OMAP4430_REV_ES1_0)
                return;
 
-       if (!sar_base)
-               sar_base = omap4_get_sar_ram_base();
-
-       for (i = 0; i < NR_REG_BANKS; i++) {
+       for (i = 0; i < irq_banks; i++) {
                /* Save the CPUx interrupt mask for IRQ 0 to 127 */
                val = wakeupgen_readl(i, 0);
                sar_writel(val, WAKEUPGENENB_OFFSET_CPU0, i);
@@ -254,6 +248,53 @@ static void irq_save_context(void)
        val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
        val |= SAR_BACKUP_STATUS_WAKEUPGEN;
        __raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET);
+
+}
+
+static inline void omap5_irq_save_context(void)
+{
+       u32 i, val;
+
+       for (i = 0; i < irq_banks; i++) {
+               /* Save the CPUx interrupt mask for IRQ 0 to 159 */
+               val = wakeupgen_readl(i, 0);
+               sar_writel(val, OMAP5_WAKEUPGENENB_OFFSET_CPU0, i);
+               val = wakeupgen_readl(i, 1);
+               sar_writel(val, OMAP5_WAKEUPGENENB_OFFSET_CPU1, i);
+               sar_writel(0x0, OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU0, i);
+               sar_writel(0x0, OMAP5_WAKEUPGENENB_SECURE_OFFSET_CPU1, i);
+       }
+
+       /* Save AuxBoot* registers */
+       val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
+       __raw_writel(val, sar_base + OMAP5_AUXCOREBOOT0_OFFSET);
+       val = __raw_readl(wakeupgen_base + OMAP_AUX_CORE_BOOT_0);
+       __raw_writel(val, sar_base + OMAP5_AUXCOREBOOT1_OFFSET);
+
+       /* Set the Backup Bit Mask status */
+       val = __raw_readl(sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET);
+       val |= SAR_BACKUP_STATUS_WAKEUPGEN;
+       __raw_writel(val, sar_base + OMAP5_SAR_BACKUP_STATUS_OFFSET);
+
+}
+
+/*
+ * Save WakeupGen interrupt context in SAR BANK3. Restore is done by
+ * ROM code. WakeupGen IP is integrated along with GIC to manage the
+ * interrupt wakeups from CPU low power states. It manages
+ * masking/unmasking of Shared peripheral interrupts(SPI). So the
+ * interrupt enable/disable control should be in sync and consistent
+ * at WakeupGen and GIC so that interrupts are not lost.
+ */
+static void irq_save_context(void)
+{
+       if (!sar_base)
+               sar_base = omap4_get_sar_ram_base();
+
+       if (soc_is_omap54xx())
+               omap5_irq_save_context();
+       else
+               omap4_irq_save_context();
 }
 
 /*
@@ -262,9 +303,14 @@ static void irq_save_context(void)
 static void irq_sar_clear(void)
 {
        u32 val;
-       val = __raw_readl(sar_base + SAR_BACKUP_STATUS_OFFSET);
+       u32 offset = SAR_BACKUP_STATUS_OFFSET;
+
+       if (soc_is_omap54xx())
+               offset = OMAP5_SAR_BACKUP_STATUS_OFFSET;
+
+       val = __raw_readl(sar_base + offset);
        val &= ~SAR_BACKUP_STATUS_WAKEUPGEN;
-       __raw_writel(val, sar_base + SAR_BACKUP_STATUS_OFFSET);
+       __raw_writel(val, sar_base + offset);
 }
 
 /*
@@ -336,13 +382,25 @@ static struct notifier_block irq_notifier_block = {
 
 static void __init irq_pm_init(void)
 {
-       cpu_pm_register_notifier(&irq_notifier_block);
+       /* FIXME: Remove this when MPU OSWR support is added */
+       if (!soc_is_omap54xx())
+               cpu_pm_register_notifier(&irq_notifier_block);
 }
 #else
 static void __init irq_pm_init(void)
 {}
 #endif
 
+void __iomem *omap_get_wakeupgen_base(void)
+{
+       return wakeupgen_base;
+}
+
+int omap_secure_apis_support(void)
+{
+       return omap_secure_apis;
+}
+
 /*
  * Initialise the wakeupgen module.
  */
@@ -358,12 +416,18 @@ int __init omap_wakeupgen_init(void)
        }
 
        /* Static mapping, never released */
-       wakeupgen_base = ioremap(OMAP44XX_WKUPGEN_BASE, SZ_4K);
+       wakeupgen_base = ioremap(OMAP_WKUPGEN_BASE, SZ_4K);
        if (WARN_ON(!wakeupgen_base))
                return -ENOMEM;
 
+       if (cpu_is_omap44xx()) {
+               irq_banks = OMAP4_NR_BANKS;
+               max_irqs = OMAP4_NR_IRQS;
+               omap_secure_apis = 1;
+       }
+
        /* Clear all IRQ bitmasks at wakeupGen level */
-       for (i = 0; i < NR_REG_BANKS; i++) {
+       for (i = 0; i < irq_banks; i++) {
                wakeupgen_writel(0, i, CPU0_ID);
                wakeupgen_writel(0, i, CPU1_ID);
        }
@@ -382,7 +446,7 @@ int __init omap_wakeupgen_init(void)
         */
 
        /* Associate all the IRQs to boot CPU like GIC init does. */
-       for (i = 0; i < NR_IRQS; i++)
+       for (i = 0; i < max_irqs; i++)
                irq_target_cpu[i] = boot_cpu;
 
        irq_hotplug_init();
index a8161e5f3204b6f41cbf94963af91fd6fc931a2d..c29dee998a798e08cb8ffbef85a556c835fc6174 100644 (file)
@@ -21,6 +21,8 @@
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
 
 #include <plat/irqs.h>
 #include <plat/sram.h>
@@ -210,6 +212,18 @@ static int __init omap4_sar_ram_init(void)
 }
 early_initcall(omap4_sar_ram_init);
 
+static struct of_device_id irq_match[] __initdata = {
+       { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+       { .compatible = "arm,cortex-a15-gic", .data = gic_of_init, },
+       { }
+};
+
+void __init omap_gic_of_init(void)
+{
+       omap_wakeupgen_init();
+       of_irq_init(irq_match);
+}
+
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 {
index fe5b545ad4439c828bc407b74c782b002965fe4e..e170fe803b046b2e0ff624e1b502960e902ac2a7 100644 (file)
@@ -12,7 +12,7 @@
 #define OMAP_ARCH_OMAP4_SAR_LAYOUT_H
 
 /*
- * SAR BANK offsets from base address OMAP44XX_SAR_RAM_BASE
+ * SAR BANK offsets from base address OMAP44XX/54XX_SAR_RAM_BASE
  */
 #define SAR_BANK1_OFFSET               0x0000
 #define SAR_BANK2_OFFSET               0x1000
 #define PTMSYNCREQ_EN_OFFSET                   (SAR_BANK3_OFFSET + 0x6d0)
 #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_SAR_BACKUP_STATUS_OFFSET         (SAR_BANK3_OFFSET + 0x800)
+
 #endif
index 2d710f50fca2fafd9cac99d2f515220c41de410f..6ca8e519968d0c4e82e94fb384ab84da90a892b1 100644 (file)
 #include "prm44xx.h"
 #include "prminst44xx.h"
 #include "mux.h"
+#include "pm.h"
 
 /* Maximum microseconds to wait for OMAP module to softreset */
 #define MAX_MODULE_SOFTRESET_WAIT      10000
  */
 #define LINKS_PER_OCP_IF               2
 
+/**
+ * struct omap_hwmod_soc_ops - fn ptrs for some SoC-specific operations
+ * @enable_module: function to enable a module (via MODULEMODE)
+ * @disable_module: function to disable a module (via MODULEMODE)
+ *
+ * XXX Eventually this functionality will be hidden inside the PRM/CM
+ * device drivers.  Until then, this should avoid huge blocks of cpu_is_*()
+ * conditionals in this code.
+ */
+struct omap_hwmod_soc_ops {
+       void (*enable_module)(struct omap_hwmod *oh);
+       int (*disable_module)(struct omap_hwmod *oh);
+       int (*wait_target_ready)(struct omap_hwmod *oh);
+       int (*assert_hardreset)(struct omap_hwmod *oh,
+                               struct omap_hwmod_rst_info *ohri);
+       int (*deassert_hardreset)(struct omap_hwmod *oh,
+                                 struct omap_hwmod_rst_info *ohri);
+       int (*is_hardreset_asserted)(struct omap_hwmod *oh,
+                                    struct omap_hwmod_rst_info *ohri);
+       int (*init_clkdm)(struct omap_hwmod *oh);
+};
+
+/* soc_ops: adapts the omap_hwmod code to the currently-booted SoC */
+static struct omap_hwmod_soc_ops soc_ops;
+
 /* omap_hwmod_list contains all registered struct omap_hwmods */
 static LIST_HEAD(omap_hwmod_list);
 
 /* mpu_oh: used to add/remove MPU initiator from sleepdep list */
 static struct omap_hwmod *mpu_oh;
 
+/* io_chain_lock: used to serialize reconfigurations of the I/O chain */
+static DEFINE_SPINLOCK(io_chain_lock);
+
 /*
  * linkspace: ptr to a buffer that struct omap_hwmod_link records are
  * allocated from - used to reduce the number of small memory
@@ -186,6 +215,9 @@ static struct omap_hwmod_link *linkspace;
  */
 static unsigned short free_ls, max_ls, ls_supp;
 
+/* inited: set to true once the hwmod code is initialized */
+static bool inited;
+
 /* Private functions */
 
 /**
@@ -387,6 +419,49 @@ static int _set_softreset(struct omap_hwmod *oh, u32 *v)
        return 0;
 }
 
+/**
+ * _set_dmadisable: set OCP_SYSCONFIG.DMADISABLE bit in @v
+ * @oh: struct omap_hwmod *
+ *
+ * The DMADISABLE bit is a semi-automatic bit present in sysconfig register
+ * of some modules. When the DMA must perform read/write accesses, the
+ * DMADISABLE bit is cleared by the hardware. But when the DMA must stop
+ * for power management, software must set the DMADISABLE bit back to 1.
+ *
+ * Set the DMADISABLE bit in @v for hwmod @oh.  Returns -EINVAL upon
+ * error or 0 upon success.
+ */
+static int _set_dmadisable(struct omap_hwmod *oh)
+{
+       u32 v;
+       u32 dmadisable_mask;
+
+       if (!oh->class->sysc ||
+           !(oh->class->sysc->sysc_flags & SYSC_HAS_DMADISABLE))
+               return -EINVAL;
+
+       if (!oh->class->sysc->sysc_fields) {
+               WARN(1, "omap_hwmod: %s: offset struct for sysconfig not provided in class\n", oh->name);
+               return -EINVAL;
+       }
+
+       /* clocks must be on for this operation */
+       if (oh->_state != _HWMOD_STATE_ENABLED) {
+               pr_warn("omap_hwmod: %s: dma can be disabled only from enabled state\n", oh->name);
+               return -EINVAL;
+       }
+
+       pr_debug("omap_hwmod: %s: setting DMADISABLE\n", oh->name);
+
+       v = oh->_sysc_cache;
+       dmadisable_mask =
+               (0x1 << oh->class->sysc->sysc_fields->dmadisable_shift);
+       v |= dmadisable_mask;
+       _write_sysconfig(v, oh);
+
+       return 0;
+}
+
 /**
  * _set_module_autoidle: set the OCP_SYSCONFIG AUTOIDLE field in @v
  * @oh: struct omap_hwmod *
@@ -771,23 +846,19 @@ static void _disable_optional_clocks(struct omap_hwmod *oh)
 }
 
 /**
- * _enable_module - enable CLKCTRL modulemode on OMAP4
+ * _omap4_enable_module - enable CLKCTRL modulemode on OMAP4
  * @oh: struct omap_hwmod *
  *
  * Enables the PRCM module mode related to the hwmod @oh.
  * No return value.
  */
-static void _enable_module(struct omap_hwmod *oh)
+static void _omap4_enable_module(struct omap_hwmod *oh)
 {
-       /* The module mode does not exist prior OMAP4 */
-       if (cpu_is_omap24xx() || cpu_is_omap34xx())
-               return;
-
        if (!oh->clkdm || !oh->prcm.omap4.modulemode)
                return;
 
-       pr_debug("omap_hwmod: %s: _enable_module: %d\n",
-                oh->name, oh->prcm.omap4.modulemode);
+       pr_debug("omap_hwmod: %s: %s: %d\n",
+                oh->name, __func__, oh->prcm.omap4.modulemode);
 
        omap4_cminst_module_enable(oh->prcm.omap4.modulemode,
                                   oh->clkdm->prcm_partition,
@@ -807,10 +878,7 @@ static void _enable_module(struct omap_hwmod *oh)
  */
 static int _omap4_wait_target_disable(struct omap_hwmod *oh)
 {
-       if (!cpu_is_omap44xx())
-               return 0;
-
-       if (!oh)
+       if (!oh || !oh->clkdm)
                return -EINVAL;
 
        if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
@@ -1301,24 +1369,20 @@ static struct omap_hwmod *_lookup(const char *name)
 
        return oh;
 }
+
 /**
  * _init_clkdm - look up a clockdomain name, store pointer in omap_hwmod
  * @oh: struct omap_hwmod *
  *
  * Convert a clockdomain name stored in a struct omap_hwmod into a
  * clockdomain pointer, and save it into the struct omap_hwmod.
- * return -EINVAL if clkdm_name does not exist or if the lookup failed.
+ * Return -EINVAL if the clkdm_name lookup failed.
  */
 static int _init_clkdm(struct omap_hwmod *oh)
 {
-       if (cpu_is_omap24xx() || cpu_is_omap34xx())
+       if (!oh->clkdm_name)
                return 0;
 
-       if (!oh->clkdm_name) {
-               pr_warning("omap_hwmod: %s: no clkdm_name\n", oh->name);
-               return -EINVAL;
-       }
-
        oh->clkdm = clkdm_lookup(oh->clkdm_name);
        if (!oh->clkdm) {
                pr_warning("omap_hwmod: %s: could not associate to clkdm %s\n",
@@ -1354,7 +1418,8 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
        ret |= _init_main_clk(oh);
        ret |= _init_interface_clks(oh);
        ret |= _init_opt_clks(oh);
-       ret |= _init_clkdm(oh);
+       if (soc_ops.init_clkdm)
+               ret |= soc_ops.init_clkdm(oh);
 
        if (!ret)
                oh->_state = _HWMOD_STATE_CLKS_INITED;
@@ -1364,53 +1429,6 @@ static int _init_clocks(struct omap_hwmod *oh, void *data)
        return ret;
 }
 
-/**
- * _wait_target_ready - wait for a module to leave slave idle
- * @oh: struct omap_hwmod *
- *
- * Wait for a module @oh to leave slave idle.  Returns 0 if the module
- * does not have an IDLEST bit or if the module successfully leaves
- * slave idle; otherwise, pass along the return value of the
- * appropriate *_cm*_wait_module_ready() function.
- */
-static int _wait_target_ready(struct omap_hwmod *oh)
-{
-       struct omap_hwmod_ocp_if *os;
-       int ret;
-
-       if (!oh)
-               return -EINVAL;
-
-       if (oh->flags & HWMOD_NO_IDLEST)
-               return 0;
-
-       os = _find_mpu_rt_port(oh);
-       if (!os)
-               return 0;
-
-       /* XXX check module SIDLEMODE */
-
-       /* XXX check clock enable states */
-
-       if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-               ret = omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs,
-                                                oh->prcm.omap2.idlest_reg_id,
-                                                oh->prcm.omap2.idlest_idle_bit);
-       } else if (cpu_is_omap44xx()) {
-               if (!oh->clkdm)
-                       return -EINVAL;
-
-               ret = omap4_cminst_wait_module_ready(oh->clkdm->prcm_partition,
-                                                    oh->clkdm->cm_inst,
-                                                    oh->clkdm->clkdm_offs,
-                                                    oh->prcm.omap4.clkctrl_offs);
-       } else {
-               BUG();
-       };
-
-       return ret;
-}
-
 /**
  * _lookup_hardreset - fill register bit info for this hwmod/reset line
  * @oh: struct omap_hwmod *
@@ -1447,32 +1465,31 @@ static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name,
  * @oh: struct omap_hwmod *
  * @name: name of the reset line to lookup and assert
  *
- * Some IP like dsp, ipu or iva contain processor that require
- * an HW reset line to be assert / deassert in order to enable fully
- * the IP.
+ * Some IP like dsp, ipu or iva contain processor that require an HW
+ * reset line to be assert / deassert in order to enable fully the IP.
+ * Returns -EINVAL if @oh is null, -ENOSYS if we have no way of
+ * asserting the hardreset line on the currently-booted SoC, or passes
+ * along the return value from _lookup_hardreset() or the SoC's
+ * assert_hardreset code.
  */
 static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
 {
        struct omap_hwmod_rst_info ohri;
-       u8 ret;
+       u8 ret = -EINVAL;
 
        if (!oh)
                return -EINVAL;
 
+       if (!soc_ops.assert_hardreset)
+               return -ENOSYS;
+
        ret = _lookup_hardreset(oh, name, &ohri);
        if (IS_ERR_VALUE(ret))
                return ret;
 
-       if (cpu_is_omap24xx() || cpu_is_omap34xx())
-               return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
-                                                 ohri.rst_shift);
-       else if (cpu_is_omap44xx())
-               return omap4_prminst_assert_hardreset(ohri.rst_shift,
-                                 oh->clkdm->pwrdm.ptr->prcm_partition,
-                                 oh->clkdm->pwrdm.ptr->prcm_offs,
-                                 oh->prcm.omap4.rstctrl_offs);
-       else
-               return -EINVAL;
+       ret = soc_ops.assert_hardreset(oh, &ohri);
+
+       return ret;
 }
 
 /**
@@ -1481,38 +1498,29 @@ static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
  * @oh: struct omap_hwmod *
  * @name: name of the reset line to look up and deassert
  *
- * Some IP like dsp, ipu or iva contain processor that require
- * an HW reset line to be assert / deassert in order to enable fully
- * the IP.
+ * Some IP like dsp, ipu or iva contain processor that require an HW
+ * reset line to be assert / deassert in order to enable fully the IP.
+ * Returns -EINVAL if @oh is null, -ENOSYS if we have no way of
+ * deasserting the hardreset line on the currently-booted SoC, or passes
+ * along the return value from _lookup_hardreset() or the SoC's
+ * deassert_hardreset code.
  */
 static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
 {
        struct omap_hwmod_rst_info ohri;
-       int ret;
+       int ret = -EINVAL;
 
        if (!oh)
                return -EINVAL;
 
+       if (!soc_ops.deassert_hardreset)
+               return -ENOSYS;
+
        ret = _lookup_hardreset(oh, name, &ohri);
        if (IS_ERR_VALUE(ret))
                return ret;
 
-       if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-               ret = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs,
-                                                  ohri.rst_shift,
-                                                  ohri.st_shift);
-       } else if (cpu_is_omap44xx()) {
-               if (ohri.st_shift)
-                       pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
-                              oh->name, name);
-               ret = omap4_prminst_deassert_hardreset(ohri.rst_shift,
-                                 oh->clkdm->pwrdm.ptr->prcm_partition,
-                                 oh->clkdm->pwrdm.ptr->prcm_offs,
-                                 oh->prcm.omap4.rstctrl_offs);
-       } else {
-               return -EINVAL;
-       }
-
+       ret = soc_ops.deassert_hardreset(oh, &ohri);
        if (ret == -EBUSY)
                pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name);
 
@@ -1525,31 +1533,28 @@ static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
  * @oh: struct omap_hwmod *
  * @name: name of the reset line to look up and read
  *
- * Return the state of the reset line.
+ * Return the state of the reset line.  Returns -EINVAL if @oh is
+ * null, -ENOSYS if we have no way of reading the hardreset line
+ * status on the currently-booted SoC, or passes along the return
+ * value from _lookup_hardreset() or the SoC's is_hardreset_asserted
+ * code.
  */
 static int _read_hardreset(struct omap_hwmod *oh, const char *name)
 {
        struct omap_hwmod_rst_info ohri;
-       u8 ret;
+       u8 ret = -EINVAL;
 
        if (!oh)
                return -EINVAL;
 
+       if (!soc_ops.is_hardreset_asserted)
+               return -ENOSYS;
+
        ret = _lookup_hardreset(oh, name, &ohri);
        if (IS_ERR_VALUE(ret))
                return ret;
 
-       if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-               return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
-                                                      ohri.st_shift);
-       } else if (cpu_is_omap44xx()) {
-               return omap4_prminst_is_hardreset_asserted(ohri.rst_shift,
-                                 oh->clkdm->pwrdm.ptr->prcm_partition,
-                                 oh->clkdm->pwrdm.ptr->prcm_offs,
-                                 oh->prcm.omap4.rstctrl_offs);
-       } else {
-               return -EINVAL;
-       }
+       return soc_ops.is_hardreset_asserted(oh, &ohri);
 }
 
 /**
@@ -1587,10 +1592,6 @@ static int _omap4_disable_module(struct omap_hwmod *oh)
 {
        int v;
 
-       /* The module mode does not exist prior OMAP4 */
-       if (!cpu_is_omap44xx())
-               return -EINVAL;
-
        if (!oh->clkdm || !oh->prcm.omap4.modulemode)
                return -EINVAL;
 
@@ -1714,11 +1715,17 @@ dis_opt_clks:
  * therefore have no OCP header registers to access.  Others (like the
  * IVA) have idiosyncratic reset sequences.  So for these relatively
  * rare cases, custom reset code can be supplied in the struct
- * omap_hwmod_class .reset function pointer.  Passes along the return
- * value from either _ocp_softreset() or the custom reset function -
- * these must return -EINVAL if the hwmod cannot be reset this way or
- * if the hwmod is in the wrong state, -ETIMEDOUT if the module did
- * not reset in time, or 0 upon success.
+ * omap_hwmod_class .reset function pointer.
+ *
+ * _set_dmadisable() is called to set the DMADISABLE bit so that it
+ * does not prevent idling of the system. This is necessary for cases
+ * where ROMCODE/BOOTLOADER uses dma and transfers control to the
+ * kernel without disabling dma.
+ *
+ * Passes along the return value from either _ocp_softreset() or the
+ * custom reset function - these must return -EINVAL if the hwmod
+ * cannot be reset this way or if the hwmod is in the wrong state,
+ * -ETIMEDOUT if the module did not reset in time, or 0 upon success.
  */
 static int _reset(struct omap_hwmod *oh)
 {
@@ -1740,6 +1747,8 @@ static int _reset(struct omap_hwmod *oh)
                }
        }
 
+       _set_dmadisable(oh);
+
        /*
         * OCP_SYSCONFIG bits need to be reprogrammed after a
         * softreset.  The _enable() function should be split to avoid
@@ -1753,6 +1762,32 @@ static int _reset(struct omap_hwmod *oh)
        return r;
 }
 
+/**
+ * _reconfigure_io_chain - clear any I/O chain wakeups and reconfigure chain
+ *
+ * Call the appropriate PRM function to clear any logged I/O chain
+ * wakeups and to reconfigure the chain.  This apparently needs to be
+ * done upon every mux change.  Since hwmods can be concurrently
+ * enabled and idled, hold a spinlock around the I/O chain
+ * reconfiguration sequence.  No return value.
+ *
+ * XXX When the PRM code is moved to drivers, this function can be removed,
+ * as the PRM infrastructure should abstract this.
+ */
+static void _reconfigure_io_chain(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&io_chain_lock, flags);
+
+       if (cpu_is_omap34xx() && omap3_has_io_chain_ctrl())
+               omap3xxx_prm_reconfigure_io_chain();
+       else if (cpu_is_omap44xx())
+               omap44xx_prm_reconfigure_io_chain();
+
+       spin_unlock_irqrestore(&io_chain_lock, flags);
+}
+
 /**
  * _enable - enable an omap_hwmod
  * @oh: struct omap_hwmod *
@@ -1809,8 +1844,10 @@ static int _enable(struct omap_hwmod *oh)
        /* Mux pins for device runtime if populated */
        if (oh->mux && (!oh->mux->enabled ||
                        ((oh->_state == _HWMOD_STATE_IDLE) &&
-                        oh->mux->pads_dynamic)))
+                        oh->mux->pads_dynamic))) {
                omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
+               _reconfigure_io_chain();
+       }
 
        _add_initiator_dep(oh, mpu_oh);
 
@@ -1830,9 +1867,11 @@ static int _enable(struct omap_hwmod *oh)
        }
 
        _enable_clocks(oh);
-       _enable_module(oh);
+       if (soc_ops.enable_module)
+               soc_ops.enable_module(oh);
 
-       r = _wait_target_ready(oh);
+       r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready(oh) :
+               -EINVAL;
        if (!r) {
                /*
                 * Set the clockdomain to HW_AUTO only if the target is ready,
@@ -1886,7 +1925,8 @@ static int _idle(struct omap_hwmod *oh)
                _idle_sysc(oh);
        _del_initiator_dep(oh, mpu_oh);
 
-       _omap4_disable_module(oh);
+       if (soc_ops.disable_module)
+               soc_ops.disable_module(oh);
 
        /*
         * The module must be in idle mode before disabling any parents
@@ -1899,8 +1939,10 @@ static int _idle(struct omap_hwmod *oh)
                clkdm_hwmod_disable(oh->clkdm, oh);
 
        /* Mux pins for device idle if populated */
-       if (oh->mux && oh->mux->pads_dynamic)
+       if (oh->mux && oh->mux->pads_dynamic) {
                omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
+               _reconfigure_io_chain();
+       }
 
        oh->_state = _HWMOD_STATE_IDLE;
 
@@ -1991,7 +2033,8 @@ static int _shutdown(struct omap_hwmod *oh)
        if (oh->_state == _HWMOD_STATE_ENABLED) {
                _del_initiator_dep(oh, mpu_oh);
                /* XXX what about the other system initiators here? dma, dsp */
-               _omap4_disable_module(oh);
+               if (soc_ops.disable_module)
+                       soc_ops.disable_module(oh);
                _disable_clocks(oh);
                if (oh->clkdm)
                        clkdm_hwmod_disable(oh->clkdm, oh);
@@ -2447,6 +2490,194 @@ static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois)
        return 0;
 }
 
+/* Static functions intended only for use in soc_ops field function pointers */
+
+/**
+ * _omap2_wait_target_ready - wait for a module to leave slave idle
+ * @oh: struct omap_hwmod *
+ *
+ * Wait for a module @oh to leave slave idle.  Returns 0 if the module
+ * does not have an IDLEST bit or if the module successfully leaves
+ * slave idle; otherwise, pass along the return value of the
+ * appropriate *_cm*_wait_module_ready() function.
+ */
+static int _omap2_wait_target_ready(struct omap_hwmod *oh)
+{
+       if (!oh)
+               return -EINVAL;
+
+       if (oh->flags & HWMOD_NO_IDLEST)
+               return 0;
+
+       if (!_find_mpu_rt_port(oh))
+               return 0;
+
+       /* XXX check module SIDLEMODE, hardreset status, enabled clocks */
+
+       return omap2_cm_wait_module_ready(oh->prcm.omap2.module_offs,
+                                         oh->prcm.omap2.idlest_reg_id,
+                                         oh->prcm.omap2.idlest_idle_bit);
+}
+
+/**
+ * _omap4_wait_target_ready - wait for a module to leave slave idle
+ * @oh: struct omap_hwmod *
+ *
+ * Wait for a module @oh to leave slave idle.  Returns 0 if the module
+ * does not have an IDLEST bit or if the module successfully leaves
+ * slave idle; otherwise, pass along the return value of the
+ * appropriate *_cm*_wait_module_ready() function.
+ */
+static int _omap4_wait_target_ready(struct omap_hwmod *oh)
+{
+       if (!oh || !oh->clkdm)
+               return -EINVAL;
+
+       if (oh->flags & HWMOD_NO_IDLEST)
+               return 0;
+
+       if (!_find_mpu_rt_port(oh))
+               return 0;
+
+       /* XXX check module SIDLEMODE, hardreset status */
+
+       return omap4_cminst_wait_module_ready(oh->clkdm->prcm_partition,
+                                             oh->clkdm->cm_inst,
+                                             oh->clkdm->clkdm_offs,
+                                             oh->prcm.omap4.clkctrl_offs);
+}
+
+/**
+ * _omap2_assert_hardreset - call OMAP2 PRM hardreset fn with hwmod args
+ * @oh: struct omap_hwmod * to assert hardreset
+ * @ohri: hardreset line data
+ *
+ * Call omap2_prm_assert_hardreset() with parameters extracted from
+ * the hwmod @oh and the hardreset line data @ohri.  Only intended for
+ * use as an soc_ops function pointer.  Passes along the return value
+ * from omap2_prm_assert_hardreset().  XXX This function is scheduled
+ * for removal when the PRM code is moved into drivers/.
+ */
+static int _omap2_assert_hardreset(struct omap_hwmod *oh,
+                                  struct omap_hwmod_rst_info *ohri)
+{
+       return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
+                                         ohri->rst_shift);
+}
+
+/**
+ * _omap2_deassert_hardreset - call OMAP2 PRM hardreset fn with hwmod args
+ * @oh: struct omap_hwmod * to deassert hardreset
+ * @ohri: hardreset line data
+ *
+ * Call omap2_prm_deassert_hardreset() with parameters extracted from
+ * the hwmod @oh and the hardreset line data @ohri.  Only intended for
+ * use as an soc_ops function pointer.  Passes along the return value
+ * from omap2_prm_deassert_hardreset().  XXX This function is
+ * scheduled for removal when the PRM code is moved into drivers/.
+ */
+static int _omap2_deassert_hardreset(struct omap_hwmod *oh,
+                                    struct omap_hwmod_rst_info *ohri)
+{
+       return omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs,
+                                           ohri->rst_shift,
+                                           ohri->st_shift);
+}
+
+/**
+ * _omap2_is_hardreset_asserted - call OMAP2 PRM hardreset fn with hwmod args
+ * @oh: struct omap_hwmod * to test hardreset
+ * @ohri: hardreset line data
+ *
+ * Call omap2_prm_is_hardreset_asserted() with parameters extracted
+ * from the hwmod @oh and the hardreset line data @ohri.  Only
+ * intended for use as an soc_ops function pointer.  Passes along the
+ * return value from omap2_prm_is_hardreset_asserted().  XXX This
+ * function is scheduled for removal when the PRM code is moved into
+ * drivers/.
+ */
+static int _omap2_is_hardreset_asserted(struct omap_hwmod *oh,
+                                       struct omap_hwmod_rst_info *ohri)
+{
+       return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
+                                              ohri->st_shift);
+}
+
+/**
+ * _omap4_assert_hardreset - call OMAP4 PRM hardreset fn with hwmod args
+ * @oh: struct omap_hwmod * to assert hardreset
+ * @ohri: hardreset line data
+ *
+ * Call omap4_prminst_assert_hardreset() with parameters extracted
+ * from the hwmod @oh and the hardreset line data @ohri.  Only
+ * intended for use as an soc_ops function pointer.  Passes along the
+ * return value from omap4_prminst_assert_hardreset().  XXX This
+ * function is scheduled for removal when the PRM code is moved into
+ * drivers/.
+ */
+static int _omap4_assert_hardreset(struct omap_hwmod *oh,
+                                  struct omap_hwmod_rst_info *ohri)
+{
+       if (!oh->clkdm)
+               return -EINVAL;
+
+       return omap4_prminst_assert_hardreset(ohri->rst_shift,
+                               oh->clkdm->pwrdm.ptr->prcm_partition,
+                               oh->clkdm->pwrdm.ptr->prcm_offs,
+                               oh->prcm.omap4.rstctrl_offs);
+}
+
+/**
+ * _omap4_deassert_hardreset - call OMAP4 PRM hardreset fn with hwmod args
+ * @oh: struct omap_hwmod * to deassert hardreset
+ * @ohri: hardreset line data
+ *
+ * Call omap4_prminst_deassert_hardreset() with parameters extracted
+ * from the hwmod @oh and the hardreset line data @ohri.  Only
+ * intended for use as an soc_ops function pointer.  Passes along the
+ * return value from omap4_prminst_deassert_hardreset().  XXX This
+ * function is scheduled for removal when the PRM code is moved into
+ * drivers/.
+ */
+static int _omap4_deassert_hardreset(struct omap_hwmod *oh,
+                                    struct omap_hwmod_rst_info *ohri)
+{
+       if (!oh->clkdm)
+               return -EINVAL;
+
+       if (ohri->st_shift)
+               pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
+                      oh->name, ohri->name);
+       return omap4_prminst_deassert_hardreset(ohri->rst_shift,
+                               oh->clkdm->pwrdm.ptr->prcm_partition,
+                               oh->clkdm->pwrdm.ptr->prcm_offs,
+                               oh->prcm.omap4.rstctrl_offs);
+}
+
+/**
+ * _omap4_is_hardreset_asserted - call OMAP4 PRM hardreset fn with hwmod args
+ * @oh: struct omap_hwmod * to test hardreset
+ * @ohri: hardreset line data
+ *
+ * Call omap4_prminst_is_hardreset_asserted() with parameters
+ * extracted from the hwmod @oh and the hardreset line data @ohri.
+ * Only intended for use as an soc_ops function pointer.  Passes along
+ * the return value from omap4_prminst_is_hardreset_asserted().  XXX
+ * This function is scheduled for removal when the PRM code is moved
+ * into drivers/.
+ */
+static int _omap4_is_hardreset_asserted(struct omap_hwmod *oh,
+                                       struct omap_hwmod_rst_info *ohri)
+{
+       if (!oh->clkdm)
+               return -EINVAL;
+
+       return omap4_prminst_is_hardreset_asserted(ohri->rst_shift,
+                               oh->clkdm->pwrdm.ptr->prcm_partition,
+                               oh->clkdm->pwrdm.ptr->prcm_offs,
+                               oh->prcm.omap4.rstctrl_offs);
+}
+
 /* Public functions */
 
 u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs)
@@ -2579,12 +2810,18 @@ int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
  *
  * Intended to be called early in boot before the clock framework is
  * initialized.  If @ois is not null, will register all omap_hwmods
- * listed in @ois that are valid for this chip.  Returns 0.
+ * listed in @ois that are valid for this chip.  Returns -EINVAL if
+ * omap_hwmod_init() hasn't been called before calling this function,
+ * -ENOMEM if the link memory area can't be allocated, or 0 upon
+ * success.
  */
 int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois)
 {
        int r, i;
 
+       if (!inited)
+               return -EINVAL;
+
        if (!ois)
                return 0;
 
@@ -3417,3 +3654,47 @@ int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx)
 
        return 0;
 }
+
+/**
+ * omap_hwmod_init - initialize the hwmod code
+ *
+ * Sets up some function pointers needed by the hwmod code to operate on the
+ * currently-booted SoC.  Intended to be called once during kernel init
+ * before any hwmods are registered.  No return value.
+ */
+void __init omap_hwmod_init(void)
+{
+       if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+               soc_ops.wait_target_ready = _omap2_wait_target_ready;
+               soc_ops.assert_hardreset = _omap2_assert_hardreset;
+               soc_ops.deassert_hardreset = _omap2_deassert_hardreset;
+               soc_ops.is_hardreset_asserted = _omap2_is_hardreset_asserted;
+       } else if (cpu_is_omap44xx() || soc_is_omap54xx()) {
+               soc_ops.enable_module = _omap4_enable_module;
+               soc_ops.disable_module = _omap4_disable_module;
+               soc_ops.wait_target_ready = _omap4_wait_target_ready;
+               soc_ops.assert_hardreset = _omap4_assert_hardreset;
+               soc_ops.deassert_hardreset = _omap4_deassert_hardreset;
+               soc_ops.is_hardreset_asserted = _omap4_is_hardreset_asserted;
+               soc_ops.init_clkdm = _init_clkdm;
+       } else {
+               WARN(1, "omap_hwmod: unknown SoC type\n");
+       }
+
+       inited = true;
+}
+
+/**
+ * omap_hwmod_get_main_clk - get pointer to main clock name
+ * @oh: struct omap_hwmod *
+ *
+ * Returns the main clock name assocated with @oh upon success,
+ * or NULL if @oh is NULL.
+ */
+const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh)
+{
+       if (!oh)
+               return NULL;
+
+       return oh->main_clk;
+}
index a7640d1b215e7f94f5dc8fea09738930d75a0208..50cfab61b0e21bb6fc3ff00e769bd38570c3761b 100644 (file)
@@ -192,6 +192,11 @@ static struct omap_hwmod_class omap2420_mcbsp_hwmod_class = {
        .name = "mcbsp",
 };
 
+static struct omap_hwmod_opt_clk mcbsp_opt_clks[] = {
+       { .role = "pad_fck", .clk = "mcbsp_clks" },
+       { .role = "prcm_fck", .clk = "func_96m_ck" },
+};
+
 /* mcbsp1 */
 static struct omap_hwmod_irq_info omap2420_mcbsp1_irqs[] = {
        { .name = "tx", .irq = 59 },
@@ -214,6 +219,8 @@ static struct omap_hwmod omap2420_mcbsp1_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_MCBSP1_SHIFT,
                },
        },
+       .opt_clks       = mcbsp_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp_opt_clks),
 };
 
 /* mcbsp2 */
@@ -238,6 +245,8 @@ static struct omap_hwmod omap2420_mcbsp2_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_MCBSP2_SHIFT,
                },
        },
+       .opt_clks       = mcbsp_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp_opt_clks),
 };
 
 static struct omap_hwmod_class_sysconfig omap2420_msdi_sysc = {
@@ -585,5 +594,6 @@ static struct omap_hwmod_ocp_if *omap2420_hwmod_ocp_ifs[] __initdata = {
 
 int __init omap2420_hwmod_init(void)
 {
+       omap_hwmod_init();
        return omap_hwmod_register_links(omap2420_hwmod_ocp_ifs);
 }
index 4d72649812303cddc2c1eeb73f6bee3bcd4c4027..58b5bc196d32c4de29054ead6137321d921c1b5a 100644 (file)
@@ -296,6 +296,11 @@ static struct omap_hwmod_class omap2430_mcbsp_hwmod_class = {
        .rev  = MCBSP_CONFIG_TYPE2,
 };
 
+static struct omap_hwmod_opt_clk mcbsp_opt_clks[] = {
+       { .role = "pad_fck", .clk = "mcbsp_clks" },
+       { .role = "prcm_fck", .clk = "func_96m_ck" },
+};
+
 /* mcbsp1 */
 static struct omap_hwmod_irq_info omap2430_mcbsp1_irqs[] = {
        { .name = "tx",         .irq = 59 },
@@ -320,6 +325,8 @@ static struct omap_hwmod omap2430_mcbsp1_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_MCBSP1_SHIFT,
                },
        },
+       .opt_clks       = mcbsp_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp_opt_clks),
 };
 
 /* mcbsp2 */
@@ -345,6 +352,8 @@ static struct omap_hwmod omap2430_mcbsp2_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_MCBSP2_SHIFT,
                },
        },
+       .opt_clks       = mcbsp_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp_opt_clks),
 };
 
 /* mcbsp3 */
@@ -370,6 +379,8 @@ static struct omap_hwmod omap2430_mcbsp3_hwmod = {
                        .idlest_idle_bit = OMAP2430_ST_MCBSP3_SHIFT,
                },
        },
+       .opt_clks       = mcbsp_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp_opt_clks),
 };
 
 /* mcbsp4 */
@@ -401,6 +412,8 @@ static struct omap_hwmod omap2430_mcbsp4_hwmod = {
                        .idlest_idle_bit = OMAP2430_ST_MCBSP4_SHIFT,
                },
        },
+       .opt_clks       = mcbsp_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp_opt_clks),
 };
 
 /* mcbsp5 */
@@ -432,6 +445,8 @@ static struct omap_hwmod omap2430_mcbsp5_hwmod = {
                        .idlest_idle_bit = OMAP2430_ST_MCBSP5_SHIFT,
                },
        },
+       .opt_clks       = mcbsp_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp_opt_clks),
 };
 
 /* MMC/SD/SDIO common */
@@ -938,5 +953,6 @@ static struct omap_hwmod_ocp_if *omap2430_hwmod_ocp_ifs[] __initdata = {
 
 int __init omap2430_hwmod_init(void)
 {
+       omap_hwmod_init();
        return omap_hwmod_register_links(omap2430_hwmod_ocp_ifs);
 }
index 83eafd96ecaa23a2b8b210e56092734d302d9649..afad69c6ba6e92f80817189bd5e53dcaf70293db 100644 (file)
@@ -68,7 +68,6 @@ static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = {
 struct omap_hwmod_class omap2xxx_timer_hwmod_class = {
        .name   = "timer",
        .sysc   = &omap2xxx_timer_sysc,
-       .rev    = OMAP_TIMER_IP_VERSION_1,
 };
 
 /*
@@ -257,7 +256,6 @@ struct omap_hwmod omap2xxx_timer2_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
        .class          = &omap2xxx_timer_hwmod_class,
 };
 
@@ -276,7 +274,6 @@ struct omap_hwmod omap2xxx_timer3_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
        .class          = &omap2xxx_timer_hwmod_class,
 };
 
@@ -295,7 +292,6 @@ struct omap_hwmod omap2xxx_timer4_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
        .class          = &omap2xxx_timer_hwmod_class,
 };
 
@@ -314,7 +310,6 @@ struct omap_hwmod omap2xxx_timer5_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
        .class          = &omap2xxx_timer_hwmod_class,
 };
 
@@ -333,7 +328,6 @@ struct omap_hwmod omap2xxx_timer6_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
        .class          = &omap2xxx_timer_hwmod_class,
 };
 
@@ -352,7 +346,6 @@ struct omap_hwmod omap2xxx_timer7_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
        .class          = &omap2xxx_timer_hwmod_class,
 };
 
@@ -371,7 +364,6 @@ struct omap_hwmod omap2xxx_timer8_hwmod = {
                        .idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
        .class          = &omap2xxx_timer_hwmod_class,
 };
 
index b26d3c9bca1621cab9ac87eea39aff6cc489fc24..c9e38200216b2985cb3ef997e530891b8e3b19dd 100644 (file)
@@ -14,6 +14,8 @@
  *
  * XXX these should be marked initdata for multi-OMAP kernels
  */
+#include <linux/power/smartreflex.h>
+
 #include <plat/omap_hwmod.h>
 #include <mach/irqs.h>
 #include <plat/cpu.h>
@@ -29,8 +31,6 @@
 #include <plat/dmtimer.h>
 
 #include "omap_hwmod_common_data.h"
-
-#include "smartreflex.h"
 #include "prm-regbits-34xx.h"
 #include "cm-regbits-34xx.h"
 #include "wd_timer.h"
@@ -129,7 +129,6 @@ static struct omap_hwmod_class_sysconfig omap3xxx_timer_1ms_sysc = {
 static struct omap_hwmod_class omap3xxx_timer_1ms_hwmod_class = {
        .name = "timer",
        .sysc = &omap3xxx_timer_1ms_sysc,
-       .rev = OMAP_TIMER_IP_VERSION_1,
 };
 
 static struct omap_hwmod_class_sysconfig omap3xxx_timer_sysc = {
@@ -145,12 +144,11 @@ static struct omap_hwmod_class_sysconfig omap3xxx_timer_sysc = {
 static struct omap_hwmod_class omap3xxx_timer_hwmod_class = {
        .name = "timer",
        .sysc = &omap3xxx_timer_sysc,
-       .rev =  OMAP_TIMER_IP_VERSION_1,
 };
 
 /* secure timers dev attribute */
 static struct omap_timer_capability_dev_attr capability_secure_dev_attr = {
-       .timer_capability       = OMAP_TIMER_SECURE,
+       .timer_capability       = OMAP_TIMER_ALWON | OMAP_TIMER_SECURE,
 };
 
 /* always-on timers dev attribute */
@@ -195,7 +193,6 @@ static struct omap_hwmod omap3xxx_timer2_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
        .class          = &omap3xxx_timer_1ms_hwmod_class,
 };
 
@@ -213,7 +210,6 @@ static struct omap_hwmod omap3xxx_timer3_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT3_SHIFT,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 };
 
@@ -231,7 +227,6 @@ static struct omap_hwmod omap3xxx_timer4_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT4_SHIFT,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 };
 
@@ -249,7 +244,6 @@ static struct omap_hwmod omap3xxx_timer5_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT5_SHIFT,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 };
 
@@ -267,7 +261,6 @@ static struct omap_hwmod omap3xxx_timer6_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT6_SHIFT,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 };
 
@@ -285,7 +278,6 @@ static struct omap_hwmod omap3xxx_timer7_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_GPT7_SHIFT,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
        .class          = &omap3xxx_timer_hwmod_class,
 };
 
@@ -527,11 +519,27 @@ static struct omap_hwmod omap36xx_uart4_hwmod = {
 
 static struct omap_hwmod_irq_info am35xx_uart4_mpu_irqs[] = {
        { .irq = INT_35XX_UART4_IRQ, },
+       { .irq = -1 }
 };
 
 static struct omap_hwmod_dma_info am35xx_uart4_sdma_reqs[] = {
        { .name = "rx", .dma_req = AM35XX_DMA_UART4_RX, },
        { .name = "tx", .dma_req = AM35XX_DMA_UART4_TX, },
+       { .dma_req = -1 }
+};
+
+/*
+ * XXX AM35xx UART4 cannot complete its softreset without uart1_fck or
+ * uart2_fck being enabled.  So we add uart1_fck as an optional clock,
+ * below, and set the HWMOD_CONTROL_OPT_CLKS_IN_RESET.  This really
+ * should not be needed.  The functional clock structure of the AM35xx
+ * UART4 is extremely unclear and opaque; it is unclear what the role
+ * of uart1/2_fck is for the UART4.  Any clarification from either
+ * empirical testing or the AM3505/3517 hardware designers would be
+ * most welcome.
+ */
+static struct omap_hwmod_opt_clk am35xx_uart4_opt_clks[] = {
+       { .role = "softreset_uart1_fck", .clk = "uart1_fck" },
 };
 
 static struct omap_hwmod am35xx_uart4_hwmod = {
@@ -543,11 +551,14 @@ static struct omap_hwmod am35xx_uart4_hwmod = {
                .omap2 = {
                        .module_offs = CORE_MOD,
                        .prcm_reg_id = 1,
-                       .module_bit = OMAP3430_EN_UART4_SHIFT,
+                       .module_bit = AM35XX_EN_UART4_SHIFT,
                        .idlest_reg_id = 1,
-                       .idlest_idle_bit = OMAP3430_EN_UART4_SHIFT,
+                       .idlest_idle_bit = AM35XX_ST_UART4_SHIFT,
                },
        },
+       .opt_clks       = am35xx_uart4_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(am35xx_uart4_opt_clks),
+       .flags          = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
        .class          = &omap2_uart_class,
 };
 
@@ -1074,6 +1085,17 @@ static struct omap_hwmod_class omap3xxx_mcbsp_hwmod_class = {
        .rev  = MCBSP_CONFIG_TYPE3,
 };
 
+/* McBSP functional clock mapping */
+static struct omap_hwmod_opt_clk mcbsp15_opt_clks[] = {
+       { .role = "pad_fck", .clk = "mcbsp_clks" },
+       { .role = "prcm_fck", .clk = "core_96m_fck" },
+};
+
+static struct omap_hwmod_opt_clk mcbsp234_opt_clks[] = {
+       { .role = "pad_fck", .clk = "mcbsp_clks" },
+       { .role = "prcm_fck", .clk = "per_96m_fck" },
+};
+
 /* mcbsp1 */
 static struct omap_hwmod_irq_info omap3xxx_mcbsp1_irqs[] = {
        { .name = "common", .irq = 16 },
@@ -1097,6 +1119,8 @@ static struct omap_hwmod omap3xxx_mcbsp1_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_MCBSP1_SHIFT,
                },
        },
+       .opt_clks       = mcbsp15_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp15_opt_clks),
 };
 
 /* mcbsp2 */
@@ -1126,6 +1150,8 @@ static struct omap_hwmod omap3xxx_mcbsp2_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_MCBSP2_SHIFT,
                },
        },
+       .opt_clks       = mcbsp234_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp234_opt_clks),
        .dev_attr       = &omap34xx_mcbsp2_dev_attr,
 };
 
@@ -1156,6 +1182,8 @@ static struct omap_hwmod omap3xxx_mcbsp3_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_MCBSP3_SHIFT,
                },
        },
+       .opt_clks       = mcbsp234_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp234_opt_clks),
        .dev_attr       = &omap34xx_mcbsp3_dev_attr,
 };
 
@@ -1188,6 +1216,8 @@ static struct omap_hwmod omap3xxx_mcbsp4_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_MCBSP4_SHIFT,
                },
        },
+       .opt_clks       = mcbsp234_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp234_opt_clks),
 };
 
 /* mcbsp5 */
@@ -1219,6 +1249,8 @@ static struct omap_hwmod omap3xxx_mcbsp5_hwmod = {
                        .idlest_idle_bit = OMAP3430_ST_MCBSP5_SHIFT,
                },
        },
+       .opt_clks       = mcbsp15_opt_clks,
+       .opt_clks_cnt   = ARRAY_SIZE(mcbsp15_opt_clks),
 };
 
 /* 'mcbsp sidetone' class */
@@ -1325,7 +1357,7 @@ static struct omap_hwmod_irq_info omap3_smartreflex_mpu_irqs[] = {
 };
 
 static struct omap_hwmod omap34xx_sr1_hwmod = {
-       .name           = "sr1",
+       .name           = "smartreflex_mpu_iva",
        .class          = &omap34xx_smartreflex_hwmod_class,
        .main_clk       = "sr1_fck",
        .prcm           = {
@@ -1343,7 +1375,7 @@ static struct omap_hwmod omap34xx_sr1_hwmod = {
 };
 
 static struct omap_hwmod omap36xx_sr1_hwmod = {
-       .name           = "sr1",
+       .name           = "smartreflex_mpu_iva",
        .class          = &omap36xx_smartreflex_hwmod_class,
        .main_clk       = "sr1_fck",
        .prcm           = {
@@ -1370,7 +1402,7 @@ static struct omap_hwmod_irq_info omap3_smartreflex_core_irqs[] = {
 };
 
 static struct omap_hwmod omap34xx_sr2_hwmod = {
-       .name           = "sr2",
+       .name           = "smartreflex_core",
        .class          = &omap34xx_smartreflex_hwmod_class,
        .main_clk       = "sr2_fck",
        .prcm           = {
@@ -1388,7 +1420,7 @@ static struct omap_hwmod omap34xx_sr2_hwmod = {
 };
 
 static struct omap_hwmod omap36xx_sr2_hwmod = {
-       .name           = "sr2",
+       .name           = "smartreflex_core",
        .class          = &omap36xx_smartreflex_hwmod_class,
        .main_clk       = "sr2_fck",
        .prcm           = {
@@ -1638,25 +1670,20 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
 
 /* usb_otg_hs */
 static struct omap_hwmod_irq_info am35xx_usbhsotg_mpu_irqs[] = {
-
        { .name = "mc", .irq = 71 },
        { .irq = -1 }
 };
 
 static struct omap_hwmod_class am35xx_usbotg_class = {
        .name = "am35xx_usbotg",
-       .sysc = NULL,
 };
 
 static struct omap_hwmod am35xx_usbhsotg_hwmod = {
        .name           = "am35x_otg_hs",
        .mpu_irqs       = am35xx_usbhsotg_mpu_irqs,
-       .main_clk       = NULL,
-       .prcm = {
-               .omap2 = {
-               },
-       },
+       .main_clk       = "hsotgusb_fck",
        .class          = &am35xx_usbotg_class,
+       .flags          = HWMOD_NO_IDLEST,
 };
 
 /* MMC/SD/SDIO common */
@@ -2097,9 +2124,10 @@ static struct omap_hwmod_ocp_if omap3xxx_usbhsotg__l3 = {
 static struct omap_hwmod_ocp_if am35xx_usbhsotg__l3 = {
        .master         = &am35xx_usbhsotg_hwmod,
        .slave          = &omap3xxx_l3_main_hwmod,
-       .clk            = "core_l3_ick",
+       .clk            = "hsotgusb_ick",
        .user           = OCP_USER_MPU,
 };
+
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
        .master = &omap3xxx_l4_core_hwmod,
@@ -2243,6 +2271,7 @@ static struct omap_hwmod_addr_space am35xx_uart4_addr_space[] = {
                .pa_end         = OMAP3_UART4_AM35XX_BASE + SZ_1K - 1,
                .flags          = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
        },
+       { }
 };
 
 static struct omap_hwmod_ocp_if am35xx_l4_core__uart4 = {
@@ -2393,7 +2422,7 @@ static struct omap_hwmod_addr_space am35xx_usbhsotg_addrs[] = {
 static struct omap_hwmod_ocp_if am35xx_l4_core__usbhsotg = {
        .master         = &omap3xxx_l4_core_hwmod,
        .slave          = &am35xx_usbhsotg_hwmod,
-       .clk            = "l4_ick",
+       .clk            = "hsotgusb_ick",
        .addr           = am35xx_usbhsotg_addrs,
        .user           = OCP_USER_MPU,
 };
@@ -3138,6 +3167,107 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__counter_32k = {
        .user           = OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* am35xx has Davinci MDIO & EMAC */
+static struct omap_hwmod_class am35xx_mdio_class = {
+       .name = "davinci_mdio",
+};
+
+static struct omap_hwmod am35xx_mdio_hwmod = {
+       .name           = "davinci_mdio",
+       .class          = &am35xx_mdio_class,
+       .flags          = HWMOD_NO_IDLEST,
+};
+
+/*
+ * XXX Should be connected to an IPSS hwmod, not the L3 directly;
+ * but this will probably require some additional hwmod core support,
+ * so is left as a future to-do item.
+ */
+static struct omap_hwmod_ocp_if am35xx_mdio__l3 = {
+       .master         = &am35xx_mdio_hwmod,
+       .slave          = &omap3xxx_l3_main_hwmod,
+       .clk            = "emac_fck",
+       .user           = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am35xx_mdio_addrs[] = {
+       {
+               .pa_start       = AM35XX_IPSS_MDIO_BASE,
+               .pa_end         = AM35XX_IPSS_MDIO_BASE + SZ_4K - 1,
+               .flags          = ADDR_TYPE_RT,
+       },
+       { }
+};
+
+/* l4_core -> davinci mdio  */
+/*
+ * XXX Should be connected to an IPSS hwmod, not the L4_CORE directly;
+ * but this will probably require some additional hwmod core support,
+ * so is left as a future to-do item.
+ */
+static struct omap_hwmod_ocp_if am35xx_l4_core__mdio = {
+       .master         = &omap3xxx_l4_core_hwmod,
+       .slave          = &am35xx_mdio_hwmod,
+       .clk            = "emac_fck",
+       .addr           = am35xx_mdio_addrs,
+       .user           = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_irq_info am35xx_emac_mpu_irqs[] = {
+       { .name = "rxthresh",   .irq = INT_35XX_EMAC_C0_RXTHRESH_IRQ },
+       { .name = "rx_pulse",   .irq = INT_35XX_EMAC_C0_RX_PULSE_IRQ },
+       { .name = "tx_pulse",   .irq = INT_35XX_EMAC_C0_TX_PULSE_IRQ },
+       { .name = "misc_pulse", .irq = INT_35XX_EMAC_C0_MISC_PULSE_IRQ },
+       { .irq = -1 }
+};
+
+static struct omap_hwmod_class am35xx_emac_class = {
+       .name = "davinci_emac",
+};
+
+static struct omap_hwmod am35xx_emac_hwmod = {
+       .name           = "davinci_emac",
+       .mpu_irqs       = am35xx_emac_mpu_irqs,
+       .class          = &am35xx_emac_class,
+       .flags          = HWMOD_NO_IDLEST,
+};
+
+/* l3_core -> davinci emac interface */
+/*
+ * XXX Should be connected to an IPSS hwmod, not the L3 directly;
+ * but this will probably require some additional hwmod core support,
+ * so is left as a future to-do item.
+ */
+static struct omap_hwmod_ocp_if am35xx_emac__l3 = {
+       .master         = &am35xx_emac_hwmod,
+       .slave          = &omap3xxx_l3_main_hwmod,
+       .clk            = "emac_ick",
+       .user           = OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space am35xx_emac_addrs[] = {
+       {
+               .pa_start       = AM35XX_IPSS_EMAC_BASE,
+               .pa_end         = AM35XX_IPSS_EMAC_BASE + 0x30000 - 1,
+               .flags          = ADDR_TYPE_RT,
+       },
+       { }
+};
+
+/* l4_core -> davinci emac  */
+/*
+ * XXX Should be connected to an IPSS hwmod, not the L4_CORE directly;
+ * but this will probably require some additional hwmod core support,
+ * so is left as a future to-do item.
+ */
+static struct omap_hwmod_ocp_if am35xx_l4_core__emac = {
+       .master         = &omap3xxx_l4_core_hwmod,
+       .slave          = &am35xx_emac_hwmod,
+       .clk            = "emac_ick",
+       .addr           = am35xx_emac_addrs,
+       .user           = OCP_USER_MPU,
+};
+
 static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
        &omap3xxx_l3_main__l4_core,
        &omap3xxx_l3_main__l4_per,
@@ -3266,6 +3396,10 @@ static struct omap_hwmod_ocp_if *am35xx_hwmod_ocp_ifs[] __initdata = {
        &omap3xxx_l4_core__usb_tll_hs,
        &omap3xxx_l4_core__es3plus_mmc1,
        &omap3xxx_l4_core__es3plus_mmc2,
+       &am35xx_mdio__l3,
+       &am35xx_l4_core__mdio,
+       &am35xx_emac__l3,
+       &am35xx_l4_core__emac,
        NULL
 };
 
@@ -3283,6 +3417,8 @@ int __init omap3xxx_hwmod_init(void)
        struct omap_hwmod_ocp_if **h = NULL;
        unsigned int rev;
 
+       omap_hwmod_init();
+
        /* Register hwmod links common to all OMAP3 */
        r = omap_hwmod_register_links(omap3xxx_hwmod_ocp_ifs);
        if (r < 0)
index b7bcba5221ba260b31d0327b37442e52fb807143..242aee498ceb21466e33ee04035ed63147e4a615 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include <linux/io.h>
+#include <linux/power/smartreflex.h>
 
 #include <plat/omap_hwmod.h>
 #include <plat/cpu.h>
@@ -32,8 +33,6 @@
 #include <plat/common.h>
 
 #include "omap_hwmod_common_data.h"
-
-#include "smartreflex.h"
 #include "cm1_44xx.h"
 #include "cm2_44xx.h"
 #include "prm44xx.h"
@@ -2544,14 +2543,12 @@ static struct omap_hwmod omap44xx_prcm_mpu_hwmod = {
 static struct omap_hwmod omap44xx_cm_core_aon_hwmod = {
        .name           = "cm_core_aon",
        .class          = &omap44xx_prcm_hwmod_class,
-       .clkdm_name     = "cm_clkdm",
 };
 
 /* cm_core */
 static struct omap_hwmod omap44xx_cm_core_hwmod = {
        .name           = "cm_core",
        .class          = &omap44xx_prcm_hwmod_class,
-       .clkdm_name     = "cm_clkdm",
 };
 
 /* prm */
@@ -2568,7 +2565,6 @@ static struct omap_hwmod_rst_info omap44xx_prm_resets[] = {
 static struct omap_hwmod omap44xx_prm_hwmod = {
        .name           = "prm",
        .class          = &omap44xx_prcm_hwmod_class,
-       .clkdm_name     = "prm_clkdm",
        .mpu_irqs       = omap44xx_prm_irqs,
        .rst_lines      = omap44xx_prm_resets,
        .rst_lines_cnt  = ARRAY_SIZE(omap44xx_prm_resets),
@@ -2947,7 +2943,6 @@ static struct omap_hwmod omap44xx_timer2_hwmod = {
                        .modulemode   = MODULEMODE_SWCTRL,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
 };
 
 /* timer3 */
@@ -2969,7 +2964,6 @@ static struct omap_hwmod omap44xx_timer3_hwmod = {
                        .modulemode   = MODULEMODE_SWCTRL,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
 };
 
 /* timer4 */
@@ -2991,7 +2985,6 @@ static struct omap_hwmod omap44xx_timer4_hwmod = {
                        .modulemode   = MODULEMODE_SWCTRL,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
 };
 
 /* timer5 */
@@ -3013,7 +3006,6 @@ static struct omap_hwmod omap44xx_timer5_hwmod = {
                        .modulemode   = MODULEMODE_SWCTRL,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
 };
 
 /* timer6 */
@@ -3036,7 +3028,6 @@ static struct omap_hwmod omap44xx_timer6_hwmod = {
                        .modulemode   = MODULEMODE_SWCTRL,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
 };
 
 /* timer7 */
@@ -3058,7 +3049,6 @@ static struct omap_hwmod omap44xx_timer7_hwmod = {
                        .modulemode   = MODULEMODE_SWCTRL,
                },
        },
-       .dev_attr       = &capability_alwon_dev_attr,
 };
 
 /* timer8 */
@@ -6148,6 +6138,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
 
 int __init omap44xx_hwmod_init(void)
 {
+       omap_hwmod_init();
        return omap_hwmod_register_links(omap44xx_hwmod_ocp_ifs);
 }
 
index 51e5418899fb446cd2317efe2622e3683860eec4..9f1ccdc8cc8cc0e137cc8b694a650f623c194646 100644 (file)
@@ -47,6 +47,16 @@ struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2 = {
        .midle_shift    = SYSC_TYPE2_MIDLEMODE_SHIFT,
        .sidle_shift    = SYSC_TYPE2_SIDLEMODE_SHIFT,
        .srst_shift     = SYSC_TYPE2_SOFTRESET_SHIFT,
+       .dmadisable_shift = SYSC_TYPE2_DMADISABLE_SHIFT,
+};
+
+/**
+ * struct omap_hwmod_sysc_type3 - TYPE3 sysconfig scheme.
+ * Used by some IPs on AM33xx
+ */
+struct omap_hwmod_sysc_fields omap_hwmod_sysc_type3 = {
+       .midle_shift    = SYSC_TYPE3_MIDLEMODE_SHIFT,
+       .sidle_shift    = SYSC_TYPE3_SIDLEMODE_SHIFT,
 };
 
 struct omap_dss_dispc_dev_attr omap2_3_dss_dispc_dev_attr = {
index 90b50984cd2e0b871e8926aeba1df34125afc4e3..a6ce34dc481413eb120fcf6c19abe7cb8fb012fb 100644 (file)
@@ -51,7 +51,9 @@ static u32 l3_targ_inst_clk1[] = {
        0x200, /* DMM2 */
        0x300, /* ABE */
        0x400, /* L4CFG */
-       0x600  /* CLK2 PWR DISC */
+       0x600,  /* CLK2 PWR DISC */
+       0x0,    /* Host CLK1 */
+       0x900   /* L4 Wakeup */
 };
 
 static u32 l3_targ_inst_clk2[] = {
@@ -72,11 +74,16 @@ static u32 l3_targ_inst_clk2[] = {
        0xE00, /* missing in TRM corresponds to AES2*/
        0xC00, /* L4 PER3 */
        0xA00, /* L4 PER1*/
-       0xB00 /* L4 PER2*/
+       0xB00, /* L4 PER2*/
+       0x0, /* HOST CLK2 */
+       0x1800, /* CAL */
+       0x1700 /* LLI */
 };
 
 static u32 l3_targ_inst_clk3[] = {
-       0x0100  /* EMUSS */
+       0x0100  /* EMUSS */,
+       0x0300, /* DEBUGSS_CT_TBR */
+       0x0 /* HOST CLK3 */
 };
 
 static struct l3_masters_data {
@@ -110,13 +117,15 @@ static struct l3_masters_data {
        { 0xC8, "USBHOSTFS"}
 };
 
-static char *l3_targ_inst_name[L3_MODULES][18] = {
+static char *l3_targ_inst_name[L3_MODULES][21] = {
        {
                "DMM1",
                "DMM2",
                "ABE",
                "L4CFG",
                "CLK2 PWR DISC",
+               "HOST CLK1",
+               "L4 WAKEUP"
        },
        {
                "CORTEX M3" ,
@@ -137,9 +146,14 @@ static char *l3_targ_inst_name[L3_MODULES][18] = {
                "L4 PER3",
                "L4 PER1",
                "L4 PER2",
+               "HOST CLK2",
+               "CAL",
+               "LLI"
        },
        {
                "EMUSS",
+               "DEBUG SOURCE",
+               "HOST CLK3"
        },
 };
 
index de6d46451746eaa19f2ba2a28c6385531acddce3..d8f6dbf45d16c32cd4f542a762d764af61406c23 100644 (file)
@@ -53,7 +53,7 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
        omap_table_init = 1;
 
        /* Lets now register with OPP library */
-       for (i = 0; i < opp_def_size; i++) {
+       for (i = 0; i < opp_def_size; i++, opp_def++) {
                struct omap_hwmod *oh;
                struct device *dev;
 
@@ -86,7 +86,6 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
                                        __func__, opp_def->freq,
                                        opp_def->hwmod_name, i, r);
                }
-               opp_def++;
        }
 
        return 0;
index 78564895e9144c327420034d5a4f3f6c9b3f44b8..686137d164dac9faee69b2293e524fa08c69bcea 100644 (file)
 
 #include "powerdomain.h"
 
+#ifdef CONFIG_CPU_IDLE
+extern int __init omap3_idle_init(void);
+extern int __init omap4_idle_init(void);
+#else
+static inline int omap3_idle_init(void)
+{
+       return 0;
+}
+
+static inline int omap4_idle_init(void)
+{
+       return 0;
+}
+#endif
+
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
 extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
-extern int omap3_idle_init(void);
-extern int omap4_idle_init(void);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 extern int (*omap_pm_suspend)(void);
 
@@ -88,7 +101,7 @@ extern void enable_omap3630_toggle_l2_on_restore(void);
 static inline void enable_omap3630_toggle_l2_on_restore(void) { }
 #endif         /* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */
 
-#ifdef CONFIG_OMAP_SMARTREFLEX
+#ifdef CONFIG_POWER_AVS_OMAP
 extern int omap_devinit_smartreflex(void);
 extern void omap_enable_smartreflex_on_init(void);
 #else
index 3a595e8997245495672d703fc52c7a148ffb0a9f..e4fc88c65dbd6a868b6dac07229de3ee3b7791ea 100644 (file)
@@ -70,34 +70,6 @@ void (*omap3_do_wfi_sram)(void);
 
 static struct powerdomain *mpu_pwrdm, *neon_pwrdm;
 static struct powerdomain *core_pwrdm, *per_pwrdm;
-static struct powerdomain *cam_pwrdm;
-
-static void omap3_enable_io_chain(void)
-{
-       int timeout = 0;
-
-       omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-                                  PM_WKEN);
-       /* Do a readback to assure write has been done */
-       omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN);
-
-       while (!(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKEN) &
-                OMAP3430_ST_IO_CHAIN_MASK)) {
-               timeout++;
-               if (timeout > 1000) {
-                       pr_err("Wake up daisy chain activation failed.\n");
-                       return;
-               }
-               omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK,
-                                          WKUP_MOD, PM_WKEN);
-       }
-}
-
-static void omap3_disable_io_chain(void)
-{
-       omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
-                                    PM_WKEN);
-}
 
 static void omap3_core_save_context(void)
 {
@@ -299,24 +271,22 @@ void omap_sram_idle(void)
        /* Enable IO-PAD and IO-CHAIN wakeups */
        per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
        core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
-       if (omap3_has_io_wakeup() &&
-           (per_next_state < PWRDM_POWER_ON ||
-            core_next_state < PWRDM_POWER_ON)) {
-               omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD, PM_WKEN);
-               if (omap3_has_io_chain_ctrl())
-                       omap3_enable_io_chain();
-       }
 
-       pwrdm_pre_transition();
+       if (mpu_next_state < PWRDM_POWER_ON) {
+               pwrdm_pre_transition(mpu_pwrdm);
+               pwrdm_pre_transition(neon_pwrdm);
+       }
 
        /* PER */
        if (per_next_state < PWRDM_POWER_ON) {
+               pwrdm_pre_transition(per_pwrdm);
                per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
                omap2_gpio_prepare_for_idle(per_going_off);
        }
 
        /* CORE */
        if (core_next_state < PWRDM_POWER_ON) {
+               pwrdm_pre_transition(core_pwrdm);
                if (core_next_state == PWRDM_POWER_OFF) {
                        omap3_core_save_context();
                        omap3_cm_save_context();
@@ -369,26 +339,20 @@ void omap_sram_idle(void)
                        omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
                                               OMAP3430_GR_MOD,
                                               OMAP3_PRM_VOLTCTRL_OFFSET);
+               pwrdm_post_transition(core_pwrdm);
        }
        omap3_intc_resume_idle();
 
-       pwrdm_post_transition();
-
        /* PER */
-       if (per_next_state < PWRDM_POWER_ON)
+       if (per_next_state < PWRDM_POWER_ON) {
                omap2_gpio_resume_after_idle();
-
-       /* Disable IO-PAD and IO-CHAIN wakeup */
-       if (omap3_has_io_wakeup() &&
-           (per_next_state < PWRDM_POWER_ON ||
-            core_next_state < PWRDM_POWER_ON)) {
-               omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
-                                            PM_WKEN);
-               if (omap3_has_io_chain_ctrl())
-                       omap3_disable_io_chain();
+               pwrdm_post_transition(per_pwrdm);
        }
 
-       clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
+       if (mpu_next_state < PWRDM_POWER_ON) {
+               pwrdm_post_transition(mpu_pwrdm);
+               pwrdm_post_transition(neon_pwrdm);
+       }
 }
 
 static void omap3_pm_idle(void)
@@ -581,10 +545,13 @@ static void __init prcm_setup_regs(void)
                          OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
 
        /* Don't attach IVA interrupts */
-       omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
-       omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
-       omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
-       omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
+       if (omap3_has_iva()) {
+               omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
+               omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
+               omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
+               omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD,
+                                       OMAP3430_PM_IVAGRPSEL);
+       }
 
        /* Clear any pending 'reset' flags */
        omap2_prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
@@ -598,7 +565,9 @@ static void __init prcm_setup_regs(void)
        /* Clear any pending PRCM interrupts */
        omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
 
-       omap3_iva_idle();
+       if (omap3_has_iva())
+               omap3_iva_idle();
+
        omap3_d2d_idle();
 }
 
@@ -749,7 +718,6 @@ int __init omap3_pm_init(void)
        neon_pwrdm = pwrdm_lookup("neon_pwrdm");
        per_pwrdm = pwrdm_lookup("per_pwrdm");
        core_pwrdm = pwrdm_lookup("core_pwrdm");
-       cam_pwrdm = pwrdm_lookup("cam_pwrdm");
 
        neon_clkdm = clkdm_lookup("neon_clkdm");
        mpu_clkdm = clkdm_lookup("mpu_clkdm");
index 96114901b932a815296bb85632c3d2f69f526eb4..69b36e185e9b7cc019e664f17c53cf96f282eee1 100644 (file)
@@ -526,7 +526,8 @@ int pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
  *
  * Return the powerdomain @pwrdm's current power state.        Returns -EINVAL
  * if the powerdomain pointer is null or returns the current power state
- * upon success.
+ * upon success. Note that if the power domain only supports the ON state
+ * then just return ON as the current state.
  */
 int pwrdm_read_pwrst(struct powerdomain *pwrdm)
 {
@@ -535,6 +536,9 @@ int pwrdm_read_pwrst(struct powerdomain *pwrdm)
        if (!pwrdm)
                return -EINVAL;
 
+       if (pwrdm->pwrsts == PWRSTS_ON)
+               return PWRDM_POWER_ON;
+
        if (arch_pwrdm && arch_pwrdm->pwrdm_read_pwrst)
                ret = arch_pwrdm->pwrdm_read_pwrst(pwrdm);
 
@@ -981,15 +985,23 @@ int pwrdm_state_switch(struct powerdomain *pwrdm)
        return ret;
 }
 
-int pwrdm_pre_transition(void)
+int pwrdm_pre_transition(struct powerdomain *pwrdm)
 {
-       pwrdm_for_each(_pwrdm_pre_transition_cb, NULL);
+       if (pwrdm)
+               _pwrdm_pre_transition_cb(pwrdm, NULL);
+       else
+               pwrdm_for_each(_pwrdm_pre_transition_cb, NULL);
+
        return 0;
 }
 
-int pwrdm_post_transition(void)
+int pwrdm_post_transition(struct powerdomain *pwrdm)
 {
-       pwrdm_for_each(_pwrdm_post_transition_cb, NULL);
+       if (pwrdm)
+               _pwrdm_post_transition_cb(pwrdm, NULL);
+       else
+               pwrdm_for_each(_pwrdm_post_transition_cb, NULL);
+
        return 0;
 }
 
index 8f88d65c46ea5ab7a28c1fb70694a386556a5039..baee90608d11b8ddd444df041e401b4ef5314456 100644 (file)
@@ -67,9 +67,9 @@
 
 /*
  * Maximum number of clockdomains that can be associated with a powerdomain.
- * CORE powerdomain on OMAP4 is the worst case
+ * PER powerdomain on AM33XX is the worst case
  */
-#define PWRDM_MAX_CLKDMS       9
+#define PWRDM_MAX_CLKDMS       11
 
 /* XXX A completely arbitrary number. What is reasonable here? */
 #define PWRDM_TRANSITION_BAILOUT 100000
@@ -92,6 +92,15 @@ struct powerdomain;
  * @pwrdm_clkdms: Clockdomains in this powerdomain
  * @node: list_head linking all powerdomains
  * @voltdm_node: list_head linking all powerdomains in a voltagedomain
+ * @pwrstctrl_offs: (AM33XX only) XXX_PWRSTCTRL reg offset from prcm_offs
+ * @pwrstst_offs: (AM33XX only) XXX_PWRSTST reg offset from prcm_offs
+ * @logicretstate_mask: (AM33XX only) mask for logic retention bitfield
+ *     in @pwrstctrl_offs
+ * @mem_on_mask: (AM33XX only) mask for mem on bitfield in @pwrstctrl_offs
+ * @mem_ret_mask: (AM33XX only) mask for mem ret bitfield in @pwrstctrl_offs
+ * @mem_pwrst_mask: (AM33XX only) mask for mem state bitfield in @pwrstst_offs
+ * @mem_retst_mask: (AM33XX only) mask for mem retention state bitfield
+ *     in @pwrstctrl_offs
  * @state:
  * @state_counter:
  * @timer:
@@ -121,6 +130,14 @@ struct powerdomain {
        unsigned ret_logic_off_counter;
        unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];
 
+       const u8 pwrstctrl_offs;
+       const u8 pwrstst_offs;
+       const u32 logicretstate_mask;
+       const u32 mem_on_mask[PWRDM_MAX_MEM_BANKS];
+       const u32 mem_ret_mask[PWRDM_MAX_MEM_BANKS];
+       const u32 mem_pwrst_mask[PWRDM_MAX_MEM_BANKS];
+       const u32 mem_retst_mask[PWRDM_MAX_MEM_BANKS];
+
 #ifdef CONFIG_PM_DEBUG
        s64 timer;
        s64 state_timer[PWRDM_MAX_PWRSTS];
@@ -213,8 +230,8 @@ bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
 int pwrdm_wait_transition(struct powerdomain *pwrdm);
 
 int pwrdm_state_switch(struct powerdomain *pwrdm);
-int pwrdm_pre_transition(void);
-int pwrdm_post_transition(void);
+int pwrdm_pre_transition(struct powerdomain *pwrdm);
+int pwrdm_post_transition(struct powerdomain *pwrdm);
 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
@@ -222,10 +239,12 @@ bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 extern void omap242x_powerdomains_init(void);
 extern void omap243x_powerdomains_init(void);
 extern void omap3xxx_powerdomains_init(void);
+extern void am33xx_powerdomains_init(void);
 extern void omap44xx_powerdomains_init(void);
 
 extern struct pwrdm_ops omap2_pwrdm_operations;
 extern struct pwrdm_ops omap3_pwrdm_operations;
+extern struct pwrdm_ops am33xx_pwrdm_operations;
 extern struct pwrdm_ops omap4_pwrdm_operations;
 
 /* Common Internal functions used across OMAP rev's */
diff --git a/arch/arm/mach-omap2/powerdomain33xx.c b/arch/arm/mach-omap2/powerdomain33xx.c
new file mode 100644 (file)
index 0000000..67c5663
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * AM33XX Powerdomain control
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Derived from mach-omap2/powerdomain44xx.c written by Rajendra Nayak
+ * <rnayak@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+
+#include <plat/prcm.h>
+
+#include "powerdomain.h"
+#include "prm33xx.h"
+#include "prm-regbits-33xx.h"
+
+
+static int am33xx_pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst)
+{
+       am33xx_prm_rmw_reg_bits(OMAP_POWERSTATE_MASK,
+                               (pwrst << OMAP_POWERSTATE_SHIFT),
+                               pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+       return 0;
+}
+
+static int am33xx_pwrdm_read_next_pwrst(struct powerdomain *pwrdm)
+{
+       u32 v;
+
+       v = am33xx_prm_read_reg(pwrdm->prcm_offs,  pwrdm->pwrstctrl_offs);
+       v &= OMAP_POWERSTATE_MASK;
+       v >>= OMAP_POWERSTATE_SHIFT;
+
+       return v;
+}
+
+static int am33xx_pwrdm_read_pwrst(struct powerdomain *pwrdm)
+{
+       u32 v;
+
+       v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+       v &= OMAP_POWERSTATEST_MASK;
+       v >>= OMAP_POWERSTATEST_SHIFT;
+
+       return v;
+}
+
+static int am33xx_pwrdm_read_prev_pwrst(struct powerdomain *pwrdm)
+{
+       u32 v;
+
+       v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+       v &= AM33XX_LASTPOWERSTATEENTERED_MASK;
+       v >>= AM33XX_LASTPOWERSTATEENTERED_SHIFT;
+
+       return v;
+}
+
+static int am33xx_pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
+{
+       am33xx_prm_rmw_reg_bits(AM33XX_LOWPOWERSTATECHANGE_MASK,
+                               (1 << AM33XX_LOWPOWERSTATECHANGE_SHIFT),
+                               pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+       return 0;
+}
+
+static int am33xx_pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm)
+{
+       am33xx_prm_rmw_reg_bits(AM33XX_LASTPOWERSTATEENTERED_MASK,
+                               AM33XX_LASTPOWERSTATEENTERED_MASK,
+                               pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+       return 0;
+}
+
+static int am33xx_pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst)
+{
+       u32 m;
+
+       m = pwrdm->logicretstate_mask;
+       if (!m)
+               return -EINVAL;
+
+       am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
+                               pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+
+       return 0;
+}
+
+static int am33xx_pwrdm_read_logic_pwrst(struct powerdomain *pwrdm)
+{
+       u32 v;
+
+       v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+       v &= AM33XX_LOGICSTATEST_MASK;
+       v >>= AM33XX_LOGICSTATEST_SHIFT;
+
+       return v;
+}
+
+static int am33xx_pwrdm_read_logic_retst(struct powerdomain *pwrdm)
+{
+       u32 v, m;
+
+       m = pwrdm->logicretstate_mask;
+       if (!m)
+               return -EINVAL;
+
+       v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+       v &= m;
+       v >>= __ffs(m);
+
+       return v;
+}
+
+static int am33xx_pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank,
+               u8 pwrst)
+{
+       u32 m;
+
+       m = pwrdm->mem_on_mask[bank];
+       if (!m)
+               return -EINVAL;
+
+       am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
+                               pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+
+       return 0;
+}
+
+static int am33xx_pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank,
+                                       u8 pwrst)
+{
+       u32 m;
+
+       m = pwrdm->mem_ret_mask[bank];
+       if (!m)
+               return -EINVAL;
+
+       am33xx_prm_rmw_reg_bits(m, (pwrst << __ffs(m)),
+                               pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+
+       return 0;
+}
+
+static int am33xx_pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank)
+{
+       u32 m, v;
+
+       m = pwrdm->mem_pwrst_mask[bank];
+       if (!m)
+               return -EINVAL;
+
+       v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs);
+       v &= m;
+       v >>= __ffs(m);
+
+       return v;
+}
+
+static int am33xx_pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank)
+{
+       u32 m, v;
+
+       m = pwrdm->mem_retst_mask[bank];
+       if (!m)
+               return -EINVAL;
+
+       v = am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstctrl_offs);
+       v &= m;
+       v >>= __ffs(m);
+
+       return v;
+}
+
+static int am33xx_pwrdm_wait_transition(struct powerdomain *pwrdm)
+{
+       u32 c = 0;
+
+       /*
+        * REVISIT: pwrdm_wait_transition() may be better implemented
+        * via a callback and a periodic timer check -- how long do we expect
+        * powerdomain transitions to take?
+        */
+
+       /* XXX Is this udelay() value meaningful? */
+       while ((am33xx_prm_read_reg(pwrdm->prcm_offs, pwrdm->pwrstst_offs)
+                       & OMAP_INTRANSITION_MASK) &&
+                       (c++ < PWRDM_TRANSITION_BAILOUT))
+               udelay(1);
+
+       if (c > PWRDM_TRANSITION_BAILOUT) {
+               pr_err("powerdomain: %s: waited too long to complete transition\n",
+                      pwrdm->name);
+               return -EAGAIN;
+       }
+
+       pr_debug("powerdomain: completed transition in %d loops\n", c);
+
+       return 0;
+}
+
+struct pwrdm_ops am33xx_pwrdm_operations = {
+       .pwrdm_set_next_pwrst           = am33xx_pwrdm_set_next_pwrst,
+       .pwrdm_read_next_pwrst          = am33xx_pwrdm_read_next_pwrst,
+       .pwrdm_read_pwrst               = am33xx_pwrdm_read_pwrst,
+       .pwrdm_read_prev_pwrst          = am33xx_pwrdm_read_prev_pwrst,
+       .pwrdm_set_logic_retst          = am33xx_pwrdm_set_logic_retst,
+       .pwrdm_read_logic_pwrst         = am33xx_pwrdm_read_logic_pwrst,
+       .pwrdm_read_logic_retst         = am33xx_pwrdm_read_logic_retst,
+       .pwrdm_clear_all_prev_pwrst     = am33xx_pwrdm_clear_all_prev_pwrst,
+       .pwrdm_set_lowpwrstchange       = am33xx_pwrdm_set_lowpwrstchange,
+       .pwrdm_read_mem_pwrst           = am33xx_pwrdm_read_mem_pwrst,
+       .pwrdm_read_mem_retst           = am33xx_pwrdm_read_mem_retst,
+       .pwrdm_set_mem_onst             = am33xx_pwrdm_set_mem_onst,
+       .pwrdm_set_mem_retst            = am33xx_pwrdm_set_mem_retst,
+       .pwrdm_wait_transition          = am33xx_pwrdm_wait_transition,
+};
diff --git a/arch/arm/mach-omap2/powerdomains33xx_data.c b/arch/arm/mach-omap2/powerdomains33xx_data.c
new file mode 100644 (file)
index 0000000..869adb8
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * AM33XX Power domain data
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include "powerdomain.h"
+#include "prcm-common.h"
+#include "prm-regbits-33xx.h"
+#include "prm33xx.h"
+
+static struct powerdomain gfx_33xx_pwrdm = {
+       .name                   = "gfx_pwrdm",
+       .voltdm                 = { .name = "core" },
+       .prcm_offs              = AM33XX_PRM_GFX_MOD,
+       .pwrstctrl_offs         = AM33XX_PM_GFX_PWRSTCTRL_OFFSET,
+       .pwrstst_offs           = AM33XX_PM_GFX_PWRSTST_OFFSET,
+       .pwrsts                 = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret       = PWRSTS_OFF_RET,
+       .flags                  = PWRDM_HAS_LOWPOWERSTATECHANGE,
+       .banks                  = 1,
+       .logicretstate_mask     = AM33XX_LOGICRETSTATE_MASK,
+       .mem_on_mask            = {
+               [0]             = AM33XX_GFX_MEM_ONSTATE_MASK,  /* gfx_mem */
+       },
+       .mem_ret_mask           = {
+               [0]             = AM33XX_GFX_MEM_RETSTATE_MASK, /* gfx_mem */
+       },
+       .mem_pwrst_mask         = {
+               [0]             = AM33XX_GFX_MEM_STATEST_MASK,  /* gfx_mem */
+       },
+       .mem_retst_mask         = {
+               [0]             = AM33XX_GFX_MEM_RETSTATE_MASK, /* gfx_mem */
+       },
+       .pwrsts_mem_ret         = {
+               [0]             = PWRSTS_OFF_RET,       /* gfx_mem */
+       },
+       .pwrsts_mem_on          = {
+               [0]             = PWRSTS_ON,            /* gfx_mem */
+       },
+};
+
+static struct powerdomain rtc_33xx_pwrdm = {
+       .name                   = "rtc_pwrdm",
+       .voltdm                 = { .name = "rtc" },
+       .prcm_offs              = AM33XX_PRM_RTC_MOD,
+       .pwrstctrl_offs         = AM33XX_PM_RTC_PWRSTCTRL_OFFSET,
+       .pwrstst_offs           = AM33XX_PM_RTC_PWRSTST_OFFSET,
+       .pwrsts                 = PWRSTS_ON,
+       .logicretstate_mask     = AM33XX_LOGICRETSTATE_MASK,
+};
+
+static struct powerdomain wkup_33xx_pwrdm = {
+       .name                   = "wkup_pwrdm",
+       .voltdm                 = { .name = "core" },
+       .prcm_offs              = AM33XX_PRM_WKUP_MOD,
+       .pwrstctrl_offs         = AM33XX_PM_WKUP_PWRSTCTRL_OFFSET,
+       .pwrstst_offs           = AM33XX_PM_WKUP_PWRSTST_OFFSET,
+       .pwrsts                 = PWRSTS_ON,
+       .logicretstate_mask     = AM33XX_LOGICRETSTATE_3_3_MASK,
+};
+
+static struct powerdomain per_33xx_pwrdm = {
+       .name                   = "per_pwrdm",
+       .voltdm                 = { .name = "core" },
+       .prcm_offs              = AM33XX_PRM_PER_MOD,
+       .pwrstctrl_offs         = AM33XX_PM_PER_PWRSTCTRL_OFFSET,
+       .pwrstst_offs           = AM33XX_PM_PER_PWRSTST_OFFSET,
+       .pwrsts                 = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret       = PWRSTS_OFF_RET,
+       .flags                  = PWRDM_HAS_LOWPOWERSTATECHANGE,
+       .banks                  = 3,
+       .logicretstate_mask     = AM33XX_LOGICRETSTATE_3_3_MASK,
+       .mem_on_mask            = {
+               [0]             = AM33XX_PRUSS_MEM_ONSTATE_MASK, /* pruss_mem */
+               [1]             = AM33XX_PER_MEM_ONSTATE_MASK,  /* per_mem */
+               [2]             = AM33XX_RAM_MEM_ONSTATE_MASK,  /* ram_mem */
+       },
+       .mem_ret_mask           = {
+               [0]             = AM33XX_PRUSS_MEM_RETSTATE_MASK, /* pruss_mem */
+               [1]             = AM33XX_PER_MEM_RETSTATE_MASK, /* per_mem */
+               [2]             = AM33XX_RAM_MEM_RETSTATE_MASK, /* ram_mem */
+       },
+       .mem_pwrst_mask         = {
+               [0]             = AM33XX_PRUSS_MEM_STATEST_MASK, /* pruss_mem */
+               [1]             = AM33XX_PER_MEM_STATEST_MASK,  /* per_mem */
+               [2]             = AM33XX_RAM_MEM_STATEST_MASK,  /* ram_mem */
+       },
+       .mem_retst_mask         = {
+               [0]             = AM33XX_PRUSS_MEM_RETSTATE_MASK, /* pruss_mem */
+               [1]             = AM33XX_PER_MEM_RETSTATE_MASK, /* per_mem */
+               [2]             = AM33XX_RAM_MEM_RETSTATE_MASK, /* ram_mem */
+       },
+       .pwrsts_mem_ret         = {
+               [0]             = PWRSTS_OFF_RET,       /* pruss_mem */
+               [1]             = PWRSTS_OFF_RET,       /* per_mem */
+               [2]             = PWRSTS_OFF_RET,       /* ram_mem */
+       },
+       .pwrsts_mem_on          = {
+               [0]             = PWRSTS_ON,            /* pruss_mem */
+               [1]             = PWRSTS_ON,            /* per_mem */
+               [2]             = PWRSTS_ON,            /* ram_mem */
+       },
+};
+
+static struct powerdomain mpu_33xx_pwrdm = {
+       .name                   = "mpu_pwrdm",
+       .voltdm                 = { .name = "mpu" },
+       .prcm_offs              = AM33XX_PRM_MPU_MOD,
+       .pwrstctrl_offs         = AM33XX_PM_MPU_PWRSTCTRL_OFFSET,
+       .pwrstst_offs           = AM33XX_PM_MPU_PWRSTST_OFFSET,
+       .pwrsts                 = PWRSTS_OFF_RET_ON,
+       .pwrsts_logic_ret       = PWRSTS_OFF_RET,
+       .flags                  = PWRDM_HAS_LOWPOWERSTATECHANGE,
+       .banks                  = 3,
+       .logicretstate_mask     = AM33XX_LOGICRETSTATE_MASK,
+       .mem_on_mask            = {
+               [0]             = AM33XX_MPU_L1_ONSTATE_MASK,   /* mpu_l1 */
+               [1]             = AM33XX_MPU_L2_ONSTATE_MASK,   /* mpu_l2 */
+               [2]             = AM33XX_MPU_RAM_ONSTATE_MASK,  /* mpu_ram */
+       },
+       .mem_ret_mask           = {
+               [0]             = AM33XX_MPU_L1_RETSTATE_MASK,  /* mpu_l1 */
+               [1]             = AM33XX_MPU_L2_RETSTATE_MASK,  /* mpu_l2 */
+               [2]             = AM33XX_MPU_RAM_RETSTATE_MASK, /* mpu_ram */
+       },
+       .mem_pwrst_mask         = {
+               [0]             = AM33XX_MPU_L1_STATEST_MASK,   /* mpu_l1 */
+               [1]             = AM33XX_MPU_L2_STATEST_MASK,   /* mpu_l2 */
+               [2]             = AM33XX_MPU_RAM_STATEST_MASK,  /* mpu_ram */
+       },
+       .mem_retst_mask         = {
+               [0]             = AM33XX_MPU_L1_RETSTATE_MASK,  /* mpu_l1 */
+               [1]             = AM33XX_MPU_L2_RETSTATE_MASK,  /* mpu_l2 */
+               [2]             = AM33XX_MPU_RAM_RETSTATE_MASK, /* mpu_ram */
+       },
+       .pwrsts_mem_ret         = {
+               [0]             = PWRSTS_OFF_RET,       /* mpu_l1 */
+               [1]             = PWRSTS_OFF_RET,       /* mpu_l2 */
+               [2]             = PWRSTS_OFF_RET,       /* mpu_ram */
+       },
+       .pwrsts_mem_on          = {
+               [0]             = PWRSTS_ON,            /* mpu_l1 */
+               [1]             = PWRSTS_ON,            /* mpu_l2 */
+               [2]             = PWRSTS_ON,            /* mpu_ram */
+       },
+};
+
+static struct powerdomain cefuse_33xx_pwrdm = {
+       .name           = "cefuse_pwrdm",
+       .voltdm         = { .name = "core" },
+       .prcm_offs      = AM33XX_PRM_CEFUSE_MOD,
+       .pwrstctrl_offs = AM33XX_PM_CEFUSE_PWRSTCTRL_OFFSET,
+       .pwrstst_offs   = AM33XX_PM_CEFUSE_PWRSTST_OFFSET,
+       .pwrsts         = PWRSTS_OFF_ON,
+};
+
+static struct powerdomain *powerdomains_am33xx[] __initdata = {
+       &gfx_33xx_pwrdm,
+       &rtc_33xx_pwrdm,
+       &wkup_33xx_pwrdm,
+       &per_33xx_pwrdm,
+       &mpu_33xx_pwrdm,
+       &cefuse_33xx_pwrdm,
+       NULL,
+};
+
+void __init am33xx_powerdomains_init(void)
+{
+       pwrdm_register_platform_funcs(&am33xx_pwrdm_operations);
+       pwrdm_register_pwrdms(powerdomains_am33xx);
+       pwrdm_complete_init();
+}
index fb0a0a6869d17b783834f93616ba29a2f3430e43..bb883e463078b264869594d150dc5a2bb49d0caf 100644 (file)
@@ -71,6 +71,22 @@ static struct powerdomain mpu_3xxx_pwrdm = {
        .voltdm           = { .name = "mpu_iva" },
 };
 
+static struct powerdomain mpu_am35x_pwrdm = {
+       .name             = "mpu_pwrdm",
+       .prcm_offs        = MPU_MOD,
+       .pwrsts           = PWRSTS_ON,
+       .pwrsts_logic_ret = PWRSTS_ON,
+       .flags            = PWRDM_HAS_MPU_QUIRK,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRSTS_ON,
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRSTS_ON,
+       },
+       .voltdm           = { .name = "mpu_iva" },
+};
+
 /*
  * The USBTLL Save-and-Restore mechanism is broken on
  * 3430s up to ES3.0 and 3630ES1.0. Hence this feature
@@ -120,6 +136,23 @@ static struct powerdomain core_3xxx_es3_1_pwrdm = {
        .voltdm           = { .name = "core" },
 };
 
+static struct powerdomain core_am35x_pwrdm = {
+       .name             = "core_pwrdm",
+       .prcm_offs        = CORE_MOD,
+       .pwrsts           = PWRSTS_ON,
+       .pwrsts_logic_ret = PWRSTS_ON,
+       .banks            = 2,
+       .pwrsts_mem_ret   = {
+               [0] = PWRSTS_ON,         /* MEM1RETSTATE */
+               [1] = PWRSTS_ON,         /* MEM2RETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRSTS_ON, /* MEM1ONSTATE */
+               [1] = PWRSTS_ON, /* MEM2ONSTATE */
+       },
+       .voltdm           = { .name = "core" },
+};
+
 static struct powerdomain dss_pwrdm = {
        .name             = "dss_pwrdm",
        .prcm_offs        = OMAP3430_DSS_MOD,
@@ -135,6 +168,21 @@ static struct powerdomain dss_pwrdm = {
        .voltdm           = { .name = "core" },
 };
 
+static struct powerdomain dss_am35x_pwrdm = {
+       .name             = "dss_pwrdm",
+       .prcm_offs        = OMAP3430_DSS_MOD,
+       .pwrsts           = PWRSTS_ON,
+       .pwrsts_logic_ret = PWRSTS_ON,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRSTS_ON, /* MEMRETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRSTS_ON,  /* MEMONSTATE */
+       },
+       .voltdm           = { .name = "core" },
+};
+
 /*
  * Although the 34XX TRM Rev K Table 4-371 notes that retention is a
  * possible SGX powerstate, the SGX device itself does not support
@@ -156,6 +204,21 @@ static struct powerdomain sgx_pwrdm = {
        .voltdm           = { .name = "core" },
 };
 
+static struct powerdomain sgx_am35x_pwrdm = {
+       .name             = "sgx_pwrdm",
+       .prcm_offs        = OMAP3430ES2_SGX_MOD,
+       .pwrsts           = PWRSTS_ON,
+       .pwrsts_logic_ret = PWRSTS_ON,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRSTS_ON, /* MEMRETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRSTS_ON,  /* MEMONSTATE */
+       },
+       .voltdm           = { .name = "core" },
+};
+
 static struct powerdomain cam_pwrdm = {
        .name             = "cam_pwrdm",
        .prcm_offs        = OMAP3430_CAM_MOD,
@@ -186,6 +249,21 @@ static struct powerdomain per_pwrdm = {
        .voltdm           = { .name = "core" },
 };
 
+static struct powerdomain per_am35x_pwrdm = {
+       .name             = "per_pwrdm",
+       .prcm_offs        = OMAP3430_PER_MOD,
+       .pwrsts           = PWRSTS_ON,
+       .pwrsts_logic_ret = PWRSTS_ON,
+       .banks            = 1,
+       .pwrsts_mem_ret   = {
+               [0] = PWRSTS_ON, /* MEMRETSTATE */
+       },
+       .pwrsts_mem_on    = {
+               [0] = PWRSTS_ON,  /* MEMONSTATE */
+       },
+       .voltdm           = { .name = "core" },
+};
+
 static struct powerdomain emu_pwrdm = {
        .name           = "emu_pwrdm",
        .prcm_offs      = OMAP3430_EMU_MOD,
@@ -200,6 +278,14 @@ static struct powerdomain neon_pwrdm = {
        .voltdm           = { .name = "mpu_iva" },
 };
 
+static struct powerdomain neon_am35x_pwrdm = {
+       .name             = "neon_pwrdm",
+       .prcm_offs        = OMAP3430_NEON_MOD,
+       .pwrsts           = PWRSTS_ON,
+       .pwrsts_logic_ret = PWRSTS_ON,
+       .voltdm           = { .name = "mpu_iva" },
+};
+
 static struct powerdomain usbhost_pwrdm = {
        .name             = "usbhost_pwrdm",
        .prcm_offs        = OMAP3430ES2_USBHOST_MOD,
@@ -293,6 +379,22 @@ static struct powerdomain *powerdomains_omap3430es3_1plus[] __initdata = {
        NULL
 };
 
+static struct powerdomain *powerdomains_am35x[] __initdata = {
+       &wkup_omap2_pwrdm,
+       &mpu_am35x_pwrdm,
+       &neon_am35x_pwrdm,
+       &core_am35x_pwrdm,
+       &sgx_am35x_pwrdm,
+       &dss_am35x_pwrdm,
+       &per_am35x_pwrdm,
+       &emu_pwrdm,
+       &dpll1_pwrdm,
+       &dpll3_pwrdm,
+       &dpll4_pwrdm,
+       &dpll5_pwrdm,
+       NULL
+};
+
 void __init omap3xxx_powerdomains_init(void)
 {
        unsigned int rev;
@@ -301,21 +403,34 @@ void __init omap3xxx_powerdomains_init(void)
                return;
 
        pwrdm_register_platform_funcs(&omap3_pwrdm_operations);
-       pwrdm_register_pwrdms(powerdomains_omap3430_common);
 
        rev = omap_rev();
 
-       if (rev == OMAP3430_REV_ES1_0)
-               pwrdm_register_pwrdms(powerdomains_omap3430es1);
-       else if (rev == OMAP3430_REV_ES2_0 || rev == OMAP3430_REV_ES2_1 ||
-                rev == OMAP3430_REV_ES3_0 || rev == OMAP3630_REV_ES1_0)
-               pwrdm_register_pwrdms(powerdomains_omap3430es2_es3_0);
-       else if (rev == OMAP3430_REV_ES3_1 || rev == OMAP3430_REV_ES3_1_2 ||
-                rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1 ||
-                rev == OMAP3630_REV_ES1_1 || rev == OMAP3630_REV_ES1_2)
-               pwrdm_register_pwrdms(powerdomains_omap3430es3_1plus);
-       else
-               WARN(1, "OMAP3 powerdomain init: unknown chip type\n");
+       if (rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1) {
+               pwrdm_register_pwrdms(powerdomains_am35x);
+       } else {
+               pwrdm_register_pwrdms(powerdomains_omap3430_common);
+
+               switch (rev) {
+               case OMAP3430_REV_ES1_0:
+                       pwrdm_register_pwrdms(powerdomains_omap3430es1);
+                       break;
+               case OMAP3430_REV_ES2_0:
+               case OMAP3430_REV_ES2_1:
+               case OMAP3430_REV_ES3_0:
+               case OMAP3630_REV_ES1_0:
+                       pwrdm_register_pwrdms(powerdomains_omap3430es2_es3_0);
+                       break;
+               case OMAP3430_REV_ES3_1:
+               case OMAP3430_REV_ES3_1_2:
+               case OMAP3630_REV_ES1_1:
+               case OMAP3630_REV_ES1_2:
+                       pwrdm_register_pwrdms(powerdomains_omap3430es3_1plus);
+                       break;
+               default:
+                       WARN(1, "OMAP3 powerdomain init: unknown chip type\n");
+               }
+       }
 
        pwrdm_complete_init();
 }
index 6da3ba483ad118ea0b0e8082fa9e5e3417635465..e5f0503a68b09e5a2eff32e1a01350a33e32c91b 100644 (file)
 #define OMAP3430_EN_MMC2_SHIFT                         25
 #define OMAP3430_EN_MMC1_MASK                          (1 << 24)
 #define OMAP3430_EN_MMC1_SHIFT                         24
-#define OMAP3430_EN_UART4_MASK                         (1 << 23)
-#define OMAP3430_EN_UART4_SHIFT                                23
+#define AM35XX_EN_UART4_MASK                           (1 << 23)
+#define AM35XX_EN_UART4_SHIFT                          23
 #define OMAP3430_EN_MCSPI4_MASK                                (1 << 21)
 #define OMAP3430_EN_MCSPI4_SHIFT                       21
 #define OMAP3430_EN_MCSPI3_MASK                                (1 << 20)
  */
 #define MAX_MODULE_HARDRESET_WAIT              10000
 
+/*
+ * Maximum time(us) it takes to output the signal WUCLKOUT of the last
+ * pad of the I/O ring after asserting WUCLKIN high.  Tero measured
+ * the actual time at 7 to 8 microseconds on OMAP3 and 2 to 4
+ * microseconds on OMAP4, so this timeout may be too high.
+ */
+#define MAX_IOPAD_LATCH_TIME                   100
+
 # ifndef __ASSEMBLER__
 extern void __iomem *prm_base;
 extern void __iomem *cm_base;
 extern void __iomem *cm2_base;
 extern void __iomem *prcm_mpu_base;
 
-#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_ARCH_OMAP5)
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)
 extern void omap_prm_base_init(void);
 extern void omap_cm_base_init(void);
 #else
index 480f40a5ee4295ae6f8d587a51616d02557df75e..053e24ed3c48275b56dff00645a40602b1d8fb0d 100644 (file)
@@ -35,6 +35,7 @@
 #include "prm2xxx_3xxx.h"
 #include "prm44xx.h"
 #include "prminst44xx.h"
+#include "cminst44xx.h"
 #include "prm-regbits-24xx.h"
 #include "prm-regbits-44xx.h"
 #include "control.h"
@@ -159,8 +160,30 @@ void __init omap2_set_globals_prcm(struct omap_globals *omap2_globals)
        if (omap2_globals->prcm_mpu)
                prcm_mpu_base = omap2_globals->prcm_mpu;
 
-       if (cpu_is_omap44xx()) {
+       if (cpu_is_omap44xx() || soc_is_omap54xx()) {
                omap_prm_base_init();
                omap_cm_base_init();
        }
 }
+
+/*
+ * Stubbed functions so that common files continue to build when
+ * custom builds are used
+ * XXX These are temporary and should be removed at the earliest possible
+ * opportunity
+ */
+int __weak omap4_cminst_wait_module_idle(u8 part, u16 inst, s16 cdoffs,
+                                       u16 clkctrl_offs)
+{
+       return 0;
+}
+
+void __weak omap4_cminst_module_enable(u8 mode, u8 part, u16 inst,
+                               s16 cdoffs, u16 clkctrl_offs)
+{
+}
+
+void __weak omap4_cminst_module_disable(u8 part, u16 inst, s16 cdoffs,
+                                u16 clkctrl_offs)
+{
+}
diff --git a/arch/arm/mach-omap2/prm-regbits-33xx.h b/arch/arm/mach-omap2/prm-regbits-33xx.h
new file mode 100644 (file)
index 0000000..0221b5c
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+ * AM33XX PRM_XXX register bits
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_33XX_H
+#define __ARCH_ARM_MACH_OMAP2_PRM_REGBITS_33XX_H
+
+#include "prm.h"
+
+/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */
+#define AM33XX_ABBOFF_ACT_EXPORT_SHIFT                 1
+#define AM33XX_ABBOFF_ACT_EXPORT_MASK                  (1 << 1)
+
+/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */
+#define AM33XX_ABBOFF_SLEEP_EXPORT_SHIFT               2
+#define AM33XX_ABBOFF_SLEEP_EXPORT_MASK                        (1 << 2)
+
+/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */
+#define AM33XX_AIPOFF_SHIFT                            8
+#define AM33XX_AIPOFF_MASK                             (1 << 8)
+
+/* Used by PM_WKUP_PWRSTST */
+#define AM33XX_DEBUGSS_MEM_STATEST_SHIFT               17
+#define AM33XX_DEBUGSS_MEM_STATEST_MASK                        (0x3 << 17)
+
+/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */
+#define AM33XX_DISABLE_RTA_EXPORT_SHIFT                        0
+#define AM33XX_DISABLE_RTA_EXPORT_MASK                 (1 << 0)
+
+/* Used by PRM_IRQENABLE_M3, PRM_IRQENABLE_MPU */
+#define AM33XX_DPLL_CORE_RECAL_EN_SHIFT                        12
+#define AM33XX_DPLL_CORE_RECAL_EN_MASK                 (1 << 12)
+
+/* Used by PRM_IRQSTATUS_M3, PRM_IRQSTATUS_MPU */
+#define AM33XX_DPLL_CORE_RECAL_ST_SHIFT                        12
+#define AM33XX_DPLL_CORE_RECAL_ST_MASK                 (1 << 12)
+
+/* Used by PRM_IRQENABLE_M3, PRM_IRQENABLE_MPU */
+#define AM33XX_DPLL_DDR_RECAL_EN_SHIFT                 14
+#define AM33XX_DPLL_DDR_RECAL_EN_MASK                  (1 << 14)
+
+/* Used by PRM_IRQSTATUS_M3, PRM_IRQSTATUS_MPU */
+#define AM33XX_DPLL_DDR_RECAL_ST_SHIFT                 14
+#define AM33XX_DPLL_DDR_RECAL_ST_MASK                  (1 << 14)
+
+/* Used by PRM_IRQENABLE_M3, PRM_IRQENABLE_MPU */
+#define AM33XX_DPLL_DISP_RECAL_EN_SHIFT                        15
+#define AM33XX_DPLL_DISP_RECAL_EN_MASK                 (1 << 15)
+
+/* Used by PRM_IRQSTATUS_M3, PRM_IRQSTATUS_MPU */
+#define AM33XX_DPLL_DISP_RECAL_ST_SHIFT                        13
+#define AM33XX_DPLL_DISP_RECAL_ST_MASK                 (1 << 13)
+
+/* Used by PRM_IRQENABLE_M3, PRM_IRQENABLE_MPU */
+#define AM33XX_DPLL_MPU_RECAL_EN_SHIFT                 11
+#define AM33XX_DPLL_MPU_RECAL_EN_MASK                  (1 << 11)
+
+/* Used by PRM_IRQSTATUS_M3, PRM_IRQSTATUS_MPU */
+#define AM33XX_DPLL_MPU_RECAL_ST_SHIFT                 11
+#define AM33XX_DPLL_MPU_RECAL_ST_MASK                  (1 << 11)
+
+/* Used by PRM_IRQENABLE_M3, PRM_IRQENABLE_MPU */
+#define AM33XX_DPLL_PER_RECAL_EN_SHIFT                 13
+#define AM33XX_DPLL_PER_RECAL_EN_MASK                  (1 << 13)
+
+/* Used by PRM_IRQSTATUS_M3, PRM_IRQSTATUS_MPU */
+#define AM33XX_DPLL_PER_RECAL_ST_SHIFT                 15
+#define AM33XX_DPLL_PER_RECAL_ST_MASK                  (1 << 15)
+
+/* Used by RM_WKUP_RSTST */
+#define AM33XX_EMULATION_M3_RST_SHIFT                  6
+#define AM33XX_EMULATION_M3_RST_MASK                   (1 << 6)
+
+/* Used by RM_MPU_RSTST */
+#define AM33XX_EMULATION_MPU_RST_SHIFT                 5
+#define AM33XX_EMULATION_MPU_RST_MASK                  (1 << 5)
+
+/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */
+#define AM33XX_ENFUNC1_EXPORT_SHIFT                    3
+#define AM33XX_ENFUNC1_EXPORT_MASK                     (1 << 3)
+
+/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */
+#define AM33XX_ENFUNC3_EXPORT_SHIFT                    5
+#define AM33XX_ENFUNC3_EXPORT_MASK                     (1 << 5)
+
+/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */
+#define AM33XX_ENFUNC4_SHIFT                           6
+#define AM33XX_ENFUNC4_MASK                            (1 << 6)
+
+/* Used by PRM_LDO_SRAM_CORE_SETUP, PRM_LDO_SRAM_MPU_SETUP */
+#define AM33XX_ENFUNC5_SHIFT                           7
+#define AM33XX_ENFUNC5_MASK                            (1 << 7)
+
+/* Used by PRM_RSTST */
+#define AM33XX_EXTERNAL_WARM_RST_SHIFT                 5
+#define AM33XX_EXTERNAL_WARM_RST_MASK                  (1 << 5)
+
+/* Used by PRM_IRQENABLE_M3, PRM_IRQENABLE_MPU */
+#define AM33XX_FORCEWKUP_EN_SHIFT                      10
+#define AM33XX_FORCEWKUP_EN_MASK                       (1 << 10)
+
+/* Used by PRM_IRQSTATUS_M3, PRM_IRQSTATUS_MPU */
+#define AM33XX_FORCEWKUP_ST_SHIFT                      10
+#define AM33XX_FORCEWKUP_ST_MASK                       (1 << 10)
+
+/* Used by PM_GFX_PWRSTCTRL */
+#define AM33XX_GFX_MEM_ONSTATE_SHIFT                   17
+#define AM33XX_GFX_MEM_ONSTATE_MASK                    (0x3 << 17)
+
+/* Used by PM_GFX_PWRSTCTRL */
+#define AM33XX_GFX_MEM_RETSTATE_SHIFT                  6
+#define AM33XX_GFX_MEM_RETSTATE_MASK                   (1 << 6)
+
+/* Used by PM_GFX_PWRSTST */
+#define AM33XX_GFX_MEM_STATEST_SHIFT                   4
+#define AM33XX_GFX_MEM_STATEST_MASK                    (0x3 << 4)
+
+/* Used by RM_GFX_RSTCTRL, RM_GFX_RSTST */
+#define AM33XX_GFX_RST_SHIFT                           0
+#define AM33XX_GFX_RST_MASK                            (1 << 0)
+
+/* Used by PRM_RSTST */
+#define AM33XX_GLOBAL_COLD_RST_SHIFT                   0
+#define AM33XX_GLOBAL_COLD_RST_MASK                    (1 << 0)
+
+/* Used by PRM_RSTST */
+#define AM33XX_GLOBAL_WARM_SW_RST_SHIFT                        1
+#define AM33XX_GLOBAL_WARM_SW_RST_MASK                 (1 << 1)
+
+/* Used by RM_WKUP_RSTST */
+#define AM33XX_ICECRUSHER_M3_RST_SHIFT                 7
+#define AM33XX_ICECRUSHER_M3_RST_MASK                  (1 << 7)
+
+/* Used by RM_MPU_RSTST */
+#define AM33XX_ICECRUSHER_MPU_RST_SHIFT                        6
+#define AM33XX_ICECRUSHER_MPU_RST_MASK                 (1 << 6)
+
+/* Used by PRM_RSTST */
+#define AM33XX_ICEPICK_RST_SHIFT                       9
+#define AM33XX_ICEPICK_RST_MASK                                (1 << 9)
+
+/* Used by RM_PER_RSTCTRL */
+#define AM33XX_PRUSS_LRST_SHIFT                                1
+#define AM33XX_PRUSS_LRST_MASK                         (1 << 1)
+
+/* Used by PM_PER_PWRSTCTRL */
+#define AM33XX_PRUSS_MEM_ONSTATE_SHIFT                 5
+#define AM33XX_PRUSS_MEM_ONSTATE_MASK                  (0x3 << 5)
+
+/* Used by PM_PER_PWRSTCTRL */
+#define AM33XX_PRUSS_MEM_RETSTATE_SHIFT                        7
+#define AM33XX_PRUSS_MEM_RETSTATE_MASK                 (1 << 7)
+
+/* Used by PM_PER_PWRSTST */
+#define AM33XX_PRUSS_MEM_STATEST_SHIFT                 23
+#define AM33XX_PRUSS_MEM_STATEST_MASK                  (0x3 << 23)
+
+/*
+ * Used by PM_GFX_PWRSTST, PM_CEFUSE_PWRSTST, PM_PER_PWRSTST, PM_MPU_PWRSTST,
+ * PM_WKUP_PWRSTST, PM_RTC_PWRSTST
+ */
+#define AM33XX_INTRANSITION_SHIFT                      20
+#define AM33XX_INTRANSITION_MASK                       (1 << 20)
+
+/* Used by PM_CEFUSE_PWRSTST */
+#define AM33XX_LASTPOWERSTATEENTERED_SHIFT             24
+#define AM33XX_LASTPOWERSTATEENTERED_MASK              (0x3 << 24)
+
+/* Used by PM_GFX_PWRSTCTRL, PM_MPU_PWRSTCTRL, PM_RTC_PWRSTCTRL */
+#define AM33XX_LOGICRETSTATE_SHIFT                     2
+#define AM33XX_LOGICRETSTATE_MASK                      (1 << 2)
+
+/* Renamed from LOGICRETSTATE Used by PM_PER_PWRSTCTRL, PM_WKUP_PWRSTCTRL */
+#define AM33XX_LOGICRETSTATE_3_3_SHIFT                 3
+#define AM33XX_LOGICRETSTATE_3_3_MASK                  (1 << 3)
+
+/*
+ * Used by PM_GFX_PWRSTST, PM_CEFUSE_PWRSTST, PM_PER_PWRSTST, PM_MPU_PWRSTST,
+ * PM_WKUP_PWRSTST, PM_RTC_PWRSTST
+ */
+#define AM33XX_LOGICSTATEST_SHIFT                      2
+#define AM33XX_LOGICSTATEST_MASK                       (1 << 2)
+
+/*
+ * Used by PM_GFX_PWRSTCTRL, PM_CEFUSE_PWRSTCTRL, PM_PER_PWRSTCTRL,
+ * PM_MPU_PWRSTCTRL, PM_WKUP_PWRSTCTRL, PM_RTC_PWRSTCTRL
+ */
+#define AM33XX_LOWPOWERSTATECHANGE_SHIFT               4
+#define AM33XX_LOWPOWERSTATECHANGE_MASK                        (1 << 4)
+
+/* Used by PM_MPU_PWRSTCTRL */
+#define AM33XX_MPU_L1_ONSTATE_SHIFT                    18
+#define AM33XX_MPU_L1_ONSTATE_MASK                     (0x3 << 18)
+
+/* Used by PM_MPU_PWRSTCTRL */
+#define AM33XX_MPU_L1_RETSTATE_SHIFT                   22
+#define AM33XX_MPU_L1_RETSTATE_MASK                    (1 << 22)
+
+/* Used by PM_MPU_PWRSTST */
+#define AM33XX_MPU_L1_STATEST_SHIFT                    6
+#define AM33XX_MPU_L1_STATEST_MASK                     (0x3 << 6)
+
+/* Used by PM_MPU_PWRSTCTRL */
+#define AM33XX_MPU_L2_ONSTATE_SHIFT                    20
+#define AM33XX_MPU_L2_ONSTATE_MASK                     (0x3 << 20)
+
+/* Used by PM_MPU_PWRSTCTRL */
+#define AM33XX_MPU_L2_RETSTATE_SHIFT                   23
+#define AM33XX_MPU_L2_RETSTATE_MASK                    (1 << 23)
+
+/* Used by PM_MPU_PWRSTST */
+#define AM33XX_MPU_L2_STATEST_SHIFT                    8
+#define AM33XX_MPU_L2_STATEST_MASK                     (0x3 << 8)
+
+/* Used by PM_MPU_PWRSTCTRL */
+#define AM33XX_MPU_RAM_ONSTATE_SHIFT                   16
+#define AM33XX_MPU_RAM_ONSTATE_MASK                    (0x3 << 16)
+
+/* Used by PM_MPU_PWRSTCTRL */
+#define AM33XX_MPU_RAM_RETSTATE_SHIFT                  24
+#define AM33XX_MPU_RAM_RETSTATE_MASK                   (1 << 24)
+
+/* Used by PM_MPU_PWRSTST */
+#define AM33XX_MPU_RAM_STATEST_SHIFT                   4
+#define AM33XX_MPU_RAM_STATEST_MASK                    (0x3 << 4)
+
+/* Used by PRM_RSTST */
+#define AM33XX_MPU_SECURITY_VIOL_RST_SHIFT             2
+#define AM33XX_MPU_SECURITY_VIOL_RST_MASK              (1 << 2)
+
+/* Used by PRM_SRAM_COUNT */
+#define AM33XX_PCHARGECNT_VALUE_SHIFT                  0
+#define AM33XX_PCHARGECNT_VALUE_MASK                   (0x3f << 0)
+
+/* Used by RM_PER_RSTCTRL */
+#define AM33XX_PCI_LRST_SHIFT                          0
+#define AM33XX_PCI_LRST_MASK                           (1 << 0)
+
+/* Renamed from PCI_LRST Used by RM_PER_RSTST */
+#define AM33XX_PCI_LRST_5_5_SHIFT                      5
+#define AM33XX_PCI_LRST_5_5_MASK                       (1 << 5)
+
+/* Used by PM_PER_PWRSTCTRL */
+#define AM33XX_PER_MEM_ONSTATE_SHIFT                   25
+#define AM33XX_PER_MEM_ONSTATE_MASK                    (0x3 << 25)
+
+/* Used by PM_PER_PWRSTCTRL */
+#define AM33XX_PER_MEM_RETSTATE_SHIFT                  29
+#define AM33XX_PER_MEM_RETSTATE_MASK                   (1 << 29)
+
+/* Used by PM_PER_PWRSTST */
+#define AM33XX_PER_MEM_STATEST_SHIFT                   17
+#define AM33XX_PER_MEM_STATEST_MASK                    (0x3 << 17)
+
+/*
+ * Used by PM_GFX_PWRSTCTRL, PM_CEFUSE_PWRSTCTRL, PM_PER_PWRSTCTRL,
+ * PM_MPU_PWRSTCTRL
+ */
+#define AM33XX_POWERSTATE_SHIFT                                0
+#define AM33XX_POWERSTATE_MASK                         (0x3 << 0)
+
+/* Used by PM_GFX_PWRSTST, PM_CEFUSE_PWRSTST, PM_PER_PWRSTST, PM_MPU_PWRSTST */
+#define AM33XX_POWERSTATEST_SHIFT                      0
+#define AM33XX_POWERSTATEST_MASK                       (0x3 << 0)
+
+/* Used by PM_PER_PWRSTCTRL */
+#define AM33XX_RAM_MEM_ONSTATE_SHIFT                   30
+#define AM33XX_RAM_MEM_ONSTATE_MASK                    (0x3 << 30)
+
+/* Used by PM_PER_PWRSTCTRL */
+#define AM33XX_RAM_MEM_RETSTATE_SHIFT                  27
+#define AM33XX_RAM_MEM_RETSTATE_MASK                   (1 << 27)
+
+/* Used by PM_PER_PWRSTST */
+#define AM33XX_RAM_MEM_STATEST_SHIFT                   21
+#define AM33XX_RAM_MEM_STATEST_MASK                    (0x3 << 21)
+
+/* Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_MPU_CTRL */
+#define AM33XX_RETMODE_ENABLE_SHIFT                    0
+#define AM33XX_RETMODE_ENABLE_MASK                     (1 << 0)
+
+/* Used by REVISION_PRM */
+#define AM33XX_REV_SHIFT                               0
+#define AM33XX_REV_MASK                                        (0xff << 0)
+
+/* Used by PRM_RSTTIME */
+#define AM33XX_RSTTIME1_SHIFT                          0
+#define AM33XX_RSTTIME1_MASK                           (0xff << 0)
+
+/* Used by PRM_RSTTIME */
+#define AM33XX_RSTTIME2_SHIFT                          8
+#define AM33XX_RSTTIME2_MASK                           (0x1f << 8)
+
+/* Used by PRM_RSTCTRL */
+#define AM33XX_RST_GLOBAL_COLD_SW_SHIFT                        1
+#define AM33XX_RST_GLOBAL_COLD_SW_MASK                 (1 << 1)
+
+/* Used by PRM_RSTCTRL */
+#define AM33XX_RST_GLOBAL_WARM_SW_SHIFT                        0
+#define AM33XX_RST_GLOBAL_WARM_SW_MASK                 (1 << 0)
+
+/* Used by PRM_SRAM_COUNT */
+#define AM33XX_SLPCNT_VALUE_SHIFT                      16
+#define AM33XX_SLPCNT_VALUE_MASK                       (0xff << 16)
+
+/* Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_MPU_CTRL */
+#define AM33XX_SRAMLDO_STATUS_SHIFT                    8
+#define AM33XX_SRAMLDO_STATUS_MASK                     (1 << 8)
+
+/* Used by PRM_LDO_SRAM_CORE_CTRL, PRM_LDO_SRAM_MPU_CTRL */
+#define AM33XX_SRAM_IN_TRANSITION_SHIFT                        9
+#define AM33XX_SRAM_IN_TRANSITION_MASK                 (1 << 9)
+
+/* Used by PRM_SRAM_COUNT */
+#define AM33XX_STARTUP_COUNT_SHIFT                     24
+#define AM33XX_STARTUP_COUNT_MASK                      (0xff << 24)
+
+/* Used by PRM_IRQENABLE_M3, PRM_IRQENABLE_MPU */
+#define AM33XX_TRANSITION_EN_SHIFT                     8
+#define AM33XX_TRANSITION_EN_MASK                      (1 << 8)
+
+/* Used by PRM_IRQSTATUS_M3, PRM_IRQSTATUS_MPU */
+#define AM33XX_TRANSITION_ST_SHIFT                     8
+#define AM33XX_TRANSITION_ST_MASK                      (1 << 8)
+
+/* Used by PRM_SRAM_COUNT */
+#define AM33XX_VSETUPCNT_VALUE_SHIFT                   8
+#define AM33XX_VSETUPCNT_VALUE_MASK                    (0xff << 8)
+
+/* Used by PRM_RSTST */
+#define AM33XX_WDT0_RST_SHIFT                          3
+#define AM33XX_WDT0_RST_MASK                           (1 << 3)
+
+/* Used by PRM_RSTST */
+#define AM33XX_WDT1_RST_SHIFT                          4
+#define AM33XX_WDT1_RST_MASK                           (1 << 4)
+
+/* Used by RM_WKUP_RSTCTRL */
+#define AM33XX_WKUP_M3_LRST_SHIFT                      3
+#define AM33XX_WKUP_M3_LRST_MASK                       (1 << 3)
+
+/* Renamed from WKUP_M3_LRST Used by RM_WKUP_RSTST */
+#define AM33XX_WKUP_M3_LRST_5_5_SHIFT                  5
+#define AM33XX_WKUP_M3_LRST_5_5_MASK                   (1 << 5)
+
+#endif
index 21cb74003a562f27bc2a5a8538093d92503c44d0..a0309dea67945eb218ff622e3a4826fad252c083 100644 (file)
@@ -302,11 +302,59 @@ void omap3xxx_prm_restore_irqen(u32 *saved_mask)
                                OMAP3_PRM_IRQENABLE_MPU_OFFSET);
 }
 
+/**
+ * omap3xxx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
+ *
+ * Clear any previously-latched I/O wakeup events and ensure that the
+ * I/O wakeup gates are aligned with the current mux settings.  Works
+ * by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
+ * deasserting WUCLKIN and clearing the ST_IO_CHAIN WKST bit.  No
+ * return value.
+ */
+void omap3xxx_prm_reconfigure_io_chain(void)
+{
+       int i = 0;
+
+       omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+                                  PM_WKEN);
+
+       omap_test_timeout(omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST) &
+                         OMAP3430_ST_IO_CHAIN_MASK,
+                         MAX_IOPAD_LATCH_TIME, i);
+       if (i == MAX_IOPAD_LATCH_TIME)
+               pr_warn("PRM: I/O chain clock line assertion timed out\n");
+
+       omap2_prm_clear_mod_reg_bits(OMAP3430_EN_IO_CHAIN_MASK, WKUP_MOD,
+                                    PM_WKEN);
+
+       omap2_prm_set_mod_reg_bits(OMAP3430_ST_IO_CHAIN_MASK, WKUP_MOD,
+                                  PM_WKST);
+
+       omap2_prm_read_mod_reg(WKUP_MOD, PM_WKST);
+}
+
+/**
+ * omap3xxx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
+ *
+ * Activates the I/O wakeup event latches and allows events logged by
+ * those latches to signal a wakeup event to the PRCM.  For I/O
+ * wakeups to occur, WAKEUPENABLE bits must be set in the pad mux
+ * registers, and omap3xxx_prm_reconfigure_io_chain() must be called.
+ * No return value.
+ */
+static void __init omap3xxx_prm_enable_io_wakeup(void)
+{
+       if (omap3_has_io_wakeup())
+               omap2_prm_set_mod_reg_bits(OMAP3430_EN_IO_MASK, WKUP_MOD,
+                                          PM_WKEN);
+}
+
 static int __init omap3xxx_prcm_init(void)
 {
        int ret = 0;
 
        if (cpu_is_omap34xx()) {
+               omap3xxx_prm_enable_io_wakeup();
                ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup);
                if (!ret)
                        irq_set_status_flags(omap_prcm_event_to_irq("io"),
index 70ac2a19dc5f9d3bea6b0cc2d290bb171b7697e2..c19d249b481675557f36ebdf315b23c5752d1d4b 100644 (file)
 
 
 #ifndef __ASSEMBLER__
-/*
- * Stub omap2xxx/omap3xxx functions so that common files
- * continue to build when custom builds are used
- */
-#if defined(CONFIG_ARCH_OMAP4) && !(defined(CONFIG_ARCH_OMAP2) ||      \
-                                       defined(CONFIG_ARCH_OMAP3))
-static inline u32 omap2_prm_read_mod_reg(s16 module, u16 idx)
-{
-       WARN(1, "prm: omap2xxx/omap3xxx specific function and "
-               "not suppose to be used on omap4\n");
-       return 0;
-}
-static inline void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx)
-{
-       WARN(1, "prm: omap2xxx/omap3xxx specific function and "
-               "not suppose to be used on omap4\n");
-}
-static inline u32 omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits,
-               s16 module, s16 idx)
-{
-       WARN(1, "prm: omap2xxx/omap3xxx specific function and "
-               "not suppose to be used on omap4\n");
-       return 0;
-}
-static inline u32 omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
-{
-       WARN(1, "prm: omap2xxx/omap3xxx specific function and "
-               "not suppose to be used on omap4\n");
-       return 0;
-}
-static inline u32 omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
-{
-       WARN(1, "prm: omap2xxx/omap3xxx specific function and "
-               "not suppose to be used on omap4\n");
-       return 0;
-}
-static inline u32 omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
-{
-       WARN(1, "prm: omap2xxx/omap3xxx specific function and "
-               "not suppose to be used on omap4\n");
-       return 0;
-}
-static inline int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
-{
-       WARN(1, "prm: omap2xxx/omap3xxx specific function and "
-               "not suppose to be used on omap4\n");
-       return 0;
-}
-static inline int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
-{
-       WARN(1, "prm: omap2xxx/omap3xxx specific function and "
-               "not suppose to be used on omap4\n");
-       return 0;
-}
-static inline int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift,
-                                               u8 st_shift)
-{
-       WARN(1, "prm: omap2xxx/omap3xxx specific function and "
-               "not suppose to be used on omap4\n");
-       return 0;
-}
-#else
 /* Power/reset management domain register get/set */
 extern u32 omap2_prm_read_mod_reg(s16 module, u16 idx);
 extern void omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx);
@@ -315,15 +253,15 @@ extern u32 omap3_prm_vcvp_read(u8 offset);
 extern void omap3_prm_vcvp_write(u32 val, u8 offset);
 extern u32 omap3_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
 
+extern void omap3xxx_prm_reconfigure_io_chain(void);
+
 /* PRM interrupt-related functions */
 extern void omap3xxx_prm_read_pending_irqs(unsigned long *events);
 extern void omap3xxx_prm_ocp_barrier(void);
 extern void omap3xxx_prm_save_and_clear_irqen(u32 *saved_mask);
 extern void omap3xxx_prm_restore_irqen(u32 *saved_mask);
 
-#endif /* CONFIG_ARCH_OMAP4 */
-
-#endif
+#endif /* __ASSEMBLER */
 
 /*
  * Bits common to specific registers
diff --git a/arch/arm/mach-omap2/prm33xx.c b/arch/arm/mach-omap2/prm33xx.c
new file mode 100644 (file)
index 0000000..e7dbb6c
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * AM33XX PRM functions
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/io.h>
+
+#include <plat/common.h>
+
+#include "common.h"
+#include "prm33xx.h"
+#include "prm-regbits-33xx.h"
+
+/* Read a register in a PRM instance */
+u32 am33xx_prm_read_reg(s16 inst, u16 idx)
+{
+       return __raw_readl(prm_base + inst + idx);
+}
+
+/* Write into a register in a PRM instance */
+void am33xx_prm_write_reg(u32 val, s16 inst, u16 idx)
+{
+       __raw_writel(val, prm_base + inst + idx);
+}
+
+/* Read-modify-write a register in PRM. Caller must lock */
+u32 am33xx_prm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx)
+{
+       u32 v;
+
+       v = am33xx_prm_read_reg(inst, idx);
+       v &= ~mask;
+       v |= bits;
+       am33xx_prm_write_reg(v, inst, idx);
+
+       return v;
+}
+
+/**
+ * am33xx_prm_is_hardreset_asserted - read the HW reset line state of
+ * submodules contained in the hwmod module
+ * @shift: register bit shift corresponding to the reset line to check
+ * @inst: CM instance register offset (*_INST macro)
+ * @rstctrl_offs: RM_RSTCTRL register address offset for this module
+ *
+ * Returns 1 if the (sub)module hardreset line is currently asserted,
+ * 0 if the (sub)module hardreset line is not currently asserted, or
+ * -EINVAL upon parameter error.
+ */
+int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst, u16 rstctrl_offs)
+{
+       u32 v;
+
+       v = am33xx_prm_read_reg(inst, rstctrl_offs);
+       v &= 1 << shift;
+       v >>= shift;
+
+       return v;
+}
+
+/**
+ * am33xx_prm_assert_hardreset - assert the HW reset line of a submodule
+ * @shift: register bit shift corresponding to the reset line to assert
+ * @inst: CM instance register offset (*_INST macro)
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * place the submodule into reset.  Returns 0 upon success or -EINVAL
+ * upon an argument error.
+ */
+int am33xx_prm_assert_hardreset(u8 shift, s16 inst, u16 rstctrl_offs)
+{
+       u32 mask = 1 << shift;
+
+       am33xx_prm_rmw_reg_bits(mask, mask, inst, rstctrl_offs);
+
+       return 0;
+}
+
+/**
+ * am33xx_prm_deassert_hardreset - deassert a submodule hardreset line and
+ * wait
+ * @shift: register bit shift corresponding to the reset line to deassert
+ * @inst: CM instance register offset (*_INST macro)
+ * @rstctrl_reg: RM_RSTCTRL register address for this module
+ * @rstst_reg: RM_RSTST register address for this module
+ *
+ * Some IPs like dsp, ipu or iva contain processors that require an HW
+ * reset line to be asserted / deasserted in order to fully enable the
+ * IP.  These modules may have multiple hard-reset lines that reset
+ * different 'submodules' inside the IP block.  This function will
+ * take the submodule out of reset and wait until the PRCM indicates
+ * that the reset has completed before returning.  Returns 0 upon success or
+ * -EINVAL upon an argument error, -EEXIST if the submodule was already out
+ * of reset, or -EBUSY if the submodule did not exit reset promptly.
+ */
+int am33xx_prm_deassert_hardreset(u8 shift, s16 inst,
+               u16 rstctrl_offs, u16 rstst_offs)
+{
+       int c;
+       u32 mask = 1 << shift;
+
+       /* Check the current status to avoid  de-asserting the line twice */
+       if (am33xx_prm_is_hardreset_asserted(shift, inst, rstctrl_offs) == 0)
+               return -EEXIST;
+
+       /* Clear the reset status by writing 1 to the status bit */
+       am33xx_prm_rmw_reg_bits(0xffffffff, mask, inst, rstst_offs);
+       /* de-assert the reset control line */
+       am33xx_prm_rmw_reg_bits(mask, 0, inst, rstctrl_offs);
+       /* wait the status to be set */
+
+       omap_test_timeout(am33xx_prm_is_hardreset_asserted(shift, inst,
+                                                          rstst_offs),
+                         MAX_MODULE_HARDRESET_WAIT, c);
+
+       return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
+}
diff --git a/arch/arm/mach-omap2/prm33xx.h b/arch/arm/mach-omap2/prm33xx.h
new file mode 100644 (file)
index 0000000..3f25c56
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * AM33XX PRM instance offset macros
+ *
+ * Copyright (C) 2011-2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_OMAP2_PRM33XX_H
+#define __ARCH_ARM_MACH_OMAP2_PRM33XX_H
+
+#include "prcm-common.h"
+#include "prm.h"
+
+#define AM33XX_PRM_BASE               0x44E00000
+
+#define AM33XX_PRM_REGADDR(inst, reg)                         \
+       AM33XX_L4_WK_IO_ADDRESS(AM33XX_PRM_BASE + (inst) + (reg))
+
+
+/* PRM instances */
+#define AM33XX_PRM_OCP_SOCKET_MOD      0x0B00
+#define AM33XX_PRM_PER_MOD             0x0C00
+#define AM33XX_PRM_WKUP_MOD            0x0D00
+#define AM33XX_PRM_MPU_MOD             0x0E00
+#define AM33XX_PRM_DEVICE_MOD          0x0F00
+#define AM33XX_PRM_RTC_MOD             0x1000
+#define AM33XX_PRM_GFX_MOD             0x1100
+#define AM33XX_PRM_CEFUSE_MOD          0x1200
+
+/* PRM */
+
+/* PRM.OCP_SOCKET_PRM register offsets */
+#define AM33XX_REVISION_PRM_OFFSET             0x0000
+#define AM33XX_REVISION_PRM                    AM33XX_PRM_REGADDR(AM33XX_PRM_OCP_SOCKET_MOD, 0x0000)
+#define AM33XX_PRM_IRQSTATUS_MPU_OFFSET                0x0004
+#define AM33XX_PRM_IRQSTATUS_MPU               AM33XX_PRM_REGADDR(AM33XX_PRM_OCP_SOCKET_MOD, 0x0004)
+#define AM33XX_PRM_IRQENABLE_MPU_OFFSET                0x0008
+#define AM33XX_PRM_IRQENABLE_MPU               AM33XX_PRM_REGADDR(AM33XX_PRM_OCP_SOCKET_MOD, 0x0008)
+#define AM33XX_PRM_IRQSTATUS_M3_OFFSET         0x000c
+#define AM33XX_PRM_IRQSTATUS_M3                        AM33XX_PRM_REGADDR(AM33XX_PRM_OCP_SOCKET_MOD, 0x000c)
+#define AM33XX_PRM_IRQENABLE_M3_OFFSET         0x0010
+#define AM33XX_PRM_IRQENABLE_M3                        AM33XX_PRM_REGADDR(AM33XX_PRM_OCP_SOCKET_MOD, 0x0010)
+
+/* PRM.PER_PRM register offsets */
+#define AM33XX_RM_PER_RSTCTRL_OFFSET           0x0000
+#define AM33XX_RM_PER_RSTCTRL                  AM33XX_PRM_REGADDR(AM33XX_PRM_PER_MOD, 0x0000)
+#define AM33XX_RM_PER_RSTST_OFFSET             0x0004
+#define AM33XX_RM_PER_RSTST                    AM33XX_PRM_REGADDR(AM33XX_PRM_PER_MOD, 0x0004)
+#define AM33XX_PM_PER_PWRSTST_OFFSET           0x0008
+#define AM33XX_PM_PER_PWRSTST                  AM33XX_PRM_REGADDR(AM33XX_PRM_PER_MOD, 0x0008)
+#define AM33XX_PM_PER_PWRSTCTRL_OFFSET         0x000c
+#define AM33XX_PM_PER_PWRSTCTRL                        AM33XX_PRM_REGADDR(AM33XX_PRM_PER_MOD, 0x000c)
+
+/* PRM.WKUP_PRM register offsets */
+#define AM33XX_RM_WKUP_RSTCTRL_OFFSET          0x0000
+#define AM33XX_RM_WKUP_RSTCTRL                 AM33XX_PRM_REGADDR(AM33XX_PRM_WKUP_MOD, 0x0000)
+#define AM33XX_PM_WKUP_PWRSTCTRL_OFFSET                0x0004
+#define AM33XX_PM_WKUP_PWRSTCTRL               AM33XX_PRM_REGADDR(AM33XX_PRM_WKUP_MOD, 0x0004)
+#define AM33XX_PM_WKUP_PWRSTST_OFFSET          0x0008
+#define AM33XX_PM_WKUP_PWRSTST                 AM33XX_PRM_REGADDR(AM33XX_PRM_WKUP_MOD, 0x0008)
+#define AM33XX_RM_WKUP_RSTST_OFFSET            0x000c
+#define AM33XX_RM_WKUP_RSTST                   AM33XX_PRM_REGADDR(AM33XX_PRM_WKUP_MOD, 0x000c)
+
+/* PRM.MPU_PRM register offsets */
+#define AM33XX_PM_MPU_PWRSTCTRL_OFFSET         0x0000
+#define AM33XX_PM_MPU_PWRSTCTRL                        AM33XX_PRM_REGADDR(AM33XX_PRM_MPU_MOD, 0x0000)
+#define AM33XX_PM_MPU_PWRSTST_OFFSET           0x0004
+#define AM33XX_PM_MPU_PWRSTST                  AM33XX_PRM_REGADDR(AM33XX_PRM_MPU_MOD, 0x0004)
+#define AM33XX_RM_MPU_RSTST_OFFSET             0x0008
+#define AM33XX_RM_MPU_RSTST                    AM33XX_PRM_REGADDR(AM33XX_PRM_MPU_MOD, 0x0008)
+
+/* PRM.DEVICE_PRM register offsets */
+#define AM33XX_PRM_RSTCTRL_OFFSET              0x0000
+#define AM33XX_PRM_RSTCTRL                     AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x0000)
+#define AM33XX_PRM_RSTTIME_OFFSET              0x0004
+#define AM33XX_PRM_RSTTIME                     AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x0004)
+#define AM33XX_PRM_RSTST_OFFSET                        0x0008
+#define AM33XX_PRM_RSTST                       AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x0008)
+#define AM33XX_PRM_SRAM_COUNT_OFFSET           0x000c
+#define AM33XX_PRM_SRAM_COUNT                  AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x000c)
+#define AM33XX_PRM_LDO_SRAM_CORE_SETUP_OFFSET  0x0010
+#define AM33XX_PRM_LDO_SRAM_CORE_SETUP         AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x0010)
+#define AM33XX_PRM_LDO_SRAM_CORE_CTRL_OFFSET   0x0014
+#define AM33XX_PRM_LDO_SRAM_CORE_CTRL          AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x0014)
+#define AM33XX_PRM_LDO_SRAM_MPU_SETUP_OFFSET   0x0018
+#define AM33XX_PRM_LDO_SRAM_MPU_SETUP          AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x0018)
+#define AM33XX_PRM_LDO_SRAM_MPU_CTRL_OFFSET    0x001c
+#define AM33XX_PRM_LDO_SRAM_MPU_CTRL           AM33XX_PRM_REGADDR(AM33XX_PRM_DEVICE_MOD, 0x001c)
+
+/* PRM.RTC_PRM register offsets */
+#define AM33XX_PM_RTC_PWRSTCTRL_OFFSET         0x0000
+#define AM33XX_PM_RTC_PWRSTCTRL                        AM33XX_PRM_REGADDR(AM33XX_PRM_RTC_MOD, 0x0000)
+#define AM33XX_PM_RTC_PWRSTST_OFFSET           0x0004
+#define AM33XX_PM_RTC_PWRSTST                  AM33XX_PRM_REGADDR(AM33XX_PRM_RTC_MOD, 0x0004)
+
+/* PRM.GFX_PRM register offsets */
+#define AM33XX_PM_GFX_PWRSTCTRL_OFFSET         0x0000
+#define AM33XX_PM_GFX_PWRSTCTRL                        AM33XX_PRM_REGADDR(AM33XX_PRM_GFX_MOD, 0x0000)
+#define AM33XX_RM_GFX_RSTCTRL_OFFSET           0x0004
+#define AM33XX_RM_GFX_RSTCTRL                  AM33XX_PRM_REGADDR(AM33XX_PRM_GFX_MOD, 0x0004)
+#define AM33XX_PM_GFX_PWRSTST_OFFSET           0x0010
+#define AM33XX_PM_GFX_PWRSTST                  AM33XX_PRM_REGADDR(AM33XX_PRM_GFX_MOD, 0x0010)
+#define AM33XX_RM_GFX_RSTST_OFFSET             0x0014
+#define AM33XX_RM_GFX_RSTST                    AM33XX_PRM_REGADDR(AM33XX_PRM_GFX_MOD, 0x0014)
+
+/* PRM.CEFUSE_PRM register offsets */
+#define AM33XX_PM_CEFUSE_PWRSTCTRL_OFFSET      0x0000
+#define AM33XX_PM_CEFUSE_PWRSTCTRL             AM33XX_PRM_REGADDR(AM33XX_PRM_CEFUSE_MOD, 0x0000)
+#define AM33XX_PM_CEFUSE_PWRSTST_OFFSET                0x0004
+#define AM33XX_PM_CEFUSE_PWRSTST               AM33XX_PRM_REGADDR(AM33XX_PRM_CEFUSE_MOD, 0x0004)
+
+extern u32 am33xx_prm_read_reg(s16 inst, u16 idx);
+extern void am33xx_prm_write_reg(u32 val, s16 inst, u16 idx);
+extern u32 am33xx_prm_rmw_reg_bits(u32 mask, u32 bits, s16 inst, s16 idx);
+extern void am33xx_prm_global_warm_sw_reset(void);
+extern int am33xx_prm_is_hardreset_asserted(u8 shift, s16 inst,
+               u16 rstctrl_offs);
+extern int am33xx_prm_assert_hardreset(u8 shift, s16 inst, u16 rstctrl_offs);
+extern int am33xx_prm_deassert_hardreset(u8 shift, s16 inst,
+               u16 rstctrl_offs, u16 rstst_offs);
+#endif
index f106d21ff581a3af4894fd45f58fe53aaebc6dd2..bb727c2d9337b73358c6e6509fdd1bef14425ffe 100644 (file)
@@ -233,10 +233,71 @@ void omap44xx_prm_restore_irqen(u32 *saved_mask)
                                 OMAP4_PRM_IRQENABLE_MPU_2_OFFSET);
 }
 
+/**
+ * omap44xx_prm_reconfigure_io_chain - clear latches and reconfigure I/O chain
+ *
+ * Clear any previously-latched I/O wakeup events and ensure that the
+ * I/O wakeup gates are aligned with the current mux settings.  Works
+ * by asserting WUCLKIN, waiting for WUCLKOUT to be asserted, and then
+ * deasserting WUCLKIN and waiting for WUCLKOUT to be deasserted.
+ * No return value. XXX Are the final two steps necessary?
+ */
+void omap44xx_prm_reconfigure_io_chain(void)
+{
+       int i = 0;
+
+       /* Trigger WUCLKIN enable */
+       omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK,
+                                   OMAP4430_WUCLK_CTRL_MASK,
+                                   OMAP4430_PRM_DEVICE_INST,
+                                   OMAP4_PRM_IO_PMCTRL_OFFSET);
+       omap_test_timeout(
+               (((omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+                                          OMAP4_PRM_IO_PMCTRL_OFFSET) &
+                  OMAP4430_WUCLK_STATUS_MASK) >>
+                 OMAP4430_WUCLK_STATUS_SHIFT) == 1),
+               MAX_IOPAD_LATCH_TIME, i);
+       if (i == MAX_IOPAD_LATCH_TIME)
+               pr_warn("PRM: I/O chain clock line assertion timed out\n");
+
+       /* Trigger WUCLKIN disable */
+       omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, 0x0,
+                                   OMAP4430_PRM_DEVICE_INST,
+                                   OMAP4_PRM_IO_PMCTRL_OFFSET);
+       omap_test_timeout(
+               (((omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST,
+                                          OMAP4_PRM_IO_PMCTRL_OFFSET) &
+                  OMAP4430_WUCLK_STATUS_MASK) >>
+                 OMAP4430_WUCLK_STATUS_SHIFT) == 0),
+               MAX_IOPAD_LATCH_TIME, i);
+       if (i == MAX_IOPAD_LATCH_TIME)
+               pr_warn("PRM: I/O chain clock line deassertion timed out\n");
+
+       return;
+}
+
+/**
+ * omap44xx_prm_enable_io_wakeup - enable wakeup events from I/O wakeup latches
+ *
+ * Activates the I/O wakeup event latches and allows events logged by
+ * those latches to signal a wakeup event to the PRCM.  For I/O wakeups
+ * to occur, WAKEUPENABLE bits must be set in the pad mux registers, and
+ * omap44xx_prm_reconfigure_io_chain() must be called.  No return value.
+ */
+static void __init omap44xx_prm_enable_io_wakeup(void)
+{
+       omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK,
+                                   OMAP4430_GLOBAL_WUEN_MASK,
+                                   OMAP4430_PRM_DEVICE_INST,
+                                   OMAP4_PRM_IO_PMCTRL_OFFSET);
+}
+
 static int __init omap4xxx_prcm_init(void)
 {
-       if (cpu_is_omap44xx())
+       if (cpu_is_omap44xx()) {
+               omap44xx_prm_enable_io_wakeup();
                return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup);
+       }
        return 0;
 }
 subsys_initcall(omap4xxx_prcm_init);
index 7978092946db5a64ec37e4c66d7f992267ba2914..ee72ae6bd8c961350be2ebb343a027f6d1f4fddf 100644 (file)
@@ -763,6 +763,8 @@ extern u32 omap4_prm_vcvp_read(u8 offset);
 extern void omap4_prm_vcvp_write(u32 val, u8 offset);
 extern u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset);
 
+extern void omap44xx_prm_reconfigure_io_chain(void);
+
 /* PRM interrupt-related functions */
 extern void omap44xx_prm_read_pending_irqs(unsigned long *events);
 extern void omap44xx_prm_ocp_barrier(void);
index dfe00ddb5c60f6d3beda1e5955251c459e0e0c7a..03b126d9ad9427bbb5027b3c740e52ca89daba57 100644 (file)
@@ -85,7 +85,7 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
        unsigned long priority_pending[OMAP_PRCM_MAX_NR_PENDING_REG];
        struct irq_chip *chip = irq_desc_get_chip(desc);
        unsigned int virtirq;
-       int nr_irqs = prcm_irq_setup->nr_regs * 32;
+       int nr_irq = prcm_irq_setup->nr_regs * 32;
 
        /*
         * If we are suspended, mask all interrupts from PRCM level,
@@ -110,7 +110,7 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
                prcm_irq_setup->read_pending_irqs(pending);
 
                /* No bit set, then all IRQs are handled */
-               if (find_first_bit(pending, nr_irqs) >= nr_irqs)
+               if (find_first_bit(pending, nr_irq) >= nr_irq)
                        break;
 
                omap_prcm_events_filter_priority(pending, priority_pending);
@@ -121,11 +121,11 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
                 */
 
                /* Serve priority events first */
-               for_each_set_bit(virtirq, priority_pending, nr_irqs)
+               for_each_set_bit(virtirq, priority_pending, nr_irq)
                        generic_handle_irq(prcm_irq_setup->base_irq + virtirq);
 
                /* Serve normal events next */
-               for_each_set_bit(virtirq, pending, nr_irqs)
+               for_each_set_bit(virtirq, pending, nr_irq)
                        generic_handle_irq(prcm_irq_setup->base_irq + virtirq);
        }
        if (chip->irq_ack)
@@ -319,3 +319,65 @@ err:
        omap_prcm_irq_cleanup();
        return -ENOMEM;
 }
+
+/*
+ * Stubbed functions so that common files continue to build when
+ * custom builds are used
+ * XXX These are temporary and should be removed at the earliest possible
+ * opportunity
+ */
+u32 __weak omap2_prm_read_mod_reg(s16 module, u16 idx)
+{
+       WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
+       return 0;
+}
+
+void __weak omap2_prm_write_mod_reg(u32 val, s16 module, u16 idx)
+{
+       WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
+}
+
+u32 __weak omap2_prm_rmw_mod_reg_bits(u32 mask, u32 bits,
+               s16 module, s16 idx)
+{
+       WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
+       return 0;
+}
+
+u32 __weak omap2_prm_set_mod_reg_bits(u32 bits, s16 module, s16 idx)
+{
+       WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
+       return 0;
+}
+
+u32 __weak omap2_prm_clear_mod_reg_bits(u32 bits, s16 module, s16 idx)
+{
+       WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
+       return 0;
+}
+
+u32 __weak omap2_prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask)
+{
+       WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
+       return 0;
+}
+
+int __weak omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift)
+{
+       WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
+       return 0;
+}
+
+int __weak omap2_prm_assert_hardreset(s16 prm_mod, u8 shift)
+{
+       WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
+       return 0;
+}
+
+int __weak omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift,
+                                               u8 st_shift)
+{
+       WARN(1, "prm: omap2xxx/omap3xxx specific function called on non-omap2xxx/3xxx\n");
+       return 0;
+}
+
index 955566eefac4ac515516957e3f6d65cbc3353c35..1da8f03c479e9940fe2f2ba7ab8a7b569e2a9691 100644 (file)
  * published by the Free Software Foundation.
  */
 
-#include "smartreflex.h"
+#include <linux/power/smartreflex.h>
+#include "voltage.h"
 
-static int sr_class3_enable(struct voltagedomain *voltdm)
+static int sr_class3_enable(struct omap_sr *sr)
 {
-       unsigned long volt = voltdm_get_voltage(voltdm);
+       unsigned long volt = voltdm_get_voltage(sr->voltdm);
 
        if (!volt) {
-               pr_warning("%s: Curr voltage unknown. Cannot enable sr_%s\n",
-                               __func__, voltdm->name);
+               pr_warning("%s: Curr voltage unknown. Cannot enable %s\n",
+                               __func__, sr->name);
                return -ENODATA;
        }
 
-       omap_vp_enable(voltdm);
-       return sr_enable(voltdm, volt);
+       omap_vp_enable(sr->voltdm);
+       return sr_enable(sr->voltdm, volt);
 }
 
-static int sr_class3_disable(struct voltagedomain *voltdm, int is_volt_reset)
+static int sr_class3_disable(struct omap_sr *sr, int is_volt_reset)
 {
-       sr_disable_errgen(voltdm);
-       omap_vp_disable(voltdm);
-       sr_disable(voltdm);
+       sr_disable_errgen(sr->voltdm);
+       omap_vp_disable(sr->voltdm);
+       sr_disable(sr->voltdm);
        if (is_volt_reset)
-               voltdm_reset(voltdm);
+               voltdm_reset(sr->voltdm);
 
        return 0;
 }
 
-static int sr_class3_configure(struct voltagedomain *voltdm)
+static int sr_class3_configure(struct omap_sr *sr)
 {
-       return sr_configure_errgen(voltdm);
+       return sr_configure_errgen(sr->voltdm);
 }
 
 /* SR class3 structure */
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
deleted file mode 100644 (file)
index 008fbd7..0000000
+++ /dev/null
@@ -1,1165 +0,0 @@
-/*
- * OMAP SmartReflex Voltage Control
- *
- * Author: Thara Gopinath      <thara@ti.com>
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Thara Gopinath <thara@ti.com>
- *
- * Copyright (C) 2008 Nokia Corporation
- * Kalle Jokiniemi
- *
- * Copyright (C) 2007 Texas Instruments, Inc.
- * Lesly A M <x0080970@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/debugfs.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <linux/pm_runtime.h>
-
-#include "common.h"
-
-#include "pm.h"
-#include "smartreflex.h"
-
-#define SMARTREFLEX_NAME_LEN   16
-#define NVALUE_NAME_LEN                40
-#define SR_DISABLE_TIMEOUT     200
-
-struct omap_sr {
-       struct list_head                node;
-       struct platform_device          *pdev;
-       struct omap_sr_nvalue_table     *nvalue_table;
-       struct voltagedomain            *voltdm;
-       struct dentry                   *dbg_dir;
-       unsigned int                    irq;
-       int                             srid;
-       int                             ip_type;
-       int                             nvalue_count;
-       bool                            autocomp_active;
-       u32                             clk_length;
-       u32                             err_weight;
-       u32                             err_minlimit;
-       u32                             err_maxlimit;
-       u32                             accum_data;
-       u32                             senn_avgweight;
-       u32                             senp_avgweight;
-       u32                             senp_mod;
-       u32                             senn_mod;
-       void __iomem                    *base;
-};
-
-/* sr_list contains all the instances of smartreflex module */
-static LIST_HEAD(sr_list);
-
-static struct omap_sr_class_data *sr_class;
-static struct omap_sr_pmic_data *sr_pmic_data;
-static struct dentry           *sr_dbg_dir;
-
-static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
-{
-       __raw_writel(value, (sr->base + offset));
-}
-
-static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
-                                       u32 value)
-{
-       u32 reg_val;
-
-       /*
-        * Smartreflex error config register is special as it contains
-        * certain status bits which if written a 1 into means a clear
-        * of those bits. So in order to make sure no accidental write of
-        * 1 happens to those status bits, do a clear of them in the read
-        * value. This mean this API doesn't rewrite values in these bits
-        * if they are currently set, but does allow the caller to write
-        * those bits.
-        */
-       if (sr->ip_type == SR_TYPE_V1 && offset == ERRCONFIG_V1)
-               mask |= ERRCONFIG_STATUS_V1_MASK;
-       else if (sr->ip_type == SR_TYPE_V2 && offset == ERRCONFIG_V2)
-               mask |= ERRCONFIG_VPBOUNDINTST_V2;
-
-       reg_val = __raw_readl(sr->base + offset);
-       reg_val &= ~mask;
-
-       value &= mask;
-
-       reg_val |= value;
-
-       __raw_writel(reg_val, (sr->base + offset));
-}
-
-static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
-{
-       return __raw_readl(sr->base + offset);
-}
-
-static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm)
-{
-       struct omap_sr *sr_info;
-
-       if (!voltdm) {
-               pr_err("%s: Null voltage domain passed!\n", __func__);
-               return ERR_PTR(-EINVAL);
-       }
-
-       list_for_each_entry(sr_info, &sr_list, node) {
-               if (voltdm == sr_info->voltdm)
-                       return sr_info;
-       }
-
-       return ERR_PTR(-ENODATA);
-}
-
-static irqreturn_t sr_interrupt(int irq, void *data)
-{
-       struct omap_sr *sr_info = data;
-       u32 status = 0;
-
-       switch (sr_info->ip_type) {
-       case SR_TYPE_V1:
-               /* Read the status bits */
-               status = sr_read_reg(sr_info, ERRCONFIG_V1);
-
-               /* Clear them by writing back */
-               sr_write_reg(sr_info, ERRCONFIG_V1, status);
-               break;
-       case SR_TYPE_V2:
-               /* Read the status bits */
-               status = sr_read_reg(sr_info, IRQSTATUS);
-
-               /* Clear them by writing back */
-               sr_write_reg(sr_info, IRQSTATUS, status);
-               break;
-       default:
-               dev_err(&sr_info->pdev->dev, "UNKNOWN IP type %d\n",
-                       sr_info->ip_type);
-               return IRQ_NONE;
-       }
-
-       if (sr_class->notify)
-               sr_class->notify(sr_info->voltdm, status);
-
-       return IRQ_HANDLED;
-}
-
-static void sr_set_clk_length(struct omap_sr *sr)
-{
-       struct clk *sys_ck;
-       u32 sys_clk_speed;
-
-       if (cpu_is_omap34xx())
-               sys_ck = clk_get(NULL, "sys_ck");
-       else
-               sys_ck = clk_get(NULL, "sys_clkin_ck");
-
-       if (IS_ERR(sys_ck)) {
-               dev_err(&sr->pdev->dev, "%s: unable to get sys clk\n",
-                       __func__);
-               return;
-       }
-
-       sys_clk_speed = clk_get_rate(sys_ck);
-       clk_put(sys_ck);
-
-       switch (sys_clk_speed) {
-       case 12000000:
-               sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK;
-               break;
-       case 13000000:
-               sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK;
-               break;
-       case 19200000:
-               sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK;
-               break;
-       case 26000000:
-               sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK;
-               break;
-       case 38400000:
-               sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK;
-               break;
-       default:
-               dev_err(&sr->pdev->dev, "%s: Invalid sysclk value: %d\n",
-                       __func__, sys_clk_speed);
-               break;
-       }
-}
-
-static void sr_set_regfields(struct omap_sr *sr)
-{
-       /*
-        * For time being these values are defined in smartreflex.h
-        * and populated during init. May be they can be moved to board
-        * file or pmic specific data structure. In that case these structure
-        * fields will have to be populated using the pdata or pmic structure.
-        */
-       if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-               sr->err_weight = OMAP3430_SR_ERRWEIGHT;
-               sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
-               sr->accum_data = OMAP3430_SR_ACCUMDATA;
-               if (!(strcmp(sr->voltdm->name, "mpu"))) {
-                       sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
-                       sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
-               } else {
-                       sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
-                       sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
-               }
-       }
-}
-
-static void sr_start_vddautocomp(struct omap_sr *sr)
-{
-       if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
-               dev_warn(&sr->pdev->dev,
-                       "%s: smartreflex class driver not registered\n",
-                       __func__);
-               return;
-       }
-
-       if (!sr_class->enable(sr->voltdm))
-               sr->autocomp_active = true;
-}
-
-static void sr_stop_vddautocomp(struct omap_sr *sr)
-{
-       if (!sr_class || !(sr_class->disable)) {
-               dev_warn(&sr->pdev->dev,
-                       "%s: smartreflex class driver not registered\n",
-                       __func__);
-               return;
-       }
-
-       if (sr->autocomp_active) {
-               sr_class->disable(sr->voltdm, 1);
-               sr->autocomp_active = false;
-       }
-}
-
-/*
- * This function handles the intializations which have to be done
- * only when both sr device and class driver regiter has
- * completed. This will be attempted to be called from both sr class
- * driver register and sr device intializtion API's. Only one call
- * will ultimately succeed.
- *
- * Currently this function registers interrupt handler for a particular SR
- * if smartreflex class driver is already registered and has
- * requested for interrupts and the SR interrupt line in present.
- */
-static int sr_late_init(struct omap_sr *sr_info)
-{
-       char *name;
-       struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data;
-       struct resource *mem;
-       int ret = 0;
-
-       if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
-               name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
-               if (name == NULL) {
-                       ret = -ENOMEM;
-                       goto error;
-               }
-               ret = request_irq(sr_info->irq, sr_interrupt,
-                               0, name, sr_info);
-               if (ret)
-                       goto error;
-               disable_irq(sr_info->irq);
-       }
-
-       if (pdata && pdata->enable_on_init)
-               sr_start_vddautocomp(sr_info);
-
-       return ret;
-
-error:
-       iounmap(sr_info->base);
-       mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
-       release_mem_region(mem->start, resource_size(mem));
-       list_del(&sr_info->node);
-       dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
-               "interrupt handler. Smartreflex will"
-               "not function as desired\n", __func__);
-       kfree(name);
-       kfree(sr_info);
-
-       return ret;
-}
-
-static void sr_v1_disable(struct omap_sr *sr)
-{
-       int timeout = 0;
-       int errconf_val = ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
-                       ERRCONFIG_MCUBOUNDINTST;
-
-       /* Enable MCUDisableAcknowledge interrupt */
-       sr_modify_reg(sr, ERRCONFIG_V1,
-                       ERRCONFIG_MCUDISACKINTEN, ERRCONFIG_MCUDISACKINTEN);
-
-       /* SRCONFIG - disable SR */
-       sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
-
-       /* Disable all other SR interrupts and clear the status as needed */
-       if (sr_read_reg(sr, ERRCONFIG_V1) & ERRCONFIG_VPBOUNDINTST_V1)
-               errconf_val |= ERRCONFIG_VPBOUNDINTST_V1;
-       sr_modify_reg(sr, ERRCONFIG_V1,
-                       (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
-                       ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN_V1),
-                       errconf_val);
-
-       /*
-        * Wait for SR to be disabled.
-        * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us.
-        */
-       omap_test_timeout((sr_read_reg(sr, ERRCONFIG_V1) &
-                       ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT,
-                       timeout);
-
-       if (timeout >= SR_DISABLE_TIMEOUT)
-               dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
-                       __func__);
-
-       /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
-       sr_modify_reg(sr, ERRCONFIG_V1, ERRCONFIG_MCUDISACKINTEN,
-                       ERRCONFIG_MCUDISACKINTST);
-}
-
-static void sr_v2_disable(struct omap_sr *sr)
-{
-       int timeout = 0;
-
-       /* Enable MCUDisableAcknowledge interrupt */
-       sr_write_reg(sr, IRQENABLE_SET, IRQENABLE_MCUDISABLEACKINT);
-
-       /* SRCONFIG - disable SR */
-       sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
-
-       /*
-        * Disable all other SR interrupts and clear the status
-        * write to status register ONLY on need basis - only if status
-        * is set.
-        */
-       if (sr_read_reg(sr, ERRCONFIG_V2) & ERRCONFIG_VPBOUNDINTST_V2)
-               sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
-                       ERRCONFIG_VPBOUNDINTST_V2);
-       else
-               sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
-                               0x0);
-       sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT |
-                       IRQENABLE_MCUVALIDINT |
-                       IRQENABLE_MCUBOUNDSINT));
-       sr_write_reg(sr, IRQSTATUS, (IRQSTATUS_MCUACCUMINT |
-                       IRQSTATUS_MCVALIDINT |
-                       IRQSTATUS_MCBOUNDSINT));
-
-       /*
-        * Wait for SR to be disabled.
-        * wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us.
-        */
-       omap_test_timeout((sr_read_reg(sr, IRQSTATUS) &
-                       IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT,
-                       timeout);
-
-       if (timeout >= SR_DISABLE_TIMEOUT)
-               dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
-                       __func__);
-
-       /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
-       sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT);
-       sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
-}
-
-static u32 sr_retrieve_nvalue(struct omap_sr *sr, u32 efuse_offs)
-{
-       int i;
-
-       if (!sr->nvalue_table) {
-               dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n",
-                       __func__);
-               return 0;
-       }
-
-       for (i = 0; i < sr->nvalue_count; i++) {
-               if (sr->nvalue_table[i].efuse_offs == efuse_offs)
-                       return sr->nvalue_table[i].nvalue;
-       }
-
-       return 0;
-}
-
-/* Public Functions */
-
-/**
- * sr_configure_errgen() - Configures the smrtreflex to perform AVS using the
- *                      error generator module.
- * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
- *
- * This API is to be called from the smartreflex class driver to
- * configure the error generator module inside the smartreflex module.
- * SR settings if using the ERROR module inside Smartreflex.
- * SR CLASS 3 by default uses only the ERROR module where as
- * SR CLASS 2 can choose between ERROR module and MINMAXAVG
- * module. Returns 0 on success and error value in case of failure.
- */
-int sr_configure_errgen(struct voltagedomain *voltdm)
-{
-       u32 sr_config, sr_errconfig, errconfig_offs;
-       u32 vpboundint_en, vpboundint_st;
-       u32 senp_en = 0, senn_en = 0;
-       u8 senp_shift, senn_shift;
-       struct omap_sr *sr = _sr_lookup(voltdm);
-
-       if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
-               return PTR_ERR(sr);
-       }
-
-       if (!sr->clk_length)
-               sr_set_clk_length(sr);
-
-       senp_en = sr->senp_mod;
-       senn_en = sr->senn_mod;
-
-       sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
-               SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN;
-
-       switch (sr->ip_type) {
-       case SR_TYPE_V1:
-               sr_config |= SRCONFIG_DELAYCTRL;
-               senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
-               senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
-               errconfig_offs = ERRCONFIG_V1;
-               vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
-               vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
-               break;
-       case SR_TYPE_V2:
-               senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
-               senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
-               errconfig_offs = ERRCONFIG_V2;
-               vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
-               vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
-               break;
-       default:
-               dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
-                       "module without specifying the ip\n", __func__);
-               return -EINVAL;
-       }
-
-       sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
-       sr_write_reg(sr, SRCONFIG, sr_config);
-       sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) |
-               (sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) |
-               (sr->err_minlimit <<  ERRCONFIG_ERRMINLIMIT_SHIFT);
-       sr_modify_reg(sr, errconfig_offs, (SR_ERRWEIGHT_MASK |
-               SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
-               sr_errconfig);
-
-       /* Enabling the interrupts if the ERROR module is used */
-       sr_modify_reg(sr, errconfig_offs, (vpboundint_en | vpboundint_st),
-                     vpboundint_en);
-
-       return 0;
-}
-
-/**
- * sr_disable_errgen() - Disables SmartReflex AVS module's errgen component
- * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
- *
- * This API is to be called from the smartreflex class driver to
- * disable the error generator module inside the smartreflex module.
- *
- * Returns 0 on success and error value in case of failure.
- */
-int sr_disable_errgen(struct voltagedomain *voltdm)
-{
-       u32 errconfig_offs;
-       u32 vpboundint_en, vpboundint_st;
-       struct omap_sr *sr = _sr_lookup(voltdm);
-
-       if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
-               return PTR_ERR(sr);
-       }
-
-       switch (sr->ip_type) {
-       case SR_TYPE_V1:
-               errconfig_offs = ERRCONFIG_V1;
-               vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
-               vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
-               break;
-       case SR_TYPE_V2:
-               errconfig_offs = ERRCONFIG_V2;
-               vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
-               vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
-               break;
-       default:
-               dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
-                       "module without specifying the ip\n", __func__);
-               return -EINVAL;
-       }
-
-       /* Disable the interrupts of ERROR module */
-       sr_modify_reg(sr, errconfig_offs, vpboundint_en | vpboundint_st, 0);
-
-       /* Disable the Sensor and errorgen */
-       sr_modify_reg(sr, SRCONFIG, SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN, 0);
-
-       return 0;
-}
-
-/**
- * sr_configure_minmax() - Configures the smrtreflex to perform AVS using the
- *                      minmaxavg module.
- * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
- *
- * This API is to be called from the smartreflex class driver to
- * configure the minmaxavg module inside the smartreflex module.
- * SR settings if using the ERROR module inside Smartreflex.
- * SR CLASS 3 by default uses only the ERROR module where as
- * SR CLASS 2 can choose between ERROR module and MINMAXAVG
- * module. Returns 0 on success and error value in case of failure.
- */
-int sr_configure_minmax(struct voltagedomain *voltdm)
-{
-       u32 sr_config, sr_avgwt;
-       u32 senp_en = 0, senn_en = 0;
-       u8 senp_shift, senn_shift;
-       struct omap_sr *sr = _sr_lookup(voltdm);
-
-       if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
-               return PTR_ERR(sr);
-       }
-
-       if (!sr->clk_length)
-               sr_set_clk_length(sr);
-
-       senp_en = sr->senp_mod;
-       senn_en = sr->senn_mod;
-
-       sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
-               SRCONFIG_SENENABLE |
-               (sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
-
-       switch (sr->ip_type) {
-       case SR_TYPE_V1:
-               sr_config |= SRCONFIG_DELAYCTRL;
-               senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
-               senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
-               break;
-       case SR_TYPE_V2:
-               senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
-               senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
-               break;
-       default:
-               dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
-                       "module without specifying the ip\n", __func__);
-               return -EINVAL;
-       }
-
-       sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
-       sr_write_reg(sr, SRCONFIG, sr_config);
-       sr_avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) |
-               (sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT);
-       sr_write_reg(sr, AVGWEIGHT, sr_avgwt);
-
-       /*
-        * Enabling the interrupts if MINMAXAVG module is used.
-        * TODO: check if all the interrupts are mandatory
-        */
-       switch (sr->ip_type) {
-       case SR_TYPE_V1:
-               sr_modify_reg(sr, ERRCONFIG_V1,
-                       (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
-                       ERRCONFIG_MCUBOUNDINTEN),
-                       (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST |
-                        ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST |
-                        ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST));
-               break;
-       case SR_TYPE_V2:
-               sr_write_reg(sr, IRQSTATUS,
-                       IRQSTATUS_MCUACCUMINT | IRQSTATUS_MCVALIDINT |
-                       IRQSTATUS_MCBOUNDSINT | IRQSTATUS_MCUDISABLEACKINT);
-               sr_write_reg(sr, IRQENABLE_SET,
-                       IRQENABLE_MCUACCUMINT | IRQENABLE_MCUVALIDINT |
-                       IRQENABLE_MCUBOUNDSINT | IRQENABLE_MCUDISABLEACKINT);
-               break;
-       default:
-               dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
-                       "module without specifying the ip\n", __func__);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-/**
- * sr_enable() - Enables the smartreflex module.
- * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
- * @volt:      The voltage at which the Voltage domain associated with
- *             the smartreflex module is operating at.
- *             This is required only to program the correct Ntarget value.
- *
- * This API is to be called from the smartreflex class driver to
- * enable a smartreflex module. Returns 0 on success. Returns error
- * value if the voltage passed is wrong or if ntarget value is wrong.
- */
-int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
-{
-       struct omap_volt_data *volt_data;
-       struct omap_sr *sr = _sr_lookup(voltdm);
-       u32 nvalue_reciprocal;
-       int ret;
-
-       if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
-               return PTR_ERR(sr);
-       }
-
-       volt_data = omap_voltage_get_voltdata(sr->voltdm, volt);
-
-       if (IS_ERR(volt_data)) {
-               dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table"
-                       "for nominal voltage %ld\n", __func__, volt);
-               return PTR_ERR(volt_data);
-       }
-
-       nvalue_reciprocal = sr_retrieve_nvalue(sr, volt_data->sr_efuse_offs);
-
-       if (!nvalue_reciprocal) {
-               dev_warn(&sr->pdev->dev, "%s: NVALUE = 0 at voltage %ld\n",
-                       __func__, volt);
-               return -ENODATA;
-       }
-
-       /* errminlimit is opp dependent and hence linked to voltage */
-       sr->err_minlimit = volt_data->sr_errminlimit;
-
-       pm_runtime_get_sync(&sr->pdev->dev);
-
-       /* Check if SR is already enabled. If yes do nothing */
-       if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE)
-               return 0;
-
-       /* Configure SR */
-       ret = sr_class->configure(voltdm);
-       if (ret)
-               return ret;
-
-       sr_write_reg(sr, NVALUERECIPROCAL, nvalue_reciprocal);
-
-       /* SRCONFIG - enable SR */
-       sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
-       return 0;
-}
-
-/**
- * sr_disable() - Disables the smartreflex module.
- * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
- *
- * This API is to be called from the smartreflex class driver to
- * disable a smartreflex module.
- */
-void sr_disable(struct voltagedomain *voltdm)
-{
-       struct omap_sr *sr = _sr_lookup(voltdm);
-
-       if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
-               return;
-       }
-
-       /* Check if SR clocks are already disabled. If yes do nothing */
-       if (pm_runtime_suspended(&sr->pdev->dev))
-               return;
-
-       /*
-        * Disable SR if only it is indeed enabled. Else just
-        * disable the clocks.
-        */
-       if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) {
-               switch (sr->ip_type) {
-               case SR_TYPE_V1:
-                       sr_v1_disable(sr);
-                       break;
-               case SR_TYPE_V2:
-                       sr_v2_disable(sr);
-                       break;
-               default:
-                       dev_err(&sr->pdev->dev, "UNKNOWN IP type %d\n",
-                               sr->ip_type);
-               }
-       }
-
-       pm_runtime_put_sync_suspend(&sr->pdev->dev);
-}
-
-/**
- * sr_register_class() - API to register a smartreflex class parameters.
- * @class_data:        The structure containing various sr class specific data.
- *
- * This API is to be called by the smartreflex class driver to register itself
- * with the smartreflex driver during init. Returns 0 on success else the
- * error value.
- */
-int sr_register_class(struct omap_sr_class_data *class_data)
-{
-       struct omap_sr *sr_info;
-
-       if (!class_data) {
-               pr_warning("%s:, Smartreflex class data passed is NULL\n",
-                       __func__);
-               return -EINVAL;
-       }
-
-       if (sr_class) {
-               pr_warning("%s: Smartreflex class driver already registered\n",
-                       __func__);
-               return -EBUSY;
-       }
-
-       sr_class = class_data;
-
-       /*
-        * Call into late init to do intializations that require
-        * both sr driver and sr class driver to be initiallized.
-        */
-       list_for_each_entry(sr_info, &sr_list, node)
-               sr_late_init(sr_info);
-
-       return 0;
-}
-
-/**
- * omap_sr_enable() -  API to enable SR clocks and to call into the
- *                     registered smartreflex class enable API.
- * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
- *
- * This API is to be called from the kernel in order to enable
- * a particular smartreflex module. This API will do the initial
- * configurations to turn on the smartreflex module and in turn call
- * into the registered smartreflex class enable API.
- */
-void omap_sr_enable(struct voltagedomain *voltdm)
-{
-       struct omap_sr *sr = _sr_lookup(voltdm);
-
-       if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
-               return;
-       }
-
-       if (!sr->autocomp_active)
-               return;
-
-       if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
-               dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
-                       "registered\n", __func__);
-               return;
-       }
-
-       sr_class->enable(voltdm);
-}
-
-/**
- * omap_sr_disable() - API to disable SR without resetting the voltage
- *                     processor voltage
- * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
- *
- * This API is to be called from the kernel in order to disable
- * a particular smartreflex module. This API will in turn call
- * into the registered smartreflex class disable API. This API will tell
- * the smartreflex class disable not to reset the VP voltage after
- * disabling smartreflex.
- */
-void omap_sr_disable(struct voltagedomain *voltdm)
-{
-       struct omap_sr *sr = _sr_lookup(voltdm);
-
-       if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
-               return;
-       }
-
-       if (!sr->autocomp_active)
-               return;
-
-       if (!sr_class || !(sr_class->disable)) {
-               dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
-                       "registered\n", __func__);
-               return;
-       }
-
-       sr_class->disable(voltdm, 0);
-}
-
-/**
- * omap_sr_disable_reset_volt() - API to disable SR and reset the
- *                             voltage processor voltage
- * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
- *
- * This API is to be called from the kernel in order to disable
- * a particular smartreflex module. This API will in turn call
- * into the registered smartreflex class disable API. This API will tell
- * the smartreflex class disable to reset the VP voltage after
- * disabling smartreflex.
- */
-void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
-{
-       struct omap_sr *sr = _sr_lookup(voltdm);
-
-       if (IS_ERR(sr)) {
-               pr_warning("%s: omap_sr struct for sr_%s not found\n",
-                       __func__, voltdm->name);
-               return;
-       }
-
-       if (!sr->autocomp_active)
-               return;
-
-       if (!sr_class || !(sr_class->disable)) {
-               dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
-                       "registered\n", __func__);
-               return;
-       }
-
-       sr_class->disable(voltdm, 1);
-}
-
-/**
- * omap_sr_register_pmic() - API to register pmic specific info.
- * @pmic_data: The structure containing pmic specific data.
- *
- * This API is to be called from the PMIC specific code to register with
- * smartreflex driver pmic specific info. Currently the only info required
- * is the smartreflex init on the PMIC side.
- */
-void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data)
-{
-       if (!pmic_data) {
-               pr_warning("%s: Trying to register NULL PMIC data structure"
-                       "with smartreflex\n", __func__);
-               return;
-       }
-
-       sr_pmic_data = pmic_data;
-}
-
-/* PM Debug FS entries to enable and disable smartreflex. */
-static int omap_sr_autocomp_show(void *data, u64 *val)
-{
-       struct omap_sr *sr_info = data;
-
-       if (!sr_info) {
-               pr_warning("%s: omap_sr struct not found\n", __func__);
-               return -EINVAL;
-       }
-
-       *val = sr_info->autocomp_active;
-
-       return 0;
-}
-
-static int omap_sr_autocomp_store(void *data, u64 val)
-{
-       struct omap_sr *sr_info = data;
-
-       if (!sr_info) {
-               pr_warning("%s: omap_sr struct not found\n", __func__);
-               return -EINVAL;
-       }
-
-       /* Sanity check */
-       if (val > 1) {
-               pr_warning("%s: Invalid argument %lld\n", __func__, val);
-               return -EINVAL;
-       }
-
-       /* control enable/disable only if there is a delta in value */
-       if (sr_info->autocomp_active != val) {
-               if (!val)
-                       sr_stop_vddautocomp(sr_info);
-               else
-                       sr_start_vddautocomp(sr_info);
-       }
-
-       return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
-                       omap_sr_autocomp_store, "%llu\n");
-
-static int __init omap_sr_probe(struct platform_device *pdev)
-{
-       struct omap_sr *sr_info;
-       struct omap_sr_data *pdata = pdev->dev.platform_data;
-       struct resource *mem, *irq;
-       struct dentry *nvalue_dir;
-       struct omap_volt_data *volt_data;
-       int i, ret = 0;
-       char *name;
-
-       sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
-       if (!sr_info) {
-               dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
-                       __func__);
-               return -ENOMEM;
-       }
-
-       platform_set_drvdata(pdev, sr_info);
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
-               ret = -EINVAL;
-               goto err_free_devinfo;
-       }
-
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!mem) {
-               dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
-               ret = -ENODEV;
-               goto err_free_devinfo;
-       }
-
-       mem = request_mem_region(mem->start, resource_size(mem),
-                                       dev_name(&pdev->dev));
-       if (!mem) {
-               dev_err(&pdev->dev, "%s: no mem region\n", __func__);
-               ret = -EBUSY;
-               goto err_free_devinfo;
-       }
-
-       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-
-       pm_runtime_enable(&pdev->dev);
-       pm_runtime_irq_safe(&pdev->dev);
-
-       sr_info->pdev = pdev;
-       sr_info->srid = pdev->id;
-       sr_info->voltdm = pdata->voltdm;
-       sr_info->nvalue_table = pdata->nvalue_table;
-       sr_info->nvalue_count = pdata->nvalue_count;
-       sr_info->senn_mod = pdata->senn_mod;
-       sr_info->senp_mod = pdata->senp_mod;
-       sr_info->autocomp_active = false;
-       sr_info->ip_type = pdata->ip_type;
-       sr_info->base = ioremap(mem->start, resource_size(mem));
-       if (!sr_info->base) {
-               dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
-               ret = -ENOMEM;
-               goto err_release_region;
-       }
-
-       if (irq)
-               sr_info->irq = irq->start;
-
-       sr_set_clk_length(sr_info);
-       sr_set_regfields(sr_info);
-
-       list_add(&sr_info->node, &sr_list);
-
-       /*
-        * Call into late init to do intializations that require
-        * both sr driver and sr class driver to be initiallized.
-        */
-       if (sr_class) {
-               ret = sr_late_init(sr_info);
-               if (ret) {
-                       pr_warning("%s: Error in SR late init\n", __func__);
-                       goto err_iounmap;
-               }
-       }
-
-       dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
-       if (!sr_dbg_dir) {
-               sr_dbg_dir = debugfs_create_dir("smartreflex", NULL);
-               if (IS_ERR_OR_NULL(sr_dbg_dir)) {
-                       ret = PTR_ERR(sr_dbg_dir);
-                       pr_err("%s:sr debugfs dir creation failed(%d)\n",
-                               __func__, ret);
-                       goto err_iounmap;
-               }
-       }
-
-       name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
-       if (!name) {
-               dev_err(&pdev->dev, "%s: Unable to alloc debugfs name\n",
-                       __func__);
-               ret = -ENOMEM;
-               goto err_iounmap;
-       }
-       sr_info->dbg_dir = debugfs_create_dir(name, sr_dbg_dir);
-       kfree(name);
-       if (IS_ERR_OR_NULL(sr_info->dbg_dir)) {
-               dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
-                       __func__);
-               ret = PTR_ERR(sr_info->dbg_dir);
-               goto err_iounmap;
-       }
-
-       (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR,
-                       sr_info->dbg_dir, (void *)sr_info, &pm_sr_fops);
-       (void) debugfs_create_x32("errweight", S_IRUGO, sr_info->dbg_dir,
-                       &sr_info->err_weight);
-       (void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr_info->dbg_dir,
-                       &sr_info->err_maxlimit);
-       (void) debugfs_create_x32("errminlimit", S_IRUGO, sr_info->dbg_dir,
-                       &sr_info->err_minlimit);
-
-       nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir);
-       if (IS_ERR_OR_NULL(nvalue_dir)) {
-               dev_err(&pdev->dev, "%s: Unable to create debugfs directory"
-                       "for n-values\n", __func__);
-               ret = PTR_ERR(nvalue_dir);
-               goto err_debugfs;
-       }
-
-       omap_voltage_get_volttable(sr_info->voltdm, &volt_data);
-       if (!volt_data) {
-               dev_warn(&pdev->dev, "%s: No Voltage table for the"
-                       " corresponding vdd vdd_%s. Cannot create debugfs"
-                       "entries for n-values\n",
-                       __func__, sr_info->voltdm->name);
-               ret = -ENODATA;
-               goto err_debugfs;
-       }
-
-       for (i = 0; i < sr_info->nvalue_count; i++) {
-               char name[NVALUE_NAME_LEN + 1];
-
-               snprintf(name, sizeof(name), "volt_%d",
-                        volt_data[i].volt_nominal);
-               (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
-                               &(sr_info->nvalue_table[i].nvalue));
-       }
-
-       return ret;
-
-err_debugfs:
-       debugfs_remove_recursive(sr_info->dbg_dir);
-err_iounmap:
-       list_del(&sr_info->node);
-       iounmap(sr_info->base);
-err_release_region:
-       release_mem_region(mem->start, resource_size(mem));
-err_free_devinfo:
-       kfree(sr_info);
-
-       return ret;
-}
-
-static int __devexit omap_sr_remove(struct platform_device *pdev)
-{
-       struct omap_sr_data *pdata = pdev->dev.platform_data;
-       struct omap_sr *sr_info;
-       struct resource *mem;
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
-               return -EINVAL;
-       }
-
-       sr_info = _sr_lookup(pdata->voltdm);
-       if (IS_ERR(sr_info)) {
-               dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
-                       __func__);
-               return PTR_ERR(sr_info);
-       }
-
-       if (sr_info->autocomp_active)
-               sr_stop_vddautocomp(sr_info);
-       if (sr_info->dbg_dir)
-               debugfs_remove_recursive(sr_info->dbg_dir);
-
-       list_del(&sr_info->node);
-       iounmap(sr_info->base);
-       kfree(sr_info);
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       release_mem_region(mem->start, resource_size(mem));
-
-       return 0;
-}
-
-static void __devexit omap_sr_shutdown(struct platform_device *pdev)
-{
-       struct omap_sr_data *pdata = pdev->dev.platform_data;
-       struct omap_sr *sr_info;
-
-       if (!pdata) {
-               dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
-               return;
-       }
-
-       sr_info = _sr_lookup(pdata->voltdm);
-       if (IS_ERR(sr_info)) {
-               dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
-                       __func__);
-               return;
-       }
-
-       if (sr_info->autocomp_active)
-               sr_stop_vddautocomp(sr_info);
-
-       return;
-}
-
-static struct platform_driver smartreflex_driver = {
-       .remove         = __devexit_p(omap_sr_remove),
-       .shutdown       = __devexit_p(omap_sr_shutdown),
-       .driver         = {
-               .name   = "smartreflex",
-       },
-};
-
-static int __init sr_init(void)
-{
-       int ret = 0;
-
-       /*
-        * sr_init is a late init. If by then a pmic specific API is not
-        * registered either there is no need for anything to be done on
-        * the PMIC side or somebody has forgotten to register a PMIC
-        * handler. Warn for the second condition.
-        */
-       if (sr_pmic_data && sr_pmic_data->sr_pmic_init)
-               sr_pmic_data->sr_pmic_init();
-       else
-               pr_warning("%s: No PMIC hook to init smartreflex\n", __func__);
-
-       ret = platform_driver_probe(&smartreflex_driver, omap_sr_probe);
-       if (ret) {
-               pr_err("%s: platform driver register failed for SR\n",
-                       __func__);
-               return ret;
-       }
-
-       return 0;
-}
-late_initcall(sr_init);
-
-static void __exit sr_exit(void)
-{
-       platform_driver_unregister(&smartreflex_driver);
-}
-module_exit(sr_exit);
-
-MODULE_DESCRIPTION("OMAP Smartreflex Driver");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:" DRIVER_NAME);
-MODULE_AUTHOR("Texas Instruments Inc");
diff --git a/arch/arm/mach-omap2/smartreflex.h b/arch/arm/mach-omap2/smartreflex.h
deleted file mode 100644 (file)
index 5809141..0000000
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * OMAP Smartreflex Defines and Routines
- *
- * Author: Thara Gopinath      <thara@ti.com>
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Thara Gopinath <thara@ti.com>
- *
- * Copyright (C) 2008 Nokia Corporation
- * Kalle Jokiniemi
- *
- * Copyright (C) 2007 Texas Instruments, Inc.
- * Lesly A M <x0080970@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __ASM_ARM_OMAP_SMARTREFLEX_H
-#define __ASM_ARM_OMAP_SMARTREFLEX_H
-
-#include <linux/platform_device.h>
-
-#include "voltage.h"
-
-/*
- * Different Smartreflex IPs version. The v1 is the 65nm version used in
- * OMAP3430. The v2 is the update for the 45nm version of the IP
- * used in OMAP3630 and OMAP4430
- */
-#define SR_TYPE_V1     1
-#define SR_TYPE_V2     2
-
-/* SMART REFLEX REG ADDRESS OFFSET */
-#define SRCONFIG               0x00
-#define SRSTATUS               0x04
-#define SENVAL                 0x08
-#define SENMIN                 0x0C
-#define SENMAX                 0x10
-#define SENAVG                 0x14
-#define AVGWEIGHT              0x18
-#define NVALUERECIPROCAL       0x1c
-#define SENERROR_V1            0x20
-#define ERRCONFIG_V1           0x24
-#define IRQ_EOI                        0x20
-#define IRQSTATUS_RAW          0x24
-#define IRQSTATUS              0x28
-#define IRQENABLE_SET          0x2C
-#define IRQENABLE_CLR          0x30
-#define SENERROR_V2            0x34
-#define ERRCONFIG_V2           0x38
-
-/* Bit/Shift Positions */
-
-/* SRCONFIG */
-#define SRCONFIG_ACCUMDATA_SHIFT       22
-#define SRCONFIG_SRCLKLENGTH_SHIFT     12
-#define SRCONFIG_SENNENABLE_V1_SHIFT   5
-#define SRCONFIG_SENPENABLE_V1_SHIFT   3
-#define SRCONFIG_SENNENABLE_V2_SHIFT   1
-#define SRCONFIG_SENPENABLE_V2_SHIFT   0
-#define SRCONFIG_CLKCTRL_SHIFT         0
-
-#define SRCONFIG_ACCUMDATA_MASK                (0x3ff << 22)
-
-#define SRCONFIG_SRENABLE              BIT(11)
-#define SRCONFIG_SENENABLE             BIT(10)
-#define SRCONFIG_ERRGEN_EN             BIT(9)
-#define SRCONFIG_MINMAXAVG_EN          BIT(8)
-#define SRCONFIG_DELAYCTRL             BIT(2)
-
-/* AVGWEIGHT */
-#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT  2
-#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT  0
-
-/* NVALUERECIPROCAL */
-#define NVALUERECIPROCAL_SENPGAIN_SHIFT        20
-#define NVALUERECIPROCAL_SENNGAIN_SHIFT        16
-#define NVALUERECIPROCAL_RNSENP_SHIFT  8
-#define NVALUERECIPROCAL_RNSENN_SHIFT  0
-
-/* ERRCONFIG */
-#define ERRCONFIG_ERRWEIGHT_SHIFT      16
-#define ERRCONFIG_ERRMAXLIMIT_SHIFT    8
-#define ERRCONFIG_ERRMINLIMIT_SHIFT    0
-
-#define SR_ERRWEIGHT_MASK              (0x07 << 16)
-#define SR_ERRMAXLIMIT_MASK            (0xff << 8)
-#define SR_ERRMINLIMIT_MASK            (0xff << 0)
-
-#define ERRCONFIG_VPBOUNDINTEN_V1      BIT(31)
-#define ERRCONFIG_VPBOUNDINTST_V1      BIT(30)
-#define        ERRCONFIG_MCUACCUMINTEN         BIT(29)
-#define ERRCONFIG_MCUACCUMINTST                BIT(28)
-#define        ERRCONFIG_MCUVALIDINTEN         BIT(27)
-#define ERRCONFIG_MCUVALIDINTST                BIT(26)
-#define ERRCONFIG_MCUBOUNDINTEN                BIT(25)
-#define        ERRCONFIG_MCUBOUNDINTST         BIT(24)
-#define        ERRCONFIG_MCUDISACKINTEN        BIT(23)
-#define ERRCONFIG_VPBOUNDINTST_V2      BIT(23)
-#define ERRCONFIG_MCUDISACKINTST       BIT(22)
-#define ERRCONFIG_VPBOUNDINTEN_V2      BIT(22)
-
-#define ERRCONFIG_STATUS_V1_MASK       (ERRCONFIG_VPBOUNDINTST_V1 | \
-                                       ERRCONFIG_MCUACCUMINTST | \
-                                       ERRCONFIG_MCUVALIDINTST | \
-                                       ERRCONFIG_MCUBOUNDINTST | \
-                                       ERRCONFIG_MCUDISACKINTST)
-/* IRQSTATUS */
-#define IRQSTATUS_MCUACCUMINT          BIT(3)
-#define IRQSTATUS_MCVALIDINT           BIT(2)
-#define IRQSTATUS_MCBOUNDSINT          BIT(1)
-#define IRQSTATUS_MCUDISABLEACKINT     BIT(0)
-
-/* IRQENABLE_SET and IRQENABLE_CLEAR */
-#define IRQENABLE_MCUACCUMINT          BIT(3)
-#define IRQENABLE_MCUVALIDINT          BIT(2)
-#define IRQENABLE_MCUBOUNDSINT         BIT(1)
-#define IRQENABLE_MCUDISABLEACKINT     BIT(0)
-
-/* Common Bit values */
-
-#define SRCLKLENGTH_12MHZ_SYSCLK       0x3c
-#define SRCLKLENGTH_13MHZ_SYSCLK       0x41
-#define SRCLKLENGTH_19MHZ_SYSCLK       0x60
-#define SRCLKLENGTH_26MHZ_SYSCLK       0x82
-#define SRCLKLENGTH_38MHZ_SYSCLK       0xC0
-
-/*
- * 3430 specific values. Maybe these should be passed from board file or
- * pmic structures.
- */
-#define OMAP3430_SR_ACCUMDATA          0x1f4
-
-#define OMAP3430_SR1_SENPAVGWEIGHT     0x03
-#define OMAP3430_SR1_SENNAVGWEIGHT     0x03
-
-#define OMAP3430_SR2_SENPAVGWEIGHT     0x01
-#define OMAP3430_SR2_SENNAVGWEIGHT     0x01
-
-#define OMAP3430_SR_ERRWEIGHT          0x04
-#define OMAP3430_SR_ERRMAXLIMIT                0x02
-
-/**
- * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
- *                             pmic specific info to smartreflex driver
- *
- * @sr_pmic_init:      API to initialize smartreflex on the PMIC side.
- */
-struct omap_sr_pmic_data {
-       void (*sr_pmic_init) (void);
-};
-
-/**
- * struct omap_smartreflex_dev_attr - Smartreflex Device attribute.
- *
- * @sensor_voltdm_name:       Name of voltdomain of SR instance
- */
-struct omap_smartreflex_dev_attr {
-       const char      *sensor_voltdm_name;
-};
-
-#ifdef CONFIG_OMAP_SMARTREFLEX
-/*
- * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
- * The smartreflex class driver should pass the class type.
- * Should be used to populate the class_type field of the
- * omap_smartreflex_class_data structure.
- */
-#define SR_CLASS1      0x1
-#define SR_CLASS2      0x2
-#define SR_CLASS3      0x3
-
-/**
- * struct omap_sr_class_data - Smartreflex class driver info
- *
- * @enable:            API to enable a particular class smaartreflex.
- * @disable:           API to disable a particular class smartreflex.
- * @configure:         API to configure a particular class smartreflex.
- * @notify:            API to notify the class driver about an event in SR.
- *                     Not needed for class3.
- * @notify_flags:      specify the events to be notified to the class driver
- * @class_type:                specify which smartreflex class.
- *                     Can be used by the SR driver to take any class
- *                     based decisions.
- */
-struct omap_sr_class_data {
-       int (*enable)(struct voltagedomain *voltdm);
-       int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
-       int (*configure)(struct voltagedomain *voltdm);
-       int (*notify)(struct voltagedomain *voltdm, u32 status);
-       u8 notify_flags;
-       u8 class_type;
-};
-
-/**
- * struct omap_sr_nvalue_table - Smartreflex n-target value info
- *
- * @efuse_offs:        The offset of the efuse where n-target values are stored.
- * @nvalue:    The n-target value.
- */
-struct omap_sr_nvalue_table {
-       u32 efuse_offs;
-       u32 nvalue;
-};
-
-/**
- * struct omap_sr_data - Smartreflex platform data.
- *
- * @ip_type:           Smartreflex IP type.
- * @senp_mod:          SENPENABLE value for the sr
- * @senn_mod:          SENNENABLE value for sr
- * @nvalue_count:      Number of distinct nvalues in the nvalue table
- * @enable_on_init:    whether this sr module needs to enabled at
- *                     boot up or not.
- * @nvalue_table:      table containing the  efuse offsets and nvalues
- *                     corresponding to them.
- * @voltdm:            Pointer to the voltage domain associated with the SR
- */
-struct omap_sr_data {
-       int                             ip_type;
-       u32                             senp_mod;
-       u32                             senn_mod;
-       int                             nvalue_count;
-       bool                            enable_on_init;
-       struct omap_sr_nvalue_table     *nvalue_table;
-       struct voltagedomain            *voltdm;
-};
-
-/* Smartreflex module enable/disable interface */
-void omap_sr_enable(struct voltagedomain *voltdm);
-void omap_sr_disable(struct voltagedomain *voltdm);
-void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
-
-/* API to register the pmic specific data with the smartreflex driver. */
-void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
-
-/* Smartreflex driver hooks to be called from Smartreflex class driver */
-int sr_enable(struct voltagedomain *voltdm, unsigned long volt);
-void sr_disable(struct voltagedomain *voltdm);
-int sr_configure_errgen(struct voltagedomain *voltdm);
-int sr_disable_errgen(struct voltagedomain *voltdm);
-int sr_configure_minmax(struct voltagedomain *voltdm);
-
-/* API to register the smartreflex class driver with the smartreflex driver */
-int sr_register_class(struct omap_sr_class_data *class_data);
-#else
-static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
-static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
-static inline void omap_sr_disable_reset_volt(
-               struct voltagedomain *voltdm) {}
-static inline void omap_sr_register_pmic(
-               struct omap_sr_pmic_data *pmic_data) {}
-#endif
-#endif
index a503e1e8358c1f011b193a22f33c48ff38ce89d2..e107e3915a8a7d1a985db47514f1ab740e1009ec 100644 (file)
@@ -17,6 +17,7 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
+#include <linux/power/smartreflex.h>
 
 #include <linux/err.h>
 #include <linux/slab.h>
@@ -24,7 +25,6 @@
 
 #include <plat/omap_device.h>
 
-#include "smartreflex.h"
 #include "voltage.h"
 #include "control.h"
 #include "pm.h"
@@ -36,7 +36,10 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
                                struct omap_sr_data *sr_data)
 {
        struct omap_sr_nvalue_table *nvalue_table;
-       int i, count = 0;
+       int i, j, count = 0;
+
+       sr_data->nvalue_count = 0;
+       sr_data->nvalue_table = NULL;
 
        while (volt_data[count].volt_nominal)
                count++;
@@ -44,8 +47,14 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
        nvalue_table = kzalloc(sizeof(struct omap_sr_nvalue_table)*count,
                        GFP_KERNEL);
 
-       for (i = 0; i < count; i++) {
+       if (!nvalue_table) {
+               pr_err("OMAP: SmartReflex: cannot allocate memory for n-value table\n");
+               return;
+       }
+
+       for (i = 0, j = 0; i < count; i++) {
                u32 v;
+
                /*
                 * In OMAP4 the efuse registers are 24 bit aligned.
                 * A __raw_readl will fail for non-32 bit aligned address
@@ -58,15 +67,30 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data,
                                omap_ctrl_readb(offset + 1) << 8 |
                                omap_ctrl_readb(offset + 2) << 16;
                } else {
-                        v = omap_ctrl_readl(volt_data[i].sr_efuse_offs);
+                       v = omap_ctrl_readl(volt_data[i].sr_efuse_offs);
                }
 
-               nvalue_table[i].efuse_offs = volt_data[i].sr_efuse_offs;
-               nvalue_table[i].nvalue = v;
+               /*
+                * Many OMAP SoCs don't have the eFuse values set.
+                * For example, pretty much all OMAP3xxx before
+                * ES3.something.
+                *
+                * XXX There needs to be some way for board files or
+                * userspace to add these in.
+                */
+               if (v == 0)
+                       continue;
+
+               nvalue_table[j].nvalue = v;
+               nvalue_table[j].efuse_offs = volt_data[i].sr_efuse_offs;
+               nvalue_table[j].errminlimit = volt_data[i].sr_errminlimit;
+               nvalue_table[j].volt_nominal = volt_data[i].volt_nominal;
+
+               j++;
        }
 
        sr_data->nvalue_table = nvalue_table;
-       sr_data->nvalue_count = count;
+       sr_data->nvalue_count = j;
 }
 
 static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
@@ -93,6 +117,7 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user)
                goto exit;
        }
 
+       sr_data->name = oh->name;
        sr_data->ip_type = oh->class->rev;
        sr_data->senn_mod = 0x1;
        sr_data->senp_mod = 0x1;
index 840929bd9daecce4ef8e1ee95c2d404a2536c9c4..13d20c8a283dd352515d659ec4c39956228a954a 100644 (file)
 #define OMAP3_SECURE_TIMER     1
 #endif
 
-/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
-#define MAX_GPTIMER_ID         12
-
-static u32 sys_timer_reserved;
-
 /* Clockevent code */
 
 static struct omap_dm_timer clkev;
@@ -173,14 +168,14 @@ static int __init omap_dm_timer_init_one(struct omap_dm_timer *timer,
                return -ENXIO;
 
        /* After the dmtimer is using hwmod these clocks won't be needed */
-       sprintf(name, "gpt%d_fck", gptimer_id);
-       timer->fclk = clk_get(NULL, name);
+       timer->fclk = clk_get(NULL, omap_hwmod_get_main_clk(oh));
        if (IS_ERR(timer->fclk))
                return -ENODEV;
 
        omap_hwmod_enable(oh);
 
-       sys_timer_reserved |= (1 << (gptimer_id - 1));
+       if (omap_dm_timer_reserve_systimer(gptimer_id))
+               return -ENODEV;
 
        if (gptimer_id != 12) {
                struct clk *src;
@@ -368,6 +363,11 @@ OMAP_SYS_TIMER_INIT(3_secure, OMAP3_SECURE_TIMER, OMAP3_CLKEV_SOURCE,
 OMAP_SYS_TIMER(3_secure)
 #endif
 
+#ifdef CONFIG_SOC_AM33XX
+OMAP_SYS_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, 2, OMAP4_MPU_SOURCE)
+OMAP_SYS_TIMER(3_am33xx)
+#endif
+
 #ifdef CONFIG_ARCH_OMAP4
 #ifdef CONFIG_LOCAL_TIMERS
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer,
@@ -393,65 +393,10 @@ static void __init omap4_timer_init(void)
 OMAP_SYS_TIMER(4)
 #endif
 
-/**
- * omap2_dm_timer_set_src - change the timer input clock source
- * @pdev:      timer platform device pointer
- * @source:    array index of parent clock source
- */
-static int omap2_dm_timer_set_src(struct platform_device *pdev, int source)
-{
-       int ret;
-       struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
-       struct clk *fclk, *parent;
-       char *parent_name = NULL;
-
-       fclk = clk_get(&pdev->dev, "fck");
-       if (IS_ERR_OR_NULL(fclk)) {
-               dev_err(&pdev->dev, "%s: %d: clk_get() FAILED\n",
-                               __func__, __LINE__);
-               return -EINVAL;
-       }
-
-       switch (source) {
-       case OMAP_TIMER_SRC_SYS_CLK:
-               parent_name = "sys_ck";
-               break;
-
-       case OMAP_TIMER_SRC_32_KHZ:
-               parent_name = "32k_ck";
-               break;
-
-       case OMAP_TIMER_SRC_EXT_CLK:
-               if (pdata->timer_ip_version == OMAP_TIMER_IP_VERSION_1) {
-                       parent_name = "alt_ck";
-                       break;
-               }
-               dev_err(&pdev->dev, "%s: %d: invalid clk src.\n",
-                       __func__, __LINE__);
-               clk_put(fclk);
-               return -EINVAL;
-       }
-
-       parent = clk_get(&pdev->dev, parent_name);
-       if (IS_ERR_OR_NULL(parent)) {
-               dev_err(&pdev->dev, "%s: %d: clk_get() %s FAILED\n",
-                       __func__, __LINE__, parent_name);
-               clk_put(fclk);
-               return -EINVAL;
-       }
-
-       ret = clk_set_parent(fclk, parent);
-       if (IS_ERR_VALUE(ret)) {
-               dev_err(&pdev->dev, "%s: clk_set_parent() to %s FAILED\n",
-                       __func__, parent_name);
-               ret = -EINVAL;
-       }
-
-       clk_put(parent);
-       clk_put(fclk);
-
-       return ret;
-}
+#ifdef CONFIG_SOC_OMAP5
+OMAP_SYS_TIMER_INIT(5, 1, OMAP4_CLKEV_SOURCE, 2, OMAP4_MPU_SOURCE)
+OMAP_SYS_TIMER(5)
+#endif
 
 /**
  * omap_timer_init - build and register timer device with an
@@ -473,7 +418,6 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
        struct dmtimer_platform_data *pdata;
        struct platform_device *pdev;
        struct omap_timer_capability_dev_attr *timer_dev_attr;
-       struct powerdomain *pwrdm;
 
        pr_debug("%s: %s\n", __func__, oh->name);
 
@@ -501,18 +445,9 @@ static int __init omap_timer_init(struct omap_hwmod *oh, void *unused)
         */
        sscanf(oh->name, "timer%2d", &id);
 
-       pdata->set_timer_src = omap2_dm_timer_set_src;
-       pdata->timer_ip_version = oh->class->rev;
+       if (timer_dev_attr)
+               pdata->timer_capability = timer_dev_attr->timer_capability;
 
-       /* Mark clocksource and clockevent timers as reserved */
-       if ((sys_timer_reserved >> (id - 1)) & 0x1)
-               pdata->reserved = 1;
-
-       pwrdm = omap_hwmod_get_pwrdm(oh);
-       pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm);
-#ifdef CONFIG_PM
-       pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
-#endif
        pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
                                 NULL, 0, 0);
 
index 43a979075338a76d03894e406952e9d6eb28c1ad..3882f3c7608cdbe77a89b826589b52c4ccfa284e 100644 (file)
@@ -49,6 +49,7 @@ static struct i2c_board_info __initdata omap4_i2c1_board_info[] = {
        },
 };
 
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
 static int twl_set_voltage(void *data, int target_uV)
 {
        struct voltagedomain *voltdm = (struct voltagedomain *)data;
@@ -60,6 +61,7 @@ static int twl_get_voltage(void *data)
        struct voltagedomain *voltdm = (struct voltagedomain *)data;
        return voltdm_get_voltage(voltdm);
 }
+#endif
 
 void __init omap_pmic_init(int bus, u32 clkrate,
                           const char *pmic_type, int pmic_irq,
@@ -213,10 +215,6 @@ static struct twl_regulator_driver_data omap3_vdd2_drvdata = {
 void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
                                  u32 pdata_flags, u32 regulators_flags)
 {
-       if (!pmic_data->irq_base)
-               pmic_data->irq_base = TWL4030_IRQ_BASE;
-       if (!pmic_data->irq_end)
-               pmic_data->irq_end = TWL4030_IRQ_END;
        if (!pmic_data->vdd1) {
                omap3_vdd1.driver_data = &omap3_vdd1_drvdata;
                omap3_vdd1_drvdata.data = voltdm_lookup("mpu_iva");
@@ -481,11 +479,6 @@ static struct regulator_init_data omap4_v2v1_idata = {
 void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
                                  u32 pdata_flags, u32 regulators_flags)
 {
-       if (!pmic_data->irq_base)
-               pmic_data->irq_base = TWL6030_IRQ_BASE;
-       if (!pmic_data->irq_end)
-               pmic_data->irq_end = TWL6030_IRQ_END;
-
        if (!pmic_data->vdd1) {
                omap4_vdd1.driver_data = &omap4_vdd1_drvdata;
                omap4_vdd1_drvdata.data = voltdm_lookup("mpu");
diff --git a/arch/arm/mach-omap2/usb-fs.c b/arch/arm/mach-omap2/usb-fs.c
deleted file mode 100644 (file)
index 1481078..0000000
+++ /dev/null
@@ -1,359 +0,0 @@
-/*
- * Platform level USB initialization for FS USB OTG controller on omap1 and 24xx
- *
- * Copyright (C) 2004 Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-
-#include <asm/irq.h>
-
-#include <plat/usb.h>
-#include <plat/board.h>
-
-#include "control.h"
-#include "mux.h"
-
-#define INT_USB_IRQ_GEN                INT_24XX_USB_IRQ_GEN
-#define INT_USB_IRQ_NISO       INT_24XX_USB_IRQ_NISO
-#define INT_USB_IRQ_ISO                INT_24XX_USB_IRQ_ISO
-#define INT_USB_IRQ_HGEN       INT_24XX_USB_IRQ_HGEN
-#define INT_USB_IRQ_OTG                INT_24XX_USB_IRQ_OTG
-
-#if defined(CONFIG_ARCH_OMAP2)
-
-#ifdef CONFIG_USB_GADGET_OMAP
-
-static struct resource udc_resources[] = {
-       /* order is significant! */
-       {               /* registers */
-               .start          = UDC_BASE,
-               .end            = UDC_BASE + 0xff,
-               .flags          = IORESOURCE_MEM,
-       }, {            /* general IRQ */
-               .start          = INT_USB_IRQ_GEN,
-               .flags          = IORESOURCE_IRQ,
-       }, {            /* PIO IRQ */
-               .start          = INT_USB_IRQ_NISO,
-               .flags          = IORESOURCE_IRQ,
-       }, {            /* SOF IRQ */
-               .start          = INT_USB_IRQ_ISO,
-               .flags          = IORESOURCE_IRQ,
-       },
-};
-
-static u64 udc_dmamask = ~(u32)0;
-
-static struct platform_device udc_device = {
-       .name           = "omap_udc",
-       .id             = -1,
-       .dev = {
-               .dma_mask               = &udc_dmamask,
-               .coherent_dma_mask      = 0xffffffff,
-       },
-       .num_resources  = ARRAY_SIZE(udc_resources),
-       .resource       = udc_resources,
-};
-
-static inline void udc_device_init(struct omap_usb_config *pdata)
-{
-       pdata->udc_device = &udc_device;
-}
-
-#else
-
-static inline void udc_device_init(struct omap_usb_config *pdata)
-{
-}
-
-#endif
-
-#if    defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-
-/* The dmamask must be set for OHCI to work */
-static u64 ohci_dmamask = ~(u32)0;
-
-static struct resource ohci_resources[] = {
-       {
-               .start  = OMAP_OHCI_BASE,
-               .end    = OMAP_OHCI_BASE + 0xff,
-               .flags  = IORESOURCE_MEM,
-       },
-       {
-               .start  = INT_USB_IRQ_HGEN,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device ohci_device = {
-       .name                   = "ohci",
-       .id                     = -1,
-       .dev = {
-               .dma_mask               = &ohci_dmamask,
-               .coherent_dma_mask      = 0xffffffff,
-       },
-       .num_resources  = ARRAY_SIZE(ohci_resources),
-       .resource               = ohci_resources,
-};
-
-static inline void ohci_device_init(struct omap_usb_config *pdata)
-{
-       pdata->ohci_device = &ohci_device;
-}
-
-#else
-
-static inline void ohci_device_init(struct omap_usb_config *pdata)
-{
-}
-
-#endif
-
-#if    defined(CONFIG_USB_OTG) && defined(CONFIG_ARCH_OMAP_OTG)
-
-static struct resource otg_resources[] = {
-       /* order is significant! */
-       {
-               .start          = OTG_BASE,
-               .end            = OTG_BASE + 0xff,
-               .flags          = IORESOURCE_MEM,
-       }, {
-               .start          = INT_USB_IRQ_OTG,
-               .flags          = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device otg_device = {
-       .name           = "omap_otg",
-       .id             = -1,
-       .num_resources  = ARRAY_SIZE(otg_resources),
-       .resource       = otg_resources,
-};
-
-static inline void otg_device_init(struct omap_usb_config *pdata)
-{
-       pdata->otg_device = &otg_device;
-}
-
-#else
-
-static inline void otg_device_init(struct omap_usb_config *pdata)
-{
-}
-
-#endif
-
-static void omap2_usb_devconf_clear(u8 port, u32 mask)
-{
-       u32 r;
-
-       r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-       r &= ~USBTXWRMODEI(port, mask);
-       omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0);
-}
-
-static void omap2_usb_devconf_set(u8 port, u32 mask)
-{
-       u32 r;
-
-       r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-       r |= USBTXWRMODEI(port, mask);
-       omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0);
-}
-
-static void omap2_usb2_disable_5pinbitll(void)
-{
-       u32 r;
-
-       r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-       r &= ~(USBTXWRMODEI(2, USB_BIDIR_TLL) | USBT2TLL5PI);
-       omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0);
-}
-
-static void omap2_usb2_enable_5pinunitll(void)
-{
-       u32 r;
-
-       r = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-       r |= USBTXWRMODEI(2, USB_UNIDIR_TLL) | USBT2TLL5PI;
-       omap_ctrl_writel(r, OMAP2_CONTROL_DEVCONF0);
-}
-
-static u32 __init omap2_usb0_init(unsigned nwires, unsigned is_device)
-{
-       u32     syscon1 = 0;
-
-       omap2_usb_devconf_clear(0, USB_BIDIR_TLL);
-
-       if (nwires == 0)
-               return 0;
-
-       if (is_device)
-               omap_mux_init_signal("usb0_puen", 0);
-
-       omap_mux_init_signal("usb0_dat", 0);
-       omap_mux_init_signal("usb0_txen", 0);
-       omap_mux_init_signal("usb0_se0", 0);
-       if (nwires != 3)
-               omap_mux_init_signal("usb0_rcv", 0);
-
-       switch (nwires) {
-       case 3:
-               syscon1 = 2;
-               omap2_usb_devconf_set(0, USB_BIDIR);
-               break;
-       case 4:
-               syscon1 = 1;
-               omap2_usb_devconf_set(0, USB_BIDIR);
-               break;
-       case 6:
-               syscon1 = 3;
-               omap_mux_init_signal("usb0_vp", 0);
-               omap_mux_init_signal("usb0_vm", 0);
-               omap2_usb_devconf_set(0, USB_UNIDIR);
-               break;
-       default:
-               printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
-                       0, nwires);
-       }
-
-       return syscon1 << 16;
-}
-
-static u32 __init omap2_usb1_init(unsigned nwires)
-{
-       u32     syscon1 = 0;
-
-       omap2_usb_devconf_clear(1, USB_BIDIR_TLL);
-
-       if (nwires == 0)
-               return 0;
-
-       /* NOTE:  board-specific code must set up pin muxing for usb1,
-        * since each signal could come out on either of two balls.
-        */
-
-       switch (nwires) {
-       case 2:
-               /* NOTE: board-specific code must override this setting if
-                * this TLL link is not using DP/DM
-                */
-               syscon1 = 1;
-               omap2_usb_devconf_set(1, USB_BIDIR_TLL);
-               break;
-       case 3:
-               syscon1 = 2;
-               omap2_usb_devconf_set(1, USB_BIDIR);
-               break;
-       case 4:
-               syscon1 = 1;
-               omap2_usb_devconf_set(1, USB_BIDIR);
-               break;
-       case 6:
-       default:
-               printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
-                       1, nwires);
-       }
-
-       return syscon1 << 20;
-}
-
-static u32 __init omap2_usb2_init(unsigned nwires, unsigned alt_pingroup)
-{
-       u32     syscon1 = 0;
-
-       omap2_usb2_disable_5pinbitll();
-       alt_pingroup = 0;
-
-       /* NOTE omap1 erratum: must leave USB2_UNI_R set if usb0 in use */
-       if (alt_pingroup || nwires == 0)
-               return 0;
-
-       omap_mux_init_signal("usb2_dat", 0);
-       omap_mux_init_signal("usb2_se0", 0);
-       if (nwires > 2)
-               omap_mux_init_signal("usb2_txen", 0);
-       if (nwires > 3)
-               omap_mux_init_signal("usb2_rcv", 0);
-
-       switch (nwires) {
-       case 2:
-               /* NOTE: board-specific code must override this setting if
-                * this TLL link is not using DP/DM
-                */
-               syscon1 = 1;
-               omap2_usb_devconf_set(2, USB_BIDIR_TLL);
-               break;
-       case 3:
-               syscon1 = 2;
-               omap2_usb_devconf_set(2, USB_BIDIR);
-               break;
-       case 4:
-               syscon1 = 1;
-               omap2_usb_devconf_set(2, USB_BIDIR);
-               break;
-       case 5:
-               /* NOTE: board-specific code must mux this setting depending
-                * on TLL link using DP/DM.  Something must also
-                * set up OTG_SYSCON2.HMC_TLL{ATTACH,SPEED}
-                * 2420: hdq_sio.usb2_tllse0 or vlynq_rx0.usb2_tllse0
-                * 2430: hdq_sio.usb2_tllse0 or sdmmc2_dat0.usb2_tllse0
-                */
-
-               syscon1 = 3;
-               omap2_usb2_enable_5pinunitll();
-               break;
-       case 6:
-       default:
-               printk(KERN_ERR "illegal usb%d %d-wire transceiver\n",
-                       2, nwires);
-       }
-
-       return syscon1 << 24;
-}
-
-void __init omap2_usbfs_init(struct omap_usb_config *pdata)
-{
-       struct clk *ick;
-
-       if (!cpu_is_omap24xx())
-               return;
-
-       ick = clk_get(NULL, "usb_l4_ick");
-       if (IS_ERR(ick))
-               return;
-
-       clk_enable(ick);
-       pdata->usb0_init = omap2_usb0_init;
-       pdata->usb1_init = omap2_usb1_init;
-       pdata->usb2_init = omap2_usb2_init;
-       udc_device_init(pdata);
-       ohci_device_init(pdata);
-       otg_device_init(pdata);
-       omap_otg_init(pdata);
-       clk_disable(ick);
-       clk_put(ick);
-}
-
-#endif
index 16a1b092cf36902b768010fc899b4defcded7eb3..0ac2caf159410d96831542c867afd81a789838e5 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <linux/err.h>
 
+#include <plat/voltage.h>
+
 #include "vc.h"
 #include "vp.h"
 
@@ -90,25 +92,6 @@ struct voltagedomain {
        struct omap_volt_data *volt_data;
 };
 
-/**
- * struct omap_volt_data - Omap voltage specific data.
- * @voltage_nominal:   The possible voltage value in uV
- * @sr_efuse_offs:     The offset of the efuse register(from system
- *                     control module base address) from where to read
- *                     the n-target value for the smartreflex module.
- * @sr_errminlimit:    Error min limit value for smartreflex. This value
- *                     differs at differnet opp and thus is linked
- *                     with voltage.
- * @vp_errorgain:      Error gain value for the voltage processor. This
- *                     field also differs according to the voltage/opp.
- */
-struct omap_volt_data {
-       u32     volt_nominal;
-       u32     sr_efuse_offs;
-       u8      sr_errminlimit;
-       u8      vp_errgain;
-};
-
 /**
  * struct omap_voltdm_pmic - PMIC specific data required by voltage driver.
  * @slew_rate: PMIC slew rate (in uv/us)
@@ -156,6 +139,7 @@ int omap_voltage_late_init(void);
 
 extern void omap2xxx_voltagedomains_init(void);
 extern void omap3xxx_voltagedomains_init(void);
+extern void am33xx_voltagedomains_init(void);
 extern void omap44xx_voltagedomains_init(void);
 
 struct voltagedomain *voltdm_lookup(const char *name);
diff --git a/arch/arm/mach-omap2/voltagedomains33xx_data.c b/arch/arm/mach-omap2/voltagedomains33xx_data.c
new file mode 100644 (file)
index 0000000..965458d
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * AM33XX voltage domain data
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+
+#include "voltage.h"
+
+static struct voltagedomain am33xx_voltdm_mpu = {
+       .name           = "mpu",
+};
+
+static struct voltagedomain am33xx_voltdm_core = {
+       .name           = "core",
+};
+
+static struct voltagedomain am33xx_voltdm_rtc = {
+       .name           = "rtc",
+};
+
+static struct voltagedomain *voltagedomains_am33xx[] __initdata = {
+       &am33xx_voltdm_mpu,
+       &am33xx_voltdm_core,
+       &am33xx_voltdm_rtc,
+       NULL,
+};
+
+void __init am33xx_voltagedomains_init(void)
+{
+       voltdm_init(voltagedomains_am33xx);
+}
index e5ec4a8d9bcb39e370a26742e237d3896dc0a20d..8e39f80fce1914a5da7a76a6dfeb22f64327e522 100644 (file)
@@ -1,2 +1 @@
 obj-y  := common.o
-obj-y  += time.o
index a2e8ae8b58214d6e702984e8b749b03ce3878acf..8f9a0b47a7fa8293860036c09516854109a310f1 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
+#include <linux/dw_apb_timer.h>
 
 #include <asm/mach/arch.h>
 #include <asm/hardware/vic.h>
@@ -97,7 +98,7 @@ DT_MACHINE_START(PICOXCELL, "Picochip picoXcell")
        .nr_irqs        = NR_IRQS_LEGACY,
        .init_irq       = picoxcell_init_irq,
        .handle_irq     = vic_handle_irq,
-       .timer          = &picoxcell_timer,
+       .timer          = &dw_apb_timer,
        .init_machine   = picoxcell_init_machine,
        .dt_compat      = picoxcell_dt_match,
        .restart        = picoxcell_wdt_restart,
index 83d55ab956a49882979cd220507aa6327645c0e9..a65cb02f84c8d4824b319718942f3b71d7d2fae4 100644 (file)
@@ -12,6 +12,6 @@
 
 #include <asm/mach/time.h>
 
-extern struct sys_timer picoxcell_timer;
+extern struct sys_timer dw_apb_timer;
 
 #endif /* __PICOXCELL_COMMON_H__ */
diff --git a/arch/arm/mach-picoxcell/time.c b/arch/arm/mach-picoxcell/time.c
deleted file mode 100644 (file)
index 2ecba67..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2011 Picochip Ltd., Jamie Iles
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * All enquiries to support@picochip.com
- */
-#include <linux/dw_apb_timer.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_irq.h>
-
-#include <asm/mach/time.h>
-#include <asm/sched_clock.h>
-
-#include "common.h"
-
-static void timer_get_base_and_rate(struct device_node *np,
-                                   void __iomem **base, u32 *rate)
-{
-       *base = of_iomap(np, 0);
-
-       if (!*base)
-               panic("Unable to map regs for %s", np->name);
-
-       if (of_property_read_u32(np, "clock-freq", rate))
-               panic("No clock-freq property for %s", np->name);
-}
-
-static void picoxcell_add_clockevent(struct device_node *event_timer)
-{
-       void __iomem *iobase;
-       struct dw_apb_clock_event_device *ced;
-       u32 irq, rate;
-
-       irq = irq_of_parse_and_map(event_timer, 0);
-       if (irq == NO_IRQ)
-               panic("No IRQ for clock event timer");
-
-       timer_get_base_and_rate(event_timer, &iobase, &rate);
-
-       ced = dw_apb_clockevent_init(0, event_timer->name, 300, iobase, irq,
-                                    rate);
-       if (!ced)
-               panic("Unable to initialise clockevent device");
-
-       dw_apb_clockevent_register(ced);
-}
-
-static void picoxcell_add_clocksource(struct device_node *source_timer)
-{
-       void __iomem *iobase;
-       struct dw_apb_clocksource *cs;
-       u32 rate;
-
-       timer_get_base_and_rate(source_timer, &iobase, &rate);
-
-       cs = dw_apb_clocksource_init(300, source_timer->name, iobase, rate);
-       if (!cs)
-               panic("Unable to initialise clocksource device");
-
-       dw_apb_clocksource_start(cs);
-       dw_apb_clocksource_register(cs);
-}
-
-static void __iomem *sched_io_base;
-
-static u32 picoxcell_read_sched_clock(void)
-{
-       return __raw_readl(sched_io_base);
-}
-
-static const struct of_device_id picoxcell_rtc_ids[] __initconst = {
-       { .compatible = "picochip,pc3x2-rtc" },
-       { /* Sentinel */ },
-};
-
-static void picoxcell_init_sched_clock(void)
-{
-       struct device_node *sched_timer;
-       u32 rate;
-
-       sched_timer = of_find_matching_node(NULL, picoxcell_rtc_ids);
-       if (!sched_timer)
-               panic("No RTC for sched clock to use");
-
-       timer_get_base_and_rate(sched_timer, &sched_io_base, &rate);
-       of_node_put(sched_timer);
-
-       setup_sched_clock(picoxcell_read_sched_clock, 32, rate);
-}
-
-static const struct of_device_id picoxcell_timer_ids[] __initconst = {
-       { .compatible = "picochip,pc3x2-timer" },
-       {},
-};
-
-static void __init picoxcell_timer_init(void)
-{
-       struct device_node *event_timer, *source_timer;
-
-       event_timer = of_find_matching_node(NULL, picoxcell_timer_ids);
-       if (!event_timer)
-               panic("No timer for clockevent");
-       picoxcell_add_clockevent(event_timer);
-
-       source_timer = of_find_matching_node(event_timer, picoxcell_timer_ids);
-       if (!source_timer)
-               panic("No timer for clocksource");
-       picoxcell_add_clocksource(source_timer);
-
-       of_node_put(source_timer);
-
-       picoxcell_init_sched_clock();
-}
-
-struct sys_timer picoxcell_timer = {
-       .init = picoxcell_timer_init,
-};
diff --git a/arch/arm/mach-prima2/include/mach/gpio.h b/arch/arm/mach-prima2/include/mach/gpio.h
new file mode 100644 (file)
index 0000000..1904bb0
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __MACH_GPIO_H
+#define __MACH_GPIO_H
+
+/* Pull up/down values */
+enum sirfsoc_gpio_pull {
+       SIRFSOC_GPIO_PULL_NONE,
+       SIRFSOC_GPIO_PULL_UP,
+       SIRFSOC_GPIO_PULL_DOWN,
+};
+
+void sirfsoc_gpio_set_pull(unsigned gpio, unsigned mode);
+
+#endif
index bb354f952fd65eda8d9a62a89571c5c90cb5471e..f6014a07541f92d3a7a2d89d7d76a99847c9b7f6 100644 (file)
@@ -11,7 +11,7 @@
 
 #define SIRFSOC_INTENAL_IRQ_START  0
 #define SIRFSOC_INTENAL_IRQ_END    59
-
+#define SIRFSOC_GPIO_IRQ_START     (SIRFSOC_INTENAL_IRQ_END + 1)
 #define NR_IRQS        220
 
 #endif
index cf0e669eaf1a2be156abf3bf448a0759ddfc4bcc..3e4fa849c64dbc7de6c3a441124396c77c39f58d 100644 (file)
@@ -163,6 +163,6 @@ void __init rpc_init_irq(void)
                }
        }
 
-       init_FIQ();
+       init_FIQ(FIQ_START);
 }
 
index 8702ecfaab3098f3987cd4bc6c23a2bc88a07a8e..14a81c2317a417eb14b3fc413678a5541e9b09a5 100644 (file)
@@ -144,7 +144,8 @@ static struct clk_lookup s3c2416_clk_lookup[] = {
        CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.0", &hsmmc0_clk),
        CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &hsmmc_mux0.clk),
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &hsmmc_mux1.clk),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &hsspi_mux.clk),
+       /* s3c2443-spi.0 is used on s3c2416 and s3c2450 as well */
+       CLKDEV_INIT("s3c2443-spi.0", "spi_busclk2", &hsspi_mux.clk),
 };
 
 void __init s3c2416_init_clocks(int xtal)
index a4c5a520d9942abe648af870f978e79ebf15bab4..7f689ce1be614b7f2b7d43a860168f677b22d330 100644 (file)
@@ -181,7 +181,7 @@ static struct clk *clks[] __initdata = {
 
 static struct clk_lookup s3c2443_clk_lookup[] = {
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_hsmmc),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &clk_hsspi.clk),
+       CLKDEV_INIT("s3c2443-spi.0", "spi_busclk2", &clk_hsspi.clk),
 };
 
 void __init s3c2443_init_clocks(int xtal)
index aeeb2be283fae341492bbe08efb3a44298182ebb..aeb4a24ff3edffb7cb79f308cc85911c555427e0 100644 (file)
@@ -559,7 +559,7 @@ static struct clk hsmmc1_clk = {
 
 static struct clk hsspi_clk = {
        .name           = "spi",
-       .devname        = "s3c64xx-spi.0",
+       .devname        = "s3c2443-spi.0",
        .parent         = &clk_p,
        .enable         = s3c2443_clkcon_enable_p,
        .ctrlbit        = S3C2443_PCLKCON_HSSPI,
@@ -633,7 +633,7 @@ static struct clk_lookup s3c2443_clk_lookup[] = {
        CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_p),
        CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_esys_uart.clk),
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.0", &hsmmc1_clk),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk0", &hsspi_clk),
+       CLKDEV_INIT("s3c2443-spi.0", "spi_busclk0", &hsspi_clk),
 };
 
 void __init s3c2443_common_init_clocks(int xtal, pll_fn get_mpll,
index 084604be6ad1317c8b58e78e96d878e291b53bb4..87e75a250d5eafe84cf4586fbaf0a563ab00ed96 100644 (file)
@@ -182,19 +182,21 @@ static struct platform_device __initdata *smdk_devs[] = {
        &smdk_led7,
 };
 
+static const struct gpio smdk_led_gpios[] = {
+       { S3C2410_GPF(4), GPIOF_OUT_INIT_HIGH, NULL },
+       { S3C2410_GPF(5), GPIOF_OUT_INIT_HIGH, NULL },
+       { S3C2410_GPF(6), GPIOF_OUT_INIT_HIGH, NULL },
+       { S3C2410_GPF(7), GPIOF_OUT_INIT_HIGH, NULL },
+};
+
 void __init smdk_machine_init(void)
 {
        /* Configure the LEDs (even if we have no LED support)*/
 
-       s3c_gpio_cfgpin(S3C2410_GPF(4), S3C2410_GPIO_OUTPUT);
-       s3c_gpio_cfgpin(S3C2410_GPF(5), S3C2410_GPIO_OUTPUT);
-       s3c_gpio_cfgpin(S3C2410_GPF(6), S3C2410_GPIO_OUTPUT);
-       s3c_gpio_cfgpin(S3C2410_GPF(7), S3C2410_GPIO_OUTPUT);
-
-       s3c2410_gpio_setpin(S3C2410_GPF(4), 1);
-       s3c2410_gpio_setpin(S3C2410_GPF(5), 1);
-       s3c2410_gpio_setpin(S3C2410_GPF(6), 1);
-       s3c2410_gpio_setpin(S3C2410_GPF(7), 1);
+       int ret = gpio_request_array(smdk_led_gpios,
+                                    ARRAY_SIZE(smdk_led_gpios));
+       if (!WARN_ON(ret < 0))
+               gpio_free_array(smdk_led_gpios, ARRAY_SIZE(smdk_led_gpios));
 
        if (machine_is_smdk2443())
                smdk_nand_info.twrph0 = 50;
index 56cdd34cce41ee3200b111a05bbf0a196acd86c0..0c9e9a785ef6e85d7e41260e09de23f1397a0871 100644 (file)
@@ -41,7 +41,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 #include <plat/regs-serial.h>
 
diff --git a/arch/arm/mach-s3c24xx/include/mach/bast-pmu.h b/arch/arm/mach-s3c24xx/include/mach/bast-pmu.h
deleted file mode 100644 (file)
index 4c38b39..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/bast-pmu.h
- *
- * Copyright (c) 2003-2004 Simtec Electronics
- *     Ben Dooks <ben@simtec.co.uk>
- *     Vincent Sanders <vince@simtec.co.uk>
- *
- * Machine BAST - Power Management chip
- *
- * 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_BASTPMU_H
-#define __ASM_ARCH_BASTPMU_H "08_OCT_2004"
-
-#define BASTPMU_REG_IDENT      (0x00)
-#define BASTPMU_REG_VERSION    (0x01)
-#define BASTPMU_REG_DDCCTRL    (0x02)
-#define BASTPMU_REG_POWER      (0x03)
-#define BASTPMU_REG_RESET      (0x04)
-#define BASTPMU_REG_GWO                (0x05)
-#define BASTPMU_REG_WOL                (0x06)
-#define BASTPMU_REG_WOR                (0x07)
-#define BASTPMU_REG_UID                (0x09)
-
-#define BASTPMU_EEPROM         (0xC0)
-
-#define BASTPMU_EEP_UID                (BASTPMU_EEPROM + 0)
-#define BASTPMU_EEP_WOL                (BASTPMU_EEPROM + 8)
-#define BASTPMU_EEP_WOR                (BASTPMU_EEPROM + 9)
-
-#define BASTPMU_IDENT_0                0x53
-#define BASTPMU_IDENT_1                0x42
-#define BASTPMU_IDENT_2                0x50
-#define BASTPMU_IDENT_3                0x4d
-
-#define BASTPMU_RESET_GUARD    (0x55)
-
-#endif /* __ASM_ARCH_BASTPMU_H */
index 019ea86057f69b4b7e383a3f871c13fb4d5fba0f..3890a05948fb1f8d8e8b4c5682feaea8f55b3574 100644 (file)
@@ -93,26 +93,5 @@ enum s3c_gpio_number {
 #define S3C2410_GPL(_nr)       (S3C2410_GPIO_L_START + (_nr))
 #define S3C2410_GPM(_nr)       (S3C2410_GPIO_M_START + (_nr))
 
-/* compatibility until drivers can be modified */
-
-#define S3C2410_GPA0   S3C2410_GPA(0)
-#define S3C2410_GPA1   S3C2410_GPA(1)
-#define S3C2410_GPA3   S3C2410_GPA(3)
-#define S3C2410_GPA7   S3C2410_GPA(7)
-
-#define S3C2410_GPE0   S3C2410_GPE(0)
-#define S3C2410_GPE1   S3C2410_GPE(1)
-#define S3C2410_GPE2   S3C2410_GPE(2)
-#define S3C2410_GPE3   S3C2410_GPE(3)
-#define S3C2410_GPE4   S3C2410_GPE(4)
-#define S3C2410_GPE5   S3C2410_GPE(5)
-#define S3C2410_GPE6   S3C2410_GPE(6)
-#define S3C2410_GPE7   S3C2410_GPE(7)
-#define S3C2410_GPE8   S3C2410_GPE(8)
-#define S3C2410_GPE9   S3C2410_GPE(9)
-#define S3C2410_GPE10  S3C2410_GPE(10)
-
-#define S3C2410_GPH10  S3C2410_GPH(10)
-
 #endif /* __MACH_GPIONRS_H */
 
index 3a56a229cac6634e47f3910e95dd21c99b527a50..2173934821533e8f1f70318e60040689429a07b4 100644 (file)
@@ -3,82 +3,13 @@
 
 #include <mach/regs-gpio.h>
 
-/* Different hardware revisions, passed in ATAG_REVISION by u-boot */
-#define GTA02v1_SYSTEM_REV     0x00000310
-#define GTA02v2_SYSTEM_REV     0x00000320
-#define GTA02v3_SYSTEM_REV     0x00000330
-#define GTA02v4_SYSTEM_REV     0x00000340
-#define GTA02v5_SYSTEM_REV     0x00000350
-/* since A7 is basically same as A6, we use A6 PCB ID */
-#define GTA02v6_SYSTEM_REV     0x00000360
-
-#define GTA02_GPIO_n3DL_GSM    S3C2410_GPA(13) /* v1 + v2 + v3 only */
-
-#define GTA02_GPIO_PWR_LED1    S3C2410_GPB(0)
-#define GTA02_GPIO_PWR_LED2    S3C2410_GPB(1)
 #define GTA02_GPIO_AUX_LED     S3C2410_GPB(2)
-#define GTA02_GPIO_VIBRATOR_ON S3C2410_GPB(3)
-#define GTA02_GPIO_MODEM_RST   S3C2410_GPB(5)
-#define GTA02_GPIO_BT_EN       S3C2410_GPB(6)
-#define GTA02_GPIO_MODEM_ON    S3C2410_GPB(7)
-#define GTA02_GPIO_EXTINT8     S3C2410_GPB(8)
 #define GTA02_GPIO_USB_PULLUP  S3C2410_GPB(9)
-
-#define GTA02_GPIO_PIO5                S3C2410_GPC(5)  /* v3 + v4 only */
-
-#define GTA02v3_GPIO_nG1_CS    S3C2410_GPD(12) /* v3 + v4 only */
-#define GTA02v3_GPIO_nG2_CS    S3C2410_GPD(13) /* v3 + v4 only */
-#define GTA02v5_GPIO_HDQ       S3C2410_GPD(14)   /* v5 + */
-
-#define GTA02_GPIO_nG1_INT     S3C2410_GPF(0)
-#define GTA02_GPIO_IO1         S3C2410_GPF(1)
-#define GTA02_GPIO_PIO_2       S3C2410_GPF(2)  /* v2 + v3 + v4 only */
-#define GTA02_GPIO_JACK_INSERT S3C2410_GPF(4)
-#define GTA02_GPIO_WLAN_GPIO1  S3C2410_GPF(5)  /* v2 + v3 + v4 only */
 #define GTA02_GPIO_AUX_KEY     S3C2410_GPF(6)
 #define GTA02_GPIO_HOLD_KEY    S3C2410_GPF(7)
-
-#define GTA02_GPIO_3D_IRQ      S3C2410_GPG(4)
-#define GTA02v2_GPIO_nG2_INT   S3C2410_GPG(8)  /* v2 + v3 + v4 only */
-#define GTA02v3_GPIO_nUSB_OC   S3C2410_GPG(9)  /* v3 + v4 only */
-#define GTA02v3_GPIO_nUSB_FLT  S3C2410_GPG(10) /* v3 + v4 only */
-#define GTA02v3_GPIO_nGSM_OC   S3C2410_GPG(11) /* v3 + v4 only */
-
 #define GTA02_GPIO_AMP_SHUT    S3C2410_GPJ(1)  /* v2 + v3 + v4 only */
-#define GTA02v1_GPIO_WLAN_GPIO10       S3C2410_GPJ(2)
 #define GTA02_GPIO_HP_IN       S3C2410_GPJ(2)  /* v2 + v3 + v4 only */
-#define GTA02_GPIO_INT0                S3C2410_GPJ(3)  /* v2 + v3 + v4 only */
-#define GTA02_GPIO_nGSM_EN     S3C2410_GPJ(4)
-#define GTA02_GPIO_3D_RESET    S3C2410_GPJ(5)
-#define GTA02_GPIO_nDL_GSM     S3C2410_GPJ(6)  /* v4 + v5 only */
-#define GTA02_GPIO_WLAN_GPIO0  S3C2410_GPJ(7)
-#define GTA02v1_GPIO_BAT_ID    S3C2410_GPJ(8)
-#define GTA02_GPIO_KEEPACT     S3C2410_GPJ(8)
-#define GTA02v1_GPIO_HP_IN     S3C2410_GPJ(10)
-#define GTA02_CHIP_PWD         S3C2410_GPJ(11) /* v2 + v3 + v4 only */
-#define GTA02_GPIO_nWLAN_RESET S3C2410_GPJ(12) /* v2 + v3 + v4 only */
 
-#define GTA02_IRQ_GSENSOR_1    IRQ_EINT0
-#define GTA02_IRQ_MODEM                IRQ_EINT1
-#define GTA02_IRQ_PIO_2                IRQ_EINT2       /* v2 + v3 + v4 only */
-#define GTA02_IRQ_nJACK_INSERT IRQ_EINT4
-#define GTA02_IRQ_WLAN_GPIO1   IRQ_EINT5
-#define GTA02_IRQ_AUX          IRQ_EINT6
-#define GTA02_IRQ_nHOLD                IRQ_EINT7
 #define GTA02_IRQ_PCF50633     IRQ_EINT9
-#define GTA02_IRQ_3D           IRQ_EINT12
-#define GTA02_IRQ_GSENSOR_2    IRQ_EINT16      /* v2 + v3 + v4 only */
-#define GTA02v3_IRQ_nUSB_OC    IRQ_EINT17      /* v3 + v4 only */
-#define GTA02v3_IRQ_nUSB_FLT   IRQ_EINT18      /* v3 + v4 only */
-#define GTA02v3_IRQ_nGSM_OC    IRQ_EINT19      /* v3 + v4 only */
-
-/* returns 00 000 on GTA02 A5 and earlier, A6 returns 01 001 */
-#define GTA02_PCB_ID1_0                S3C2410_GPC(13)
-#define GTA02_PCB_ID1_1                S3C2410_GPC(15)
-#define GTA02_PCB_ID1_2                S3C2410_GPD(0)
-#define GTA02_PCB_ID2_0                S3C2410_GPD(3)
-#define GTA02_PCB_ID2_1                S3C2410_GPD(4)
-
-int gta02_get_pcb_revision(void);
 
 #endif /* _GTA02_H */
index cac1ad6b582cc42aaede66ff65ca9931e4e58724..a11a638bd5996368a9bc28b265462e19496e3d92 100644 (file)
 /* S3C2410:
  * Port G consists of 8 GPIO/IRQ/Special function
  *
- * GPGCON has 2 bits for each of the input pins on port F
+ * GPGCON has 2 bits for each of the input pins on port G
  *   00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 special func
  *
  * pull up works like all other ports.
 
 /* Port H consists of11 GPIO/serial/Misc pins
  *
- * GPGCON has 2 bits for each of the input pins on port F
+ * GPHCON has 2 bits for each of the input pins on port H
  *   00 = 0 input, 1 output, 2 interrupt (EINT0..7), 3 special func
  *
  * pull up works like all other ports.
  * for the 2412/2413 from the 2410/2440/2442
 */
 
+/*
+ * Port J consists of 13 GPIO/Camera pins. GPJCON has 2 bits
+ * for each of the pins on port J.
+ *   00 - input, 01 output, 10 - camera
+ *
+ * Pull up works like all other ports.
+ */
+
+#define S3C2413_GPJCON    S3C2410_GPIOREG(0x80)
+#define S3C2413_GPJDAT    S3C2410_GPIOREG(0x84)
+#define S3C2413_GPJUP     S3C2410_GPIOREG(0x88)
+#define S3C2413_GPJSLPCON  S3C2410_GPIOREG(0x8C)
+
 /* S3C2443 and above */
 #define S3C2440_GPJCON    S3C2410_GPIOREG(0xD0)
 #define S3C2440_GPJDAT    S3C2410_GPIOREG(0xD4)
diff --git a/arch/arm/mach-s3c24xx/include/mach/regs-gpioj.h b/arch/arm/mach-s3c24xx/include/mach/regs-gpioj.h
deleted file mode 100644 (file)
index 19575e0..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/* arch/arm/mach-s3c2410/include/mach/regs-gpioj.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.
- *
- * S3C2440 GPIO J register definitions
-*/
-
-
-#ifndef __ASM_ARCH_REGS_GPIOJ_H
-#define __ASM_ARCH_REGS_GPIOJ_H "gpioj"
-
-/* Port J consists of 13 GPIO/Camera pins
- *
- * GPJCON has 2 bits for each of the input pins on port F
- *   00 = 0 input, 1 output, 2 Camera
- *
- * pull up works like all other ports.
-*/
-
-#define S3C2413_GPJCON         S3C2410_GPIOREG(0x80)
-#define S3C2413_GPJDAT         S3C2410_GPIOREG(0x84)
-#define S3C2413_GPJUP          S3C2410_GPIOREG(0x88)
-#define S3C2413_GPJSLPCON      S3C2410_GPIOREG(0x8C)
-
-#define S3C2440_GPJ0_OUTP       (0x01 << 0)
-#define S3C2440_GPJ0_CAMDATA0   (0x02 << 0)
-
-#define S3C2440_GPJ1_OUTP       (0x01 << 2)
-#define S3C2440_GPJ1_CAMDATA1   (0x02 << 2)
-
-#define S3C2440_GPJ2_OUTP       (0x01 << 4)
-#define S3C2440_GPJ2_CAMDATA2   (0x02 << 4)
-
-#define S3C2440_GPJ3_OUTP       (0x01 << 6)
-#define S3C2440_GPJ3_CAMDATA3   (0x02 << 6)
-
-#define S3C2440_GPJ4_OUTP       (0x01 << 8)
-#define S3C2440_GPJ4_CAMDATA4   (0x02 << 8)
-
-#define S3C2440_GPJ5_OUTP       (0x01 << 10)
-#define S3C2440_GPJ5_CAMDATA5   (0x02 << 10)
-
-#define S3C2440_GPJ6_OUTP       (0x01 << 12)
-#define S3C2440_GPJ6_CAMDATA6   (0x02 << 12)
-
-#define S3C2440_GPJ7_OUTP       (0x01 << 14)
-#define S3C2440_GPJ7_CAMDATA7   (0x02 << 14)
-
-#define S3C2440_GPJ8_OUTP       (0x01 << 16)
-#define S3C2440_GPJ8_CAMPCLK    (0x02 << 16)
-
-#define S3C2440_GPJ9_OUTP       (0x01 << 18)
-#define S3C2440_GPJ9_CAMVSYNC   (0x02 << 18)
-
-#define S3C2440_GPJ10_OUTP      (0x01 << 20)
-#define S3C2440_GPJ10_CAMHREF   (0x02 << 20)
-
-#define S3C2440_GPJ11_OUTP      (0x01 << 22)
-#define S3C2440_GPJ11_CAMCLKOUT (0x02 << 22)
-
-#define S3C2440_GPJ12_OUTP      (0x01 << 24)
-#define S3C2440_GPJ12_CAMRESET  (0x02 << 24)
-
-#endif /* __ASM_ARCH_REGS_GPIOJ_H */
-
index 0f29f64a3eeb8b98c3b3e6ccd394687cffe83b42..92e1f93a6bca73f9c0227e6bbd8c1283d452fe4e 100644 (file)
@@ -71,7 +71,6 @@
 
 #include <mach/regs-irq.h>
 #include <mach/regs-gpio.h>
-#include <mach/regs-gpioj.h>
 #include <mach/fb.h>
 
 #include <plat/usb-control.h>
index f092b188ab70afba8e3012aad0b717c9936b97be..bd6d2525debef34a3d6e8752912bcb26da6cf52f 100644 (file)
@@ -634,8 +634,8 @@ static void __init mini2440_init(void)
        s3c_gpio_cfgpin(S3C2410_GPC(0), S3C2410_GPC0_LEND);
 
        /* Turn the backlight early on */
-       WARN_ON(gpio_request(S3C2410_GPG(4), "backlight"));
-       gpio_direction_output(S3C2410_GPG(4), 1);
+       WARN_ON(gpio_request_one(S3C2410_GPG(4), GPIOF_OUT_INIT_HIGH, NULL));
+       gpio_free(S3C2410_GPG(4));
 
        /* remove pullup on optional PWM backlight -- unused on 3.5 and 7"s */
        s3c_gpio_setpull(S3C2410_GPB(1), S3C_GPIO_PULL_UP);
index b868dddcb836c318d4315feeaaef1f37a5e851da..678bbca2b5e5ae7738e5921b041afb80a0214af6 100644 (file)
@@ -47,7 +47,6 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <mach/regs-gpio.h>
 #include <mach/leds-gpio.h>
 #include <mach/regs-lcd.h>
 #include <plat/regs-serial.h>
@@ -325,8 +324,9 @@ static void __init qt2410_machine_init(void)
        }
        s3c24xx_fb_set_platdata(&qt2410_fb_info);
 
-       s3c_gpio_cfgpin(S3C2410_GPB(0), S3C2410_GPIO_OUTPUT);
-       s3c2410_gpio_setpin(S3C2410_GPB(0), 1);
+       /* set initial state of the LED GPIO */
+       WARN_ON(gpio_request_one(S3C2410_GPB(0), GPIOF_OUT_INIT_HIGH, NULL));
+       gpio_free(S3C2410_GPB(0));
 
        s3c24xx_udc_set_platdata(&qt2410_udc_cfg);
        s3c_i2c0_set_platdata(NULL);
index a6762aae4727f0289724ac1746aa2b3adaf63a7b..7ee73f27f207db87456f904405e61e16c4fceb0e 100644 (file)
@@ -42,7 +42,6 @@
 #include <asm/mach-types.h>
 
 #include <mach/regs-gpio.h>
-#include <mach/regs-gpioj.h>
 #include <mach/regs-lcd.h>
 #include <mach/h1940.h>
 #include <mach/fb.h>
index 03f706dd6009a2f21b5910991c4e228351529ba7..949ae05e07c5c8ff103c6d053da9c650bccbfe96 100644 (file)
@@ -77,8 +77,10 @@ static void s3c2410_pm_prepare(void)
                __raw_writel(calc, phys_to_virt(H1940_SUSPEND_CHECKSUM));
        }
 
-       if ( machine_is_aml_m5900() )
-               s3c2410_gpio_setpin(S3C2410_GPF(2), 1);
+       if (machine_is_aml_m5900()) {
+               gpio_request_one(S3C2410_GPF(2), GPIOF_OUT_INIT_HIGH, NULL);
+               gpio_free(S3C2410_GPF(2));
+       }
 
        if (machine_is_rx1950()) {
                /* According to S3C2442 user's manual, page 7-17,
@@ -103,8 +105,10 @@ static void s3c2410_pm_resume(void)
        tmp &= S3C2410_GSTATUS2_OFFRESET;
        __raw_writel(tmp, S3C2410_GSTATUS2);
 
-       if ( machine_is_aml_m5900() )
-               s3c2410_gpio_setpin(S3C2410_GPF(2), 0);
+       if (machine_is_aml_m5900()) {
+               gpio_request_one(S3C2410_GPF(2), GPIOF_OUT_INIT_LOW, NULL);
+               gpio_free(S3C2410_GPF(2));
+       }
 }
 
 struct syscore_ops s3c2410_pm_syscore_ops = {
index d04588506ec401a99f7eddae63b2d1932d47d47c..c60f67a75afff8ba291d712091a744696e64893c 100644 (file)
@@ -26,7 +26,6 @@
 #include <asm/irq.h>
 
 #include <mach/regs-power.h>
-#include <mach/regs-gpioj.h>
 #include <mach/regs-gpio.h>
 #include <mach/regs-dsc.h>
 
index d4bc7f960bbbe2fa047696258979f2c69190b73a..6c5f4031ff0cba6adc8ba68c3ed660970a75e989 100644 (file)
@@ -39,7 +39,6 @@
 #include <plat/regs-serial.h>
 #include <mach/regs-power.h>
 #include <mach/regs-gpio.h>
-#include <mach/regs-gpioj.h>
 #include <mach/regs-dsc.h>
 #include <plat/regs-spi.h>
 #include <mach/regs-s3c2412.h>
index 6f74118f60c60f66ffbd46f6f0c72821ea2bbc4d..b0b60a1154d68d6e2df2216ca2aa65b6f91dd927 100644 (file)
@@ -36,7 +36,6 @@
 #include <mach/regs-clock.h>
 #include <plat/regs-serial.h>
 #include <mach/regs-gpio.h>
-#include <mach/regs-gpioj.h>
 #include <mach/regs-dsc.h>
 
 #include <plat/s3c2410.h>
index 5712c85f39b1f2f83ea18dea8bc3857d94dd727a..3d47e023ce942a6de1147e4dcf7f381443a08a63 100644 (file)
 #include <linux/platform_device.h>
 
 #include <plat/gpio-cfg.h>
-#include <plat/s3c64xx-spi.h>
 
 #include <mach/hardware.h>
 #include <mach/regs-gpio.h>
 
 #ifdef CONFIG_S3C64XX_DEV_SPI0
-struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 13,
-       .tx_st_done     = 21,
-       .high_speed     = 1,
-};
-
-int s3c64xx_spi0_cfg_gpio(struct platform_device *pdev)
+int s3c64xx_spi0_cfg_gpio(void)
 {
        /* enable hsspi bit in misccr */
        s3c2410_modify_misccr(S3C2416_MISCCR_HSSPI_EN2, 1);
index ed26386636759ebf28f483ed266e34923d2df45e..4e11affce3a88a37997d1d98b3dc1012ffe45423 100644 (file)
@@ -16,7 +16,6 @@
 struct platform_device; /* don't need the contents */
 
 #include <mach/hardware.h>
-#include <mach/regs-gpio.h>
 
 /**
  * s3c24xx_ts_cfg_gpio - configure gpio for s3c2410 systems
@@ -27,8 +26,5 @@ struct platform_device; /* don't need the contents */
  */
 void s3c24xx_ts_cfg_gpio(struct platform_device *dev)
 {
-       s3c2410_gpio_cfgpin(S3C2410_GPG(12), S3C2410_GPG12_XMON);
-       s3c2410_gpio_cfgpin(S3C2410_GPG(13), S3C2410_GPG13_nXPON);
-       s3c2410_gpio_cfgpin(S3C2410_GPG(14), S3C2410_GPG14_YMON);
-       s3c2410_gpio_cfgpin(S3C2410_GPG(15), S3C2410_GPG15_nYPON);
+       s3c_gpio_cfgpin_range(S3C2410_GPG(12), 4, S3C_GPIO_SFN(3));
 }
index 52f079a691cb4627b66eb6fa4bb7ad2d14327e9a..28041e83dc823c3d437d2a0ad863adf65f339be5 100644 (file)
@@ -178,13 +178,13 @@ static struct clk init_clocks_off[] = {
                .ctrlbit        = S3C_CLKCON_PCLK_KEYPAD,
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s3c6410-spi.0",
                .parent         = &clk_p,
                .enable         = s3c64xx_pclk_ctrl,
                .ctrlbit        = S3C_CLKCON_PCLK_SPI0,
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s3c6410-spi.1",
                .parent         = &clk_p,
                .enable         = s3c64xx_pclk_ctrl,
                .ctrlbit        = S3C_CLKCON_PCLK_SPI1,
@@ -331,7 +331,7 @@ static struct clk init_clocks_off[] = {
 
 static struct clk clk_48m_spi0 = {
        .name           = "spi_48m",
-       .devname        = "s3c64xx-spi.0",
+       .devname        = "s3c6410-spi.0",
        .parent         = &clk_48m,
        .enable         = s3c64xx_sclk_ctrl,
        .ctrlbit        = S3C_CLKCON_SCLK_SPI0_48,
@@ -339,7 +339,7 @@ static struct clk clk_48m_spi0 = {
 
 static struct clk clk_48m_spi1 = {
        .name           = "spi_48m",
-       .devname        = "s3c64xx-spi.1",
+       .devname        = "s3c6410-spi.1",
        .parent         = &clk_48m,
        .enable         = s3c64xx_sclk_ctrl,
        .ctrlbit        = S3C_CLKCON_SCLK_SPI1_48,
@@ -802,7 +802,7 @@ static struct clksrc_clk clk_sclk_mmc2 = {
 static struct clksrc_clk clk_sclk_spi0 = {
        .clk    = {
                .name           = "spi-bus",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s3c6410-spi.0",
                .ctrlbit        = S3C_CLKCON_SCLK_SPI0,
                .enable         = s3c64xx_sclk_ctrl,
        },
@@ -814,7 +814,7 @@ static struct clksrc_clk clk_sclk_spi0 = {
 static struct clksrc_clk clk_sclk_spi1 = {
        .clk    = {
                .name           = "spi-bus",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s3c6410-spi.1",
                .ctrlbit        = S3C_CLKCON_SCLK_SPI1,
                .enable         = s3c64xx_sclk_ctrl,
        },
@@ -858,10 +858,10 @@ static struct clk_lookup s3c64xx_clk_lookup[] = {
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
        CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &clk_48m_spi0),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk2", &clk_48m_spi1),
+       CLKDEV_INIT("s3c6410-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
+       CLKDEV_INIT("s3c6410-spi.0", "spi_busclk2", &clk_48m_spi0),
+       CLKDEV_INIT("s3c6410-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
+       CLKDEV_INIT("s3c6410-spi.1", "spi_busclk2", &clk_48m_spi1),
 };
 
 #define GET_DIV(clk, field) ((((clk) & field##_MASK) >> field##_SHIFT) + 1)
index 4cb2f951f1e9155d9b4434fac10ff4ea330e9039..4c3c9994fc2c2bac09fa6bb02de090664694b713 100644 (file)
@@ -13,9 +13,7 @@
 
 #include <linux/gpio.h>
 
-#define BANFF_PMIC_IRQ_BASE            IRQ_BOARD_START
-#define GLENFARCLAS_PMIC_IRQ_BASE      (IRQ_BOARD_START + 64)
-#define CODEC_IRQ_BASE                 (IRQ_BOARD_START + 128)
+#define GLENFARCLAS_PMIC_IRQ_BASE      IRQ_BOARD_START
 
 #define PCA935X_GPIO_BASE              GPIO_BOARD_START
 #define CODEC_GPIO_BASE                        (GPIO_BOARD_START + 8)
index fe1a98cf0e4c7cb3a63311efec61f507e9ebf8e2..57b1ff4b2d7ce6417cb113770e9a642230f558bc 100644 (file)
@@ -21,6 +21,7 @@
  */
 enum dma_ch {
        /* DMA0/SDMA0 */
+       DMACH_DT_PROP = -1, /* not yet supported, do not use */
        DMACH_UART0 = 0,
        DMACH_UART0_SRC2,
        DMACH_UART1,
diff --git a/arch/arm/mach-s3c64xx/include/mach/spi-clocks.h b/arch/arm/mach-s3c64xx/include/mach/spi-clocks.h
deleted file mode 100644 (file)
index 9d0c43b..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s3c64xx/include/mach/spi-clocks.h
- *
- * Copyright (C) 2009 Samsung Electronics Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __S3C64XX_PLAT_SPI_CLKS_H
-#define __S3C64XX_PLAT_SPI_CLKS_H __FILE__
-
-#define S3C64XX_SPI_SRCCLK_PCLK                0
-#define S3C64XX_SPI_SRCCLK_SPIBUS      1
-#define S3C64XX_SPI_SRCCLK_48M         2
-
-#endif /* __S3C64XX_PLAT_SPI_CLKS_H */
index 7a27f5603c7405fca49409c33ee9af79413de701..9e382e7c77cb77a04450dffa5ecc90e8f13f674d 100644 (file)
@@ -29,7 +29,6 @@
 #include <mach/crag6410.h>
 
 static struct s3c64xx_spi_csinfo wm0010_spi_csinfo = {
-       .set_level = gpio_set_value,
        .line = S3C64XX_GPC(3),
 };
 
@@ -39,6 +38,7 @@ static struct spi_board_info wm1253_devs[] = {
                .bus_num        = 0,
                .chip_select    = 0,
                .mode           = SPI_MODE_0,
+               .irq            = S3C_EINT(5),
                .controller_data = &wm0010_spi_csinfo,
        },
 };
@@ -168,7 +168,6 @@ static struct wm8994_pdata wm8994_pdata = {
        .gpio_defaults = {
                0x3,          /* IRQ out, active high, CMOS */
        },
-       .irq_base = CODEC_IRQ_BASE,
        .ldo = {
                 { .init_data = &wm8994_ldo1, },
                 { .init_data = &wm8994_ldo2, },
@@ -182,6 +181,11 @@ static const struct i2c_board_info wm1277_devs[] = {
        },
 };
 
+static const struct i2c_board_info wm5102_devs[] = {
+       { I2C_BOARD_INFO("wm5102", 0x1a),
+         .irq = GLENFARCLAS_PMIC_IRQ_BASE + WM831X_IRQ_GPIO_2, },
+};
+
 static const struct i2c_board_info wm6230_i2c_devs[] = {
        { I2C_BOARD_INFO("wm9081", 0x6c),
          .platform_data = &wm9081_pdata, },
@@ -209,6 +213,7 @@ static __devinitdata const struct {
          .spi_devs = wm1253_devs, .num_spi_devs = ARRAY_SIZE(wm1253_devs) },
        { .id = 0x32, .name = "XXXX-EV1 Caol Illa" },
        { .id = 0x33, .name = "XXXX-EV1 Oban" },
+       { .id = 0x34, .name = "WM0010-6320-CS42 Balblair" },
        { .id = 0x39, .name = "1254-EV1 Dallas Dhu",
          .i2c_devs = wm1254_devs, .num_i2c_devs = ARRAY_SIZE(wm1254_devs) },
        { .id = 0x3a, .name = "1259-EV1 Tobermory",
@@ -218,6 +223,8 @@ static __devinitdata const struct {
        { .id = 0x3c, .name = "1273-EV1 Longmorn" },
        { .id = 0x3d, .name = "1277-EV1 Littlemill",
          .i2c_devs = wm1277_devs, .num_i2c_devs = ARRAY_SIZE(wm1277_devs) },
+       { .id = 0x3e, .name = "WM5102-6271-EV1-CS127",
+         .i2c_devs = wm5102_devs, .num_i2c_devs = ARRAY_SIZE(wm5102_devs) },
 };
 
 static __devinit int wlf_gf_module_probe(struct i2c_client *i2c,
index d0c352d861f8f341fd93ac2da561b7c2bab35805..09cd81207a3fd39cbdfb061f9939dc728487a398 100644 (file)
@@ -171,7 +171,7 @@ static struct fb_videomode crag6410_lcd_timing = {
 };
 
 /* 405566 clocks per frame => 60Hz refresh requires 24333960Hz clock */
-static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = {
+static struct s3c_fb_platdata crag6410_lcd_pdata __devinitdata = {
        .setup_gpio     = s3c64xx_fb_gpio_setup_24bpp,
        .vtiming        = &crag6410_lcd_timing,
        .win[0]         = &crag6410_fb_win0,
@@ -181,7 +181,7 @@ static struct s3c_fb_platdata crag6410_lcd_pdata __initdata = {
 
 /* 2x6 keypad */
 
-static uint32_t crag6410_keymap[] __initdata = {
+static uint32_t crag6410_keymap[] __devinitdata = {
        /* KEY(row, col, keycode) */
        KEY(0, 0, KEY_VOLUMEUP),
        KEY(0, 1, KEY_HOME),
@@ -197,12 +197,12 @@ static uint32_t crag6410_keymap[] __initdata = {
        KEY(1, 5, KEY_CAMERA),
 };
 
-static struct matrix_keymap_data crag6410_keymap_data __initdata = {
+static struct matrix_keymap_data crag6410_keymap_data __devinitdata = {
        .keymap         = crag6410_keymap,
        .keymap_size    = ARRAY_SIZE(crag6410_keymap),
 };
 
-static struct samsung_keypad_platdata crag6410_keypad_data __initdata = {
+static struct samsung_keypad_platdata crag6410_keypad_data __devinitdata = {
        .keymap_data    = &crag6410_keymap_data,
        .rows           = 2,
        .cols           = 6,
@@ -373,11 +373,11 @@ static struct wm831x_buckv_pdata vddarm_pdata = {
        .dvs_gpio = S3C64XX_GPK(0),
 };
 
-static struct regulator_consumer_supply vddarm_consumers[] __initdata = {
+static struct regulator_consumer_supply vddarm_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("vddarm", NULL),
 };
 
-static struct regulator_init_data vddarm __initdata = {
+static struct regulator_init_data vddarm __devinitdata = {
        .constraints = {
                .name = "VDDARM",
                .min_uV = 1000000,
@@ -391,11 +391,11 @@ static struct regulator_init_data vddarm __initdata = {
        .driver_data = &vddarm_pdata,
 };
 
-static struct regulator_consumer_supply vddint_consumers[] __initdata = {
+static struct regulator_consumer_supply vddint_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("vddint", NULL),
 };
 
-static struct regulator_init_data vddint __initdata = {
+static struct regulator_init_data vddint __devinitdata = {
        .constraints = {
                .name = "VDDINT",
                .min_uV = 1000000,
@@ -408,27 +408,27 @@ static struct regulator_init_data vddint __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddmem __initdata = {
+static struct regulator_init_data vddmem __devinitdata = {
        .constraints = {
                .name = "VDDMEM",
                .always_on = 1,
        },
 };
 
-static struct regulator_init_data vddsys __initdata = {
+static struct regulator_init_data vddsys __devinitdata = {
        .constraints = {
                .name = "VDDSYS,VDDEXT,VDDPCM,VDDSS",
                .always_on = 1,
        },
 };
 
-static struct regulator_consumer_supply vddmmc_consumers[] __initdata = {
+static struct regulator_consumer_supply vddmmc_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
        REGULATOR_SUPPLY("vmmc", "s3c-sdhci.1"),
        REGULATOR_SUPPLY("vmmc", "s3c-sdhci.2"),
 };
 
-static struct regulator_init_data vddmmc __initdata = {
+static struct regulator_init_data vddmmc __devinitdata = {
        .constraints = {
                .name = "VDDMMC,UH",
                .always_on = 1,
@@ -438,7 +438,7 @@ static struct regulator_init_data vddmmc __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddotgi __initdata = {
+static struct regulator_init_data vddotgi __devinitdata = {
        .constraints = {
                .name = "VDDOTGi",
                .always_on = 1,
@@ -446,7 +446,7 @@ static struct regulator_init_data vddotgi __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddotg __initdata = {
+static struct regulator_init_data vddotg __devinitdata = {
        .constraints = {
                .name = "VDDOTG",
                .always_on = 1,
@@ -454,7 +454,7 @@ static struct regulator_init_data vddotg __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddhi __initdata = {
+static struct regulator_init_data vddhi __devinitdata = {
        .constraints = {
                .name = "VDDHI",
                .always_on = 1,
@@ -462,7 +462,7 @@ static struct regulator_init_data vddhi __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddadc __initdata = {
+static struct regulator_init_data vddadc __devinitdata = {
        .constraints = {
                .name = "VDDADC,VDDDAC",
                .always_on = 1,
@@ -470,7 +470,7 @@ static struct regulator_init_data vddadc __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddmem0 __initdata = {
+static struct regulator_init_data vddmem0 __devinitdata = {
        .constraints = {
                .name = "VDDMEM0",
                .always_on = 1,
@@ -478,7 +478,7 @@ static struct regulator_init_data vddmem0 __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddpll __initdata = {
+static struct regulator_init_data vddpll __devinitdata = {
        .constraints = {
                .name = "VDDPLL",
                .always_on = 1,
@@ -486,7 +486,7 @@ static struct regulator_init_data vddpll __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddlcd __initdata = {
+static struct regulator_init_data vddlcd __devinitdata = {
        .constraints = {
                .name = "VDDLCD",
                .always_on = 1,
@@ -494,7 +494,7 @@ static struct regulator_init_data vddlcd __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct regulator_init_data vddalive __initdata = {
+static struct regulator_init_data vddalive __devinitdata = {
        .constraints = {
                .name = "VDDALIVE",
                .always_on = 1,
@@ -502,30 +502,29 @@ static struct regulator_init_data vddalive __initdata = {
        .supply_regulator = "WALLVDD",
 };
 
-static struct wm831x_backup_pdata banff_backup_pdata __initdata = {
+static struct wm831x_backup_pdata banff_backup_pdata __devinitdata = {
        .charger_enable = 1,
        .vlim = 2500,  /* mV */
        .ilim = 200,   /* uA */
 };
 
-static struct wm831x_status_pdata banff_red_led __initdata = {
+static struct wm831x_status_pdata banff_red_led __devinitdata = {
        .name = "banff:red:",
        .default_src = WM831X_STATUS_MANUAL,
 };
 
-static struct wm831x_status_pdata banff_green_led __initdata = {
+static struct wm831x_status_pdata banff_green_led __devinitdata = {
        .name = "banff:green:",
        .default_src = WM831X_STATUS_MANUAL,
 };
 
-static struct wm831x_touch_pdata touch_pdata __initdata = {
+static struct wm831x_touch_pdata touch_pdata __devinitdata = {
        .data_irq = S3C_EINT(26),
        .pd_irq = S3C_EINT(27),
 };
 
-static struct wm831x_pdata crag_pmic_pdata __initdata = {
+static struct wm831x_pdata crag_pmic_pdata __devinitdata = {
        .wm831x_num = 1,
-       .irq_base = BANFF_PMIC_IRQ_BASE,
        .gpio_base = BANFF_PMIC_GPIO_BASE,
        .soft_shutdown = true,
 
@@ -568,7 +567,7 @@ static struct wm831x_pdata crag_pmic_pdata __initdata = {
        .touch = &touch_pdata,
 };
 
-static struct i2c_board_info i2c_devs0[] __initdata = {
+static struct i2c_board_info i2c_devs0[] __devinitdata = {
        { I2C_BOARD_INFO("24c08", 0x50), },
        { I2C_BOARD_INFO("tca6408", 0x20),
          .platform_data = &crag6410_pca_data,
@@ -583,12 +582,12 @@ static struct s3c2410_platform_i2c i2c0_pdata = {
        .frequency = 400000,
 };
 
-static struct regulator_consumer_supply pvdd_1v2_consumers[] __initdata = {
+static struct regulator_consumer_supply pvdd_1v2_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("DCVDD", "spi0.0"),
        REGULATOR_SUPPLY("AVDD", "spi0.0"),
 };
 
-static struct regulator_init_data pvdd_1v2 __initdata = {
+static struct regulator_init_data pvdd_1v2 __devinitdata = {
        .constraints = {
                .name = "PVDD_1V2",
                .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -598,7 +597,7 @@ static struct regulator_init_data pvdd_1v2 __initdata = {
        .num_consumer_supplies = ARRAY_SIZE(pvdd_1v2_consumers),
 };
 
-static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
+static struct regulator_consumer_supply pvdd_1v8_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("LDOVDD", "1-001a"),
        REGULATOR_SUPPLY("PLLVDD", "1-001a"),
        REGULATOR_SUPPLY("DBVDD", "1-001a"),
@@ -612,7 +611,7 @@ static struct regulator_consumer_supply pvdd_1v8_consumers[] __initdata = {
        REGULATOR_SUPPLY("DBVDD", "spi0.0"),
 };
 
-static struct regulator_init_data pvdd_1v8 __initdata = {
+static struct regulator_init_data pvdd_1v8 __devinitdata = {
        .constraints = {
                .name = "PVDD_1V8",
                .always_on = 1,
@@ -622,12 +621,12 @@ static struct regulator_init_data pvdd_1v8 __initdata = {
        .num_consumer_supplies = ARRAY_SIZE(pvdd_1v8_consumers),
 };
 
-static struct regulator_consumer_supply pvdd_3v3_consumers[] __initdata = {
+static struct regulator_consumer_supply pvdd_3v3_consumers[] __devinitdata = {
        REGULATOR_SUPPLY("MICVDD", "1-001a"),
        REGULATOR_SUPPLY("AVDD1", "1-001a"),
 };
 
-static struct regulator_init_data pvdd_3v3 __initdata = {
+static struct regulator_init_data pvdd_3v3 __devinitdata = {
        .constraints = {
                .name = "PVDD_3V3",
                .always_on = 1,
@@ -637,7 +636,7 @@ static struct regulator_init_data pvdd_3v3 __initdata = {
        .num_consumer_supplies = ARRAY_SIZE(pvdd_3v3_consumers),
 };
 
-static struct wm831x_pdata glenfarclas_pmic_pdata __initdata = {
+static struct wm831x_pdata glenfarclas_pmic_pdata __devinitdata = {
        .wm831x_num = 2,
        .irq_base = GLENFARCLAS_PMIC_IRQ_BASE,
        .gpio_base = GLENFARCLAS_PMIC_GPIO_BASE,
@@ -669,7 +668,7 @@ static struct wm1250_ev1_pdata wm1250_ev1_pdata = {
        },
 };
 
-static struct i2c_board_info i2c_devs1[] __initdata = {
+static struct i2c_board_info i2c_devs1[] __devinitdata = {
        { I2C_BOARD_INFO("wm8311", 0x34),
          .irq = S3C_EINT(0),
          .platform_data = &glenfarclas_pmic_pdata },
@@ -799,7 +798,7 @@ static void __init crag6410_machine_init(void)
        i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
 
        samsung_keypad_set_platdata(&crag6410_keypad_data);
-       s3c64xx_spi0_set_platdata(&s3c64xx_spi0_pdata, 0, 1);
+       s3c64xx_spi0_set_platdata(NULL, 0, 1);
 
        platform_add_devices(crag6410_devices, ARRAY_SIZE(crag6410_devices));
 
index df3103d450e22c93f55976634ea003a03c6881d9..0fe4f1503f4f91dd0f64da18bd1a3c4202e4ad35 100644 (file)
@@ -566,7 +566,6 @@ static struct wm831x_status_pdata wm1192_led8_pdata = {
 
 static struct wm831x_pdata smdk6410_wm1192_pdata = {
        .pre_init = wm1192_pre_init,
-       .irq_base = IRQ_BOARD_START,
 
        .backlight = &wm1192_backlight_pdata,
        .dcdc = {
index d9592ad7a82553c56355e4c9474fe839bf4d8e52..4dc53450d71547f3ea4137092354682006a16962 100644 (file)
@@ -9,19 +9,10 @@
  */
 
 #include <linux/gpio.h>
-#include <linux/platform_device.h>
-
 #include <plat/gpio-cfg.h>
-#include <plat/s3c64xx-spi.h>
 
 #ifdef CONFIG_S3C64XX_DEV_SPI0
-struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 13,
-       .tx_st_done     = 21,
-};
-
-int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi0_cfg_gpio(void)
 {
        s3c_gpio_cfgall_range(S3C64XX_GPC(0), 3,
                                S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
@@ -30,13 +21,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
 #endif
 
 #ifdef CONFIG_S3C64XX_DEV_SPI1
-struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 13,
-       .tx_st_done     = 21,
-};
-
-int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi1_cfg_gpio(void)
 {
        s3c_gpio_cfgall_range(S3C64XX_GPC(4), 3,
                                S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
index ee1e8e7f563142b8775b1b2001f502ccd20ba540..000445596ec4ff5a3577e0d034e40c3574a882ae 100644 (file)
@@ -227,13 +227,13 @@ static struct clk init_clocks_off[] = {
                .ctrlbit        = (1 << 17),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5p64x0-spi.0",
                .parent         = &clk_pclk_low.clk,
                .enable         = s5p64x0_pclk_ctrl,
                .ctrlbit        = (1 << 21),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5p64x0-spi.1",
                .parent         = &clk_pclk_low.clk,
                .enable         = s5p64x0_pclk_ctrl,
                .ctrlbit        = (1 << 22),
@@ -467,7 +467,7 @@ static struct clksrc_clk clk_sclk_uclk = {
 static struct clksrc_clk clk_sclk_spi0 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5p64x0-spi.0",
                .ctrlbit        = (1 << 20),
                .enable         = s5p64x0_sclk_ctrl,
        },
@@ -479,7 +479,7 @@ static struct clksrc_clk clk_sclk_spi0 = {
 static struct clksrc_clk clk_sclk_spi1 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5p64x0-spi.1",
                .ctrlbit        = (1 << 21),
                .enable         = s5p64x0_sclk_ctrl,
        },
@@ -519,8 +519,8 @@ static struct clk_lookup s5p6440_clk_lookup[] = {
        CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk),
        CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
        CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
+       CLKDEV_INIT("s5p64x0-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
+       CLKDEV_INIT("s5p64x0-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
        CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
index dae6a13f43bb4dd7eac1425aa01a54e4390f42a8..f3e0ef3d27c9f3d3ba60cc5d053066b0e3af1092 100644 (file)
@@ -236,13 +236,13 @@ static struct clk init_clocks_off[] = {
                .ctrlbit        = (1 << 17),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5p64x0-spi.0",
                .parent         = &clk_pclk_low.clk,
                .enable         = s5p64x0_pclk_ctrl,
                .ctrlbit        = (1 << 21),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5p64x0-spi.1",
                .parent         = &clk_pclk_low.clk,
                .enable         = s5p64x0_pclk_ctrl,
                .ctrlbit        = (1 << 22),
@@ -528,7 +528,7 @@ static struct clksrc_clk clk_sclk_uclk = {
 static struct clksrc_clk clk_sclk_spi0 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5p64x0-spi.0",
                .ctrlbit        = (1 << 20),
                .enable         = s5p64x0_sclk_ctrl,
        },
@@ -540,7 +540,7 @@ static struct clksrc_clk clk_sclk_spi0 = {
 static struct clksrc_clk clk_sclk_spi1 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5p64x0-spi.1",
                .ctrlbit        = (1 << 21),
                .enable         = s5p64x0_sclk_ctrl,
        },
@@ -562,8 +562,8 @@ static struct clk_lookup s5p6450_clk_lookup[] = {
        CLKDEV_INIT(NULL, "clk_uart_baud2", &clk_pclk_low.clk),
        CLKDEV_INIT(NULL, "clk_uart_baud3", &clk_sclk_uclk.clk),
        CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
+       CLKDEV_INIT("s5p64x0-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
+       CLKDEV_INIT("s5p64x0-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
        CLKDEV_INIT("s3c-sdhci.0", "mmc_busclk.2", &clk_sclk_mmc0.clk),
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
index 2ee5dc069b3754de7fdb922048a99c3d9156ee74..9c4ce085f5857a3e31e73f31059e29c38998a180 100644 (file)
@@ -36,8 +36,6 @@
 #include <plat/devs.h>
 #include <plat/irqs.h>
 
-static u64 dma_dmamask = DMA_BIT_MASK(32);
-
 static u8 s5p6440_pdma_peri[] = {
        DMACH_UART0_RX,
        DMACH_UART0_TX,
diff --git a/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h b/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h
deleted file mode 100644 (file)
index 170a20a..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/spi-clocks.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_ARCH_SPI_CLKS_H
-#define __ASM_ARCH_SPI_CLKS_H __FILE__
-
-#define S5P64X0_SPI_SRCCLK_PCLK                0
-#define S5P64X0_SPI_SRCCLK_SCLK                1
-
-#endif /* __ASM_ARCH_SPI_CLKS_H */
index e9b841240352d229f39557a2301bd71bae7df6a2..7664356720ca625ebd2022761dbf22f1f1069306 100644 (file)
@@ -9,21 +9,10 @@
  */
 
 #include <linux/gpio.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
 #include <plat/gpio-cfg.h>
-#include <plat/cpu.h>
-#include <plat/s3c64xx-spi.h>
 
 #ifdef CONFIG_S3C64XX_DEV_SPI0
-struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = {
-       .fifo_lvl_mask  = 0x1ff,
-       .rx_lvl_offset  = 15,
-       .tx_st_done     = 25,
-};
-
-int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi0_cfg_gpio(void)
 {
        if (soc_is_s5p6450())
                s3c_gpio_cfgall_range(S5P6450_GPC(0), 3,
@@ -36,13 +25,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
 #endif
 
 #ifdef CONFIG_S3C64XX_DEV_SPI1
-struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 15,
-       .tx_st_done     = 25,
-};
-
-int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi1_cfg_gpio(void)
 {
        if (soc_is_s5p6450())
                s3c_gpio_cfgall_range(S5P6450_GPC(4), 3,
index 16eca4ea201066b6498a503e1f53b1d4c0d7efd0..926219791f0dcd1bbaba3b49f5b690f89ab70975 100644 (file)
@@ -564,19 +564,19 @@ static struct clk init_clocks_off[] = {
                .ctrlbit        = (1 << 5),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5pc100-spi.0",
                .parent         = &clk_div_d1_bus.clk,
                .enable         = s5pc100_d1_4_ctrl,
                .ctrlbit        = (1 << 6),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5pc100-spi.1",
                .parent         = &clk_div_d1_bus.clk,
                .enable         = s5pc100_d1_4_ctrl,
                .ctrlbit        = (1 << 7),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.2",
+               .devname        = "s5pc100-spi.2",
                .parent         = &clk_div_d1_bus.clk,
                .enable         = s5pc100_d1_4_ctrl,
                .ctrlbit        = (1 << 8),
@@ -702,7 +702,7 @@ static struct clk clk_hsmmc0 = {
 
 static struct clk clk_48m_spi0 = {
        .name           = "spi_48m",
-       .devname        = "s3c64xx-spi.0",
+       .devname        = "s5pc100-spi.0",
        .parent         = &clk_mout_48m.clk,
        .enable         = s5pc100_sclk0_ctrl,
        .ctrlbit        = (1 << 7),
@@ -710,7 +710,7 @@ static struct clk clk_48m_spi0 = {
 
 static struct clk clk_48m_spi1 = {
        .name           = "spi_48m",
-       .devname        = "s3c64xx-spi.1",
+       .devname        = "s5pc100-spi.1",
        .parent         = &clk_mout_48m.clk,
        .enable         = s5pc100_sclk0_ctrl,
        .ctrlbit        = (1 << 8),
@@ -718,7 +718,7 @@ static struct clk clk_48m_spi1 = {
 
 static struct clk clk_48m_spi2 = {
        .name           = "spi_48m",
-       .devname        = "s3c64xx-spi.2",
+       .devname        = "s5pc100-spi.2",
        .parent         = &clk_mout_48m.clk,
        .enable         = s5pc100_sclk0_ctrl,
        .ctrlbit        = (1 << 9),
@@ -1085,7 +1085,7 @@ static struct clksrc_clk clk_sclk_mmc2 = {
 static struct clksrc_clk clk_sclk_spi0 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5pc100-spi.0",
                .ctrlbit        = (1 << 4),
                .enable         = s5pc100_sclk0_ctrl,
        },
@@ -1097,7 +1097,7 @@ static struct clksrc_clk clk_sclk_spi0 = {
 static struct clksrc_clk clk_sclk_spi1 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5pc100-spi.1",
                .ctrlbit        = (1 << 5),
                .enable         = s5pc100_sclk0_ctrl,
        },
@@ -1109,7 +1109,7 @@ static struct clksrc_clk clk_sclk_spi1 = {
 static struct clksrc_clk clk_sclk_spi2 = {
        .clk    = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.2",
+               .devname        = "s5pc100-spi.2",
                .ctrlbit        = (1 << 6),
                .enable         = s5pc100_sclk0_ctrl,
        },
@@ -1315,12 +1315,12 @@ static struct clk_lookup s5pc100_clk_lookup[] = {
        CLKDEV_INIT("s3c-sdhci.1", "mmc_busclk.2", &clk_sclk_mmc1.clk),
        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
        CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_48m_spi0),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk2", &clk_sclk_spi0.clk),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_48m_spi1),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk2", &clk_sclk_spi1.clk),
-       CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk1", &clk_48m_spi2),
-       CLKDEV_INIT("s3c64xx-spi.2", "spi_busclk2", &clk_sclk_spi2.clk),
+       CLKDEV_INIT("s5pc100-spi.0", "spi_busclk1", &clk_48m_spi0),
+       CLKDEV_INIT("s5pc100-spi.0", "spi_busclk2", &clk_sclk_spi0.clk),
+       CLKDEV_INIT("s5pc100-spi.1", "spi_busclk1", &clk_48m_spi1),
+       CLKDEV_INIT("s5pc100-spi.1", "spi_busclk2", &clk_sclk_spi1.clk),
+       CLKDEV_INIT("s5pc100-spi.2", "spi_busclk1", &clk_48m_spi2),
+       CLKDEV_INIT("s5pc100-spi.2", "spi_busclk2", &clk_sclk_spi2.clk),
 };
 
 void __init s5pc100_register_clocks(void)
index afd8db2d599155720f0a8b1fafc7bec7a539bde8..b1418409709e531cc3ed47d2d971a0ace6940da4 100644 (file)
@@ -33,8 +33,6 @@
 #include <mach/irqs.h>
 #include <mach/dma.h>
 
-static u64 dma_dmamask = DMA_BIT_MASK(32);
-
 static u8 pdma0_peri[] = {
        DMACH_UART0_RX,
        DMACH_UART0_TX,
diff --git a/arch/arm/mach-s5pc100/include/mach/spi-clocks.h b/arch/arm/mach-s5pc100/include/mach/spi-clocks.h
deleted file mode 100644 (file)
index 65e4263..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5pc100/include/mach/spi-clocks.h
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __S5PC100_PLAT_SPI_CLKS_H
-#define __S5PC100_PLAT_SPI_CLKS_H __FILE__
-
-#define S5PC100_SPI_SRCCLK_PCLK                0
-#define S5PC100_SPI_SRCCLK_48M         1
-#define S5PC100_SPI_SRCCLK_SPIBUS      2
-
-#endif /* __S5PC100_PLAT_SPI_CLKS_H */
index 431a6f747caa196844c3f3bcb5559a0c3c33dac9..183567961de1c32a842674b0b3812168785d1908 100644 (file)
@@ -9,20 +9,10 @@
  */
 
 #include <linux/gpio.h>
-#include <linux/platform_device.h>
-
 #include <plat/gpio-cfg.h>
-#include <plat/s3c64xx-spi.h>
 
 #ifdef CONFIG_S3C64XX_DEV_SPI0
-struct s3c64xx_spi_info s3c64xx_spi0_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 13,
-       .high_speed     = 1,
-       .tx_st_done     = 21,
-};
-
-int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi0_cfg_gpio(void)
 {
        s3c_gpio_cfgall_range(S5PC100_GPB(0), 3,
                                S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
@@ -31,14 +21,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
 #endif
 
 #ifdef CONFIG_S3C64XX_DEV_SPI1
-struct s3c64xx_spi_info s3c64xx_spi1_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 13,
-       .high_speed     = 1,
-       .tx_st_done     = 21,
-};
-
-int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi1_cfg_gpio(void)
 {
        s3c_gpio_cfgall_range(S5PC100_GPB(4), 3,
                                S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
@@ -47,14 +30,7 @@ int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
 #endif
 
 #ifdef CONFIG_S3C64XX_DEV_SPI2
-struct s3c64xx_spi_info s3c64xx_spi2_pdata __initdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 13,
-       .high_speed     = 1,
-       .tx_st_done     = 21,
-};
-
-int s3c64xx_spi2_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi2_cfg_gpio(void)
 {
        s3c_gpio_cfgpin(S5PC100_GPG3(0), S3C_GPIO_SFN(3));
        s3c_gpio_setpull(S5PC100_GPG3(0), S3C_GPIO_PULL_UP);
index 88e983b0c82e568ee1da3c173256ec6c913f8c8f..77185c38188bc313366d43847c0b1f7ad3164984 100644 (file)
@@ -152,6 +152,7 @@ config MACH_SMDKV210
        select S3C_DEV_I2C1
        select S3C_DEV_I2C2
        select S3C_DEV_RTC
+       select S3C_DEV_USB_HSOTG
        select S3C_DEV_WDT
        select S5P_DEV_FIMC0
        select S5P_DEV_FIMC1
@@ -170,6 +171,7 @@ config MACH_SMDKV210
        select S5PV210_SETUP_IDE
        select S5PV210_SETUP_KEYPAD
        select S5PV210_SETUP_SDHCI
+       select S5PV210_SETUP_USB_PHY
        help
          Machine support for Samsung SMDKV210
 
index 09609d50961d491c09f0f2e8926453e3db7cd0ce..fcdf52dbcc49f9bb8525790bc77953db7f452b73 100644 (file)
@@ -445,19 +445,19 @@ static struct clk init_clocks_off[] = {
                .ctrlbit        = (1 << 11),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5pv210-spi.0",
                .parent         = &clk_pclk_psys.clk,
                .enable         = s5pv210_clk_ip3_ctrl,
                .ctrlbit        = (1<<12),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5pv210-spi.1",
                .parent         = &clk_pclk_psys.clk,
                .enable         = s5pv210_clk_ip3_ctrl,
                .ctrlbit        = (1<<13),
        }, {
                .name           = "spi",
-               .devname        = "s3c64xx-spi.2",
+               .devname        = "s5pv210-spi.2",
                .parent         = &clk_pclk_psys.clk,
                .enable         = s5pv210_clk_ip3_ctrl,
                .ctrlbit        = (1<<14),
@@ -1035,7 +1035,7 @@ static struct clksrc_clk clk_sclk_mmc3 = {
 static struct clksrc_clk clk_sclk_spi0 = {
        .clk            = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.0",
+               .devname        = "s5pv210-spi.0",
                .enable         = s5pv210_clk_mask0_ctrl,
                .ctrlbit        = (1 << 16),
        },
@@ -1047,7 +1047,7 @@ static struct clksrc_clk clk_sclk_spi0 = {
 static struct clksrc_clk clk_sclk_spi1 = {
        .clk            = {
                .name           = "sclk_spi",
-               .devname        = "s3c64xx-spi.1",
+               .devname        = "s5pv210-spi.1",
                .enable         = s5pv210_clk_mask0_ctrl,
                .ctrlbit        = (1 << 17),
        },
@@ -1331,8 +1331,8 @@ static struct clk_lookup s5pv210_clk_lookup[] = {
        CLKDEV_INIT("s3c-sdhci.2", "mmc_busclk.2", &clk_sclk_mmc2.clk),
        CLKDEV_INIT("s3c-sdhci.3", "mmc_busclk.2", &clk_sclk_mmc3.clk),
        CLKDEV_INIT(NULL, "spi_busclk0", &clk_p),
-       CLKDEV_INIT("s3c64xx-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
-       CLKDEV_INIT("s3c64xx-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
+       CLKDEV_INIT("s5pv210-spi.0", "spi_busclk1", &clk_sclk_spi0.clk),
+       CLKDEV_INIT("s5pv210-spi.1", "spi_busclk1", &clk_sclk_spi1.clk),
 };
 
 void __init s5pv210_register_clocks(void)
diff --git a/arch/arm/mach-s5pv210/include/mach/spi-clocks.h b/arch/arm/mach-s5pv210/include/mach/spi-clocks.h
deleted file mode 100644 (file)
index 02acded..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/spi-clocks.h
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __S5PV210_PLAT_SPI_CLKS_H
-#define __S5PV210_PLAT_SPI_CLKS_H __FILE__
-
-#define S5PV210_SPI_SRCCLK_PCLK                0
-#define S5PV210_SPI_SRCCLK_SCLK                1
-
-#endif /* __S5PV210_PLAT_SPI_CLKS_H */
index af528f9e97f976ea0bb9efe654ef46a843280194..78028df86c5dd6d6411a46454ba1932bf980e07e 100644 (file)
@@ -600,10 +600,17 @@ static void aquila_setup_sdhci(void)
        s3c_sdhci2_set_platdata(&aquila_hsmmc2_data);
 };
 
+/* Audio device */
+static struct platform_device aquila_device_audio = {
+       .name = "smdk-audio",
+       .id = -1,
+};
+
 static struct platform_device *aquila_devices[] __initdata = {
        &aquila_i2c_gpio_pmic,
        &aquila_i2c_gpio5,
        &aquila_device_gpiokeys,
+       &aquila_device_audio,
        &s3c_device_fb,
        &s5p_device_onenand,
        &s3c_device_hsmmc0,
index bf5087c2b7fe6078e40837374fe1933a4c143cf3..822a5595068515128f868c36e6a90756eba65232 100644 (file)
@@ -859,12 +859,19 @@ static struct s5p_platform_fimc goni_fimc_md_platdata __initdata = {
        .num_clients    = ARRAY_SIZE(goni_camera_sensors),
 };
 
+/* Audio device */
+static struct platform_device goni_device_audio = {
+       .name = "smdk-audio",
+       .id = -1,
+};
+
 static struct platform_device *goni_devices[] __initdata = {
        &s3c_device_fb,
        &s5p_device_onenand,
        &goni_spi_gpio,
        &goni_i2c_gpio_pmic,
        &goni_i2c_gpio5,
+       &goni_device_audio,
        &mmc2_fixed_voltage,
        &goni_device_gpiokeys,
        &s5p_device_mfc,
@@ -901,7 +908,7 @@ static void __init goni_sound_init(void)
 static void __init goni_map_io(void)
 {
        s5pv210_init_io(NULL, 0);
-       s3c24xx_init_clocks(24000000);
+       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(goni_uartcfgs, ARRAY_SIZE(goni_uartcfgs));
        s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
@@ -959,8 +966,6 @@ static void __init goni_machine_init(void)
        /* KEYPAD */
        samsung_keypad_set_platdata(&keypad_data);
 
-       clk_xusbxti.rate = 24000000;
-
        platform_add_devices(goni_devices, ARRAY_SIZE(goni_devices));
 }
 
index 0d7ddec88eb74ade7505bca367a855e714752b2b..918b23d71fdf4a71800aabe07b79b5a5f712b9a6 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/gpio.h>
 #include <linux/delay.h>
 #include <linux/pwm_backlight.h>
+#include <linux/platform_data/s3c-hsotg.h>
 
 #include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
@@ -47,6 +48,7 @@
 #include <plat/backlight.h>
 #include <plat/regs-fb-v4.h>
 #include <plat/mfc.h>
+#include <plat/clock.h>
 
 #include "common.h"
 
@@ -203,6 +205,9 @@ static struct s3c_fb_platdata smdkv210_lcd0_pdata __initdata = {
        .setup_gpio     = s5pv210_fb_gpio_setup_24bpp,
 };
 
+/* USB OTG */
+static struct s3c_hsotg_plat smdkv210_hsotg_pdata;
+
 static struct platform_device *smdkv210_devices[] __initdata = {
        &s3c_device_adc,
        &s3c_device_cfcon,
@@ -216,6 +221,7 @@ static struct platform_device *smdkv210_devices[] __initdata = {
        &s3c_device_i2c2,
        &s3c_device_rtc,
        &s3c_device_ts,
+       &s3c_device_usb_hsotg,
        &s3c_device_wdt,
        &s5p_device_fimc0,
        &s5p_device_fimc1,
@@ -279,7 +285,7 @@ static struct platform_pwm_backlight_data smdkv210_bl_data = {
 static void __init smdkv210_map_io(void)
 {
        s5pv210_init_io(NULL, 0);
-       s3c24xx_init_clocks(24000000);
+       s3c24xx_init_clocks(clk_xusbxti.rate);
        s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
        s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
 }
@@ -314,6 +320,8 @@ static void __init smdkv210_machine_init(void)
 
        samsung_bl_set(&smdkv210_bl_gpio_info, &smdkv210_bl_data);
 
+       s3c_hsotg_set_platdata(&smdkv210_hsotg_pdata);
+
        platform_add_devices(smdkv210_devices, ARRAY_SIZE(smdkv210_devices));
 }
 
index f43c5048a37d0f5038b1be3c872b159be6ac5448..81aecc162f8220991e4e7d4452912758f29ea446 100644 (file)
@@ -9,20 +9,10 @@
  */
 
 #include <linux/gpio.h>
-#include <linux/platform_device.h>
-
 #include <plat/gpio-cfg.h>
-#include <plat/s3c64xx-spi.h>
 
 #ifdef CONFIG_S3C64XX_DEV_SPI0
-struct s3c64xx_spi_info s3c64xx_spi0_pdata = {
-       .fifo_lvl_mask  = 0x1ff,
-       .rx_lvl_offset  = 15,
-       .high_speed     = 1,
-       .tx_st_done     = 25,
-};
-
-int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi0_cfg_gpio(void)
 {
        s3c_gpio_cfgpin(S5PV210_GPB(0), S3C_GPIO_SFN(2));
        s3c_gpio_setpull(S5PV210_GPB(0), S3C_GPIO_PULL_UP);
@@ -33,14 +23,7 @@ int s3c64xx_spi0_cfg_gpio(struct platform_device *dev)
 #endif
 
 #ifdef CONFIG_S3C64XX_DEV_SPI1
-struct s3c64xx_spi_info s3c64xx_spi1_pdata = {
-       .fifo_lvl_mask  = 0x7f,
-       .rx_lvl_offset  = 15,
-       .high_speed     = 1,
-       .tx_st_done     = 25,
-};
-
-int s3c64xx_spi1_cfg_gpio(struct platform_device *dev)
+int s3c64xx_spi1_cfg_gpio(void)
 {
        s3c_gpio_cfgpin(S5PV210_GPB(4), S3C_GPIO_SFN(2));
        s3c_gpio_setpull(S5PV210_GPB(4), S3C_GPIO_PULL_UP);
diff --git a/arch/arm/mach-socfpga/Makefile b/arch/arm/mach-socfpga/Makefile
new file mode 100644 (file)
index 0000000..4fb9324
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for the linux kernel.
+#
+
+obj-y                                  := socfpga.o
diff --git a/arch/arm/mach-socfpga/Makefile.boot b/arch/arm/mach-socfpga/Makefile.boot
new file mode 100644 (file)
index 0000000..dae9661
--- /dev/null
@@ -0,0 +1 @@
+zreladdr-y     := 0x00008000
diff --git a/arch/arm/mach-socfpga/include/mach/debug-macro.S b/arch/arm/mach-socfpga/include/mach/debug-macro.S
new file mode 100644 (file)
index 0000000..d6f26d2
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  Copyright (C) 1994-1999 Russell King
+ *  Moved from linux/arch/arm/kernel/debug.S by Ben Dooks
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+               .macro  addruart, rp, rv, tmp
+               mov     \rp, #DEBUG_LL_UART_OFFSET
+               orr     \rp, \rp, #0x00c00000
+               orr     \rv, \rp, #0xfe000000   @ virtual base
+               orr     \rp, \rp, #0xff000000   @ physical base
+               .endm
+
diff --git a/arch/arm/mach-socfpga/include/mach/timex.h b/arch/arm/mach-socfpga/include/mach/timex.h
new file mode 100644 (file)
index 0000000..43df435
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ *  Copyright (C) 2003 ARM Limited
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define CLOCK_TICK_RATE                (50000000 / 16)
diff --git a/arch/arm/mach-socfpga/include/mach/uncompress.h b/arch/arm/mach-socfpga/include/mach/uncompress.h
new file mode 100644 (file)
index 0000000..bbe20e6
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __MACH_UNCOMPRESS_H
+#define __MACH_UNCOMPRESS_H
+
+#define putc(c)
+#define flush()
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
+
+#endif
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
new file mode 100644 (file)
index 0000000..f01e1eb
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ *  Copyright (C) 2012 Altera Corporation
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/dw_apb_timer.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/hardware/cache-l2x0.h>
+#include <asm/hardware/gic.h>
+#include <asm/mach/arch.h>
+
+extern void socfpga_init_clocks(void);
+
+const static struct of_device_id irq_match[] = {
+       { .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
+       {}
+};
+
+static void __init gic_init_irq(void)
+{
+       of_irq_init(irq_match);
+}
+
+static void socfpga_cyclone5_restart(char mode, const char *cmd)
+{
+       /* TODO: */
+}
+
+static void __init socfpga_cyclone5_init(void)
+{
+       l2x0_of_init(0, ~0UL);
+       of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+       socfpga_init_clocks();
+}
+
+static const char *altera_dt_match[] = {
+       "altr,socfpga",
+       "altr,socfpga-cyclone5",
+       NULL
+};
+
+DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA")
+       .init_irq       = gic_init_irq,
+       .handle_irq     = gic_handle_irq,
+       .timer          = &dw_apb_timer,
+       .init_machine   = socfpga_cyclone5_init,
+       .restart        = socfpga_cyclone5_restart,
+       .dt_compat      = altera_dt_match,
+MACHINE_END
index 6a113a9bb87a73b17368267715aec791127fcd83..9077aaa398d9f0903aec32cec87d1d6b9263c354 100644 (file)
@@ -63,40 +63,15 @@ comment "Tegra board type"
 config MACH_HARMONY
        bool "Harmony board"
        depends on ARCH_TEGRA_2x_SOC
-       select MACH_HAS_SND_SOC_TEGRA_WM8903 if SND_SOC
        help
          Support for nVidia Harmony development platform
 
-config MACH_KAEN
-       bool "Kaen board"
-       depends on ARCH_TEGRA_2x_SOC
-       select MACH_SEABOARD
-       select MACH_HAS_SND_SOC_TEGRA_WM8903 if SND_SOC
-       help
-         Support for the Kaen version of Seaboard
-
 config MACH_PAZ00
        bool "Paz00 board"
        depends on ARCH_TEGRA_2x_SOC
        help
          Support for the Toshiba AC100/Dynabook AZ netbook
 
-config MACH_SEABOARD
-       bool "Seaboard board"
-       depends on ARCH_TEGRA_2x_SOC
-       select MACH_HAS_SND_SOC_TEGRA_WM8903 if SND_SOC
-       help
-         Support for nVidia Seaboard development platform. It will
-        also be included for some of the derivative boards that
-        have large similarities with the seaboard design.
-
-config MACH_TEGRA_DT
-       bool "Generic Tegra20 board (FDT support)"
-       depends on ARCH_TEGRA_2x_SOC
-       select USE_OF
-       help
-         Support for generic NVIDIA Tegra20 boards using Flattened Device Tree
-
 config MACH_TRIMSLICE
        bool "TrimSlice board"
        depends on ARCH_TEGRA_2x_SOC
@@ -104,20 +79,6 @@ config MACH_TRIMSLICE
        help
          Support for CompuLab TrimSlice platform
 
-config MACH_WARIO
-       bool "Wario board"
-       depends on ARCH_TEGRA_2x_SOC
-       select MACH_SEABOARD
-       help
-         Support for the Wario version of Seaboard
-
-config MACH_VENTANA
-       bool "Ventana board"
-       depends on ARCH_TEGRA_2x_SOC
-       select MACH_TEGRA_DT
-       help
-         Support for the nVidia Ventana development platform
-
 choice
         prompt "Default low-level debug console UART"
         default TEGRA_DEBUG_UART_NONE
index 2eb4445ddb1435648cdba9d587d50fa8c8b7a04a..c3d7303b9ac8f07a662e25739c6362a8e7ee4fd8 100644 (file)
@@ -8,21 +8,24 @@ obj-y                                   += timer.o
 obj-y                                  += fuse.o
 obj-y                                  += pmc.o
 obj-y                                  += flowctrl.o
+obj-y                                  += powergate.o
+obj-y                                  += apbio.o
 obj-$(CONFIG_CPU_IDLE)                 += cpuidle.o
 obj-$(CONFIG_CPU_IDLE)                 += sleep.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += powergate.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_clocks.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += tegra2_emc.o
-obj-$(CONFIG_ARCH_TEGRA_3x_SOC)                += board-dt-tegra30.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)                += tegra30_clocks.o
 obj-$(CONFIG_SMP)                      += platsmp.o headsmp.o
 obj-$(CONFIG_SMP)                       += reset.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
-obj-$(CONFIG_TEGRA_SYSTEM_DMA)         += dma.o apbio.o
+obj-$(CONFIG_TEGRA_SYSTEM_DMA)         += dma.o
 obj-$(CONFIG_CPU_FREQ)                  += cpu-tegra.o
 obj-$(CONFIG_TEGRA_PCI)                        += pcie.o
 obj-$(CONFIG_USB_SUPPORT)              += usb_phy.o
 
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)                += board-dt-tegra20.o
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC)                += board-dt-tegra30.o
+
 obj-$(CONFIG_MACH_HARMONY)              += board-harmony.o
 obj-$(CONFIG_MACH_HARMONY)              += board-harmony-pinmux.o
 obj-$(CONFIG_MACH_HARMONY)              += board-harmony-pcie.o
@@ -31,14 +34,5 @@ obj-$(CONFIG_MACH_HARMONY)              += board-harmony-power.o
 obj-$(CONFIG_MACH_PAZ00)               += board-paz00.o
 obj-$(CONFIG_MACH_PAZ00)               += board-paz00-pinmux.o
 
-obj-$(CONFIG_MACH_SEABOARD)             += board-seaboard.o
-obj-$(CONFIG_MACH_SEABOARD)             += board-seaboard-pinmux.o
-
-obj-$(CONFIG_MACH_TEGRA_DT)             += board-dt-tegra20.o
-obj-$(CONFIG_MACH_TEGRA_DT)             += board-harmony-pinmux.o
-obj-$(CONFIG_MACH_TEGRA_DT)             += board-seaboard-pinmux.o
-obj-$(CONFIG_MACH_TEGRA_DT)             += board-paz00-pinmux.o
-obj-$(CONFIG_MACH_TEGRA_DT)             += board-trimslice-pinmux.o
-
 obj-$(CONFIG_MACH_TRIMSLICE)            += board-trimslice.o
 obj-$(CONFIG_MACH_TRIMSLICE)            += board-trimslice-pinmux.o
index 9a82094092d72221e987f603496d93a683da2931..7a1bb62ddcf037b9b07e38a7835f2d2cf1d023f8 100644 (file)
@@ -2,9 +2,10 @@ zreladdr-$(CONFIG_ARCH_TEGRA_2x_SOC)   += 0x00008000
 params_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)        := 0x00000100
 initrd_phys-$(CONFIG_ARCH_TEGRA_2x_SOC)        := 0x00800000
 
-dtb-$(CONFIG_MACH_HARMONY) += tegra-harmony.dtb
-dtb-$(CONFIG_MACH_PAZ00) += tegra-paz00.dtb
-dtb-$(CONFIG_MACH_SEABOARD) += tegra-seaboard.dtb
-dtb-$(CONFIG_MACH_TRIMSLICE) += tegra-trimslice.dtb
-dtb-$(CONFIG_MACH_VENTANA) += tegra-ventana.dtb
-dtb-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra-cardhu.dtb
+dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-harmony.dtb
+dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-paz00.dtb
+dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-seaboard.dtb
+dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-trimslice.dtb
+dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-ventana.dtb
+dtb-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20-whistler.dtb
+dtb-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra30-cardhu.dtb
index e75451e517bdd2b55a4c94bc17be3abaddc24c1c..dc0fe389be5645e632a669ee932f50140e43d80c 100644 (file)
@@ -15,6 +15,9 @@
 
 #include <linux/kernel.h>
 #include <linux/io.h>
+#include <mach/iomap.h>
+#include <linux/of.h>
+#include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
 #include <linux/completion.h>
 #include <linux/mutex.h>
 
 #include <mach/dma.h>
-#include <mach/iomap.h>
 
 #include "apbio.h"
 
+#if defined(CONFIG_TEGRA_SYSTEM_DMA) || defined(CONFIG_TEGRA20_APB_DMA)
 static DEFINE_MUTEX(tegra_apb_dma_lock);
-
-static struct tegra_dma_channel *tegra_apb_dma;
 static u32 *tegra_apb_bb;
 static dma_addr_t tegra_apb_bb_phys;
 static DECLARE_COMPLETION(tegra_apb_wait);
 
+static u32 tegra_apb_readl_direct(unsigned long offset);
+static void tegra_apb_writel_direct(u32 value, unsigned long offset);
+
+#if defined(CONFIG_TEGRA_SYSTEM_DMA)
+static struct tegra_dma_channel *tegra_apb_dma;
+
 bool tegra_apb_init(void)
 {
        struct tegra_dma_channel *ch;
@@ -72,13 +79,13 @@ static void apb_dma_complete(struct tegra_dma_req *req)
        complete(&tegra_apb_wait);
 }
 
-u32 tegra_apb_readl(unsigned long offset)
+static u32 tegra_apb_readl_using_dma(unsigned long offset)
 {
        struct tegra_dma_req req;
        int ret;
 
        if (!tegra_apb_dma && !tegra_apb_init())
-               return readl(IO_TO_VIRT(offset));
+               return tegra_apb_readl_direct(offset);
 
        mutex_lock(&tegra_apb_dma_lock);
        req.complete = apb_dma_complete;
@@ -108,13 +115,13 @@ u32 tegra_apb_readl(unsigned long offset)
        return *((u32 *)tegra_apb_bb);
 }
 
-void tegra_apb_writel(u32 value, unsigned long offset)
+static void tegra_apb_writel_using_dma(u32 value, unsigned long offset)
 {
        struct tegra_dma_req req;
        int ret;
 
        if (!tegra_apb_dma && !tegra_apb_init()) {
-               writel(value, IO_TO_VIRT(offset));
+               tegra_apb_writel_direct(value, offset);
                return;
        }
 
@@ -143,3 +150,176 @@ void tegra_apb_writel(u32 value, unsigned long offset)
 
        mutex_unlock(&tegra_apb_dma_lock);
 }
+
+#else
+static struct dma_chan *tegra_apb_dma_chan;
+static struct dma_slave_config dma_sconfig;
+
+bool tegra_apb_dma_init(void)
+{
+       dma_cap_mask_t mask;
+
+       mutex_lock(&tegra_apb_dma_lock);
+
+       /* Check to see if we raced to setup */
+       if (tegra_apb_dma_chan)
+               goto skip_init;
+
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_SLAVE, mask);
+       tegra_apb_dma_chan = dma_request_channel(mask, NULL, NULL);
+       if (!tegra_apb_dma_chan) {
+               /*
+                * This is common until the device is probed, so don't
+                * shout about it.
+                */
+               pr_debug("%s: can not allocate dma channel\n", __func__);
+               goto err_dma_alloc;
+       }
+
+       tegra_apb_bb = dma_alloc_coherent(NULL, sizeof(u32),
+               &tegra_apb_bb_phys, GFP_KERNEL);
+       if (!tegra_apb_bb) {
+               pr_err("%s: can not allocate bounce buffer\n", __func__);
+               goto err_buff_alloc;
+       }
+
+       dma_sconfig.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       dma_sconfig.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+       dma_sconfig.slave_id = TEGRA_DMA_REQ_SEL_CNTR;
+       dma_sconfig.src_maxburst = 1;
+       dma_sconfig.dst_maxburst = 1;
+
+skip_init:
+       mutex_unlock(&tegra_apb_dma_lock);
+       return true;
+
+err_buff_alloc:
+       dma_release_channel(tegra_apb_dma_chan);
+       tegra_apb_dma_chan = NULL;
+
+err_dma_alloc:
+       mutex_unlock(&tegra_apb_dma_lock);
+       return false;
+}
+
+static void apb_dma_complete(void *args)
+{
+       complete(&tegra_apb_wait);
+}
+
+static int do_dma_transfer(unsigned long apb_add,
+               enum dma_transfer_direction dir)
+{
+       struct dma_async_tx_descriptor *dma_desc;
+       int ret;
+
+       if (dir == DMA_DEV_TO_MEM)
+               dma_sconfig.src_addr = apb_add;
+       else
+               dma_sconfig.dst_addr = apb_add;
+
+       ret = dmaengine_slave_config(tegra_apb_dma_chan, &dma_sconfig);
+       if (ret)
+               return ret;
+
+       dma_desc = dmaengine_prep_slave_single(tegra_apb_dma_chan,
+                       tegra_apb_bb_phys, sizeof(u32), dir,
+                       DMA_PREP_INTERRUPT |  DMA_CTRL_ACK);
+       if (!dma_desc)
+               return -EINVAL;
+
+       dma_desc->callback = apb_dma_complete;
+       dma_desc->callback_param = NULL;
+
+       INIT_COMPLETION(tegra_apb_wait);
+
+       dmaengine_submit(dma_desc);
+       dma_async_issue_pending(tegra_apb_dma_chan);
+       ret = wait_for_completion_timeout(&tegra_apb_wait,
+               msecs_to_jiffies(50));
+
+       if (WARN(ret == 0, "apb read dma timed out")) {
+               dmaengine_terminate_all(tegra_apb_dma_chan);
+               return -EFAULT;
+       }
+       return 0;
+}
+
+static u32 tegra_apb_readl_using_dma(unsigned long offset)
+{
+       int ret;
+
+       if (!tegra_apb_dma_chan && !tegra_apb_dma_init())
+               return tegra_apb_readl_direct(offset);
+
+       mutex_lock(&tegra_apb_dma_lock);
+       ret = do_dma_transfer(offset, DMA_DEV_TO_MEM);
+       if (ret < 0) {
+               pr_err("error in reading offset 0x%08lx using dma\n", offset);
+               *(u32 *)tegra_apb_bb = 0;
+       }
+       mutex_unlock(&tegra_apb_dma_lock);
+       return *((u32 *)tegra_apb_bb);
+}
+
+static void tegra_apb_writel_using_dma(u32 value, unsigned long offset)
+{
+       int ret;
+
+       if (!tegra_apb_dma_chan && !tegra_apb_dma_init()) {
+               tegra_apb_writel_direct(value, offset);
+               return;
+       }
+
+       mutex_lock(&tegra_apb_dma_lock);
+       *((u32 *)tegra_apb_bb) = value;
+       ret = do_dma_transfer(offset, DMA_MEM_TO_DEV);
+       if (ret < 0)
+               pr_err("error in writing offset 0x%08lx using dma\n", offset);
+       mutex_unlock(&tegra_apb_dma_lock);
+}
+#endif
+#else
+#define tegra_apb_readl_using_dma tegra_apb_readl_direct
+#define tegra_apb_writel_using_dma tegra_apb_writel_direct
+#endif
+
+typedef u32 (*apbio_read_fptr)(unsigned long offset);
+typedef void (*apbio_write_fptr)(u32 value, unsigned long offset);
+
+static apbio_read_fptr apbio_read;
+static apbio_write_fptr apbio_write;
+
+static u32 tegra_apb_readl_direct(unsigned long offset)
+{
+       return readl(IO_TO_VIRT(offset));
+}
+
+static void tegra_apb_writel_direct(u32 value, unsigned long offset)
+{
+       writel(value, IO_TO_VIRT(offset));
+}
+
+void tegra_apb_io_init(void)
+{
+       /* Need to use dma only when it is Tegra20 based platform */
+       if (of_machine_is_compatible("nvidia,tegra20") ||
+                       !of_have_populated_dt()) {
+               apbio_read = tegra_apb_readl_using_dma;
+               apbio_write = tegra_apb_writel_using_dma;
+       } else {
+               apbio_read = tegra_apb_readl_direct;
+               apbio_write = tegra_apb_writel_direct;
+       }
+}
+
+u32 tegra_apb_readl(unsigned long offset)
+{
+       return apbio_read(offset);
+}
+
+void tegra_apb_writel(u32 value, unsigned long offset)
+{
+       apbio_write(value, offset);
+}
index 8b49e8c89a648993ec7452d2550a5552998c03c6..f05d71c303c75979abd43ebb1f079920a156632f 100644 (file)
 #ifndef __MACH_TEGRA_APBIO_H
 #define __MACH_TEGRA_APBIO_H
 
-#ifdef CONFIG_TEGRA_SYSTEM_DMA
-
+void tegra_apb_io_init(void);
 u32 tegra_apb_readl(unsigned long offset);
 void tegra_apb_writel(u32 value, unsigned long offset);
-
-#else
-#include <asm/io.h>
-#include <mach/io.h>
-
-static inline u32 tegra_apb_readl(unsigned long offset)
-{
-        return readl(IO_TO_VIRT(offset));
-}
-
-static inline void tegra_apb_writel(u32 value, unsigned long offset)
-{
-        writel(value, IO_TO_VIRT(offset));
-}
-#endif
-
 #endif
index eb7249db50a59cada041847515313f60cd05eb59..d0de9c1192f78eae03b70a8c9d0c7b72e4bc4d0c 100644 (file)
@@ -64,6 +64,7 @@ struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
                       &tegra_ehci2_pdata),
        OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB3_BASE, "tegra-ehci.2",
                       &tegra_ehci3_pdata),
+       OF_DEV_AUXDATA("nvidia,tegra20-apbdma", 0x6000a000, "tegra-apbdma", NULL),
        {}
 };
 
@@ -81,11 +82,6 @@ static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
        { NULL,         NULL,           0,              0},
 };
 
-static struct of_device_id tegra_dt_match_table[] __initdata = {
-       { .compatible = "simple-bus", },
-       {}
-};
-
 static void __init tegra_dt_init(void)
 {
        tegra_clk_init_from_table(tegra_dt_clk_init_table);
@@ -94,10 +90,74 @@ static void __init tegra_dt_init(void)
         * Finished with the static registrations now; fill in the missing
         * devices
         */
-       of_platform_populate(NULL, tegra_dt_match_table,
+       of_platform_populate(NULL, of_default_bus_match_table,
                                tegra20_auxdata_lookup, NULL);
 }
 
+#ifdef CONFIG_MACH_TRIMSLICE
+static void __init trimslice_init(void)
+{
+       int ret;
+
+       ret = tegra_pcie_init(true, true);
+       if (ret)
+               pr_err("tegra_pci_init() failed: %d\n", ret);
+}
+#endif
+
+#ifdef CONFIG_MACH_HARMONY
+static void __init harmony_init(void)
+{
+       int ret;
+
+       ret = harmony_regulator_init();
+       if (ret) {
+               pr_err("harmony_regulator_init() failed: %d\n", ret);
+               return;
+       }
+
+       ret = harmony_pcie_init();
+       if (ret)
+               pr_err("harmony_pcie_init() failed: %d\n", ret);
+}
+#endif
+
+#ifdef CONFIG_MACH_PAZ00
+static void __init paz00_init(void)
+{
+       tegra_paz00_wifikill_init();
+}
+#endif
+
+static struct {
+       char *machine;
+       void (*init)(void);
+} board_init_funcs[] = {
+#ifdef CONFIG_MACH_TRIMSLICE
+       { "compulab,trimslice", trimslice_init },
+#endif
+#ifdef CONFIG_MACH_HARMONY
+       { "nvidia,harmony", harmony_init },
+#endif
+#ifdef CONFIG_MACH_PAZ00
+       { "compal,paz00", paz00_init },
+#endif
+};
+
+static void __init tegra_dt_init_late(void)
+{
+       int i;
+
+       tegra_init_late();
+
+       for (i = 0; i < ARRAY_SIZE(board_init_funcs); i++) {
+               if (of_machine_is_compatible(board_init_funcs[i].machine)) {
+                       board_init_funcs[i].init();
+                       break;
+               }
+       }
+}
+
 static const char *tegra20_dt_board_compat[] = {
        "nvidia,tegra20",
        NULL
@@ -110,7 +170,7 @@ DT_MACHINE_START(TEGRA_DT, "nVidia Tegra20 (Flattened Device Tree)")
        .handle_irq     = gic_handle_irq,
        .timer          = &tegra_timer,
        .init_machine   = tegra_dt_init,
-       .init_late      = tegra_init_late,
+       .init_late      = tegra_dt_init_late,
        .restart        = tegra_assert_system_reset,
        .dt_compat      = tegra20_dt_board_compat,
 MACHINE_END
index 4f76fa7a5da396860f9bf3a5a4d672c037b52a47..ee48214bfd898ea86f2084dba182e85df96bbc58 100644 (file)
 #include "board.h"
 #include "clock.h"
 
-static struct of_device_id tegra_dt_match_table[] __initdata = {
-       { .compatible = "simple-bus", },
-       {}
-};
-
 struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000000, "sdhci-tegra.0", NULL),
        OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000200, "sdhci-tegra.1", NULL),
@@ -52,6 +47,7 @@ struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C700, "tegra-i2c.3", NULL),
        OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000D000, "tegra-i2c.4", NULL),
        OF_DEV_AUXDATA("nvidia,tegra30-ahub", 0x70080000, "tegra30-ahub", NULL),
+       OF_DEV_AUXDATA("nvidia,tegra30-apbdma", 0x6000a000, "tegra-apbdma", NULL),
        {}
 };
 
@@ -74,7 +70,7 @@ static void __init tegra30_dt_init(void)
 {
        tegra_clk_init_from_table(tegra_dt_clk_init_table);
 
-       of_platform_populate(NULL, tegra_dt_match_table,
+       of_platform_populate(NULL, of_default_bus_match_table,
                                tegra30_auxdata_lookup, NULL);
 }
 
index 33c4fedab840fc42fee9232fb2d1d581d85ba7d8..e8c3fda9bec2faa0665372c04ffbcb8cd22f448f 100644 (file)
 
 #ifdef CONFIG_TEGRA_PCI
 
-static int __init harmony_pcie_init(void)
+int __init harmony_pcie_init(void)
 {
        struct regulator *regulator = NULL;
        int err;
 
-       if (!machine_is_harmony())
-               return 0;
-
        err = gpio_request(TEGRA_GPIO_EN_VDD_1V05_GPIO, "EN_VDD_1V05");
        if (err)
                return err;
@@ -62,7 +59,15 @@ err_reg:
        return err;
 }
 
+static int __init harmony_pcie_initcall(void)
+{
+       if (!machine_is_harmony())
+               return 0;
+
+       return harmony_pcie_init();
+}
+
 /* PCI should be initialized after I2C, mfd and regulators */
-subsys_initcall_sync(harmony_pcie_init);
+subsys_initcall_sync(harmony_pcie_initcall);
 
 #endif
index 82f32300796c082fe4f76c938ba76ac9b4bb1ff2..44dcb2e869b50ddbf64277c16c38a6790ad31b4a 100644 (file)
 #include <linux/gpio.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/tps6586x.h>
+#include <linux/of.h>
+#include <linux/of_i2c.h>
+
+#include <asm/mach-types.h>
 
 #include <mach/irqs.h>
 
@@ -110,7 +114,26 @@ static struct i2c_board_info __initdata harmony_regulators[] = {
 
 int __init harmony_regulator_init(void)
 {
-       i2c_register_board_info(3, harmony_regulators, 1);
+       if (machine_is_harmony()) {
+               i2c_register_board_info(3, harmony_regulators, 1);
+       } else { /* Harmony, booted using device tree */
+               struct device_node *np;
+               struct i2c_adapter *adapter;
+
+               np = of_find_node_by_path("/i2c@7000d000");
+               if (np == NULL) {
+                       pr_err("Could not find device_node for DVC I2C\n");
+                       return -ENODEV;
+               }
+
+               adapter = of_find_i2c_adapter_by_node(np);
+               if (!adapter) {
+                       pr_err("Could not find i2c_adapter for DVC I2C\n");
+                       return -ENODEV;
+               }
+
+               i2c_new_device(adapter, harmony_regulators);
+       }
 
        return 0;
 }
index bbc1907e98a69875144b32e367629a9f8b2739f9..4b64af5cab27bdbbb4251053c1ae9e702b1fbcb3 100644 (file)
@@ -148,7 +148,6 @@ static struct platform_device *paz00_devices[] __initdata = {
        &debug_uart,
        &tegra_sdhci_device4,
        &tegra_sdhci_device1,
-       &wifi_rfkill_device,
        &leds_gpio,
        &gpio_keys_device,
 };
@@ -201,6 +200,11 @@ static struct tegra_sdhci_platform_data sdhci_pdata4 = {
        .is_8bit        = 1,
 };
 
+void __init tegra_paz00_wifikill_init(void)
+{
+       platform_device_register(&wifi_rfkill_device);
+}
+
 static void __init tegra_paz00_init(void)
 {
        tegra_clk_init_from_table(paz00_clk_init_table);
@@ -211,6 +215,7 @@ static void __init tegra_paz00_init(void)
        tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
 
        platform_add_devices(paz00_devices, ARRAY_SIZE(paz00_devices));
+       tegra_paz00_wifikill_init();
 
        paz00_i2c_init();
        paz00_usb_init();
diff --git a/arch/arm/mach-tegra/board-seaboard-pinmux.c b/arch/arm/mach-tegra/board-seaboard-pinmux.c
deleted file mode 100644 (file)
index 11fc8a5..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright (C) 2010-2012 NVIDIA Corporation
- * Copyright (C) 2011 Google, Inc.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-#include <linux/kernel.h>
-
-#include "board-seaboard.h"
-#include "board-pinmux.h"
-
-static unsigned long seaboard_pincfg_drive_sdio1[] = {
-       TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_HIGH_SPEED_MODE, 0),
-       TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_SCHMITT, 0),
-       TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_LOW_POWER_MODE, 3),
-       TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_DRIVE_DOWN_STRENGTH, 31),
-       TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_DRIVE_UP_STRENGTH, 31),
-       TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_SLEW_RATE_FALLING, 3),
-       TEGRA_PINCONF_PACK(TEGRA_PINCONF_PARAM_SLEW_RATE_RISING, 3),
-};
-
-static struct pinctrl_map common_map[] = {
-       TEGRA_MAP_MUXCONF("ata",   "ide",           none, driven),
-       TEGRA_MAP_MUXCONF("atb",   "sdio4",         none, driven),
-       TEGRA_MAP_MUXCONF("atc",   "nand",          none, driven),
-       TEGRA_MAP_MUXCONF("atd",   "gmi",           none, driven),
-       TEGRA_MAP_MUXCONF("ate",   "gmi",           none, tristate),
-       TEGRA_MAP_MUXCONF("cdev1", "plla_out",      none, driven),
-       TEGRA_MAP_MUXCONF("cdev2", "pllp_out4",     none, driven),
-       TEGRA_MAP_MUXCONF("crtp",  "crt",           up,   tristate),
-       TEGRA_MAP_MUXCONF("csus",  "vi_sensor_clk", none, tristate),
-       TEGRA_MAP_MUXCONF("dap1",  "dap1",          none, driven),
-       TEGRA_MAP_MUXCONF("dap2",  "dap2",          none, driven),
-       TEGRA_MAP_MUXCONF("dap3",  "dap3",          none, tristate),
-       TEGRA_MAP_MUXCONF("dap4",  "dap4",          none, driven),
-       TEGRA_MAP_MUXCONF("dta",   "vi",            down, driven),
-       TEGRA_MAP_MUXCONF("dtb",   "vi",            down, driven),
-       TEGRA_MAP_MUXCONF("dtc",   "vi",            down, driven),
-       TEGRA_MAP_MUXCONF("dtd",   "vi",            down, driven),
-       TEGRA_MAP_MUXCONF("dte",   "vi",            down, tristate),
-       TEGRA_MAP_MUXCONF("dtf",   "i2c3",          none, driven),
-       TEGRA_MAP_MUXCONF("gma",   "sdio4",         none, driven),
-       TEGRA_MAP_MUXCONF("gmb",   "gmi",           up,   tristate),
-       TEGRA_MAP_MUXCONF("gmc",   "uartd",         none, driven),
-       TEGRA_MAP_MUXCONF("gme",   "sdio4",         none, driven),
-       TEGRA_MAP_MUXCONF("gpu",   "pwm",           none, driven),
-       TEGRA_MAP_MUXCONF("gpu7",  "rtck",          none, driven),
-       TEGRA_MAP_MUXCONF("gpv",   "pcie",          none, tristate),
-       TEGRA_MAP_MUXCONF("hdint", "hdmi",          na,   tristate),
-       TEGRA_MAP_MUXCONF("i2cp",  "i2cp",          none, driven),
-       TEGRA_MAP_MUXCONF("irrx",  "uartb",         none, driven),
-       TEGRA_MAP_MUXCONF("irtx",  "uartb",         none, driven),
-       TEGRA_MAP_MUXCONF("kbca",  "kbc",           up,   driven),
-       TEGRA_MAP_MUXCONF("kbcb",  "kbc",           up,   driven),
-       TEGRA_MAP_MUXCONF("kbcc",  "kbc",           up,   driven),
-       TEGRA_MAP_MUXCONF("kbcd",  "kbc",           up,   driven),
-       TEGRA_MAP_MUXCONF("kbce",  "kbc",           up,   driven),
-       TEGRA_MAP_MUXCONF("kbcf",  "kbc",           up,   driven),
-       TEGRA_MAP_MUXCONF("lcsn",  "rsvd4",         na,   tristate),
-       TEGRA_MAP_MUXCONF("ld0",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld1",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld10",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld11",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld12",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld13",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld14",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld15",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld16",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld17",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld2",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld3",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld4",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld5",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld6",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld7",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld8",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ld9",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("ldc",   "rsvd4",         na,   tristate),
-       TEGRA_MAP_MUXCONF("ldi",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lhp0",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lhp1",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lhp2",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lhs",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lm0",   "rsvd4",         na,   driven),
-       TEGRA_MAP_MUXCONF("lm1",   "crt",           na,   tristate),
-       TEGRA_MAP_MUXCONF("lpp",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lpw1",  "rsvd4",         na,   tristate),
-       TEGRA_MAP_MUXCONF("lsc0",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lsdi",  "rsvd4",         na,   tristate),
-       TEGRA_MAP_MUXCONF("lspi",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lvp0",  "rsvd4",         na,   tristate),
-       TEGRA_MAP_MUXCONF("lvp1",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lvs",   "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("owc",   "rsvd2",         none, tristate),
-       TEGRA_MAP_MUXCONF("pmc",   "pwr_on",        na,   driven),
-       TEGRA_MAP_MUXCONF("pta",   "hdmi",          none, driven),
-       TEGRA_MAP_MUXCONF("rm",    "i2c1",          none, driven),
-       TEGRA_MAP_MUXCONF("sdb",   "sdio3",         na,   driven),
-       TEGRA_MAP_MUXCONF("sdc",   "sdio3",         none, driven),
-       TEGRA_MAP_MUXCONF("sdd",   "sdio3",         none, driven),
-       TEGRA_MAP_MUXCONF("sdio1", "sdio1",         up,   driven),
-       TEGRA_MAP_MUXCONF("slxa",  "pcie",          up,   tristate),
-       TEGRA_MAP_MUXCONF("slxd",  "spdif",         none, driven),
-       TEGRA_MAP_MUXCONF("slxk",  "pcie",          none, driven),
-       TEGRA_MAP_MUXCONF("spdi",  "rsvd2",         none, driven),
-       TEGRA_MAP_MUXCONF("spdo",  "rsvd2",         none, driven),
-       TEGRA_MAP_MUXCONF("spib",  "gmi",           none, tristate),
-       TEGRA_MAP_MUXCONF("spid",  "spi1",          none, tristate),
-       TEGRA_MAP_MUXCONF("spie",  "spi1",          none, tristate),
-       TEGRA_MAP_MUXCONF("spif",  "spi1",          down, tristate),
-       TEGRA_MAP_MUXCONF("spih",  "spi2_alt",      up,   tristate),
-       TEGRA_MAP_MUXCONF("uaa",   "ulpi",          up,   driven),
-       TEGRA_MAP_MUXCONF("uab",   "ulpi",          up,   driven),
-       TEGRA_MAP_MUXCONF("uac",   "rsvd2",         none, driven),
-       TEGRA_MAP_MUXCONF("uad",   "irda",          none, driven),
-       TEGRA_MAP_MUXCONF("uca",   "uartc",         none, driven),
-       TEGRA_MAP_MUXCONF("ucb",   "uartc",         none, driven),
-       TEGRA_MAP_MUXCONF("uda",   "ulpi",          none, driven),
-       TEGRA_MAP_CONF("ck32",    none, na),
-       TEGRA_MAP_CONF("ddrc",    none, na),
-       TEGRA_MAP_CONF("pmca",    none, na),
-       TEGRA_MAP_CONF("pmcb",    none, na),
-       TEGRA_MAP_CONF("pmcc",    none, na),
-       TEGRA_MAP_CONF("pmcd",    none, na),
-       TEGRA_MAP_CONF("pmce",    none, na),
-       TEGRA_MAP_CONF("xm2c",    none, na),
-       TEGRA_MAP_CONF("xm2d",    none, na),
-       TEGRA_MAP_CONF("ls",      up,   na),
-       TEGRA_MAP_CONF("lc",      up,   na),
-       TEGRA_MAP_CONF("ld17_0",  down, na),
-       TEGRA_MAP_CONF("ld19_18", down, na),
-       TEGRA_MAP_CONF("ld21_20", down, na),
-       TEGRA_MAP_CONF("ld23_22", down, na),
-};
-
-static struct pinctrl_map seaboard_map[] = {
-       TEGRA_MAP_MUXCONF("ddc",   "rsvd2",         none, tristate),
-       TEGRA_MAP_MUXCONF("gmd",   "sflash",        none, driven),
-       TEGRA_MAP_MUXCONF("lpw0",  "hdmi",          na,   driven),
-       TEGRA_MAP_MUXCONF("lpw2",  "hdmi",          na,   driven),
-       TEGRA_MAP_MUXCONF("lsc1",  "hdmi",          na,   tristate),
-       TEGRA_MAP_MUXCONF("lsck",  "hdmi",          na,   tristate),
-       TEGRA_MAP_MUXCONF("lsda",  "hdmi",          na,   tristate),
-       TEGRA_MAP_MUXCONF("slxc",  "spdif",         none, tristate),
-       TEGRA_MAP_MUXCONF("spia",  "gmi",           up,   tristate),
-       TEGRA_MAP_MUXCONF("spic",  "gmi",           up,   driven),
-       TEGRA_MAP_MUXCONF("spig",  "spi2_alt",      up,   tristate),
-       PIN_MAP_CONFIGS_GROUP_HOG_DEFAULT(PINMUX_DEV, "drive_sdio1", seaboard_pincfg_drive_sdio1),
-};
-
-static struct pinctrl_map ventana_map[] = {
-       TEGRA_MAP_MUXCONF("ddc",   "rsvd2",         none, driven),
-       TEGRA_MAP_MUXCONF("gmd",   "sflash",        none, tristate),
-       TEGRA_MAP_MUXCONF("lpw0",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lpw2",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lsc1",  "displaya",      na,   driven),
-       TEGRA_MAP_MUXCONF("lsck",  "displaya",      na,   tristate),
-       TEGRA_MAP_MUXCONF("lsda",  "displaya",      na,   tristate),
-       TEGRA_MAP_MUXCONF("slxc",  "sdio3",         none, driven),
-       TEGRA_MAP_MUXCONF("spia",  "gmi",           none, tristate),
-       TEGRA_MAP_MUXCONF("spic",  "gmi",           none, tristate),
-       TEGRA_MAP_MUXCONF("spig",  "spi2_alt",      none, tristate),
-};
-
-static struct tegra_board_pinmux_conf common_conf = {
-       .maps = common_map,
-       .map_count = ARRAY_SIZE(common_map),
-};
-
-static struct tegra_board_pinmux_conf seaboard_conf = {
-       .maps = seaboard_map,
-       .map_count = ARRAY_SIZE(seaboard_map),
-};
-
-static struct tegra_board_pinmux_conf ventana_conf = {
-       .maps = ventana_map,
-       .map_count = ARRAY_SIZE(ventana_map),
-};
-
-void seaboard_pinmux_init(void)
-{
-       tegra_board_pinmux_init(&common_conf, &seaboard_conf);
-}
-
-void ventana_pinmux_init(void)
-{
-       tegra_board_pinmux_init(&common_conf, &ventana_conf);
-}
diff --git a/arch/arm/mach-tegra/board-seaboard.c b/arch/arm/mach-tegra/board-seaboard.c
deleted file mode 100644 (file)
index 71e9f3f..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (c) 2010, 2011 NVIDIA Corporation.
- * Copyright (C) 2010, 2011 Google, Inc.
- *
- * 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/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/of_serial.h>
-#include <linux/i2c.h>
-#include <linux/delay.h>
-#include <linux/input.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-#include <linux/gpio_keys.h>
-#include <linux/platform_data/tegra_usb.h>
-
-#include <sound/wm8903.h>
-
-#include <mach/iomap.h>
-#include <mach/irqs.h>
-#include <mach/sdhci.h>
-#include <mach/tegra_wm8903_pdata.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
-
-#include "board.h"
-#include "board-seaboard.h"
-#include "clock.h"
-#include "devices.h"
-#include "gpio-names.h"
-
-static struct plat_serial8250_port debug_uart_platform_data[] = {
-       {
-               /* Memory and IRQ filled in before registration */
-               .flags          = UPF_BOOT_AUTOCONF | UPF_FIXED_TYPE,
-               .type           = PORT_TEGRA,
-               .handle_break   = tegra_serial_handle_break,
-               .iotype         = UPIO_MEM,
-               .regshift       = 2,
-               .uartclk        = 216000000,
-       }, {
-               .flags          = 0,
-       }
-};
-
-static struct platform_device debug_uart = {
-       .name = "serial8250",
-       .id = PLAT8250_DEV_PLATFORM,
-       .dev = {
-               .platform_data = debug_uart_platform_data,
-       },
-};
-
-static __initdata struct tegra_clk_init_table seaboard_clk_init_table[] = {
-       /* name         parent          rate            enabled */
-       { "uartb",      "pll_p",        216000000,      true},
-       { "uartd",      "pll_p",        216000000,      true},
-       { "pll_a",      "pll_p_out1",   56448000,       true },
-       { "pll_a_out0", "pll_a",        11289600,       true },
-       { "cdev1",      NULL,           0,              true },
-       { "i2s1",       "pll_a_out0",   11289600,       false},
-       { "usbd",       "clk_m",        12000000,       true},
-       { "usb3",       "clk_m",        12000000,       true},
-       { NULL,         NULL,           0,              0},
-};
-
-static struct gpio_keys_button seaboard_gpio_keys_buttons[] = {
-       {
-               .code           = SW_LID,
-               .gpio           = TEGRA_GPIO_LIDSWITCH,
-               .active_low     = 0,
-               .desc           = "Lid",
-               .type           = EV_SW,
-               .wakeup         = 1,
-               .debounce_interval = 1,
-       },
-       {
-               .code           = KEY_POWER,
-               .gpio           = TEGRA_GPIO_POWERKEY,
-               .active_low     = 1,
-               .desc           = "Power",
-               .type           = EV_KEY,
-               .wakeup         = 1,
-       },
-};
-
-static struct gpio_keys_platform_data seaboard_gpio_keys = {
-       .buttons        = seaboard_gpio_keys_buttons,
-       .nbuttons       = ARRAY_SIZE(seaboard_gpio_keys_buttons),
-};
-
-static struct platform_device seaboard_gpio_keys_device = {
-       .name           = "gpio-keys",
-       .id             = -1,
-       .dev            = {
-               .platform_data = &seaboard_gpio_keys,
-       }
-};
-
-static struct tegra_sdhci_platform_data sdhci_pdata1 = {
-       .cd_gpio        = -1,
-       .wp_gpio        = -1,
-       .power_gpio     = -1,
-};
-
-static struct tegra_sdhci_platform_data sdhci_pdata3 = {
-       .cd_gpio        = TEGRA_GPIO_SD2_CD,
-       .wp_gpio        = TEGRA_GPIO_SD2_WP,
-       .power_gpio     = TEGRA_GPIO_SD2_POWER,
-};
-
-static struct tegra_sdhci_platform_data sdhci_pdata4 = {
-       .cd_gpio        = -1,
-       .wp_gpio        = -1,
-       .power_gpio     = -1,
-       .is_8bit        = 1,
-};
-
-static struct tegra_wm8903_platform_data seaboard_audio_pdata = {
-       .gpio_spkr_en           = TEGRA_GPIO_SPKR_EN,
-       .gpio_hp_det            = TEGRA_GPIO_HP_DET,
-       .gpio_hp_mute           = -1,
-       .gpio_int_mic_en        = -1,
-       .gpio_ext_mic_en        = -1,
-};
-
-static struct platform_device seaboard_audio_device = {
-       .name   = "tegra-snd-wm8903",
-       .id     = 0,
-       .dev    = {
-               .platform_data  = &seaboard_audio_pdata,
-       },
-};
-
-static struct platform_device *seaboard_devices[] __initdata = {
-       &debug_uart,
-       &tegra_pmu_device,
-       &tegra_sdhci_device4,
-       &tegra_sdhci_device3,
-       &tegra_sdhci_device1,
-       &seaboard_gpio_keys_device,
-       &tegra_i2s_device1,
-       &tegra_das_device,
-       &seaboard_audio_device,
-};
-
-static struct i2c_board_info __initdata isl29018_device = {
-       I2C_BOARD_INFO("isl29018", 0x44),
-};
-
-static struct i2c_board_info __initdata adt7461_device = {
-       I2C_BOARD_INFO("adt7461", 0x4c),
-};
-
-static struct wm8903_platform_data wm8903_pdata = {
-       .irq_active_low = 0,
-       .micdet_cfg = 0,
-       .micdet_delay = 100,
-       .gpio_base = SEABOARD_GPIO_WM8903(0),
-       .gpio_cfg = {
-               0,
-               0,
-               WM8903_GPIO_CONFIG_ZERO,
-               0,
-               0,
-       },
-};
-
-static struct i2c_board_info __initdata wm8903_device = {
-       I2C_BOARD_INFO("wm8903", 0x1a),
-       .platform_data = &wm8903_pdata,
-};
-
-static int seaboard_ehci_init(void)
-{
-       struct tegra_ehci_platform_data *pdata;
-
-       pdata = tegra_ehci1_device.dev.platform_data;
-       pdata->vbus_gpio = TEGRA_GPIO_USB1;
-
-       platform_device_register(&tegra_ehci1_device);
-       platform_device_register(&tegra_ehci3_device);
-
-       return 0;
-}
-
-static void __init seaboard_i2c_init(void)
-{
-       isl29018_device.irq = gpio_to_irq(TEGRA_GPIO_ISL29018_IRQ);
-       i2c_register_board_info(0, &isl29018_device, 1);
-
-       wm8903_device.irq = gpio_to_irq(TEGRA_GPIO_CDC_IRQ);
-       i2c_register_board_info(0, &wm8903_device, 1);
-
-       i2c_register_board_info(3, &adt7461_device, 1);
-
-       platform_device_register(&tegra_i2c_device1);
-       platform_device_register(&tegra_i2c_device2);
-       platform_device_register(&tegra_i2c_device3);
-       platform_device_register(&tegra_i2c_device4);
-}
-
-static void __init seaboard_common_init(void)
-{
-       seaboard_pinmux_init();
-
-       tegra_clk_init_from_table(seaboard_clk_init_table);
-
-       tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
-       tegra_sdhci_device3.dev.platform_data = &sdhci_pdata3;
-       tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
-
-       platform_add_devices(seaboard_devices, ARRAY_SIZE(seaboard_devices));
-
-       seaboard_ehci_init();
-}
-
-static void __init tegra_seaboard_init(void)
-{
-       /* Seaboard uses UARTD for the debug port. */
-       debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTD_BASE);
-       debug_uart_platform_data[0].mapbase = TEGRA_UARTD_BASE;
-       debug_uart_platform_data[0].irq = INT_UARTD;
-
-       seaboard_common_init();
-
-       seaboard_i2c_init();
-}
-
-static void __init tegra_kaen_init(void)
-{
-       /* Kaen uses UARTB for the debug port. */
-       debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE);
-       debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE;
-       debug_uart_platform_data[0].irq = INT_UARTB;
-
-       seaboard_audio_pdata.gpio_hp_mute = TEGRA_GPIO_KAEN_HP_MUTE;
-
-       seaboard_common_init();
-
-       seaboard_i2c_init();
-}
-
-static void __init tegra_wario_init(void)
-{
-       /* Wario uses UARTB for the debug port. */
-       debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE);
-       debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE;
-       debug_uart_platform_data[0].irq = INT_UARTB;
-
-       seaboard_common_init();
-
-       seaboard_i2c_init();
-}
-
-
-MACHINE_START(SEABOARD, "seaboard")
-       .atag_offset    = 0x100,
-       .map_io         = tegra_map_common_io,
-       .init_early     = tegra20_init_early,
-       .init_irq       = tegra_init_irq,
-       .handle_irq     = gic_handle_irq,
-       .timer          = &tegra_timer,
-       .init_machine   = tegra_seaboard_init,
-       .init_late      = tegra_init_late,
-       .restart        = tegra_assert_system_reset,
-MACHINE_END
-
-MACHINE_START(KAEN, "kaen")
-       .atag_offset    = 0x100,
-       .map_io         = tegra_map_common_io,
-       .init_early     = tegra20_init_early,
-       .init_irq       = tegra_init_irq,
-       .handle_irq     = gic_handle_irq,
-       .timer          = &tegra_timer,
-       .init_machine   = tegra_kaen_init,
-       .init_late      = tegra_init_late,
-       .restart        = tegra_assert_system_reset,
-MACHINE_END
-
-MACHINE_START(WARIO, "wario")
-       .atag_offset    = 0x100,
-       .map_io         = tegra_map_common_io,
-       .init_early     = tegra20_init_early,
-       .init_irq       = tegra_init_irq,
-       .handle_irq     = gic_handle_irq,
-       .timer          = &tegra_timer,
-       .init_machine   = tegra_wario_init,
-       .init_late      = tegra_init_late,
-       .restart        = tegra_assert_system_reset,
-MACHINE_END
diff --git a/arch/arm/mach-tegra/board-seaboard.h b/arch/arm/mach-tegra/board-seaboard.h
deleted file mode 100644 (file)
index 4c45d4c..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * arch/arm/mach-tegra/board-seaboard.h
- *
- * 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.
- *
- */
-
-#ifndef _MACH_TEGRA_BOARD_SEABOARD_H
-#define _MACH_TEGRA_BOARD_SEABOARD_H
-
-#include <mach/gpio-tegra.h>
-
-#define SEABOARD_GPIO_TPS6586X(_x_)    (TEGRA_NR_GPIOS + (_x_))
-#define SEABOARD_GPIO_WM8903(_x_)      (SEABOARD_GPIO_TPS6586X(4) + (_x_))
-
-#define TEGRA_GPIO_SD2_CD              TEGRA_GPIO_PI5
-#define TEGRA_GPIO_SD2_WP              TEGRA_GPIO_PH1
-#define TEGRA_GPIO_SD2_POWER           TEGRA_GPIO_PI6
-#define TEGRA_GPIO_LIDSWITCH           TEGRA_GPIO_PC7
-#define TEGRA_GPIO_USB1                        TEGRA_GPIO_PD0
-#define TEGRA_GPIO_POWERKEY            TEGRA_GPIO_PV2
-#define TEGRA_GPIO_BACKLIGHT           TEGRA_GPIO_PD4
-#define TEGRA_GPIO_LVDS_SHUTDOWN       TEGRA_GPIO_PB2
-#define TEGRA_GPIO_BACKLIGHT_PWM       TEGRA_GPIO_PU5
-#define TEGRA_GPIO_BACKLIGHT_VDD       TEGRA_GPIO_PW0
-#define TEGRA_GPIO_EN_VDD_PNL          TEGRA_GPIO_PC6
-#define TEGRA_GPIO_MAGNETOMETER                TEGRA_GPIO_PN5
-#define TEGRA_GPIO_ISL29018_IRQ                TEGRA_GPIO_PZ2
-#define TEGRA_GPIO_AC_ONLINE           TEGRA_GPIO_PV3
-#define TEGRA_GPIO_WWAN_PWR            SEABOARD_GPIO_TPS6586X(2)
-#define TEGRA_GPIO_CDC_IRQ             TEGRA_GPIO_PX3
-#define TEGRA_GPIO_SPKR_EN             SEABOARD_GPIO_WM8903(2)
-#define TEGRA_GPIO_HP_DET              TEGRA_GPIO_PX1
-#define TEGRA_GPIO_KAEN_HP_MUTE                TEGRA_GPIO_PA5
-
-void seaboard_pinmux_init(void);
-
-#endif
index 65014968fc6c05ad1144c421856034b40756f037..f88e5143c767989e7cc8e634635d858055f9de61 100644 (file)
@@ -46,5 +46,14 @@ int __init tegra_powergate_debugfs_init(void);
 static inline int tegra_powergate_debugfs_init(void) { return 0; }
 #endif
 
+int __init harmony_regulator_init(void);
+#ifdef CONFIG_TEGRA_PCI
+int __init harmony_pcie_init(void);
+#else
+static inline int harmony_pcie_init(void) { return 0; }
+#endif
+
+void __init tegra_paz00_wifikill_init(void);
+
 extern struct sys_timer tegra_timer;
 #endif
index 204a5c8b0b574bd0cf2b46f5b0d4d1ccde87dd61..96fef6bcc65116bde2071ba6a2c46b66d6a1ed54 100644 (file)
@@ -33,6 +33,7 @@
 #include "clock.h"
 #include "fuse.h"
 #include "pmc.h"
+#include "apbio.h"
 
 /*
  * Storage for debug-macro.S's state.
@@ -127,6 +128,7 @@ static void __init tegra_init_cache(u32 tag_latency, u32 data_latency)
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
 void __init tegra20_init_early(void)
 {
+       tegra_apb_io_init();
        tegra_init_fuse();
        tegra2_init_clocks();
        tegra_clk_init_from_table(tegra20_clk_init_table);
@@ -138,6 +140,7 @@ void __init tegra20_init_early(void)
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
 void __init tegra30_init_early(void)
 {
+       tegra_apb_io_init();
        tegra_init_fuse();
        tegra30_init_clocks();
        tegra_clk_init_from_table(tegra30_clk_init_table);
index 7a065f0cf6338dfa6566b23d7a48e318c843a1f9..ceb52db1e2f16409729c2ef0205b854163a3fae7 100644 (file)
@@ -189,8 +189,8 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
                return PTR_ERR(emc_clk);
        }
 
-       clk_enable(emc_clk);
-       clk_enable(cpu_clk);
+       clk_prepare_enable(emc_clk);
+       clk_prepare_enable(cpu_clk);
 
        cpufreq_frequency_table_cpuinfo(policy, freq_table);
        cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
@@ -212,7 +212,7 @@ static int tegra_cpu_init(struct cpufreq_policy *policy)
 static int tegra_cpu_exit(struct cpufreq_policy *policy)
 {
        cpufreq_frequency_table_cpuinfo(policy, freq_table);
-       clk_disable(emc_clk);
+       clk_disable_unprepare(emc_clk);
        clk_put(emc_clk);
        clk_put(cpu_clk);
        return 0;
index d83a8c0296f5a2babaf161965aed5d5276fb95df..566e2f88899bdbde99595d4e166a1e87ad47f0aa 100644 (file)
@@ -27,9 +27,9 @@
 #include <linux/cpuidle.h>
 #include <linux/hrtimer.h>
 
-#include <mach/iomap.h>
+#include <asm/proc-fns.h>
 
-extern void tegra_cpu_wfi(void);
+#include <mach/iomap.h>
 
 static int tegra_idle_enter_lp3(struct cpuidle_device *dev,
                                struct cpuidle_driver *drv, int index);
@@ -64,7 +64,7 @@ static int tegra_idle_enter_lp3(struct cpuidle_device *dev,
 
        enter = ktime_get();
 
-       tegra_cpu_wfi();
+       cpu_do_idle();
 
        exit = ktime_sub(ktime_get(), enter);
        us = ktime_to_us(exit);
index abea4f6e2dd5cbc47aeb3a516fea05d27afe08d4..29c5114d607ccc1b651be43381d3e15bf3db7257 100644 (file)
@@ -714,13 +714,13 @@ int __init tegra_dma_init(void)
 
        bitmap_fill(channel_usage, NV_DMA_MAX_CHANNELS);
 
-       c = clk_get_sys("tegra-dma", NULL);
+       c = clk_get_sys("tegra-apbdma", NULL);
        if (IS_ERR(c)) {
                pr_err("Unable to get clock for APB DMA\n");
                ret = PTR_ERR(c);
                goto fail;
        }
-       ret = clk_enable(c);
+       ret = clk_prepare_enable(c);
        if (ret != 0) {
                pr_err("Unable to enable clock for APB DMA\n");
                goto fail;
index 0e09137506ec79890b56f76c47ac9e0bc8b225d9..d3ad5150d6609e135a063421d2c9acad62e204df 100644 (file)
@@ -723,9 +723,9 @@ static int tegra_pcie_power_regate(void)
 
        tegra_pcie_xclk_clamp(false);
 
-       clk_enable(tegra_pcie.afi_clk);
-       clk_enable(tegra_pcie.pex_clk);
-       return clk_enable(tegra_pcie.pll_e);
+       clk_prepare_enable(tegra_pcie.afi_clk);
+       clk_prepare_enable(tegra_pcie.pex_clk);
+       return clk_prepare_enable(tegra_pcie.pll_e);
 }
 
 static int tegra_pcie_clocks_get(void)
index f5b12fb4ff12306563fd5da0152230424118a843..15d506501cccbb64dc25e5a1178bd91d40e94901 100644 (file)
@@ -146,7 +146,7 @@ int tegra_powergate_sequence_power_up(int id, struct clk *clk)
        if (ret)
                goto err_power;
 
-       ret = clk_enable(clk);
+       ret = clk_prepare_enable(clk);
        if (ret)
                goto err_clk;
 
@@ -162,7 +162,7 @@ int tegra_powergate_sequence_power_up(int id, struct clk *clk)
        return 0;
 
 err_clamp:
-       clk_disable(clk);
+       clk_disable_unprepare(clk);
 err_clk:
        tegra_powergate_power_off(id);
 err_power:
index 5b20197bae7ffbe334c2f7f1ca6bf3167006832c..d29b156a801123b8d0bdbc60045a89ab06a948b2 100644 (file)
        movw    \reg, #:lower16:\val
        movt    \reg, #:upper16:\val
 .endm
-
-/*
- * tegra_cpu_wfi
- *
- * puts current CPU in clock-gated wfi using the flow controller
- *
- * corrupts r0-r3
- * must be called with MMU on
- */
-
-ENTRY(tegra_cpu_wfi)
-       cpu_id  r0
-       cpu_to_halt_reg r1, r0
-       cpu_to_csr_reg r2, r0
-       mov32   r0, TEGRA_FLOW_CTRL_VIRT
-       mov     r3, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
-       str     r3, [r0, r2]    @ clear event & interrupt status
-       mov     r3, #FLOW_CTRL_WAIT_FOR_INTERRUPT | FLOW_CTRL_JTAG_RESUME
-       str     r3, [r0, r1]    @ put flow controller in wait irq mode
-       dsb
-       wfi
-       mov     r3, #0
-       str     r3, [r0, r1]    @ clear flow controller halt status
-       mov     r3, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
-       str     r3, [r0, r2]    @ clear event & interrupt status
-       dsb
-       mov     pc, lr
-ENDPROC(tegra_cpu_wfi)
-
index b59315ce3691c8c73fefdccd9e91328b14d07dab..a703844b20612c5231fa580bbf3681fb1640c1fb 100644 (file)
@@ -69,6 +69,8 @@
 
 #define PERIPH_CLK_SOURCE_MASK         (3<<30)
 #define PERIPH_CLK_SOURCE_SHIFT                30
+#define PERIPH_CLK_SOURCE_PWM_MASK     (7<<28)
+#define PERIPH_CLK_SOURCE_PWM_SHIFT    28
 #define PERIPH_CLK_SOURCE_ENABLE       (1<<28)
 #define PERIPH_CLK_SOURCE_DIVU71_MASK  0xFF
 #define PERIPH_CLK_SOURCE_DIVU16_MASK  0xFFFF
@@ -908,9 +910,20 @@ static void tegra2_periph_clk_init(struct clk *c)
        u32 val = clk_readl(c->reg);
        const struct clk_mux_sel *mux = NULL;
        const struct clk_mux_sel *sel;
+       u32 shift;
+       u32 mask;
+
+       if (c->flags & MUX_PWM) {
+               shift = PERIPH_CLK_SOURCE_PWM_SHIFT;
+               mask = PERIPH_CLK_SOURCE_PWM_MASK;
+       } else {
+               shift = PERIPH_CLK_SOURCE_SHIFT;
+               mask = PERIPH_CLK_SOURCE_MASK;
+       }
+
        if (c->flags & MUX) {
                for (sel = c->inputs; sel->input != NULL; sel++) {
-                       if (val >> PERIPH_CLK_SOURCE_SHIFT == sel->value)
+                       if ((val & mask) >> shift == sel->value)
                                mux = sel;
                }
                BUG_ON(!mux);
@@ -1023,12 +1036,23 @@ static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p)
 {
        u32 val;
        const struct clk_mux_sel *sel;
+       u32 mask, shift;
+
        pr_debug("%s: %s %s\n", __func__, c->name, p->name);
+
+       if (c->flags & MUX_PWM) {
+               shift = PERIPH_CLK_SOURCE_PWM_SHIFT;
+               mask = PERIPH_CLK_SOURCE_PWM_MASK;
+       } else {
+               shift = PERIPH_CLK_SOURCE_SHIFT;
+               mask = PERIPH_CLK_SOURCE_MASK;
+       }
+
        for (sel = c->inputs; sel->input != NULL; sel++) {
                if (sel->input == p) {
                        val = clk_readl(c->reg);
-                       val &= ~PERIPH_CLK_SOURCE_MASK;
-                       val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT;
+                       val &= ~mask;
+                       val |= (sel->value) << shift;
 
                        if (c->refcnt)
                                clk_enable(p);
@@ -2149,14 +2173,14 @@ static struct clk tegra_clk_emc = {
        }
 
 static struct clk tegra_list_clks[] = {
-       PERIPH_CLK("apbdma",    "tegra-dma",            NULL,   34,     0,      108000000, mux_pclk,                    0),
+       PERIPH_CLK("apbdma",    "tegra-apbdma",         NULL,   34,     0,      108000000, mux_pclk,                    0),
        PERIPH_CLK("rtc",       "rtc-tegra",            NULL,   4,      0,      32768,     mux_clk_32k,                 PERIPH_NO_RESET),
        PERIPH_CLK("timer",     "timer",                NULL,   5,      0,      26000000,  mux_clk_m,                   0),
        PERIPH_CLK("i2s1",      "tegra20-i2s.0",        NULL,   11,     0x100,  26000000,  mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
        PERIPH_CLK("i2s2",      "tegra20-i2s.1",        NULL,   18,     0x104,  26000000,  mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
        PERIPH_CLK("spdif_out", "spdif_out",            NULL,   10,     0x108,  100000000, mux_pllaout0_audio2x_pllp_clkm,      MUX | DIV_U71),
        PERIPH_CLK("spdif_in",  "spdif_in",             NULL,   10,     0x10c,  100000000, mux_pllp_pllc_pllm,          MUX | DIV_U71),
-       PERIPH_CLK("pwm",       "pwm",                  NULL,   17,     0x110,  432000000, mux_pllp_pllc_audio_clkm_clk32,      MUX | DIV_U71),
+       PERIPH_CLK("pwm",       "tegra-pwm",            NULL,   17,     0x110,  432000000, mux_pllp_pllc_audio_clkm_clk32,      MUX | DIV_U71 | MUX_PWM),
        PERIPH_CLK("spi",       "spi",                  NULL,   43,     0x114,  40000000,  mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
        PERIPH_CLK("xio",       "xio",                  NULL,   45,     0x120,  150000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
        PERIPH_CLK("twc",       "twc",                  NULL,   16,     0x12c,  150000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71),
@@ -2189,11 +2213,11 @@ static struct clk tegra_list_clks[] = {
        PERIPH_CLK("i2c2_i2c",  "tegra-i2c.1",          "i2c",  0,      0,      72000000,  mux_pllp_out3,                       0),
        PERIPH_CLK("i2c3_i2c",  "tegra-i2c.2",          "i2c",  0,      0,      72000000,  mux_pllp_out3,                       0),
        PERIPH_CLK("dvc_i2c",   "tegra-i2c.3",          "i2c",  0,      0,      72000000,  mux_pllp_out3,                       0),
-       PERIPH_CLK("uarta",     "uart.0",               NULL,   6,      0x178,  600000000, mux_pllp_pllc_pllm_clkm,     MUX),
-       PERIPH_CLK("uartb",     "uart.1",               NULL,   7,      0x17c,  600000000, mux_pllp_pllc_pllm_clkm,     MUX),
-       PERIPH_CLK("uartc",     "uart.2",               NULL,   55,     0x1a0,  600000000, mux_pllp_pllc_pllm_clkm,     MUX),
-       PERIPH_CLK("uartd",     "uart.3",               NULL,   65,     0x1c0,  600000000, mux_pllp_pllc_pllm_clkm,     MUX),
-       PERIPH_CLK("uarte",     "uart.4",               NULL,   66,     0x1c4,  600000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("uarta",     "tegra-uart.0",         NULL,   6,      0x178,  600000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("uartb",     "tegra-uart.1",         NULL,   7,      0x17c,  600000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("uartc",     "tegra-uart.2",         NULL,   55,     0x1a0,  600000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("uartd",     "tegra-uart.3",         NULL,   65,     0x1c0,  600000000, mux_pllp_pllc_pllm_clkm,     MUX),
+       PERIPH_CLK("uarte",     "tegra-uart.4",         NULL,   66,     0x1c4,  600000000, mux_pllp_pllc_pllm_clkm,     MUX),
        PERIPH_CLK("3d",        "3d",                   NULL,   24,     0x158,  300000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */
        PERIPH_CLK("2d",        "2d",                   NULL,   21,     0x15c,  300000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
        PERIPH_CLK("vi",        "tegra_camera",         "vi",   20,     0x148,  150000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71), /* scales with voltage and process_id */
@@ -2245,20 +2269,16 @@ static struct clk tegra_list_clks[] = {
  * table under two names.
  */
 static struct clk_duplicate tegra_clk_duplicates[] = {
-       CLK_DUPLICATE("uarta",  "tegra_uart.0", NULL),
-       CLK_DUPLICATE("uartb",  "tegra_uart.1", NULL),
-       CLK_DUPLICATE("uartc",  "tegra_uart.2", NULL),
-       CLK_DUPLICATE("uartd",  "tegra_uart.3", NULL),
-       CLK_DUPLICATE("uarte",  "tegra_uart.4", NULL),
+       CLK_DUPLICATE("uarta",  "serial8250.0", NULL),
+       CLK_DUPLICATE("uartb",  "serial8250.1", NULL),
+       CLK_DUPLICATE("uartc",  "serial8250.2", NULL),
+       CLK_DUPLICATE("uartd",  "serial8250.3", NULL),
+       CLK_DUPLICATE("uarte",  "serial8250.4", NULL),
        CLK_DUPLICATE("usbd", "utmip-pad", NULL),
        CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
        CLK_DUPLICATE("usbd", "tegra-otg", NULL),
        CLK_DUPLICATE("hdmi", "tegradc.0", "hdmi"),
        CLK_DUPLICATE("hdmi", "tegradc.1", "hdmi"),
-       CLK_DUPLICATE("pwm", "tegra_pwm.0", NULL),
-       CLK_DUPLICATE("pwm", "tegra_pwm.1", NULL),
-       CLK_DUPLICATE("pwm", "tegra_pwm.2", NULL),
-       CLK_DUPLICATE("pwm", "tegra_pwm.3", NULL),
        CLK_DUPLICATE("host1x", "tegra_grhost", "host1x"),
        CLK_DUPLICATE("2d", "tegra_grhost", "gr2d"),
        CLK_DUPLICATE("3d", "tegra_grhost", "gr3d"),
index e33fe4b14a2a5ab86f674c1848320740448bfa6c..6674f100e16f8076e804a508a488e6c5e36a8a9b 100644 (file)
@@ -2871,7 +2871,7 @@ static struct clk tegra30_clk_twd = {
                },                                      \
        }
 struct clk tegra_list_clks[] = {
-       PERIPH_CLK("apbdma",    "tegra-dma",            NULL,   34,     0,      26000000,  mux_clk_m,                   0),
+       PERIPH_CLK("apbdma",    "tegra-apbdma",         NULL,   34,     0,      26000000,  mux_clk_m,                   0),
        PERIPH_CLK("rtc",       "rtc-tegra",            NULL,   4,      0,      32768,     mux_clk_32k,                 PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("kbc",       "tegra-kbc",            NULL,   36,     0,      32768,     mux_clk_32k,                 PERIPH_NO_RESET | PERIPH_ON_APB),
        PERIPH_CLK("timer",     "timer",                NULL,   5,      0,      26000000,  mux_clk_m,                   0),
@@ -2886,7 +2886,7 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("i2s4",      "tegra30-i2s.4",        NULL,   102,    0x3c0,  26000000,  mux_pllaout0_audio4_2x_pllp_clkm,    MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("spdif_out", "tegra30-spdif",        "spdif_out",    10,     0x108,  100000000, mux_pllaout0_audio_2x_pllp_clkm,     MUX | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("spdif_in",  "tegra30-spdif",        "spdif_in",     10,     0x10c,  100000000, mux_pllp_pllc_pllm,          MUX | DIV_U71 | PERIPH_ON_APB),
-       PERIPH_CLK("pwm",       "pwm",                  NULL,   17,     0x110,  432000000, mux_pllp_pllc_clk32_clkm,    MUX | MUX_PWM | DIV_U71 | PERIPH_ON_APB),
+       PERIPH_CLK("pwm",       "tegra-pwm",            NULL,   17,     0x110,  432000000, mux_pllp_pllc_clk32_clkm,    MUX | MUX_PWM | DIV_U71 | PERIPH_ON_APB),
        PERIPH_CLK("d_audio",   "tegra30-ahub",         "d_audio", 106, 0x3d0,  48000000,  mux_plla_pllc_pllp_clkm,     MUX | DIV_U71),
        PERIPH_CLK("dam0",      "tegra30-dam.0",        NULL,   108,    0x3d8,  48000000,  mux_plla_pllc_pllp_clkm,     MUX | DIV_U71),
        PERIPH_CLK("dam1",      "tegra30-dam.1",        NULL,   109,    0x3dc,  48000000,  mux_plla_pllc_pllp_clkm,     MUX | DIV_U71),
@@ -2924,16 +2924,11 @@ struct clk tegra_list_clks[] = {
        PERIPH_CLK("i2c3",      "tegra-i2c.2",          NULL,   67,     0x1b8,  26000000,  mux_pllp_clkm,               MUX | DIV_U16 | PERIPH_ON_APB),
        PERIPH_CLK("i2c4",      "tegra-i2c.3",          NULL,   103,    0x3c4,  26000000,  mux_pllp_clkm,               MUX | DIV_U16 | PERIPH_ON_APB),
        PERIPH_CLK("i2c5",      "tegra-i2c.4",          NULL,   47,     0x128,  26000000,  mux_pllp_clkm,               MUX | DIV_U16 | PERIPH_ON_APB),
-       PERIPH_CLK("uarta",     "tegra_uart.0",         NULL,   6,      0x178,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
-       PERIPH_CLK("uartb",     "tegra_uart.1",         NULL,   7,      0x17c,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
-       PERIPH_CLK("uartc",     "tegra_uart.2",         NULL,   55,     0x1a0,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
-       PERIPH_CLK("uartd",     "tegra_uart.3",         NULL,   65,     0x1c0,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
-       PERIPH_CLK("uarte",     "tegra_uart.4",         NULL,   66,     0x1c4,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
-       PERIPH_CLK("uarta_dbg", "serial8250.0",         "uarta", 6,     0x178,  800000000, mux_pllp_clkm,               MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
-       PERIPH_CLK("uartb_dbg", "serial8250.0",         "uartb", 7,     0x17c,  800000000, mux_pllp_clkm,               MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
-       PERIPH_CLK("uartc_dbg", "serial8250.0",         "uartc", 55,    0x1a0,  800000000, mux_pllp_clkm,               MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
-       PERIPH_CLK("uartd_dbg", "serial8250.0",         "uartd", 65,    0x1c0,  800000000, mux_pllp_clkm,               MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
-       PERIPH_CLK("uarte_dbg", "serial8250.0",         "uarte", 66,    0x1c4,  800000000, mux_pllp_clkm,               MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uarta",     "tegra-uart.0",         NULL,   6,      0x178,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uartb",     "tegra-uart.1",         NULL,   7,      0x17c,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uartc",     "tegra-uart.2",         NULL,   55,     0x1a0,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uartd",     "tegra-uart.3",         NULL,   65,     0x1c0,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
+       PERIPH_CLK("uarte",     "tegra-uart.4",         NULL,   66,     0x1c4,  800000000, mux_pllp_pllc_pllm_clkm,     MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB),
        PERIPH_CLK_EX("vi",     "tegra_camera",         "vi",   20,     0x148,  425000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | DIV_U71_INT,    &tegra_vi_clk_ops),
        PERIPH_CLK("3d",        "3d",                   NULL,   24,     0x158,  520000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET),
        PERIPH_CLK("3d2",       "3d2",                  NULL,   98,     0x3b0,  520000000, mux_pllm_pllc_pllp_plla,     MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET),
@@ -2983,6 +2978,11 @@ struct clk tegra_list_clks[] = {
  * table under two names.
  */
 struct clk_duplicate tegra_clk_duplicates[] = {
+       CLK_DUPLICATE("uarta",  "serial8250.0", NULL),
+       CLK_DUPLICATE("uartb",  "serial8250.1", NULL),
+       CLK_DUPLICATE("uartc",  "serial8250.2", NULL),
+       CLK_DUPLICATE("uartd",  "serial8250.3", NULL),
+       CLK_DUPLICATE("uarte",  "serial8250.4", NULL),
        CLK_DUPLICATE("usbd", "utmip-pad", NULL),
        CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
        CLK_DUPLICATE("usbd", "tegra-otg", NULL),
@@ -2990,10 +2990,6 @@ struct clk_duplicate tegra_clk_duplicates[] = {
        CLK_DUPLICATE("hdmi", "tegradc.1", "hdmi"),
        CLK_DUPLICATE("dsib", "tegradc.0", "dsib"),
        CLK_DUPLICATE("dsia", "tegradc.1", "dsia"),
-       CLK_DUPLICATE("pwm", "tegra_pwm.0", NULL),
-       CLK_DUPLICATE("pwm", "tegra_pwm.1", NULL),
-       CLK_DUPLICATE("pwm", "tegra_pwm.2", NULL),
-       CLK_DUPLICATE("pwm", "tegra_pwm.3", NULL),
        CLK_DUPLICATE("bsev", "tegra-avp", "bsev"),
        CLK_DUPLICATE("bsev", "nvavp", "bsev"),
        CLK_DUPLICATE("vde", "tegra-aes", "vde"),
index 315672c7bd48f09e4c684fdb048cafde0857ab2c..57b5bdc13b9b9525b227e05e85907d508e2617c5 100644 (file)
@@ -189,7 +189,7 @@ static void __init tegra_init_timer(void)
                        " Assuming 12Mhz input clock.\n");
                rate = 12000000;
        } else {
-               clk_enable(clk);
+               clk_prepare_enable(clk);
                rate = clk_get_rate(clk);
        }
 
@@ -201,7 +201,7 @@ static void __init tegra_init_timer(void)
        if (IS_ERR(clk))
                pr_warn("Unable to get rtc-tegra clock\n");
        else
-               clk_enable(clk);
+               clk_prepare_enable(clk);
 
        switch (rate) {
        case 12000000:
index 54e353c8e3042f61e7c487c16f1cd29d22758fb6..022b33a05c3a22f8586d835271d26508abbdbab4 100644 (file)
@@ -247,7 +247,7 @@ static void utmip_pad_power_on(struct tegra_usb_phy *phy)
        unsigned long val, flags;
        void __iomem *base = phy->pad_regs;
 
-       clk_enable(phy->pad_clk);
+       clk_prepare_enable(phy->pad_clk);
 
        spin_lock_irqsave(&utmip_pad_lock, flags);
 
@@ -259,7 +259,7 @@ static void utmip_pad_power_on(struct tegra_usb_phy *phy)
 
        spin_unlock_irqrestore(&utmip_pad_lock, flags);
 
-       clk_disable(phy->pad_clk);
+       clk_disable_unprepare(phy->pad_clk);
 }
 
 static int utmip_pad_power_off(struct tegra_usb_phy *phy)
@@ -272,7 +272,7 @@ static int utmip_pad_power_off(struct tegra_usb_phy *phy)
                return -EINVAL;
        }
 
-       clk_enable(phy->pad_clk);
+       clk_prepare_enable(phy->pad_clk);
 
        spin_lock_irqsave(&utmip_pad_lock, flags);
 
@@ -284,7 +284,7 @@ static int utmip_pad_power_off(struct tegra_usb_phy *phy)
 
        spin_unlock_irqrestore(&utmip_pad_lock, flags);
 
-       clk_disable(phy->pad_clk);
+       clk_disable_unprepare(phy->pad_clk);
 
        return 0;
 }
@@ -580,7 +580,7 @@ static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
        msleep(5);
        gpio_direction_output(config->reset_gpio, 1);
 
-       clk_enable(phy->clk);
+       clk_prepare_enable(phy->clk);
        msleep(1);
 
        val = readl(base + USB_SUSP_CTRL);
@@ -689,7 +689,7 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
                err = PTR_ERR(phy->pll_u);
                goto err0;
        }
-       clk_enable(phy->pll_u);
+       clk_prepare_enable(phy->pll_u);
 
        parent_rate = clk_get_rate(clk_get_parent(phy->pll_u));
        for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) {
@@ -735,7 +735,7 @@ struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
        return phy;
 
 err1:
-       clk_disable(phy->pll_u);
+       clk_disable_unprepare(phy->pll_u);
        clk_put(phy->pll_u);
 err0:
        kfree(phy);
@@ -810,7 +810,7 @@ void tegra_usb_phy_close(struct tegra_usb_phy *phy)
                clk_put(phy->clk);
        else
                utmip_pad_close(phy);
-       clk_disable(phy->pll_u);
+       clk_disable_unprepare(phy->pll_u);
        clk_put(phy->pll_u);
        kfree(phy);
 }
index 53d3d46dec1290b4265a3c3c26d7ffc0449f223e..c013bbf79cac0d0eff64edfd5221d7815bb04879 100644 (file)
@@ -41,6 +41,7 @@ config MACH_HREFV60
 config MACH_SNOWBALL
        bool "U8500 Snowball platform"
        select MACH_MOP500
+       select LEDS_GPIO
        help
          Include support for the snowball development platform.
 
index 920251cf834cd8859900417cd106d9af7e83a210..18ff781cfbe41a748e4765915292f62f7781540c 100644 (file)
@@ -80,7 +80,7 @@ static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
 };
 #endif
 
-static struct mmci_platform_data mop500_sdi0_data = {
+struct mmci_platform_data mop500_sdi0_data = {
        .ios_handler    = mop500_sdi0_ios_handler,
        .ocr_mask       = MMC_VDD_29_30,
        .f_max          = 50000000,
@@ -227,7 +227,7 @@ static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
 };
 #endif
 
-static struct mmci_platform_data mop500_sdi4_data = {
+struct mmci_platform_data mop500_sdi4_data = {
        .ocr_mask       = MMC_VDD_29_30,
        .f_max          = 50000000,
        .capabilities   = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA |
index 4fd93f5c49ec359f6889f054fe33cd076c7bf822..84461fa2a3ba3d44095797ae4899e669afce83bc 100644 (file)
@@ -58,7 +58,7 @@
 static struct gpio_led snowball_led_array[] = {
        {
                .name = "user_led",
-               .default_trigger = "none",
+               .default_trigger = "heartbeat",
                .gpio = 142,
        },
 };
@@ -331,43 +331,12 @@ static struct i2c_board_info __initdata mop500_i2c2_devices[] = {
        },
 };
 
-#define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, t_out, _sm)   \
-static struct nmk_i2c_controller u8500_i2c##id##_data = { \
-       /*                              \
-        * slave data setup time, which is      \
-        * 250 ns,100ns,10ns which is 14,6,2    \
-        * respectively for a 48 Mhz    \
-        * i2c clock                    \
-        */                             \
-       .slsu           = _slsu,        \
-       /* Tx FIFO threshold */         \
-       .tft            = _tft,         \
-       /* Rx FIFO threshold */         \
-       .rft            = _rft,         \
-       /* std. mode operation */       \
-       .clk_freq       = clk,          \
-       /* Slave response timeout(ms) */\
-       .timeout        = t_out,        \
-       .sm             = _sm,          \
-}
-
-/*
- * The board uses 4 i2c controllers, initialize all of
- * them with slave data setup time of 250 ns,
- * Tx & Rx FIFO threshold values as 8 and standard
- * mode of operation
- */
-U8500_I2C_CONTROLLER(0, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST);
-U8500_I2C_CONTROLLER(1, 0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST);
-U8500_I2C_CONTROLLER(2,        0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST);
-U8500_I2C_CONTROLLER(3,        0xe, 1, 8, 100000, 200, I2C_FREQ_MODE_FAST);
-
 static void __init mop500_i2c_init(struct device *parent)
 {
-       db8500_add_i2c0(parent, &u8500_i2c0_data);
-       db8500_add_i2c1(parent, &u8500_i2c1_data);
-       db8500_add_i2c2(parent, &u8500_i2c2_data);
-       db8500_add_i2c3(parent, &u8500_i2c3_data);
+       db8500_add_i2c0(parent, NULL);
+       db8500_add_i2c1(parent, NULL);
+       db8500_add_i2c2(parent, NULL);
+       db8500_add_i2c3(parent, NULL);
 }
 
 static struct gpio_keys_button mop500_gpio_keys[] = {
@@ -776,6 +745,8 @@ struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("arm,pl011", 0x80007000, "uart2", &uart2_plat),
        /* Requires DMA bindings. */
        OF_DEV_AUXDATA("arm,pl022", 0x80002000, "ssp0",  &ssp0_plat),
+       OF_DEV_AUXDATA("arm,pl18x", 0x80126000, "sdi0",  &mop500_sdi0_data),
+       OF_DEV_AUXDATA("arm,pl18x", 0x80114000, "sdi4",  &mop500_sdi4_data),
        /* Requires clock name bindings. */
        OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e000, "gpio.0", NULL),
        OF_DEV_AUXDATA("st,nomadik-gpio", 0x8012e080, "gpio.1", NULL),
@@ -786,6 +757,11 @@ struct of_dev_auxdata u8500_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("st,nomadik-gpio", 0x8011e000, "gpio.6", NULL),
        OF_DEV_AUXDATA("st,nomadik-gpio", 0x8011e080, "gpio.7", NULL),
        OF_DEV_AUXDATA("st,nomadik-gpio", 0xa03fe000, "gpio.8", NULL),
+       OF_DEV_AUXDATA("st,nomadik-i2c", 0x80004000, "nmk-i2c.0", NULL),
+       OF_DEV_AUXDATA("st,nomadik-i2c", 0x80122000, "nmk-i2c.1", NULL),
+       OF_DEV_AUXDATA("st,nomadik-i2c", 0x80128000, "nmk-i2c.2", NULL),
+       OF_DEV_AUXDATA("st,nomadik-i2c", 0x80110000, "nmk-i2c.3", NULL),
+       OF_DEV_AUXDATA("st,nomadik-i2c", 0x8012a000, "nmk-i2c.4", NULL),
        /* Requires device name bindings. */
        OF_DEV_AUXDATA("stericsson,nmk_pinctrl", 0, "pinctrl-db8500", NULL),
        {},
@@ -820,8 +796,6 @@ static void __init u8500_init_machine(void)
 
        for (i = 0; i < ARRAY_SIZE(mop500_platform_devs); i++)
                mop500_platform_devs[i]->dev.parent = parent;
-       for (i = 0; i < ARRAY_SIZE(snowball_platform_devs); i++)
-               snowball_platform_devs[i]->dev.parent = parent;
 
        /* automatically probe child nodes of db8500 device */
        of_platform_populate(NULL, u8500_local_bus_nodes, u8500_auxdata_lookup, parent);
@@ -840,18 +814,6 @@ static void __init u8500_init_machine(void)
 
                mop500_uib_init();
 
-       } else if (of_machine_is_compatible("calaosystems,snowball-a9500")) {
-               /*
-                * Devices to be DT:ed:
-                *   snowball_led_dev   = todo
-                *   snowball_key_dev   = todo
-                *   snowball_sbnet_dev = done
-                *   ab8500_device      = done
-                */
-               platform_add_devices(snowball_of_platform_devs,
-                               ARRAY_SIZE(snowball_of_platform_devs));
-
-               snowball_sdi_init(parent);
        } else if (of_machine_is_compatible("st-ericsson,hrefv60+")) {
                /*
                 * The HREFv60 board removed a GPIO expander and routed
@@ -873,7 +835,6 @@ static void __init u8500_init_machine(void)
 
                mop500_uib_init();
        }
-       mop500_i2c_init(parent);
 
        /* This board has full regulator constraints */
        regulator_has_full_constraints();
index 2f87b25a908a31c74264ac0b7a29eb34f85f2c58..b5bfc1a78b1adb0313dd96ff301f7a10f8a842c3 100644 (file)
@@ -9,6 +9,7 @@
 
 /* For NOMADIK_NR_GPIO */
 #include <mach/irqs.h>
+#include <linux/amba/mmci.h>
 
 /* Snowball specific GPIO assignments, this board has no GPIO expander */
 #define SNOWBALL_ACCEL_INT1_GPIO       163
@@ -78,6 +79,8 @@
 
 struct device;
 struct i2c_board_info;
+extern struct mmci_platform_data mop500_sdi0_data;
+extern struct mmci_platform_data mop500_sdi4_data;
 
 extern void mop500_sdi_init(struct device *parent);
 extern void snowball_sdi_init(struct device *parent);
index 33275eb4c6890ab7745bbf0d2b2601ecca5e413f..c8dd94f606dc2d2db89ebf6a3273167d94773d3c 100644 (file)
@@ -139,7 +139,6 @@ static struct platform_device *platform_devs[] __initdata = {
 
 static struct platform_device *of_platform_devs[] __initdata = {
        &u8500_dma40_device,
-       &db8500_pmu_device,
 };
 
 static resource_size_t __initdata db8500_gpio_base[] = {
@@ -237,7 +236,6 @@ struct device * __init u8500_of_init_devices(void)
 
        parent = db8500_soc_device_init();
 
-       db8500_add_rtc(parent);
        db8500_add_usb(parent, usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
 
        platform_device_register_data(parent,
@@ -249,7 +247,7 @@ struct device * __init u8500_of_init_devices(void)
        /*
         * Devices to be DT:ed:
         *   u8500_dma40_device  = todo
-        *   db8500_pmu_device   = todo
+        *   db8500_pmu_device   = done
         *   db8500_prcmu_device = done
         */
        platform_add_devices(of_platform_devs, ARRAY_SIZE(of_platform_devs));
index cf8730d35e70bec50ff00d3a35aa4942b1d4d042..fc3730f01650efb674f893f4a78d7077ce015429 100644 (file)
@@ -2,7 +2,8 @@ menu "Versatile Express platform type"
        depends on ARCH_VEXPRESS
 
 config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
-       bool
+       bool "Enable A5 and A9 only errata work-arounds"
+       default y
        select ARM_ERRATA_720789
        select ARM_ERRATA_751472
        select PL310_ERRATA_753970 if CACHE_PL310
@@ -14,7 +15,6 @@ config ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
 
 config ARCH_VEXPRESS_CA9X4
        bool "Versatile Express Cortex-A9x4 tile"
-       select ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
        select ARM_GIC
        select CPU_V7
        select HAVE_SMP
@@ -22,7 +22,6 @@ config ARCH_VEXPRESS_CA9X4
 
 config ARCH_VEXPRESS_DT
        bool "Device Tree support for Versatile Express platforms"
-       select ARCH_VEXPRESS_CORTEX_A5_A9_ERRATA
        select ARM_GIC
        select ARM_PATCH_PHYS_VIRT
        select AUTO_ZRELADDR
index 909f85ebf5f4c2871c17bfa82700238c3f613f04..318d308dfb93993488ab2b3519a8f5089c4c70bc 100644 (file)
@@ -6,4 +6,5 @@ initrd_phys-y   := 0x60800000
 
 dtb-$(CONFIG_ARCH_VEXPRESS_DT) += vexpress-v2p-ca5s.dtb \
                                   vexpress-v2p-ca9.dtb \
-                                  vexpress-v2p-ca15-tc1.dtb
+                                  vexpress-v2p-ca15-tc1.dtb \
+                                  vexpress-v2p-ca15_a7.dtb
index c65cc3b462a5ddef5aad8e4421305c8d22104191..61c492403b05f46957787a7836ef12a0eee44695 100644 (file)
@@ -66,8 +66,15 @@ static void __init ct_ca9x4_init_irq(void)
 
 static void ct_ca9x4_clcd_enable(struct clcd_fb *fb)
 {
-       v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0);
-       v2m_cfg_write(SYS_CFG_DVIMODE | SYS_CFG_SITE_DB1, 2);
+       u32 site = v2m_get_master_site();
+
+       /*
+        * Old firmware was using the "site" component of the command
+        * to control the DVI muxer (while it should be always 0 ie. MB).
+        * Newer firmware uses the data register. Keep both for compatibility.
+        */
+       v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE(site), site);
+       v2m_cfg_write(SYS_CFG_DVIMODE | SYS_CFG_SITE(SYS_CFG_SITE_MB), 2);
 }
 
 static int ct_ca9x4_clcd_setup(struct clcd_fb *fb)
@@ -105,43 +112,11 @@ static struct amba_device *ct_ca9x4_amba_devs[] __initdata = {
 };
 
 
-static long ct_round(struct clk *clk, unsigned long rate)
-{
-       return rate;
-}
-
-static int ct_set(struct clk *clk, unsigned long rate)
-{
-       return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_DB1 | 1, rate);
-}
-
-static const struct clk_ops osc1_clk_ops = {
-       .round  = ct_round,
-       .set    = ct_set,
-};
-
-static struct clk osc1_clk = {
-       .ops    = &osc1_clk_ops,
-       .rate   = 24000000,
-};
-
-static struct clk ct_sp804_clk = {
-       .rate   = 1000000,
-};
-
-static struct clk_lookup lookups[] = {
-       {       /* CLCD */
-               .dev_id         = "ct:clcd",
-               .clk            = &osc1_clk,
-       }, {    /* SP804 timers */
-               .dev_id         = "sp804",
-               .con_id         = "ct-timer0",
-               .clk            = &ct_sp804_clk,
-       }, {    /* SP804 timers */
-               .dev_id         = "sp804",
-               .con_id         = "ct-timer1",
-               .clk            = &ct_sp804_clk,
-       },
+static struct v2m_osc ct_osc1 = {
+       .osc = 1,
+       .rate_min = 10000000,
+       .rate_max = 80000000,
+       .rate_default = 23750000,
 };
 
 static struct resource pmu_resources[] = {
@@ -174,14 +149,10 @@ static struct platform_device pmu_device = {
        .resource       = pmu_resources,
 };
 
-static void __init ct_ca9x4_init_early(void)
-{
-       clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-}
-
 static void __init ct_ca9x4_init(void)
 {
        int i;
+       struct clk *clk;
 
 #ifdef CONFIG_CACHE_L2X0
        void __iomem *l2x0_base = ioremap(CT_CA9X4_L2CC, SZ_4K);
@@ -193,6 +164,10 @@ static void __init ct_ca9x4_init(void)
        l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
 #endif
 
+       ct_osc1.site = v2m_get_master_site();
+       clk = v2m_osc_register("ct:osc1", &ct_osc1);
+       clk_register_clkdev(clk, NULL, "ct:clcd");
+
        for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++)
                amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource);
 
@@ -234,7 +209,6 @@ struct ct_desc ct_ca9x4_desc __initdata = {
        .id             = V2M_CT_ID_CA9,
        .name           = "CA9x4",
        .map_io         = ct_ca9x4_map_io,
-       .init_early     = ct_ca9x4_init_early,
        .init_irq       = ct_ca9x4_init_irq,
        .init_tile      = ct_ca9x4_init,
 #ifdef CONFIG_SMP
diff --git a/arch/arm/mach-vexpress/include/mach/clkdev.h b/arch/arm/mach-vexpress/include/mach/clkdev.h
deleted file mode 100644 (file)
index 3f8307d..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __ASM_MACH_CLKDEV_H
-#define __ASM_MACH_CLKDEV_H
-
-#include <plat/clock.h>
-
-struct clk {
-       const struct clk_ops    *ops;
-       unsigned long           rate;
-       const struct icst_params *params;
-};
-
-#define __clk_get(clk) ({ 1; })
-#define __clk_put(clk) do { } while (0)
-
-#endif
index fa8224794e0b75c6a6139d92f0102f5d79d6d829..9f509f55d078c90fb822cad9b44087090f5d2a56 100644 (file)
@@ -18,6 +18,8 @@
 
 #define DEBUG_LL_VIRT_BASE             0xf8000000
 
+#if defined(CONFIG_DEBUG_VEXPRESS_UART0_DETECT)
+
                .macro  addruart,rp,rv,tmp
 
                @ Make an educated guess regarding the memory map:
                .endm
 
 #include <asm/hardware/debug-pl01x.S>
+
+#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_CA9)
+
+               .macro  addruart,rp,rv,tmp
+               mov     \rp, #DEBUG_LL_UART_OFFSET
+               orr     \rv, \rp, #DEBUG_LL_VIRT_BASE
+               orr     \rp, \rp, #DEBUG_LL_PHYS_BASE
+               .endm
+
+#include <asm/hardware/debug-pl01x.S>
+
+#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_RS1)
+
+               .macro  addruart,rp,rv,tmp
+               mov     \rp, #DEBUG_LL_UART_OFFSET_RS1
+               orr     \rv, \rp, #DEBUG_LL_VIRT_BASE
+               orr     \rp, \rp, #DEBUG_LL_PHYS_BASE_RS1
+               .endm
+
+#include <asm/hardware/debug-pl01x.S>
+
+#else /* CONFIG_DEBUG_LL_UART_NONE */
+
+               .macro  addruart, rp, rv, tmp
+               /* Safe dummy values */
+               mov     \rp, #0
+               mov     \rv, #DEBUG_LL_VIRT_BASE
+               .endm
+
+               .macro  senduart,rd,rx
+               .endm
+
+               .macro  waituart,rd,rx
+               .endm
+
+               .macro  busyuart,rd,rx
+               .endm
+
+#endif
index 31a92890893d79385dae0e72ed1a097f8e0f637d..1e388c7bf4d72496dc4d586062d3f8c82753cd5a 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef __MACH_MOTHERBOARD_H
 #define __MACH_MOTHERBOARD_H
 
+#include <linux/clk-provider.h>
+
 /*
  * Physical addresses, offset from V2M_PA_CS0-3
  */
 #define SYS_CFG_REBOOT         (9 << 20)
 #define SYS_CFG_DVIMODE                (11 << 20)
 #define SYS_CFG_POWER          (12 << 20)
-#define SYS_CFG_SITE_MB                (0 << 16)
-#define SYS_CFG_SITE_DB1       (1 << 16)
-#define SYS_CFG_SITE_DB2       (2 << 16)
+#define SYS_CFG_SITE(n)                ((n) << 16)
+#define SYS_CFG_SITE_MB                0
+#define SYS_CFG_SITE_DB1       1
+#define SYS_CFG_SITE_DB2       2
 #define SYS_CFG_STACK(n)       ((n) << 12)
 
 #define SYS_CFG_ERR            (1 << 1)
@@ -122,6 +125,8 @@ void v2m_flags_set(u32 data);
 #define SYS_MISC_MASTERSITE    (1 << 14)
 #define SYS_PROCIDx_HBI_MASK   0xfff
 
+int v2m_get_master_site(void);
+
 /*
  * Core tile IDs
  */
@@ -144,4 +149,21 @@ struct ct_desc {
 
 extern struct ct_desc *ct_desc;
 
+/*
+ * OSC clock provider
+ */
+struct v2m_osc {
+       struct clk_hw hw;
+       u8 site; /* 0 = motherboard, 1 = site 1, 2 = site 2 */
+       u8 stack; /* board stack position */
+       u16 osc;
+       unsigned long rate_min;
+       unsigned long rate_max;
+       unsigned long rate_default;
+};
+
+#define to_v2m_osc(osc) container_of(osc, struct v2m_osc, hw)
+
+struct clk *v2m_osc_register(const char *name, struct v2m_osc *osc);
+
 #endif
index 7dab5596b86831936e59053207c9721c7dabbdd1..1e472eb0bbdcc907f725fbba1e13e6f38a43c6f8 100644 (file)
@@ -27,6 +27,7 @@
 
 static unsigned long get_uart_base(void)
 {
+#if defined(CONFIG_DEBUG_VEXPRESS_UART0_DETECT)
        unsigned long mpcore_periph;
 
        /*
@@ -42,6 +43,13 @@ static unsigned long get_uart_base(void)
                return UART_BASE;
        else
                return UART_BASE_RS1;
+#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_CA9)
+       return UART_BASE;
+#elif defined(CONFIG_DEBUG_VEXPRESS_UART0_RS1)
+       return UART_BASE_RS1;
+#else
+       return 0;
+#endif
 }
 
 /*
@@ -51,6 +59,9 @@ static inline void putc(int c)
 {
        unsigned long base = get_uart_base();
 
+       if (!base)
+               return;
+
        while (AMBA_UART_FR(base) & (1 << 5))
                barrier();
 
@@ -61,6 +72,9 @@ static inline void flush(void)
 {
        unsigned long base = get_uart_base();
 
+       if (!base)
+               return;
+
        while (AMBA_UART_FR(base) & (1 << 3))
                barrier();
 }
index fde26adaef32d964a539a12a97f4596af27b1fe1..37608f22ee318a903a79d33ad97678ce71244f23 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/usb/isp1760.h>
 #include <linux/clkdev.h>
+#include <linux/clk-provider.h>
 #include <linux/mtd/physmap.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/machine.h>
 
 #include <asm/arch_timer.h>
 #include <asm/mach-types.h>
@@ -81,16 +84,6 @@ static void __init v2m_sp804_init(void __iomem *base, unsigned int irq)
        sp804_clockevents_init(base + TIMER_1_BASE, irq, "v2m-timer0");
 }
 
-static void __init v2m_timer_init(void)
-{
-       v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K));
-       v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
-}
-
-static struct sys_timer v2m_timer = {
-       .init   = v2m_timer_init,
-};
-
 
 static DEFINE_SPINLOCK(v2m_cfg_lock);
 
@@ -147,6 +140,13 @@ void __init v2m_flags_set(u32 data)
        writel(data, v2m_sysreg_base + V2M_SYS_FLAGSSET);
 }
 
+int v2m_get_master_site(void)
+{
+       u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC);
+
+       return misc & SYS_MISC_MASTERSITE ? SYS_CFG_SITE_DB2 : SYS_CFG_SITE_DB1;
+}
+
 
 static struct resource v2m_pcie_i2c_resource = {
        .start  = V2M_SERIAL_BUS_PCI,
@@ -201,6 +201,11 @@ static struct platform_device v2m_eth_device = {
        .dev.platform_data = &v2m_eth_config,
 };
 
+static struct regulator_consumer_supply v2m_eth_supplies[] = {
+       REGULATOR_SUPPLY("vddvario", "smsc911x"),
+       REGULATOR_SUPPLY("vdd33a", "smsc911x"),
+};
+
 static struct resource v2m_usb_resources[] = {
        {
                .start  = V2M_ISP1761,
@@ -319,98 +324,145 @@ static struct amba_device *v2m_amba_devs[] __initdata = {
 };
 
 
-static long v2m_osc_round(struct clk *clk, unsigned long rate)
+static unsigned long v2m_osc_recalc_rate(struct clk_hw *hw,
+               unsigned long parent_rate)
+{
+       struct v2m_osc *osc = to_v2m_osc(hw);
+
+       return !parent_rate ? osc->rate_default : parent_rate;
+}
+
+static long v2m_osc_round_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long *parent_rate)
 {
+       struct v2m_osc *osc = to_v2m_osc(hw);
+
+       if (WARN_ON(rate < osc->rate_min))
+               rate = osc->rate_min;
+
+       if (WARN_ON(rate > osc->rate_max))
+               rate = osc->rate_max;
+
        return rate;
 }
 
-static int v2m_osc1_set(struct clk *clk, unsigned long rate)
+static int v2m_osc_set_rate(struct clk_hw *hw, unsigned long rate,
+               unsigned long parent_rate)
 {
-       return v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE_MB | 1, rate);
+       struct v2m_osc *osc = to_v2m_osc(hw);
+
+       v2m_cfg_write(SYS_CFG_OSC | SYS_CFG_SITE(osc->site) |
+                       SYS_CFG_STACK(osc->stack) | osc->osc, rate);
+
+       return 0;
 }
 
-static const struct clk_ops osc1_clk_ops = {
-       .round  = v2m_osc_round,
-       .set    = v2m_osc1_set,
-};
-
-static struct clk osc1_clk = {
-       .ops    = &osc1_clk_ops,
-       .rate   = 24000000,
-};
-
-static struct clk osc2_clk = {
-       .rate   = 24000000,
-};
-
-static struct clk v2m_sp804_clk = {
-       .rate   = 1000000,
-};
-
-static struct clk v2m_ref_clk = {
-       .rate   = 32768,
-};
-
-static struct clk dummy_apb_pclk;
-
-static struct clk_lookup v2m_lookups[] = {
-       {       /* AMBA bus clock */
-               .con_id         = "apb_pclk",
-               .clk            = &dummy_apb_pclk,
-       }, {    /* UART0 */
-               .dev_id         = "mb:uart0",
-               .clk            = &osc2_clk,
-       }, {    /* UART1 */
-               .dev_id         = "mb:uart1",
-               .clk            = &osc2_clk,
-       }, {    /* UART2 */
-               .dev_id         = "mb:uart2",
-               .clk            = &osc2_clk,
-       }, {    /* UART3 */
-               .dev_id         = "mb:uart3",
-               .clk            = &osc2_clk,
-       }, {    /* KMI0 */
-               .dev_id         = "mb:kmi0",
-               .clk            = &osc2_clk,
-       }, {    /* KMI1 */
-               .dev_id         = "mb:kmi1",
-               .clk            = &osc2_clk,
-       }, {    /* MMC0 */
-               .dev_id         = "mb:mmci",
-               .clk            = &osc2_clk,
-       }, {    /* CLCD */
-               .dev_id         = "mb:clcd",
-               .clk            = &osc1_clk,
-       }, {    /* SP805 WDT */
-               .dev_id         = "mb:wdt",
-               .clk            = &v2m_ref_clk,
-       }, {    /* SP804 timers */
-               .dev_id         = "sp804",
-               .con_id         = "v2m-timer0",
-               .clk            = &v2m_sp804_clk,
-       }, {    /* SP804 timers */
-               .dev_id         = "sp804",
-               .con_id         = "v2m-timer1",
-               .clk            = &v2m_sp804_clk,
-       },
+static struct clk_ops v2m_osc_ops = {
+       .recalc_rate = v2m_osc_recalc_rate,
+       .round_rate = v2m_osc_round_rate,
+       .set_rate = v2m_osc_set_rate,
+};
+
+struct clk * __init v2m_osc_register(const char *name, struct v2m_osc *osc)
+{
+       struct clk_init_data init;
+
+       WARN_ON(osc->site > 2);
+       WARN_ON(osc->stack > 15);
+       WARN_ON(osc->osc > 4095);
+
+       init.name = name;
+       init.ops = &v2m_osc_ops;
+       init.flags = CLK_IS_ROOT;
+       init.num_parents = 0;
+
+       osc->hw.init = &init;
+
+       return clk_register(NULL, &osc->hw);
+}
+
+static struct v2m_osc v2m_mb_osc1 = {
+       .site = SYS_CFG_SITE_MB,
+       .osc = 1,
+       .rate_min = 23750000,
+       .rate_max = 63500000,
+       .rate_default = 23750000,
+};
+
+static const char *v2m_ref_clk_periphs[] __initconst = {
+       "mb:wdt",   "1000f000.wdt",  "1c0f0000.wdt",    /* SP805 WDT */
+};
+
+static const char *v2m_osc1_periphs[] __initconst = {
+       "mb:clcd",  "1001f000.clcd", "1c1f0000.clcd",   /* PL111 CLCD */
+};
+
+static const char *v2m_osc2_periphs[] __initconst = {
+       "mb:mmci",  "10005000.mmci", "1c050000.mmci",   /* PL180 MMCI */
+       "mb:kmi0",  "10006000.kmi",  "1c060000.kmi",    /* PL050 KMI0 */
+       "mb:kmi1",  "10007000.kmi",  "1c070000.kmi",    /* PL050 KMI1 */
+       "mb:uart0", "10009000.uart", "1c090000.uart",   /* PL011 UART0 */
+       "mb:uart1", "1000a000.uart", "1c0a0000.uart",   /* PL011 UART1 */
+       "mb:uart2", "1000b000.uart", "1c0b0000.uart",   /* PL011 UART2 */
+       "mb:uart3", "1000c000.uart", "1c0c0000.uart",   /* PL011 UART3 */
+};
+
+static void __init v2m_clk_init(void)
+{
+       struct clk *clk;
+       int i;
+
+       clk = clk_register_fixed_rate(NULL, "dummy_apb_pclk", NULL,
+                       CLK_IS_ROOT, 0);
+       WARN_ON(clk_register_clkdev(clk, "apb_pclk", NULL));
+
+       clk = clk_register_fixed_rate(NULL, "mb:ref_clk", NULL,
+                       CLK_IS_ROOT, 32768);
+       for (i = 0; i < ARRAY_SIZE(v2m_ref_clk_periphs); i++)
+               WARN_ON(clk_register_clkdev(clk, NULL, v2m_ref_clk_periphs[i]));
+
+       clk = clk_register_fixed_rate(NULL, "mb:sp804_clk", NULL,
+                       CLK_IS_ROOT, 1000000);
+       WARN_ON(clk_register_clkdev(clk, "v2m-timer0", "sp804"));
+       WARN_ON(clk_register_clkdev(clk, "v2m-timer1", "sp804"));
+
+       clk = v2m_osc_register("mb:osc1", &v2m_mb_osc1);
+       for (i = 0; i < ARRAY_SIZE(v2m_osc1_periphs); i++)
+               WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc1_periphs[i]));
+
+       clk = clk_register_fixed_rate(NULL, "mb:osc2", NULL,
+                       CLK_IS_ROOT, 24000000);
+       for (i = 0; i < ARRAY_SIZE(v2m_osc2_periphs); i++)
+               WARN_ON(clk_register_clkdev(clk, NULL, v2m_osc2_periphs[i]));
+}
+
+static void __init v2m_timer_init(void)
+{
+       v2m_sysctl_init(ioremap(V2M_SYSCTL, SZ_4K));
+       v2m_clk_init();
+       v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
+}
+
+static struct sys_timer v2m_timer = {
+       .init   = v2m_timer_init,
 };
 
 static void __init v2m_init_early(void)
 {
-       ct_desc->init_early();
-       clkdev_add_table(v2m_lookups, ARRAY_SIZE(v2m_lookups));
+       if (ct_desc->init_early)
+               ct_desc->init_early();
        versatile_sched_clock_init(v2m_sysreg_base + V2M_SYS_24MHZ, 24000000);
 }
 
 static void v2m_power_off(void)
 {
-       if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE_MB, 0))
+       if (v2m_cfg_write(SYS_CFG_SHUTDOWN | SYS_CFG_SITE(SYS_CFG_SITE_MB), 0))
                printk(KERN_EMERG "Unable to shutdown\n");
 }
 
 static void v2m_restart(char str, const char *cmd)
 {
-       if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE_MB, 0))
+       if (v2m_cfg_write(SYS_CFG_REBOOT | SYS_CFG_SITE(SYS_CFG_SITE_MB), 0))
                printk(KERN_EMERG "Unable to reboot\n");
 }
 
@@ -458,6 +510,9 @@ static void __init v2m_init(void)
 {
        int i;
 
+       regulator_register_fixed(0, v2m_eth_supplies,
+                       ARRAY_SIZE(v2m_eth_supplies));
+
        platform_device_register(&v2m_pcie_i2c_device);
        platform_device_register(&v2m_ddc_i2c_device);
        platform_device_register(&v2m_flash_device);
@@ -522,77 +577,6 @@ void __init v2m_dt_map_io(void)
 #endif
 }
 
-static struct clk_lookup v2m_dt_lookups[] = {
-       {       /* AMBA bus clock */
-               .con_id         = "apb_pclk",
-               .clk            = &dummy_apb_pclk,
-       }, {    /* SP804 timers */
-               .dev_id         = "sp804",
-               .con_id         = "v2m-timer0",
-               .clk            = &v2m_sp804_clk,
-       }, {    /* SP804 timers */
-               .dev_id         = "sp804",
-               .con_id         = "v2m-timer1",
-               .clk            = &v2m_sp804_clk,
-       }, {    /* PL180 MMCI */
-               .dev_id         = "mb:mmci", /* 10005000.mmci */
-               .clk            = &osc2_clk,
-       }, {    /* PL050 KMI0 */
-               .dev_id         = "10006000.kmi",
-               .clk            = &osc2_clk,
-       }, {    /* PL050 KMI1 */
-               .dev_id         = "10007000.kmi",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART0 */
-               .dev_id         = "10009000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART1 */
-               .dev_id         = "1000a000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART2 */
-               .dev_id         = "1000b000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART3 */
-               .dev_id         = "1000c000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* SP805 WDT */
-               .dev_id         = "1000f000.wdt",
-               .clk            = &v2m_ref_clk,
-       }, {    /* PL111 CLCD */
-               .dev_id         = "1001f000.clcd",
-               .clk            = &osc1_clk,
-       },
-       /* RS1 memory map */
-       {       /* PL180 MMCI */
-               .dev_id         = "mb:mmci", /* 1c050000.mmci */
-               .clk            = &osc2_clk,
-       }, {    /* PL050 KMI0 */
-               .dev_id         = "1c060000.kmi",
-               .clk            = &osc2_clk,
-       }, {    /* PL050 KMI1 */
-               .dev_id         = "1c070000.kmi",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART0 */
-               .dev_id         = "1c090000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART1 */
-               .dev_id         = "1c0a0000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART2 */
-               .dev_id         = "1c0b0000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* PL011 UART3 */
-               .dev_id         = "1c0c0000.uart",
-               .clk            = &osc2_clk,
-       }, {    /* SP805 WDT */
-               .dev_id         = "1c0f0000.wdt",
-               .clk            = &v2m_ref_clk,
-       }, {    /* PL111 CLCD */
-               .dev_id         = "1c1f0000.clcd",
-               .clk            = &osc1_clk,
-       },
-};
-
 void __init v2m_dt_init_early(void)
 {
        struct device_node *node;
@@ -605,8 +589,8 @@ void __init v2m_dt_init_early(void)
 
        /* Confirm board type against DT property, if available */
        if (of_property_read_u32(allnodes, "arm,hbi", &dt_hbi) == 0) {
-               u32 misc = readl(v2m_sysreg_base + V2M_SYS_MISC);
-               u32 id = readl(v2m_sysreg_base + (misc & SYS_MISC_MASTERSITE ?
+               int site = v2m_get_master_site();
+               u32 id = readl(v2m_sysreg_base + (site == SYS_CFG_SITE_DB2 ?
                                V2M_SYS_PROCID1 : V2M_SYS_PROCID0));
                u32 hbi = id & SYS_PROCIDx_HBI_MASK;
 
@@ -614,8 +598,6 @@ void __init v2m_dt_init_early(void)
                        pr_warning("vexpress: DT HBI (%x) is not matching "
                                        "hardware (%x)!\n", dt_hbi, hbi);
        }
-
-       clkdev_add_table(v2m_dt_lookups, ARRAY_SIZE(v2m_dt_lookups));
 }
 
 static  struct of_device_id vexpress_irq_match[] __initdata = {
@@ -637,6 +619,8 @@ static void __init v2m_dt_timer_init(void)
        node = of_find_compatible_node(NULL, NULL, "arm,sp810");
        v2m_sysctl_init(of_iomap(node, 0));
 
+       v2m_clk_init();
+
        err = of_property_read_string(of_aliases, "arm,v2m_timer", &path);
        if (WARN_ON(err))
                return;
index 81aedb7c893c24d94814f1c74e32b40cad08e543..54e69973f39b7344ca0e7ccdb01b2a1be696c907 100644 (file)
@@ -1,4 +1,4 @@
-obj-y += devices.o gpio.o irq.o timer.o
+obj-y += devices.o gpio.o irq.o timer.o restart.o
 
 obj-$(CONFIG_VTWM_VERSION_VT8500) += devices-vt8500.o
 obj-$(CONFIG_VTWM_VERSION_WM8505) += devices-wm8505.o
index a464c75844112d8147e07f1ef5cf689e9a969350..f9fbeb2d10e988525c7c775d960f619ec643d6c4 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <mach/restart.h>
 
 #include "devices.h"
 
@@ -62,6 +63,7 @@ void __init bv07_init(void)
        else
                printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
 
+       wmt_setup_restart();
        vt8500_set_resources();
        platform_add_devices(devices, ARRAY_SIZE(devices));
        vt8500_gpio_init();
@@ -69,6 +71,7 @@ void __init bv07_init(void)
 
 MACHINE_START(BV07, "Benign BV07 Mini Netbook")
        .atag_offset    = 0x100,
+       .restart        = wmt_restart,
        .reserve        = vt8500_reserve_mem,
        .map_io         = vt8500_map_io,
        .init_irq       = vt8500_init_irq,
diff --git a/arch/arm/mach-vt8500/include/mach/restart.h b/arch/arm/mach-vt8500/include/mach/restart.h
new file mode 100644 (file)
index 0000000..89f9b78
--- /dev/null
@@ -0,0 +1,17 @@
+/* linux/arch/arm/mach-vt8500/restart.h
+ *
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * 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.
+ *
+ */
+
+void wmt_setup_restart(void);
+void wmt_restart(char mode, const char *cmd);
diff --git a/arch/arm/mach-vt8500/include/mach/system.h b/arch/arm/mach-vt8500/include/mach/system.h
deleted file mode 100644 (file)
index 58fa801..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * arch/arm/mach-vt8500/include/mach/system.h
- *
- */
-#include <asm/io.h>
-
-/* PM Software Reset request register */
-#define VT8500_PMSR_VIRT       0xf8130060
-
-static inline void arch_reset(char mode, const char *cmd)
-{
-       writel(1, VT8500_PMSR_VIRT);
-}
diff --git a/arch/arm/mach-vt8500/restart.c b/arch/arm/mach-vt8500/restart.c
new file mode 100644 (file)
index 0000000..497e89a
--- /dev/null
@@ -0,0 +1,54 @@
+/* linux/arch/arm/mach-vt8500/restart.c
+ *
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * 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 <asm/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#define LEGACY_PMC_BASE                0xD8130000
+#define WMT_PRIZM_PMSR_REG     0x60
+
+static void __iomem *pmc_base;
+
+void wmt_setup_restart(void)
+{
+       struct device_node *np;
+
+       /*
+        * Check if Power Mgmt Controller node is present in device tree. If no
+        * device tree node, use the legacy PMSR value (valid for all current
+        * SoCs).
+        */
+       np = of_find_compatible_node(NULL, NULL, "wmt,prizm-pmc");
+       if (np) {
+               pmc_base = of_iomap(np, 0);
+
+               if (!pmc_base)
+                       pr_err("%s:of_iomap(pmc) failed\n", __func__);
+
+               of_node_put(np);
+       } else {
+               pmc_base = ioremap(LEGACY_PMC_BASE, 0x1000);
+               if (!pmc_base) {
+                       pr_err("%s:ioremap(rstc) failed\n", __func__);
+                       return;
+               }
+       }
+}
+
+void wmt_restart(char mode, const char *cmd)
+{
+       if (pmc_base)
+               writel(1, pmc_base + WMT_PRIZM_PMSR_REG);
+}
index cf910a956080c56126ee57a34dc7b2ea87fc6295..db19886caf7ce679ff6ac2f98f0d5d70568e2eac 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <mach/restart.h>
 
 #include "devices.h"
 
@@ -61,7 +62,7 @@ void __init wm8505_7in_init(void)
                pm_power_off = &vt8500_power_off;
        else
                printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
-
+       wmt_setup_restart();
        wm8505_set_resources();
        platform_add_devices(devices, ARRAY_SIZE(devices));
        vt8500_gpio_init();
@@ -69,6 +70,7 @@ void __init wm8505_7in_init(void)
 
 MACHINE_START(WM8505_7IN_NETBOOK, "WM8505 7-inch generic netbook")
        .atag_offset    = 0x100,
+       .restart        = wmt_restart,
        .reserve        = wm8505_reserve_mem,
        .map_io         = wm8505_map_io,
        .init_irq       = wm8505_init_irq,
index 5cac2c540f4f86b6d73ecd5b24617e4ee9b27705..5c10ad05df740fe6d514ad61fea52b3cd01f12c5 100644 (file)
 
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
+#include <linux/module.h>
 #include <linux/smsc911x.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
 /* CPU ID and Personality ID */
 #define MCU_BOARD_ID_REG       0x68
 
-#define MXC_IRQ_TO_EXPIO(irq)   ((irq) - MXC_BOARD_IRQ_START)
-#define MXC_IRQ_TO_GPIO(irq)   ((irq) - MXC_INTERNAL_IRQS)
-
-#define MXC_EXP_IO_BASE                (MXC_BOARD_IRQ_START)
 #define MXC_MAX_EXP_IO_LINES   16
 
 /* interrupts like external uart , external ethernet etc*/
-#define EXPIO_INT_ENET         (MXC_BOARD_IRQ_START + 0)
-#define EXPIO_INT_XUART_A      (MXC_BOARD_IRQ_START + 1)
-#define EXPIO_INT_XUART_B      (MXC_BOARD_IRQ_START + 2)
-#define EXPIO_INT_BUTTON_A     (MXC_BOARD_IRQ_START + 3)
-#define EXPIO_INT_BUTTON_B     (MXC_BOARD_IRQ_START + 4)
+#define EXPIO_INT_ENET         0
+#define EXPIO_INT_XUART_A      1
+#define EXPIO_INT_XUART_B      2
+#define EXPIO_INT_BUTTON_A     3
+#define EXPIO_INT_BUTTON_B     4
 
 static void __iomem *brd_io;
+static struct irq_domain *domain;
 
 static struct resource smsc911x_resources[] = {
        {
                .flags = IORESOURCE_MEM,
        } , {
-               .start = EXPIO_INT_ENET,
-               .end = EXPIO_INT_ENET,
                .flags = IORESOURCE_IRQ,
        },
 };
@@ -100,11 +97,11 @@ static void mxc_expio_irq_handler(u32 irq, struct irq_desc *desc)
        imr_val = __raw_readw(brd_io + INTR_MASK_REG);
        int_valid = __raw_readw(brd_io + INTR_STATUS_REG) & ~imr_val;
 
-       expio_irq = MXC_BOARD_IRQ_START;
+       expio_irq = 0;
        for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
                if ((int_valid & 1) == 0)
                        continue;
-               generic_handle_irq(expio_irq);
+               generic_handle_irq(irq_find_mapping(domain, expio_irq));
        }
 
        desc->irq_data.chip->irq_ack(&desc->irq_data);
@@ -118,7 +115,7 @@ static void mxc_expio_irq_handler(u32 irq, struct irq_desc *desc)
 static void expio_mask_irq(struct irq_data *d)
 {
        u16 reg;
-       u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
+       u32 expio = d->hwirq;
 
        reg = __raw_readw(brd_io + INTR_MASK_REG);
        reg |= (1 << expio);
@@ -127,7 +124,7 @@ static void expio_mask_irq(struct irq_data *d)
 
 static void expio_ack_irq(struct irq_data *d)
 {
-       u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
+       u32 expio = d->hwirq;
 
        __raw_writew(1 << expio, brd_io + INTR_RESET_REG);
        __raw_writew(0, brd_io + INTR_RESET_REG);
@@ -137,7 +134,7 @@ static void expio_ack_irq(struct irq_data *d)
 static void expio_unmask_irq(struct irq_data *d)
 {
        u16 reg;
-       u32 expio = MXC_IRQ_TO_EXPIO(d->irq);
+       u32 expio = d->hwirq;
 
        reg = __raw_readw(brd_io + INTR_MASK_REG);
        reg &= ~(1 << expio);
@@ -155,8 +152,10 @@ static struct regulator_consumer_supply dummy_supplies[] = {
        REGULATOR_SUPPLY("vddvario", "smsc911x"),
 };
 
-int __init mxc_expio_init(u32 base, u32 p_irq)
+int __init mxc_expio_init(u32 base, u32 intr_gpio)
 {
+       u32 p_irq = gpio_to_irq(intr_gpio);
+       int irq_base;
        int i;
 
        brd_io = ioremap(BOARD_IO_ADDR(base), SZ_4K);
@@ -178,16 +177,23 @@ int __init mxc_expio_init(u32 base, u32 p_irq)
        /*
         * Configure INT line as GPIO input
         */
-       gpio_request(MXC_IRQ_TO_GPIO(p_irq), "expio_pirq");
-       gpio_direction_input(MXC_IRQ_TO_GPIO(p_irq));
+       gpio_request(intr_gpio, "expio_pirq");
+       gpio_direction_input(intr_gpio);
 
        /* disable the interrupt and clear the status */
        __raw_writew(0, brd_io + INTR_MASK_REG);
        __raw_writew(0xFFFF, brd_io + INTR_RESET_REG);
        __raw_writew(0, brd_io + INTR_RESET_REG);
        __raw_writew(0x1F, brd_io + INTR_MASK_REG);
-       for (i = MXC_EXP_IO_BASE;
-            i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES); i++) {
+
+       irq_base = irq_alloc_descs(-1, 0, MXC_MAX_EXP_IO_LINES, numa_node_id());
+       WARN_ON(irq_base < 0);
+
+       domain = irq_domain_add_legacy(NULL, MXC_MAX_EXP_IO_LINES, irq_base, 0,
+                                      &irq_domain_simple_ops, NULL);
+       WARN_ON(!domain);
+
+       for (i = irq_base; i < irq_base + MXC_MAX_EXP_IO_LINES; i++) {
                irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq);
                set_irq_flags(i, IRQF_VALID);
        }
@@ -199,6 +205,8 @@ int __init mxc_expio_init(u32 base, u32 p_irq)
 
        smsc911x_resources[0].start = LAN9217_BASE_ADDR(base);
        smsc911x_resources[0].end = LAN9217_BASE_ADDR(base) + 0x100 - 1;
+       smsc911x_resources[1].start = irq_find_mapping(domain, EXPIO_INT_ENET);
+       smsc911x_resources[1].end = irq_find_mapping(domain, EXPIO_INT_ENET);
        platform_device_register(&smsc_lan9217_device);
 
        return 0;
index e81290c27c655bdf4ab5f4d58a61ee41cc8013e9..63b064b5c1d55148c1c5fa226a6173aafbb3a23f 100644 (file)
@@ -16,6 +16,7 @@ obj-$(CONFIG_MXC_ULPI) += ulpi.o
 obj-$(CONFIG_MXC_USE_EPIT) += epit.o
 obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpufreq.o
+obj-$(CONFIG_CPU_IDLE) += cpuidle.o
 ifdef CONFIG_SND_IMX_SOC
 obj-y += ssi-fiq.o
 obj-y += ssi-fiq-ksym.o
index 689f81f9593bf436adbca616cc0904bfe8cb59b1..cbd55c36def3e52d304fbd965ba9891b89d345e5 100644 (file)
 
 #include <linux/module.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/io.h>
+#include <linux/of.h>
 #include <mach/common.h>
 #include <asm/mach/irq.h>
 #include <asm/exception.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 
 #include "irq-common.h"
 
 #define AVIC_NUM_IRQS 64
 
 void __iomem *avic_base;
+static struct irq_domain *domain;
 
 static u32 avic_saved_mask_reg[2];
 
 #ifdef CONFIG_MXC_IRQ_PRIOR
 static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
 {
+       struct irq_data *d = irq_get_irq_data(irq);
        unsigned int temp;
        unsigned int mask = 0x0F << irq % 8 * 4;
 
+       irq = d->hwirq;
+
        if (irq >= AVIC_NUM_IRQS)
                return -EINVAL;
 
@@ -75,8 +82,11 @@ static int avic_irq_set_priority(unsigned char irq, unsigned char prio)
 #ifdef CONFIG_FIQ
 static int avic_set_irq_fiq(unsigned int irq, unsigned int type)
 {
+       struct irq_data *d = irq_get_irq_data(irq);
        unsigned int irqt;
 
+       irq = d->hwirq;
+
        if (irq >= AVIC_NUM_IRQS)
                return -EINVAL;
 
@@ -108,7 +118,7 @@ static void avic_irq_suspend(struct irq_data *d)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct irq_chip_type *ct = gc->chip_types;
-       int idx = gc->irq_base >> 5;
+       int idx = d->hwirq >> 5;
 
        avic_saved_mask_reg[idx] = __raw_readl(avic_base + ct->regs.mask);
        __raw_writel(gc->wake_active, avic_base + ct->regs.mask);
@@ -118,7 +128,7 @@ static void avic_irq_resume(struct irq_data *d)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct irq_chip_type *ct = gc->chip_types;
-       int idx = gc->irq_base >> 5;
+       int idx = d->hwirq >> 5;
 
        __raw_writel(avic_saved_mask_reg[idx], avic_base + ct->regs.mask);
 }
@@ -128,11 +138,10 @@ static void avic_irq_resume(struct irq_data *d)
 #define avic_irq_resume NULL
 #endif
 
-static __init void avic_init_gc(unsigned int irq_start)
+static __init void avic_init_gc(int idx, unsigned int irq_start)
 {
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
-       int idx = irq_start >> 5;
 
        gc = irq_alloc_generic_chip("mxc-avic", 1, irq_start, avic_base,
                                    handle_level_irq);
@@ -161,7 +170,7 @@ asmlinkage void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
                if (nivector == 0xffff)
                        break;
 
-               handle_IRQ(nivector, regs);
+               handle_IRQ(irq_find_mapping(domain, nivector), regs);
        } while (1);
 }
 
@@ -172,6 +181,8 @@ asmlinkage void __exception_irq_entry avic_handle_irq(struct pt_regs *regs)
  */
 void __init mxc_init_irq(void __iomem *irqbase)
 {
+       struct device_node *np;
+       int irq_base;
        int i;
 
        avic_base = irqbase;
@@ -190,8 +201,16 @@ void __init mxc_init_irq(void __iomem *irqbase)
        __raw_writel(0, avic_base + AVIC_INTTYPEH);
        __raw_writel(0, avic_base + AVIC_INTTYPEL);
 
-       for (i = 0; i < AVIC_NUM_IRQS; i += 32)
-               avic_init_gc(i);
+       irq_base = irq_alloc_descs(-1, 0, AVIC_NUM_IRQS, numa_node_id());
+       WARN_ON(irq_base < 0);
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,avic");
+       domain = irq_domain_add_legacy(np, AVIC_NUM_IRQS, irq_base, 0,
+                                      &irq_domain_simple_ops, NULL);
+       WARN_ON(!domain);
+
+       for (i = 0; i < AVIC_NUM_IRQS / 32; i++, irq_base += 32)
+               avic_init_gc(i, irq_base);
 
        /* Set default priority value (0) for all IRQ's */
        for (i = 0; i < 8; i++)
@@ -199,7 +218,7 @@ void __init mxc_init_irq(void __iomem *irqbase)
 
 #ifdef CONFIG_FIQ
        /* Initialize FIQ */
-       init_FIQ();
+       init_FIQ(FIQ_START);
 #endif
 
        printk(KERN_INFO "MXC IRQ initialized\n");
diff --git a/arch/arm/plat-mxc/cpuidle.c b/arch/arm/plat-mxc/cpuidle.c
new file mode 100644 (file)
index 0000000..d4cb511
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/cpuidle.h>
+#include <linux/err.h>
+#include <linux/hrtimer.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+static struct cpuidle_device __percpu * imx_cpuidle_devices;
+
+static void __init imx_cpuidle_devices_uninit(void)
+{
+       int cpu_id;
+       struct cpuidle_device *dev;
+
+       for_each_possible_cpu(cpu_id) {
+               dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
+               cpuidle_unregister_device(dev);
+       }
+
+       free_percpu(imx_cpuidle_devices);
+}
+
+int __init imx_cpuidle_init(struct cpuidle_driver *drv)
+{
+       struct cpuidle_device *dev;
+       int cpu_id, ret;
+
+       if (drv->state_count > CPUIDLE_STATE_MAX) {
+               pr_err("%s: state_count exceeds maximum\n", __func__);
+               return -EINVAL;
+       }
+
+       ret = cpuidle_register_driver(drv);
+       if (ret) {
+               pr_err("%s: Failed to register cpuidle driver with error: %d\n",
+                        __func__, ret);
+               return ret;
+       }
+
+       imx_cpuidle_devices = alloc_percpu(struct cpuidle_device);
+       if (imx_cpuidle_devices == NULL) {
+               ret = -ENOMEM;
+               goto unregister_drv;
+       }
+
+       /* initialize state data for each cpuidle_device */
+       for_each_possible_cpu(cpu_id) {
+               dev = per_cpu_ptr(imx_cpuidle_devices, cpu_id);
+               dev->cpu = cpu_id;
+               dev->state_count = drv->state_count;
+
+               ret = cpuidle_register_device(dev);
+               if (ret) {
+                       pr_err("%s: Failed to register cpu %u, error: %d\n",
+                               __func__, cpu_id, ret);
+                       goto uninit;
+               }
+       }
+
+       return 0;
+
+uninit:
+       imx_cpuidle_devices_uninit();
+
+unregister_drv:
+       cpuidle_unregister_driver(drv);
+       return ret;
+}
index 79d340ae0af134eb00431fab41b2a3f55770355a..d1e33cc6f12e8cd9e5d332df58a4788ec2c61952 100644 (file)
@@ -30,8 +30,7 @@ const struct imx_ipu_core_data imx35_ipu_core_data __initconst =
 static struct platform_device *imx_ipu_coredev __initdata;
 
 struct platform_device *__init imx_add_ipu_core(
-               const struct imx_ipu_core_data *data,
-               const struct ipu_platform_data *pdata)
+               const struct imx_ipu_core_data *data)
 {
        /* The resource order is important! */
        struct resource res[] = {
@@ -55,7 +54,7 @@ struct platform_device *__init imx_add_ipu_core(
        };
 
        return imx_ipu_coredev = imx_add_platform_device("ipu-core", -1,
-                       res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+                       res, ARRAY_SIZE(res), NULL, 0);
 }
 
 struct platform_device *__init imx_alloc_mx3_camera(
index 16d0ec4df5f65c7905896bfead4353ba643ebf14..a5c9ad5721c2a1374815cc737ede4c3436dfdba5 100644 (file)
@@ -20,6 +20,11 @@ const struct imx_mxc_rtc_data imx31_mxc_rtc_data __initconst =
        imx_mxc_rtc_data_entry_single(MX31);
 #endif /* ifdef CONFIG_SOC_IMX31 */
 
+#ifdef CONFIG_SOC_IMX35
+const struct imx_mxc_rtc_data imx35_mxc_rtc_data __initconst =
+       imx_mxc_rtc_data_entry_single(MX35);
+#endif /* ifdef CONFIG_SOC_IMX35 */
+
 struct platform_device *__init imx_add_mxc_rtc(
                const struct imx_mxc_rtc_data *data)
 {
index 9bfae8bd5b8db54e750acf5ef296c220f586a6ab..9c50c14c8f927fbf8e28018f817128e41a70018c 100644 (file)
@@ -95,7 +95,7 @@ const struct imx_spi_imx_data imx51_ecspi_data[] __initconst = {
 #ifdef CONFIG_SOC_IMX53
 /* i.mx53 has the i.mx35 type cspi */
 const struct imx_spi_imx_data imx53_cspi_data __initconst =
-       imx_spi_imx_data_entry_single(MX53, CSPI, "imx35-cspi", 0, , SZ_4K);
+       imx_spi_imx_data_entry_single(MX53, CSPI, "imx35-cspi", 2, , SZ_4K);
 
 /* i.mx53 has the i.mx51 type ecspi */
 const struct imx_spi_imx_data imx53_ecspi_data[] __initconst = {
index a384fdd49c6236630141d0456590789c08150586..9fd6cb3f8fad6da3861015897edc66d6a17afa87 100644 (file)
@@ -13,6 +13,6 @@
 #ifndef __ASM_ARCH_MXC_3DS_DB_H__
 #define __ASM_ARCH_MXC_3DS_DB_H__
 
-extern int __init mxc_expio_init(u32 base, u32 p_irq);
+extern int __init mxc_expio_init(u32 base, u32 intr_gpio);
 
 #endif /* __ASM_ARCH_MXC_3DS_DB_H__ */
index e429ca1b814a179522bdf2bc9bb9e514ac136efc..7128e9710417d2a77b06f29cfd45efcb558ff2e3 100644 (file)
@@ -54,6 +54,7 @@ extern void imx50_soc_init(void);
 extern void imx51_soc_init(void);
 extern void imx53_soc_init(void);
 extern void imx51_init_late(void);
+extern void imx53_init_late(void);
 extern void epit_timer_init(void __iomem *base, int irq);
 extern void mxc_timer_init(void __iomem *, int);
 extern int mx1_clocks_init(unsigned long fref);
@@ -67,6 +68,7 @@ extern int mx51_clocks_init(unsigned long ckil, unsigned long osc,
 extern int mx53_clocks_init(unsigned long ckil, unsigned long osc,
                        unsigned long ckih1, unsigned long ckih2);
 extern int mx27_clocks_init_dt(void);
+extern int mx31_clocks_init_dt(void);
 extern int mx51_clocks_init_dt(void);
 extern int mx53_clocks_init_dt(void);
 extern int mx6q_clocks_init(void);
@@ -95,7 +97,6 @@ enum mx3_cpu_pwr_mode {
 };
 
 extern void mx3_cpu_lp_set(enum mx3_cpu_pwr_mode mode);
-extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
 extern void imx_print_silicon_rev(const char *cpu, int srev);
 
 void avic_handle_irq(struct pt_regs *);
@@ -146,8 +147,12 @@ extern void imx6q_clock_map_io(void);
 
 #ifdef CONFIG_PM
 extern void imx6q_pm_init(void);
+extern void imx51_pm_init(void);
+extern void imx53_pm_init(void);
 #else
 static inline void imx6q_pm_init(void) {}
+static inline void imx51_pm_init(void) {}
+static inline void imx53_pm_init(void) {}
 #endif
 
 #ifdef CONFIG_NEON
diff --git a/arch/arm/plat-mxc/include/mach/cpuidle.h b/arch/arm/plat-mxc/include/mach/cpuidle.h
new file mode 100644 (file)
index 0000000..bc932d1
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/cpuidle.h>
+
+#ifdef CONFIG_CPU_IDLE
+extern int imx_cpuidle_init(struct cpuidle_driver *drv);
+#else
+static inline int imx_cpuidle_init(struct cpuidle_driver *drv)
+{
+       return -ENODEV;
+}
+#endif
index 1b2258daa05b22849cd9e028228187ee852793c2..a7f5bb1084d72da97843fb73468cdd1c8f4a70fd 100644 (file)
@@ -183,7 +183,6 @@ struct platform_device *__init imx_add_imx_udc(
                const struct imx_imx_udc_data *data,
                const struct imxusb_platform_data *pdata);
 
-#include <mach/ipu.h>
 #include <mach/mx3fb.h>
 #include <mach/mx3_camera.h>
 struct imx_ipu_core_data {
@@ -192,8 +191,7 @@ struct imx_ipu_core_data {
        resource_size_t errirq;
 };
 struct platform_device *__init imx_add_ipu_core(
-               const struct imx_ipu_core_data *data,
-               const struct ipu_platform_data *pdata);
+               const struct imx_ipu_core_data *data);
 struct platform_device *__init imx_alloc_mx3_camera(
                const struct imx_ipu_core_data *data,
                const struct mx3_camera_pdata *pdata);
index 0630513554def1f851ea708fabd484dbf50deec6..ebf10654bb42ae477cfdeede23eedbcbc308c395 100644 (file)
@@ -50,7 +50,7 @@
  *     IO      0x00200000+0x100000     ->      0xf4000000+0x100000
  * mx21:
  *     AIPI    0x10000000+0x100000     ->      0xf4400000+0x100000
- *     SAHB1   0x80000000+0x100000     ->      0xf4000000+0x100000
+ *     SAHB1   0x80000000+0x100000     ->      0xf5000000+0x100000
  *     X_MEMC  0xdf000000+0x004000     ->      0xf5f00000+0x004000
  * mx25:
  *     AIPS1   0x43f00000+0x100000     ->      0xf5300000+0x100000
  *     AVIC    0x68000000+0x100000     ->      0xf5800000+0x100000
  * mx27:
  *     AIPI    0x10000000+0x100000     ->      0xf4400000+0x100000
- *     SAHB1   0x80000000+0x100000     ->      0xf4000000+0x100000
+ *     SAHB1   0x80000000+0x100000     ->      0xf5000000+0x100000
  *     X_MEMC  0xd8000000+0x100000     ->      0xf5c00000+0x100000
  * mx31:
  *     AIPS1   0x43f00000+0x100000     ->      0xf5300000+0x100000
  *     AIPS2   0x53f00000+0x100000     ->      0xf5700000+0x100000
  *     AVIC    0x68000000+0x100000     ->      0xf5800000+0x100000
- *     X_MEMC  0xb8000000+0x010000     ->      0xf4c00000+0x010000
+ *     X_MEMC  0xb8000000+0x010000     ->      0xf5c00000+0x010000
  *     SPBA0   0x50000000+0x100000     ->      0xf5400000+0x100000
  * mx35:
  *     AIPS1   0x43f00000+0x100000     ->      0xf5300000+0x100000
  *     AIPS2   0x53f00000+0x100000     ->      0xf5700000+0x100000
  *     AVIC    0x68000000+0x100000     ->      0xf5800000+0x100000
- *     X_MEMC  0xb8000000+0x010000     ->      0xf4c00000+0x010000
+ *     X_MEMC  0xb8000000+0x010000     ->      0xf5c00000+0x010000
  *     SPBA0   0x50000000+0x100000     ->      0xf5400000+0x100000
  * mx50:
  *     TZIC    0x0fffc000+0x004000     ->      0xf4bfc000+0x004000
- *     SPBA0   0x50000000+0x100000     ->      0xf5400000+0x100000
  *     AIPS1   0x53f00000+0x100000     ->      0xf5700000+0x100000
+ *     SPBA0   0x50000000+0x100000     ->      0xf5400000+0x100000
  *     AIPS2   0x63f00000+0x100000     ->      0xf5300000+0x100000
  * mx51:
- *     TZIC    0xe0000000+0x004000     ->      0xf5000000+0x004000
+ *     TZIC    0x0fffc000+0x004000     ->      0xf4bfc000+0x004000
  *     IRAM    0x1ffe0000+0x020000     ->      0xf4fe0000+0x020000
+ *     DEBUG   0x60000000+0x100000     ->      0xf5000000+0x100000
  *     SPBA0   0x70000000+0x100000     ->      0xf5400000+0x100000
  *     AIPS1   0x73f00000+0x100000     ->      0xf5700000+0x100000
- *     AIPS2   0x83f00000+0x100000     ->      0xf4300000+0x100000
+ *     AIPS2   0x83f00000+0x100000     ->      0xf5300000+0x100000
  * mx53:
  *     TZIC    0x0fffc000+0x004000     ->      0xf4bfc000+0x004000
+ *     DEBUG   0x40000000+0x100000     ->      0xf5000000+0x100000
  *     SPBA0   0x50000000+0x100000     ->      0xf5400000+0x100000
  *     AIPS1   0x53f00000+0x100000     ->      0xf5700000+0x100000
  *     AIPS2   0x63f00000+0x100000     ->      0xf5300000+0x100000
  * mx6q:
- *     SCU     0x00a00000+0x001000     ->      0xf4000000+0x001000
+ *     SCU     0x00a00000+0x004000     ->      0xf4000000+0x004000
  *     CCM     0x020c4000+0x004000     ->      0xf42c4000+0x004000
- *     ANATOP  0x020c8000+0x001000     ->      0xf42c8000+0x001000
+ *     ANATOP  0x020c8000+0x004000     ->      0xf42c8000+0x004000
  *     UART4   0x021f0000+0x004000     ->      0xf42f0000+0x004000
  */
 #define IMX_IO_P2V(x)  (                                               \
-                       0xf4000000 +                                    \
+                       (((x) & 0x80000000) >> 7) |                     \
+                       (0xf4000000 +                                   \
                        (((x) & 0x50000000) >> 6) +                     \
                        (((x) & 0x0b000000) >> 4) +                     \
-                       (((x) & 0x000fffff)))
+                       (((x) & 0x000fffff))))
 
 #define IMX_IO_ADDRESS(x)      IOMEM(IMX_IO_P2V(x))
 
 /* range e.g. GPIO_1_5 is gpio 5 under linux */
 #define IMX_GPIO_NR(bank, nr)          (((bank) - 1) * 32 + (nr))
 
-#define IMX_GPIO_TO_IRQ(gpio)  (MXC_GPIO_IRQ_START + (gpio))
-
 #endif /* __ASM_ARCH_MXC_HARDWARE_H__ */
index 63f22a009a65f61e5e786c59eb8fbffb9dbd20d4..d8b65b51f2a994d4b00e4a83568cbeb4378d16fa 100644 (file)
@@ -160,9 +160,6 @@ int mxc_iomux_mode(unsigned int pin_mode);
 
 #define IOMUX_TO_GPIO(iomux_pin) \
        ((iomux_pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT)
-#define IOMUX_TO_IRQ(iomux_pin) \
-       (((iomux_pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT) + \
-       MXC_GPIO_IRQ_START)
 
 /*
  * This enumeration is constructed based on the Section
index 36c8989d9de6b993e13dfd8197dcdc95b46df104..2623e7a2e1907368d9d8e7926122199d9892c89c 100644 (file)
 #define MX51_PAD_EIM_D25__UART2_CTS            IOMUX_PAD(0x414, 0x080, 4, __NA_, 0, MX51_UART_PAD_CTRL)
 #define MX51_PAD_EIM_D25__UART3_RXD            IOMUX_PAD(0x414, 0x080, 3, 0x9f4, 0, MX51_UART_PAD_CTRL)
 #define MX51_PAD_EIM_D25__USBOTG_DATA1         IOMUX_PAD(0x414, 0x080, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D25__GPT_CMPOUT1          IOMUX_PAD(0x414, 0x080, 5, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_D26__EIM_D26              IOMUX_PAD(0x418, 0x084, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_D26__KEY_COL7             IOMUX_PAD(0x418, 0x084, 1, 0x9cc, 0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_D26__UART2_RTS            IOMUX_PAD(0x418, 0x084, 4, 0x9e8, 3, MX51_UART_PAD_CTRL)
 #define MX51_PAD_EIM_D26__UART3_TXD            IOMUX_PAD(0x418, 0x084, 3, __NA_, 0, MX51_UART_PAD_CTRL)
 #define MX51_PAD_EIM_D26__USBOTG_DATA2         IOMUX_PAD(0x418, 0x084, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_EIM_D26__GPT_CMPOUT2          IOMUX_PAD(0x418, 0x084, 5, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_D27__AUD6_RXC             IOMUX_PAD(0x41c, 0x088, 5, 0x8f4, 0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_D27__EIM_D27              IOMUX_PAD(0x41c, 0x088, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_D27__GPIO2_9              IOMUX_PAD(0x41c, 0x088, 1, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_EIM_CRE__EIM_CRE              IOMUX_PAD(0x4a0, 0x100, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_EIM_CRE__GPIO3_2              IOMUX_PAD(0x4a0, 0x100, 1, 0x97c, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_DRAM_CS1__DRAM_CS1            IOMUX_PAD(0x4d0, 0x104, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DRAM_CS1__CCM_CLKO            IOMUX_PAD(0x4d0, 0x104, 1, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_WE_B__GPIO3_3           IOMUX_PAD(0x4e4, 0x108, 3, 0x980, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_NANDF_WE_B__NANDF_WE_B                IOMUX_PAD(0x4e4, 0x108, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_WE_B__PATA_DIOW         IOMUX_PAD(0x4e4, 0x108, 1, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB1__GPIO3_9            IOMUX_PAD(0x4fc, 0x120, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB1__NANDF_RB1          IOMUX_PAD(0x4fc, 0x120, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB1__PATA_IORDY         IOMUX_PAD(0x4fc, 0x120, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB1__GPT_CMPOUT2                IOMUX_PAD(0x4fc, 0x120, 4, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB1__SD4_CMD            IOMUX_PAD(0x4fc, 0x120, 0x15, __NA_, 0, MX51_SDHCI_PAD_CTRL)
 #define MX51_PAD_NANDF_RB2__DISP2_WAIT         IOMUX_PAD(0x500, 0x124, 5, 0x9a8, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB2__ECSPI2_SCLK                IOMUX_PAD(0x500, 0x124, 2, __NA_, 0, MX51_ECSPI_PAD_CTRL)
 #define MX51_PAD_NANDF_RB2__FEC_COL            IOMUX_PAD(0x500, 0x124, 1, 0x94c, 0, MX51_PAD_CTRL_2)
 #define MX51_PAD_NANDF_RB2__GPIO3_10           IOMUX_PAD(0x500, 0x124, 3, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB2__NANDF_RB2          IOMUX_PAD(0x500, 0x124, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_NANDF_RB2__GPT_CMPOUT3                IOMUX_PAD(0x500, 0x124, 4, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB2__USBH3_H3_DP                IOMUX_PAD(0x500, 0x124, 0x17, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB2__USBH3_NXT          IOMUX_PAD(0x500, 0x124, 6, 0xa20, 0, NO_PAD_CTRL)
 #define MX51_PAD_NANDF_RB3__DISP1_WAIT         IOMUX_PAD(0x504, 0x128, 5, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_DISP1_DAT23__DISP2_DAT17      IOMUX_PAD(0x728, 0x328, 5, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_DISP1_DAT23__DISP2_SER_CS     IOMUX_PAD(0x728, 0x328, 4, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_DI1_PIN3__DI1_PIN3            IOMUX_PAD(0x72c, 0x32c, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_DISP_CLK__DI1_DISP_CLK    IOMUX_PAD(0x730, __NA_, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_DI1_PIN2__DI1_PIN2            IOMUX_PAD(0x734, 0x330, 0, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_DI1_PIN15__DI1_PIN15          IOMUX_PAD(0x738, __NA_, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_DI_GP2__DISP1_SER_CLK         IOMUX_PAD(0x740, 0x338, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_DI_GP2__DISP2_WAIT            IOMUX_PAD(0x740, 0x338, 2, 0x9a8, 1, NO_PAD_CTRL)
 #define MX51_PAD_DI_GP3__CSI1_DATA_EN          IOMUX_PAD(0x744, 0x33c, 3, 0x9a0, 1, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_2__PWM1_PWMO            IOMUX_PAD(0x7d4, 0x3cc, 1, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_3__GPIO1_3              IOMUX_PAD(0x7d8, 0x3d0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO1_3__I2C2_SDA             IOMUX_PAD(0x7d8, 0x3d0, 0x12, 0x9bc, 3, MX51_I2C_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__CCM_CLKO2            IOMUX_PAD(0x7d8, 0x3d0, 5, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_3__GPT_CLKIN            IOMUX_PAD(0x7d8, 0x3d0, 6, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_3__PLL2_BYP             IOMUX_PAD(0x7d8, 0x3d0, 7, 0x910, 1, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_3__PWM2_PWMO            IOMUX_PAD(0x7d8, 0x3d0, 1, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_PMIC_INT_REQ__PMIC_INT_REQ    IOMUX_PAD(0x7fc, 0x3d4, 0, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_4__EIM_RDY              IOMUX_PAD(0x804, 0x3d8, 3, 0x938, 1, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_4__GPIO1_4              IOMUX_PAD(0x804, 0x3d8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO1_4__WDOG1_WDOG_B         IOMUX_PAD(0x804, 0x3d8, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_4__GPT_CAPIN1           IOMUX_PAD(0x804, 0x3d8, 6, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_5__CSI2_MCLK            IOMUX_PAD(0x808, 0x3dc, 6, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_5__DISP2_PIN16          IOMUX_PAD(0x808, 0x3dc, 3, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_5__GPIO1_5              IOMUX_PAD(0x808, 0x3dc, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO1_5__WDOG2_WDOG_B         IOMUX_PAD(0x808, 0x3dc, 2, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_5__CCM_CLKO             IOMUX_PAD(0x808, 0x3dc, 5, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_6__DISP2_PIN17          IOMUX_PAD(0x80c, 0x3e0, 4, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_6__GPIO1_6              IOMUX_PAD(0x80c, 0x3e0, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO1_6__REF_EN_B             IOMUX_PAD(0x80c, 0x3e0, 3, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_6__GPT_CAPIN2           IOMUX_PAD(0x80c, 0x3e0, 6, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_7__CCM_OUT_0            IOMUX_PAD(0x810, 0x3e4, 3, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_7__GPIO1_7              IOMUX_PAD(0x810, 0x3e4, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO1_7__SD2_WP               IOMUX_PAD(0x810, 0x3e4, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
 #define MX51_PAD_GPIO1_8__GPIO1_8              IOMUX_PAD(0x814, 0x3e8, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO1_8__SD2_CD               IOMUX_PAD(0x814, 0x3e8, 6, __NA_, 0, MX51_ESDHC_PAD_CTRL)
 #define MX51_PAD_GPIO1_8__USBH3_PWR            IOMUX_PAD(0x814, 0x3e8, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_8__CCM_CLKO2            IOMUX_PAD(0x814, 0x3e8, 4, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_9__CCM_OUT_1            IOMUX_PAD(0x818, 0x3ec, 3, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_9__DISP2_D1_CS          IOMUX_PAD(0x818, 0x3ec, 2, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_9__DISP2_SER_CS         IOMUX_PAD(0x818, 0x3ec, 7, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_9__GPIO1_9              IOMUX_PAD(0x818, 0x3ec, 0, __NA_, 0, MX51_GPIO_PAD_CTRL)
 #define MX51_PAD_GPIO1_9__SD2_LCTL             IOMUX_PAD(0x818, 0x3ec, 6, __NA_, 0, NO_PAD_CTRL)
 #define MX51_PAD_GPIO1_9__USBH3_OC             IOMUX_PAD(0x818, 0x3ec, 1, __NA_, 0, NO_PAD_CTRL)
+#define MX51_PAD_GPIO1_9__CCM_CLKO             IOMUX_PAD(0x818, 0x3ec, 4, __NA_, 0, NO_PAD_CTRL)
 
 #endif /* __MACH_IOMUX_MX51_H__ */
index f7d18046c04ffd49e52f678da6270c288f8958e0..02651a40fe234ea4ca12f43962e97e8212bcd8e9 100644 (file)
 #define GPIO_BOUT_0    (2 << GPIO_BOUT_SHIFT)
 #define GPIO_BOUT_1    (3 << GPIO_BOUT_SHIFT)
 
-#define IRQ_GPIOA(x)  (MXC_GPIO_IRQ_START + x)
-#define IRQ_GPIOB(x)  (IRQ_GPIOA(32) + x)
-#define IRQ_GPIOC(x)  (IRQ_GPIOB(32) + x)
-#define IRQ_GPIOD(x)  (IRQ_GPIOC(32) + x)
-#define IRQ_GPIOE(x)  (IRQ_GPIOD(32) + x)
-#define IRQ_GPIOF(x)  (IRQ_GPIOE(32) + x)
-
 extern int mxc_gpio_mode(int gpio_mode);
 extern int mxc_gpio_setup_multiple_pins(const int *pin_list, unsigned count,
                const char *label);
index a9221f1cc1a0922a0c2dd39e285b5e50e038feae..539e559d18b2c6f1046f3909e22760d43eaea9b1 100644 (file)
@@ -110,10 +110,6 @@ enum ipu_rotate_mode {
        IPU_ROTATE_90_LEFT = 7,
 };
 
-struct ipu_platform_data {
-       unsigned int    irq_base;
-};
-
 /*
  * Enumeration of DI ports for ADC.
  */
index fd9efb044656591c3b28981fd4761994ab558681..d73f5e8ea9cbb15b5304bf3c25874bc5232ff119 100644 (file)
 #ifndef __ASM_ARCH_MXC_IRQS_H__
 #define __ASM_ARCH_MXC_IRQS_H__
 
-#include <asm-generic/gpio.h>
-
-/*
- * SoCs with GIC interrupt controller have 160 IRQs, those with TZIC
- * have 128 IRQs, and those with AVIC have 64.
- *
- * To support single image, the biggest number should be defined on
- * top of the list.
- */
-#if defined CONFIG_ARM_GIC
-#define MXC_INTERNAL_IRQS      160
-#elif defined CONFIG_MXC_TZIC
-#define MXC_INTERNAL_IRQS      128
-#else
-#define MXC_INTERNAL_IRQS      64
-#endif
-
-#define MXC_GPIO_IRQ_START     MXC_INTERNAL_IRQS
-
-/*
- * The next 16 interrupts are for board specific purposes.  Since
- * the kernel can only run on one machine at a time, we can re-use
- * these.  If you need more, increase MXC_BOARD_IRQS, but keep it
- * within sensible limits.
- */
-#define MXC_BOARD_IRQ_START    (MXC_INTERNAL_IRQS + ARCH_NR_GPIOS)
-
-#ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
-#define MXC_BOARD_IRQS  80
-#else
-#define MXC_BOARD_IRQS 16
-#endif
-
-#define MXC_IPU_IRQ_START      (MXC_BOARD_IRQ_START + MXC_BOARD_IRQS)
-
-#ifdef CONFIG_MX3_IPU_IRQS
-#define MX3_IPU_IRQS CONFIG_MX3_IPU_IRQS
-#else
-#define MX3_IPU_IRQS 0
-#endif
-/* REVISIT: Add IPU irqs on IMX51 */
-
-#define NR_IRQS                        (MXC_IPU_IRQ_START + MX3_IPU_IRQS)
-
 extern int imx_irq_set_priority(unsigned char irq, unsigned char prio);
 
 /* all normal IRQs can be FIQs */
index 2b7c08d13e89be022848ced8f176a9760d0ce86d..45bd31cc34d65393c9e8a5ca711a252c5739e62a 100644 (file)
 #define MX1_IO_ADDRESS(x)              IOMEM(MX1_IO_P2V(x))
 
 /* fixed interrput numbers */
-#define MX1_INT_SOFTINT                0
-#define MX1_INT_CSI            6
-#define MX1_DSPA_MAC_INT       7
-#define MX1_DSPA_INT           8
-#define MX1_COMP_INT           9
-#define MX1_MSHC_XINT          10
-#define MX1_GPIO_INT_PORTA     11
-#define MX1_GPIO_INT_PORTB     12
-#define MX1_GPIO_INT_PORTC     13
-#define MX1_INT_LCDC           14
-#define MX1_SIM_INT            15
-#define MX1_SIM_DATA_INT       16
-#define MX1_RTC_INT            17
-#define MX1_RTC_SAMINT         18
-#define MX1_INT_UART2PFERR     19
-#define MX1_INT_UART2RTS       20
-#define MX1_INT_UART2DTR       21
-#define MX1_INT_UART2UARTC     22
-#define MX1_INT_UART2TX                23
-#define MX1_INT_UART2RX                24
-#define MX1_INT_UART1PFERR     25
-#define MX1_INT_UART1RTS       26
-#define MX1_INT_UART1DTR       27
-#define MX1_INT_UART1UARTC     28
-#define MX1_INT_UART1TX                29
-#define MX1_INT_UART1RX                30
-#define MX1_VOICE_DAC_INT      31
-#define MX1_VOICE_ADC_INT      32
-#define MX1_PEN_DATA_INT       33
-#define MX1_PWM_INT            34
-#define MX1_SDHC_INT           35
-#define MX1_INT_I2C            39
-#define MX1_INT_CSPI2          40
-#define MX1_INT_CSPI1          41
-#define MX1_SSI_TX_INT         42
-#define MX1_SSI_TX_ERR_INT     43
-#define MX1_SSI_RX_INT         44
-#define MX1_SSI_RX_ERR_INT     45
-#define MX1_TOUCH_INT          46
-#define MX1_INT_USBD0          47
-#define MX1_INT_USBD1          48
-#define MX1_INT_USBD2          49
-#define MX1_INT_USBD3          50
-#define MX1_INT_USBD4          51
-#define MX1_INT_USBD5          52
-#define MX1_INT_USBD6          53
-#define MX1_BTSYS_INT          55
-#define MX1_BTTIM_INT          56
-#define MX1_BTWUI_INT          57
-#define MX1_TIM2_INT           58
-#define MX1_TIM1_INT           59
-#define MX1_DMA_ERR            60
-#define MX1_DMA_INT            61
-#define MX1_GPIO_INT_PORTD     62
-#define MX1_WDT_INT            63
+#include <asm/irq.h>
+#define MX1_INT_SOFTINT                (NR_IRQS_LEGACY + 0)
+#define MX1_INT_CSI            (NR_IRQS_LEGACY + 6)
+#define MX1_DSPA_MAC_INT       (NR_IRQS_LEGACY + 7)
+#define MX1_DSPA_INT           (NR_IRQS_LEGACY + 8)
+#define MX1_COMP_INT           (NR_IRQS_LEGACY + 9)
+#define MX1_MSHC_XINT          (NR_IRQS_LEGACY + 10)
+#define MX1_GPIO_INT_PORTA     (NR_IRQS_LEGACY + 11)
+#define MX1_GPIO_INT_PORTB     (NR_IRQS_LEGACY + 12)
+#define MX1_GPIO_INT_PORTC     (NR_IRQS_LEGACY + 13)
+#define MX1_INT_LCDC           (NR_IRQS_LEGACY + 14)
+#define MX1_SIM_INT            (NR_IRQS_LEGACY + 15)
+#define MX1_SIM_DATA_INT       (NR_IRQS_LEGACY + 16)
+#define MX1_RTC_INT            (NR_IRQS_LEGACY + 17)
+#define MX1_RTC_SAMINT         (NR_IRQS_LEGACY + 18)
+#define MX1_INT_UART2PFERR     (NR_IRQS_LEGACY + 19)
+#define MX1_INT_UART2RTS       (NR_IRQS_LEGACY + 20)
+#define MX1_INT_UART2DTR       (NR_IRQS_LEGACY + 21)
+#define MX1_INT_UART2UARTC     (NR_IRQS_LEGACY + 22)
+#define MX1_INT_UART2TX                (NR_IRQS_LEGACY + 23)
+#define MX1_INT_UART2RX                (NR_IRQS_LEGACY + 24)
+#define MX1_INT_UART1PFERR     (NR_IRQS_LEGACY + 25)
+#define MX1_INT_UART1RTS       (NR_IRQS_LEGACY + 26)
+#define MX1_INT_UART1DTR       (NR_IRQS_LEGACY + 27)
+#define MX1_INT_UART1UARTC     (NR_IRQS_LEGACY + 28)
+#define MX1_INT_UART1TX                (NR_IRQS_LEGACY + 29)
+#define MX1_INT_UART1RX                (NR_IRQS_LEGACY + 30)
+#define MX1_VOICE_DAC_INT      (NR_IRQS_LEGACY + 31)
+#define MX1_VOICE_ADC_INT      (NR_IRQS_LEGACY + 32)
+#define MX1_PEN_DATA_INT       (NR_IRQS_LEGACY + 33)
+#define MX1_PWM_INT            (NR_IRQS_LEGACY + 34)
+#define MX1_SDHC_INT           (NR_IRQS_LEGACY + 35)
+#define MX1_INT_I2C            (NR_IRQS_LEGACY + 39)
+#define MX1_INT_CSPI2          (NR_IRQS_LEGACY + 40)
+#define MX1_INT_CSPI1          (NR_IRQS_LEGACY + 41)
+#define MX1_SSI_TX_INT         (NR_IRQS_LEGACY + 42)
+#define MX1_SSI_TX_ERR_INT     (NR_IRQS_LEGACY + 43)
+#define MX1_SSI_RX_INT         (NR_IRQS_LEGACY + 44)
+#define MX1_SSI_RX_ERR_INT     (NR_IRQS_LEGACY + 45)
+#define MX1_TOUCH_INT          (NR_IRQS_LEGACY + 46)
+#define MX1_INT_USBD0          (NR_IRQS_LEGACY + 47)
+#define MX1_INT_USBD1          (NR_IRQS_LEGACY + 48)
+#define MX1_INT_USBD2          (NR_IRQS_LEGACY + 49)
+#define MX1_INT_USBD3          (NR_IRQS_LEGACY + 50)
+#define MX1_INT_USBD4          (NR_IRQS_LEGACY + 51)
+#define MX1_INT_USBD5          (NR_IRQS_LEGACY + 52)
+#define MX1_INT_USBD6          (NR_IRQS_LEGACY + 53)
+#define MX1_BTSYS_INT          (NR_IRQS_LEGACY + 55)
+#define MX1_BTTIM_INT          (NR_IRQS_LEGACY + 56)
+#define MX1_BTWUI_INT          (NR_IRQS_LEGACY + 57)
+#define MX1_TIM2_INT           (NR_IRQS_LEGACY + 58)
+#define MX1_TIM1_INT           (NR_IRQS_LEGACY + 59)
+#define MX1_DMA_ERR            (NR_IRQS_LEGACY + 60)
+#define MX1_DMA_INT            (NR_IRQS_LEGACY + 61)
+#define MX1_GPIO_INT_PORTD     (NR_IRQS_LEGACY + 62)
+#define MX1_WDT_INT            (NR_IRQS_LEGACY + 63)
 
 /* DMA */
 #define MX1_DMA_REQ_UART3_T            2
index 6cd049ebbd8d8e94a29393427b5fa14266d5fae8..468738aa997f7c7ecc383c1ea7dd4d3ad18d2c61 100644 (file)
 #define MX21_IO_ADDRESS(x)             IOMEM(MX21_IO_P2V(x))
 
 /* fixed interrupt numbers */
-#define MX21_INT_CSPI3         6
-#define MX21_INT_GPIO          8
-#define MX21_INT_FIRI          9
-#define MX21_INT_SDHC2         10
-#define MX21_INT_SDHC1         11
-#define MX21_INT_I2C           12
-#define MX21_INT_SSI2          13
-#define MX21_INT_SSI1          14
-#define MX21_INT_CSPI2         15
-#define MX21_INT_CSPI1         16
-#define MX21_INT_UART4         17
-#define MX21_INT_UART3         18
-#define MX21_INT_UART2         19
-#define MX21_INT_UART1         20
-#define MX21_INT_KPP           21
-#define MX21_INT_RTC           22
-#define MX21_INT_PWM           23
-#define MX21_INT_GPT3          24
-#define MX21_INT_GPT2          25
-#define MX21_INT_GPT1          26
-#define MX21_INT_WDOG          27
-#define MX21_INT_PCMCIA                28
-#define MX21_INT_NFC           29
-#define MX21_INT_BMI           30
-#define MX21_INT_CSI           31
-#define MX21_INT_DMACH0                32
-#define MX21_INT_DMACH1                33
-#define MX21_INT_DMACH2                34
-#define MX21_INT_DMACH3                35
-#define MX21_INT_DMACH4                36
-#define MX21_INT_DMACH5                37
-#define MX21_INT_DMACH6                38
-#define MX21_INT_DMACH7                39
-#define MX21_INT_DMACH8                40
-#define MX21_INT_DMACH9                41
-#define MX21_INT_DMACH10       42
-#define MX21_INT_DMACH11       43
-#define MX21_INT_DMACH12       44
-#define MX21_INT_DMACH13       45
-#define MX21_INT_DMACH14       46
-#define MX21_INT_DMACH15       47
-#define MX21_INT_EMMAENC       49
-#define MX21_INT_EMMADEC       50
-#define MX21_INT_EMMAPRP       51
-#define MX21_INT_EMMAPP                52
-#define MX21_INT_USBWKUP       53
-#define MX21_INT_USBDMA                54
-#define MX21_INT_USBHOST       55
-#define MX21_INT_USBFUNC       56
-#define MX21_INT_USBMNP                57
-#define MX21_INT_USBCTRL       58
-#define MX21_INT_SLCDC         60
-#define MX21_INT_LCDC          61
+#include <asm/irq.h>
+#define MX21_INT_CSPI3         (NR_IRQS_LEGACY + 6)
+#define MX21_INT_GPIO          (NR_IRQS_LEGACY + 8)
+#define MX21_INT_FIRI          (NR_IRQS_LEGACY + 9)
+#define MX21_INT_SDHC2         (NR_IRQS_LEGACY + 10)
+#define MX21_INT_SDHC1         (NR_IRQS_LEGACY + 11)
+#define MX21_INT_I2C           (NR_IRQS_LEGACY + 12)
+#define MX21_INT_SSI2          (NR_IRQS_LEGACY + 13)
+#define MX21_INT_SSI1          (NR_IRQS_LEGACY + 14)
+#define MX21_INT_CSPI2         (NR_IRQS_LEGACY + 15)
+#define MX21_INT_CSPI1         (NR_IRQS_LEGACY + 16)
+#define MX21_INT_UART4         (NR_IRQS_LEGACY + 17)
+#define MX21_INT_UART3         (NR_IRQS_LEGACY + 18)
+#define MX21_INT_UART2         (NR_IRQS_LEGACY + 19)
+#define MX21_INT_UART1         (NR_IRQS_LEGACY + 20)
+#define MX21_INT_KPP           (NR_IRQS_LEGACY + 21)
+#define MX21_INT_RTC           (NR_IRQS_LEGACY + 22)
+#define MX21_INT_PWM           (NR_IRQS_LEGACY + 23)
+#define MX21_INT_GPT3          (NR_IRQS_LEGACY + 24)
+#define MX21_INT_GPT2          (NR_IRQS_LEGACY + 25)
+#define MX21_INT_GPT1          (NR_IRQS_LEGACY + 26)
+#define MX21_INT_WDOG          (NR_IRQS_LEGACY + 27)
+#define MX21_INT_PCMCIA                (NR_IRQS_LEGACY + 28)
+#define MX21_INT_NFC           (NR_IRQS_LEGACY + 29)
+#define MX21_INT_BMI           (NR_IRQS_LEGACY + 30)
+#define MX21_INT_CSI           (NR_IRQS_LEGACY + 31)
+#define MX21_INT_DMACH0                (NR_IRQS_LEGACY + 32)
+#define MX21_INT_DMACH1                (NR_IRQS_LEGACY + 33)
+#define MX21_INT_DMACH2                (NR_IRQS_LEGACY + 34)
+#define MX21_INT_DMACH3                (NR_IRQS_LEGACY + 35)
+#define MX21_INT_DMACH4                (NR_IRQS_LEGACY + 36)
+#define MX21_INT_DMACH5                (NR_IRQS_LEGACY + 37)
+#define MX21_INT_DMACH6                (NR_IRQS_LEGACY + 38)
+#define MX21_INT_DMACH7                (NR_IRQS_LEGACY + 39)
+#define MX21_INT_DMACH8                (NR_IRQS_LEGACY + 40)
+#define MX21_INT_DMACH9                (NR_IRQS_LEGACY + 41)
+#define MX21_INT_DMACH10       (NR_IRQS_LEGACY + 42)
+#define MX21_INT_DMACH11       (NR_IRQS_LEGACY + 43)
+#define MX21_INT_DMACH12       (NR_IRQS_LEGACY + 44)
+#define MX21_INT_DMACH13       (NR_IRQS_LEGACY + 45)
+#define MX21_INT_DMACH14       (NR_IRQS_LEGACY + 46)
+#define MX21_INT_DMACH15       (NR_IRQS_LEGACY + 47)
+#define MX21_INT_EMMAENC       (NR_IRQS_LEGACY + 49)
+#define MX21_INT_EMMADEC       (NR_IRQS_LEGACY + 50)
+#define MX21_INT_EMMAPRP       (NR_IRQS_LEGACY + 51)
+#define MX21_INT_EMMAPP                (NR_IRQS_LEGACY + 52)
+#define MX21_INT_USBWKUP       (NR_IRQS_LEGACY + 53)
+#define MX21_INT_USBDMA                (NR_IRQS_LEGACY + 54)
+#define MX21_INT_USBHOST       (NR_IRQS_LEGACY + 55)
+#define MX21_INT_USBFUNC       (NR_IRQS_LEGACY + 56)
+#define MX21_INT_USBMNP                (NR_IRQS_LEGACY + 57)
+#define MX21_INT_USBCTRL       (NR_IRQS_LEGACY + 58)
+#define MX21_INT_SLCDC         (NR_IRQS_LEGACY + 60)
+#define MX21_INT_LCDC          (NR_IRQS_LEGACY + 61)
 
 /* fixed DMA request numbers */
 #define MX21_DMA_REQ_CSPI3_RX  1
index ccebf5ba12f06f7927e44c24c12937e8b084f660..627d94f1b010d32d09091bf4f025fabb617bde03 100644 (file)
 #define MX25_IO_P2V(x)                 IMX_IO_P2V(x)
 #define MX25_IO_ADDRESS(x)             IOMEM(MX25_IO_P2V(x))
 
-#define MX25_INT_CSPI3         0
-#define MX25_INT_I2C1          3
-#define MX25_INT_I2C2          4
-#define MX25_INT_UART4         5
-#define MX25_INT_ESDHC2                8
-#define MX25_INT_ESDHC1                9
-#define MX25_INT_I2C3          10
-#define MX25_INT_SSI2          11
-#define MX25_INT_SSI1          12
-#define MX25_INT_CSPI2         13
-#define MX25_INT_CSPI1         14
-#define MX25_INT_GPIO3         16
-#define MX25_INT_CSI           17
-#define MX25_INT_UART3         18
-#define MX25_INT_GPIO4         23
-#define MX25_INT_KPP           24
-#define MX25_INT_DRYICE                25
-#define MX25_INT_PWM1          26
-#define MX25_INT_UART2         32
-#define MX25_INT_NFC           33
-#define MX25_INT_SDMA          34
-#define MX25_INT_USB_HS                35
-#define MX25_INT_PWM2          36
-#define MX25_INT_USB_OTG       37
-#define MX25_INT_LCDC          39
-#define MX25_INT_UART5         40
-#define MX25_INT_PWM3          41
-#define MX25_INT_PWM4          42
-#define MX25_INT_CAN1          43
-#define MX25_INT_CAN2          44
-#define MX25_INT_UART1         45
-#define MX25_INT_GPIO2         51
-#define MX25_INT_GPIO1         52
-#define MX25_INT_FEC           57
+/*
+ * Interrupt numbers
+ */
+#include <asm/irq.h>
+#define MX25_INT_CSPI3         (NR_IRQS_LEGACY + 0)
+#define MX25_INT_I2C1          (NR_IRQS_LEGACY + 3)
+#define MX25_INT_I2C2          (NR_IRQS_LEGACY + 4)
+#define MX25_INT_UART4         (NR_IRQS_LEGACY + 5)
+#define MX25_INT_ESDHC2                (NR_IRQS_LEGACY + 8)
+#define MX25_INT_ESDHC1                (NR_IRQS_LEGACY + 9)
+#define MX25_INT_I2C3          (NR_IRQS_LEGACY + 10)
+#define MX25_INT_SSI2          (NR_IRQS_LEGACY + 11)
+#define MX25_INT_SSI1          (NR_IRQS_LEGACY + 12)
+#define MX25_INT_CSPI2         (NR_IRQS_LEGACY + 13)
+#define MX25_INT_CSPI1         (NR_IRQS_LEGACY + 14)
+#define MX25_INT_GPIO3         (NR_IRQS_LEGACY + 16)
+#define MX25_INT_CSI           (NR_IRQS_LEGACY + 17)
+#define MX25_INT_UART3         (NR_IRQS_LEGACY + 18)
+#define MX25_INT_GPIO4         (NR_IRQS_LEGACY + 23)
+#define MX25_INT_KPP           (NR_IRQS_LEGACY + 24)
+#define MX25_INT_DRYICE                (NR_IRQS_LEGACY + 25)
+#define MX25_INT_PWM1          (NR_IRQS_LEGACY + 26)
+#define MX25_INT_UART2         (NR_IRQS_LEGACY + 32)
+#define MX25_INT_NFC           (NR_IRQS_LEGACY + 33)
+#define MX25_INT_SDMA          (NR_IRQS_LEGACY + 34)
+#define MX25_INT_USB_HS                (NR_IRQS_LEGACY + 35)
+#define MX25_INT_PWM2          (NR_IRQS_LEGACY + 36)
+#define MX25_INT_USB_OTG       (NR_IRQS_LEGACY + 37)
+#define MX25_INT_LCDC          (NR_IRQS_LEGACY + 39)
+#define MX25_INT_UART5         (NR_IRQS_LEGACY + 40)
+#define MX25_INT_PWM3          (NR_IRQS_LEGACY + 41)
+#define MX25_INT_PWM4          (NR_IRQS_LEGACY + 42)
+#define MX25_INT_CAN1          (NR_IRQS_LEGACY + 43)
+#define MX25_INT_CAN2          (NR_IRQS_LEGACY + 44)
+#define MX25_INT_UART1         (NR_IRQS_LEGACY + 45)
+#define MX25_INT_GPIO2         (NR_IRQS_LEGACY + 51)
+#define MX25_INT_GPIO1         (NR_IRQS_LEGACY + 52)
+#define MX25_INT_FEC           (NR_IRQS_LEGACY + 57)
 
 #define MX25_DMA_REQ_SSI2_RX1  22
 #define MX25_DMA_REQ_SSI2_TX1  23
index 6265357284d746158a3be99c18bf9005ffc5e154..e074616d54ca5e034e0b6331b8235c7a72971a37 100644 (file)
 #define MX27_IO_ADDRESS(x)             IOMEM(MX27_IO_P2V(x))
 
 /* fixed interrupt numbers */
-#define MX27_INT_I2C2          1
-#define MX27_INT_GPT6          2
-#define MX27_INT_GPT5          3
-#define MX27_INT_GPT4          4
-#define MX27_INT_RTIC          5
-#define MX27_INT_CSPI3         6
-#define MX27_INT_SDHC          7
-#define MX27_INT_GPIO          8
-#define MX27_INT_SDHC3         9
-#define MX27_INT_SDHC2         10
-#define MX27_INT_SDHC1         11
-#define MX27_INT_I2C1          12
-#define MX27_INT_SSI2          13
-#define MX27_INT_SSI1          14
-#define MX27_INT_CSPI2         15
-#define MX27_INT_CSPI1         16
-#define MX27_INT_UART4         17
-#define MX27_INT_UART3         18
-#define MX27_INT_UART2         19
-#define MX27_INT_UART1         20
-#define MX27_INT_KPP           21
-#define MX27_INT_RTC           22
-#define MX27_INT_PWM           23
-#define MX27_INT_GPT3          24
-#define MX27_INT_GPT2          25
-#define MX27_INT_GPT1          26
-#define MX27_INT_WDOG          27
-#define MX27_INT_PCMCIA                28
-#define MX27_INT_NFC           29
-#define MX27_INT_ATA           30
-#define MX27_INT_CSI           31
-#define MX27_INT_DMACH0                32
-#define MX27_INT_DMACH1                33
-#define MX27_INT_DMACH2                34
-#define MX27_INT_DMACH3                35
-#define MX27_INT_DMACH4                36
-#define MX27_INT_DMACH5                37
-#define MX27_INT_DMACH6                38
-#define MX27_INT_DMACH7                39
-#define MX27_INT_DMACH8                40
-#define MX27_INT_DMACH9                41
-#define MX27_INT_DMACH10       42
-#define MX27_INT_DMACH11       43
-#define MX27_INT_DMACH12       44
-#define MX27_INT_DMACH13       45
-#define MX27_INT_DMACH14       46
-#define MX27_INT_DMACH15       47
-#define MX27_INT_UART6         48
-#define MX27_INT_UART5         49
-#define MX27_INT_FEC           50
-#define MX27_INT_EMMAPRP       51
-#define MX27_INT_EMMAPP                52
-#define MX27_INT_VPU           53
-#define MX27_INT_USB_HS1       54
-#define MX27_INT_USB_HS2       55
-#define MX27_INT_USB_OTG       56
-#define MX27_INT_SCC_SMN       57
-#define MX27_INT_SCC_SCM       58
-#define MX27_INT_SAHARA                59
-#define MX27_INT_SLCDC         60
-#define MX27_INT_LCDC          61
-#define MX27_INT_IIM           62
-#define MX27_INT_CCM           63
+#include <asm/irq.h>
+#define MX27_INT_I2C2          (NR_IRQS_LEGACY + 1)
+#define MX27_INT_GPT6          (NR_IRQS_LEGACY + 2)
+#define MX27_INT_GPT5          (NR_IRQS_LEGACY + 3)
+#define MX27_INT_GPT4          (NR_IRQS_LEGACY + 4)
+#define MX27_INT_RTIC          (NR_IRQS_LEGACY + 5)
+#define MX27_INT_CSPI3         (NR_IRQS_LEGACY + 6)
+#define MX27_INT_SDHC          (NR_IRQS_LEGACY + 7)
+#define MX27_INT_GPIO          (NR_IRQS_LEGACY + 8)
+#define MX27_INT_SDHC3         (NR_IRQS_LEGACY + 9)
+#define MX27_INT_SDHC2         (NR_IRQS_LEGACY + 10)
+#define MX27_INT_SDHC1         (NR_IRQS_LEGACY + 11)
+#define MX27_INT_I2C1          (NR_IRQS_LEGACY + 12)
+#define MX27_INT_SSI2          (NR_IRQS_LEGACY + 13)
+#define MX27_INT_SSI1          (NR_IRQS_LEGACY + 14)
+#define MX27_INT_CSPI2         (NR_IRQS_LEGACY + 15)
+#define MX27_INT_CSPI1         (NR_IRQS_LEGACY + 16)
+#define MX27_INT_UART4         (NR_IRQS_LEGACY + 17)
+#define MX27_INT_UART3         (NR_IRQS_LEGACY + 18)
+#define MX27_INT_UART2         (NR_IRQS_LEGACY + 19)
+#define MX27_INT_UART1         (NR_IRQS_LEGACY + 20)
+#define MX27_INT_KPP           (NR_IRQS_LEGACY + 21)
+#define MX27_INT_RTC           (NR_IRQS_LEGACY + 22)
+#define MX27_INT_PWM           (NR_IRQS_LEGACY + 23)
+#define MX27_INT_GPT3          (NR_IRQS_LEGACY + 24)
+#define MX27_INT_GPT2          (NR_IRQS_LEGACY + 25)
+#define MX27_INT_GPT1          (NR_IRQS_LEGACY + 26)
+#define MX27_INT_WDOG          (NR_IRQS_LEGACY + 27)
+#define MX27_INT_PCMCIA                (NR_IRQS_LEGACY + 28)
+#define MX27_INT_NFC           (NR_IRQS_LEGACY + 29)
+#define MX27_INT_ATA           (NR_IRQS_LEGACY + 30)
+#define MX27_INT_CSI           (NR_IRQS_LEGACY + 31)
+#define MX27_INT_DMACH0                (NR_IRQS_LEGACY + 32)
+#define MX27_INT_DMACH1                (NR_IRQS_LEGACY + 33)
+#define MX27_INT_DMACH2                (NR_IRQS_LEGACY + 34)
+#define MX27_INT_DMACH3                (NR_IRQS_LEGACY + 35)
+#define MX27_INT_DMACH4                (NR_IRQS_LEGACY + 36)
+#define MX27_INT_DMACH5                (NR_IRQS_LEGACY + 37)
+#define MX27_INT_DMACH6                (NR_IRQS_LEGACY + 38)
+#define MX27_INT_DMACH7                (NR_IRQS_LEGACY + 39)
+#define MX27_INT_DMACH8                (NR_IRQS_LEGACY + 40)
+#define MX27_INT_DMACH9                (NR_IRQS_LEGACY + 41)
+#define MX27_INT_DMACH10       (NR_IRQS_LEGACY + 42)
+#define MX27_INT_DMACH11       (NR_IRQS_LEGACY + 43)
+#define MX27_INT_DMACH12       (NR_IRQS_LEGACY + 44)
+#define MX27_INT_DMACH13       (NR_IRQS_LEGACY + 45)
+#define MX27_INT_DMACH14       (NR_IRQS_LEGACY + 46)
+#define MX27_INT_DMACH15       (NR_IRQS_LEGACY + 47)
+#define MX27_INT_UART6         (NR_IRQS_LEGACY + 48)
+#define MX27_INT_UART5         (NR_IRQS_LEGACY + 49)
+#define MX27_INT_FEC           (NR_IRQS_LEGACY + 50)
+#define MX27_INT_EMMAPRP       (NR_IRQS_LEGACY + 51)
+#define MX27_INT_EMMAPP                (NR_IRQS_LEGACY + 52)
+#define MX27_INT_VPU           (NR_IRQS_LEGACY + 53)
+#define MX27_INT_USB_HS1       (NR_IRQS_LEGACY + 54)
+#define MX27_INT_USB_HS2       (NR_IRQS_LEGACY + 55)
+#define MX27_INT_USB_OTG       (NR_IRQS_LEGACY + 56)
+#define MX27_INT_SCC_SMN       (NR_IRQS_LEGACY + 57)
+#define MX27_INT_SCC_SCM       (NR_IRQS_LEGACY + 58)
+#define MX27_INT_SAHARA                (NR_IRQS_LEGACY + 59)
+#define MX27_INT_SLCDC         (NR_IRQS_LEGACY + 60)
+#define MX27_INT_LCDC          (NR_IRQS_LEGACY + 61)
+#define MX27_INT_IIM           (NR_IRQS_LEGACY + 62)
+#define MX27_INT_CCM           (NR_IRQS_LEGACY + 63)
 
 /* fixed DMA request numbers */
 #define MX27_DMA_REQ_CSPI3_RX  1
index 6d07839fdec222d0459148c748736d1bc9c3ea36..11642f5b224c041403ef54d8f3bc755dbdd8afe6 100644 (file)
 #define MX2x_CSI_BASE_ADDR                     (MX2x_SAHB1_BASE_ADDR + 0x0000)
 
 /* fixed interrupt numbers */
-#define MX2x_INT_CSPI3         6
-#define MX2x_INT_GPIO          8
-#define MX2x_INT_SDHC2         10
-#define MX2x_INT_SDHC1         11
-#define MX2x_INT_I2C           12
-#define MX2x_INT_SSI2          13
-#define MX2x_INT_SSI1          14
-#define MX2x_INT_CSPI2         15
-#define MX2x_INT_CSPI1         16
-#define MX2x_INT_UART4         17
-#define MX2x_INT_UART3         18
-#define MX2x_INT_UART2         19
-#define MX2x_INT_UART1         20
-#define MX2x_INT_KPP           21
-#define MX2x_INT_RTC           22
-#define MX2x_INT_PWM           23
-#define MX2x_INT_GPT3          24
-#define MX2x_INT_GPT2          25
-#define MX2x_INT_GPT1          26
-#define MX2x_INT_WDOG          27
-#define MX2x_INT_PCMCIA                28
-#define MX2x_INT_NANDFC                29
-#define MX2x_INT_CSI           31
-#define MX2x_INT_DMACH0                32
-#define MX2x_INT_DMACH1                33
-#define MX2x_INT_DMACH2                34
-#define MX2x_INT_DMACH3                35
-#define MX2x_INT_DMACH4                36
-#define MX2x_INT_DMACH5                37
-#define MX2x_INT_DMACH6                38
-#define MX2x_INT_DMACH7                39
-#define MX2x_INT_DMACH8                40
-#define MX2x_INT_DMACH9                41
-#define MX2x_INT_DMACH10       42
-#define MX2x_INT_DMACH11       43
-#define MX2x_INT_DMACH12       44
-#define MX2x_INT_DMACH13       45
-#define MX2x_INT_DMACH14       46
-#define MX2x_INT_DMACH15       47
-#define MX2x_INT_EMMAPRP       51
-#define MX2x_INT_EMMAPP                52
-#define MX2x_INT_SLCDC         60
-#define MX2x_INT_LCDC          61
+#include <asm/irq.h>
+#define MX2x_INT_CSPI3         (NR_IRQS_LEGACY + 6)
+#define MX2x_INT_GPIO          (NR_IRQS_LEGACY + 8)
+#define MX2x_INT_SDHC2         (NR_IRQS_LEGACY + 10)
+#define MX2x_INT_SDHC1         (NR_IRQS_LEGACY + 11)
+#define MX2x_INT_I2C           (NR_IRQS_LEGACY + 12)
+#define MX2x_INT_SSI2          (NR_IRQS_LEGACY + 13)
+#define MX2x_INT_SSI1          (NR_IRQS_LEGACY + 14)
+#define MX2x_INT_CSPI2         (NR_IRQS_LEGACY + 15)
+#define MX2x_INT_CSPI1         (NR_IRQS_LEGACY + 16)
+#define MX2x_INT_UART4         (NR_IRQS_LEGACY + 17)
+#define MX2x_INT_UART3         (NR_IRQS_LEGACY + 18)
+#define MX2x_INT_UART2         (NR_IRQS_LEGACY + 19)
+#define MX2x_INT_UART1         (NR_IRQS_LEGACY + 20)
+#define MX2x_INT_KPP           (NR_IRQS_LEGACY + 21)
+#define MX2x_INT_RTC           (NR_IRQS_LEGACY + 22)
+#define MX2x_INT_PWM           (NR_IRQS_LEGACY + 23)
+#define MX2x_INT_GPT3          (NR_IRQS_LEGACY + 24)
+#define MX2x_INT_GPT2          (NR_IRQS_LEGACY + 25)
+#define MX2x_INT_GPT1          (NR_IRQS_LEGACY + 26)
+#define MX2x_INT_WDOG          (NR_IRQS_LEGACY + 27)
+#define MX2x_INT_PCMCIA                (NR_IRQS_LEGACY + 28)
+#define MX2x_INT_NANDFC                (NR_IRQS_LEGACY + 29)
+#define MX2x_INT_CSI           (NR_IRQS_LEGACY + 31)
+#define MX2x_INT_DMACH0                (NR_IRQS_LEGACY + 32)
+#define MX2x_INT_DMACH1                (NR_IRQS_LEGACY + 33)
+#define MX2x_INT_DMACH2                (NR_IRQS_LEGACY + 34)
+#define MX2x_INT_DMACH3                (NR_IRQS_LEGACY + 35)
+#define MX2x_INT_DMACH4                (NR_IRQS_LEGACY + 36)
+#define MX2x_INT_DMACH5                (NR_IRQS_LEGACY + 37)
+#define MX2x_INT_DMACH6                (NR_IRQS_LEGACY + 38)
+#define MX2x_INT_DMACH7                (NR_IRQS_LEGACY + 39)
+#define MX2x_INT_DMACH8                (NR_IRQS_LEGACY + 40)
+#define MX2x_INT_DMACH9                (NR_IRQS_LEGACY + 41)
+#define MX2x_INT_DMACH10       (NR_IRQS_LEGACY + 42)
+#define MX2x_INT_DMACH11       (NR_IRQS_LEGACY + 43)
+#define MX2x_INT_DMACH12       (NR_IRQS_LEGACY + 44)
+#define MX2x_INT_DMACH13       (NR_IRQS_LEGACY + 45)
+#define MX2x_INT_DMACH14       (NR_IRQS_LEGACY + 46)
+#define MX2x_INT_DMACH15       (NR_IRQS_LEGACY + 47)
+#define MX2x_INT_EMMAPRP       (NR_IRQS_LEGACY + 51)
+#define MX2x_INT_EMMAPP                (NR_IRQS_LEGACY + 52)
+#define MX2x_INT_SLCDC         (NR_IRQS_LEGACY + 60)
+#define MX2x_INT_LCDC          (NR_IRQS_LEGACY + 61)
 
 /* fixed DMA request numbers */
 #define MX2x_DMA_REQ_CSPI3_RX  1
index e27619e442c0462e597b68f5105b4d95242d795c..dbced61d9fdae0a58f0932c4c8f75a4aee325cd6 100644 (file)
 #define MX31_IO_P2V(x)                 IMX_IO_P2V(x)
 #define MX31_IO_ADDRESS(x)             IOMEM(MX31_IO_P2V(x))
 
-#define MX31_INT_I2C3          3
-#define MX31_INT_I2C2          4
-#define MX31_INT_MPEG4_ENCODER 5
-#define MX31_INT_RTIC          6
-#define MX31_INT_FIRI          7
-#define MX31_INT_SDHC2         8
-#define MX31_INT_SDHC1         9
-#define MX31_INT_I2C1          10
-#define MX31_INT_SSI2          11
-#define MX31_INT_SSI1          12
-#define MX31_INT_CSPI2         13
-#define MX31_INT_CSPI1         14
-#define MX31_INT_ATA           15
-#define MX31_INT_MBX           16
-#define MX31_INT_CSPI3         17
-#define MX31_INT_UART3         18
-#define MX31_INT_IIM           19
-#define MX31_INT_SIM2          20
-#define MX31_INT_SIM1          21
-#define MX31_INT_RNGA          22
-#define MX31_INT_EVTMON                23
-#define MX31_INT_KPP           24
-#define MX31_INT_RTC           25
-#define MX31_INT_PWM           26
-#define MX31_INT_EPIT2         27
-#define MX31_INT_EPIT1         28
-#define MX31_INT_GPT           29
-#define MX31_INT_POWER_FAIL    30
-#define MX31_INT_CCM_DVFS      31
-#define MX31_INT_UART2         32
-#define MX31_INT_NFC           33
-#define MX31_INT_SDMA          34
-#define MX31_INT_USB_HS1       35
-#define MX31_INT_USB_HS2       36
-#define MX31_INT_USB_OTG       37
-#define MX31_INT_MSHC1         39
-#define MX31_INT_MSHC2         40
-#define MX31_INT_IPU_ERR       41
-#define MX31_INT_IPU_SYN       42
-#define MX31_INT_UART1         45
-#define MX31_INT_UART4         46
-#define MX31_INT_UART5         47
-#define MX31_INT_ECT           48
-#define MX31_INT_SCC_SCM       49
-#define MX31_INT_SCC_SMN       50
-#define MX31_INT_GPIO2         51
-#define MX31_INT_GPIO1         52
-#define MX31_INT_CCM           53
-#define MX31_INT_PCMCIA                54
-#define MX31_INT_WDOG          55
-#define MX31_INT_GPIO3         56
-#define MX31_INT_EXT_POWER     58
-#define MX31_INT_EXT_TEMPER    59
-#define MX31_INT_EXT_SENSOR60  60
-#define MX31_INT_EXT_SENSOR61  61
-#define MX31_INT_EXT_WDOG      62
-#define MX31_INT_EXT_TV                63
+/*
+ * Interrupt numbers
+ */
+#include <asm/irq.h>
+#define MX31_INT_I2C3          (NR_IRQS_LEGACY + 3)
+#define MX31_INT_I2C2          (NR_IRQS_LEGACY + 4)
+#define MX31_INT_MPEG4_ENCODER (NR_IRQS_LEGACY + 5)
+#define MX31_INT_RTIC          (NR_IRQS_LEGACY + 6)
+#define MX31_INT_FIRI          (NR_IRQS_LEGACY + 7)
+#define MX31_INT_SDHC2         (NR_IRQS_LEGACY + 8)
+#define MX31_INT_SDHC1         (NR_IRQS_LEGACY + 9)
+#define MX31_INT_I2C1          (NR_IRQS_LEGACY + 10)
+#define MX31_INT_SSI2          (NR_IRQS_LEGACY + 11)
+#define MX31_INT_SSI1          (NR_IRQS_LEGACY + 12)
+#define MX31_INT_CSPI2         (NR_IRQS_LEGACY + 13)
+#define MX31_INT_CSPI1         (NR_IRQS_LEGACY + 14)
+#define MX31_INT_ATA           (NR_IRQS_LEGACY + 15)
+#define MX31_INT_MBX           (NR_IRQS_LEGACY + 16)
+#define MX31_INT_CSPI3         (NR_IRQS_LEGACY + 17)
+#define MX31_INT_UART3         (NR_IRQS_LEGACY + 18)
+#define MX31_INT_IIM           (NR_IRQS_LEGACY + 19)
+#define MX31_INT_SIM2          (NR_IRQS_LEGACY + 20)
+#define MX31_INT_SIM1          (NR_IRQS_LEGACY + 21)
+#define MX31_INT_RNGA          (NR_IRQS_LEGACY + 22)
+#define MX31_INT_EVTMON                (NR_IRQS_LEGACY + 23)
+#define MX31_INT_KPP           (NR_IRQS_LEGACY + 24)
+#define MX31_INT_RTC           (NR_IRQS_LEGACY + 25)
+#define MX31_INT_PWM           (NR_IRQS_LEGACY + 26)
+#define MX31_INT_EPIT2         (NR_IRQS_LEGACY + 27)
+#define MX31_INT_EPIT1         (NR_IRQS_LEGACY + 28)
+#define MX31_INT_GPT           (NR_IRQS_LEGACY + 29)
+#define MX31_INT_POWER_FAIL    (NR_IRQS_LEGACY + 30)
+#define MX31_INT_CCM_DVFS      (NR_IRQS_LEGACY + 31)
+#define MX31_INT_UART2         (NR_IRQS_LEGACY + 32)
+#define MX31_INT_NFC           (NR_IRQS_LEGACY + 33)
+#define MX31_INT_SDMA          (NR_IRQS_LEGACY + 34)
+#define MX31_INT_USB_HS1       (NR_IRQS_LEGACY + 35)
+#define MX31_INT_USB_HS2       (NR_IRQS_LEGACY + 36)
+#define MX31_INT_USB_OTG       (NR_IRQS_LEGACY + 37)
+#define MX31_INT_MSHC1         (NR_IRQS_LEGACY + 39)
+#define MX31_INT_MSHC2         (NR_IRQS_LEGACY + 40)
+#define MX31_INT_IPU_ERR       (NR_IRQS_LEGACY + 41)
+#define MX31_INT_IPU_SYN       (NR_IRQS_LEGACY + 42)
+#define MX31_INT_UART1         (NR_IRQS_LEGACY + 45)
+#define MX31_INT_UART4         (NR_IRQS_LEGACY + 46)
+#define MX31_INT_UART5         (NR_IRQS_LEGACY + 47)
+#define MX31_INT_ECT           (NR_IRQS_LEGACY + 48)
+#define MX31_INT_SCC_SCM       (NR_IRQS_LEGACY + 49)
+#define MX31_INT_SCC_SMN       (NR_IRQS_LEGACY + 50)
+#define MX31_INT_GPIO2         (NR_IRQS_LEGACY + 51)
+#define MX31_INT_GPIO1         (NR_IRQS_LEGACY + 52)
+#define MX31_INT_CCM           (NR_IRQS_LEGACY + 53)
+#define MX31_INT_PCMCIA                (NR_IRQS_LEGACY + 54)
+#define MX31_INT_WDOG          (NR_IRQS_LEGACY + 55)
+#define MX31_INT_GPIO3         (NR_IRQS_LEGACY + 56)
+#define MX31_INT_EXT_POWER     (NR_IRQS_LEGACY + 58)
+#define MX31_INT_EXT_TEMPER    (NR_IRQS_LEGACY + 59)
+#define MX31_INT_EXT_SENSOR60  (NR_IRQS_LEGACY + 60)
+#define MX31_INT_EXT_SENSOR61  (NR_IRQS_LEGACY + 61)
+#define MX31_INT_EXT_WDOG      (NR_IRQS_LEGACY + 62)
+#define MX31_INT_EXT_TV                (NR_IRQS_LEGACY + 63)
 
 #define MX31_DMA_REQ_SDHC1     20
 #define MX31_DMA_REQ_SDHC2     21
index 80965a99aa55b0b0cc38462716b975fdef2eb060..2af5d3a699c7271d56ba6d610ed1bb331547dd7d 100644 (file)
 /*
  * Interrupt numbers
  */
-#define MX35_INT_OWIRE         2
-#define MX35_INT_I2C3          3
-#define MX35_INT_I2C2          4
-#define MX35_INT_RTIC          6
-#define MX35_INT_ESDHC1                7
-#define MX35_INT_ESDHC2                8
-#define MX35_INT_ESDHC3                9
-#define MX35_INT_I2C1          10
-#define MX35_INT_SSI1          11
-#define MX35_INT_SSI2          12
-#define MX35_INT_CSPI2         13
-#define MX35_INT_CSPI1         14
-#define MX35_INT_ATA           15
-#define MX35_INT_GPU2D         16
-#define MX35_INT_ASRC          17
-#define MX35_INT_UART3         18
-#define MX35_INT_IIM           19
-#define MX35_INT_RNGA          22
-#define MX35_INT_EVTMON                23
-#define MX35_INT_KPP           24
-#define MX35_INT_RTC           25
-#define MX35_INT_PWM           26
-#define MX35_INT_EPIT2         27
-#define MX35_INT_EPIT1         28
-#define MX35_INT_GPT           29
-#define MX35_INT_POWER_FAIL    30
-#define MX35_INT_UART2         32
-#define MX35_INT_NFC           33
-#define MX35_INT_SDMA          34
-#define MX35_INT_USB_HS                35
-#define MX35_INT_USB_OTG       37
-#define MX35_INT_MSHC1         39
-#define MX35_INT_ESAI          40
-#define MX35_INT_IPU_ERR       41
-#define MX35_INT_IPU_SYN       42
-#define MX35_INT_CAN1          43
-#define MX35_INT_CAN2          44
-#define MX35_INT_UART1         45
-#define MX35_INT_MLB           46
-#define MX35_INT_SPDIF         47
-#define MX35_INT_ECT           48
-#define MX35_INT_SCC_SCM       49
-#define MX35_INT_SCC_SMN       50
-#define MX35_INT_GPIO2         51
-#define MX35_INT_GPIO1         52
-#define MX35_INT_WDOG          55
-#define MX35_INT_GPIO3         56
-#define MX35_INT_FEC           57
-#define MX35_INT_EXT_POWER     58
-#define MX35_INT_EXT_TEMPER    59
-#define MX35_INT_EXT_SENSOR60  60
-#define MX35_INT_EXT_SENSOR61  61
-#define MX35_INT_EXT_WDOG      62
-#define MX35_INT_EXT_TV                63
+#include <asm/irq.h>
+#define MX35_INT_OWIRE         (NR_IRQS_LEGACY + 2)
+#define MX35_INT_I2C3          (NR_IRQS_LEGACY + 3)
+#define MX35_INT_I2C2          (NR_IRQS_LEGACY + 4)
+#define MX35_INT_RTIC          (NR_IRQS_LEGACY + 6)
+#define MX35_INT_ESDHC1                (NR_IRQS_LEGACY + 7)
+#define MX35_INT_ESDHC2                (NR_IRQS_LEGACY + 8)
+#define MX35_INT_ESDHC3                (NR_IRQS_LEGACY + 9)
+#define MX35_INT_I2C1          (NR_IRQS_LEGACY + 10)
+#define MX35_INT_SSI1          (NR_IRQS_LEGACY + 11)
+#define MX35_INT_SSI2          (NR_IRQS_LEGACY + 12)
+#define MX35_INT_CSPI2         (NR_IRQS_LEGACY + 13)
+#define MX35_INT_CSPI1         (NR_IRQS_LEGACY + 14)
+#define MX35_INT_ATA           (NR_IRQS_LEGACY + 15)
+#define MX35_INT_GPU2D         (NR_IRQS_LEGACY + 16)
+#define MX35_INT_ASRC          (NR_IRQS_LEGACY + 17)
+#define MX35_INT_UART3         (NR_IRQS_LEGACY + 18)
+#define MX35_INT_IIM           (NR_IRQS_LEGACY + 19)
+#define MX35_INT_RNGA          (NR_IRQS_LEGACY + 22)
+#define MX35_INT_EVTMON                (NR_IRQS_LEGACY + 23)
+#define MX35_INT_KPP           (NR_IRQS_LEGACY + 24)
+#define MX35_INT_RTC           (NR_IRQS_LEGACY + 25)
+#define MX35_INT_PWM           (NR_IRQS_LEGACY + 26)
+#define MX35_INT_EPIT2         (NR_IRQS_LEGACY + 27)
+#define MX35_INT_EPIT1         (NR_IRQS_LEGACY + 28)
+#define MX35_INT_GPT           (NR_IRQS_LEGACY + 29)
+#define MX35_INT_POWER_FAIL    (NR_IRQS_LEGACY + 30)
+#define MX35_INT_UART2         (NR_IRQS_LEGACY + 32)
+#define MX35_INT_NFC           (NR_IRQS_LEGACY + 33)
+#define MX35_INT_SDMA          (NR_IRQS_LEGACY + 34)
+#define MX35_INT_USB_HS                (NR_IRQS_LEGACY + 35)
+#define MX35_INT_USB_OTG       (NR_IRQS_LEGACY + 37)
+#define MX35_INT_MSHC1         (NR_IRQS_LEGACY + 39)
+#define MX35_INT_ESAI          (NR_IRQS_LEGACY + 40)
+#define MX35_INT_IPU_ERR       (NR_IRQS_LEGACY + 41)
+#define MX35_INT_IPU_SYN       (NR_IRQS_LEGACY + 42)
+#define MX35_INT_CAN1          (NR_IRQS_LEGACY + 43)
+#define MX35_INT_CAN2          (NR_IRQS_LEGACY + 44)
+#define MX35_INT_UART1         (NR_IRQS_LEGACY + 45)
+#define MX35_INT_MLB           (NR_IRQS_LEGACY + 46)
+#define MX35_INT_SPDIF         (NR_IRQS_LEGACY + 47)
+#define MX35_INT_ECT           (NR_IRQS_LEGACY + 48)
+#define MX35_INT_SCC_SCM       (NR_IRQS_LEGACY + 49)
+#define MX35_INT_SCC_SMN       (NR_IRQS_LEGACY + 50)
+#define MX35_INT_GPIO2         (NR_IRQS_LEGACY + 51)
+#define MX35_INT_GPIO1         (NR_IRQS_LEGACY + 52)
+#define MX35_INT_WDOG          (NR_IRQS_LEGACY + 55)
+#define MX35_INT_GPIO3         (NR_IRQS_LEGACY + 56)
+#define MX35_INT_FEC           (NR_IRQS_LEGACY + 57)
+#define MX35_INT_EXT_POWER     (NR_IRQS_LEGACY + 58)
+#define MX35_INT_EXT_TEMPER    (NR_IRQS_LEGACY + 59)
+#define MX35_INT_EXT_SENSOR60  (NR_IRQS_LEGACY + 60)
+#define MX35_INT_EXT_SENSOR61  (NR_IRQS_LEGACY + 61)
+#define MX35_INT_EXT_WDOG      (NR_IRQS_LEGACY + 62)
+#define MX35_INT_EXT_TV                (NR_IRQS_LEGACY + 63)
 
 #define MX35_DMA_REQ_SSI2_RX1   22
 #define MX35_DMA_REQ_SSI2_TX1   23
index 30dbf424583eddc5b83a6693ebca15de5ade0997..96fb4fbc8ad7c34dd4ea9d9324a655470db58318 100644 (file)
 /*
  * Interrupt numbers
  */
-#define MX3x_INT_I2C3          3
-#define MX3x_INT_I2C2          4
-#define MX3x_INT_RTIC          6
-#define MX3x_INT_I2C           10
-#define MX3x_INT_CSPI2         13
-#define MX3x_INT_CSPI1         14
-#define MX3x_INT_ATA           15
-#define MX3x_INT_UART3         18
-#define MX3x_INT_IIM           19
-#define MX3x_INT_RNGA          22
-#define MX3x_INT_EVTMON                23
-#define MX3x_INT_KPP           24
-#define MX3x_INT_RTC           25
-#define MX3x_INT_PWM           26
-#define MX3x_INT_EPIT2         27
-#define MX3x_INT_EPIT1         28
-#define MX3x_INT_GPT           29
-#define MX3x_INT_POWER_FAIL    30
-#define MX3x_INT_UART2         32
-#define MX3x_INT_NANDFC                33
-#define MX3x_INT_SDMA          34
-#define MX3x_INT_MSHC1         39
-#define MX3x_INT_IPU_ERR       41
-#define MX3x_INT_IPU_SYN       42
-#define MX3x_INT_UART1         45
-#define MX3x_INT_ECT           48
-#define MX3x_INT_SCC_SCM       49
-#define MX3x_INT_SCC_SMN       50
-#define MX3x_INT_GPIO2         51
-#define MX3x_INT_GPIO1         52
-#define MX3x_INT_WDOG          55
-#define MX3x_INT_GPIO3         56
-#define MX3x_INT_EXT_POWER     58
-#define MX3x_INT_EXT_TEMPER    59
-#define MX3x_INT_EXT_SENSOR60  60
-#define MX3x_INT_EXT_SENSOR61  61
-#define MX3x_INT_EXT_WDOG      62
-#define MX3x_INT_EXT_TV                63
+#include <asm/irq.h>
+#define MX3x_INT_I2C3          (NR_IRQS_LEGACY + 3)
+#define MX3x_INT_I2C2          (NR_IRQS_LEGACY + 4)
+#define MX3x_INT_RTIC          (NR_IRQS_LEGACY + 6)
+#define MX3x_INT_I2C           (NR_IRQS_LEGACY + 10)
+#define MX3x_INT_CSPI2         (NR_IRQS_LEGACY + 13)
+#define MX3x_INT_CSPI1         (NR_IRQS_LEGACY + 14)
+#define MX3x_INT_ATA           (NR_IRQS_LEGACY + 15)
+#define MX3x_INT_UART3         (NR_IRQS_LEGACY + 18)
+#define MX3x_INT_IIM           (NR_IRQS_LEGACY + 19)
+#define MX3x_INT_RNGA          (NR_IRQS_LEGACY + 22)
+#define MX3x_INT_EVTMON                (NR_IRQS_LEGACY + 23)
+#define MX3x_INT_KPP           (NR_IRQS_LEGACY + 24)
+#define MX3x_INT_RTC           (NR_IRQS_LEGACY + 25)
+#define MX3x_INT_PWM           (NR_IRQS_LEGACY + 26)
+#define MX3x_INT_EPIT2         (NR_IRQS_LEGACY + 27)
+#define MX3x_INT_EPIT1         (NR_IRQS_LEGACY + 28)
+#define MX3x_INT_GPT           (NR_IRQS_LEGACY + 29)
+#define MX3x_INT_POWER_FAIL    (NR_IRQS_LEGACY + 30)
+#define MX3x_INT_UART2         (NR_IRQS_LEGACY + 32)
+#define MX3x_INT_NANDFC                (NR_IRQS_LEGACY + 33)
+#define MX3x_INT_SDMA          (NR_IRQS_LEGACY + 34)
+#define MX3x_INT_MSHC1         (NR_IRQS_LEGACY + 39)
+#define MX3x_INT_IPU_ERR       (NR_IRQS_LEGACY + 41)
+#define MX3x_INT_IPU_SYN       (NR_IRQS_LEGACY + 42)
+#define MX3x_INT_UART1         (NR_IRQS_LEGACY + 45)
+#define MX3x_INT_ECT           (NR_IRQS_LEGACY + 48)
+#define MX3x_INT_SCC_SCM       (NR_IRQS_LEGACY + 49)
+#define MX3x_INT_SCC_SMN       (NR_IRQS_LEGACY + 50)
+#define MX3x_INT_GPIO2         (NR_IRQS_LEGACY + 51)
+#define MX3x_INT_GPIO1         (NR_IRQS_LEGACY + 52)
+#define MX3x_INT_WDOG          (NR_IRQS_LEGACY + 55)
+#define MX3x_INT_GPIO3         (NR_IRQS_LEGACY + 56)
+#define MX3x_INT_EXT_POWER     (NR_IRQS_LEGACY + 58)
+#define MX3x_INT_EXT_TEMPER    (NR_IRQS_LEGACY + 59)
+#define MX3x_INT_EXT_SENSOR60  (NR_IRQS_LEGACY + 60)
+#define MX3x_INT_EXT_SENSOR61  (NR_IRQS_LEGACY + 61)
+#define MX3x_INT_EXT_WDOG      (NR_IRQS_LEGACY + 62)
+#define MX3x_INT_EXT_TV                (NR_IRQS_LEGACY + 63)
 
 #define MX3x_PROD_SIGNATURE            0x1     /* For MX31 */
 
index 5f2da75a47f4a14ddee0234b590079b8ae4f0208..09ac19c1570c6e9c39cd1984725fea23d6a72aa3 100644 (file)
 /*
  * Interrupt numbers
  */
-#define MX50_INT_MMC_SDHC1     1
-#define MX50_INT_MMC_SDHC2     2
-#define MX50_INT_MMC_SDHC3     3
-#define MX50_INT_MMC_SDHC4     4
-#define MX50_INT_DAP           5
-#define MX50_INT_SDMA          6
-#define MX50_INT_IOMUX         7
-#define MX50_INT_UART4         13
-#define MX50_INT_USB_H1                14
-#define MX50_INT_USB_OTG       18
-#define MX50_INT_DATABAHN      19
-#define MX50_INT_ELCDIF                20
-#define MX50_INT_EPXP          21
-#define MX50_INT_SRTC_NTZ      24
-#define MX50_INT_SRTC_TZ       25
-#define MX50_INT_EPDC          27
-#define MX50_INT_NIC           28
-#define MX50_INT_SSI1          29
-#define MX50_INT_SSI2          30
-#define MX50_INT_UART1         31
-#define MX50_INT_UART2         32
-#define MX50_INT_UART3         33
-#define MX50_INT_RESV34                34
-#define MX50_INT_RESV35                35
-#define MX50_INT_CSPI1         36
-#define MX50_INT_CSPI2         37
-#define MX50_INT_CSPI          38
-#define MX50_INT_GPT           39
-#define MX50_INT_EPIT1         40
-#define MX50_INT_GPIO1_INT7    42
-#define MX50_INT_GPIO1_INT6    43
-#define MX50_INT_GPIO1_INT5    44
-#define MX50_INT_GPIO1_INT4    45
-#define MX50_INT_GPIO1_INT3    46
-#define MX50_INT_GPIO1_INT2    47
-#define MX50_INT_GPIO1_INT1    48
-#define MX50_INT_GPIO1_INT0    49
-#define MX50_INT_GPIO1_LOW     50
-#define MX50_INT_GPIO1_HIGH    51
-#define MX50_INT_GPIO2_LOW     52
-#define MX50_INT_GPIO2_HIGH    53
-#define MX50_INT_GPIO3_LOW     54
-#define MX50_INT_GPIO3_HIGH    55
-#define MX50_INT_GPIO4_LOW     56
-#define MX50_INT_GPIO4_HIGH    57
-#define MX50_INT_WDOG1         58
-#define MX50_INT_KPP           60
-#define MX50_INT_PWM1          61
-#define MX50_INT_I2C1          62
-#define MX50_INT_I2C2          63
-#define MX50_INT_I2C3          64
-#define MX50_INT_RESV65                65
-#define MX50_INT_DCDC          66
-#define MX50_INT_THERMAL_ALARM 67
-#define MX50_INT_ANA3          68
-#define MX50_INT_ANA4          69
-#define MX50_INT_CCM1          71
-#define MX50_INT_CCM2          72
-#define MX50_INT_GPC1          73
-#define MX50_INT_GPC2          74
-#define MX50_INT_SRC           75
-#define MX50_INT_NM            76
-#define MX50_INT_PMU           77
-#define MX50_INT_CTI_IRQ       78
-#define MX50_INT_CTI1_TG0      79
-#define MX50_INT_CTI1_TG1      80
-#define MX50_INT_GPU2_IRQ      84
-#define MX50_INT_GPU2_BUSY     85
-#define MX50_INT_UART5         86
-#define MX50_INT_FEC           87
-#define MX50_INT_OWIRE         88
-#define MX50_INT_CTI1_TG2      89
-#define MX50_INT_SJC           90
-#define MX50_INT_DCP_CHAN1_3   91
-#define MX50_INT_DCP_CHAN0     92
-#define MX50_INT_PWM2          94
-#define MX50_INT_RNGB          97
-#define MX50_INT_CTI1_TG3      98
-#define MX50_INT_RAWNAND_BCH   100
-#define MX50_INT_RAWNAND_GPMI  102
-#define MX50_INT_GPIO5_LOW     103
-#define MX50_INT_GPIO5_HIGH    104
-#define MX50_INT_GPIO6_LOW     105
-#define MX50_INT_GPIO6_HIGH    106
-#define MX50_INT_MSHC          109
-#define MX50_INT_APBHDMA_CHAN0 110
-#define MX50_INT_APBHDMA_CHAN1 111
-#define MX50_INT_APBHDMA_CHAN2 112
-#define MX50_INT_APBHDMA_CHAN3 113
-#define MX50_INT_APBHDMA_CHAN4 114
-#define MX50_INT_APBHDMA_CHAN5 115
-#define MX50_INT_APBHDMA_CHAN6 116
-#define MX50_INT_APBHDMA_CHAN7 117
+#include <asm/irq.h>
+#define MX50_INT_MMC_SDHC1     (NR_IRQS_LEGACY + 1)
+#define MX50_INT_MMC_SDHC2     (NR_IRQS_LEGACY + 2)
+#define MX50_INT_MMC_SDHC3     (NR_IRQS_LEGACY + 3)
+#define MX50_INT_MMC_SDHC4     (NR_IRQS_LEGACY + 4)
+#define MX50_INT_DAP           (NR_IRQS_LEGACY + 5)
+#define MX50_INT_SDMA          (NR_IRQS_LEGACY + 6)
+#define MX50_INT_IOMUX         (NR_IRQS_LEGACY + 7)
+#define MX50_INT_UART4         (NR_IRQS_LEGACY + 13)
+#define MX50_INT_USB_H1                (NR_IRQS_LEGACY + 14)
+#define MX50_INT_USB_OTG       (NR_IRQS_LEGACY + 18)
+#define MX50_INT_DATABAHN      (NR_IRQS_LEGACY + 19)
+#define MX50_INT_ELCDIF                (NR_IRQS_LEGACY + 20)
+#define MX50_INT_EPXP          (NR_IRQS_LEGACY + 21)
+#define MX50_INT_SRTC_NTZ      (NR_IRQS_LEGACY + 24)
+#define MX50_INT_SRTC_TZ       (NR_IRQS_LEGACY + 25)
+#define MX50_INT_EPDC          (NR_IRQS_LEGACY + 27)
+#define MX50_INT_NIC           (NR_IRQS_LEGACY + 28)
+#define MX50_INT_SSI1          (NR_IRQS_LEGACY + 29)
+#define MX50_INT_SSI2          (NR_IRQS_LEGACY + 30)
+#define MX50_INT_UART1         (NR_IRQS_LEGACY + 31)
+#define MX50_INT_UART2         (NR_IRQS_LEGACY + 32)
+#define MX50_INT_UART3         (NR_IRQS_LEGACY + 33)
+#define MX50_INT_RESV34                (NR_IRQS_LEGACY + 34)
+#define MX50_INT_RESV35                (NR_IRQS_LEGACY + 35)
+#define MX50_INT_CSPI1         (NR_IRQS_LEGACY + 36)
+#define MX50_INT_CSPI2         (NR_IRQS_LEGACY + 37)
+#define MX50_INT_CSPI          (NR_IRQS_LEGACY + 38)
+#define MX50_INT_GPT           (NR_IRQS_LEGACY + 39)
+#define MX50_INT_EPIT1         (NR_IRQS_LEGACY + 40)
+#define MX50_INT_GPIO1_INT7    (NR_IRQS_LEGACY + 42)
+#define MX50_INT_GPIO1_INT6    (NR_IRQS_LEGACY + 43)
+#define MX50_INT_GPIO1_INT5    (NR_IRQS_LEGACY + 44)
+#define MX50_INT_GPIO1_INT4    (NR_IRQS_LEGACY + 45)
+#define MX50_INT_GPIO1_INT3    (NR_IRQS_LEGACY + 46)
+#define MX50_INT_GPIO1_INT2    (NR_IRQS_LEGACY + 47)
+#define MX50_INT_GPIO1_INT1    (NR_IRQS_LEGACY + 48)
+#define MX50_INT_GPIO1_INT0    (NR_IRQS_LEGACY + 49)
+#define MX50_INT_GPIO1_LOW     (NR_IRQS_LEGACY + 50)
+#define MX50_INT_GPIO1_HIGH    (NR_IRQS_LEGACY + 51)
+#define MX50_INT_GPIO2_LOW     (NR_IRQS_LEGACY + 52)
+#define MX50_INT_GPIO2_HIGH    (NR_IRQS_LEGACY + 53)
+#define MX50_INT_GPIO3_LOW     (NR_IRQS_LEGACY + 54)
+#define MX50_INT_GPIO3_HIGH    (NR_IRQS_LEGACY + 55)
+#define MX50_INT_GPIO4_LOW     (NR_IRQS_LEGACY + 56)
+#define MX50_INT_GPIO4_HIGH    (NR_IRQS_LEGACY + 57)
+#define MX50_INT_WDOG1         (NR_IRQS_LEGACY + 58)
+#define MX50_INT_KPP           (NR_IRQS_LEGACY + 60)
+#define MX50_INT_PWM1          (NR_IRQS_LEGACY + 61)
+#define MX50_INT_I2C1          (NR_IRQS_LEGACY + 62)
+#define MX50_INT_I2C2          (NR_IRQS_LEGACY + 63)
+#define MX50_INT_I2C3          (NR_IRQS_LEGACY + 64)
+#define MX50_INT_RESV65                (NR_IRQS_LEGACY + 65)
+#define MX50_INT_DCDC          (NR_IRQS_LEGACY + 66)
+#define MX50_INT_THERMAL_ALARM (NR_IRQS_LEGACY + 67)
+#define MX50_INT_ANA3          (NR_IRQS_LEGACY + 68)
+#define MX50_INT_ANA4          (NR_IRQS_LEGACY + 69)
+#define MX50_INT_CCM1          (NR_IRQS_LEGACY + 71)
+#define MX50_INT_CCM2          (NR_IRQS_LEGACY + 72)
+#define MX50_INT_GPC1          (NR_IRQS_LEGACY + 73)
+#define MX50_INT_GPC2          (NR_IRQS_LEGACY + 74)
+#define MX50_INT_SRC           (NR_IRQS_LEGACY + 75)
+#define MX50_INT_NM            (NR_IRQS_LEGACY + 76)
+#define MX50_INT_PMU           (NR_IRQS_LEGACY + 77)
+#define MX50_INT_CTI_IRQ       (NR_IRQS_LEGACY + 78)
+#define MX50_INT_CTI1_TG0      (NR_IRQS_LEGACY + 79)
+#define MX50_INT_CTI1_TG1      (NR_IRQS_LEGACY + 80)
+#define MX50_INT_GPU2_IRQ      (NR_IRQS_LEGACY + 84)
+#define MX50_INT_GPU2_BUSY     (NR_IRQS_LEGACY + 85)
+#define MX50_INT_UART5         (NR_IRQS_LEGACY + 86)
+#define MX50_INT_FEC           (NR_IRQS_LEGACY + 87)
+#define MX50_INT_OWIRE         (NR_IRQS_LEGACY + 88)
+#define MX50_INT_CTI1_TG2      (NR_IRQS_LEGACY + 89)
+#define MX50_INT_SJC           (NR_IRQS_LEGACY + 90)
+#define MX50_INT_DCP_CHAN1_3   (NR_IRQS_LEGACY + 91)
+#define MX50_INT_DCP_CHAN0     (NR_IRQS_LEGACY + 92)
+#define MX50_INT_PWM2          (NR_IRQS_LEGACY + 94)
+#define MX50_INT_RNGB          (NR_IRQS_LEGACY + 97)
+#define MX50_INT_CTI1_TG3      (NR_IRQS_LEGACY + 98)
+#define MX50_INT_RAWNAND_BCH   (NR_IRQS_LEGACY + 100)
+#define MX50_INT_RAWNAND_GPMI  (NR_IRQS_LEGACY + 102)
+#define MX50_INT_GPIO5_LOW     (NR_IRQS_LEGACY + 103)
+#define MX50_INT_GPIO5_HIGH    (NR_IRQS_LEGACY + 104)
+#define MX50_INT_GPIO6_LOW     (NR_IRQS_LEGACY + 105)
+#define MX50_INT_GPIO6_HIGH    (NR_IRQS_LEGACY + 106)
+#define MX50_INT_MSHC          (NR_IRQS_LEGACY + 109)
+#define MX50_INT_APBHDMA_CHAN0 (NR_IRQS_LEGACY + 110)
+#define MX50_INT_APBHDMA_CHAN1 (NR_IRQS_LEGACY + 111)
+#define MX50_INT_APBHDMA_CHAN2 (NR_IRQS_LEGACY + 112)
+#define MX50_INT_APBHDMA_CHAN3 (NR_IRQS_LEGACY + 113)
+#define MX50_INT_APBHDMA_CHAN4 (NR_IRQS_LEGACY + 114)
+#define MX50_INT_APBHDMA_CHAN5 (NR_IRQS_LEGACY + 115)
+#define MX50_INT_APBHDMA_CHAN6 (NR_IRQS_LEGACY + 116)
+#define MX50_INT_APBHDMA_CHAN7 (NR_IRQS_LEGACY + 117)
 
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
 extern int mx50_revision(void);
index cdf07c65ec1e3b76aa9a8d84f409f83df5afcead..af844f76261a4584c48f0039d109366627d4e6e6 100644 (file)
 /*
  * Interrupt numbers
  */
-#define MX51_INT_BASE                  0
-#define MX51_INT_RESV0                 0
-#define MX51_INT_ESDHC1                        1
-#define MX51_INT_ESDHC2                        2
-#define MX51_INT_ESDHC3                        3
-#define MX51_INT_ESDHC4                        4
-#define MX51_INT_RESV5                 5
-#define MX51_INT_SDMA                  6
-#define MX51_INT_IOMUX                 7
-#define MX51_INT_NFC                   8
-#define MX51_INT_VPU                   9
-#define MX51_INT_IPU_ERR               10
-#define MX51_INT_IPU_SYN               11
-#define MX51_INT_GPU                   12
-#define MX51_INT_RESV13                        13
-#define MX51_INT_USB_HS1               14
-#define MX51_INT_EMI                   15
-#define MX51_INT_USB_HS2               16
-#define MX51_INT_USB_HS3               17
-#define MX51_INT_USB_OTG               18
-#define MX51_INT_SAHARA_H0             19
-#define MX51_INT_SAHARA_H1             20
-#define MX51_INT_SCC_SMN               21
-#define MX51_INT_SCC_STZ               22
-#define MX51_INT_SCC_SCM               23
-#define MX51_INT_SRTC_NTZ              24
-#define MX51_INT_SRTC_TZ               25
-#define MX51_INT_RTIC                  26
-#define MX51_INT_CSU                   27
-#define MX51_INT_SLIM_B                        28
-#define MX51_INT_SSI1                  29
-#define MX51_INT_SSI2                  30
-#define MX51_INT_UART1                 31
-#define MX51_INT_UART2                 32
-#define MX51_INT_UART3                 33
-#define MX51_INT_RESV34                        34
-#define MX51_INT_RESV35                        35
-#define MX51_INT_ECSPI1                        36
-#define MX51_INT_ECSPI2                        37
-#define MX51_INT_CSPI                  38
-#define MX51_INT_GPT                   39
-#define MX51_INT_EPIT1                 40
-#define MX51_INT_EPIT2                 41
-#define MX51_INT_GPIO1_INT7            42
-#define MX51_INT_GPIO1_INT6            43
-#define MX51_INT_GPIO1_INT5            44
-#define MX51_INT_GPIO1_INT4            45
-#define MX51_INT_GPIO1_INT3            46
-#define MX51_INT_GPIO1_INT2            47
-#define MX51_INT_GPIO1_INT1            48
-#define MX51_INT_GPIO1_INT0            49
-#define MX51_INT_GPIO1_LOW             50
-#define MX51_INT_GPIO1_HIGH            51
-#define MX51_INT_GPIO2_LOW             52
-#define MX51_INT_GPIO2_HIGH            53
-#define MX51_INT_GPIO3_LOW             54
-#define MX51_INT_GPIO3_HIGH            55
-#define MX51_INT_GPIO4_LOW             56
-#define MX51_INT_GPIO4_HIGH            57
-#define MX51_INT_WDOG1                 58
-#define MX51_INT_WDOG2                 59
-#define MX51_INT_KPP                   60
-#define MX51_INT_PWM1                  61
-#define MX51_INT_I2C1                  62
-#define MX51_INT_I2C2                  63
-#define MX51_INT_HS_I2C                        64
-#define MX51_INT_RESV65                        65
-#define MX51_INT_RESV66                        66
-#define MX51_INT_SIM_IPB               67
-#define MX51_INT_SIM_DAT               68
-#define MX51_INT_IIM                   69
-#define MX51_INT_ATA                   70
-#define MX51_INT_CCM1                  71
-#define MX51_INT_CCM2                  72
-#define MX51_INT_GPC1                          73
-#define MX51_INT_GPC2                  74
-#define MX51_INT_SRC                   75
-#define MX51_INT_NM                    76
-#define MX51_INT_PMU                   77
-#define MX51_INT_CTI_IRQ               78
-#define MX51_INT_CTI1_TG0              79
-#define MX51_INT_CTI1_TG1              80
-#define MX51_INT_MCG_ERR               81
-#define MX51_INT_MCG_TMR               82
-#define MX51_INT_MCG_FUNC              83
-#define MX51_INT_GPU2_IRQ              84
-#define MX51_INT_GPU2_BUSY             85
-#define MX51_INT_RESV86                        86
-#define MX51_INT_FEC                   87
-#define MX51_INT_OWIRE                 88
-#define MX51_INT_CTI1_TG2              89
-#define MX51_INT_SJC                   90
-#define MX51_INT_SPDIF                 91
-#define MX51_INT_TVE                   92
-#define MX51_INT_FIRI                  93
-#define MX51_INT_PWM2                  94
-#define MX51_INT_SLIM_EXP              95
-#define MX51_INT_SSI3                  96
-#define MX51_INT_EMI_BOOT              97
-#define MX51_INT_CTI1_TG3              98
-#define MX51_INT_SMC_RX                        99
-#define MX51_INT_VPU_IDLE              100
-#define MX51_INT_EMI_NFC               101
-#define MX51_INT_GPU_IDLE              102
+#include <asm/irq.h>
+#define MX51_INT_BASE                  (NR_IRQS_LEGACY + 0)
+#define MX51_INT_RESV0                 (NR_IRQS_LEGACY + 0)
+#define MX51_INT_ESDHC1                        (NR_IRQS_LEGACY + 1)
+#define MX51_INT_ESDHC2                        (NR_IRQS_LEGACY + 2)
+#define MX51_INT_ESDHC3                        (NR_IRQS_LEGACY + 3)
+#define MX51_INT_ESDHC4                        (NR_IRQS_LEGACY + 4)
+#define MX51_INT_RESV5                 (NR_IRQS_LEGACY + 5)
+#define MX51_INT_SDMA                  (NR_IRQS_LEGACY + 6)
+#define MX51_INT_IOMUX                 (NR_IRQS_LEGACY + 7)
+#define MX51_INT_NFC                   (NR_IRQS_LEGACY + 8)
+#define MX51_INT_VPU                   (NR_IRQS_LEGACY + 9)
+#define MX51_INT_IPU_ERR               (NR_IRQS_LEGACY + 10)
+#define MX51_INT_IPU_SYN               (NR_IRQS_LEGACY + 11)
+#define MX51_INT_GPU                   (NR_IRQS_LEGACY + 12)
+#define MX51_INT_RESV13                        (NR_IRQS_LEGACY + 13)
+#define MX51_INT_USB_HS1               (NR_IRQS_LEGACY + 14)
+#define MX51_INT_EMI                   (NR_IRQS_LEGACY + 15)
+#define MX51_INT_USB_HS2               (NR_IRQS_LEGACY + 16)
+#define MX51_INT_USB_HS3               (NR_IRQS_LEGACY + 17)
+#define MX51_INT_USB_OTG               (NR_IRQS_LEGACY + 18)
+#define MX51_INT_SAHARA_H0             (NR_IRQS_LEGACY + 19)
+#define MX51_INT_SAHARA_H1             (NR_IRQS_LEGACY + 20)
+#define MX51_INT_SCC_SMN               (NR_IRQS_LEGACY + 21)
+#define MX51_INT_SCC_STZ               (NR_IRQS_LEGACY + 22)
+#define MX51_INT_SCC_SCM               (NR_IRQS_LEGACY + 23)
+#define MX51_INT_SRTC_NTZ              (NR_IRQS_LEGACY + 24)
+#define MX51_INT_SRTC_TZ               (NR_IRQS_LEGACY + 25)
+#define MX51_INT_RTIC                  (NR_IRQS_LEGACY + 26)
+#define MX51_INT_CSU                   (NR_IRQS_LEGACY + 27)
+#define MX51_INT_SLIM_B                        (NR_IRQS_LEGACY + 28)
+#define MX51_INT_SSI1                  (NR_IRQS_LEGACY + 29)
+#define MX51_INT_SSI2                  (NR_IRQS_LEGACY + 30)
+#define MX51_INT_UART1                 (NR_IRQS_LEGACY + 31)
+#define MX51_INT_UART2                 (NR_IRQS_LEGACY + 32)
+#define MX51_INT_UART3                 (NR_IRQS_LEGACY + 33)
+#define MX51_INT_RESV34                        (NR_IRQS_LEGACY + 34)
+#define MX51_INT_RESV35                        (NR_IRQS_LEGACY + 35)
+#define MX51_INT_ECSPI1                        (NR_IRQS_LEGACY + 36)
+#define MX51_INT_ECSPI2                        (NR_IRQS_LEGACY + 37)
+#define MX51_INT_CSPI                  (NR_IRQS_LEGACY + 38)
+#define MX51_INT_GPT                   (NR_IRQS_LEGACY + 39)
+#define MX51_INT_EPIT1                 (NR_IRQS_LEGACY + 40)
+#define MX51_INT_EPIT2                 (NR_IRQS_LEGACY + 41)
+#define MX51_INT_GPIO1_INT7            (NR_IRQS_LEGACY + 42)
+#define MX51_INT_GPIO1_INT6            (NR_IRQS_LEGACY + 43)
+#define MX51_INT_GPIO1_INT5            (NR_IRQS_LEGACY + 44)
+#define MX51_INT_GPIO1_INT4            (NR_IRQS_LEGACY + 45)
+#define MX51_INT_GPIO1_INT3            (NR_IRQS_LEGACY + 46)
+#define MX51_INT_GPIO1_INT2            (NR_IRQS_LEGACY + 47)
+#define MX51_INT_GPIO1_INT1            (NR_IRQS_LEGACY + 48)
+#define MX51_INT_GPIO1_INT0            (NR_IRQS_LEGACY + 49)
+#define MX51_INT_GPIO1_LOW             (NR_IRQS_LEGACY + 50)
+#define MX51_INT_GPIO1_HIGH            (NR_IRQS_LEGACY + 51)
+#define MX51_INT_GPIO2_LOW             (NR_IRQS_LEGACY + 52)
+#define MX51_INT_GPIO2_HIGH            (NR_IRQS_LEGACY + 53)
+#define MX51_INT_GPIO3_LOW             (NR_IRQS_LEGACY + 54)
+#define MX51_INT_GPIO3_HIGH            (NR_IRQS_LEGACY + 55)
+#define MX51_INT_GPIO4_LOW             (NR_IRQS_LEGACY + 56)
+#define MX51_INT_GPIO4_HIGH            (NR_IRQS_LEGACY + 57)
+#define MX51_INT_WDOG1                 (NR_IRQS_LEGACY + 58)
+#define MX51_INT_WDOG2                 (NR_IRQS_LEGACY + 59)
+#define MX51_INT_KPP                   (NR_IRQS_LEGACY + 60)
+#define MX51_INT_PWM1                  (NR_IRQS_LEGACY + 61)
+#define MX51_INT_I2C1                  (NR_IRQS_LEGACY + 62)
+#define MX51_INT_I2C2                  (NR_IRQS_LEGACY + 63)
+#define MX51_INT_HS_I2C                        (NR_IRQS_LEGACY + 64)
+#define MX51_INT_RESV65                        (NR_IRQS_LEGACY + 65)
+#define MX51_INT_RESV66                        (NR_IRQS_LEGACY + 66)
+#define MX51_INT_SIM_IPB               (NR_IRQS_LEGACY + 67)
+#define MX51_INT_SIM_DAT               (NR_IRQS_LEGACY + 68)
+#define MX51_INT_IIM                   (NR_IRQS_LEGACY + 69)
+#define MX51_INT_ATA                   (NR_IRQS_LEGACY + 70)
+#define MX51_INT_CCM1                  (NR_IRQS_LEGACY + 71)
+#define MX51_INT_CCM2                  (NR_IRQS_LEGACY + 72)
+#define MX51_INT_GPC1                  (NR_IRQS_LEGACY + 73)
+#define MX51_INT_GPC2                  (NR_IRQS_LEGACY + 74)
+#define MX51_INT_SRC                   (NR_IRQS_LEGACY + 75)
+#define MX51_INT_NM                    (NR_IRQS_LEGACY + 76)
+#define MX51_INT_PMU                   (NR_IRQS_LEGACY + 77)
+#define MX51_INT_CTI_IRQ               (NR_IRQS_LEGACY + 78)
+#define MX51_INT_CTI1_TG0              (NR_IRQS_LEGACY + 79)
+#define MX51_INT_CTI1_TG1              (NR_IRQS_LEGACY + 80)
+#define MX51_INT_MCG_ERR               (NR_IRQS_LEGACY + 81)
+#define MX51_INT_MCG_TMR               (NR_IRQS_LEGACY + 82)
+#define MX51_INT_MCG_FUNC              (NR_IRQS_LEGACY + 83)
+#define MX51_INT_GPU2_IRQ              (NR_IRQS_LEGACY + 84)
+#define MX51_INT_GPU2_BUSY             (NR_IRQS_LEGACY + 85)
+#define MX51_INT_RESV86                        (NR_IRQS_LEGACY + 86)
+#define MX51_INT_FEC                   (NR_IRQS_LEGACY + 87)
+#define MX51_INT_OWIRE                 (NR_IRQS_LEGACY + 88)
+#define MX51_INT_CTI1_TG2              (NR_IRQS_LEGACY + 89)
+#define MX51_INT_SJC                   (NR_IRQS_LEGACY + 90)
+#define MX51_INT_SPDIF                 (NR_IRQS_LEGACY + 91)
+#define MX51_INT_TVE                   (NR_IRQS_LEGACY + 92)
+#define MX51_INT_FIRI                  (NR_IRQS_LEGACY + 93)
+#define MX51_INT_PWM2                  (NR_IRQS_LEGACY + 94)
+#define MX51_INT_SLIM_EXP              (NR_IRQS_LEGACY + 95)
+#define MX51_INT_SSI3                  (NR_IRQS_LEGACY + 96)
+#define MX51_INT_EMI_BOOT              (NR_IRQS_LEGACY + 97)
+#define MX51_INT_CTI1_TG3              (NR_IRQS_LEGACY + 98)
+#define MX51_INT_SMC_RX                        (NR_IRQS_LEGACY + 99)
+#define MX51_INT_VPU_IDLE              (NR_IRQS_LEGACY + 100)
+#define MX51_INT_EMI_NFC               (NR_IRQS_LEGACY + 101)
+#define MX51_INT_GPU_IDLE              (NR_IRQS_LEGACY + 102)
 
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
 extern int mx51_revision(void);
index a37e8c3539941040f754b9288cee57b562d6d808..f829d1c22501bd960f65f2b7bb142b9b8f3c78bd 100644 (file)
 /*
  * Interrupt numbers
  */
-#define MX53_INT_RESV0         0
-#define MX53_INT_ESDHC1        1
-#define MX53_INT_ESDHC2        2
-#define MX53_INT_ESDHC3        3
-#define MX53_INT_ESDHC4        4
-#define MX53_INT_DAP   5
-#define MX53_INT_SDMA  6
-#define MX53_INT_IOMUX 7
-#define MX53_INT_NFC   8
-#define MX53_INT_VPU   9
-#define MX53_INT_IPU_ERR       10
-#define MX53_INT_IPU_SYN       11
-#define MX53_INT_GPU   12
-#define MX53_INT_UART4 13
-#define MX53_INT_USB_H1        14
-#define MX53_INT_EMI   15
-#define MX53_INT_USB_H2        16
-#define MX53_INT_USB_H3        17
-#define MX53_INT_USB_OTG       18
-#define MX53_INT_SAHARA_H0     19
-#define MX53_INT_SAHARA_H1     20
-#define MX53_INT_SCC_SMN       21
-#define MX53_INT_SCC_STZ       22
-#define MX53_INT_SCC_SCM       23
-#define MX53_INT_SRTC_NTZ      24
-#define MX53_INT_SRTC_TZ       25
-#define MX53_INT_RTIC  26
-#define MX53_INT_CSU   27
-#define MX53_INT_SATA  28
-#define MX53_INT_SSI1  29
-#define MX53_INT_SSI2  30
-#define MX53_INT_UART1 31
-#define MX53_INT_UART2 32
-#define MX53_INT_UART3 33
-#define MX53_INT_RTC   34
-#define MX53_INT_PTP   35
-#define MX53_INT_ECSPI1        36
-#define MX53_INT_ECSPI2        37
-#define MX53_INT_CSPI  38
-#define MX53_INT_GPT   39
-#define MX53_INT_EPIT1 40
-#define MX53_INT_EPIT2 41
-#define MX53_INT_GPIO1_INT7    42
-#define MX53_INT_GPIO1_INT6    43
-#define MX53_INT_GPIO1_INT5    44
-#define MX53_INT_GPIO1_INT4    45
-#define MX53_INT_GPIO1_INT3    46
-#define MX53_INT_GPIO1_INT2    47
-#define MX53_INT_GPIO1_INT1    48
-#define MX53_INT_GPIO1_INT0    49
-#define MX53_INT_GPIO1_LOW     50
-#define MX53_INT_GPIO1_HIGH    51
-#define MX53_INT_GPIO2_LOW     52
-#define MX53_INT_GPIO2_HIGH    53
-#define MX53_INT_GPIO3_LOW     54
-#define MX53_INT_GPIO3_HIGH    55
-#define MX53_INT_GPIO4_LOW     56
-#define MX53_INT_GPIO4_HIGH    57
-#define MX53_INT_WDOG1 58
-#define MX53_INT_WDOG2 59
-#define MX53_INT_KPP   60
-#define MX53_INT_PWM1  61
-#define MX53_INT_I2C1  62
-#define MX53_INT_I2C2  63
-#define MX53_INT_I2C3  64
-#define MX53_INT_MLB   65
-#define MX53_INT_ASRC  66
-#define MX53_INT_SPDIF 67
-#define MX53_INT_SIM_DAT       68
-#define MX53_INT_IIM   69
-#define MX53_INT_ATA   70
-#define MX53_INT_CCM1  71
-#define MX53_INT_CCM2  72
-#define MX53_INT_GPC1  73
-#define MX53_INT_GPC2  74
-#define MX53_INT_SRC   75
-#define MX53_INT_NM            76
-#define MX53_INT_PMU   77
-#define MX53_INT_CTI_IRQ       78
-#define MX53_INT_CTI1_TG0      79
-#define MX53_INT_CTI1_TG1      80
-#define MX53_INT_ESAI  81
-#define MX53_INT_CAN1  82
-#define MX53_INT_CAN2  83
-#define MX53_INT_GPU2_IRQ      84
-#define MX53_INT_GPU2_BUSY     85
-#define MX53_INT_UART5 86
-#define MX53_INT_FEC   87
-#define MX53_INT_OWIRE 88
-#define MX53_INT_CTI1_TG2      89
-#define MX53_INT_SJC   90
-#define MX53_INT_TVE   92
-#define MX53_INT_FIRI  93
-#define MX53_INT_PWM2  94
-#define MX53_INT_SLIM_EXP      95
-#define MX53_INT_SSI3  96
-#define MX53_INT_EMI_BOOT      97
-#define MX53_INT_CTI1_TG3      98
-#define MX53_INT_SMC_RX        99
-#define MX53_INT_VPU_IDLE      100
-#define MX53_INT_EMI_NFC       101
-#define MX53_INT_GPU_IDLE      102
-#define MX53_INT_GPIO5_LOW     103
-#define MX53_INT_GPIO5_HIGH    104
-#define MX53_INT_GPIO6_LOW     105
-#define MX53_INT_GPIO6_HIGH    106
-#define MX53_INT_GPIO7_LOW     107
-#define MX53_INT_GPIO7_HIGH    108
+#include <asm/irq.h>
+#define MX53_INT_RESV0         (NR_IRQS_LEGACY + 0)
+#define MX53_INT_ESDHC1                (NR_IRQS_LEGACY + 1)
+#define MX53_INT_ESDHC2                (NR_IRQS_LEGACY + 2)
+#define MX53_INT_ESDHC3                (NR_IRQS_LEGACY + 3)
+#define MX53_INT_ESDHC4                (NR_IRQS_LEGACY + 4)
+#define MX53_INT_DAP           (NR_IRQS_LEGACY + 5)
+#define MX53_INT_SDMA          (NR_IRQS_LEGACY + 6)
+#define MX53_INT_IOMUX         (NR_IRQS_LEGACY + 7)
+#define MX53_INT_NFC           (NR_IRQS_LEGACY + 8)
+#define MX53_INT_VPU           (NR_IRQS_LEGACY + 9)
+#define MX53_INT_IPU_ERR       (NR_IRQS_LEGACY + 10)
+#define MX53_INT_IPU_SYN       (NR_IRQS_LEGACY + 11)
+#define MX53_INT_GPU           (NR_IRQS_LEGACY + 12)
+#define MX53_INT_UART4         (NR_IRQS_LEGACY + 13)
+#define MX53_INT_USB_H1                (NR_IRQS_LEGACY + 14)
+#define MX53_INT_EMI           (NR_IRQS_LEGACY + 15)
+#define MX53_INT_USB_H2                (NR_IRQS_LEGACY + 16)
+#define MX53_INT_USB_H3                (NR_IRQS_LEGACY + 17)
+#define MX53_INT_USB_OTG       (NR_IRQS_LEGACY + 18)
+#define MX53_INT_SAHARA_H0     (NR_IRQS_LEGACY + 19)
+#define MX53_INT_SAHARA_H1     (NR_IRQS_LEGACY + 20)
+#define MX53_INT_SCC_SMN       (NR_IRQS_LEGACY + 21)
+#define MX53_INT_SCC_STZ       (NR_IRQS_LEGACY + 22)
+#define MX53_INT_SCC_SCM       (NR_IRQS_LEGACY + 23)
+#define MX53_INT_SRTC_NTZ      (NR_IRQS_LEGACY + 24)
+#define MX53_INT_SRTC_TZ       (NR_IRQS_LEGACY + 25)
+#define MX53_INT_RTIC          (NR_IRQS_LEGACY + 26)
+#define MX53_INT_CSU           (NR_IRQS_LEGACY + 27)
+#define MX53_INT_SATA          (NR_IRQS_LEGACY + 28)
+#define MX53_INT_SSI1          (NR_IRQS_LEGACY + 29)
+#define MX53_INT_SSI2          (NR_IRQS_LEGACY + 30)
+#define MX53_INT_UART1         (NR_IRQS_LEGACY + 31)
+#define MX53_INT_UART2         (NR_IRQS_LEGACY + 32)
+#define MX53_INT_UART3         (NR_IRQS_LEGACY + 33)
+#define MX53_INT_RTC           (NR_IRQS_LEGACY + 34)
+#define MX53_INT_PTP           (NR_IRQS_LEGACY + 35)
+#define MX53_INT_ECSPI1                (NR_IRQS_LEGACY + 36)
+#define MX53_INT_ECSPI2                (NR_IRQS_LEGACY + 37)
+#define MX53_INT_CSPI          (NR_IRQS_LEGACY + 38)
+#define MX53_INT_GPT           (NR_IRQS_LEGACY + 39)
+#define MX53_INT_EPIT1         (NR_IRQS_LEGACY + 40)
+#define MX53_INT_EPIT2         (NR_IRQS_LEGACY + 41)
+#define MX53_INT_GPIO1_INT7    (NR_IRQS_LEGACY + 42)
+#define MX53_INT_GPIO1_INT6    (NR_IRQS_LEGACY + 43)
+#define MX53_INT_GPIO1_INT5    (NR_IRQS_LEGACY + 44)
+#define MX53_INT_GPIO1_INT4    (NR_IRQS_LEGACY + 45)
+#define MX53_INT_GPIO1_INT3    (NR_IRQS_LEGACY + 46)
+#define MX53_INT_GPIO1_INT2    (NR_IRQS_LEGACY + 47)
+#define MX53_INT_GPIO1_INT1    (NR_IRQS_LEGACY + 48)
+#define MX53_INT_GPIO1_INT0    (NR_IRQS_LEGACY + 49)
+#define MX53_INT_GPIO1_LOW     (NR_IRQS_LEGACY + 50)
+#define MX53_INT_GPIO1_HIGH    (NR_IRQS_LEGACY + 51)
+#define MX53_INT_GPIO2_LOW     (NR_IRQS_LEGACY + 52)
+#define MX53_INT_GPIO2_HIGH    (NR_IRQS_LEGACY + 53)
+#define MX53_INT_GPIO3_LOW     (NR_IRQS_LEGACY + 54)
+#define MX53_INT_GPIO3_HIGH    (NR_IRQS_LEGACY + 55)
+#define MX53_INT_GPIO4_LOW     (NR_IRQS_LEGACY + 56)
+#define MX53_INT_GPIO4_HIGH    (NR_IRQS_LEGACY + 57)
+#define MX53_INT_WDOG1         (NR_IRQS_LEGACY + 58)
+#define MX53_INT_WDOG2         (NR_IRQS_LEGACY + 59)
+#define MX53_INT_KPP           (NR_IRQS_LEGACY + 60)
+#define MX53_INT_PWM1          (NR_IRQS_LEGACY + 61)
+#define MX53_INT_I2C1          (NR_IRQS_LEGACY + 62)
+#define MX53_INT_I2C2          (NR_IRQS_LEGACY + 63)
+#define MX53_INT_I2C3          (NR_IRQS_LEGACY + 64)
+#define MX53_INT_MLB           (NR_IRQS_LEGACY + 65)
+#define MX53_INT_ASRC          (NR_IRQS_LEGACY + 66)
+#define MX53_INT_SPDIF         (NR_IRQS_LEGACY + 67)
+#define MX53_INT_SIM_DAT       (NR_IRQS_LEGACY + 68)
+#define MX53_INT_IIM           (NR_IRQS_LEGACY + 69)
+#define MX53_INT_ATA           (NR_IRQS_LEGACY + 70)
+#define MX53_INT_CCM1          (NR_IRQS_LEGACY + 71)
+#define MX53_INT_CCM2          (NR_IRQS_LEGACY + 72)
+#define MX53_INT_GPC1          (NR_IRQS_LEGACY + 73)
+#define MX53_INT_GPC2          (NR_IRQS_LEGACY + 74)
+#define MX53_INT_SRC           (NR_IRQS_LEGACY + 75)
+#define MX53_INT_NM            (NR_IRQS_LEGACY + 76)
+#define MX53_INT_PMU           (NR_IRQS_LEGACY + 77)
+#define MX53_INT_CTI_IRQ       (NR_IRQS_LEGACY + 78)
+#define MX53_INT_CTI1_TG0      (NR_IRQS_LEGACY + 79)
+#define MX53_INT_CTI1_TG1      (NR_IRQS_LEGACY + 80)
+#define MX53_INT_ESAI          (NR_IRQS_LEGACY + 81)
+#define MX53_INT_CAN1          (NR_IRQS_LEGACY + 82)
+#define MX53_INT_CAN2          (NR_IRQS_LEGACY + 83)
+#define MX53_INT_GPU2_IRQ      (NR_IRQS_LEGACY + 84)
+#define MX53_INT_GPU2_BUSY     (NR_IRQS_LEGACY + 85)
+#define MX53_INT_UART5         (NR_IRQS_LEGACY + 86)
+#define MX53_INT_FEC           (NR_IRQS_LEGACY + 87)
+#define MX53_INT_OWIRE         (NR_IRQS_LEGACY + 88)
+#define MX53_INT_CTI1_TG2      (NR_IRQS_LEGACY + 89)
+#define MX53_INT_SJC           (NR_IRQS_LEGACY + 90)
+#define MX53_INT_TVE           (NR_IRQS_LEGACY + 92)
+#define MX53_INT_FIRI          (NR_IRQS_LEGACY + 93)
+#define MX53_INT_PWM2          (NR_IRQS_LEGACY + 94)
+#define MX53_INT_SLIM_EXP      (NR_IRQS_LEGACY + 95)
+#define MX53_INT_SSI3          (NR_IRQS_LEGACY + 96)
+#define MX53_INT_EMI_BOOT      (NR_IRQS_LEGACY + 97)
+#define MX53_INT_CTI1_TG3      (NR_IRQS_LEGACY + 98)
+#define MX53_INT_SMC_RX                (NR_IRQS_LEGACY + 99)
+#define MX53_INT_VPU_IDLE      (NR_IRQS_LEGACY + 100)
+#define MX53_INT_EMI_NFC       (NR_IRQS_LEGACY + 101)
+#define MX53_INT_GPU_IDLE      (NR_IRQS_LEGACY + 102)
+#define MX53_INT_GPIO5_LOW     (NR_IRQS_LEGACY + 103)
+#define MX53_INT_GPIO5_HIGH    (NR_IRQS_LEGACY + 104)
+#define MX53_INT_GPIO6_LOW     (NR_IRQS_LEGACY + 105)
+#define MX53_INT_GPIO6_HIGH    (NR_IRQS_LEGACY + 106)
+#define MX53_INT_GPIO7_LOW     (NR_IRQS_LEGACY + 107)
+#define MX53_INT_GPIO7_HIGH    (NR_IRQS_LEGACY + 108)
 
 #endif /* ifndef __MACH_MX53_H__ */
index 9ffd1bbe615f91fc598268c69be4aa35b2b9dcff..7eb9d13296719a81f9d2bf03622acf1a83add3a1 100644 (file)
 #define MXC_EHCI_INTERFACE_MASK                (0xf)
 
 #define MXC_EHCI_POWER_PINS_ENABLED    (1 << 5)
-#define MXC_EHCI_TTL_ENABLED           (1 << 6)
-
-#define MXC_EHCI_INTERNAL_PHY          (1 << 7)
-#define MXC_EHCI_IPPUE_DOWN            (1 << 8)
-#define MXC_EHCI_IPPUE_UP              (1 << 9)
-#define MXC_EHCI_WAKEUP_ENABLED        (1 << 10)
-#define MXC_EHCI_ITC_NO_THRESHOLD      (1 << 11)
+#define MXC_EHCI_PWR_PIN_ACTIVE_HIGH   (1 << 6)
+#define MXC_EHCI_OC_PIN_ACTIVE_LOW     (1 << 7)
+#define MXC_EHCI_TTL_ENABLED           (1 << 8)
+
+#define MXC_EHCI_INTERNAL_PHY          (1 << 9)
+#define MXC_EHCI_IPPUE_DOWN            (1 << 10)
+#define MXC_EHCI_IPPUE_UP              (1 << 11)
+#define MXC_EHCI_WAKEUP_ENABLED                (1 << 12)
+#define MXC_EHCI_ITC_NO_THRESHOLD      (1 << 13)
 
 #define MXC_USBCTRL_OFFSET             0
 #define MXC_USB_PHY_CTR_FUNC_OFFSET    0x8
index 00e8e659e66762104fc487cada9bbd8e81968df8..a17abcf983259064ff2a87664d81d3610b6ef3b1 100644 (file)
@@ -160,7 +160,8 @@ static const char *clock_event_mode_label[] = {
        [CLOCK_EVT_MODE_PERIODIC] = "CLOCK_EVT_MODE_PERIODIC",
        [CLOCK_EVT_MODE_ONESHOT]  = "CLOCK_EVT_MODE_ONESHOT",
        [CLOCK_EVT_MODE_SHUTDOWN] = "CLOCK_EVT_MODE_SHUTDOWN",
-       [CLOCK_EVT_MODE_UNUSED]   = "CLOCK_EVT_MODE_UNUSED"
+       [CLOCK_EVT_MODE_UNUSED]   = "CLOCK_EVT_MODE_UNUSED",
+       [CLOCK_EVT_MODE_RESUME]   = "CLOCK_EVT_MODE_RESUME",
 };
 #endif /* DEBUG */
 
index 98308ec1f3214e0fc7bf5477e8acd7c03781407e..c2193178210bdd47dbd04b904cdba45a82fd1ad9 100644 (file)
@@ -15,6 +15,8 @@
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/io.h>
+#include <linux/irqdomain.h>
+#include <linux/of.h>
 
 #include <asm/mach/irq.h>
 #include <asm/exception.h>
@@ -49,6 +51,7 @@
 #define TZIC_ID0       0x0FD0  /* Indentification Register 0 */
 
 void __iomem *tzic_base; /* Used as irq controller base in entry-macro.S */
+static struct irq_domain *domain;
 
 #define TZIC_NUM_IRQS 128
 
@@ -77,15 +80,14 @@ static int tzic_set_irq_fiq(unsigned int irq, unsigned int type)
 static void tzic_irq_suspend(struct irq_data *d)
 {
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-       int idx = gc->irq_base >> 5;
+       int idx = d->hwirq >> 5;
 
        __raw_writel(gc->wake_active, tzic_base + TZIC_WAKEUP0(idx));
 }
 
 static void tzic_irq_resume(struct irq_data *d)
 {
-       struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
-       int idx = gc->irq_base >> 5;
+       int idx = d->hwirq >> 5;
 
        __raw_writel(__raw_readl(tzic_base + TZIC_ENSET0(idx)),
                     tzic_base + TZIC_WAKEUP0(idx));
@@ -102,11 +104,10 @@ static struct mxc_extra_irq tzic_extra_irq = {
 #endif
 };
 
-static __init void tzic_init_gc(unsigned int irq_start)
+static __init void tzic_init_gc(int idx, unsigned int irq_start)
 {
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
-       int idx = irq_start >> 5;
 
        gc = irq_alloc_generic_chip("tzic", 1, irq_start, tzic_base,
                                    handle_level_irq);
@@ -140,7 +141,8 @@ asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
                        while (stat) {
                                handled = 1;
                                irqofs = fls(stat) - 1;
-                               handle_IRQ(irqofs + i * 32, regs);
+                               handle_IRQ(irq_find_mapping(domain,
+                                               irqofs + i * 32), regs);
                                stat &= ~(1 << irqofs);
                        }
                }
@@ -154,6 +156,8 @@ asmlinkage void __exception_irq_entry tzic_handle_irq(struct pt_regs *regs)
  */
 void __init tzic_init_irq(void __iomem *irqbase)
 {
+       struct device_node *np;
+       int irq_base;
        int i;
 
        tzic_base = irqbase;
@@ -175,12 +179,20 @@ void __init tzic_init_irq(void __iomem *irqbase)
 
        /* all IRQ no FIQ Warning :: No selection */
 
-       for (i = 0; i < TZIC_NUM_IRQS; i += 32)
-               tzic_init_gc(i);
+       irq_base = irq_alloc_descs(-1, 0, TZIC_NUM_IRQS, numa_node_id());
+       WARN_ON(irq_base < 0);
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,tzic");
+       domain = irq_domain_add_legacy(np, TZIC_NUM_IRQS, irq_base, 0,
+                                      &irq_domain_simple_ops, NULL);
+       WARN_ON(!domain);
+
+       for (i = 0; i < 4; i++, irq_base += 32)
+               tzic_init_gc(i, irq_base);
 
 #ifdef CONFIG_FIQ
        /* Initialize FIQ */
-       init_FIQ();
+       init_FIQ(FIQ_START);
 #endif
 
        pr_info("TrustZone Interrupt Controller (TZIC) initialized\n");
@@ -190,6 +202,10 @@ void __init tzic_init_irq(void __iomem *irqbase)
  * tzic_enable_wake() - enable wakeup interrupt
  *
  * @return                     0 if successful; non-zero otherwise
+ *
+ * This function provides an interrupt synchronization point that is required
+ * by tzic enabled platforms before entering imx specific low power modes (ie,
+ * those low power modes beyond the WAIT_CLOCKED basic ARM WFI only mode).
  */
 int tzic_enable_wake(void)
 {
index ad95c7a5d00926f933864cb9a9285e95ae1f7f10..dd36eba9506c85877d91e57d2d95894343199d7d 100644 (file)
@@ -29,7 +29,7 @@ config ARCH_OMAP2PLUS
        select USE_OF
        select PROC_DEVICETREE if PROC_FS
        help
-         "Systems based on OMAP2, OMAP3 or OMAP4"
+         "Systems based on OMAP2, OMAP3, OMAP4 or OMAP5"
 
 endchoice
 
@@ -45,31 +45,30 @@ config OMAP_DEBUG_LEDS
        depends on OMAP_DEBUG_DEVICES
        default y if LEDS_CLASS
 
-config OMAP_SMARTREFLEX
-       bool "SmartReflex support"
-       depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM
+config POWER_AVS_OMAP
+       bool "AVS(Adaptive Voltage Scaling) support for OMAP IP versions 1&2"
+       depends on POWER_AVS && (ARCH_OMAP3 || ARCH_OMAP4) && PM
        help
-         Say Y if you want to enable SmartReflex.
-
-         SmartReflex can perform continuous dynamic voltage
-         scaling around the nominal operating point voltage
-         according to silicon characteristics and operating
-         conditions. Enabling SmartReflex reduces power
-         consumption.
+         Say Y to enable AVS(Adaptive Voltage Scaling)
+         support on OMAP containing the version 1 or
+         version 2 of the SmartReflex IP.
+         V1 is the 65nm version used in OMAP3430.
+         V2 is the update for the 45nm version of the IP used in OMAP3630
+         and OMAP4430
 
          Please note, that by default SmartReflex is only
-         initialized. To enable the automatic voltage
-         compensation for vdd mpu  and vdd core from user space,
+         initialized and not enabled. To enable the automatic voltage
+         compensation for vdd mpu and vdd core from user space,
          user must write 1 to
-               /debug/voltage/vdd_<X>/smartreflex/autocomp,
-         where X is mpu or core for OMAP3.
+               /debug/smartreflex/sr_<X>/autocomp,
+         where X is mpu_iva or core for OMAP3.
          Optionally autocompensation can be enabled in the kernel
          by default during system init via the enable_on_init flag
          which an be passed as platform data to the smartreflex driver.
 
-config OMAP_SMARTREFLEX_CLASS3
+config POWER_AVS_OMAP_CLASS3
        bool "Class 3 mode of Smartreflex Implementation"
-       depends on OMAP_SMARTREFLEX && TWL4030_CORE
+       depends on POWER_AVS_OMAP && TWL4030_CORE
        help
          Say Y to enable Class 3 implementation of Smartreflex
 
@@ -150,7 +149,7 @@ config OMAP_32K_TIMER
          This timer saves power compared to the OMAP_MPU_TIMER, and has
          support for no tick during idle. The 32KHz timer provides less
          intra-tick resolution than OMAP_MPU_TIMER. The 32KHz timer is
-         currently only available for OMAP16XX, 24XX, 34XX and OMAP4.
+         currently only available for OMAP16XX, 24XX, 34XX and OMAP4/5.
 
 config OMAP3_L2_AUX_SECURE_SAVE_RESTORE
        bool "OMAP3 HS/EMU save and restore for L2 AUX control register"
index ed8605f0115561ac44dc542c52d27afc0f98233b..961bf859bc0cd7f90040c33de25fc9573056730c 100644 (file)
@@ -4,15 +4,13 @@
 
 # Common support
 obj-y := common.o sram.o clock.o devices.o dma.o mux.o \
-        usb.o fb.o counter_32k.o
+        fb.o counter_32k.o
 obj-m :=
 obj-n :=
 obj-  :=
 
 # omap_device support (OMAP2+ only at the moment)
-obj-$(CONFIG_ARCH_OMAP2) += omap_device.o
-obj-$(CONFIG_ARCH_OMAP3) += omap_device.o
-obj-$(CONFIG_ARCH_OMAP4) += omap_device.o
+obj-$(CONFIG_ARCH_OMAP2PLUS) += omap_device.o
 
 obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
 obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
index 0a9b9a970113d2d1e1818cf0e4c316bcbfc44a3e..89a3723b353889805841dfc0ca9a4804e48d6377 100644 (file)
@@ -77,3 +77,12 @@ void __init omap_init_consistent_dma_size(void)
        init_consistent_dma_size(CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE << 20);
 #endif
 }
+
+/*
+ * Stub function for OMAP2 so that common files
+ * continue to build when custom builds are used
+ */
+int __weak omap_secure_ram_reserve_memblock(void)
+{
+       return 0;
+}
index 2132c4f389e1a799db97a95c78ee4924d57caa16..dbf1e03029a5707c36ac8e16978cd756649e6ab4 100644 (file)
 #include <plat/clock.h>
 
 /* OMAP2_32KSYNCNT_CR_OFF: offset of 32ksync counter register */
-#define OMAP2_32KSYNCNT_CR_OFF         0x10
+#define OMAP2_32KSYNCNT_REV_OFF                0x0
+#define OMAP2_32KSYNCNT_REV_SCHEME     (0x3 << 30)
+#define OMAP2_32KSYNCNT_CR_OFF_LOW     0x10
+#define OMAP2_32KSYNCNT_CR_OFF_HIGH    0x30
 
 /*
  * 32KHz clocksource ... always available, on pretty most chips except
@@ -84,9 +87,16 @@ int __init omap_init_clocksource_32k(void __iomem *vbase)
        int ret;
 
        /*
-        * 32k sync Counter register offset is at 0x10
+        * 32k sync Counter IP register offsets vary between the
+        * highlander version and the legacy ones.
+        * The 'SCHEME' bits(30-31) of the revision register is used
+        * to identify the version.
         */
-       sync32k_cnt_reg = vbase + OMAP2_32KSYNCNT_CR_OFF;
+       if (__raw_readl(vbase + OMAP2_32KSYNCNT_REV_OFF) &
+                                               OMAP2_32KSYNCNT_REV_SCHEME)
+               sync32k_cnt_reg = vbase + OMAP2_32KSYNCNT_CR_OFF_HIGH;
+       else
+               sync32k_cnt_reg = vbase + OMAP2_32KSYNCNT_CR_OFF_LOW;
 
        /*
         * 120000 rough estimate from the calculations in
index cb16ade437cb6d94fc608c4e2060dfa512514e58..7fe626761e53bc87a2aaec3add8c7f7854635875 100644 (file)
@@ -573,22 +573,25 @@ EXPORT_SYMBOL(omap_set_dma_dest_burst_mode);
 
 static inline void omap_enable_channel_irq(int lch)
 {
-       u32 status;
-
        /* Clear CSR */
        if (cpu_class_is_omap1())
-               status = p->dma_read(CSR, lch);
-       else if (cpu_class_is_omap2())
+               p->dma_read(CSR, lch);
+       else
                p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
 
        /* Enable some nice interrupts. */
        p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch);
 }
 
-static void omap_disable_channel_irq(int lch)
+static inline void omap_disable_channel_irq(int lch)
 {
-       if (cpu_class_is_omap2())
-               p->dma_write(0, CICR, lch);
+       /* disable channel interrupts */
+       p->dma_write(0, CICR, lch);
+       /* Clear CSR */
+       if (cpu_class_is_omap1())
+               p->dma_read(CSR, lch);
+       else
+               p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
 }
 
 void omap_enable_dma_irq(int lch, u16 bits)
@@ -632,14 +635,14 @@ static inline void disable_lnk(int lch)
        l = p->dma_read(CLNK_CTRL, lch);
 
        /* Disable interrupts */
+       omap_disable_channel_irq(lch);
+
        if (cpu_class_is_omap1()) {
-               p->dma_write(0, CICR, lch);
                /* Set the STOP_LNK bit */
                l |= 1 << 14;
        }
 
        if (cpu_class_is_omap2()) {
-               omap_disable_channel_irq(lch);
                /* Clear the ENABLE_LNK bit */
                l &= ~(1 << 15);
        }
@@ -657,6 +660,9 @@ static inline void omap2_enable_irq_lch(int lch)
                return;
 
        spin_lock_irqsave(&dma_chan_lock, flags);
+       /* clear IRQ STATUS */
+       p->dma_write(1 << lch, IRQSTATUS_L0, lch);
+       /* Enable interrupt */
        val = p->dma_read(IRQENABLE_L0, lch);
        val |= 1 << lch;
        p->dma_write(val, IRQENABLE_L0, lch);
@@ -672,9 +678,12 @@ static inline void omap2_disable_irq_lch(int lch)
                return;
 
        spin_lock_irqsave(&dma_chan_lock, flags);
+       /* Disable interrupt */
        val = p->dma_read(IRQENABLE_L0, lch);
        val &= ~(1 << lch);
        p->dma_write(val, IRQENABLE_L0, lch);
+       /* clear IRQ STATUS */
+       p->dma_write(1 << lch, IRQSTATUS_L0, lch);
        spin_unlock_irqrestore(&dma_chan_lock, flags);
 }
 
@@ -745,11 +754,8 @@ int omap_request_dma(int dev_id, const char *dev_name,
        }
 
        if (cpu_class_is_omap2()) {
-               omap2_enable_irq_lch(free_ch);
                omap_enable_channel_irq(free_ch);
-               /* Clear the CSR register and IRQ status register */
-               p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch);
-               p->dma_write(1 << free_ch, IRQSTATUS_L0, 0);
+               omap2_enable_irq_lch(free_ch);
        }
 
        *dma_ch_out = free_ch;
@@ -768,27 +774,19 @@ void omap_free_dma(int lch)
                return;
        }
 
-       if (cpu_class_is_omap1()) {
-               /* Disable all DMA interrupts for the channel. */
-               p->dma_write(0, CICR, lch);
-               /* Make sure the DMA transfer is stopped. */
-               p->dma_write(0, CCR, lch);
-       }
-
-       if (cpu_class_is_omap2()) {
+       /* Disable interrupt for logical channel */
+       if (cpu_class_is_omap2())
                omap2_disable_irq_lch(lch);
 
-               /* Clear the CSR register and IRQ status register */
-               p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch);
-               p->dma_write(1 << lch, IRQSTATUS_L0, lch);
+       /* Disable all DMA interrupts for the channel. */
+       omap_disable_channel_irq(lch);
 
-               /* Disable all DMA interrupts for the channel. */
-               p->dma_write(0, CICR, lch);
+       /* Make sure the DMA transfer is stopped. */
+       p->dma_write(0, CCR, lch);
 
-               /* Make sure the DMA transfer is stopped. */
-               p->dma_write(0, CCR, lch);
+       /* Clear registers */
+       if (cpu_class_is_omap2())
                omap_clear_dma(lch);
-       }
 
        spin_lock_irqsave(&dma_chan_lock, flags);
        dma_chan[lch].dev_id = -1;
@@ -943,8 +941,7 @@ void omap_stop_dma(int lch)
        u32 l;
 
        /* Disable all interrupts on the channel */
-       if (cpu_class_is_omap1())
-               p->dma_write(0, CICR, lch);
+       omap_disable_channel_irq(lch);
 
        l = p->dma_read(CCR, lch);
        if (IS_DMA_ERRATA(DMA_ERRATA_i541) &&
index 3b0cfeb33d05a21c4b58ab477a2d02dd8f481024..626ad8cad7a9486d71408f611b4f99b46c85b995 100644 (file)
 
 #include <linux/module.h>
 #include <linux/io.h>
-#include <linux/slab.h>
+#include <linux/device.h>
 #include <linux/err.h>
 #include <linux/pm_runtime.h>
 
 #include <plat/dmtimer.h>
+#include <plat/omap-pm.h>
 
 #include <mach/hardware.h>
 
+static u32 omap_reserved_systimers;
 static LIST_HEAD(omap_timer_list);
 static DEFINE_SPINLOCK(dm_timer_lock);
 
@@ -133,17 +135,22 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
 
 int omap_dm_timer_prepare(struct omap_dm_timer *timer)
 {
-       struct dmtimer_platform_data *pdata = timer->pdev->dev.platform_data;
        int ret;
 
-       timer->fclk = clk_get(&timer->pdev->dev, "fck");
-       if (WARN_ON_ONCE(IS_ERR_OR_NULL(timer->fclk))) {
-               timer->fclk = NULL;
-               dev_err(&timer->pdev->dev, ": No fclk handle.\n");
-               return -EINVAL;
+       /*
+        * FIXME: OMAP1 devices do not use the clock framework for dmtimers so
+        * do not call clk_get() for these devices.
+        */
+       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;
+                       dev_err(&timer->pdev->dev, ": No fclk handle.\n");
+                       return -EINVAL;
+               }
        }
 
-       if (pdata->needs_manual_reset)
+       if (timer->capability & OMAP_TIMER_NEEDS_RESET)
                omap_dm_timer_reset(timer);
 
        ret = omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
@@ -152,6 +159,21 @@ int omap_dm_timer_prepare(struct omap_dm_timer *timer)
        return ret;
 }
 
+static inline u32 omap_dm_timer_reserved_systimer(int id)
+{
+       return (omap_reserved_systimers & (1 << (id - 1))) ? 1 : 0;
+}
+
+int omap_dm_timer_reserve_systimer(int id)
+{
+       if (omap_dm_timer_reserved_systimer(id))
+               return -ENODEV;
+
+       omap_reserved_systimers |= (1 << (id - 1));
+
+       return 0;
+}
+
 struct omap_dm_timer *omap_dm_timer_request(void)
 {
        struct omap_dm_timer *timer = NULL, *t;
@@ -325,10 +347,9 @@ int omap_dm_timer_start(struct omap_dm_timer *timer)
 
        omap_dm_timer_enable(timer);
 
-       if (timer->loses_context) {
-               u32 ctx_loss_cnt_after =
-                       timer->get_context_loss_count(&timer->pdev->dev);
-               if (ctx_loss_cnt_after != timer->ctx_loss_count)
+       if (!(timer->capability & OMAP_TIMER_ALWON)) {
+               if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
+                               timer->ctx_loss_count)
                        omap_timer_restore_context(timer);
        }
 
@@ -347,20 +368,18 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_start);
 int omap_dm_timer_stop(struct omap_dm_timer *timer)
 {
        unsigned long rate = 0;
-       struct dmtimer_platform_data *pdata;
 
        if (unlikely(!timer))
                return -EINVAL;
 
-       pdata = timer->pdev->dev.platform_data;
-       if (!pdata->needs_manual_reset)
+       if (!(timer->capability & OMAP_TIMER_NEEDS_RESET))
                rate = clk_get_rate(timer->fclk);
 
        __omap_dm_timer_stop(timer, timer->posted, rate);
 
-       if (timer->loses_context && timer->get_context_loss_count)
+       if (!(timer->capability & OMAP_TIMER_ALWON))
                timer->ctx_loss_count =
-                       timer->get_context_loss_count(&timer->pdev->dev);
+                       omap_pm_get_dev_context_loss_count(&timer->pdev->dev);
 
        /*
         * Since the register values are computed and written within
@@ -378,6 +397,8 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
 int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
 {
        int ret;
+       char *parent_name = NULL;
+       struct clk *fclk, *parent;
        struct dmtimer_platform_data *pdata;
 
        if (unlikely(!timer))
@@ -388,7 +409,49 @@ int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
        if (source < 0 || source >= 3)
                return -EINVAL;
 
-       ret = pdata->set_timer_src(timer->pdev, source);
+       /*
+        * FIXME: Used for OMAP1 devices only because they do not currently
+        * use the clock framework to set the parent clock. To be removed
+        * once OMAP1 migrated to using clock framework for dmtimers
+        */
+       if (pdata->set_timer_src)
+               return pdata->set_timer_src(timer->pdev, source);
+
+       fclk = clk_get(&timer->pdev->dev, "fck");
+       if (IS_ERR_OR_NULL(fclk)) {
+               pr_err("%s: fck not found\n", __func__);
+               return -EINVAL;
+       }
+
+       switch (source) {
+       case OMAP_TIMER_SRC_SYS_CLK:
+               parent_name = "timer_sys_ck";
+               break;
+
+       case OMAP_TIMER_SRC_32_KHZ:
+               parent_name = "timer_32k_ck";
+               break;
+
+       case OMAP_TIMER_SRC_EXT_CLK:
+               parent_name = "timer_ext_ck";
+               break;
+       }
+
+       parent = clk_get(&timer->pdev->dev, parent_name);
+       if (IS_ERR_OR_NULL(parent)) {
+               pr_err("%s: %s not found\n", __func__, parent_name);
+               ret = -EINVAL;
+               goto out;
+       }
+
+       ret = clk_set_parent(fclk, parent);
+       if (IS_ERR_VALUE(ret))
+               pr_err("%s: failed to set %s as parent\n", __func__,
+                       parent_name);
+
+       clk_put(parent);
+out:
+       clk_put(fclk);
 
        return ret;
 }
@@ -431,10 +494,9 @@ int omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
 
        omap_dm_timer_enable(timer);
 
-       if (timer->loses_context) {
-               u32 ctx_loss_cnt_after =
-                       timer->get_context_loss_count(&timer->pdev->dev);
-               if (ctx_loss_cnt_after != timer->ctx_loss_count)
+       if (!(timer->capability & OMAP_TIMER_ALWON)) {
+               if (omap_pm_get_dev_context_loss_count(&timer->pdev->dev) !=
+                               timer->ctx_loss_count)
                        omap_timer_restore_context(timer);
        }
 
@@ -627,68 +689,57 @@ EXPORT_SYMBOL_GPL(omap_dm_timers_active);
  */
 static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
 {
-       int ret;
        unsigned long flags;
        struct omap_dm_timer *timer;
-       struct resource *mem, *irq, *ioarea;
+       struct resource *mem, *irq;
+       struct device *dev = &pdev->dev;
        struct dmtimer_platform_data *pdata = pdev->dev.platform_data;
 
        if (!pdata) {
-               dev_err(&pdev->dev, "%s: no platform data.\n", __func__);
+               dev_err(dev, "%s: no platform data.\n", __func__);
                return -ENODEV;
        }
 
        irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (unlikely(!irq)) {
-               dev_err(&pdev->dev, "%s: no IRQ resource.\n", __func__);
+               dev_err(dev, "%s: no IRQ resource.\n", __func__);
                return -ENODEV;
        }
 
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (unlikely(!mem)) {
-               dev_err(&pdev->dev, "%s: no memory resource.\n", __func__);
+               dev_err(dev, "%s: no memory resource.\n", __func__);
                return -ENODEV;
        }
 
-       ioarea = request_mem_region(mem->start, resource_size(mem),
-                       pdev->name);
-       if (!ioarea) {
-               dev_err(&pdev->dev, "%s: region already claimed.\n", __func__);
-               return -EBUSY;
-       }
-
-       timer = kzalloc(sizeof(struct omap_dm_timer), GFP_KERNEL);
+       timer = devm_kzalloc(dev, sizeof(struct omap_dm_timer), GFP_KERNEL);
        if (!timer) {
-               dev_err(&pdev->dev, "%s: no memory for omap_dm_timer.\n",
-                       __func__);
-               ret = -ENOMEM;
-               goto err_free_ioregion;
+               dev_err(dev, "%s: memory alloc failed!\n", __func__);
+               return  -ENOMEM;
        }
 
-       timer->io_base = ioremap(mem->start, resource_size(mem));
+       timer->io_base = devm_request_and_ioremap(dev, mem);
        if (!timer->io_base) {
-               dev_err(&pdev->dev, "%s: ioremap failed.\n", __func__);
-               ret = -ENOMEM;
-               goto err_free_mem;
+               dev_err(dev, "%s: region already claimed.\n", __func__);
+               return -ENOMEM;
        }
 
        timer->id = pdev->id;
        timer->irq = irq->start;
-       timer->reserved = pdata->reserved;
+       timer->reserved = omap_dm_timer_reserved_systimer(timer->id);
        timer->pdev = pdev;
-       timer->loses_context = pdata->loses_context;
-       timer->get_context_loss_count = pdata->get_context_loss_count;
+       timer->capability = pdata->timer_capability;
 
        /* Skip pm_runtime_enable for OMAP1 */
-       if (!pdata->needs_manual_reset) {
-               pm_runtime_enable(&pdev->dev);
-               pm_runtime_irq_safe(&pdev->dev);
+       if (!(timer->capability & OMAP_TIMER_NEEDS_RESET)) {
+               pm_runtime_enable(dev);
+               pm_runtime_irq_safe(dev);
        }
 
        if (!timer->reserved) {
-               pm_runtime_get_sync(&pdev->dev);
+               pm_runtime_get_sync(dev);
                __omap_dm_timer_init_regs(timer);
-               pm_runtime_put(&pdev->dev);
+               pm_runtime_put(dev);
        }
 
        /* add the timer element to the list */
@@ -696,17 +747,9 @@ static int __devinit omap_dm_timer_probe(struct platform_device *pdev)
        list_add_tail(&timer->node, &omap_timer_list);
        spin_unlock_irqrestore(&dm_timer_lock, flags);
 
-       dev_dbg(&pdev->dev, "Device Probed.\n");
+       dev_dbg(dev, "Device Probed.\n");
 
        return 0;
-
-err_free_mem:
-       kfree(timer);
-
-err_free_ioregion:
-       release_mem_region(mem->start, resource_size(mem));
-
-       return ret;
 }
 
 /**
@@ -727,7 +770,6 @@ static int __devexit omap_dm_timer_remove(struct platform_device *pdev)
        list_for_each_entry(timer, &omap_timer_list, node)
                if (timer->pdev->id == pdev->id) {
                        list_del(&timer->node);
-                       kfree(timer);
                        ret = 0;
                        break;
                }
index 4814c5b653068a94f14fcfa941b76c0b232c2f50..e62f20a5c0afafedbf1c620f01c25419e867c03f 100644 (file)
@@ -57,44 +57,6 @@ struct omap_camera_sensor_config {
        int (*power_off)(void * data);
 };
 
-struct omap_usb_config {
-       /* Configure drivers according to the connectors on your board:
-        *  - "A" connector (rectagular)
-        *      ... for host/OHCI use, set "register_host".
-        *  - "B" connector (squarish) or "Mini-B"
-        *      ... for device/gadget use, set "register_dev".
-        *  - "Mini-AB" connector (very similar to Mini-B)
-        *      ... for OTG use as device OR host, initialize "otg"
-        */
-       unsigned        register_host:1;
-       unsigned        register_dev:1;
-       u8              otg;    /* port number, 1-based:  usb1 == 2 */
-
-       u8              hmc_mode;
-
-       /* implicitly true if otg:  host supports remote wakeup? */
-       u8              rwc;
-
-       /* signaling pins used to talk to transceiver on usbN:
-        *  0 == usbN unused
-        *  2 == usb0-only, using internal transceiver
-        *  3 == 3 wire bidirectional
-        *  4 == 4 wire bidirectional
-        *  6 == 6 wire unidirectional (or TLL)
-        */
-       u8              pins[3];
-
-       struct platform_device *udc_device;
-       struct platform_device *ohci_device;
-       struct platform_device *otg_device;
-
-       u32 (*usb0_init)(unsigned nwires, unsigned is_device);
-       u32 (*usb1_init)(unsigned nwires);
-       u32 (*usb2_init)(unsigned nwires, unsigned alt_pingroup);
-
-       int (*ocpi_enable)(void);
-};
-
 struct omap_lcd_config {
        char panel_name[16];
        char ctrl_name[16];
index d0ed8c443a635ebb03be51c3c17843945a1638f8..025d85a3ee866a66f6f4cc39452b99b3e1cba42c 100644 (file)
@@ -39,6 +39,7 @@ struct omap_clk {
 #define CK_443X                (1 << 11)
 #define CK_TI816X      (1 << 12)
 #define CK_446X                (1 << 13)
+#define CK_AM33XX      (1 << 14)       /* AM33xx specific clocks */
 #define CK_1710                (1 << 15)       /* 1710 extra for rate selection */
 
 
index d0ef57c1d71b8d674fd649342f3241eed5d0ba53..656b9862279e7f757e9e1328a81279f20ef3b7e7 100644 (file)
@@ -156,7 +156,6 @@ struct dpll_data {
        u8                      min_divider;
        u16                     max_divider;
        u8                      modes;
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
        void __iomem            *autoidle_reg;
        void __iomem            *idlest_reg;
        u32                     autoidle_mask;
@@ -167,7 +166,6 @@ struct dpll_data {
        u8                      auto_recal_bit;
        u8                      recal_en_bit;
        u8                      recal_st_bit;
-#  endif
        u8                      flags;
 };
 
index de6c0a08f4615d6fba3f07b316285f9a9b47095a..68b180edcfffd0e05c9256aaa153993500177f84 100644 (file)
@@ -9,7 +9,7 @@
  *
  * Written by Tony Lindgren <tony.lindgren@nokia.com>
  *
- * Added OMAP4 specific defines - Santosh Shilimkar<santosh.shilimkar@ti.com>
+ * Added OMAP4/5 specific defines - Santosh Shilimkar<santosh.shilimkar@ti.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
@@ -70,6 +70,7 @@ unsigned int omap_rev(void);
  * cpu_is_omap443x():  True for OMAP4430
  * cpu_is_omap446x():  True for OMAP4460
  * cpu_is_omap447x():  True for OMAP4470
+ * soc_is_omap543x():  True for OMAP5430, OMAP5432
  */
 #define GET_OMAP_CLASS (omap_rev() & 0xff)
 
@@ -122,6 +123,7 @@ IS_OMAP_CLASS(24xx, 0x24)
 IS_OMAP_CLASS(34xx, 0x34)
 IS_OMAP_CLASS(44xx, 0x44)
 IS_AM_CLASS(35xx, 0x35)
+IS_OMAP_CLASS(54xx, 0x54)
 IS_AM_CLASS(33xx, 0x33)
 
 IS_TI_CLASS(81xx, 0x81)
@@ -133,6 +135,7 @@ IS_OMAP_SUBCLASS(363x, 0x363)
 IS_OMAP_SUBCLASS(443x, 0x443)
 IS_OMAP_SUBCLASS(446x, 0x446)
 IS_OMAP_SUBCLASS(447x, 0x447)
+IS_OMAP_SUBCLASS(543x, 0x543)
 
 IS_TI_SUBCLASS(816x, 0x816)
 IS_TI_SUBCLASS(814x, 0x814)
@@ -150,12 +153,14 @@ IS_AM_SUBCLASS(335x, 0x335)
 #define cpu_is_ti816x()                        0
 #define cpu_is_ti814x()                        0
 #define soc_is_am35xx()                        0
-#define cpu_is_am33xx()                        0
-#define cpu_is_am335x()                        0
+#define soc_is_am33xx()                        0
+#define soc_is_am335x()                        0
 #define cpu_is_omap44xx()              0
 #define cpu_is_omap443x()              0
 #define cpu_is_omap446x()              0
 #define cpu_is_omap447x()              0
+#define soc_is_omap54xx()              0
+#define soc_is_omap543x()              0
 
 #if defined(MULTI_OMAP1)
 # if defined(CONFIG_ARCH_OMAP730)
@@ -238,9 +243,7 @@ IS_AM_SUBCLASS(335x, 0x335)
 /*
  * Macros to detect individual cpu types.
  * These are only rarely needed.
- * cpu_is_omap330():   True for OMAP330
- * cpu_is_omap730():   True for OMAP730
- * cpu_is_omap850():   True for OMAP850
+ * cpu_is_omap310():   True for OMAP310
  * cpu_is_omap1510():  True for OMAP1510
  * cpu_is_omap1610():  True for OMAP1610
  * cpu_is_omap1611():  True for OMAP1611
@@ -262,8 +265,6 @@ static inline int is_omap ##type (void)                     \
 }
 
 IS_OMAP_TYPE(310, 0x0310)
-IS_OMAP_TYPE(730, 0x0730)
-IS_OMAP_TYPE(850, 0x0850)
 IS_OMAP_TYPE(1510, 0x1510)
 IS_OMAP_TYPE(1610, 0x1610)
 IS_OMAP_TYPE(1611, 0x1611)
@@ -277,8 +278,6 @@ IS_OMAP_TYPE(2430, 0x2430)
 IS_OMAP_TYPE(3430, 0x3430)
 
 #define cpu_is_omap310()               0
-#define cpu_is_omap730()               0
-#define cpu_is_omap850()               0
 #define cpu_is_omap1510()              0
 #define cpu_is_omap1610()              0
 #define cpu_is_omap5912()              0
@@ -291,22 +290,13 @@ IS_OMAP_TYPE(3430, 0x3430)
 #define cpu_is_omap2430()              0
 #define cpu_is_omap3430()              0
 #define cpu_is_omap3630()              0
+#define soc_is_omap5430()              0
 
 /*
  * Whether we have MULTI_OMAP1 or not, we still need to distinguish
- * between 730 vs 850, 330 vs. 1510 and 1611B/5912 vs. 1710.
+ * between 310 vs. 1510 and 1611B/5912 vs. 1710.
  */
 
-#if defined(CONFIG_ARCH_OMAP730)
-# undef  cpu_is_omap730
-# define cpu_is_omap730()              is_omap730()
-#endif
-
-#if defined(CONFIG_ARCH_OMAP850)
-# undef  cpu_is_omap850
-# define cpu_is_omap850()              is_omap850()
-#endif
-
 #if defined(CONFIG_ARCH_OMAP15XX)
 # undef  cpu_is_omap310
 # undef  cpu_is_omap1510
@@ -344,8 +334,6 @@ IS_OMAP_TYPE(3430, 0x3430)
 # undef cpu_is_ti816x
 # undef cpu_is_ti814x
 # undef soc_is_am35xx
-# undef cpu_is_am33xx
-# undef cpu_is_am335x
 # define cpu_is_omap3430()             is_omap3430()
 # undef cpu_is_omap3630
 # define cpu_is_omap3630()             is_omap363x()
@@ -353,8 +341,13 @@ IS_OMAP_TYPE(3430, 0x3430)
 # define cpu_is_ti816x()               is_ti816x()
 # define cpu_is_ti814x()               is_ti814x()
 # define soc_is_am35xx()               is_am35xx()
-# define cpu_is_am33xx()               is_am33xx()
-# define cpu_is_am335x()               is_am335x()
+#endif
+
+# if defined(CONFIG_SOC_AM33XX)
+# undef soc_is_am33xx
+# undef soc_is_am335x
+# define soc_is_am33xx()               is_am33xx()
+# define soc_is_am335x()               is_am335x()
 #endif
 
 # if defined(CONFIG_ARCH_OMAP4)
@@ -368,11 +361,18 @@ IS_OMAP_TYPE(3430, 0x3430)
 # define cpu_is_omap447x()             is_omap447x()
 # endif
 
+# if defined(CONFIG_SOC_OMAP5)
+# undef soc_is_omap54xx
+# undef soc_is_omap543x
+# define soc_is_omap54xx()             is_omap54xx()
+# define soc_is_omap543x()             is_omap543x()
+#endif
+
 /* Macros to detect if we have OMAP1 or OMAP2 */
 #define cpu_class_is_omap1()   (cpu_is_omap7xx() || cpu_is_omap15xx() || \
                                cpu_is_omap16xx())
 #define cpu_class_is_omap2()   (cpu_is_omap24xx() || cpu_is_omap34xx() || \
-                               cpu_is_omap44xx())
+                               cpu_is_omap44xx() || soc_is_omap54xx())
 
 /* Various silicon revisions for omap2 */
 #define OMAP242X_CLASS         0x24200024
@@ -408,7 +408,7 @@ IS_OMAP_TYPE(3430, 0x3430)
 #define AM35XX_REV_ES1_0       AM35XX_CLASS
 #define AM35XX_REV_ES1_1       (AM35XX_CLASS | (0x1 << 8))
 
-#define AM335X_CLASS           0x33500034
+#define AM335X_CLASS           0x33500033
 #define AM335X_REV_ES1_0       AM335X_CLASS
 
 #define OMAP443X_CLASS         0x44300044
@@ -425,9 +425,14 @@ IS_OMAP_TYPE(3430, 0x3430)
 #define OMAP447X_CLASS         0x44700044
 #define OMAP4470_REV_ES1_0     (OMAP447X_CLASS | (0x10 << 8))
 
+#define OMAP54XX_CLASS         0x54000054
+#define OMAP5430_REV_ES1_0     (OMAP54XX_CLASS | (0x30 << 16) | (0x10 << 8))
+#define OMAP5432_REV_ES1_0     (OMAP54XX_CLASS | (0x32 << 16) | (0x10 << 8))
+
 void omap2xxx_check_revision(void);
 void omap3xxx_check_revision(void);
 void omap4xxx_check_revision(void);
+void omap5xxx_check_revision(void);
 void omap3xxx_check_features(void);
 void ti81xx_check_features(void);
 void omap4xxx_check_features(void);
index 5da73562e4867ce732a9ca9b3aeb2db33eebee45..19e7fa577bd0ad04eadcc4276d0de4f40039dadd 100644 (file)
 #define OMAP_TIMER_TRIGGER_OVERFLOW            0x01
 #define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE        0x02
 
-/*
- * IP revision identifier so that Highlander IP
- * in OMAP4 can be distinguished.
- */
-#define OMAP_TIMER_IP_VERSION_1                        0x1
-
 /* timer capabilities used in hwmod database */
 #define OMAP_TIMER_SECURE                              0x80000000
 #define OMAP_TIMER_ALWON                               0x40000000
 #define OMAP_TIMER_HAS_PWM                             0x20000000
+#define OMAP_TIMER_NEEDS_RESET                         0x10000000
 
 struct omap_timer_capability_dev_attr {
        u32 timer_capability;
 };
 
 struct omap_dm_timer;
-struct clk;
 
 struct timer_regs {
        u32 tidr;
@@ -96,16 +90,12 @@ struct timer_regs {
 };
 
 struct dmtimer_platform_data {
+       /* set_timer_src - Only used for OMAP1 devices */
        int (*set_timer_src)(struct platform_device *pdev, int source);
-       int timer_ip_version;
-       u32 needs_manual_reset:1;
-       bool reserved;
-
-       bool loses_context;
-
-       int (*get_context_loss_count)(struct device *dev);
+       u32 timer_capability;
 };
 
+int omap_dm_timer_reserve_systimer(int id);
 struct omap_dm_timer *omap_dm_timer_request(void);
 struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
 int omap_dm_timer_free(struct omap_dm_timer *timer);
@@ -272,13 +262,11 @@ struct omap_dm_timer {
        unsigned reserved:1;
        unsigned posted:1;
        struct timer_regs context;
-       bool loses_context;
        int ctx_loss_count;
        int revision;
+       u32 capability;
        struct platform_device *pdev;
        struct list_head node;
-
-       int (*get_context_loss_count)(struct device *dev);
 };
 
 int omap_dm_timer_prepare(struct omap_dm_timer *timer);
index 9c604b390f9f74cd8fdfa63eb617a1cd6e3ebe02..5927709b19089910d6a04b5478ed19c7b3db5426 100644 (file)
@@ -18,6 +18,9 @@ struct omap_dsp_platform_data {
        u32 (*dsp_cm_read)(s16 , u16);
        u32 (*dsp_cm_rmw_bits)(u32, u32, s16, s16);
 
+       void (*set_bootaddr)(u32);
+       void (*set_bootmode)(u8);
+
        phys_addr_t phys_mempool_base;
        phys_addr_t phys_mempool_size;
 };
index e897978371c2719167eb7bfbe2625dc5d7bc6fdf..ddbde38e1e332266c7eedb69762658414772c76b 100644 (file)
 #include <plat/omap44xx.h>
 #include <plat/ti81xx.h>
 #include <plat/am33xx.h>
+#include <plat/omap54xx.h>
 
 #endif /* __ASM_ARCH_OMAP_HARDWARE_H */
index 999ffba2690c148749c96b65bfbcde7fbbb833a5..045e320f1067408abc1ef08e6a3667fe911c63f7 100644 (file)
 # endif
 #endif
 
+#ifdef CONFIG_SOC_OMAP5
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP2
+#  define MULTI_OMAP2
+# else
+#  define OMAP_NAME omap5
+# endif
+#endif
+
 #endif /* __PLAT_OMAP_MULTI_H */
index aeba71796ad943b0f412104682cab2a40cabda92..32394895920080b7aa5344016bb90a0199482072 100644 (file)
@@ -99,7 +99,7 @@
 
 /*
  * OMAP730/850 has a slightly different config for the pin mux.
- * - config regs are the OMAP7XX_IO_CONF_x regs (see omap730.h) regs and
+ * - config regs are the OMAP7XX_IO_CONF_x regs (see omap7xx.h) regs and
  *   not the FUNC_MUX_CTRL_x regs from hardware.h
  * - for pull-up/down, only has one enable bit which is is in the same register
  *   as mux config
index 8c7994ce9869a98fc7b673d6ebfcc0b4d63187c0..0e4acd2d2deb84fa6d864865a20da582f94990fd 100644 (file)
@@ -3,12 +3,7 @@
 
 #include <linux/types.h>
 
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
 extern int omap_secure_ram_reserve_memblock(void);
-#else
-static inline void omap_secure_ram_reserve_memblock(void)
-{ }
-#endif
 
 #ifdef CONFIG_OMAP4_ERRATA_I688
 extern int omap_barrier_reserve_memblock(void);
diff --git a/arch/arm/plat-omap/include/plat/omap54xx.h b/arch/arm/plat-omap/include/plat/omap54xx.h
new file mode 100644 (file)
index 0000000..a2582bb
--- /dev/null
@@ -0,0 +1,32 @@
+/*:
+ * Address mappings and base address for OMAP5 interconnects
+ * and peripherals.
+ *
+ * Copyright (C) 2012 Texas Instruments
+ *     Santosh Shilimkar <santosh.shilimkar@ti.com>
+ *     Sricharan <r.sricharan@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#ifndef __ASM_SOC_OMAP54XX_H
+#define __ASM_SOC_OMAP54XX_H
+
+/*
+ * Please place only base defines here and put the rest in device
+ * specific headers.
+ */
+#define L4_54XX_BASE                   0x4a000000
+#define L4_WK_54XX_BASE                        0x4ae00000
+#define L4_PER_54XX_BASE               0x48000000
+#define L3_54XX_BASE                   0x44000000
+#define OMAP54XX_32KSYNCT_BASE         0x4ae04000
+#define OMAP54XX_CM_CORE_AON_BASE      0x4a004000
+#define OMAP54XX_CM_CORE_BASE          0x4a008000
+#define OMAP54XX_PRM_BASE              0x4ae06000
+#define OMAP54XX_PRCM_MPU_BASE         0x48243000
+#define OMAP54XX_SCM_BASE              0x4a002000
+#define OMAP54XX_CTRL_BASE             0x4a002800
+
+#endif /* __ASM_SOC_OMAP555554XX_H */
diff --git a/arch/arm/plat-omap/include/plat/omap730.h b/arch/arm/plat-omap/include/plat/omap730.h
deleted file mode 100644 (file)
index 14272bc..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/* arch/arm/plat-omap/include/mach/omap730.h
- *
- * Hardware definitions for TI OMAP730 processor.
- *
- * Cleanup for Linux-2.6 by Dirk Behme <dirk.behme@de.bosch.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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ASM_ARCH_OMAP730_H
-#define __ASM_ARCH_OMAP730_H
-
-/*
- * ----------------------------------------------------------------------------
- * Base addresses
- * ----------------------------------------------------------------------------
- */
-
-/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-
-#define OMAP730_DSP_BASE       0xE0000000
-#define OMAP730_DSP_SIZE       0x50000
-#define OMAP730_DSP_START      0xE0000000
-
-#define OMAP730_DSPREG_BASE    0xE1000000
-#define OMAP730_DSPREG_SIZE    SZ_128K
-#define OMAP730_DSPREG_START   0xE1000000
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP730 specific configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP730_CONFIG_BASE    0xfffe1000
-#define OMAP730_IO_CONF_0      0xfffe1070
-#define OMAP730_IO_CONF_1      0xfffe1074
-#define OMAP730_IO_CONF_2      0xfffe1078
-#define OMAP730_IO_CONF_3      0xfffe107c
-#define OMAP730_IO_CONF_4      0xfffe1080
-#define OMAP730_IO_CONF_5      0xfffe1084
-#define OMAP730_IO_CONF_6      0xfffe1088
-#define OMAP730_IO_CONF_7      0xfffe108c
-#define OMAP730_IO_CONF_8      0xfffe1090
-#define OMAP730_IO_CONF_9      0xfffe1094
-#define OMAP730_IO_CONF_10     0xfffe1098
-#define OMAP730_IO_CONF_11     0xfffe109c
-#define OMAP730_IO_CONF_12     0xfffe10a0
-#define OMAP730_IO_CONF_13     0xfffe10a4
-
-#define OMAP730_MODE_1         0xfffe1010
-#define OMAP730_MODE_2         0xfffe1014
-
-/* CSMI specials: in terms of base + offset */
-#define OMAP730_MODE2_OFFSET   0x14
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP730 traffic controller configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP730_FLASH_CFG_0    0xfffecc10
-#define OMAP730_FLASH_ACFG_0   0xfffecc50
-#define OMAP730_FLASH_CFG_1    0xfffecc14
-#define OMAP730_FLASH_ACFG_1   0xfffecc54
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP730 DSP control registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP730_ICR_BASE       0xfffbb800
-#define OMAP730_DSP_M_CTL      0xfffbb804
-#define OMAP730_DSP_MMU_BASE   0xfffed200
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP730 PCC_UPLD configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP730_PCC_UPLD_CTRL_BASE     (0xfffe0900)
-#define OMAP730_PCC_UPLD_CTRL          (OMAP730_PCC_UPLD_CTRL_BASE + 0x00)
-
-#endif /*  __ASM_ARCH_OMAP730_H */
-
diff --git a/arch/arm/plat-omap/include/plat/omap850.h b/arch/arm/plat-omap/include/plat/omap850.h
deleted file mode 100644 (file)
index c33f679..0000000
+++ /dev/null
@@ -1,102 +0,0 @@
-/* arch/arm/plat-omap/include/mach/omap850.h
- *
- * Hardware definitions for TI OMAP850 processor.
- *
- * Derived from omap730.h by Zebediah C. McClure <zmc@lurian.net>
- *
- * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
- * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * 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.,
- * 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#ifndef __ASM_ARCH_OMAP850_H
-#define __ASM_ARCH_OMAP850_H
-
-/*
- * ----------------------------------------------------------------------------
- * Base addresses
- * ----------------------------------------------------------------------------
- */
-
-/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
-
-#define OMAP850_DSP_BASE       0xE0000000
-#define OMAP850_DSP_SIZE       0x50000
-#define OMAP850_DSP_START      0xE0000000
-
-#define OMAP850_DSPREG_BASE    0xE1000000
-#define OMAP850_DSPREG_SIZE    SZ_128K
-#define OMAP850_DSPREG_START   0xE1000000
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP850 specific configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP850_CONFIG_BASE    0xfffe1000
-#define OMAP850_IO_CONF_0      0xfffe1070
-#define OMAP850_IO_CONF_1      0xfffe1074
-#define OMAP850_IO_CONF_2      0xfffe1078
-#define OMAP850_IO_CONF_3      0xfffe107c
-#define OMAP850_IO_CONF_4      0xfffe1080
-#define OMAP850_IO_CONF_5      0xfffe1084
-#define OMAP850_IO_CONF_6      0xfffe1088
-#define OMAP850_IO_CONF_7      0xfffe108c
-#define OMAP850_IO_CONF_8      0xfffe1090
-#define OMAP850_IO_CONF_9      0xfffe1094
-#define OMAP850_IO_CONF_10     0xfffe1098
-#define OMAP850_IO_CONF_11     0xfffe109c
-#define OMAP850_IO_CONF_12     0xfffe10a0
-#define OMAP850_IO_CONF_13     0xfffe10a4
-
-#define OMAP850_MODE_1         0xfffe1010
-#define OMAP850_MODE_2         0xfffe1014
-
-/* CSMI specials: in terms of base + offset */
-#define OMAP850_MODE2_OFFSET   0x14
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP850 traffic controller configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP850_FLASH_CFG_0    0xfffecc10
-#define OMAP850_FLASH_ACFG_0   0xfffecc50
-#define OMAP850_FLASH_CFG_1    0xfffecc14
-#define OMAP850_FLASH_ACFG_1   0xfffecc54
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP850 DSP control registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP850_ICR_BASE       0xfffbb800
-#define OMAP850_DSP_M_CTL      0xfffbb804
-#define OMAP850_DSP_MMU_BASE   0xfffed200
-
-/*
- * ----------------------------------------------------------------------------
- * OMAP850 PCC_UPLD configuration registers
- * ----------------------------------------------------------------------------
- */
-#define OMAP850_PCC_UPLD_CTRL_BASE     (0xfffe0900)
-#define OMAP850_PCC_UPLD_CTRL          (OMAP850_PCC_UPLD_CTRL_BASE + 0x00)
-
-#endif /*  __ASM_ARCH_OMAP850_H */
-
index c835b7194ff57ba71d5448746ea21e6134e39ef7..6132972aff372e399f1595f9e8e398f06a5b5fa8 100644 (file)
@@ -41,6 +41,7 @@ struct omap_device;
 
 extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type1;
 extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
+extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type3;
 
 /*
  * OCP SYSCONFIG bit shifts/masks TYPE1. These are for IPs compliant
@@ -69,6 +70,17 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2;
 #define SYSC_TYPE2_SIDLEMODE_MASK      (0x3 << SYSC_TYPE2_SIDLEMODE_SHIFT)
 #define SYSC_TYPE2_MIDLEMODE_SHIFT     4
 #define SYSC_TYPE2_MIDLEMODE_MASK      (0x3 << SYSC_TYPE2_MIDLEMODE_SHIFT)
+#define SYSC_TYPE2_DMADISABLE_SHIFT    16
+#define SYSC_TYPE2_DMADISABLE_MASK     (0x1 << SYSC_TYPE2_DMADISABLE_SHIFT)
+
+/*
+ * OCP SYSCONFIG bit shifts/masks TYPE3.
+ * This is applicable for some IPs present in AM33XX
+ */
+#define SYSC_TYPE3_SIDLEMODE_SHIFT     0
+#define SYSC_TYPE3_SIDLEMODE_MASK      (0x3 << SYSC_TYPE3_SIDLEMODE_SHIFT)
+#define SYSC_TYPE3_MIDLEMODE_SHIFT     2
+#define SYSC_TYPE3_MIDLEMODE_MASK      (0x3 << SYSC_TYPE3_MIDLEMODE_SHIFT)
 
 /* OCP SYSSTATUS bit shifts/masks */
 #define SYSS_RESETDONE_SHIFT           0
@@ -283,6 +295,7 @@ struct omap_hwmod_ocp_if {
 #define SYSS_HAS_RESET_STATUS  (1 << 7)
 #define SYSC_NO_CACHE          (1 << 8)  /* XXX SW flag, belongs elsewhere */
 #define SYSC_HAS_RESET_STATUS  (1 << 9)
+#define SYSC_HAS_DMADISABLE    (1 << 10)
 
 /* omap_hwmod_sysconfig.clockact flags */
 #define CLOCKACT_TEST_BOTH     0x0
@@ -298,6 +311,7 @@ struct omap_hwmod_ocp_if {
  * @enwkup_shift: Offset of the enawakeup bit
  * @srst_shift: Offset of the softreset bit
  * @autoidle_shift: Offset of the autoidle bit
+ * @dmadisable_shift: Offset of the dmadisable bit
  */
 struct omap_hwmod_sysc_fields {
        u8 midle_shift;
@@ -306,6 +320,7 @@ struct omap_hwmod_sysc_fields {
        u8 enwkup_shift;
        u8 srst_shift;
        u8 autoidle_shift;
+       u8 dmadisable_shift;
 };
 
 /**
@@ -374,11 +389,13 @@ struct omap_hwmod_omap2_prcm {
  * struct omap_hwmod_omap4_prcm - OMAP4-specific PRCM data
  * @clkctrl_reg: PRCM address of the clock control register
  * @rstctrl_reg: address of the XXX_RSTCTRL register located in the PRM
+ * @rstst_reg: (AM33XX only) address of the XXX_RSTST register in the PRM
  * @submodule_wkdep_bit: bit shift of the WKDEP range
  */
 struct omap_hwmod_omap4_prcm {
        u16             clkctrl_offs;
        u16             rstctrl_offs;
+       u16             rstst_offs;
        u16             context_offs;
        u8              submodule_wkdep_bit;
        u8              modulemode;
@@ -629,6 +646,10 @@ int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
 
 int omap_hwmod_pad_route_irq(struct omap_hwmod *oh, int pad_idx, int irq_idx);
 
+extern void __init omap_hwmod_init(void);
+
+const char *omap_hwmod_get_main_clk(struct omap_hwmod *oh);
+
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
  * to use initcalls once the initial boot ordering is straightened out
index 9bb978ecd884ac3a378a40a03f9c59b494181929..36d6a76662166d1e570afdc293252e0bcb39884a 100644 (file)
@@ -123,7 +123,7 @@ struct omap_sdrc_params {
        u32 mr;
 };
 
-#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+#ifdef CONFIG_SOC_HAS_OMAP2_SDRC
 void omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
                            struct omap_sdrc_params *sdrc_cs1);
 #else
index b073e5f2b190a6b4b04543d7a20d94dbc48a8c19..65fce44dce342b3650637b53beaeb0e8f1d2c3d8 100644 (file)
 /* AM3505/3517 UART4 */
 #define AM35XX_UART4_BASE      0x4809E000      /* Only on AM3505/3517 */
 
+/* AM33XX serial port */
+#define AM33XX_UART1_BASE      0x44E09000
+
+/* OMAP5 serial ports */
+#define OMAP5_UART1_BASE       OMAP2_UART1_BASE
+#define OMAP5_UART2_BASE       OMAP2_UART2_BASE
+#define OMAP5_UART3_BASE       OMAP4_UART3_BASE
+#define OMAP5_UART4_BASE       OMAP4_UART4_BASE
+#define OMAP5_UART5_BASE       0x48066000
+#define OMAP5_UART6_BASE       0x48068000
+
 /* External port on Zoom2/3 */
 #define ZOOM_UART_BASE         0x10000000
 #define ZOOM_UART_VIRT         0xfa400000
 #define TI81XXUART1            81
 #define TI81XXUART2            82
 #define TI81XXUART3            83
+#define AM33XXUART1            84
+#define OMAP5UART3             OMAP4UART3
+#define OMAP5UART4             OMAP4UART4
 #define ZOOM_UART              95              /* Only on zoom2/3 */
 
 /* This is only used by 8250.c for omap1510 */
index cc3f11ba7a994cb0207f757d02bba617e8a8fd13..b8d19a136781e4ba89382cc151ba6fe0190ccbc3 100644 (file)
@@ -95,6 +95,9 @@ static inline void flush(void)
        _DEBUG_LL_ENTRY(mach, OMAP4_UART##p##_BASE, OMAP_PORT_SHIFT,    \
                OMAP4UART##p)
 
+#define DEBUG_LL_OMAP5(p, mach)                                                \
+       _DEBUG_LL_ENTRY(mach, OMAP5_UART##p##_BASE, OMAP_PORT_SHIFT,    \
+               OMAP5UART##p)
 /* Zoom2/3 shift is different for UART1 and external port */
 #define DEBUG_LL_ZOOM(mach)                                            \
        _DEBUG_LL_ENTRY(mach, ZOOM_UART_BASE, ZOOM_PORT_SHIFT, ZOOM_UART)
@@ -103,6 +106,10 @@ static inline void flush(void)
        _DEBUG_LL_ENTRY(mach, TI81XX_UART##p##_BASE, OMAP_PORT_SHIFT,   \
                TI81XXUART##p)
 
+#define DEBUG_LL_AM33XX(p, mach)                                       \
+       _DEBUG_LL_ENTRY(mach, AM33XX_UART##p##_BASE, OMAP_PORT_SHIFT,   \
+               AM33XXUART##p)
+
 static inline void __arch_decomp_setup(unsigned long arch_id)
 {
        int port = 0;
@@ -173,6 +180,9 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
                DEBUG_LL_OMAP4(3, omap_4430sdp);
                DEBUG_LL_OMAP4(3, omap4_panda);
 
+               /* omap5 based boards using UART3 */
+               DEBUG_LL_OMAP5(3, omap5_sevm);
+
                /* zoom2/3 external uart */
                DEBUG_LL_ZOOM(omap_zoom2);
                DEBUG_LL_ZOOM(omap_zoom3);
@@ -183,6 +193,8 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
                /* TI8148 base boards using UART1 */
                DEBUG_LL_TI81XX(1, ti8148evm);
 
+               /* AM33XX base boards using UART1 */
+               DEBUG_LL_AM33XX(1, am335xevm);
        } while (0);
 }
 
index 762eeb0626c128fd5c40bbb97daff230ef881466..548a4c8d63df4b5d072ee560d901d39137941d47 100644 (file)
@@ -44,6 +44,8 @@ struct usbhs_omap_board_data {
        struct regulator                *regulator[OMAP3_HS_USB_PORTS];
 };
 
+#ifdef CONFIG_ARCH_OMAP2PLUS
+
 struct ehci_hcd_omap_platform_data {
        enum usbhs_omap_port_mode       port_mode[OMAP3_HS_USB_PORTS];
        int                             reset_gpio_port[OMAP3_HS_USB_PORTS];
@@ -64,26 +66,6 @@ struct usbhs_omap_platform_data {
 };
 /*-------------------------------------------------------------------------*/
 
-#define OMAP1_OTG_BASE                 0xfffb0400
-#define OMAP1_UDC_BASE                 0xfffb4000
-#define OMAP1_OHCI_BASE                        0xfffba000
-
-#define OMAP2_OHCI_BASE                        0x4805e000
-#define OMAP2_UDC_BASE                 0x4805e200
-#define OMAP2_OTG_BASE                 0x4805e300
-
-#ifdef CONFIG_ARCH_OMAP1
-
-#define OTG_BASE                       OMAP1_OTG_BASE
-#define UDC_BASE                       OMAP1_UDC_BASE
-#define OMAP_OHCI_BASE                 OMAP1_OHCI_BASE
-
-#else
-
-#define OTG_BASE                       OMAP2_OTG_BASE
-#define UDC_BASE                       OMAP2_UDC_BASE
-#define OMAP_OHCI_BASE                 OMAP2_OHCI_BASE
-
 struct omap_musb_board_data {
        u8      interface_type;
        u8      mode;
@@ -107,44 +89,6 @@ extern int omap4430_phy_init(struct device *dev);
 extern int omap4430_phy_exit(struct device *dev);
 extern int omap4430_phy_suspend(struct device *dev, int suspend);
 
-/*
- * NOTE: Please update omap USB drivers to use ioremap + read/write
- */
-
-#define OMAP2_L4_IO_OFFSET     0xb2000000
-#define OMAP2_L4_IO_ADDRESS(pa)        IOMEM((pa) + OMAP2_L4_IO_OFFSET)
-
-static inline u8 omap_readb(u32 pa)
-{
-       return __raw_readb(OMAP2_L4_IO_ADDRESS(pa));
-}
-
-static inline u16 omap_readw(u32 pa)
-{
-       return __raw_readw(OMAP2_L4_IO_ADDRESS(pa));
-}
-
-static inline u32 omap_readl(u32 pa)
-{
-       return __raw_readl(OMAP2_L4_IO_ADDRESS(pa));
-}
-
-static inline void omap_writeb(u8 v, u32 pa)
-{
-       __raw_writeb(v, OMAP2_L4_IO_ADDRESS(pa));
-}
-
-
-static inline void omap_writew(u16 v, u32 pa)
-{
-       __raw_writew(v, OMAP2_L4_IO_ADDRESS(pa));
-}
-
-static inline void omap_writel(u32 v, u32 pa)
-{
-       __raw_writel(v, OMAP2_L4_IO_ADDRESS(pa));
-}
-
 #endif
 
 extern void am35x_musb_reset(void);
@@ -153,142 +97,6 @@ extern void am35x_musb_clear_irq(void);
 extern void am35x_set_mode(u8 musb_mode);
 extern void ti81xx_musb_phy_power(u8 on);
 
-/*
- * FIXME correct answer depends on hmc_mode,
- * as does (on omap1) any nonzero value for config->otg port number
- */
-#ifdef CONFIG_USB_GADGET_OMAP
-#define        is_usb0_device(config)  1
-#else
-#define        is_usb0_device(config)  0
-#endif
-
-void omap_otg_init(struct omap_usb_config *config);
-
-#if defined(CONFIG_USB) || defined(CONFIG_USB_MODULE)
-void omap1_usb_init(struct omap_usb_config *pdata);
-#else
-static inline void omap1_usb_init(struct omap_usb_config *pdata)
-{
-}
-#endif
-
-#if defined(CONFIG_ARCH_OMAP_OTG) || defined(CONFIG_ARCH_OMAP_OTG_MODULE)
-void omap2_usbfs_init(struct omap_usb_config *pdata);
-#else
-static inline void omap2_usbfs_init(struct omap_usb_config *pdata)
-{
-}
-#endif
-
-/*-------------------------------------------------------------------------*/
-
-/*
- * OTG and transceiver registers, for OMAPs starting with ARM926
- */
-#define OTG_REV                                (OTG_BASE + 0x00)
-#define OTG_SYSCON_1                   (OTG_BASE + 0x04)
-#      define   USB2_TRX_MODE(w)       (((w)>>24)&0x07)
-#      define   USB1_TRX_MODE(w)       (((w)>>20)&0x07)
-#      define   USB0_TRX_MODE(w)       (((w)>>16)&0x07)
-#      define   OTG_IDLE_EN            (1 << 15)
-#      define   HST_IDLE_EN            (1 << 14)
-#      define   DEV_IDLE_EN            (1 << 13)
-#      define   OTG_RESET_DONE         (1 << 2)
-#      define   OTG_SOFT_RESET         (1 << 1)
-#define OTG_SYSCON_2                   (OTG_BASE + 0x08)
-#      define   OTG_EN                 (1 << 31)
-#      define   USBX_SYNCHRO           (1 << 30)
-#      define   OTG_MST16              (1 << 29)
-#      define   SRP_GPDATA             (1 << 28)
-#      define   SRP_GPDVBUS            (1 << 27)
-#      define   SRP_GPUVBUS(w)         (((w)>>24)&0x07)
-#      define   A_WAIT_VRISE(w)        (((w)>>20)&0x07)
-#      define   B_ASE_BRST(w)          (((w)>>16)&0x07)
-#      define   SRP_DPW                (1 << 14)
-#      define   SRP_DATA               (1 << 13)
-#      define   SRP_VBUS               (1 << 12)
-#      define   OTG_PADEN              (1 << 10)
-#      define   HMC_PADEN              (1 << 9)
-#      define   UHOST_EN               (1 << 8)
-#      define   HMC_TLLSPEED           (1 << 7)
-#      define   HMC_TLLATTACH          (1 << 6)
-#      define   OTG_HMC(w)             (((w)>>0)&0x3f)
-#define OTG_CTRL                       (OTG_BASE + 0x0c)
-#      define   OTG_USB2_EN            (1 << 29)
-#      define   OTG_USB2_DP            (1 << 28)
-#      define   OTG_USB2_DM            (1 << 27)
-#      define   OTG_USB1_EN            (1 << 26)
-#      define   OTG_USB1_DP            (1 << 25)
-#      define   OTG_USB1_DM            (1 << 24)
-#      define   OTG_USB0_EN            (1 << 23)
-#      define   OTG_USB0_DP            (1 << 22)
-#      define   OTG_USB0_DM            (1 << 21)
-#      define   OTG_ASESSVLD           (1 << 20)
-#      define   OTG_BSESSEND           (1 << 19)
-#      define   OTG_BSESSVLD           (1 << 18)
-#      define   OTG_VBUSVLD            (1 << 17)
-#      define   OTG_ID                 (1 << 16)
-#      define   OTG_DRIVER_SEL         (1 << 15)
-#      define   OTG_A_SETB_HNPEN       (1 << 12)
-#      define   OTG_A_BUSREQ           (1 << 11)
-#      define   OTG_B_HNPEN            (1 << 9)
-#      define   OTG_B_BUSREQ           (1 << 8)
-#      define   OTG_BUSDROP            (1 << 7)
-#      define   OTG_PULLDOWN           (1 << 5)
-#      define   OTG_PULLUP             (1 << 4)
-#      define   OTG_DRV_VBUS           (1 << 3)
-#      define   OTG_PD_VBUS            (1 << 2)
-#      define   OTG_PU_VBUS            (1 << 1)
-#      define   OTG_PU_ID              (1 << 0)
-#define OTG_IRQ_EN                     (OTG_BASE + 0x10)       /* 16-bit */
-#      define   DRIVER_SWITCH          (1 << 15)
-#      define   A_VBUS_ERR             (1 << 13)
-#      define   A_REQ_TMROUT           (1 << 12)
-#      define   A_SRP_DETECT           (1 << 11)
-#      define   B_HNP_FAIL             (1 << 10)
-#      define   B_SRP_TMROUT           (1 << 9)
-#      define   B_SRP_DONE             (1 << 8)
-#      define   B_SRP_STARTED          (1 << 7)
-#      define   OPRT_CHG               (1 << 0)
-#define OTG_IRQ_SRC                    (OTG_BASE + 0x14)       /* 16-bit */
-       // same bits as in IRQ_EN
-#define OTG_OUTCTRL                    (OTG_BASE + 0x18)       /* 16-bit */
-#      define   OTGVPD                 (1 << 14)
-#      define   OTGVPU                 (1 << 13)
-#      define   OTGPUID                (1 << 12)
-#      define   USB2VDR                (1 << 10)
-#      define   USB2PDEN               (1 << 9)
-#      define   USB2PUEN               (1 << 8)
-#      define   USB1VDR                (1 << 6)
-#      define   USB1PDEN               (1 << 5)
-#      define   USB1PUEN               (1 << 4)
-#      define   USB0VDR                (1 << 2)
-#      define   USB0PDEN               (1 << 1)
-#      define   USB0PUEN               (1 << 0)
-#define OTG_TEST                       (OTG_BASE + 0x20)       /* 16-bit */
-#define OTG_VENDOR_CODE                        (OTG_BASE + 0xfc)       /* 16-bit */
-
-/*-------------------------------------------------------------------------*/
-
-/* OMAP1 */
-#define        USB_TRANSCEIVER_CTRL            (0xfffe1000 + 0x0064)
-#      define  CONF_USB2_UNI_R         (1 << 8)
-#      define  CONF_USB1_UNI_R         (1 << 7)
-#      define  CONF_USB_PORT0_R(x)     (((x)>>4)&0x7)
-#      define  CONF_USB0_ISOLATE_R     (1 << 3)
-#      define  CONF_USB_PWRDN_DM_R     (1 << 2)
-#      define  CONF_USB_PWRDN_DP_R     (1 << 1)
-
-/* OMAP2 */
-#      define  USB_UNIDIR                      0x0
-#      define  USB_UNIDIR_TLL                  0x1
-#      define  USB_BIDIR                       0x2
-#      define  USB_BIDIR_TLL                   0x3
-#      define  USBTXWRMODEI(port, x)   ((x) << (22 - (port * 2)))
-#      define  USBT2TLL5PI             (1 << 17)
-#      define  USB0PUENACTLOI          (1 << 16)
-#      define  USBSTANDBYCTRL          (1 << 15)
 /* AM35x */
 /* USB 2.0 PHY Control */
 #define CONF2_PHY_GPIOMODE     (1 << 23)
index 0a6a482ec01439320dee0f7e51746720aa4aa78b..5be4d5def427a9b97a39dff2473ca76f12f5f976 100644 (file)
 #ifndef __ARCH_ARM_OMAP_VOLTAGE_H
 #define __ARCH_ARM_OMAP_VOLTAGE_H
 
+/**
+ * struct omap_volt_data - Omap voltage specific data.
+ * @voltage_nominal:   The possible voltage value in uV
+ * @sr_efuse_offs:     The offset of the efuse register(from system
+ *                     control module base address) from where to read
+ *                     the n-target value for the smartreflex module.
+ * @sr_errminlimit:    Error min limit value for smartreflex. This value
+ *                     differs at differnet opp and thus is linked
+ *                     with voltage.
+ * @vp_errorgain:      Error gain value for the voltage processor. This
+ *                     field also differs according to the voltage/opp.
+ */
+struct omap_volt_data {
+       u32     volt_nominal;
+       u32     sr_efuse_offs;
+       u8      sr_errminlimit;
+       u8      vp_errgain;
+};
 struct voltagedomain;
 
 struct voltagedomain *voltdm_lookup(const char *name);
 int voltdm_scale(struct voltagedomain *voltdm, unsigned long target_volt);
 unsigned long voltdm_get_voltage(struct voltagedomain *voltdm);
-
+struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
+               unsigned long volt);
 #endif
index ad32621aa52e259fe20346d60f5d9f7d38edbad6..5e13c3884aa441c099bd274ef51d27acf36e06ab 100644 (file)
@@ -282,6 +282,8 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
                }
                mbox->rxq = mq;
                mq->mbox = mbox;
+
+               omap_mbox_enable_irq(mbox, IRQ_RX);
        }
        mutex_unlock(&mbox_configured_lock);
        return 0;
@@ -305,6 +307,7 @@ static void omap_mbox_fini(struct omap_mbox *mbox)
        mutex_lock(&mbox_configured_lock);
 
        if (!--mbox->use_count) {
+               omap_mbox_disable_irq(mbox, IRQ_RX);
                free_irq(mbox->irq, mbox);
                tasklet_kill(&mbox->txq->tasklet);
                flush_work_sync(&mbox->rxq->work);
@@ -338,13 +341,15 @@ struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
        if (!mbox)
                return ERR_PTR(-ENOENT);
 
-       ret = omap_mbox_startup(mbox);
-       if (ret)
-               return ERR_PTR(-ENODEV);
-
        if (nb)
                blocking_notifier_chain_register(&mbox->notifier, nb);
 
+       ret = omap_mbox_startup(mbox);
+       if (ret) {
+               blocking_notifier_chain_unregister(&mbox->notifier, nb);
+               return ERR_PTR(-ENODEV);
+       }
+
        return mbox;
 }
 EXPORT_SYMBOL(omap_mbox_get);
index 477363c163ec5b3fc12b3f4de942673ce213c999..766181cb5c95c277b8495966835571059a36dda5 100644 (file)
@@ -6,8 +6,8 @@
  * Copyright (C) 2005 Nokia Corporation
  * Written by Tony Lindgren <tony@atomide.com>
  *
- * Copyright (C) 2009 Texas Instruments
- * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
+ * Copyright (C) 2009-2012 Texas Instruments
+ * Added OMAP4/5 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -44,6 +44,7 @@
 #else
 #define OMAP4_SRAM_PUB_PA      (OMAP4_SRAM_PA + 0x4000)
 #endif
+#define OMAP5_SRAM_PA          0x40300000
 
 #if defined(CONFIG_ARCH_OMAP2PLUS)
 #define SRAM_BOOTLOADER_SZ     0x00
@@ -85,7 +86,7 @@ static int is_sram_locked(void)
                        __raw_writel(0xCFDE, OMAP24XX_VA_READPERM0);  /* all i-read */
                        __raw_writel(0xCFDE, OMAP24XX_VA_WRITEPERM0); /* all i-write */
                }
-               if (cpu_is_omap34xx() && !cpu_is_am33xx()) {
+               if (cpu_is_omap34xx()) {
                        __raw_writel(0xFFFF, OMAP34XX_VA_REQINFOPERM0); /* all q-vects */
                        __raw_writel(0xFFFF, OMAP34XX_VA_READPERM0);  /* all i-read */
                        __raw_writel(0xFFFF, OMAP34XX_VA_WRITEPERM0); /* all i-write */
@@ -118,12 +119,15 @@ static void __init omap_detect_sram(void)
                        } else if (cpu_is_omap44xx()) {
                                omap_sram_start = OMAP4_SRAM_PUB_PA;
                                omap_sram_size = 0xa000; /* 40K */
+                       } else if (soc_is_omap54xx()) {
+                               omap_sram_start = OMAP5_SRAM_PA;
+                               omap_sram_size = SZ_128K; /* 128KB */
                        } else {
                                omap_sram_start = OMAP2_SRAM_PUB_PA;
                                omap_sram_size = 0x800; /* 2K */
                        }
                } else {
-                       if (cpu_is_am33xx()) {
+                       if (soc_is_am33xx()) {
                                omap_sram_start = AM33XX_SRAM_PA;
                                omap_sram_size = 0x10000; /* 64K */
                        } else if (cpu_is_omap34xx()) {
@@ -132,6 +136,9 @@ static void __init omap_detect_sram(void)
                        } else if (cpu_is_omap44xx()) {
                                omap_sram_start = OMAP4_SRAM_PA;
                                omap_sram_size = 0xe000; /* 56K */
+                       } else if (soc_is_omap54xx()) {
+                               omap_sram_start = OMAP5_SRAM_PA;
+                               omap_sram_size = SZ_128K; /* 128KB */
                        } else {
                                omap_sram_start = OMAP2_SRAM_PA;
                                if (cpu_is_omap242x())
@@ -386,7 +393,7 @@ int __init omap_sram_init(void)
                omap242x_sram_init();
        else if (cpu_is_omap2430())
                omap243x_sram_init();
-       else if (cpu_is_am33xx())
+       else if (soc_is_am33xx())
                am33xx_sram_init();
        else if (cpu_is_omap34xx())
                omap34xx_sram_init();
diff --git a/arch/arm/plat-omap/usb.c b/arch/arm/plat-omap/usb.c
deleted file mode 100644 (file)
index daa0327..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
- /*
- * arch/arm/plat-omap/usb.c -- platform level USB initialization
- *
- * Copyright (C) 2004 Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License 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
- */
-
-#undef DEBUG
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <plat/usb.h>
-#include <plat/board.h>
-
-#include <mach/hardware.h>
-
-#ifdef CONFIG_ARCH_OMAP_OTG
-
-void __init
-omap_otg_init(struct omap_usb_config *config)
-{
-       u32             syscon;
-       int             alt_pingroup = 0;
-
-       /* NOTE:  no bus or clock setup (yet?) */
-
-       syscon = omap_readl(OTG_SYSCON_1) & 0xffff;
-       if (!(syscon & OTG_RESET_DONE))
-               pr_debug("USB resets not complete?\n");
-
-       //omap_writew(0, OTG_IRQ_EN);
-
-       /* pin muxing and transceiver pinouts */
-       if (config->pins[0] > 2)        /* alt pingroup 2 */
-               alt_pingroup = 1;
-       syscon |= config->usb0_init(config->pins[0], is_usb0_device(config));
-       syscon |= config->usb1_init(config->pins[1]);
-       syscon |= config->usb2_init(config->pins[2], alt_pingroup);
-       pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1));
-       omap_writel(syscon, OTG_SYSCON_1);
-
-       syscon = config->hmc_mode;
-       syscon |= USBX_SYNCHRO | (4 << 16) /* B_ASE0_BRST */;
-#ifdef CONFIG_USB_OTG
-       if (config->otg)
-               syscon |= OTG_EN;
-#endif
-       if (cpu_class_is_omap1())
-               pr_debug("USB_TRANSCEIVER_CTRL = %03x\n",
-                        omap_readl(USB_TRANSCEIVER_CTRL));
-       pr_debug("OTG_SYSCON_2 = %08x\n", omap_readl(OTG_SYSCON_2));
-       omap_writel(syscon, OTG_SYSCON_2);
-
-       printk("USB: hmc %d", config->hmc_mode);
-       if (!alt_pingroup)
-               printk(", usb2 alt %d wires", config->pins[2]);
-       else if (config->pins[0])
-               printk(", usb0 %d wires%s", config->pins[0],
-                       is_usb0_device(config) ? " (dev)" : "");
-       if (config->pins[1])
-               printk(", usb1 %d wires", config->pins[1]);
-       if (!alt_pingroup && config->pins[2])
-               printk(", usb2 %d wires", config->pins[2]);
-       if (config->otg)
-               printk(", Mini-AB on usb%d", config->otg - 1);
-       printk("\n");
-
-       if (cpu_class_is_omap1()) {
-               u16 w;
-
-               /* leave USB clocks/controllers off until needed */
-               w = omap_readw(ULPD_SOFT_REQ);
-               w &= ~SOFT_USB_CLK_REQ;
-               omap_writew(w, ULPD_SOFT_REQ);
-
-               w = omap_readw(ULPD_CLOCK_CTRL);
-               w &= ~USB_MCLK_EN;
-               w |= DIS_USB_PVCI_CLK;
-               omap_writew(w, ULPD_CLOCK_CTRL);
-       }
-       syscon = omap_readl(OTG_SYSCON_1);
-       syscon |= HST_IDLE_EN|DEV_IDLE_EN|OTG_IDLE_EN;
-
-#ifdef CONFIG_USB_GADGET_OMAP
-       if (config->otg || config->register_dev) {
-               struct platform_device *udc_device = config->udc_device;
-               int status;
-
-               syscon &= ~DEV_IDLE_EN;
-               udc_device->dev.platform_data = config;
-               status = platform_device_register(udc_device);
-               if (status)
-                       pr_debug("can't register UDC device, %d\n", status);
-       }
-#endif
-
-#if    defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-       if (config->otg || config->register_host) {
-               struct platform_device *ohci_device = config->ohci_device;
-               int status;
-
-               syscon &= ~HST_IDLE_EN;
-               ohci_device->dev.platform_data = config;
-               status = platform_device_register(ohci_device);
-               if (status)
-                       pr_debug("can't register OHCI device, %d\n", status);
-       }
-#endif
-
-#ifdef CONFIG_USB_OTG
-       if (config->otg) {
-               struct platform_device *otg_device = config->otg_device;
-               int status;
-
-               syscon &= ~OTG_IDLE_EN;
-               otg_device->dev.platform_data = config;
-               status = platform_device_register(otg_device);
-               if (status)
-                       pr_debug("can't register OTG device, %d\n", status);
-       }
-#endif
-       pr_debug("OTG_SYSCON_1 = %08x\n", omap_readl(OTG_SYSCON_1));
-       omap_writel(syscon, OTG_SYSCON_1);
-}
-
-#else
-void omap_otg_init(struct omap_usb_config *config) {}
-#endif
index bc42c04091fdfc90c7c346279a61e284830afd35..fe57bbbf166bae61ccb21203e185b6e7e64c827c 100644 (file)
@@ -533,7 +533,7 @@ void __init s3c24xx_init_irq(void)
        int i;
 
 #ifdef CONFIG_FIQ
-       init_FIQ();
+       init_FIQ(FIQ_START);
 #endif
 
        irqdbf("s3c2410_init_irq: clearing interrupt status flags\n");
index a2fae4ea0936655b0f3b0131c1be748c943c71ee..7aca31c1df1fe57ac91b4278b13ad8036a8dac93 100644 (file)
@@ -78,6 +78,10 @@ config S5P_HRT
 
 # clock options
 
+config SAMSUNG_CLOCK
+       bool
+       default y if !COMMON_CLK
+
 config SAMSUNG_CLKSRC
        bool
        help
@@ -491,14 +495,6 @@ config S5P_SLEEP
          Internal config node to apply common S5P sleep management code.
          Can be selected by S5P and newer SoCs with similar sleep procedure.
 
-comment "Power Domain"
-
-config SAMSUNG_PD
-       bool "Samsung Power Domain"
-       depends on PM_RUNTIME
-       help
-         Say Y here if you want to control Power Domain by Runtime PM.
-
 config DEBUG_S3C_UART
        depends on PLAT_SAMSUNG
        int
index 860b2db4db155062b66361ce6688a11d6b86ff49..b78717496677fae8e17ba77392785aeea90e9ffd 100644 (file)
@@ -15,8 +15,8 @@ obj-y                         += init.o cpu.o
 obj-$(CONFIG_ARCH_USES_GETTIMEOFFSET)   += time.o
 obj-$(CONFIG_S5P_HRT)          += s5p-time.o
 
-obj-y                          += clock.o
-obj-y                          += pwm-clock.o
+obj-$(CONFIG_SAMSUNG_CLOCK)    += clock.o
+obj-$(CONFIG_SAMSUNG_CLOCK)    += pwm-clock.o
 
 obj-$(CONFIG_SAMSUNG_CLKSRC)   += clock-clksrc.o
 obj-$(CONFIG_S5P_CLOCK)                += s5p-clock.o
@@ -60,10 +60,6 @@ obj-$(CONFIG_SAMSUNG_WAKEMASK)       += wakeup-mask.o
 obj-$(CONFIG_S5P_PM)           += s5p-pm.o s5p-irq-pm.o
 obj-$(CONFIG_S5P_SLEEP)                += s5p-sleep.o
 
-# PD support
-
-obj-$(CONFIG_SAMSUNG_PD)       += pd.o
-
 # PWM support
 
 obj-$(CONFIG_HAVE_PWM)         += pwm.o
index 6303974c2ee06af0e81a4f60437f0fac86d2f4f6..74e31ce355388bd7c2062b35fb30e09ca085b3f5 100644 (file)
@@ -1513,7 +1513,7 @@ static struct resource s3c64xx_spi0_resource[] = {
 };
 
 struct platform_device s3c64xx_device_spi0 = {
-       .name           = "s3c64xx-spi",
+       .name           = "s3c6410-spi",
        .id             = 0,
        .num_resources  = ARRAY_SIZE(s3c64xx_spi0_resource),
        .resource       = s3c64xx_spi0_resource,
@@ -1523,13 +1523,10 @@ struct platform_device s3c64xx_device_spi0 = {
        },
 };
 
-void __init s3c64xx_spi0_set_platdata(struct s3c64xx_spi_info *pd,
-                                     int src_clk_nr, int num_cs)
+void __init s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
+                                               int num_cs)
 {
-       if (!pd) {
-               pr_err("%s:Need to pass platform data\n", __func__);
-               return;
-       }
+       struct s3c64xx_spi_info pd;
 
        /* Reject invalid configuration */
        if (!num_cs || src_clk_nr < 0) {
@@ -1537,12 +1534,11 @@ void __init s3c64xx_spi0_set_platdata(struct s3c64xx_spi_info *pd,
                return;
        }
 
-       pd->num_cs = num_cs;
-       pd->src_clk_nr = src_clk_nr;
-       if (!pd->cfg_gpio)
-               pd->cfg_gpio = s3c64xx_spi0_cfg_gpio;
+       pd.num_cs = num_cs;
+       pd.src_clk_nr = src_clk_nr;
+       pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi0_cfg_gpio;
 
-       s3c_set_platdata(pd, sizeof(*pd), &s3c64xx_device_spi0);
+       s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi0);
 }
 #endif /* CONFIG_S3C64XX_DEV_SPI0 */
 
@@ -1555,7 +1551,7 @@ static struct resource s3c64xx_spi1_resource[] = {
 };
 
 struct platform_device s3c64xx_device_spi1 = {
-       .name           = "s3c64xx-spi",
+       .name           = "s3c6410-spi",
        .id             = 1,
        .num_resources  = ARRAY_SIZE(s3c64xx_spi1_resource),
        .resource       = s3c64xx_spi1_resource,
@@ -1565,26 +1561,20 @@ struct platform_device s3c64xx_device_spi1 = {
        },
 };
 
-void __init s3c64xx_spi1_set_platdata(struct s3c64xx_spi_info *pd,
-                                     int src_clk_nr, int num_cs)
+void __init s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
+                                               int num_cs)
 {
-       if (!pd) {
-               pr_err("%s:Need to pass platform data\n", __func__);
-               return;
-       }
-
        /* Reject invalid configuration */
        if (!num_cs || src_clk_nr < 0) {
                pr_err("%s: Invalid SPI configuration\n", __func__);
                return;
        }
 
-       pd->num_cs = num_cs;
-       pd->src_clk_nr = src_clk_nr;
-       if (!pd->cfg_gpio)
-               pd->cfg_gpio = s3c64xx_spi1_cfg_gpio;
+       pd.num_cs = num_cs;
+       pd.src_clk_nr = src_clk_nr;
+       pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi1_cfg_gpio;
 
-       s3c_set_platdata(pd, sizeof(*pd), &s3c64xx_device_spi1);
+       s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi1);
 }
 #endif /* CONFIG_S3C64XX_DEV_SPI1 */
 
@@ -1597,7 +1587,7 @@ static struct resource s3c64xx_spi2_resource[] = {
 };
 
 struct platform_device s3c64xx_device_spi2 = {
-       .name           = "s3c64xx-spi",
+       .name           = "s3c6410-spi",
        .id             = 2,
        .num_resources  = ARRAY_SIZE(s3c64xx_spi2_resource),
        .resource       = s3c64xx_spi2_resource,
@@ -1607,13 +1597,10 @@ struct platform_device s3c64xx_device_spi2 = {
        },
 };
 
-void __init s3c64xx_spi2_set_platdata(struct s3c64xx_spi_info *pd,
-                                     int src_clk_nr, int num_cs)
+void __init s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
+                                               int num_cs)
 {
-       if (!pd) {
-               pr_err("%s:Need to pass platform data\n", __func__);
-               return;
-       }
+       struct s3c64xx_spi_info pd;
 
        /* Reject invalid configuration */
        if (!num_cs || src_clk_nr < 0) {
@@ -1621,11 +1608,10 @@ void __init s3c64xx_spi2_set_platdata(struct s3c64xx_spi_info *pd,
                return;
        }
 
-       pd->num_cs = num_cs;
-       pd->src_clk_nr = src_clk_nr;
-       if (!pd->cfg_gpio)
-               pd->cfg_gpio = s3c64xx_spi2_cfg_gpio;
+       pd.num_cs = num_cs;
+       pd.src_clk_nr = src_clk_nr;
+       pd.cfg_gpio = (cfg_gpio) ? cfg_gpio : s3c64xx_spi2_cfg_gpio;
 
-       s3c_set_platdata(pd, sizeof(*pd), &s3c64xx_device_spi2);
+       s3c_set_platdata(&pd, sizeof(pd), &s3c64xx_device_spi2);
 }
 #endif /* CONFIG_S3C64XX_DEV_SPI2 */
index eb9f4f5340060d432f7fd6741a3acfc6fbfa2dbc..c38d75489240fc34476ef9bfd2a3caa010df2967 100644 (file)
 #include <mach/dma.h>
 
 static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
-                               struct samsung_dma_info *info)
+                               struct samsung_dma_req *param)
 {
-       struct dma_chan *chan;
        dma_cap_mask_t mask;
-       struct dma_slave_config slave_config;
        void *filter_param;
 
        dma_cap_zero(mask);
-       dma_cap_set(info->cap, mask);
+       dma_cap_set(param->cap, mask);
 
        /*
         * If a dma channel property of a device node from device tree is
         * specified, use that as the fliter parameter.
         */
-       filter_param = (dma_ch == DMACH_DT_PROP) ? (void *)info->dt_dmach_prop :
-                               (void *)dma_ch;
-       chan = dma_request_channel(mask, pl330_filter, filter_param);
+       filter_param = (dma_ch == DMACH_DT_PROP) ?
+               (void *)param->dt_dmach_prop : (void *)dma_ch;
+       return (unsigned)dma_request_channel(mask, pl330_filter, filter_param);
+}
+
+static int samsung_dmadev_release(unsigned ch, void *param)
+{
+       dma_release_channel((struct dma_chan *)ch);
 
-       if (info->direction == DMA_DEV_TO_MEM) {
+       return 0;
+}
+
+static int samsung_dmadev_config(unsigned ch,
+                               struct samsung_dma_config *param)
+{
+       struct dma_chan *chan = (struct dma_chan *)ch;
+       struct dma_slave_config slave_config;
+
+       if (param->direction == DMA_DEV_TO_MEM) {
                memset(&slave_config, 0, sizeof(struct dma_slave_config));
-               slave_config.direction = info->direction;
-               slave_config.src_addr = info->fifo;
-               slave_config.src_addr_width = info->width;
+               slave_config.direction = param->direction;
+               slave_config.src_addr = param->fifo;
+               slave_config.src_addr_width = param->width;
                slave_config.src_maxburst = 1;
                dmaengine_slave_config(chan, &slave_config);
-       } else if (info->direction == DMA_MEM_TO_DEV) {
+       } else if (param->direction == DMA_MEM_TO_DEV) {
                memset(&slave_config, 0, sizeof(struct dma_slave_config));
-               slave_config.direction = info->direction;
-               slave_config.dst_addr = info->fifo;
-               slave_config.dst_addr_width = info->width;
+               slave_config.direction = param->direction;
+               slave_config.dst_addr = param->fifo;
+               slave_config.dst_addr_width = param->width;
                slave_config.dst_maxburst = 1;
                dmaengine_slave_config(chan, &slave_config);
+       } else {
+               pr_warn("unsupported direction\n");
+               return -EINVAL;
        }
 
-       return (unsigned)chan;
-}
-
-static int samsung_dmadev_release(unsigned ch,
-                       struct s3c2410_dma_client *client)
-{
-       dma_release_channel((struct dma_chan *)ch);
-
        return 0;
 }
 
 static int samsung_dmadev_prepare(unsigned ch,
-                       struct samsung_dma_prep_info *info)
+                       struct samsung_dma_prep *param)
 {
        struct scatterlist sg;
        struct dma_chan *chan = (struct dma_chan *)ch;
        struct dma_async_tx_descriptor *desc;
 
-       switch (info->cap) {
+       switch (param->cap) {
        case DMA_SLAVE:
                sg_init_table(&sg, 1);
-               sg_dma_len(&sg) = info->len;
-               sg_set_page(&sg, pfn_to_page(PFN_DOWN(info->buf)),
-                           info->len, offset_in_page(info->buf));
-               sg_dma_address(&sg) = info->buf;
+               sg_dma_len(&sg) = param->len;
+               sg_set_page(&sg, pfn_to_page(PFN_DOWN(param->buf)),
+                           param->len, offset_in_page(param->buf));
+               sg_dma_address(&sg) = param->buf;
 
                desc = dmaengine_prep_slave_sg(chan,
-                       &sg, 1, info->direction, DMA_PREP_INTERRUPT);
+                       &sg, 1, param->direction, DMA_PREP_INTERRUPT);
                break;
        case DMA_CYCLIC:
-               desc = dmaengine_prep_dma_cyclic(chan,
-                       info->buf, info->len, info->period, info->direction);
+               desc = dmaengine_prep_dma_cyclic(chan, param->buf,
+                       param->len, param->period, param->direction);
                break;
        default:
                dev_err(&chan->dev->device, "unsupported format\n");
@@ -96,8 +103,8 @@ static int samsung_dmadev_prepare(unsigned ch,
                return -EFAULT;
        }
 
-       desc->callback = info->fp;
-       desc->callback_param = info->fp_param;
+       desc->callback = param->fp;
+       desc->callback_param = param->fp_param;
 
        dmaengine_submit((struct dma_async_tx_descriptor *)desc);
 
@@ -119,6 +126,7 @@ static inline int samsung_dmadev_flush(unsigned ch)
 static struct samsung_dma_ops dmadev_ops = {
        .request        = samsung_dmadev_request,
        .release        = samsung_dmadev_release,
+       .config         = samsung_dmadev_config,
        .prepare        = samsung_dmadev_prepare,
        .trigger        = samsung_dmadev_trigger,
        .started        = NULL,
index 0721293fad635b913a3a07f082f13aba32ea0179..ace4451b7651388053eeaa8644e0a3f8856c54e8 100644 (file)
@@ -132,6 +132,10 @@ IS_SAMSUNG_CPU(exynos5250, EXYNOS5250_SOC_ID, EXYNOS5_SOC_MASK)
 
 #define IODESC_ENT(x) { (unsigned long)S3C24XX_VA_##x, __phys_to_pfn(S3C24XX_PA_##x), S3C24XX_SZ_##x, MT_DEVICE }
 
+#ifndef KHZ
+#define KHZ (1000)
+#endif
+
 #ifndef MHZ
 #define MHZ (1000*1000)
 #endif
index 61ca2f356c52d6d4ea3fac036788cc422aa02235..5da4b4f38f40ebb41c076fbe74bd205aefefdacf 100644 (file)
@@ -131,7 +131,6 @@ extern struct platform_device exynos4_device_ohci;
 extern struct platform_device exynos4_device_pcm0;
 extern struct platform_device exynos4_device_pcm1;
 extern struct platform_device exynos4_device_pcm2;
-extern struct platform_device exynos4_device_pd[];
 extern struct platform_device exynos4_device_spdif;
 
 extern struct platform_device exynos_device_drm;
index 71a6827c7706b21e10200bd834b5dbaad1fa9e45..f5144cdd300106b5afb936015a35251eae1d2de9 100644 (file)
 #include <linux/dmaengine.h>
 #include <mach/dma.h>
 
-struct samsung_dma_prep_info {
+struct samsung_dma_req {
+       enum dma_transaction_type cap;
+       struct property *dt_dmach_prop;
+       struct s3c2410_dma_client *client;
+};
+
+struct samsung_dma_prep {
        enum dma_transaction_type cap;
        enum dma_transfer_direction direction;
        dma_addr_t buf;
@@ -26,19 +32,17 @@ struct samsung_dma_prep_info {
        void *fp_param;
 };
 
-struct samsung_dma_info {
-       enum dma_transaction_type cap;
+struct samsung_dma_config {
        enum dma_transfer_direction direction;
        enum dma_slave_buswidth width;
        dma_addr_t fifo;
-       struct s3c2410_dma_client *client;
-       struct property *dt_dmach_prop;
 };
 
 struct samsung_dma_ops {
-       unsigned (*request)(enum dma_ch ch, struct samsung_dma_info *info);
-       int (*release)(unsigned ch, struct s3c2410_dma_client *client);
-       int (*prepare)(unsigned ch, struct samsung_dma_prep_info *info);
+       unsigned (*request)(enum dma_ch ch, struct samsung_dma_req *param);
+       int (*release)(unsigned ch, void *param);
+       int (*config)(unsigned ch, struct samsung_dma_config *param);
+       int (*prepare)(unsigned ch, struct samsung_dma_prep *param);
        int (*trigger)(unsigned ch);
        int (*started)(unsigned ch);
        int (*flush)(unsigned ch);
index 536002ff2ab8d665993b1f554a90ac74642917ad..b885322717a14258a74675062d792705b0bd849e 100644 (file)
@@ -43,7 +43,6 @@ struct s3c_fb_pd_win {
  * @setup_gpio: Setup the external GPIO pins to the right state to transfer
  *             the data from the display system to the connected display
  *             device.
- * @default_win: default window layer number to be used for UI layer.
  * @vidcon0: The base vidcon0 values to control the panel data format.
  * @vidcon1: The base vidcon1 values to control the panel data output.
  * @vtiming: Video timing when connected to a RGB type panel.
diff --git a/arch/arm/plat-samsung/include/plat/pd.h b/arch/arm/plat-samsung/include/plat/pd.h
deleted file mode 100644 (file)
index abb4bc3..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/* linux/arch/arm/plat-samsung/include/plat/pd.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
-*/
-
-#ifndef __ASM_PLAT_SAMSUNG_PD_H
-#define __ASM_PLAT_SAMSUNG_PD_H __FILE__
-
-struct samsung_pd_info {
-       int (*enable)(struct device *dev);
-       int (*disable)(struct device *dev);
-       void __iomem *base;
-};
-
-enum exynos4_pd_block {
-       PD_MFC,
-       PD_G3D,
-       PD_LCD0,
-       PD_LCD1,
-       PD_TV,
-       PD_CAM,
-       PD_GPS
-};
-
-#endif /* __ASM_PLAT_SAMSUNG_PD_H */
index fa95e9a009729f41ddd1c39174e4f6908f515226..ceba18d23a5a530ef233f5f5ecfe0e987cb87274 100644 (file)
@@ -18,7 +18,6 @@ struct platform_device;
  * @fb_delay: Slave specific feedback delay.
  *            Refer to FB_CLK_SEL register definition in SPI chapter.
  * @line: Custom 'identity' of the CS line.
- * @set_level: CS line control.
  *
  * This is per SPI-Slave Chipselect information.
  * Allocate and initialize one in machine init code and make the
@@ -27,57 +26,41 @@ struct platform_device;
 struct s3c64xx_spi_csinfo {
        u8 fb_delay;
        unsigned line;
-       void (*set_level)(unsigned line_id, int lvl);
 };
 
 /**
  * struct s3c64xx_spi_info - SPI Controller defining structure
  * @src_clk_nr: Clock source index for the CLK_CFG[SPI_CLKSEL] field.
- * @clk_from_cmu: If the SPI clock/prescalar control block is present
- *     by the platform's clock-management-unit and not in SPI controller.
  * @num_cs: Number of CS this controller emulates.
  * @cfg_gpio: Configure pins for this SPI controller.
- * @fifo_lvl_mask: All tx fifo_lvl fields start at offset-6
- * @rx_lvl_offset: Depends on tx fifo_lvl field and bus number
- * @high_speed: If the controller supports HIGH_SPEED_EN bit
- * @tx_st_done: Depends on tx fifo_lvl field
  */
 struct s3c64xx_spi_info {
        int src_clk_nr;
-       bool clk_from_cmu;
-
        int num_cs;
-
-       int (*cfg_gpio)(struct platform_device *pdev);
-
-       /* Following two fields are for future compatibility */
-       int fifo_lvl_mask;
-       int rx_lvl_offset;
-       int high_speed;
-       int tx_st_done;
+       int (*cfg_gpio)(void);
 };
 
 /**
  * s3c64xx_spi_set_platdata - SPI Controller configure callback by the board
  *                             initialization code.
- * @pd: SPI platform data to set.
+ * @cfg_gpio: Pointer to gpio setup function.
  * @src_clk_nr: Clock the SPI controller is to use to generate SPI clocks.
  * @num_cs: Number of elements in the 'cs' array.
  *
  * Call this from machine init code for each SPI Controller that
  * has some chips attached to it.
  */
-extern void s3c64xx_spi0_set_platdata(struct s3c64xx_spi_info *pd,
-                                     int src_clk_nr, int num_cs);
-extern void s3c64xx_spi1_set_platdata(struct s3c64xx_spi_info *pd,
-                                     int src_clk_nr, int num_cs);
-extern void s3c64xx_spi2_set_platdata(struct s3c64xx_spi_info *pd,
-                                     int src_clk_nr, int num_cs);
+extern void s3c64xx_spi0_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
+                                               int num_cs);
+extern void s3c64xx_spi1_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
+                                               int num_cs);
+extern void s3c64xx_spi2_set_platdata(int (*cfg_gpio)(void), int src_clk_nr,
+                                               int num_cs);
 
 /* defined by architecture to configure gpio */
-extern int s3c64xx_spi0_cfg_gpio(struct platform_device *dev);
-extern int s3c64xx_spi1_cfg_gpio(struct platform_device *dev);
-extern int s3c64xx_spi2_cfg_gpio(struct platform_device *dev);
+extern int s3c64xx_spi0_cfg_gpio(void);
+extern int s3c64xx_spi1_cfg_gpio(void);
+extern int s3c64xx_spi2_cfg_gpio(void);
 
 extern struct s3c64xx_spi_info s3c64xx_spi0_pdata;
 extern struct s3c64xx_spi_info s3c64xx_spi1_pdata;
diff --git a/arch/arm/plat-samsung/pd.c b/arch/arm/plat-samsung/pd.c
deleted file mode 100644 (file)
index 312b510..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/* linux/arch/arm/plat-samsung/pd.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *             http://www.samsung.com
- *
- * Samsung Power domain 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/init.h>
-#include <linux/export.h>
-#include <linux/platform_device.h>
-#include <linux/err.h>
-#include <linux/pm_runtime.h>
-
-#include <plat/pd.h>
-
-static int samsung_pd_probe(struct platform_device *pdev)
-{
-       struct samsung_pd_info *pdata = pdev->dev.platform_data;
-       struct device *dev = &pdev->dev;
-
-       if (!pdata) {
-               dev_err(dev, "no device data specified\n");
-               return -ENOENT;
-       }
-
-       pm_runtime_set_active(dev);
-       pm_runtime_enable(dev);
-
-       dev_info(dev, "power domain registered\n");
-       return 0;
-}
-
-static int __devexit samsung_pd_remove(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-
-       pm_runtime_disable(dev);
-       return 0;
-}
-
-static int samsung_pd_runtime_suspend(struct device *dev)
-{
-       struct samsung_pd_info *pdata = dev->platform_data;
-       int ret = 0;
-
-       if (pdata->disable)
-               ret = pdata->disable(dev);
-
-       dev_dbg(dev, "suspended\n");
-       return ret;
-}
-
-static int samsung_pd_runtime_resume(struct device *dev)
-{
-       struct samsung_pd_info *pdata = dev->platform_data;
-       int ret = 0;
-
-       if (pdata->enable)
-               ret = pdata->enable(dev);
-
-       dev_dbg(dev, "resumed\n");
-       return ret;
-}
-
-static const struct dev_pm_ops samsung_pd_pm_ops = {
-       .runtime_suspend        = samsung_pd_runtime_suspend,
-       .runtime_resume         = samsung_pd_runtime_resume,
-};
-
-static struct platform_driver samsung_pd_driver = {
-       .driver         = {
-               .name           = "samsung-pd",
-               .owner          = THIS_MODULE,
-               .pm             = &samsung_pd_pm_ops,
-       },
-       .probe          = samsung_pd_probe,
-       .remove         = __devexit_p(samsung_pd_remove),
-};
-
-static int __init samsung_pd_init(void)
-{
-       int ret;
-
-       ret = platform_driver_register(&samsung_pd_driver);
-       if (ret)
-               printk(KERN_ERR "%s: failed to add PD driver\n", __func__);
-
-       return ret;
-}
-arch_initcall(samsung_pd_init);
index c559d8438c70ee2d873afc43a7d14ee1fc2002c2..d3583050fb05461d83af523a9d1f909d9994c094 100644 (file)
@@ -36,7 +36,6 @@ struct pwm_device {
        unsigned int             duty_ns;
 
        unsigned char            tcon_base;
-       unsigned char            running;
        unsigned char            use_count;
        unsigned char            pwm_id;
 };
@@ -116,7 +115,6 @@ int pwm_enable(struct pwm_device *pwm)
 
        local_irq_restore(flags);
 
-       pwm->running = 1;
        return 0;
 }
 
@@ -134,8 +132,6 @@ void pwm_disable(struct pwm_device *pwm)
        __raw_writel(tcon, S3C2410_TCON);
 
        local_irq_restore(flags);
-
-       pwm->running = 0;
 }
 
 EXPORT_SYMBOL(pwm_disable);
index 78149491282749adf6c71051c1321c35c9404077..f99448c48d30dc93d1dcd7a3f9658b523a9e10dd 100644 (file)
@@ -36,30 +36,26 @@ static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
 }
 
 static unsigned s3c_dma_request(enum dma_ch dma_ch,
-                                struct samsung_dma_info *info)
+                                       struct samsung_dma_req *param)
 {
        struct cb_data *data;
 
-       if (s3c2410_dma_request(dma_ch, info->client, NULL) < 0) {
-               s3c2410_dma_free(dma_ch, info->client);
+       if (s3c2410_dma_request(dma_ch, param->client, NULL) < 0) {
+               s3c2410_dma_free(dma_ch, param->client);
                return 0;
        }
 
+       if (param->cap == DMA_CYCLIC)
+               s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
+
        data = kzalloc(sizeof(struct cb_data), GFP_KERNEL);
        data->ch = dma_ch;
        list_add_tail(&data->node, &dma_list);
 
-       s3c2410_dma_devconfig(dma_ch, info->direction, info->fifo);
-
-       if (info->cap == DMA_CYCLIC)
-               s3c2410_dma_setflags(dma_ch, S3C2410_DMAF_CIRCULAR);
-
-       s3c2410_dma_config(dma_ch, info->width);
-
        return (unsigned)dma_ch;
 }
 
-static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
+static int s3c_dma_release(unsigned ch, void *param)
 {
        struct cb_data *data;
 
@@ -68,16 +64,24 @@ static int s3c_dma_release(unsigned ch, struct s3c2410_dma_client *client)
                        break;
        list_del(&data->node);
 
-       s3c2410_dma_free(ch, client);
+       s3c2410_dma_free(ch, param);
        kfree(data);
 
        return 0;
 }
 
-static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
+static int s3c_dma_config(unsigned ch, struct samsung_dma_config *param)
+{
+       s3c2410_dma_devconfig(ch, param->direction, param->fifo);
+       s3c2410_dma_config(ch, param->width);
+
+       return 0;
+}
+
+static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep *param)
 {
        struct cb_data *data;
-       int len = (info->cap == DMA_CYCLIC) ? info->period : info->len;
+       int len = (param->cap == DMA_CYCLIC) ? param->period : param->len;
 
        list_for_each_entry(data, &dma_list, node)
                if (data->ch == ch)
@@ -85,11 +89,11 @@ static int s3c_dma_prepare(unsigned ch, struct samsung_dma_prep_info *info)
 
        if (!data->fp) {
                s3c2410_dma_set_buffdone_fn(ch, s3c_dma_cb);
-               data->fp = info->fp;
-               data->fp_param = info->fp_param;
+               data->fp = param->fp;
+               data->fp_param = param->fp_param;
        }
 
-       s3c2410_dma_enqueue(ch, (void *)data, info->buf, len);
+       s3c2410_dma_enqueue(ch, (void *)data, param->buf, len);
 
        return 0;
 }
@@ -117,6 +121,7 @@ static inline int s3c_dma_stop(unsigned ch)
 static struct samsung_dma_ops s3c_dma_ops = {
        .request        = s3c_dma_request,
        .release        = s3c_dma_release,
+       .config         = s3c_dma_config,
        .prepare        = s3c_dma_prepare,
        .trigger        = s3c_dma_trigger,
        .started        = s3c_dma_started,
index 81ee7cc344575956a698ad929fe70ca8df1cee33..8d5c10a5084da5dcaa87855abacb9f0a7e005a02 100644 (file)
@@ -1,5 +1,8 @@
 if PLAT_VERSATILE
 
+config PLAT_VERSATILE_CLOCK
+       bool
+
 config PLAT_VERSATILE_CLCD
        bool
 
index a5cb1945bdcc7ec637f288bd65096e5a77ae12f7..272769a8a7d6532bbc0391c0228501467c9a3d95 100644 (file)
@@ -1,4 +1,4 @@
-obj-y  := clock.o
+obj-$(CONFIG_PLAT_VERSATILE_CLOCK) += clock.o
 obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
 obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o
 obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o
index fef96f47876cd0e07364323008d7ad29805bd198..9b765107e15cf8a17cc4803dfabb1c9ada64b337 100644 (file)
@@ -352,6 +352,11 @@ config MEM_MT48H32M16LFCJ_75
        depends on (BFIN526_EZBRD)
        default y
 
+config MEM_MT47H64M16
+       bool
+       depends on (BFIN609_EZKIT)
+       default y
+
 source "arch/blackfin/mach-bf518/Kconfig"
 source "arch/blackfin/mach-bf527/Kconfig"
 source "arch/blackfin/mach-bf533/Kconfig"
@@ -399,8 +404,9 @@ config ROM_BASE
        hex "Kernel ROM Base"
        depends on ROMKERNEL
        default "0x20040040"
-       range 0x20000000 0x20400000 if !(BF54x || BF561)
+       range 0x20000000 0x20400000 if !(BF54x || BF561 || BF60x)
        range 0x20000000 0x30000000 if (BF54x || BF561)
+       range 0xB0000000 0xC0000000 if (BF60x)
        help
          Make sure your ROM base does not include any file-header
          information that is prepended to the kernel.
@@ -1009,6 +1015,12 @@ config HAVE_PWM
 choice
        prompt "Uncached DMA region"
        default DMA_UNCACHED_1M
+config DMA_UNCACHED_32M
+       bool "Enable 32M DMA region"
+config DMA_UNCACHED_16M
+       bool "Enable 16M DMA region"
+config DMA_UNCACHED_8M
+       bool "Enable 8M DMA region"
 config DMA_UNCACHED_4M
        bool "Enable 4M DMA region"
 config DMA_UNCACHED_2M
@@ -1038,7 +1050,7 @@ config BFIN_EXTMEM_ICACHEABLE
 config BFIN_L2_ICACHEABLE
        bool "Enable ICACHE for L2 SRAM"
        depends on BFIN_ICACHE
-       depends on BF54x || BF561
+       depends on (BF54x || BF561 || BF60x) && !SMP
        default n
 
 config BFIN_DCACHE
index be9526bee4fbd9b5b2e7ec26036f08620ff0624d..f4b02350e415b8050a06998b7f6fd706b5403279 100644 (file)
@@ -90,6 +90,7 @@ CONFIG_INPUT_BFIN_ROTARY=y
 # CONFIG_SERIO is not set
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_BFIN_SIMPLE_TIMER=m
+# CONFIG_BFIN_CRC is not set
 CONFIG_BFIN_LINKPORT=y
 # CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_BFIN=y
@@ -153,3 +154,4 @@ CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_MD5=y
 CONFIG_CRYPTO_ARC4=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_DEV_BFIN_CRC=y
index 608be5e6d25c50c69202f7101e9e8061e8148681..dc47d79287f981278211405c364d7f5afdfdbd81 100644 (file)
 #include <linux/linkage.h>
 #include <linux/types.h>
 
-#if defined(CONFIG_DMA_UNCACHED_4M)
+#if defined(CONFIG_DMA_UNCACHED_32M)
+# define DMA_UNCACHED_REGION (32 * 1024 * 1024)
+#elif defined(CONFIG_DMA_UNCACHED_16M)
+# define DMA_UNCACHED_REGION (16 * 1024 * 1024)
+#elif defined(CONFIG_DMA_UNCACHED_8M)
+# define DMA_UNCACHED_REGION (8 * 1024 * 1024)
+#elif defined(CONFIG_DMA_UNCACHED_4M)
 # define DMA_UNCACHED_REGION (4 * 1024 * 1024)
 #elif defined(CONFIG_DMA_UNCACHED_2M)
 # define DMA_UNCACHED_REGION (2 * 1024 * 1024)
index 3deb4452ceedd292d5d548d1a329b8865c793551..75cef4dc85a1a8812b8135a31c6316f1c40f263a 100644 (file)
@@ -79,20 +79,6 @@ struct crc_register {
        u32 revid;
 };
 
-struct bfin_crc {
-       struct miscdevice mdev;
-       struct list_head list;
-       int irq;
-       int dma_ch_src;
-       int dma_ch_dest;
-       volatile struct crc_register *regs;
-       struct crc_info *info;
-       struct mutex mutex;
-       struct completion c;
-       unsigned short opmode;
-       char name[20];
-};
-
 /* CRC_STATUS Masks */
 #define CMPERR                 0x00000002      /* Compare error */
 #define DCNTEXP                        0x00000010      /* datacnt register expired */
index 8597158010b53c69b1c707b8faccbba1065c1de1..2d90d62edc9704e108e01eb29a82fd34cd638a85 100644 (file)
@@ -282,7 +282,7 @@ struct bfin_uart_regs {
 #define UART_GET_GCTL(p)      UART_GET_CTL(p)
 #define UART_GET_LCR(p)       UART_GET_CTL(p)
 #define UART_GET_MCR(p)       UART_GET_CTL(p)
-#if ANOMALY_05001001
+#if ANOMALY_16000030
 #define UART_GET_STAT(p) \
 ({ \
        u32 __ret; \
index aadfb1ad1fac077e436c8b5967d9476c309a3f60..b2d5e733079e18faa72fe2a6de9c3099d705f1d1 100644 (file)
 #define BFIN_SIMPLE_TIMER_START      _IO(BFIN_SIMPLE_TIMER_IOCTL_MAGIC,  6)
 #define BFIN_SIMPLE_TIMER_STOP       _IO(BFIN_SIMPLE_TIMER_IOCTL_MAGIC,  8)
 #define BFIN_SIMPLE_TIMER_READ       _IO(BFIN_SIMPLE_TIMER_IOCTL_MAGIC, 10)
+#define BFIN_SIMPLE_TIMER_READ_COUNTER _IO(BFIN_SIMPLE_TIMER_IOCTL_MAGIC, 11)
+
+#define BFIN_SIMPLE_TIMER_MODE_PWM_ONESHOT             0
+#define BFIN_SIMPLE_TIMER_MODE_PWMOUT_CONT             1
+#define BFIN_SIMPLE_TIMER_MODE_WDTH_CAP                        2
+#define BFIN_SIMPLE_TIMER_MODE_PWMOUT_CONT_NOIRQ       3
 
 #endif
index 2f3339a47626e7e57074f142af8cc28faccdc1dc..f4a0727874365bc748cfb80a72cd5d8e1e850a6b 100644 (file)
@@ -66,9 +66,9 @@ struct bfin_twi_iface {
 
 #define DEFINE_TWI_REG(reg_name, reg) \
 static inline u16 read_##reg_name(struct bfin_twi_iface *iface) \
-       { return iface->regs_base->reg; } \
+       { return bfin_read16(&iface->regs_base->reg); } \
 static inline void write_##reg_name(struct bfin_twi_iface *iface, u16 v) \
-       { iface->regs_base->reg = v; }
+       { bfin_write16(&iface->regs_base->reg, v); }
 
 DEFINE_TWI_REG(CLKDIV, clkdiv)
 DEFINE_TWI_REG(CONTROL, control)
@@ -84,7 +84,7 @@ DEFINE_TWI_REG(FIFO_CTL, fifo_ctl)
 DEFINE_TWI_REG(FIFO_STAT, fifo_stat)
 DEFINE_TWI_REG(XMT_DATA8, xmt_data8)
 DEFINE_TWI_REG(XMT_DATA16, xmt_data16)
-#if !ANOMALY_05001001
+#if !ANOMALY_16000030
 DEFINE_TWI_REG(RCV_DATA8, rcv_data8)
 DEFINE_TWI_REG(RCV_DATA16, rcv_data16)
 #else
@@ -94,7 +94,7 @@ static inline u16 read_RCV_DATA8(struct bfin_twi_iface *iface)
        unsigned long flags;
 
        flags = hard_local_irq_save();
-       ret = iface->regs_base->rcv_data8;
+       ret = bfin_read16(&iface->regs_base->rcv_data8);
        hard_local_irq_restore(flags);
 
        return ret;
@@ -106,7 +106,7 @@ static inline u16 read_RCV_DATA16(struct bfin_twi_iface *iface)
        unsigned long flags;
 
        flags = hard_local_irq_save();
-       ret = iface->regs_base->rcv_data16;
+       ret = bfin_read16(&iface->regs_base->rcv_data16);
        hard_local_irq_restore(flags);
 
        return ret;
index 1f9060395a0a7f767e53bcea97f6f83fa6a787f1..507e7aa6a561d56f0e744181c52ceeef9eab7834 100644 (file)
        call \func;
 #endif
 .endm
+
+#if defined(CONFIG_BFIN_SCRATCH_REG_RETN)
+# define EX_SCRATCH_REG RETN
+#elif defined(CONFIG_BFIN_SCRATCH_REG_RETE)
+# define EX_SCRATCH_REG RETE
+#else
+# define EX_SCRATCH_REG CYCLES
+#endif
+
index e91eae8330a6030a931b33cabf718aba756e7b5e..2673b11376f4deb232106cc348b5ddc25b7f9c05 100644 (file)
        PM_POP_SYNC(9)
 #endif
 
-#ifdef EBIU_AMBCTL
+#ifdef EBIU_AMGCTL
        PM_SYS_POP(9, EBIU_AMBCTL1)
        PM_SYS_POP(8, EBIU_AMBCTL0)
        PM_SYS_POP16(7, EBIU_AMGCTL)
index 3d84d96f7c2cdac272ec7d799be295f86ad0b6a8..98d0133346b5a57042baa2e494c3906b597fd608 100644 (file)
@@ -141,6 +141,8 @@ static inline void bfin_pm_standby_restore(void)
 
 void bfin_gpio_pm_hibernate_restore(void);
 void bfin_gpio_pm_hibernate_suspend(void);
+void bfin_pint_suspend(void);
+void bfin_pint_resume(void);
 
 # if !BFIN_GPIO_PINT
 int gpio_pm_wakeup_ctrl(unsigned gpio, unsigned ctrl);
index 89de539ed0100624ead2e5ea6d7f9790eed11cf2..4ae1144a457821c9349cfa0c4026e481f86a6545 100644 (file)
 /* SYS_IRQS and NR_IRQS are defined in <mach-bf5xx/irq.h> */
 #include <mach/irq.h>
 
+/*
+ * pm save bfin pint registers
+ */
+struct bfin_pm_pint_save {
+       u32 mask_set;
+       u32 assign;
+       u32 edge_set;
+       u32 invert_set;
+};
+
 #if ANOMALY_05000244 && defined(CONFIG_BFIN_ICACHE)
 # define NOP_PAD_ANOMALY_05000244 "nop; nop;"
 #else
index 237579935e29cdf3d30dc5a578c798cbbf7bc2a7..f019e9bcefe9ff1fd211e237fcf509a2d2d5deb6 100644 (file)
@@ -6,6 +6,9 @@
  * Licensed under the GPL-2 or later.
  */
 
+#ifndef __MEM_INIT_H__
+#define __MEM_INIT_H__
+
 #if defined(EBIU_SDGCTL)
 #if defined(CONFIG_MEM_MT48LC16M16A2TG_75) || \
     defined(CONFIG_MEM_MT48LC64M4A2FB_7E) || \
 #else
 #define PLL_BYPASS       0
 #endif
+
+#ifdef CONFIG_BF60x
+
+/* DMC status bits */
+#define IDLE                   0x1
+#define MEMINITDONE            0x4
+#define SRACK                  0x8
+#define PDACK                  0x10
+#define DPDACK                 0x20
+#define DLLCALDONE             0x2000
+#define PENDREF                        0xF0000
+#define PHYRDPHASE             0xF00000
+#define PHYRDPHASE_OFFSET      20
+
+/* DMC control bits */
+#define LPDDR                  0x2
+#define INIT                   0x4
+#define        SRREQ                   0x8
+#define PDREQ                  0x10
+#define DPDREQ                 0x20
+#define PREC                   0x40
+#define ADDRMODE               0x100
+#define RDTOWR                 0xE00
+#define PPREF                  0x1000
+#define DLLCAL                 0x2000
+
+/* DMC DLL control bits */
+#define DLLCALRDCNT            0xFF
+#define DATACYC                        0xF00
+#define DATACYC_OFFSET         8
+
+/* CGU Divisor bits */
+#define CSEL_OFFSET            0
+#define S0SEL_OFFSET           5
+#define SYSSEL_OFFSET          8
+#define S1SEL_OFFSET           13
+#define DSEL_OFFSET            16
+#define OSEL_OFFSET            22
+#define ALGN                   0x20000000
+#define UPDT                   0x40000000
+#define LOCK                   0x80000000
+
+/* CGU Status bits */
+#define PLLEN                  0x1
+#define PLLBP                  0x2
+#define PLOCK                  0x4
+#define CLKSALGN               0x8
+
+/* CGU Control bits */
+#define MSEL_MASK              0x7F00
+#define DF_MASK                        0x1
+
+struct ddr_config {
+       u32 ddr_clk;
+       u32 dmc_ddrctl;
+       u32 dmc_ddrcfg;
+       u32 dmc_ddrtr0;
+       u32 dmc_ddrtr1;
+       u32 dmc_ddrtr2;
+       u32 dmc_ddrmr;
+       u32 dmc_ddrmr1;
+};
+
+#if defined(CONFIG_MEM_MT47H64M16)
+static struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) = {
+       [0] = {
+               .ddr_clk    = 125,
+               .dmc_ddrctl = 0x00000904,
+               .dmc_ddrcfg = 0x00000422,
+               .dmc_ddrtr0 = 0x20705212,
+               .dmc_ddrtr1 = 0x201003CF,
+               .dmc_ddrtr2 = 0x00320107,
+               .dmc_ddrmr  = 0x00000422,
+               .dmc_ddrmr1 = 0x4,
+       },
+       [1] = {
+               .ddr_clk    = 133,
+               .dmc_ddrctl = 0x00000904,
+               .dmc_ddrcfg = 0x00000422,
+               .dmc_ddrtr0 = 0x20806313,
+               .dmc_ddrtr1 = 0x2013040D,
+               .dmc_ddrtr2 = 0x00320108,
+               .dmc_ddrmr  = 0x00000632,
+               .dmc_ddrmr1 = 0x4,
+       },
+       [2] = {
+               .ddr_clk    = 150,
+               .dmc_ddrctl = 0x00000904,
+               .dmc_ddrcfg = 0x00000422,
+               .dmc_ddrtr0 = 0x20A07323,
+               .dmc_ddrtr1 = 0x20160492,
+               .dmc_ddrtr2 = 0x00320209,
+               .dmc_ddrmr  = 0x00000632,
+               .dmc_ddrmr1 = 0x4,
+       },
+       [3] = {
+               .ddr_clk    = 166,
+               .dmc_ddrctl = 0x00000904,
+               .dmc_ddrcfg = 0x00000422,
+               .dmc_ddrtr0 = 0x20A07323,
+               .dmc_ddrtr1 = 0x2016050E,
+               .dmc_ddrtr2 = 0x00320209,
+               .dmc_ddrmr  = 0x00000632,
+               .dmc_ddrmr1 = 0x4,
+       },
+       [4] = {
+               .ddr_clk    = 200,
+               .dmc_ddrctl = 0x00000904,
+               .dmc_ddrcfg = 0x00000422,
+               .dmc_ddrtr0 = 0x20a07323,
+               .dmc_ddrtr1 = 0x2016050f,
+               .dmc_ddrtr2 = 0x00320509,
+               .dmc_ddrmr  = 0x00000632,
+               .dmc_ddrmr1 = 0x4,
+       },
+       [5] = {
+               .ddr_clk    = 225,
+               .dmc_ddrctl = 0x00000904,
+               .dmc_ddrcfg = 0x00000422,
+               .dmc_ddrtr0 = 0x20E0A424,
+               .dmc_ddrtr1 = 0x302006DB,
+               .dmc_ddrtr2 = 0x0032020D,
+               .dmc_ddrmr  = 0x00000842,
+               .dmc_ddrmr1 = 0x4,
+       },
+       [6] = {
+               .ddr_clk    = 250,
+               .dmc_ddrctl = 0x00000904,
+               .dmc_ddrcfg = 0x00000422,
+               .dmc_ddrtr0 = 0x20E0A424,
+               .dmc_ddrtr1 = 0x3020079E,
+               .dmc_ddrtr2 = 0x0032020D,
+               .dmc_ddrmr  = 0x00000842,
+               .dmc_ddrmr1 = 0x4,
+       },
+};
+#endif
+
+static inline void dmc_enter_self_refresh(void)
+{
+       if (bfin_read_DMC0_STAT() & MEMINITDONE) {
+               bfin_write_DMC0_CTL(bfin_read_DMC0_CTL() | SRREQ);
+               while (!(bfin_read_DMC0_STAT() & SRACK))
+                       continue;
+       }
+}
+
+static inline void dmc_exit_self_refresh(void)
+{
+       if (bfin_read_DMC0_STAT() & MEMINITDONE) {
+               bfin_write_DMC0_CTL(bfin_read_DMC0_CTL() & ~SRREQ);
+               while (bfin_read_DMC0_STAT() & SRACK)
+                       continue;
+       }
+}
+
+static inline void init_cgu(u32 cgu_div, u32 cgu_ctl)
+{
+       dmc_enter_self_refresh();
+
+       /* Don't set the same value of MSEL and DF to CGU_CTL */
+       if ((bfin_read32(CGU0_CTL) & (MSEL_MASK | DF_MASK))
+               != cgu_ctl) {
+               bfin_write32(CGU0_DIV, cgu_div);
+               bfin_write32(CGU0_CTL, cgu_ctl);
+               while ((bfin_read32(CGU0_STAT) & (CLKSALGN | PLLBP)) ||
+                       !(bfin_read32(CGU0_STAT) & PLOCK))
+                       continue;
+       }
+
+       bfin_write32(CGU0_DIV, cgu_div | UPDT);
+       while (bfin_read32(CGU0_STAT) & CLKSALGN)
+               continue;
+
+       dmc_exit_self_refresh();
+}
+
+static inline void init_dmc(u32 dmc_clk)
+{
+       int i, dlldatacycle, dll_ctl;
+
+       for (i = 0; i < 7; i++) {
+               if (ddr_config_table[i].ddr_clk == dmc_clk) {
+                       bfin_write_DMC0_CFG(ddr_config_table[i].dmc_ddrcfg);
+                       bfin_write_DMC0_TR0(ddr_config_table[i].dmc_ddrtr0);
+                       bfin_write_DMC0_TR1(ddr_config_table[i].dmc_ddrtr1);
+                       bfin_write_DMC0_TR2(ddr_config_table[i].dmc_ddrtr2);
+                       bfin_write_DMC0_MR(ddr_config_table[i].dmc_ddrmr);
+                       bfin_write_DMC0_EMR1(ddr_config_table[i].dmc_ddrmr1);
+                       bfin_write_DMC0_CTL(ddr_config_table[i].dmc_ddrctl);
+                       break;
+               }
+       }
+
+       while (!(bfin_read_DMC0_STAT() & MEMINITDONE))
+               continue;
+
+       dlldatacycle = (bfin_read_DMC0_STAT() & PHYRDPHASE) >> PHYRDPHASE_OFFSET;
+       dll_ctl = bfin_read_DMC0_DLLCTL();
+       dll_ctl &= ~DATACYC;
+       bfin_write_DMC0_DLLCTL(dll_ctl | (dlldatacycle << DATACYC_OFFSET));
+
+       while (!(bfin_read_DMC0_STAT() & DLLCALDONE))
+               continue;
+}
+#endif
+
+#endif /*__MEM_INIT_H__*/
+
index 70c4e511cae648c4dfbbf0fc2dcf0ac04ddb37af..cec771b8100c7c7e55f4ca242cf4741dc5546166 100644 (file)
        level "   for Supervisor use: Supervisor only registers, all MMRs, and Supervisor\n" \
        level "   only instructions.\n"
 
+extern void double_fault_c(struct pt_regs *fp);
+
 #endif                         /* __ASSEMBLY__ */
 #endif                         /* _BFIN_TRAPS_H */
index c166939ffb2b6b92673e4d721fc534837389a3af..4a32f2dd5ddc39120bb66c1c49e4bc49c630c940 100644 (file)
@@ -45,7 +45,7 @@ static int __init blackfin_dma_init(void)
                atomic_set(&dma_ch[i].chan_status, 0);
                dma_ch[i].regs = dma_io_base_addr[i];
        }
-#ifdef CH_MEM_STREAM3_SRC
+#if defined(CH_MEM_STREAM3_SRC) && defined(CONFIG_BF60x)
        /* Mark MEMDMA Channel 3 as requested since we're using it internally */
        request_dma(CH_MEM_STREAM3_DEST, "Blackfin dma_memcpy");
        request_dma(CH_MEM_STREAM3_SRC, "Blackfin dma_memcpy");
@@ -361,7 +361,7 @@ void __init early_dma_memcpy_done(void)
        __builtin_bfin_ssync();
 }
 
-#ifdef CH_MEM_STREAM3_SRC
+#if defined(CH_MEM_STREAM3_SRC) && defined(CONFIG_BF60x)
 #define bfin_read_MDMA_S_CONFIG bfin_read_MDMA_S3_CONFIG
 #define bfin_write_MDMA_S_CONFIG bfin_write_MDMA_S3_CONFIG
 #define bfin_write_MDMA_S_START_ADDR bfin_write_MDMA_S3_START_ADDR
index 3e366dc2d6e11593fc9a0b986ae3550cf162ec91..34e96ce02aa9671701197e7bc3b8f65902fbb5d5 100644 (file)
@@ -58,11 +58,19 @@ void __init generate_cplb_tables_cpu(unsigned int cpu)
 
 #ifdef CONFIG_ROMKERNEL
        /* Cover kernel XIP flash area */
+#ifdef CONFIG_BF60x
+       addr = CONFIG_ROM_BASE & ~(16 * 1024 * 1024 - 1);
+       d_tbl[i_d].addr = addr;
+       d_tbl[i_d++].data = SDRAM_DGENERIC | PAGE_SIZE_16MB;
+       i_tbl[i_i].addr = addr;
+       i_tbl[i_i++].data = SDRAM_IGENERIC | PAGE_SIZE_16MB;
+#else
        addr = CONFIG_ROM_BASE & ~(4 * 1024 * 1024 - 1);
        d_tbl[i_d].addr = addr;
        d_tbl[i_d++].data = SDRAM_DGENERIC | PAGE_SIZE_4MB;
        i_tbl[i_i].addr = addr;
        i_tbl[i_i++].data = SDRAM_IGENERIC | PAGE_SIZE_4MB;
+#endif
 #endif
 
        /* Cover L1 memory.  One 4M area for code and data each is enough.  */
index f0d1118f1825bf9c3ce5f280f45fabcdbd3e0391..e7be6532d6a04f00cf7d6d1de5d035e4f3b565a9 100644 (file)
@@ -122,12 +122,13 @@ void __dma_sync(dma_addr_t addr, size_t size,
 EXPORT_SYMBOL(__dma_sync);
 
 int
-dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+dma_map_sg(struct device *dev, struct scatterlist *sg_list, int nents,
           enum dma_data_direction direction)
 {
+       struct scatterlist *sg;
        int i;
 
-       for (i = 0; i < nents; i++, sg++) {
+       for_each_sg(sg_list, sg, nents, i) {
                sg->dma_address = (dma_addr_t) sg_virt(sg);
                __dma_sync(sg_dma_address(sg), sg_dma_len(sg), direction);
        }
@@ -136,12 +137,13 @@ dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
 }
 EXPORT_SYMBOL(dma_map_sg);
 
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg_list,
                            int nelems, enum dma_data_direction direction)
 {
+       struct scatterlist *sg;
        int i;
 
-       for (i = 0; i < nelems; i++, sg++) {
+       for_each_sg(sg_list, sg, nelems, i) {
                sg->dma_address = (dma_addr_t) sg_virt(sg);
                __dma_sync(sg_dma_address(sg), sg_dma_len(sg), direction);
        }
index af732eb3a687426b22dfa828f0f6d393975cdf0d..fc179ca077994ea94f1e204294a892885c10ea2b 100644 (file)
@@ -114,9 +114,9 @@ static struct musb_hdrc_config musb_config = {
 };
 
 static struct musb_hdrc_platform_data musb_plat = {
-#if defined(CONFIG_USB_MUSB_OTG)
+#if defined(CONFIG_USB_MUSB_HDRC) && defined(CONFIG_USB_GADGET_MUSB_HDRC)
        .mode           = MUSB_OTG,
-#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
+#elif defined(CONFIG_USB_MUSB_HDRC)
        .mode           = MUSB_HOST,
 #elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
        .mode           = MUSB_PERIPHERAL,
index 3bd75bae750dd004f45d4ff3c8e6ede35b78a0b0..c4d07f040947cba025c1df2d87d9431c7bc2fd36 100644 (file)
@@ -635,9 +635,9 @@ static struct musb_hdrc_config musb_config = {
 };
 
 static struct musb_hdrc_platform_data musb_plat = {
-#if defined(CONFIG_USB_MUSB_OTG)
+#if defined(CONFIG_USB_MUSB_HDRC) && defined(CONFIG_USB_GADGET_MUSB_HDRC)
        .mode           = MUSB_OTG,
-#elif defined(CONFIG_USB_MUSB_HDRC_HCD)
+#elif defined(CONFIG_USB_MUSB_HDRC)
        .mode           = MUSB_HOST,
 #elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
        .mode           = MUSB_PERIPHERAL,
index 35c8ced46158fb0b37bbead251be75d747872977..be9edb28f96bd6bea7fb5b3604d572f6c35b1fc8 100644 (file)
 #define MAX_BLACKFIN_GPIOS 160
 
 #define BFIN_GPIO_PINT 1
+#define NR_PINT_SYS_IRQS        4
+#define NR_PINTS                160
 
 #ifndef __ASSEMBLY__
 
index 838978808a15a4414410301b2ba464604eae5f36..7c36777c645558315d651af24e992d0bd2f722f1 100644 (file)
@@ -452,18 +452,21 @@ static struct v4l2_input adv7183_inputs[] = {
                .name = "Composite",
                .type = V4L2_INPUT_TYPE_CAMERA,
                .std = V4L2_STD_ALL,
+               .capabilities = V4L2_IN_CAP_STD,
        },
        {
                .index = 1,
                .name = "S-Video",
                .type = V4L2_INPUT_TYPE_CAMERA,
                .std = V4L2_STD_ALL,
+               .capabilities = V4L2_IN_CAP_STD,
        },
        {
                .index = 2,
                .name = "Component",
                .type = V4L2_INPUT_TYPE_CAMERA,
                .std = V4L2_STD_ALL,
+               .capabilities = V4L2_IN_CAP_STD,
        },
 };
 
index 2cb7272437787cd50e31aaa2e89b08adfd4b2c74..101b33ee9bbab914d75a7e2295feb6a57290aafa 100644 (file)
@@ -51,6 +51,14 @@ config PINT5_ASSIGN
 
 endmenu
 
+config SEC_IRQ_PRIORITY_LEVELS
+       int "SEC interrupt priority levels"
+       default 7
+       range 0 7
+       help
+         Devide the total number of interrupt priority levels into sub-levels.
+         There is 2 ^ (SEC_IRQ_PRIORITY_LEVELS + 1) different levels.
+
 endmenu
 
 endif
index 2a27f817454367cb1c5b42aac49355f58cd8bee4..234fe1b4bb0e90bd8121fdae991f5428357ea20d 100644 (file)
@@ -2,5 +2,5 @@
 # arch/blackfin/mach-bf609/Makefile
 #
 
-obj-y := dma.o clock.o
-obj-$(CONFIG_PM) += pm.o hibernate.o
+obj-y := dma.o clock.o ints-priority.o
+obj-$(CONFIG_PM) += pm.o dpm.o
index ac64f47217c156d58be5eac34d4cd054ba5acdf8..c2cf1ae31189cb2ce0be5d04e4b6450dc209bebe 100644 (file)
@@ -677,11 +677,28 @@ int bf609_nor_flash_init(struct platform_device *dev)
        return 0;
 }
 
+void bf609_nor_flash_exit(struct platform_device *dev)
+{
+       const unsigned short pins[] = {
+               P_A3, P_A4, P_A5, P_A6, P_A7, P_A8, P_A9, P_A10, P_A11, P_A12,
+               P_A13, P_A14, P_A15, P_A16, P_A17, P_A18, P_A19, P_A20, P_A21,
+               P_A22, P_A23, P_A24, P_A25, P_NORCK, 0,
+       };
+
+       peripheral_free_list(pins);
+
+       bfin_write32(SMC_GCTL, 0);
+}
+
 static struct physmap_flash_data ezkit_flash_data = {
        .width      = 2,
        .parts      = ezkit_partitions,
-       .init       = bf609_nor_flash_init,
+       .init       = bf609_nor_flash_init,
+       .exit       = bf609_nor_flash_exit,
        .nr_parts   = ARRAY_SIZE(ezkit_partitions),
+#ifdef CONFIG_ROMKERNEL
+       .probe_type = "map_rom",
+#endif
 };
 
 static struct resource ezkit_flash_resource = {
@@ -739,7 +756,7 @@ static struct bfin6xx_spi_chip spidev_chip_info = {
 };
 #endif
 
-#if defined(CONFIG_SND_BF6XX_I2S) || defined(CONFIG_SND_BF6XX_I2S_MODULE)
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
 static struct platform_device bfin_i2s_pcm = {
        .name = "bfin-i2s-pcm-audio",
        .id = -1,
@@ -825,6 +842,12 @@ static struct adau1761_platform_data adau1761_info = {
 static const unsigned short ppi_req[] = {
        P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
        P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+       P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+       P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
+#if !defined(CONFIG_VIDEO_VS6624) && !defined(CONFIG_VIDEO_VS6624_MODULE)
+       P_PPI0_D16, P_PPI0_D17, P_PPI0_D18, P_PPI0_D19,
+       P_PPI0_D20, P_PPI0_D21, P_PPI0_D22, P_PPI0_D23,
+#endif
        P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
        0,
 };
@@ -855,7 +878,7 @@ static struct bcap_route vs6624_routes[] = {
        },
 };
 
-static const unsigned vs6624_ce_pin = GPIO_PD1;
+static const unsigned vs6624_ce_pin = GPIO_PE4;
 
 static struct bfin_capture_config bfin_capture_data = {
        .card_name = "BF609",
@@ -871,7 +894,128 @@ static struct bfin_capture_config bfin_capture_data = {
        .ppi_info = &ppi_info,
        .ppi_control = (PACK_EN | DLEN_8 | EPPI_CTL_FS1HI_FS2HI
                        | EPPI_CTL_POLC3 | EPPI_CTL_SYNC2 | EPPI_CTL_NON656),
-       .blank_clocks = 8,
+       .blank_pixels = 4,
+};
+#endif
+
+#if defined(CONFIG_VIDEO_ADV7842) \
+       || defined(CONFIG_VIDEO_ADV7842_MODULE)
+#include <media/adv7842.h>
+
+static struct v4l2_input adv7842_inputs[] = {
+       {
+               .index = 0,
+               .name = "Composite",
+               .type = V4L2_INPUT_TYPE_CAMERA,
+               .std = V4L2_STD_ALL,
+               .capabilities = V4L2_IN_CAP_STD,
+       },
+       {
+               .index = 1,
+               .name = "S-Video",
+               .type = V4L2_INPUT_TYPE_CAMERA,
+               .std = V4L2_STD_ALL,
+               .capabilities = V4L2_IN_CAP_STD,
+       },
+       {
+               .index = 2,
+               .name = "Component",
+               .type = V4L2_INPUT_TYPE_CAMERA,
+               .capabilities = V4L2_IN_CAP_CUSTOM_TIMINGS,
+       },
+       {
+               .index = 3,
+               .name = "VGA",
+               .type = V4L2_INPUT_TYPE_CAMERA,
+               .capabilities = V4L2_IN_CAP_CUSTOM_TIMINGS,
+       },
+       {
+               .index = 4,
+               .name = "HDMI",
+               .type = V4L2_INPUT_TYPE_CAMERA,
+               .capabilities = V4L2_IN_CAP_CUSTOM_TIMINGS,
+       },
+};
+
+static struct bcap_route adv7842_routes[] = {
+       {
+               .input = 3,
+               .output = 0,
+               .ppi_control = (PACK_EN | DLEN_8 | EPPI_CTL_FLDSEL
+                               | EPPI_CTL_ACTIVE656),
+       },
+       {
+               .input = 4,
+               .output = 0,
+       },
+       {
+               .input = 2,
+               .output = 0,
+       },
+       {
+               .input = 1,
+               .output = 0,
+       },
+       {
+               .input = 0,
+               .output = 1,
+               .ppi_control = (EPPI_CTL_SPLTWRD | PACK_EN | DLEN_16
+                               | EPPI_CTL_FS1LO_FS2LO | EPPI_CTL_POLC2
+                               | EPPI_CTL_SYNC2 | EPPI_CTL_NON656),
+       },
+};
+
+static struct adv7842_output_format adv7842_opf[] = {
+       {
+               .op_ch_sel = ADV7842_OP_CH_SEL_BRG,
+               .op_format_sel = ADV7842_OP_FORMAT_SEL_SDR_ITU656_8,
+               .op_656_range = 1,
+               .blank_data = 1,
+               .insert_av_codes = 1,
+       },
+       {
+               .op_ch_sel = ADV7842_OP_CH_SEL_RGB,
+               .op_format_sel = ADV7842_OP_FORMAT_SEL_SDR_ITU656_16,
+               .op_656_range = 1,
+               .blank_data = 1,
+       },
+};
+
+static struct adv7842_platform_data adv7842_data = {
+       .opf = adv7842_opf,
+       .num_opf = ARRAY_SIZE(adv7842_opf),
+       .ain_sel = ADV7842_AIN10_11_12_NC_SYNC_4_1,
+       .prim_mode = ADV7842_PRIM_MODE_SDP,
+       .vid_std_select = ADV7842_SDP_VID_STD_CVBS_SD_4x1,
+       .inp_color_space = ADV7842_INP_COLOR_SPACE_AUTO,
+       .i2c_sdp_io = 0x40,
+       .i2c_sdp = 0x41,
+       .i2c_cp = 0x42,
+       .i2c_vdp = 0x43,
+       .i2c_afe = 0x44,
+       .i2c_hdmi = 0x45,
+       .i2c_repeater = 0x46,
+       .i2c_edid = 0x47,
+       .i2c_infoframe = 0x48,
+       .i2c_cec = 0x49,
+       .i2c_avlink = 0x4a,
+       .i2c_ex = 0x26,
+};
+
+static struct bfin_capture_config bfin_capture_data = {
+       .card_name = "BF609",
+       .inputs = adv7842_inputs,
+       .num_inputs = ARRAY_SIZE(adv7842_inputs),
+       .routes = adv7842_routes,
+       .i2c_adapter_id = 0,
+       .board_info = {
+               .type = "adv7842",
+               .addr = 0x20,
+               .platform_data = (void *)&adv7842_data,
+       },
+       .ppi_info = &ppi_info,
+       .ppi_control = (PACK_EN | DLEN_8 | EPPI_CTL_FLDSEL
+                       | EPPI_CTL_ACTIVE656),
 };
 #endif
 
@@ -883,6 +1027,80 @@ static struct platform_device bfin_capture_device = {
 };
 #endif
 
+#if defined(CONFIG_VIDEO_BLACKFIN_DISPLAY) \
+       || defined(CONFIG_VIDEO_BLACKFIN_DISPLAY_MODULE)
+#include <linux/videodev2.h>
+#include <media/blackfin/bfin_display.h>
+#include <media/blackfin/ppi.h>
+
+static const unsigned short ppi_req_disp[] = {
+       P_PPI0_D0, P_PPI0_D1, P_PPI0_D2, P_PPI0_D3,
+       P_PPI0_D4, P_PPI0_D5, P_PPI0_D6, P_PPI0_D7,
+       P_PPI0_D8, P_PPI0_D9, P_PPI0_D10, P_PPI0_D11,
+       P_PPI0_D12, P_PPI0_D13, P_PPI0_D14, P_PPI0_D15,
+       P_PPI0_CLK, P_PPI0_FS1, P_PPI0_FS2,
+       0,
+};
+
+static const struct ppi_info ppi_info = {
+       .type = PPI_TYPE_EPPI3,
+       .dma_ch = CH_EPPI0_CH0,
+       .irq_err = IRQ_EPPI0_STAT,
+       .base = (void __iomem *)EPPI0_STAT,
+       .pin_req = ppi_req_disp,
+};
+
+#if defined(CONFIG_VIDEO_ADV7511) \
+       || defined(CONFIG_VIDEO_ADV7511_MODULE)
+#include <media/adv7511.h>
+
+static struct v4l2_output adv7511_outputs[] = {
+       {
+               .index = 0,
+               .name = "HDMI",
+               .type = V4L2_INPUT_TYPE_CAMERA,
+               .capabilities = V4L2_OUT_CAP_CUSTOM_TIMINGS,
+       },
+};
+
+static struct disp_route adv7511_routes[] = {
+       {
+               .output = 0,
+       },
+};
+
+static struct adv7511_platform_data adv7511_data = {
+       .edid_addr = 0x7e,
+       .i2c_ex = 0x25,
+};
+
+static struct bfin_display_config bfin_display_data = {
+       .card_name = "BF609",
+       .outputs = adv7511_outputs,
+       .num_outputs = ARRAY_SIZE(adv7511_outputs),
+       .routes = adv7511_routes,
+       .i2c_adapter_id = 0,
+       .board_info = {
+               .type = "adv7511",
+               .addr = 0x39,
+               .platform_data = (void *)&adv7511_data,
+       },
+       .ppi_info = &ppi_info,
+       .ppi_control = (EPPI_CTL_SPLTWRD | PACK_EN | DLEN_16
+                       | EPPI_CTL_FS1LO_FS2LO | EPPI_CTL_POLC3
+                       | EPPI_CTL_IFSGEN | EPPI_CTL_SYNC2
+                       | EPPI_CTL_NON656 | EPPI_CTL_DIR),
+};
+#endif
+
+static struct platform_device bfin_display_device = {
+       .name = "bfin_display",
+       .dev = {
+               .platform_data = &bfin_display_data,
+       },
+};
+#endif
+
 #if defined(CONFIG_BFIN_CRC)
 #define BFIN_CRC_NAME "bfin-crc"
 
@@ -947,6 +1165,39 @@ static struct platform_device bfin_crc1_device = {
 };
 #endif
 
+#if defined(CONFIG_CRYPTO_DEV_BFIN_CRC)
+#define BFIN_CRYPTO_CRC_NAME           "bfin-hmac-crc"
+#define BFIN_CRYPTO_CRC_POLY_DATA      0x5c5c5c5c
+
+static struct resource bfin_crypto_crc_resources[] = {
+       {
+               .start = REG_CRC0_CTL,
+               .end = REG_CRC0_REVID+4,
+               .flags = IORESOURCE_MEM,
+       },
+       {
+               .start = IRQ_CRC0_DCNTEXP,
+               .end = IRQ_CRC0_DCNTEXP,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = CH_MEM_STREAM0_SRC_CRC0,
+               .end = CH_MEM_STREAM0_SRC_CRC0,
+               .flags = IORESOURCE_DMA,
+       },
+};
+
+static struct platform_device bfin_crypto_crc_device = {
+       .name = BFIN_CRYPTO_CRC_NAME,
+       .id = 0,
+       .num_resources = ARRAY_SIZE(bfin_crypto_crc_resources),
+       .resource = bfin_crypto_crc_resources,
+       .dev = {
+               .platform_data = (void *)BFIN_CRYPTO_CRC_POLY_DATA,
+       },
+};
+#endif
+
 #if defined(CONFIG_TOUCHSCREEN_AD7877) || defined(CONFIG_TOUCHSCREEN_AD7877_MODULE)
 static const struct ad7877_platform_data bfin_ad7877_ts_info = {
        .model                  = 7877,
@@ -963,6 +1214,28 @@ static const struct ad7877_platform_data bfin_ad7877_ts_info = {
 };
 #endif
 
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+static struct gpio_keys_button bfin_gpio_keys_table[] = {
+       {BTN_0, GPIO_PB10, 1, "gpio-keys: BTN0"},
+       {BTN_1, GPIO_PE1, 1, "gpio-keys: BTN1"},
+};
+
+static struct gpio_keys_platform_data bfin_gpio_keys_data = {
+       .buttons        = bfin_gpio_keys_table,
+       .nbuttons       = ARRAY_SIZE(bfin_gpio_keys_table),
+};
+
+static struct platform_device bfin_device_gpiokeys = {
+       .name      = "gpio-keys",
+       .dev = {
+               .platform_data = &bfin_gpio_keys_data,
+       },
+};
+#endif
+
 static struct spi_board_info bfin_spi_board_info[] __initdata = {
 #if defined(CONFIG_MTD_M25P80) \
        || defined(CONFIG_MTD_M25P80_MODULE)
@@ -981,10 +1254,10 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
        {
                .modalias               = "ad7877",
                .platform_data          = &bfin_ad7877_ts_info,
-               .irq                    = IRQ_PB4,      /* old boards (<=Rev 1.3) use IRQ_PJ11 */
+               .irq                    = IRQ_PD9,
                .max_speed_hz           = 12500000,     /* max spi clock (SCK) speed in HZ */
                .bus_num                = 0,
-               .chip_select            = 2,
+               .chip_select            = 4,
        },
 #endif
 #if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
@@ -1050,7 +1323,7 @@ static struct resource bfin_spi1_resource[] = {
 
 /* SPI controller data */
 static struct bfin6xx_spi_master bf60x_spi_master_info0 = {
-       .num_chipselect = 4,
+       .num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS,
        .pin_req = {P_SPI0_SCK, P_SPI0_MISO, P_SPI0_MOSI, 0},
 };
 
@@ -1065,7 +1338,7 @@ static struct platform_device bf60x_spi_master0 = {
 };
 
 static struct bfin6xx_spi_master bf60x_spi_master_info1 = {
-       .num_chipselect = 4,
+       .num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS,
        .pin_req = {P_SPI1_SCK, P_SPI1_MISO, P_SPI1_MOSI, 0},
 };
 
@@ -1146,6 +1419,11 @@ static struct i2c_board_info __initdata bfin_i2c_board_info0[] = {
                .platform_data = (void *)&adau1761_info
        },
 #endif
+#if defined(CONFIG_SND_SOC_SSM2602) || defined(CONFIG_SND_SOC_SSM2602_MODULE)
+       {
+               I2C_BOARD_INFO("ssm2602", 0x1b),
+       },
+#endif
 };
 
 static struct i2c_board_info __initdata bfin_i2c_board_info1[] = {
@@ -1261,6 +1539,9 @@ static struct platform_device *ezkit_devices[] __initdata = {
        &bfin_crc0_device,
        &bfin_crc1_device,
 #endif
+#if defined(CONFIG_CRYPTO_DEV_BFIN_CRC)
+       &bfin_crypto_crc_device,
+#endif
 
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
        &bfin_device_gpiokeys,
@@ -1269,7 +1550,7 @@ static struct platform_device *ezkit_devices[] __initdata = {
 #if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
        &ezkit_flash_device,
 #endif
-#if defined(CONFIG_SND_BF6XX_I2S) || defined(CONFIG_SND_BF6XX_I2S_MODULE)
+#if defined(CONFIG_SND_BF5XX_I2S) || defined(CONFIG_SND_BF5XX_I2S_MODULE)
        &bfin_i2s_pcm,
 #endif
 #if defined(CONFIG_SND_BF6XX_SOC_I2S) || \
@@ -1284,6 +1565,11 @@ static struct platform_device *ezkit_devices[] __initdata = {
        || defined(CONFIG_VIDEO_BLACKFIN_CAPTURE_MODULE)
        &bfin_capture_device,
 #endif
+#if defined(CONFIG_VIDEO_BLACKFIN_DISPLAY) \
+       || defined(CONFIG_VIDEO_BLACKFIN_DISPLAY_MODULE)
+       &bfin_display_device,
+#endif
+
 };
 
 static int __init ezkit_init(void)
index 7f8f529693aeaae16f156cabcd7b6a920f5cc743..437d56c8228132301fce013f6ebf49e9f9467df6 100644 (file)
@@ -97,9 +97,10 @@ int wait_for_pll_align(void)
        while (i-- && (bfin_read32(CGU0_STAT) & CGU0_STAT_CLKSALGN));
 
        if (bfin_read32(CGU0_STAT) & CGU0_STAT_CLKSALGN) {
-               printk(KERN_DEBUG "fail to align clk\n");
+               printk(KERN_CRIT "fail to align clk\n");
                return -1;
        }
+
        return 0;
 }
 
diff --git a/arch/blackfin/mach-bf609/dpm.S b/arch/blackfin/mach-bf609/dpm.S
new file mode 100644 (file)
index 0000000..54d50c6
--- /dev/null
@@ -0,0 +1,157 @@
+#include <linux/linkage.h>
+#include <asm/blackfin.h>
+#include <asm/dpmc.h>
+
+#include <asm/context.S>
+
+#define PM_STACK   (COREA_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
+
+.section .l1.text
+ENTRY(_enter_hibernate)
+       /* switch stack to L1 scratch, prepare for ddr srfr */
+       P0.H = HI(PM_STACK);
+       P0.L = LO(PM_STACK);
+       SP = P0;
+
+       call _bf609_ddr_sr;
+       call _bfin_hibernate_syscontrol;
+
+       P0.H = HI(DPM0_RESTORE4);
+       P0.L = LO(DPM0_RESTORE4);
+       P1.H = _bf609_pm_data;
+       P1.L = _bf609_pm_data;
+       [P0] = P1;
+
+       P0.H = HI(DPM0_CTL);
+       P0.L = LO(DPM0_CTL);
+       R3.H = HI(0x00000010);
+       R3.L = LO(0x00000010);
+
+       bfin_init_pm_bench_cycles;
+
+       [P0] = R3;
+
+       SSYNC;
+ENDPROC(_enter_hibernate)
+
+/* DPM wake up interrupt won't wake up core on bf60x if its core IMASK
+ * is disabled. This behavior differ from bf5xx serial processor.
+ */
+ENTRY(_dummy_deepsleep)
+       [--sp] = SYSCFG;
+       [--sp] = (R7:0,P5:0);
+       cli r0;
+
+       /* get wake up interrupt ID */
+       P0.l = LO(SEC_SCI_BASE + SEC_CSID);
+       P0.h = HI(SEC_SCI_BASE + SEC_CSID);
+       R0 = [P0];
+
+       /* ACK wake up interrupt in SEC */
+       P1.l = LO(SEC_END);
+       P1.h = HI(SEC_END);
+
+       [P1] = R0;
+       SSYNC;
+
+       /* restore EVT 11 entry */
+       p0.h = hi(EVT11);
+       p0.l = lo(EVT11);
+       p1.h = _evt_evt11;
+       p1.l = _evt_evt11;
+
+       [p0] = p1;
+       SSYNC;
+
+       (R7:0,P5:0) = [sp++];
+       SYSCFG = [sp++];
+       RTI;
+ENDPROC(_dummy_deepsleep)
+
+ENTRY(_enter_deepsleep)
+       LINK 0xC;
+       [--sp] = (R7:0,P5:0);
+
+       /* Change EVT 11 entry to dummy handler for wake up event */
+       p0.h = hi(EVT11);
+       p0.l = lo(EVT11);
+       p1.h = _dummy_deepsleep;
+       p1.l = _dummy_deepsleep;
+
+       [p0] = p1;
+
+       P0.H = HI(PM_STACK);
+       P0.L = LO(PM_STACK);
+
+       EX_SCRATCH_REG = SP;
+       SP = P0;
+
+       SSYNC;
+
+       /* should put ddr to self refresh mode before sleep */
+       call _bf609_ddr_sr;
+
+       /* Set DPM controller to deep sleep mode */
+       P0.H = HI(DPM0_CTL);
+       P0.L = LO(DPM0_CTL);
+       R3.H = HI(0x00000008);
+       R3.L = LO(0x00000008);
+       [P0] = R3;
+       CSYNC;
+
+       /* Enable evt 11 in IMASK before idle, otherwise core doesn't wake up. */
+       r0.l = 0x800;
+       r0.h = 0;
+       sti r0;
+       SSYNC;
+
+       bfin_init_pm_bench_cycles;
+
+       /* Fall into deep sleep in idle*/
+       idle;
+       SSYNC;
+
+       /* Restore PLL after wake up from deep sleep */
+       call _bf609_resume_ccbuf;
+
+       /* turn ddr out of self refresh mode */
+       call _bf609_ddr_sr_exit;
+
+       SP = EX_SCRATCH_REG;
+
+       (R7:0,P5:0) = [SP++];
+       UNLINK;
+       RTS;
+ENDPROC(_enter_deepsleep)
+
+.section .text
+ENTRY(_bf609_hibernate)
+       bfin_cpu_reg_save;
+       bfin_core_mmr_save;
+
+       P0.H = _bf609_pm_data;
+       P0.L = _bf609_pm_data;
+       R1.H = 0xDEAD;
+       R1.L = 0xBEEF;
+       R2.H = .Lpm_resume_here;
+       R2.L = .Lpm_resume_here;
+       [P0++] = R1;
+       [P0++] = R2;
+       [P0++] = SP;
+
+       P1.H = _enter_hibernate;
+       P1.L = _enter_hibernate;
+
+       call (P1);
+.Lpm_resume_here:
+
+       bfin_core_mmr_restore;
+       bfin_cpu_reg_restore;
+
+       [--sp] = RETI;  /* Clear Global Interrupt Disable */
+       SP += 4;
+
+       RTS;
+
+ENDPROC(_bf609_hibernate)
+
diff --git a/arch/blackfin/mach-bf609/hibernate.S b/arch/blackfin/mach-bf609/hibernate.S
deleted file mode 100644 (file)
index d37a532..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-#include <linux/linkage.h>
-#include <asm/blackfin.h>
-#include <asm/dpmc.h>
-
-#define PM_STACK   (COREA_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
-
-.section .l1.text
-ENTRY(_enter_hibernate)
-       /* switch stack to L1 scratch, prepare for ddr srfr */
-       P0.H = HI(PM_STACK);
-       P0.L = LO(PM_STACK);
-       SP = P0;
-
-       call _bf609_ddr_sr;
-       call _bfin_hibernate_syscontrol;
-
-       P0.H = HI(DPM0_RESTORE4);
-       P0.L = LO(DPM0_RESTORE4);
-       P1.H = _bf609_pm_data;
-       P1.L = _bf609_pm_data;
-       [P0] = P1;
-
-       P0.H = HI(DPM0_CTL);
-       P0.L = LO(DPM0_CTL);
-       R3.H = HI(0x00000010);
-       R3.L = LO(0x00000010);
-
-       bfin_init_pm_bench_cycles;
-
-       [P0] = R3;
-
-       SSYNC;
-ENDPROC(_enter_hibernate_mode)
-
-.section .text
-ENTRY(_bf609_hibernate)
-       bfin_cpu_reg_save;
-       bfin_core_mmr_save;
-
-       P0.H = _bf609_pm_data;
-       P0.L = _bf609_pm_data;
-       R1.H = 0xDEAD;
-       R1.L = 0xBEEF;
-       R2.H = .Lpm_resume_here;
-       R2.L = .Lpm_resume_here;
-       [P0++] = R1;
-       [P0++] = R2;
-       [P0++] = SP;
-
-       P1.H = _enter_hibernate;
-       P1.L = _enter_hibernate;
-
-       call (P1);
-.Lpm_resume_here:
-
-       bfin_core_mmr_restore;
-       bfin_cpu_reg_restore;
-
-       [--sp] = RETI;  /* Clear Global Interrupt Disable */
-       SP += 4;
-
-       RTS;
-
-ENDPROC(_bf609_hibernate)
-
index bdd39aefb5655d6f7d545b0bd50f9d81272cbbcd..7a07374308aca4e0aba7b28276bd1114eb9a6f4a 100644 (file)
  * and can be replaced with that version at any time
  * DO NOT EDIT THIS FILE
  *
- * Copyright 2004-2011 Analog Devices Inc.
+ * Copyright 2004-2012 Analog Devices Inc.
  * Licensed under the Clear BSD license.
  */
 
 /* This file should be up to date with:
+ *  - Revision A, 15/06/2012; ADSP-BF609 Blackfin Processor Anomaly List
  */
 
 #if __SILICON_REVISION__ < 0
-# error will not work on BF506 silicon version
+# error will not work on BF609 silicon version
 #endif
 
 #ifndef _MACH_ANOMALY_H_
 #define _MACH_ANOMALY_H_
 
-/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
-#define ANOMALY_05000074 (1)
-/* DMA_RUN Bit Is Not Valid after a Peripheral Receive Channel DMA Stops */
-#define ANOMALY_05000119 (1)
-/* Rx.H Cannot Be Used to Access 16-bit System MMR Registers */
-#define ANOMALY_05000122 (1)
-/* False Hardware Error from an Access in the Shadow of a Conditional Branch */
-#define ANOMALY_05000245 (1)
-/* Incorrect Timer Pulse Width in Single-Shot PWM_OUT Mode with External Clock */
-#define ANOMALY_05000254 (1)
-/* Sensitivity To Noise with Slow Input Edge Rates on External SPORT TX and RX Clocks */
-#define ANOMALY_05000265 (1)
-/* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
-#define ANOMALY_05000310 (1)
-/* PPI Underflow Error Goes Undetected in ITU-R 656 Mode */
-#define ANOMALY_05000366 (1)
-/* Speculative Fetches Can Cause Undesired External FIFO Operations */
-#define ANOMALY_05000416 (1)
-/* Speculative Fetches of Indirect-Pointer Instructions Can Cause False Hardware Errors */
-#define ANOMALY_05000426 (1)
+/* TRU_STAT.ADDRERR and TRU_ERRADDR.ADDR May Not Reflect the Correct Status */
+#define ANOMALY_16000003 (1)
+/* The EPPI Data Enable (DEN) Signal is Not Functional */
+#define ANOMALY_16000004 (1)
+/* Using L1 Instruction Cache with Parity Enabled is Unreliable */
+#define ANOMALY_16000005 (1)
+/* SEQSTAT.SYSNMI Clears Upon Entering the NMI ISR */
+#define ANOMALY_16000006 (1)
+/* DDR2 Memory Reads May Fail Intermittently */
+#define ANOMALY_16000007 (1)
+/* Instruction Memory Stalls Can Cause IFLUSH to Fail */
+#define ANOMALY_16000008 (1)
+/* TestSET Instruction Cannot Be Interrupted */
+#define ANOMALY_16000009 (1)
 /* IFLUSH Instruction at End of Hardware Loop Causes Infinite Stall */
-#define ANOMALY_05000443 (1)
-/* UART IrDA Receiver Fails on Extended Bit Pulses */
-#define ANOMALY_05000447 (1)
+#define ANOMALY_16000010 (1)
 /* False Hardware Error when RETI Points to Invalid Memory */
-#define ANOMALY_05000461 (1)
-/* PLL Latches Incorrect Settings During Reset */
-#define ANOMALY_05000469 (1)
-/* Incorrect Default MSEL Value in PLL_CTL */
-#define ANOMALY_05000472 (1)
-/* Interrupted SPORT Receive Data Register Read Results In Underflow when SLEN > 15 */
-#define ANOMALY_05000473 (1)
-/* TESTSET Instruction Cannot Be Interrupted */
-#define ANOMALY_05000477 (1)
-/* Reads of ITEST_COMMAND and ITEST_DATA Registers Cause Cache Corruption */
-#define ANOMALY_05000481 (1)
-/* IFLUSH sucks at life */
-#define ANOMALY_05000491 (1)
-/* Tempopary anomaly ID for data loss in MMR read operation if interrupted */
-#define ANOMALY_05001001 (__SILICON_REVISION__ < 1)
+#define ANOMALY_16000011 (1)
+/* Speculative Fetches of Indirect-Pointer Instructions Can Cause False Hardware Errors */
+#define ANOMALY_16000012 (1)
+/* False Hardware Errors Caused by Fetches at the Boundary of Reserved Memory */
+#define ANOMALY_16000013 (1)
+/* False Hardware Error from an Access in the Shadow of a Conditional Branch */
+#define ANOMALY_16000014 (1)
+/* Multi-Issue Instruction with dsp32shiftimm in slot1 and P-reg Store in slot2 Not Supported */
+#define ANOMALY_16000015 (1)
+/* Speculative Fetches Can Cause Undesired External FIFO Operations */
+#define ANOMALY_16000017 (1)
+/* RSI Boot Cleanup Routine Does Not Clear Registers */
+#define ANOMALY_16000018 (1)
+/* SPI Master Boot Device Auto-detection Frequency is Set Incorrectly */
+#define ANOMALY_16000019 (1)
+/* rom_SysControl() Fails to Set DDR0_CTL.INIT for Wakeup From Hibernate */
+#define ANOMALY_16000020 (1)
+/* rom_SysControl() Fails to Save and Restore DDR0_PHYCTL3 for Hibernate/Wakeup Sequence */
+#define ANOMALY_16000021 (1)
+/* Boot Code Fails to Enable Parity Fault Detection */
+#define ANOMALY_16000022 (1)
+/* USB DMA interrupt status do not show the DMA channel interrupt in the DMA ISR */
+#define ANOMALY_16000027 (1)
+/* Interrupted Core Reads of MMRs May Cause Data Loss */
+#define ANOMALY_16000030 (1)
 
 /* Anomalies that don't exist on this proc */
-#define ANOMALY_05000099 (0)
-#define ANOMALY_05000120 (0)
-#define ANOMALY_05000125 (0)
-#define ANOMALY_05000149 (0)
 #define ANOMALY_05000158 (0)
-#define ANOMALY_05000171 (0)
-#define ANOMALY_05000179 (0)
-#define ANOMALY_05000182 (0)
-#define ANOMALY_05000183 (0)
 #define ANOMALY_05000189 (0)
 #define ANOMALY_05000198 (0)
-#define ANOMALY_05000202 (0)
-#define ANOMALY_05000215 (0)
-#define ANOMALY_05000219 (0)
 #define ANOMALY_05000220 (0)
-#define ANOMALY_05000227 (0)
 #define ANOMALY_05000230 (0)
 #define ANOMALY_05000231 (0)
-#define ANOMALY_05000233 (0)
-#define ANOMALY_05000234 (0)
-#define ANOMALY_05000242 (0)
 #define ANOMALY_05000244 (0)
-#define ANOMALY_05000248 (0)
-#define ANOMALY_05000250 (0)
-#define ANOMALY_05000257 (0)
-#define ANOMALY_05000261 (0)
 #define ANOMALY_05000263 (0)
-#define ANOMALY_05000266 (0)
 #define ANOMALY_05000273 (0)
 #define ANOMALY_05000274 (0)
 #define ANOMALY_05000278 (0)
 #define ANOMALY_05000281 (0)
-#define ANOMALY_05000283 (0)
-#define ANOMALY_05000285 (0)
 #define ANOMALY_05000287 (0)
-#define ANOMALY_05000301 (0)
-#define ANOMALY_05000305 (0)
-#define ANOMALY_05000307 (0)
 #define ANOMALY_05000311 (0)
 #define ANOMALY_05000312 (0)
-#define ANOMALY_05000315 (0)
 #define ANOMALY_05000323 (0)
-#define ANOMALY_05000353 (1)
-#define ANOMALY_05000357 (0)
-#define ANOMALY_05000362 (1)
 #define ANOMALY_05000363 (0)
-#define ANOMALY_05000364 (0)
-#define ANOMALY_05000371 (0)
 #define ANOMALY_05000380 (0)
-#define ANOMALY_05000386 (0)
-#define ANOMALY_05000389 (0)
-#define ANOMALY_05000400 (0)
-#define ANOMALY_05000402 (0)
-#define ANOMALY_05000412 (0)
-#define ANOMALY_05000432 (0)
-#define ANOMALY_05000440 (0)
 #define ANOMALY_05000448 (0)
-#define ANOMALY_05000456 (0)
 #define ANOMALY_05000450 (0)
-#define ANOMALY_05000465 (0)
-#define ANOMALY_05000467 (0)
-#define ANOMALY_05000474 (0)
-#define ANOMALY_05000475 (0)
+#define ANOMALY_05000456 (0)
 #define ANOMALY_05000480 (0)
-#define ANOMALY_05000485 (0)
+#define ANOMALY_05000481 (1)
+
+/* Reuse BF5xx anomalies IDs for the same anomaly in BF60x */
+#define ANOMALY_05000491 ANOMALY_16000008
+#define ANOMALY_05000477 ANOMALY_16000009
+#define ANOMALY_05000443 ANOMALY_16000010
+#define ANOMALY_05000461 ANOMALY_16000011
+#define ANOMALY_05000426 ANOMALY_16000012
+#define ANOMALY_05000310 ANOMALY_16000013
+#define ANOMALY_05000245 ANOMALY_16000014
+#define ANOMALY_05000074 ANOMALY_16000015
+#define ANOMALY_05000416 ANOMALY_16000017
+
 
 #endif
index 6aac38544cc99acfdf81c35ab8384ba912f23e53..f1a6afae1a714a85255731213323a5684b07057c 100644 (file)
 #define DEVSZ_1G                0x400         /* DMC External Bank Size = 1Gbit */
 #define DEVSZ_2G                0x500         /* DMC External Bank Size = 2Gbit */
 
-
 /* =========================
         L2CTL Registers
    ========================= */
index 127586b1e04ab2859423d6fce239dca50d495b1f..c32c8cc8db2e79e0ae4aa2d1c892c8ec9cff4c3a 100644 (file)
 
 
 #define BFIN_GPIO_PINT 1
+#define NR_PINT_SYS_IRQS        6
+#define NR_PINTS                112
 
 
 #ifndef __ASSEMBLY__
index 0004552433b2e776b3aefdad22fd5d4bb9f6b5e7..23e74cdeeee86c6e7efb30db0ed2cd04741286c7 100644 (file)
 
 #define NR_MACH_IRQS           (IRQ_PG15 + 1)
 
+#define SEC_SCTL_PRIO_OFFSET   8
+
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
 
+extern u8 sec_int_priority[];
+
 /*
  * bfin pint registers layout
  */
index 036d9bdc889e0d8c9e7b4719d3872bc9cfdecfda..3ca0fb965636ed3fad126ae021d9d87a6518ea8a 100644 (file)
 
 #include <linux/suspend.h>
 
-int bfin609_pm_enter(suspend_state_t state);
-int bf609_pm_prepare(void);
-void bf609_pm_finish(void);
+extern int bfin609_pm_enter(suspend_state_t state);
+extern int bf609_pm_prepare(void);
+extern void bf609_pm_finish(void);
 
 void bf609_hibernate(void);
 void bfin_sec_raise_irq(unsigned int sid);
 void coreb_enable(void);
+
+int bf609_nor_flash_init(void);
+void bf609_nor_flash_exit(void);
 #endif
diff --git a/arch/blackfin/mach-bf609/ints-priority.c b/arch/blackfin/mach-bf609/ints-priority.c
new file mode 100644 (file)
index 0000000..f68abb9
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2007-2008 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ *
+ * Set up the interrupt priorities
+ */
+
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <asm/blackfin.h>
+
+u8 sec_int_priority[] = {
+       255,    /* IRQ_SEC_ERR */
+       255,    /* IRQ_CGU_EVT */
+       254,    /* IRQ_WATCH0 */
+       254,    /* IRQ_WATCH1 */
+       253,    /* IRQ_L2CTL0_ECC_ERR */
+       253,    /* IRQ_L2CTL0_ECC_WARN */
+       253,    /* IRQ_C0_DBL_FAULT */
+       253,    /* IRQ_C1_DBL_FAULT */
+       252,    /* IRQ_C0_HW_ERR */
+       252,    /* IRQ_C1_HW_ERR */
+       255,    /* IRQ_C0_NMI_L1_PARITY_ERR */
+       255,    /* IRQ_C1_NMI_L1_PARITY_ERR */
+
+       50,     /* IRQ_TIMER0 */
+       50,     /* IRQ_TIMER1 */
+       50,     /* IRQ_TIMER2 */
+       50,     /* IRQ_TIMER3 */
+       50,     /* IRQ_TIMER4 */
+       50,     /* IRQ_TIMER5 */
+       50,     /* IRQ_TIMER6 */
+       50,     /* IRQ_TIMER7 */
+       50,     /* IRQ_TIMER_STAT */
+       0,      /* IRQ_PINT0 */
+       0,      /* IRQ_PINT1 */
+       0,      /* IRQ_PINT2 */
+       0,      /* IRQ_PINT3 */
+       0,      /* IRQ_PINT4 */
+       0,      /* IRQ_PINT5 */
+       0,      /* IRQ_CNT */
+       50,     /* RQ_PWM0_TRIP */
+       50,     /* IRQ_PWM0_SYNC */
+       50,     /* IRQ_PWM1_TRIP */
+       50,     /* IRQ_PWM1_SYNC */
+       0,      /* IRQ_TWI0 */
+       0,      /* IRQ_TWI1 */
+       10,     /* IRQ_SOFT0 */
+       10,     /* IRQ_SOFT1 */
+       10,     /* IRQ_SOFT2 */
+       10,     /* IRQ_SOFT3 */
+       0,      /* IRQ_ACM_EVT_MISS */
+       0,      /* IRQ_ACM_EVT_COMPLETE */
+       0,      /* IRQ_CAN0_RX */
+       0,      /* IRQ_CAN0_TX */
+       0,      /* IRQ_CAN0_STAT */
+       100,    /* IRQ_SPORT0_TX */
+       100,    /* IRQ_SPORT0_TX_STAT */
+       100,    /* IRQ_SPORT0_RX */
+       100,    /* IRQ_SPORT0_RX_STAT */
+       100,    /* IRQ_SPORT1_TX */
+       100,    /* IRQ_SPORT1_TX_STAT */
+       100,    /* IRQ_SPORT1_RX */
+       100,    /* IRQ_SPORT1_RX_STAT */
+       100,    /* IRQ_SPORT2_TX */
+       100,    /* IRQ_SPORT2_TX_STAT */
+       100,    /* IRQ_SPORT2_RX */
+       100,    /* IRQ_SPORT2_RX_STAT */
+       0,      /* IRQ_SPI0_TX */
+       0,      /* IRQ_SPI0_RX */
+       0,      /* IRQ_SPI0_STAT */
+       0,      /* IRQ_SPI1_TX */
+       0,      /* IRQ_SPI1_RX */
+       0,      /* IRQ_SPI1_STAT */
+       0,      /* IRQ_RSI */
+       0,      /* IRQ_RSI_INT0 */
+       0,      /* IRQ_RSI_INT1 */
+       0,      /* DMA11 Data (SDU) */
+       0,      /* DMA12 Data (Reserved) */
+       0,      /* Reserved */
+       0,      /* Reserved */
+       30,     /* IRQ_EMAC0_STAT */
+       0,      /* EMAC0 Power (Reserved) */
+       30,     /* IRQ_EMAC1_STAT */
+       0,      /* EMAC1 Power (Reserved) */
+       0,      /* IRQ_LP0 */
+       0,      /* IRQ_LP0_STAT */
+       0,      /* IRQ_LP1 */
+       0,      /* IRQ_LP1_STAT */
+       0,      /* IRQ_LP2 */
+       0,      /* IRQ_LP2_STAT */
+       0,      /* IRQ_LP3 */
+       0,      /* IRQ_LP3_STAT */
+       0,      /* IRQ_UART0_TX */
+       0,      /* IRQ_UART0_RX */
+       0,      /* IRQ_UART0_STAT */
+       0,      /* IRQ_UART1_TX */
+       0,      /* IRQ_UART1_RX */
+       0,      /* IRQ_UART1_STAT */
+       0,      /* IRQ_MDMA0_SRC_CRC0 */
+       0,      /* IRQ_MDMA0_DEST_CRC0 */
+       0,      /* IRQ_CRC0_DCNTEXP */
+       0,      /* IRQ_CRC0_ERR */
+       0,      /* IRQ_MDMA1_SRC_CRC1 */
+       0,      /* IRQ_MDMA1_DEST_CRC1 */
+       0,      /* IRQ_CRC1_DCNTEXP */
+       0,      /* IRQ_CRC1_ERR */
+       0,      /* IRQ_MDMA2_SRC */
+       0,      /* IRQ_MDMA2_DEST */
+       0,      /* IRQ_MDMA3_SRC */
+       0,      /* IRQ_MDMA3_DEST */
+       120,    /* IRQ_EPPI0_CH0 */
+       120,    /* IRQ_EPPI0_CH1 */
+       120,    /* IRQ_EPPI0_STAT */
+       120,    /* IRQ_EPPI2_CH0 */
+       120,    /* IRQ_EPPI2_CH1 */
+       120,    /* IRQ_EPPI2_STAT */
+       120,    /* IRQ_EPPI1_CH0 */
+       120,    /* IRQ_EPPI1_CH1 */
+       120,    /* IRQ_EPPI1_STAT */
+       120,    /* IRQ_PIXC_CH0 */
+       120,    /* IRQ_PIXC_CH1 */
+       120,    /* IRQ_PIXC_CH2 */
+       120,    /* IRQ_PIXC_STAT */
+       120,    /* IRQ_PVP_CPDOB */
+       120,    /* IRQ_PVP_CPDOC */
+       120,    /* IRQ_PVP_CPSTAT */
+       120,    /* IRQ_PVP_CPCI */
+       120,    /* IRQ_PVP_STAT0 */
+       120,    /* IRQ_PVP_MPDO */
+       120,    /* IRQ_PVP_MPDI */
+       120,    /* IRQ_PVP_MPSTAT */
+       120,    /* IRQ_PVP_MPCI */
+       120,    /* IRQ_PVP_CPDOA */
+       120,    /* IRQ_PVP_STAT1 */
+       0,      /* IRQ_USB_STAT */
+       0,      /* IRQ_USB_DMA */
+       0,      /* IRQ_TRU_INT0 */
+       0,      /* IRQ_TRU_INT1 */
+       0,      /* IRQ_TRU_INT2 */
+       0,      /* IRQ_TRU_INT3 */
+       0,      /* IRQ_DMAC0_ERROR */
+       0,      /* IRQ_CGU0_ERROR */
+       0,      /* Reserved */
+       0,      /* IRQ_DPM */
+       0,      /* Reserved */
+       0,      /* IRQ_SWU0 */
+       0,      /* IRQ_SWU1 */
+       0,      /* IRQ_SWU2 */
+       0,      /* IRQ_SWU3 */
+       0,      /* IRQ_SWU4 */
+       0,      /* IRQ_SWU4 */
+       0,      /* IRQ_SWU6 */
+};
+
index b76966eb16ad9e387925243a477aee48130f83dd..dacafc163f76a7230d924bfbdad696639ab6a822 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/gpio.h>
 #include <linux/irq.h>
-
 #include <linux/delay.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/dpmc.h>
 #include <asm/pm.h>
 #include <mach/pm.h>
 #include <asm/blackfin.h>
+#include <asm/mem_init.h>
 
 /***********************************************************/
 /*                                                         */
@@ -132,60 +133,30 @@ void bfin_cpu_suspend(void)
 }
 
 __attribute__((l1_text))
-void bfin_deepsleep(unsigned long mask)
+void bf609_ddr_sr(void)
 {
-       uint32_t dpm0_ctl;
-
-       bfin_write32(DPM0_WAKE_EN, 0x10);
-       bfin_write32(DPM0_WAKE_POL, 0x10);
-       dpm0_ctl = 0x00000008;
-       bfin_write32(DPM0_CTL, dpm0_ctl);
-       SSYNC();
-       __asm__ __volatile__( \
-                       ".align 8;" \
-                       "idle;" \
-                       : : \
-                       );
-#ifdef CONFIG_BFIN_PM_WAKEUP_TIME_BENCH
-       __asm__ __volatile__(
-               "R0 = 0;"
-               "CYCLES = R0;"
-               "CYCLES2 = R0;"
-               "R0 = SYSCFG;"
-               "BITSET(R0, 1);"
-               "SYSCFG = R0;"
-               : : : "R0"
-       );
-#endif
-
+       dmc_enter_self_refresh();
 }
 
 __attribute__((l1_text))
-void bf609_ddr_sr(void)
+void bf609_ddr_sr_exit(void)
 {
-       uint32_t reg;
-
-       reg = bfin_read_DMC0_CTL();
-       reg |= 0x8;
-       bfin_write_DMC0_CTL(reg);
+       dmc_exit_self_refresh();
 
-       while (!(bfin_read_DMC0_STAT() & 0x8))
+       /* After wake up from deep sleep and exit DDR from self refress mode,
+        * should wait till CGU PLL is locked.
+        */
+       while (bfin_read32(CGU0_STAT) & CLKSALGN)
                continue;
 }
 
 __attribute__((l1_text))
-void bf609_ddr_sr_exit(void)
+void bf609_resume_ccbuf(void)
 {
-       uint32_t reg;
-       while (!(bfin_read_DMC0_STAT() & 0x1))
-               continue;
+       bfin_write32(DPM0_CCBF_EN, 3);
+       bfin_write32(DPM0_CTL, 2);
 
-       reg = bfin_read_DMC0_CTL();
-       reg &= ~0x8;
-       bfin_write_DMC0_CTL(reg);
-
-       while ((bfin_read_DMC0_STAT() & 0x8))
-               continue;
+       while ((bfin_read32(DPM0_STAT) & 0xf) != 1);
 }
 
 __attribute__((l1_text))
@@ -203,20 +174,25 @@ void bfin_hibernate_syscontrol(void)
        bfin_write32(DPM0_RESTORE5, bfin_read32(DPM0_RESTORE5) | 4);
 }
 
-#ifndef CONFIG_BF60x
-# define SIC_SYSIRQ(irq)       (irq - (IRQ_CORETMR + 1))
-#else
-# define SIC_SYSIRQ(irq)       ((irq) - IVG15)
-#endif
-void bfin_hibernate(unsigned long mask)
+#define IRQ_SID(irq)   ((irq) - IVG15)
+asmlinkage void enter_deepsleep(void);
+
+__attribute__((l1_text))
+void bfin_deepsleep(unsigned long mask, unsigned long pol_mask)
 {
-       bfin_write32(DPM0_WAKE_EN, 0x10);
-       bfin_write32(DPM0_WAKE_POL, 0x10);
+       bfin_write32(DPM0_WAKE_EN, mask);
+       bfin_write32(DPM0_WAKE_POL, pol_mask);
+       SSYNC();
+       enter_deepsleep();
+}
+
+void bfin_hibernate(unsigned long mask, unsigned long pol_mask)
+{
+       bfin_write32(DPM0_WAKE_EN, mask);
+       bfin_write32(DPM0_WAKE_POL, pol_mask);
        bfin_write32(DPM0_PGCNTR, 0x0000FFFF);
        bfin_write32(DPM0_HIB_DIS, 0xFFFF);
 
-       printk(KERN_DEBUG "hibernate: restore %x pgcnt %x\n", bfin_read32(DPM0_RESTORE0), bfin_read32(DPM0_PGCNTR));
-
        bf609_hibernate();
 }
 
@@ -290,10 +266,11 @@ void bf609_cpu_pm_enter(suspend_state_t state)
                printk(KERN_DEBUG "Unable to get irq wake\n");
 
        if (state == PM_SUSPEND_STANDBY)
-               bfin_deepsleep(wakeup);
+               bfin_deepsleep(wakeup, wakeup_pol);
        else {
-               bfin_hibernate(wakeup);
+               bfin_hibernate(wakeup, wakeup_pol);
        }
+
 }
 
 int bf609_cpu_pm_prepare(void)
@@ -312,20 +289,36 @@ static struct bfin_cpu_pm_fns bf609_cpu_pm = {
        .finish         = bf609_cpu_pm_finish,
 };
 
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+static int smc_pm_syscore_suspend(void)
+{
+       bf609_nor_flash_exit();
+       return 0;
+}
+
+static void smc_pm_syscore_resume(void)
+{
+       bf609_nor_flash_init();
+}
+
+static struct syscore_ops smc_pm_syscore_ops = {
+       .suspend        = smc_pm_syscore_suspend,
+       .resume         = smc_pm_syscore_resume,
+};
+#endif
+
 static irqreturn_t test_isr(int irq, void *dev_id)
 {
        printk(KERN_DEBUG "gpio irq %d\n", irq);
+       if (irq == 231)
+               bfin_sec_raise_irq(IRQ_SID(IRQ_SOFT1));
        return IRQ_HANDLED;
 }
 
 static irqreturn_t dpm0_isr(int irq, void *dev_id)
 {
-       uint32_t wake_stat;
-
-       wake_stat = bfin_read32(DPM0_WAKE_STAT);
-       printk(KERN_DEBUG "enter %s wake stat %08x\n", __func__, wake_stat);
-
-       bfin_write32(DPM0_WAKE_STAT, wake_stat);
+       bfin_write32(DPM0_WAKE_STAT, bfin_read32(DPM0_WAKE_STAT));
+       bfin_write32(CGU0_STAT, bfin_read32(CGU0_STAT));
        return IRQ_HANDLED;
 }
 
@@ -334,7 +327,11 @@ static int __init bf609_init_pm(void)
        int irq;
        int error;
 
-#if CONFIG_PM_BFIN_WAKE_PE12
+#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
+       register_syscore_ops(&smc_pm_syscore_ops);
+#endif
+
+#ifdef CONFIG_PM_BFIN_WAKE_PE12
        irq = gpio_to_irq(GPIO_PE12);
        if (irq < 0) {
                error = irq;
@@ -342,16 +339,19 @@ static int __init bf609_init_pm(void)
                                GPIO_PE12, error);
        }
 
-       error = request_irq(irq, test_isr, IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND, "gpiope12", NULL);
+       error = request_irq(irq, test_isr, IRQF_TRIGGER_RISING | IRQF_NO_SUSPEND
+                               | IRQF_FORCE_RESUME, "gpiope12", NULL);
        if(error < 0)
                printk(KERN_DEBUG "Unable to get irq\n");
 #endif
 
-       error = request_irq(IRQ_CGU_EVT, dpm0_isr, IRQF_NO_SUSPEND, "cgu0 event", NULL);
+       error = request_irq(IRQ_CGU_EVT, dpm0_isr, IRQF_NO_SUSPEND |
+                               IRQF_FORCE_RESUME, "cgu0 event", NULL);
        if(error < 0)
                printk(KERN_DEBUG "Unable to get irq\n");
 
-       error = request_irq(IRQ_DPM, dpm0_isr, IRQF_NO_SUSPEND, "dpm0 event", NULL);
+       error = request_irq(IRQ_DPM, dpm0_isr, IRQF_NO_SUSPEND |
+                               IRQF_FORCE_RESUME, "dpm0 event", NULL);
        if (error < 0)
                printk(KERN_DEBUG "Unable to get irq\n");
 
index 7ad2407d157102cc035cccaccaedb9c34f6feb08..2308ce52f849b582ed8046bdfca9476bdad49e0e 100644 (file)
 #include <asm/dpmc.h>
 
 #ifdef CONFIG_BF60x
-#define CSEL_P                 0
-#define S0SEL_P                        5
-#define SYSSEL_P               8
-#define S1SEL_P                        13
-#define DSEL_P                 16
-#define OSEL_P                 22
-#define ALGN_P                 29
-#define UPDT_P                 30
-#define LOCK_P                 31
 
 #define CGU_CTL_VAL ((CONFIG_VCO_MULT << 8) | CLKIN_HALF)
 #define CGU_DIV_VAL \
-       ((CONFIG_CCLK_DIV   << CSEL_P)   | \
-       (CONFIG_SCLK_DIV << SYSSEL_P)   | \
-       (CONFIG_SCLK0_DIV  << S0SEL_P)  | \
-       (CONFIG_SCLK1_DIV  << S1SEL_P)  | \
-       (CONFIG_DCLK_DIV   << DSEL_P))
+       ((CONFIG_CCLK_DIV   << CSEL_OFFSET)   | \
+       (CONFIG_SCLK_DIV << SYSSEL_OFFSET)   | \
+       (CONFIG_SCLK0_DIV  << S0SEL_OFFSET)  | \
+       (CONFIG_SCLK1_DIV  << S1SEL_OFFSET)  | \
+       (CONFIG_DCLK_DIV   << DSEL_OFFSET))
 
 #define CONFIG_BFIN_DCLK (((CONFIG_CLKIN_HZ * CONFIG_VCO_MULT) / CONFIG_DCLK_DIV) / 1000000)
 #if ((CONFIG_BFIN_DCLK != 125) && \
        (CONFIG_BFIN_DCLK != 225) && (CONFIG_BFIN_DCLK != 250))
 #error "DCLK must be in (125, 133, 150, 166, 200, 225, 250)MHz"
 #endif
-struct ddr_config {
-       u32 ddr_clk;
-       u32 dmc_ddrctl;
-       u32 dmc_ddrcfg;
-       u32 dmc_ddrtr0;
-       u32 dmc_ddrtr1;
-       u32 dmc_ddrtr2;
-       u32 dmc_ddrmr;
-       u32 dmc_ddrmr1;
-};
 
-struct ddr_config ddr_config_table[] __attribute__((section(".data_l1"))) = {
-       [0] = {
-               .ddr_clk    = 125,
-               .dmc_ddrctl = 0x00000904,
-               .dmc_ddrcfg = 0x00000422,
-               .dmc_ddrtr0 = 0x20705212,
-               .dmc_ddrtr1 = 0x201003CF,
-               .dmc_ddrtr2 = 0x00320107,
-               .dmc_ddrmr  = 0x00000422,
-               .dmc_ddrmr1 = 0x4,
-       },
-       [1] = {
-               .ddr_clk    = 133,
-               .dmc_ddrctl = 0x00000904,
-               .dmc_ddrcfg = 0x00000422,
-               .dmc_ddrtr0 = 0x20806313,
-               .dmc_ddrtr1 = 0x2013040D,
-               .dmc_ddrtr2 = 0x00320108,
-               .dmc_ddrmr  = 0x00000632,
-               .dmc_ddrmr1 = 0x4,
-       },
-       [2] = {
-               .ddr_clk    = 150,
-               .dmc_ddrctl = 0x00000904,
-               .dmc_ddrcfg = 0x00000422,
-               .dmc_ddrtr0 = 0x20A07323,
-               .dmc_ddrtr1 = 0x20160492,
-               .dmc_ddrtr2 = 0x00320209,
-               .dmc_ddrmr  = 0x00000632,
-               .dmc_ddrmr1 = 0x4,
-       },
-       [3] = {
-               .ddr_clk    = 166,
-               .dmc_ddrctl = 0x00000904,
-               .dmc_ddrcfg = 0x00000422,
-               .dmc_ddrtr0 = 0x20A07323,
-               .dmc_ddrtr1 = 0x2016050E,
-               .dmc_ddrtr2 = 0x00320209,
-               .dmc_ddrmr  = 0x00000632,
-               .dmc_ddrmr1 = 0x4,
-       },
-       [4] = {
-               .ddr_clk    = 200,
-               .dmc_ddrctl = 0x00000904,
-               .dmc_ddrcfg = 0x00000422,
-               .dmc_ddrtr0 = 0x20a07323,
-               .dmc_ddrtr1 = 0x2016050f,
-               .dmc_ddrtr2 = 0x00320509,
-               .dmc_ddrmr  = 0x00000632,
-               .dmc_ddrmr1 = 0x4,
-       },
-       [5] = {
-               .ddr_clk    = 225,
-               .dmc_ddrctl = 0x00000904,
-               .dmc_ddrcfg = 0x00000422,
-               .dmc_ddrtr0 = 0x20E0A424,
-               .dmc_ddrtr1 = 0x302006DB,
-               .dmc_ddrtr2 = 0x0032020D,
-               .dmc_ddrmr  = 0x00000842,
-               .dmc_ddrmr1 = 0x4,
-       },
-       [6] = {
-               .ddr_clk    = 250,
-               .dmc_ddrctl = 0x00000904,
-               .dmc_ddrcfg = 0x00000422,
-               .dmc_ddrtr0 = 0x20E0A424,
-               .dmc_ddrtr1 = 0x3020079E,
-               .dmc_ddrtr2 = 0x0032020D,
-               .dmc_ddrmr  = 0x00000842,
-               .dmc_ddrmr1 = 0x4,
-       },
-};
 #else
 #define SDGCTL_WIDTH (1 << 31) /* SDRAM external data path width */
 #define PLL_CTL_VAL \
@@ -144,43 +53,9 @@ void init_clocks(void)
         * in the middle of reprogramming things, and that'll screw us up.
         * For example, any automatic DMAs left by U-Boot for splash screens.
         */
-
 #ifdef CONFIG_BF60x
-       int i, dlldatacycle, dll_ctl;
-       bfin_write32(CGU0_DIV, CGU_DIV_VAL);
-       bfin_write32(CGU0_CTL, CGU_CTL_VAL);
-       while ((bfin_read32(CGU0_STAT) & 0x8) || !(bfin_read32(CGU0_STAT) & 0x4))
-               continue;
-
-       bfin_write32(CGU0_DIV, CGU_DIV_VAL | (1 << UPDT_P));
-       while (bfin_read32(CGU0_STAT) & (1 << 3))
-               continue;
-
-       for (i = 0; i < 7; i++) {
-               if (ddr_config_table[i].ddr_clk == CONFIG_BFIN_DCLK) {
-                       bfin_write_DDR0_CFG(ddr_config_table[i].dmc_ddrcfg);
-                       bfin_write_DDR0_TR0(ddr_config_table[i].dmc_ddrtr0);
-                       bfin_write_DDR0_TR1(ddr_config_table[i].dmc_ddrtr1);
-                       bfin_write_DDR0_TR2(ddr_config_table[i].dmc_ddrtr2);
-                       bfin_write_DDR0_MR(ddr_config_table[i].dmc_ddrmr);
-                       bfin_write_DDR0_EMR1(ddr_config_table[i].dmc_ddrmr1);
-                       bfin_write_DDR0_CTL(ddr_config_table[i].dmc_ddrctl);
-                       break;
-               }
-       }
-
-       do_sync();
-       while (!(bfin_read_DDR0_STAT() & 0x4))
-               continue;
-
-       dlldatacycle = (bfin_read_DDR0_STAT() & 0x00f00000) >> 20;
-       dll_ctl = bfin_read_DDR0_DLLCTL();
-       dll_ctl &= 0x0ff;
-       bfin_write_DDR0_DLLCTL(dll_ctl | (dlldatacycle << 8));
-
-       do_sync();
-       while (!(bfin_read_DDR0_STAT() & 0x2000))
-               continue;
+       init_cgu(CGU_DIV_VAL, CGU_CTL_VAL);
+       init_dmc(CONFIG_BFIN_DCLK);
 #else
        size_t i;
        for (i = 0; i < MAX_DMA_CHANNELS; ++i) {
index 6e87dc13f6bfa1dde4dbfa72e4ce506b711cad62..c854a27cbeab2087d88b5711433b1247a94013e1 100644 (file)
@@ -64,7 +64,8 @@ static void __init bfin_init_tables(unsigned long cclk, unsigned long sclk)
 
        /* Anomaly 273 seems to still exist on non-BF54x w/dcache turned on */
 #if ANOMALY_05000273 || ANOMALY_05000274 || \
-       (!defined(CONFIG_BF54x) && defined(CONFIG_BFIN_EXTMEM_DCACHEABLE))
+       (!(defined(CONFIG_BF54x) || defined(CONFIG_BF60x)) \
+       && defined(CONFIG_BFIN_EXTMEM_DCACHEABLE))
        min_cclk = sclk * 2;
 #else
        min_cclk = sclk;
@@ -173,7 +174,7 @@ static int bfin_target(struct cpufreq_policy *poli,
 #else
                        ret = cpu_set_cclk(cpu, freqs.new * 1000);
                        if (ret != 0) {
-                               pr_debug("cpufreq set freq failed %d\n", ret);
+                               WARN_ONCE(ret, "cpufreq set freq failed %d\n", ret);
                                break;
                        }
 #endif
index 04c2fbe41a7ff3e7193532b1e809b8dbcb7474ee..1c3d2c5bb0bb873fcec8f65eb48379279e479c65 100644 (file)
 
 #include <asm/context.S>
 
-#if defined(CONFIG_BFIN_SCRATCH_REG_RETN)
-# define EX_SCRATCH_REG RETN
-#elif defined(CONFIG_BFIN_SCRATCH_REG_RETE)
-# define EX_SCRATCH_REG RETE
-#else
-# define EX_SCRATCH_REG CYCLES
-#endif
 
 #ifdef CONFIG_EXCPT_IRQ_SYSC_L1
 .section .l1.text
index 2729cba715b0326c7411c3446248c8c0b5837668..7ca09ec2ca539cf01ec9e3f81240b5fa9c0c94b8 100644 (file)
@@ -26,8 +26,9 @@
 #include <asm/gpio.h>
 #include <asm/irq_handler.h>
 #include <asm/dpmc.h>
+#include <asm/traps.h>
 
-#ifndef CONFIG_BF60x
+#ifndef SEC_GCTL
 # define SIC_SYSIRQ(irq)       (irq - (IRQ_CORETMR + 1))
 #else
 # define SIC_SYSIRQ(irq)       ((irq) - IVG15)
@@ -56,7 +57,7 @@ unsigned long bfin_sic_iwr[3];        /* Up to 3 SIC_IWRx registers */
 unsigned vr_wakeup;
 #endif
 
-#ifndef CONFIG_BF60x
+#ifndef SEC_GCTL
 static struct ivgx {
        /* irq number for request_irq, available in mach-bf5xx/irq.h */
        unsigned int irqno;
@@ -143,7 +144,7 @@ static void bfin_core_unmask_irq(struct irq_data *d)
 void bfin_internal_mask_irq(unsigned int irq)
 {
        unsigned long flags = hard_local_irq_save();
-#ifndef CONFIG_BF60x
+#ifndef SEC_GCTL
 #ifdef SIC_IMASK0
        unsigned mask_bank = SIC_SYSIRQ(irq) / 32;
        unsigned mask_bit = SIC_SYSIRQ(irq) % 32;
@@ -175,7 +176,7 @@ void bfin_internal_unmask_irq(unsigned int irq)
 {
        unsigned long flags = hard_local_irq_save();
 
-#ifndef CONFIG_BF60x
+#ifndef SEC_GCTL
 #ifdef SIC_IMASK0
        unsigned mask_bank = SIC_SYSIRQ(irq) / 32;
        unsigned mask_bit = SIC_SYSIRQ(irq) % 32;
@@ -199,7 +200,7 @@ void bfin_internal_unmask_irq(unsigned int irq)
        hard_local_irq_restore(flags);
 }
 
-#ifdef CONFIG_BF60x
+#ifdef SEC_GCTL
 static void bfin_sec_preflow_handler(struct irq_data *d)
 {
        unsigned long flags = hard_local_irq_save();
@@ -310,7 +311,24 @@ static void bfin_sec_disable(struct irq_data *d)
        hard_local_irq_restore(flags);
 }
 
-static void bfin_sec_raise_irq(unsigned int sid)
+static void bfin_sec_set_priority(unsigned int sec_int_levels, u8 *sec_int_priority)
+{
+       unsigned long flags = hard_local_irq_save();
+       uint32_t reg_sctl;
+       int i;
+
+       bfin_write_SEC_SCI(0, SEC_CPLVL, sec_int_levels);
+
+       for (i = 0; i < SYS_IRQS - BFIN_IRQ(0); i++) {
+               reg_sctl = bfin_read_SEC_SCTL(i) & ~SEC_SCTL_PRIO;
+               reg_sctl |= sec_int_priority[i] << SEC_SCTL_PRIO_OFFSET;
+               bfin_write_SEC_SCTL(i, reg_sctl);
+       }
+
+       hard_local_irq_restore(flags);
+}
+
+void bfin_sec_raise_irq(unsigned int sid)
 {
        unsigned long flags = hard_local_irq_save();
 
@@ -396,24 +414,34 @@ void handle_sec_fault(unsigned int irq, struct irq_desc *desc)
        raw_spin_unlock(&desc->lock);
 }
 
-static int sec_suspend(void)
+void handle_core_fault(unsigned int irq, struct irq_desc *desc)
 {
-       return 0;
-}
+       struct pt_regs *fp = get_irq_regs();
 
-static void sec_resume(void)
-{
-       bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_RESET);
-       udelay(100);
-       bfin_write_SEC_GCTL(SEC_GCTL_EN);
-       bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN);
-}
+       raw_spin_lock(&desc->lock);
 
-static struct syscore_ops sec_pm_syscore_ops = {
-       .suspend = sec_suspend,
-       .resume = sec_resume,
-};
+       switch (irq) {
+       case IRQ_C0_DBL_FAULT:
+               double_fault_c(fp);
+               break;
+       case IRQ_C0_HW_ERR:
+               dump_bfin_process(fp);
+               dump_bfin_mem(fp);
+               show_regs(fp);
+               printk(KERN_NOTICE "Kernel Stack\n");
+               show_stack(current, NULL);
+               print_modules();
+               panic("Kernel core hardware error");
+               break;
+       case IRQ_C0_NMI_L1_PARITY_ERR:
+               panic("NMI occurs unexpectedly");
+               break;
+       default:
+               panic("Core 1 fault occurs unexpectedly");
+       }
 
+       raw_spin_unlock(&desc->lock);
+}
 #endif
 
 #ifdef CONFIG_SMP
@@ -437,7 +465,7 @@ static void bfin_internal_unmask_irq_chip(struct irq_data *d)
 }
 #endif
 
-#if defined(CONFIG_PM) && !defined(CONFIG_BF60x)
+#if defined(CONFIG_PM) && !defined(SEC_GCTL)
 int bfin_internal_set_wake(unsigned int irq, unsigned int state)
 {
        u32 bank, bit, wakeup = 0;
@@ -496,7 +524,10 @@ static int bfin_internal_set_wake_chip(struct irq_data *d, unsigned int state)
        return bfin_internal_set_wake(d->irq, state);
 }
 #else
-# define bfin_internal_set_wake(irq, state)
+inline int bfin_internal_set_wake(unsigned int irq, unsigned int state)
+{
+       return 0;
+}
 # define bfin_internal_set_wake_chip NULL
 #endif
 
@@ -518,7 +549,7 @@ static struct irq_chip bfin_internal_irqchip = {
        .irq_set_wake = bfin_internal_set_wake_chip,
 };
 
-#ifdef CONFIG_BF60x
+#ifdef SEC_GCTL
 static struct irq_chip bfin_sec_irqchip = {
        .name = "SEC",
        .irq_mask_ack = bfin_sec_mask_ack_irq,
@@ -868,14 +899,6 @@ void bfin_demux_gpio_irq(unsigned int inta_irq,
 
 #else
 
-# ifndef CONFIG_BF60x
-#define NR_PINT_SYS_IRQS       4
-#define NR_PINTS               160
-# else
-#define NR_PINT_SYS_IRQS       6
-#define NR_PINTS               112
-#endif
-
 #define NR_PINT_BITS           32
 #define IRQ_NOT_AVAIL          0xFF
 
@@ -897,29 +920,21 @@ static struct bfin_pint_regs * const pint[NR_PINT_SYS_IRQS] = {
 #endif
 };
 
-#ifndef CONFIG_BF60x
 inline unsigned int get_irq_base(u32 bank, u8 bmap)
 {
        unsigned int irq_base;
 
+#ifndef CONFIG_BF60x
        if (bank < 2) {         /*PA-PB */
                irq_base = IRQ_PA0 + bmap * 16;
        } else {                /*PC-PJ */
                irq_base = IRQ_PC0 + bmap * 16;
        }
-
-       return irq_base;
-}
 #else
-inline unsigned int get_irq_base(u32 bank, u8 bmap)
-{
-       unsigned int irq_base;
-
        irq_base = IRQ_PA0 + bank * 16 + bmap * 16;
-
+#endif
        return irq_base;
 }
-#endif
 
        /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
 void init_pint_lut(void)
@@ -1089,6 +1104,9 @@ static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)
 }
 
 #ifdef CONFIG_PM
+static struct bfin_pm_pint_save save_pint_reg[NR_PINT_SYS_IRQS];
+static u32 save_pint_sec_ctl[NR_PINT_SYS_IRQS];
+
 static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
 {
        u32 pint_irq;
@@ -1124,6 +1142,59 @@ static int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
 
        return 0;
 }
+
+void bfin_pint_suspend(void)
+{
+       u32 bank;
+
+       for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) {
+               save_pint_reg[bank].mask_set = pint[bank]->mask_set;
+               save_pint_reg[bank].assign = pint[bank]->assign;
+               save_pint_reg[bank].edge_set = pint[bank]->edge_set;
+               save_pint_reg[bank].invert_set = pint[bank]->invert_set;
+       }
+}
+
+void bfin_pint_resume(void)
+{
+       u32 bank;
+
+       for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++) {
+               pint[bank]->mask_set = save_pint_reg[bank].mask_set;
+               pint[bank]->assign = save_pint_reg[bank].assign;
+               pint[bank]->edge_set = save_pint_reg[bank].edge_set;
+               pint[bank]->invert_set = save_pint_reg[bank].invert_set;
+       }
+}
+
+#ifdef SEC_GCTL
+static int sec_suspend(void)
+{
+       u32 bank;
+
+       for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++)
+               save_pint_sec_ctl[bank] = bfin_read_SEC_SCTL(bank + SIC_SYSIRQ(IRQ_PINT0));
+       return 0;
+}
+
+static void sec_resume(void)
+{
+       u32 bank;
+
+       bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_RESET);
+       udelay(100);
+       bfin_write_SEC_GCTL(SEC_GCTL_EN);
+       bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN);
+
+       for (bank = 0; bank < NR_PINT_SYS_IRQS; bank++)
+               bfin_write_SEC_SCTL(bank + SIC_SYSIRQ(IRQ_PINT0), save_pint_sec_ctl[bank]);
+}
+
+static struct syscore_ops sec_pm_syscore_ops = {
+       .suspend = sec_suspend,
+       .resume = sec_resume,
+};
+#endif
 #else
 # define bfin_gpio_set_wake NULL
 #endif
@@ -1230,6 +1301,7 @@ void __cpuinit init_exception_vectors(void)
        CSYNC();
 }
 
+#ifndef SEC_GCTL
 /*
  * This function should be called during kernel startup to initialize
  * the BFin IRQ handling routines.
@@ -1240,7 +1312,6 @@ int __init init_arch_irq(void)
        int irq;
        unsigned long ilat = 0;
 
-#ifndef CONFIG_BF60x
        /*  Disable all the peripheral intrs  - page 4-29 HW Ref manual */
 #ifdef SIC_IMASK0
        bfin_write_SIC_IMASK0(SIC_UNMASK_ALL);
@@ -1255,9 +1326,6 @@ int __init init_arch_irq(void)
 #else
        bfin_write_SIC_IMASK(SIC_UNMASK_ALL);
 #endif
-#else /* CONFIG_BF60x */
-       bfin_write_SEC_GCTL(SEC_GCTL_RESET);
-#endif
 
        local_irq_disable();
 
@@ -1267,10 +1335,6 @@ int __init init_arch_irq(void)
        pint[1]->assign = CONFIG_PINT1_ASSIGN;
        pint[2]->assign = CONFIG_PINT2_ASSIGN;
        pint[3]->assign = CONFIG_PINT3_ASSIGN;
-# ifdef CONFIG_BF60x
-       pint[4]->assign = CONFIG_PINT4_ASSIGN;
-       pint[5]->assign = CONFIG_PINT5_ASSIGN;
-# endif
 # endif
        /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
        init_pint_lut();
@@ -1283,7 +1347,6 @@ int __init init_arch_irq(void)
                        irq_set_chip(irq, &bfin_internal_irqchip);
 
                switch (irq) {
-#ifndef CONFIG_BF60x
 #if BFIN_GPIO_PINT
                case IRQ_PINT0:
                case IRQ_PINT1:
@@ -1319,7 +1382,6 @@ int __init init_arch_irq(void)
                        irq_set_handler(irq, handle_percpu_irq);
                        break;
 #endif
-#endif
 
 #ifdef CONFIG_TICKSOURCE_CORETMR
                case IRQ_CORETMR:
@@ -1349,8 +1411,7 @@ int __init init_arch_irq(void)
 
        init_mach_irq();
 
-#ifndef CONFIG_BF60x
-#if (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)) && !defined(CONFIG_BF60x)
+#if (defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE))
        for (irq = IRQ_MAC_PHYINT; irq <= IRQ_MAC_STMDONE; irq++)
                irq_set_chip_and_handler(irq, &bfin_mac_status_irqchip,
                                         handle_level_irq);
@@ -1360,28 +1421,6 @@ int __init init_arch_irq(void)
                irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++)
                irq_set_chip_and_handler(irq, &bfin_gpio_irqchip,
                                         handle_level_irq);
-#else
-       for (irq = BFIN_IRQ(0); irq <= SYS_IRQS; irq++) {
-               if (irq < CORE_IRQS) {
-                       irq_set_chip(irq, &bfin_sec_irqchip);
-                       __irq_set_handler(irq, handle_sec_fault, 0, NULL);
-               } else if (irq >= BFIN_IRQ(21) && irq <= BFIN_IRQ(26)) {
-                       irq_set_chip(irq, &bfin_sec_irqchip);
-                       irq_set_chained_handler(irq, bfin_demux_gpio_irq);
-               } else if (irq >= BFIN_IRQ(34) && irq <= BFIN_IRQ(37)) {
-                       irq_set_chip(irq, &bfin_sec_irqchip);
-                       irq_set_handler(irq, handle_percpu_irq);
-               } else {
-                       irq_set_chip_and_handler(irq, &bfin_sec_irqchip,
-                                       handle_fasteoi_irq);
-                       __irq_set_preflow_handler(irq, bfin_sec_preflow_handler);
-               }
-       }
-       for (irq = GPIO_IRQ_BASE;
-               irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++)
-               irq_set_chip_and_handler(irq, &bfin_gpio_irqchip,
-                                       handle_level_irq);
-#endif
        bfin_write_IMASK(0);
        CSYNC();
        ilat = bfin_read_ILAT();
@@ -1393,7 +1432,6 @@ int __init init_arch_irq(void)
        /* IMASK=xxx is equivalent to STI xx or bfin_irq_flags=xx,
         * local_irq_enable()
         */
-#ifndef CONFIG_BF60x
        program_IAR();
        /* Therefore it's better to setup IARs before interrupts enabled */
        search_IAR();
@@ -1426,23 +1464,6 @@ int __init init_arch_irq(void)
 # endif
 #else
        bfin_write_SIC_IWR(IWR_DISABLE_ALL);
-#endif
-#else  /* CONFIG_BF60x */
-       /* Enable interrupts IVG7-15 */
-       bfin_irq_flags |= IMASK_IVG15 |
-           IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
-           IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
-
-
-       bfin_write_SEC_FCTL(SEC_FCTL_EN | SEC_FCTL_SYSRST_EN | SEC_FCTL_FLTIN_EN);
-       bfin_sec_enable_sci(SIC_SYSIRQ(IRQ_WATCH0));
-       bfin_sec_enable_ssi(SIC_SYSIRQ(IRQ_WATCH0));
-       bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_RESET);
-       udelay(100);
-       bfin_write_SEC_GCTL(SEC_GCTL_EN);
-       bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN);
-       init_software_driven_irq();
-       register_syscore_ops(&sec_pm_syscore_ops);
 #endif
        return 0;
 }
@@ -1452,14 +1473,11 @@ __attribute__((l1_text))
 #endif
 static int vec_to_irq(int vec)
 {
-#ifndef CONFIG_BF60x
        struct ivgx *ivg = ivg7_13[vec - IVG7].ifirst;
        struct ivgx *ivg_stop = ivg7_13[vec - IVG7].istop;
        unsigned long sic_status[3];
-#endif
        if (likely(vec == EVT_IVTMR_P))
                return IRQ_CORETMR;
-#ifndef CONFIG_BF60x
 #ifdef SIC_ISR
        sic_status[0] = bfin_read_SIC_IMASK() & bfin_read_SIC_ISR();
 #else
@@ -1488,11 +1506,119 @@ static int vec_to_irq(int vec)
 #endif
                        return ivg->irqno;
        }
-#else
-       /* for bf60x read */
+}
+
+#else /* SEC_GCTL */
+
+/*
+ * This function should be called during kernel startup to initialize
+ * the BFin IRQ handling routines.
+ */
+
+int __init init_arch_irq(void)
+{
+       int irq;
+       unsigned long ilat = 0;
+
+       bfin_write_SEC_GCTL(SEC_GCTL_RESET);
+
+       local_irq_disable();
+
+#if BFIN_GPIO_PINT
+# ifdef CONFIG_PINTx_REASSIGN
+       pint[0]->assign = CONFIG_PINT0_ASSIGN;
+       pint[1]->assign = CONFIG_PINT1_ASSIGN;
+       pint[2]->assign = CONFIG_PINT2_ASSIGN;
+       pint[3]->assign = CONFIG_PINT3_ASSIGN;
+       pint[4]->assign = CONFIG_PINT4_ASSIGN;
+       pint[5]->assign = CONFIG_PINT5_ASSIGN;
+# endif
+       /* Whenever PINTx_ASSIGN is altered init_pint_lut() must be executed! */
+       init_pint_lut();
+#endif
+
+       for (irq = 0; irq <= SYS_IRQS; irq++) {
+               if (irq <= IRQ_CORETMR) {
+                       irq_set_chip(irq, &bfin_core_irqchip);
+#ifdef CONFIG_TICKSOURCE_CORETMR
+                       if (irq == IRQ_CORETMR)
+# ifdef CONFIG_SMP
+                               irq_set_handler(irq, handle_percpu_irq);
+# else
+                               irq_set_handler(irq, handle_simple_irq);
+# endif
+#endif
+               } else if (irq < BFIN_IRQ(0)) {
+                       irq_set_chip_and_handler(irq, &bfin_internal_irqchip,
+                                       handle_simple_irq);
+               } else if (irq == IRQ_SEC_ERR) {
+                       irq_set_chip_and_handler(irq, &bfin_sec_irqchip,
+                                       handle_sec_fault);
+               } else if (irq < CORE_IRQS && irq >= IRQ_C0_DBL_FAULT) {
+                       irq_set_chip_and_handler(irq, &bfin_sec_irqchip,
+                                       handle_core_fault);
+               } else if (irq >= BFIN_IRQ(21) && irq <= BFIN_IRQ(26)) {
+                       irq_set_chip(irq, &bfin_sec_irqchip);
+                       irq_set_chained_handler(irq, bfin_demux_gpio_irq);
+               } else if (irq >= BFIN_IRQ(34) && irq <= BFIN_IRQ(37)) {
+                       irq_set_chip(irq, &bfin_sec_irqchip);
+                       irq_set_handler(irq, handle_percpu_irq);
+               } else {
+                       irq_set_chip_and_handler(irq, &bfin_sec_irqchip,
+                                       handle_fasteoi_irq);
+                       __irq_set_preflow_handler(irq, bfin_sec_preflow_handler);
+               }
+       }
+       for (irq = GPIO_IRQ_BASE;
+               irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++)
+               irq_set_chip_and_handler(irq, &bfin_gpio_irqchip,
+                                       handle_level_irq);
+
+       bfin_write_IMASK(0);
+       CSYNC();
+       ilat = bfin_read_ILAT();
+       CSYNC();
+       bfin_write_ILAT(ilat);
+       CSYNC();
+
+       printk(KERN_INFO "Configuring Blackfin Priority Driven Interrupts\n");
+
+       bfin_sec_set_priority(CONFIG_SEC_IRQ_PRIORITY_LEVELS, sec_int_priority);
+
+       bfin_sec_set_priority(CONFIG_SEC_IRQ_PRIORITY_LEVELS, sec_int_priority);
+
+       /* Enable interrupts IVG7-15 */
+       bfin_irq_flags |= IMASK_IVG15 |
+           IMASK_IVG14 | IMASK_IVG13 | IMASK_IVG12 | IMASK_IVG11 |
+           IMASK_IVG10 | IMASK_IVG9 | IMASK_IVG8 | IMASK_IVG7 | IMASK_IVGHW;
+
+
+       bfin_write_SEC_FCTL(SEC_FCTL_EN | SEC_FCTL_SYSRST_EN | SEC_FCTL_FLTIN_EN);
+       bfin_sec_enable_sci(SIC_SYSIRQ(IRQ_WATCH0));
+       bfin_sec_enable_ssi(SIC_SYSIRQ(IRQ_WATCH0));
+       bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_RESET);
+       udelay(100);
+       bfin_write_SEC_GCTL(SEC_GCTL_EN);
+       bfin_write_SEC_SCI(0, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN);
+       bfin_write_SEC_SCI(1, SEC_CCTL, SEC_CCTL_EN | SEC_CCTL_NMI_EN);
+
+       init_software_driven_irq();
+       register_syscore_ops(&sec_pm_syscore_ops);
+
+       return 0;
+}
+
+#ifdef CONFIG_DO_IRQ_L1
+__attribute__((l1_text))
+#endif
+static int vec_to_irq(int vec)
+{
+       if (likely(vec == EVT_IVTMR_P))
+               return IRQ_CORETMR;
+
        return BFIN_IRQ(bfin_read_SEC_SCI(0, SEC_CSID));
-#endif  /* end of CONFIG_BF60x */
 }
+#endif  /* SEC_GCTL */
 
 #ifdef CONFIG_DO_IRQ_L1
 __attribute__((l1_text))
@@ -1514,6 +1640,10 @@ int __ipipe_get_irq_priority(unsigned irq)
        if (irq <= IRQ_CORETMR)
                return irq;
 
+#ifdef SEC_GCTL
+       if (irq >= BFIN_IRQ(0))
+               return IVG11;
+#else
        for (ient = 0; ient < NR_PERI_INTS; ient++) {
                struct ivgx *ivg = ivg_table + ient;
                if (ivg->irqno == irq) {
@@ -1524,6 +1654,7 @@ int __ipipe_get_irq_priority(unsigned irq)
                        }
                }
        }
+#endif
 
        return IVG15;
 }
@@ -1536,8 +1667,6 @@ asmlinkage int __ipipe_grab_irq(int vec, struct pt_regs *regs)
 {
        struct ipipe_percpu_domain_data *p = ipipe_root_cpudom_ptr();
        struct ipipe_domain *this_domain = __ipipe_current_domain;
-       struct ivgx *ivg_stop = ivg7_13[vec-IVG7].istop;
-       struct ivgx *ivg = ivg7_13[vec-IVG7].ifirst;
        int irq, s = 0;
 
        irq = vec_to_irq(vec);
index ca6655e0d653903e39999dc9a2567040fee4b6bc..87bfe549ad3f5044b8ce652434b98d00470672fc 100644 (file)
@@ -172,6 +172,10 @@ int bfin_pm_suspend_mem_enter(void)
 
        bfin_gpio_pm_hibernate_suspend();
 
+#if BFIN_GPIO_PINT
+       bfin_pint_suspend();
+#endif
+
 #if defined(CONFIG_BFIN_EXTMEM_WRITEBACK) || defined(CONFIG_BFIN_L2_WRITEBACK)
        flushinv_all_dcache();
 #endif
@@ -190,6 +194,10 @@ int bfin_pm_suspend_mem_enter(void)
        _enable_icplb();
        _enable_dcplb();
 
+#if BFIN_GPIO_PINT
+       bfin_pint_resume();
+#endif
+
        bfin_gpio_pm_hibernate_restore();
        blackfin_dma_resume();
 
diff --git a/arch/c6x/boot/dts/evmc6678.dts b/arch/c6x/boot/dts/evmc6678.dts
new file mode 100644 (file)
index 0000000..ab68630
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * arch/c6x/boot/dts/evmc6678.dts
+ *
+ * EVMC6678 Evaluation Platform For TMS320C6678
+ *
+ * Copyright (C) 2012 Texas Instruments Incorporated
+ *
+ * Author: Ken Cox <jkc@redhat.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.
+ *
+ */
+
+/dts-v1/;
+
+/include/ "tms320c6678.dtsi"
+
+/ {
+       model = "Advantech EVMC6678";
+       compatible = "advantech,evmc6678";
+
+       chosen {
+               bootargs = "root=/dev/nfs ip=dhcp rw";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x80000000 0x20000000>;
+       };
+
+       soc {
+               megamod_pic: interrupt-controller@1800000 {
+                      interrupts = < 12 13 14 15 >;
+               };
+
+               timer8: timer@2280000 {
+                       interrupt-parent = <&megamod_pic>;
+                       interrupts = < 66 >;
+               };
+
+               timer9: timer@2290000 {
+                       interrupt-parent = <&megamod_pic>;
+                       interrupts = < 68 >;
+               };
+
+               timer10: timer@22A0000 {
+                       interrupt-parent = <&megamod_pic>;
+                       interrupts = < 70 >;
+               };
+
+               timer11: timer@22B0000 {
+                       interrupt-parent = <&megamod_pic>;
+                       interrupts = < 72 >;
+               };
+
+               timer12: timer@22C0000 {
+                       interrupt-parent = <&megamod_pic>;
+                       interrupts = < 74 >;
+               };
+
+               timer13: timer@22D0000 {
+                       interrupt-parent = <&megamod_pic>;
+                       interrupts = < 76 >;
+               };
+
+               timer14: timer@22E0000 {
+                       interrupt-parent = <&megamod_pic>;
+                       interrupts = < 78 >;
+               };
+
+               timer15: timer@22F0000 {
+                       interrupt-parent = <&megamod_pic>;
+                       interrupts = < 80 >;
+               };
+
+               clock-controller@2310000 {
+                       clock-frequency = <100000000>;
+               };
+       };
+};
diff --git a/arch/c6x/boot/dts/tms320c6678.dtsi b/arch/c6x/boot/dts/tms320c6678.dtsi
new file mode 100644 (file)
index 0000000..386196e
--- /dev/null
@@ -0,0 +1,146 @@
+
+/ {
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       reg = <0>;
+                       model = "ti,c66x";
+               };
+               cpu@1 {
+                       device_type = "cpu";
+                       reg = <1>;
+                       model = "ti,c66x";
+               };
+               cpu@2 {
+                       device_type = "cpu";
+                       reg = <2>;
+                       model = "ti,c66x";
+               };
+               cpu@3 {
+                       device_type = "cpu";
+                       reg = <3>;
+                       model = "ti,c66x";
+               };
+               cpu@4 {
+                       device_type = "cpu";
+                       reg = <4>;
+                       model = "ti,c66x";
+               };
+               cpu@5 {
+                       device_type = "cpu";
+                       reg = <5>;
+                       model = "ti,c66x";
+               };
+               cpu@6 {
+                       device_type = "cpu";
+                       reg = <6>;
+                       model = "ti,c66x";
+               };
+               cpu@7 {
+                       device_type = "cpu";
+                       reg = <7>;
+                       model = "ti,c66x";
+               };
+       };
+
+       soc {
+               compatible = "simple-bus";
+               model = "tms320c6678";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               core_pic: interrupt-controller {
+                       compatible = "ti,c64x+core-pic";
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+               };
+
+               megamod_pic: interrupt-controller@1800000 {
+                      compatible = "ti,c64x+megamod-pic";
+                      interrupt-controller;
+                      #interrupt-cells = <1>;
+                      reg = <0x1800000 0x1000>;
+                      interrupt-parent = <&core_pic>;
+               };
+
+               cache-controller@1840000 {
+                       compatible = "ti,c64x+cache";
+                       reg = <0x01840000 0x8400>;
+               };
+
+               timer8: timer@2280000 {
+                       compatible = "ti,c64x+timer64";
+                       ti,core-mask = < 0x01 >;
+                       reg = <0x2280000 0x40>;
+               };
+
+               timer9: timer@2290000 {
+                       compatible = "ti,c64x+timer64";
+                       ti,core-mask = < 0x02 >;
+                       reg = <0x2290000 0x40>;
+               };
+
+               timer10: timer@22A0000 {
+                       compatible = "ti,c64x+timer64";
+                       ti,core-mask = < 0x04 >;
+                       reg = <0x22A0000 0x40>;
+               };
+
+               timer11: timer@22B0000 {
+                       compatible = "ti,c64x+timer64";
+                       ti,core-mask = < 0x08 >;
+                       reg = <0x22B0000 0x40>;
+               };
+
+               timer12: timer@22C0000 {
+                       compatible = "ti,c64x+timer64";
+                       ti,core-mask = < 0x10 >;
+                       reg = <0x22C0000 0x40>;
+               };
+
+               timer13: timer@22D0000 {
+                       compatible = "ti,c64x+timer64";
+                       ti,core-mask = < 0x20 >;
+                       reg = <0x22D0000 0x40>;
+               };
+
+               timer14: timer@22E0000 {
+                       compatible = "ti,c64x+timer64";
+                       ti,core-mask = < 0x40 >;
+                       reg = <0x22E0000 0x40>;
+               };
+
+               timer15: timer@22F0000 {
+                       compatible = "ti,c64x+timer64";
+                       ti,core-mask = < 0x80 >;
+                       reg = <0x22F0000 0x40>;
+               };
+
+               clock-controller@2310000 {
+                       compatible = "ti,c6678-pll", "ti,c64x+pll";
+                       reg = <0x02310000 0x200>;
+                       ti,c64x+pll-bypass-delay = <200>;
+                       ti,c64x+pll-reset-delay = <12000>;
+                       ti,c64x+pll-lock-delay = <80000>;
+               };
+
+               device-state-controller@2620000 {
+                       compatible = "ti,c64x+dscr";
+                       reg = <0x02620000 0x1000>;
+
+                       ti,dscr-devstat = <0x20>;
+                       ti,dscr-silicon-rev = <0x18 28 0xf>;
+
+                       ti,dscr-mac-fuse-regs = <0x110 1 2 3 4
+                                                0x114 5 6 0 0>;
+
+               };
+       };
+};
diff --git a/arch/c6x/configs/evmc6678_defconfig b/arch/c6x/configs/evmc6678_defconfig
new file mode 100644 (file)
index 0000000..5f126d4
--- /dev/null
@@ -0,0 +1,42 @@
+CONFIG_SOC_TMS320C6678=y
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_NAMESPACES=y
+# CONFIG_UTS_NS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_PID_NS is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_EXPERT=y
+# CONFIG_FUTEX is not set
+# CONFIG_SLUB_DEBUG is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_FORCE_LOAD=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE=""
+# CONFIG_CMDLINE_FORCE is not set
+CONFIG_BOARD_EVM6678=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=2
+CONFIG_BLK_DEV_RAM_SIZE=17000
+CONFIG_MISC_DEVICES=y
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+# CONFIG_IOMMU_SUPPORT is not set
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_CRC16=y
+# CONFIG_ENABLE_MUST_CHECK is not set
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_DEBUG_BUGVERBOSE is not set
index ab4577f93d96c97f347936a33a75dce2825df0c4..1324e62bd4ef8e70b524832fa72d3c1b223905f5 100644 (file)
@@ -34,8 +34,6 @@
  */
 #define NR_PRIORITY_IRQS 16
 
-#define NR_IRQS_LEGACY NR_PRIORITY_IRQS
-
 /* Total number of virq in the platform */
 #define NR_IRQS                256
 
index c90fb5e82ad7b829fb9be3a9d562118374eff901..247e0eb5e4670c8e6615ebaa4b90edc65c6fb851 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (C) 2011 Texas Instruments Incorporated
+ *  Copyright (C) 2011-2012 Texas Instruments Incorporated
  *
  *  This borrows heavily from powerpc version, which is:
  *
@@ -35,9 +35,7 @@ static DEFINE_RAW_SPINLOCK(core_irq_lock);
 
 static void mask_core_irq(struct irq_data *data)
 {
-       unsigned int prio = data->irq;
-
-       BUG_ON(prio < 4 || prio >= NR_PRIORITY_IRQS);
+       unsigned int prio = data->hwirq;
 
        raw_spin_lock(&core_irq_lock);
        and_creg(IER, ~(1 << prio));
@@ -46,7 +44,7 @@ static void mask_core_irq(struct irq_data *data)
 
 static void unmask_core_irq(struct irq_data *data)
 {
-       unsigned int prio = data->irq;
+       unsigned int prio = data->hwirq;
 
        raw_spin_lock(&core_irq_lock);
        or_creg(IER, 1 << prio);
@@ -59,15 +57,15 @@ static struct irq_chip core_chip = {
        .irq_unmask     = unmask_core_irq,
 };
 
+static int prio_to_virq[NR_PRIORITY_IRQS];
+
 asmlinkage void c6x_do_IRQ(unsigned int prio, struct pt_regs *regs)
 {
        struct pt_regs *old_regs = set_irq_regs(regs);
 
        irq_enter();
 
-       BUG_ON(prio < 4 || prio >= NR_PRIORITY_IRQS);
-
-       generic_handle_irq(prio);
+       generic_handle_irq(prio_to_virq[prio]);
 
        irq_exit();
 
@@ -82,6 +80,8 @@ static int core_domain_map(struct irq_domain *h, unsigned int virq,
        if (hw < 4 || hw >= NR_PRIORITY_IRQS)
                return -EINVAL;
 
+       prio_to_virq[hw] = virq;
+
        irq_set_status_flags(virq, IRQ_LEVEL);
        irq_set_chip_and_handler(virq, &core_chip, handle_level_irq);
        return 0;
@@ -102,9 +102,8 @@ void __init init_IRQ(void)
        np = of_find_compatible_node(NULL, NULL, "ti,c64x+core-pic");
        if (np != NULL) {
                /* create the core host */
-               core_domain = irq_domain_add_legacy(np, NR_PRIORITY_IRQS,
-                                                   0, 0, &core_domain_ops,
-                                                   NULL);
+               core_domain = irq_domain_add_linear(np, NR_PRIORITY_IRQS,
+                                                   &core_domain_ops, NULL);
                if (core_domain)
                        irq_set_default_host(core_domain);
                of_node_put(np);
index ce46186600c51841a8d2ca9fb5d0b66cdf1e1976..f4e72bd8c10308ba1f6c26460992df11749017a7 100644 (file)
@@ -143,6 +143,10 @@ static void __init get_cpuinfo(void)
                p->cpu_name = "C64x+";
                p->cpu_voltage = "1.2";
                break;
+       case 21:
+               p->cpu_name = "C66X";
+               p->cpu_voltage = "1.2";
+               break;
        default:
                p->cpu_name = "unknown";
                break;
index 3d8f3c22a94fa0adf7e66fe2a793a65326759990..3998b24e26f2d7d3bfef802389c90617a2961b49 100644 (file)
@@ -249,8 +249,6 @@ static void handle_signal(int sig,
                         siginfo_t *info, struct k_sigaction *ka,
                         struct pt_regs *regs, int syscall)
 {
-       int ret;
-
        /* Are we from a system call? */
        if (syscall) {
                /* If so, check system call restarting.. */
index 401ee678fd014897a680ad745e8f55217e0544cd..c4a0fad89aafc117a116e00ff2ff3280ec91e9f3 100644 (file)
@@ -14,3 +14,7 @@ config SOC_TMS320C6472
 config SOC_TMS320C6474
        bool "TMS320C6474"
        default n
+
+config SOC_TMS320C6678
+       bool "TMS320C6678"
+       default n
index c1c4e2ae3f85be2804d4987c149a65d5e03ec66c..74e3371eb8245bc4c769eff1b8923707c0fc883f 100644 (file)
@@ -243,27 +243,37 @@ static struct megamod_pic * __init init_megamod_pic(struct device_node *np)
         * as their interrupt parent.
         */
        for (i = 0; i < NR_COMBINERS; i++) {
+               struct irq_data *irq_data;
+               irq_hw_number_t hwirq;
 
                irq = irq_of_parse_and_map(np, i);
                if (irq == NO_IRQ)
                        continue;
 
+               irq_data = irq_get_irq_data(irq);
+               if (!irq_data) {
+                       pr_err("%s: combiner-%d no irq_data for virq %d!\n",
+                              np->full_name, i, irq);
+                       continue;
+               }
+
+               hwirq = irq_data->hwirq;
+
                /*
-                * We count on the core priority interrupts (4 - 15) being
-                * direct mapped. Check that device tree provided something
-                * in that range.
+                * Check that device tree provided something in the range
+                * of the core priority interrupts (4 - 15).
                 */
-               if (irq < 4 || irq >= NR_PRIORITY_IRQS) {
-                       pr_err("%s: combiner-%d virq %d out of range!\n",
-                                np->full_name, i, irq);
+               if (hwirq < 4 || hwirq >= NR_PRIORITY_IRQS) {
+                       pr_err("%s: combiner-%d core irq %ld out of range!\n",
+                              np->full_name, i, hwirq);
                        continue;
                }
 
                /* record the mapping */
-               mapping[irq - 4] = i;
+               mapping[hwirq - 4] = i;
 
-               pr_debug("%s: combiner-%d cascading to virq %d\n",
-                        np->full_name, i, irq);
+               pr_debug("%s: combiner-%d cascading to hwirq %ld\n",
+                        np->full_name, i, hwirq);
 
                cascade_data[i].pic = pic;
                cascade_data[i].index = i;
index 2cfd6f42968f3bdec2159827d0954e4d6effcc6b..755359eb628622ffd60d2bdd6ebb3a060159620b 100644 (file)
@@ -335,6 +335,68 @@ static void __init c6474_setup_clocks(struct device_node *node)
 }
 #endif /* CONFIG_SOC_TMS320C6474 */
 
+#ifdef CONFIG_SOC_TMS320C6678
+static struct clk_lookup c6678_clks[] = {
+       CLK(NULL, "pll1", &c6x_soc_pll1.sysclks[0]),
+       CLK(NULL, "pll1_refclk", &c6x_soc_pll1.sysclks[1]),
+       CLK(NULL, "pll1_sysclk2", &c6x_soc_pll1.sysclks[2]),
+       CLK(NULL, "pll1_sysclk3", &c6x_soc_pll1.sysclks[3]),
+       CLK(NULL, "pll1_sysclk4", &c6x_soc_pll1.sysclks[4]),
+       CLK(NULL, "pll1_sysclk5", &c6x_soc_pll1.sysclks[5]),
+       CLK(NULL, "pll1_sysclk6", &c6x_soc_pll1.sysclks[6]),
+       CLK(NULL, "pll1_sysclk7", &c6x_soc_pll1.sysclks[7]),
+       CLK(NULL, "pll1_sysclk8", &c6x_soc_pll1.sysclks[8]),
+       CLK(NULL, "pll1_sysclk9", &c6x_soc_pll1.sysclks[9]),
+       CLK(NULL, "pll1_sysclk10", &c6x_soc_pll1.sysclks[10]),
+       CLK(NULL, "pll1_sysclk11", &c6x_soc_pll1.sysclks[11]),
+       CLK(NULL, "core", &c6x_core_clk),
+       CLK("", NULL, NULL)
+};
+
+static void __init c6678_setup_clocks(struct device_node *node)
+{
+       struct pll_data *pll = &c6x_soc_pll1;
+       struct clk *sysclks = pll->sysclks;
+
+       pll->flags = PLL_HAS_MUL;
+
+       sysclks[1].flags |= FIXED_DIV_PLL;
+       sysclks[1].div = 1;
+
+       sysclks[2].div = PLLDIV2;
+
+       sysclks[3].flags |= FIXED_DIV_PLL;
+       sysclks[3].div = 2;
+
+       sysclks[4].flags |= FIXED_DIV_PLL;
+       sysclks[4].div = 3;
+
+       sysclks[5].div = PLLDIV5;
+
+       sysclks[6].flags |= FIXED_DIV_PLL;
+       sysclks[6].div = 64;
+
+       sysclks[7].flags |= FIXED_DIV_PLL;
+       sysclks[7].div = 6;
+
+       sysclks[8].div = PLLDIV8;
+
+       sysclks[9].flags |= FIXED_DIV_PLL;
+       sysclks[9].div = 12;
+
+       sysclks[10].flags |= FIXED_DIV_PLL;
+       sysclks[10].div = 3;
+
+       sysclks[11].flags |= FIXED_DIV_PLL;
+       sysclks[11].div = 6;
+
+       c6x_core_clk.parent = &sysclks[0];
+       c6x_i2c_clk.parent = &sysclks[7];
+
+       c6x_clks_init(c6678_clks);
+}
+#endif /* CONFIG_SOC_TMS320C6678 */
+
 static struct of_device_id c6x_clkc_match[] __initdata = {
 #ifdef CONFIG_SOC_TMS320C6455
        { .compatible = "ti,c6455-pll", .data = c6455_setup_clocks },
@@ -347,6 +409,9 @@ static struct of_device_id c6x_clkc_match[] __initdata = {
 #endif
 #ifdef CONFIG_SOC_TMS320C6474
        { .compatible = "ti,c6474-pll", .data = c6474_setup_clocks },
+#endif
+#ifdef CONFIG_SOC_TMS320C6678
+       { .compatible = "ti,c6678-pll", .data = c6678_setup_clocks },
 #endif
        { .compatible = "ti,c64x+pll" },
        {}
index f7264621e58ddf888708dcbe114320bd2d2fd934..149fbefc1a4d36988d6f5ce3422aaac57d029b60 100644 (file)
@@ -180,9 +180,7 @@ void __cpuinit start_secondary(void)
 
        notify_cpu_starting(cpu);
 
-       ipi_call_lock();
        set_cpu_online(cpu, true);
-       ipi_call_unlock();
 
        local_irq_enable();
 
index 1113b8aba07f5a0caa632ff01dc8111899e49185..963d2db53bfa55a9d50932b3301300d3411c3115 100644 (file)
@@ -382,7 +382,6 @@ smp_callin (void)
        set_numa_node(cpu_to_node_map[cpuid]);
        set_numa_mem(local_memory_node(cpu_to_node_map[cpuid]));
 
-       ipi_call_lock_irq();
        spin_lock(&vector_lock);
        /* Setup the per cpu irq handling data structures */
        __setup_vector_irq(cpuid);
@@ -390,7 +389,6 @@ smp_callin (void)
        set_cpu_online(cpuid, true);
        per_cpu(cpu_state, cpuid) = CPU_ONLINE;
        spin_unlock(&vector_lock);
-       ipi_call_unlock_irq();
 
        smp_setup_percpu_timer();
 
index 02d29c2a132a028f92c2c55e92fc36bbc5edfb2e..8443daf4f515777ca3cd6d710bef4a92b6373608 100644 (file)
@@ -72,6 +72,10 @@ mapped_kernel_page_is_present (unsigned long address)
        return pte_present(pte);
 }
 
+#      define VM_READ_BIT      0
+#      define VM_WRITE_BIT     1
+#      define VM_EXEC_BIT      2
+
 void __kprobes
 ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
 {
@@ -81,6 +85,12 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
        struct siginfo si;
        unsigned long mask;
        int fault;
+       unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
+
+       mask = ((((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
+               | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT));
+
+       flags |= ((mask & VM_WRITE) ? FAULT_FLAG_WRITE : 0);
 
        /* mmap_sem is performance critical.... */
        prefetchw(&mm->mmap_sem);
@@ -109,6 +119,7 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
        if (notify_page_fault(regs, TRAP_BRKPT))
                return;
 
+retry:
        down_read(&mm->mmap_sem);
 
        vma = find_vma_prev(mm, address, &prev_vma);
@@ -130,10 +141,6 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
 
        /* OK, we've got a good vm_area for this memory area.  Check the access permissions: */
 
-#      define VM_READ_BIT      0
-#      define VM_WRITE_BIT     1
-#      define VM_EXEC_BIT      2
-
 #      if (((1 << VM_READ_BIT) != VM_READ || (1 << VM_WRITE_BIT) != VM_WRITE) \
            || (1 << VM_EXEC_BIT) != VM_EXEC)
 #              error File is out of sync with <linux/mm.h>.  Please update.
@@ -142,9 +149,6 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
        if (((isr >> IA64_ISR_R_BIT) & 1UL) && (!(vma->vm_flags & (VM_READ | VM_WRITE))))
                goto bad_area;
 
-       mask = (  (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT)
-               | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT));
-
        if ((vma->vm_flags & mask) != mask)
                goto bad_area;
 
@@ -153,7 +157,11 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
         * sure we exit gracefully rather than endlessly redo the
         * fault.
         */
-       fault = handle_mm_fault(mm, vma, address, (mask & VM_WRITE) ? FAULT_FLAG_WRITE : 0);
+       fault = handle_mm_fault(mm, vma, address, flags);
+
+       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
+               return;
+
        if (unlikely(fault & VM_FAULT_ERROR)) {
                /*
                 * We ran out of memory, or some other thing happened
@@ -168,10 +176,24 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
                }
                BUG();
        }
-       if (fault & VM_FAULT_MAJOR)
-               current->maj_flt++;
-       else
-               current->min_flt++;
+
+       if (flags & FAULT_FLAG_ALLOW_RETRY) {
+               if (fault & VM_FAULT_MAJOR)
+                       current->maj_flt++;
+               else
+                       current->min_flt++;
+               if (fault & VM_FAULT_RETRY) {
+                       flags &= ~FAULT_FLAG_ALLOW_RETRY;
+
+                        /* No need to up_read(&mm->mmap_sem) as we would
+                        * have already released it in __lock_page_or_retry
+                        * in mm/filemap.c.
+                        */
+
+                       goto retry;
+               }
+       }
+
        up_read(&mm->mmap_sem);
        return;
 
index cf7829a615513e1597d903c6398348d8e0d5ac1e..c689b828dfe2b0b218d6ec523c0233fddd086785 100644 (file)
@@ -79,11 +79,6 @@ static __inline__ int cpu_number_map(int cpu)
        return cpu;
 }
 
-static __inline__ unsigned int num_booting_cpus(void)
-{
-       return cpumask_weight(&cpu_callout_map);
-}
-
 extern void smp_send_timer(void);
 extern unsigned long send_IPI_mask_phys(const cpumask_t*, int, int);
 
index 09ab87ee6fef654eef0220ab05b1224492947efc..b3e10fdd389866659212f947971af764b98dcf3f 100644 (file)
@@ -288,6 +288,7 @@ config MIPS_MALTA
        select SYS_HAS_CPU_MIPS32_R1
        select SYS_HAS_CPU_MIPS32_R2
        select SYS_HAS_CPU_MIPS64_R1
+       select SYS_HAS_CPU_MIPS64_R2
        select SYS_HAS_CPU_NEVADA
        select SYS_HAS_CPU_RM7000
        select SYS_HAS_EARLY_PRINTK
@@ -1423,6 +1424,7 @@ config CPU_SB1
 config CPU_CAVIUM_OCTEON
        bool "Cavium Octeon processor"
        depends on SYS_HAS_CPU_CAVIUM_OCTEON
+       select ARCH_SPARSEMEM_ENABLE
        select CPU_HAS_PREFETCH
        select CPU_SUPPORTS_64BIT_KERNEL
        select SYS_SUPPORTS_SMP
index 6210b8d841098c5182a7ea986e6ac66c6a02371b..b311be45a7207028a7cf6df754a8b54c0f259938 100644 (file)
@@ -21,6 +21,7 @@ config BCM47XX_BCMA
        select BCMA
        select BCMA_HOST_SOC
        select BCMA_DRIVER_MIPS
+       select BCMA_HOST_PCI if PCI
        select BCMA_DRIVER_PCI_HOSTMODE if PCI
        default y
        help
index de4d917fd54d5ae99fa3ec69e55666a4fe3945cc..a551bab5ecb94b2aafce31787cea8e6bb31dbd10 100644 (file)
@@ -79,11 +79,11 @@ static int __init config_pcmcia_cs(unsigned int cs,
        return ret;
 }
 
-static const __initdata struct {
+static const struct {
        unsigned int    cs;
        unsigned int    base;
        unsigned int    size;
-} pcmcia_cs[3] = {
+} pcmcia_cs[3] __initconst = {
        {
                .cs     = MPI_CS_PCMCIA_COMMON,
                .base   = BCM_PCMCIA_COMMON_BASE_PA,
index f9e275a50d982be23ffda94a1e23d019c25569b5..2f4f6d5e05b66bdad381da0ddaff5b83d3897d51 100644 (file)
@@ -82,10 +82,6 @@ config CAVIUM_OCTEON_LOCK_L2_MEMCPY
        help
          Lock the kernel's implementation of memcpy() into L2.
 
-config ARCH_SPARSEMEM_ENABLE
-       def_bool y
-       select SPARSEMEM_STATIC
-
 config IOMMU_HELPER
        bool
 
index 4b93048044eb266457b4c9ac80a164c056e6eba9..ee1fb9f7f517c29e1ce6781699cbf90e75a314ce 100644 (file)
@@ -185,7 +185,6 @@ static void __cpuinit octeon_init_secondary(void)
        octeon_init_cvmcount();
 
        octeon_irq_setup_secondary();
-       raw_local_irq_enable();
 }
 
 /**
@@ -233,6 +232,7 @@ static void octeon_smp_finish(void)
 
        /* to generate the first CPU timer interrupt */
        write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ);
+       local_irq_enable();
 }
 
 /**
index 285a41fa0b18dd0412a291805781f8d811ee82de..eee10dc07ac100defc6b0f00f6d8616da692e2c0 100644 (file)
@@ -8,6 +8,7 @@
 #ifndef __ASM_CMPXCHG_H
 #define __ASM_CMPXCHG_H
 
+#include <linux/bug.h>
 #include <linux/irqflags.h>
 #include <asm/war.h>
 
index f9fa2a479dd0e175ae7fc839d833b15695103f04..95e40c1e8ed114a3a95ad9cab9794e129ccbdca2 100644 (file)
@@ -94,6 +94,7 @@
 #define PRID_IMP_24KE          0x9600
 #define PRID_IMP_74K           0x9700
 #define PRID_IMP_1004K         0x9900
+#define PRID_IMP_M14KC         0x9c00
 
 /*
  * These are the PRID's for when 23:16 == PRID_COMP_SIBYTE
@@ -260,12 +261,12 @@ enum cpu_type_enum {
         */
        CPU_4KC, CPU_4KEC, CPU_4KSC, CPU_24K, CPU_34K, CPU_1004K, CPU_74K,
        CPU_ALCHEMY, CPU_PR4450, CPU_BMIPS32, CPU_BMIPS3300, CPU_BMIPS4350,
-       CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC,
+       CPU_BMIPS4380, CPU_BMIPS5000, CPU_JZRISC, CPU_M14KC,
 
        /*
         * MIPS64 class processors
         */
-       CPU_5KC, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2,
+       CPU_5KC, CPU_5KE, CPU_20KC, CPU_25KF, CPU_SB1, CPU_SB1A, CPU_LOONGSON2,
        CPU_CAVIUM_OCTEON, CPU_CAVIUM_OCTEON_PLUS, CPU_CAVIUM_OCTEON2,
        CPU_XLR, CPU_XLP,
 
@@ -288,7 +289,7 @@ enum cpu_type_enum {
 #define MIPS_CPU_ISA_M64R2     0x00000100
 
 #define MIPS_CPU_ISA_32BIT (MIPS_CPU_ISA_I | MIPS_CPU_ISA_II | \
-       MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2 )
+       MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M32R2)
 #define MIPS_CPU_ISA_64BIT (MIPS_CPU_ISA_III | MIPS_CPU_ISA_IV | \
        MIPS_CPU_ISA_V | MIPS_CPU_ISA_M64R1 | MIPS_CPU_ISA_M64R2)
 
index 86548da650e765f79db345f4d3964a5d0eb6c0fe..991b659e254803937cc99c9854d2c24f1153b0d3 100644 (file)
 
 #define GIC_VPE_EIC_SHADOW_SET_BASE    0x0100
 #define GIC_VPE_EIC_SS(intr) \
-       (GIC_EIC_SHADOW_SET_BASE + (4 * intr))
+       (GIC_VPE_EIC_SHADOW_SET_BASE + (4 * intr))
 
 #define GIC_VPE_EIC_VEC_BASE           0x0800
 #define GIC_VPE_EIC_VEC(intr) \
@@ -330,6 +330,17 @@ struct gic_intr_map {
 #define GIC_FLAG_TRANSPARENT   0x02
 };
 
+/*
+ * This is only used in EIC mode. This helps to figure out which
+ * shared interrupts we need to process when we get a vector interrupt.
+ */
+#define GIC_MAX_SHARED_INTR  0x5
+struct gic_shared_intr_map {
+       unsigned int num_shared_intr;
+       unsigned int intr_list[GIC_MAX_SHARED_INTR];
+       unsigned int local_intr_mask;
+};
+
 extern void gic_init(unsigned long gic_base_addr,
        unsigned long gic_addrspace_size, struct gic_intr_map *intrmap,
        unsigned int intrmap_size, unsigned int irqbase);
@@ -338,5 +349,7 @@ extern unsigned int gic_get_int(void);
 extern void gic_send_ipi(unsigned int intr);
 extern unsigned int plat_ipi_call_int_xlate(unsigned int);
 extern unsigned int plat_ipi_resched_int_xlate(unsigned int);
+extern void gic_bind_eic_interrupt(int irq, int set);
+extern unsigned int gic_get_timer_pending(void);
 
 #endif /* _ASM_GICREGS_H */
index 7ebfc392e58d1d5cb7c8f2a686e25a9041f853b8..ab84064283db2c50d847d888b32e42a4d316dd7d 100644 (file)
@@ -251,7 +251,7 @@ struct f_format {   /* FPU register format */
        unsigned int func : 6;
 };
 
-struct ma_format {     /* FPU multipy and add format (MIPS IV) */
+struct ma_format {     /* FPU multiply and add format (MIPS IV) */
        unsigned int opcode : 6;
        unsigned int fr : 5;
        unsigned int ft : 5;
@@ -324,7 +324,7 @@ struct f_format {   /* FPU register format */
        unsigned int opcode : 6;
 };
 
-struct ma_format {     /* FPU multipy and add format (MIPS IV) */
+struct ma_format {     /* FPU multiply and add format (MIPS IV) */
        unsigned int fmt : 2;
        unsigned int func : 4;
        unsigned int fd : 5;
index fb698dc09bc9c39c60cf7c0d43992b424e239551..78dbb8a86da249d4bd4e6fa2db6b6c6b0c4bd4ed 100644 (file)
@@ -136,6 +136,7 @@ extern void free_irqno(unsigned int irq);
  * IE7.  Since R2 their number has to be read from the c0_intctl register.
  */
 #define CP0_LEGACY_COMPARE_IRQ 7
+#define CP0_LEGACY_PERFCNT_IRQ 7
 
 extern int cp0_compare_irq;
 extern int cp0_compare_irq_shift;
index 94d4faad29a1a4286c934d28e76175ca97eee935..fdcd78ca1b03d054f807ee0c64839c763194f855 100644 (file)
@@ -99,7 +99,7 @@
 #define CKCTL_6368_USBH_CLK_EN         (1 << 15)
 #define CKCTL_6368_DISABLE_GLESS_EN    (1 << 16)
 #define CKCTL_6368_NAND_CLK_EN         (1 << 17)
-#define CKCTL_6368_IPSEC_CLK_EN                (1 << 17)
+#define CKCTL_6368_IPSEC_CLK_EN                (1 << 18)
 
 #define CKCTL_6368_ALL_SAFE_EN         (CKCTL_6368_SWPKT_USB_EN |      \
                                        CKCTL_6368_SWPKT_SAR_EN |       \
index d11aa02a956a57ca41ff890dbe16bbdd0145db53..5447d9fc421941da85a2b0ce6bed2b865a4a8282 100644 (file)
 #define GIC_CPU_INT4           4 /* .                  */
 #define GIC_CPU_INT5           5 /* Core Interrupt 5   */
 
+/* MALTA GIC local interrupts */
+#define GIC_INT_TMR             (GIC_CPU_INT5)
+#define GIC_INT_PERFCTR         (GIC_CPU_INT5)
+
+/* GIC constants */
+/* Add 2 to convert non-eic hw int # to eic vector # */
+#define GIC_CPU_TO_VEC_OFFSET   (2)
+/* If we map an intr to pin X, GIC will actually generate vector X+1 */
+#define GIC_PIN_TO_VEC_OFFSET   (1)
+
 #define GIC_EXT_INTR(x)                x
 
 /* External Interrupts used for IPI */
index c9420aa97e3232dc8b96ccf2c960e6d0aa8f1f00..e71ff4c317f2d0bdd8df430b0f439286abb4559f 100644 (file)
@@ -48,7 +48,7 @@
 #define CP0_VPECONF0           $1, 2
 #define CP0_VPECONF1           $1, 3
 #define CP0_YQMASK             $1, 4
-#define CP0_VPESCHEDULE        $1, 5
+#define CP0_VPESCHEDULE                $1, 5
 #define CP0_VPESCHEFBK         $1, 6
 #define CP0_TCSTATUS           $2, 1
 #define CP0_TCBIND             $2, 2
index 5d33621b5658f9c46314f4fcc1d2d123eaaf83d5..4f8ddba8c360050703d6d760b5909e92944e8b23 100644 (file)
@@ -22,7 +22,7 @@ struct task_struct;
  * switch_to(n) should switch tasks to task nr n, first
  * checking that n isn't the current task, in which case it does nothing.
  */
-extern asmlinkage void *resume(void *last, void *next, void *next_ti);
+extern asmlinkage void *resume(void *last, void *next, void *next_ti, u32 __usedfpu);
 
 extern unsigned int ll_bit;
 extern struct task_struct *ll_task;
@@ -66,11 +66,13 @@ do {                                                                        \
 
 #define switch_to(prev, next, last)                                    \
 do {                                                                   \
+       u32 __usedfpu;                                                  \
        __mips_mt_fpaff_switch_to(prev);                                \
        if (cpu_has_dsp)                                                \
                __save_dsp(prev);                                       \
        __clear_software_ll_bit();                                      \
-       (last) = resume(prev, next, task_thread_info(next));            \
+       __usedfpu = test_and_clear_tsk_thread_flag(prev, TIF_USEDFPU);  \
+       (last) = resume(prev, next, task_thread_info(next), __usedfpu); \
 } while (0)
 
 #define finish_arch_switch(prev)                                       \
index e2eca7d1059800e22704b467ab4f94f955df27c0..ca97e0ecb64b5054195b7d271017fa2760b7d05a 100644 (file)
@@ -60,6 +60,8 @@ struct thread_info {
 register struct thread_info *__current_thread_info __asm__("$28");
 #define current_thread_info()  __current_thread_info
 
+#endif /* !__ASSEMBLY__ */
+
 /* thread information allocation */
 #if defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_32BIT)
 #define THREAD_SIZE_ORDER (1)
@@ -85,8 +87,6 @@ register struct thread_info *__current_thread_info __asm__("$28");
 
 #define STACK_WARN     (THREAD_SIZE / 8)
 
-#endif /* !__ASSEMBLY__ */
-
 #define PREEMPT_ACTIVE         0x10000000
 
 /*
index 6ae7ce4ac63eb9b6a65ecf8ae0a49093579ae597..f4630e1082ab676a96e052e504995e86716be012 100644 (file)
@@ -4,7 +4,7 @@
  * Copyright (C) xxxx  the Anonymous
  * Copyright (C) 1994 - 2006 Ralf Baechle
  * Copyright (C) 2003, 2004  Maciej W. Rozycki
- * Copyright (C) 2001, 2004  MIPS Inc.
+ * Copyright (C) 2001, 2004, 2011, 2012  MIPS Technologies, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -199,6 +199,7 @@ void __init check_wait(void)
                cpu_wait = rm7k_wait_irqoff;
                break;
 
+       case CPU_M14KC:
        case CPU_24K:
        case CPU_34K:
        case CPU_1004K:
@@ -810,6 +811,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
                c->cputype = CPU_5KC;
                __cpu_name[cpu] = "MIPS 5Kc";
                break;
+       case PRID_IMP_5KE:
+               c->cputype = CPU_5KE;
+               __cpu_name[cpu] = "MIPS 5KE";
+               break;
        case PRID_IMP_20KC:
                c->cputype = CPU_20KC;
                __cpu_name[cpu] = "MIPS 20Kc";
@@ -831,6 +836,10 @@ static inline void cpu_probe_mips(struct cpuinfo_mips *c, unsigned int cpu)
                c->cputype = CPU_74K;
                __cpu_name[cpu] = "MIPS 74Kc";
                break;
+       case PRID_IMP_M14KC:
+               c->cputype = CPU_M14KC;
+               __cpu_name[cpu] = "MIPS M14Kc";
+               break;
        case PRID_IMP_1004K:
                c->cputype = CPU_1004K;
                __cpu_name[cpu] = "MIPS 1004Kc";
index 57ba13edb03af10da20a9ce936645902d9f562c1..3fc1691110dc52f82e8ec1271054c1411c122658 100644 (file)
@@ -5,7 +5,7 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 1996, 97, 98, 99, 2000, 01, 03, 04, 05 by Ralf Baechle
+ * Copyright (C) 1996, 97, 98, 99, 2000, 01, 03, 04, 05, 12 by Ralf Baechle
  * Copyright (C) 1999, 2000, 01 Silicon Graphics, Inc.
  */
 #include <linux/interrupt.h>
@@ -34,6 +34,12 @@ EXPORT_SYMBOL(memmove);
 
 EXPORT_SYMBOL(kernel_thread);
 
+/*
+ * Functions that operate on entire pages.  Mostly used by memory management.
+ */
+EXPORT_SYMBOL(clear_page);
+EXPORT_SYMBOL(copy_page);
+
 /*
  * Userspace access stuff.
  */
index ce89c806170846a1ea2bbcf027598fae11028648..0441f54b2a6acc9ab27a0d229c1465a8e0fa5975 100644 (file)
@@ -31,7 +31,7 @@
 
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *                     struct thread_info *next_ti)
+ *                     struct thread_info *next_ti, int usedfpu)
  */
        .align  7
        LEAF(resume)
index f29099b104c497e5cb4b4a3d368a801fc6c60d05..eb5e394a4650bbe9f0814e51bc00e1b8523c57f1 100644 (file)
@@ -162,11 +162,6 @@ static unsigned int counters_total_to_per_cpu(unsigned int counters)
        return counters >> vpe_shift();
 }
 
-static unsigned int counters_per_cpu_to_total(unsigned int counters)
-{
-       return counters << vpe_shift();
-}
-
 #else /* !CONFIG_MIPS_MT_SMP */
 #define vpe_id()       0
 
index 293898391e674bd0979f87918a019b3a377d575d..9c51be5a163a9249efa3bd74f12be62b64eba923 100644 (file)
@@ -43,7 +43,7 @@
 
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *                     struct thread_info *next_ti)
+ *                     struct thread_info *next_ti, int usedfpu)
  */
 LEAF(resume)
        mfc0    t1, CP0_STATUS
@@ -51,18 +51,9 @@ LEAF(resume)
        cpu_save_nonscratch a0
        sw      ra, THREAD_REG31(a0)
 
-       /*
-        * check if we need to save FPU registers
-        */
-       lw      t3, TASK_THREAD_INFO(a0)
-       lw      t0, TI_FLAGS(t3)
-       li      t1, _TIF_USEDFPU
-       and     t2, t0, t1
-       beqz    t2, 1f
-       nor     t1, zero, t1
+       beqz    a3, 1f
 
-       and     t0, t0, t1
-       sw      t0, TI_FLAGS(t3)
+       PTR_L   t3, TASK_THREAD_INFO(a0)
 
        /*
         * clear saved user stack CU1 bit
index 9414f935446968069ec4f22daed1ae19b0799fb7..42d2a3938420df28e64d1f016459529b13991b7e 100644 (file)
@@ -41,7 +41,7 @@
 
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
- *                     struct thread_info *next_ti)
+ *                     struct thread_info *next_ti, int usedfpu)
  */
        .align  5
        LEAF(resume)
        /*
         * check if we need to save FPU registers
         */
-       PTR_L   t3, TASK_THREAD_INFO(a0)
-       LONG_L  t0, TI_FLAGS(t3)
-       li      t1, _TIF_USEDFPU
-       and     t2, t0, t1
-       beqz    t2, 1f
-       nor     t1, zero, t1
 
-       and     t0, t0, t1
-       LONG_S  t0, TI_FLAGS(t3)
+       beqz    a3, 1f
 
+       PTR_L   t3, TASK_THREAD_INFO(a0)
        /*
         * clear saved user stack CU1 bit
         */
index 3046e2986006b448c884bbb7355a676cc63e6ad9..8e393b8443f7ae4aa8c4b8a99eb1f689e49957c1 100644 (file)
@@ -15,7 +15,6 @@
 #include <linux/smp.h>
 #include <linux/interrupt.h>
 #include <linux/spinlock.h>
-#include <linux/init.h>
 #include <linux/cpu.h>
 #include <linux/cpumask.h>
 #include <linux/reboot.h>
@@ -197,13 +196,6 @@ static void bmips_init_secondary(void)
 
        write_c0_brcm_action(ACTION_CLR_IPI(smp_processor_id(), 0));
 #endif
-
-       /* make sure there won't be a timer interrupt for a little while */
-       write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ);
-
-       irq_enable_hazard();
-       set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ1 | IE_IRQ5 | ST0_IE);
-       irq_enable_hazard();
 }
 
 /*
@@ -212,6 +204,13 @@ static void bmips_init_secondary(void)
 static void bmips_smp_finish(void)
 {
        pr_info("SMP: CPU%d is running\n", smp_processor_id());
+
+       /* make sure there won't be a timer interrupt for a little while */
+       write_c0_compare(read_c0_count() + mips_hpt_frequency / HZ);
+
+       irq_enable_hazard();
+       set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ1 | IE_IRQ5 | ST0_IE);
+       irq_enable_hazard();
 }
 
 /*
index 48650c8180401aeb1ce1c3f2713471d9c6e45536..1268392f1d2786bc3abb91fdb9a88ad84fa85ec9 100644 (file)
@@ -122,13 +122,21 @@ asmlinkage __cpuinit void start_secondary(void)
 
        notify_cpu_starting(cpu);
 
-       mp_ops->smp_finish();
+       set_cpu_online(cpu, true);
+
        set_cpu_sibling_map(cpu);
 
        cpu_set(cpu, cpu_callin_map);
 
        synchronise_count_slave();
 
+       /*
+        * irq will be enabled in ->smp_finish(), enabling it too early
+        * is dangerous.
+        */
+       WARN_ON_ONCE(!irqs_disabled());
+       mp_ops->smp_finish();
+
        cpu_idle();
 }
 
@@ -196,8 +204,6 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
        while (!cpu_isset(cpu, cpu_callin_map))
                udelay(100);
 
-       set_cpu_online(cpu, true);
-
        return 0;
 }
 
index f5dd38f1d0152b49b13c971c59fde0cd218cb93e..15b5f3cfd20c48b9424dd5364d29cf1aeff77d4a 100644 (file)
@@ -322,7 +322,7 @@ int __init smtc_build_cpu_map(int start_cpu_slot)
 
 /*
  * Common setup before any secondaries are started
- * Make sure all CPU's are in a sensible state before we boot any of the
+ * Make sure all CPUs are in a sensible state before we boot any of the
  * secondaries.
  *
  * For MIPS MT "SMTC" operation, we set up all TCs, spread as evenly
@@ -340,12 +340,12 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)
        /*
         * TCContext gets an offset from the base of the IPIQ array
         * to be used in low-level code to detect the presence of
-        * an active IPI queue
+        * an active IPI queue.
         */
        write_tc_c0_tccontext((sizeof(struct smtc_ipi_q) * cpu) << 16);
        /* Bind tc to vpe */
        write_tc_c0_tcbind(vpe);
-       /* In general, all TCs should have the same cpu_data indications */
+       /* In general, all TCs should have the same cpu_data indications. */
        memcpy(&cpu_data[cpu], &cpu_data[0], sizeof(struct cpuinfo_mips));
        /* For 34Kf, start with TC/CPU 0 as sole owner of single FPU context */
        if (cpu_data[0].cputype == CPU_34K ||
@@ -358,8 +358,8 @@ static void smtc_tc_setup(int vpe, int tc, int cpu)
 }
 
 /*
- * Tweak to get Count registes in as close a sync as possible.
- * Value seems good for 34K-class cores.
+ * Tweak to get Count registes in as close a sync as possible.  The
+ * value seems good for 34K-class cores.
  */
 
 #define CP0_SKEW 8
@@ -615,7 +615,6 @@ void __cpuinit smtc_boot_secondary(int cpu, struct task_struct *idle)
 
 void smtc_init_secondary(void)
 {
-       local_irq_enable();
 }
 
 void smtc_smp_finish(void)
@@ -631,6 +630,8 @@ void smtc_smp_finish(void)
        if (cpu > 0 && (cpu_data[cpu].vpe_id != cpu_data[cpu - 1].vpe_id))
                write_c0_compare(read_c0_count() + mips_hpt_frequency/HZ);
 
+       local_irq_enable();
+
        printk("TC %d going on-line as CPU %d\n",
                cpu_data[smp_processor_id()].tc_id, smp_processor_id());
 }
index 99f913c8d7a6eb3e4db9ac2f7b8def493a4e5e5e..842d55e411fd396479b611ba0a1c0c2af2d4cb92 100644 (file)
@@ -111,7 +111,6 @@ void __cpuinit synchronise_count_master(void)
 void __cpuinit synchronise_count_slave(void)
 {
        int i;
-       unsigned long flags;
        unsigned int initcount;
        int ncpus;
 
@@ -123,8 +122,6 @@ void __cpuinit synchronise_count_slave(void)
        return;
 #endif
 
-       local_irq_save(flags);
-
        /*
         * Not every cpu is online at the time this gets called,
         * so we first wait for the master to say everyone is ready
@@ -154,7 +151,5 @@ void __cpuinit synchronise_count_slave(void)
        }
        /* Arrange for an interrupt in a short while */
        write_c0_compare(read_c0_count() + COUNTON);
-
-       local_irq_restore(flags);
 }
 #undef NR_LOOPS
index 2d0c2a277f525b5b89b89500a5153c9032ed4ce3..c3c29354370345ae74c25dce1e4e7e7da9263316 100644 (file)
@@ -132,6 +132,9 @@ static void show_backtrace(struct task_struct *task, const struct pt_regs *regs)
        unsigned long ra = regs->regs[31];
        unsigned long pc = regs->cp0_epc;
 
+       if (!task)
+               task = current;
+
        if (raw_show_trace || !__kernel_text_address(pc)) {
                show_raw_backtrace(sp);
                return;
@@ -1249,6 +1252,7 @@ static inline void parity_protection_init(void)
                break;
 
        case CPU_5KC:
+       case CPU_5KE:
                write_c0_ecc(0x80000000);
                back_to_back_c0_hazard();
                /* Set the PE bit (bit 31) in the c0_errctl register. */
@@ -1498,6 +1502,7 @@ extern void flush_tlb_handlers(void);
  * Timer interrupt
  */
 int cp0_compare_irq;
+EXPORT_SYMBOL_GPL(cp0_compare_irq);
 int cp0_compare_irq_shift;
 
 /*
@@ -1597,7 +1602,7 @@ void __cpuinit per_cpu_trap_init(bool is_boot_cpu)
                        cp0_perfcount_irq = -1;
        } else {
                cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ;
-               cp0_compare_irq_shift = cp0_compare_irq;
+               cp0_compare_irq_shift = CP0_LEGACY_PERFCNT_IRQ;
                cp0_perfcount_irq = -1;
        }
 
index 924da5eb7031498ea93dc050a7492aa78f5bb0ec..df243a64f4305305564ec1e1e5b7f68c4c6e55ad 100644 (file)
@@ -1,5 +1,6 @@
 #include <asm/asm-offsets.h>
 #include <asm/page.h>
+#include <asm/thread_info.h>
 #include <asm-generic/vmlinux.lds.h>
 
 #undef mips
@@ -72,7 +73,7 @@ SECTIONS
        .data : {       /* Data */
                . = . + DATAOFFSET;             /* for CONFIG_MAPPED_KERNEL */
 
-               INIT_TASK_DATA(PAGE_SIZE)
+               INIT_TASK_DATA(THREAD_SIZE)
                NOSAVE_DATA
                CACHELINE_ALIGNED_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
                READ_MOSTLY_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
index 4aa20280613ea3954db6e7925cc2fead924b0b78..fd6203f14f1fbfb8e608606235f77f3dd3113272 100644 (file)
@@ -3,8 +3,8 @@
 #
 
 obj-y                          += cache.o dma-default.o extable.o fault.o \
-                                  gup.o init.o mmap.o page.o tlbex.o \
-                                  tlbex-fault.o uasm.o
+                                  gup.o init.o mmap.o page.o page-funcs.o \
+                                  tlbex.o tlbex-fault.o uasm.o
 
 obj-$(CONFIG_32BIT)            += ioremap.o pgtable-32.o
 obj-$(CONFIG_64BIT)            += pgtable-64.o
index 5109be96d98d099ec8509dd1de6a9048f5c4b82d..f092c265dc6360a89403ac62c184b7f4ab417437 100644 (file)
@@ -977,7 +977,7 @@ static void __cpuinit probe_pcache(void)
                        c->icache.linesz = 2 << lsize;
                else
                        c->icache.linesz = lsize;
-               c->icache.sets = 64 << ((config1 >> 22) & 7);
+               c->icache.sets = 32 << (((config1 >> 22) + 1) & 7);
                c->icache.ways = 1 + ((config1 >> 16) & 7);
 
                icache_size = c->icache.sets *
@@ -997,7 +997,7 @@ static void __cpuinit probe_pcache(void)
                        c->dcache.linesz = 2 << lsize;
                else
                        c->dcache.linesz= lsize;
-               c->dcache.sets = 64 << ((config1 >> 13) & 7);
+               c->dcache.sets = 32 << (((config1 >> 13) + 1) & 7);
                c->dcache.ways = 1 + ((config1 >> 7) & 7);
 
                dcache_size = c->dcache.sets *
@@ -1051,6 +1051,7 @@ static void __cpuinit probe_pcache(void)
        case CPU_R14000:
                break;
 
+       case CPU_M14KC:
        case CPU_24K:
        case CPU_34K:
        case CPU_74K:
diff --git a/arch/mips/mm/page-funcs.S b/arch/mips/mm/page-funcs.S
new file mode 100644 (file)
index 0000000..48a6b38
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Micro-assembler generated clear_page/copy_page functions.
+ *
+ * Copyright (C) 2012  MIPS Technologies, Inc.
+ * Copyright (C) 2012  Ralf Baechle <ralf@linux-mips.org>
+ */
+#include <asm/asm.h>
+#include <asm/regdef.h>
+
+#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
+#define cpu_clear_page_function_name   clear_page_cpu
+#define cpu_copy_page_function_name    copy_page_cpu
+#else
+#define cpu_clear_page_function_name   clear_page
+#define cpu_copy_page_function_name    copy_page
+#endif
+
+/*
+ * Maximum sizes:
+ *
+ * R4000 128 bytes S-cache:            0x058 bytes
+ * R4600 v1.7:                         0x05c bytes
+ * R4600 v2.0:                         0x060 bytes
+ * With prefetching, 16 word strides   0x120 bytes
+ */
+EXPORT(__clear_page_start)
+LEAF(cpu_clear_page_function_name)
+1:     j       1b              /* Dummy, will be replaced. */
+       .space 288
+END(cpu_clear_page_function_name)
+EXPORT(__clear_page_end)
+
+/*
+ * Maximum sizes:
+ *
+ * R4000 128 bytes S-cache:            0x11c bytes
+ * R4600 v1.7:                         0x080 bytes
+ * R4600 v2.0:                         0x07c bytes
+ * With prefetching, 16 word strides   0x540 bytes
+ */
+EXPORT(__copy_page_start)
+LEAF(cpu_copy_page_function_name)
+1:     j       1b              /* Dummy, will be replaced. */
+       .space 1344
+END(cpu_copy_page_function_name)
+EXPORT(__copy_page_end)
index cc0b626858b3d0b6e34e5e510004083ce7bfba24..98f530e182163146ee4bba570edc2c3013236f31 100644 (file)
@@ -6,6 +6,7 @@
  * Copyright (C) 2003, 04, 05 Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 2007  Maciej W. Rozycki
  * Copyright (C) 2008  Thiemo Seufer
+ * Copyright (C) 2012  MIPS Technologies, Inc.
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -71,45 +72,6 @@ static struct uasm_reloc __cpuinitdata relocs[5];
 #define cpu_is_r4600_v1_x()    ((read_c0_prid() & 0xfffffff0) == 0x00002010)
 #define cpu_is_r4600_v2_x()    ((read_c0_prid() & 0xfffffff0) == 0x00002020)
 
-/*
- * Maximum sizes:
- *
- * R4000 128 bytes S-cache:            0x058 bytes
- * R4600 v1.7:                         0x05c bytes
- * R4600 v2.0:                         0x060 bytes
- * With prefetching, 16 word strides   0x120 bytes
- */
-
-static u32 clear_page_array[0x120 / 4];
-
-#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
-void clear_page_cpu(void *page) __attribute__((alias("clear_page_array")));
-#else
-void clear_page(void *page) __attribute__((alias("clear_page_array")));
-#endif
-
-EXPORT_SYMBOL(clear_page);
-
-/*
- * Maximum sizes:
- *
- * R4000 128 bytes S-cache:            0x11c bytes
- * R4600 v1.7:                         0x080 bytes
- * R4600 v2.0:                         0x07c bytes
- * With prefetching, 16 word strides   0x540 bytes
- */
-static u32 copy_page_array[0x540 / 4];
-
-#ifdef CONFIG_SIBYTE_DMA_PAGEOPS
-void
-copy_page_cpu(void *to, void *from) __attribute__((alias("copy_page_array")));
-#else
-void copy_page(void *to, void *from) __attribute__((alias("copy_page_array")));
-#endif
-
-EXPORT_SYMBOL(copy_page);
-
-
 static int pref_bias_clear_store __cpuinitdata;
 static int pref_bias_copy_load __cpuinitdata;
 static int pref_bias_copy_store __cpuinitdata;
@@ -282,10 +244,15 @@ static inline void __cpuinit build_clear_pref(u32 **buf, int off)
                }
 }
 
+extern u32 __clear_page_start;
+extern u32 __clear_page_end;
+extern u32 __copy_page_start;
+extern u32 __copy_page_end;
+
 void __cpuinit build_clear_page(void)
 {
        int off;
-       u32 *buf = (u32 *)&clear_page_array;
+       u32 *buf = &__clear_page_start;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
        int i;
@@ -356,17 +323,17 @@ void __cpuinit build_clear_page(void)
        uasm_i_jr(&buf, RA);
        uasm_i_nop(&buf);
 
-       BUG_ON(buf > clear_page_array + ARRAY_SIZE(clear_page_array));
+       BUG_ON(buf > &__clear_page_end);
 
        uasm_resolve_relocs(relocs, labels);
 
        pr_debug("Synthesized clear page handler (%u instructions).\n",
-                (u32)(buf - clear_page_array));
+                (u32)(buf - &__clear_page_start));
 
        pr_debug("\t.set push\n");
        pr_debug("\t.set noreorder\n");
-       for (i = 0; i < (buf - clear_page_array); i++)
-               pr_debug("\t.word 0x%08x\n", clear_page_array[i]);
+       for (i = 0; i < (buf - &__clear_page_start); i++)
+               pr_debug("\t.word 0x%08x\n", (&__clear_page_start)[i]);
        pr_debug("\t.set pop\n");
 }
 
@@ -427,7 +394,7 @@ static inline void build_copy_store_pref(u32 **buf, int off)
 void __cpuinit build_copy_page(void)
 {
        int off;
-       u32 *buf = (u32 *)&copy_page_array;
+       u32 *buf = &__copy_page_start;
        struct uasm_label *l = labels;
        struct uasm_reloc *r = relocs;
        int i;
@@ -595,21 +562,23 @@ void __cpuinit build_copy_page(void)
        uasm_i_jr(&buf, RA);
        uasm_i_nop(&buf);
 
-       BUG_ON(buf > copy_page_array + ARRAY_SIZE(copy_page_array));
+       BUG_ON(buf > &__copy_page_end);
 
        uasm_resolve_relocs(relocs, labels);
 
        pr_debug("Synthesized copy page handler (%u instructions).\n",
-                (u32)(buf - copy_page_array));
+                (u32)(buf - &__copy_page_start));
 
        pr_debug("\t.set push\n");
        pr_debug("\t.set noreorder\n");
-       for (i = 0; i < (buf - copy_page_array); i++)
-               pr_debug("\t.word 0x%08x\n", copy_page_array[i]);
+       for (i = 0; i < (buf - &__copy_page_start); i++)
+               pr_debug("\t.word 0x%08x\n", (&__copy_page_start)[i]);
        pr_debug("\t.set pop\n");
 }
 
 #ifdef CONFIG_SIBYTE_DMA_PAGEOPS
+extern void clear_page_cpu(void *page);
+extern void copy_page_cpu(void *to, void *from);
 
 /*
  * Pad descriptors to cacheline, since each is exclusively owned by a
index 0bc485b3cd606de49e62aff00c9fe611e3a90540..03eb0ef9158047b023ee87d8d5d0e45c67c1583f 100644 (file)
@@ -9,6 +9,7 @@
  * Copyright (C) 2005, 2007, 2008, 2009  Maciej W. Rozycki
  * Copyright (C) 2006  Ralf Baechle (ralf@linux-mips.org)
  * Copyright (C) 2008, 2009 Cavium Networks, Inc.
+ * Copyright (C) 2011  MIPS Technologies, Inc.
  *
  * ... and the days got worse and worse and now you see
  * I've gone completly out of my mind.
@@ -494,6 +495,7 @@ static void __cpuinit build_tlb_write_entry(u32 **p, struct uasm_label **l,
        case CPU_R14000:
        case CPU_4KC:
        case CPU_4KEC:
+       case CPU_M14KC:
        case CPU_SB1:
        case CPU_SB1A:
        case CPU_4KSC:
index bf80921f2f56c0b145e698fa2c673ff49c7c0636..284dea54faf5a9f629e9d2cab18121cc5db328c6 100644 (file)
@@ -241,8 +241,9 @@ void __init mips_pcibios_init(void)
                return;
        }
 
-       if (controller->io_resource->start < 0x00001000UL)      /* FIXME */
-               controller->io_resource->start = 0x00001000UL;
+       /* Change start address to avoid conflicts with ACPI and SMB devices */
+       if (controller->io_resource->start < 0x00002000UL)
+               controller->io_resource->start = 0x00002000UL;
 
        iomem_resource.end &= 0xfffffffffULL;                   /* 64 GB */
        ioport_resource.end = controller->io_resource->end;
@@ -253,7 +254,7 @@ void __init mips_pcibios_init(void)
 }
 
 /* Enable PCI 2.1 compatibility in PIIX4 */
-static void __init quirk_dlcsetup(struct pci_dev *dev)
+static void __devinit quirk_dlcsetup(struct pci_dev *dev)
 {
        u8 odlc, ndlc;
        (void) pci_read_config_byte(dev, 0x82, &odlc);
index b7f37d4982fab27b91213a83be7a178626b694cb..2e28f653f66d1b582b9d0ca89c389aaaa1b18ca8 100644 (file)
@@ -111,7 +111,7 @@ static void __init pci_clock_check(void)
        unsigned int __iomem *jmpr_p =
                (unsigned int *) ioremap(MALTA_JMPRS_REG, sizeof(unsigned int));
        int jmpr = (__raw_readl(jmpr_p) >> 2) & 0x07;
-       static const int pciclocks[] __initdata = {
+       static const int pciclocks[] __initconst = {
                33, 20, 25, 30, 12, 16, 37, 10
        };
        int pciclock = pciclocks[jmpr];
index acb677a1227cc043a364b8938e78d7bd911c64d3..b3df7c2aad1e144fe8be92584272b14aed53973f 100644 (file)
@@ -82,8 +82,10 @@ void __init prom_free_prom_memory(void)
 
 void xlp_mmu_init(void)
 {
+       /* enable extended TLB and Large Fixed TLB */
        write_c0_config6(read_c0_config6() | 0x24);
-       current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1;
+
+       /* set page mask of Fixed TLB in config7 */
        write_c0_config7(PM_DEFAULT_MASK >>
                (13 + (ffz(PM_DEFAULT_MASK >> 13) / 2)));
 }
@@ -100,6 +102,10 @@ void __init prom_init(void)
        nlm_common_ebase = read_c0_ebase() & (~((1 << 12) - 1));
 #ifdef CONFIG_SMP
        nlm_wakeup_secondary_cpus(0xffffffff);
+
+       /* update TLB size after waking up threads */
+       current_cpu_data.tlbsize = ((read_c0_config6() >> 16) & 0xffff) + 1;
+
        register_smp_ops(&nlm_smp_ops);
 #endif
 }
index d1f2d4c52d42d3a0e1e92f5605d81632eefc8aa6..b6e378211a2c940021fb2e7befb342b90b1b1777 100644 (file)
@@ -78,6 +78,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
 
        switch (current_cpu_type()) {
        case CPU_5KC:
+       case CPU_M14KC:
        case CPU_20KC:
        case CPU_24K:
        case CPU_25KF:
index baba3bcaa3c28100067a39d9e1a1132a5a8d02b4..4d80a856048d19261e3af077ff1ff5344b3b26d2 100644 (file)
@@ -322,6 +322,10 @@ static int __init mipsxx_init(void)
 
        op_model_mipsxx_ops.num_counters = counters;
        switch (current_cpu_type()) {
+       case CPU_M14KC:
+               op_model_mipsxx_ops.cpu_type = "mips/M14Kc";
+               break;
+
        case CPU_20KC:
                op_model_mipsxx_ops.cpu_type = "mips/20K";
                break;
index d5d4c018fb04c03f4ef6b1d26d05fd263ad4835e..0857ab8c3919750feb164b3649f60df502290312 100644 (file)
@@ -48,7 +48,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
        return 0;
 }
 
-static void __init loongson2e_nec_fixup(struct pci_dev *pdev)
+static void __devinit loongson2e_nec_fixup(struct pci_dev *pdev)
 {
        unsigned int val;
 
@@ -60,7 +60,7 @@ static void __init loongson2e_nec_fixup(struct pci_dev *pdev)
        pci_write_config_dword(pdev, 0xe4, 1 << 5);
 }
 
-static void __init loongson2e_686b_func0_fixup(struct pci_dev *pdev)
+static void __devinit loongson2e_686b_func0_fixup(struct pci_dev *pdev)
 {
        unsigned char c;
 
@@ -135,7 +135,7 @@ static void __init loongson2e_686b_func0_fixup(struct pci_dev *pdev)
        printk(KERN_INFO"via686b fix: ISA bridge done\n");
 }
 
-static void __init loongson2e_686b_func1_fixup(struct pci_dev *pdev)
+static void __devinit loongson2e_686b_func1_fixup(struct pci_dev *pdev)
 {
        printk(KERN_INFO"via686b fix: IDE\n");
 
@@ -168,19 +168,19 @@ static void __init loongson2e_686b_func1_fixup(struct pci_dev *pdev)
        printk(KERN_INFO"via686b fix: IDE done\n");
 }
 
-static void __init loongson2e_686b_func2_fixup(struct pci_dev *pdev)
+static void __devinit loongson2e_686b_func2_fixup(struct pci_dev *pdev)
 {
        /* irq routing */
        pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 10);
 }
 
-static void __init loongson2e_686b_func3_fixup(struct pci_dev *pdev)
+static void __devinit loongson2e_686b_func3_fixup(struct pci_dev *pdev)
 {
        /* irq routing */
        pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, 11);
 }
 
-static void __init loongson2e_686b_func5_fixup(struct pci_dev *pdev)
+static void __devinit loongson2e_686b_func5_fixup(struct pci_dev *pdev)
 {
        unsigned int val;
        unsigned char c;
index 4b9768d5d72948b200d7431b4754fb7c21a27bc9..a7b917dcf604bde1ee359b20fb203356c0e4a84e 100644 (file)
@@ -96,21 +96,21 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
 }
 
 /* CS5536 SPEC. fixup */
-static void __init loongson_cs5536_isa_fixup(struct pci_dev *pdev)
+static void __devinit loongson_cs5536_isa_fixup(struct pci_dev *pdev)
 {
        /* the uart1 and uart2 interrupt in PIC is enabled as default */
        pci_write_config_dword(pdev, PCI_UART1_INT_REG, 1);
        pci_write_config_dword(pdev, PCI_UART2_INT_REG, 1);
 }
 
-static void __init loongson_cs5536_ide_fixup(struct pci_dev *pdev)
+static void __devinit loongson_cs5536_ide_fixup(struct pci_dev *pdev)
 {
        /* setting the mutex pin as IDE function */
        pci_write_config_dword(pdev, PCI_IDE_CFG_REG,
                               CS5536_IDE_FLASH_SIGNATURE);
 }
 
-static void __init loongson_cs5536_acc_fixup(struct pci_dev *pdev)
+static void __devinit loongson_cs5536_acc_fixup(struct pci_dev *pdev)
 {
        /* enable the AUDIO interrupt in PIC  */
        pci_write_config_dword(pdev, PCI_ACC_INT_REG, 1);
@@ -118,14 +118,14 @@ static void __init loongson_cs5536_acc_fixup(struct pci_dev *pdev)
        pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xc0);
 }
 
-static void __init loongson_cs5536_ohci_fixup(struct pci_dev *pdev)
+static void __devinit loongson_cs5536_ohci_fixup(struct pci_dev *pdev)
 {
        /* enable the OHCI interrupt in PIC */
        /* THE OHCI, EHCI, UDC, OTG are shared with interrupt in PIC */
        pci_write_config_dword(pdev, PCI_OHCI_INT_REG, 1);
 }
 
-static void __init loongson_cs5536_ehci_fixup(struct pci_dev *pdev)
+static void __devinit loongson_cs5536_ehci_fixup(struct pci_dev *pdev)
 {
        u32 hi, lo;
 
@@ -137,7 +137,7 @@ static void __init loongson_cs5536_ehci_fixup(struct pci_dev *pdev)
        pci_write_config_dword(pdev, PCI_EHCI_FLADJ_REG, 0x2000);
 }
 
-static void __init loongson_nec_fixup(struct pci_dev *pdev)
+static void __devinit loongson_nec_fixup(struct pci_dev *pdev)
 {
        unsigned int val;
 
index 0f48498bc231b074f1ec8b401e9660b29bf37e5c..70073c98ed320dc6f88f457028c8b9cd094e93ab 100644 (file)
@@ -49,10 +49,10 @@ int pcibios_plat_dev_init(struct pci_dev *dev)
        return 0;
 }
 
-static void __init malta_piix_func0_fixup(struct pci_dev *pdev)
+static void __devinit malta_piix_func0_fixup(struct pci_dev *pdev)
 {
        unsigned char reg_val;
-       static int piixirqmap[16] __initdata = {  /* PIIX PIRQC[A:D] irq mappings */
+       static int piixirqmap[16] __devinitdata = {  /* PIIX PIRQC[A:D] irq mappings */
                0,  0,  0,  3,
                4,  5,  6,  7,
                0,  9, 10, 11,
@@ -83,7 +83,7 @@ static void __init malta_piix_func0_fixup(struct pci_dev *pdev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
         malta_piix_func0_fixup);
 
-static void __init malta_piix_func1_fixup(struct pci_dev *pdev)
+static void __devinit malta_piix_func1_fixup(struct pci_dev *pdev)
 {
        unsigned char reg_val;
 
index e08f49cb6875abd65d50b7cb1cee964f816d96b7..8e4f8288eca2e2fcfc17bd615a26a5e0a6a152de 100644 (file)
 
 #include <asm/vr41xx/mpc30x.h>
 
-static const int internal_func_irqs[] __initdata = {
+static const int internal_func_irqs[] __initconst = {
        VRC4173_CASCADE_IRQ,
        VRC4173_AC97_IRQ,
        VRC4173_USB_IRQ,
 };
 
-static const int irq_tab_mpc30x[] __initdata = {
+static const int irq_tab_mpc30x[] __initconst = {
  [12] = VRC4173_PCMCIA1_IRQ,
  [13] = VRC4173_PCMCIA2_IRQ,
  [29] = MQ200_IRQ,
index f0bb9146e6c038424281cd45bb5b3ebc9dab0815..d02900a72916869dc39a03d0dd2075a5f8e85d82 100644 (file)
@@ -15,7 +15,7 @@
  * Set the BCM1250, etc. PCI host bridge's TRDY timeout
  * to the finite max.
  */
-static void __init quirk_sb1250_pci(struct pci_dev *dev)
+static void __devinit quirk_sb1250_pci(struct pci_dev *dev)
 {
        pci_write_config_byte(dev, 0x40, 0xff);
 }
@@ -25,7 +25,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_PCI,
 /*
  * The BCM1250, etc. PCI/HT bridge reports as a host bridge.
  */
-static void __init quirk_sb1250_ht(struct pci_dev *dev)
+static void __devinit quirk_sb1250_ht(struct pci_dev *dev)
 {
        dev->class = PCI_CLASS_BRIDGE_PCI << 8;
 }
@@ -35,7 +35,7 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_SIBYTE, PCI_DEVICE_ID_BCM1250_HT,
 /*
  * Set the SP1011 HT/PCI bridge's TRDY timeout to the finite max.
  */
-static void __init quirk_sp1011(struct pci_dev *dev)
+static void __devinit quirk_sp1011(struct pci_dev *dev)
 {
        pci_write_config_byte(dev, 0x64, 0xff);
 }
index a1e7e6d80c8c718e9b532e5ccb8ff0e7bac9e164..bc13e29d2bb34d6f9a257322e222b943da533c1c 100644 (file)
@@ -495,7 +495,7 @@ irqreturn_t tx4927_pcierr_interrupt(int irq, void *dev_id)
 }
 
 #ifdef CONFIG_TOSHIBA_FPCIB0
-static void __init tx4927_quirk_slc90e66_bridge(struct pci_dev *dev)
+static void __devinit tx4927_quirk_slc90e66_bridge(struct pci_dev *dev)
 {
        struct tx4927_pcic_reg __iomem *pcicptr = pci_bus_to_pcicptr(dev->bus);
 
index 0fbe4c0c170a25f5af0bd0da083a14c47e82e5f7..fdc24440294c7028c6fdf7e2a655b896dbe60ef7 100644 (file)
@@ -212,7 +212,7 @@ static inline void pci_enable_swapping(struct pci_dev *dev)
        bridge->b_widget.w_tflush;      /* Flush */
 }
 
-static void __init pci_fixup_ioc3(struct pci_dev *d)
+static void __devinit pci_fixup_ioc3(struct pci_dev *d)
 {
        pci_disable_swapping(d);
 }
index 1644805a6730db188bf9f26245c947551e8a4b5b..172af1cd58672e137924e88dae7f37dcf82393be 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/irq.h>
 #include <linux/irqdesc.h>
 #include <linux/console.h>
+#include <linux/pci_regs.h>
 
 #include <asm/io.h>
 
@@ -156,35 +157,55 @@ struct pci_controller nlm_pci_controller = {
        .io_offset      = 0x00000000UL,
 };
 
+/*
+ * The top level PCIe links on the XLS PCIe controller appear as
+ * bridges. Given a device, this function finds which link it is
+ * on.
+ */
+static struct pci_dev *xls_get_pcie_link(const struct pci_dev *dev)
+{
+       struct pci_bus *bus, *p;
+
+       /* Find the bridge on bus 0 */
+       bus = dev->bus;
+       for (p = bus->parent; p && p->number != 0; p = p->parent)
+               bus = p;
+
+       return p ? bus->self : NULL;
+}
+
 static int get_irq_vector(const struct pci_dev *dev)
 {
+       struct pci_dev *lnk;
+
        if (!nlm_chip_is_xls())
-               return  PIC_PCIX_IRQ;   /* for XLR just one IRQ*/
+               return  PIC_PCIX_IRQ;   /* for XLR just one IRQ */
 
        /*
         * For XLS PCIe, there is an IRQ per Link, find out which
         * link the device is on to assign interrupts
-       */
-       if (dev->bus->self == NULL)
+        */
+       lnk = xls_get_pcie_link(dev);
+       if (lnk == NULL)
                return 0;
 
-       switch  (dev->bus->self->devfn) {
-       case 0x0:
+       switch  (PCI_SLOT(lnk->devfn)) {
+       case 0:
                return PIC_PCIE_LINK0_IRQ;
-       case 0x8:
+       case 1:
                return PIC_PCIE_LINK1_IRQ;
-       case 0x10:
+       case 2:
                if (nlm_chip_is_xls_b())
                        return PIC_PCIE_XLSB0_LINK2_IRQ;
                else
                        return PIC_PCIE_LINK2_IRQ;
-       case 0x18:
+       case 3:
                if (nlm_chip_is_xls_b())
                        return PIC_PCIE_XLSB0_LINK3_IRQ;
                else
                        return PIC_PCIE_LINK3_IRQ;
        }
-       WARN(1, "Unexpected devfn %d\n", dev->bus->self->devfn);
+       WARN(1, "Unexpected devfn %d\n", lnk->devfn);
        return 0;
 }
 
@@ -202,7 +223,27 @@ void arch_teardown_msi_irq(unsigned int irq)
 int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
 {
        struct msi_msg msg;
+       struct pci_dev *lnk;
        int irq, ret;
+       u16 val;
+
+       /* MSI not supported on XLR */
+       if (!nlm_chip_is_xls())
+               return 1;
+
+       /*
+        * Enable MSI on the XLS PCIe controller bridge which was disabled
+        * at enumeration, the bridge MSI capability is at 0x50
+        */
+       lnk = xls_get_pcie_link(dev);
+       if (lnk == NULL)
+               return 1;
+
+       pci_read_config_word(lnk, 0x50 + PCI_MSI_FLAGS, &val);
+       if ((val & PCI_MSI_FLAGS_ENABLE) == 0) {
+               val |= PCI_MSI_FLAGS_ENABLE;
+               pci_write_config_word(lnk, 0x50 + PCI_MSI_FLAGS, val);
+       }
 
        irq = get_irq_vector(dev);
        if (irq <= 0)
@@ -327,7 +368,7 @@ static int __init pcibios_init(void)
                }
        } else {
                /* XLR PCI controller ACK */
-               irq_set_handler_data(PIC_PCIE_XLSB0_LINK3_IRQ, xlr_pci_ack);
+               irq_set_handler_data(PIC_PCIX_IRQ, xlr_pci_ack);
        }
 
        return 0;
index b71fae231049dfa86d25f3e5fef2216d968faa17..5edab2bc6fc0c3314d5925d2197781a7f563b4df 100644 (file)
@@ -115,11 +115,11 @@ static void yos_send_ipi_mask(const struct cpumask *mask, unsigned int action)
  */
 static void __cpuinit yos_init_secondary(void)
 {
-       set_c0_status(ST0_CO | ST0_IE | ST0_IM);
 }
 
 static void __cpuinit yos_smp_finish(void)
 {
+       set_c0_status(ST0_CO | ST0_IM | ST0_IE);
 }
 
 /* Hook for after all CPUs are online */
index 0a170e0ffeaae4ea84e0d5bfe1480203e69524be..7773f3d956b0cdc914ab82cb7c2fd79664c558f8 100644 (file)
@@ -28,7 +28,7 @@
 
 #define CALLIOPE_ADDR(x)       (CALLIOPE_IO_BASE + (x))
 
-const struct register_map calliope_register_map __initdata = {
+const struct register_map calliope_register_map __initconst = {
        .eic_slow0_strt_add = {.phys = CALLIOPE_ADDR(0x800000)},
        .eic_cfg_bits = {.phys = CALLIOPE_ADDR(0x800038)},
        .eic_ready_status = {.phys = CALLIOPE_ADDR(0x80004c)},
index bbc0c122be5ee34c3ece4cb2fdee9ddf8efef384..da076db7b7ed2fd572d6429231b370e381a10e69 100644 (file)
@@ -28,7 +28,7 @@
 
 #define CRONUS_ADDR(x) (CRONUS_IO_BASE + (x))
 
-const struct register_map cronus_register_map __initdata = {
+const struct register_map cronus_register_map __initconst = {
        .eic_slow0_strt_add = {.phys = CRONUS_ADDR(0x000000)},
        .eic_cfg_bits = {.phys = CRONUS_ADDR(0x000038)},
        .eic_ready_status = {.phys = CRONUS_ADDR(0x00004C)},
index 91dda682752ce25ece90b800a9103bb33cd80c86..47683b370e748da98a21860ce04424e8f8459b36 100644 (file)
@@ -23,7 +23,7 @@
 #include <linux/init.h>
 #include <asm/mach-powertv/asic.h>
 
-const struct register_map gaia_register_map __initdata = {
+const struct register_map gaia_register_map __initconst = {
        .eic_slow0_strt_add = {.phys = GAIA_IO_BASE + 0x000000},
        .eic_cfg_bits = {.phys = GAIA_IO_BASE + 0x000038},
        .eic_ready_status = {.phys = GAIA_IO_BASE + 0x00004C},
index 4a05bb096476a1ef7751f528c16d9ea9015827a9..6ff4b10f09dab4e4c3ba35242db83654315df0ab 100644 (file)
@@ -28,7 +28,7 @@
 
 #define ZEUS_ADDR(x)   (ZEUS_IO_BASE + (x))
 
-const struct register_map zeus_register_map __initdata = {
+const struct register_map zeus_register_map __initconst = {
        .eic_slow0_strt_add = {.phys = ZEUS_ADDR(0x000000)},
        .eic_cfg_bits = {.phys = ZEUS_ADDR(0x000038)},
        .eic_ready_status = {.phys = ZEUS_ADDR(0x00004c)},
index 682efb0c108d22576992c9f554653e9329916d3b..64eb71b1528032ea4af4f084fbbe9cf6c8d91216 100644 (file)
@@ -269,7 +269,7 @@ txx9_i8259_irq_setup(int irq)
        return err;
 }
 
-static void __init quirk_slc90e66_bridge(struct pci_dev *dev)
+static void __devinit quirk_slc90e66_bridge(struct pci_dev *dev)
 {
        int irq;        /* PCI/ISA Bridge interrupt */
        u8 reg_64;
index 090d35d369737599ec5c48f603ecba45c49797b3..e62c223e4c4594c3c06c762352d8e61a975e2d35 100644 (file)
@@ -876,9 +876,7 @@ static void __init smp_online(void)
 
        notify_cpu_starting(cpu);
 
-       ipi_call_lock();
        set_cpu_online(cpu, true);
-       ipi_call_unlock();
 
        local_irq_enable();
 }
index a47828d31fe6d0c4f8f5197a348c8fce64a827e6..6266730efd615552f71a9e9409932c2298001167 100644 (file)
@@ -300,9 +300,7 @@ smp_cpu_init(int cpunum)
 
        notify_cpu_starting(cpunum);
 
-       ipi_call_lock();
        set_cpu_online(cpunum, true);
-       ipi_call_unlock();
 
        /* Initialise the idle task for this CPU */
        atomic_inc(&init_mm.mm_count);
index 050cb371a69e6f6892e700c312fc02facd9a5e97..9a5d3cdc3e12f16e3dcbd2060e214dbc8ef23881 100644 (file)
@@ -653,7 +653,7 @@ config SBUS
 config FSL_SOC
        bool
        select HAVE_CAN_FLEXCAN if NET && CAN
-       select PPC_CLOCK if CAN_FLEXCAN
+       select PPC_CLOCK
 
 config FSL_PCI
        bool
index e5f26890a69e01e5a5f1c4a3008f9abb49060879..5416e28a753871ec02c75503e9583e8ff5abfbe9 100644 (file)
@@ -331,4 +331,13 @@ config STRICT_DEVMEM
 
          If you are unsure, say Y.
 
+config FAIL_IOMMU
+       bool "Fault-injection capability for IOMMU"
+       depends on FAULT_INJECTION
+       help
+         Provide fault-injection capability for IOMMU. Each device can
+         be selectively enabled via the fail_iommu property.
+
+         If you are unsure, say N.
+
 endmenu
index e8461cb18d0435e5716ae0ef098116d82ecb242f..b7d833382be4889e09e7b6e6e62402afb9dd2056 100644 (file)
@@ -62,26 +62,45 @@ libfdtheader := fdt.h libfdt.h libfdt_internal.h
 $(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o epapr.o): \
        $(addprefix $(obj)/,$(libfdtheader))
 
-src-wlib := string.S crt0.S crtsavres.S stdio.c main.c \
+src-wlib-y := string.S crt0.S crtsavres.S stdio.c main.c \
                $(libfdt) libfdt-wrapper.c \
                ns16550.c serial.c simple_alloc.c div64.S util.S \
-               gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
-               4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
-               cpm-serial.c stdlib.c mpc52xx-psc.c planetcore.c uartlite.c \
-               fsl-soc.c mpc8xx.c pq2.c ugecon.c
-src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c \
-               cuboot-ebony.c cuboot-hotfoot.c epapr.c treeboot-ebony.c \
-               prpmc2800.c \
-               ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \
-               cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c \
-               cuboot-bamboo.c cuboot-mpc7448hpc2.c cuboot-taishan.c \
-               fixed-head.S ep88xc.c ep405.c cuboot-c2k.c \
-               cuboot-katmai.c cuboot-rainier.c redboot-8xx.c ep8248e.c \
-               cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
-               virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c \
-               cuboot-acadia.c cuboot-amigaone.c cuboot-kilauea.c \
-               gamecube-head.S gamecube.c wii-head.S wii.c treeboot-iss4xx.c \
-               treeboot-currituck.c
+               gunzip_util.c elf_util.c $(zlib) devtree.c stdlib.c \
+               oflib.c ofconsole.c cuboot.c mpsc.c cpm-serial.c \
+               uartlite.c mpc52xx-psc.c
+src-wlib-$(CONFIG_40x) += 4xx.c planetcore.c
+src-wlib-$(CONFIG_44x) += 4xx.c ebony.c bamboo.c
+src-wlib-$(CONFIG_8xx) += mpc8xx.c planetcore.c
+src-wlib-$(CONFIG_PPC_82xx) += pq2.c fsl-soc.c planetcore.c
+src-wlib-$(CONFIG_EMBEDDED6xx) += mv64x60.c mv64x60_i2c.c ugecon.c
+
+src-plat-y := of.c
+src-plat-$(CONFIG_40x) += fixed-head.S ep405.c cuboot-hotfoot.c \
+                               treeboot-walnut.c cuboot-acadia.c \
+                               cuboot-kilauea.c simpleboot.c \
+                               virtex405-head.S virtex.c
+src-plat-$(CONFIG_44x) += treeboot-ebony.c cuboot-ebony.c treeboot-bamboo.c \
+                               cuboot-bamboo.c cuboot-sam440ep.c \
+                               cuboot-sequoia.c cuboot-rainier.c \
+                               cuboot-taishan.c cuboot-katmai.c \
+                               cuboot-warp.c cuboot-yosemite.c \
+                               treeboot-iss4xx.c treeboot-currituck.c \
+                               simpleboot.c fixed-head.S virtex.c
+src-plat-$(CONFIG_8xx) += cuboot-8xx.c fixed-head.S ep88xc.c redboot-8xx.c
+src-plat-$(CONFIG_PPC_MPC52xx) += cuboot-52xx.c
+src-plat-$(CONFIG_PPC_82xx) += cuboot-pq2.c fixed-head.S ep8248e.c cuboot-824x.c
+src-plat-$(CONFIG_PPC_83xx) += cuboot-83xx.c fixed-head.S redboot-83xx.c
+src-plat-$(CONFIG_FSL_SOC_BOOKE) += cuboot-85xx.c cuboot-85xx-cpm2.c
+src-plat-$(CONFIG_EMBEDDED6xx) += cuboot-pq2.c cuboot-mpc7448hpc2.c \
+                                       cuboot-c2k.c gamecube-head.S \
+                                       gamecube.c wii-head.S wii.c holly.c \
+                                       prpmc2800.c
+src-plat-$(CONFIG_AMIGAONE) += cuboot-amigaone.c
+src-plat-$(CONFIG_PPC_PS3) += ps3-head.S ps3-hvcall.S ps3.c
+src-plat-$(CONFIG_EPAPR_BOOT) += epapr.c
+
+src-wlib := $(sort $(src-wlib-y))
+src-plat := $(sort $(src-plat-y))
 src-boot := $(src-wlib) $(src-plat) empty.c
 
 src-boot := $(addprefix $(obj)/, $(src-boot))
@@ -257,7 +276,6 @@ image-$(CONFIG_TQM8548)                     += cuImage.tqm8548
 image-$(CONFIG_TQM8555)                        += cuImage.tqm8555
 image-$(CONFIG_TQM8560)                        += cuImage.tqm8560
 image-$(CONFIG_SBC8548)                        += cuImage.sbc8548
-image-$(CONFIG_SBC8560)                        += cuImage.sbc8560
 image-$(CONFIG_KSI8560)                        += cuImage.ksi8560
 
 # Board ports in arch/powerpc/platform/embedded6xx/Kconfig
@@ -412,4 +430,3 @@ $(wrapper-installed): $(DESTDIR)$(WRAPPER_BINDIR) $(srctree)/$(obj)/wrapper | $(
        $(call cmd,install_wrapper)
 
 $(obj)/bootwrapper_install: $(all-installed)
-
diff --git a/arch/powerpc/boot/dts/bsc9131rdb.dts b/arch/powerpc/boot/dts/bsc9131rdb.dts
new file mode 100644 (file)
index 0000000..e13d2d4
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * BSC9131 RDB Device Tree Source
+ *
+ * Copyright 2011-2012 Freescale Semiconductor Inc.
+ *
+ * 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/ "fsl/bsc9131si-pre.dtsi"
+
+/ {
+       model = "fsl,bsc9131rdb";
+       compatible = "fsl,bsc9131rdb";
+
+       memory {
+               device_type = "memory";
+       };
+
+       board_ifc: ifc: ifc@ff71e000 {
+               /* NAND Flash on board */
+               ranges = <0x0 0x0 0x0 0xff800000 0x00004000>;
+               reg = <0x0 0xff71e000 0x0 0x2000>;
+       };
+
+       board_soc: soc: soc@ff700000 {
+               ranges = <0x0 0x0 0xff700000 0x100000>;
+       };
+};
+
+/include/ "bsc9131rdb.dtsi"
+/include/ "fsl/bsc9131si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/bsc9131rdb.dtsi b/arch/powerpc/boot/dts/bsc9131rdb.dtsi
new file mode 100644 (file)
index 0000000..638adda
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * BSC9131 RDB Device Tree Source stub (no addresses or top-level ranges)
+ *
+ * Copyright 2011-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+&board_ifc {
+
+       nand@0,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,ifc-nand";
+               reg = <0x0 0x0 0x4000>;
+
+               partition@0 {
+                       /* This location must not be altered  */
+                       /* 3MB for u-boot Bootloader Image */
+                       reg = <0x0 0x00300000>;
+                       label = "NAND U-Boot Image";
+                       read-only;
+               };
+
+               partition@300000 {
+                       /* 1MB for DTB Image */
+                       reg = <0x00300000 0x00100000>;
+                       label = "NAND DTB Image";
+               };
+
+               partition@400000 {
+                       /* 8MB for Linux Kernel Image */
+                       reg = <0x00400000 0x00800000>;
+                       label = "NAND Linux Kernel Image";
+               };
+
+               partition@c00000 {
+                       /* Rest space for Root file System Image */
+                       reg = <0x00c00000 0x07400000>;
+                       label = "NAND RFS Image";
+               };
+       };
+};
+
+&board_soc {
+       /* BSC9131RDB does not have any device on i2c@3100 */
+       i2c@3100 {
+               status = "disabled";
+       };
+
+       spi@7000 {
+               flash@0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "spansion,s25sl12801";
+                       reg = <0>;
+                       spi-max-frequency = <50000000>;
+
+                       /* 512KB for u-boot Bootloader Image */
+                       partition@0 {
+                               reg = <0x0 0x00080000>;
+                               label = "SPI Flash U-Boot Image";
+                               read-only;
+                       };
+
+                       /* 512KB for DTB Image */
+                       partition@80000 {
+                               reg = <0x00080000 0x00080000>;
+                               label = "SPI Flash DTB Image";
+                       };
+
+                       /* 4MB for Linux Kernel Image */
+                       partition@100000 {
+                               reg = <0x00100000 0x00400000>;
+                               label = "SPI Flash Kernel Image";
+                       };
+
+                       /*11MB for RFS Image */
+                       partition@500000 {
+                               reg = <0x00500000 0x00B00000>;
+                               label = "SPI Flash RFS Image";
+                       };
+
+               };
+       };
+
+       usb@22000 {
+               phy_type = "ulpi";
+       };
+
+       mdio@24000 {
+               phy0: ethernet-phy@0 {
+                       interrupts = <3 1 0 0>;
+                       reg = <0x0>;
+               };
+
+               phy1: ethernet-phy@1 {
+                       interrupts = <2 1 0 0>;
+                       reg = <0x3>;
+               };
+       };
+
+       sdhci@2e000 {
+               status = "disabled";
+       };
+
+       enet0: ethernet@b0000 {
+               phy-handle = <&phy0>;
+               phy-connection-type = "rgmii-id";
+       };
+
+       enet1: ethernet@b1000 {
+               phy-handle = <&phy1>;
+               phy-connection-type = "rgmii-id";
+       };
+};
diff --git a/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi b/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi
new file mode 100644 (file)
index 0000000..5180d9d
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * BSC9131 Silicon/SoC Device Tree Source (post include)
+ *
+ * Copyright 2011-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+&ifc {
+       #address-cells = <2>;
+       #size-cells = <1>;
+       compatible = "fsl,ifc", "simple-bus";
+       interrupts = <16 2 0 0 20 2 0 0>;
+};
+
+&soc {
+       #address-cells = <1>;
+       #size-cells = <1>;
+       device_type = "soc";
+       compatible = "fsl,bsc9131-immr", "simple-bus";
+       bus-frequency = <0>;            // Filled out by uboot.
+
+       ecm-law@0 {
+               compatible = "fsl,ecm-law";
+               reg = <0x0 0x1000>;
+               fsl,num-laws = <12>;
+       };
+
+       ecm@1000 {
+               compatible = "fsl,bsc9131-ecm", "fsl,ecm";
+               reg = <0x1000 0x1000>;
+               interrupts = <16 2 0 0>;
+       };
+
+       memory-controller@2000 {
+               compatible = "fsl,bsc9131-memory-controller";
+               reg = <0x2000 0x1000>;
+               interrupts = <16 2 0 0>;
+       };
+
+/include/ "pq3-i2c-0.dtsi"
+       i2c@3000 {
+               interrupts = <17 2 0 0>;
+       };
+
+/include/ "pq3-i2c-1.dtsi"
+       i2c@3100 {
+               interrupts = <17 2 0 0>;
+       };
+
+/include/ "pq3-duart-0.dtsi"
+       serial0: serial@4500 {
+               interrupts = <18 2 0 0>;
+       };
+
+       serial1: serial@4600 {
+               interrupts = <18 2 0 0 >;
+       };
+/include/ "pq3-espi-0.dtsi"
+       spi0: spi@7000 {
+               fsl,espi-num-chipselects = <1>;
+               interrupts = <22 0x2 0 0>;
+       };
+
+/include/ "pq3-gpio-0.dtsi"
+       gpio-controller@f000 {
+               interrupts = <19 0x2 0 0>;
+               };
+
+       L2: l2-cache-controller@20000 {
+               compatible = "fsl,bsc9131-l2-cache-controller";
+               reg = <0x20000 0x1000>;
+               cache-line-size = <32>; // 32 bytes
+               cache-size = <0x40000>; // L2,256K
+               interrupts = <16 2 0 0>;
+       };
+
+/include/ "pq3-dma-0.dtsi"
+
+dma@21300 {
+
+       dma-channel@0 {
+               interrupts = <62 2 0 0>;
+       };
+
+       dma-channel@80 {
+               interrupts = <63 2 0 0>;
+       };
+
+       dma-channel@100 {
+               interrupts = <64 2 0 0>;
+       };
+
+       dma-channel@180 {
+               interrupts = <65 2 0 0>;
+       };
+};
+
+/include/ "pq3-usb2-dr-0.dtsi"
+usb@22000 {
+       compatible = "fsl-usb2-dr","fsl-usb2-dr-v2.2";
+       interrupts = <40 0x2 0 0>;
+};
+
+/include/ "pq3-esdhc-0.dtsi"
+       sdhc@2e000 {
+               fsl,sdhci-auto-cmd12;
+               interrupts = <41 0x2 0 0>;
+       };
+
+/include/ "pq3-sec4.4-0.dtsi"
+crypto@30000 {
+       interrupts       = <57 2 0 0>;
+
+       sec_jr0: jr@1000 {
+               interrupts       = <58 2 0 0>;
+       };
+
+       sec_jr1: jr@2000 {
+               interrupts       = <59 2 0 0>;
+       };
+
+       sec_jr2: jr@3000 {
+               interrupts       = <60 2 0 0>;
+       };
+
+       sec_jr3: jr@4000 {
+               interrupts       = <61 2 0 0>;
+       };
+};
+
+/include/ "pq3-mpic.dtsi"
+
+timer@41100 {
+       compatible = "fsl,mpic-v1.2-msgr", "fsl,mpic-msg";
+       reg = <0x41400 0x200>;
+       interrupts = <
+               0xb0 2
+               0xb1 2
+               0xb2 2
+               0xb3 2>;
+};
+
+/include/ "pq3-etsec2-0.dtsi"
+enet0: ethernet@b0000 {
+       queue-group@b0000 {
+               fsl,rx-bit-map = <0xff>;
+               fsl,tx-bit-map = <0xff>;
+               interrupts = <26 2 0 0 27 2 0 0 28 2 0 0>;
+       };
+};
+
+/include/ "pq3-etsec2-1.dtsi"
+enet1: ethernet@b1000 {
+       queue-group@b1000 {
+               fsl,rx-bit-map = <0xff>;
+               fsl,tx-bit-map = <0xff>;
+               interrupts = <33 2 0 0 34 2 0 0 35 2 0 0>;
+       };
+};
+
+global-utilities@e0000 {
+               compatible = "fsl,bsc9131-guts";
+               reg = <0xe0000 0x1000>;
+               fsl,has-rstcr;
+       };
+};
diff --git a/arch/powerpc/boot/dts/fsl/bsc9131si-pre.dtsi b/arch/powerpc/boot/dts/fsl/bsc9131si-pre.dtsi
new file mode 100644 (file)
index 0000000..743e4ae
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * BSC9131 Silicon/SoC Device Tree Source (pre include)
+ *
+ * Copyright 2011-2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+/ {
+       compatible = "fsl,BSC9131";
+       #address-cells = <2>;
+       #size-cells = <2>;
+       interrupt-parent = <&mpic>;
+
+       aliases {
+               serial0 = &serial0;
+               ethernet0 = &enet0;
+               ethernet1 = &enet1;
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               PowerPC,BSC9131@0 {
+                       device_type = "cpu";
+                       compatible = "fsl,e500v2";
+                       reg = <0x0>;
+                       next-level-cache = <&L2>;
+               };
+       };
+};
index 4252ef85fb7a9689902e03865e8cd17e0225a01b..adb82fd9057f3ddba3861b3a1f5928fd7d5844c9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * P1021/P1012 Silicon/SoC Device Tree Source (post include)
  *
- * Copyright 2011 Freescale Semiconductor Inc.
+ * Copyright 2011-2012 Freescale Semiconductor Inc.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
                interrupt-parent = <&qeic>;
        };
 
+       ucc@2600 {
+               cell-index = <7>;
+               reg = <0x2600 0x200>;
+               interrupts = <42>;
+               interrupt-parent = <&qeic>;
+       };
+
+       ucc@2200 {
+               cell-index = <3>;
+               reg = <0x2200 0x200>;
+               interrupts = <34>;
+               interrupt-parent = <&qeic>;
+       };
+
        muram@10000 {
                #address-cells = <1>;
                #size-cells = <1>;
diff --git a/arch/powerpc/boot/dts/fsl/p3060si-post.dtsi b/arch/powerpc/boot/dts/fsl/p3060si-post.dtsi
deleted file mode 100644 (file)
index b3e5692..0000000
+++ /dev/null
@@ -1,302 +0,0 @@
-/*
- * P3060 Silicon/SoC Device Tree Source (post include)
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-&lbc {
-       compatible = "fsl,p3060-elbc", "fsl,elbc", "simple-bus";
-       interrupts = <25 2 0 0>;
-       #address-cells = <2>;
-       #size-cells = <1>;
-};
-
-/* controller at 0x200000 */
-&pci0 {
-       compatible = "fsl,p3060-pcie", "fsl,qoriq-pcie-v2.2";
-       device_type = "pci";
-       #size-cells = <2>;
-       #address-cells = <3>;
-       bus-range = <0x0 0xff>;
-       clock-frequency = <33333333>;
-       interrupts = <16 2 1 15>;
-       pcie@0 {
-               reg = <0 0 0 0 0>;
-               #interrupt-cells = <1>;
-               #size-cells = <2>;
-               #address-cells = <3>;
-               device_type = "pci";
-               interrupts = <16 2 1 15>;
-               interrupt-map-mask = <0xf800 0 0 7>;
-               interrupt-map = <
-                       /* IDSEL 0x0 */
-                       0000 0 0 1 &mpic 40 1 0 0
-                       0000 0 0 2 &mpic 1 1 0 0
-                       0000 0 0 3 &mpic 2 1 0 0
-                       0000 0 0 4 &mpic 3 1 0 0
-                       >;
-       };
-};
-
-/* controller at 0x201000 */
-&pci1 {
-       compatible = "fsl,p3060-pcie", "fsl,qoriq-pcie-v2.2";
-       device_type = "pci";
-       #size-cells = <2>;
-       #address-cells = <3>;
-       bus-range = <0 0xff>;
-       clock-frequency = <33333333>;
-       interrupts = <16 2 1 14>;
-       pcie@0 {
-               reg = <0 0 0 0 0>;
-               #interrupt-cells = <1>;
-               #size-cells = <2>;
-               #address-cells = <3>;
-               device_type = "pci";
-               interrupts = <16 2 1 14>;
-               interrupt-map-mask = <0xf800 0 0 7>;
-               interrupt-map = <
-                       /* IDSEL 0x0 */
-                       0000 0 0 1 &mpic 41 1 0 0
-                       0000 0 0 2 &mpic 5 1 0 0
-                       0000 0 0 3 &mpic 6 1 0 0
-                       0000 0 0 4 &mpic 7 1 0 0
-                       >;
-       };
-};
-
-&rio {
-       compatible = "fsl,srio";
-       interrupts = <16 2 1 11>;
-       #address-cells = <2>;
-       #size-cells = <2>;
-       fsl,srio-rmu-handle = <&rmu>;
-       ranges;
-
-       port1 {
-               #address-cells = <2>;
-               #size-cells = <2>;
-               cell-index = <1>;
-       };
-
-       port2 {
-               #address-cells = <2>;
-               #size-cells = <2>;
-               cell-index = <2>;
-       };
-};
-
-&dcsr {
-       #address-cells = <1>;
-       #size-cells = <1>;
-       compatible = "fsl,dcsr", "simple-bus";
-
-       dcsr-epu@0 {
-               compatible = "fsl,dcsr-epu";
-               interrupts = <52 2 0 0
-                             84 2 0 0
-                             85 2 0 0>;
-               reg = <0x0 0x1000>;
-       };
-       dcsr-npc {
-               compatible = "fsl,dcsr-npc";
-               reg = <0x1000 0x1000 0x1000000 0x8000>;
-       };
-       dcsr-nxc@2000 {
-               compatible = "fsl,dcsr-nxc";
-               reg = <0x2000 0x1000>;
-       };
-       dcsr-corenet {
-               compatible = "fsl,dcsr-corenet";
-               reg = <0x8000 0x1000 0xB0000 0x1000>;
-       };
-       dcsr-dpaa@9000 {
-               compatible = "fsl,p3060-dcsr-dpaa", "fsl,dcsr-dpaa";
-               reg = <0x9000 0x1000>;
-       };
-       dcsr-ocn@11000 {
-               compatible = "fsl,p3060-dcsr-ocn", "fsl,dcsr-ocn";
-               reg = <0x11000 0x1000>;
-       };
-       dcsr-ddr@12000 {
-               compatible = "fsl,dcsr-ddr";
-               dev-handle = <&ddr1>;
-               reg = <0x12000 0x1000>;
-       };
-       dcsr-nal@18000 {
-               compatible = "fsl,p3060-dcsr-nal", "fsl,dcsr-nal";
-               reg = <0x18000 0x1000>;
-       };
-       dcsr-rcpm@22000 {
-               compatible = "fsl,p3060-dcsr-rcpm", "fsl,dcsr-rcpm";
-               reg = <0x22000 0x1000>;
-       };
-       dcsr-cpu-sb-proxy@40000 {
-               compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
-               cpu-handle = <&cpu0>;
-               reg = <0x40000 0x1000>;
-       };
-       dcsr-cpu-sb-proxy@41000 {
-               compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
-               cpu-handle = <&cpu1>;
-               reg = <0x41000 0x1000>;
-       };
-       dcsr-cpu-sb-proxy@44000 {
-               compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
-               cpu-handle = <&cpu4>;
-               reg = <0x44000 0x1000>;
-       };
-       dcsr-cpu-sb-proxy@45000 {
-               compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
-               cpu-handle = <&cpu5>;
-               reg = <0x45000 0x1000>;
-       };
-       dcsr-cpu-sb-proxy@46000 {
-               compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
-               cpu-handle = <&cpu6>;
-               reg = <0x46000 0x1000>;
-       };
-       dcsr-cpu-sb-proxy@47000 {
-               compatible = "fsl,dcsr-e500mc-sb-proxy", "fsl,dcsr-cpu-sb-proxy";
-               cpu-handle = <&cpu7>;
-               reg = <0x47000 0x1000>;
-       };
-
-};
-
-&soc {
-       #address-cells = <1>;
-       #size-cells = <1>;
-       device_type = "soc";
-       compatible = "simple-bus";
-
-       soc-sram-error {
-               compatible = "fsl,soc-sram-error";
-               interrupts = <16 2 1 29>;
-       };
-
-       corenet-law@0 {
-               compatible = "fsl,corenet-law";
-               reg = <0x0 0x1000>;
-               fsl,num-laws = <32>;
-       };
-
-       ddr1: memory-controller@8000 {
-               compatible = "fsl,qoriq-memory-controller-v4.4", "fsl,qoriq-memory-controller";
-               reg = <0x8000 0x1000>;
-               interrupts = <16 2 1 23>;
-       };
-
-       cpc: l3-cache-controller@10000 {
-               compatible = "fsl,p3060-l3-cache-controller", "cache";
-               reg = <0x10000 0x1000
-                      0x11000 0x1000>;
-               interrupts = <16 2 1 27
-                             16 2 1 26>;
-       };
-
-       corenet-cf@18000 {
-               compatible = "fsl,corenet-cf";
-               reg = <0x18000 0x1000>;
-               interrupts = <16 2 1 31>;
-               fsl,ccf-num-csdids = <32>;
-               fsl,ccf-num-snoopids = <32>;
-       };
-
-       iommu@20000 {
-               compatible = "fsl,pamu-v1.0", "fsl,pamu";
-               reg = <0x20000 0x5000>;
-               interrupts = <
-                       24 2 0 0
-                       16 2 1 30>;
-       };
-
-/include/ "qoriq-rmu-0.dtsi"
-/include/ "qoriq-mpic.dtsi"
-
-       guts: global-utilities@e0000 {
-               compatible = "fsl,qoriq-device-config-1.0";
-               reg = <0xe0000 0xe00>;
-               fsl,has-rstcr;
-               #sleep-cells = <1>;
-               fsl,liodn-bits = <12>;
-       };
-
-       pins: global-utilities@e0e00 {
-               compatible = "fsl,qoriq-pin-control-1.0";
-               reg = <0xe0e00 0x200>;
-               #sleep-cells = <2>;
-       };
-
-       clockgen: global-utilities@e1000 {
-               compatible = "fsl,p3060-clockgen", "fsl,qoriq-clockgen-1.0";
-               reg = <0xe1000 0x1000>;
-               clock-frequency = <0>;
-       };
-
-       rcpm: global-utilities@e2000 {
-               compatible = "fsl,qoriq-rcpm-1.0";
-               reg = <0xe2000 0x1000>;
-               #sleep-cells = <1>;
-       };
-
-       sfp: sfp@e8000 {
-               compatible = "fsl,p3060-sfp", "fsl,qoriq-sfp-1.0";
-               reg        = <0xe8000 0x1000>;
-       };
-
-       serdes: serdes@ea000 {
-               compatible = "fsl,p3060-serdes";
-               reg        = <0xea000 0x1000>;
-       };
-
-/include/ "qoriq-dma-0.dtsi"
-/include/ "qoriq-dma-1.dtsi"
-/include/ "qoriq-espi-0.dtsi"
-       spi@110000 {
-               fsl,espi-num-chipselects = <4>;
-       };
-
-/include/ "qoriq-i2c-0.dtsi"
-/include/ "qoriq-i2c-1.dtsi"
-/include/ "qoriq-duart-0.dtsi"
-/include/ "qoriq-duart-1.dtsi"
-/include/ "qoriq-gpio-0.dtsi"
-/include/ "qoriq-usb2-mph-0.dtsi"
-       usb@210000 {
-               compatible = "fsl-usb2-mph-v2.2", "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
-       };
-/include/ "qoriq-usb2-dr-0.dtsi"
-       usb@211000 {
-               compatible = "fsl-usb2-dr-v2.2", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
-       };
-/include/ "qoriq-sec4.1-0.dtsi"
-};
diff --git a/arch/powerpc/boot/dts/fsl/p3060si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p3060si-pre.dtsi
deleted file mode 100644 (file)
index 00c8e70..0000000
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * P3060 Silicon/SoC Device Tree Source (pre include)
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/dts-v1/;
-/ {
-       compatible = "fsl,P3060";
-       #address-cells = <2>;
-       #size-cells = <2>;
-       interrupt-parent = <&mpic>;
-
-       aliases {
-               ccsr = &soc;
-               dcsr = &dcsr;
-
-               serial0 = &serial0;
-               serial1 = &serial1;
-               serial2 = &serial2;
-               serial3 = &serial3;
-               pci0 = &pci0;
-               pci1 = &pci1;
-               usb0 = &usb0;
-               usb1 = &usb1;
-               dma0 = &dma0;
-               dma1 = &dma1;
-               msi0 = &msi0;
-               msi1 = &msi1;
-               msi2 = &msi2;
-
-               crypto = &crypto;
-               sec_jr0 = &sec_jr0;
-               sec_jr1 = &sec_jr1;
-               sec_jr2 = &sec_jr2;
-               sec_jr3 = &sec_jr3;
-               rtic_a = &rtic_a;
-               rtic_b = &rtic_b;
-               rtic_c = &rtic_c;
-               rtic_d = &rtic_d;
-               sec_mon = &sec_mon;
-       };
-
-       cpus {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               cpu0: PowerPC,e500mc@0 {
-                       device_type = "cpu";
-                       reg = <0>;
-                       next-level-cache = <&L2_0>;
-                       L2_0: l2-cache {
-                               next-level-cache = <&cpc>;
-                       };
-               };
-               cpu1: PowerPC,e500mc@1 {
-                       device_type = "cpu";
-                       reg = <1>;
-                       next-level-cache = <&L2_1>;
-                       L2_1: l2-cache {
-                               next-level-cache = <&cpc>;
-                       };
-               };
-               cpu4: PowerPC,e500mc@4 {
-                       device_type = "cpu";
-                       reg = <4>;
-                       next-level-cache = <&L2_4>;
-                       L2_4: l2-cache {
-                               next-level-cache = <&cpc>;
-                       };
-               };
-               cpu5: PowerPC,e500mc@5 {
-                       device_type = "cpu";
-                       reg = <5>;
-                       next-level-cache = <&L2_5>;
-                       L2_5: l2-cache {
-                               next-level-cache = <&cpc>;
-                       };
-               };
-               cpu6: PowerPC,e500mc@6 {
-                       device_type = "cpu";
-                       reg = <6>;
-                       next-level-cache = <&L2_6>;
-                       L2_6: l2-cache {
-                               next-level-cache = <&cpc>;
-                       };
-               };
-               cpu7: PowerPC,e500mc@7 {
-                       device_type = "cpu";
-                       reg = <7>;
-                       next-level-cache = <&L2_7>;
-                       L2_7: l2-cache {
-                               next-level-cache = <&cpc>;
-                       };
-               };
-       };
-};
index ededaf5ac015e78b2fc269b4151b919ce5552497..d72fb5e219d08c2b67423449d85012c518733d23 100644 (file)
                                interrupt-parent = <&PIC>;
                                usb-clock = <5>;
                        };
+                       spi@11aa0 {
+                               cell-index = <0>;
+                               compatible = "fsl,spi", "fsl,cpm2-spi";
+                               reg = <0x11a80 0x40 0x89fc 0x2>;
+                               interrupts = <2 8>;
+                               interrupt-parent = <&PIC>;
+                               gpios = < &cpm2_pio_d 19 0>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               ds3106@1 {
+                                       compatible = "gen,spidev";
+                                       reg = <0>;
+                                       spi-max-frequency = <8000000>;
+                               };
+                       };
+
+               };
+
+               cpm2_pio_d: gpio-controller@10d60 {
+                       #gpio-cells = <2>;
+                       compatible = "fsl,cpm2-pario-bank";
+                       reg = <0x10d60 0x14>;
+                       gpio-controller;
                };
 
                cpm2_pio_c: gpio-controller@10d40 {
index cc46dbd9746d7a1bac21ce42e80e1b3157a51081..d304a2d68c62bfee4faef2d4a85f2e13aabec5bf 100644 (file)
                        reg = <1>;
                        device_type = "ethernet-phy";
                };
+               sgmii_phy0: sgmii-phy@0 {
+                       interrupts = <6 1 0 0>;
+                       reg = <0x1d>;
+               };
+               sgmii_phy1: sgmii-phy@1 {
+                       interrupts = <6 1 0 0>;
+                       reg = <0x1c>;
+               };
                tbi0: tbi-phy@11 {
                        reg = <0x11>;
                        device_type = "tbi-phy";
index 270f64b90f4e4834145bce8faeb1f008dcad2290..77ebc9f1d37ca9ff91151dbaff1aaef3f9d9d4f9 100644 (file)
                        device_type = "ethernet-phy";
                };
 
+               sgmii_phy0: sgmii-phy@0 {
+                       interrupts = <6 1 0 0>;
+                       reg = <0x1c>;
+               };
+               sgmii_phy1: sgmii-phy@1 {
+                       interrupts = <6 1 0 0>;
+                       reg = <0x1d>;
+               };
+
                tbi0: tbi-phy@11 {
                        reg = <0x11>;
                        device_type = "tbi-phy";
index 14178944e2209ef5308791608fac988d977ea547..357490bb84dad8e1a1a08b3f284d0522ec486c67 100644 (file)
                        reg = <0x3>;
                };
 
+               sgmii_phy0: sgmii-phy@0 {
+                       interrupts = <6 1 0 0>;
+                       reg = <0x1c>;
+               };
+               sgmii_phy1: sgmii-phy@1 {
+                       interrupts = <6 1 0 0>;
+                       reg = <0x1d>;
+               };
+               sgmii_phy2: sgmii-phy@2 {
+                       interrupts = <7 1 0 0>;
+                       reg = <0x1e>;
+               };
+               sgmii_phy3: sgmii-phy@3 {
+                       interrupts = <7 1 0 0>;
+                       reg = <0x1f>;
+               };
+
                tbi0: tbi-phy@11 {
                        reg = <0x11>;
                        device_type = "tbi-phy";
index d34d12712125ea398e1d2fccfee5c8dce715bf8b..ef9ef56b3eebc06aa89d9c2457e03a642c2c3374 100644 (file)
                msi@41600 {
                        msi-available-ranges = <0 0x80>;
                        interrupts = <
-                               0xe0 0
-                               0xe1 0
-                               0xe2 0
-                               0xe3 0>;
+                               0xe0 0 0 0
+                               0xe1 0 0 0
+                               0xe2 0 0 0
+                               0xe3 0 0 0>;
                };
                timer@42100 {
                        status = "disabled";
index d6a8fafc0d0d5adf9dd69afe894ce734a939d8e2..24564ee108e5ca41edd2b87b2d37d3209d8a55dc 100644 (file)
@@ -67,9 +67,6 @@
                ethernet@24000 {
                        status = "disabled";
                };
-               mdio@24520 {
-                       status = "disabled";
-               };
                ptp_clock@24e00 {
                        status = "disabled";
                };
                msi@41600 {
                        msi-available-ranges = <0x80 0x80>;
                        interrupts = <
-                               0xe4 0
-                               0xe5 0
-                               0xe6 0
-                               0xe7 0>;
+                               0xe4 0 0 0
+                               0xe5 0 0 0
+                               0xe6 0 0 0
+                               0xe7 0 0 0>;
                };
                global-utilities@e0000 {
                        status = "disabled";
index 49776143a1b84874b515ecd164a384aface0f122..ec7c27a646711c176ba3cd1a51cf5d5e9b9d37b7 100644 (file)
 
 &board_soc {
        i2c@3000 {
+               eeprom@50 {
+                       compatible = "st,24c256";
+                       reg = <0x50>;
+               };
+
                rtc@68 {
                        compatible = "pericom,pt7c4338";
                        reg = <0x68>;
                };
        };
 
+       i2c@3100 {
+               eeprom@52 {
+                       compatible = "atmel,24c01";
+                       reg = <0x52>;
+               };
+       };
+
        spi@7000 {
                flash@0 {
                        #address-cells = <1>;
diff --git a/arch/powerpc/boot/dts/p1021rdb-pc.dtsi b/arch/powerpc/boot/dts/p1021rdb-pc.dtsi
new file mode 100644 (file)
index 0000000..c13abfb
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * P1021 RDB Device Tree Source stub (no addresses or top-level ranges)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+&lbc {
+       nor@0,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "cfi-flash";
+               reg = <0x0 0x0 0x1000000>;
+               bank-width = <2>;
+               device-width = <1>;
+
+               partition@0 {
+                       /* This location must not be altered  */
+                       /* 256KB for Vitesse 7385 Switch firmware */
+                       reg = <0x0 0x00040000>;
+                       label = "NOR Vitesse-7385 Firmware";
+                       read-only;
+               };
+
+               partition@40000 {
+                       /* 256KB for DTB Image */
+                       reg = <0x00040000 0x00040000>;
+                       label = "NOR DTB Image";
+               };
+
+               partition@80000 {
+                       /* 3.5 MB for Linux Kernel Image */
+                       reg = <0x00080000 0x00380000>;
+                       label = "NOR Linux Kernel Image";
+               };
+
+               partition@400000 {
+                       /* 11MB for JFFS2 based Root file System */
+                       reg = <0x00400000 0x00b00000>;
+                       label = "NOR JFFS2 Root File System";
+               };
+
+               partition@f00000 {
+                       /* This location must not be altered  */
+                       /* 512KB for u-boot Bootloader Image */
+                       /* 512KB for u-boot Environment Variables */
+                       reg = <0x00f00000 0x00100000>;
+                       label = "NOR U-Boot Image";
+               };
+       };
+
+       nand@1,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,p1021-fcm-nand",
+                            "fsl,elbc-fcm-nand";
+               reg = <0x1 0x0 0x40000>;
+
+               partition@0 {
+                       /* This location must not be altered  */
+                       /* 1MB for u-boot Bootloader Image */
+                       reg = <0x0 0x00100000>;
+                       label = "NAND U-Boot Image";
+                       read-only;
+               };
+
+               partition@100000 {
+                       /* 1MB for DTB Image */
+                       reg = <0x00100000 0x00100000>;
+                       label = "NAND DTB Image";
+               };
+
+               partition@200000 {
+                       /* 4MB for Linux Kernel Image */
+                       reg = <0x00200000 0x00400000>;
+                       label = "NAND Linux Kernel Image";
+               };
+
+               partition@600000 {
+                       /* 4MB for Compressed Root file System Image */
+                       reg = <0x00600000 0x00400000>;
+                       label = "NAND Compressed RFS Image";
+               };
+
+               partition@a00000 {
+                       /* 7MB for JFFS2 based Root file System */
+                       reg = <0x00a00000 0x00700000>;
+                       label = "NAND JFFS2 Root File System";
+               };
+
+               partition@1100000 {
+                       /* 15MB for User Writable Area  */
+                       reg = <0x01100000 0x00f00000>;
+                       label = "NAND Writable User area";
+               };
+       };
+
+       L2switch@2,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "vitesse-7385";
+               reg = <0x2 0x0 0x20000>;
+       };
+};
+
+&soc {
+       i2c@3000 {
+               rtc@68 {
+                       compatible = "pericom,pt7c4338";
+                       reg = <0x68>;
+               };
+       };
+
+       spi@7000 {
+               flash@0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "spansion,s25sl12801";
+                       reg = <0>;
+                       spi-max-frequency = <40000000>; /* input clock */
+
+                       partition@u-boot {
+                               /* 512KB for u-boot Bootloader Image */
+                               reg = <0x0 0x00080000>;
+                               label = "SPI Flash U-Boot Image";
+                               read-only;
+                       };
+
+                       partition@dtb {
+                               /* 512KB for DTB Image */
+                               reg = <0x00080000 0x00080000>;
+                               label = "SPI Flash DTB Image";
+                       };
+
+                       partition@kernel {
+                               /* 4MB for Linux Kernel Image */
+                               reg = <0x00100000 0x00400000>;
+                               label = "SPI Flash Linux Kernel Image";
+                       };
+
+                       partition@fs {
+                               /* 4MB for Compressed RFS Image */
+                               reg = <0x00500000 0x00400000>;
+                               label = "SPI Flash Compressed RFSImage";
+                       };
+
+                       partition@jffs-fs {
+                               /* 7MB for JFFS2 based RFS */
+                               reg = <0x00900000 0x00700000>;
+                               label = "SPI Flash JFFS2 RFS";
+                       };
+               };
+       };
+
+       usb@22000 {
+               phy_type = "ulpi";
+       };
+
+       mdio@24000 {
+               phy0: ethernet-phy@0 {
+                       interrupt-parent = <&mpic>;
+                       interrupts = <3 1 0 0>;
+                       reg = <0x0>;
+               };
+
+               phy1: ethernet-phy@1 {
+                       interrupt-parent = <&mpic>;
+                       interrupts = <2 1 0 0>;
+                       reg = <0x1>;
+               };
+
+               tbi0: tbi-phy@11 {
+                       reg = <0x11>;
+                       device_type = "tbi-phy";
+               };
+       };
+
+       mdio@25000 {
+               tbi1: tbi-phy@11 {
+                       reg = <0x11>;
+                       device_type = "tbi-phy";
+               };
+       };
+
+       mdio@26000 {
+               tbi2: tbi-phy@11 {
+                       reg = <0x11>;
+                       device_type = "tbi-phy";
+               };
+       };
+
+       enet0: ethernet@b0000 {
+               fixed-link = <1 1 1000 0 0>;
+               phy-connection-type = "rgmii-id";
+
+       };
+
+       enet1: ethernet@b1000 {
+               phy-handle = <&phy0>;
+               tbi-handle = <&tbi1>;
+               phy-connection-type = "sgmii";
+       };
+
+       enet2: ethernet@b2000 {
+               phy-handle = <&phy1>;
+               tbi-handle = <&tbi2>;
+               phy-connection-type = "rgmii-id";
+       };
+};
diff --git a/arch/powerpc/boot/dts/p1021rdb-pc_32b.dts b/arch/powerpc/boot/dts/p1021rdb-pc_32b.dts
new file mode 100644 (file)
index 0000000..7cefa12
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * P1021 RDB Device Tree Source
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1021si-pre.dtsi"
+/ {
+       model = "fsl,P1021RDB";
+       compatible = "fsl,P1021RDB-PC";
+
+       memory {
+               device_type = "memory";
+       };
+
+       lbc: localbus@ffe05000 {
+               reg = <0 0xffe05000 0 0x1000>;
+
+               /* NOR, NAND Flashes and Vitesse 5 port L2 switch */
+               ranges = <0x0 0x0 0x0 0xef000000 0x01000000
+                         0x1 0x0 0x0 0xff800000 0x00040000
+                         0x2 0x0 0x0 0xffb00000 0x00020000>;
+       };
+
+       soc: soc@ffe00000 {
+               ranges = <0x0 0x0 0xffe00000 0x100000>;
+       };
+
+       pci0: pcie@ffe09000 {
+               ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
+               reg = <0 0xffe09000 0 0x1000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xa0000000
+                                 0x2000000 0x0 0xa0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       pci1: pcie@ffe0a000 {
+               reg = <0 0xffe0a000 0 0x1000>;
+               ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0x80000000
+                                 0x2000000 0x0 0x80000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       qe: qe@ffe80000 {
+                ranges = <0x0 0x0 0xffe80000 0x40000>;
+                reg = <0 0xffe80000 0 0x480>;
+                brg-frequency = <0>;
+                bus-frequency = <0>;
+        };
+};
+
+/include/ "p1021rdb-pc.dtsi"
+/include/ "fsl/p1021si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1021rdb-pc_36b.dts b/arch/powerpc/boot/dts/p1021rdb-pc_36b.dts
new file mode 100644 (file)
index 0000000..53d0c88
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * P1021 RDB Device Tree Source (36-bit address map)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1021si-pre.dtsi"
+/ {
+       model = "fsl,P1021RDB";
+       compatible = "fsl,P1021RDB-PC";
+
+       memory {
+               device_type = "memory";
+       };
+
+       lbc: localbus@fffe05000 {
+               reg = <0xf 0xffe05000 0 0x1000>;
+
+               /* NOR, NAND Flashes and Vitesse 5 port L2 switch */
+               ranges = <0x0 0x0 0xf 0xef000000 0x01000000
+                         0x1 0x0 0xf 0xff800000 0x00040000
+                         0x2 0x0 0xf 0xffb00000 0x00020000>;
+       };
+
+       soc: soc@fffe00000 {
+               ranges = <0x0 0xf 0xffe00000 0x100000>;
+       };
+
+       pci0: pcie@fffe09000 {
+               ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
+               reg = <0xf 0xffe09000 0 0x1000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xa0000000
+                                 0x2000000 0x0 0xa0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       pci1: pcie@fffe0a000 {
+               reg = <0xf 0xffe0a000 0 0x1000>;
+               ranges = <0x2000000 0x0 0x80000000 0xc 0x00000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xc0000000
+                                 0x2000000 0x0 0xc0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       qe: qe@fffe80000 {
+                ranges = <0x0 0xf 0xffe80000 0x40000>;
+                reg = <0xf 0xffe80000 0 0x480>;
+                brg-frequency = <0>;
+                bus-frequency = <0>;
+        };
+};
+
+/include/ "p1021rdb-pc.dtsi"
+/include/ "fsl/p1021si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1021rdb.dts b/arch/powerpc/boot/dts/p1021rdb.dts
deleted file mode 100644 (file)
index 90b6b4c..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * P1021 RDB Device Tree Source
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/include/ "fsl/p1021si-pre.dtsi"
-/ {
-       model = "fsl,P1021RDB";
-       compatible = "fsl,P1021RDB-PC";
-
-       memory {
-               device_type = "memory";
-       };
-
-       lbc: localbus@ffe05000 {
-               reg = <0 0xffe05000 0 0x1000>;
-
-               /* NOR, NAND Flashes and Vitesse 5 port L2 switch */
-               ranges = <0x0 0x0 0x0 0xef000000 0x01000000
-                         0x1 0x0 0x0 0xff800000 0x00040000
-                         0x2 0x0 0x0 0xffb00000 0x00020000>;
-       };
-
-       soc: soc@ffe00000 {
-               ranges = <0x0 0x0 0xffe00000 0x100000>;
-       };
-
-       pci0: pcie@ffe09000 {
-               ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
-                         0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
-               reg = <0 0xffe09000 0 0x1000>;
-               pcie@0 {
-                       ranges = <0x2000000 0x0 0xa0000000
-                                 0x2000000 0x0 0xa0000000
-                                 0x0 0x20000000
-
-                                 0x1000000 0x0 0x0
-                                 0x1000000 0x0 0x0
-                                 0x0 0x100000>;
-               };
-       };
-
-       pci1: pcie@ffe0a000 {
-               reg = <0 0xffe0a000 0 0x1000>;
-               ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
-                         0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
-               pcie@0 {
-                       ranges = <0x2000000 0x0 0x80000000
-                                 0x2000000 0x0 0x80000000
-                                 0x0 0x20000000
-
-                                 0x1000000 0x0 0x0
-                                 0x1000000 0x0 0x0
-                                 0x0 0x100000>;
-               };
-       };
-
-       qe: qe@ffe80000 {
-                ranges = <0x0 0x0 0xffe80000 0x40000>;
-                reg = <0 0xffe80000 0 0x480>;
-                brg-frequency = <0>;
-                bus-frequency = <0>;
-        };
-};
-
-/include/ "p1021rdb.dtsi"
-/include/ "fsl/p1021si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1021rdb.dtsi b/arch/powerpc/boot/dts/p1021rdb.dtsi
deleted file mode 100644 (file)
index b973461..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * P1021 RDB Device Tree Source stub (no addresses or top-level ranges)
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-&lbc {
-       nor@0,0 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "cfi-flash";
-               reg = <0x0 0x0 0x1000000>;
-               bank-width = <2>;
-               device-width = <1>;
-
-               partition@0 {
-                       /* This location must not be altered  */
-                       /* 256KB for Vitesse 7385 Switch firmware */
-                       reg = <0x0 0x00040000>;
-                       label = "NOR Vitesse-7385 Firmware";
-                       read-only;
-               };
-
-               partition@40000 {
-                       /* 256KB for DTB Image */
-                       reg = <0x00040000 0x00040000>;
-                       label = "NOR DTB Image";
-               };
-
-               partition@80000 {
-                       /* 3.5 MB for Linux Kernel Image */
-                       reg = <0x00080000 0x00380000>;
-                       label = "NOR Linux Kernel Image";
-               };
-
-               partition@400000 {
-                       /* 11MB for JFFS2 based Root file System */
-                       reg = <0x00400000 0x00b00000>;
-                       label = "NOR JFFS2 Root File System";
-               };
-
-               partition@f00000 {
-                       /* This location must not be altered  */
-                       /* 512KB for u-boot Bootloader Image */
-                       /* 512KB for u-boot Environment Variables */
-                       reg = <0x00f00000 0x00100000>;
-                       label = "NOR U-Boot Image";
-               };
-       };
-
-       nand@1,0 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "fsl,p1021-fcm-nand",
-                            "fsl,elbc-fcm-nand";
-               reg = <0x1 0x0 0x40000>;
-
-               partition@0 {
-                       /* This location must not be altered  */
-                       /* 1MB for u-boot Bootloader Image */
-                       reg = <0x0 0x00100000>;
-                       label = "NAND U-Boot Image";
-                       read-only;
-               };
-
-               partition@100000 {
-                       /* 1MB for DTB Image */
-                       reg = <0x00100000 0x00100000>;
-                       label = "NAND DTB Image";
-               };
-
-               partition@200000 {
-                       /* 4MB for Linux Kernel Image */
-                       reg = <0x00200000 0x00400000>;
-                       label = "NAND Linux Kernel Image";
-               };
-
-               partition@600000 {
-                       /* 4MB for Compressed Root file System Image */
-                       reg = <0x00600000 0x00400000>;
-                       label = "NAND Compressed RFS Image";
-               };
-
-               partition@a00000 {
-                       /* 7MB for JFFS2 based Root file System */
-                       reg = <0x00a00000 0x00700000>;
-                       label = "NAND JFFS2 Root File System";
-               };
-
-               partition@1100000 {
-                       /* 15MB for User Writable Area  */
-                       reg = <0x01100000 0x00f00000>;
-                       label = "NAND Writable User area";
-               };
-       };
-
-       L2switch@2,0 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "vitesse-7385";
-               reg = <0x2 0x0 0x20000>;
-       };
-};
-
-&soc {
-       i2c@3000 {
-               rtc@68 {
-                       compatible = "pericom,pt7c4338";
-                       reg = <0x68>;
-               };
-       };
-
-       spi@7000 {
-               flash@0 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       compatible = "spansion,s25sl12801";
-                       reg = <0>;
-                       spi-max-frequency = <40000000>; /* input clock */
-
-                       partition@u-boot {
-                               /* 512KB for u-boot Bootloader Image */
-                               reg = <0x0 0x00080000>;
-                               label = "SPI Flash U-Boot Image";
-                               read-only;
-                       };
-
-                       partition@dtb {
-                               /* 512KB for DTB Image */
-                               reg = <0x00080000 0x00080000>;
-                               label = "SPI Flash DTB Image";
-                       };
-
-                       partition@kernel {
-                               /* 4MB for Linux Kernel Image */
-                               reg = <0x00100000 0x00400000>;
-                               label = "SPI Flash Linux Kernel Image";
-                       };
-
-                       partition@fs {
-                               /* 4MB for Compressed RFS Image */
-                               reg = <0x00500000 0x00400000>;
-                               label = "SPI Flash Compressed RFSImage";
-                       };
-
-                       partition@jffs-fs {
-                               /* 7MB for JFFS2 based RFS */
-                               reg = <0x00900000 0x00700000>;
-                               label = "SPI Flash JFFS2 RFS";
-                       };
-               };
-       };
-
-       usb@22000 {
-               phy_type = "ulpi";
-       };
-
-       mdio@24000 {
-               phy0: ethernet-phy@0 {
-                       interrupt-parent = <&mpic>;
-                       interrupts = <3 1 0 0>;
-                       reg = <0x0>;
-               };
-
-               phy1: ethernet-phy@1 {
-                       interrupt-parent = <&mpic>;
-                       interrupts = <2 1 0 0>;
-                       reg = <0x1>;
-               };
-
-               tbi0: tbi-phy@11 {
-                       reg = <0x11>;
-                       device_type = "tbi-phy";
-               };
-       };
-
-       mdio@25000 {
-               tbi1: tbi-phy@11 {
-                       reg = <0x11>;
-                       device_type = "tbi-phy";
-               };
-       };
-
-       mdio@26000 {
-               tbi2: tbi-phy@11 {
-                       reg = <0x11>;
-                       device_type = "tbi-phy";
-               };
-       };
-
-       enet0: ethernet@b0000 {
-               fixed-link = <1 1 1000 0 0>;
-               phy-connection-type = "rgmii-id";
-
-       };
-
-       enet1: ethernet@b1000 {
-               phy-handle = <&phy0>;
-               tbi-handle = <&tbi1>;
-               phy-connection-type = "sgmii";
-       };
-
-       enet2: ethernet@b2000 {
-               phy-handle = <&phy1>;
-               tbi-handle = <&tbi2>;
-               phy-connection-type = "rgmii-id";
-       };
-};
diff --git a/arch/powerpc/boot/dts/p1021rdb_36b.dts b/arch/powerpc/boot/dts/p1021rdb_36b.dts
deleted file mode 100644 (file)
index ea6d8b5..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * P1021 RDB Device Tree Source (36-bit address map)
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/include/ "fsl/p1021si-pre.dtsi"
-/ {
-       model = "fsl,P1021RDB";
-       compatible = "fsl,P1021RDB-PC";
-
-       memory {
-               device_type = "memory";
-       };
-
-       lbc: localbus@fffe05000 {
-               reg = <0xf 0xffe05000 0 0x1000>;
-
-               /* NOR, NAND Flashes and Vitesse 5 port L2 switch */
-               ranges = <0x0 0x0 0xf 0xef000000 0x01000000
-                         0x1 0x0 0xf 0xff800000 0x00040000
-                         0x2 0x0 0xf 0xffb00000 0x00020000>;
-       };
-
-       soc: soc@fffe00000 {
-               ranges = <0x0 0xf 0xffe00000 0x100000>;
-       };
-
-       pci0: pcie@fffe09000 {
-               ranges = <0x2000000 0x0 0xc0000000 0xc 0x20000000 0x0 0x20000000
-                         0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
-               reg = <0xf 0xffe09000 0 0x1000>;
-               pcie@0 {
-                       ranges = <0x2000000 0x0 0xa0000000
-                                 0x2000000 0x0 0xa0000000
-                                 0x0 0x20000000
-
-                                 0x1000000 0x0 0x0
-                                 0x1000000 0x0 0x0
-                                 0x0 0x100000>;
-               };
-       };
-
-       pci1: pcie@fffe0a000 {
-               reg = <0xf 0xffe0a000 0 0x1000>;
-               ranges = <0x2000000 0x0 0x80000000 0xc 0x00000000 0x0 0x20000000
-                         0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>;
-               pcie@0 {
-                       ranges = <0x2000000 0x0 0xc0000000
-                                 0x2000000 0x0 0xc0000000
-                                 0x0 0x20000000
-
-                                 0x1000000 0x0 0x0
-                                 0x1000000 0x0 0x0
-                                 0x0 0x100000>;
-               };
-       };
-
-       qe: qe@fffe80000 {
-                ranges = <0x0 0xf 0xffe80000 0x40000>;
-                reg = <0xf 0xffe80000 0 0x480>;
-                brg-frequency = <0>;
-                bus-frequency = <0>;
-        };
-};
-
-/include/ "p1021rdb.dtsi"
-/include/ "fsl/p1021si-post.dtsi"
index 7cdb505036bb5a02dc85e3bfd76ad1b94baa4154..c3344b04d8ff5f5aa52542f4c44299bbda851c30 100644 (file)
  */
 
 &board_lbc {
-       /*
-        * This node is used to access the pixis via "indirect" mode,
-        * which is done by writing the pixis register index to chip
-        * select 0 and the value to/from chip select 1.  Indirect
-        * mode is the only way to access the pixis when DIU video
-        * is enabled.  Note that this assumes that the first column
-        * of the 'ranges' property above is the chip select number.
-        */
-       board-control@0,0 {
-               compatible = "fsl,p1022ds-indirect-pixis";
-               reg = <0x0 0x0 1        /* CS0 */
-                      0x1 0x0 1>;      /* CS1 */
-               interrupt-parent = <&mpic>;
-               interrupts = <8 0 0 0>;
-       };
-
        nor@0,0 {
                #address-cells = <1>;
                #size-cells = <1>;
                         * the clock is enabled.
                         */
                };
+               rtc@68 {
+                       compatible = "dallas,ds1339";
+                       reg = <0x68>;
+               };
        };
 
        spi@7000 {
diff --git a/arch/powerpc/boot/dts/p1024rdb.dtsi b/arch/powerpc/boot/dts/p1024rdb.dtsi
new file mode 100644 (file)
index 0000000..b05dcb4
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * P1024 RDB Device Tree Source stub (no addresses or top-level ranges)
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+&lbc {
+       nor@0,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "cfi-flash";
+               reg = <0x0 0x0 0x1000000>;
+               bank-width = <2>;
+               device-width = <1>;
+
+               partition@0 {
+                       /* This location must not be altered  */
+                       /* 256KB for Vitesse 7385 Switch firmware */
+                       reg = <0x0 0x00040000>;
+                       label = "NOR Vitesse-7385 Firmware";
+                       read-only;
+               };
+
+               partition@40000 {
+                       /* 256KB for DTB Image */
+                       reg = <0x00040000 0x00040000>;
+                       label = "NOR DTB Image";
+               };
+
+               partition@80000 {
+                       /* 3.5 MB for Linux Kernel Image */
+                       reg = <0x00080000 0x00380000>;
+                       label = "NOR Linux Kernel Image";
+               };
+
+               partition@400000 {
+                       /* 11MB for JFFS2 based Root file System */
+                       reg = <0x00400000 0x00b00000>;
+                       label = "NOR JFFS2 Root File System";
+               };
+
+               partition@f00000 {
+                       /* This location must not be altered  */
+                       /* 512KB for u-boot Bootloader Image */
+                       /* 512KB for u-boot Environment Variables */
+                       reg = <0x00f00000 0x00100000>;
+                       label = "NOR U-Boot Image";
+                       read-only;
+               };
+       };
+
+       nand@1,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "fsl,p1020-fcm-nand",
+                                "fsl,elbc-fcm-nand";
+               reg = <0x1 0x0 0x40000>;
+
+               partition@0 {
+                       /* This location must not be altered  */
+                       /* 1MB for u-boot Bootloader Image */
+                       reg = <0x0 0x00100000>;
+                       label = "NAND U-Boot Image";
+                       read-only;
+               };
+
+               partition@100000 {
+                       /* 1MB for DTB Image */
+                       reg = <0x00100000 0x00100000>;
+                       label = "NAND DTB Image";
+               };
+
+               partition@200000 {
+                       /* 4MB for Linux Kernel Image */
+                       reg = <0x00200000 0x00400000>;
+                       label = "NAND Linux Kernel Image";
+               };
+
+               partition@600000 {
+                       /* 4MB for Compressed Root file System Image */
+                       reg = <0x00600000 0x00400000>;
+                       label = "NAND Compressed RFS Image";
+               };
+
+               partition@a00000 {
+                       /* 15MB for JFFS2 based Root file System */
+                       reg = <0x00a00000 0x00f00000>;
+                       label = "NAND JFFS2 Root File System";
+               };
+
+               partition@1900000 {
+                       /* 7MB for User Writable Area */
+                       reg = <0x01900000 0x00700000>;
+                       label = "NAND Writable User area";
+               };
+       };
+};
+
+&soc {
+       spi@7000 {
+               flash@0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "spansion,m25p80";
+                       reg = <0>;
+                       spi-max-frequency = <40000000>;
+
+                       partition@0 {
+                               /* 512KB for u-boot Bootloader Image */
+                               reg = <0x0 0x00080000>;
+                               label = "SPI U-Boot Image";
+                               read-only;
+                       };
+
+                       partition@80000 {
+                               /* 512KB for DTB Image */
+                               reg = <0x00080000 0x00080000>;
+                               label = "SPI DTB Image";
+                       };
+
+                       partition@100000 {
+                               /* 4MB for Linux Kernel Image */
+                               reg = <0x00100000 0x00400000>;
+                               label = "SPI Linux Kernel Image";
+                       };
+
+                       partition@500000 {
+                               /* 4MB for Compressed RFS Image */
+                               reg = <0x00500000 0x00400000>;
+                               label = "SPI Compressed RFS Image";
+                       };
+
+                       partition@900000 {
+                               /* 7MB for JFFS2 based RFS */
+                               reg = <0x00900000 0x00700000>;
+                               label = "SPI JFFS2 RFS";
+                       };
+               };
+       };
+
+       i2c@3000 {
+               rtc@68 {
+                       compatible = "dallas,ds1339";
+                       reg = <0x68>;
+               };
+       };
+
+       usb@22000 {
+               phy_type = "ulpi";
+       };
+
+       usb@23000 {
+               status = "disabled";
+       };
+
+       mdio@24000 {
+               phy0: ethernet-phy@0 {
+                       interrupts = <3 1 0 0>;
+                       reg = <0x0>;
+               };
+               phy1: ethernet-phy@1 {
+                       interrupts = <2 1 0 0>;
+                       reg = <0x1>;
+               };
+               phy2: ethernet-phy@2 {
+                       interrupts = <1 1 0 0>;
+                       reg = <0x2>;
+               };
+       };
+
+       mdio@25000 {
+               tbi0: tbi-phy@11 {
+                       reg = <0x11>;
+                       device_type = "tbi-phy";
+               };
+       };
+
+       mdio@26000 {
+               tbi1: tbi-phy@11 {
+                       reg = <0x11>;
+                       device_type = "tbi-phy";
+               };
+       };
+
+       ethernet@b0000 {
+               phy-handle = <&phy2>;
+               phy-connection-type = "rgmii-id";
+       };
+
+       ethernet@b1000 {
+               phy-handle = <&phy0>;
+               tbi-handle = <&tbi0>;
+               phy-connection-type = "sgmii";
+       };
+
+       ethernet@b2000 {
+               phy-handle = <&phy1>;
+               phy-connection-type = "rgmii-id";
+       };
+};
diff --git a/arch/powerpc/boot/dts/p1024rdb_32b.dts b/arch/powerpc/boot/dts/p1024rdb_32b.dts
new file mode 100644 (file)
index 0000000..90e803e
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * P1024 RDB 32Bit Physical Address Map Device Tree Source
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1020si-pre.dtsi"
+/ {
+       model = "fsl,P1024RDB";
+       compatible = "fsl,P1024RDB";
+
+       memory {
+               device_type = "memory";
+       };
+
+       lbc: localbus@ffe05000 {
+               reg = <0x0 0xffe05000 0 0x1000>;
+               ranges = <0x0 0x0 0x0 0xef000000 0x01000000
+                         0x1 0x0 0x0 0xff800000 0x00040000>;
+       };
+
+       soc: soc@ffe00000 {
+               ranges = <0x0 0x0 0xffe00000 0x100000>;
+       };
+
+       pci0: pcie@ffe09000 {
+               reg = <0x0 0xffe09000 0 0x1000>;
+               ranges = <0x2000000 0x0 0xe0000000 0x0 0xa0000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0x0 0xffc10000 0x0 0x10000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       pci1: pcie@ffe0a000 {
+               reg = <0x0 0xffe0a000 0 0x1000>;
+               ranges = <0x2000000 0x0 0xe0000000 0x0 0x80000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0x0 0xffc00000 0x0 0x10000>;
+               pcie@0 {
+                       reg = <0x0 0x0 0x0 0x0 0x0>;
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+};
+
+/include/ "p1024rdb.dtsi"
+/include/ "fsl/p1020si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/p1024rdb_36b.dts b/arch/powerpc/boot/dts/p1024rdb_36b.dts
new file mode 100644 (file)
index 0000000..3656825
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * P1024 RDB 36Bit Physical Address Map Device Tree Source
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/include/ "fsl/p1020si-pre.dtsi"
+/ {
+       model = "fsl,P1024RDB";
+       compatible = "fsl,P1024RDB";
+
+       memory {
+               device_type = "memory";
+       };
+
+       lbc: localbus@fffe05000 {
+               reg = <0xf 0xffe05000 0 0x1000>;
+               ranges = <0x0 0x0 0xf 0xef000000 0x01000000
+                         0x1 0x0 0xf 0xff800000 0x00040000>;
+       };
+
+       soc: soc@fffe00000 {
+               ranges = <0x0 0xf 0xffe00000 0x100000>;
+       };
+
+       pci0: pcie@fffe09000 {
+               reg = <0xf 0xffe09000 0 0x1000>;
+               ranges = <0x2000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0xf 0xffc10000 0x0 0x10000>;
+               pcie@0 {
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+
+       pci1: pcie@fffe0a000 {
+               reg = <0xf 0xffe0a000 0 0x1000>;
+               ranges = <0x2000000 0x0 0xe0000000 0xc 0x00000000 0x0 0x20000000
+                         0x1000000 0x0 0x00000000 0xf 0xffc00000 0x0 0x10000>;
+               pcie@0 {
+                       reg = <0x0 0x0 0x0 0x0 0x0>;
+                       ranges = <0x2000000 0x0 0xe0000000
+                                 0x2000000 0x0 0xe0000000
+                                 0x0 0x20000000
+
+                                 0x1000000 0x0 0x0
+                                 0x1000000 0x0 0x0
+                                 0x0 0x100000>;
+               };
+       };
+};
+
+/include/ "p1024rdb.dtsi"
+/include/ "fsl/p1020si-post.dtsi"
index cf3676fc714b13f5f95fcfb627eae1066988ac28..f50256482297101c4fcda8c1093eadad638447ac 100644 (file)
                                0x1  0x4  0x2  0x0  0x2  0x0    /* ENET5_RX_DV_SER5_CTS_B */
                                0x1  0x8  0x2  0x0  0x2  0x0>;    /* ENET5_RX_ER_SER5_CD_B */
                };
+
+               pio3: ucc_pin@03 {
+                       pio-map = <
+               /* port  pin  dir  open_drain  assignment  has_irq */
+                               0x0  0x16 0x2  0x0  0x2  0x0    /* SER7_CD_B*/
+                               0x0  0x12 0x2  0x0  0x2  0x0    /* SER7_CTS_B*/
+                               0x0  0x13 0x1  0x0  0x2  0x0    /* SER7_RTS_B*/
+                               0x0  0x14 0x2  0x0  0x2  0x0    /* SER7_RXD0*/
+                               0x0  0x15 0x1  0x0  0x2  0x0>;    /* SER7_TXD0*/
+               };
+
+               pio4: ucc_pin@04 {
+                       pio-map = <
+               /* port  pin  dir  open_drain  assignment  has_irq */
+                               0x1  0x0  0x2  0x0  0x2  0x0    /* SER3_CD_B*/
+                               0x0  0x1c 0x2  0x0  0x2  0x0    /* SER3_CTS_B*/
+                               0x0  0x1d 0x1  0x0  0x2  0x0    /* SER3_RTS_B*/
+                               0x0  0x1e 0x2  0x0  0x2  0x0    /* SER3_RXD0*/
+                               0x0  0x1f 0x1  0x0  0x2  0x0>;    /* SER3_TXD0*/
+               };
+       };
+};
+
+&qe {
+       serial2: ucc@2600 {
+               device_type = "serial";
+               compatible = "ucc_uart";
+               port-number = <0>;
+               rx-clock-name = "brg6";
+               tx-clock-name = "brg6";
+               pio-handle = <&pio3>;
+       };
+
+       serial3: ucc@2200 {
+               device_type = "serial";
+               compatible = "ucc_uart";
+               port-number = <1>;
+               rx-clock-name = "brg2";
+               tx-clock-name = "brg2";
+               pio-handle = <&pio4>;
        };
 };
index d3b939c573b007e5ca25ad89f58523abb3db56cc..e699cf95b06342b94d8609f1b68c6511cf63505f 100644 (file)
                        interrupts = <3 1 0 0>;
                        reg = <0x2>;
                };
+
+               sgmii_phy1: sgmii-phy@1 {
+                       interrupts = <5 1 0 0>;
+                       reg = <0x1c>;
+               };
+               sgmii_phy2: sgmii-phy@2 {
+                       interrupts = <5 1 0 0>;
+                       reg = <0x1d>;
+               };
+
                tbi0: tbi-phy@11 {
                        reg = <0x11>;
                        device_type = "tbi-phy";
index 153bc76bb48ea75cc93ca9d93d41207fe420a147..4d52bce1d5b00807b07b1ce64e36b1d22a6e9722 100644 (file)
@@ -34,7 +34,7 @@
 
                /* NOR and NAND Flashes */
                ranges = <0x0 0x0 0x0 0xef000000 0x01000000
-                         0x1 0x0 0x0 0xff800000 0x00040000
+                         0x1 0x0 0x0 0xffa00000 0x00040000
                          0x2 0x0 0x0 0xffb00000 0x00020000>;
 
                nor@0,0 {
index 285213976a7f18811e5a90e5f00af2858c9a1cdd..baab0347dab0167925a641883c69b320963e765b 100644 (file)
 
        lbc: localbus@ffe124000 {
                reg = <0xf 0xfe124000 0 0x1000>;
-               ranges = <0 0 0xf 0xe8000000 0x08000000>;
+               ranges = <0 0 0xf 0xe8000000 0x08000000
+                         1 0 0xf 0xffa00000 0x00040000>;
 
                flash@0,0 {
                        compatible = "cfi-flash";
                        bank-width = <2>;
                        device-width = <2>;
                };
+
+               nand@1,0 {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "fsl,elbc-fcm-nand";
+                       reg = <0x1 0x0 0x40000>;
+
+                       partition@0 {
+                               label = "NAND U-Boot Image";
+                               reg = <0x0 0x02000000>;
+                               read-only;
+                       };
+
+                       partition@2000000 {
+                               label = "NAND Root File System";
+                               reg = <0x02000000 0x10000000>;
+                       };
+
+                       partition@12000000 {
+                               label = "NAND Compressed RFS Image";
+                               reg = <0x12000000 0x08000000>;
+                       };
+
+                       partition@1a000000 {
+                               label = "NAND Linux Kernel Image";
+                               reg = <0x1a000000 0x04000000>;
+                       };
+
+                       partition@1e000000 {
+                               label = "NAND DTB Image";
+                               reg = <0x1e000000 0x01000000>;
+                       };
+
+                       partition@1f000000 {
+                               label = "NAND Writable User area";
+                               reg = <0x1f000000 0x01000000>;
+                       };
+               };
        };
 
        pci0: pcie@ffe200000 {
diff --git a/arch/powerpc/boot/dts/p3060qds.dts b/arch/powerpc/boot/dts/p3060qds.dts
deleted file mode 100644 (file)
index 9ae875c..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * P3060QDS Device Tree Source
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above copyright
- *       notice, this list of conditions and the following disclaimer in the
- *       documentation and/or other materials provided with the distribution.
- *     * Neither the name of Freescale Semiconductor nor the
- *       names of its contributors may be used to endorse or promote products
- *       derived from this software without specific prior written permission.
- *
- *
- * ALTERNATIVELY, this software may be distributed under the terms of the
- * GNU General Public License ("GPL") as published by the Free Software
- * Foundation, either version 2 of that License or (at your option) any
- * later version.
- *
- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/include/ "fsl/p3060si-pre.dtsi"
-
-/ {
-       model = "fsl,P3060QDS";
-       compatible = "fsl,P3060QDS";
-       #address-cells = <2>;
-       #size-cells = <2>;
-       interrupt-parent = <&mpic>;
-
-       memory {
-               device_type = "memory";
-       };
-
-       dcsr: dcsr@f00000000 {
-               ranges = <0x00000000 0xf 0x00000000 0x01008000>;
-       };
-
-       soc: soc@ffe000000 {
-               ranges = <0x00000000 0xf 0xfe000000 0x1000000>;
-               reg = <0xf 0xfe000000 0 0x00001000>;
-               spi@110000 {
-                       flash@0 {
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                               compatible = "spansion,s25sl12801";
-                               reg = <0>;
-                               spi-max-frequency = <40000000>; /* input clock */
-                               partition@u-boot {
-                                       label = "u-boot";
-                                       reg = <0x00000000 0x00100000>;
-                                       read-only;
-                               };
-                               partition@kernel {
-                                       label = "kernel";
-                                       reg = <0x00100000 0x00500000>;
-                                       read-only;
-                               };
-                               partition@dtb {
-                                       label = "dtb";
-                                       reg = <0x00600000 0x00100000>;
-                                       read-only;
-                               };
-                               partition@fs {
-                                       label = "file system";
-                                       reg = <0x00700000 0x00900000>;
-                               };
-                       };
-                       flash@1 {
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                               compatible = "spansion,en25q32b";
-                               reg = <1>;
-                               spi-max-frequency = <40000000>; /* input clock */
-                               partition@spi1 {
-                                       label = "spi1";
-                                       reg = <0x00000000 0x00400000>;
-                               };
-                       };
-                       flash@2 {
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                               compatible = "atmel,at45db081d";
-                               reg = <2>;
-                               spi-max-frequency = <40000000>; /* input clock */
-                               partition@spi1 {
-                                       label = "spi2";
-                                       reg = <0x00000000 0x00100000>;
-                               };
-                       };
-                       flash@3 {
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                               compatible = "spansion,sst25wf040";
-                               reg = <3>;
-                               spi-max-frequency = <40000000>; /* input clock */
-                               partition@spi3 {
-                                       label = "spi3";
-                                       reg = <0x00000000 0x00080000>;
-                               };
-                       };
-               };
-
-               i2c@118000 {
-                       eeprom@51 {
-                               compatible = "at24,24c256";
-                               reg = <0x51>;
-                       };
-                       eeprom@53 {
-                               compatible = "at24,24c256";
-                               reg = <0x53>;
-                       };
-                       rtc@68 {
-                               compatible = "dallas,ds3232";
-                               reg = <0x68>;
-                               interrupts = <0x1 0x1 0 0>;
-                       };
-               };
-
-               usb0: usb@210000 {
-                       phy_type = "ulpi";
-               };
-
-               usb1: usb@211000 {
-                       dr_mode = "host";
-                       phy_type = "ulpi";
-               };
-       };
-
-       rio: rapidio@ffe0c0000 {
-               reg = <0xf 0xfe0c0000 0 0x11000>;
-
-               port1 {
-                       ranges = <0 0 0xc 0x20000000 0 0x10000000>;
-               };
-               port2 {
-                       ranges = <0 0 0xc 0x30000000 0 0x10000000>;
-               };
-       };
-
-       lbc: localbus@ffe124000 {
-               reg = <0xf 0xfe124000 0 0x1000>;
-               ranges = <0 0 0xf 0xe8000000 0x08000000
-                         2 0 0xf 0xffa00000 0x00040000
-                         3 0 0xf 0xffdf0000 0x00008000>;
-
-               flash@0,0 {
-                       compatible = "cfi-flash";
-                       reg = <0 0 0x08000000>;
-                       bank-width = <2>;
-                       device-width = <2>;
-               };
-
-               nand@2,0 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       compatible = "fsl,elbc-fcm-nand";
-                       reg = <0x2 0x0 0x40000>;
-
-                       partition@0 {
-                               label = "NAND U-Boot Image";
-                               reg = <0x0 0x02000000>;
-                               read-only;
-                       };
-
-                       partition@2000000 {
-                               label = "NAND Root File System";
-                               reg = <0x02000000 0x10000000>;
-                       };
-
-                       partition@12000000 {
-                               label = "NAND Compressed RFS Image";
-                               reg = <0x12000000 0x08000000>;
-                       };
-
-                       partition@1a000000 {
-                               label = "NAND Linux Kernel Image";
-                               reg = <0x1a000000 0x04000000>;
-                       };
-
-                       partition@1e000000 {
-                               label = "NAND DTB Image";
-                               reg = <0x1e000000 0x01000000>;
-                       };
-
-                       partition@1f000000 {
-                               label = "NAND Writable User area";
-                               reg = <0x1f000000 0x21000000>;
-                       };
-               };
-
-               board-control@3,0 {
-                       compatible = "fsl,p3060qds-fpga", "fsl,fpga-qixis";
-                       reg = <3 0 0x100>;
-               };
-       };
-
-       pci0: pcie@ffe200000 {
-               reg = <0xf 0xfe200000 0 0x1000>;
-               ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000
-                         0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>;
-               pcie@0 {
-                       ranges = <0x02000000 0 0xe0000000
-                                 0x02000000 0 0xe0000000
-                                 0 0x20000000
-
-                                 0x01000000 0 0x00000000
-                                 0x01000000 0 0x00000000
-                                 0 0x00010000>;
-               };
-       };
-
-       pci1: pcie@ffe201000 {
-               reg = <0xf 0xfe201000 0 0x1000>;
-               ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000
-                         0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>;
-               pcie@0 {
-                       ranges = <0x02000000 0 0xe0000000
-                                 0x02000000 0 0xe0000000
-                                 0 0x20000000
-
-                                 0x01000000 0 0x00000000
-                                 0x01000000 0 0x00000000
-                                 0 0x00010000>;
-               };
-       };
-};
-
-/include/ "fsl/p3060si-post.dtsi"
diff --git a/arch/powerpc/boot/dts/sbc8560.dts b/arch/powerpc/boot/dts/sbc8560.dts
deleted file mode 100644 (file)
index 72078eb..0000000
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * SBC8560 Device Tree Source
- *
- * Copyright 2007 Wind River Systems Inc.
- *
- * Paul Gortmaker (see MAINTAINERS for contact information)
- *
- * 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.
- */
-
-/dts-v1/;
-
-/ {
-       model = "SBC8560";
-       compatible = "SBC8560";
-       #address-cells = <1>;
-       #size-cells = <1>;
-
-       aliases {
-               ethernet0 = &enet0;
-               ethernet1 = &enet1;
-               ethernet2 = &enet2;
-               ethernet3 = &enet3;
-               serial0 = &serial0;
-               serial1 = &serial1;
-               pci0 = &pci0;
-       };
-
-       cpus {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               PowerPC,8560@0 {
-                       device_type = "cpu";
-                       reg = <0>;
-                       d-cache-line-size = <0x20>;     // 32 bytes
-                       i-cache-line-size = <0x20>;     // 32 bytes
-                       d-cache-size = <0x8000>;        // L1, 32K
-                       i-cache-size = <0x8000>;        // L1, 32K
-                       timebase-frequency = <0>;       // From uboot
-                       bus-frequency = <0>;
-                       clock-frequency = <0>;
-                       next-level-cache = <&L2>;
-               };
-       };
-
-       memory {
-               device_type = "memory";
-               reg = <0x00000000 0x20000000>;
-       };
-
-       soc@ff700000 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               device_type = "soc";
-               ranges = <0x0 0xff700000 0x00100000>;
-               clock-frequency = <0>;
-
-               ecm-law@0 {
-                       compatible = "fsl,ecm-law";
-                       reg = <0x0 0x1000>;
-                       fsl,num-laws = <8>;
-               };
-
-               ecm@1000 {
-                       compatible = "fsl,mpc8560-ecm", "fsl,ecm";
-                       reg = <0x1000 0x1000>;
-                       interrupts = <17 2>;
-                       interrupt-parent = <&mpic>;
-               };
-
-               memory-controller@2000 {
-                       compatible = "fsl,mpc8560-memory-controller";
-                       reg = <0x2000 0x1000>;
-                       interrupt-parent = <&mpic>;
-                       interrupts = <0x12 0x2>;
-               };
-
-               L2: l2-cache-controller@20000 {
-                       compatible = "fsl,mpc8560-l2-cache-controller";
-                       reg = <0x20000 0x1000>;
-                       cache-line-size = <0x20>;       // 32 bytes
-                       cache-size = <0x40000>;         // L2, 256K
-                       interrupt-parent = <&mpic>;
-                       interrupts = <0x10 0x2>;
-               };
-
-               i2c@3000 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       cell-index = <0>;
-                       compatible = "fsl-i2c";
-                       reg = <0x3000 0x100>;
-                       interrupts = <0x2b 0x2>;
-                       interrupt-parent = <&mpic>;
-                       dfsrr;
-               };
-
-               i2c@3100 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       cell-index = <1>;
-                       compatible = "fsl-i2c";
-                       reg = <0x3100 0x100>;
-                       interrupts = <0x2b 0x2>;
-                       interrupt-parent = <&mpic>;
-                       dfsrr;
-               };
-
-               dma@21300 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       compatible = "fsl,mpc8560-dma", "fsl,eloplus-dma";
-                       reg = <0x21300 0x4>;
-                       ranges = <0x0 0x21100 0x200>;
-                       cell-index = <0>;
-                       dma-channel@0 {
-                               compatible = "fsl,mpc8560-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x0 0x80>;
-                               cell-index = <0>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <20 2>;
-                       };
-                       dma-channel@80 {
-                               compatible = "fsl,mpc8560-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x80 0x80>;
-                               cell-index = <1>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <21 2>;
-                       };
-                       dma-channel@100 {
-                               compatible = "fsl,mpc8560-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x100 0x80>;
-                               cell-index = <2>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <22 2>;
-                       };
-                       dma-channel@180 {
-                               compatible = "fsl,mpc8560-dma-channel",
-                                               "fsl,eloplus-dma-channel";
-                               reg = <0x180 0x80>;
-                               cell-index = <3>;
-                               interrupt-parent = <&mpic>;
-                               interrupts = <23 2>;
-                       };
-               };
-
-               enet0: ethernet@24000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <0>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x24000 0x1000>;
-                       ranges = <0x0 0x24000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <0x1d 0x2 0x1e 0x2 0x22 0x2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi0>;
-                       phy-handle = <&phy0>;
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-mdio";
-                               reg = <0x520 0x20>;
-                               phy0: ethernet-phy@19 {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <0x6 0x1>;
-                                       reg = <0x19>;
-                                       device_type = "ethernet-phy";
-                               };
-                               phy1: ethernet-phy@1a {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <0x7 0x1>;
-                                       reg = <0x1a>;
-                                       device_type = "ethernet-phy";
-                               };
-                               phy2: ethernet-phy@1b {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <0x8 0x1>;
-                                       reg = <0x1b>;
-                                       device_type = "ethernet-phy";
-                               };
-                               phy3: ethernet-phy@1c {
-                                       interrupt-parent = <&mpic>;
-                                       interrupts = <0x8 0x1>;
-                                       reg = <0x1c>;
-                                       device_type = "ethernet-phy";
-                               };
-                               tbi0: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               enet1: ethernet@25000 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       cell-index = <1>;
-                       device_type = "network";
-                       model = "TSEC";
-                       compatible = "gianfar";
-                       reg = <0x25000 0x1000>;
-                       ranges = <0x0 0x25000 0x1000>;
-                       local-mac-address = [ 00 00 00 00 00 00 ];
-                       interrupts = <0x23 0x2 0x24 0x2 0x28 0x2>;
-                       interrupt-parent = <&mpic>;
-                       tbi-handle = <&tbi1>;
-                       phy-handle = <&phy1>;
-
-                       mdio@520 {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-                               compatible = "fsl,gianfar-tbi";
-                               reg = <0x520 0x20>;
-
-                               tbi1: tbi-phy@11 {
-                                       reg = <0x11>;
-                                       device_type = "tbi-phy";
-                               };
-                       };
-               };
-
-               mpic: pic@40000 {
-                       interrupt-controller;
-                       #address-cells = <0>;
-                       #interrupt-cells = <2>;
-                       compatible = "chrp,open-pic";
-                       reg = <0x40000 0x40000>;
-                       device_type = "open-pic";
-               };
-
-               cpm@919c0 {
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       compatible = "fsl,mpc8560-cpm", "fsl,cpm2";
-                       reg = <0x919c0 0x30>;
-                       ranges;
-
-                       muram@80000 {
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                               ranges = <0x0 0x80000 0x10000>;
-
-                               data@0 {
-                                       compatible = "fsl,cpm-muram-data";
-                                       reg = <0x0 0x4000 0x9000 0x2000>;
-                               };
-                       };
-
-                       brg@919f0 {
-                               compatible = "fsl,mpc8560-brg",
-                                            "fsl,cpm2-brg",
-                                            "fsl,cpm-brg";
-                               reg = <0x919f0 0x10 0x915f0 0x10>;
-                               clock-frequency = <165000000>;
-                       };
-
-                       cpmpic: pic@90c00 {
-                               interrupt-controller;
-                               #address-cells = <0>;
-                               #interrupt-cells = <2>;
-                               interrupts = <0x2e 0x2>;
-                               interrupt-parent = <&mpic>;
-                               reg = <0x90c00 0x80>;
-                               compatible = "fsl,mpc8560-cpm-pic", "fsl,cpm2-pic";
-                       };
-
-                       enet2: ethernet@91320 {
-                               device_type = "network";
-                               compatible = "fsl,mpc8560-fcc-enet",
-                                            "fsl,cpm2-fcc-enet";
-                               reg = <0x91320 0x20 0x88500 0x100 0x913b0 0x1>;
-                               local-mac-address = [ 00 00 00 00 00 00 ];
-                               fsl,cpm-command = <0x16200300>;
-                               interrupts = <0x21 0x8>;
-                               interrupt-parent = <&cpmpic>;
-                               phy-handle = <&phy2>;
-                       };
-
-                       enet3: ethernet@91340 {
-                               device_type = "network";
-                               compatible = "fsl,mpc8560-fcc-enet",
-                                            "fsl,cpm2-fcc-enet";
-                               reg = <0x91340 0x20 0x88600 0x100 0x913d0 0x1>;
-                               local-mac-address = [ 00 00 00 00 00 00 ];
-                               fsl,cpm-command = <0x1a400300>;
-                               interrupts = <0x22 0x8>;
-                               interrupt-parent = <&cpmpic>;
-                               phy-handle = <&phy3>;
-                       };
-               };
-
-               global-utilities@e0000 {
-                       compatible = "fsl,mpc8560-guts";
-                       reg = <0xe0000 0x1000>;
-               };
-       };
-
-       pci0: pci@ff708000 {
-               #interrupt-cells = <1>;
-               #size-cells = <2>;
-               #address-cells = <3>;
-               compatible = "fsl,mpc8540-pcix", "fsl,mpc8540-pci";
-               device_type = "pci";
-               reg = <0xff708000 0x1000>;
-               clock-frequency = <66666666>;
-               interrupt-map-mask = <0xf800 0x0 0x0 0x7>;
-               interrupt-map = <
-
-                       /* IDSEL 0x02 */
-                       0x1000 0x0 0x0 0x1 &mpic 0x2 0x1
-                       0x1000 0x0 0x0 0x2 &mpic 0x3 0x1
-                       0x1000 0x0 0x0 0x3 &mpic 0x4 0x1
-                       0x1000 0x0 0x0 0x4 &mpic 0x5 0x1>;
-
-               interrupt-parent = <&mpic>;
-               interrupts = <0x18 0x2>;
-               bus-range = <0x0 0x0>;
-               ranges = <0x02000000 0x0 0x80000000 0x80000000 0x0 0x20000000
-                         0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>;
-       };
-
-       localbus@ff705000 {
-               compatible = "fsl,mpc8560-localbus", "simple-bus";
-               #address-cells = <2>;
-               #size-cells = <1>;
-               reg = <0xff705000 0x100>;       // BRx, ORx, etc.
-
-               ranges = <
-                       0x0 0x0 0xff800000 0x0800000    // 8MB boot flash
-                       0x1 0x0 0xe4000000 0x4000000    // 64MB flash
-                       0x3 0x0 0x20000000 0x4000000    // 64MB SDRAM
-                       0x4 0x0 0x24000000 0x4000000    // 64MB SDRAM
-                       0x5 0x0 0xfc000000 0x0c00000    // EPLD
-                       0x6 0x0 0xe0000000 0x4000000    // 64MB flash
-                       0x7 0x0 0x80000000 0x0200000    // ATM1,2
-               >;
-
-               epld@5,0 {
-                       compatible = "wrs,epld-localbus";
-                       #address-cells = <2>;
-                       #size-cells = <1>;
-                       reg = <0x5 0x0 0xc00000>;
-                       ranges = <
-                               0x0 0x0 0x5 0x000000 0x1fff     // LED disp.
-                               0x1 0x0 0x5 0x100000 0x1fff     // switches
-                               0x2 0x0 0x5 0x200000 0x1fff     // ID reg.
-                               0x3 0x0 0x5 0x300000 0x1fff     // status reg.
-                               0x4 0x0 0x5 0x400000 0x1fff     // reset reg.
-                               0x5 0x0 0x5 0x500000 0x1fff     // Wind port
-                               0x7 0x0 0x5 0x700000 0x1fff     // UART #1
-                               0x8 0x0 0x5 0x800000 0x1fff     // UART #2
-                               0x9 0x0 0x5 0x900000 0x1fff     // RTC
-                               0xb 0x0 0x5 0xb00000 0x1fff     // EEPROM
-                       >;
-
-                       bidr@2,0 {
-                               compatible = "wrs,sbc8560-bidr";
-                               reg = <0x2 0x0 0x10>;
-                       };
-
-                       bcsr@3,0 {
-                               compatible = "wrs,sbc8560-bcsr";
-                               reg = <0x3 0x0 0x10>;
-                       };
-
-                       brstcr@4,0 {
-                               compatible = "wrs,sbc8560-brstcr";
-                               reg = <0x4 0x0 0x10>;
-                       };
-
-                       serial0: serial@7,0 {
-                               device_type = "serial";
-                               compatible = "ns16550";
-                               reg = <0x7 0x0 0x100>;
-                               clock-frequency = <1843200>;
-                               interrupts = <0x9 0x2>;
-                               interrupt-parent = <&mpic>;
-                       };
-
-                       serial1: serial@8,0 {
-                               device_type = "serial";
-                               compatible = "ns16550";
-                               reg = <0x8 0x0 0x100>;
-                               clock-frequency = <1843200>;
-                               interrupts = <0xa 0x2>;
-                               interrupt-parent = <&mpic>;
-                       };
-
-                       rtc@9,0 {
-                               compatible = "m48t59";
-                               reg = <0x9 0x0 0x1fff>;
-                       };
-               };
-       };
-};
diff --git a/arch/powerpc/boot/flatdevtree_env.h b/arch/powerpc/boot/flatdevtree_env.h
deleted file mode 100644 (file)
index 66e0ebb..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * This file adds the header file glue so that the shared files
- * flatdevicetree.[ch] can compile and work in the powerpc bootwrapper.
- *
- * strncmp & strchr copied from <file:lib/string.c>
- * Copyright (C) 1991, 1992  Linus Torvalds
- *
- * Maintained by: Mark A. Greer <mgreer@mvista.com>
- */
-#ifndef _PPC_BOOT_FLATDEVTREE_ENV_H_
-#define _PPC_BOOT_FLATDEVTREE_ENV_H_
-
-#include <stdarg.h>
-#include <stddef.h>
-#include "types.h"
-#include "string.h"
-#include "stdio.h"
-#include "ops.h"
-
-#define be16_to_cpu(x)         (x)
-#define cpu_to_be16(x)         (x)
-#define be32_to_cpu(x)         (x)
-#define cpu_to_be32(x)         (x)
-#define be64_to_cpu(x)         (x)
-#define cpu_to_be64(x)         (x)
-
-#endif /* _PPC_BOOT_FLATDEVTREE_ENV_H_ */
index 07e1bbadebfe25ef7dc723e2deafa9f93f0dbf5e..a0dfef1fcdb70eebfbd2bc762ba476acbef65b1c 100644 (file)
@@ -2,14 +2,14 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_EXPERT=y
-# CONFIG_HOTPLUG is not set
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_MSDOS_PARTITION is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 # CONFIG_IOSCHED_CFQ is not set
 # CONFIG_PPC_CHRP is not set
@@ -31,11 +31,10 @@ CONFIG_IP_PNP=y
 # CONFIG_INET_XFRM_MODE_BEET is not set
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
+CONFIG_TIPC=y
 CONFIG_BRIDGE=m
 CONFIG_VLAN_8021Q=y
 CONFIG_MTD=y
-CONFIG_MTD_CONCAT=y
-CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
@@ -50,17 +49,15 @@ CONFIG_MTD_UBI_DEBUG=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
-CONFIG_TUN=y
 CONFIG_MII=y
-CONFIG_MARVELL_PHY=y
-CONFIG_NET_ETHERNET=y
+CONFIG_TUN=y
 CONFIG_UCC_GETH=y
-# CONFIG_NETDEV_10000 is not set
-CONFIG_WAN=y
-CONFIG_HDLC=y
+CONFIG_MARVELL_PHY=y
 CONFIG_PPP=y
 CONFIG_PPP_MULTILINK=y
 CONFIG_PPPOE=y
+CONFIG_WAN=y
+CONFIG_HDLC=y
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
 # CONFIG_VT is not set
@@ -77,10 +74,7 @@ CONFIG_UIO=y
 # CONFIG_DNOTIFY is not set
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
+CONFIG_UBIFS_FS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_MSDOS_PARTITION is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
diff --git a/arch/powerpc/configs/85xx/sbc8560_defconfig b/arch/powerpc/configs/85xx/sbc8560_defconfig
deleted file mode 100644 (file)
index f7fdb03..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-CONFIG_PPC_85xx=y
-CONFIG_EXPERIMENTAL=y
-CONFIG_SYSVIPC=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-CONFIG_SLAB=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_SBC8560=y
-CONFIG_BINFMT_MISC=y
-CONFIG_SPARSE_IRQ=y
-# CONFIG_SECCOMP is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_XFRM_USER=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-# CONFIG_FW_LOADER is not set
-CONFIG_PROC_DEVICETREE=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-CONFIG_BLK_DEV_RAM_SIZE=32768
-CONFIG_NETDEVICES=y
-CONFIG_BROADCOM_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_GIANFAR=y
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_8250=y
-CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_NR_UARTS=2
-CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-# CONFIG_HW_RANDOM is not set
-CONFIG_VIDEO_OUTPUT_CONTROL=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_M48T59=y
-CONFIG_INOTIFY=y
-CONFIG_PROC_KCORE=y
-CONFIG_TMPFS=y
-CONFIG_NFS_FS=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-# CONFIG_MSDOS_PARTITION is not set
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DETECT_HUNG_TASK=y
-CONFIG_DEBUG_MUTEXES=y
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_PPC_EARLY_DEBUG=y
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
index 91db656294e85a642f40182b4245231293aaa22b..cbb98c1234fdea1040292542a4ec4277e5bf76e2 100644 (file)
@@ -23,7 +23,6 @@ CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
 CONFIG_P2041_RDB=y
 CONFIG_P3041_DS=y
-CONFIG_P3060_QDS=y
 CONFIG_P4080_DS=y
 CONFIG_P5020_DS=y
 CONFIG_HIGHMEM=y
@@ -32,10 +31,12 @@ CONFIG_HIGH_RES_TIMERS=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_KEXEC=y
+CONFIG_IRQ_ALL_CPUS=y
 CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_FSL_LBC=y
 CONFIG_PCI=y
 CONFIG_PCIEPORTBUS=y
+CONFIG_PCI_MSI=y
 # CONFIG_PCIEASPM is not set
 CONFIG_RAPIDIO=y
 CONFIG_FSL_RIO=y
@@ -76,6 +77,11 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_ECC=y
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_NAND_FSL_IFC=y
+CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_MTD_M25P80=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
@@ -136,6 +142,8 @@ CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_OF=y
+CONFIG_MMC_SDHCI_OF_ESDHC=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_MPC85XX=y
index 6798343580f0bfcd9bc03eaab6baab9e675eb257..dd89de8b0b7f59945eb656564d49d19bcf2af121 100644 (file)
@@ -6,7 +6,9 @@ CONFIG_NR_CPUS=2
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_BSD_PROCESS_ACCT=y
-CONFIG_SPARSE_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -18,11 +20,14 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
 CONFIG_P5020_DS=y
 # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=m
+CONFIG_IRQ_ALL_CPUS=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCI_MSI=y
 CONFIG_RAPIDIO=y
 CONFIG_FSL_RIO=y
 CONFIG_NET=y
@@ -51,12 +56,25 @@ CONFIG_INET_ESP=y
 CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSL_ELBC=y
+CONFIG_MTD_NAND_FSL_IFC=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
+CONFIG_ATA=y
+CONFIG_SATA_FSL=y
+CONFIG_SATA_SIL24=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_INPUT_FF_MEMLESS=m
@@ -66,39 +84,59 @@ CONFIG_INPUT_FF_MEMLESS=m
 CONFIG_SERIO_LIBPS2=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
+CONFIG_SPI=y
+CONFIG_SPI_GPIO=y
+CONFIG_SPI_FSL_SPI=y
+CONFIG_SPI_FSL_ESPI=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_USB_HID=m
+CONFIG_USB=y
+CONFIG_USB_MON=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_FSL=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_EDAC=y
+CONFIG_EDAC_MM_EDAC=y
 CONFIG_DMADEVICES=y
 CONFIG_FSL_DMA=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=y
+CONFIG_NTFS_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_HUGETLBFS=y
 # CONFIG_MISC_FILESYSTEMS is not set
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
-CONFIG_NLS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=m
 CONFIG_CRC_T10DIF=y
-CONFIG_CRC_ITU_T=m
 CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_CRYPTO_NULL=y
 CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_MD4=y
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
 CONFIG_CRYPTO_AES=y
index 0d36b0e1e2681134f86d50934c1413f46b27f71b..8fa84f156ef3f28eea3a45c6f02df28f55b5be86 100644 (file)
@@ -2,7 +2,6 @@ CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -12,6 +11,7 @@ CONFIG_KALLSYMS_ALL=y
 # CONFIG_PCSPKR_PLATFORM is not set
 CONFIG_EMBEDDED=y
 CONFIG_SLAB=y
+CONFIG_PARTITION_ADVANCED=y
 # CONFIG_IOSCHED_CFQ is not set
 # CONFIG_PPC_PMAC is not set
 CONFIG_PPC_82xx=y
@@ -49,12 +49,9 @@ CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_NETDEVICES=y
-CONFIG_FIXED_PHY=y
-CONFIG_NET_ETHERNET=y
 CONFIG_FS_ENET=y
 CONFIG_FS_ENET_MDIO_FCC=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
+CONFIG_FIXED_PHY=y
 # CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
@@ -64,6 +61,8 @@ CONFIG_SERIAL_CPM_CONSOLE=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_CPM=y
+CONFIG_SPI=y
+CONFIG_SPI_FSL_SPI=y
 # CONFIG_HWMON is not set
 CONFIG_USB_GADGET=y
 CONFIG_USB_FSL_USB2=y
@@ -80,8 +79,6 @@ CONFIG_SQUASHFS=y
 CONFIG_NFS_FS=y
 CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_NLS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
@@ -90,7 +87,6 @@ CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_FS=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_DEBUG_INFO=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_BDI_SWITCH=y
 CONFIG_CRYPTO_ECB=y
 CONFIG_CRYPTO_PCBC=y
index 62bb723c5b54443e01efd6c0cf6827e8b8afd33e..03ee911c45775410c141ab108019b278ae726d17 100644 (file)
@@ -74,6 +74,30 @@ CONFIG_INET_ESP=y
 CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_FTL=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSL_ELBC=y
+CONFIG_MTD_NAND_FSL_IFC=y
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_NAND_ECC=y
+CONFIG_MTD_M25P80=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
index d1828427ae55ffb7b998e277b36404679352f7cc..fdfa84dc908f21c318f0b0409f0604524f99a2c2 100644 (file)
@@ -46,6 +46,7 @@ CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
+CONFIG_IRQ_ALL_CPUS=y
 CONFIG_FORCE_MAX_ZONEORDER=12
 CONFIG_PCI=y
 CONFIG_PCI_MSI=y
@@ -76,6 +77,30 @@ CONFIG_INET_ESP=y
 CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_FTL=y
+CONFIG_MTD_GEN_PROBE=y
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_FSL_ELBC=y
+CONFIG_MTD_NAND_FSL_IFC=y
+CONFIG_MTD_NAND_IDS=y
+CONFIG_MTD_NAND_ECC=y
+CONFIG_MTD_M25P80=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
index c1442a3758aea9646e16de371d44a919059ddfd4..f2fe0c2b41e48d50b9aec1f7ceedb59dd8efd59c 100644 (file)
@@ -16,6 +16,7 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
 CONFIG_KPROBES=y
+CONFIG_JUMP_LABEL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
@@ -489,3 +490,4 @@ CONFIG_VIRTUALIZATION=y
 CONFIG_KVM_BOOK3S_64=m
 CONFIG_KVM_BOOK3S_64_HV=y
 CONFIG_VHOST_NET=m
+CONFIG_BPF_JIT=y
index 6608232663cb1978b39c431621c77a89c9aec6d0..187fb8d536055c6d42294cf2ce931a6b0a9f1cd8 100644 (file)
@@ -24,6 +24,7 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_PROFILING=y
 CONFIG_OPROFILE=y
 CONFIG_KPROBES=y
+CONFIG_JUMP_LABEL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
index 5d7fbe1950f93dc9e285360637cfc78324db66a6..6e82f5f9a6fd232357eda6737725fb5ed5d4703a 100644 (file)
@@ -29,7 +29,7 @@
 #define PPC_LLARX(t, a, b, eh) PPC_LDARX(t, a, b, eh)
 #define PPC_STLCX      stringify_in_c(stdcx.)
 #define PPC_CNTLZL     stringify_in_c(cntlzd)
-#define PPC_MTOCRF(FXM, RS) MTOCRF((FXM), (RS))
+#define PPC_MTOCRF(FXM, RS) MTOCRF((FXM), RS)
 #define PPC_LR_STKOFF  16
 #define PPC_MIN_STKFRM 112
 #else /* 32-bit */
index 37c32aba79b7f690dc749af1b2c9393719cc27cb..a6f8c7a5cbb74f61925243a1ca42bc183d80361a 100644 (file)
@@ -26,8 +26,8 @@ unsigned int create_branch(const unsigned int *addr,
                           unsigned long target, int flags);
 unsigned int create_cond_branch(const unsigned int *addr,
                                unsigned long target, int flags);
-void patch_branch(unsigned int *addr, unsigned long target, int flags);
-void patch_instruction(unsigned int *addr, unsigned int instr);
+int patch_branch(unsigned int *addr, unsigned long target, int flags);
+int patch_instruction(unsigned int *addr, unsigned int instr);
 
 int instr_is_relative_branch(unsigned int instr);
 int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr);
index 63d5ca49cece245e79f83f3c08b150de18d508a3..77e97dd0c15d8b495ee245a3fbcc14aa38a2f785 100644 (file)
@@ -34,6 +34,9 @@ struct dev_archdata {
 #ifdef CONFIG_EEH
        struct eeh_dev          *edev;
 #endif
+#ifdef CONFIG_FAIL_IOMMU
+       int fail_iommu;
+#endif
 };
 
 struct pdev_archdata {
index d58fc4e4149cb11c69abf8cb462c7e7021cf822a..a43c1473915fd745cc50cb8b574065ce7ad12507 100644 (file)
@@ -293,7 +293,7 @@ label##_hv:                                                         \
 
 #define RUNLATCH_ON                            \
 BEGIN_FTR_SECTION                              \
-       clrrdi  r3,r1,THREAD_SHIFT;             \
+       CURRENT_THREAD_INFO(r3, r1);            \
        ld      r4,TI_LOCAL_FLAGS(r3);          \
        andi.   r0,r4,_TLF_RUNLATCH;            \
        beql    ppc64_runlatch_on_trampoline;   \
@@ -332,7 +332,7 @@ label##_common:                                                     \
 #ifdef CONFIG_PPC_970_NAP
 #define FINISH_NAP                             \
 BEGIN_FTR_SECTION                              \
-       clrrdi  r11,r1,THREAD_SHIFT;            \
+       CURRENT_THREAD_INFO(r11, r1);           \
        ld      r9,TI_LOCAL_FLAGS(r11);         \
        andi.   r10,r9,_TLF_NAPPING;            \
        bnel    power4_fixup_nap;               \
index 0edb6842b13ddc461c55c961170a4f0a9eaac4b0..61e8490786b808af0d93cb18729cb8b32c14bdec 100644 (file)
@@ -26,7 +26,9 @@
 struct qe_iram {
        __be32  iadd;           /* I-RAM Address Register */
        __be32  idata;          /* I-RAM Data Register */
-       u8      res0[0x78];
+       u8      res0[0x04];
+       __be32  iready;         /* I-RAM Ready Register */
+       u8      res1[0x70];
 } __attribute__ ((packed));
 
 /* QE Interrupt Controller */
index a3855b81eada2ed893a6d272198e6add4b85752e..f94ef4213e9d03f80e1c0f180ea9a75d966358ad 100644 (file)
@@ -20,6 +20,14 @@ extern int check_legacy_ioport(unsigned long base_port);
 #define _PNPWRP                0xa79
 #define PNPBIOS_BASE   0xf000
 
+#if defined(CONFIG_PPC64) && defined(CONFIG_PCI)
+extern struct pci_dev *isa_bridge_pcidev;
+/*
+ * has legacy ISA devices ?
+ */
+#define arch_has_dev_port()    (isa_bridge_pcidev != NULL)
+#endif
+
 #include <linux/device.h>
 #include <linux/io.h>
 
index 957a83f436465e52256855730a51ef307a7f6bdf..cbfe678e3dbea1ac8b33a087d736e3d102a741a4 100644 (file)
@@ -53,6 +53,16 @@ static __inline__ __attribute_const__ int get_iommu_order(unsigned long size)
  */
 #define IOMAP_MAX_ORDER                13
 
+#define IOMMU_POOL_HASHBITS    2
+#define IOMMU_NR_POOLS         (1 << IOMMU_POOL_HASHBITS)
+
+struct iommu_pool {
+       unsigned long start;
+       unsigned long end;
+       unsigned long hint;
+       spinlock_t lock;
+} ____cacheline_aligned_in_smp;
+
 struct iommu_table {
        unsigned long  it_busno;     /* Bus number this table belongs to */
        unsigned long  it_size;      /* Size of iommu table in entries */
@@ -61,10 +71,10 @@ struct iommu_table {
        unsigned long  it_index;     /* which iommu table this is */
        unsigned long  it_type;      /* type: PCI or Virtual Bus */
        unsigned long  it_blocksize; /* Entries in each block (cacheline) */
-       unsigned long  it_hint;      /* Hint for next alloc */
-       unsigned long  it_largehint; /* Hint for large allocs */
-       unsigned long  it_halfpoint; /* Breaking point for small/large allocs */
-       spinlock_t     it_lock;      /* Protects it_map */
+       unsigned long  poolsize;
+       unsigned long  nr_pools;
+       struct iommu_pool large_pool;
+       struct iommu_pool pools[IOMMU_NR_POOLS];
        unsigned long *it_map;       /* A simple allocation bitmap for now */
 };
 
index 88609b23b775460c96a4d9d805feaf49fecf94a3..bfcd00c1485d04474c00461d4f7b9097bd624fb4 100644 (file)
@@ -74,6 +74,7 @@ struct kvmppc_host_state {
        ulong vmhandler;
        ulong scratch0;
        ulong scratch1;
+       ulong sprg3;
        u8 in_guest;
        u8 restore_hid5;
        u8 napping;
index f0145522cfbae427805cad72ac900d3d3432ea06..e8a26db2e8f320920123c4e0c0eed0eab8eb60d8 100644 (file)
@@ -163,12 +163,7 @@ extern u64 ppc64_rma_size;
  * to think about, feedback welcome. --BenH.
  */
 
-/* There are #define as they have to be used in assembly
- *
- * WARNING: If you change this list, make sure to update the array of
- * names currently in arch/powerpc/mm/hugetlbpage.c or bad things will
- * happen
- */
+/* These are #defines as they have to be used in assembly */
 #define MMU_PAGE_4K    0
 #define MMU_PAGE_16K   1
 #define MMU_PAGE_64K   2
index 5c16b891d501f8f3943a10311d1020da608843d1..0bb23725b1e721a0d5e89f23db233f15b8a9b3ac 100644 (file)
 #include <asm/ptrace.h>
 #include <asm/reg.h>
 
+/*
+ * Overload regs->result to specify whether we should use the MSR (result
+ * is zero) or the SIAR (result is non zero).
+ */
 #define perf_arch_fetch_caller_regs(regs, __ip)                        \
        do {                                                    \
+               (regs)->result = 0;                             \
                (regs)->nip = __ip;                             \
                (regs)->gpr[1] = *(unsigned long *)__get_SP();  \
                asm volatile("mfmsr %0" : "=r" ((regs)->msr));  \
index d81f99430fe75b9b7b53ebe38337ee9184091eb4..4c25319f2fbcf010e8b8763f93f09fcc47014a84 100644 (file)
 #include <linux/stringify.h>
 #include <asm/asm-compat.h>
 
+#define        __REG_R0        0
+#define        __REG_R1        1
+#define        __REG_R2        2
+#define        __REG_R3        3
+#define        __REG_R4        4
+#define        __REG_R5        5
+#define        __REG_R6        6
+#define        __REG_R7        7
+#define        __REG_R8        8
+#define        __REG_R9        9
+#define        __REG_R10       10
+#define        __REG_R11       11
+#define        __REG_R12       12
+#define        __REG_R13       13
+#define        __REG_R14       14
+#define        __REG_R15       15
+#define        __REG_R16       16
+#define        __REG_R17       17
+#define        __REG_R18       18
+#define        __REG_R19       19
+#define        __REG_R20       20
+#define        __REG_R21       21
+#define        __REG_R22       22
+#define        __REG_R23       23
+#define        __REG_R24       24
+#define        __REG_R25       25
+#define        __REG_R26       26
+#define        __REG_R27       27
+#define        __REG_R28       28
+#define        __REG_R29       29
+#define        __REG_R30       30
+#define        __REG_R31       31
+
+#define        __REGA0_0       0
+#define        __REGA0_R1      1
+#define        __REGA0_R2      2
+#define        __REGA0_R3      3
+#define        __REGA0_R4      4
+#define        __REGA0_R5      5
+#define        __REGA0_R6      6
+#define        __REGA0_R7      7
+#define        __REGA0_R8      8
+#define        __REGA0_R9      9
+#define        __REGA0_R10     10
+#define        __REGA0_R11     11
+#define        __REGA0_R12     12
+#define        __REGA0_R13     13
+#define        __REGA0_R14     14
+#define        __REGA0_R15     15
+#define        __REGA0_R16     16
+#define        __REGA0_R17     17
+#define        __REGA0_R18     18
+#define        __REGA0_R19     19
+#define        __REGA0_R20     20
+#define        __REGA0_R21     21
+#define        __REGA0_R22     22
+#define        __REGA0_R23     23
+#define        __REGA0_R24     24
+#define        __REGA0_R25     25
+#define        __REGA0_R26     26
+#define        __REGA0_R27     27
+#define        __REGA0_R28     28
+#define        __REGA0_R29     29
+#define        __REGA0_R30     30
+#define        __REGA0_R31     31
+
 /* sorted alphabetically */
 #define PPC_INST_DCBA                  0x7c0005ec
 #define PPC_INST_DCBA_MASK             0xfc0007fe
 #define PPC_INST_NEG                   0x7c0000d0
 #define PPC_INST_BRANCH                        0x48000000
 #define PPC_INST_BRANCH_COND           0x40800000
+#define PPC_INST_LBZCIX                        0x7c0006aa
+#define PPC_INST_STBCIX                        0x7c0007aa
 
 /* macros to insert fields into opcodes */
-#define __PPC_RA(a)    (((a) & 0x1f) << 16)
-#define __PPC_RB(b)    (((b) & 0x1f) << 11)
-#define __PPC_RS(s)    (((s) & 0x1f) << 21)
-#define __PPC_RT(s)    __PPC_RS(s)
+#define ___PPC_RA(a)   (((a) & 0x1f) << 16)
+#define ___PPC_RB(b)   (((b) & 0x1f) << 11)
+#define ___PPC_RS(s)   (((s) & 0x1f) << 21)
+#define ___PPC_RT(t)   ___PPC_RS(t)
+#define __PPC_RA(a)    ___PPC_RA(__REG_##a)
+#define __PPC_RA0(a)   ___PPC_RA(__REGA0_##a)
+#define __PPC_RB(b)    ___PPC_RB(__REG_##b)
+#define __PPC_RS(s)    ___PPC_RS(__REG_##s)
+#define __PPC_RT(t)    ___PPC_RT(__REG_##t)
 #define __PPC_XA(a)    ((((a) & 0x1f) << 16) | (((a) & 0x20) >> 3))
 #define __PPC_XB(b)    ((((b) & 0x1f) << 11) | (((b) & 0x20) >> 4))
 #define __PPC_XS(s)    ((((s) & 0x1f) << 21) | (((s) & 0x20) >> 5))
 #define        PPC_DCBZL(a, b)         stringify_in_c(.long PPC_INST_DCBZL | \
                                        __PPC_RA(a) | __PPC_RB(b))
 #define PPC_LDARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LDARX | \
-                                       __PPC_RT(t) | __PPC_RA(a) | \
-                                       __PPC_RB(b) | __PPC_EH(eh))
+                                       ___PPC_RT(t) | ___PPC_RA(a) | \
+                                       ___PPC_RB(b) | __PPC_EH(eh))
 #define PPC_LWARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LWARX | \
-                                       __PPC_RT(t) | __PPC_RA(a) | \
-                                       __PPC_RB(b) | __PPC_EH(eh))
+                                       ___PPC_RT(t) | ___PPC_RA(a) | \
+                                       ___PPC_RB(b) | __PPC_EH(eh))
 #define PPC_MSGSND(b)          stringify_in_c(.long PPC_INST_MSGSND | \
-                                       __PPC_RB(b))
+                                       ___PPC_RB(b))
 #define PPC_POPCNTB(a, s)      stringify_in_c(.long PPC_INST_POPCNTB | \
                                        __PPC_RA(a) | __PPC_RS(s))
 #define PPC_POPCNTD(a, s)      stringify_in_c(.long PPC_INST_POPCNTD | \
 #define PPC_RFDI               stringify_in_c(.long PPC_INST_RFDI)
 #define PPC_RFMCI              stringify_in_c(.long PPC_INST_RFMCI)
 #define PPC_TLBILX(t, a, b)    stringify_in_c(.long PPC_INST_TLBILX | \
-                                       __PPC_T_TLB(t) | __PPC_RA(a) | __PPC_RB(b))
+                                       __PPC_T_TLB(t) | __PPC_RA0(a) | __PPC_RB(b))
 #define PPC_TLBILX_ALL(a, b)   PPC_TLBILX(0, a, b)
 #define PPC_TLBILX_PID(a, b)   PPC_TLBILX(1, a, b)
 #define PPC_TLBILX_VA(a, b)    PPC_TLBILX(3, a, b)
 #define PPC_WAIT(w)            stringify_in_c(.long PPC_INST_WAIT | \
                                        __PPC_WC(w))
 #define PPC_TLBIE(lp,a)        stringify_in_c(.long PPC_INST_TLBIE | \
-                                              __PPC_RB(a) | __PPC_RS(lp))
+                                              ___PPC_RB(a) | ___PPC_RS(lp))
 #define PPC_TLBSRX_DOT(a,b)    stringify_in_c(.long PPC_INST_TLBSRX_DOT | \
-                                       __PPC_RA(a) | __PPC_RB(b))
+                                       __PPC_RA0(a) | __PPC_RB(b))
 #define PPC_TLBIVAX(a,b)       stringify_in_c(.long PPC_INST_TLBIVAX | \
-                                       __PPC_RA(a) | __PPC_RB(b))
+                                       __PPC_RA0(a) | __PPC_RB(b))
 
 #define PPC_ERATWE(s, a, w)    stringify_in_c(.long PPC_INST_ERATWE | \
                                        __PPC_RS(s) | __PPC_RA(a) | __PPC_WS(w))
 #define PPC_ERATRE(s, a, w)    stringify_in_c(.long PPC_INST_ERATRE | \
                                        __PPC_RS(s) | __PPC_RA(a) | __PPC_WS(w))
 #define PPC_ERATILX(t, a, b)   stringify_in_c(.long PPC_INST_ERATILX | \
-                                       __PPC_T_TLB(t) | __PPC_RA(a) | \
+                                       __PPC_T_TLB(t) | __PPC_RA0(a) | \
                                        __PPC_RB(b))
 #define PPC_ERATIVAX(s, a, b)  stringify_in_c(.long PPC_INST_ERATIVAX | \
-                                       __PPC_RS(s) | __PPC_RA(a) | __PPC_RB(b))
+                                       __PPC_RS(s) | __PPC_RA0(a) | __PPC_RB(b))
 #define PPC_ERATSX(t, a, w)    stringify_in_c(.long PPC_INST_ERATSX | \
-                                       __PPC_RS(t) | __PPC_RA(a) | __PPC_RB(b))
+                                       __PPC_RS(t) | __PPC_RA0(a) | __PPC_RB(b))
 #define PPC_ERATSX_DOT(t, a, w)        stringify_in_c(.long PPC_INST_ERATSX_DOT | \
-                                       __PPC_RS(t) | __PPC_RA(a) | __PPC_RB(b))
+                                       __PPC_RS(t) | __PPC_RA0(a) | __PPC_RB(b))
 #define PPC_SLBFEE_DOT(t, b)   stringify_in_c(.long PPC_INST_SLBFEE | \
                                        __PPC_RT(t) | __PPC_RB(b))
+/* PASemi instructions */
+#define LBZCIX(t,a,b)          stringify_in_c(.long PPC_INST_LBZCIX | \
+                                      __PPC_RT(t) | __PPC_RA(a) | __PPC_RB(b))
+#define STBCIX(s,a,b)          stringify_in_c(.long PPC_INST_STBCIX | \
+                                      __PPC_RS(s) | __PPC_RA(a) | __PPC_RB(b))
 
 /*
  * Define what the VSX XX1 form instructions will look like, then add
 #define VSX_XX1(s, a, b)       (__PPC_XS(s) | __PPC_RA(a) | __PPC_RB(b))
 #define VSX_XX3(t, a, b)       (__PPC_XT(t) | __PPC_XA(a) | __PPC_XB(b))
 #define STXVD2X(s, a, b)       stringify_in_c(.long PPC_INST_STXVD2X | \
-                                              VSX_XX1((s), (a), (b)))
+                                              VSX_XX1((s), a, b))
 #define LXVD2X(s, a, b)                stringify_in_c(.long PPC_INST_LXVD2X | \
-                                              VSX_XX1((s), (a), (b)))
+                                              VSX_XX1((s), a, b))
 #define XXLOR(t, a, b)         stringify_in_c(.long PPC_INST_XXLOR | \
-                                              VSX_XX3((t), (a), (b)))
+                                              VSX_XX3((t), a, b))
 
 #define PPC_NAP                        stringify_in_c(.long PPC_INST_NAP)
 #define PPC_SLEEP              stringify_in_c(.long PPC_INST_SLEEP)
index 15444204a3a1d25049bca2b8115c7e88ed3d2d4f..ea2a86e8ff95bf731a399850cf2c8934b3fa8a19 100644 (file)
@@ -126,26 +126,26 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
 #define REST_32VRS(n,b,base)   REST_16VRS(n,b,base); REST_16VRS(n+16,b,base)
 
 /* Save the lower 32 VSRs in the thread VSR region */
-#define SAVE_VSR(n,b,base)     li b,THREAD_VSR0+(16*(n));  STXVD2X(n,base,b)
+#define SAVE_VSR(n,b,base)     li b,THREAD_VSR0+(16*(n));  STXVD2X(n,R##base,R##b)
 #define SAVE_2VSRS(n,b,base)   SAVE_VSR(n,b,base); SAVE_VSR(n+1,b,base)
 #define SAVE_4VSRS(n,b,base)   SAVE_2VSRS(n,b,base); SAVE_2VSRS(n+2,b,base)
 #define SAVE_8VSRS(n,b,base)   SAVE_4VSRS(n,b,base); SAVE_4VSRS(n+4,b,base)
 #define SAVE_16VSRS(n,b,base)  SAVE_8VSRS(n,b,base); SAVE_8VSRS(n+8,b,base)
 #define SAVE_32VSRS(n,b,base)  SAVE_16VSRS(n,b,base); SAVE_16VSRS(n+16,b,base)
-#define REST_VSR(n,b,base)     li b,THREAD_VSR0+(16*(n)); LXVD2X(n,base,b)
+#define REST_VSR(n,b,base)     li b,THREAD_VSR0+(16*(n)); LXVD2X(n,R##base,R##b)
 #define REST_2VSRS(n,b,base)   REST_VSR(n,b,base); REST_VSR(n+1,b,base)
 #define REST_4VSRS(n,b,base)   REST_2VSRS(n,b,base); REST_2VSRS(n+2,b,base)
 #define REST_8VSRS(n,b,base)   REST_4VSRS(n,b,base); REST_4VSRS(n+4,b,base)
 #define REST_16VSRS(n,b,base)  REST_8VSRS(n,b,base); REST_8VSRS(n+8,b,base)
 #define REST_32VSRS(n,b,base)  REST_16VSRS(n,b,base); REST_16VSRS(n+16,b,base)
 /* Save the upper 32 VSRs (32-63) in the thread VSX region (0-31) */
-#define SAVE_VSRU(n,b,base)    li b,THREAD_VR0+(16*(n));  STXVD2X(n+32,base,b)
+#define SAVE_VSRU(n,b,base)    li b,THREAD_VR0+(16*(n));  STXVD2X(n+32,R##base,R##b)
 #define SAVE_2VSRSU(n,b,base)  SAVE_VSRU(n,b,base); SAVE_VSRU(n+1,b,base)
 #define SAVE_4VSRSU(n,b,base)  SAVE_2VSRSU(n,b,base); SAVE_2VSRSU(n+2,b,base)
 #define SAVE_8VSRSU(n,b,base)  SAVE_4VSRSU(n,b,base); SAVE_4VSRSU(n+4,b,base)
 #define SAVE_16VSRSU(n,b,base) SAVE_8VSRSU(n,b,base); SAVE_8VSRSU(n+8,b,base)
 #define SAVE_32VSRSU(n,b,base) SAVE_16VSRSU(n,b,base); SAVE_16VSRSU(n+16,b,base)
-#define REST_VSRU(n,b,base)    li b,THREAD_VR0+(16*(n)); LXVD2X(n+32,base,b)
+#define REST_VSRU(n,b,base)    li b,THREAD_VR0+(16*(n)); LXVD2X(n+32,R##base,R##b)
 #define REST_2VSRSU(n,b,base)  REST_VSRU(n,b,base); REST_VSRU(n+1,b,base)
 #define REST_4VSRSU(n,b,base)  REST_2VSRSU(n,b,base); REST_2VSRSU(n+2,b,base)
 #define REST_8VSRSU(n,b,base)  REST_4VSRSU(n,b,base); REST_4VSRSU(n+4,b,base)
@@ -178,9 +178,24 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
 #define HMT_HIGH       or      3,3,3
 #define HMT_EXTRA_HIGH or      7,7,7           # power7 only
 
+#ifdef CONFIG_PPC64
+#define ULONG_SIZE     8
+#else
+#define ULONG_SIZE     4
+#endif
+#define __VCPU_GPR(n)  (VCPU_GPRS + (n * ULONG_SIZE))
+#define VCPU_GPR(n)    __VCPU_GPR(__REG_##n)
+
 #ifdef __KERNEL__
 #ifdef CONFIG_PPC64
 
+#define STACKFRAMESIZE 256
+#define __STK_REG(i)   (112 + ((i)-14)*8)
+#define STK_REG(i)     __STK_REG(__REG_##i)
+
+#define __STK_PARAM(i) (48 + ((i)-3)*8)
+#define STK_PARAM(i)   __STK_PARAM(__REG_##i)
+
 #define XGLUE(a,b) a##b
 #define GLUE(a,b) XGLUE(a,b)
 
@@ -295,14 +310,14 @@ n:
  */
 #ifdef __powerpc64__
 #define LOAD_REG_IMMEDIATE(reg,expr)           \
-       lis     (reg),(expr)@highest;           \
-       ori     (reg),(reg),(expr)@higher;      \
-       rldicr  (reg),(reg),32,31;              \
-       oris    (reg),(reg),(expr)@h;           \
-       ori     (reg),(reg),(expr)@l;
+       lis     reg,(expr)@highest;             \
+       ori     reg,reg,(expr)@higher;  \
+       rldicr  reg,reg,32,31;          \
+       oris    reg,reg,(expr)@h;               \
+       ori     reg,reg,(expr)@l;
 
 #define LOAD_REG_ADDR(reg,name)                        \
-       ld      (reg),name@got(r2)
+       ld      reg,name@got(r2)
 
 #define LOAD_REG_ADDRBASE(reg,name)    LOAD_REG_ADDR(reg,name)
 #define ADDROFF(name)                  0
@@ -313,12 +328,12 @@ n:
 #else /* 32-bit */
 
 #define LOAD_REG_IMMEDIATE(reg,expr)           \
-       lis     (reg),(expr)@ha;                \
-       addi    (reg),(reg),(expr)@l;
+       lis     reg,(expr)@ha;          \
+       addi    reg,reg,(expr)@l;
 
 #define LOAD_REG_ADDR(reg,name)                LOAD_REG_IMMEDIATE(reg, name)
 
-#define LOAD_REG_ADDRBASE(reg, name)   lis     (reg),name@ha
+#define LOAD_REG_ADDRBASE(reg, name)   lis     reg,name@ha
 #define ADDROFF(name)                  name@l
 
 /* offsets for stack frame layout */
@@ -372,9 +387,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
 #ifdef CONFIG_PPC64
 #define MTOCRF(FXM, RS)                        \
        BEGIN_FTR_SECTION_NESTED(848);  \
-       mtcrf   (FXM), (RS);            \
+       mtcrf   (FXM), RS;              \
        FTR_SECTION_ELSE_NESTED(848);   \
-       mtocrf (FXM), (RS);             \
+       mtocrf (FXM), RS;               \
        ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_NOEXECUTE, 848)
 #endif
 
@@ -463,6 +478,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
 #ifdef CONFIG_PPC_BOOK3S_64
 #define RFI            rfid
 #define MTMSRD(r)      mtmsrd  r
+#define MTMSR_EERI(reg)        mtmsrd  reg,1
 #else
 #define FIX_SRR1(ra, rb)
 #ifndef CONFIG_40x
@@ -471,6 +487,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
 #define RFI            rfi; b .        /* Prevent prefetch past rfi */
 #endif
 #define MTMSRD(r)      mtmsr   r
+#define MTMSR_EERI(reg)        mtmsr   reg
 #define CLR_TOP32(r)
 #endif
 
@@ -490,40 +507,46 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
 #define        cr7     7
 
 
-/* General Purpose Registers (GPRs) */
-
-#define        r0      0
-#define        r1      1
-#define        r2      2
-#define        r3      3
-#define        r4      4
-#define        r5      5
-#define        r6      6
-#define        r7      7
-#define        r8      8
-#define        r9      9
-#define        r10     10
-#define        r11     11
-#define        r12     12
-#define        r13     13
-#define        r14     14
-#define        r15     15
-#define        r16     16
-#define        r17     17
-#define        r18     18
-#define        r19     19
-#define        r20     20
-#define        r21     21
-#define        r22     22
-#define        r23     23
-#define        r24     24
-#define        r25     25
-#define        r26     26
-#define        r27     27
-#define        r28     28
-#define        r29     29
-#define        r30     30
-#define        r31     31
+/*
+ * General Purpose Registers (GPRs)
+ *
+ * The lower case r0-r31 should be used in preference to the upper
+ * case R0-R31 as they provide more error checking in the assembler.
+ * Use R0-31 only when really nessesary.
+ */
+
+#define        r0      %r0
+#define        r1      %r1
+#define        r2      %r2
+#define        r3      %r3
+#define        r4      %r4
+#define        r5      %r5
+#define        r6      %r6
+#define        r7      %r7
+#define        r8      %r8
+#define        r9      %r9
+#define        r10     %r10
+#define        r11     %r11
+#define        r12     %r12
+#define        r13     %r13
+#define        r14     %r14
+#define        r15     %r15
+#define        r16     %r16
+#define        r17     %r17
+#define        r18     %r18
+#define        r19     %r19
+#define        r20     %r20
+#define        r21     %r21
+#define        r22     %r22
+#define        r23     %r23
+#define        r24     %r24
+#define        r25     %r25
+#define        r26     %r26
+#define        r27     %r27
+#define        r28     %r28
+#define        r29     %r29
+#define        r30     %r30
+#define        r31     %r31
 
 
 /* Floating Point Registers (FPRs) */
index 413a5eaef56c94340d16451a0f65e56453c5b38d..53b6dfa83344a9f3dbe6b68ef72c6d60948f26ab 100644 (file)
@@ -389,10 +389,8 @@ extern int powersave_nap;  /* set if nap mode can be used in idle loop */
 
 #ifdef CONFIG_PSERIES_IDLE
 extern void update_smt_snooze_delay(int snooze);
-extern int pseries_notify_cpuidle_add_cpu(int cpu);
 #else
 static inline void update_smt_snooze_delay(int snooze) {}
-static inline int pseries_notify_cpuidle_add_cpu(int cpu) { return 0; }
 #endif
 
 extern void flush_instruction_cache(void);
index 5e0b6d511e14e8843cb5cfdbe181d992d0b1793e..229571a49391366ed5eea30c8ce5d9cf05b91606 100644 (file)
@@ -499,6 +499,7 @@ enum comm_dir {
 /* I-RAM */
 #define QE_IRAM_IADD_AIE       0x80000000      /* Auto Increment Enable */
 #define QE_IRAM_IADD_BADDR     0x00080000      /* Base Address */
+#define QE_IRAM_READY           0x80000000      /* Ready */
 
 /* UPC */
 #define UPGCR_PROTOCOL 0x80000000      /* protocol ul2 or pl2 */
index f0cb7f461b9d5470c2cd61e7428d44e9f10f4238..638608677e2a53679128800323d26d5caa53cd44 100644 (file)
 #define SPRN_SPRG1     0x111   /* Special Purpose Register General 1 */
 #define SPRN_SPRG2     0x112   /* Special Purpose Register General 2 */
 #define SPRN_SPRG3     0x113   /* Special Purpose Register General 3 */
+#define SPRN_USPRG3    0x103   /* SPRG3 userspace read */
 #define SPRN_SPRG4     0x114   /* Special Purpose Register General 4 */
 #define SPRN_SPRG5     0x115   /* Special Purpose Register General 5 */
 #define SPRN_SPRG6     0x116   /* Special Purpose Register General 6 */
  * 64-bit server:
  *     - SPRG0 unused (reserved for HV on Power4)
  *     - SPRG2 scratch for exception vectors
- *     - SPRG3 unused (user visible)
+ *     - SPRG3 CPU and NUMA node for VDSO getcpu (user visible)
  *      - HSPRG0 stores PACA in HV mode
  *      - HSPRG1 scratch for "HV" exceptions
  *
  * 64-bit embedded
  *     - SPRG0 generic exception scratch
  *     - SPRG2 TLB exception stack
- *     - SPRG3 unused (user visible)
+ *     - SPRG3 CPU and NUMA node for VDSO getcpu (user visible)
  *     - SPRG4 unused (user visible)
  *     - SPRG6 TLB miss scratch (user visible, sorry !)
  *     - SPRG7 critical exception scratch
 /* Macros for setting and retrieving special purpose registers */
 #ifndef __ASSEMBLY__
 #define mfmsr()                ({unsigned long rval; \
-                       asm volatile("mfmsr %0" : "=r" (rval)); rval;})
+                       asm volatile("mfmsr %0" : "=r" (rval) : \
+                                               : "memory"); rval;})
 #ifdef CONFIG_PPC_BOOK3S_64
 #define __mtmsrd(v, l) asm volatile("mtmsrd %0," __stringify(l) \
                                     : : "r" (v) : "memory")
index 68831e9cf82f01ddf8f12164962d8db438b93af3..faf93529cbf087876049790c2e1ef30fb29c5cd7 100644 (file)
 
 #define THREAD_SIZE            (1 << THREAD_SHIFT)
 
+#ifdef CONFIG_PPC64
+#define CURRENT_THREAD_INFO(dest, sp)  clrrdi dest, sp, THREAD_SHIFT
+#else
+#define CURRENT_THREAD_INFO(dest, sp)  rlwinm dest, sp, 0, 0, 31-THREAD_SHIFT
+#endif
+
 #ifndef __ASSEMBLY__
 #include <linux/cache.h>
 #include <asm/processor.h>
index cbe2297d68b6465ceeb204fbd4eeb863cdc7a1b0..5712f06905a92432ab09959762452ae662c9678f 100644 (file)
@@ -8,7 +8,7 @@
 
 struct pt_regs;
 
-TRACE_EVENT(irq_entry,
+DECLARE_EVENT_CLASS(ppc64_interrupt_class,
 
        TP_PROTO(struct pt_regs *regs),
 
@@ -25,55 +25,32 @@ TRACE_EVENT(irq_entry,
        TP_printk("pt_regs=%p", __entry->regs)
 );
 
-TRACE_EVENT(irq_exit,
+DEFINE_EVENT(ppc64_interrupt_class, irq_entry,
 
        TP_PROTO(struct pt_regs *regs),
 
-       TP_ARGS(regs),
-
-       TP_STRUCT__entry(
-               __field(struct pt_regs *, regs)
-       ),
-
-       TP_fast_assign(
-               __entry->regs = regs;
-       ),
-
-       TP_printk("pt_regs=%p", __entry->regs)
+       TP_ARGS(regs)
 );
 
-TRACE_EVENT(timer_interrupt_entry,
+DEFINE_EVENT(ppc64_interrupt_class, irq_exit,
 
        TP_PROTO(struct pt_regs *regs),
 
-       TP_ARGS(regs),
-
-       TP_STRUCT__entry(
-               __field(struct pt_regs *, regs)
-       ),
-
-       TP_fast_assign(
-               __entry->regs = regs;
-       ),
-
-       TP_printk("pt_regs=%p", __entry->regs)
+       TP_ARGS(regs)
 );
 
-TRACE_EVENT(timer_interrupt_exit,
+DEFINE_EVENT(ppc64_interrupt_class, timer_interrupt_entry,
 
        TP_PROTO(struct pt_regs *regs),
 
-       TP_ARGS(regs),
+       TP_ARGS(regs)
+);
 
-       TP_STRUCT__entry(
-               __field(struct pt_regs *, regs)
-       ),
+DEFINE_EVENT(ppc64_interrupt_class, timer_interrupt_exit,
 
-       TP_fast_assign(
-               __entry->regs = regs;
-       ),
+       TP_PROTO(struct pt_regs *regs),
 
-       TP_printk("pt_regs=%p", __entry->regs)
+       TP_ARGS(regs)
 );
 
 #ifdef CONFIG_PPC_PSERIES
index dc0419b66f17ac1f676bf247f8706b0a1a08b9f2..50f261bc3e9595a1ad972a63af1f14073710c105 100644 (file)
@@ -22,6 +22,8 @@ extern unsigned long vdso64_rt_sigtramp;
 extern unsigned long vdso32_sigtramp;
 extern unsigned long vdso32_rt_sigtramp;
 
+int __cpuinit vdso_getcpu_init(void);
+
 #else /* __ASSEMBLY__ */
 
 #ifdef __VDSO64__
index b19adf751dd954c492b7afc062a76df896ef6b61..df81cb72d1e08a805a94fe267b9dcc712a199459 100644 (file)
@@ -44,6 +44,8 @@
  */
 #define VIO_CMO_MIN_ENT 1562624
 
+extern struct bus_type vio_bus_type;
+
 struct iommu_table;
 
 /*
index 52c7ad78242ebd95c16d950424552d6a4741018e..85b05c463fae9077b4490bacfa80c31050a617fa 100644 (file)
@@ -533,6 +533,7 @@ int main(void)
        HSTATE_FIELD(HSTATE_VMHANDLER, vmhandler);
        HSTATE_FIELD(HSTATE_SCRATCH0, scratch0);
        HSTATE_FIELD(HSTATE_SCRATCH1, scratch1);
+       HSTATE_FIELD(HSTATE_SPRG3, sprg3);
        HSTATE_FIELD(HSTATE_IN_GUEST, in_guest);
        HSTATE_FIELD(HSTATE_RESTORE_HID5, restore_hid5);
        HSTATE_FIELD(HSTATE_NAPPING, napping);
index ebc62f42a2372105cb6b6722cb4fbb95d426a35a..61f079e05b61191d5ffb845dcfdd8f8e27bf132d 100644 (file)
@@ -100,19 +100,19 @@ _icswx_skip_guest:
        lis     r4,(MMUCR0_TLBSEL_I|MMUCR0_ECL)@h
        mtspr   SPRN_MMUCR0, r4
        li      r4,A2_IERAT_SIZE-1
-       PPC_ERATWE(r4,r4,3)
+       PPC_ERATWE(R4,R4,3)
 
        /* Now set the D-ERAT watermark to 31 */
        lis     r4,(MMUCR0_TLBSEL_D|MMUCR0_ECL)@h
        mtspr   SPRN_MMUCR0, r4
        li      r4,A2_DERAT_SIZE-1
-       PPC_ERATWE(r4,r4,3)
+       PPC_ERATWE(R4,R4,3)
 
        /* And invalidate the beast just in case. That won't get rid of
         * a bolted entry though it will be in LRU and so will go away eventually
         * but let's not bother for now
         */
-       PPC_ERATILX(0,0,0)
+       PPC_ERATILX(0,0,R0)
 1:
        blr
 
index b1ec983dcec8954ada2bf1cd9937c9d52706b333..289be751cd756b71220d90fb7d3820824976bd83 100644 (file)
@@ -11,6 +11,8 @@
 #include <linux/gfp.h>
 #include <linux/memblock.h>
 #include <linux/export.h>
+#include <linux/pci.h>
+#include <asm/vio.h>
 #include <asm/bug.h>
 #include <asm/abs_addr.h>
 #include <asm/machdep.h>
@@ -205,7 +207,13 @@ EXPORT_SYMBOL_GPL(dma_get_required_mask);
 
 static int __init dma_init(void)
 {
-       dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+       dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
+#ifdef CONFIG_PCI
+       dma_debug_add_bus(&pci_bus_type);
+#endif
+#ifdef CONFIG_IBMVIO
+       dma_debug_add_bus(&vio_bus_type);
+#endif
 
        return 0;
 }
index ba3aeb4bc06a81453105c6294bd74b81b340ed77..5207d5a405e2a7302edcea701bdf384c4e8772e6 100644 (file)
@@ -92,7 +92,7 @@ crit_transfer_to_handler:
        mfspr   r8,SPRN_SPRG_THREAD
        lwz     r0,KSP_LIMIT(r8)
        stw     r0,SAVED_KSP_LIMIT(r11)
-       rlwimi  r0,r1,0,0,(31-THREAD_SHIFT)
+       CURRENT_THREAD_INFO(r0, r1)
        stw     r0,KSP_LIMIT(r8)
        /* fall through */
 #endif
@@ -112,7 +112,7 @@ crit_transfer_to_handler:
        mfspr   r8,SPRN_SPRG_THREAD
        lwz     r0,KSP_LIMIT(r8)
        stw     r0,saved_ksp_limit@l(0)
-       rlwimi  r0,r1,0,0,(31-THREAD_SHIFT)
+       CURRENT_THREAD_INFO(r0, r1)
        stw     r0,KSP_LIMIT(r8)
        /* fall through */
 #endif
@@ -158,7 +158,7 @@ transfer_to_handler:
        tophys(r11,r11)
        addi    r11,r11,global_dbcr0@l
 #ifdef CONFIG_SMP
-       rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
+       CURRENT_THREAD_INFO(r9, r1)
        lwz     r9,TI_CPU(r9)
        slwi    r9,r9,3
        add     r11,r11,r9
@@ -179,7 +179,7 @@ transfer_to_handler:
        ble-    stack_ovf               /* then the kernel stack overflowed */
 5:
 #if defined(CONFIG_6xx) || defined(CONFIG_E500)
-       rlwinm  r9,r1,0,0,31-THREAD_SHIFT
+       CURRENT_THREAD_INFO(r9, r1)
        tophys(r9,r9)                   /* check local flags */
        lwz     r12,TI_LOCAL_FLAGS(r9)
        mtcrf   0x01,r12
@@ -226,13 +226,7 @@ reenable_mmu:                              /* re-enable mmu so we can */
        stw     r3,16(r1)
        stw     r4,20(r1)
        stw     r5,24(r1)
-       andi.   r12,r12,MSR_PR
-       b       11f
        bl      trace_hardirqs_off
-       b       12f
-11:
-       bl      trace_hardirqs_off
-12:
        lwz     r5,24(r1)
        lwz     r4,20(r1)
        lwz     r3,16(r1)
@@ -333,7 +327,7 @@ _GLOBAL(DoSyscall)
        mtmsr   r11
 1:
 #endif /* CONFIG_TRACE_IRQFLAGS */
-       rlwinm  r10,r1,0,0,(31-THREAD_SHIFT)    /* current_thread_info() */
+       CURRENT_THREAD_INFO(r10, r1)
        lwz     r11,TI_FLAGS(r10)
        andi.   r11,r11,_TIF_SYSCALL_T_OR_A
        bne-    syscall_dotrace
@@ -354,7 +348,7 @@ ret_from_syscall:
        bl      do_show_syscall_exit
 #endif
        mr      r6,r3
-       rlwinm  r12,r1,0,0,(31-THREAD_SHIFT)    /* current_thread_info() */
+       CURRENT_THREAD_INFO(r12, r1)
        /* disable interrupts so current_thread_info()->flags can't change */
        LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */
        /* Note: We don't bother telling lockdep about it */
@@ -815,7 +809,7 @@ ret_from_except:
 
 user_exc_return:               /* r10 contains MSR_KERNEL here */
        /* Check current_thread_info()->flags */
-       rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
+       CURRENT_THREAD_INFO(r9, r1)
        lwz     r9,TI_FLAGS(r9)
        andi.   r0,r9,_TIF_USER_WORK_MASK
        bne     do_work
@@ -835,7 +829,7 @@ restore_user:
 /* N.B. the only way to get here is from the beq following ret_from_except. */
 resume_kernel:
        /* check current_thread_info->preempt_count */
-       rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
+       CURRENT_THREAD_INFO(r9, r1)
        lwz     r0,TI_PREEMPT(r9)
        cmpwi   0,r0,0          /* if non-zero, just restore regs and return */
        bne     restore
@@ -852,7 +846,7 @@ resume_kernel:
        bl      trace_hardirqs_off
 #endif
 1:     bl      preempt_schedule_irq
-       rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
+       CURRENT_THREAD_INFO(r9, r1)
        lwz     r3,TI_FLAGS(r9)
        andi.   r0,r3,_TIF_NEED_RESCHED
        bne-    1b
@@ -1122,7 +1116,7 @@ ret_from_debug_exc:
        lwz     r10,SAVED_KSP_LIMIT(r1)
        stw     r10,KSP_LIMIT(r9)
        lwz     r9,THREAD_INFO-THREAD(r9)
-       rlwinm  r10,r1,0,0,(31-THREAD_SHIFT)
+       CURRENT_THREAD_INFO(r10, r1)
        lwz     r10,TI_PREEMPT(r10)
        stw     r10,TI_PREEMPT(r9)
        RESTORE_xSRR(SRR0,SRR1);
@@ -1156,7 +1150,7 @@ load_dbcr0:
        lis     r11,global_dbcr0@ha
        addi    r11,r11,global_dbcr0@l
 #ifdef CONFIG_SMP
-       rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
+       CURRENT_THREAD_INFO(r9, r1)
        lwz     r9,TI_CPU(r9)
        slwi    r9,r9,3
        add     r11,r11,r9
@@ -1197,7 +1191,7 @@ recheck:
        LOAD_MSR_KERNEL(r10,MSR_KERNEL)
        SYNC
        MTMSRD(r10)             /* disable interrupts */
-       rlwinm  r9,r1,0,0,(31-THREAD_SHIFT)
+       CURRENT_THREAD_INFO(r9, r1)
        lwz     r9,TI_FLAGS(r9)
        andi.   r0,r9,_TIF_NEED_RESCHED
        bne-    do_resched
index 5971c85df1369780decc5dbc6feb0b10f9d23a05..4b01a25e29ef61ea5cdeb07a14939142ba1ecdd9 100644 (file)
@@ -146,7 +146,7 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR)
        REST_2GPRS(7,r1)
        addi    r9,r1,STACK_FRAME_OVERHEAD
 #endif
-       clrrdi  r11,r1,THREAD_SHIFT
+       CURRENT_THREAD_INFO(r11, r1)
        ld      r10,TI_FLAGS(r11)
        andi.   r11,r10,_TIF_SYSCALL_T_OR_A
        bne-    syscall_dotrace
@@ -181,7 +181,7 @@ syscall_exit:
        bl      .do_show_syscall_exit
        ld      r3,RESULT(r1)
 #endif
-       clrrdi  r12,r1,THREAD_SHIFT
+       CURRENT_THREAD_INFO(r12, r1)
 
        ld      r8,_MSR(r1)
 #ifdef CONFIG_PPC_BOOK3S
@@ -197,7 +197,16 @@ syscall_exit:
        wrteei  0
 #else
        ld      r10,PACAKMSR(r13)
-       mtmsrd  r10,1
+       /*
+        * For performance reasons we clear RI the same time that we
+        * clear EE. We only need to clear RI just before we restore r13
+        * below, but batching it with EE saves us one expensive mtmsrd call.
+        * We have to be careful to restore RI if we branch anywhere from
+        * here (eg syscall_exit_work).
+        */
+       li      r9,MSR_RI
+       andc    r11,r10,r9
+       mtmsrd  r11,1
 #endif /* CONFIG_PPC_BOOK3E */
 
        ld      r9,TI_FLAGS(r12)
@@ -214,17 +223,6 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS)
        andi.   r6,r8,MSR_PR
        ld      r4,_LINK(r1)
-       /*
-        * Clear RI before restoring r13.  If we are returning to
-        * userspace and we take an exception after restoring r13,
-        * we end up corrupting the userspace r13 value.
-        */
-#ifdef CONFIG_PPC_BOOK3S
-       /* No MSR:RI on BookE */
-       li      r12,MSR_RI
-       andc    r11,r10,r12
-       mtmsrd  r11,1                   /* clear MSR.RI */
-#endif /* CONFIG_PPC_BOOK3S */
 
        beq-    1f
        ACCOUNT_CPU_USER_EXIT(r11, r12)
@@ -262,7 +260,7 @@ syscall_dotrace:
        ld      r7,GPR7(r1)
        ld      r8,GPR8(r1)
        addi    r9,r1,STACK_FRAME_OVERHEAD
-       clrrdi  r10,r1,THREAD_SHIFT
+       CURRENT_THREAD_INFO(r10, r1)
        ld      r10,TI_FLAGS(r10)
        b       .Lsyscall_dotrace_cont
 
@@ -271,6 +269,9 @@ syscall_enosys:
        b       syscall_exit
        
 syscall_exit_work:
+#ifdef CONFIG_PPC_BOOK3S
+       mtmsrd  r10,1           /* Restore RI */
+#endif
        /* If TIF_RESTOREALL is set, don't scribble on either r3 or ccr.
         If TIF_NOERROR is set, just save r3 as it is. */
 
@@ -499,7 +500,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
 2:
 #endif /* !CONFIG_PPC_BOOK3S */
 
-       clrrdi  r7,r8,THREAD_SHIFT      /* base of new stack */
+       CURRENT_THREAD_INFO(r7, r8)  /* base of new stack */
        /* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE
           because we don't need to leave the 288-byte ABI gap at the
           top of the kernel stack. */
@@ -558,7 +559,7 @@ _GLOBAL(ret_from_except_lite)
        mtmsrd  r10,1             /* Update machine state */
 #endif /* CONFIG_PPC_BOOK3E */
 
-       clrrdi  r9,r1,THREAD_SHIFT      /* current_thread_info() */
+       CURRENT_THREAD_INFO(r9, r1)
        ld      r3,_MSR(r1)
        ld      r4,TI_FLAGS(r9)
        andi.   r3,r3,MSR_PR
@@ -601,7 +602,7 @@ resume_kernel:
 1:     bl      .preempt_schedule_irq
 
        /* Re-test flags and eventually loop */
-       clrrdi  r9,r1,THREAD_SHIFT
+       CURRENT_THREAD_INFO(r9, r1)
        ld      r4,TI_FLAGS(r9)
        andi.   r0,r4,_TIF_NEED_RESCHED
        bne     1b
index 7215cc2495df1d95a91af88471af120e98ae2656..98be7f0cd227019cbe6b6a07ad989327b8e36979 100644 (file)
@@ -222,7 +222,7 @@ exc_##n##_bad_stack:                                                            \
  * interrupts happen before the wait instruction.
  */
 #define CHECK_NAPPING()                                                        \
-       clrrdi  r11,r1,THREAD_SHIFT;                                    \
+       CURRENT_THREAD_INFO(r11, r1);                                   \
        ld      r10,TI_LOCAL_FLAGS(r11);                                \
        andi.   r9,r10,_TLF_NAPPING;                                    \
        beq+    1f;                                                     \
@@ -903,7 +903,7 @@ skpinv:     addi    r6,r6,1                         /* Increment */
        bne     1b                              /* If not, repeat */
 
        /* Invalidate all TLBs */
-       PPC_TLBILX_ALL(0,0)
+       PPC_TLBILX_ALL(0,R0)
        sync
        isync
 
@@ -961,7 +961,7 @@ skpinv:     addi    r6,r6,1                         /* Increment */
        tlbwe
 
        /* Invalidate TLB1 */
-       PPC_TLBILX_ALL(0,0)
+       PPC_TLBILX_ALL(0,R0)
        sync
        isync
 
@@ -1020,7 +1020,7 @@ skpinv:   addi    r6,r6,1                         /* Increment */
        tlbwe
 
        /* Invalidate TLB1 */
-       PPC_TLBILX_ALL(0,0)
+       PPC_TLBILX_ALL(0,R0)
        sync
        isync
 
@@ -1138,7 +1138,7 @@ a2_tlbinit_after_iprot_flush:
        tlbwe
 #endif /* CONFIG_PPC_EARLY_DEBUG_WSP */
 
-       PPC_TLBILX(0,0,0)
+       PPC_TLBILX(0,0,R0)
        sync
        isync
 
index 1c06d297154532473527de1ee7a26081714f4fa0..e894515e77bbfa950c7d3e00cfbaafa07d0a0075 100644 (file)
@@ -239,6 +239,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
         * out of line to handle them
         */
        . = 0xe00
+hv_exception_trampoline:
        b       h_data_storage_hv
        . = 0xe20
        b       h_instr_storage_hv
@@ -851,7 +852,7 @@ BEGIN_FTR_SECTION
        bne-    do_ste_alloc            /* If so handle it */
 END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB)
 
-       clrrdi  r11,r1,THREAD_SHIFT
+       CURRENT_THREAD_INFO(r11, r1)
        lwz     r0,TI_PREEMPT(r11)      /* If we're in an "NMI" */
        andis.  r0,r0,NMI_MASK@h        /* (i.e. an irq when soft-disabled) */
        bne     77f                     /* then don't call hash_page now */
index de369558bf0a183c58e94f5f9871fc497f06b971..e0ada05f2df31f16f61e07259bce6d4549d8aa25 100644 (file)
@@ -26,7 +26,7 @@
 #include <asm/ptrace.h>
 
 #ifdef CONFIG_VSX
-#define REST_32FPVSRS(n,c,base)                                                \
+#define __REST_32FPVSRS(n,c,base)                                      \
 BEGIN_FTR_SECTION                                                      \
        b       2f;                                                     \
 END_FTR_SECTION_IFSET(CPU_FTR_VSX);                                    \
@@ -35,7 +35,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX);                                   \
 2:     REST_32VSRS(n,c,base);                                          \
 3:
 
-#define SAVE_32FPVSRS(n,c,base)                                                \
+#define __SAVE_32FPVSRS(n,c,base)                                      \
 BEGIN_FTR_SECTION                                                      \
        b       2f;                                                     \
 END_FTR_SECTION_IFSET(CPU_FTR_VSX);                                    \
@@ -44,9 +44,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX);                                  \
 2:     SAVE_32VSRS(n,c,base);                                          \
 3:
 #else
-#define REST_32FPVSRS(n,b,base)        REST_32FPRS(n, base)
-#define SAVE_32FPVSRS(n,b,base)        SAVE_32FPRS(n, base)
+#define __REST_32FPVSRS(n,b,base)      REST_32FPRS(n, base)
+#define __SAVE_32FPVSRS(n,b,base)      SAVE_32FPRS(n, base)
 #endif
+#define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base)
+#define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base)
 
 /*
  * This task wants to use the FPU now.
@@ -79,7 +81,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
        beq     1f
        toreal(r4)
        addi    r4,r4,THREAD            /* want last_task_used_math->thread */
-       SAVE_32FPVSRS(0, r5, r4)
+       SAVE_32FPVSRS(0, R5, R4)
        mffs    fr0
        stfd    fr0,THREAD_FPSCR(r4)
        PPC_LL  r5,PT_REGS(r4)
@@ -106,7 +108,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
 #endif
        lfd     fr0,THREAD_FPSCR(r5)
        MTFSF_L(fr0)
-       REST_32FPVSRS(0, r4, r5)
+       REST_32FPVSRS(0, R4, R5)
 #ifndef CONFIG_SMP
        subi    r4,r5,THREAD
        fromreal(r4)
@@ -140,7 +142,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
        addi    r3,r3,THREAD            /* want THREAD of task */
        PPC_LL  r5,PT_REGS(r3)
        PPC_LCMPI       0,r5,0
-       SAVE_32FPVSRS(0, r4 ,r3)
+       SAVE_32FPVSRS(0, R4 ,R3)
        mffs    fr0
        stfd    fr0,THREAD_FPSCR(r3)
        beq     1f
index bf99cfa6bbfe3a29240094eb5fe2db695ed78e66..91b46b7f6f0dd6701c434a6ec1ce9f189645eaf6 100644 (file)
@@ -63,11 +63,9 @@ ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
                return -EINVAL;
 
        /* replace the text with the new text */
-       if (probe_kernel_write((void *)ip, &new, MCOUNT_INSN_SIZE))
+       if (patch_instruction((unsigned int *)ip, new))
                return -EPERM;
 
-       flush_icache_range(ip, ip + 8);
-
        return 0;
 }
 
@@ -212,12 +210,9 @@ __ftrace_make_nop(struct module *mod,
         */
        op = 0x48000008;        /* b +8 */
 
-       if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE))
+       if (patch_instruction((unsigned int *)ip, op))
                return -EPERM;
 
-
-       flush_icache_range(ip, ip + 8);
-
        return 0;
 }
 
@@ -245,9 +240,9 @@ __ftrace_make_nop(struct module *mod,
 
        /*
         * On PPC32 the trampoline looks like:
-        *  0x3d, 0x60, 0x00, 0x00  lis r11,sym@ha
-        *  0x39, 0x6b, 0x00, 0x00  addi r11,r11,sym@l
-        *  0x7d, 0x69, 0x03, 0xa6  mtctr r11
+        *  0x3d, 0x80, 0x00, 0x00  lis r12,sym@ha
+        *  0x39, 0x8c, 0x00, 0x00  addi r12,r12,sym@l
+        *  0x7d, 0x89, 0x03, 0xa6  mtctr r12
         *  0x4e, 0x80, 0x04, 0x20  bctr
         */
 
@@ -262,9 +257,9 @@ __ftrace_make_nop(struct module *mod,
        pr_devel(" %08x %08x ", jmp[0], jmp[1]);
 
        /* verify that this is what we expect it to be */
-       if (((jmp[0] & 0xffff0000) != 0x3d600000) ||
-           ((jmp[1] & 0xffff0000) != 0x396b0000) ||
-           (jmp[2] != 0x7d6903a6) ||
+       if (((jmp[0] & 0xffff0000) != 0x3d800000) ||
+           ((jmp[1] & 0xffff0000) != 0x398c0000) ||
+           (jmp[2] != 0x7d8903a6) ||
            (jmp[3] != 0x4e800420)) {
                printk(KERN_ERR "Not a trampoline\n");
                return -EINVAL;
@@ -286,11 +281,9 @@ __ftrace_make_nop(struct module *mod,
 
        op = PPC_INST_NOP;
 
-       if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE))
+       if (patch_instruction((unsigned int *)ip, op))
                return -EPERM;
 
-       flush_icache_range(ip, ip + 8);
-
        return 0;
 }
 #endif /* PPC64 */
@@ -426,11 +419,9 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
 
        pr_devel("write to %lx\n", rec->ip);
 
-       if (probe_kernel_write((void *)ip, &op, MCOUNT_INSN_SIZE))
+       if (patch_instruction((unsigned int *)ip, op))
                return -EPERM;
 
-       flush_icache_range(ip, ip + 8);
-
        return 0;
 }
 #endif /* CONFIG_PPC64 */
@@ -484,6 +475,58 @@ int ftrace_update_ftrace_func(ftrace_func_t func)
        return ret;
 }
 
+static int __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
+{
+       unsigned long ftrace_addr = (unsigned long)FTRACE_ADDR;
+       int ret;
+
+       ret = ftrace_update_record(rec, enable);
+
+       switch (ret) {
+       case FTRACE_UPDATE_IGNORE:
+               return 0;
+       case FTRACE_UPDATE_MAKE_CALL:
+               return ftrace_make_call(rec, ftrace_addr);
+       case FTRACE_UPDATE_MAKE_NOP:
+               return ftrace_make_nop(NULL, rec, ftrace_addr);
+       }
+
+       return 0;
+}
+
+void ftrace_replace_code(int enable)
+{
+       struct ftrace_rec_iter *iter;
+       struct dyn_ftrace *rec;
+       int ret;
+
+       for (iter = ftrace_rec_iter_start(); iter;
+            iter = ftrace_rec_iter_next(iter)) {
+               rec = ftrace_rec_iter_record(iter);
+               ret = __ftrace_replace_code(rec, enable);
+               if (ret) {
+                       ftrace_bug(ret, rec->ip);
+                       return;
+               }
+       }
+}
+
+void arch_ftrace_update_code(int command)
+{
+       if (command & FTRACE_UPDATE_CALLS)
+               ftrace_replace_code(1);
+       else if (command & FTRACE_DISABLE_CALLS)
+               ftrace_replace_code(0);
+
+       if (command & FTRACE_UPDATE_TRACE_FUNC)
+               ftrace_update_ftrace_func(ftrace_trace_function);
+
+       if (command & FTRACE_START_FUNC_RET)
+               ftrace_enable_ftrace_graph_caller();
+       else if (command & FTRACE_STOP_FUNC_RET)
+               ftrace_disable_ftrace_graph_caller();
+}
+
 int __init ftrace_dyn_arch_init(void *data)
 {
        /* caller expects data to be zero */
index 1f4434a3860885bc9fa33c821359731be7b7398d..0f59863c3adeb3f220ef63093af71b1ce2bb23e4 100644 (file)
@@ -192,7 +192,7 @@ _ENTRY(__early_start)
        li      r0,0
        stwu    r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1)
 
-       rlwinm  r22,r1,0,0,31-THREAD_SHIFT      /* current thread_info */
+       CURRENT_THREAD_INFO(r22, r1)
        stw     r24, TI_CPU(r22)
 
        bl      early_init
@@ -556,8 +556,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV)
        /* SPE Unavailable */
        START_EXCEPTION(SPEUnavailable)
        NORMAL_EXCEPTION_PROLOG(SPE_UNAVAIL)
-       bne     load_up_spe
-       addi    r3,r1,STACK_FRAME_OVERHEAD
+       beq     1f
+       bl      load_up_spe
+       b       fast_exception_return
+1:     addi    r3,r1,STACK_FRAME_OVERHEAD
        EXC_XFER_EE_LITE(0x2010, KernelSPE)
 #else
        EXCEPTION(0x2020, SPE_UNAVAIL, SPEUnavailable, \
@@ -778,7 +780,7 @@ tlb_write_entry:
 /* Note that the SPE support is closely modeled after the AltiVec
  * support.  Changes to one are likely to be applicable to the
  * other!  */
-load_up_spe:
+_GLOBAL(load_up_spe)
 /*
  * Disable SPE for the task which had SPE previously,
  * and save its SPE registers in its thread_struct.
@@ -826,20 +828,7 @@ load_up_spe:
        subi    r4,r5,THREAD
        stw     r4,last_task_used_spe@l(r3)
 #endif /* !CONFIG_SMP */
-       /* restore registers and return */
-2:     REST_4GPRS(3, r11)
-       lwz     r10,_CCR(r11)
-       REST_GPR(1, r11)
-       mtcr    r10
-       lwz     r10,_LINK(r11)
-       mtlr    r10
-       REST_GPR(10, r11)
-       mtspr   SPRN_SRR1,r9
-       mtspr   SPRN_SRR0,r12
-       REST_GPR(9, r11)
-       REST_GPR(12, r11)
-       lwz     r11,GPR11(r11)
-       rfi
+       blr
 
 /*
  * SPE unavailable trap from kernel - print a message, but let
index 2bc0584be81c1441b5519fae9c82e4fc2ed08bff..f3a82dde61dbfe8b469a63d4874f2de53bf1b476 100644 (file)
@@ -111,7 +111,7 @@ void arch_unregister_hw_breakpoint(struct perf_event *bp)
         * and the single_step_dabr_instruction(), then cleanup the breakpoint
         * restoration variables to prevent dangling pointers.
         */
-       if (bp->ctx->task)
+       if (bp->ctx && bp->ctx->task)
                bp->ctx->task->thread.last_hit_ubp = NULL;
 }
 
index 15c611de1ee2a0cdb25cd7524179373aca32a1d2..1686916cc7f0739dab7a0593e71e878c51f00b67 100644 (file)
@@ -135,7 +135,7 @@ BEGIN_FTR_SECTION
        DSSALL
        sync
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-       rlwinm  r9,r1,0,0,31-THREAD_SHIFT       /* current thread_info */
+       CURRENT_THREAD_INFO(r9, r1)
        lwz     r8,TI_LOCAL_FLAGS(r9)   /* set napping bit */
        ori     r8,r8,_TLF_NAPPING      /* so when we take an exception */
        stw     r8,TI_LOCAL_FLAGS(r9)   /* it will return to our caller */
@@ -158,7 +158,7 @@ _GLOBAL(power_save_ppc32_restore)
        stw     r9,_NIP(r11)            /* make it do a blr */
 
 #ifdef CONFIG_SMP
-       rlwinm  r12,r11,0,0,31-THREAD_SHIFT
+       CURRENT_THREAD_INFO(r12, r11)
        lwz     r11,TI_CPU(r12)         /* get cpu number * 4 */
        slwi    r11,r11,2
 #else
index ff007b59448db24523fc1590caa83057a6446dce..4c7cb40085851fa2b21cc4ceebd6cc302485f36b 100644 (file)
@@ -60,7 +60,7 @@ _GLOBAL(book3e_idle)
 1:     /* Let's set the _TLF_NAPPING flag so interrupts make us return
         * to the right spot
        */
-       clrrdi  r11,r1,THREAD_SHIFT
+       CURRENT_THREAD_INFO(r11, r1)
        ld      r10,TI_LOCAL_FLAGS(r11)
        ori     r10,r10,_TLF_NAPPING
        std     r10,TI_LOCAL_FLAGS(r11)
index 4f0ab85f37883b9487ea23d46dc405e79f53f163..15448668988dd85a902b830fba8ef020c2557cb0 100644 (file)
@@ -21,7 +21,7 @@
        .text
 
 _GLOBAL(e500_idle)
-       rlwinm  r3,r1,0,0,31-THREAD_SHIFT       /* current thread_info */
+       CURRENT_THREAD_INFO(r3, r1)
        lwz     r4,TI_LOCAL_FLAGS(r3)   /* set napping bit */
        ori     r4,r4,_TLF_NAPPING      /* so when we take an exception */
        stw     r4,TI_LOCAL_FLAGS(r3)   /* it will return to our caller */
@@ -96,7 +96,7 @@ _GLOBAL(power_save_ppc32_restore)
        stw     r9,_NIP(r11)            /* make it do a blr */
 
 #ifdef CONFIG_SMP
-       rlwinm  r12,r1,0,0,31-THREAD_SHIFT
+       CURRENT_THREAD_INFO(r12, r1)
        lwz     r11,TI_CPU(r12)         /* get cpu number * 4 */
        slwi    r11,r11,2
 #else
index 2c71b0fc9f9101361475e8baaea3136a84753c45..e3edaa189911b8232d2c0682b52dedd982f88ae0 100644 (file)
@@ -59,7 +59,7 @@ BEGIN_FTR_SECTION
        DSSALL
        sync
 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-       clrrdi  r9,r1,THREAD_SHIFT      /* current thread_info */
+       CURRENT_THREAD_INFO(r9, r1)
        ld      r8,TI_LOCAL_FLAGS(r9)   /* set napping bit */
        ori     r8,r8,_TLF_NAPPING      /* so when we take an exception */
        std     r8,TI_LOCAL_FLAGS(r9)   /* it will return to our caller */
index 359f078571c7e5c9da9a6b90e5a53e0feec78b06..ff5a6ce027b88e88df6dbf7aa32519f2d08e6d7c 100644 (file)
@@ -33,6 +33,9 @@
 #include <linux/bitmap.h>
 #include <linux/iommu-helper.h>
 #include <linux/crash_dump.h>
+#include <linux/hash.h>
+#include <linux/fault-inject.h>
+#include <linux/pci.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/iommu.h>
@@ -40,6 +43,7 @@
 #include <asm/machdep.h>
 #include <asm/kdump.h>
 #include <asm/fadump.h>
+#include <asm/vio.h>
 
 #define DBG(...)
 
@@ -58,6 +62,114 @@ static int __init setup_iommu(char *str)
 
 __setup("iommu=", setup_iommu);
 
+static DEFINE_PER_CPU(unsigned int, iommu_pool_hash);
+
+/*
+ * We precalculate the hash to avoid doing it on every allocation.
+ *
+ * The hash is important to spread CPUs across all the pools. For example,
+ * on a POWER7 with 4 way SMT we want interrupts on the primary threads and
+ * with 4 pools all primary threads would map to the same pool.
+ */
+static int __init setup_iommu_pool_hash(void)
+{
+       unsigned int i;
+
+       for_each_possible_cpu(i)
+               per_cpu(iommu_pool_hash, i) = hash_32(i, IOMMU_POOL_HASHBITS);
+
+       return 0;
+}
+subsys_initcall(setup_iommu_pool_hash);
+
+#ifdef CONFIG_FAIL_IOMMU
+
+static DECLARE_FAULT_ATTR(fail_iommu);
+
+static int __init setup_fail_iommu(char *str)
+{
+       return setup_fault_attr(&fail_iommu, str);
+}
+__setup("fail_iommu=", setup_fail_iommu);
+
+static bool should_fail_iommu(struct device *dev)
+{
+       return dev->archdata.fail_iommu && should_fail(&fail_iommu, 1);
+}
+
+static int __init fail_iommu_debugfs(void)
+{
+       struct dentry *dir = fault_create_debugfs_attr("fail_iommu",
+                                                      NULL, &fail_iommu);
+
+       return IS_ERR(dir) ? PTR_ERR(dir) : 0;
+}
+late_initcall(fail_iommu_debugfs);
+
+static ssize_t fail_iommu_show(struct device *dev,
+                              struct device_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", dev->archdata.fail_iommu);
+}
+
+static ssize_t fail_iommu_store(struct device *dev,
+                               struct device_attribute *attr, const char *buf,
+                               size_t count)
+{
+       int i;
+
+       if (count > 0 && sscanf(buf, "%d", &i) > 0)
+               dev->archdata.fail_iommu = (i == 0) ? 0 : 1;
+
+       return count;
+}
+
+static DEVICE_ATTR(fail_iommu, S_IRUGO|S_IWUSR, fail_iommu_show,
+                  fail_iommu_store);
+
+static int fail_iommu_bus_notify(struct notifier_block *nb,
+                                unsigned long action, void *data)
+{
+       struct device *dev = data;
+
+       if (action == BUS_NOTIFY_ADD_DEVICE) {
+               if (device_create_file(dev, &dev_attr_fail_iommu))
+                       pr_warn("Unable to create IOMMU fault injection sysfs "
+                               "entries\n");
+       } else if (action == BUS_NOTIFY_DEL_DEVICE) {
+               device_remove_file(dev, &dev_attr_fail_iommu);
+       }
+
+       return 0;
+}
+
+static struct notifier_block fail_iommu_bus_notifier = {
+       .notifier_call = fail_iommu_bus_notify
+};
+
+static int __init fail_iommu_setup(void)
+{
+#ifdef CONFIG_PCI
+       bus_register_notifier(&pci_bus_type, &fail_iommu_bus_notifier);
+#endif
+#ifdef CONFIG_IBMVIO
+       bus_register_notifier(&vio_bus_type, &fail_iommu_bus_notifier);
+#endif
+
+       return 0;
+}
+/*
+ * Must execute after PCI and VIO subsystem have initialised but before
+ * devices are probed.
+ */
+arch_initcall(fail_iommu_setup);
+#else
+static inline bool should_fail_iommu(struct device *dev)
+{
+       return false;
+}
+#endif
+
 static unsigned long iommu_range_alloc(struct device *dev,
                                       struct iommu_table *tbl,
                                        unsigned long npages,
@@ -71,6 +183,9 @@ static unsigned long iommu_range_alloc(struct device *dev,
        int pass = 0;
        unsigned long align_mask;
        unsigned long boundary_size;
+       unsigned long flags;
+       unsigned int pool_nr;
+       struct iommu_pool *pool;
 
        align_mask = 0xffffffffffffffffl >> (64 - align_order);
 
@@ -83,36 +198,49 @@ static unsigned long iommu_range_alloc(struct device *dev,
                return DMA_ERROR_CODE;
        }
 
-       if (handle && *handle)
-               start = *handle;
+       if (should_fail_iommu(dev))
+               return DMA_ERROR_CODE;
+
+       /*
+        * We don't need to disable preemption here because any CPU can
+        * safely use any IOMMU pool.
+        */
+       pool_nr = __raw_get_cpu_var(iommu_pool_hash) & (tbl->nr_pools - 1);
+
+       if (largealloc)
+               pool = &(tbl->large_pool);
        else
-               start = largealloc ? tbl->it_largehint : tbl->it_hint;
+               pool = &(tbl->pools[pool_nr]);
 
-       /* Use only half of the table for small allocs (15 pages or less) */
-       limit = largealloc ? tbl->it_size : tbl->it_halfpoint;
+       spin_lock_irqsave(&(pool->lock), flags);
 
-       if (largealloc && start < tbl->it_halfpoint)
-               start = tbl->it_halfpoint;
+again:
+       if ((pass == 0) && handle && *handle)
+               start = *handle;
+       else
+               start = pool->hint;
+
+       limit = pool->end;
 
        /* The case below can happen if we have a small segment appended
         * to a large, or when the previous alloc was at the very end of
         * the available space. If so, go back to the initial start.
         */
        if (start >= limit)
-               start = largealloc ? tbl->it_largehint : tbl->it_hint;
-
- again:
+               start = pool->start;
 
        if (limit + tbl->it_offset > mask) {
                limit = mask - tbl->it_offset + 1;
                /* If we're constrained on address range, first try
                 * at the masked hint to avoid O(n) search complexity,
-                * but on second pass, start at 0.
+                * but on second pass, start at 0 in pool 0.
                 */
-               if ((start & mask) >= limit || pass > 0)
-                       start = 0;
-               else
+               if ((start & mask) >= limit || pass > 0) {
+                       pool = &(tbl->pools[0]);
+                       start = pool->start;
+               } else {
                        start &= mask;
+               }
        }
 
        if (dev)
@@ -126,16 +254,25 @@ static unsigned long iommu_range_alloc(struct device *dev,
                             tbl->it_offset, boundary_size >> IOMMU_PAGE_SHIFT,
                             align_mask);
        if (n == -1) {
-               if (likely(pass < 2)) {
-                       /* First failure, just rescan the half of the table.
-                        * Second failure, rescan the other half of the table.
-                        */
-                       start = (largealloc ^ pass) ? tbl->it_halfpoint : 0;
-                       limit = pass ? tbl->it_size : limit;
+               if (likely(pass == 0)) {
+                       /* First try the pool from the start */
+                       pool->hint = pool->start;
                        pass++;
                        goto again;
+
+               } else if (pass <= tbl->nr_pools) {
+                       /* Now try scanning all the other pools */
+                       spin_unlock(&(pool->lock));
+                       pool_nr = (pool_nr + 1) & (tbl->nr_pools - 1);
+                       pool = &tbl->pools[pool_nr];
+                       spin_lock(&(pool->lock));
+                       pool->hint = pool->start;
+                       pass++;
+                       goto again;
+
                } else {
-                       /* Third failure, give up */
+                       /* Give up */
+                       spin_unlock_irqrestore(&(pool->lock), flags);
                        return DMA_ERROR_CODE;
                }
        }
@@ -145,10 +282,10 @@ static unsigned long iommu_range_alloc(struct device *dev,
        /* Bump the hint to a new block for small allocs. */
        if (largealloc) {
                /* Don't bump to new block to avoid fragmentation */
-               tbl->it_largehint = end;
+               pool->hint = end;
        } else {
                /* Overflow will be taken care of at the next allocation */
-               tbl->it_hint = (end + tbl->it_blocksize - 1) &
+               pool->hint = (end + tbl->it_blocksize - 1) &
                                ~(tbl->it_blocksize - 1);
        }
 
@@ -156,6 +293,8 @@ static unsigned long iommu_range_alloc(struct device *dev,
        if (handle)
                *handle = end;
 
+       spin_unlock_irqrestore(&(pool->lock), flags);
+
        return n;
 }
 
@@ -165,18 +304,14 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
                              unsigned long mask, unsigned int align_order,
                              struct dma_attrs *attrs)
 {
-       unsigned long entry, flags;
+       unsigned long entry;
        dma_addr_t ret = DMA_ERROR_CODE;
        int build_fail;
 
-       spin_lock_irqsave(&(tbl->it_lock), flags);
-
        entry = iommu_range_alloc(dev, tbl, npages, NULL, mask, align_order);
 
-       if (unlikely(entry == DMA_ERROR_CODE)) {
-               spin_unlock_irqrestore(&(tbl->it_lock), flags);
+       if (unlikely(entry == DMA_ERROR_CODE))
                return DMA_ERROR_CODE;
-       }
 
        entry += tbl->it_offset;        /* Offset into real TCE table */
        ret = entry << IOMMU_PAGE_SHIFT;        /* Set the return dma address */
@@ -193,8 +328,6 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
         */
        if (unlikely(build_fail)) {
                __iommu_free(tbl, ret, npages);
-
-               spin_unlock_irqrestore(&(tbl->it_lock), flags);
                return DMA_ERROR_CODE;
        }
 
@@ -202,16 +335,14 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
        if (ppc_md.tce_flush)
                ppc_md.tce_flush(tbl);
 
-       spin_unlock_irqrestore(&(tbl->it_lock), flags);
-
        /* Make sure updates are seen by hardware */
        mb();
 
        return ret;
 }
 
-static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, 
-                        unsigned int npages)
+static bool iommu_free_check(struct iommu_table *tbl, dma_addr_t dma_addr,
+                            unsigned int npages)
 {
        unsigned long entry, free_entry;
 
@@ -231,20 +362,57 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
                        printk(KERN_INFO "\tindex     = 0x%llx\n", (u64)tbl->it_index);
                        WARN_ON(1);
                }
-               return;
+
+               return false;
+       }
+
+       return true;
+}
+
+static struct iommu_pool *get_pool(struct iommu_table *tbl,
+                                  unsigned long entry)
+{
+       struct iommu_pool *p;
+       unsigned long largepool_start = tbl->large_pool.start;
+
+       /* The large pool is the last pool at the top of the table */
+       if (entry >= largepool_start) {
+               p = &tbl->large_pool;
+       } else {
+               unsigned int pool_nr = entry / tbl->poolsize;
+
+               BUG_ON(pool_nr > tbl->nr_pools);
+               p = &tbl->pools[pool_nr];
        }
 
+       return p;
+}
+
+static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
+                        unsigned int npages)
+{
+       unsigned long entry, free_entry;
+       unsigned long flags;
+       struct iommu_pool *pool;
+
+       entry = dma_addr >> IOMMU_PAGE_SHIFT;
+       free_entry = entry - tbl->it_offset;
+
+       pool = get_pool(tbl, free_entry);
+
+       if (!iommu_free_check(tbl, dma_addr, npages))
+               return;
+
        ppc_md.tce_free(tbl, entry, npages);
+
+       spin_lock_irqsave(&(pool->lock), flags);
        bitmap_clear(tbl->it_map, free_entry, npages);
+       spin_unlock_irqrestore(&(pool->lock), flags);
 }
 
 static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
                unsigned int npages)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&(tbl->it_lock), flags);
-
        __iommu_free(tbl, dma_addr, npages);
 
        /* Make sure TLB cache is flushed if the HW needs it. We do
@@ -253,8 +421,6 @@ static void iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr,
         */
        if (ppc_md.tce_flush)
                ppc_md.tce_flush(tbl);
-
-       spin_unlock_irqrestore(&(tbl->it_lock), flags);
 }
 
 int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
@@ -263,7 +429,6 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
                 struct dma_attrs *attrs)
 {
        dma_addr_t dma_next = 0, dma_addr;
-       unsigned long flags;
        struct scatterlist *s, *outs, *segstart;
        int outcount, incount, i, build_fail = 0;
        unsigned int align;
@@ -285,8 +450,6 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
 
        DBG("sg mapping %d elements:\n", nelems);
 
-       spin_lock_irqsave(&(tbl->it_lock), flags);
-
        max_seg_size = dma_get_max_seg_size(dev);
        for_each_sg(sglist, s, nelems, i) {
                unsigned long vaddr, npages, entry, slen;
@@ -369,8 +532,6 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
        if (ppc_md.tce_flush)
                ppc_md.tce_flush(tbl);
 
-       spin_unlock_irqrestore(&(tbl->it_lock), flags);
-
        DBG("mapped %d elements:\n", outcount);
 
        /* For the sake of iommu_unmap_sg, we clear out the length in the
@@ -402,7 +563,6 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl,
                if (s == outs)
                        break;
        }
-       spin_unlock_irqrestore(&(tbl->it_lock), flags);
        return 0;
 }
 
@@ -412,15 +572,12 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
                struct dma_attrs *attrs)
 {
        struct scatterlist *sg;
-       unsigned long flags;
 
        BUG_ON(direction == DMA_NONE);
 
        if (!tbl)
                return;
 
-       spin_lock_irqsave(&(tbl->it_lock), flags);
-
        sg = sglist;
        while (nelems--) {
                unsigned int npages;
@@ -440,8 +597,6 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist,
         */
        if (ppc_md.tce_flush)
                ppc_md.tce_flush(tbl);
-
-       spin_unlock_irqrestore(&(tbl->it_lock), flags);
 }
 
 static void iommu_table_clear(struct iommu_table *tbl)
@@ -494,9 +649,8 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
        unsigned long sz;
        static int welcomed = 0;
        struct page *page;
-
-       /* Set aside 1/4 of the table for large allocations. */
-       tbl->it_halfpoint = tbl->it_size * 3 / 4;
+       unsigned int i;
+       struct iommu_pool *p;
 
        /* number of bytes needed for the bitmap */
        sz = (tbl->it_size + 7) >> 3;
@@ -515,9 +669,28 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid)
        if (tbl->it_offset == 0)
                set_bit(0, tbl->it_map);
 
-       tbl->it_hint = 0;
-       tbl->it_largehint = tbl->it_halfpoint;
-       spin_lock_init(&tbl->it_lock);
+       /* We only split the IOMMU table if we have 1GB or more of space */
+       if ((tbl->it_size << IOMMU_PAGE_SHIFT) >= (1UL * 1024 * 1024 * 1024))
+               tbl->nr_pools = IOMMU_NR_POOLS;
+       else
+               tbl->nr_pools = 1;
+
+       /* We reserve the top 1/4 of the table for large allocations */
+       tbl->poolsize = (tbl->it_size * 3 / 4) / tbl->nr_pools;
+
+       for (i = 0; i < tbl->nr_pools; i++) {
+               p = &tbl->pools[i];
+               spin_lock_init(&(p->lock));
+               p->start = tbl->poolsize * i;
+               p->hint = p->start;
+               p->end = p->start + tbl->poolsize;
+       }
+
+       p = &tbl->large_pool;
+       spin_lock_init(&(p->lock));
+       p->start = tbl->poolsize * i;
+       p->hint = p->start;
+       p->end = tbl->it_size;
 
        iommu_table_clear(tbl);
 
index 62bdf238966985d8b98d84105b3fd4d108601194..02c167db6ba027fc0f895679b0a3320a5790b0d8 100644 (file)
@@ -302,7 +302,7 @@ static void kvm_patch_ins_wrtee(u32 *inst, u32 rt, int imm_one)
 
        if (imm_one) {
                p[kvm_emulate_wrtee_reg_offs] =
-                       KVM_INST_LI | __PPC_RT(30) | MSR_EE;
+                       KVM_INST_LI | __PPC_RT(R30) | MSR_EE;
        } else {
                /* Make clobbered registers work too */
                switch (get_rt(rt)) {
index 386d57f66f28771de46265b5ad2ae0fbed32a8fa..407e293aad2fcad29c97be4d88961af12827f357 100644 (file)
@@ -179,7 +179,7 @@ _GLOBAL(low_choose_750fx_pll)
        mtspr   SPRN_HID1,r4
 
        /* Store new HID1 image */
-       rlwinm  r6,r1,0,0,(31-THREAD_SHIFT)
+       CURRENT_THREAD_INFO(r6, r1)
        lwz     r6,TI_CPU(r6)
        slwi    r6,r6,2
        addis   r6,r6,nap_save_hid1@ha
@@ -699,7 +699,7 @@ _GLOBAL(kernel_thread)
 #ifdef CONFIG_SMP
 _GLOBAL(start_secondary_resume)
        /* Reset stack */
-       rlwinm  r1,r1,0,0,(31-THREAD_SHIFT)     /* current_thread_info() */
+       CURRENT_THREAD_INFO(r1, r1)
        addi    r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
        li      r3,0
        stw     r3,0(r1)                /* Zero the stack frame pointer */
index 616921ef143917291051a71f4f0243e0f1ccc98f..565b78625a32a149ce4959fb9610a46a82a5e04a 100644 (file)
@@ -301,11 +301,6 @@ _GLOBAL(real_writeb)
 
 #ifdef CONFIG_PPC_PASEMI
 
-/* No support in all binutils for these yet, so use defines */
-#define LBZCIX(RT,RA,RB)  .long (0x7c0006aa|(RT<<21)|(RA<<16)|(RB << 11))
-#define STBCIX(RS,RA,RB)  .long (0x7c0007aa|(RS<<21)|(RA<<16)|(RB << 11))
-
-
 _GLOBAL(real_205_readb)
        mfmsr   r7
        ori     r0,r7,MSR_DR
@@ -314,7 +309,7 @@ _GLOBAL(real_205_readb)
        mtmsrd  r0
        sync
        isync
-       LBZCIX(r3,0,r3)
+       LBZCIX(R3,R0,R3)
        isync
        mtmsrd  r7
        sync
@@ -329,7 +324,7 @@ _GLOBAL(real_205_writeb)
        mtmsrd  r0
        sync
        isync
-       STBCIX(r3,0,r4)
+       STBCIX(R3,R0,R4)
        isync
        mtmsrd  r7
        sync
index 8e78e93c818536b4a33a1ae29f10b3d157b29e63..0f75bd50040418a0b36a4b33c3eaf5fd7fc0cdaa 100644 (file)
@@ -1646,7 +1646,6 @@ void __devinit pcibios_scan_phb(struct pci_controller *hose)
                pci_free_resource_list(&resources);
                return;
        }
-       bus->secondary = hose->first_busno;
        hose->bus = bus;
 
        /* Get probe mode and perform scan */
index 89dde171a6fabfafc23d1e29f3cba0bf00350bbe..d7dd42bd1452651a4c069a4e7fe15158769f3510 100644 (file)
@@ -198,7 +198,6 @@ EXPORT_SYMBOL(of_create_pci_dev);
 
 /**
  * of_scan_pci_bridge - Set up a PCI bridge and scan for child nodes
- * @node: device tree node of bridge
  * @dev: pci_dev structure for the bridge
  *
  * of_scan_bus() calls this routine for each PCI bridge that it finds, and
index afd4f051f3f249e6c6da4c63408a63295101e3bd..bdc499c178728e9c19b8f8afa0463136d646782a 100644 (file)
@@ -720,6 +720,33 @@ static int powerpc_debugfs_init(void)
 arch_initcall(powerpc_debugfs_init);
 #endif
 
+#ifdef CONFIG_BOOKE_WDT
+extern u32 booke_wdt_enabled;
+extern u32 booke_wdt_period;
+
+/* Checks wdt=x and wdt_period=xx command-line option */
+notrace int __init early_parse_wdt(char *p)
+{
+       if (p && strncmp(p, "0", 1) != 0)
+               booke_wdt_enabled = 1;
+
+       return 0;
+}
+early_param("wdt", early_parse_wdt);
+
+int __init early_parse_wdt_period(char *p)
+{
+       unsigned long ret;
+       if (p) {
+               if (!kstrtol(p, 0, &ret))
+                       booke_wdt_period = ret;
+       }
+
+       return 0;
+}
+early_param("wdt_period", early_parse_wdt_period);
+#endif /* CONFIG_BOOKE_WDT */
+
 void ppc_printk_progress(char *s, unsigned short hex)
 {
        pr_info("%s\n", s);
index ec8a53fa9e8f6a07f82b640426ef50f38e224d53..a8f54ecb091f866a7c93cb76d36d1a3702bf2184 100644 (file)
@@ -149,30 +149,6 @@ notrace void __init machine_init(u64 dt_ptr)
                ppc_md.progress("id mach(): done", 0x200);
 }
 
-#ifdef CONFIG_BOOKE_WDT
-extern u32 booke_wdt_enabled;
-extern u32 booke_wdt_period;
-
-/* Checks wdt=x and wdt_period=xx command-line option */
-notrace int __init early_parse_wdt(char *p)
-{
-       if (p && strncmp(p, "0", 1) != 0)
-              booke_wdt_enabled = 1;
-
-       return 0;
-}
-early_param("wdt", early_parse_wdt);
-
-int __init early_parse_wdt_period (char *p)
-{
-       if (p)
-               booke_wdt_period = simple_strtoul(p, NULL, 0);
-
-       return 0;
-}
-early_param("wdt_period", early_parse_wdt_period);
-#endif /* CONFIG_BOOKE_WDT */
-
 /* Checks "l2cr=xxxx" command-line option */
 int __init ppc_setup_l2cr(char *str)
 {
index e4cb34322de4aba848ce279b7792ea9d495dee5e..0321007086f7c499771ad0f71bc1f63969faff7a 100644 (file)
@@ -48,6 +48,7 @@
 #ifdef CONFIG_PPC64
 #include <asm/paca.h>
 #endif
+#include <asm/vdso.h>
 #include <asm/debug.h>
 
 #ifdef DEBUG
@@ -570,8 +571,9 @@ void __devinit start_secondary(void *unused)
 #ifdef CONFIG_PPC64
        if (system_state == SYSTEM_RUNNING)
                vdso_data->processorCount++;
+
+       vdso_getcpu_init();
 #endif
-       ipi_call_lock();
        notify_cpu_starting(cpu);
        set_cpu_online(cpu, true);
        /* Update sibling maps */
@@ -601,7 +603,6 @@ void __devinit start_secondary(void *unused)
                of_node_put(np);
        }
        of_node_put(l2_cache);
-       ipi_call_unlock();
 
        local_irq_enable();
 
index 9eb5b9b536a71b704b62a6cc6b38660f80d426b4..b67db22e102dd93dc11ec131ac7e942cf6de3d5c 100644 (file)
@@ -706,6 +706,34 @@ static void __init vdso_setup_syscall_map(void)
        }
 }
 
+#ifdef CONFIG_PPC64
+int __cpuinit vdso_getcpu_init(void)
+{
+       unsigned long cpu, node, val;
+
+       /*
+        * SPRG3 contains the CPU in the bottom 16 bits and the NUMA node in
+        * the next 16 bits. The VDSO uses this to implement getcpu().
+        */
+       cpu = get_cpu();
+       WARN_ON_ONCE(cpu > 0xffff);
+
+       node = cpu_to_node(cpu);
+       WARN_ON_ONCE(node > 0xffff);
+
+       val = (cpu & 0xfff) | ((node & 0xffff) << 16);
+       mtspr(SPRN_SPRG3, val);
+#ifdef CONFIG_KVM_BOOK3S_HANDLER
+       get_paca()->kvm_hstate.sprg3 = val;
+#endif
+
+       put_cpu();
+
+       return 0;
+}
+/* We need to call this before SMP init */
+early_initcall(vdso_getcpu_init);
+#endif
 
 static int __init vdso_init(void)
 {
index 9a7946c417387fdd0c56b4c3dd1010c4b642312f..53e6c9b979ec6bd44d4892f62b281e5a4c0906b3 100644 (file)
@@ -1,7 +1,9 @@
 
 # List of files in the vdso, has to be asm only for now
 
-obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o
+obj-vdso32-$(CONFIG_PPC64) = getcpu.o
+obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o \
+               $(obj-vdso32-y)
 
 # Build rules
 
diff --git a/arch/powerpc/kernel/vdso32/getcpu.S b/arch/powerpc/kernel/vdso32/getcpu.S
new file mode 100644 (file)
index 0000000..47afd08
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2012
+ *
+ * Author: Anton Blanchard <anton@au.ibm.com>
+ */
+#include <asm/ppc_asm.h>
+#include <asm/vdso.h>
+
+       .text
+/*
+ * Exact prototype of getcpu
+ *
+ * int __kernel_getcpu(unsigned *cpu, unsigned *node);
+ *
+ */
+V_FUNCTION_BEGIN(__kernel_getcpu)
+  .cfi_startproc
+       mfspr   r5,SPRN_USPRG3
+       cmpdi   cr0,r3,0
+       cmpdi   cr1,r4,0
+       clrlwi  r6,r5,16
+       rlwinm  r7,r5,16,31-15,31-0
+       beq     cr0,1f
+       stw     r6,0(r3)
+1:     beq     cr1,2f
+       stw     r7,0(r4)
+2:     crclr   cr0*4+so
+       li      r3,0                    /* always success */
+       blr
+  .cfi_endproc
+V_FUNCTION_END(__kernel_getcpu)
index 0546bcd49cd0363c317424e25359c7e08176b832..43200ba2e57004f74e3f990d427d729c789e07c9 100644 (file)
@@ -147,6 +147,9 @@ VERSION
                __kernel_sync_dicache_p5;
                __kernel_sigtramp32;
                __kernel_sigtramp_rt32;
+#ifdef CONFIG_PPC64
+               __kernel_getcpu;
+#endif
 
        local: *;
        };
index 8c500d8622e4d8d7696099b684b0ad519c63a8a4..effca9404b1763c077ff0dcde9e2910ded4c0423 100644 (file)
@@ -1,6 +1,6 @@
 # List of files in the vdso, has to be asm only for now
 
-obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o
+obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o getcpu.o
 
 # Build rules
 
diff --git a/arch/powerpc/kernel/vdso64/getcpu.S b/arch/powerpc/kernel/vdso64/getcpu.S
new file mode 100644 (file)
index 0000000..47afd08
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2012
+ *
+ * Author: Anton Blanchard <anton@au.ibm.com>
+ */
+#include <asm/ppc_asm.h>
+#include <asm/vdso.h>
+
+       .text
+/*
+ * Exact prototype of getcpu
+ *
+ * int __kernel_getcpu(unsigned *cpu, unsigned *node);
+ *
+ */
+V_FUNCTION_BEGIN(__kernel_getcpu)
+  .cfi_startproc
+       mfspr   r5,SPRN_USPRG3
+       cmpdi   cr0,r3,0
+       cmpdi   cr1,r4,0
+       clrlwi  r6,r5,16
+       rlwinm  r7,r5,16,31-15,31-0
+       beq     cr0,1f
+       stw     r6,0(r3)
+1:     beq     cr1,2f
+       stw     r7,0(r4)
+2:     crclr   cr0*4+so
+       li      r3,0                    /* always success */
+       blr
+  .cfi_endproc
+V_FUNCTION_END(__kernel_getcpu)
index 0e615404e247353cd9a696bb086d03486013403e..e6c1758f3588c4c2d4e5f314e489a8c4c8b65a36 100644 (file)
@@ -146,6 +146,7 @@ VERSION
                __kernel_sync_dicache;
                __kernel_sync_dicache_p5;
                __kernel_sigtramp_rt64;
+               __kernel_getcpu;
 
        local: *;
        };
index cb87301ccd55a63a46f3069efe3b860e3da5c3c8..7a421e8fe7cad2159547c32e4b3a3530540ff93c 100644 (file)
@@ -37,8 +37,6 @@
 #include <asm/page.h>
 #include <asm/hvcall.h>
 
-static struct bus_type vio_bus_type;
-
 static struct vio_dev vio_bus_device  = { /* fake "parent" device */
        .name = "vio",
        .type = "",
@@ -625,7 +623,7 @@ struct dma_map_ops vio_dma_mapping_ops = {
  * vio_cmo_set_dev_desired - Set desired entitlement for a device
  *
  * @viodev: struct vio_dev for device to alter
- * @new_desired: new desired entitlement level in bytes
+ * @desired: new desired entitlement level in bytes
  *
  * For use by devices to request a change to their entitlement at runtime or
  * through sysfs.  The desired entitlement level is changed and a balancing
@@ -1262,7 +1260,7 @@ static int vio_bus_remove(struct device *dev)
 
 /**
  * vio_register_driver: - Register a new vio driver
- * @drv:       The vio_driver structure to be registered.
+ * @viodrv:    The vio_driver structure to be registered.
  */
 int __vio_register_driver(struct vio_driver *viodrv, struct module *owner,
                          const char *mod_name)
@@ -1282,7 +1280,7 @@ EXPORT_SYMBOL(__vio_register_driver);
 
 /**
  * vio_unregister_driver - Remove registration of vio driver.
- * @driver:    The vio_driver struct to be removed form registration
+ * @viodrv:    The vio_driver struct to be removed form registration
  */
 void vio_unregister_driver(struct vio_driver *viodrv)
 {
@@ -1397,21 +1395,27 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node)
        viodev->name = of_node->name;
        viodev->dev.of_node = of_node_get(of_node);
 
-       if (firmware_has_feature(FW_FEATURE_CMO))
-               vio_cmo_set_dma_ops(viodev);
-       else
-               set_dma_ops(&viodev->dev, &dma_iommu_ops);
-       set_iommu_table_base(&viodev->dev, vio_build_iommu_table(viodev));
        set_dev_node(&viodev->dev, of_node_to_nid(of_node));
 
        /* init generic 'struct device' fields: */
        viodev->dev.parent = &vio_bus_device.dev;
        viodev->dev.bus = &vio_bus_type;
        viodev->dev.release = vio_dev_release;
-        /* needed to ensure proper operation of coherent allocations
-         * later, in case driver doesn't set it explicitly */
-        dma_set_mask(&viodev->dev, DMA_BIT_MASK(64));
-        dma_set_coherent_mask(&viodev->dev, DMA_BIT_MASK(64));
+
+       if (of_get_property(viodev->dev.of_node, "ibm,my-dma-window", NULL)) {
+               if (firmware_has_feature(FW_FEATURE_CMO))
+                       vio_cmo_set_dma_ops(viodev);
+               else
+                       set_dma_ops(&viodev->dev, &dma_iommu_ops);
+
+               set_iommu_table_base(&viodev->dev,
+                                    vio_build_iommu_table(viodev));
+
+               /* needed to ensure proper operation of coherent allocations
+                * later, in case driver doesn't set it explicitly */
+               dma_set_mask(&viodev->dev, DMA_BIT_MASK(64));
+               dma_set_coherent_mask(&viodev->dev, DMA_BIT_MASK(64));
+       }
 
        /* register with generic device framework */
        if (device_register(&viodev->dev)) {
@@ -1491,12 +1495,18 @@ static int __init vio_bus_init(void)
        if (firmware_has_feature(FW_FEATURE_CMO))
                vio_cmo_bus_init();
 
+       return 0;
+}
+postcore_initcall(vio_bus_init);
+
+static int __init vio_device_init(void)
+{
        vio_bus_scan_register_devices("vdevice");
        vio_bus_scan_register_devices("ibm,platform-facilities");
 
        return 0;
 }
-__initcall(vio_bus_init);
+device_initcall(vio_device_init);
 
 static ssize_t name_show(struct device *dev,
                struct device_attribute *attr, char *buf)
@@ -1568,7 +1578,7 @@ static int vio_hotplug(struct device *dev, struct kobj_uevent_env *env)
        return 0;
 }
 
-static struct bus_type vio_bus_type = {
+struct bus_type vio_bus_type = {
        .name = "vio",
        .dev_attrs = vio_dev_attrs,
        .uevent = vio_hotplug,
index a1044f43becd380cdc7216e082fbf267b97a3fae..5a84c8d3d04050b98ab818c9d83cedeb74b8f235 100644 (file)
@@ -72,9 +72,6 @@ _GLOBAL(kvmppc_hv_entry_trampoline)
        mtsrr1  r6
        RFI
 
-#define ULONG_SIZE             8
-#define VCPU_GPR(n)            (VCPU_GPRS + (n * ULONG_SIZE))
-
 /******************************************************************************
  *                                                                            *
  *                               Entry code                                   *
@@ -206,24 +203,24 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201)
        /* Load up FP, VMX and VSX registers */
        bl      kvmppc_load_fp
 
-       ld      r14, VCPU_GPR(r14)(r4)
-       ld      r15, VCPU_GPR(r15)(r4)
-       ld      r16, VCPU_GPR(r16)(r4)
-       ld      r17, VCPU_GPR(r17)(r4)
-       ld      r18, VCPU_GPR(r18)(r4)
-       ld      r19, VCPU_GPR(r19)(r4)
-       ld      r20, VCPU_GPR(r20)(r4)
-       ld      r21, VCPU_GPR(r21)(r4)
-       ld      r22, VCPU_GPR(r22)(r4)
-       ld      r23, VCPU_GPR(r23)(r4)
-       ld      r24, VCPU_GPR(r24)(r4)
-       ld      r25, VCPU_GPR(r25)(r4)
-       ld      r26, VCPU_GPR(r26)(r4)
-       ld      r27, VCPU_GPR(r27)(r4)
-       ld      r28, VCPU_GPR(r28)(r4)
-       ld      r29, VCPU_GPR(r29)(r4)
-       ld      r30, VCPU_GPR(r30)(r4)
-       ld      r31, VCPU_GPR(r31)(r4)
+       ld      r14, VCPU_GPR(R14)(r4)
+       ld      r15, VCPU_GPR(R15)(r4)
+       ld      r16, VCPU_GPR(R16)(r4)
+       ld      r17, VCPU_GPR(R17)(r4)
+       ld      r18, VCPU_GPR(R18)(r4)
+       ld      r19, VCPU_GPR(R19)(r4)
+       ld      r20, VCPU_GPR(R20)(r4)
+       ld      r21, VCPU_GPR(R21)(r4)
+       ld      r22, VCPU_GPR(R22)(r4)
+       ld      r23, VCPU_GPR(R23)(r4)
+       ld      r24, VCPU_GPR(R24)(r4)
+       ld      r25, VCPU_GPR(R25)(r4)
+       ld      r26, VCPU_GPR(R26)(r4)
+       ld      r27, VCPU_GPR(R27)(r4)
+       ld      r28, VCPU_GPR(R28)(r4)
+       ld      r29, VCPU_GPR(R29)(r4)
+       ld      r30, VCPU_GPR(R30)(r4)
+       ld      r31, VCPU_GPR(R31)(r4)
 
 BEGIN_FTR_SECTION
        /* Switch DSCR to guest value */
@@ -547,21 +544,21 @@ fast_guest_return:
        mtlr    r5
        mtcr    r6
 
-       ld      r0, VCPU_GPR(r0)(r4)
-       ld      r1, VCPU_GPR(r1)(r4)
-       ld      r2, VCPU_GPR(r2)(r4)
-       ld      r3, VCPU_GPR(r3)(r4)
-       ld      r5, VCPU_GPR(r5)(r4)
-       ld      r6, VCPU_GPR(r6)(r4)
-       ld      r7, VCPU_GPR(r7)(r4)
-       ld      r8, VCPU_GPR(r8)(r4)
-       ld      r9, VCPU_GPR(r9)(r4)
-       ld      r10, VCPU_GPR(r10)(r4)
-       ld      r11, VCPU_GPR(r11)(r4)
-       ld      r12, VCPU_GPR(r12)(r4)
-       ld      r13, VCPU_GPR(r13)(r4)
-
-       ld      r4, VCPU_GPR(r4)(r4)
+       ld      r0, VCPU_GPR(R0)(r4)
+       ld      r1, VCPU_GPR(R1)(r4)
+       ld      r2, VCPU_GPR(R2)(r4)
+       ld      r3, VCPU_GPR(R3)(r4)
+       ld      r5, VCPU_GPR(R5)(r4)
+       ld      r6, VCPU_GPR(R6)(r4)
+       ld      r7, VCPU_GPR(R7)(r4)
+       ld      r8, VCPU_GPR(R8)(r4)
+       ld      r9, VCPU_GPR(R9)(r4)
+       ld      r10, VCPU_GPR(R10)(r4)
+       ld      r11, VCPU_GPR(R11)(r4)
+       ld      r12, VCPU_GPR(R12)(r4)
+       ld      r13, VCPU_GPR(R13)(r4)
+
+       ld      r4, VCPU_GPR(R4)(r4)
 
        hrfid
        b       .
@@ -590,22 +587,22 @@ kvmppc_interrupt:
 
        /* Save registers */
 
-       std     r0, VCPU_GPR(r0)(r9)
-       std     r1, VCPU_GPR(r1)(r9)
-       std     r2, VCPU_GPR(r2)(r9)
-       std     r3, VCPU_GPR(r3)(r9)
-       std     r4, VCPU_GPR(r4)(r9)
-       std     r5, VCPU_GPR(r5)(r9)
-       std     r6, VCPU_GPR(r6)(r9)
-       std     r7, VCPU_GPR(r7)(r9)
-       std     r8, VCPU_GPR(r8)(r9)
+       std     r0, VCPU_GPR(R0)(r9)
+       std     r1, VCPU_GPR(R1)(r9)
+       std     r2, VCPU_GPR(R2)(r9)
+       std     r3, VCPU_GPR(R3)(r9)
+       std     r4, VCPU_GPR(R4)(r9)
+       std     r5, VCPU_GPR(R5)(r9)
+       std     r6, VCPU_GPR(R6)(r9)
+       std     r7, VCPU_GPR(R7)(r9)
+       std     r8, VCPU_GPR(R8)(r9)
        ld      r0, HSTATE_HOST_R2(r13)
-       std     r0, VCPU_GPR(r9)(r9)
-       std     r10, VCPU_GPR(r10)(r9)
-       std     r11, VCPU_GPR(r11)(r9)
+       std     r0, VCPU_GPR(R9)(r9)
+       std     r10, VCPU_GPR(R10)(r9)
+       std     r11, VCPU_GPR(R11)(r9)
        ld      r3, HSTATE_SCRATCH0(r13)
        lwz     r4, HSTATE_SCRATCH1(r13)
-       std     r3, VCPU_GPR(r12)(r9)
+       std     r3, VCPU_GPR(R12)(r9)
        stw     r4, VCPU_CR(r9)
 
        /* Restore R1/R2 so we can handle faults */
@@ -626,7 +623,7 @@ kvmppc_interrupt:
 
        GET_SCRATCH0(r3)
        mflr    r4
-       std     r3, VCPU_GPR(r13)(r9)
+       std     r3, VCPU_GPR(R13)(r9)
        std     r4, VCPU_LR(r9)
 
        /* Unset guest mode */
@@ -968,24 +965,24 @@ BEGIN_FTR_SECTION
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
 
        /* Save non-volatile GPRs */
-       std     r14, VCPU_GPR(r14)(r9)
-       std     r15, VCPU_GPR(r15)(r9)
-       std     r16, VCPU_GPR(r16)(r9)
-       std     r17, VCPU_GPR(r17)(r9)
-       std     r18, VCPU_GPR(r18)(r9)
-       std     r19, VCPU_GPR(r19)(r9)
-       std     r20, VCPU_GPR(r20)(r9)
-       std     r21, VCPU_GPR(r21)(r9)
-       std     r22, VCPU_GPR(r22)(r9)
-       std     r23, VCPU_GPR(r23)(r9)
-       std     r24, VCPU_GPR(r24)(r9)
-       std     r25, VCPU_GPR(r25)(r9)
-       std     r26, VCPU_GPR(r26)(r9)
-       std     r27, VCPU_GPR(r27)(r9)
-       std     r28, VCPU_GPR(r28)(r9)
-       std     r29, VCPU_GPR(r29)(r9)
-       std     r30, VCPU_GPR(r30)(r9)
-       std     r31, VCPU_GPR(r31)(r9)
+       std     r14, VCPU_GPR(R14)(r9)
+       std     r15, VCPU_GPR(R15)(r9)
+       std     r16, VCPU_GPR(R16)(r9)
+       std     r17, VCPU_GPR(R17)(r9)
+       std     r18, VCPU_GPR(R18)(r9)
+       std     r19, VCPU_GPR(R19)(r9)
+       std     r20, VCPU_GPR(R20)(r9)
+       std     r21, VCPU_GPR(R21)(r9)
+       std     r22, VCPU_GPR(R22)(r9)
+       std     r23, VCPU_GPR(R23)(r9)
+       std     r24, VCPU_GPR(R24)(r9)
+       std     r25, VCPU_GPR(R25)(r9)
+       std     r26, VCPU_GPR(R26)(r9)
+       std     r27, VCPU_GPR(R27)(r9)
+       std     r28, VCPU_GPR(R28)(r9)
+       std     r29, VCPU_GPR(R29)(r9)
+       std     r30, VCPU_GPR(R30)(r9)
+       std     r31, VCPU_GPR(R31)(r9)
 
        /* Save SPRGs */
        mfspr   r3, SPRN_SPRG0
@@ -1067,6 +1064,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206)
        mtspr   SPRN_DABR,r5
        mtspr   SPRN_DABRX,r6
 
+       /* Restore SPRG3 */
+       ld      r3,HSTATE_SPRG3(r13)
+       mtspr   SPRN_SPRG3,r3
+
        /*
         * Reload DEC.  HDEC interrupts were disabled when
         * we reloaded the host's LPCR value.
@@ -1160,7 +1161,7 @@ kvmppc_hdsi:
        andi.   r0, r11, MSR_DR         /* data relocation enabled? */
        beq     3f
        clrrdi  r0, r4, 28
-       PPC_SLBFEE_DOT(r5, r0)          /* if so, look up SLB */
+       PPC_SLBFEE_DOT(R5, R0)          /* if so, look up SLB */
        bne     1f                      /* if no SLB entry found */
 4:     std     r4, VCPU_FAULT_DAR(r9)
        stw     r6, VCPU_FAULT_DSISR(r9)
@@ -1234,7 +1235,7 @@ kvmppc_hisi:
        andi.   r0, r11, MSR_IR         /* instruction relocation enabled? */
        beq     3f
        clrrdi  r0, r10, 28
-       PPC_SLBFEE_DOT(r5, r0)          /* if so, look up SLB */
+       PPC_SLBFEE_DOT(R5, R0)          /* if so, look up SLB */
        bne     1f                      /* if no SLB entry found */
 4:
        /* Search the hash table. */
@@ -1278,7 +1279,7 @@ kvmppc_hisi:
  */
        .globl  hcall_try_real_mode
 hcall_try_real_mode:
-       ld      r3,VCPU_GPR(r3)(r9)
+       ld      r3,VCPU_GPR(R3)(r9)
        andi.   r0,r11,MSR_PR
        bne     hcall_real_cont
        clrrdi  r3,r3,2
@@ -1291,12 +1292,12 @@ hcall_try_real_mode:
        add     r3,r3,r4
        mtctr   r3
        mr      r3,r9           /* get vcpu pointer */
-       ld      r4,VCPU_GPR(r4)(r9)
+       ld      r4,VCPU_GPR(R4)(r9)
        bctrl
        cmpdi   r3,H_TOO_HARD
        beq     hcall_real_fallback
        ld      r4,HSTATE_KVM_VCPU(r13)
-       std     r3,VCPU_GPR(r3)(r4)
+       std     r3,VCPU_GPR(R3)(r4)
        ld      r10,VCPU_PC(r4)
        ld      r11,VCPU_MSR(r4)
        b       fast_guest_return
@@ -1424,7 +1425,7 @@ _GLOBAL(kvmppc_h_cede)
        li      r0,0            /* set trap to 0 to say hcall is handled */
        stw     r0,VCPU_TRAP(r3)
        li      r0,H_SUCCESS
-       std     r0,VCPU_GPR(r3)(r3)
+       std     r0,VCPU_GPR(R3)(r3)
 BEGIN_FTR_SECTION
        b       2f              /* just send it up to host on 970 */
 END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
@@ -1443,7 +1444,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
        addi    r6,r5,VCORE_NAPPING_THREADS
 31:    lwarx   r4,0,r6
        or      r4,r4,r0
-       PPC_POPCNTW(r7,r4)
+       PPC_POPCNTW(R7,R4)
        cmpw    r7,r8
        bge     2f
        stwcx.  r4,0,r6
@@ -1464,24 +1465,24 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
  * DAR, DSISR, DABR, DABRX, DSCR, PMCx, MMCRx, SIAR, SDAR.
  */
        /* Save non-volatile GPRs */
-       std     r14, VCPU_GPR(r14)(r3)
-       std     r15, VCPU_GPR(r15)(r3)
-       std     r16, VCPU_GPR(r16)(r3)
-       std     r17, VCPU_GPR(r17)(r3)
-       std     r18, VCPU_GPR(r18)(r3)
-       std     r19, VCPU_GPR(r19)(r3)
-       std     r20, VCPU_GPR(r20)(r3)
-       std     r21, VCPU_GPR(r21)(r3)
-       std     r22, VCPU_GPR(r22)(r3)
-       std     r23, VCPU_GPR(r23)(r3)
-       std     r24, VCPU_GPR(r24)(r3)
-       std     r25, VCPU_GPR(r25)(r3)
-       std     r26, VCPU_GPR(r26)(r3)
-       std     r27, VCPU_GPR(r27)(r3)
-       std     r28, VCPU_GPR(r28)(r3)
-       std     r29, VCPU_GPR(r29)(r3)
-       std     r30, VCPU_GPR(r30)(r3)
-       std     r31, VCPU_GPR(r31)(r3)
+       std     r14, VCPU_GPR(R14)(r3)
+       std     r15, VCPU_GPR(R15)(r3)
+       std     r16, VCPU_GPR(R16)(r3)
+       std     r17, VCPU_GPR(R17)(r3)
+       std     r18, VCPU_GPR(R18)(r3)
+       std     r19, VCPU_GPR(R19)(r3)
+       std     r20, VCPU_GPR(R20)(r3)
+       std     r21, VCPU_GPR(R21)(r3)
+       std     r22, VCPU_GPR(R22)(r3)
+       std     r23, VCPU_GPR(R23)(r3)
+       std     r24, VCPU_GPR(R24)(r3)
+       std     r25, VCPU_GPR(R25)(r3)
+       std     r26, VCPU_GPR(R26)(r3)
+       std     r27, VCPU_GPR(R27)(r3)
+       std     r28, VCPU_GPR(R28)(r3)
+       std     r29, VCPU_GPR(R29)(r3)
+       std     r30, VCPU_GPR(R30)(r3)
+       std     r31, VCPU_GPR(R31)(r3)
 
        /* save FP state */
        bl      .kvmppc_save_fp
@@ -1513,24 +1514,24 @@ kvm_end_cede:
        bl      kvmppc_load_fp
 
        /* Load NV GPRS */
-       ld      r14, VCPU_GPR(r14)(r4)
-       ld      r15, VCPU_GPR(r15)(r4)
-       ld      r16, VCPU_GPR(r16)(r4)
-       ld      r17, VCPU_GPR(r17)(r4)
-       ld      r18, VCPU_GPR(r18)(r4)
-       ld      r19, VCPU_GPR(r19)(r4)
-       ld      r20, VCPU_GPR(r20)(r4)
-       ld      r21, VCPU_GPR(r21)(r4)
-       ld      r22, VCPU_GPR(r22)(r4)
-       ld      r23, VCPU_GPR(r23)(r4)
-       ld      r24, VCPU_GPR(r24)(r4)
-       ld      r25, VCPU_GPR(r25)(r4)
-       ld      r26, VCPU_GPR(r26)(r4)
-       ld      r27, VCPU_GPR(r27)(r4)
-       ld      r28, VCPU_GPR(r28)(r4)
-       ld      r29, VCPU_GPR(r29)(r4)
-       ld      r30, VCPU_GPR(r30)(r4)
-       ld      r31, VCPU_GPR(r31)(r4)
+       ld      r14, VCPU_GPR(R14)(r4)
+       ld      r15, VCPU_GPR(R15)(r4)
+       ld      r16, VCPU_GPR(R16)(r4)
+       ld      r17, VCPU_GPR(R17)(r4)
+       ld      r18, VCPU_GPR(R18)(r4)
+       ld      r19, VCPU_GPR(R19)(r4)
+       ld      r20, VCPU_GPR(R20)(r4)
+       ld      r21, VCPU_GPR(R21)(r4)
+       ld      r22, VCPU_GPR(R22)(r4)
+       ld      r23, VCPU_GPR(R23)(r4)
+       ld      r24, VCPU_GPR(R24)(r4)
+       ld      r25, VCPU_GPR(R25)(r4)
+       ld      r26, VCPU_GPR(R26)(r4)
+       ld      r27, VCPU_GPR(R27)(r4)
+       ld      r28, VCPU_GPR(R28)(r4)
+       ld      r29, VCPU_GPR(R29)(r4)
+       ld      r30, VCPU_GPR(R30)(r4)
+       ld      r31, VCPU_GPR(R31)(r4)
 
        /* clear our bit in vcore->napping_threads */
 33:    ld      r5,HSTATE_KVM_VCORE(r13)
@@ -1649,7 +1650,7 @@ BEGIN_FTR_SECTION
        reg = 0
        .rept   32
        li      r6,reg*16+VCPU_VSRS
-       STXVD2X(reg,r6,r3)
+       STXVD2X(reg,R6,R3)
        reg = reg + 1
        .endr
 FTR_SECTION_ELSE
@@ -1711,7 +1712,7 @@ BEGIN_FTR_SECTION
        reg = 0
        .rept   32
        li      r7,reg*16+VCPU_VSRS
-       LXVD2X(reg,r7,r4)
+       LXVD2X(reg,R7,R4)
        reg = reg + 1
        .endr
 FTR_SECTION_ELSE
index 3e35383bdb2186e81bb78dfbae2ebe8818c223ac..48cbbf862958f8e3eea8b82932ec03cf231595b0 100644 (file)
 #include <asm/exception-64s.h>
 
 #if defined(CONFIG_PPC_BOOK3S_64)
-
-#define ULONG_SIZE             8
 #define FUNC(name)             GLUE(.,name)
-
 #elif defined(CONFIG_PPC_BOOK3S_32)
-
-#define ULONG_SIZE              4
 #define FUNC(name)             name
-
 #endif /* CONFIG_PPC_BOOK3S_XX */
 
-
-#define VCPU_GPR(n)            (VCPU_GPRS + (n * ULONG_SIZE))
 #define VCPU_LOAD_NVGPRS(vcpu) \
-       PPC_LL  r14, VCPU_GPR(r14)(vcpu); \
-       PPC_LL  r15, VCPU_GPR(r15)(vcpu); \
-       PPC_LL  r16, VCPU_GPR(r16)(vcpu); \
-       PPC_LL  r17, VCPU_GPR(r17)(vcpu); \
-       PPC_LL  r18, VCPU_GPR(r18)(vcpu); \
-       PPC_LL  r19, VCPU_GPR(r19)(vcpu); \
-       PPC_LL  r20, VCPU_GPR(r20)(vcpu); \
-       PPC_LL  r21, VCPU_GPR(r21)(vcpu); \
-       PPC_LL  r22, VCPU_GPR(r22)(vcpu); \
-       PPC_LL  r23, VCPU_GPR(r23)(vcpu); \
-       PPC_LL  r24, VCPU_GPR(r24)(vcpu); \
-       PPC_LL  r25, VCPU_GPR(r25)(vcpu); \
-       PPC_LL  r26, VCPU_GPR(r26)(vcpu); \
-       PPC_LL  r27, VCPU_GPR(r27)(vcpu); \
-       PPC_LL  r28, VCPU_GPR(r28)(vcpu); \
-       PPC_LL  r29, VCPU_GPR(r29)(vcpu); \
-       PPC_LL  r30, VCPU_GPR(r30)(vcpu); \
-       PPC_LL  r31, VCPU_GPR(r31)(vcpu); \
+       PPC_LL  r14, VCPU_GPR(R14)(vcpu); \
+       PPC_LL  r15, VCPU_GPR(R15)(vcpu); \
+       PPC_LL  r16, VCPU_GPR(R16)(vcpu); \
+       PPC_LL  r17, VCPU_GPR(R17)(vcpu); \
+       PPC_LL  r18, VCPU_GPR(R18)(vcpu); \
+       PPC_LL  r19, VCPU_GPR(R19)(vcpu); \
+       PPC_LL  r20, VCPU_GPR(R20)(vcpu); \
+       PPC_LL  r21, VCPU_GPR(R21)(vcpu); \
+       PPC_LL  r22, VCPU_GPR(R22)(vcpu); \
+       PPC_LL  r23, VCPU_GPR(R23)(vcpu); \
+       PPC_LL  r24, VCPU_GPR(R24)(vcpu); \
+       PPC_LL  r25, VCPU_GPR(R25)(vcpu); \
+       PPC_LL  r26, VCPU_GPR(R26)(vcpu); \
+       PPC_LL  r27, VCPU_GPR(R27)(vcpu); \
+       PPC_LL  r28, VCPU_GPR(R28)(vcpu); \
+       PPC_LL  r29, VCPU_GPR(R29)(vcpu); \
+       PPC_LL  r30, VCPU_GPR(R30)(vcpu); \
+       PPC_LL  r31, VCPU_GPR(R31)(vcpu); \
 
 /*****************************************************************************
  *                                                                           *
@@ -131,24 +123,24 @@ kvmppc_handler_highmem:
        /* R7 = vcpu */
        PPC_LL  r7, GPR4(r1)
 
-       PPC_STL r14, VCPU_GPR(r14)(r7)
-       PPC_STL r15, VCPU_GPR(r15)(r7)
-       PPC_STL r16, VCPU_GPR(r16)(r7)
-       PPC_STL r17, VCPU_GPR(r17)(r7)
-       PPC_STL r18, VCPU_GPR(r18)(r7)
-       PPC_STL r19, VCPU_GPR(r19)(r7)
-       PPC_STL r20, VCPU_GPR(r20)(r7)
-       PPC_STL r21, VCPU_GPR(r21)(r7)
-       PPC_STL r22, VCPU_GPR(r22)(r7)
-       PPC_STL r23, VCPU_GPR(r23)(r7)
-       PPC_STL r24, VCPU_GPR(r24)(r7)
-       PPC_STL r25, VCPU_GPR(r25)(r7)
-       PPC_STL r26, VCPU_GPR(r26)(r7)
-       PPC_STL r27, VCPU_GPR(r27)(r7)
-       PPC_STL r28, VCPU_GPR(r28)(r7)
-       PPC_STL r29, VCPU_GPR(r29)(r7)
-       PPC_STL r30, VCPU_GPR(r30)(r7)
-       PPC_STL r31, VCPU_GPR(r31)(r7)
+       PPC_STL r14, VCPU_GPR(R14)(r7)
+       PPC_STL r15, VCPU_GPR(R15)(r7)
+       PPC_STL r16, VCPU_GPR(R16)(r7)
+       PPC_STL r17, VCPU_GPR(R17)(r7)
+       PPC_STL r18, VCPU_GPR(R18)(r7)
+       PPC_STL r19, VCPU_GPR(R19)(r7)
+       PPC_STL r20, VCPU_GPR(R20)(r7)
+       PPC_STL r21, VCPU_GPR(R21)(r7)
+       PPC_STL r22, VCPU_GPR(R22)(r7)
+       PPC_STL r23, VCPU_GPR(R23)(r7)
+       PPC_STL r24, VCPU_GPR(R24)(r7)
+       PPC_STL r25, VCPU_GPR(R25)(r7)
+       PPC_STL r26, VCPU_GPR(R26)(r7)
+       PPC_STL r27, VCPU_GPR(R27)(r7)
+       PPC_STL r28, VCPU_GPR(R28)(r7)
+       PPC_STL r29, VCPU_GPR(R29)(r7)
+       PPC_STL r30, VCPU_GPR(R30)(r7)
+       PPC_STL r31, VCPU_GPR(R31)(r7)
 
        /* Pass the exit number as 3rd argument to kvmppc_handle_exit */
        mr      r5, r12
index 34187585c50731717bb4ccec8660d0a4740ccf85..ab523f3c1731a0ecf57e3fec538442875d1107ef 100644 (file)
@@ -37,7 +37,6 @@
 #if defined(CONFIG_PPC_BOOK3S_64)
 
 #define FUNC(name)             GLUE(.,name)
-#define MTMSR_EERI(reg)                mtmsrd  (reg),1
 
        .globl  kvmppc_skip_interrupt
 kvmppc_skip_interrupt:
index 798491a268b3f6d0da8e4b9c96fbbcca64d44dd2..1abe4788191ae15855305dc11fffa7486ceffd9b 100644 (file)
@@ -23,7 +23,6 @@
 
 #define GET_SHADOW_VCPU(reg)    \
        mr      reg, r13
-#define MTMSR_EERI(reg)                mtmsrd  (reg),1
 
 #elif defined(CONFIG_PPC_BOOK3S_32)
 
@@ -31,7 +30,6 @@
        tophys(reg, r2);                        \
        lwz     reg, (THREAD + THREAD_KVM_SVCPU)(reg);  \
        tophys(reg, reg)
-#define MTMSR_EERI(reg)                mtmsr   (reg)
 
 #endif
 
index 8feec2ff3928e2e89ce917588704b95d661bf149..8fd4b2a0911b76ba60f1c5c35c3ed2cd9f84a49c 100644 (file)
@@ -25,8 +25,6 @@
 #include <asm/page.h>
 #include <asm/asm-offsets.h>
 
-#define VCPU_GPR(n)     (VCPU_GPRS + (n * 4))
-
 /* The host stack layout: */
 #define HOST_R1         0 /* Implied by stwu. */
 #define HOST_CALLEE_LR  4
@@ -36,8 +34,9 @@
 #define HOST_R2         12
 #define HOST_CR         16
 #define HOST_NV_GPRS    20
-#define HOST_NV_GPR(n)  (HOST_NV_GPRS + ((n - 14) * 4))
-#define HOST_MIN_STACK_SIZE (HOST_NV_GPR(31) + 4)
+#define __HOST_NV_GPR(n)  (HOST_NV_GPRS + ((n - 14) * 4))
+#define HOST_NV_GPR(n)  __HOST_NV_GPR(__REG_##n)
+#define HOST_MIN_STACK_SIZE (HOST_NV_GPR(R31) + 4)
 #define HOST_STACK_SIZE (((HOST_MIN_STACK_SIZE + 15) / 16) * 16) /* Align. */
 #define HOST_STACK_LR   (HOST_STACK_SIZE + 4) /* In caller stack frame. */
 
@@ -58,8 +57,8 @@ _GLOBAL(kvmppc_handler_\ivor_nr)
        /* Get pointer to vcpu and record exit number. */
        mtspr   SPRN_SPRG_WSCRATCH0, r4
        mfspr   r4, SPRN_SPRG_RVCPU
-       stw     r5, VCPU_GPR(r5)(r4)
-       stw     r6, VCPU_GPR(r6)(r4)
+       stw     r5, VCPU_GPR(R5)(r4)
+       stw     r6, VCPU_GPR(R6)(r4)
        mfctr   r5
        lis     r6, kvmppc_resume_host@h
        stw     r5, VCPU_CTR(r4)
@@ -100,12 +99,12 @@ _GLOBAL(kvmppc_handler_len)
  *  r5: KVM exit number
  */
 _GLOBAL(kvmppc_resume_host)
-       stw     r3, VCPU_GPR(r3)(r4)
+       stw     r3, VCPU_GPR(R3)(r4)
        mfcr    r3
        stw     r3, VCPU_CR(r4)
-       stw     r7, VCPU_GPR(r7)(r4)
-       stw     r8, VCPU_GPR(r8)(r4)
-       stw     r9, VCPU_GPR(r9)(r4)
+       stw     r7, VCPU_GPR(R7)(r4)
+       stw     r8, VCPU_GPR(R8)(r4)
+       stw     r9, VCPU_GPR(R9)(r4)
 
        li      r6, 1
        slw     r6, r6, r5
@@ -135,23 +134,23 @@ _GLOBAL(kvmppc_resume_host)
        isync
        stw     r9, VCPU_LAST_INST(r4)
 
-       stw     r15, VCPU_GPR(r15)(r4)
-       stw     r16, VCPU_GPR(r16)(r4)
-       stw     r17, VCPU_GPR(r17)(r4)
-       stw     r18, VCPU_GPR(r18)(r4)
-       stw     r19, VCPU_GPR(r19)(r4)
-       stw     r20, VCPU_GPR(r20)(r4)
-       stw     r21, VCPU_GPR(r21)(r4)
-       stw     r22, VCPU_GPR(r22)(r4)
-       stw     r23, VCPU_GPR(r23)(r4)
-       stw     r24, VCPU_GPR(r24)(r4)
-       stw     r25, VCPU_GPR(r25)(r4)
-       stw     r26, VCPU_GPR(r26)(r4)
-       stw     r27, VCPU_GPR(r27)(r4)
-       stw     r28, VCPU_GPR(r28)(r4)
-       stw     r29, VCPU_GPR(r29)(r4)
-       stw     r30, VCPU_GPR(r30)(r4)
-       stw     r31, VCPU_GPR(r31)(r4)
+       stw     r15, VCPU_GPR(R15)(r4)
+       stw     r16, VCPU_GPR(R16)(r4)
+       stw     r17, VCPU_GPR(R17)(r4)
+       stw     r18, VCPU_GPR(R18)(r4)
+       stw     r19, VCPU_GPR(R19)(r4)
+       stw     r20, VCPU_GPR(R20)(r4)
+       stw     r21, VCPU_GPR(R21)(r4)
+       stw     r22, VCPU_GPR(R22)(r4)
+       stw     r23, VCPU_GPR(R23)(r4)
+       stw     r24, VCPU_GPR(R24)(r4)
+       stw     r25, VCPU_GPR(R25)(r4)
+       stw     r26, VCPU_GPR(R26)(r4)
+       stw     r27, VCPU_GPR(R27)(r4)
+       stw     r28, VCPU_GPR(R28)(r4)
+       stw     r29, VCPU_GPR(R29)(r4)
+       stw     r30, VCPU_GPR(R30)(r4)
+       stw     r31, VCPU_GPR(R31)(r4)
 ..skip_inst_copy:
 
        /* Also grab DEAR and ESR before the host can clobber them. */
@@ -169,20 +168,20 @@ _GLOBAL(kvmppc_resume_host)
 ..skip_esr:
 
        /* Save remaining volatile guest register state to vcpu. */
-       stw     r0, VCPU_GPR(r0)(r4)
-       stw     r1, VCPU_GPR(r1)(r4)
-       stw     r2, VCPU_GPR(r2)(r4)
-       stw     r10, VCPU_GPR(r10)(r4)
-       stw     r11, VCPU_GPR(r11)(r4)
-       stw     r12, VCPU_GPR(r12)(r4)
-       stw     r13, VCPU_GPR(r13)(r4)
-       stw     r14, VCPU_GPR(r14)(r4) /* We need a NV GPR below. */
+       stw     r0, VCPU_GPR(R0)(r4)
+       stw     r1, VCPU_GPR(R1)(r4)
+       stw     r2, VCPU_GPR(R2)(r4)
+       stw     r10, VCPU_GPR(R10)(r4)
+       stw     r11, VCPU_GPR(R11)(r4)
+       stw     r12, VCPU_GPR(R12)(r4)
+       stw     r13, VCPU_GPR(R13)(r4)
+       stw     r14, VCPU_GPR(R14)(r4) /* We need a NV GPR below. */
        mflr    r3
        stw     r3, VCPU_LR(r4)
        mfxer   r3
        stw     r3, VCPU_XER(r4)
        mfspr   r3, SPRN_SPRG_RSCRATCH0
-       stw     r3, VCPU_GPR(r4)(r4)
+       stw     r3, VCPU_GPR(R4)(r4)
        mfspr   r3, SPRN_SRR0
        stw     r3, VCPU_PC(r4)
 
@@ -214,28 +213,28 @@ _GLOBAL(kvmppc_resume_host)
 
        /* Restore vcpu pointer and the nonvolatiles we used. */
        mr      r4, r14
-       lwz     r14, VCPU_GPR(r14)(r4)
+       lwz     r14, VCPU_GPR(R14)(r4)
 
        /* Sometimes instruction emulation must restore complete GPR state. */
        andi.   r5, r3, RESUME_FLAG_NV
        beq     ..skip_nv_load
-       lwz     r15, VCPU_GPR(r15)(r4)
-       lwz     r16, VCPU_GPR(r16)(r4)
-       lwz     r17, VCPU_GPR(r17)(r4)
-       lwz     r18, VCPU_GPR(r18)(r4)
-       lwz     r19, VCPU_GPR(r19)(r4)
-       lwz     r20, VCPU_GPR(r20)(r4)
-       lwz     r21, VCPU_GPR(r21)(r4)
-       lwz     r22, VCPU_GPR(r22)(r4)
-       lwz     r23, VCPU_GPR(r23)(r4)
-       lwz     r24, VCPU_GPR(r24)(r4)
-       lwz     r25, VCPU_GPR(r25)(r4)
-       lwz     r26, VCPU_GPR(r26)(r4)
-       lwz     r27, VCPU_GPR(r27)(r4)
-       lwz     r28, VCPU_GPR(r28)(r4)
-       lwz     r29, VCPU_GPR(r29)(r4)
-       lwz     r30, VCPU_GPR(r30)(r4)
-       lwz     r31, VCPU_GPR(r31)(r4)
+       lwz     r15, VCPU_GPR(R15)(r4)
+       lwz     r16, VCPU_GPR(R16)(r4)
+       lwz     r17, VCPU_GPR(R17)(r4)
+       lwz     r18, VCPU_GPR(R18)(r4)
+       lwz     r19, VCPU_GPR(R19)(r4)
+       lwz     r20, VCPU_GPR(R20)(r4)
+       lwz     r21, VCPU_GPR(R21)(r4)
+       lwz     r22, VCPU_GPR(R22)(r4)
+       lwz     r23, VCPU_GPR(R23)(r4)
+       lwz     r24, VCPU_GPR(R24)(r4)
+       lwz     r25, VCPU_GPR(R25)(r4)
+       lwz     r26, VCPU_GPR(R26)(r4)
+       lwz     r27, VCPU_GPR(R27)(r4)
+       lwz     r28, VCPU_GPR(R28)(r4)
+       lwz     r29, VCPU_GPR(R29)(r4)
+       lwz     r30, VCPU_GPR(R30)(r4)
+       lwz     r31, VCPU_GPR(R31)(r4)
 ..skip_nv_load:
 
        /* Should we return to the guest? */
@@ -257,43 +256,43 @@ heavyweight_exit:
 
        /* We already saved guest volatile register state; now save the
         * non-volatiles. */
-       stw     r15, VCPU_GPR(r15)(r4)
-       stw     r16, VCPU_GPR(r16)(r4)
-       stw     r17, VCPU_GPR(r17)(r4)
-       stw     r18, VCPU_GPR(r18)(r4)
-       stw     r19, VCPU_GPR(r19)(r4)
-       stw     r20, VCPU_GPR(r20)(r4)
-       stw     r21, VCPU_GPR(r21)(r4)
-       stw     r22, VCPU_GPR(r22)(r4)
-       stw     r23, VCPU_GPR(r23)(r4)
-       stw     r24, VCPU_GPR(r24)(r4)
-       stw     r25, VCPU_GPR(r25)(r4)
-       stw     r26, VCPU_GPR(r26)(r4)
-       stw     r27, VCPU_GPR(r27)(r4)
-       stw     r28, VCPU_GPR(r28)(r4)
-       stw     r29, VCPU_GPR(r29)(r4)
-       stw     r30, VCPU_GPR(r30)(r4)
-       stw     r31, VCPU_GPR(r31)(r4)
+       stw     r15, VCPU_GPR(R15)(r4)
+       stw     r16, VCPU_GPR(R16)(r4)
+       stw     r17, VCPU_GPR(R17)(r4)
+       stw     r18, VCPU_GPR(R18)(r4)
+       stw     r19, VCPU_GPR(R19)(r4)
+       stw     r20, VCPU_GPR(R20)(r4)
+       stw     r21, VCPU_GPR(R21)(r4)
+       stw     r22, VCPU_GPR(R22)(r4)
+       stw     r23, VCPU_GPR(R23)(r4)
+       stw     r24, VCPU_GPR(R24)(r4)
+       stw     r25, VCPU_GPR(R25)(r4)
+       stw     r26, VCPU_GPR(R26)(r4)
+       stw     r27, VCPU_GPR(R27)(r4)
+       stw     r28, VCPU_GPR(R28)(r4)
+       stw     r29, VCPU_GPR(R29)(r4)
+       stw     r30, VCPU_GPR(R30)(r4)
+       stw     r31, VCPU_GPR(R31)(r4)
 
        /* Load host non-volatile register state from host stack. */
-       lwz     r14, HOST_NV_GPR(r14)(r1)
-       lwz     r15, HOST_NV_GPR(r15)(r1)
-       lwz     r16, HOST_NV_GPR(r16)(r1)
-       lwz     r17, HOST_NV_GPR(r17)(r1)
-       lwz     r18, HOST_NV_GPR(r18)(r1)
-       lwz     r19, HOST_NV_GPR(r19)(r1)
-       lwz     r20, HOST_NV_GPR(r20)(r1)
-       lwz     r21, HOST_NV_GPR(r21)(r1)
-       lwz     r22, HOST_NV_GPR(r22)(r1)
-       lwz     r23, HOST_NV_GPR(r23)(r1)
-       lwz     r24, HOST_NV_GPR(r24)(r1)
-       lwz     r25, HOST_NV_GPR(r25)(r1)
-       lwz     r26, HOST_NV_GPR(r26)(r1)
-       lwz     r27, HOST_NV_GPR(r27)(r1)
-       lwz     r28, HOST_NV_GPR(r28)(r1)
-       lwz     r29, HOST_NV_GPR(r29)(r1)
-       lwz     r30, HOST_NV_GPR(r30)(r1)
-       lwz     r31, HOST_NV_GPR(r31)(r1)
+       lwz     r14, HOST_NV_GPR(R14)(r1)
+       lwz     r15, HOST_NV_GPR(R15)(r1)
+       lwz     r16, HOST_NV_GPR(R16)(r1)
+       lwz     r17, HOST_NV_GPR(R17)(r1)
+       lwz     r18, HOST_NV_GPR(R18)(r1)
+       lwz     r19, HOST_NV_GPR(R19)(r1)
+       lwz     r20, HOST_NV_GPR(R20)(r1)
+       lwz     r21, HOST_NV_GPR(R21)(r1)
+       lwz     r22, HOST_NV_GPR(R22)(r1)
+       lwz     r23, HOST_NV_GPR(R23)(r1)
+       lwz     r24, HOST_NV_GPR(R24)(r1)
+       lwz     r25, HOST_NV_GPR(R25)(r1)
+       lwz     r26, HOST_NV_GPR(R26)(r1)
+       lwz     r27, HOST_NV_GPR(R27)(r1)
+       lwz     r28, HOST_NV_GPR(R28)(r1)
+       lwz     r29, HOST_NV_GPR(R29)(r1)
+       lwz     r30, HOST_NV_GPR(R30)(r1)
+       lwz     r31, HOST_NV_GPR(R31)(r1)
 
        /* Return to kvm_vcpu_run(). */
        lwz     r4, HOST_STACK_LR(r1)
@@ -321,44 +320,44 @@ _GLOBAL(__kvmppc_vcpu_run)
        stw     r5, HOST_CR(r1)
 
        /* Save host non-volatile register state to stack. */
-       stw     r14, HOST_NV_GPR(r14)(r1)
-       stw     r15, HOST_NV_GPR(r15)(r1)
-       stw     r16, HOST_NV_GPR(r16)(r1)
-       stw     r17, HOST_NV_GPR(r17)(r1)
-       stw     r18, HOST_NV_GPR(r18)(r1)
-       stw     r19, HOST_NV_GPR(r19)(r1)
-       stw     r20, HOST_NV_GPR(r20)(r1)
-       stw     r21, HOST_NV_GPR(r21)(r1)
-       stw     r22, HOST_NV_GPR(r22)(r1)
-       stw     r23, HOST_NV_GPR(r23)(r1)
-       stw     r24, HOST_NV_GPR(r24)(r1)
-       stw     r25, HOST_NV_GPR(r25)(r1)
-       stw     r26, HOST_NV_GPR(r26)(r1)
-       stw     r27, HOST_NV_GPR(r27)(r1)
-       stw     r28, HOST_NV_GPR(r28)(r1)
-       stw     r29, HOST_NV_GPR(r29)(r1)
-       stw     r30, HOST_NV_GPR(r30)(r1)
-       stw     r31, HOST_NV_GPR(r31)(r1)
+       stw     r14, HOST_NV_GPR(R14)(r1)
+       stw     r15, HOST_NV_GPR(R15)(r1)
+       stw     r16, HOST_NV_GPR(R16)(r1)
+       stw     r17, HOST_NV_GPR(R17)(r1)
+       stw     r18, HOST_NV_GPR(R18)(r1)
+       stw     r19, HOST_NV_GPR(R19)(r1)
+       stw     r20, HOST_NV_GPR(R20)(r1)
+       stw     r21, HOST_NV_GPR(R21)(r1)
+       stw     r22, HOST_NV_GPR(R22)(r1)
+       stw     r23, HOST_NV_GPR(R23)(r1)
+       stw     r24, HOST_NV_GPR(R24)(r1)
+       stw     r25, HOST_NV_GPR(R25)(r1)
+       stw     r26, HOST_NV_GPR(R26)(r1)
+       stw     r27, HOST_NV_GPR(R27)(r1)
+       stw     r28, HOST_NV_GPR(R28)(r1)
+       stw     r29, HOST_NV_GPR(R29)(r1)
+       stw     r30, HOST_NV_GPR(R30)(r1)
+       stw     r31, HOST_NV_GPR(R31)(r1)
 
        /* Load guest non-volatiles. */
-       lwz     r14, VCPU_GPR(r14)(r4)
-       lwz     r15, VCPU_GPR(r15)(r4)
-       lwz     r16, VCPU_GPR(r16)(r4)
-       lwz     r17, VCPU_GPR(r17)(r4)
-       lwz     r18, VCPU_GPR(r18)(r4)
-       lwz     r19, VCPU_GPR(r19)(r4)
-       lwz     r20, VCPU_GPR(r20)(r4)
-       lwz     r21, VCPU_GPR(r21)(r4)
-       lwz     r22, VCPU_GPR(r22)(r4)
-       lwz     r23, VCPU_GPR(r23)(r4)
-       lwz     r24, VCPU_GPR(r24)(r4)
-       lwz     r25, VCPU_GPR(r25)(r4)
-       lwz     r26, VCPU_GPR(r26)(r4)
-       lwz     r27, VCPU_GPR(r27)(r4)
-       lwz     r28, VCPU_GPR(r28)(r4)
-       lwz     r29, VCPU_GPR(r29)(r4)
-       lwz     r30, VCPU_GPR(r30)(r4)
-       lwz     r31, VCPU_GPR(r31)(r4)
+       lwz     r14, VCPU_GPR(R14)(r4)
+       lwz     r15, VCPU_GPR(R15)(r4)
+       lwz     r16, VCPU_GPR(R16)(r4)
+       lwz     r17, VCPU_GPR(R17)(r4)
+       lwz     r18, VCPU_GPR(R18)(r4)
+       lwz     r19, VCPU_GPR(R19)(r4)
+       lwz     r20, VCPU_GPR(R20)(r4)
+       lwz     r21, VCPU_GPR(R21)(r4)
+       lwz     r22, VCPU_GPR(R22)(r4)
+       lwz     r23, VCPU_GPR(R23)(r4)
+       lwz     r24, VCPU_GPR(R24)(r4)
+       lwz     r25, VCPU_GPR(R25)(r4)
+       lwz     r26, VCPU_GPR(R26)(r4)
+       lwz     r27, VCPU_GPR(R27)(r4)
+       lwz     r28, VCPU_GPR(R28)(r4)
+       lwz     r29, VCPU_GPR(R29)(r4)
+       lwz     r30, VCPU_GPR(R30)(r4)
+       lwz     r31, VCPU_GPR(R31)(r4)
 
 #ifdef CONFIG_SPE
        /* save host SPEFSCR and load guest SPEFSCR */
@@ -386,13 +385,13 @@ lightweight_exit:
 #endif
 
        /* Load some guest volatiles. */
-       lwz     r0, VCPU_GPR(r0)(r4)
-       lwz     r2, VCPU_GPR(r2)(r4)
-       lwz     r9, VCPU_GPR(r9)(r4)
-       lwz     r10, VCPU_GPR(r10)(r4)
-       lwz     r11, VCPU_GPR(r11)(r4)
-       lwz     r12, VCPU_GPR(r12)(r4)
-       lwz     r13, VCPU_GPR(r13)(r4)
+       lwz     r0, VCPU_GPR(R0)(r4)
+       lwz     r2, VCPU_GPR(R2)(r4)
+       lwz     r9, VCPU_GPR(R9)(r4)
+       lwz     r10, VCPU_GPR(R10)(r4)
+       lwz     r11, VCPU_GPR(R11)(r4)
+       lwz     r12, VCPU_GPR(R12)(r4)
+       lwz     r13, VCPU_GPR(R13)(r4)
        lwz     r3, VCPU_LR(r4)
        mtlr    r3
        lwz     r3, VCPU_XER(r4)
@@ -411,7 +410,7 @@ lightweight_exit:
 
        /* Can't switch the stack pointer until after IVPR is switched,
         * because host interrupt handlers would get confused. */
-       lwz     r1, VCPU_GPR(r1)(r4)
+       lwz     r1, VCPU_GPR(R1)(r4)
 
        /*
         * Host interrupt handlers may have clobbered these
@@ -449,10 +448,10 @@ lightweight_exit:
        mtcr    r5
        mtsrr0  r6
        mtsrr1  r7
-       lwz     r5, VCPU_GPR(r5)(r4)
-       lwz     r6, VCPU_GPR(r6)(r4)
-       lwz     r7, VCPU_GPR(r7)(r4)
-       lwz     r8, VCPU_GPR(r8)(r4)
+       lwz     r5, VCPU_GPR(R5)(r4)
+       lwz     r6, VCPU_GPR(R6)(r4)
+       lwz     r7, VCPU_GPR(R7)(r4)
+       lwz     r8, VCPU_GPR(R8)(r4)
 
        /* Clear any debug events which occurred since we disabled MSR[DE].
         * XXX This gives us a 3-instruction window in which a breakpoint
@@ -461,8 +460,8 @@ lightweight_exit:
        ori     r3, r3, 0xffff
        mtspr   SPRN_DBSR, r3
 
-       lwz     r3, VCPU_GPR(r3)(r4)
-       lwz     r4, VCPU_GPR(r4)(r4)
+       lwz     r3, VCPU_GPR(R3)(r4)
+       lwz     r4, VCPU_GPR(R4)(r4)
        rfi
 
 #ifdef CONFIG_SPE
index 6048a00515d7613d3c21346692477c0e24429f37..1685dc43bcf286615b246eb83f163a3a183bb2c3 100644 (file)
@@ -37,7 +37,6 @@
 
 #define LONGBYTES              (BITS_PER_LONG / 8)
 
-#define VCPU_GPR(n)            (VCPU_GPRS + (n * LONGBYTES))
 #define VCPU_GUEST_SPRG(n)     (VCPU_GUEST_SPRGS + (n * LONGBYTES))
 
 /* The host stack layout: */
  */
 .macro kvm_handler_common intno, srr0, flags
        /* Restore host stack pointer */
-       PPC_STL r1, VCPU_GPR(r1)(r4)
-       PPC_STL r2, VCPU_GPR(r2)(r4)
+       PPC_STL r1, VCPU_GPR(R1)(r4)
+       PPC_STL r2, VCPU_GPR(R2)(r4)
        PPC_LL  r1, VCPU_HOST_STACK(r4)
        PPC_LL  r2, HOST_R2(r1)
 
        mfspr   r10, SPRN_PID
        lwz     r8, VCPU_HOST_PID(r4)
        PPC_LL  r11, VCPU_SHARED(r4)
-       PPC_STL r14, VCPU_GPR(r14)(r4) /* We need a non-volatile GPR. */
+       PPC_STL r14, VCPU_GPR(R14)(r4) /* We need a non-volatile GPR. */
        li      r14, \intno
 
        stw     r10, VCPU_GUEST_PID(r4)
         */
 
        mfspr   r3, SPRN_EPLC   /* will already have correct ELPID and EGS */
-       PPC_STL r15, VCPU_GPR(r15)(r4)
-       PPC_STL r16, VCPU_GPR(r16)(r4)
-       PPC_STL r17, VCPU_GPR(r17)(r4)
-       PPC_STL r18, VCPU_GPR(r18)(r4)
-       PPC_STL r19, VCPU_GPR(r19)(r4)
+       PPC_STL r15, VCPU_GPR(R15)(r4)
+       PPC_STL r16, VCPU_GPR(R16)(r4)
+       PPC_STL r17, VCPU_GPR(R17)(r4)
+       PPC_STL r18, VCPU_GPR(R18)(r4)
+       PPC_STL r19, VCPU_GPR(R19)(r4)
        mr      r8, r3
-       PPC_STL r20, VCPU_GPR(r20)(r4)
+       PPC_STL r20, VCPU_GPR(R20)(r4)
        rlwimi  r8, r6, EPC_EAS_SHIFT - MSR_IR_LG, EPC_EAS
-       PPC_STL r21, VCPU_GPR(r21)(r4)
+       PPC_STL r21, VCPU_GPR(R21)(r4)
        rlwimi  r8, r6, EPC_EPR_SHIFT - MSR_PR_LG, EPC_EPR
-       PPC_STL r22, VCPU_GPR(r22)(r4)
+       PPC_STL r22, VCPU_GPR(R22)(r4)
        rlwimi  r8, r10, EPC_EPID_SHIFT, EPC_EPID
-       PPC_STL r23, VCPU_GPR(r23)(r4)
-       PPC_STL r24, VCPU_GPR(r24)(r4)
-       PPC_STL r25, VCPU_GPR(r25)(r4)
-       PPC_STL r26, VCPU_GPR(r26)(r4)
-       PPC_STL r27, VCPU_GPR(r27)(r4)
-       PPC_STL r28, VCPU_GPR(r28)(r4)
-       PPC_STL r29, VCPU_GPR(r29)(r4)
-       PPC_STL r30, VCPU_GPR(r30)(r4)
-       PPC_STL r31, VCPU_GPR(r31)(r4)
+       PPC_STL r23, VCPU_GPR(R23)(r4)
+       PPC_STL r24, VCPU_GPR(R24)(r4)
+       PPC_STL r25, VCPU_GPR(R25)(r4)
+       PPC_STL r26, VCPU_GPR(R26)(r4)
+       PPC_STL r27, VCPU_GPR(R27)(r4)
+       PPC_STL r28, VCPU_GPR(R28)(r4)
+       PPC_STL r29, VCPU_GPR(R29)(r4)
+       PPC_STL r30, VCPU_GPR(R30)(r4)
+       PPC_STL r31, VCPU_GPR(R31)(r4)
        mtspr   SPRN_EPLC, r8
 
        /* disable preemption, so we are sure we hit the fixup handler */
-#ifdef CONFIG_PPC64
-       clrrdi  r8,r1,THREAD_SHIFT
-#else
-       rlwinm  r8,r1,0,0,31-THREAD_SHIFT       /* current thread_info */
-#endif
+       CURRENT_THREAD_INFO(r8, r1)
        li      r7, 1
        stw     r7, TI_PREEMPT(r8)
 
 .macro kvm_handler intno srr0, srr1, flags
 _GLOBAL(kvmppc_handler_\intno\()_\srr1)
        GET_VCPU(r11, r10)
-       PPC_STL r3, VCPU_GPR(r3)(r11)
+       PPC_STL r3, VCPU_GPR(R3)(r11)
        mfspr   r3, SPRN_SPRG_RSCRATCH0
-       PPC_STL r4, VCPU_GPR(r4)(r11)
+       PPC_STL r4, VCPU_GPR(R4)(r11)
        PPC_LL  r4, THREAD_NORMSAVE(0)(r10)
-       PPC_STL r5, VCPU_GPR(r5)(r11)
+       PPC_STL r5, VCPU_GPR(R5)(r11)
        stw     r13, VCPU_CR(r11)
        mfspr   r5, \srr0
-       PPC_STL r3, VCPU_GPR(r10)(r11)
+       PPC_STL r3, VCPU_GPR(R10)(r11)
        PPC_LL  r3, THREAD_NORMSAVE(2)(r10)
-       PPC_STL r6, VCPU_GPR(r6)(r11)
-       PPC_STL r4, VCPU_GPR(r11)(r11)
+       PPC_STL r6, VCPU_GPR(R6)(r11)
+       PPC_STL r4, VCPU_GPR(R11)(r11)
        mfspr   r6, \srr1
-       PPC_STL r7, VCPU_GPR(r7)(r11)
-       PPC_STL r8, VCPU_GPR(r8)(r11)
-       PPC_STL r9, VCPU_GPR(r9)(r11)
-       PPC_STL r3, VCPU_GPR(r13)(r11)
+       PPC_STL r7, VCPU_GPR(R7)(r11)
+       PPC_STL r8, VCPU_GPR(R8)(r11)
+       PPC_STL r9, VCPU_GPR(R9)(r11)
+       PPC_STL r3, VCPU_GPR(R13)(r11)
        mfctr   r7
-       PPC_STL r12, VCPU_GPR(r12)(r11)
+       PPC_STL r12, VCPU_GPR(R12)(r11)
        PPC_STL r7, VCPU_CTR(r11)
        mr      r4, r11
        kvm_handler_common \intno, \srr0, \flags
@@ -238,25 +233,25 @@ _GLOBAL(kvmppc_handler_\intno\()_\srr1)
 _GLOBAL(kvmppc_handler_\intno\()_\srr1)
        mfspr   r10, SPRN_SPRG_THREAD
        GET_VCPU(r11, r10)
-       PPC_STL r3, VCPU_GPR(r3)(r11)
+       PPC_STL r3, VCPU_GPR(R3)(r11)
        mfspr   r3, \scratch
-       PPC_STL r4, VCPU_GPR(r4)(r11)
+       PPC_STL r4, VCPU_GPR(R4)(r11)
        PPC_LL  r4, GPR9(r8)
-       PPC_STL r5, VCPU_GPR(r5)(r11)
+       PPC_STL r5, VCPU_GPR(R5)(r11)
        stw     r9, VCPU_CR(r11)
        mfspr   r5, \srr0
-       PPC_STL r3, VCPU_GPR(r8)(r11)
+       PPC_STL r3, VCPU_GPR(R8)(r11)
        PPC_LL  r3, GPR10(r8)
-       PPC_STL r6, VCPU_GPR(r6)(r11)
-       PPC_STL r4, VCPU_GPR(r9)(r11)
+       PPC_STL r6, VCPU_GPR(R6)(r11)
+       PPC_STL r4, VCPU_GPR(R9)(r11)
        mfspr   r6, \srr1
        PPC_LL  r4, GPR11(r8)
-       PPC_STL r7, VCPU_GPR(r7)(r11)
-       PPC_STL r3, VCPU_GPR(r10)(r11)
+       PPC_STL r7, VCPU_GPR(R7)(r11)
+       PPC_STL r3, VCPU_GPR(R10)(r11)
        mfctr   r7
-       PPC_STL r12, VCPU_GPR(r12)(r11)
-       PPC_STL r13, VCPU_GPR(r13)(r11)
-       PPC_STL r4, VCPU_GPR(r11)(r11)
+       PPC_STL r12, VCPU_GPR(R12)(r11)
+       PPC_STL r13, VCPU_GPR(R13)(r11)
+       PPC_STL r4, VCPU_GPR(R11)(r11)
        PPC_STL r7, VCPU_CTR(r11)
        mr      r4, r11
        kvm_handler_common \intno, \srr0, \flags
@@ -310,7 +305,7 @@ kvm_lvl_handler BOOKE_INTERRUPT_DEBUG, \
 _GLOBAL(kvmppc_resume_host)
        /* Save remaining volatile guest register state to vcpu. */
        mfspr   r3, SPRN_VRSAVE
-       PPC_STL r0, VCPU_GPR(r0)(r4)
+       PPC_STL r0, VCPU_GPR(R0)(r4)
        mflr    r5
        mfspr   r6, SPRN_SPRG4
        PPC_STL r5, VCPU_LR(r4)
@@ -358,27 +353,27 @@ _GLOBAL(kvmppc_resume_host)
 
        /* Restore vcpu pointer and the nonvolatiles we used. */
        mr      r4, r14
-       PPC_LL  r14, VCPU_GPR(r14)(r4)
+       PPC_LL  r14, VCPU_GPR(R14)(r4)
 
        andi.   r5, r3, RESUME_FLAG_NV
        beq     skip_nv_load
-       PPC_LL  r15, VCPU_GPR(r15)(r4)
-       PPC_LL  r16, VCPU_GPR(r16)(r4)
-       PPC_LL  r17, VCPU_GPR(r17)(r4)
-       PPC_LL  r18, VCPU_GPR(r18)(r4)
-       PPC_LL  r19, VCPU_GPR(r19)(r4)
-       PPC_LL  r20, VCPU_GPR(r20)(r4)
-       PPC_LL  r21, VCPU_GPR(r21)(r4)
-       PPC_LL  r22, VCPU_GPR(r22)(r4)
-       PPC_LL  r23, VCPU_GPR(r23)(r4)
-       PPC_LL  r24, VCPU_GPR(r24)(r4)
-       PPC_LL  r25, VCPU_GPR(r25)(r4)
-       PPC_LL  r26, VCPU_GPR(r26)(r4)
-       PPC_LL  r27, VCPU_GPR(r27)(r4)
-       PPC_LL  r28, VCPU_GPR(r28)(r4)
-       PPC_LL  r29, VCPU_GPR(r29)(r4)
-       PPC_LL  r30, VCPU_GPR(r30)(r4)
-       PPC_LL  r31, VCPU_GPR(r31)(r4)
+       PPC_LL  r15, VCPU_GPR(R15)(r4)
+       PPC_LL  r16, VCPU_GPR(R16)(r4)
+       PPC_LL  r17, VCPU_GPR(R17)(r4)
+       PPC_LL  r18, VCPU_GPR(R18)(r4)
+       PPC_LL  r19, VCPU_GPR(R19)(r4)
+       PPC_LL  r20, VCPU_GPR(R20)(r4)
+       PPC_LL  r21, VCPU_GPR(R21)(r4)
+       PPC_LL  r22, VCPU_GPR(R22)(r4)
+       PPC_LL  r23, VCPU_GPR(R23)(r4)
+       PPC_LL  r24, VCPU_GPR(R24)(r4)
+       PPC_LL  r25, VCPU_GPR(R25)(r4)
+       PPC_LL  r26, VCPU_GPR(R26)(r4)
+       PPC_LL  r27, VCPU_GPR(R27)(r4)
+       PPC_LL  r28, VCPU_GPR(R28)(r4)
+       PPC_LL  r29, VCPU_GPR(R29)(r4)
+       PPC_LL  r30, VCPU_GPR(R30)(r4)
+       PPC_LL  r31, VCPU_GPR(R31)(r4)
 skip_nv_load:
        /* Should we return to the guest? */
        andi.   r5, r3, RESUME_FLAG_HOST
@@ -396,23 +391,23 @@ heavyweight_exit:
         * non-volatiles.
         */
 
-       PPC_STL r15, VCPU_GPR(r15)(r4)
-       PPC_STL r16, VCPU_GPR(r16)(r4)
-       PPC_STL r17, VCPU_GPR(r17)(r4)
-       PPC_STL r18, VCPU_GPR(r18)(r4)
-       PPC_STL r19, VCPU_GPR(r19)(r4)
-       PPC_STL r20, VCPU_GPR(r20)(r4)
-       PPC_STL r21, VCPU_GPR(r21)(r4)
-       PPC_STL r22, VCPU_GPR(r22)(r4)
-       PPC_STL r23, VCPU_GPR(r23)(r4)
-       PPC_STL r24, VCPU_GPR(r24)(r4)
-       PPC_STL r25, VCPU_GPR(r25)(r4)
-       PPC_STL r26, VCPU_GPR(r26)(r4)
-       PPC_STL r27, VCPU_GPR(r27)(r4)
-       PPC_STL r28, VCPU_GPR(r28)(r4)
-       PPC_STL r29, VCPU_GPR(r29)(r4)
-       PPC_STL r30, VCPU_GPR(r30)(r4)
-       PPC_STL r31, VCPU_GPR(r31)(r4)
+       PPC_STL r15, VCPU_GPR(R15)(r4)
+       PPC_STL r16, VCPU_GPR(R16)(r4)
+       PPC_STL r17, VCPU_GPR(R17)(r4)
+       PPC_STL r18, VCPU_GPR(R18)(r4)
+       PPC_STL r19, VCPU_GPR(R19)(r4)
+       PPC_STL r20, VCPU_GPR(R20)(r4)
+       PPC_STL r21, VCPU_GPR(R21)(r4)
+       PPC_STL r22, VCPU_GPR(R22)(r4)
+       PPC_STL r23, VCPU_GPR(R23)(r4)
+       PPC_STL r24, VCPU_GPR(R24)(r4)
+       PPC_STL r25, VCPU_GPR(R25)(r4)
+       PPC_STL r26, VCPU_GPR(R26)(r4)
+       PPC_STL r27, VCPU_GPR(R27)(r4)
+       PPC_STL r28, VCPU_GPR(R28)(r4)
+       PPC_STL r29, VCPU_GPR(R29)(r4)
+       PPC_STL r30, VCPU_GPR(R30)(r4)
+       PPC_STL r31, VCPU_GPR(R31)(r4)
 
        /* Load host non-volatile register state from host stack. */
        PPC_LL  r14, HOST_NV_GPR(r14)(r1)
@@ -478,24 +473,24 @@ _GLOBAL(__kvmppc_vcpu_run)
        PPC_STL r31, HOST_NV_GPR(r31)(r1)
 
        /* Load guest non-volatiles. */
-       PPC_LL  r14, VCPU_GPR(r14)(r4)
-       PPC_LL  r15, VCPU_GPR(r15)(r4)
-       PPC_LL  r16, VCPU_GPR(r16)(r4)
-       PPC_LL  r17, VCPU_GPR(r17)(r4)
-       PPC_LL  r18, VCPU_GPR(r18)(r4)
-       PPC_LL  r19, VCPU_GPR(r19)(r4)
-       PPC_LL  r20, VCPU_GPR(r20)(r4)
-       PPC_LL  r21, VCPU_GPR(r21)(r4)
-       PPC_LL  r22, VCPU_GPR(r22)(r4)
-       PPC_LL  r23, VCPU_GPR(r23)(r4)
-       PPC_LL  r24, VCPU_GPR(r24)(r4)
-       PPC_LL  r25, VCPU_GPR(r25)(r4)
-       PPC_LL  r26, VCPU_GPR(r26)(r4)
-       PPC_LL  r27, VCPU_GPR(r27)(r4)
-       PPC_LL  r28, VCPU_GPR(r28)(r4)
-       PPC_LL  r29, VCPU_GPR(r29)(r4)
-       PPC_LL  r30, VCPU_GPR(r30)(r4)
-       PPC_LL  r31, VCPU_GPR(r31)(r4)
+       PPC_LL  r14, VCPU_GPR(R14)(r4)
+       PPC_LL  r15, VCPU_GPR(R15)(r4)
+       PPC_LL  r16, VCPU_GPR(R16)(r4)
+       PPC_LL  r17, VCPU_GPR(R17)(r4)
+       PPC_LL  r18, VCPU_GPR(R18)(r4)
+       PPC_LL  r19, VCPU_GPR(R19)(r4)
+       PPC_LL  r20, VCPU_GPR(R20)(r4)
+       PPC_LL  r21, VCPU_GPR(R21)(r4)
+       PPC_LL  r22, VCPU_GPR(R22)(r4)
+       PPC_LL  r23, VCPU_GPR(R23)(r4)
+       PPC_LL  r24, VCPU_GPR(R24)(r4)
+       PPC_LL  r25, VCPU_GPR(R25)(r4)
+       PPC_LL  r26, VCPU_GPR(R26)(r4)
+       PPC_LL  r27, VCPU_GPR(R27)(r4)
+       PPC_LL  r28, VCPU_GPR(R28)(r4)
+       PPC_LL  r29, VCPU_GPR(R29)(r4)
+       PPC_LL  r30, VCPU_GPR(R30)(r4)
+       PPC_LL  r31, VCPU_GPR(R31)(r4)
 
 
 lightweight_exit:
@@ -554,13 +549,13 @@ lightweight_exit:
        lwz     r7, VCPU_CR(r4)
        PPC_LL  r8, VCPU_PC(r4)
        PPC_LD(r9, VCPU_SHARED_MSR, r11)
-       PPC_LL  r0, VCPU_GPR(r0)(r4)
-       PPC_LL  r1, VCPU_GPR(r1)(r4)
-       PPC_LL  r2, VCPU_GPR(r2)(r4)
-       PPC_LL  r10, VCPU_GPR(r10)(r4)
-       PPC_LL  r11, VCPU_GPR(r11)(r4)
-       PPC_LL  r12, VCPU_GPR(r12)(r4)
-       PPC_LL  r13, VCPU_GPR(r13)(r4)
+       PPC_LL  r0, VCPU_GPR(R0)(r4)
+       PPC_LL  r1, VCPU_GPR(R1)(r4)
+       PPC_LL  r2, VCPU_GPR(R2)(r4)
+       PPC_LL  r10, VCPU_GPR(R10)(r4)
+       PPC_LL  r11, VCPU_GPR(R11)(r4)
+       PPC_LL  r12, VCPU_GPR(R12)(r4)
+       PPC_LL  r13, VCPU_GPR(R13)(r4)
        mtlr    r3
        mtxer   r5
        mtctr   r6
@@ -586,12 +581,12 @@ lightweight_exit:
        mtcr    r7
 
        /* Finish loading guest volatiles and jump to guest. */
-       PPC_LL  r5, VCPU_GPR(r5)(r4)
-       PPC_LL  r6, VCPU_GPR(r6)(r4)
-       PPC_LL  r7, VCPU_GPR(r7)(r4)
-       PPC_LL  r8, VCPU_GPR(r8)(r4)
-       PPC_LL  r9, VCPU_GPR(r9)(r4)
-
-       PPC_LL  r3, VCPU_GPR(r3)(r4)
-       PPC_LL  r4, VCPU_GPR(r4)(r4)
+       PPC_LL  r5, VCPU_GPR(R5)(r4)
+       PPC_LL  r6, VCPU_GPR(R6)(r4)
+       PPC_LL  r7, VCPU_GPR(R7)(r4)
+       PPC_LL  r8, VCPU_GPR(R8)(r4)
+       PPC_LL  r9, VCPU_GPR(R9)(r4)
+
+       PPC_LL  r3, VCPU_GPR(R3)(r4)
+       PPC_LL  r4, VCPU_GPR(R4)(r4)
        rfi
index 7735a2c2e6d9052db505d50b02fc8ed09750fbc4..746e0c895cd77e866938abef1a6dcb1214edc6a4 100644 (file)
@@ -17,14 +17,15 @@ obj-$(CONFIG_HAS_IOMEM)     += devres.o
 obj-$(CONFIG_PPC64)    += copypage_64.o copyuser_64.o \
                           memcpy_64.o usercopy_64.o mem_64.o string.o \
                           checksum_wrappers_64.o hweight_64.o \
-                          copyuser_power7.o
+                          copyuser_power7.o string_64.o copypage_power7.o \
+                          memcpy_power7.o
 obj-$(CONFIG_XMON)     += sstep.o ldstfp.o
 obj-$(CONFIG_KPROBES)  += sstep.o ldstfp.o
 obj-$(CONFIG_HAVE_HW_BREAKPOINT)       += sstep.o ldstfp.o
 
 ifeq ($(CONFIG_PPC64),y)
 obj-$(CONFIG_SMP)      += locks.o
-obj-$(CONFIG_ALTIVEC)  += copyuser_power7_vmx.o
+obj-$(CONFIG_ALTIVEC)  += vmx-helper.o
 endif
 
 obj-$(CONFIG_PPC_LIB_RHEAP) += rheap.o
index 18245af38aea7f747bd034dd5892c300ce73111c..167f72555d604dc6c24194e3bb9c1e0b3d021bc4 100644 (file)
@@ -65,9 +65,6 @@ _GLOBAL(csum_tcpudp_magic)
        srwi    r3,r3,16
        blr
 
-#define STACKFRAMESIZE 256
-#define STK_REG(i)     (112 + ((i)-14)*8)
-
 /*
  * Computes the checksum of a memory block at buff, length len,
  * and adds in "sum" (32-bit).
@@ -114,9 +111,9 @@ _GLOBAL(csum_partial)
        mtctr   r6
 
        stdu    r1,-STACKFRAMESIZE(r1)
-       std     r14,STK_REG(r14)(r1)
-       std     r15,STK_REG(r15)(r1)
-       std     r16,STK_REG(r16)(r1)
+       std     r14,STK_REG(R14)(r1)
+       std     r15,STK_REG(R15)(r1)
+       std     r16,STK_REG(R16)(r1)
 
        ld      r6,0(r3)
        ld      r9,8(r3)
@@ -175,9 +172,9 @@ _GLOBAL(csum_partial)
        adde    r0,r0,r15
        adde    r0,r0,r16
 
-       ld      r14,STK_REG(r14)(r1)
-       ld      r15,STK_REG(r15)(r1)
-       ld      r16,STK_REG(r16)(r1)
+       ld      r14,STK_REG(R14)(r1)
+       ld      r15,STK_REG(R15)(r1)
+       ld      r16,STK_REG(R16)(r1)
        addi    r1,r1,STACKFRAMESIZE
 
        andi.   r4,r4,63
@@ -299,9 +296,9 @@ dest;       sth     r6,0(r4)
        mtctr   r6
 
        stdu    r1,-STACKFRAMESIZE(r1)
-       std     r14,STK_REG(r14)(r1)
-       std     r15,STK_REG(r15)(r1)
-       std     r16,STK_REG(r16)(r1)
+       std     r14,STK_REG(R14)(r1)
+       std     r15,STK_REG(R15)(r1)
+       std     r16,STK_REG(R16)(r1)
 
 source;        ld      r6,0(r3)
 source;        ld      r9,8(r3)
@@ -382,9 +379,9 @@ dest;       std     r16,56(r4)
        adde    r0,r0,r15
        adde    r0,r0,r16
 
-       ld      r14,STK_REG(r14)(r1)
-       ld      r15,STK_REG(r15)(r1)
-       ld      r16,STK_REG(r16)(r1)
+       ld      r14,STK_REG(R14)(r1)
+       ld      r15,STK_REG(R15)(r1)
+       ld      r16,STK_REG(R16)(r1)
        addi    r1,r1,STACKFRAMESIZE
 
        andi.   r5,r5,63
index 7c975d43e3f388d50152bbdcb42a72adfcb50a13..dd223b3eb333ac3446725f0768d5da412000ba75 100644 (file)
 #include <linux/mm.h>
 #include <asm/page.h>
 #include <asm/code-patching.h>
+#include <asm/uaccess.h>
 
 
-void patch_instruction(unsigned int *addr, unsigned int instr)
+int patch_instruction(unsigned int *addr, unsigned int instr)
 {
-       *addr = instr;
+       int err;
+
+       err = __put_user(instr, addr);
+       if (err)
+               return err;
        asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr));
+       return 0;
 }
 
-void patch_branch(unsigned int *addr, unsigned long target, int flags)
+int patch_branch(unsigned int *addr, unsigned long target, int flags)
 {
-       patch_instruction(addr, create_branch(addr, target, flags));
+       return patch_instruction(addr, create_branch(addr, target, flags));
 }
 
 unsigned int create_branch(const unsigned int *addr,
index 53dcb6b1b708b666429502067dfe9163a60eb571..9f9434a8526443c482b715b74824f99c99d86f0c 100644 (file)
@@ -17,7 +17,11 @@ PPC64_CACHES:
         .section        ".text"
 
 _GLOBAL(copy_page)
+BEGIN_FTR_SECTION
        lis     r5,PAGE_SIZE@h
+FTR_SECTION_ELSE
+       b       .copypage_power7
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_VMX_COPY)
        ori     r5,r5,PAGE_SIZE@l
 BEGIN_FTR_SECTION
        ld      r10,PPC64_CACHES@toc(r2)
diff --git a/arch/powerpc/lib/copypage_power7.S b/arch/powerpc/lib/copypage_power7.S
new file mode 100644 (file)
index 0000000..0ef75bf
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2012
+ *
+ * Author: Anton Blanchard <anton@au.ibm.com>
+ */
+#include <asm/page.h>
+#include <asm/ppc_asm.h>
+
+_GLOBAL(copypage_power7)
+       /*
+        * We prefetch both the source and destination using enhanced touch
+        * instructions. We use a stream ID of 0 for the load side and
+        * 1 for the store side. Since source and destination are page
+        * aligned we don't need to clear the bottom 7 bits of either
+        * address.
+        */
+       ori     r9,r3,1         /* stream=1 */
+
+#ifdef CONFIG_PPC_64K_PAGES
+       lis     r7,0x0E01       /* depth=7, units=512 */
+#else
+       lis     r7,0x0E00       /* depth=7 */
+       ori     r7,r7,0x1000    /* units=32 */
+#endif
+       ori     r10,r7,1        /* stream=1 */
+
+       lis     r8,0x8000       /* GO=1 */
+       clrldi  r8,r8,32
+
+.machine push
+.machine "power4"
+       dcbt    r0,r4,0b01000
+       dcbt    r0,r7,0b01010
+       dcbtst  r0,r9,0b01000
+       dcbtst  r0,r10,0b01010
+       eieio
+       dcbt    r0,r8,0b01010   /* GO */
+.machine pop
+
+#ifdef CONFIG_ALTIVEC
+       mflr    r0
+       std     r3,48(r1)
+       std     r4,56(r1)
+       std     r0,16(r1)
+       stdu    r1,-STACKFRAMESIZE(r1)
+       bl      .enter_vmx_copy
+       cmpwi   r3,0
+       ld      r0,STACKFRAMESIZE+16(r1)
+       ld      r3,STACKFRAMESIZE+48(r1)
+       ld      r4,STACKFRAMESIZE+56(r1)
+       mtlr    r0
+
+       li      r0,(PAGE_SIZE/128)
+       mtctr   r0
+
+       beq     .Lnonvmx_copy
+
+       addi    r1,r1,STACKFRAMESIZE
+
+       li      r6,16
+       li      r7,32
+       li      r8,48
+       li      r9,64
+       li      r10,80
+       li      r11,96
+       li      r12,112
+
+       .align  5
+1:     lvx     vr7,r0,r4
+       lvx     vr6,r4,r6
+       lvx     vr5,r4,r7
+       lvx     vr4,r4,r8
+       lvx     vr3,r4,r9
+       lvx     vr2,r4,r10
+       lvx     vr1,r4,r11
+       lvx     vr0,r4,r12
+       addi    r4,r4,128
+       stvx    vr7,r0,r3
+       stvx    vr6,r3,r6
+       stvx    vr5,r3,r7
+       stvx    vr4,r3,r8
+       stvx    vr3,r3,r9
+       stvx    vr2,r3,r10
+       stvx    vr1,r3,r11
+       stvx    vr0,r3,r12
+       addi    r3,r3,128
+       bdnz    1b
+
+       b       .exit_vmx_copy          /* tail call optimise */
+
+#else
+       li      r0,(PAGE_SIZE/128)
+       mtctr   r0
+
+       stdu    r1,-STACKFRAMESIZE(r1)
+#endif
+
+.Lnonvmx_copy:
+       std     r14,STK_REG(R14)(r1)
+       std     r15,STK_REG(R15)(r1)
+       std     r16,STK_REG(R16)(r1)
+       std     r17,STK_REG(R17)(r1)
+       std     r18,STK_REG(R18)(r1)
+       std     r19,STK_REG(R19)(r1)
+       std     r20,STK_REG(R20)(r1)
+
+1:     ld      r0,0(r4)
+       ld      r5,8(r4)
+       ld      r6,16(r4)
+       ld      r7,24(r4)
+       ld      r8,32(r4)
+       ld      r9,40(r4)
+       ld      r10,48(r4)
+       ld      r11,56(r4)
+       ld      r12,64(r4)
+       ld      r14,72(r4)
+       ld      r15,80(r4)
+       ld      r16,88(r4)
+       ld      r17,96(r4)
+       ld      r18,104(r4)
+       ld      r19,112(r4)
+       ld      r20,120(r4)
+       addi    r4,r4,128
+       std     r0,0(r3)
+       std     r5,8(r3)
+       std     r6,16(r3)
+       std     r7,24(r3)
+       std     r8,32(r3)
+       std     r9,40(r3)
+       std     r10,48(r3)
+       std     r11,56(r3)
+       std     r12,64(r3)
+       std     r14,72(r3)
+       std     r15,80(r3)
+       std     r16,88(r3)
+       std     r17,96(r3)
+       std     r18,104(r3)
+       std     r19,112(r3)
+       std     r20,120(r3)
+       addi    r3,r3,128
+       bdnz    1b
+
+       ld      r14,STK_REG(R14)(r1)
+       ld      r15,STK_REG(R15)(r1)
+       ld      r16,STK_REG(R16)(r1)
+       ld      r17,STK_REG(R17)(r1)
+       ld      r18,STK_REG(R18)(r1)
+       ld      r19,STK_REG(R19)(r1)
+       ld      r20,STK_REG(R20)(r1)
+       addi    r1,r1,STACKFRAMESIZE
+       blr
index 497db7b23bb1be8be3518c12a6e0e7307ddb2fe0..f9ede7c6606e54d36f4b54fddc5b3101085ee5ef 100644 (file)
@@ -19,9 +19,6 @@
  */
 #include <asm/ppc_asm.h>
 
-#define STACKFRAMESIZE 256
-#define STK_REG(i)     (112 + ((i)-14)*8)
-
        .macro err1
 100:
        .section __ex_table,"a"
 
 
 .Ldo_err4:
-       ld      r16,STK_REG(r16)(r1)
-       ld      r15,STK_REG(r15)(r1)
-       ld      r14,STK_REG(r14)(r1)
+       ld      r16,STK_REG(R16)(r1)
+       ld      r15,STK_REG(R15)(r1)
+       ld      r14,STK_REG(R14)(r1)
 .Ldo_err3:
-       bl      .exit_vmx_copy
+       bl      .exit_vmx_usercopy
        ld      r0,STACKFRAMESIZE+16(r1)
        mtlr    r0
        b       .Lexit
 #endif /* CONFIG_ALTIVEC */
 
 .Ldo_err2:
-       ld      r22,STK_REG(r22)(r1)
-       ld      r21,STK_REG(r21)(r1)
-       ld      r20,STK_REG(r20)(r1)
-       ld      r19,STK_REG(r19)(r1)
-       ld      r18,STK_REG(r18)(r1)
-       ld      r17,STK_REG(r17)(r1)
-       ld      r16,STK_REG(r16)(r1)
-       ld      r15,STK_REG(r15)(r1)
-       ld      r14,STK_REG(r14)(r1)
+       ld      r22,STK_REG(R22)(r1)
+       ld      r21,STK_REG(R21)(r1)
+       ld      r20,STK_REG(R20)(r1)
+       ld      r19,STK_REG(R19)(r1)
+       ld      r18,STK_REG(R18)(r1)
+       ld      r17,STK_REG(R17)(r1)
+       ld      r16,STK_REG(R16)(r1)
+       ld      r15,STK_REG(R15)(r1)
+       ld      r14,STK_REG(R14)(r1)
 .Lexit:
        addi    r1,r1,STACKFRAMESIZE
 .Ldo_err1:
@@ -137,15 +134,15 @@ err1;     stw     r0,0(r3)
 
        mflr    r0
        stdu    r1,-STACKFRAMESIZE(r1)
-       std     r14,STK_REG(r14)(r1)
-       std     r15,STK_REG(r15)(r1)
-       std     r16,STK_REG(r16)(r1)
-       std     r17,STK_REG(r17)(r1)
-       std     r18,STK_REG(r18)(r1)
-       std     r19,STK_REG(r19)(r1)
-       std     r20,STK_REG(r20)(r1)
-       std     r21,STK_REG(r21)(r1)
-       std     r22,STK_REG(r22)(r1)
+       std     r14,STK_REG(R14)(r1)
+       std     r15,STK_REG(R15)(r1)
+       std     r16,STK_REG(R16)(r1)
+       std     r17,STK_REG(R17)(r1)
+       std     r18,STK_REG(R18)(r1)
+       std     r19,STK_REG(R19)(r1)
+       std     r20,STK_REG(R20)(r1)
+       std     r21,STK_REG(R21)(r1)
+       std     r22,STK_REG(R22)(r1)
        std     r0,STACKFRAMESIZE+16(r1)
 
        srdi    r6,r5,7
@@ -192,15 +189,15 @@ err2;     std     r21,120(r3)
 
        clrldi  r5,r5,(64-7)
 
-       ld      r14,STK_REG(r14)(r1)
-       ld      r15,STK_REG(r15)(r1)
-       ld      r16,STK_REG(r16)(r1)
-       ld      r17,STK_REG(r17)(r1)
-       ld      r18,STK_REG(r18)(r1)
-       ld      r19,STK_REG(r19)(r1)
-       ld      r20,STK_REG(r20)(r1)
-       ld      r21,STK_REG(r21)(r1)
-       ld      r22,STK_REG(r22)(r1)
+       ld      r14,STK_REG(R14)(r1)
+       ld      r15,STK_REG(R15)(r1)
+       ld      r16,STK_REG(R16)(r1)
+       ld      r17,STK_REG(R17)(r1)
+       ld      r18,STK_REG(R18)(r1)
+       ld      r19,STK_REG(R19)(r1)
+       ld      r20,STK_REG(R20)(r1)
+       ld      r21,STK_REG(R21)(r1)
+       ld      r22,STK_REG(R22)(r1)
        addi    r1,r1,STACKFRAMESIZE
 
        /* Up to 127B to go */
@@ -290,7 +287,7 @@ err1;       stb     r0,0(r3)
        mflr    r0
        std     r0,16(r1)
        stdu    r1,-STACKFRAMESIZE(r1)
-       bl      .enter_vmx_copy
+       bl      .enter_vmx_usercopy
        cmpwi   r3,0
        ld      r0,STACKFRAMESIZE+16(r1)
        ld      r3,STACKFRAMESIZE+48(r1)
@@ -298,6 +295,68 @@ err1;      stb     r0,0(r3)
        ld      r5,STACKFRAMESIZE+64(r1)
        mtlr    r0
 
+       /*
+        * We prefetch both the source and destination using enhanced touch
+        * instructions. We use a stream ID of 0 for the load side and
+        * 1 for the store side.
+        */
+       clrrdi  r6,r4,7
+       clrrdi  r9,r3,7
+       ori     r9,r9,1         /* stream=1 */
+
+       srdi    r7,r5,7         /* length in cachelines, capped at 0x3FF */
+       cmpldi  r7,0x3FF
+       ble     1f
+       li      r7,0x3FF
+1:     lis     r0,0x0E00       /* depth=7 */
+       sldi    r7,r7,7
+       or      r7,r7,r0
+       ori     r10,r7,1        /* stream=1 */
+
+       lis     r8,0x8000       /* GO=1 */
+       clrldi  r8,r8,32
+
+.machine push
+.machine "power4"
+       dcbt    r0,r6,0b01000
+       dcbt    r0,r7,0b01010
+       dcbtst  r0,r9,0b01000
+       dcbtst  r0,r10,0b01010
+       eieio
+       dcbt    r0,r8,0b01010   /* GO */
+.machine pop
+
+       /*
+        * We prefetch both the source and destination using enhanced touch
+        * instructions. We use a stream ID of 0 for the load side and
+        * 1 for the store side.
+        */
+       clrrdi  r6,r4,7
+       clrrdi  r9,r3,7
+       ori     r9,r9,1         /* stream=1 */
+
+       srdi    r7,r5,7         /* length in cachelines, capped at 0x3FF */
+       cmpldi  cr1,r7,0x3FF
+       ble     cr1,1f
+       li      r7,0x3FF
+1:     lis     r0,0x0E00       /* depth=7 */
+       sldi    r7,r7,7
+       or      r7,r7,r0
+       ori     r10,r7,1        /* stream=1 */
+
+       lis     r8,0x8000       /* GO=1 */
+       clrldi  r8,r8,32
+
+.machine push
+.machine "power4"
+       dcbt    r0,r6,0b01000
+       dcbt    r0,r7,0b01010
+       dcbtst  r0,r9,0b01000
+       dcbtst  r0,r10,0b01010
+       eieio
+       dcbt    r0,r8,0b01010   /* GO */
+.machine pop
+
        beq     .Lunwind_stack_nonvmx_copy
 
        /*
@@ -378,9 +437,9 @@ err3;       stvx    vr0,r3,r11
 7:     sub     r5,r5,r6
        srdi    r6,r5,7
 
-       std     r14,STK_REG(r14)(r1)
-       std     r15,STK_REG(r15)(r1)
-       std     r16,STK_REG(r16)(r1)
+       std     r14,STK_REG(R14)(r1)
+       std     r15,STK_REG(R15)(r1)
+       std     r16,STK_REG(R16)(r1)
 
        li      r12,64
        li      r14,80
@@ -415,9 +474,9 @@ err4;       stvx    vr0,r3,r16
        addi    r3,r3,128
        bdnz    8b
 
-       ld      r14,STK_REG(r14)(r1)
-       ld      r15,STK_REG(r15)(r1)
-       ld      r16,STK_REG(r16)(r1)
+       ld      r14,STK_REG(R14)(r1)
+       ld      r15,STK_REG(R15)(r1)
+       ld      r16,STK_REG(R16)(r1)
 
        /* Up to 127B to go */
        clrldi  r5,r5,(64-7)
@@ -476,7 +535,7 @@ err3;       lbz     r0,0(r4)
 err3;  stb     r0,0(r3)
 
 15:    addi    r1,r1,STACKFRAMESIZE
-       b       .exit_vmx_copy          /* tail call optimise */
+       b       .exit_vmx_usercopy      /* tail call optimise */
 
 .Lvmx_unaligned_copy:
        /* Get the destination 16B aligned */
@@ -563,9 +622,9 @@ err3;       stvx    vr11,r3,r11
 7:     sub     r5,r5,r6
        srdi    r6,r5,7
 
-       std     r14,STK_REG(r14)(r1)
-       std     r15,STK_REG(r15)(r1)
-       std     r16,STK_REG(r16)(r1)
+       std     r14,STK_REG(R14)(r1)
+       std     r15,STK_REG(R15)(r1)
+       std     r16,STK_REG(R16)(r1)
 
        li      r12,64
        li      r14,80
@@ -608,9 +667,9 @@ err4;       stvx    vr15,r3,r16
        addi    r3,r3,128
        bdnz    8b
 
-       ld      r14,STK_REG(r14)(r1)
-       ld      r15,STK_REG(r15)(r1)
-       ld      r16,STK_REG(r16)(r1)
+       ld      r14,STK_REG(R14)(r1)
+       ld      r15,STK_REG(R15)(r1)
+       ld      r16,STK_REG(R16)(r1)
 
        /* Up to 127B to go */
        clrldi  r5,r5,(64-7)
@@ -679,5 +738,5 @@ err3;       lbz     r0,0(r4)
 err3;  stb     r0,0(r3)
 
 15:    addi    r1,r1,STACKFRAMESIZE
-       b       .exit_vmx_copy          /* tail call optimise */
+       b       .exit_vmx_usercopy      /* tail call optimise */
 #endif /* CONFiG_ALTIVEC */
diff --git a/arch/powerpc/lib/copyuser_power7_vmx.c b/arch/powerpc/lib/copyuser_power7_vmx.c
deleted file mode 100644 (file)
index bf2654f..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.
- *
- * Copyright (C) IBM Corporation, 2011
- *
- * Authors: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
- *          Anton Blanchard <anton@au.ibm.com>
- */
-#include <linux/uaccess.h>
-#include <linux/hardirq.h>
-#include <asm/switch_to.h>
-
-int enter_vmx_copy(void)
-{
-       if (in_interrupt())
-               return 0;
-
-       /* This acts as preempt_disable() as well and will make
-        * enable_kernel_altivec(). We need to disable page faults
-        * as they can call schedule and thus make us lose the VMX
-        * context. So on page faults, we just fail which will cause
-        * a fallback to the normal non-vmx copy.
-        */
-       pagefault_disable();
-
-       enable_kernel_altivec();
-
-       return 1;
-}
-
-/*
- * This function must return 0 because we tail call optimise when calling
- * from __copy_tofrom_user_power7 which returns 0 on success.
- */
-int exit_vmx_copy(void)
-{
-       pagefault_enable();
-       return 0;
-}
index 1c893f05d224cab5ae36cff82e3eeb30cd46171c..b2c68ce139aecbc6819ff8f6493dde59c749fa7e 100644 (file)
 #include <asm/ppc_asm.h>
 
        .file   "crtsavres.S"
-       .section ".text"
 
 #ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
 
 #ifndef CONFIG_PPC64
 
+       .section ".text"
+
 /* Routines for saving integer registers, called by the compiler.  */
 /* Called with r11 pointing to the stack header word of the caller of the */
 /* function, just beyond the end of the integer save area.  */
@@ -232,6 +233,8 @@ _GLOBAL(_rest32gpr_31_x)
 
 #else /* CONFIG_PPC64 */
 
+       .section ".text.save.restore","ax",@progbits
+
 .globl _savegpr0_14
 _savegpr0_14:
        std     r14,-144(r1)
index fda27868cf8c58b2a3be8fe8f26b998de6f19eae..9b96ff2ecd4dadb0aae350e80fde94fb93afb20b 100644 (file)
@@ -28,7 +28,7 @@ BEGIN_FTR_SECTION
        nop
        nop
 FTR_SECTION_ELSE
-       PPC_POPCNTB(r3,r3)
+       PPC_POPCNTB(R3,R3)
        clrldi  r3,r3,64-8
        blr
 ALT_FTR_SECTION_END_IFCLR(CPU_FTR_POPCNTB)
@@ -42,14 +42,14 @@ BEGIN_FTR_SECTION
        nop
 FTR_SECTION_ELSE
   BEGIN_FTR_SECTION_NESTED(50)
-       PPC_POPCNTB(r3,r3)
+       PPC_POPCNTB(R3,R3)
        srdi    r4,r3,8
        add     r3,r4,r3
        clrldi  r3,r3,64-8
        blr
   FTR_SECTION_ELSE_NESTED(50)
        clrlwi  r3,r3,16
-       PPC_POPCNTW(r3,r3)
+       PPC_POPCNTW(R3,R3)
        clrldi  r3,r3,64-8
        blr
   ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_POPCNTD, 50)
@@ -66,7 +66,7 @@ BEGIN_FTR_SECTION
        nop
 FTR_SECTION_ELSE
   BEGIN_FTR_SECTION_NESTED(51)
-       PPC_POPCNTB(r3,r3)
+       PPC_POPCNTB(R3,R3)
        srdi    r4,r3,16
        add     r3,r4,r3
        srdi    r4,r3,8
@@ -74,7 +74,7 @@ FTR_SECTION_ELSE
        clrldi  r3,r3,64-8
        blr
   FTR_SECTION_ELSE_NESTED(51)
-       PPC_POPCNTW(r3,r3)
+       PPC_POPCNTW(R3,R3)
        clrldi  r3,r3,64-8
        blr
   ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_POPCNTD, 51)
@@ -93,7 +93,7 @@ BEGIN_FTR_SECTION
        nop
 FTR_SECTION_ELSE
   BEGIN_FTR_SECTION_NESTED(52)
-       PPC_POPCNTB(r3,r3)
+       PPC_POPCNTB(R3,R3)
        srdi    r4,r3,32
        add     r3,r4,r3
        srdi    r4,r3,16
@@ -103,7 +103,7 @@ FTR_SECTION_ELSE
        clrldi  r3,r3,64-8
        blr
   FTR_SECTION_ELSE_NESTED(52)
-       PPC_POPCNTD(r3,r3)
+       PPC_POPCNTD(R3,R3)
        clrldi  r3,r3,64-8
        blr
   ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_POPCNTD, 52)
index 6a85380520b61163dff57eab585bfa1c4352bffb..85aec08ab23411a98041bfee837e82a29ff2d107 100644 (file)
@@ -330,13 +330,13 @@ _GLOBAL(do_lxvd2x)
        MTMSRD(r7)
        isync
        beq     cr7,1f
-       STXVD2X(0,r1,r8)
+       STXVD2X(0,R1,R8)
 1:     li      r9,-EFAULT
-2:     LXVD2X(0,0,r4)
+2:     LXVD2X(0,R0,R4)
        li      r9,0
 3:     beq     cr7,4f
        bl      put_vsr
-       LXVD2X(0,r1,r8)
+       LXVD2X(0,R1,R8)
 4:     PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
        mtlr    r0
        MTMSRD(r6)
@@ -358,13 +358,13 @@ _GLOBAL(do_stxvd2x)
        MTMSRD(r7)
        isync
        beq     cr7,1f
-       STXVD2X(0,r1,r8)
+       STXVD2X(0,R1,R8)
        bl      get_vsr
 1:     li      r9,-EFAULT
-2:     STXVD2X(0,0,r4)
+2:     STXVD2X(0,R0,R4)
        li      r9,0
 3:     beq     cr7,4f
-       LXVD2X(0,r1,r8)
+       LXVD2X(0,R1,R8)
 4:     PPC_LL  r0,STKFRM+PPC_LR_STKOFF(r1)
        mtlr    r0
        MTMSRD(r6)
index 82fea3963e15d36f8c30577fce53e7bc30196ac3..d2bbbc8d7dc0b045aab751d79264a2f4f959fe61 100644 (file)
 
        .align  7
 _GLOBAL(memcpy)
+BEGIN_FTR_SECTION
        std     r3,48(r1)       /* save destination pointer for return value */
+FTR_SECTION_ELSE
+       b       memcpy_power7
+ALT_FTR_SECTION_END_IFCLR(CPU_FTR_VMX_COPY)
        PPC_MTOCRF(0x01,r5)
        cmpldi  cr1,r5,16
        neg     r6,r3           # LS 3 bits = # bytes to 8-byte dest bdry
diff --git a/arch/powerpc/lib/memcpy_power7.S b/arch/powerpc/lib/memcpy_power7.S
new file mode 100644 (file)
index 0000000..0efdc51
--- /dev/null
@@ -0,0 +1,647 @@
+/*
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2012
+ *
+ * Author: Anton Blanchard <anton@au.ibm.com>
+ */
+#include <asm/ppc_asm.h>
+
+_GLOBAL(memcpy_power7)
+#ifdef CONFIG_ALTIVEC
+       cmpldi  r5,16
+       cmpldi  cr1,r5,4096
+
+       std     r3,48(r1)
+
+       blt     .Lshort_copy
+       bgt     cr1,.Lvmx_copy
+#else
+       cmpldi  r5,16
+
+       std     r3,48(r1)
+
+       blt     .Lshort_copy
+#endif
+
+.Lnonvmx_copy:
+       /* Get the source 8B aligned */
+       neg     r6,r4
+       mtocrf  0x01,r6
+       clrldi  r6,r6,(64-3)
+
+       bf      cr7*4+3,1f
+       lbz     r0,0(r4)
+       addi    r4,r4,1
+       stb     r0,0(r3)
+       addi    r3,r3,1
+
+1:     bf      cr7*4+2,2f
+       lhz     r0,0(r4)
+       addi    r4,r4,2
+       sth     r0,0(r3)
+       addi    r3,r3,2
+
+2:     bf      cr7*4+1,3f
+       lwz     r0,0(r4)
+       addi    r4,r4,4
+       stw     r0,0(r3)
+       addi    r3,r3,4
+
+3:     sub     r5,r5,r6
+       cmpldi  r5,128
+       blt     5f
+
+       mflr    r0
+       stdu    r1,-STACKFRAMESIZE(r1)
+       std     r14,STK_REG(R14)(r1)
+       std     r15,STK_REG(R15)(r1)
+       std     r16,STK_REG(R16)(r1)
+       std     r17,STK_REG(R17)(r1)
+       std     r18,STK_REG(R18)(r1)
+       std     r19,STK_REG(R19)(r1)
+       std     r20,STK_REG(R20)(r1)
+       std     r21,STK_REG(R21)(r1)
+       std     r22,STK_REG(R22)(r1)
+       std     r0,STACKFRAMESIZE+16(r1)
+
+       srdi    r6,r5,7
+       mtctr   r6
+
+       /* Now do cacheline (128B) sized loads and stores. */
+       .align  5
+4:
+       ld      r0,0(r4)
+       ld      r6,8(r4)
+       ld      r7,16(r4)
+       ld      r8,24(r4)
+       ld      r9,32(r4)
+       ld      r10,40(r4)
+       ld      r11,48(r4)
+       ld      r12,56(r4)
+       ld      r14,64(r4)
+       ld      r15,72(r4)
+       ld      r16,80(r4)
+       ld      r17,88(r4)
+       ld      r18,96(r4)
+       ld      r19,104(r4)
+       ld      r20,112(r4)
+       ld      r21,120(r4)
+       addi    r4,r4,128
+       std     r0,0(r3)
+       std     r6,8(r3)
+       std     r7,16(r3)
+       std     r8,24(r3)
+       std     r9,32(r3)
+       std     r10,40(r3)
+       std     r11,48(r3)
+       std     r12,56(r3)
+       std     r14,64(r3)
+       std     r15,72(r3)
+       std     r16,80(r3)
+       std     r17,88(r3)
+       std     r18,96(r3)
+       std     r19,104(r3)
+       std     r20,112(r3)
+       std     r21,120(r3)
+       addi    r3,r3,128
+       bdnz    4b
+
+       clrldi  r5,r5,(64-7)
+
+       ld      r14,STK_REG(R14)(r1)
+       ld      r15,STK_REG(R15)(r1)
+       ld      r16,STK_REG(R16)(r1)
+       ld      r17,STK_REG(R17)(r1)
+       ld      r18,STK_REG(R18)(r1)
+       ld      r19,STK_REG(R19)(r1)
+       ld      r20,STK_REG(R20)(r1)
+       ld      r21,STK_REG(R21)(r1)
+       ld      r22,STK_REG(R22)(r1)
+       addi    r1,r1,STACKFRAMESIZE
+
+       /* Up to 127B to go */
+5:     srdi    r6,r5,4
+       mtocrf  0x01,r6
+
+6:     bf      cr7*4+1,7f
+       ld      r0,0(r4)
+       ld      r6,8(r4)
+       ld      r7,16(r4)
+       ld      r8,24(r4)
+       ld      r9,32(r4)
+       ld      r10,40(r4)
+       ld      r11,48(r4)
+       ld      r12,56(r4)
+       addi    r4,r4,64
+       std     r0,0(r3)
+       std     r6,8(r3)
+       std     r7,16(r3)
+       std     r8,24(r3)
+       std     r9,32(r3)
+       std     r10,40(r3)
+       std     r11,48(r3)
+       std     r12,56(r3)
+       addi    r3,r3,64
+
+       /* Up to 63B to go */
+7:     bf      cr7*4+2,8f
+       ld      r0,0(r4)
+       ld      r6,8(r4)
+       ld      r7,16(r4)
+       ld      r8,24(r4)
+       addi    r4,r4,32
+       std     r0,0(r3)
+       std     r6,8(r3)
+       std     r7,16(r3)
+       std     r8,24(r3)
+       addi    r3,r3,32
+
+       /* Up to 31B to go */
+8:     bf      cr7*4+3,9f
+       ld      r0,0(r4)
+       ld      r6,8(r4)
+       addi    r4,r4,16
+       std     r0,0(r3)
+       std     r6,8(r3)
+       addi    r3,r3,16
+
+9:     clrldi  r5,r5,(64-4)
+
+       /* Up to 15B to go */
+.Lshort_copy:
+       mtocrf  0x01,r5
+       bf      cr7*4+0,12f
+       lwz     r0,0(r4)        /* Less chance of a reject with word ops */
+       lwz     r6,4(r4)
+       addi    r4,r4,8
+       stw     r0,0(r3)
+       stw     r6,4(r3)
+       addi    r3,r3,8
+
+12:    bf      cr7*4+1,13f
+       lwz     r0,0(r4)
+       addi    r4,r4,4
+       stw     r0,0(r3)
+       addi    r3,r3,4
+
+13:    bf      cr7*4+2,14f
+       lhz     r0,0(r4)
+       addi    r4,r4,2
+       sth     r0,0(r3)
+       addi    r3,r3,2
+
+14:    bf      cr7*4+3,15f
+       lbz     r0,0(r4)
+       stb     r0,0(r3)
+
+15:    ld      r3,48(r1)
+       blr
+
+.Lunwind_stack_nonvmx_copy:
+       addi    r1,r1,STACKFRAMESIZE
+       b       .Lnonvmx_copy
+
+#ifdef CONFIG_ALTIVEC
+.Lvmx_copy:
+       mflr    r0
+       std     r4,56(r1)
+       std     r5,64(r1)
+       std     r0,16(r1)
+       stdu    r1,-STACKFRAMESIZE(r1)
+       bl      .enter_vmx_copy
+       cmpwi   r3,0
+       ld      r0,STACKFRAMESIZE+16(r1)
+       ld      r3,STACKFRAMESIZE+48(r1)
+       ld      r4,STACKFRAMESIZE+56(r1)
+       ld      r5,STACKFRAMESIZE+64(r1)
+       mtlr    r0
+
+       /*
+        * We prefetch both the source and destination using enhanced touch
+        * instructions. We use a stream ID of 0 for the load side and
+        * 1 for the store side.
+        */
+       clrrdi  r6,r4,7
+       clrrdi  r9,r3,7
+       ori     r9,r9,1         /* stream=1 */
+
+       srdi    r7,r5,7         /* length in cachelines, capped at 0x3FF */
+       cmpldi  cr1,r7,0x3FF
+       ble     cr1,1f
+       li      r7,0x3FF
+1:     lis     r0,0x0E00       /* depth=7 */
+       sldi    r7,r7,7
+       or      r7,r7,r0
+       ori     r10,r7,1        /* stream=1 */
+
+       lis     r8,0x8000       /* GO=1 */
+       clrldi  r8,r8,32
+
+.machine push
+.machine "power4"
+       dcbt    r0,r6,0b01000
+       dcbt    r0,r7,0b01010
+       dcbtst  r0,r9,0b01000
+       dcbtst  r0,r10,0b01010
+       eieio
+       dcbt    r0,r8,0b01010   /* GO */
+.machine pop
+
+       beq     .Lunwind_stack_nonvmx_copy
+
+       /*
+        * If source and destination are not relatively aligned we use a
+        * slower permute loop.
+        */
+       xor     r6,r4,r3
+       rldicl. r6,r6,0,(64-4)
+       bne     .Lvmx_unaligned_copy
+
+       /* Get the destination 16B aligned */
+       neg     r6,r3
+       mtocrf  0x01,r6
+       clrldi  r6,r6,(64-4)
+
+       bf      cr7*4+3,1f
+       lbz     r0,0(r4)
+       addi    r4,r4,1
+       stb     r0,0(r3)
+       addi    r3,r3,1
+
+1:     bf      cr7*4+2,2f
+       lhz     r0,0(r4)
+       addi    r4,r4,2
+       sth     r0,0(r3)
+       addi    r3,r3,2
+
+2:     bf      cr7*4+1,3f
+       lwz     r0,0(r4)
+       addi    r4,r4,4
+       stw     r0,0(r3)
+       addi    r3,r3,4
+
+3:     bf      cr7*4+0,4f
+       ld      r0,0(r4)
+       addi    r4,r4,8
+       std     r0,0(r3)
+       addi    r3,r3,8
+
+4:     sub     r5,r5,r6
+
+       /* Get the desination 128B aligned */
+       neg     r6,r3
+       srdi    r7,r6,4
+       mtocrf  0x01,r7
+       clrldi  r6,r6,(64-7)
+
+       li      r9,16
+       li      r10,32
+       li      r11,48
+
+       bf      cr7*4+3,5f
+       lvx     vr1,r0,r4
+       addi    r4,r4,16
+       stvx    vr1,r0,r3
+       addi    r3,r3,16
+
+5:     bf      cr7*4+2,6f
+       lvx     vr1,r0,r4
+       lvx     vr0,r4,r9
+       addi    r4,r4,32
+       stvx    vr1,r0,r3
+       stvx    vr0,r3,r9
+       addi    r3,r3,32
+
+6:     bf      cr7*4+1,7f
+       lvx     vr3,r0,r4
+       lvx     vr2,r4,r9
+       lvx     vr1,r4,r10
+       lvx     vr0,r4,r11
+       addi    r4,r4,64
+       stvx    vr3,r0,r3
+       stvx    vr2,r3,r9
+       stvx    vr1,r3,r10
+       stvx    vr0,r3,r11
+       addi    r3,r3,64
+
+7:     sub     r5,r5,r6
+       srdi    r6,r5,7
+
+       std     r14,STK_REG(R14)(r1)
+       std     r15,STK_REG(R15)(r1)
+       std     r16,STK_REG(R16)(r1)
+
+       li      r12,64
+       li      r14,80
+       li      r15,96
+       li      r16,112
+
+       mtctr   r6
+
+       /*
+        * Now do cacheline sized loads and stores. By this stage the
+        * cacheline stores are also cacheline aligned.
+        */
+       .align  5
+8:
+       lvx     vr7,r0,r4
+       lvx     vr6,r4,r9
+       lvx     vr5,r4,r10
+       lvx     vr4,r4,r11
+       lvx     vr3,r4,r12
+       lvx     vr2,r4,r14
+       lvx     vr1,r4,r15
+       lvx     vr0,r4,r16
+       addi    r4,r4,128
+       stvx    vr7,r0,r3
+       stvx    vr6,r3,r9
+       stvx    vr5,r3,r10
+       stvx    vr4,r3,r11
+       stvx    vr3,r3,r12
+       stvx    vr2,r3,r14
+       stvx    vr1,r3,r15
+       stvx    vr0,r3,r16
+       addi    r3,r3,128
+       bdnz    8b
+
+       ld      r14,STK_REG(R14)(r1)
+       ld      r15,STK_REG(R15)(r1)
+       ld      r16,STK_REG(R16)(r1)
+
+       /* Up to 127B to go */
+       clrldi  r5,r5,(64-7)
+       srdi    r6,r5,4
+       mtocrf  0x01,r6
+
+       bf      cr7*4+1,9f
+       lvx     vr3,r0,r4
+       lvx     vr2,r4,r9
+       lvx     vr1,r4,r10
+       lvx     vr0,r4,r11
+       addi    r4,r4,64
+       stvx    vr3,r0,r3
+       stvx    vr2,r3,r9
+       stvx    vr1,r3,r10
+       stvx    vr0,r3,r11
+       addi    r3,r3,64
+
+9:     bf      cr7*4+2,10f
+       lvx     vr1,r0,r4
+       lvx     vr0,r4,r9
+       addi    r4,r4,32
+       stvx    vr1,r0,r3
+       stvx    vr0,r3,r9
+       addi    r3,r3,32
+
+10:    bf      cr7*4+3,11f
+       lvx     vr1,r0,r4
+       addi    r4,r4,16
+       stvx    vr1,r0,r3
+       addi    r3,r3,16
+
+       /* Up to 15B to go */
+11:    clrldi  r5,r5,(64-4)
+       mtocrf  0x01,r5
+       bf      cr7*4+0,12f
+       ld      r0,0(r4)
+       addi    r4,r4,8
+       std     r0,0(r3)
+       addi    r3,r3,8
+
+12:    bf      cr7*4+1,13f
+       lwz     r0,0(r4)
+       addi    r4,r4,4
+       stw     r0,0(r3)
+       addi    r3,r3,4
+
+13:    bf      cr7*4+2,14f
+       lhz     r0,0(r4)
+       addi    r4,r4,2
+       sth     r0,0(r3)
+       addi    r3,r3,2
+
+14:    bf      cr7*4+3,15f
+       lbz     r0,0(r4)
+       stb     r0,0(r3)
+
+15:    addi    r1,r1,STACKFRAMESIZE
+       ld      r3,48(r1)
+       b       .exit_vmx_copy          /* tail call optimise */
+
+.Lvmx_unaligned_copy:
+       /* Get the destination 16B aligned */
+       neg     r6,r3
+       mtocrf  0x01,r6
+       clrldi  r6,r6,(64-4)
+
+       bf      cr7*4+3,1f
+       lbz     r0,0(r4)
+       addi    r4,r4,1
+       stb     r0,0(r3)
+       addi    r3,r3,1
+
+1:     bf      cr7*4+2,2f
+       lhz     r0,0(r4)
+       addi    r4,r4,2
+       sth     r0,0(r3)
+       addi    r3,r3,2
+
+2:     bf      cr7*4+1,3f
+       lwz     r0,0(r4)
+       addi    r4,r4,4
+       stw     r0,0(r3)
+       addi    r3,r3,4
+
+3:     bf      cr7*4+0,4f
+       lwz     r0,0(r4)        /* Less chance of a reject with word ops */
+       lwz     r7,4(r4)
+       addi    r4,r4,8
+       stw     r0,0(r3)
+       stw     r7,4(r3)
+       addi    r3,r3,8
+
+4:     sub     r5,r5,r6
+
+       /* Get the desination 128B aligned */
+       neg     r6,r3
+       srdi    r7,r6,4
+       mtocrf  0x01,r7
+       clrldi  r6,r6,(64-7)
+
+       li      r9,16
+       li      r10,32
+       li      r11,48
+
+       lvsl    vr16,0,r4       /* Setup permute control vector */
+       lvx     vr0,0,r4
+       addi    r4,r4,16
+
+       bf      cr7*4+3,5f
+       lvx     vr1,r0,r4
+       vperm   vr8,vr0,vr1,vr16
+       addi    r4,r4,16
+       stvx    vr8,r0,r3
+       addi    r3,r3,16
+       vor     vr0,vr1,vr1
+
+5:     bf      cr7*4+2,6f
+       lvx     vr1,r0,r4
+       vperm   vr8,vr0,vr1,vr16
+       lvx     vr0,r4,r9
+       vperm   vr9,vr1,vr0,vr16
+       addi    r4,r4,32
+       stvx    vr8,r0,r3
+       stvx    vr9,r3,r9
+       addi    r3,r3,32
+
+6:     bf      cr7*4+1,7f
+       lvx     vr3,r0,r4
+       vperm   vr8,vr0,vr3,vr16
+       lvx     vr2,r4,r9
+       vperm   vr9,vr3,vr2,vr16
+       lvx     vr1,r4,r10
+       vperm   vr10,vr2,vr1,vr16
+       lvx     vr0,r4,r11
+       vperm   vr11,vr1,vr0,vr16
+       addi    r4,r4,64
+       stvx    vr8,r0,r3
+       stvx    vr9,r3,r9
+       stvx    vr10,r3,r10
+       stvx    vr11,r3,r11
+       addi    r3,r3,64
+
+7:     sub     r5,r5,r6
+       srdi    r6,r5,7
+
+       std     r14,STK_REG(R14)(r1)
+       std     r15,STK_REG(R15)(r1)
+       std     r16,STK_REG(R16)(r1)
+
+       li      r12,64
+       li      r14,80
+       li      r15,96
+       li      r16,112
+
+       mtctr   r6
+
+       /*
+        * Now do cacheline sized loads and stores. By this stage the
+        * cacheline stores are also cacheline aligned.
+        */
+       .align  5
+8:
+       lvx     vr7,r0,r4
+       vperm   vr8,vr0,vr7,vr16
+       lvx     vr6,r4,r9
+       vperm   vr9,vr7,vr6,vr16
+       lvx     vr5,r4,r10
+       vperm   vr10,vr6,vr5,vr16
+       lvx     vr4,r4,r11
+       vperm   vr11,vr5,vr4,vr16
+       lvx     vr3,r4,r12
+       vperm   vr12,vr4,vr3,vr16
+       lvx     vr2,r4,r14
+       vperm   vr13,vr3,vr2,vr16
+       lvx     vr1,r4,r15
+       vperm   vr14,vr2,vr1,vr16
+       lvx     vr0,r4,r16
+       vperm   vr15,vr1,vr0,vr16
+       addi    r4,r4,128
+       stvx    vr8,r0,r3
+       stvx    vr9,r3,r9
+       stvx    vr10,r3,r10
+       stvx    vr11,r3,r11
+       stvx    vr12,r3,r12
+       stvx    vr13,r3,r14
+       stvx    vr14,r3,r15
+       stvx    vr15,r3,r16
+       addi    r3,r3,128
+       bdnz    8b
+
+       ld      r14,STK_REG(R14)(r1)
+       ld      r15,STK_REG(R15)(r1)
+       ld      r16,STK_REG(R16)(r1)
+
+       /* Up to 127B to go */
+       clrldi  r5,r5,(64-7)
+       srdi    r6,r5,4
+       mtocrf  0x01,r6
+
+       bf      cr7*4+1,9f
+       lvx     vr3,r0,r4
+       vperm   vr8,vr0,vr3,vr16
+       lvx     vr2,r4,r9
+       vperm   vr9,vr3,vr2,vr16
+       lvx     vr1,r4,r10
+       vperm   vr10,vr2,vr1,vr16
+       lvx     vr0,r4,r11
+       vperm   vr11,vr1,vr0,vr16
+       addi    r4,r4,64
+       stvx    vr8,r0,r3
+       stvx    vr9,r3,r9
+       stvx    vr10,r3,r10
+       stvx    vr11,r3,r11
+       addi    r3,r3,64
+
+9:     bf      cr7*4+2,10f
+       lvx     vr1,r0,r4
+       vperm   vr8,vr0,vr1,vr16
+       lvx     vr0,r4,r9
+       vperm   vr9,vr1,vr0,vr16
+       addi    r4,r4,32
+       stvx    vr8,r0,r3
+       stvx    vr9,r3,r9
+       addi    r3,r3,32
+
+10:    bf      cr7*4+3,11f
+       lvx     vr1,r0,r4
+       vperm   vr8,vr0,vr1,vr16
+       addi    r4,r4,16
+       stvx    vr8,r0,r3
+       addi    r3,r3,16
+
+       /* Up to 15B to go */
+11:    clrldi  r5,r5,(64-4)
+       addi    r4,r4,-16       /* Unwind the +16 load offset */
+       mtocrf  0x01,r5
+       bf      cr7*4+0,12f
+       lwz     r0,0(r4)        /* Less chance of a reject with word ops */
+       lwz     r6,4(r4)
+       addi    r4,r4,8
+       stw     r0,0(r3)
+       stw     r6,4(r3)
+       addi    r3,r3,8
+
+12:    bf      cr7*4+1,13f
+       lwz     r0,0(r4)
+       addi    r4,r4,4
+       stw     r0,0(r3)
+       addi    r3,r3,4
+
+13:    bf      cr7*4+2,14f
+       lhz     r0,0(r4)
+       addi    r4,r4,2
+       sth     r0,0(r3)
+       addi    r3,r3,2
+
+14:    bf      cr7*4+3,15f
+       lbz     r0,0(r4)
+       stb     r0,0(r3)
+
+15:    addi    r1,r1,STACKFRAMESIZE
+       ld      r3,48(r1)
+       b       .exit_vmx_copy          /* tail call optimise */
+#endif /* CONFiG_ALTIVEC */
index 093d6316435cc0733ecfa45c6e7e9f8bec1b3b95..1b5a0a09d609664301c9de54c42e8cde42af650f 100644 (file)
@@ -119,6 +119,7 @@ _GLOBAL(memchr)
 2:     li      r3,0
        blr
 
+#ifdef CONFIG_PPC32
 _GLOBAL(__clear_user)
        addi    r6,r3,-4
        li      r3,0
@@ -160,3 +161,4 @@ _GLOBAL(__clear_user)
        PPC_LONG        1b,91b
        PPC_LONG        8b,92b
        .text
+#endif
diff --git a/arch/powerpc/lib/string_64.S b/arch/powerpc/lib/string_64.S
new file mode 100644 (file)
index 0000000..3b1e480
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2012
+ *
+ * Author: Anton Blanchard <anton@au.ibm.com>
+ */
+
+#include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
+
+       .section        ".toc","aw"
+PPC64_CACHES:
+       .tc             ppc64_caches[TC],ppc64_caches
+       .section        ".text"
+
+/**
+ * __clear_user: - Zero a block of memory in user space, with less checking.
+ * @to:   Destination address, in user space.
+ * @n:    Number of bytes to zero.
+ *
+ * Zero a block of memory in user space.  Caller must check
+ * the specified block with access_ok() before calling this function.
+ *
+ * Returns number of bytes that could not be cleared.
+ * On success, this will be zero.
+ */
+
+       .macro err1
+100:
+       .section __ex_table,"a"
+       .align 3
+       .llong 100b,.Ldo_err1
+       .previous
+       .endm
+
+       .macro err2
+200:
+       .section __ex_table,"a"
+       .align 3
+       .llong 200b,.Ldo_err2
+       .previous
+       .endm
+
+       .macro err3
+300:
+       .section __ex_table,"a"
+       .align 3
+       .llong 300b,.Ldo_err3
+       .previous
+       .endm
+
+.Ldo_err1:
+       mr      r3,r8
+
+.Ldo_err2:
+       mtctr   r4
+1:
+err3;  stb     r0,0(r3)
+       addi    r3,r3,1
+       addi    r4,r4,-1
+       bdnz    1b
+
+.Ldo_err3:
+       mr      r3,r4
+       blr
+
+_GLOBAL(__clear_user)
+       cmpdi   r4,32
+       neg     r6,r3
+       li      r0,0
+       blt     .Lshort_clear
+       mr      r8,r3
+       mtocrf  0x01,r6
+       clrldi  r6,r6,(64-3)
+
+       /* Get the destination 8 byte aligned */
+       bf      cr7*4+3,1f
+err1;  stb     r0,0(r3)
+       addi    r3,r3,1
+
+1:     bf      cr7*4+2,2f
+err1;  sth     r0,0(r3)
+       addi    r3,r3,2
+
+2:     bf      cr7*4+1,3f
+err1;  stw     r0,0(r3)
+       addi    r3,r3,4
+
+3:     sub     r4,r4,r6
+
+       cmpdi   r4,32
+       cmpdi   cr1,r4,512
+       blt     .Lshort_clear
+       bgt     cr1,.Llong_clear
+
+.Lmedium_clear:
+       srdi    r6,r4,5
+       mtctr   r6
+
+       /* Do 32 byte chunks */
+4:
+err2;  std     r0,0(r3)
+err2;  std     r0,8(r3)
+err2;  std     r0,16(r3)
+err2;  std     r0,24(r3)
+       addi    r3,r3,32
+       addi    r4,r4,-32
+       bdnz    4b
+
+.Lshort_clear:
+       /* up to 31 bytes to go */
+       cmpdi   r4,16
+       blt     6f
+err2;  std     r0,0(r3)
+err2;  std     r0,8(r3)
+       addi    r3,r3,16
+       addi    r4,r4,-16
+
+       /* Up to 15 bytes to go */
+6:     mr      r8,r3
+       clrldi  r4,r4,(64-4)
+       mtocrf  0x01,r4
+       bf      cr7*4+0,7f
+err1;  std     r0,0(r3)
+       addi    r3,r3,8
+
+7:     bf      cr7*4+1,8f
+err1;  stw     r0,0(r3)
+       addi    r3,r3,4
+
+8:     bf      cr7*4+2,9f
+err1;  sth     r0,0(r3)
+       addi    r3,r3,2
+
+9:     bf      cr7*4+3,10f
+err1;  stb     r0,0(r3)
+
+10:    li      r3,0
+       blr
+
+.Llong_clear:
+       ld      r5,PPC64_CACHES@toc(r2)
+
+       bf      cr7*4+0,11f
+err2;  std     r0,0(r3)
+       addi    r3,r3,8
+       addi    r4,r4,-8
+
+       /* Destination is 16 byte aligned, need to get it cacheline aligned */
+11:    lwz     r7,DCACHEL1LOGLINESIZE(r5)
+       lwz     r9,DCACHEL1LINESIZE(r5)
+
+       /*
+        * With worst case alignment the long clear loop takes a minimum
+        * of 1 byte less than 2 cachelines.
+        */
+       sldi    r10,r9,2
+       cmpd    r4,r10
+       blt     .Lmedium_clear
+
+       neg     r6,r3
+       addi    r10,r9,-1
+       and.    r5,r6,r10
+       beq     13f
+
+       srdi    r6,r5,4
+       mtctr   r6
+       mr      r8,r3
+12:
+err1;  std     r0,0(r3)
+err1;  std     r0,8(r3)
+       addi    r3,r3,16
+       bdnz    12b
+
+       sub     r4,r4,r5
+
+13:    srd     r6,r4,r7
+       mtctr   r6
+       mr      r8,r3
+14:
+err1;  dcbz    r0,r3
+       add     r3,r3,r9
+       bdnz    14b
+
+       and     r4,r4,r10
+
+       cmpdi   r4,32
+       blt     .Lshort_clear
+       b       .Lmedium_clear
diff --git a/arch/powerpc/lib/vmx-helper.c b/arch/powerpc/lib/vmx-helper.c
new file mode 100644 (file)
index 0000000..3cf529c
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ *
+ * Copyright (C) IBM Corporation, 2011
+ *
+ * Authors: Sukadev Bhattiprolu <sukadev@linux.vnet.ibm.com>
+ *          Anton Blanchard <anton@au.ibm.com>
+ */
+#include <linux/uaccess.h>
+#include <linux/hardirq.h>
+#include <asm/switch_to.h>
+
+int enter_vmx_usercopy(void)
+{
+       if (in_interrupt())
+               return 0;
+
+       /* This acts as preempt_disable() as well and will make
+        * enable_kernel_altivec(). We need to disable page faults
+        * as they can call schedule and thus make us lose the VMX
+        * context. So on page faults, we just fail which will cause
+        * a fallback to the normal non-vmx copy.
+        */
+       pagefault_disable();
+
+       enable_kernel_altivec();
+
+       return 1;
+}
+
+/*
+ * This function must return 0 because we tail call optimise when calling
+ * from __copy_tofrom_user_power7 which returns 0 on success.
+ */
+int exit_vmx_usercopy(void)
+{
+       pagefault_enable();
+       return 0;
+}
+
+int enter_vmx_copy(void)
+{
+       if (in_interrupt())
+               return 0;
+
+       preempt_disable();
+
+       enable_kernel_altivec();
+
+       return 1;
+}
+
+/*
+ * All calls to this function will be optimised into tail calls. We are
+ * passed a pointer to the destination which we return as required by a
+ * memcpy implementation.
+ */
+void *exit_vmx_copy(void *dest)
+{
+       preempt_enable();
+       return dest;
+}
index b13d58932bf6dd51118d23b77f97935b92fab5e9..115347f74ce5867199b2b329cc94cbddd0e0d5b4 100644 (file)
@@ -184,7 +184,7 @@ _GLOBAL(add_hash_page)
        add     r3,r3,r0                /* note create_hpte trims to 24 bits */
 
 #ifdef CONFIG_SMP
-       rlwinm  r8,r1,0,0,(31-THREAD_SHIFT) /* use cpu number to make tag */
+       CURRENT_THREAD_INFO(r8, r1)     /* use cpu number to make tag */
        lwz     r8,TI_CPU(r8)           /* to go in mmu_hash_lock */
        oris    r8,r8,12
 #endif /* CONFIG_SMP */
@@ -545,7 +545,7 @@ _GLOBAL(flush_hash_pages)
 #ifdef CONFIG_SMP
        addis   r9,r7,mmu_hash_lock@ha
        addi    r9,r9,mmu_hash_lock@l
-       rlwinm  r8,r1,0,0,(31-THREAD_SHIFT)
+       CURRENT_THREAD_INFO(r8, r1)
        add     r8,r8,r7
        lwz     r8,TI_CPU(r8)
        oris    r8,r8,9
@@ -639,7 +639,7 @@ _GLOBAL(flush_hash_patch_B)
  */
 _GLOBAL(_tlbie)
 #ifdef CONFIG_SMP
-       rlwinm  r8,r1,0,0,(31-THREAD_SHIFT)
+       CURRENT_THREAD_INFO(r8, r1)
        lwz     r8,TI_CPU(r8)
        oris    r8,r8,11
        mfmsr   r10
@@ -677,7 +677,7 @@ _GLOBAL(_tlbie)
  */
 _GLOBAL(_tlbia)
 #if defined(CONFIG_SMP)
-       rlwinm  r8,r1,0,0,(31-THREAD_SHIFT)
+       CURRENT_THREAD_INFO(r8, r1)
        lwz     r8,TI_CPU(r8)
        oris    r8,r8,10
        mfmsr   r10
index a242b5d7cbe477c109a78152a344b663444738a1..602aeb06d298b1eccc72089b0251443dff397163 100644 (file)
  *         |   CR save area                    (SP + 8)
  * SP ---> +-- Back chain                      (SP + 0)
  */
-#define STACKFRAMESIZE 256
-
-/* Save parameters offsets */
-#define STK_PARM(i)    (STACKFRAMESIZE + 48 + ((i)-3)*8)
-
-/* Save non-volatile offsets */
-#define STK_REG(i)     (112 + ((i)-14)*8)
-
 
 #ifndef CONFIG_PPC_64K_PAGES
 
@@ -64,9 +56,9 @@ _GLOBAL(__hash_page_4K)
        std     r0,16(r1)
        stdu    r1,-STACKFRAMESIZE(r1)
        /* Save all params that we need after a function call */
-       std     r6,STK_PARM(r6)(r1)
-       std     r8,STK_PARM(r8)(r1)
-       std     r9,STK_PARM(r9)(r1)
+       std     r6,STK_PARAM(R6)(r1)
+       std     r8,STK_PARAM(R8)(r1)
+       std     r9,STK_PARAM(R9)(r1)
        
        /* Save non-volatile registers.
         * r31 will hold "old PTE"
@@ -75,11 +67,11 @@ _GLOBAL(__hash_page_4K)
         * r28 is a hash value
         * r27 is hashtab mask (maybe dynamic patched instead ?)
         */
-       std     r27,STK_REG(r27)(r1)
-       std     r28,STK_REG(r28)(r1)
-       std     r29,STK_REG(r29)(r1)
-       std     r30,STK_REG(r30)(r1)
-       std     r31,STK_REG(r31)(r1)
+       std     r27,STK_REG(R27)(r1)
+       std     r28,STK_REG(R28)(r1)
+       std     r29,STK_REG(R29)(r1)
+       std     r30,STK_REG(R30)(r1)
+       std     r31,STK_REG(R31)(r1)
        
        /* Step 1:
         *
@@ -162,7 +154,7 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
        /* At this point, r3 contains new PP bits, save them in
         * place of "access" in the param area (sic)
         */
-       std     r3,STK_PARM(r4)(r1)
+       std     r3,STK_PARAM(R4)(r1)
 
        /* Get htab_hash_mask */
        ld      r4,htab_hash_mask@got(2)
@@ -192,11 +184,11 @@ htab_insert_pte:
        rldicr  r3,r0,3,63-3            /* r3 = (hash & mask) << 3 */
 
        /* Call ppc_md.hpte_insert */
-       ld      r6,STK_PARM(r4)(r1)     /* Retrieve new pp bits */
+       ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
        mr      r4,r29                  /* Retrieve va */
        li      r7,0                    /* !bolted, !secondary */
        li      r8,MMU_PAGE_4K          /* page size */
-       ld      r9,STK_PARM(r9)(r1)     /* segment size */
+       ld      r9,STK_PARAM(R9)(r1)    /* segment size */
 _GLOBAL(htab_call_hpte_insert1)
        bl      .                       /* Patched by htab_finish_init() */
        cmpdi   0,r3,0
@@ -215,11 +207,11 @@ _GLOBAL(htab_call_hpte_insert1)
        rldicr  r3,r0,3,63-3    /* r0 = (~hash & mask) << 3 */
        
        /* Call ppc_md.hpte_insert */
-       ld      r6,STK_PARM(r4)(r1)     /* Retrieve new pp bits */
+       ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
        mr      r4,r29                  /* Retrieve va */
        li      r7,HPTE_V_SECONDARY     /* !bolted, secondary */
        li      r8,MMU_PAGE_4K          /* page size */
-       ld      r9,STK_PARM(r9)(r1)     /* segment size */
+       ld      r9,STK_PARAM(R9)(r1)    /* segment size */
 _GLOBAL(htab_call_hpte_insert2)
        bl      .                       /* Patched by htab_finish_init() */
        cmpdi   0,r3,0
@@ -255,15 +247,15 @@ htab_pte_insert_ok:
         * (maybe add eieio may be good still ?)
         */
 htab_write_out_pte:
-       ld      r6,STK_PARM(r6)(r1)
+       ld      r6,STK_PARAM(R6)(r1)
        std     r30,0(r6)
        li      r3, 0
 htab_bail:
-       ld      r27,STK_REG(r27)(r1)
-       ld      r28,STK_REG(r28)(r1)
-       ld      r29,STK_REG(r29)(r1)
-       ld      r30,STK_REG(r30)(r1)
-       ld      r31,STK_REG(r31)(r1)
+       ld      r27,STK_REG(R27)(r1)
+       ld      r28,STK_REG(R28)(r1)
+       ld      r29,STK_REG(R29)(r1)
+       ld      r30,STK_REG(R30)(r1)
+       ld      r31,STK_REG(R31)(r1)
        addi    r1,r1,STACKFRAMESIZE
        ld      r0,16(r1)
        mtlr    r0
@@ -288,8 +280,8 @@ htab_modify_pte:
        /* Call ppc_md.hpte_updatepp */
        mr      r5,r29                  /* va */
        li      r6,MMU_PAGE_4K          /* page size */
-       ld      r7,STK_PARM(r9)(r1)     /* segment size */
-       ld      r8,STK_PARM(r8)(r1)     /* get "local" param */
+       ld      r7,STK_PARAM(R9)(r1)    /* segment size */
+       ld      r8,STK_PARAM(R8)(r1)    /* get "local" param */
 _GLOBAL(htab_call_hpte_updatepp)
        bl      .                       /* Patched by htab_finish_init() */
 
@@ -312,7 +304,7 @@ htab_wrong_access:
 
 htab_pte_insert_failure:
        /* Bail out restoring old PTE */
-       ld      r6,STK_PARM(r6)(r1)
+       ld      r6,STK_PARAM(R6)(r1)
        std     r31,0(r6)
        li      r3,-1
        b       htab_bail
@@ -340,9 +332,9 @@ _GLOBAL(__hash_page_4K)
        std     r0,16(r1)
        stdu    r1,-STACKFRAMESIZE(r1)
        /* Save all params that we need after a function call */
-       std     r6,STK_PARM(r6)(r1)
-       std     r8,STK_PARM(r8)(r1)
-       std     r9,STK_PARM(r9)(r1)
+       std     r6,STK_PARAM(R6)(r1)
+       std     r8,STK_PARAM(R8)(r1)
+       std     r9,STK_PARAM(R9)(r1)
 
        /* Save non-volatile registers.
         * r31 will hold "old PTE"
@@ -353,13 +345,13 @@ _GLOBAL(__hash_page_4K)
         * r26 is the hidx mask
         * r25 is the index in combo page
         */
-       std     r25,STK_REG(r25)(r1)
-       std     r26,STK_REG(r26)(r1)
-       std     r27,STK_REG(r27)(r1)
-       std     r28,STK_REG(r28)(r1)
-       std     r29,STK_REG(r29)(r1)
-       std     r30,STK_REG(r30)(r1)
-       std     r31,STK_REG(r31)(r1)
+       std     r25,STK_REG(R25)(r1)
+       std     r26,STK_REG(R26)(r1)
+       std     r27,STK_REG(R27)(r1)
+       std     r28,STK_REG(R28)(r1)
+       std     r29,STK_REG(R29)(r1)
+       std     r30,STK_REG(R30)(r1)
+       std     r31,STK_REG(R31)(r1)
 
        /* Step 1:
         *
@@ -452,7 +444,7 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
        /* At this point, r3 contains new PP bits, save them in
         * place of "access" in the param area (sic)
         */
-       std     r3,STK_PARM(r4)(r1)
+       std     r3,STK_PARAM(R4)(r1)
 
        /* Get htab_hash_mask */
        ld      r4,htab_hash_mask@got(2)
@@ -473,7 +465,7 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
        andis.  r0,r31,_PAGE_COMBO@h
        beq     htab_inval_old_hpte
 
-       ld      r6,STK_PARM(r6)(r1)
+       ld      r6,STK_PARAM(R6)(r1)
        ori     r26,r6,0x8000           /* Load the hidx mask */
        ld      r26,0(r26)
        addi    r5,r25,36               /* Check actual HPTE_SUB bit, this */
@@ -495,11 +487,11 @@ htab_special_pfn:
        rldicr  r3,r0,3,63-3            /* r0 = (hash & mask) << 3 */
 
        /* Call ppc_md.hpte_insert */
-       ld      r6,STK_PARM(r4)(r1)     /* Retrieve new pp bits */
+       ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
        mr      r4,r29                  /* Retrieve va */
        li      r7,0                    /* !bolted, !secondary */
        li      r8,MMU_PAGE_4K          /* page size */
-       ld      r9,STK_PARM(r9)(r1)     /* segment size */
+       ld      r9,STK_PARAM(R9)(r1)    /* segment size */
 _GLOBAL(htab_call_hpte_insert1)
        bl      .                       /* patched by htab_finish_init() */
        cmpdi   0,r3,0
@@ -522,11 +514,11 @@ _GLOBAL(htab_call_hpte_insert1)
        rldicr  r3,r0,3,63-3            /* r0 = (~hash & mask) << 3 */
 
        /* Call ppc_md.hpte_insert */
-       ld      r6,STK_PARM(r4)(r1)     /* Retrieve new pp bits */
+       ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
        mr      r4,r29                  /* Retrieve va */
        li      r7,HPTE_V_SECONDARY     /* !bolted, secondary */
        li      r8,MMU_PAGE_4K          /* page size */
-       ld      r9,STK_PARM(r9)(r1)     /* segment size */
+       ld      r9,STK_PARAM(R9)(r1)    /* segment size */
 _GLOBAL(htab_call_hpte_insert2)
        bl      .                       /* patched by htab_finish_init() */
        cmpdi   0,r3,0
@@ -559,8 +551,8 @@ htab_inval_old_hpte:
        mr      r4,r31                  /* PTE.pte */
        li      r5,0                    /* PTE.hidx */
        li      r6,MMU_PAGE_64K         /* psize */
-       ld      r7,STK_PARM(r9)(r1)     /* ssize */
-       ld      r8,STK_PARM(r8)(r1)     /* local */
+       ld      r7,STK_PARAM(R9)(r1)    /* ssize */
+       ld      r8,STK_PARAM(R8)(r1)    /* local */
        bl      .flush_hash_page
        /* Clear out _PAGE_HPTE_SUB bits in the new linux PTE */
        lis     r0,_PAGE_HPTE_SUB@h
@@ -576,7 +568,7 @@ htab_pte_insert_ok:
        /* Insert slot number & secondary bit in PTE second half,
         * clear _PAGE_BUSY and set approriate HPTE slot bit
         */
-       ld      r6,STK_PARM(r6)(r1)
+       ld      r6,STK_PARAM(R6)(r1)
        li      r0,_PAGE_BUSY
        andc    r30,r30,r0
        /* HPTE SUB bit */
@@ -597,13 +589,13 @@ htab_pte_insert_ok:
        std     r30,0(r6)
        li      r3, 0
 htab_bail:
-       ld      r25,STK_REG(r25)(r1)
-       ld      r26,STK_REG(r26)(r1)
-       ld      r27,STK_REG(r27)(r1)
-       ld      r28,STK_REG(r28)(r1)
-       ld      r29,STK_REG(r29)(r1)
-       ld      r30,STK_REG(r30)(r1)
-       ld      r31,STK_REG(r31)(r1)
+       ld      r25,STK_REG(R25)(r1)
+       ld      r26,STK_REG(R26)(r1)
+       ld      r27,STK_REG(R27)(r1)
+       ld      r28,STK_REG(R28)(r1)
+       ld      r29,STK_REG(R29)(r1)
+       ld      r30,STK_REG(R30)(r1)
+       ld      r31,STK_REG(R31)(r1)
        addi    r1,r1,STACKFRAMESIZE
        ld      r0,16(r1)
        mtlr    r0
@@ -630,8 +622,8 @@ htab_modify_pte:
        /* Call ppc_md.hpte_updatepp */
        mr      r5,r29                  /* va */
        li      r6,MMU_PAGE_4K          /* page size */
-       ld      r7,STK_PARM(r9)(r1)     /* segment size */
-       ld      r8,STK_PARM(r8)(r1)     /* get "local" param */
+       ld      r7,STK_PARAM(R9)(r1)    /* segment size */
+       ld      r8,STK_PARAM(R8)(r1)    /* get "local" param */
 _GLOBAL(htab_call_hpte_updatepp)
        bl      .                       /* patched by htab_finish_init() */
 
@@ -644,7 +636,7 @@ _GLOBAL(htab_call_hpte_updatepp)
        /* Clear the BUSY bit and Write out the PTE */
        li      r0,_PAGE_BUSY
        andc    r30,r30,r0
-       ld      r6,STK_PARM(r6)(r1)
+       ld      r6,STK_PARAM(R6)(r1)
        std     r30,0(r6)
        li      r3,0
        b       htab_bail
@@ -657,7 +649,7 @@ htab_wrong_access:
 
 htab_pte_insert_failure:
        /* Bail out restoring old PTE */
-       ld      r6,STK_PARM(r6)(r1)
+       ld      r6,STK_PARAM(R6)(r1)
        std     r31,0(r6)
        li      r3,-1
        b       htab_bail
@@ -677,9 +669,9 @@ _GLOBAL(__hash_page_64K)
        std     r0,16(r1)
        stdu    r1,-STACKFRAMESIZE(r1)
        /* Save all params that we need after a function call */
-       std     r6,STK_PARM(r6)(r1)
-       std     r8,STK_PARM(r8)(r1)
-       std     r9,STK_PARM(r9)(r1)
+       std     r6,STK_PARAM(R6)(r1)
+       std     r8,STK_PARAM(R8)(r1)
+       std     r9,STK_PARAM(R9)(r1)
 
        /* Save non-volatile registers.
         * r31 will hold "old PTE"
@@ -688,11 +680,11 @@ _GLOBAL(__hash_page_64K)
         * r28 is a hash value
         * r27 is hashtab mask (maybe dynamic patched instead ?)
         */
-       std     r27,STK_REG(r27)(r1)
-       std     r28,STK_REG(r28)(r1)
-       std     r29,STK_REG(r29)(r1)
-       std     r30,STK_REG(r30)(r1)
-       std     r31,STK_REG(r31)(r1)
+       std     r27,STK_REG(R27)(r1)
+       std     r28,STK_REG(R28)(r1)
+       std     r29,STK_REG(R29)(r1)
+       std     r30,STK_REG(R30)(r1)
+       std     r31,STK_REG(R31)(r1)
 
        /* Step 1:
         *
@@ -780,7 +772,7 @@ END_FTR_SECTION(CPU_FTR_NOEXECUTE|CPU_FTR_COHERENT_ICACHE, CPU_FTR_NOEXECUTE)
        /* At this point, r3 contains new PP bits, save them in
         * place of "access" in the param area (sic)
         */
-       std     r3,STK_PARM(r4)(r1)
+       std     r3,STK_PARAM(R4)(r1)
 
        /* Get htab_hash_mask */
        ld      r4,htab_hash_mask@got(2)
@@ -813,11 +805,11 @@ ht64_insert_pte:
        rldicr  r3,r0,3,63-3    /* r0 = (hash & mask) << 3 */
 
        /* Call ppc_md.hpte_insert */
-       ld      r6,STK_PARM(r4)(r1)     /* Retrieve new pp bits */
+       ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
        mr      r4,r29                  /* Retrieve va */
        li      r7,0                    /* !bolted, !secondary */
        li      r8,MMU_PAGE_64K
-       ld      r9,STK_PARM(r9)(r1)     /* segment size */
+       ld      r9,STK_PARAM(R9)(r1)    /* segment size */
 _GLOBAL(ht64_call_hpte_insert1)
        bl      .                       /* patched by htab_finish_init() */
        cmpdi   0,r3,0
@@ -836,11 +828,11 @@ _GLOBAL(ht64_call_hpte_insert1)
        rldicr  r3,r0,3,63-3    /* r0 = (~hash & mask) << 3 */
 
        /* Call ppc_md.hpte_insert */
-       ld      r6,STK_PARM(r4)(r1)     /* Retrieve new pp bits */
+       ld      r6,STK_PARAM(R4)(r1)    /* Retrieve new pp bits */
        mr      r4,r29                  /* Retrieve va */
        li      r7,HPTE_V_SECONDARY     /* !bolted, secondary */
        li      r8,MMU_PAGE_64K
-       ld      r9,STK_PARM(r9)(r1)     /* segment size */
+       ld      r9,STK_PARAM(R9)(r1)    /* segment size */
 _GLOBAL(ht64_call_hpte_insert2)
        bl      .                       /* patched by htab_finish_init() */
        cmpdi   0,r3,0
@@ -876,15 +868,15 @@ ht64_pte_insert_ok:
         * (maybe add eieio may be good still ?)
         */
 ht64_write_out_pte:
-       ld      r6,STK_PARM(r6)(r1)
+       ld      r6,STK_PARAM(R6)(r1)
        std     r30,0(r6)
        li      r3, 0
 ht64_bail:
-       ld      r27,STK_REG(r27)(r1)
-       ld      r28,STK_REG(r28)(r1)
-       ld      r29,STK_REG(r29)(r1)
-       ld      r30,STK_REG(r30)(r1)
-       ld      r31,STK_REG(r31)(r1)
+       ld      r27,STK_REG(R27)(r1)
+       ld      r28,STK_REG(R28)(r1)
+       ld      r29,STK_REG(R29)(r1)
+       ld      r30,STK_REG(R30)(r1)
+       ld      r31,STK_REG(R31)(r1)
        addi    r1,r1,STACKFRAMESIZE
        ld      r0,16(r1)
        mtlr    r0
@@ -909,8 +901,8 @@ ht64_modify_pte:
        /* Call ppc_md.hpte_updatepp */
        mr      r5,r29                  /* va */
        li      r6,MMU_PAGE_64K
-       ld      r7,STK_PARM(r9)(r1)     /* segment size */
-       ld      r8,STK_PARM(r8)(r1)     /* get "local" param */
+       ld      r7,STK_PARAM(R9)(r1)    /* segment size */
+       ld      r8,STK_PARAM(R8)(r1)    /* get "local" param */
 _GLOBAL(ht64_call_hpte_updatepp)
        bl      .                       /* patched by htab_finish_init() */
 
@@ -933,7 +925,7 @@ ht64_wrong_access:
 
 ht64_pte_insert_failure:
        /* Bail out restoring old PTE */
-       ld      r6,STK_PARM(r6)(r1)
+       ld      r6,STK_PARAM(R6)(r1)
        std     r31,0(r6)
        li      r3,-1
        b       ht64_bail
index 1e95556dc692e3702f2df518dd4e08e7770ae52e..39b159751c35ab17d5e3df0dd48282abe5228700 100644 (file)
@@ -340,6 +340,8 @@ static int __init find_min_common_depth(void)
                                dbg("Using form 1 affinity\n");
                                form1_affinity = 1;
                        }
+
+                       of_node_put(chosen);
                }
        }
 
index ff672bd8fea92a4d110355ae4da341ec817ffc50..f09d48e3268d9bab371f31e616147bb53894c69a 100644 (file)
@@ -126,7 +126,7 @@ BEGIN_MMU_FTR_SECTION
        /* Set the TLB reservation and search for existing entry. Then load
         * the entry.
         */
-       PPC_TLBSRX_DOT(0,r16)
+       PPC_TLBSRX_DOT(0,R16)
        ldx     r14,r14,r15             /* grab pgd entry */
        beq     normal_tlb_miss_done    /* tlb exists already, bail */
 MMU_FTR_SECTION_ELSE
@@ -395,7 +395,7 @@ BEGIN_MMU_FTR_SECTION
        /* Set the TLB reservation and search for existing entry. Then load
         * the entry.
         */
-       PPC_TLBSRX_DOT(0,r16)
+       PPC_TLBSRX_DOT(0,R16)
        ld      r14,0(r10)
        beq     normal_tlb_miss_done
 MMU_FTR_SECTION_ELSE
@@ -528,7 +528,7 @@ BEGIN_MMU_FTR_SECTION
        /* Search if we already have a TLB entry for that virtual address, and
         * if we do, bail out.
         */
-       PPC_TLBSRX_DOT(0,r16)
+       PPC_TLBSRX_DOT(0,R16)
        beq     virt_page_table_tlb_miss_done
 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_TLBRSRV)
 
@@ -779,7 +779,7 @@ htw_tlb_miss:
         *
         * MAS1:IND should be already set based on MAS4
         */
-       PPC_TLBSRX_DOT(0,r16)
+       PPC_TLBSRX_DOT(0,R16)
        beq     htw_tlb_miss_done
 
        /* Now, we need to walk the page tables. First check if we are in
@@ -919,7 +919,7 @@ tlb_load_linear:
        mtspr   SPRN_MAS1,r15
 
        /* Already somebody there ? */
-       PPC_TLBSRX_DOT(0,r16)
+       PPC_TLBSRX_DOT(0,R16)
        beq     tlb_load_linear_done
 
        /* Now we build the remaining MAS. MAS0 and 2 should be fine
index 7c63c0ed4f1b21b40e980403cb231f8408e8c645..fab919fd1384b8d3a8f589bc368f0e4bdaf03903 100644 (file)
@@ -266,7 +266,7 @@ BEGIN_MMU_FTR_SECTION
        andi.   r3,r3,MMUCSR0_TLBFI@l
        bne     1b
 MMU_FTR_SECTION_ELSE
-       PPC_TLBILX_ALL(0,0)
+       PPC_TLBILX_ALL(0,R0)
 ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_USE_TLBILX)
        msync
        isync
@@ -279,7 +279,7 @@ BEGIN_MMU_FTR_SECTION
        wrteei  0
        mfspr   r4,SPRN_MAS6    /* save MAS6 */
        mtspr   SPRN_MAS6,r3
-       PPC_TLBILX_PID(0,0)
+       PPC_TLBILX_PID(0,R0)
        mtspr   SPRN_MAS6,r4    /* restore MAS6 */
        wrtee   r10
 MMU_FTR_SECTION_ELSE
@@ -313,7 +313,7 @@ BEGIN_MMU_FTR_SECTION
        mtspr   SPRN_MAS1,r4
        tlbwe
 MMU_FTR_SECTION_ELSE
-       PPC_TLBILX_VA(0,r3)
+       PPC_TLBILX_VA(0,R3)
 ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_USE_TLBILX)
        msync
        isync
@@ -331,7 +331,7 @@ _GLOBAL(_tlbil_pid)
        mfmsr   r10
        wrteei  0
        mtspr   SPRN_MAS6,r4
-       PPC_TLBILX_PID(0,0)
+       PPC_TLBILX_PID(0,R0)
        wrtee   r10
        msync
        isync
@@ -343,14 +343,14 @@ _GLOBAL(_tlbil_pid_noind)
        ori     r4,r4,MAS6_SIND
        wrteei  0
        mtspr   SPRN_MAS6,r4
-       PPC_TLBILX_PID(0,0)
+       PPC_TLBILX_PID(0,R0)
        wrtee   r10
        msync
        isync
        blr
 
 _GLOBAL(_tlbil_all)
-       PPC_TLBILX_ALL(0,0)
+       PPC_TLBILX_ALL(0,R0)
        msync
        isync
        blr
@@ -364,7 +364,7 @@ _GLOBAL(_tlbil_va)
        beq     1f
        rlwimi  r4,r6,MAS6_SIND_SHIFT,MAS6_SIND
 1:     mtspr   SPRN_MAS6,r4            /* assume AS=0 for now */
-       PPC_TLBILX_VA(0,r3)
+       PPC_TLBILX_VA(0,R3)
        msync
        isync
        wrtee   r10
@@ -379,7 +379,7 @@ _GLOBAL(_tlbivax_bcast)
        beq     1f
        rlwimi  r4,r6,MAS6_SIND_SHIFT,MAS6_SIND
 1:     mtspr   SPRN_MAS6,r4            /* assume AS=0 for now */
-       PPC_TLBIVAX(0,r3)
+       PPC_TLBIVAX(0,R3)
        eieio
        tlbsync
        sync
index 5c3cf2d04e41ccaa6e8b7aa94eb7ca27ba4baad9..1fc8109bf2f94761d01c21eb1f9358d58668aeee 100644 (file)
@@ -75,23 +75,23 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh);
 #define PPC_NOP()              EMIT(PPC_INST_NOP)
 #define PPC_BLR()              EMIT(PPC_INST_BLR)
 #define PPC_BLRL()             EMIT(PPC_INST_BLRL)
-#define PPC_MTLR(r)            EMIT(PPC_INST_MTLR | __PPC_RT(r))
-#define PPC_ADDI(d, a, i)      EMIT(PPC_INST_ADDI | __PPC_RT(d) |            \
-                                    __PPC_RA(a) | IMM_L(i))
+#define PPC_MTLR(r)            EMIT(PPC_INST_MTLR | ___PPC_RT(r))
+#define PPC_ADDI(d, a, i)      EMIT(PPC_INST_ADDI | ___PPC_RT(d) |           \
+                                    ___PPC_RA(a) | IMM_L(i))
 #define PPC_MR(d, a)           PPC_OR(d, a, a)
 #define PPC_LI(r, i)           PPC_ADDI(r, 0, i)
 #define PPC_ADDIS(d, a, i)     EMIT(PPC_INST_ADDIS |                         \
-                                    __PPC_RS(d) | __PPC_RA(a) | IMM_L(i))
+                                    ___PPC_RS(d) | ___PPC_RA(a) | IMM_L(i))
 #define PPC_LIS(r, i)          PPC_ADDIS(r, 0, i)
-#define PPC_STD(r, base, i)    EMIT(PPC_INST_STD | __PPC_RS(r) |             \
-                                    __PPC_RA(base) | ((i) & 0xfffc))
-
-#define PPC_LD(r, base, i)     EMIT(PPC_INST_LD | __PPC_RT(r) |              \
-                                    __PPC_RA(base) | IMM_L(i))
-#define PPC_LWZ(r, base, i)    EMIT(PPC_INST_LWZ | __PPC_RT(r) |             \
-                                    __PPC_RA(base) | IMM_L(i))
-#define PPC_LHZ(r, base, i)    EMIT(PPC_INST_LHZ | __PPC_RT(r) |             \
-                                    __PPC_RA(base) | IMM_L(i))
+#define PPC_STD(r, base, i)    EMIT(PPC_INST_STD | ___PPC_RS(r) |            \
+                                    ___PPC_RA(base) | ((i) & 0xfffc))
+
+#define PPC_LD(r, base, i)     EMIT(PPC_INST_LD | ___PPC_RT(r) |             \
+                                    ___PPC_RA(base) | IMM_L(i))
+#define PPC_LWZ(r, base, i)    EMIT(PPC_INST_LWZ | ___PPC_RT(r) |            \
+                                    ___PPC_RA(base) | IMM_L(i))
+#define PPC_LHZ(r, base, i)    EMIT(PPC_INST_LHZ | ___PPC_RT(r) |            \
+                                    ___PPC_RA(base) | IMM_L(i))
 /* Convenience helpers for the above with 'far' offsets: */
 #define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) PPC_LD(r, base, i);     \
                else {  PPC_ADDIS(r, base, IMM_HA(i));                        \
@@ -105,52 +105,52 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh);
                else {  PPC_ADDIS(r, base, IMM_HA(i));                        \
                        PPC_LHZ(r, r, IMM_L(i)); } } while(0)
 
-#define PPC_CMPWI(a, i)                EMIT(PPC_INST_CMPWI | __PPC_RA(a) | IMM_L(i))
-#define PPC_CMPDI(a, i)                EMIT(PPC_INST_CMPDI | __PPC_RA(a) | IMM_L(i))
-#define PPC_CMPLWI(a, i)       EMIT(PPC_INST_CMPLWI | __PPC_RA(a) | IMM_L(i))
-#define PPC_CMPLW(a, b)                EMIT(PPC_INST_CMPLW | __PPC_RA(a) | __PPC_RB(b))
-
-#define PPC_SUB(d, a, b)       EMIT(PPC_INST_SUB | __PPC_RT(d) |             \
-                                    __PPC_RB(a) | __PPC_RA(b))
-#define PPC_ADD(d, a, b)       EMIT(PPC_INST_ADD | __PPC_RT(d) |             \
-                                    __PPC_RA(a) | __PPC_RB(b))
-#define PPC_MUL(d, a, b)       EMIT(PPC_INST_MULLW | __PPC_RT(d) |           \
-                                    __PPC_RA(a) | __PPC_RB(b))
-#define PPC_MULHWU(d, a, b)    EMIT(PPC_INST_MULHWU | __PPC_RT(d) |          \
-                                    __PPC_RA(a) | __PPC_RB(b))
-#define PPC_MULI(d, a, i)      EMIT(PPC_INST_MULLI | __PPC_RT(d) |           \
-                                    __PPC_RA(a) | IMM_L(i))
-#define PPC_DIVWU(d, a, b)     EMIT(PPC_INST_DIVWU | __PPC_RT(d) |           \
-                                    __PPC_RA(a) | __PPC_RB(b))
-#define PPC_AND(d, a, b)       EMIT(PPC_INST_AND | __PPC_RA(d) |             \
-                                    __PPC_RS(a) | __PPC_RB(b))
-#define PPC_ANDI(d, a, i)      EMIT(PPC_INST_ANDI | __PPC_RA(d) |            \
-                                    __PPC_RS(a) | IMM_L(i))
-#define PPC_AND_DOT(d, a, b)   EMIT(PPC_INST_ANDDOT | __PPC_RA(d) |          \
-                                    __PPC_RS(a) | __PPC_RB(b))
-#define PPC_OR(d, a, b)                EMIT(PPC_INST_OR | __PPC_RA(d) |              \
-                                    __PPC_RS(a) | __PPC_RB(b))
-#define PPC_ORI(d, a, i)       EMIT(PPC_INST_ORI | __PPC_RA(d) |             \
-                                    __PPC_RS(a) | IMM_L(i))
-#define PPC_ORIS(d, a, i)      EMIT(PPC_INST_ORIS | __PPC_RA(d) |            \
-                                    __PPC_RS(a) | IMM_L(i))
-#define PPC_SLW(d, a, s)       EMIT(PPC_INST_SLW | __PPC_RA(d) |             \
-                                    __PPC_RS(a) | __PPC_RB(s))
-#define PPC_SRW(d, a, s)       EMIT(PPC_INST_SRW | __PPC_RA(d) |             \
-                                    __PPC_RS(a) | __PPC_RB(s))
+#define PPC_CMPWI(a, i)                EMIT(PPC_INST_CMPWI | ___PPC_RA(a) | IMM_L(i))
+#define PPC_CMPDI(a, i)                EMIT(PPC_INST_CMPDI | ___PPC_RA(a) | IMM_L(i))
+#define PPC_CMPLWI(a, i)       EMIT(PPC_INST_CMPLWI | ___PPC_RA(a) | IMM_L(i))
+#define PPC_CMPLW(a, b)                EMIT(PPC_INST_CMPLW | ___PPC_RA(a) | ___PPC_RB(b))
+
+#define PPC_SUB(d, a, b)       EMIT(PPC_INST_SUB | ___PPC_RT(d) |            \
+                                    ___PPC_RB(a) | ___PPC_RA(b))
+#define PPC_ADD(d, a, b)       EMIT(PPC_INST_ADD | ___PPC_RT(d) |            \
+                                    ___PPC_RA(a) | ___PPC_RB(b))
+#define PPC_MUL(d, a, b)       EMIT(PPC_INST_MULLW | ___PPC_RT(d) |          \
+                                    ___PPC_RA(a) | ___PPC_RB(b))
+#define PPC_MULHWU(d, a, b)    EMIT(PPC_INST_MULHWU | ___PPC_RT(d) |         \
+                                    ___PPC_RA(a) | ___PPC_RB(b))
+#define PPC_MULI(d, a, i)      EMIT(PPC_INST_MULLI | ___PPC_RT(d) |          \
+                                    ___PPC_RA(a) | IMM_L(i))
+#define PPC_DIVWU(d, a, b)     EMIT(PPC_INST_DIVWU | ___PPC_RT(d) |          \
+                                    ___PPC_RA(a) | ___PPC_RB(b))
+#define PPC_AND(d, a, b)       EMIT(PPC_INST_AND | ___PPC_RA(d) |            \
+                                    ___PPC_RS(a) | ___PPC_RB(b))
+#define PPC_ANDI(d, a, i)      EMIT(PPC_INST_ANDI | ___PPC_RA(d) |           \
+                                    ___PPC_RS(a) | IMM_L(i))
+#define PPC_AND_DOT(d, a, b)   EMIT(PPC_INST_ANDDOT | ___PPC_RA(d) |         \
+                                    ___PPC_RS(a) | ___PPC_RB(b))
+#define PPC_OR(d, a, b)                EMIT(PPC_INST_OR | ___PPC_RA(d) |             \
+                                    ___PPC_RS(a) | ___PPC_RB(b))
+#define PPC_ORI(d, a, i)       EMIT(PPC_INST_ORI | ___PPC_RA(d) |            \
+                                    ___PPC_RS(a) | IMM_L(i))
+#define PPC_ORIS(d, a, i)      EMIT(PPC_INST_ORIS | ___PPC_RA(d) |           \
+                                    ___PPC_RS(a) | IMM_L(i))
+#define PPC_SLW(d, a, s)       EMIT(PPC_INST_SLW | ___PPC_RA(d) |            \
+                                    ___PPC_RS(a) | ___PPC_RB(s))
+#define PPC_SRW(d, a, s)       EMIT(PPC_INST_SRW | ___PPC_RA(d) |            \
+                                    ___PPC_RS(a) | ___PPC_RB(s))
 /* slwi = rlwinm Rx, Ry, n, 0, 31-n */
-#define PPC_SLWI(d, a, i)      EMIT(PPC_INST_RLWINM | __PPC_RA(d) |          \
-                                    __PPC_RS(a) | __PPC_SH(i) |              \
+#define PPC_SLWI(d, a, i)      EMIT(PPC_INST_RLWINM | ___PPC_RA(d) |         \
+                                    ___PPC_RS(a) | __PPC_SH(i) |             \
                                     __PPC_MB(0) | __PPC_ME(31-(i)))
 /* srwi = rlwinm Rx, Ry, 32-n, n, 31 */
-#define PPC_SRWI(d, a, i)      EMIT(PPC_INST_RLWINM | __PPC_RA(d) |          \
-                                    __PPC_RS(a) | __PPC_SH(32-(i)) |         \
+#define PPC_SRWI(d, a, i)      EMIT(PPC_INST_RLWINM | ___PPC_RA(d) |         \
+                                    ___PPC_RS(a) | __PPC_SH(32-(i)) |        \
                                     __PPC_MB(i) | __PPC_ME(31))
 /* sldi = rldicr Rx, Ry, n, 63-n */
-#define PPC_SLDI(d, a, i)      EMIT(PPC_INST_RLDICR | __PPC_RA(d) |          \
-                                    __PPC_RS(a) | __PPC_SH(i) |              \
+#define PPC_SLDI(d, a, i)      EMIT(PPC_INST_RLDICR | ___PPC_RA(d) |         \
+                                    ___PPC_RS(a) | __PPC_SH(i) |             \
                                     __PPC_MB(63-(i)) | (((i) & 0x20) >> 4))
-#define PPC_NEG(d, a)          EMIT(PPC_INST_NEG | __PPC_RT(d) | __PPC_RA(a))
+#define PPC_NEG(d, a)          EMIT(PPC_INST_NEG | ___PPC_RT(d) | ___PPC_RA(a))
 
 /* Long jump; (unconditional 'branch') */
 #define PPC_JMP(dest)          EMIT(PPC_INST_BRANCH |                        \
index 2dc8b14848455122918d13cf1d2985984f8a248b..dd1130642d0753b217e9a73c3e9404bb2aef2d0d 100644 (file)
@@ -39,7 +39,7 @@ static void bpf_jit_build_prologue(struct sk_filter *fp, u32 *image,
                /* Make stackframe */
                if (ctx->seen & SEEN_DATAREF) {
                        /* If we call any helpers (for loads), save LR */
-                       EMIT(PPC_INST_MFLR | __PPC_RT(0));
+                       EMIT(PPC_INST_MFLR | __PPC_RT(R0));
                        PPC_STD(0, 1, 16);
 
                        /* Back up non-volatile regs. */
@@ -56,7 +56,7 @@ static void bpf_jit_build_prologue(struct sk_filter *fp, u32 *image,
                                        PPC_STD(i, 1, -(8*(32-i)));
                        }
                }
-               EMIT(PPC_INST_STDU | __PPC_RS(1) | __PPC_RA(1) |
+               EMIT(PPC_INST_STDU | __PPC_RS(R1) | __PPC_RA(R1) |
                     (-BPF_PPC_STACKFRAME & 0xfffc));
        }
 
index e8a18d1cc7c92ba51a6187920c3f624db0620038..74d1e780748b58f17f8987218a6184c87aae63da 100644 (file)
@@ -57,7 +57,7 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)
 
        lr = regs->link;
        sp = regs->gpr[1];
-       perf_callchain_store(entry, regs->nip);
+       perf_callchain_store(entry, perf_instruction_pointer(regs));
 
        if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD))
                return;
@@ -238,7 +238,7 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry,
        struct signal_frame_64 __user *sigframe;
        unsigned long __user *fp, *uregs;
 
-       next_ip = regs->nip;
+       next_ip = perf_instruction_pointer(regs);
        lr = regs->link;
        sp = regs->gpr[1];
        perf_callchain_store(entry, next_ip);
@@ -444,7 +444,7 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry,
        long level = 0;
        unsigned int __user *fp, *uregs;
 
-       next_ip = regs->nip;
+       next_ip = perf_instruction_pointer(regs);
        lr = regs->link;
        sp = regs->gpr[1];
        perf_callchain_store(entry, next_ip);
index 8f84bcba18da12f1ee9b1f1f5727075777febb8c..77b49ddda9d3675ed816d65af7f8c242578c01a0 100644 (file)
@@ -73,7 +73,10 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 {
        return 0;
 }
-static inline void perf_read_regs(struct pt_regs *regs) { }
+static inline void perf_read_regs(struct pt_regs *regs)
+{
+       regs->result = 0;
+}
 static inline int perf_intr_is_nmi(struct pt_regs *regs)
 {
        return 0;
@@ -116,6 +119,26 @@ static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp)
                *addrp = mfspr(SPRN_SDAR);
 }
 
+static bool mmcra_sihv(unsigned long mmcra)
+{
+       unsigned long sihv = MMCRA_SIHV;
+
+       if (ppmu->flags & PPMU_ALT_SIPR)
+               sihv = POWER6_MMCRA_SIHV;
+
+       return !!(mmcra & sihv);
+}
+
+static bool mmcra_sipr(unsigned long mmcra)
+{
+       unsigned long sipr = MMCRA_SIPR;
+
+       if (ppmu->flags & PPMU_ALT_SIPR)
+               sipr = POWER6_MMCRA_SIPR;
+
+       return !!(mmcra & sipr);
+}
+
 static inline u32 perf_flags_from_msr(struct pt_regs *regs)
 {
        if (regs->msr & MSR_PR)
@@ -128,19 +151,9 @@ static inline u32 perf_flags_from_msr(struct pt_regs *regs)
 static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 {
        unsigned long mmcra = regs->dsisr;
-       unsigned long sihv = MMCRA_SIHV;
-       unsigned long sipr = MMCRA_SIPR;
+       unsigned long use_siar = regs->result;
 
-       /* Not a PMU interrupt: Make up flags from regs->msr */
-       if (TRAP(regs) != 0xf00)
-               return perf_flags_from_msr(regs);
-
-       /*
-        * If we don't support continuous sampling and this
-        * is not a marked event, same deal
-        */
-       if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
-           !(mmcra & MMCRA_SAMPLE_ENABLE))
+       if (!use_siar)
                return perf_flags_from_msr(regs);
 
        /*
@@ -156,15 +169,10 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs)
                return PERF_RECORD_MISC_USER;
        }
 
-       if (ppmu->flags & PPMU_ALT_SIPR) {
-               sihv = POWER6_MMCRA_SIHV;
-               sipr = POWER6_MMCRA_SIPR;
-       }
-
        /* PR has priority over HV, so order below is important */
-       if (mmcra & sipr)
+       if (mmcra_sipr(mmcra))
                return PERF_RECORD_MISC_USER;
-       if ((mmcra & sihv) && (freeze_events_kernel != MMCR0_FCHV))
+       if (mmcra_sihv(mmcra) && (freeze_events_kernel != MMCR0_FCHV))
                return PERF_RECORD_MISC_HYPERVISOR;
        return PERF_RECORD_MISC_KERNEL;
 }
@@ -172,10 +180,45 @@ static inline u32 perf_get_misc_flags(struct pt_regs *regs)
 /*
  * Overload regs->dsisr to store MMCRA so we only need to read it once
  * on each interrupt.
+ * Overload regs->result to specify whether we should use the MSR (result
+ * is zero) or the SIAR (result is non zero).
  */
 static inline void perf_read_regs(struct pt_regs *regs)
 {
-       regs->dsisr = mfspr(SPRN_MMCRA);
+       unsigned long mmcra = mfspr(SPRN_MMCRA);
+       int marked = mmcra & MMCRA_SAMPLE_ENABLE;
+       int use_siar;
+
+       /*
+        * If this isn't a PMU exception (eg a software event) the SIAR is
+        * not valid. Use pt_regs.
+        *
+        * If it is a marked event use the SIAR.
+        *
+        * If the PMU doesn't update the SIAR for non marked events use
+        * pt_regs.
+        *
+        * If the PMU has HV/PR flags then check to see if they
+        * place the exception in userspace. If so, use pt_regs. In
+        * continuous sampling mode the SIAR and the PMU exception are
+        * not synchronised, so they may be many instructions apart.
+        * This can result in confusing backtraces. We still want
+        * hypervisor samples as well as samples in the kernel with
+        * interrupts off hence the userspace check.
+        */
+       if (TRAP(regs) != 0xf00)
+               use_siar = 0;
+       else if (marked)
+               use_siar = 1;
+       else if ((ppmu->flags & PPMU_NO_CONT_SAMPLING))
+               use_siar = 0;
+       else if (!(ppmu->flags & PPMU_NO_SIPR) && mmcra_sipr(mmcra))
+               use_siar = 0;
+       else
+               use_siar = 1;
+
+       regs->dsisr = mmcra;
+       regs->result = use_siar;
 }
 
 /*
@@ -1329,18 +1372,12 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
  */
 unsigned long perf_instruction_pointer(struct pt_regs *regs)
 {
-       unsigned long mmcra = regs->dsisr;
+       unsigned long use_siar = regs->result;
 
-       /* Not a PMU interrupt */
-       if (TRAP(regs) != 0xf00)
-               return regs->nip;
-
-       /* Processor doesn't support sampling non marked events */
-       if ((ppmu->flags & PPMU_NO_CONT_SAMPLING) &&
-           !(mmcra & MMCRA_SAMPLE_ENABLE))
+       if (use_siar)
+               return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
+       else
                return regs->nip;
-
-       return mfspr(SPRN_SIAR) + perf_ip_adjust(regs);
 }
 
 static bool pmc_overflow(unsigned long val)
index 583e67fee37ee1fd4daddc84ea3064fc4178ed6c..9f6c33d63a42c207a80444650646c1b3a1af7d08 100644 (file)
@@ -160,7 +160,7 @@ static void __init ppc47x_setup_arch(void)
        /* No need to check the DMA config as we /know/ our windows are all of
         * RAM.  Lets hope that doesn't change */
 #ifdef CONFIG_SWIOTLB
-       if (memblock_end_of_DRAM() > 0xffffffff) {
+       if ((memblock_end_of_DRAM() - 1) > 0xffffffff) {
                ppc_swiotlb_enable = 1;
                set_pci_dma_ops(&swiotlb_dma_ops);
                ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
index 3661bcdc326a6551b0e0a11c8d964e4b0597a619..cf964e19573a15b8d8c3f9f2c33f0079f146f290 100644 (file)
@@ -128,6 +128,11 @@ static __initdata struct cpm_pin km82xx_pins[] = {
        {3, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, /* TXP */
        {3, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, /* TXN */
        {3, 25, CPM_PIN_INPUT  | CPM_PIN_PRIMARY}, /* RXD */
+
+       /* SPI */
+       {3, 16, CPM_PIN_INPUT | CPM_PIN_SECONDARY},/* SPI_MISO PD16 */
+       {3, 17, CPM_PIN_INPUT | CPM_PIN_SECONDARY},/* SPI_MOSI PD17 */
+       {3, 18, CPM_PIN_INPUT | CPM_PIN_SECONDARY},/* SPI_CLK PD18 */
 };
 
 static void __init init_ioports(void)
index a266ba8768639b8f05196fe831968ad12f8e1c61..89923d72334980ddc74e81561426ae24aeae5351 100644 (file)
@@ -3,7 +3,7 @@
  * Author: Heiko Schocher <hs@denx.de>
  *
  * Description:
- * Keymile KMETER1 board specific routines.
+ * Keymile 83xx platform specific routines.
  *
  * 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
@@ -70,54 +70,88 @@ static void __init mpc83xx_km_setup_arch(void)
                for_each_node_by_name(np, "spi")
                        par_io_of_config(np);
 
-               for (np = NULL; (np = of_find_node_by_name(np, "ucc")) != NULL;)
+               for_each_node_by_name(np, "ucc")
                        par_io_of_config(np);
        }
 
        np = of_find_compatible_node(NULL, "network", "ucc_geth");
        if (np != NULL) {
-               uint svid;
+               /*
+                * handle mpc8360E Erratum QE_ENET10:
+                * RGMII AC values do not meet the specification
+                */
+               uint svid = mfspr(SPRN_SVR);
+               struct  device_node *np_par;
+               struct  resource res;
+               void    __iomem *base;
+               int     ret;
+
+               np_par = of_find_node_by_name(NULL, "par_io");
+               if (np_par == NULL) {
+                       printk(KERN_WARNING "%s couldn;t find par_io node\n",
+                               __func__);
+                       return;
+               }
+               /* Map Parallel I/O ports registers */
+               ret = of_address_to_resource(np_par, 0, &res);
+               if (ret) {
+                       printk(KERN_WARNING "%s couldn;t map par_io registers\n",
+                               __func__);
+                       return;
+               }
+
+               base = ioremap(res.start, res.end - res.start + 1);
+
+               /*
+                * set output delay adjustments to default values according
+                * table 5 in Errata Rev. 5, 9/2011:
+                *
+                * write 0b01 to UCC1 bits 18:19
+                * write 0b01 to UCC2 option 1 bits 4:5
+                * write 0b01 to UCC2 option 2 bits 16:17
+                */
+               clrsetbits_be32((base + 0xa8), 0x0c00f000, 0x04005000);
+
+               /*
+                * set output delay adjustments to default values according
+                * table 3-13 in Reference Manual Rev.3 05/2010:
+                *
+                * write 0b01 to UCC2 option 2 bits 16:17
+                * write 0b0101 to UCC1 bits 20:23
+                * write 0b0101 to UCC2 option 1 bits 24:27
+                */
+               clrsetbits_be32((base + 0xac), 0x0000cff0, 0x00004550);
 
-               /* handle mpc8360ea rev.2.1 erratum 2: RGMII Timing */
-               svid = mfspr(SPRN_SVR);
                if (SVR_REV(svid) == 0x0021) {
-                       struct  device_node *np_par;
-                       struct  resource res;
-                       void    __iomem *base;
-                       int     ret;
-
-                       np_par = of_find_node_by_name(NULL, "par_io");
-                       if (np_par == NULL) {
-                               printk(KERN_WARNING "%s couldn;t find par_io node\n",
-                                       __func__);
-                               return;
-                       }
-                       /* Map Parallel I/O ports registers */
-                       ret = of_address_to_resource(np_par, 0, &res);
-                       if (ret) {
-                               printk(KERN_WARNING "%s couldn;t map par_io registers\n",
-                                       __func__);
-                               return;
-                       }
-                       base = ioremap(res.start, resource_size(&res));
+                       /*
+                        * UCC2 option 1: write 0b1010 to bits 24:27
+                        * at address IMMRBAR+0x14AC
+                        */
+                       clrsetbits_be32((base + 0xac), 0x000000f0, 0x000000a0);
+               } else if (SVR_REV(svid) == 0x0020) {
+                       /*
+                        * UCC1: write 0b11 to bits 18:19
+                        * at address IMMRBAR+0x14A8
+                        */
+                       setbits32((base + 0xa8), 0x00003000);
 
                        /*
-                        * IMMR + 0x14A8[4:5] = 11 (clk delay for UCC 2)
-                        * IMMR + 0x14A8[18:19] = 11 (clk delay for UCC 1)
+                        * UCC2 option 1: write 0b11 to bits 4:5
+                        * at address IMMRBAR+0x14A8
                         */
-                       setbits32((base + 0xa8), 0x0c003000);
+                       setbits32((base + 0xa8), 0x0c000000);
 
                        /*
-                        * IMMR + 0x14AC[20:27] = 10101010
-                        * (data delay for both UCC's)
+                        * UCC2 option 2: write 0b11 to bits 16:17
+                        * at address IMMRBAR+0x14AC
                         */
-                       clrsetbits_be32((base + 0xac), 0xff0, 0xaa0);
-                       iounmap(base);
-                       of_node_put(np_par);
+                       setbits32((base + 0xac), 0x0000c000);
                }
+               iounmap(base);
+               of_node_put(np_par);
                of_node_put(np);
        }
-#endif                         /* CONFIG_QUICC_ENGINE */
+#endif /* CONFIG_QUICC_ENGINE */
 }
 
 machine_device_initcall(mpc83xx_km, mpc83xx_declare_of_platform_devices);
index f000d81c4e31214f5cf7dd3176419f847fdb0128..159c01e914635d3cc025a502e88767f0d679d286 100644 (file)
@@ -23,6 +23,15 @@ config FSL_85XX_CACHE_SRAM
          cache-sram-size and cache-sram-offset kernel boot
          parameters should be passed when this option is enabled.
 
+config BSC9131_RDB
+       bool "Freescale BSC9131RDB"
+       select DEFAULT_UIMAGE
+       help
+         This option enables support for the Freescale BSC9131RDB board.
+         The BSC9131 is a heterogeneous SoC containing an e500v2 powerpc and a
+         StarCore SC3850 DSP
+         Manufacturer : Freescale Semiconductor, Inc
+
 config MPC8540_ADS
        bool "Freescale MPC8540 ADS"
        select DEFAULT_UIMAGE
@@ -175,12 +184,6 @@ config SBC8548
        help
          This option enables support for the Wind River SBC8548 board
 
-config SBC8560
-       bool "Wind River SBC8560"
-       select DEFAULT_UIMAGE
-       help
-         This option enables support for the Wind River SBC8560 board
-
 config GE_IMP3A
        bool "GE Intelligent Platforms IMP3A"
        select DEFAULT_UIMAGE
@@ -222,18 +225,6 @@ config P3041_DS
        help
          This option enables support for the P3041 DS board
 
-config P3060_QDS
-       bool "Freescale P3060 QDS"
-       select DEFAULT_UIMAGE
-       select PPC_E500MC
-       select PHYS_64BIT
-       select SWIOTLB
-       select GPIO_MPC8XXX
-       select HAS_RAPIDIO
-       select PPC_EPAPR_HV_PIC
-       help
-         This option enables support for the P3060 QDS board
-
 config P4080_DS
        bool "Freescale P4080 DS"
        select DEFAULT_UIMAGE
@@ -263,6 +254,22 @@ config P5020_DS
        help
          This option enables support for the P5020 DS board
 
+config PPC_QEMU_E500
+       bool "QEMU generic e500 platform"
+       depends on EXPERIMENTAL
+       select DEFAULT_UIMAGE
+       help
+         This option enables support for running as a QEMU guest using
+         QEMU's generic e500 machine.  This is not required if you're
+         using a QEMU machine that targets a specific board, such as
+         mpc8544ds.
+
+         Unlike most e500 boards that target a specific CPU, this
+         platform works with any e500-family CPU that QEMU supports.
+         Thus, you'll need to make sure CONFIG_PPC_E500MC is set or
+         unset based on the emulated CPU (or actual host CPU in the case
+         of KVM).
+
 endif # FSL_SOC_BOOKE
 
 config TQM85xx
index 2125d4ca068a983b0bd30b92e9daabb72b04ab82..3dfe81175036bb794dc5f3648b22571d001a7c02 100644 (file)
@@ -5,6 +5,7 @@ obj-$(CONFIG_SMP) += smp.o
 
 obj-y += common.o
 
+obj-$(CONFIG_BSC9131_RDB) += bsc913x_rdb.o
 obj-$(CONFIG_MPC8540_ADS) += mpc85xx_ads.o
 obj-$(CONFIG_MPC8560_ADS) += mpc85xx_ads.o
 obj-$(CONFIG_MPC85xx_CDS) += mpc85xx_cds.o
@@ -17,14 +18,13 @@ obj-$(CONFIG_P1022_DS)    += p1022_ds.o
 obj-$(CONFIG_P1023_RDS)   += p1023_rds.o
 obj-$(CONFIG_P2041_RDB)   += p2041_rdb.o corenet_ds.o
 obj-$(CONFIG_P3041_DS)    += p3041_ds.o corenet_ds.o
-obj-$(CONFIG_P3060_QDS)   += p3060_qds.o corenet_ds.o
 obj-$(CONFIG_P4080_DS)    += p4080_ds.o corenet_ds.o
 obj-$(CONFIG_P5020_DS)    += p5020_ds.o corenet_ds.o
 obj-$(CONFIG_STX_GP3)    += stx_gp3.o
 obj-$(CONFIG_TQM85xx)    += tqm85xx.o
-obj-$(CONFIG_SBC8560)     += sbc8560.o
 obj-$(CONFIG_SBC8548)     += sbc8548.o
 obj-$(CONFIG_SOCRATES)    += socrates.o socrates_fpga_pic.o
 obj-$(CONFIG_KSI8560)    += ksi8560.o
 obj-$(CONFIG_XES_MPC85xx) += xes_mpc85xx.o
 obj-$(CONFIG_GE_IMP3A)   += ge_imp3a.o
+obj-$(CONFIG_PPC_QEMU_E500) += qemu_e500.o
diff --git a/arch/powerpc/platforms/85xx/bsc913x_rdb.c b/arch/powerpc/platforms/85xx/bsc913x_rdb.c
new file mode 100644 (file)
index 0000000..9d57bed
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * BSC913xRDB Board Setup
+ *
+ * Author: Priyanka Jain <Priyanka.Jain@freescale.com>
+ *
+ * Copyright 2011-2012 Freescale Semiconductor Inc.
+ *
+ * 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/of_platform.h>
+#include <linux/pci.h>
+#include <asm/mpic.h>
+#include <sysdev/fsl_soc.h>
+#include <asm/udbg.h>
+
+#include "mpc85xx.h"
+
+void __init bsc913x_rdb_pic_init(void)
+{
+       struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN |
+         MPIC_SINGLE_DEST_CPU,
+         0, 256, " OpenPIC  ");
+
+       if (!mpic)
+               pr_err("bsc913x: Failed to allocate MPIC structure\n");
+       else
+               mpic_init(mpic);
+}
+
+/*
+ * Setup the architecture
+ */
+static void __init bsc913x_rdb_setup_arch(void)
+{
+       if (ppc_md.progress)
+               ppc_md.progress("bsc913x_rdb_setup_arch()", 0);
+
+       pr_info("bsc913x board from Freescale Semiconductor\n");
+}
+
+machine_device_initcall(bsc9131_rdb, mpc85xx_common_publish_devices);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+
+static int __init bsc9131_rdb_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       return of_flat_dt_is_compatible(root, "fsl,bsc9131rdb");
+}
+
+define_machine(bsc9131_rdb) {
+       .name                   = "BSC9131 RDB",
+       .probe                  = bsc9131_rdb_probe,
+       .setup_arch             = bsc913x_rdb_setup_arch,
+       .init_IRQ               = bsc913x_rdb_pic_init,
+       .get_irq                = mpic_get_irq,
+       .restart                = fsl_rstcr_restart,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+};
index dd3617c531d74260e01cbd88640e586a9f9ea2bd..925b02874233fe52dc118eec691a334d3be5fde8 100644 (file)
@@ -77,7 +77,7 @@ void __init corenet_ds_setup_arch(void)
 #endif
 
 #ifdef CONFIG_SWIOTLB
-       if (memblock_end_of_DRAM() > max) {
+       if ((memblock_end_of_DRAM() - 1) > max) {
                ppc_swiotlb_enable = 1;
                set_pci_dma_ops(&swiotlb_dma_ops);
                ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
index 18014629416df50976ccc74e93fcb99cccc6f7ce..b6a728b0a8ca0aae6427e619046633b94a35cd25 100644 (file)
@@ -125,7 +125,7 @@ static void __init ge_imp3a_setup_arch(void)
        mpc85xx_smp_init();
 
 #ifdef CONFIG_SWIOTLB
-       if (memblock_end_of_DRAM() > max) {
+       if ((memblock_end_of_DRAM() - 1) > max) {
                ppc_swiotlb_enable = 1;
                set_pci_dma_ops(&swiotlb_dma_ops);
                ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
index 585bd22b14062b897bc18d0be1244f8e52cc4030..767c7cf18a9c978f7b9b70f700ed5ca496fdfd73 100644 (file)
@@ -75,7 +75,7 @@ static void __init mpc8536_ds_setup_arch(void)
 #endif
 
 #ifdef CONFIG_SWIOTLB
-       if (memblock_end_of_DRAM() > max) {
+       if ((memblock_end_of_DRAM() - 1) > max) {
                ppc_swiotlb_enable = 1;
                set_pci_dma_ops(&swiotlb_dma_ops);
                ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
index 1fd91e9e0ffbc766452a925edd6eb8007b56a422..6d3265fe7718c7ff71785329133013ec1382c979 100644 (file)
@@ -114,71 +114,53 @@ void __init mpc85xx_ds_pic_init(void)
 }
 
 #ifdef CONFIG_PCI
-static int primary_phb_addr;
 extern int uli_exclude_device(struct pci_controller *hose,
                                u_char bus, u_char devfn);
 
+static struct device_node *pci_with_uli;
+
 static int mpc85xx_exclude_device(struct pci_controller *hose,
                                   u_char bus, u_char devfn)
 {
-       struct device_node* node;
-       struct resource rsrc;
-
-       node = hose->dn;
-       of_address_to_resource(node, 0, &rsrc);
-
-       if ((rsrc.start & 0xfffff) == primary_phb_addr) {
+       if (hose->dn == pci_with_uli)
                return uli_exclude_device(hose, bus, devfn);
-       }
 
        return PCIBIOS_SUCCESSFUL;
 }
 #endif /* CONFIG_PCI */
 
-/*
- * Setup the architecture
- */
-static void __init mpc85xx_ds_setup_arch(void)
+static void __init mpc85xx_ds_pci_init(void)
 {
 #ifdef CONFIG_PCI
-       struct device_node *np;
-       struct pci_controller *hose;
-#endif
-       dma_addr_t max = 0xffffffff;
+       struct device_node *node;
 
-       if (ppc_md.progress)
-               ppc_md.progress("mpc85xx_ds_setup_arch()", 0);
+       fsl_pci_init();
 
-#ifdef CONFIG_PCI
-       for_each_node_by_type(np, "pci") {
-               if (of_device_is_compatible(np, "fsl,mpc8540-pci") ||
-                   of_device_is_compatible(np, "fsl,mpc8548-pcie") ||
-                   of_device_is_compatible(np, "fsl,p2020-pcie")) {
-                       struct resource rsrc;
-                       of_address_to_resource(np, 0, &rsrc);
-                       if ((rsrc.start & 0xfffff) == primary_phb_addr)
-                               fsl_add_bridge(np, 1);
-                       else
-                               fsl_add_bridge(np, 0);
-
-                       hose = pci_find_hose_for_OF_device(np);
-                       max = min(max, hose->dma_window_base_cur +
-                                       hose->dma_window_size);
+       /* See if we have a ULI under the primary */
+
+       node = of_find_node_by_name(NULL, "uli1575");
+       while ((pci_with_uli = of_get_parent(node))) {
+               of_node_put(node);
+               node = pci_with_uli;
+
+               if (pci_with_uli == fsl_pci_primary) {
+                       ppc_md.pci_exclude_device = mpc85xx_exclude_device;
+                       break;
                }
        }
-
-       ppc_md.pci_exclude_device = mpc85xx_exclude_device;
 #endif
+}
 
-       mpc85xx_smp_init();
+/*
+ * Setup the architecture
+ */
+static void __init mpc85xx_ds_setup_arch(void)
+{
+       if (ppc_md.progress)
+               ppc_md.progress("mpc85xx_ds_setup_arch()", 0);
 
-#ifdef CONFIG_SWIOTLB
-       if (memblock_end_of_DRAM() > max) {
-               ppc_swiotlb_enable = 1;
-               set_pci_dma_ops(&swiotlb_dma_ops);
-               ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
-       }
-#endif
+       mpc85xx_ds_pci_init();
+       mpc85xx_smp_init();
 
        printk("MPC85xx DS board from Freescale Semiconductor\n");
 }
@@ -190,14 +172,7 @@ static int __init mpc8544_ds_probe(void)
 {
        unsigned long root = of_get_flat_dt_root();
 
-       if (of_flat_dt_is_compatible(root, "MPC8544DS")) {
-#ifdef CONFIG_PCI
-               primary_phb_addr = 0xb000;
-#endif
-               return 1;
-       }
-
-       return 0;
+       return !!of_flat_dt_is_compatible(root, "MPC8544DS");
 }
 
 machine_device_initcall(mpc8544_ds, mpc85xx_common_publish_devices);
@@ -215,14 +190,7 @@ static int __init mpc8572_ds_probe(void)
 {
        unsigned long root = of_get_flat_dt_root();
 
-       if (of_flat_dt_is_compatible(root, "fsl,MPC8572DS")) {
-#ifdef CONFIG_PCI
-               primary_phb_addr = 0x8000;
-#endif
-               return 1;
-       }
-
-       return 0;
+       return !!of_flat_dt_is_compatible(root, "fsl,MPC8572DS");
 }
 
 /*
@@ -232,14 +200,7 @@ static int __init p2020_ds_probe(void)
 {
        unsigned long root = of_get_flat_dt_root();
 
-       if (of_flat_dt_is_compatible(root, "fsl,P2020DS")) {
-#ifdef CONFIG_PCI
-               primary_phb_addr = 0x9000;
-#endif
-               return 1;
-       }
-
-       return 0;
+       return !!of_flat_dt_is_compatible(root, "fsl,P2020DS");
 }
 
 define_machine(mpc8544_ds) {
index d208ebccb91cc5f5db92bee1cf47e82e0e0c4b31..8e4b094c553b49d142bceba1f29cf48c0805ed18 100644 (file)
@@ -359,7 +359,7 @@ static void __init mpc85xx_mds_setup_arch(void)
        mpc85xx_mds_qe_init();
 
 #ifdef CONFIG_SWIOTLB
-       if (memblock_end_of_DRAM() > max) {
+       if ((memblock_end_of_DRAM() - 1) > max) {
                ppc_swiotlb_enable = 1;
                set_pci_dma_ops(&swiotlb_dma_ops);
                ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
index 313fce4f55747eb9d0fe8639a145ef7489c2e52e..1910fdcb75b2479558564fd08cb4031f553d34f2 100644 (file)
@@ -169,6 +169,7 @@ machine_device_initcall(p1020_rdb_pc, mpc85xx_common_publish_devices);
 machine_device_initcall(p1020_utm_pc, mpc85xx_common_publish_devices);
 machine_device_initcall(p1021_rdb_pc, mpc85xx_common_publish_devices);
 machine_device_initcall(p1025_rdb, mpc85xx_common_publish_devices);
+machine_device_initcall(p1024_rdb, mpc85xx_common_publish_devices);
 
 /*
  * Called very early, device-tree isn't unflattened
@@ -237,6 +238,13 @@ static int __init p1020_utm_pc_probe(void)
        return of_flat_dt_is_compatible(root, "fsl,P1020UTM-PC");
 }
 
+static int __init p1024_rdb_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       return of_flat_dt_is_compatible(root, "fsl,P1024RDB");
+}
+
 define_machine(p2020_rdb) {
        .name                   = "P2020 RDB",
        .probe                  = p2020_rdb_probe,
@@ -348,3 +356,17 @@ define_machine(p1020_rdb_pc) {
        .calibrate_decr         = generic_calibrate_decr,
        .progress               = udbg_progress,
 };
+
+define_machine(p1024_rdb) {
+       .name                   = "P1024 RDB",
+       .probe                  = p1024_rdb_probe,
+       .setup_arch             = mpc85xx_rdb_setup_arch,
+       .init_IRQ               = mpc85xx_rdb_pic_init,
+#ifdef CONFIG_PCI
+       .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
+#endif
+       .get_irq                = mpic_get_irq,
+       .restart                = fsl_rstcr_restart,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+};
index f700c81a1321ca2de222b6f1561408e454094204..89ee02c54561d1802fd72a49afaedd88fc9e2368 100644 (file)
@@ -27,6 +27,7 @@
 #include <sysdev/fsl_pci.h>
 #include <asm/udbg.h>
 #include <asm/fsl_guts.h>
+#include <asm/fsl_lbc.h>
 #include "smp.h"
 
 #include "mpc85xx.h"
@@ -142,17 +143,73 @@ static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port,
 {
 }
 
+struct fsl_law {
+       u32     lawbar;
+       u32     reserved1;
+       u32     lawar;
+       u32     reserved[5];
+};
+
+#define LAWBAR_MASK    0x00F00000
+#define LAWBAR_SHIFT   12
+
+#define LAWAR_EN       0x80000000
+#define LAWAR_TGT_MASK 0x01F00000
+#define LAW_TRGT_IF_LBC        (0x04 << 20)
+
+#define LAWAR_MASK     (LAWAR_EN | LAWAR_TGT_MASK)
+#define LAWAR_MATCH    (LAWAR_EN | LAW_TRGT_IF_LBC)
+
+#define BR_BA          0xFFFF8000
+
+/*
+ * Map a BRx value to a physical address
+ *
+ * The localbus BRx registers only store the lower 32 bits of the address.  To
+ * obtain the upper four bits, we need to scan the LAW table.  The entry which
+ * maps to the localbus will contain the upper four bits.
+ */
+static phys_addr_t lbc_br_to_phys(const void *ecm, unsigned int count, u32 br)
+{
+#ifndef CONFIG_PHYS_64BIT
+       /*
+        * If we only have 32-bit addressing, then the BRx address *is* the
+        * physical address.
+        */
+       return br & BR_BA;
+#else
+       const struct fsl_law *law = ecm + 0xc08;
+       unsigned int i;
+
+       for (i = 0; i < count; i++) {
+               u64 lawbar = in_be32(&law[i].lawbar);
+               u32 lawar = in_be32(&law[i].lawar);
+
+               if ((lawar & LAWAR_MASK) == LAWAR_MATCH)
+                       /* Extract the upper four bits */
+                       return (br & BR_BA) | ((lawbar & LAWBAR_MASK) << 12);
+       }
+
+       return 0;
+#endif
+}
+
 /**
  * p1022ds_set_monitor_port: switch the output to a different monitor port
- *
  */
 static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
 {
        struct device_node *guts_node;
-       struct device_node *indirect_node = NULL;
+       struct device_node *lbc_node = NULL;
+       struct device_node *law_node = NULL;
        struct ccsr_guts __iomem *guts;
+       struct fsl_lbc_regs *lbc = NULL;
+       void *ecm = NULL;
        u8 __iomem *lbc_lcs0_ba = NULL;
        u8 __iomem *lbc_lcs1_ba = NULL;
+       phys_addr_t cs0_addr, cs1_addr;
+       const __be32 *iprop;
+       unsigned int num_laws;
        u8 b;
 
        /* Map the global utilities registers. */
@@ -168,24 +225,42 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
                goto exit;
        }
 
-       indirect_node = of_find_compatible_node(NULL, NULL,
-                                            "fsl,p1022ds-indirect-pixis");
-       if (!indirect_node) {
-               pr_err("p1022ds: missing pixis indirect mode node\n");
+       lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc");
+       if (!lbc_node) {
+               pr_err("p1022ds: missing localbus node\n");
+               goto exit;
+       }
+
+       lbc = of_iomap(lbc_node, 0);
+       if (!lbc) {
+               pr_err("p1022ds: could not map localbus node\n");
+               goto exit;
+       }
+
+       law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law");
+       if (!law_node) {
+               pr_err("p1022ds: missing local access window node\n");
                goto exit;
        }
 
-       lbc_lcs0_ba = of_iomap(indirect_node, 0);
-       if (!lbc_lcs0_ba) {
-               pr_err("p1022ds: could not map localbus chip select 0\n");
+       ecm = of_iomap(law_node, 0);
+       if (!ecm) {
+               pr_err("p1022ds: could not map local access window node\n");
                goto exit;
        }
 
-       lbc_lcs1_ba = of_iomap(indirect_node, 1);
-       if (!lbc_lcs1_ba) {
-               pr_err("p1022ds: could not map localbus chip select 1\n");
+       iprop = of_get_property(law_node, "fsl,num-laws", 0);
+       if (!iprop) {
+               pr_err("p1022ds: LAW node is missing fsl,num-laws property\n");
                goto exit;
        }
+       num_laws = be32_to_cpup(iprop);
+
+       cs0_addr = lbc_br_to_phys(ecm, num_laws, in_be32(&lbc->bank[0].br));
+       cs1_addr = lbc_br_to_phys(ecm, num_laws, in_be32(&lbc->bank[1].br));
+
+       lbc_lcs0_ba = ioremap(cs0_addr, 1);
+       lbc_lcs1_ba = ioremap(cs1_addr, 1);
 
        /* Make sure we're in indirect mode first. */
        if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) !=
@@ -254,10 +329,15 @@ exit:
                iounmap(lbc_lcs1_ba);
        if (lbc_lcs0_ba)
                iounmap(lbc_lcs0_ba);
+       if (lbc)
+               iounmap(lbc);
+       if (ecm)
+               iounmap(ecm);
        if (guts)
                iounmap(guts);
 
-       of_node_put(indirect_node);
+       of_node_put(law_node);
+       of_node_put(lbc_node);
        of_node_put(guts_node);
 }
 
@@ -348,13 +428,7 @@ void __init p1022_ds_pic_init(void)
  */
 static void __init disable_one_node(struct device_node *np, struct property *new)
 {
-       struct property *old;
-
-       old = of_find_property(np, new->name, NULL);
-       if (old)
-               prom_update_property(np, new, old);
-       else
-               prom_add_property(np, new);
+       prom_update_property(np, new);
 }
 
 /* TRUE if there is a "video=fslfb" command-line parameter. */
@@ -450,7 +524,7 @@ static void __init p1022_ds_setup_arch(void)
        mpc85xx_smp_init();
 
 #ifdef CONFIG_SWIOTLB
-       if (memblock_end_of_DRAM() > max) {
+       if ((memblock_end_of_DRAM() - 1) > max) {
                ppc_swiotlb_enable = 1;
                set_pci_dma_ops(&swiotlb_dma_ops);
                ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
diff --git a/arch/powerpc/platforms/85xx/p3060_qds.c b/arch/powerpc/platforms/85xx/p3060_qds.c
deleted file mode 100644 (file)
index 081cf4a..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * P3060 QDS Setup
- *
- * Copyright 2011 Freescale Semiconductor Inc.
- *
- * 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/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/phy.h>
-#include <asm/machdep.h>
-#include <asm/udbg.h>
-#include <asm/mpic.h>
-#include <linux/of_platform.h>
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
-#include <asm/ehv_pic.h>
-#include "corenet_ds.h"
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init p3060_qds_probe(void)
-{
-       unsigned long root = of_get_flat_dt_root();
-#ifdef CONFIG_SMP
-       extern struct smp_ops_t smp_85xx_ops;
-#endif
-
-       if (of_flat_dt_is_compatible(root, "fsl,P3060QDS"))
-               return 1;
-
-       /* Check if we're running under the Freescale hypervisor */
-       if (of_flat_dt_is_compatible(root, "fsl,P3060QDS-hv")) {
-               ppc_md.init_IRQ = ehv_pic_init;
-               ppc_md.get_irq = ehv_pic_get_irq;
-               ppc_md.restart = fsl_hv_restart;
-               ppc_md.power_off = fsl_hv_halt;
-               ppc_md.halt = fsl_hv_halt;
-#ifdef CONFIG_SMP
-               /*
-                * Disable the timebase sync operations because we can't write
-                * to the timebase registers under the hypervisor.
-                */
-               smp_85xx_ops.give_timebase = NULL;
-               smp_85xx_ops.take_timebase = NULL;
-#endif
-               return 1;
-       }
-
-       return 0;
-}
-
-define_machine(p3060_qds) {
-       .name                   = "P3060 QDS",
-       .probe                  = p3060_qds_probe,
-       .setup_arch             = corenet_ds_setup_arch,
-       .init_IRQ               = corenet_ds_pic_init,
-#ifdef CONFIG_PCI
-       .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
-#endif
-       .get_irq                = mpic_get_coreint_irq,
-       .restart                = fsl_rstcr_restart,
-       .calibrate_decr         = generic_calibrate_decr,
-       .progress               = udbg_progress,
-       .power_save             = e500_idle,
-};
-
-machine_device_initcall(p3060_qds, corenet_ds_publish_devices);
-
-#ifdef CONFIG_SWIOTLB
-machine_arch_initcall(p3060_qds, swiotlb_setup_bus_notifier);
-#endif
diff --git a/arch/powerpc/platforms/85xx/qemu_e500.c b/arch/powerpc/platforms/85xx/qemu_e500.c
new file mode 100644 (file)
index 0000000..95a2e53
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Paravirt target for a generic QEMU e500 machine
+ *
+ * This is intended to be a flexible device-tree-driven platform, not fixed
+ * to a particular piece of hardware or a particular spec of virtual hardware,
+ * beyond the assumption of an e500-family CPU.  Some things are still hardcoded
+ * here, such as MPIC, but this is a limitation of the current code rather than
+ * an interface contract with QEMU.
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * 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/kernel.h>
+#include <linux/of_fdt.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/udbg.h>
+#include <asm/mpic.h>
+#include <sysdev/fsl_soc.h>
+#include <sysdev/fsl_pci.h>
+#include "smp.h"
+#include "mpc85xx.h"
+
+void __init qemu_e500_pic_init(void)
+{
+       struct mpic *mpic;
+
+       mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN | MPIC_SINGLE_DEST_CPU,
+                       0, 256, " OpenPIC  ");
+
+       BUG_ON(mpic == NULL);
+       mpic_init(mpic);
+}
+
+static void __init qemu_e500_setup_arch(void)
+{
+       ppc_md.progress("qemu_e500_setup_arch()", 0);
+
+       fsl_pci_init();
+       mpc85xx_smp_init();
+}
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init qemu_e500_probe(void)
+{
+       unsigned long root = of_get_flat_dt_root();
+
+       return !!of_flat_dt_is_compatible(root, "fsl,qemu-e500");
+}
+
+machine_device_initcall(qemu_e500, mpc85xx_common_publish_devices);
+
+define_machine(qemu_e500) {
+       .name                   = "QEMU e500",
+       .probe                  = qemu_e500_probe,
+       .setup_arch             = qemu_e500_setup_arch,
+       .init_IRQ               = qemu_e500_pic_init,
+#ifdef CONFIG_PCI
+       .pcibios_fixup_bus      = fsl_pcibios_fixup_bus,
+#endif
+       .get_irq                = mpic_get_irq,
+       .restart                = fsl_rstcr_restart,
+       .calibrate_decr         = generic_calibrate_decr,
+       .progress               = udbg_progress,
+};
diff --git a/arch/powerpc/platforms/85xx/sbc8560.c b/arch/powerpc/platforms/85xx/sbc8560.c
deleted file mode 100644 (file)
index b1be632..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * Wind River SBC8560 setup and early boot code.
- *
- * Copyright 2007 Wind River Systems Inc.
- *
- * By Paul Gortmaker (see MAINTAINERS for contact information)
- *
- * Based largely on the MPC8560ADS support - Copyright 2005 Freescale Inc.
- *
- * 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/stddef.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/kdev_t.h>
-#include <linux/delay.h>
-#include <linux/seq_file.h>
-#include <linux/of_platform.h>
-
-#include <asm/time.h>
-#include <asm/machdep.h>
-#include <asm/pci-bridge.h>
-#include <asm/mpic.h>
-#include <mm/mmu_decl.h>
-#include <asm/udbg.h>
-
-#include <sysdev/fsl_soc.h>
-#include <sysdev/fsl_pci.h>
-
-#include "mpc85xx.h"
-
-#ifdef CONFIG_CPM2
-#include <asm/cpm2.h>
-#include <sysdev/cpm2_pic.h>
-#endif
-
-static void __init sbc8560_pic_init(void)
-{
-       struct mpic *mpic = mpic_alloc(NULL, 0, MPIC_BIG_ENDIAN,
-                       0, 256, " OpenPIC  ");
-       BUG_ON(mpic == NULL);
-       mpic_init(mpic);
-
-       mpc85xx_cpm2_pic_init();
-}
-
-/*
- * Setup the architecture
- */
-#ifdef CONFIG_CPM2
-struct cpm_pin {
-       int port, pin, flags;
-};
-
-static const struct cpm_pin sbc8560_pins[] = {
-       /* SCC1 */
-       {3, 29, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-       {3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
-       {3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-
-       /* SCC2 */
-       {3, 26, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-       {3, 27, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-       {3, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-
-       /* FCC2 */
-       {1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-       {1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-       {1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-       {1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-       {1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
-       {1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-       {2, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK14 */
-       {2, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY}, /* CLK13 */
-
-       /* FCC3 */
-       {1, 4, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-       {1, 5, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-       {1, 6, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-       {1, 7, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-       {1, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 9, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 10, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 11, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 12, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 13, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 14, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-       {1, 15, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-       {1, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {1, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-       {2, 16, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* CLK16 */
-       {2, 17, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* CLK15 */
-};
-
-static void __init init_ioports(void)
-{
-       int i;
-
-       for (i = 0; i < ARRAY_SIZE(sbc8560_pins); i++) {
-               const struct cpm_pin *pin = &sbc8560_pins[i];
-               cpm2_set_pin(pin->port, pin->pin, pin->flags);
-       }
-
-       cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_RX);
-       cpm2_clk_setup(CPM_CLK_SCC1, CPM_BRG1, CPM_CLK_TX);
-       cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_RX);
-       cpm2_clk_setup(CPM_CLK_SCC2, CPM_BRG2, CPM_CLK_TX);
-       cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK13, CPM_CLK_RX);
-       cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK14, CPM_CLK_TX);
-       cpm2_clk_setup(CPM_CLK_FCC3, CPM_CLK15, CPM_CLK_RX);
-       cpm2_clk_setup(CPM_CLK_FCC3, CPM_CLK16, CPM_CLK_TX);
-}
-#endif
-
-static void __init sbc8560_setup_arch(void)
-{
-#ifdef CONFIG_PCI
-       struct device_node *np;
-#endif
-
-       if (ppc_md.progress)
-               ppc_md.progress("sbc8560_setup_arch()", 0);
-
-#ifdef CONFIG_CPM2
-       cpm2_reset();
-       init_ioports();
-#endif
-
-#ifdef CONFIG_PCI
-       for_each_compatible_node(np, "pci", "fsl,mpc8540-pci")
-               fsl_add_bridge(np, 1);
-#endif
-}
-
-static void sbc8560_show_cpuinfo(struct seq_file *m)
-{
-       uint pvid, svid, phid1;
-
-       pvid = mfspr(SPRN_PVR);
-       svid = mfspr(SPRN_SVR);
-
-       seq_printf(m, "Vendor\t\t: Wind River\n");
-       seq_printf(m, "PVR\t\t: 0x%x\n", pvid);
-       seq_printf(m, "SVR\t\t: 0x%x\n", svid);
-
-       /* Display cpu Pll setting */
-       phid1 = mfspr(SPRN_HID1);
-       seq_printf(m, "PLL setting\t: 0x%x\n", ((phid1 >> 24) & 0x3f));
-}
-
-machine_device_initcall(sbc8560, mpc85xx_common_publish_devices);
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init sbc8560_probe(void)
-{
-        unsigned long root = of_get_flat_dt_root();
-
-        return of_flat_dt_is_compatible(root, "SBC8560");
-}
-
-#ifdef CONFIG_RTC_DRV_M48T59
-static int __init sbc8560_rtc_init(void)
-{
-       struct device_node *np;
-       struct resource res;
-       struct platform_device *rtc_dev;
-
-       np = of_find_compatible_node(NULL, NULL, "m48t59");
-       if (np == NULL) {
-               printk("No RTC in DTB. Has it been eaten by wild dogs?\n");
-               return -ENODEV;
-       }
-
-       of_address_to_resource(np, 0, &res);
-       of_node_put(np);
-
-       printk("Found RTC (m48t59) at i/o 0x%x\n", res.start);
-
-       rtc_dev = platform_device_register_simple("rtc-m48t59", 0, &res, 1);
-
-       if (IS_ERR(rtc_dev)) {
-               printk("Registering sbc8560 RTC device failed\n");
-               return PTR_ERR(rtc_dev);
-       }
-
-       return 0;
-}
-
-arch_initcall(sbc8560_rtc_init);
-
-#endif /* M48T59 */
-
-static __u8 __iomem *brstcr;
-
-static int __init sbc8560_bdrstcr_init(void)
-{
-       struct device_node *np;
-       struct resource res;
-
-       np = of_find_compatible_node(NULL, NULL, "wrs,sbc8560-brstcr");
-       if (np == NULL) {
-               printk(KERN_WARNING "sbc8560: No board specific RSTCR in DTB.\n");
-               return -ENODEV;
-       }
-
-       of_address_to_resource(np, 0, &res);
-
-       printk(KERN_INFO "sbc8560: Found BRSTCR at %pR\n", &res);
-
-       brstcr = ioremap(res.start, resource_size(&res));
-       if(!brstcr)
-               printk(KERN_WARNING "sbc8560: ioremap of brstcr failed.\n");
-
-       of_node_put(np);
-
-       return 0;
-}
-
-arch_initcall(sbc8560_bdrstcr_init);
-
-void sbc8560_rstcr_restart(char * cmd)
-{
-       local_irq_disable();
-       if(brstcr)
-               clrbits8(brstcr, 0x80);
-
-       while(1);
-}
-
-define_machine(sbc8560) {
-       .name                   = "SBC8560",
-       .probe                  = sbc8560_probe,
-       .setup_arch             = sbc8560_setup_arch,
-       .init_IRQ               = sbc8560_pic_init,
-       .show_cpuinfo           = sbc8560_show_cpuinfo,
-       .get_irq                = mpic_get_irq,
-       .restart                = sbc8560_rstcr_restart,
-       .calibrate_decr         = generic_calibrate_decr,
-       .progress               = udbg_progress,
-};
index 3755e61d7ecfac489a8ca6837a93f49c54132782..817245bc02195a37917b5dd341d7790ba5a50737 100644 (file)
@@ -102,7 +102,7 @@ mpc86xx_hpcn_setup_arch(void)
 #endif
 
 #ifdef CONFIG_SWIOTLB
-       if (memblock_end_of_DRAM() > max) {
+       if ((memblock_end_of_DRAM() - 1) > max) {
                ppc_swiotlb_enable = 1;
                set_pci_dma_ops(&swiotlb_dma_ops);
                ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
index 61c9550819a255395aff1403d348e19dc4a538e3..30fd01de6bed5d93cb83fb380787c2a3586ccdd6 100644 (file)
@@ -159,6 +159,10 @@ config PPC_E500MC
        bool "e500mc Support"
        select PPC_FPU
        depends on E500
+       help
+         This must be enabled for running on e500mc (and derivatives
+         such as e5500/e6500), and must be disabled for running on
+         e500v1 or e500v2.
 
 config PPC_FPU
        bool
index 74c8174489483bfbc582482ff5312aef4aee8eba..96c801907126df35ca99dd6abba2ec3a0b222052 100644 (file)
@@ -22,8 +22,6 @@
 
 #include <asm/ppc_asm.h>
 
-#define        STK_PARM(i)     (48 + ((i)-3)*8)
-
 /* Not implemented on Beat, now */
 #define        HCALL_INST_PRECALL
 #define        HCALL_INST_POSTCALL
@@ -74,7 +72,7 @@ _GLOBAL(beat_hcall_norets8)
        mr      r6,r7
        mr      r7,r8
        mr      r8,r9
-       ld      r10,STK_PARM(r10)(r1)
+       ld      r10,STK_PARAM(R10)(r1)
 
        HVSC                            /* invoke the hypervisor */
 
@@ -94,7 +92,7 @@ _GLOBAL(beat_hcall1)
 
        HCALL_INST_PRECALL
 
-       std     r4,STK_PARM(r4)(r1)     /* save ret buffer */
+       std     r4,STK_PARAM(R4)(r1)    /* save ret buffer */
 
        mr      r11,r3
        mr      r3,r5
@@ -108,7 +106,7 @@ _GLOBAL(beat_hcall1)
 
        HCALL_INST_POSTCALL
 
-       ld      r12,STK_PARM(r4)(r1)
+       ld      r12,STK_PARAM(R4)(r1)
        std     r4,  0(r12)
 
        lwz     r0,8(r1)
@@ -125,7 +123,7 @@ _GLOBAL(beat_hcall2)
 
        HCALL_INST_PRECALL
 
-       std     r4,STK_PARM(r4)(r1)     /* save ret buffer */
+       std     r4,STK_PARAM(R4)(r1)    /* save ret buffer */
 
        mr      r11,r3
        mr      r3,r5
@@ -139,7 +137,7 @@ _GLOBAL(beat_hcall2)
 
        HCALL_INST_POSTCALL
 
-       ld      r12,STK_PARM(r4)(r1)
+       ld      r12,STK_PARAM(R4)(r1)
        std     r4,  0(r12)
        std     r5,  8(r12)
 
@@ -157,7 +155,7 @@ _GLOBAL(beat_hcall3)
 
        HCALL_INST_PRECALL
 
-       std     r4,STK_PARM(r4)(r1)     /* save ret buffer */
+       std     r4,STK_PARAM(R4)(r1)    /* save ret buffer */
 
        mr      r11,r3
        mr      r3,r5
@@ -171,7 +169,7 @@ _GLOBAL(beat_hcall3)
 
        HCALL_INST_POSTCALL
 
-       ld      r12,STK_PARM(r4)(r1)
+       ld      r12,STK_PARAM(R4)(r1)
        std     r4,  0(r12)
        std     r5,  8(r12)
        std     r6, 16(r12)
@@ -190,7 +188,7 @@ _GLOBAL(beat_hcall4)
 
        HCALL_INST_PRECALL
 
-       std     r4,STK_PARM(r4)(r1)     /* save ret buffer */
+       std     r4,STK_PARAM(R4)(r1)    /* save ret buffer */
 
        mr      r11,r3
        mr      r3,r5
@@ -204,7 +202,7 @@ _GLOBAL(beat_hcall4)
 
        HCALL_INST_POSTCALL
 
-       ld      r12,STK_PARM(r4)(r1)
+       ld      r12,STK_PARAM(R4)(r1)
        std     r4,  0(r12)
        std     r5,  8(r12)
        std     r6, 16(r12)
@@ -224,7 +222,7 @@ _GLOBAL(beat_hcall5)
 
        HCALL_INST_PRECALL
 
-       std     r4,STK_PARM(r4)(r1)     /* save ret buffer */
+       std     r4,STK_PARAM(R4)(r1)    /* save ret buffer */
 
        mr      r11,r3
        mr      r3,r5
@@ -238,7 +236,7 @@ _GLOBAL(beat_hcall5)
 
        HCALL_INST_POSTCALL
 
-       ld      r12,STK_PARM(r4)(r1)
+       ld      r12,STK_PARAM(R4)(r1)
        std     r4,  0(r12)
        std     r5,  8(r12)
        std     r6, 16(r12)
@@ -259,7 +257,7 @@ _GLOBAL(beat_hcall6)
 
        HCALL_INST_PRECALL
 
-       std     r4,STK_PARM(r4)(r1)     /* save ret buffer */
+       std     r4,STK_PARAM(R4)(r1)    /* save ret buffer */
 
        mr      r11,r3
        mr      r3,r5
@@ -273,7 +271,7 @@ _GLOBAL(beat_hcall6)
 
        HCALL_INST_POSTCALL
 
-       ld      r12,STK_PARM(r4)(r1)
+       ld      r12,STK_PARAM(R4)(r1)
        std     r4,  0(r12)
        std     r5,  8(r12)
        std     r6, 16(r12)
index b9f509a34c012b672e3b368f8121d9446b52d2ee..c264969c93198bdbcf040683d285a6eea25f465f 100644 (file)
@@ -518,7 +518,6 @@ cell_iommu_setup_window(struct cbe_iommu *iommu, struct device_node *np,
        __set_bit(0, window->table.it_map);
        tce_build_cell(&window->table, window->table.it_offset, 1,
                       (unsigned long)iommu->pad_page, DMA_TO_DEVICE, NULL);
-       window->table.it_hint = window->table.it_blocksize;
 
        return window;
 }
index 66519d263da7fa250499abf9f4d7c288fe8e6432..d544d7816df3229780e4f2c58a1a28355c5c4aae 100644 (file)
@@ -317,28 +317,23 @@ out:
        return ret;
 }
 
-static int spufs_context_open(struct dentry *dentry, struct vfsmount *mnt)
+static int spufs_context_open(struct path *path)
 {
        int ret;
        struct file *filp;
 
        ret = get_unused_fd();
-       if (ret < 0) {
-               dput(dentry);
-               mntput(mnt);
-               goto out;
-       }
+       if (ret < 0)
+               return ret;
 
-       filp = dentry_open(dentry, mnt, O_RDONLY, current_cred());
+       filp = dentry_open(path, O_RDONLY, current_cred());
        if (IS_ERR(filp)) {
                put_unused_fd(ret);
-               ret = PTR_ERR(filp);
-               goto out;
+               return PTR_ERR(filp);
        }
 
        filp->f_op = &spufs_context_fops;
        fd_install(ret, filp);
-out:
        return ret;
 }
 
@@ -453,6 +448,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
        int affinity;
        struct spu_gang *gang;
        struct spu_context *neighbor;
+       struct path path = {.mnt = mnt, .dentry = dentry};
 
        ret = -EPERM;
        if ((flags & SPU_CREATE_NOSCHED) &&
@@ -495,11 +491,7 @@ spufs_create_context(struct inode *inode, struct dentry *dentry,
                        put_spu_context(neighbor);
        }
 
-       /*
-        * get references for dget and mntget, will be released
-        * in error path of *_open().
-        */
-       ret = spufs_context_open(dget(dentry), mntget(mnt));
+       ret = spufs_context_open(&path);
        if (ret < 0) {
                WARN_ON(spufs_rmdir(inode, dentry));
                if (affinity)
@@ -556,28 +548,27 @@ out:
        return ret;
 }
 
-static int spufs_gang_open(struct dentry *dentry, struct vfsmount *mnt)
+static int spufs_gang_open(struct path *path)
 {
        int ret;
        struct file *filp;
 
        ret = get_unused_fd();
-       if (ret < 0) {
-               dput(dentry);
-               mntput(mnt);
-               goto out;
-       }
+       if (ret < 0)
+               return ret;
 
-       filp = dentry_open(dentry, mnt, O_RDONLY, current_cred());
+       /*
+        * get references for dget and mntget, will be released
+        * in error path of *_open().
+        */
+       filp = dentry_open(path, O_RDONLY, current_cred());
        if (IS_ERR(filp)) {
                put_unused_fd(ret);
-               ret = PTR_ERR(filp);
-               goto out;
+               return PTR_ERR(filp);
        }
 
        filp->f_op = &simple_dir_operations;
        fd_install(ret, filp);
-out:
        return ret;
 }
 
@@ -585,17 +576,14 @@ static int spufs_create_gang(struct inode *inode,
                        struct dentry *dentry,
                        struct vfsmount *mnt, umode_t mode)
 {
+       struct path path = {.mnt = mnt, .dentry = dentry};
        int ret;
 
        ret = spufs_mkgang(inode, dentry, mode & S_IRWXUGO);
        if (ret)
                goto out;
 
-       /*
-        * get references for dget and mntget, will be released
-        * in error path of *_open().
-        */
-       ret = spufs_gang_open(dget(dentry), mntget(mnt));
+       ret = spufs_gang_open(&path);
        if (ret < 0) {
                int err = simple_rmdir(inode, dentry);
                WARN_ON(err);
index 77b48b2b930946703387d6f3dd2e811b79c788f6..3cd262897c272c5ee62f577bf4c9cef052f5a8c0 100644 (file)
@@ -14,8 +14,6 @@
 #include <asm/asm-offsets.h>
 #include <asm/opal.h>
 
-#define STK_PARAM(i)   (48 + ((i)-3)*8)
-
 #define H_HAL_TAKEOVER                 0x5124
 #define H_HAL_TAKEOVER_QUERY_MAGIC     -1
 
 _GLOBAL(opal_query_takeover)
        mfcr    r0
        stw     r0,8(r1)
-       std     r3,STK_PARAM(r3)(r1)
-       std     r4,STK_PARAM(r4)(r1)
+       std     r3,STK_PARAM(R3)(r1)
+       std     r4,STK_PARAM(R4)(r1)
        li      r3,H_HAL_TAKEOVER
        li      r4,H_HAL_TAKEOVER_QUERY_MAGIC
        HVSC
-       ld      r10,STK_PARAM(r3)(r1)
+       ld      r10,STK_PARAM(R3)(r1)
        std     r4,0(r10)
-       ld      r10,STK_PARAM(r4)(r1)
+       ld      r10,STK_PARAM(R4)(r1)
        std     r5,0(r10)
        lwz     r0,8(r1)
        mtcrf   0xff,r0
index 4cb375c0f8d173ff545c665971d8054d61fdfc17..fb506317ebb09141716d0d9bfe068fe7f953221d 100644 (file)
@@ -85,8 +85,10 @@ static int eeh_event_handler(void * dummy)
        set_current_state(TASK_INTERRUPTIBLE);  /* Don't add to load average */
        edev = handle_eeh_events(event);
 
-       eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING);
-       pci_dev_put(edev->pdev);
+       if (edev) {
+               eeh_clear_slot(eeh_dev_to_of_node(edev), EEH_MODE_RECOVERING);
+               pci_dev_put(edev->pdev);
+       }
 
        kfree(event);
        mutex_unlock(&eeh_event_mutex);
index 8752f79a6af828fb3333c12b84630b6912a576bc..c33360ec4f4f4d9acf4cade2360358c115c4829f 100644 (file)
@@ -81,7 +81,7 @@ static int pseries_eeh_init(void)
        ibm_get_config_addr_info2       = rtas_token("ibm,get-config-addr-info2");
        ibm_get_config_addr_info        = rtas_token("ibm,get-config-addr-info");
        ibm_configure_pe                = rtas_token("ibm,configure-pe");
-       ibm_configure_bridge            = rtas_token ("ibm,configure-bridge");
+       ibm_configure_bridge            = rtas_token("ibm,configure-bridge");
 
        /* necessary sanity check */
        if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) {
@@ -89,7 +89,7 @@ static int pseries_eeh_init(void)
                        __func__);
                return -EINVAL;
        } else if (ibm_set_slot_reset == RTAS_UNKNOWN_SERVICE) {
-               pr_warning("%s: RTAS service <ibm, set-slot-reset> invalid\n",
+               pr_warning("%s: RTAS service <ibm,set-slot-reset> invalid\n",
                        __func__);
                return -EINVAL;
        } else if (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE &&
index 3ce73d0052b17a2b2e934af3daf33499d0afd4ac..444fe7759e55097236a42534009304baa3cf1693 100644 (file)
@@ -13,8 +13,6 @@
 #include <asm/asm-offsets.h>
 #include <asm/ptrace.h>
        
-#define STK_PARM(i)     (48 + ((i)-3)*8)
-
 #ifdef CONFIG_TRACEPOINTS
 
        .section        ".toc","aw"
@@ -26,7 +24,7 @@ hcall_tracepoint_refcount:
        .section        ".text"
 
 /*
- * precall must preserve all registers.  use unused STK_PARM()
+ * precall must preserve all registers.  use unused STK_PARAM()
  * areas to save snapshots and opcode. We branch around this
  * in early init (eg when populating the MMU hashtable) by using an
  * unconditional cpu feature.
@@ -40,28 +38,28 @@ END_FTR_SECTION(0, 1);                                              \
        cmpdi   r12,0;                                          \
        beq+    1f;                                             \
        mflr    r0;                                             \
-       std     r3,STK_PARM(r3)(r1);                            \
-       std     r4,STK_PARM(r4)(r1);                            \
-       std     r5,STK_PARM(r5)(r1);                            \
-       std     r6,STK_PARM(r6)(r1);                            \
-       std     r7,STK_PARM(r7)(r1);                            \
-       std     r8,STK_PARM(r8)(r1);                            \
-       std     r9,STK_PARM(r9)(r1);                            \
-       std     r10,STK_PARM(r10)(r1);                          \
+       std     r3,STK_PARAM(R3)(r1);                           \
+       std     r4,STK_PARAM(R4)(r1);                           \
+       std     r5,STK_PARAM(R5)(r1);                           \
+       std     r6,STK_PARAM(R6)(r1);                           \
+       std     r7,STK_PARAM(R7)(r1);                           \
+       std     r8,STK_PARAM(R8)(r1);                           \
+       std     r9,STK_PARAM(R9)(r1);                           \
+       std     r10,STK_PARAM(R10)(r1);                         \
        std     r0,16(r1);                                      \
-       addi    r4,r1,STK_PARM(FIRST_REG);                      \
+       addi    r4,r1,STK_PARAM(FIRST_REG);                     \
        stdu    r1,-STACK_FRAME_OVERHEAD(r1);                   \
        bl      .__trace_hcall_entry;                           \
        addi    r1,r1,STACK_FRAME_OVERHEAD;                     \
        ld      r0,16(r1);                                      \
-       ld      r3,STK_PARM(r3)(r1);                            \
-       ld      r4,STK_PARM(r4)(r1);                            \
-       ld      r5,STK_PARM(r5)(r1);                            \
-       ld      r6,STK_PARM(r6)(r1);                            \
-       ld      r7,STK_PARM(r7)(r1);                            \
-       ld      r8,STK_PARM(r8)(r1);                            \
-       ld      r9,STK_PARM(r9)(r1);                            \
-       ld      r10,STK_PARM(r10)(r1);                          \
+       ld      r3,STK_PARAM(R3)(r1);                           \
+       ld      r4,STK_PARAM(R4)(r1);                           \
+       ld      r5,STK_PARAM(R5)(r1);                           \
+       ld      r6,STK_PARAM(R6)(r1);                           \
+       ld      r7,STK_PARAM(R7)(r1);                           \
+       ld      r8,STK_PARAM(R8)(r1);                           \
+       ld      r9,STK_PARAM(R9)(r1);                           \
+       ld      r10,STK_PARAM(R10)(r1);                         \
        mtlr    r0;                                             \
 1:
 
@@ -79,8 +77,8 @@ END_FTR_SECTION(0, 1);                                                \
        cmpdi   r12,0;                                          \
        beq+    1f;                                             \
        mflr    r0;                                             \
-       ld      r6,STK_PARM(r3)(r1);                            \
-       std     r3,STK_PARM(r3)(r1);                            \
+       ld      r6,STK_PARAM(R3)(r1);                           \
+       std     r3,STK_PARAM(R3)(r1);                           \
        mr      r4,r3;                                          \
        mr      r3,r6;                                          \
        std     r0,16(r1);                                      \
@@ -88,7 +86,7 @@ END_FTR_SECTION(0, 1);                                                \
        bl      .__trace_hcall_exit;                            \
        addi    r1,r1,STACK_FRAME_OVERHEAD;                     \
        ld      r0,16(r1);                                      \
-       ld      r3,STK_PARM(r3)(r1);                            \
+       ld      r3,STK_PARAM(R3)(r1);                           \
        mtlr    r0;                                             \
 1:
 
@@ -114,7 +112,7 @@ _GLOBAL(plpar_hcall_norets)
        mfcr    r0
        stw     r0,8(r1)
 
-       HCALL_INST_PRECALL(r4)
+       HCALL_INST_PRECALL(R4)
 
        HVSC                            /* invoke the hypervisor */
 
@@ -130,9 +128,9 @@ _GLOBAL(plpar_hcall)
        mfcr    r0
        stw     r0,8(r1)
 
-       HCALL_INST_PRECALL(r5)
+       HCALL_INST_PRECALL(R5)
 
-       std     r4,STK_PARM(r4)(r1)     /* Save ret buffer */
+       std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
 
        mr      r4,r5
        mr      r5,r6
@@ -143,7 +141,7 @@ _GLOBAL(plpar_hcall)
 
        HVSC                            /* invoke the hypervisor */
 
-       ld      r12,STK_PARM(r4)(r1)
+       ld      r12,STK_PARAM(R4)(r1)
        std     r4,  0(r12)
        std     r5,  8(r12)
        std     r6, 16(r12)
@@ -168,7 +166,7 @@ _GLOBAL(plpar_hcall_raw)
        mfcr    r0
        stw     r0,8(r1)
 
-       std     r4,STK_PARM(r4)(r1)     /* Save ret buffer */
+       std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
 
        mr      r4,r5
        mr      r5,r6
@@ -179,7 +177,7 @@ _GLOBAL(plpar_hcall_raw)
 
        HVSC                            /* invoke the hypervisor */
 
-       ld      r12,STK_PARM(r4)(r1)
+       ld      r12,STK_PARAM(R4)(r1)
        std     r4,  0(r12)
        std     r5,  8(r12)
        std     r6, 16(r12)
@@ -196,9 +194,9 @@ _GLOBAL(plpar_hcall9)
        mfcr    r0
        stw     r0,8(r1)
 
-       HCALL_INST_PRECALL(r5)
+       HCALL_INST_PRECALL(R5)
 
-       std     r4,STK_PARM(r4)(r1)     /* Save ret buffer */
+       std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
 
        mr      r4,r5
        mr      r5,r6
@@ -206,14 +204,14 @@ _GLOBAL(plpar_hcall9)
        mr      r7,r8
        mr      r8,r9
        mr      r9,r10
-       ld      r10,STK_PARM(r11)(r1)    /* put arg7 in R10 */
-       ld      r11,STK_PARM(r12)(r1)    /* put arg8 in R11 */
-       ld      r12,STK_PARM(r13)(r1)    /* put arg9 in R12 */
+       ld      r10,STK_PARAM(R11)(r1)   /* put arg7 in R10 */
+       ld      r11,STK_PARAM(R12)(r1)   /* put arg8 in R11 */
+       ld      r12,STK_PARAM(R13)(r1)    /* put arg9 in R12 */
 
        HVSC                            /* invoke the hypervisor */
 
        mr      r0,r12
-       ld      r12,STK_PARM(r4)(r1)
+       ld      r12,STK_PARAM(R4)(r1)
        std     r4,  0(r12)
        std     r5,  8(r12)
        std     r6, 16(r12)
@@ -238,7 +236,7 @@ _GLOBAL(plpar_hcall9_raw)
        mfcr    r0
        stw     r0,8(r1)
 
-       std     r4,STK_PARM(r4)(r1)     /* Save ret buffer */
+       std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
 
        mr      r4,r5
        mr      r5,r6
@@ -246,14 +244,14 @@ _GLOBAL(plpar_hcall9_raw)
        mr      r7,r8
        mr      r8,r9
        mr      r9,r10
-       ld      r10,STK_PARM(r11)(r1)    /* put arg7 in R10 */
-       ld      r11,STK_PARM(r12)(r1)    /* put arg8 in R11 */
-       ld      r12,STK_PARM(r13)(r1)    /* put arg9 in R12 */
+       ld      r10,STK_PARAM(R11)(r1)   /* put arg7 in R10 */
+       ld      r11,STK_PARAM(R12)(r1)   /* put arg8 in R11 */
+       ld      r12,STK_PARAM(R13)(r1)    /* put arg9 in R12 */
 
        HVSC                            /* invoke the hypervisor */
 
        mr      r0,r12
-       ld      r12,STK_PARM(r4)(r1)
+       ld      r12,STK_PARAM(R4)(r1)
        std     r4,  0(r12)
        std     r5,  8(r12)
        std     r6, 16(r12)
index 2d311c0caf8ef4499a3a54ebdb24f0c4e41c8735..07c09cbbfb19fdf1807dd0c87a5870d9a9a9cf3b 100644 (file)
@@ -192,12 +192,15 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
        long l, limit;
        long tcenum_start = tcenum, npages_start = npages;
        int ret = 0;
+       unsigned long flags;
 
        if (npages == 1) {
                return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
                                           direction, attrs);
        }
 
+       local_irq_save(flags);  /* to protect tcep and the page behind it */
+
        tcep = __get_cpu_var(tce_page);
 
        /* This is safe to do since interrupts are off when we're called
@@ -207,6 +210,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
                tcep = (u64 *)__get_free_page(GFP_ATOMIC);
                /* If allocation fails, fall back to the loop implementation */
                if (!tcep) {
+                       local_irq_restore(flags);
                        return tce_build_pSeriesLP(tbl, tcenum, npages, uaddr,
                                            direction, attrs);
                }
@@ -240,6 +244,8 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum,
                tcenum += limit;
        } while (npages > 0 && !rc);
 
+       local_irq_restore(flags);
+
        if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) {
                ret = (int)rc;
                tce_freemulti_pSeriesLP(tbl, tcenum_start,
@@ -707,6 +713,21 @@ static int __init disable_ddw_setup(char *str)
 
 early_param("disable_ddw", disable_ddw_setup);
 
+static inline void __remove_ddw(struct device_node *np, const u32 *ddw_avail, u64 liobn)
+{
+       int ret;
+
+       ret = rtas_call(ddw_avail[2], 1, 1, NULL, liobn);
+       if (ret)
+               pr_warning("%s: failed to remove DMA window: rtas returned "
+                       "%d to ibm,remove-pe-dma-window(%x) %llx\n",
+                       np->full_name, ret, ddw_avail[2], liobn);
+       else
+               pr_debug("%s: successfully removed DMA window: rtas returned "
+                       "%d to ibm,remove-pe-dma-window(%x) %llx\n",
+                       np->full_name, ret, ddw_avail[2], liobn);
+}
+
 static void remove_ddw(struct device_node *np)
 {
        struct dynamic_dma_window_prop *dwp;
@@ -736,15 +757,7 @@ static void remove_ddw(struct device_node *np)
                pr_debug("%s successfully cleared tces in window.\n",
                         np->full_name);
 
-       ret = rtas_call(ddw_avail[2], 1, 1, NULL, liobn);
-       if (ret)
-               pr_warning("%s: failed to remove direct window: rtas returned "
-                       "%d to ibm,remove-pe-dma-window(%x) %llx\n",
-                       np->full_name, ret, ddw_avail[2], liobn);
-       else
-               pr_debug("%s: successfully removed direct window: rtas returned "
-                       "%d to ibm,remove-pe-dma-window(%x) %llx\n",
-                       np->full_name, ret, ddw_avail[2], liobn);
+       __remove_ddw(np, ddw_avail, liobn);
 
 delprop:
        ret = prom_remove_property(np, win64);
@@ -869,6 +882,35 @@ static int create_ddw(struct pci_dev *dev, const u32 *ddw_avail,
        return ret;
 }
 
+static void restore_default_window(struct pci_dev *dev,
+                               u32 ddw_restore_token, unsigned long liobn)
+{
+       struct eeh_dev *edev;
+       u32 cfg_addr;
+       u64 buid;
+       int ret;
+
+       /*
+        * Get the config address and phb buid of the PE window.
+        * Rely on eeh to retrieve this for us.
+        * Retrieve them from the pci device, not the node with the
+        * dma-window property
+        */
+       edev = pci_dev_to_eeh_dev(dev);
+       cfg_addr = edev->config_addr;
+       if (edev->pe_config_addr)
+               cfg_addr = edev->pe_config_addr;
+       buid = edev->phb->buid;
+
+       do {
+               ret = rtas_call(ddw_restore_token, 3, 1, NULL, cfg_addr,
+                                       BUID_HI(buid), BUID_LO(buid));
+       } while (rtas_busy_delay(ret));
+       dev_info(&dev->dev,
+               "ibm,reset-pe-dma-windows(%x) %x %x %x returned %d\n",
+                ddw_restore_token, cfg_addr, BUID_HI(buid), BUID_LO(buid), ret);
+}
+
 /*
  * If the PE supports dynamic dma windows, and there is space for a table
  * that can map all pages in a linear offset, then setup such a table,
@@ -889,9 +931,13 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
        u64 dma_addr, max_addr;
        struct device_node *dn;
        const u32 *uninitialized_var(ddw_avail);
+       const u32 *uninitialized_var(ddw_extensions);
+       u32 ddw_restore_token = 0;
        struct direct_window *window;
        struct property *win64;
        struct dynamic_dma_window_prop *ddwprop;
+       const void *dma_window = NULL;
+       unsigned long liobn, offset, size;
 
        mutex_lock(&direct_window_init_mutex);
 
@@ -911,7 +957,40 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
        if (!ddw_avail || len < 3 * sizeof(u32))
                goto out_unlock;
 
-       /*
+       /*
+        * the extensions property is only required to exist in certain
+        * levels of firmware and later
+        * the ibm,ddw-extensions property is a list with the first
+        * element containing the number of extensions and each
+        * subsequent entry is a value corresponding to that extension
+        */
+       ddw_extensions = of_get_property(pdn, "ibm,ddw-extensions", &len);
+       if (ddw_extensions) {
+               /*
+                * each new defined extension length should be added to
+                * the top of the switch so the "earlier" entries also
+                * get picked up
+                */
+               switch (ddw_extensions[0]) {
+                       /* ibm,reset-pe-dma-windows */
+                       case 1:
+                               ddw_restore_token = ddw_extensions[1];
+                               break;
+               }
+       }
+
+       /*
+        * Only remove the existing DMA window if we can restore back to
+        * the default state. Removing the existing window maximizes the
+        * resources available to firmware for dynamic window creation.
+        */
+       if (ddw_restore_token) {
+               dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
+               of_parse_dma_window(pdn, dma_window, &liobn, &offset, &size);
+               __remove_ddw(pdn, ddw_avail, liobn);
+       }
+
+       /*
         * Query if there is a second window of size to map the
         * whole partition.  Query returns number of windows, largest
         * block assigned to PE (partition endpoint), and two bitmasks
@@ -920,7 +999,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
        dn = pci_device_to_OF_node(dev);
        ret = query_ddw(dev, ddw_avail, &query);
        if (ret != 0)
-               goto out_unlock;
+               goto out_restore_window;
 
        if (query.windows_available == 0) {
                /*
@@ -929,7 +1008,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
                 * trading in for a larger page size.
                 */
                dev_dbg(&dev->dev, "no free dynamic windows");
-               goto out_unlock;
+               goto out_restore_window;
        }
        if (query.page_size & 4) {
                page_shift = 24; /* 16MB */
@@ -940,7 +1019,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
        } else {
                dev_dbg(&dev->dev, "no supported direct page size in mask %x",
                          query.page_size);
-               goto out_unlock;
+               goto out_restore_window;
        }
        /* verify the window * number of ptes will map the partition */
        /* check largest block * page size > max memory hotplug addr */
@@ -949,14 +1028,14 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
                dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u "
                          "%llu-sized pages\n", max_addr,  query.largest_available_block,
                          1ULL << page_shift);
-               goto out_unlock;
+               goto out_restore_window;
        }
        len = order_base_2(max_addr);
        win64 = kzalloc(sizeof(struct property), GFP_KERNEL);
        if (!win64) {
                dev_info(&dev->dev,
                        "couldn't allocate property for 64bit dma window\n");
-               goto out_unlock;
+               goto out_restore_window;
        }
        win64->name = kstrdup(DIRECT64_PROPNAME, GFP_KERNEL);
        win64->value = ddwprop = kmalloc(sizeof(*ddwprop), GFP_KERNEL);
@@ -1018,6 +1097,10 @@ out_free_prop:
        kfree(win64->value);
        kfree(win64);
 
+out_restore_window:
+       if (ddw_restore_token)
+               restore_default_window(dev, ddw_restore_token, liobn);
+
 out_unlock:
        mutex_unlock(&direct_window_init_mutex);
        return dma_addr;
index 029a562af3738070d5d612dbad13c3819f970642..dd30b12edfe4c5d8166c6cf1ca67a1aaddca1711 100644 (file)
@@ -67,7 +67,6 @@ static int update_dt_property(struct device_node *dn, struct property **prop,
                              const char *name, u32 vd, char *value)
 {
        struct property *new_prop = *prop;
-       struct property *old_prop;
        int more = 0;
 
        /* A negative 'vd' value indicates that only part of the new property
@@ -117,12 +116,7 @@ static int update_dt_property(struct device_node *dn, struct property **prop,
        }
 
        if (!more) {
-               old_prop = of_find_property(dn, new_prop->name, NULL);
-               if (old_prop)
-                       prom_update_property(dn, new_prop, old_prop);
-               else
-                       prom_add_property(dn, new_prop);
-
+               prom_update_property(dn, new_prop);
                new_prop = NULL;
        }
 
index c71be66bd5dc2ff3bc6e0b3309ad969859cb4b84..455760b1fe6e1fde723ec96a4afeb24b75af6ca8 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/moduleparam.h>
 #include <linux/cpuidle.h>
 #include <linux/cpu.h>
+#include <linux/notifier.h>
 
 #include <asm/paca.h>
 #include <asm/reg.h>
@@ -189,17 +190,40 @@ static struct cpuidle_state shared_states[MAX_IDLE_STATE_COUNT] = {
                .enter = &shared_cede_loop },
 };
 
-int pseries_notify_cpuidle_add_cpu(int cpu)
+static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n,
+                       unsigned long action, void *hcpu)
 {
+       int hotcpu = (unsigned long)hcpu;
        struct cpuidle_device *dev =
-                       per_cpu_ptr(pseries_cpuidle_devices, cpu);
+                       per_cpu_ptr(pseries_cpuidle_devices, hotcpu);
+
        if (dev && cpuidle_get_driver()) {
-               cpuidle_disable_device(dev);
-               cpuidle_enable_device(dev);
+               switch (action) {
+               case CPU_ONLINE:
+               case CPU_ONLINE_FROZEN:
+                       cpuidle_pause_and_lock();
+                       cpuidle_enable_device(dev);
+                       cpuidle_resume_and_unlock();
+                       break;
+
+               case CPU_DEAD:
+               case CPU_DEAD_FROZEN:
+                       cpuidle_pause_and_lock();
+                       cpuidle_disable_device(dev);
+                       cpuidle_resume_and_unlock();
+                       break;
+
+               default:
+                       return NOTIFY_DONE;
+               }
        }
-       return 0;
+       return NOTIFY_OK;
 }
 
+static struct notifier_block setup_hotplug_notifier = {
+       .notifier_call = pseries_cpuidle_add_cpu_notifier,
+};
+
 /*
  * pseries_cpuidle_driver_init()
  */
@@ -324,6 +348,7 @@ static int __init pseries_processor_idle_init(void)
                return retval;
        }
 
+       register_cpu_notifier(&setup_hotplug_notifier);
        printk(KERN_DEBUG "pseries_idle_driver registered\n");
 
        return 0;
@@ -332,6 +357,7 @@ static int __init pseries_processor_idle_init(void)
 static void __exit pseries_processor_idle_exit(void)
 {
 
+       unregister_cpu_notifier(&setup_hotplug_notifier);
        pseries_idle_devices_uninit();
        cpuidle_unregister_driver(&pseries_idle_driver);
 
index 7b3bf76ef8344f0d36c5d99fa221a175aec36bba..39f71fba9b38eed2e34d717d2bd2e4ea1ca38925 100644 (file)
@@ -432,7 +432,7 @@ static int do_update_property(char *buf, size_t bufsize)
        unsigned char *value;
        char *name, *end, *next_prop;
        int rc, length;
-       struct property *newprop, *oldprop;
+       struct property *newprop;
        buf = parse_node(buf, bufsize, &np);
        end = buf + bufsize;
 
@@ -443,6 +443,9 @@ static int do_update_property(char *buf, size_t bufsize)
        if (!next_prop)
                return -EINVAL;
 
+       if (!strlen(name))
+               return -ENODEV;
+
        newprop = new_property(name, length, value, NULL);
        if (!newprop)
                return -ENOMEM;
@@ -450,18 +453,11 @@ static int do_update_property(char *buf, size_t bufsize)
        if (!strcmp(name, "slb-size") || !strcmp(name, "ibm,slb-size"))
                slb_set_size(*(int *)value);
 
-       oldprop = of_find_property(np, name,NULL);
-       if (!oldprop) {
-               if (strlen(name))
-                       return prom_add_property(np, newprop);
-               return -ENODEV;
-       }
-
        upd_value.node = np;
        upd_value.property = newprop;
        pSeries_reconfig_notify(PSERIES_UPDATE_PROPERTY, &upd_value);
 
-       rc = prom_update_property(np, newprop, oldprop);
+       rc = prom_update_property(np, newprop);
        if (rc)
                return rc;
 
@@ -486,7 +482,7 @@ static int do_update_property(char *buf, size_t bufsize)
 
                rc = pSeries_reconfig_notify(action, value);
                if (rc) {
-                       prom_update_property(np, oldprop, newprop);
+                       prom_update_property(np, newprop);
                        return rc;
                }
        }
index e16bb8d48550b60e249ade3aac24b00ed2159233..71706bc34a0dd8a117f5ef71d70b93ab65880ca3 100644 (file)
@@ -147,7 +147,6 @@ static void __devinit smp_xics_setup_cpu(int cpu)
        set_cpu_current_state(cpu, CPU_STATE_ONLINE);
        set_default_offline_state(cpu);
 #endif
-       pseries_notify_cpuidle_add_cpu(cpu);
 }
 
 static int __devinit smp_pSeries_kick_cpu(int nr)
index 21cda085d926417eed53992f711c9d843c99a7a2..cf48e9cb257596698a65f88877e85a3bb33c1f8c 100644 (file)
@@ -29,7 +29,7 @@ _GLOBAL(mpc6xx_enter_standby)
        ori     r5, r5, ret_from_standby@l
        mtlr    r5
 
-       rlwinm  r5, r1, 0, 0, 31-THREAD_SHIFT
+       CURRENT_THREAD_INFO(r5, r1)
        lwz     r6, TI_LOCAL_FLAGS(r5)
        ori     r6, r6, _TLF_SLEEPING
        stw     r6, TI_LOCAL_FLAGS(r5)
index 6073288fed29889399bb640bc22f709043363f72..a7b2a600d0a4d0aa7878a633eb3549f0a0d3a373 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * MPC83xx/85xx/86xx PCI/PCIE support routing.
  *
- * Copyright 2007-2011 Freescale Semiconductor, Inc.
+ * Copyright 2007-2012 Freescale Semiconductor, Inc.
  * Copyright 2008-2009 MontaVista Software, Inc.
  *
  * Initial author: Xianghua Xiao <x.xiao@freescale.com>
@@ -36,7 +36,7 @@
 
 static int fsl_pcie_bus_fixup, is_mpc83xx_pci;
 
-static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
+static void __devinit quirk_fsl_pcie_header(struct pci_dev *dev)
 {
        u8 progif;
 
@@ -807,3 +807,72 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose)
 
        return 0;
 }
+
+#if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx)
+static const struct of_device_id pci_ids[] = {
+       { .compatible = "fsl,mpc8540-pci", },
+       { .compatible = "fsl,mpc8548-pcie", },
+       { .compatible = "fsl,mpc8610-pci", },
+       { .compatible = "fsl,mpc8641-pcie", },
+       { .compatible = "fsl,p1022-pcie", },
+       { .compatible = "fsl,p1010-pcie", },
+       { .compatible = "fsl,p1023-pcie", },
+       { .compatible = "fsl,p4080-pcie", },
+       { .compatible = "fsl,qoriq-pcie-v2.3", },
+       { .compatible = "fsl,qoriq-pcie-v2.2", },
+       {},
+};
+
+struct device_node *fsl_pci_primary;
+
+void __devinit fsl_pci_init(void)
+{
+       struct device_node *node;
+       struct pci_controller *hose;
+       dma_addr_t max = 0xffffffff;
+
+       /* Callers can specify the primary bus using other means. */
+       if (!fsl_pci_primary) {
+               /* If a PCI host bridge contains an ISA node, it's primary. */
+               node = of_find_node_by_type(NULL, "isa");
+               while ((fsl_pci_primary = of_get_parent(node))) {
+                       of_node_put(node);
+                       node = fsl_pci_primary;
+
+                       if (of_match_node(pci_ids, node))
+                               break;
+               }
+       }
+
+       node = NULL;
+       for_each_node_by_type(node, "pci") {
+               if (of_match_node(pci_ids, node)) {
+                       /*
+                        * If there's no PCI host bridge with ISA, arbitrarily
+                        * designate one as primary.  This can go away once
+                        * various bugs with primary-less systems are fixed.
+                        */
+                       if (!fsl_pci_primary)
+                               fsl_pci_primary = node;
+
+                       fsl_add_bridge(node, fsl_pci_primary == node);
+                       hose = pci_find_hose_for_OF_device(node);
+                       max = min(max, hose->dma_window_base_cur +
+                                       hose->dma_window_size);
+               }
+       }
+
+#ifdef CONFIG_SWIOTLB
+       /*
+        * if we couldn't map all of DRAM via the dma windows
+        * we need SWIOTLB to handle buffers located outside of
+        * dma capable memory region
+        */
+       if (memblock_end_of_DRAM() - 1 > max) {
+               ppc_swiotlb_enable = 1;
+               set_pci_dma_ops(&swiotlb_dma_ops);
+               ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
+       }
+#endif
+}
+#endif
index a39ed5cc2c5ab41ab076073a279460099987c891..baa0fd18289fa294d4187b853355ce8616fe4b1e 100644 (file)
@@ -93,5 +93,13 @@ extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
 extern int mpc83xx_add_bridge(struct device_node *dev);
 u64 fsl_pci_immrbar_base(struct pci_controller *hose);
 
+extern struct device_node *fsl_pci_primary;
+
+#ifdef CONFIG_FSL_PCI
+void fsl_pci_init(void);
+#else
+static inline void fsl_pci_init(void) {}
+#endif
+
 #endif /* __POWERPC_FSL_PCI_H */
 #endif /* __KERNEL__ */
index 395af1347749104aeef3c832fb48dd26e6385ace..bfc6211e5422ef17b6e0bb0d24b926fa653354d9 100644 (file)
@@ -1211,7 +1211,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
        if (of_get_property(node, "single-cpu-affinity", NULL))
                flags |= MPIC_SINGLE_DEST_CPU;
        if (of_device_is_compatible(node, "fsl,mpic"))
-               flags |= MPIC_FSL;
+               flags |= MPIC_FSL | MPIC_LARGE_VECTORS;
 
        mpic = kzalloc(sizeof(struct mpic), GFP_KERNEL);
        if (mpic == NULL)
@@ -1376,7 +1376,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
        mpic->isu_mask = (1 << mpic->isu_shift) - 1;
 
        mpic->irqhost = irq_domain_add_linear(mpic->node,
-                                      last_irq + 1,
+                                      intvec_top,
                                       &mpic_host_ops, mpic);
 
        /*
index 818e763f826509b78efdcd2ca216e395b8a52c43..b043675297299ceea7f317dfb1579c8a311aba98 100644 (file)
@@ -395,6 +395,9 @@ static void qe_upload_microcode(const void *base,
 
        for (i = 0; i < be32_to_cpu(ucode->count); i++)
                out_be32(&qe_immr->iram.idata, be32_to_cpu(code[i]));
+       
+       /* Set I-RAM Ready Register */
+       out_be32(&qe_immr->iram.iready, be32_to_cpu(QE_IRAM_READY));
 }
 
 /*
index f0b23fc759ba35db19345bfa86be4dc6cd289859..4a67f2b5f6aa154e04898e07aea0cc3f6959f90a 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/s390/appldata/appldata.h
- *
  * Definitions and interface for Linux - z/VM Monitor Stream.
  *
  * Copyright IBM Corp. 2003, 2008
index 24bff4f1cc52ba906a9a6432af6f4e1ebf16c818..bae0f402bf2ab7eb3c8c501c23bbd7e8f81e364a 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/s390/appldata/appldata_base.c
- *
  * Base infrastructure for Linux-z/VM Monitor Stream, Stage 1.
  * Exports appldata_register_ops() and appldata_unregister_ops() for the
  * data gathering modules.
@@ -29,7 +27,7 @@
 #include <linux/suspend.h>
 #include <linux/platform_device.h>
 #include <asm/appldata.h>
-#include <asm/timer.h>
+#include <asm/vtimer.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
 #include <asm/smp.h>
@@ -84,8 +82,7 @@ static struct ctl_table appldata_dir_table[] = {
 /*
  * Timer
  */
-static DEFINE_PER_CPU(struct vtimer_list, appldata_timer);
-static atomic_t appldata_expire_count = ATOMIC_INIT(0);
+static struct vtimer_list appldata_timer;
 
 static DEFINE_SPINLOCK(appldata_timer_lock);
 static int appldata_interval = APPLDATA_CPU_INTERVAL;
@@ -115,10 +112,7 @@ static LIST_HEAD(appldata_ops_list);
  */
 static void appldata_timer_function(unsigned long data)
 {
-       if (atomic_dec_and_test(&appldata_expire_count)) {
-               atomic_set(&appldata_expire_count, num_online_cpus());
-               queue_work(appldata_wq, (struct work_struct *) data);
-       }
+       queue_work(appldata_wq, (struct work_struct *) data);
 }
 
 /*
@@ -131,7 +125,6 @@ static void appldata_work_fn(struct work_struct *work)
        struct list_head *lh;
        struct appldata_ops *ops;
 
-       get_online_cpus();
        mutex_lock(&appldata_ops_mutex);
        list_for_each(lh, &appldata_ops_list) {
                ops = list_entry(lh, struct appldata_ops, list);
@@ -140,7 +133,6 @@ static void appldata_work_fn(struct work_struct *work)
                }
        }
        mutex_unlock(&appldata_ops_mutex);
-       put_online_cpus();
 }
 
 /*
@@ -168,20 +160,6 @@ int appldata_diag(char record_nr, u16 function, unsigned long buffer,
 
 /****************************** /proc stuff **********************************/
 
-/*
- * appldata_mod_vtimer_wrap()
- *
- * wrapper function for mod_virt_timer(), because smp_call_function_single()
- * accepts only one parameter.
- */
-static void __appldata_mod_vtimer_wrap(void *p) {
-       struct {
-               struct vtimer_list *timer;
-               u64    expires;
-       } *args = p;
-       mod_virt_timer_periodic(args->timer, args->expires);
-}
-
 #define APPLDATA_ADD_TIMER     0
 #define APPLDATA_DEL_TIMER     1
 #define APPLDATA_MOD_TIMER     2
@@ -192,49 +170,28 @@ static void __appldata_mod_vtimer_wrap(void *p) {
  * Add, delete or modify virtual timers on all online cpus.
  * The caller needs to get the appldata_timer_lock spinlock.
  */
-static void
-__appldata_vtimer_setup(int cmd)
+static void __appldata_vtimer_setup(int cmd)
 {
-       u64 per_cpu_interval;
-       int i;
+       u64 timer_interval = (u64) appldata_interval * 1000 * TOD_MICRO;
 
        switch (cmd) {
        case APPLDATA_ADD_TIMER:
                if (appldata_timer_active)
                        break;
-               per_cpu_interval = (u64) (appldata_interval*1000 /
-                                         num_online_cpus()) * TOD_MICRO;
-               for_each_online_cpu(i) {
-                       per_cpu(appldata_timer, i).expires = per_cpu_interval;
-                       smp_call_function_single(i, add_virt_timer_periodic,
-                                                &per_cpu(appldata_timer, i),
-                                                1);
-               }
+               appldata_timer.expires = timer_interval;
+               add_virt_timer_periodic(&appldata_timer);
                appldata_timer_active = 1;
                break;
        case APPLDATA_DEL_TIMER:
-               for_each_online_cpu(i)
-                       del_virt_timer(&per_cpu(appldata_timer, i));
+               del_virt_timer(&appldata_timer);
                if (!appldata_timer_active)
                        break;
                appldata_timer_active = 0;
-               atomic_set(&appldata_expire_count, num_online_cpus());
                break;
        case APPLDATA_MOD_TIMER:
-               per_cpu_interval = (u64) (appldata_interval*1000 /
-                                         num_online_cpus()) * TOD_MICRO;
                if (!appldata_timer_active)
                        break;
-               for_each_online_cpu(i) {
-                       struct {
-                               struct vtimer_list *timer;
-                               u64    expires;
-                       } args;
-                       args.timer = &per_cpu(appldata_timer, i);
-                       args.expires = per_cpu_interval;
-                       smp_call_function_single(i, __appldata_mod_vtimer_wrap,
-                                                &args, 1);
-               }
+               mod_virt_timer_periodic(&appldata_timer, timer_interval);
        }
 }
 
@@ -265,14 +222,12 @@ appldata_timer_handler(ctl_table *ctl, int write,
        len = *lenp;
        if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len))
                return -EFAULT;
-       get_online_cpus();
        spin_lock(&appldata_timer_lock);
        if (buf[0] == '1')
                __appldata_vtimer_setup(APPLDATA_ADD_TIMER);
        else if (buf[0] == '0')
                __appldata_vtimer_setup(APPLDATA_DEL_TIMER);
        spin_unlock(&appldata_timer_lock);
-       put_online_cpus();
 out:
        *lenp = len;
        *ppos += len;
@@ -305,20 +260,17 @@ appldata_interval_handler(ctl_table *ctl, int write,
                goto out;
        }
        len = *lenp;
-       if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len)) {
+       if (copy_from_user(buf, buffer, len > sizeof(buf) ? sizeof(buf) : len))
                return -EFAULT;
-       }
        interval = 0;
        sscanf(buf, "%i", &interval);
        if (interval <= 0)
                return -EINVAL;
 
-       get_online_cpus();
        spin_lock(&appldata_timer_lock);
        appldata_interval = interval;
        __appldata_vtimer_setup(APPLDATA_MOD_TIMER);
        spin_unlock(&appldata_timer_lock);
-       put_online_cpus();
 out:
        *lenp = len;
        *ppos += len;
@@ -485,14 +437,12 @@ static int appldata_freeze(struct device *dev)
        int rc;
        struct list_head *lh;
 
-       get_online_cpus();
        spin_lock(&appldata_timer_lock);
        if (appldata_timer_active) {
                __appldata_vtimer_setup(APPLDATA_DEL_TIMER);
                appldata_timer_suspended = 1;
        }
        spin_unlock(&appldata_timer_lock);
-       put_online_cpus();
 
        mutex_lock(&appldata_ops_mutex);
        list_for_each(lh, &appldata_ops_list) {
@@ -516,14 +466,12 @@ static int appldata_restore(struct device *dev)
        int rc;
        struct list_head *lh;
 
-       get_online_cpus();
        spin_lock(&appldata_timer_lock);
        if (appldata_timer_suspended) {
                __appldata_vtimer_setup(APPLDATA_ADD_TIMER);
                appldata_timer_suspended = 0;
        }
        spin_unlock(&appldata_timer_lock);
-       put_online_cpus();
 
        mutex_lock(&appldata_ops_mutex);
        list_for_each(lh, &appldata_ops_list) {
@@ -567,53 +515,6 @@ static struct platform_driver appldata_pdrv = {
 
 /******************************* init / exit *********************************/
 
-static void __cpuinit appldata_online_cpu(int cpu)
-{
-       init_virt_timer(&per_cpu(appldata_timer, cpu));
-       per_cpu(appldata_timer, cpu).function = appldata_timer_function;
-       per_cpu(appldata_timer, cpu).data = (unsigned long)
-               &appldata_work;
-       atomic_inc(&appldata_expire_count);
-       spin_lock(&appldata_timer_lock);
-       __appldata_vtimer_setup(APPLDATA_MOD_TIMER);
-       spin_unlock(&appldata_timer_lock);
-}
-
-static void __cpuinit appldata_offline_cpu(int cpu)
-{
-       del_virt_timer(&per_cpu(appldata_timer, cpu));
-       if (atomic_dec_and_test(&appldata_expire_count)) {
-               atomic_set(&appldata_expire_count, num_online_cpus());
-               queue_work(appldata_wq, &appldata_work);
-       }
-       spin_lock(&appldata_timer_lock);
-       __appldata_vtimer_setup(APPLDATA_MOD_TIMER);
-       spin_unlock(&appldata_timer_lock);
-}
-
-static int __cpuinit appldata_cpu_notify(struct notifier_block *self,
-                                        unsigned long action,
-                                        void *hcpu)
-{
-       switch (action) {
-       case CPU_ONLINE:
-       case CPU_ONLINE_FROZEN:
-               appldata_online_cpu((long) hcpu);
-               break;
-       case CPU_DEAD:
-       case CPU_DEAD_FROZEN:
-               appldata_offline_cpu((long) hcpu);
-               break;
-       default:
-               break;
-       }
-       return NOTIFY_OK;
-}
-
-static struct notifier_block __cpuinitdata appldata_nb = {
-       .notifier_call = appldata_cpu_notify,
-};
-
 /*
  * appldata_init()
  *
@@ -621,7 +522,10 @@ static struct notifier_block __cpuinitdata appldata_nb = {
  */
 static int __init appldata_init(void)
 {
-       int i, rc;
+       int rc;
+
+       appldata_timer.function = appldata_timer_function;
+       appldata_timer.data = (unsigned long) &appldata_work;
 
        rc = platform_driver_register(&appldata_pdrv);
        if (rc)
@@ -639,14 +543,6 @@ static int __init appldata_init(void)
                goto out_device;
        }
 
-       get_online_cpus();
-       for_each_online_cpu(i)
-               appldata_online_cpu(i);
-       put_online_cpus();
-
-       /* Register cpu hotplug notifier */
-       register_hotcpu_notifier(&appldata_nb);
-
        appldata_sysctl_header = register_sysctl_table(appldata_dir_table);
        return 0;
 
index f7d3dc555bdbd5c44b45f7f2feeb75560d38887d..02d9a1cf5057d18b1b92b2e03e4d7889be97479d 100644 (file)
@@ -1,10 +1,8 @@
 /*
- * arch/s390/appldata/appldata_mem.c
- *
  * Data gathering module for Linux-VM Monitor Stream, Stage 1.
  * Collects data related to memory management.
  *
- * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ * Copyright IBM Corp. 2003, 2006
  *
  * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
  */
index 5da7c562a90b5dc557524ed1ae6f41bce7258bac..1370e358d49a3772ea7f8a27e33684478a683b58 100644 (file)
@@ -1,11 +1,9 @@
 /*
- * arch/s390/appldata/appldata_net_sum.c
- *
  * Data gathering module for Linux-VM Monitor Stream, Stage 1.
  * Collects accumulated network statistics (Packets received/transmitted,
  * dropped, errors, ...).
  *
- * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ * Copyright IBM Corp. 2003, 2006
  *
  * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
  */
index 4de031d6b76cf8a8662d12f0c6858c590a3a70ba..87521ba682e53276a135901e40225c59f3d0dc09 100644 (file)
@@ -1,10 +1,8 @@
 /*
- * arch/s390/appldata/appldata_os.c
- *
  * Data gathering module for Linux-VM Monitor Stream, Stage 1.
  * Collects misc. OS related data (CPU utilization, running processes).
  *
- * Copyright (C) 2003,2006 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ * Copyright IBM Corp. 2003, 2006
  *
  * Author: Gerald Schaefer <gerald.schaefer@de.ibm.com>
  */
index a9ce135893f8c215e0ac19cb91b3429522010f6e..e402a9dd4eda67944893eeef40fa8d67a3066008 100644 (file)
@@ -4,7 +4,7 @@
  * s390 implementation of the AES Cipher Algorithm.
  *
  * s390 Version:
- *   Copyright IBM Corp. 2005,2007
+ *   Copyright IBM Corp. 2005, 2007
  *   Author(s): Jan Glauber (jang@de.ibm.com)
  *             Sebastian Siewior (sebastian@breakpoint.cc> SW-Fallback
  *
index 9178db6db0a5abaa44055f0f5224632513d97976..6c5cc6da71114e51e8430d2eaf5a32be6a676127 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Support for s390 cryptographic instructions.
  *
- *   Copyright IBM Corp. 2003,2007
+ *   Copyright IBM Corp. 2003, 2007
  *   Author(s): Thomas Spatzier
  *             Jan Glauber (jan.glauber@de.ibm.com)
  *
index a52bfd124d86e009184c8326a9e1b03bfeedf76e..1eaa371ca3eea30fd9856c70371ffda5a335e0a5 100644 (file)
@@ -3,7 +3,7 @@
  *
  * s390 implementation of the DES Cipher Algorithm.
  *
- * Copyright IBM Corp. 2003,2011
+ * Copyright IBM Corp. 2003, 2011
  * Author(s): Thomas Spatzier
  *           Jan Glauber (jan.glauber@de.ibm.com)
  *
index 0808fbf0f7d3770d5a0b4c2d3267bf4eeafd2492..94a35a4c1b486c02200f6be510ecafd8a59701c6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright IBM Corp. 2006,2007
+ * Copyright IBM Corp. 2006, 2007
  * Author(s): Jan Glauber <jan.glauber@de.ibm.com>
  * Driver for the s390 pseudo random number generator
  */
index e9868c6e0a08c0868a65d64a3999e2a48d5ee31b..a1b3a9dc9d8a0f420f6389bd56331890e259ab6b 100644 (file)
@@ -8,7 +8,7 @@
  * implementation written by Steve Reid.
  *
  * s390 Version:
- *   Copyright IBM Corp. 2003,2007
+ *   Copyright IBM Corp. 2003, 2007
  *   Author(s): Thomas Spatzier
  *             Jan Glauber (jan.glauber@de.ibm.com)
  *
index 0317a3547cb9982aa6e4d47a9fece44a603f94c5..9b853809a492b68e6781ba6a8c32e5a60fe78932 100644 (file)
@@ -4,7 +4,7 @@
  * s390 implementation of the SHA256 and SHA224 Secure Hash Algorithm.
  *
  * s390 Version:
- *   Copyright IBM Corp. 2005,2011
+ *   Copyright IBM Corp. 2005, 2011
  *   Author(s): Jan Glauber (jang@de.ibm.com)
  *
  * This program is free software; you can redistribute it and/or modify it
index d9df5a060a83fdb96ca567974ac443395872f094..f41e0ef7fdf94578166eafee6d55df6a6f946390 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  arch/s390/hypfs/hypfs.h
  *    Hypervisor filesystem for Linux on s390.
  *
- *    Copyright (C) IBM Corp. 2006
+ *    Copyright IBM Corp. 2006
  *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
  */
 
index b478013b7fecedf9e409c004c0456f2586e818de..13e76dabbe8bd7d91df2182a6b83372e165368c4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Hypervisor filesystem for Linux on s390 - debugfs interface
  *
- * Copyright (C) IBM Corp. 2010
+ * Copyright IBM Corp. 2010
  * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
  */
 
index 74c8f5e76ce4fffdfedaa9c7745f9a34dacc4abc..7fd3690b676050eab20af1caf6a2c50b6a73aba0 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *  arch/s390/hypfs/hypfs_diag.c
  *    Hypervisor filesystem for Linux on s390. Diag 204 and 224
  *    implementation.
  *
index e54796002f615c690a45167d16ba938f85c584c3..4f6afaa8bd8ff5182b9a7bb06a87ee4d5bb7d017 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Hypervisor filesystem for Linux on s390. z/VM implementation.
  *
- *    Copyright (C) IBM Corp. 2006
+ *    Copyright IBM Corp. 2006
  *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
  */
 
index 73dae8b9b77a8c9f58c3c9e1f81f206b74dac04c..6767b437a103aa2eb9d46fc19df6732f188f040b 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *  arch/s390/hypfs/inode.c
  *    Hypervisor filesystem for Linux on s390.
  *
  *    Copyright IBM Corp. 2006, 2008
@@ -103,6 +102,7 @@ static struct inode *hypfs_make_inode(struct super_block *sb, umode_t mode)
 
        if (ret) {
                struct hypfs_sb_info *hypfs_info = sb->s_fs_info;
+               ret->i_ino = get_next_ino();
                ret->i_mode = mode;
                ret->i_uid = hypfs_info->uid;
                ret->i_gid = hypfs_info->gid;
index 1ac80d6b05887815f0fceec4ed6e428c11849d99..9819891ed7a20c74d2804fe31723439ad88600e8 100644 (file)
@@ -1,7 +1,5 @@
 /*
- *  include/asm-s390/airq.h
- *
- *    Copyright IBM Corp. 2002,2007
+ *    Copyright IBM Corp. 2002, 2007
  *    Author(s): Ingo Adlung <adlung@de.ibm.com>
  *              Cornelia Huck <cornelia.huck@de.ibm.com>
  *              Arnd Bergmann <arndb@de.ibm.com>
index 79283dac8281453419dde45f78a28f4732553469..f328294faeae572f59c5b2dcd89f116299a8bd3b 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * include/asm-s390/appldata.h
- *
- * Copyright (C) IBM Corp. 2006
+ * Copyright IBM Corp. 2006
  *
  * Author(s): Melissa Howland <melissah@us.ibm.com>
  */
index 748347baecb8da6a9b22fb3daad326302c517ef0..c797832daa5f596bac9da8f5075d1bd2e006559c 100644 (file)
@@ -1,8 +1,5 @@
-#ifndef __ARCH_S390_ATOMIC__
-#define __ARCH_S390_ATOMIC__
-
 /*
- * Copyright 1999,2009 IBM Corp.
+ * Copyright IBM Corp. 1999, 2009
  * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
  *           Denis Joseph Barrow,
  *           Arnd Bergmann <arndb@de.ibm.com>,
@@ -13,6 +10,9 @@
  *
  */
 
+#ifndef __ARCH_S390_ATOMIC__
+#define __ARCH_S390_ATOMIC__
+
 #include <linux/compiler.h>
 #include <linux/types.h>
 #include <asm/cmpxchg.h>
index a6ff5a83e227279fe6e49dd9b6420eeca3400606..6f573890fb2853602271d2a16b0b39b792ff9cfe 100644 (file)
@@ -1,11 +1,6 @@
-#ifndef _S390_BITOPS_H
-#define _S390_BITOPS_H
-
 /*
- *  include/asm-s390/bitops.h
- *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
  *  Derived from "include/asm-i386/bitops.h"
@@ -13,6 +8,9 @@
  *
  */
 
+#ifndef _S390_BITOPS_H
+#define _S390_BITOPS_H
+
 #ifndef _LINUX_BITOPS_H
 #error only <linux/bitops.h> can be included directly
 #endif
index 011f1e6a2a6cd8af7078fbc39eed791368dd3056..0f5bd894f4dcfcbac666e3c5521c52c960d60623 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/bugs.h
- *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
  *  Derived from "include/asm-i386/bugs.h"
index 2a30d5ac0667aa6285eef8c3bb95a86ad04db809..4d7ccac5fd1d693e3875f2eac011d46ff3750a0e 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/cache.h
- *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *
  *  Derived from "include/asm-i386/cache.h"
  *    Copyright (C) 1992, Linus Torvalds
index 9381c92cc779b14afbf940fe5b4f56f54ad7d125..1cb4bb3f32d92709d11cee7f96c198d2689d3a77 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright  IBM Corp. 2002, 2009
+ * Copyright IBM Corp. 2002, 2009
  *
  * Author(s): Arnd Bergmann <arndb@de.ibm.com>
  *
index f2ef34f6d6e56b669ab3479a059ba37fd89efc7e..01a905eb11e036e2601580053af149ec1ef89da2 100644 (file)
@@ -6,14 +6,12 @@ struct ccw_driver;
 
 /**
  * struct ccwgroup_device - ccw group device
- * @creator_id: unique number of the driver
  * @state: online/offline state
  * @count: number of attached slave devices
  * @dev: embedded device structure
  * @cdev: variable number of slave devices, allocated as needed
  */
 struct ccwgroup_device {
-       unsigned long creator_id;
        enum {
                CCWGROUP_OFFLINE,
                CCWGROUP_ONLINE,
index 6c00f6800a343b4569494d769ccadb95c4f6fe01..4f57a4f3909a1682822a61976cbc4e01f417dda5 100644 (file)
@@ -1,18 +1,16 @@
-#ifndef _S390_CHECKSUM_H
-#define _S390_CHECKSUM_H
-
 /*
- *  include/asm-s390/checksum.h
  *    S390 fast network checksum routines
- *    see also arch/S390/lib/checksum.c
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Ulrich Hild        (first version)
  *               Martin Schwidefsky (heavily optimized CKSM version)
  *               D.J. Barrow        (third attempt) 
  */
 
+#ifndef _S390_CHECKSUM_H
+#define _S390_CHECKSUM_H
+
 #include <asm/uaccess.h>
 
 /*
index 8e88e2221771bf41f2c379d460da4e8fd3499cdd..e5bde9f9291f9a57b7bd6cfce430f7a9c7e37160 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/cio/chpid.h
- *
  *    Copyright IBM Corp. 2007
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
index 4943654ed7fd673c55ad324dacdbde891a6d45cc..bf115b49f444980d47a70f1a3f4232b50a52aec2 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * ioctl interface for /dev/chsc
  *
- * Copyright 2008 IBM Corp.
+ * Copyright IBM Corp. 2008
  * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
  */
 
index 4c8d4d5b8bd2ca545a1e35dcacaa4f45b115c083..77043aa44d67184549ae93d948acb13cea0bd678 100644 (file)
@@ -1,7 +1,4 @@
 /*
- *  include/asm-s390/cio.h
- *  include/asm-s390x/cio.h
- *
  * Common interface for I/O on S/390
  */
 #ifndef _ASM_S390_CIO_H_
index 48a9eab1642972f49d666188962e05d1d41af6f1..3dfadb5d648f5de6a14d2010a101d377dadb0787 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  arch/s390/kernel/cpcmd.h
- *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Christian Borntraeger (cborntra@de.ibm.com),
  */
index e0b69540216f0839818fc4cfc3a18d98ee211415..f5a8e2fcde0c56a3ff17208e10c90cea2f5757b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2000,2009
+ *    Copyright IBM Corp. 2000, 2009
  *    Author(s): Hartmut Penner <hp@de.ibm.com>,
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>,
  *              Christian Ehrhardt <ehrhardt@de.ibm.com>,
index 718374de9c7f3f75f658bbaedb54695760ed25eb..8709bdef233cc5a7a42d3b9bafc19d0682167849 100644 (file)
@@ -1,7 +1,5 @@
 /*
- *  include/asm-s390/cputime.h
- *
- *  (C) Copyright IBM Corp. 2004
+ *  Copyright IBM Corp. 2004
  *
  *  Author: Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
@@ -167,12 +165,14 @@ static inline clock_t cputime64_to_clock_t(cputime64_t cputime)
 }
 
 struct s390_idle_data {
+       int nohz_delay;
        unsigned int sequence;
        unsigned long long idle_count;
-       unsigned long long idle_enter;
-       unsigned long long idle_exit;
        unsigned long long idle_time;
-       int nohz_delay;
+       unsigned long long clock_idle_enter;
+       unsigned long long clock_idle_exit;
+       unsigned long long timer_idle_enter;
+       unsigned long long timer_idle_exit;
 };
 
 DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
index 749a97e61bea0b014cc54639a1d8b9528e62f8c7..7c31d3e25cd13a295d0bd632fb5127dbe7356ca0 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *   Data definitions for channel report processing
- *    Copyright IBM Corp. 2000,2009
+ *    Copyright IBM Corp. 2000, 2009
  *    Author(s): Ingo Adlung <adlung@de.ibm.com>,
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>,
  *              Cornelia Huck <cornelia.huck@de.ibm.com>,
index 7a68084ec2f0aa0443ff671048082562ca63c346..b80941f30df5518159e4fe5681ae56472bc90592 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/current.h
- *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
  *  Derived from "include/asm-i386/current.h"
index 0be28efe5b665a37df7fec66900f8cc521f5717f..38eca3ba40e28a3c5bb2e710bbca2f8e9e8d201d 100644 (file)
@@ -1,8 +1,7 @@
 /* 
- * File...........: linux/drivers/s390/block/dasd.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ * Copyright IBM Corp. 1999, 2000
  * EMC Symmetrix ioctl Copyright EMC Corporation, 2008
  * Author.........: Nigel Hislop <hislop_nigel@emc.com>
  *
index 8a8245ed14d22b888c9691e43de7e9c573fd88cf..f39677e6ccdef3105776d6062ca8a11a9431367b 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  include/asm-s390/debug.h
  *   S/390 debug facility
  *
- *    Copyright (C) 1999, 2000 IBM Deutschland Entwicklung GmbH,
- *                             IBM Corporation
+ *    Copyright IBM Corp. 1999, 2000
  */
 
 #ifndef DEBUG_H
index 0e3b35f96be174c12df5d93e33acee36532bcb61..3f6e4095f4715f5c92aaf01b69b416efad9ac69f 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/delay.h
- *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
  *  Derived from "include/asm-i386/delay.h"
index 7425c6af6cd4c8a686bd28ce6972f575e12a4602..6fb6de4f15b0d987f377ddb3fbeabef949929ab2 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/dma.h
- *
  *  S390 version
  */
 
index 7f6f641d32f4b3b42e0eaeacbc03eef3beaf7855..c5befc5a3bf5757c98e0f5cedefa9bc4ec00815a 100644 (file)
@@ -1,9 +1,8 @@
 /*
- *  include/asm-s390/ebcdic.h
  *    EBCDIC -> ASCII, ASCII -> EBCDIC conversion routines.
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
 
index 06151e6a309889a16b46e62efbc26798d8b0e42d..32e8449640facbef375b0a5cb1d33610290c3a7e 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/elf.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/elf.h"
index e41d5b37c4d651b43b20dd1920b6ffee1c001d67..395e97d8005e9f6698b4ac932aba046a80ba3324 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/errno.h
- *
  *  S390 version
  *
  */
index 538e1b36a726e71c2149e90041ff6cada6d2b2cc..a24b03b9fb647d44cdf78a7c4bbb8b82e26d8d9b 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/etr.h
- *
  *  Copyright IBM Corp. 2006
  *  Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
index 33837d7561843def942ad264591dfa8ca6584c7d..6276002d76ba64f6dc2c4690e49a2368ab27f10e 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390x/extmem.h
- *
  *  definitions for external memory segment support
- *  Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *  Copyright IBM Corp. 2003
  */
 
 #ifndef _ASM_S390X_DCSS_H
index 510ba9ef424887555770f3aa6267f03f055c1211..0c82ba86e997d5d088b019daa677968fccdaf7e6 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/hardirq.h
- *
  *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999, 2000
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  *
index aef0dde340d1f54b866874a9f14061b8237ef4dc..ea5a6e45fd936412b537b5fd34828a54f57ac325 100644 (file)
@@ -1,10 +1,9 @@
 /* 
- * File...........: linux/include/asm-s390x/idals.h
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  *                 Martin Schwidefsky <schwidefsky@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000a
+ * Copyright IBM Corp. 2000
+ *
  * History of changes
  * 07/24/00 new file
  * 05/04/02 code restructuring.
index f81a0975cbea0efb88db7b8a123072f125f80e10..559e921a6bbafa082df673fa9989ea44d4a23427 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/io.h
- *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
  *  Derived from "include/asm-i386/io.h"
index 38fdf451febb475cae7ce93229596d78b75a01f1..37b9091ab8c010c88a22bb2851f0133b10c6f032 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2006,2010
+ *    Copyright IBM Corp. 2006, 2010
  *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
 
index f4f38826eebb3347ed5c5039db329e1d318b2ef1..694bcd6bd927bff60bf76ceede7a222877e02999 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * include/asm-s390/kexec.h
- *
- * (C) Copyright IBM Corp. 2005
+ * Copyright IBM Corp. 2005
  *
  * Author(s): Rolf Adelsberger <adelsberger@de.ibm.com>
  *
index a231a9439c4bc23e4bfcbda841d294924ebfb7fa..dcf6948a875ca6d0b12b08100cc3d2362d28224b 100644 (file)
@@ -17,7 +17,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
- * Copyright (C) IBM Corporation, 2002, 2006
+ * Copyright IBM Corp. 2002, 2006
  *
  * 2002-Oct    Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
  *             Probes initial implementation ( includes suggestions from
index bdcbe0f8dd7b6f6560931a35e12bfebe16394b01..d25da598ec6217321da63e1a839d20c68d3e9274 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __LINUX_KVM_S390_H
 #define __LINUX_KVM_S390_H
 /*
- * asm-s390/kvm.h - KVM s390 specific structures and definitions
+ * KVM s390 specific structures and definitions
  *
  * Copyright IBM Corp. 2008
  *
index dd17537b9a9d2362a749a0325d8ed6b86b348ed0..b7841546991fe6a9b0f20d73f8a06cf65557e9c1 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * asm-s390/kvm_host.h - definition for kernel virtual machines on s390
+ * definition for kernel virtual machines on s390
  *
- * Copyright IBM Corp. 2008,2009
+ * Copyright IBM Corp. 2008, 2009
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
index a98832961035b6daf24d871d152faa2d228fb91e..da44867de60f6e1deaa6b8edbd35c9e834db027b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * asm-s390/kvm_para.h - definition for paravirtual devices on s390
+ * definition for paravirtual devices on s390
  *
  * Copyright IBM Corp. 2008
  *
index 72f614181eff834def19193915efd26a828f6f54..44a438ca9e72d320a2e0e31ae2753ceebee6deb0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * kvm_virtio.h - definition for virtio for kvm on s390
+ * definition for virtio for kvm on s390
  *
  * Copyright IBM Corp. 2008
  *
index 47853debb3b9de98eed2a3ac70a0cb95c3a19412..aab5555bbbdaecb1f52f8456ece7f1ee8f11a490 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 1999,2012
+ *    Copyright IBM Corp. 1999, 2012
  *    Author(s): Hartmut Penner <hp@de.ibm.com>,
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>,
  *              Denis Joseph Barrow,
@@ -302,12 +302,7 @@ struct _lowcore {
         */
        __u64   ipib;                           /* 0x0e00 */
        __u32   ipib_checksum;                  /* 0x0e08 */
-       /*
-        * Because the vmcore_info pointer is not 8 byte aligned it never
-        * should not be accessed directly. For accessing the pointer, first
-        * copy it to a local pointer variable.
-        */
-       __u8    vmcore_info[8];                 /* 0x0e0c */
+       __u64   vmcore_info;                    /* 0x0e0c */
        __u8    pad_0x0e14[0x0e18-0x0e14];      /* 0x0e14 */
        __u64   os_info;                        /* 0x0e18 */
        __u8    pad_0x0e20[0x0f00-0x0e20];      /* 0x0e20 */
index e8dd1ba8edb0ac069a8217d3a2df708e6129a433..614dfaf47f71619740059d56f89df157b0f775d8 100644 (file)
@@ -1,9 +1,8 @@
 /*
- *  arch/s390/kernel/mathemu.h
  *    IEEE floating point emulation.
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
 
index d49760e63506dd401df1e2f81da69982ed6a468c..abc1932ac4e163b3a6f3df36e012dea0cac18d06 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/mman.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/mman.h"
index 69bdf72e95ecfd7fd5134640a48b929952a74747..5c63615f1349f862762ced5e20147acae7f2c5ec 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/mmu_context.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/mmu_context.h"
index f0cbf96c52e61efc5c696de38e6e9dddfc2eeca1..f845c8e2f86158f5d899ff7ac0a41fd3ebbb5dca 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * include/asm-s390/monwriter.h
- *
- * Copyright (C) IBM Corp. 2006
+ * Copyright IBM Corp. 2006
  * Character device driver for writing z/VM APPLDATA monitor records
  * Version 1.0
  * Author(s): Melissa Howland <melissah@us.ibm.com>
index f4b60441adcafb6ca1da3560c15a7437cd353002..35f8ec185616f07a1485b1bd7085133d3f299d07 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   Machine check handler definitions
  *
- *    Copyright IBM Corp. 2000,2009
+ *    Copyright IBM Corp. 2000, 2009
  *    Author(s): Ingo Adlung <adlung@de.ibm.com>,
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>,
  *              Cornelia Huck <cornelia.huck@de.ibm.com>,
index f7ec548c2b9d4dbe1fec8496043c8e5bb36bbeb7..27ab3c7c1e8bc7e3e353b3eaefc0a806edc8400c 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/page.h
- *
  *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999, 2000
  *    Author(s): Hartmut Penner (hp@de.ibm.com)
  */
 
index 43078c1943948ca9b801dc60f684ef7025eed616..590c3219c63445f2214a1befc033b7d28e0cf10f 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/pgalloc.h
- *
  *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999, 2000
  *    Author(s): Hartmut Penner (hp@de.ibm.com)
  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
index b3227415abdaca94d3f3dcc301cb7ce425cd6a9e..6bd7d74830171096c82ac74f5dc671dbb7098090 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/pgtable.h
- *
  *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999, 2000
  *    Author(s): Hartmut Penner (hp@de.ibm.com)
  *               Ulrich Weigand (weigand@de.ibm.com)
  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
index 7be104c0f19230e157d569efb9a18002dfa4709d..7bcc14e395f0a2fd1d85ded571010e05c5c0392e 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/posix_types.h
- *
  *  S390 version
  *
  */
index 20d0585cf905675422ad406d406401eba2bd6f82..c40fa91e38a8da85fcad46d66435701f98076758 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/processor.h
- *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Hartmut Penner (hp@de.ibm.com),
  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
@@ -348,4 +346,14 @@ extern void (*s390_base_ext_handler_fn)(void);
        ".previous\n"
 #endif
 
+extern int memcpy_real(void *, void *, size_t);
+extern void memcpy_absolute(void *, void *, size_t);
+
+#define mem_assign_absolute(dest, val) {                       \
+       __typeof__(dest) __tmp = (val);                         \
+                                                               \
+       BUILD_BUG_ON(sizeof(__tmp) != sizeof(val));             \
+       memcpy_absolute(&(dest), &__tmp, sizeof(__tmp));        \
+}
+
 #endif                                 /* __ASM_S390_PROCESSOR_H           */
index aeb77f01798504cd250aebbd8748516b8c64e113..d5f08ea566ed9ac9d03085f8c6ea5cfe378befd5 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/ptrace.h
- *
  *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999, 2000
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  */
 
index f039d86adf6741c7e2d454c46c4d56fada7d21a2..57d0d7e794b18a1976b2b5901d0409e53a69d9a8 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * linux/include/asm-s390/qdio.h
- *
- * Copyright 2000,2008 IBM Corp.
+ * Copyright IBM Corp. 2000, 2008
  * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
  *           Jan Glauber <jang@linux.vnet.ibm.com>
  *
index 2c7c898c03e47a83c822508a127efc9f2162f9de..3a896cf52589c7ee19ba383c83284ca2063763f2 100644 (file)
@@ -1,9 +1,7 @@
 /*
- * include/asm-s390/qeth.h
- *
  * ioctl definitions for qeth driver
  *
- * Copyright (C) 2004 IBM Corporation
+ * Copyright IBM Corp. 2004
  *
  * Author(s):  Thomas Spatzier <tspat@de.ibm.com>
  *
index 3d6ad4ad2a3f536a28d72164d43d57b887cb2724..804578587a7a87e6e0b9eb56a1aee121bf9d2fdf 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/reset.h
- *
  *    Copyright IBM Corp. 2006
  *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  */
index 366c01de04f26895db9362a23792c92b105e0096..ec23d1c73c923e9fe45d057746b0f6b25c05a8df 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/resource.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/resources.h"
index 1ceee10264c3832bce52f2cae57070d549afc35c..487f9b64efb9a5f8d64d7a25fea34ae40e1faa29 100644 (file)
@@ -2,10 +2,8 @@
 #define _S390_RWSEM_H
 
 /*
- *  include/asm-s390/rwsem.h
- *
  *  S390 version
- *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2002
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
  *  Based on asm-alpha/semaphore.h and asm-i386/rwsem.h
index bf238c55740bc56e7f60148eafc9f89ee99d09e5..8685d1fb8b75104b6fbb761247f26b543a65a7e6 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/sclp.h
- *
  *    Copyright IBM Corp. 2007
  *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  */
index de389cb54d28aafe5b14733d5b8928546ae7ecb4..4071d00978cb3518eef684b7e3931f3de4d7d15e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Helper functions for scsw access.
  *
- *    Copyright IBM Corp. 2008,2009
+ *    Copyright IBM Corp. 2008, 2009
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
index 40eb2ff88e9e59766cc7e1ba931e65a303e06a16..57e80534375a603f2f839893bfa6ebc2b79e5845 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/setup.h
- *
  *  S390 version
- *    Copyright IBM Corp. 1999,2010
+ *    Copyright IBM Corp. 1999, 2010
  */
 
 #ifndef _ASM_S390_SETUP_H
index c2e0c0508e73edc872c50ccbfa524ef50490c1dc..e985182738f82f0e76c1ebca4c5bd3fb29f8d8d8 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/shmparam.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/shmparam.h"
index aeb6e0b13329b512a3d1deb77ee84a349915cecc..584787f6ce44d88569b964bf8543a5c74475e030 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/sigcontext.h
- *
  *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999, 2000
  */
 
 #ifndef _ASM_S390_SIGCONTEXT_H
index e0ff1ab054beaf3ac61212a576818446855e9d83..91fd3e4b70ce0decf20f6c22bbb8bf0338180b27 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/siginfo.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/siginfo.h"
index cdf5cb2fe03f5aa0c2c45765a54536b78d88dde5..6d4d9d1faee9e24eac40741b2f24c8c9f3a3c5ae 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/signal.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/signal.h"
diff --git a/arch/s390/include/asm/sigp.h b/arch/s390/include/asm/sigp.h
new file mode 100644 (file)
index 0000000..7306270
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef __S390_ASM_SIGP_H
+#define __S390_ASM_SIGP_H
+
+/* SIGP order codes */
+#define SIGP_SENSE                   1
+#define SIGP_EXTERNAL_CALL           2
+#define SIGP_EMERGENCY_SIGNAL        3
+#define SIGP_STOP                    5
+#define SIGP_RESTART                 6
+#define SIGP_STOP_AND_STORE_STATUS    9
+#define SIGP_INITIAL_CPU_RESET      11
+#define SIGP_SET_PREFIX                     13
+#define SIGP_STORE_STATUS_AT_ADDRESS 14
+#define SIGP_SET_ARCHITECTURE       18
+#define SIGP_SENSE_RUNNING          21
+
+/* SIGP condition codes */
+#define SIGP_CC_ORDER_CODE_ACCEPTED 0
+#define SIGP_CC_STATUS_STORED      1
+#define SIGP_CC_BUSY               2
+#define SIGP_CC_NOT_OPERATIONAL            3
+
+/* SIGP cpu status bits */
+
+#define SIGP_STATUS_CHECK_STOP         0x00000010UL
+#define SIGP_STATUS_STOPPED            0x00000040UL
+#define SIGP_STATUS_INVALID_PARAMETER  0x00000100UL
+#define SIGP_STATUS_INCORRECT_STATE    0x00000200UL
+#define SIGP_STATUS_NOT_RUNNING                0x00000400UL
+
+#endif /* __S390_ASM_SIGP_H */
index 0b6f586c1383d616954ba35e6953d3ef688705d7..a0a8340daafafb90ad25c822949b6ace5a84a595 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 1999,2012
+ *    Copyright IBM Corp. 1999, 2012
  *    Author(s): Denis Joseph Barrow,
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>,
  *              Heiko Carstens <heiko.carstens@de.ibm.com>,
index c91b720965c07063436949394acfb8cb7b2f74f9..69718cd6d63503e657a4878a1277ab260fa44bf7 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/socket.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/socket.h"
index fd94dfec8d081a0f3da4d740f48c4cc2cc68fd66..701fe8c59e1f0e9efc302e711eef5bcfe3db479a 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/spinlock.h
- *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
  *  Derived from "include/asm-i386/spinlock.h"
index d92959eebb65b8f8c024dedf6982fb31a1ccd4fc..b4ca97d91466a5f36cd4957eb7f090755e045f7d 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/stat.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/stat.h"
index 3be7fbd406c8603a0ddbbd2666b3a5c9f0a2621e..5acca0a34c20c7cd243f8843cce3a41655a8ee27 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/statfs.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/statfs.h"
index 8cc160c9e1cb108c2ce9829dc4c5684a34a3b4ae..1bd1352fa3b55ae3082aa5815ff6a2f1b2e6949c 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/string.h
- *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  */
 
index a3e4ebb32090dc10ab0692f320c3ae3137f0f7dc..da3bfe5cc161557f770d49dc0a1a67d10676b04a 100644 (file)
@@ -2,10 +2,8 @@
 #define _S390_SWAB_H
 
 /*
- *  include/asm-s390/swab.h
- *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
 
index 79d3d6e2e9c5681787ca1c8064c35b6a87992668..282ee36f6162a424a905b7e8afb670bbd9541444 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * definition for store system information stsi
  *
- * Copyright IBM Corp. 2001,2008
+ * Copyright IBM Corp. 2001, 2008
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
index 884fba48f1ff522e3fecd09cbf04deaeb7ca69cb..b2bc4bab79294210328534624946525c2c6f1b03 100644 (file)
@@ -1,10 +1,9 @@
 /*************************************************************************
  *
- * tape390.h
  *        enables user programs to display messages and control encryption
  *        on s390 tape devices
  *
- *        Copyright IBM Corp. 2001,2006
+ *        Copyright IBM Corp. 2001, 2006
  *        Author(s): Michael Holzheu <holzheu@de.ibm.com>
  *
  *************************************************************************/
index bc3a35cefc9629e4ebae31ee601d6a2432b14c5c..cb9fe2786b8174e3b1be80fdfd5705d6d171c9a9 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/termios.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/termios.h"
index 4e40b25cd0600e7d76fcdf38789f86fd32275839..bb08e2afc5de6c570787ce518d7aeda778a28b92 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/thread_info.h
- *
  *  S390 version
- *    Copyright (C) IBM Corp. 2002,2006
+ *    Copyright IBM Corp. 2002, 2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
 
diff --git a/arch/s390/include/asm/timer.h b/arch/s390/include/asm/timer.h
deleted file mode 100644 (file)
index 15d6479..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *  include/asm-s390/timer.h
- *
- *  (C) Copyright IBM Corp. 2003,2006
- *  Virtual CPU timer
- *
- *  Author: Jan Glauber (jang@de.ibm.com)
- */
-
-#ifndef _ASM_S390_TIMER_H
-#define _ASM_S390_TIMER_H
-
-#include <linux/timer.h>
-
-#define VTIMER_MAX_SLICE (0x7ffffffffffff000LL)
-
-struct vtimer_list {
-       struct list_head entry;
-
-       int cpu;
-       __u64 expires;
-       __u64 interval;
-
-       void (*function)(unsigned long);
-       unsigned long data;
-};
-
-/* the vtimer value will wrap after ca. 71 years */
-struct vtimer_queue {
-       struct list_head list;
-       spinlock_t lock;
-       __u64 timer;            /* last programmed timer */
-       __u64 elapsed;          /* elapsed time of timer expire values */
-       __u64 idle_enter;       /* cpu timer on idle enter */
-       __u64 idle_exit;        /* cpu timer on idle exit */
-};
-
-extern void init_virt_timer(struct vtimer_list *timer);
-extern void add_virt_timer(void *new);
-extern void add_virt_timer_periodic(void *new);
-extern int mod_virt_timer(struct vtimer_list *timer, __u64 expires);
-extern int mod_virt_timer_periodic(struct vtimer_list *timer, __u64 expires);
-extern int del_virt_timer(struct vtimer_list *timer);
-
-extern void init_cpu_vtimer(void);
-extern void vtime_init(void);
-
-extern void vtime_stop_cpu(void);
-extern void vtime_start_leave(void);
-
-#endif /* _ASM_S390_TIMER_H */
index 239ece9e53c133f182a810cb731688a268e3fdaa..fba4d66788a247c94adfba5c13ae750e19929496 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/timex.h
- *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *
  *  Derived from "include/asm-i386/timex.h"
  *    Copyright (C) 1992, Linus Torvalds
index 6c8c35f8df142b3b8e22dd21d3230a2403dcab38..6ba7c2c7217afa3fc6b221506a44449d3535d481 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/types.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/types.h"
index 1f3a79bcd262722e251d575009cec172a9c77509..a8ab18b18b54d0c87e8c1c6f7a160352fb7d073e 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  include/asm-s390/uaccess.h
- *
  *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999, 2000
  *    Author(s): Hartmut Penner (hp@de.ibm.com),
  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
@@ -381,8 +379,6 @@ clear_user(void __user *to, unsigned long n)
        return n;
 }
 
-extern int memcpy_real(void *, void *, size_t);
-extern void memcpy_absolute(void *, void *, size_t);
 extern int copy_to_user_real(void __user *dest, void *src, size_t count);
 extern int copy_from_user_real(void *dest, void __user *src, size_t count);
 
index cfb874e66c9a1f7f9bed1e9c5c330c3aed4be455..200e06325c6a52448ac7926928940a62b24c5b90 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/ucontext.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/ucontext.h"
index 8a8008fe7b8f15354d4661d1bddf37e0ac05e16a..2e37157ba6a92cf48dd6360b994db0803f791624 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/unistd.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/unistd.h"
index 1b050e35fdc6f8448dada25aeb1790d16ee71f35..6ed1d1886333cb8c457c0bb1e12ceabcb0d2ca37 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  include/asm-s390/user.h
- *
  *  S390 version
  *
  *  Derived from "include/asm-i386/usr.h"
diff --git a/arch/s390/include/asm/vtimer.h b/arch/s390/include/asm/vtimer.h
new file mode 100644 (file)
index 0000000..bfe25d5
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ *  Copyright IBM Corp. 2003, 2012
+ *  Virtual CPU timer
+ *
+ *  Author(s): Jan Glauber <jan.glauber@de.ibm.com>
+ */
+
+#ifndef _ASM_S390_TIMER_H
+#define _ASM_S390_TIMER_H
+
+#define VTIMER_MAX_SLICE (0x7fffffffffffffffULL)
+
+struct vtimer_list {
+       struct list_head entry;
+       u64 expires;
+       u64 interval;
+       void (*function)(unsigned long);
+       unsigned long data;
+};
+
+extern void init_virt_timer(struct vtimer_list *timer);
+extern void add_virt_timer(struct vtimer_list *timer);
+extern void add_virt_timer_periodic(struct vtimer_list *timer);
+extern int mod_virt_timer(struct vtimer_list *timer, u64 expires);
+extern int mod_virt_timer_periodic(struct vtimer_list *timer, u64 expires);
+extern int del_virt_timer(struct vtimer_list *timer);
+
+extern void init_cpu_vtimer(void);
+extern void vtime_init(void);
+
+extern void vtime_stop_cpu(void);
+
+#endif /* _ASM_S390_TIMER_H */
index 8406a2b3157a2d98f16bc4485d83d452a58e9cc5..221419de275ec6736650fb6e22bbc4942835eb4f 100644 (file)
@@ -1,9 +1,7 @@
 /*
- * include/asm-s390/vtoc.h
- *
  * This file contains volume label definitions for DASD devices.
  *
- * (C) Copyright IBM Corp. 2005
+ * Copyright IBM Corp. 2005
  *
  * Author(s): Volker Sameske <sameske@de.ibm.com>
  *
index 00d3bbd44117fe2093abe6dfca8ec6d6bb3e93cf..e83fc116f5bf2c24ceb4f4b9aa663d7d1c291b8f 100644 (file)
@@ -3,7 +3,7 @@
  *
  *  zcrypt 2.1.0 (user-visible header)
  *
- *  Copyright (C)  2001, 2006 IBM Corporation
+ *  Copyright IBM Corp. 2001, 2006
  *  Author(s): Robert Burroughs
  *            Eric Rossman (edrossma@us.ibm.com)
  *
index 83e6edf5cf17345d592636a49229394777600c82..45ef1a7b08f906b85ed929cb7dd9ce34da1ded9b 100644 (file)
@@ -9,7 +9,6 @@
 #include <linux/kbuild.h>
 #include <linux/sched.h>
 #include <asm/cputime.h>
-#include <asm/timer.h>
 #include <asm/vdso.h>
 #include <asm/pgtable.h>
 
@@ -72,11 +71,10 @@ int main(void)
        DEFINE(__CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC);
        BLANK();
        /* idle data offsets */
-       DEFINE(__IDLE_ENTER, offsetof(struct s390_idle_data, idle_enter));
-       DEFINE(__IDLE_EXIT, offsetof(struct s390_idle_data, idle_exit));
-       /* vtimer queue offsets */
-       DEFINE(__VQ_IDLE_ENTER, offsetof(struct vtimer_queue, idle_enter));
-       DEFINE(__VQ_IDLE_EXIT, offsetof(struct vtimer_queue, idle_exit));
+       DEFINE(__CLOCK_IDLE_ENTER, offsetof(struct s390_idle_data, clock_idle_enter));
+       DEFINE(__CLOCK_IDLE_EXIT, offsetof(struct s390_idle_data, clock_idle_exit));
+       DEFINE(__TIMER_IDLE_ENTER, offsetof(struct s390_idle_data, timer_idle_enter));
+       DEFINE(__TIMER_IDLE_EXIT, offsetof(struct s390_idle_data, timer_idle_exit));
        /* lowcore offsets */
        DEFINE(__LC_EXT_PARAMS, offsetof(struct _lowcore, ext_params));
        DEFINE(__LC_EXT_CPU_ADDR, offsetof(struct _lowcore, ext_cpu_addr));
@@ -131,6 +129,8 @@ int main(void)
        DEFINE(__LC_PANIC_STACK, offsetof(struct _lowcore, panic_stack));
        DEFINE(__LC_RESTART_STACK, offsetof(struct _lowcore, restart_stack));
        DEFINE(__LC_RESTART_FN, offsetof(struct _lowcore, restart_fn));
+       DEFINE(__LC_RESTART_DATA, offsetof(struct _lowcore, restart_data));
+       DEFINE(__LC_RESTART_SOURCE, offsetof(struct _lowcore, restart_source));
        DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce));
        DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock));
        DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock));
index c880ff72db44a0247f57c48450a230f682843ec1..797a823a22755d9b76f8c12717e043226c7395bd 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  arch/s390/kernel/base.S
  *
- *    Copyright IBM Corp. 2006,2007
+ *    Copyright IBM Corp. 2006, 2007
  *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  *              Michael Holzheu <holzheu@de.ibm.com>
  */
@@ -9,6 +9,7 @@
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
 #include <asm/ptrace.h>
+#include <asm/sigp.h>
 
 #ifdef CONFIG_64BIT
 
@@ -100,7 +101,7 @@ ENTRY(diag308_reset)
 .Lrestart_part2:
        lhi     %r0,0                   # Load r0 with zero
        lhi     %r1,2                   # Use mode 2 = ESAME (dump)
-       sigp    %r1,%r0,0x12            # Switch to ESAME mode
+       sigp    %r1,%r0,SIGP_SET_ARCHITECTURE   # Switch to ESAME mode
        sam64                           # Switch to 64 bit addressing mode
        larl    %r4,.Lctlregs           # Restore control registers
        lctlg   %c0,%c15,0(%r4)
index 3ae4757b006a8014a7898d1260429125dc6462b0..102da5e2303753b79f4d637d9f169646a77dd5ed 100644 (file)
@@ -2,7 +2,7 @@
  *    Bitmaps for set_bit, clear_bit, test_and_set_bit, ...
  *    See include/asm/{bitops.h|posix_types.h} for details
  *
- *    Copyright IBM Corp. 1999,2009
+ *    Copyright IBM Corp. 1999, 2009
  *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
  */
 
index 914d49444f92270d6492199bba9ab46d81ccff8d..765fabdada9fbb7c43e13d565b4872af1c97ba3e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Support for 32-bit Linux for S390 personality.
  *
- * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright IBM Corp. 2000
  * Author(s): Gerhard Tonn (ton@de.ibm.com)
  *
  *
index 65426525d9f22f576788e88804bb893ff817cca5..d1225089a4bbe09519555c4f5336e283394ff03e 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  arch/s390x/kernel/linux32.c
- *
  *  S390 version
- *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2000
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Gerhard Tonn (ton@de.ibm.com)   
  *               Thomas Spatzier (tspat@de.ibm.com)
index 3c0c19830c37f5a0f7896d0a292762b794b30a74..a1e8a8694bb70561a8c78c35558ff3a635e2203e 100644 (file)
@@ -1,7 +1,5 @@
 /*
- *  arch/s390/kernel/compat_signal.c
- *
- *    Copyright (C) IBM Corp. 2000,2006
+ *    Copyright IBM Corp. 2000, 2006
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  *               Gerhard Tonn (ton@de.ibm.com)                  
  *
index ff605a39cf435661a6ba6ab5dee05544239fae6b..e835d6d5b7fdc94ee90e5293087328d638c2f74f 100644 (file)
@@ -1,8 +1,7 @@
 /*
-*  arch/s390/kernel/compat_wrapper.S
 *    wrapper for 31 bit compatible system calls.
 *
-*    Copyright (C) IBM Corp. 2000,2006
+*    Copyright IBM Corp. 2000, 2006
 *    Author(s): Gerhard Tonn (ton@de.ibm.com),
 *              Thomas Spatzier (tspat@de.ibm.com)
 */
index e3dd886e1b3218e6b59ec29af4426879b6279570..d7b0c4d27880995d99b51be94b8d54a0cc903ea8 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  arch/s390/kernel/cpcmd.c
- *
  *  S390 version
- *    Copyright IBM Corp. 1999,2007
+ *    Copyright IBM Corp. 1999, 2007
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Christian Borntraeger (cborntra@de.ibm.com),
  */
index 8cc7c9fa64f5fe6e8834e1b7190b831d885cf1ac..3819153de8bd2b33c90454c591bcc84be4552704 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * arch/s390/kernel/crash.c
- *
- * (C) Copyright IBM Corp. 2005
+ * Copyright IBM Corp. 2005
  *
  * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  *
index 19e5e9eba546e26995f08d04f73dd74cc7fc45b0..21be961e8a43e643daa31a26680c91edf2a5ee66 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *  arch/s390/kernel/debug.c
  *   S/390 debug facility
  *
  *    Copyright IBM Corp. 1999, 2012
index 3221c6fca8bb77ceedd9c6ee00b9c2018d45251d..1f6b428e276239d94927086f6d5b2ccc668fbe2b 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * arch/s390/kernel/dis.c
- *
  * Disassemble s390 instructions.
  *
  * Copyright IBM Corp. 2007
@@ -613,6 +611,7 @@ static struct insn opcode_b2[] = {
        { "sie", 0x14, INSTR_S_RD },
        { "pc", 0x18, INSTR_S_RD },
        { "sac", 0x19, INSTR_S_RD },
+       { "servc", 0x20, INSTR_RRE_RR },
        { "cfc", 0x1a, INSTR_S_RD },
        { "ipte", 0x21, INSTR_RRE_RR },
        { "ipm", 0x22, INSTR_RRE_R0 },
index 6684fff1755834f14837868248a31a66644f4575..bc95a8ebd9cc3810a0bfb83d34f10cca512d1d92 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  arch/s390/kernel/early.c
- *
  *    Copyright IBM Corp. 2007, 2009
  *    Author(s): Hongjie Yang <hongjie@us.ibm.com>,
  *              Heiko Carstens <heiko.carstens@de.ibm.com>
index cc0dc609d738c7e148acfd3855da42f8e303b784..b971c6be6298bd52c2fe00d170c2b1781547e0a0 100644 (file)
@@ -1,10 +1,9 @@
 /*
- *  arch/s390/kernel/ebcdic.c
  *    ECBDIC -> ASCII, ASCII -> ECBDIC,
  *    upper to lower case (EBCDIC) conversion tables.
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  *               Martin Peschke <peschke@fh-brandenburg.de>
  */
index 1ae93b573d7dc35f09b4a4ef08722dce3e4212ea..870bad6d56fc4fb7a5a9e308446148a7efec6633 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  arch/s390/kernel/entry.S
  *    S390 low-level entry points.
  *
- *    Copyright (C) IBM Corp. 1999,2012
+ *    Copyright IBM Corp. 1999, 2012
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *              Hartmut Penner (hp@de.ibm.com),
  *              Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
@@ -18,6 +17,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 #include <asm/page.h>
+#include <asm/sigp.h>
 
 __PT_R0      = __PT_GPRS
 __PT_R1      = __PT_GPRS + 4
@@ -616,17 +616,13 @@ ext_skip:
  * Load idle PSW. The second "half" of this function is in cleanup_idle.
  */
 ENTRY(psw_idle)
-       st      %r4,__SF_EMPTY(%r15)
+       st      %r3,__SF_EMPTY(%r15)
        basr    %r1,0
        la      %r1,psw_idle_lpsw+4-.(%r1)
        st      %r1,__SF_EMPTY+4(%r15)
        oi      __SF_EMPTY+4(%r15),0x80
-       la      %r1,.Lvtimer_max-psw_idle_lpsw-4(%r1)
-       stck    __IDLE_ENTER(%r2)
-       ltr     %r5,%r5
-       stpt    __VQ_IDLE_ENTER(%r3)
-       jz      psw_idle_lpsw
-       spt     0(%r1)
+       stck    __CLOCK_IDLE_ENTER(%r2)
+       stpt    __TIMER_IDLE_ENTER(%r2)
 psw_idle_lpsw:
        lpsw    __SF_EMPTY(%r15)
        br      %r14
@@ -723,15 +719,17 @@ ENTRY(restart_int_handler)
        mvc     __PT_PSW(8,%r15),__LC_RST_OLD_PSW # store restart old psw
        ahi     %r15,-STACK_FRAME_OVERHEAD      # create stack frame on stack
        xc      0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
-       lm      %r1,%r3,__LC_RESTART_FN         # load fn, parm & source cpu
+       l       %r1,__LC_RESTART_FN             # load fn, parm & source cpu
+       l       %r2,__LC_RESTART_DATA
+       l       %r3,__LC_RESTART_SOURCE
        ltr     %r3,%r3                         # test source cpu address
        jm      1f                              # negative -> skip source stop
-0:     sigp    %r4,%r3,1                       # sigp sense to source cpu
+0:     sigp    %r4,%r3,SIGP_SENSE              # sigp sense to source cpu
        brc     10,0b                           # wait for status stored
 1:     basr    %r14,%r1                        # call function
        stap    __SF_EMPTY(%r15)                # store cpu address
        lh      %r3,__SF_EMPTY(%r15)
-2:     sigp    %r4,%r3,5                       # sigp stop to current cpu
+2:     sigp    %r4,%r3,SIGP_STOP               # sigp stop to current cpu
        brc     2,2b
 3:     j       3b
 
@@ -883,33 +881,28 @@ cleanup_io_restore_insn:
 
 cleanup_idle:
        # copy interrupt clock & cpu timer
-       mvc     __IDLE_EXIT(8,%r2),__LC_INT_CLOCK
-       mvc     __VQ_IDLE_EXIT(8,%r3),__LC_ASYNC_ENTER_TIMER
+       mvc     __CLOCK_IDLE_EXIT(8,%r2),__LC_INT_CLOCK
+       mvc     __TIMER_IDLE_EXIT(8,%r2),__LC_ASYNC_ENTER_TIMER
        chi     %r11,__LC_SAVE_AREA_ASYNC
        je      0f
-       mvc     __IDLE_EXIT(8,%r2),__LC_MCCK_CLOCK
-       mvc     __VQ_IDLE_EXIT(8,%r3),__LC_MCCK_ENTER_TIMER
+       mvc     __CLOCK_IDLE_EXIT(8,%r2),__LC_MCCK_CLOCK
+       mvc     __TIMER_IDLE_EXIT(8,%r2),__LC_MCCK_ENTER_TIMER
 0:     # check if stck has been executed
        cl      %r9,BASED(cleanup_idle_insn)
        jhe     1f
-       mvc     __IDLE_ENTER(8,%r2),__IDLE_EXIT(%r2)
-       mvc     __VQ_IDLE_ENTER(8,%r3),__VQ_IDLE_EXIT(%r3)
-       j       2f
-1:     # check if the cpu timer has been reprogrammed
-       ltr     %r5,%r5
-       jz      2f
-       spt     __VQ_IDLE_ENTER(%r3)
-2:     # account system time going idle
+       mvc     __CLOCK_IDLE_ENTER(8,%r2),__CLOCK_IDLE_EXIT(%r2)
+       mvc     __TIMER_IDLE_ENTER(8,%r2),__TIMER_IDLE_EXIT(%r3)
+1:     # account system time going idle
        lm      %r9,%r10,__LC_STEAL_TIMER
-       ADD64   %r9,%r10,__IDLE_ENTER(%r2)
+       ADD64   %r9,%r10,__CLOCK_IDLE_ENTER(%r2)
        SUB64   %r9,%r10,__LC_LAST_UPDATE_CLOCK
        stm     %r9,%r10,__LC_STEAL_TIMER
-       mvc     __LC_LAST_UPDATE_CLOCK(8),__IDLE_EXIT(%r2)
+       mvc     __LC_LAST_UPDATE_CLOCK(8),__CLOCK_IDLE_EXIT(%r2)
        lm      %r9,%r10,__LC_SYSTEM_TIMER
        ADD64   %r9,%r10,__LC_LAST_UPDATE_TIMER
-       SUB64   %r9,%r10,__VQ_IDLE_ENTER(%r3)
+       SUB64   %r9,%r10,__TIMER_IDLE_ENTER(%r2)
        stm     %r9,%r10,__LC_SYSTEM_TIMER
-       mvc     __LC_LAST_UPDATE_TIMER(8),__VQ_IDLE_EXIT(%r3)
+       mvc     __LC_LAST_UPDATE_TIMER(8),__TIMER_IDLE_EXIT(%r2)
        # prepare return psw
        n       %r8,BASED(cleanup_idle_wait)    # clear wait state bit
        l       %r9,24(%r11)                    # return from psw_idle
index f66a229ab0b3fdf52308cb55c0ab627ef9564a7b..a5f4dc42a5db18843e54972cfdfb28216a30daa2 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/signal.h>
 #include <asm/ptrace.h>
 #include <asm/cputime.h>
-#include <asm/timer.h>
 
 extern void (*pgm_check_table[128])(struct pt_regs *);
 extern void *restart_stack;
@@ -17,8 +16,7 @@ void io_int_handler(void);
 void mcck_int_handler(void);
 void restart_int_handler(void);
 void restart_call_handler(void);
-void psw_idle(struct s390_idle_data *, struct vtimer_queue *,
-             unsigned long, int);
+void psw_idle(struct s390_idle_data *, unsigned long);
 
 asmlinkage long do_syscall_trace_enter(struct pt_regs *regs);
 asmlinkage void do_syscall_trace_exit(struct pt_regs *regs);
index 229fe1d07749ffa33944132fa1c9af0b221e977c..349b7eeb348a9ee9b2f4aac83ae1c4be0a728a27 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  arch/s390/kernel/entry64.S
  *    S390 low-level entry points.
  *
- *    Copyright (C) IBM Corp. 1999,2012
+ *    Copyright IBM Corp. 1999, 2012
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *              Hartmut Penner (hp@de.ibm.com),
  *              Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
@@ -18,6 +17,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/unistd.h>
 #include <asm/page.h>
+#include <asm/sigp.h>
 
 __PT_R0      = __PT_GPRS
 __PT_R1      = __PT_GPRS + 8
@@ -642,15 +642,11 @@ ext_skip:
  * Load idle PSW. The second "half" of this function is in cleanup_idle.
  */
 ENTRY(psw_idle)
-       stg     %r4,__SF_EMPTY(%r15)
+       stg     %r3,__SF_EMPTY(%r15)
        larl    %r1,psw_idle_lpsw+4
        stg     %r1,__SF_EMPTY+8(%r15)
-       larl    %r1,.Lvtimer_max
-       STCK    __IDLE_ENTER(%r2)
-       ltr     %r5,%r5
-       stpt    __VQ_IDLE_ENTER(%r3)
-       jz      psw_idle_lpsw
-       spt     0(%r1)
+       STCK    __CLOCK_IDLE_ENTER(%r2)
+       stpt    __TIMER_IDLE_ENTER(%r2)
 psw_idle_lpsw:
        lpswe   __SF_EMPTY(%r15)
        br      %r14
@@ -750,15 +746,17 @@ ENTRY(restart_int_handler)
        mvc     __PT_PSW(16,%r15),__LC_RST_OLD_PSW # store restart old psw
        aghi    %r15,-STACK_FRAME_OVERHEAD      # create stack frame on stack
        xc      0(STACK_FRAME_OVERHEAD,%r15),0(%r15)
-       lmg     %r1,%r3,__LC_RESTART_FN         # load fn, parm & source cpu
+       lg      %r1,__LC_RESTART_FN             # load fn, parm & source cpu
+       lg      %r2,__LC_RESTART_DATA
+       lg      %r3,__LC_RESTART_SOURCE
        ltgr    %r3,%r3                         # test source cpu address
        jm      1f                              # negative -> skip source stop
-0:     sigp    %r4,%r3,1                       # sigp sense to source cpu
+0:     sigp    %r4,%r3,SIGP_SENSE              # sigp sense to source cpu
        brc     10,0b                           # wait for status stored
 1:     basr    %r14,%r1                        # call function
        stap    __SF_EMPTY(%r15)                # store cpu address
        llgh    %r3,__SF_EMPTY(%r15)
-2:     sigp    %r4,%r3,5                       # sigp stop to current cpu
+2:     sigp    %r4,%r3,SIGP_STOP               # sigp stop to current cpu
        brc     2,2b
 3:     j       3b
 
@@ -916,33 +914,28 @@ cleanup_io_restore_insn:
 
 cleanup_idle:
        # copy interrupt clock & cpu timer
-       mvc     __IDLE_EXIT(8,%r2),__LC_INT_CLOCK
-       mvc     __VQ_IDLE_EXIT(8,%r3),__LC_ASYNC_ENTER_TIMER
+       mvc     __CLOCK_IDLE_EXIT(8,%r2),__LC_INT_CLOCK
+       mvc     __TIMER_IDLE_EXIT(8,%r2),__LC_ASYNC_ENTER_TIMER
        cghi    %r11,__LC_SAVE_AREA_ASYNC
        je      0f
-       mvc     __IDLE_EXIT(8,%r2),__LC_MCCK_CLOCK
-       mvc     __VQ_IDLE_EXIT(8,%r3),__LC_MCCK_ENTER_TIMER
+       mvc     __CLOCK_IDLE_EXIT(8,%r2),__LC_MCCK_CLOCK
+       mvc     __TIMER_IDLE_EXIT(8,%r2),__LC_MCCK_ENTER_TIMER
 0:     # check if stck & stpt have been executed
        clg     %r9,BASED(cleanup_idle_insn)
        jhe     1f
-       mvc     __IDLE_ENTER(8,%r2),__IDLE_EXIT(%r2)
-       mvc     __VQ_IDLE_ENTER(8,%r3),__VQ_IDLE_EXIT(%r3)
-       j       2f
-1:     # check if the cpu timer has been reprogrammed
-       ltr     %r5,%r5
-       jz      2f
-       spt     __VQ_IDLE_ENTER(%r3)
-2:     # account system time going idle
+       mvc     __CLOCK_IDLE_ENTER(8,%r2),__CLOCK_IDLE_EXIT(%r2)
+       mvc     __TIMER_IDLE_ENTER(8,%r2),__TIMER_IDLE_EXIT(%r2)
+1:     # account system time going idle
        lg      %r9,__LC_STEAL_TIMER
-       alg     %r9,__IDLE_ENTER(%r2)
+       alg     %r9,__CLOCK_IDLE_ENTER(%r2)
        slg     %r9,__LC_LAST_UPDATE_CLOCK
        stg     %r9,__LC_STEAL_TIMER
-       mvc     __LC_LAST_UPDATE_CLOCK(8),__IDLE_EXIT(%r2)
+       mvc     __LC_LAST_UPDATE_CLOCK(8),__CLOCK_IDLE_EXIT(%r2)
        lg      %r9,__LC_SYSTEM_TIMER
        alg     %r9,__LC_LAST_UPDATE_TIMER
-       slg     %r9,__VQ_IDLE_ENTER(%r3)
+       slg     %r9,__TIMER_IDLE_ENTER(%r2)
        stg     %r9,__LC_SYSTEM_TIMER
-       mvc     __LC_LAST_UPDATE_TIMER(8),__VQ_IDLE_EXIT(%r3)
+       mvc     __LC_LAST_UPDATE_TIMER(8),__TIMER_IDLE_EXIT(%r2)
        # prepare return psw
        nihh    %r8,0xfffd              # clear wait state bit
        lg      %r9,48(%r11)            # return from psw_idle
@@ -958,8 +951,6 @@ cleanup_idle_insn:
        .quad   __critical_start
 .Lcritical_length:
        .quad   __critical_end - __critical_start
-.Lvtimer_max:
-       .quad   0x7fffffffffffffff
 
 
 #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE)
@@ -974,7 +965,6 @@ ENTRY(sie64a)
        stg     %r3,__SF_EMPTY+8(%r15)          # save guest register save area
        xc      __SF_EMPTY+16(8,%r15),__SF_EMPTY+16(%r15) # host id == 0
        lmg     %r0,%r13,0(%r3)                 # load guest gprs 0-13
-       lg      %r14,__LC_THREAD_INFO           # pointer thread_info struct
 sie_loop:
        lg      %r14,__LC_THREAD_INFO           # pointer thread_info struct
        tm      __TI_flags+7(%r14),_TIF_EXIT_SIE
index 4939d15375aac4702d8afc384391528b26c10bb8..805b6686b641dacf24afd15e4e34ee61d42cac8b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright IBM Corp. 1999,2010
+ * Copyright IBM Corp. 1999, 2010
  *
  *    Author(s): Hartmut Penner <hp@de.ibm.com>
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>
index d3f1ab7d90ada12d5a7a4a59bc98bcfa245c3c71..a1372ae24ae111229cc532a1f638abfc9f0b75f8 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * arch/s390/kernel/head31.S
- *
- * Copyright (C) IBM Corp. 2005,2010
+ * Copyright IBM Corp. 2005, 2010
  *
  *   Author(s):        Hartmut Penner <hp@de.ibm.com>
  *             Martin Schwidefsky <schwidefsky@de.ibm.com>
index 99348c0eaa4105a8e8e000be3182911da58b61a7..c108af28bbe890b95ec606300b1129e893071b87 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * arch/s390/kernel/head64.S
- *
- * Copyright (C) IBM Corp. 1999,2010
+ * Copyright IBM Corp. 1999, 2010
  *
  *   Author(s):        Hartmut Penner <hp@de.ibm.com>
  *             Martin Schwidefsky <schwidefsky@de.ibm.com>
index 796c976b5fdc1b49a6d82e5a9a7cf19906a9443c..acaaaf4b7055e2d50122f43e6f695771a6f781cd 100644 (file)
@@ -5,6 +5,8 @@
  * Author(s): Michael Holzheu <holzheu@linux.vnet.ibm.com>
  */
 
+#include <asm/sigp.h>
+
 #define DATAMOVER_ADDR 0x4000
 #define COPY_PAGE_ADDR 0x6000
 
@@ -19,7 +21,7 @@
 .align 2
 .Lep_startup_kdump:
        lhi     %r1,2                           # mode 2 = esame (dump)
-       sigp    %r1,%r0,0x12                    # Switch to esame mode
+       sigp    %r1,%r0,SIGP_SET_ARCHITECTURE   # Switch to esame mode
        sam64                                   # Switch to 64 bit addressing
        basr    %r13,0
 .Lbase:
@@ -88,7 +90,7 @@ startup_kdump_relocated:
        sam31                                   # Switch to 31 bit addr mode
        sr      %r1,%r1                         # Erase register r1
        sr      %r2,%r2                         # Erase register r2
-       sigp    %r1,%r2,0x12                    # Switch to 31 bit arch mode
+       sigp    %r1,%r2,SIGP_SET_ARCHITECTURE   # Switch to 31 bit arch mode
        lpsw    0                               # Start new kernel...
 .align 8
 .Lrestart_psw:
index 2f6cfd460cb6ad5a04fd033ea7f515b49ba3e487..e64d141555ce99843f4995827f4644e1dc127c79 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  arch/s390/kernel/ipl.c
  *    ipl/reipl/dump support for Linux on s390.
  *
- *    Copyright IBM Corp. 2005,2012
+ *    Copyright IBM Corp. 2005, 2012
  *    Author(s): Michael Holzheu <holzheu@de.ibm.com>
  *              Heiko Carstens <heiko.carstens@de.ibm.com>
  *              Volker Sameske <sameske@de.ibm.com>
@@ -1528,15 +1527,12 @@ static struct shutdown_action __refdata dump_action = {
 
 static void dump_reipl_run(struct shutdown_trigger *trigger)
 {
-       struct {
-               void    *addr;
-               __u32   csum;
-       } __packed ipib;
+       unsigned long ipib = (unsigned long) reipl_block_actual;
+       unsigned int csum;
 
-       ipib.csum = csum_partial(reipl_block_actual,
-                                reipl_block_actual->hdr.len, 0);
-       ipib.addr = reipl_block_actual;
-       memcpy_absolute(&S390_lowcore.ipib, &ipib, sizeof(ipib));
+       csum = csum_partial(reipl_block_actual, reipl_block_actual->hdr.len, 0);
+       mem_assign_absolute(S390_lowcore.ipib, ipib);
+       mem_assign_absolute(S390_lowcore.ipib_checksum, csum);
        dump_run(trigger);
 }
 
index b4f4a7133fa10e3456b82f7f27fc8fbf70d942ed..dd7630d8aab7ce11ca405fb0c6da17f51b4998d6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2004,2011
+ *    Copyright IBM Corp. 2004, 2011
  *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
  *              Holger Smolinski <Holger.Smolinski@de.ibm.com>,
  *              Thomas Spatzier <tspat@de.ibm.com>,
index 64b761aef004a29a33eec80f49cd26fc5ec7c7ec..8aa634f5944b4be9f4f6a1d810de9a2d65e26f7b 100644 (file)
@@ -15,7 +15,7 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  *
- * Copyright (C) IBM Corporation, 2002, 2006
+ * Copyright IBM Corp. 2002, 2006
  *
  * s390 port, used ppc64 as template. Mike Grundy <grundym@us.ibm.com>
  */
index 87f080b17af103f1aa6d2977c9a7266ae87d3ed8..eca94e74d19aa77dfe437a753b4951fd50dd0da3 100644 (file)
@@ -45,7 +45,7 @@ struct lgr_info {
 /*
  * LGR globals
  */
-static void *lgr_page;
+static char lgr_page[PAGE_SIZE] __aligned(PAGE_SIZE);
 static struct lgr_info lgr_info_last;
 static struct lgr_info lgr_info_cur;
 static struct debug_info *lgr_dbf;
@@ -74,7 +74,7 @@ static void cpascii(char *dst, char *src, int size)
  */
 static void lgr_stsi_1_1_1(struct lgr_info *lgr_info)
 {
-       struct sysinfo_1_1_1 *si = lgr_page;
+       struct sysinfo_1_1_1 *si = (void *) lgr_page;
 
        if (stsi(si, 1, 1, 1) == -ENOSYS)
                return;
@@ -91,7 +91,7 @@ static void lgr_stsi_1_1_1(struct lgr_info *lgr_info)
  */
 static void lgr_stsi_2_2_2(struct lgr_info *lgr_info)
 {
-       struct sysinfo_2_2_2 *si = lgr_page;
+       struct sysinfo_2_2_2 *si = (void *) lgr_page;
 
        if (stsi(si, 2, 2, 2) == -ENOSYS)
                return;
@@ -105,7 +105,7 @@ static void lgr_stsi_2_2_2(struct lgr_info *lgr_info)
  */
 static void lgr_stsi_3_2_2(struct lgr_info *lgr_info)
 {
-       struct sysinfo_3_2_2 *si = lgr_page;
+       struct sysinfo_3_2_2 *si = (void *) lgr_page;
        int i;
 
        if (stsi(si, 3, 2, 2) == -ENOSYS)
@@ -183,14 +183,9 @@ static void lgr_timer_set(void)
  */
 static int __init lgr_init(void)
 {
-       lgr_page = (void *) __get_free_pages(GFP_KERNEL, 0);
-       if (!lgr_page)
-               return -ENOMEM;
        lgr_dbf = debug_register("lgr", 1, 1, sizeof(struct lgr_info));
-       if (!lgr_dbf) {
-               free_page((unsigned long) lgr_page);
+       if (!lgr_dbf)
                return -ENOMEM;
-       }
        debug_register_view(lgr_dbf, &debug_hex_ascii_view);
        lgr_info_get(&lgr_info_last);
        debug_event(lgr_dbf, 1, &lgr_info_last, sizeof(lgr_info_last));
index cdacf8f91b2d11b7cb3acd683f7a8db830c6fb05..493304bdf1c7845c34c632b33361b6468126c7a6 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * arch/s390/kernel/machine_kexec.c
- *
- * Copyright IBM Corp. 2005,2011
+ * Copyright IBM Corp. 2005, 2011
  *
  * Author(s): Rolf Adelsberger,
  *           Heiko Carstens <heiko.carstens@de.ibm.com>
index 7e2c38ba13732317062f9b1f226adec6ef986f6e..4567ce20d900c128a23d27a6b8668b72d921149f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright IBM Corp. 2008,2009
+ * Copyright IBM Corp. 2008, 2009
  *
  *   Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
  *
index f70cadec68fccbcc12e60776aaa092fdc6239a05..11332193db30552a7d028de8debf6af8e019531b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright IBM Corp. 2008,2009
+ * Copyright IBM Corp. 2008, 2009
  *
  *   Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>,
  *
index dfcb3436bad069d9dd75290d54c868b92a2d6beb..46412b1d7e1e868243a083faa1a066e17f081c13 100644 (file)
@@ -1,9 +1,8 @@
 /*
- *  arch/s390/kernel/module.c - Kernel module help for s390.
+ *  Kernel module help for s390.
  *
  *  S390 version
- *    Copyright (C) 2002, 2003 IBM Deutschland Entwicklung GmbH,
- *                            IBM Corporation
+ *    Copyright IBM Corp. 2002, 2003
  *    Author(s): Arnd Bergmann (arndb@de.ibm.com)
  *              Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
index 8c372ca613500d93c23daaea586efb9ca585f764..a6daa5c5cdb047708be93a173e47095af9d0f9f4 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   Machine check handler
  *
- *    Copyright IBM Corp. 2000,2009
+ *    Copyright IBM Corp. 2000, 2009
  *    Author(s): Ingo Adlung <adlung@de.ibm.com>,
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>,
  *              Cornelia Huck <cornelia.huck@de.ibm.com>,
index 95fa5ac6c4cedbf6d287ca25708b906cb1f35c4c..46480d81df00029aa395f39861a7d40dd7f49bde 100644 (file)
@@ -60,7 +60,7 @@ void __init os_info_init(void)
        os_info.version_minor = OS_INFO_VERSION_MINOR;
        os_info.magic = OS_INFO_MAGIC;
        os_info.csum = os_info_csum(&os_info);
-       memcpy_absolute(&S390_lowcore.os_info, &ptr, sizeof(ptr));
+       mem_assign_absolute(S390_lowcore.os_info, (unsigned long) ptr);
 }
 
 #ifdef CONFIG_CRASH_DUMP
index 60055cefdd04da2db1d3af3061d80eb50f669e17..733175373a4c6e9a95c204f30f47214d81351f73 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * This file handles the architecture dependent parts of process handling.
  *
- *    Copyright IBM Corp. 1999,2009
+ *    Copyright IBM Corp. 1999, 2009
  *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
  *              Hartmut Penner <hp@de.ibm.com>,
  *              Denis Joseph Barrow,
@@ -25,8 +25,8 @@
 #include <linux/module.h>
 #include <asm/io.h>
 #include <asm/processor.h>
+#include <asm/vtimer.h>
 #include <asm/irq.h>
-#include <asm/timer.h>
 #include <asm/nmi.h>
 #include <asm/smp.h>
 #include <asm/switch_to.h>
index 6e0073e43f5448e8910fae02e973aecfdf1594f8..572d4c9cb33b0dd66641a45568700babe8916215 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  arch/s390/kernel/processor.c
- *
  *  Copyright IBM Corp. 2008
  *  Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
@@ -25,13 +23,15 @@ static DEFINE_PER_CPU(struct cpuid, cpu_id);
  */
 void __cpuinit cpu_init(void)
 {
-       struct cpuid *id = &per_cpu(cpu_id, smp_processor_id());
+       struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
+       struct cpuid *id = &__get_cpu_var(cpu_id);
 
        get_cpu_id(id);
        atomic_inc(&init_mm.mm_count);
        current->active_mm = &init_mm;
        BUG_ON(current->mm);
        enter_lazy_tlb(&init_mm, current);
+       memset(idle, 0, sizeof(*idle));
 }
 
 /*
index 4993e689b2c2bd19135e873234d699c9a2da8f16..f4eb37680b9152b458938ff37b875754823be695 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Ptrace user space interface.
  *
- *    Copyright IBM Corp. 1999,2010
+ *    Copyright IBM Corp. 1999, 2010
  *    Author(s): Denis Joseph Barrow
  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
index ad67c214be047df4c6ddb02f65b0b645de152258..dd8016b0477eae6117c8cae5917e8c59d1fe65d5 100644 (file)
@@ -1,13 +1,12 @@
 /*
- *  arch/s390/kernel/reipl.S
- *
  *  S390 version
- *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2000
  *    Author(s): Holger Smolinski (Holger.Smolinski@de.ibm.com)
  */
 
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
+#include <asm/sigp.h>
 
 #
 # store_status: Empty implementation until kdump is supported on 31 bit
@@ -60,7 +59,7 @@ ENTRY(do_reipl_asm)
                bas     %r14,.Ldisab-.Lpg0(%r13)
 .L003:         st      %r1,__LC_SUBCHANNEL_ID
                lpsw    0
-               sigp    0,0,0(6)
+               sigp    0,0,SIGP_RESTART
 .Ldisab:       st      %r14,.Ldispsw+4-.Lpg0(%r13)
                lpsw    .Ldispsw-.Lpg0(%r13)
                .align  8
index 36b32658fb241146d86d672fd498781b3180e441..dc3b1273c4dc766e752ee48ab69d41ca48b9c8a4 100644 (file)
@@ -1,11 +1,12 @@
 /*
- *    Copyright IBM Corp 2000,2011
+ *    Copyright IBM Corp 2000, 2011
  *    Author(s): Holger Smolinski <Holger.Smolinski@de.ibm.com>,
  *              Denis Joseph Barrow,
  */
 
 #include <linux/linkage.h>
 #include <asm/asm-offsets.h>
+#include <asm/sigp.h>
 
 #
 # store_status
@@ -106,7 +107,7 @@ ENTRY(do_reipl_asm)
 .L003:         st      %r1,__LC_SUBCHANNEL_ID
                lhi     %r1,0            # mode 0 = esa
                slr     %r0,%r0          # set cpuid to zero
-               sigp    %r1,%r0,0x12     # switch to esa mode
+               sigp    %r1,%r0,SIGP_SET_ARCHITECTURE # switch to esa mode
                lpsw    0
 .Ldisab:       sll     %r14,1
                srl     %r14,1           # need to kill hi bit to avoid specification exceptions.
index c91d70aede919e7af075df789f504d571d8c985c..f4e6f20e117a96e4ee37b47fa0ca0a371c0fa95e 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * arch/s390/kernel/relocate_kernel.S
- *
- * (C) Copyright IBM Corp. 2005
+ * Copyright IBM Corp. 2005
  *
  * Author(s): Rolf Adelsberger,
  *           Heiko Carstens <heiko.carstens@de.ibm.com>
@@ -9,6 +7,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/sigp.h>
 
 /*
  * moves the new kernel to its destination...
@@ -93,7 +92,7 @@ ENTRY(relocate_kernel)
        .no_diag308:
                sr      %r1,%r1         # clear %r1
                sr      %r2,%r2         # clear %r2
-               sigp    %r1,%r2,0x12    # set cpuid to zero
+               sigp    %r1,%r2,SIGP_SET_ARCHITECTURE # set cpuid to zero
                lpsw    0               # hopefully start new kernel...
 
                .align  8
index 7c3ce589a7f0cdb3ceef2b08d24977b504f80a23..cfac28330b03f271726bf8b1d61ee74c7ceac5a7 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * arch/s390/kernel/relocate_kernel64.S
- *
- * (C) Copyright IBM Corp. 2005
+ * Copyright IBM Corp. 2005
  *
  * Author(s): Rolf Adelsberger,
  *           Heiko Carstens <heiko.carstens@de.ibm.com>
@@ -9,6 +7,7 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/sigp.h>
 
 /*
  * moves the new kernel to its destination...
@@ -45,7 +44,7 @@ ENTRY(relocate_kernel)
                diag    %r0,%r0,0x308
        .back:
                lhi     %r1,1           # mode 1 = esame
-               sigp    %r1,%r0,0x12    # switch to esame mode
+               sigp    %r1,%r0,SIGP_SET_ARCHITECTURE # switch to esame mode
                sam64                   # switch to 64 bit addressing mode
                basr    %r13,0
        .back_base:
@@ -96,7 +95,7 @@ ENTRY(relocate_kernel)
                sam31                   # 31 bit mode
                sr      %r1,%r1         # erase register r1
                sr      %r2,%r2         # erase register r2
-               sigp    %r1,%r2,0x12    # set cpuid to zero
+               sigp    %r1,%r2,SIGP_SET_ARCHITECTURE # set cpuid to zero
                lpsw    0               # hopefully start new kernel...
 
                .align  8
index 95792d846bb6996d531afa16c88d769a1d0a115d..bf053898630de935aa4bcbd875c62a405169384c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Mini SCLP driver.
  *
- * Copyright IBM Corp. 2004,2009
+ * Copyright IBM Corp. 2004, 2009
  *
  *   Author(s):        Peter Oberparleiter <Peter.Oberparleiter@de.ibm.com>,
  *             Heiko Carstens <heiko.carstens@de.ibm.com>,
index 489d1d8d96b068f63b61886ee3c55d50f52b3913..34d75b50526c471380744c1cf99718c6130e6132 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  arch/s390/kernel/setup.c
- *
  *  S390 version
- *    Copyright (C) IBM Corp. 1999,2012
+ *    Copyright IBM Corp. 1999, 2012
  *    Author(s): Hartmut Penner (hp@de.ibm.com),
  *               Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
@@ -430,10 +428,11 @@ static void __init setup_lowcore(void)
        lc->restart_source = -1UL;
 
        /* Setup absolute zero lowcore */
-       memcpy_absolute(&S390_lowcore.restart_stack, &lc->restart_stack,
-                       4 * sizeof(unsigned long));
-       memcpy_absolute(&S390_lowcore.restart_psw, &lc->restart_psw,
-                       sizeof(lc->restart_psw));
+       mem_assign_absolute(S390_lowcore.restart_stack, lc->restart_stack);
+       mem_assign_absolute(S390_lowcore.restart_fn, lc->restart_fn);
+       mem_assign_absolute(S390_lowcore.restart_data, lc->restart_data);
+       mem_assign_absolute(S390_lowcore.restart_source, lc->restart_source);
+       mem_assign_absolute(S390_lowcore.restart_psw, lc->restart_psw);
 
        set_prefix((u32)(unsigned long) lc);
        lowcore_ptr[0] = lc;
@@ -598,9 +597,7 @@ static void __init setup_memory_end(void)
 static void __init setup_vmcoreinfo(void)
 {
 #ifdef CONFIG_KEXEC
-       unsigned long ptr = paddr_vmcoreinfo_note();
-
-       memcpy_absolute(&S390_lowcore.vmcore_info, &ptr, sizeof(ptr));
+       mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note());
 #endif
 }
 
index ac565b44aabbf76c23da00540f8f2884e06f07a6..c13a2a37ef007b2634a508b7053b0c3cc12e30b2 100644 (file)
@@ -1,7 +1,5 @@
 /*
- *  arch/s390/kernel/signal.c
- *
- *    Copyright (C) IBM Corp. 1999,2006
+ *    Copyright IBM Corp. 1999, 2006
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  *
  *    Based on Intel version
index 15cca26ccb6c4ff1cbde51c60259a7ec95471718..720fda1620f29119f56f437fafef8f04657cc893 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  SMP related functions
  *
- *    Copyright IBM Corp. 1999,2012
+ *    Copyright IBM Corp. 1999, 2012
  *    Author(s): Denis Joseph Barrow,
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>,
  *              Heiko Carstens <heiko.carstens@de.ibm.com>,
 #include <asm/setup.h>
 #include <asm/irq.h>
 #include <asm/tlbflush.h>
-#include <asm/timer.h>
+#include <asm/vtimer.h>
 #include <asm/lowcore.h>
 #include <asm/sclp.h>
 #include <asm/vdso.h>
 #include <asm/debug.h>
 #include <asm/os_info.h>
+#include <asm/sigp.h>
 #include "entry.h"
 
-enum {
-       sigp_sense = 1,
-       sigp_external_call = 2,
-       sigp_emergency_signal = 3,
-       sigp_start = 4,
-       sigp_stop = 5,
-       sigp_restart = 6,
-       sigp_stop_and_store_status = 9,
-       sigp_initial_cpu_reset = 11,
-       sigp_cpu_reset = 12,
-       sigp_set_prefix = 13,
-       sigp_store_status_at_address = 14,
-       sigp_store_extended_status_at_address = 15,
-       sigp_set_architecture = 18,
-       sigp_conditional_emergency_signal = 19,
-       sigp_sense_running = 21,
-};
-
-enum {
-       sigp_order_code_accepted = 0,
-       sigp_status_stored = 1,
-       sigp_busy = 2,
-       sigp_not_operational = 3,
-};
-
 enum {
        ec_schedule = 0,
        ec_call_function,
@@ -124,7 +100,7 @@ static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status)
 
        while (1) {
                cc = __pcpu_sigp(addr, order, parm, status);
-               if (cc != sigp_busy)
+               if (cc != SIGP_CC_BUSY)
                        return cc;
                cpu_relax();
        }
@@ -136,7 +112,7 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm)
 
        for (retry = 0; ; retry++) {
                cc = __pcpu_sigp(pcpu->address, order, parm, &pcpu->status);
-               if (cc != sigp_busy)
+               if (cc != SIGP_CC_BUSY)
                        break;
                if (retry >= 3)
                        udelay(10);
@@ -146,20 +122,19 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm)
 
 static inline int pcpu_stopped(struct pcpu *pcpu)
 {
-       if (__pcpu_sigp(pcpu->address, sigp_sense,
-                       0, &pcpu->status) != sigp_status_stored)
+       if (__pcpu_sigp(pcpu->address, SIGP_SENSE,
+                       0, &pcpu->status) != SIGP_CC_STATUS_STORED)
                return 0;
-       /* Check for stopped and check stop state */
-       return !!(pcpu->status & 0x50);
+       return !!(pcpu->status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED));
 }
 
 static inline int pcpu_running(struct pcpu *pcpu)
 {
-       if (__pcpu_sigp(pcpu->address, sigp_sense_running,
-                       0, &pcpu->status) != sigp_status_stored)
+       if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING,
+                       0, &pcpu->status) != SIGP_CC_STATUS_STORED)
                return 1;
-       /* Check for running status */
-       return !(pcpu->status & 0x400);
+       /* Status stored condition code is equivalent to cpu not running. */
+       return 0;
 }
 
 /*
@@ -181,7 +156,7 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit)
 
        set_bit(ec_bit, &pcpu->ec_mask);
        order = pcpu_running(pcpu) ?
-               sigp_external_call : sigp_emergency_signal;
+               SIGP_EXTERNAL_CALL : SIGP_EMERGENCY_SIGNAL;
        pcpu_sigp_retry(pcpu, order, 0);
 }
 
@@ -214,7 +189,7 @@ static int __cpuinit pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)
                goto out;
 #endif
        lowcore_ptr[cpu] = lc;
-       pcpu_sigp_retry(pcpu, sigp_set_prefix, (u32)(unsigned long) lc);
+       pcpu_sigp_retry(pcpu, SIGP_SET_PREFIX, (u32)(unsigned long) lc);
        return 0;
 out:
        if (pcpu != &pcpu_devices[0]) {
@@ -229,7 +204,7 @@ out:
 
 static void pcpu_free_lowcore(struct pcpu *pcpu)
 {
-       pcpu_sigp_retry(pcpu, sigp_set_prefix, 0);
+       pcpu_sigp_retry(pcpu, SIGP_SET_PREFIX, 0);
        lowcore_ptr[pcpu - pcpu_devices] = NULL;
 #ifndef CONFIG_64BIT
        if (MACHINE_HAS_IEEE) {
@@ -288,7 +263,7 @@ static void pcpu_start_fn(struct pcpu *pcpu, void (*func)(void *), void *data)
        lc->restart_fn = (unsigned long) func;
        lc->restart_data = (unsigned long) data;
        lc->restart_source = -1UL;
-       pcpu_sigp_retry(pcpu, sigp_restart, 0);
+       pcpu_sigp_retry(pcpu, SIGP_RESTART, 0);
 }
 
 /*
@@ -298,26 +273,26 @@ static void pcpu_delegate(struct pcpu *pcpu, void (*func)(void *),
                          void *data, unsigned long stack)
 {
        struct _lowcore *lc = lowcore_ptr[pcpu - pcpu_devices];
-       struct {
-               unsigned long   stack;
-               void            *func;
-               void            *data;
-               unsigned long   source;
-       } restart = { stack, func, data, stap() };
+       unsigned long source_cpu = stap();
 
        __load_psw_mask(psw_kernel_bits);
-       if (pcpu->address == restart.source)
+       if (pcpu->address == source_cpu)
                func(data);     /* should not return */
        /* Stop target cpu (if func returns this stops the current cpu). */
-       pcpu_sigp_retry(pcpu, sigp_stop, 0);
+       pcpu_sigp_retry(pcpu, SIGP_STOP, 0);
        /* Restart func on the target cpu and stop the current cpu. */
-       memcpy_absolute(&lc->restart_stack, &restart, sizeof(restart));
+       mem_assign_absolute(lc->restart_stack, stack);
+       mem_assign_absolute(lc->restart_fn, (unsigned long) func);
+       mem_assign_absolute(lc->restart_data, (unsigned long) data);
+       mem_assign_absolute(lc->restart_source, source_cpu);
        asm volatile(
-               "0:     sigp    0,%0, # sigp restart to target cpu\n"
+               "0:     sigp    0,%0,%2 # sigp restart to target cpu\n"
                "       brc     2,0b    # busy, try again\n"
-               "1:     sigp    0,%1, # sigp stop to current cpu\n"
+               "1:     sigp    0,%1,%3 # sigp stop to current cpu\n"
                "       brc     2,1b    # busy, try again\n"
-               : : "d" (pcpu->address), "d" (restart.source) : "0", "1", "cc");
+               : : "d" (pcpu->address), "d" (source_cpu),
+                   "K" (SIGP_RESTART), "K" (SIGP_STOP)
+               : "0", "1", "cc");
        for (;;) ;
 }
 
@@ -388,8 +363,8 @@ void smp_emergency_stop(cpumask_t *cpumask)
        for_each_cpu(cpu, cpumask) {
                struct pcpu *pcpu = pcpu_devices + cpu;
                set_bit(ec_stop_cpu, &pcpu->ec_mask);
-               while (__pcpu_sigp(pcpu->address, sigp_emergency_signal,
-                                  0, NULL) == sigp_busy &&
+               while (__pcpu_sigp(pcpu->address, SIGP_EMERGENCY_SIGNAL,
+                                  0, NULL) == SIGP_CC_BUSY &&
                       get_clock() < end)
                        cpu_relax();
        }
@@ -425,7 +400,7 @@ void smp_send_stop(void)
        /* stop all processors */
        for_each_cpu(cpu, &cpumask) {
                struct pcpu *pcpu = pcpu_devices + cpu;
-               pcpu_sigp_retry(pcpu, sigp_stop, 0);
+               pcpu_sigp_retry(pcpu, SIGP_STOP, 0);
                while (!pcpu_stopped(pcpu))
                        cpu_relax();
        }
@@ -436,7 +411,7 @@ void smp_send_stop(void)
  */
 void smp_stop_cpu(void)
 {
-       pcpu_sigp_retry(pcpu_devices + smp_processor_id(), sigp_stop, 0);
+       pcpu_sigp_retry(pcpu_devices + smp_processor_id(), SIGP_STOP, 0);
        for (;;) ;
 }
 
@@ -590,7 +565,7 @@ static void __init smp_get_save_area(int cpu, u16 address)
        }
 #endif
        /* Get the registers of a non-boot cpu. */
-       __pcpu_sigp_relax(address, sigp_stop_and_store_status, 0, NULL);
+       __pcpu_sigp_relax(address, SIGP_STOP_AND_STORE_STATUS, 0, NULL);
        memcpy_real(save_area, lc + SAVE_AREA_BASE, sizeof(*save_area));
 }
 
@@ -599,8 +574,8 @@ int smp_store_status(int cpu)
        struct pcpu *pcpu;
 
        pcpu = pcpu_devices + cpu;
-       if (__pcpu_sigp_relax(pcpu->address, sigp_stop_and_store_status,
-                             0, NULL) != sigp_order_code_accepted)
+       if (__pcpu_sigp_relax(pcpu->address, SIGP_STOP_AND_STORE_STATUS,
+                             0, NULL) != SIGP_CC_ORDER_CODE_ACCEPTED)
                return -EIO;
        return 0;
 }
@@ -621,8 +596,8 @@ static struct sclp_cpu_info *smp_get_cpu_info(void)
        if (info && (use_sigp_detection || sclp_get_cpu_info(info))) {
                use_sigp_detection = 1;
                for (address = 0; address <= MAX_CPU_ADDRESS; address++) {
-                       if (__pcpu_sigp_relax(address, sigp_sense, 0, NULL) ==
-                           sigp_not_operational)
+                       if (__pcpu_sigp_relax(address, SIGP_SENSE, 0, NULL) ==
+                           SIGP_CC_NOT_OPERATIONAL)
                                continue;
                        info->cpu[info->configured].address = address;
                        info->configured++;
@@ -717,9 +692,7 @@ static void __cpuinit smp_start_secondary(void *cpuvoid)
        init_cpu_vtimer();
        pfault_init();
        notify_cpu_starting(smp_processor_id());
-       ipi_call_lock();
        set_cpu_online(smp_processor_id(), true);
-       ipi_call_unlock();
        local_irq_enable();
        /* cpu_idle will call schedule for us */
        cpu_idle();
@@ -734,8 +707,8 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
        pcpu = pcpu_devices + cpu;
        if (pcpu->state != CPU_STATE_CONFIGURED)
                return -EIO;
-       if (pcpu_sigp_retry(pcpu, sigp_initial_cpu_reset, 0) !=
-           sigp_order_code_accepted)
+       if (pcpu_sigp_retry(pcpu, SIGP_INITIAL_CPU_RESET, 0) !=
+           SIGP_CC_ORDER_CODE_ACCEPTED)
                return -EIO;
 
        rc = pcpu_alloc_lowcore(pcpu, cpu);
@@ -795,7 +768,7 @@ void __cpu_die(unsigned int cpu)
 void __noreturn cpu_die(void)
 {
        idle_task_exit();
-       pcpu_sigp_retry(pcpu_devices + smp_processor_id(), sigp_stop, 0);
+       pcpu_sigp_retry(pcpu_devices + smp_processor_id(), SIGP_STOP, 0);
        for (;;) ;
 }
 
@@ -942,7 +915,7 @@ static ssize_t show_idle_count(struct device *dev,
        do {
                sequence = ACCESS_ONCE(idle->sequence);
                idle_count = ACCESS_ONCE(idle->idle_count);
-               if (ACCESS_ONCE(idle->idle_enter))
+               if (ACCESS_ONCE(idle->clock_idle_enter))
                        idle_count++;
        } while ((sequence & 1) || (idle->sequence != sequence));
        return sprintf(buf, "%llu\n", idle_count);
@@ -960,8 +933,8 @@ static ssize_t show_idle_time(struct device *dev,
                now = get_clock();
                sequence = ACCESS_ONCE(idle->sequence);
                idle_time = ACCESS_ONCE(idle->idle_time);
-               idle_enter = ACCESS_ONCE(idle->idle_enter);
-               idle_exit = ACCESS_ONCE(idle->idle_exit);
+               idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
+               idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
        } while ((sequence & 1) || (idle->sequence != sequence));
        idle_time += idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
        return sprintf(buf, "%llu\n", idle_time >> 12);
@@ -984,14 +957,11 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self,
        unsigned int cpu = (unsigned int)(long)hcpu;
        struct cpu *c = &pcpu_devices[cpu].cpu;
        struct device *s = &c->dev;
-       struct s390_idle_data *idle;
        int err = 0;
 
        switch (action) {
        case CPU_ONLINE:
        case CPU_ONLINE_FROZEN:
-               idle = &per_cpu(s390_idle, cpu);
-               memset(idle, 0, sizeof(struct s390_idle_data));
                err = sysfs_create_group(&s->kobj, &cpu_online_attr_group);
                break;
        case CPU_DEAD:
index 8841919ef7e64b9417f8fc8934403970a47644f8..1785cd82253caec869abbb7f5d7804b42effad04 100644 (file)
@@ -1,9 +1,7 @@
 /*
- * arch/s390/kernel/stacktrace.c
- *
  * Stack trace management functions
  *
- *  Copyright (C) IBM Corp. 2006
+ *  Copyright IBM Corp. 2006
  *  Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
index dd70ef046058b22c2dc35a959a0793eaafb4b23b..d4ca4e0617b52ae12e039a6110ef4872f9de07ee 100644 (file)
@@ -12,6 +12,7 @@
 #include <asm/ptrace.h>
 #include <asm/thread_info.h>
 #include <asm/asm-offsets.h>
+#include <asm/sigp.h>
 
 /*
  * Save register context in absolute 0 lowcore and call swsusp_save() to
@@ -163,7 +164,7 @@ ENTRY(swsusp_arch_resume)
        diag    %r0,%r0,0x308
 restart_entry:
        lhi     %r1,1
-       sigp    %r1,%r0,0x12
+       sigp    %r1,%r0,SIGP_SET_ARCHITECTURE
        sam64
        larl    %r1,.Lnew_pgm_check_psw
        lpswe   0(%r1)
@@ -179,7 +180,7 @@ pgm_check_entry:
        larl    %r4,.Lrestart_suspend_psw       /* Set new restart PSW */
        mvc     __LC_RST_NEW_PSW(16,%r0),0(%r4)
 3:
-       sigp    %r9,%r1,11                      /* sigp initial cpu reset */
+       sigp    %r9,%r1,SIGP_INITIAL_CPU_RESET  /* sigp initial cpu reset */
        brc     8,4f                            /* accepted */
        brc     2,3b                            /* busy, try again */
 
@@ -190,16 +191,16 @@ pgm_check_entry:
        larl    %r3,_sclp_print_early
        lghi    %r1,0
        sam31
-       sigp    %r1,%r0,0x12
+       sigp    %r1,%r0,SIGP_SET_ARCHITECTURE
        basr    %r14,%r3
        larl    %r3,.Ldisabled_wait_31
        lpsw    0(%r3)
 4:
        /* Switch to suspend CPU */
-       sigp    %r9,%r1,6               /* sigp restart to suspend CPU */
+       sigp    %r9,%r1,SIGP_RESTART    /* sigp restart to suspend CPU */
        brc     2,4b                    /* busy, try again */
 5:
-       sigp    %r9,%r2,5               /* sigp stop to current resume CPU */
+       sigp    %r9,%r2,SIGP_STOP       /* sigp stop to current resume CPU */
        brc     2,5b                    /* busy, try again */
 6:     j       6b
 
@@ -207,7 +208,7 @@ restart_suspend:
        larl    %r1,.Lresume_cpu
        llgh    %r2,0(%r1)
 7:
-       sigp    %r9,%r2,1               /* sigp sense, wait for resume CPU */
+       sigp    %r9,%r2,SIGP_SENSE      /* sigp sense, wait for resume CPU */
        brc     8,7b                    /* accepted, status 0, still running */
        brc     2,7b                    /* busy, try again */
        tmll    %r9,0x40                /* Test if resume CPU is stopped */
index 78ea1948ff514f4e20df0686f38308427644fe21..b4a29eee41b8d59a7542ce040019a62b0e5f4be8 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  arch/s390/kernel/sys_s390.c
- *
  *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999, 2000
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Thomas Spatzier (tspat@de.ibm.com)
  *
index d4e1cb1dbcd1a409af059d413bcef525f84cce52..dcec960fc724486aed8e5c742f60372fa645a855 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *  arch/s390/kernel/time.c
  *    Time of day based timer functions.
  *
  *  S390 version
@@ -45,7 +44,7 @@
 #include <asm/vdso.h>
 #include <asm/irq.h>
 #include <asm/irq_regs.h>
-#include <asm/timer.h>
+#include <asm/vtimer.h>
 #include <asm/etr.h>
 #include <asm/cio.h>
 #include "entry.h"
index 4f8dc942257c378bba5a940f41cc8e6c270861c0..05151e06c38808e8fb7e70acf487aaae6c031e93 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2007,2011
+ *    Copyright IBM Corp. 2007, 2011
  *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  */
 
index 77cdf4234ebc8bd7e62bf0c2893147953e4dc9dd..af2421a0f3156e9c8a965ee34d95322de55602be 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  arch/s390/kernel/traps.c
- *
  *  S390 version
- *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999, 2000
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *               Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com),
  *
index 39ebff506946ef158d97604da5c87d41e312d81c..4fc97b40a6e1a3fe48a9ca108cf0227e1fa637b9 100644 (file)
@@ -1,71 +1,82 @@
 /*
- *  arch/s390/kernel/vtime.c
  *    Virtual cpu timer based timer functions.
  *
- *  S390 version
- *    Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2004, 2012
  *    Author(s): Jan Glauber <jan.glauber@de.ibm.com>
  */
 
-#include <linux/module.h>
+#include <linux/kernel_stat.h>
+#include <linux/notifier.h>
+#include <linux/kprobes.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
-#include <linux/time.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/types.h>
 #include <linux/timex.h>
-#include <linux/notifier.h>
-#include <linux/kernel_stat.h>
-#include <linux/rcupdate.h>
-#include <linux/posix-timers.h>
+#include <linux/types.h>
+#include <linux/time.h>
 #include <linux/cpu.h>
-#include <linux/kprobes.h>
+#include <linux/smp.h>
 
-#include <asm/timer.h>
 #include <asm/irq_regs.h>
 #include <asm/cputime.h>
+#include <asm/vtimer.h>
 #include <asm/irq.h>
 #include "entry.h"
 
-static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
+static void virt_timer_expire(void);
 
 DEFINE_PER_CPU(struct s390_idle_data, s390_idle);
 
-static inline __u64 get_vtimer(void)
+static LIST_HEAD(virt_timer_list);
+static DEFINE_SPINLOCK(virt_timer_lock);
+static atomic64_t virt_timer_current;
+static atomic64_t virt_timer_elapsed;
+
+static inline u64 get_vtimer(void)
 {
-       __u64 timer;
+       u64 timer;
 
-       asm volatile("STPT %0" : "=m" (timer));
+       asm volatile("stpt %0" : "=m" (timer));
        return timer;
 }
 
-static inline void set_vtimer(__u64 expires)
+static inline void set_vtimer(u64 expires)
 {
-       __u64 timer;
+       u64 timer;
 
-       asm volatile ("  STPT %0\n"  /* Store current cpu timer value */
-                     "  SPT %1"     /* Set new value immediately afterwards */
-                     : "=m" (timer) : "m" (expires) );
+       asm volatile(
+               "       stpt    %0\n"   /* Store current cpu timer value */
+               "       spt     %1"     /* Set new value imm. afterwards */
+               : "=m" (timer) : "m" (expires));
        S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer;
        S390_lowcore.last_update_timer = expires;
 }
 
+static inline int virt_timer_forward(u64 elapsed)
+{
+       BUG_ON(!irqs_disabled());
+
+       if (list_empty(&virt_timer_list))
+               return 0;
+       elapsed = atomic64_add_return(elapsed, &virt_timer_elapsed);
+       return elapsed >= atomic64_read(&virt_timer_current);
+}
+
 /*
  * Update process times based on virtual cpu times stored by entry.S
  * to the lowcore fields user_timer, system_timer & steal_clock.
  */
-static void do_account_vtime(struct task_struct *tsk, int hardirq_offset)
+static int do_account_vtime(struct task_struct *tsk, int hardirq_offset)
 {
        struct thread_info *ti = task_thread_info(tsk);
-       __u64 timer, clock, user, system, steal;
+       u64 timer, clock, user, system, steal;
 
        timer = S390_lowcore.last_update_timer;
        clock = S390_lowcore.last_update_clock;
-       asm volatile ("  STPT %0\n"    /* Store current cpu timer value */
-                     "  STCK %1"      /* Store current tod clock value */
-                     : "=m" (S390_lowcore.last_update_timer),
-                       "=m" (S390_lowcore.last_update_clock) );
+       asm volatile(
+               "       stpt    %0\n"   /* Store current cpu timer value */
+               "       stck    %1"     /* Store current tod clock value */
+               : "=m" (S390_lowcore.last_update_timer),
+                 "=m" (S390_lowcore.last_update_clock));
        S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
        S390_lowcore.steal_timer += S390_lowcore.last_update_clock - clock;
 
@@ -84,6 +95,8 @@ static void do_account_vtime(struct task_struct *tsk, int hardirq_offset)
                S390_lowcore.steal_timer = 0;
                account_steal_time(steal);
        }
+
+       return virt_timer_forward(user + system);
 }
 
 void account_vtime(struct task_struct *prev, struct task_struct *next)
@@ -101,7 +114,8 @@ void account_vtime(struct task_struct *prev, struct task_struct *next)
 
 void account_process_tick(struct task_struct *tsk, int user_tick)
 {
-       do_account_vtime(tsk, HARDIRQ_OFFSET);
+       if (do_account_vtime(tsk, HARDIRQ_OFFSET))
+               virt_timer_expire();
 }
 
 /*
@@ -111,7 +125,7 @@ void account_process_tick(struct task_struct *tsk, int user_tick)
 void account_system_vtime(struct task_struct *tsk)
 {
        struct thread_info *ti = task_thread_info(tsk);
-       __u64 timer, system;
+       u64 timer, system;
 
        timer = S390_lowcore.last_update_timer;
        S390_lowcore.last_update_timer = get_vtimer();
@@ -121,13 +135,14 @@ void account_system_vtime(struct task_struct *tsk)
        S390_lowcore.steal_timer -= system;
        ti->system_timer = S390_lowcore.system_timer;
        account_system_time(tsk, 0, system, system);
+
+       virt_timer_forward(system);
 }
 EXPORT_SYMBOL_GPL(account_system_vtime);
 
 void __kprobes vtime_stop_cpu(void)
 {
        struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
-       struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer);
        unsigned long long idle_time;
        unsigned long psw_mask;
 
@@ -141,7 +156,7 @@ void __kprobes vtime_stop_cpu(void)
        idle->nohz_delay = 0;
 
        /* Call the assembler magic in entry.S */
-       psw_idle(idle, vq, psw_mask, !list_empty(&vq->list));
+       psw_idle(idle, psw_mask);
 
        /* Reenable preemption tracer. */
        start_critical_timings();
@@ -149,9 +164,9 @@ void __kprobes vtime_stop_cpu(void)
        /* Account time spent with enabled wait psw loaded as idle time. */
        idle->sequence++;
        smp_wmb();
-       idle_time = idle->idle_exit - idle->idle_enter;
+       idle_time = idle->clock_idle_exit - idle->clock_idle_enter;
+       idle->clock_idle_enter = idle->clock_idle_exit = 0ULL;
        idle->idle_time += idle_time;
-       idle->idle_enter = idle->idle_exit = 0ULL;
        idle->idle_count++;
        account_idle_time(idle_time);
        smp_wmb();
@@ -167,10 +182,10 @@ cputime64_t s390_get_idle_time(int cpu)
        do {
                now = get_clock();
                sequence = ACCESS_ONCE(idle->sequence);
-               idle_enter = ACCESS_ONCE(idle->idle_enter);
-               idle_exit = ACCESS_ONCE(idle->idle_exit);
+               idle_enter = ACCESS_ONCE(idle->clock_idle_enter);
+               idle_exit = ACCESS_ONCE(idle->clock_idle_exit);
        } while ((sequence & 1) || (idle->sequence != sequence));
-       return idle_enter ? ((idle_exit ? : now) - idle_enter) : 0;
+       return idle_enter ? ((idle_exit ?: now) - idle_enter) : 0;
 }
 
 /*
@@ -179,11 +194,11 @@ cputime64_t s390_get_idle_time(int cpu)
  */
 static void list_add_sorted(struct vtimer_list *timer, struct list_head *head)
 {
-       struct vtimer_list *event;
+       struct vtimer_list *tmp;
 
-       list_for_each_entry(event, head, entry) {
-               if (event->expires > timer->expires) {
-                       list_add_tail(&timer->entry, &event->entry);
+       list_for_each_entry(tmp, head, entry) {
+               if (tmp->expires > timer->expires) {
+                       list_add_tail(&timer->entry, &tmp->entry);
                        return;
                }
        }
@@ -191,82 +206,45 @@ static void list_add_sorted(struct vtimer_list *timer, struct list_head *head)
 }
 
 /*
- * Do the callback functions of expired vtimer events.
- * Called from within the interrupt handler.
- */
-static void do_callbacks(struct list_head *cb_list)
-{
-       struct vtimer_queue *vq;
-       struct vtimer_list *event, *tmp;
-
-       if (list_empty(cb_list))
-               return;
-
-       vq = &__get_cpu_var(virt_cpu_timer);
-
-       list_for_each_entry_safe(event, tmp, cb_list, entry) {
-               list_del_init(&event->entry);
-               (event->function)(event->data);
-               if (event->interval) {
-                       /* Recharge interval timer */
-                       event->expires = event->interval + vq->elapsed;
-                       spin_lock(&vq->lock);
-                       list_add_sorted(event, &vq->list);
-                       spin_unlock(&vq->lock);
-               }
-       }
-}
-
-/*
- * Handler for the virtual CPU timer.
+ * Handler for expired virtual CPU timer.
  */
-static void do_cpu_timer_interrupt(struct ext_code ext_code,
-                                  unsigned int param32, unsigned long param64)
+static void virt_timer_expire(void)
 {
-       struct vtimer_queue *vq;
-       struct vtimer_list *event, *tmp;
-       struct list_head cb_list;       /* the callback queue */
-       __u64 elapsed, next;
-
-       kstat_cpu(smp_processor_id()).irqs[EXTINT_TMR]++;
-       INIT_LIST_HEAD(&cb_list);
-       vq = &__get_cpu_var(virt_cpu_timer);
-
-       /* walk timer list, fire all expired events */
-       spin_lock(&vq->lock);
-
-       elapsed = vq->elapsed + (vq->timer - S390_lowcore.async_enter_timer);
-       BUG_ON((s64) elapsed < 0);
-       vq->elapsed = 0;
-       list_for_each_entry_safe(event, tmp, &vq->list, entry) {
-               if (event->expires < elapsed)
+       struct vtimer_list *timer, *tmp;
+       unsigned long elapsed;
+       LIST_HEAD(cb_list);
+
+       /* walk timer list, fire all expired timers */
+       spin_lock(&virt_timer_lock);
+       elapsed = atomic64_read(&virt_timer_elapsed);
+       list_for_each_entry_safe(timer, tmp, &virt_timer_list, entry) {
+               if (timer->expires < elapsed)
                        /* move expired timer to the callback queue */
-                       list_move_tail(&event->entry, &cb_list);
+                       list_move_tail(&timer->entry, &cb_list);
                else
-                       event->expires -= elapsed;
+                       timer->expires -= elapsed;
        }
-       spin_unlock(&vq->lock);
-
-       do_callbacks(&cb_list);
-
-       /* next event is first in list */
-       next = VTIMER_MAX_SLICE;
-       spin_lock(&vq->lock);
-       if (!list_empty(&vq->list)) {
-               event = list_first_entry(&vq->list, struct vtimer_list, entry);
-               next = event->expires;
+       if (!list_empty(&virt_timer_list)) {
+               timer = list_first_entry(&virt_timer_list,
+                                        struct vtimer_list, entry);
+               atomic64_set(&virt_timer_current, timer->expires);
+       }
+       atomic64_sub(elapsed, &virt_timer_elapsed);
+       spin_unlock(&virt_timer_lock);
+
+       /* Do callbacks and recharge periodic timers */
+       list_for_each_entry_safe(timer, tmp, &cb_list, entry) {
+               list_del_init(&timer->entry);
+               timer->function(timer->data);
+               if (timer->interval) {
+                       /* Recharge interval timer */
+                       timer->expires = timer->interval +
+                               atomic64_read(&virt_timer_elapsed);
+                       spin_lock(&virt_timer_lock);
+                       list_add_sorted(timer, &virt_timer_list);
+                       spin_unlock(&virt_timer_lock);
+               }
        }
-       spin_unlock(&vq->lock);
-       /*
-        * To improve precision add the time spent by the
-        * interrupt handler to the elapsed time.
-        * Note: CPU timer counts down and we got an interrupt,
-        *       the current content is negative
-        */
-       elapsed = S390_lowcore.async_enter_timer - get_vtimer();
-       set_vtimer(next - elapsed);
-       vq->timer = next - elapsed;
-       vq->elapsed = elapsed;
 }
 
 void init_virt_timer(struct vtimer_list *timer)
@@ -278,179 +256,108 @@ EXPORT_SYMBOL(init_virt_timer);
 
 static inline int vtimer_pending(struct vtimer_list *timer)
 {
-       return (!list_empty(&timer->entry));
+       return !list_empty(&timer->entry);
 }
 
-/*
- * this function should only run on the specified CPU
- */
 static void internal_add_vtimer(struct vtimer_list *timer)
 {
-       struct vtimer_queue *vq;
-       unsigned long flags;
-       __u64 left, expires;
-
-       vq = &per_cpu(virt_cpu_timer, timer->cpu);
-       spin_lock_irqsave(&vq->lock, flags);
-
-       BUG_ON(timer->cpu != smp_processor_id());
-
-       if (list_empty(&vq->list)) {
-               /* First timer on this cpu, just program it. */
-               list_add(&timer->entry, &vq->list);
-               set_vtimer(timer->expires);
-               vq->timer = timer->expires;
-               vq->elapsed = 0;
+       if (list_empty(&virt_timer_list)) {
+               /* First timer, just program it. */
+               atomic64_set(&virt_timer_current, timer->expires);
+               atomic64_set(&virt_timer_elapsed, 0);
+               list_add(&timer->entry, &virt_timer_list);
        } else {
-               /* Check progress of old timers. */
-               expires = timer->expires;
-               left = get_vtimer();
-               if (likely((s64) expires < (s64) left)) {
+               /* Update timer against current base. */
+               timer->expires += atomic64_read(&virt_timer_elapsed);
+               if (likely((s64) timer->expires <
+                          (s64) atomic64_read(&virt_timer_current)))
                        /* The new timer expires before the current timer. */
-                       set_vtimer(expires);
-                       vq->elapsed += vq->timer - left;
-                       vq->timer = expires;
-               } else {
-                       vq->elapsed += vq->timer - left;
-                       vq->timer = left;
-               }
-               /* Insert new timer into per cpu list. */
-               timer->expires += vq->elapsed;
-               list_add_sorted(timer, &vq->list);
+                       atomic64_set(&virt_timer_current, timer->expires);
+               /* Insert new timer into the list. */
+               list_add_sorted(timer, &virt_timer_list);
        }
-
-       spin_unlock_irqrestore(&vq->lock, flags);
-       /* release CPU acquired in prepare_vtimer or mod_virt_timer() */
-       put_cpu();
 }
 
-static inline void prepare_vtimer(struct vtimer_list *timer)
+static void __add_vtimer(struct vtimer_list *timer, int periodic)
 {
-       BUG_ON(!timer->function);
-       BUG_ON(!timer->expires || timer->expires > VTIMER_MAX_SLICE);
-       BUG_ON(vtimer_pending(timer));
-       timer->cpu = get_cpu();
+       unsigned long flags;
+
+       timer->interval = periodic ? timer->expires : 0;
+       spin_lock_irqsave(&virt_timer_lock, flags);
+       internal_add_vtimer(timer);
+       spin_unlock_irqrestore(&virt_timer_lock, flags);
 }
 
 /*
  * add_virt_timer - add an oneshot virtual CPU timer
  */
-void add_virt_timer(void *new)
+void add_virt_timer(struct vtimer_list *timer)
 {
-       struct vtimer_list *timer;
-
-       timer = (struct vtimer_list *)new;
-       prepare_vtimer(timer);
-       timer->interval = 0;
-       internal_add_vtimer(timer);
+       __add_vtimer(timer, 0);
 }
 EXPORT_SYMBOL(add_virt_timer);
 
 /*
  * add_virt_timer_int - add an interval virtual CPU timer
  */
-void add_virt_timer_periodic(void *new)
+void add_virt_timer_periodic(struct vtimer_list *timer)
 {
-       struct vtimer_list *timer;
-
-       timer = (struct vtimer_list *)new;
-       prepare_vtimer(timer);
-       timer->interval = timer->expires;
-       internal_add_vtimer(timer);
+       __add_vtimer(timer, 1);
 }
 EXPORT_SYMBOL(add_virt_timer_periodic);
 
-static int __mod_vtimer(struct vtimer_list *timer, __u64 expires, int periodic)
+static int __mod_vtimer(struct vtimer_list *timer, u64 expires, int periodic)
 {
-       struct vtimer_queue *vq;
        unsigned long flags;
-       int cpu;
+       int rc;
 
        BUG_ON(!timer->function);
-       BUG_ON(!expires || expires > VTIMER_MAX_SLICE);
 
        if (timer->expires == expires && vtimer_pending(timer))
                return 1;
-
-       cpu = get_cpu();
-       vq = &per_cpu(virt_cpu_timer, cpu);
-
-       /* disable interrupts before test if timer is pending */
-       spin_lock_irqsave(&vq->lock, flags);
-
-       /* if timer isn't pending add it on the current CPU */
-       if (!vtimer_pending(timer)) {
-               spin_unlock_irqrestore(&vq->lock, flags);
-
-               if (periodic)
-                       timer->interval = expires;
-               else
-                       timer->interval = 0;
-               timer->expires = expires;
-               timer->cpu = cpu;
-               internal_add_vtimer(timer);
-               return 0;
-       }
-
-       /* check if we run on the right CPU */
-       BUG_ON(timer->cpu != cpu);
-
-       list_del_init(&timer->entry);
+       spin_lock_irqsave(&virt_timer_lock, flags);
+       rc = vtimer_pending(timer);
+       if (rc)
+               list_del_init(&timer->entry);
+       timer->interval = periodic ? expires : 0;
        timer->expires = expires;
-       if (periodic)
-               timer->interval = expires;
-
-       /* the timer can't expire anymore so we can release the lock */
-       spin_unlock_irqrestore(&vq->lock, flags);
        internal_add_vtimer(timer);
-       return 1;
+       spin_unlock_irqrestore(&virt_timer_lock, flags);
+       return rc;
 }
 
 /*
- * If we change a pending timer the function must be called on the CPU
- * where the timer is running on.
- *
  * returns whether it has modified a pending timer (1) or not (0)
  */
-int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
+int mod_virt_timer(struct vtimer_list *timer, u64 expires)
 {
        return __mod_vtimer(timer, expires, 0);
 }
 EXPORT_SYMBOL(mod_virt_timer);
 
 /*
- * If we change a pending timer the function must be called on the CPU
- * where the timer is running on.
- *
  * returns whether it has modified a pending timer (1) or not (0)
  */
-int mod_virt_timer_periodic(struct vtimer_list *timer, __u64 expires)
+int mod_virt_timer_periodic(struct vtimer_list *timer, u64 expires)
 {
        return __mod_vtimer(timer, expires, 1);
 }
 EXPORT_SYMBOL(mod_virt_timer_periodic);
 
 /*
- * delete a virtual timer
+ * Delete a virtual timer.
  *
  * returns whether the deleted timer was pending (1) or not (0)
  */
 int del_virt_timer(struct vtimer_list *timer)
 {
        unsigned long flags;
-       struct vtimer_queue *vq;
 
-       /* check if timer is pending */
        if (!vtimer_pending(timer))
                return 0;
-
-       vq = &per_cpu(virt_cpu_timer, timer->cpu);
-       spin_lock_irqsave(&vq->lock, flags);
-
-       /* we don't interrupt a running timer, just let it expire! */
+       spin_lock_irqsave(&virt_timer_lock, flags);
        list_del_init(&timer->entry);
-
-       spin_unlock_irqrestore(&vq->lock, flags);
+       spin_unlock_irqrestore(&virt_timer_lock, flags);
        return 1;
 }
 EXPORT_SYMBOL(del_virt_timer);
@@ -458,20 +365,10 @@ EXPORT_SYMBOL(del_virt_timer);
 /*
  * Start the virtual CPU timer on the current CPU.
  */
-void init_cpu_vtimer(void)
+void __cpuinit init_cpu_vtimer(void)
 {
-       struct vtimer_queue *vq;
-
-       /* initialize per cpu vtimer structure */
-       vq = &__get_cpu_var(virt_cpu_timer);
-       INIT_LIST_HEAD(&vq->list);
-       spin_lock_init(&vq->lock);
-
-       /* enable cpu timer interrupts */
-       __ctl_set_bit(0,10);
-
        /* set initial cpu timer */
-       set_vtimer(0x7fffffffffffffffULL);
+       set_vtimer(VTIMER_MAX_SLICE);
 }
 
 static int __cpuinit s390_nohz_notify(struct notifier_block *self,
@@ -493,12 +390,7 @@ static int __cpuinit s390_nohz_notify(struct notifier_block *self,
 
 void __init vtime_init(void)
 {
-       /* request the cpu timer external interrupt */
-       if (register_external_interrupt(0x1005, do_cpu_timer_interrupt))
-               panic("Couldn't request external interrupt 0x1005");
-
        /* Enable cpu timer interrupts on the boot cpu. */
        init_cpu_vtimer();
        cpu_notifier(s390_nohz_notify, 0);
 }
-
index b23d9ac77dfc77fcf090f52fc739b17cc036a69c..c88bb7793390d7a1e26d0982529b32d4747ca67f 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * diag.c - handling diagnose instructions
+ * handling diagnose instructions
  *
- * Copyright IBM Corp. 2008,2011
+ * Copyright IBM Corp. 2008, 2011
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
index c86f6ae43f7612ea63e6f626565f30eee7db67f3..4703f129e95e1153570129a0a0f0fc79c34b0f1e 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * access.h -  access guest memory
+ * access guest memory
  *
- * Copyright IBM Corp. 2008,2009
+ * Copyright IBM Corp. 2008, 2009
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
index 979cbe55bf5ef1dd42589935ba04aa208d2bb30a..adae539f12e2fbaeb49f41b462f95bc4354ce3f9 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * intercept.c - in-kernel handling for sie intercepts
+ * in-kernel handling for sie intercepts
  *
- * Copyright IBM Corp. 2008,2009
+ * Copyright IBM Corp. 2008, 2009
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
index 2d9f9a72bb8108ddb3ea4c03c3339eb0d3f5d118..b7bc1aac8ed2dc3611c50f24c7c4b53989642661 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * interrupt.c - handling kvm guest interrupts
+ * handling kvm guest interrupts
  *
  * Copyright IBM Corp. 2008
  *
index 664766d0c83c6a8461634c4dfd31679cf74c7b02..c552d1f4103f772561ee3e5fac5a35c90cc7520a 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * s390host.c --  hosting zSeries kernel virtual machines
+ * hosting zSeries kernel virtual machines
  *
- * Copyright IBM Corp. 2008,2009
+ * Copyright IBM Corp. 2008, 2009
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
index 2294377975e8cf56ad06e03d380a4e211820bce3..d75bc5e92c5bf4c53a3a19bf2479007646834f49 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * kvm_s390.h -  definition for kvm on s390
+ * definition for kvm on s390
  *
- * Copyright IBM Corp. 2008,2009
+ * Copyright IBM Corp. 2008, 2009
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
index 68a6b2ed16bf125c56ce7456e76c68f4fd6bd236..60da903d6f3ecbb596a2fc90352be1fffc137315 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * priv.c - handling privileged instructions
+ * handling privileged instructions
  *
  * Copyright IBM Corp. 2008
  *
index 0ad4cf238391d5889b8d3ea955c116edd6a80a36..1ab2ce1611c5e46e71d12d25671f39a7b2f9aa78 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * sigp.c - handlinge interprocessor communication
+ * handling interprocessor communication
  *
- * Copyright IBM Corp. 2008,2009
+ * Copyright IBM Corp. 2008, 2009
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License (version 2 only)
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/slab.h>
+#include <asm/sigp.h>
 #include "gaccess.h"
 #include "kvm-s390.h"
 
-/* sigp order codes */
-#define SIGP_SENSE             0x01
-#define SIGP_EXTERNAL_CALL     0x02
-#define SIGP_EMERGENCY         0x03
-#define SIGP_START             0x04
-#define SIGP_STOP              0x05
-#define SIGP_RESTART           0x06
-#define SIGP_STOP_STORE_STATUS 0x09
-#define SIGP_INITIAL_CPU_RESET 0x0b
-#define SIGP_CPU_RESET         0x0c
-#define SIGP_SET_PREFIX        0x0d
-#define SIGP_STORE_STATUS_ADDR 0x0e
-#define SIGP_SET_ARCH          0x12
-#define SIGP_SENSE_RUNNING     0x15
-
-/* cpu status bits */
-#define SIGP_STAT_EQUIPMENT_CHECK   0x80000000UL
-#define SIGP_STAT_NOT_RUNNING      0x00000400UL
-#define SIGP_STAT_INCORRECT_STATE   0x00000200UL
-#define SIGP_STAT_INVALID_PARAMETER 0x00000100UL
-#define SIGP_STAT_EXT_CALL_PENDING  0x00000080UL
-#define SIGP_STAT_STOPPED           0x00000040UL
-#define SIGP_STAT_OPERATOR_INTERV   0x00000020UL
-#define SIGP_STAT_CHECK_STOP        0x00000010UL
-#define SIGP_STAT_INOPERATIVE       0x00000004UL
-#define SIGP_STAT_INVALID_ORDER     0x00000002UL
-#define SIGP_STAT_RECEIVER_CHECK    0x00000001UL
-
-
 static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr,
                        u64 *reg)
 {
@@ -65,7 +37,7 @@ static int __sigp_sense(struct kvm_vcpu *vcpu, u16 cpu_addr,
                rc = 1; /* status stored */
        } else {
                *reg &= 0xffffffff00000000UL;
-               *reg |= SIGP_STAT_STOPPED;
+               *reg |= SIGP_STATUS_STOPPED;
                rc = 1; /* status stored */
        }
        spin_unlock(&fi->lock);
@@ -235,7 +207,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
        address = address & 0x7fffe000u;
        if (copy_from_guest_absolute(vcpu, &tmp, address, 1) ||
           copy_from_guest_absolute(vcpu, &tmp, address + PAGE_SIZE, 1)) {
-               *reg |= SIGP_STAT_INVALID_PARAMETER;
+               *reg |= SIGP_STATUS_INVALID_PARAMETER;
                return 1; /* invalid parameter */
        }
 
@@ -249,7 +221,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
 
        if (li == NULL) {
                rc = 1; /* incorrect state */
-               *reg &= SIGP_STAT_INCORRECT_STATE;
+               *reg &= SIGP_STATUS_INCORRECT_STATE;
                kfree(inti);
                goto out_fi;
        }
@@ -258,7 +230,7 @@ static int __sigp_set_prefix(struct kvm_vcpu *vcpu, u16 cpu_addr, u32 address,
        /* cpu must be in stopped state */
        if (!(atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) {
                rc = 1; /* incorrect state */
-               *reg &= SIGP_STAT_INCORRECT_STATE;
+               *reg &= SIGP_STATUS_INCORRECT_STATE;
                kfree(inti);
                goto out_li;
        }
@@ -300,7 +272,7 @@ static int __sigp_sense_running(struct kvm_vcpu *vcpu, u16 cpu_addr,
                } else {
                        /* not running */
                        *reg &= 0xffffffff00000000UL;
-                       *reg |= SIGP_STAT_NOT_RUNNING;
+                       *reg |= SIGP_STATUS_NOT_RUNNING;
                        rc = 0;
                }
        }
@@ -375,7 +347,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
                vcpu->stat.instruction_sigp_external_call++;
                rc = __sigp_external_call(vcpu, cpu_addr);
                break;
-       case SIGP_EMERGENCY:
+       case SIGP_EMERGENCY_SIGNAL:
                vcpu->stat.instruction_sigp_emergency++;
                rc = __sigp_emergency(vcpu, cpu_addr);
                break;
@@ -383,12 +355,12 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
                vcpu->stat.instruction_sigp_stop++;
                rc = __sigp_stop(vcpu, cpu_addr, ACTION_STOP_ON_STOP);
                break;
-       case SIGP_STOP_STORE_STATUS:
+       case SIGP_STOP_AND_STORE_STATUS:
                vcpu->stat.instruction_sigp_stop++;
                rc = __sigp_stop(vcpu, cpu_addr, ACTION_STORE_ON_STOP |
                                                 ACTION_STOP_ON_STOP);
                break;
-       case SIGP_SET_ARCH:
+       case SIGP_SET_ARCHITECTURE:
                vcpu->stat.instruction_sigp_arch++;
                rc = __sigp_set_arch(vcpu, parameter);
                break;
index 9f1f71e857784096b76ddf88f92c5464813a39b4..42d0cf89121def981b0d3b2852004ec04ea66bf8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *    Precise Delay Loops for S390
  *
- *    Copyright IBM Corp. 1999,2008
+ *    Copyright IBM Corp. 1999, 2008
  *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
  *              Heiko Carstens <heiko.carstens@de.ibm.com>,
  */
@@ -12,8 +12,8 @@
 #include <linux/module.h>
 #include <linux/irqflags.h>
 #include <linux/interrupt.h>
+#include <asm/vtimer.h>
 #include <asm/div64.h>
-#include <asm/timer.h>
 
 void __delay(unsigned long loops)
 {
index d9e62c0b576a2691088f62f537cb0f1e237f7194..261152f832424602988abbb4073bc14d10b231eb 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  arch/s390/lib/div64.c
- *
  *  __div64_32 implementation for 31 bit.
  *
- *    Copyright (C) IBM Corp. 2006
+ *    Copyright IBM Corp. 2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  */
 
index 093eb694d9c157c717d56a685eb104dd03b0cdab..f709983f41f883ed567aeba87a6c1e15bc196340 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  arch/s390/lib/spinlock.c
  *    Out of line spinlock code.
  *
- *    Copyright (C) IBM Corp. 2004, 2006
+ *    Copyright IBM Corp. 2004, 2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
 
index 4143b7c1909628fd7e8284b97acfc9392e158910..846ec64ab2c9f3a9d36fb5d70478b6acffaeface 100644 (file)
@@ -1,9 +1,8 @@
 /*
- *  arch/s390/lib/string.c
  *    Optimized string functions
  *
  *  S390 version
- *    Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2004
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
 
index 1d2536cb630bc5a99ce5f88a3cba871cc096b519..315dbe09983e518b06326b2f730c45a176a57aa5 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  arch/s390/uaccess.h
- *
  *    Copyright IBM Corp. 2007
  *
  */
index 58a75a8ae90ce7beae1a4553801c47dd544cd1ee..2443ae476e333944291d4ded535ce3ba9fe5e5bf 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  arch/s390/lib/uaccess_mvcos.c
- *
  *  Optimized user space space access functions based on mvcos.
  *
- *    Copyright (C) IBM Corp. 2006
+ *    Copyright IBM Corp. 2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *              Gerald Schaefer (gerald.schaefer@de.ibm.com)
  */
index 342ae35a5ba90ddbcf89ef2a6dc5b8676de2faff..60ee2b8837972c27d8bfb3d95dd9fc3b0b4d0091 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  arch/s390/lib/uaccess_pt.c
- *
  *  User access functions based on page table walks for enhanced
  *  system layout without hardware support.
  *
index 57e94298539b51326ff1d9a4a10a9ef36c405326..6fbd063382709f7ec3a9a0ca2fafbaa0cf72dd86 100644 (file)
@@ -1,10 +1,8 @@
 /*
- *  arch/s390/lib/uaccess_std.c
- *
  *  Standard user space access functions based on mvcp/mvcs and doing
  *  interesting things in the secondary space mode.
  *
- *    Copyright (C) IBM Corp. 2006
+ *    Copyright IBM Corp. 2006
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *              Gerald Schaefer (gerald.schaefer@de.ibm.com)
  */
index cd4e9c168dd7674d2fcd918fdaa3ff21c4e38fe1..58bff541fde9c95edcd0db4f49da3aa8629371b9 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  arch/s390/math-emu/math.c
- *
  *  S390 version
- *    Copyright (C) 1999-2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999, 2001
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  *
  * 'math.c' emulates IEEE instructions on a S390 processor
index 1f1dba9dcf58f713211bbb6b3fc063171681ed70..479e94282910199d8268efd05b5f0e2be0d4526e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Collaborative memory management interface.
  *
- *    Copyright IBM Corp 2003,2010
+ *    Copyright IBM Corp 2003, 2010
  *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
  *
  */
index 075ddada4911bd05369d292d3e04d4b95eb56771..519bba716cc30c29acbb74f7cfd30db876af170c 100644 (file)
@@ -1,10 +1,9 @@
 /*
- * File...........: arch/s390/mm/extmem.c
  * Author(s)......: Carsten Otte <cotte@de.ibm.com>
  *                 Rob M van der Heij <rvdheij@nl.ibm.com>
  *                 Steven Shultz <shultzss@us.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation 2002-2004
+ * Copyright IBM Corp. 2002, 2004
  */
 
 #define KMSG_COMPONENT "extmem"
index 72cec9ecd96c7304486fc49b732764edcf4cb0f3..6a12d1bb6e09d065e5a4b2625ce79ba7209b5c2b 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  arch/s390/mm/fault.c
- *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Hartmut Penner (hp@de.ibm.com)
  *               Ulrich Weigand (uweigand@de.ibm.com)
  *
index 900de2b3cf28fb640417d1f4f94289b4ece2f08d..532525ec88c1ebce808da0e5b6dc06630b4d997f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  IBM System z Huge TLB Page Support for Kernel.
  *
- *    Copyright 2007 IBM Corp.
+ *    Copyright IBM Corp. 2007
  *    Author(s): Gerald Schaefer <gerald.schaefer@de.ibm.com>
  */
 
index 2bea0605856e85ac76e96c7e7c8dbb34ff6c94a5..6adbc082618a1893b4ad4b074be9aefb577584c8 100644 (file)
@@ -1,8 +1,6 @@
 /*
- *  arch/s390/mm/init.c
- *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Hartmut Penner (hp@de.ibm.com)
  *
  *  Derived from "arch/i386/mm/init.c"
index 2857c48486ea9005ba5d3bb8a9924e4704c8ceb2..573384256c5c5ebd1aa65295e635e808345902d0 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  linux/arch/s390/mm/mmap.c
- *
  *  flexible mmap layout support
  *
  * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
index a3db5a3ea0836c6412c21f92bed109cca9962242..1cab221077cc872b5f5e5528ff1918d8551fa9d2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *    Copyright IBM Corp. 2007,2011
+ *    Copyright IBM Corp. 2007, 2011
  *    Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
 
index 71ae20df674e53f051834f20319f3c48fae1358b..6f896e75ab49da1f58eb83c249a7e880f800a3ea 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  arch/s390/mm/vmem.c
- *
  *    Copyright IBM Corp. 2006
  *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  */
index bc4b84a35cadde2420c41a5580be3408ebf57181..c82f62fb9c28ef6096a486c6a3458725e91b31e3 100644 (file)
@@ -1,8 +1,6 @@
-/**
- * arch/s390/oprofile/backtrace.c
- *
+/*
  * S390 Version
- *   Copyright (C) 2005 IBM Corporation, IBM Deutschland Entwicklung GmbH.
+ *   Copyright IBM Corp. 2005
  *   Author(s): Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
  */
 
index a4a89fa980d6c4e0e8e44a00e8519d9ead2ac2b1..0cb385da202c60836fd2cd006e5950ed448de656 100644 (file)
@@ -1,6 +1,4 @@
-/**
- * arch/s390/oprofile/hwsampler.c
- *
+/*
  * Copyright IBM Corp. 2010
  * Author: Heinz Graalfs <graalfs@de.ibm.com>
  */
index 2297be406c61a5d78d473a2890bb755715a8f210..a1e9d69a9c90e579c2f68cea8869ae6ec26d05c4 100644 (file)
@@ -1,8 +1,6 @@
-/**
- * arch/s390/oprofile/init.c
- *
+/*
  * S390 Version
- *   Copyright (C) 2002-2011 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *   Copyright IBM Corp. 2002, 2011
  *   Author(s): Thomas Spatzier (tspat@de.ibm.com)
  *   Author(s): Mahesh Salgaonkar (mahesh@linux.vnet.ibm.com)
  *   Author(s): Heinz Graalfs (graalfs@linux.vnet.ibm.com)
index 1a8d3ca09014c36fdf967ee981f258e3012b9949..61b2531eef17edb07b2b7e6dad78ddfdbefd1ce5 100644 (file)
@@ -1,7 +1,5 @@
-/**
- * arch/s390/oprofile/op_counter.h
- *
- *   Copyright (C) 2011 IBM Deutschland Entwicklung GmbH, IBM Corporation
+/*
+ *   Copyright IBM Corp. 2011
  *   Author(s): Andreas Krebbel (krebbel@linux.vnet.ibm.com)
  *
  * @remark Copyright 2011 OProfile authors
index 31d9db7913e4352a10680f76f2aaa8a5e800eef5..a24595d83ad6c48c5685faed4d59ecb00d410c41 100644 (file)
@@ -60,6 +60,7 @@ config SUPERH32
 
 config SUPERH64
        def_bool ARCH = "sh64"
+       select KALLSYMS
 
 config ARCH_DEFCONFIG
        string
index 1f56b35d32481b04de59a7415b0f0abe73b58db0..7048c03490d9a06d48cff04ed6821db9a76e08d4 100644 (file)
@@ -44,6 +44,8 @@ config SH_7721_SOLUTION_ENGINE
 config SH_7722_SOLUTION_ENGINE
        bool "SolutionEngine7722"
        select SOLUTION_ENGINE
+       select GENERIC_IRQ_CHIP
+       select IRQ_DOMAIN
        depends on CPU_SUBTYPE_SH7722
        help
          Select 7722 SolutionEngine if configuring for a Hitachi SH772
@@ -80,6 +82,8 @@ config SH_7780_SOLUTION_ENGINE
 config SH_7343_SOLUTION_ENGINE
        bool "SolutionEngine7343"
        select SOLUTION_ENGINE
+       select GENERIC_IRQ_CHIP
+       select IRQ_DOMAIN
        depends on CPU_SUBTYPE_SH7343
        help
          Select 7343 SolutionEngine if configuring for a Hitachi
@@ -295,6 +299,7 @@ config SH_X3PROTO
        bool "SH-X3 Prototype board"
        depends on CPU_SUBTYPE_SHX3
        select NO_IOPORT if !PCI
+       select IRQ_DOMAIN
 
 config SH_MAGIC_PANEL_R2
        bool "Magic Panel R2"
index f63d323f411f5f32043e32f966be6e3a1289df41..2789647abebef2308a28f3260b6016410c078cab 100644 (file)
@@ -8,10 +8,11 @@
  * This file is part of the LinuxDC project (www.linuxdc.org)
  * Released under the terms of the GNU GPL v2.0
  */
-
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
+#include <linux/export.h>
+#include <linux/err.h>
 #include <mach/sysasic.h>
 
 /*
@@ -141,26 +142,15 @@ int systemasic_irq_demux(int irq)
 
 void systemasic_irq_init(void)
 {
-       int i, nid = cpu_to_node(boot_cpu_data);
-
-       /* Assign all virtual IRQs to the System ASIC int. handler */
-       for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++) {
-               unsigned int irq;
-
-               irq = create_irq_nr(i, nid);
-               if (unlikely(irq == 0)) {
-                       pr_err("%s: failed hooking irq %d for systemasic\n",
-                              __func__, i);
-                       return;
-               }
+       int irq_base, i;
 
-               if (unlikely(irq != i)) {
-                       pr_err("%s: got irq %d but wanted %d, bailing.\n",
-                              __func__, irq, i);
-                       destroy_irq(irq);
-                       return;
-               }
+       irq_base = irq_alloc_descs(HW_EVENT_IRQ_BASE, HW_EVENT_IRQ_BASE,
+                                  HW_EVENT_IRQ_MAX - HW_EVENT_IRQ_BASE, -1);
+       if (IS_ERR_VALUE(irq_base)) {
+               pr_err("%s: failed hooking irqs\n", __func__);
+               return;
+       }
 
+       for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++)
                irq_set_chip_and_handler(i, &systemasic_int, handle_level_irq);
-       }
 }
index fd45ffc48340b898cac839d6be1d5e038693d52a..7646bf0486c2c9b17d60dff4c4b59ef9a50a1b7b 100644 (file)
 /*
- * linux/arch/sh/boards/se/7343/irq.c
+ * Hitachi UL SolutionEngine 7343 FPGA IRQ Support.
  *
  * Copyright (C) 2008  Yoshihiro Shimoda
+ * Copyright (C) 2012  Paul Mundt
  *
- * Based on linux/arch/sh/boards/se/7722/irq.c
+ * Based on linux/arch/sh/boards/se/7343/irq.c
  * Copyright (C) 2007  Nobuhiro Iwamatsu
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
+#define DRV_NAME "SE7343-FPGA"
+#define pr_fmt(fmt) DRV_NAME ": " fmt
+
+#define irq_reg_readl  ioread16
+#define irq_reg_writel iowrite16
+
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
 #include <linux/io.h>
+#include <asm/sizes.h>
 #include <mach-se/mach/se7343.h>
 
-unsigned int se7343_fpga_irq[SE7343_FPGA_IRQ_NR] = { 0, };
+#define PA_CPLD_BASE_ADDR      0x11400000
+#define PA_CPLD_ST_REG         0x08    /* CPLD Interrupt status register */
+#define PA_CPLD_IMSK_REG       0x0a    /* CPLD Interrupt mask register */
 
-static void disable_se7343_irq(struct irq_data *data)
-{
-       unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data);
-       __raw_writew(__raw_readw(PA_CPLD_IMSK) | 1 << bit, PA_CPLD_IMSK);
-}
+static void __iomem *se7343_irq_regs;
+struct irq_domain *se7343_irq_domain;
 
-static void enable_se7343_irq(struct irq_data *data)
+static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-       unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data);
-       __raw_writew(__raw_readw(PA_CPLD_IMSK) & ~(1 << bit), PA_CPLD_IMSK);
-}
+       struct irq_data *data = irq_get_irq_data(irq);
+       struct irq_chip *chip = irq_data_get_irq_chip(data);
+       unsigned long mask;
+       int bit;
 
-static struct irq_chip se7343_irq_chip __read_mostly = {
-       .name           = "SE7343-FPGA",
-       .irq_mask       = disable_se7343_irq,
-       .irq_unmask     = enable_se7343_irq,
-};
+       chip->irq_mask_ack(data);
 
-static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc)
+       mask = ioread16(se7343_irq_regs + PA_CPLD_ST_REG);
+
+       for_each_set_bit(bit, &mask, SE7343_FPGA_IRQ_NR)
+               generic_handle_irq(irq_linear_revmap(se7343_irq_domain, bit));
+
+       chip->irq_unmask(data);
+}
+
+static void __init se7343_domain_init(void)
 {
-       unsigned short intv = __raw_readw(PA_CPLD_ST);
-       unsigned int ext_irq = 0;
+       int i;
 
-       intv &= (1 << SE7343_FPGA_IRQ_NR) - 1;
+       se7343_irq_domain = irq_domain_add_linear(NULL, SE7343_FPGA_IRQ_NR,
+                                                 &irq_domain_simple_ops, NULL);
+       if (unlikely(!se7343_irq_domain)) {
+               printk("Failed to get IRQ domain\n");
+               return;
+       }
 
-       for (; intv; intv >>= 1, ext_irq++) {
-               if (!(intv & 1))
-                       continue;
+       for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) {
+               int irq = irq_create_mapping(se7343_irq_domain, i);
 
-               generic_handle_irq(se7343_fpga_irq[ext_irq]);
+               if (unlikely(irq == 0)) {
+                       printk("Failed to allocate IRQ %d\n", i);
+                       return;
+               }
        }
 }
 
-/*
- * Initialize IRQ setting
- */
-void __init init_7343se_IRQ(void)
+static void __init se7343_gc_init(void)
 {
-       int i, irq;
+       struct irq_chip_generic *gc;
+       struct irq_chip_type *ct;
+       unsigned int irq_base;
 
-       __raw_writew(0, PA_CPLD_IMSK);  /* disable all irqs */
-       __raw_writew(0x2000, 0xb03fffec);       /* mrshpc irq enable */
+       irq_base = irq_linear_revmap(se7343_irq_domain, 0);
 
-       for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) {
-               irq = create_irq();
-               if (irq < 0)
-                       return;
-               se7343_fpga_irq[i] = irq;
+       gc = irq_alloc_generic_chip(DRV_NAME, 1, irq_base, se7343_irq_regs,
+                                   handle_level_irq);
+       if (unlikely(!gc))
+               return;
 
-               irq_set_chip_and_handler_name(se7343_fpga_irq[i],
-                                             &se7343_irq_chip,
-                                             handle_level_irq,
-                                             "level");
+       ct = gc->chip_types;
+       ct->chip.irq_mask = irq_gc_mask_set_bit;
+       ct->chip.irq_unmask = irq_gc_mask_clr_bit;
 
-               irq_set_chip_data(se7343_fpga_irq[i], (void *)i);
-       }
+       ct->regs.mask = PA_CPLD_IMSK_REG;
+
+       irq_setup_generic_chip(gc, IRQ_MSK(SE7343_FPGA_IRQ_NR),
+                              IRQ_GC_INIT_MASK_CACHE,
+                              IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 
        irq_set_chained_handler(IRQ0_IRQ, se7343_irq_demux);
        irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
+
        irq_set_chained_handler(IRQ1_IRQ, se7343_irq_demux);
        irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
+
        irq_set_chained_handler(IRQ4_IRQ, se7343_irq_demux);
        irq_set_irq_type(IRQ4_IRQ, IRQ_TYPE_LEVEL_LOW);
+
        irq_set_chained_handler(IRQ5_IRQ, se7343_irq_demux);
        irq_set_irq_type(IRQ5_IRQ, IRQ_TYPE_LEVEL_LOW);
 }
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_7343se_IRQ(void)
+{
+       se7343_irq_regs = ioremap(PA_CPLD_BASE_ADDR, SZ_16);
+       if (unlikely(!se7343_irq_regs)) {
+               pr_err("Failed to remap CPLD\n");
+               return;
+       }
+
+       /*
+        * All FPGA IRQs disabled by default
+        */
+       iowrite16(0, se7343_irq_regs + PA_CPLD_IMSK_REG);
+
+       __raw_writew(0x2000, 0xb03fffec);       /* mrshpc irq enable */
+
+       se7343_domain_init();
+       se7343_gc_init();
+}
index d2370af56d772a83630d6dacdc5a02f846b799ea..8ce4f2a202a8c1885ee26014826041be35d149f7 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/serial_reg.h>
 #include <linux/usb/isp116x.h>
 #include <linux/delay.h>
+#include <linux/irqdomain.h>
 #include <asm/machvec.h>
 #include <mach-se/mach/se7343.h>
 #include <asm/heartbeat.h>
@@ -145,11 +146,12 @@ static struct platform_device *sh7343se_platform_devices[] __initdata = {
 static int __init sh7343se_devices_setup(void)
 {
        /* Wire-up dynamic vectors */
-       serial_platform_data[0].irq = se7343_fpga_irq[SE7343_FPGA_IRQ_UARTA];
-       serial_platform_data[1].irq = se7343_fpga_irq[SE7343_FPGA_IRQ_UARTB];
-
+       serial_platform_data[0].irq = irq_find_mapping(se7343_irq_domain,
+                                                      SE7343_FPGA_IRQ_UARTA);
+       serial_platform_data[1].irq = irq_find_mapping(se7343_irq_domain,
+                                                      SE7343_FPGA_IRQ_UARTB);
        usb_resources[2].start = usb_resources[2].end =
-               se7343_fpga_irq[SE7343_FPGA_IRQ_USB];
+               irq_find_mapping(se7343_irq_domain, SE7343_FPGA_IRQ_USB);
 
        return platform_add_devices(sh7343se_platform_devices,
                                    ARRAY_SIZE(sh7343se_platform_devices));
index aac92f21ebd23e945b680550eb90274ec622ca0d..f5e2af1bf040ff93dc415362e7ef3f2ac4e75753 100644 (file)
@@ -1,79 +1,96 @@
 /*
- * linux/arch/sh/boards/se/7722/irq.c
+ * Hitachi UL SolutionEngine 7722 FPGA IRQ Support.
  *
  * Copyright (C) 2007  Nobuhiro Iwamatsu
- *
- * Hitachi UL SolutionEngine 7722 Support.
+ * Copyright (C) 2012  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
+#define DRV_NAME "SE7722-FPGA"
+#define pr_fmt(fmt) DRV_NAME ": " fmt
+
+#define irq_reg_readl  ioread16
+#define irq_reg_writel iowrite16
+
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <asm/irq.h>
-#include <asm/io.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <asm/sizes.h>
 #include <mach-se/mach/se7722.h>
 
-unsigned int se7722_fpga_irq[SE7722_FPGA_IRQ_NR] = { 0, };
+#define IRQ01_BASE_ADDR        0x11800000
+#define IRQ01_MODE_REG 0
+#define IRQ01_STS_REG  4
+#define IRQ01_MASK_REG 8
 
-static void disable_se7722_irq(struct irq_data *data)
-{
-       unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data);
-       __raw_writew(__raw_readw(IRQ01_MASK) | 1 << bit, IRQ01_MASK);
-}
+static void __iomem *se7722_irq_regs;
+struct irq_domain *se7722_irq_domain;
 
-static void enable_se7722_irq(struct irq_data *data)
+static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-       unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data);
-       __raw_writew(__raw_readw(IRQ01_MASK) & ~(1 << bit), IRQ01_MASK);
-}
+       struct irq_data *data = irq_get_irq_data(irq);
+       struct irq_chip *chip = irq_data_get_irq_chip(data);
+       unsigned long mask;
+       int bit;
 
-static struct irq_chip se7722_irq_chip __read_mostly = {
-       .name           = "SE7722-FPGA",
-       .irq_mask       = disable_se7722_irq,
-       .irq_unmask     = enable_se7722_irq,
-};
+       chip->irq_mask_ack(data);
 
-static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc)
+       mask = ioread16(se7722_irq_regs + IRQ01_STS_REG);
+
+       for_each_set_bit(bit, &mask, SE7722_FPGA_IRQ_NR)
+               generic_handle_irq(irq_linear_revmap(se7722_irq_domain, bit));
+
+       chip->irq_unmask(data);
+}
+
+static void __init se7722_domain_init(void)
 {
-       unsigned short intv = __raw_readw(IRQ01_STS);
-       unsigned int ext_irq = 0;
+       int i;
 
-       intv &= (1 << SE7722_FPGA_IRQ_NR) - 1;
+       se7722_irq_domain = irq_domain_add_linear(NULL, SE7722_FPGA_IRQ_NR,
+                                                 &irq_domain_simple_ops, NULL);
+       if (unlikely(!se7722_irq_domain)) {
+               printk("Failed to get IRQ domain\n");
+               return;
+       }
 
-       for (; intv; intv >>= 1, ext_irq++) {
-               if (!(intv & 1))
-                       continue;
+       for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) {
+               int irq = irq_create_mapping(se7722_irq_domain, i);
 
-               generic_handle_irq(se7722_fpga_irq[ext_irq]);
+               if (unlikely(irq == 0)) {
+                       printk("Failed to allocate IRQ %d\n", i);
+                       return;
+               }
        }
 }
 
-/*
- * Initialize IRQ setting
- */
-void __init init_se7722_IRQ(void)
+static void __init se7722_gc_init(void)
 {
-       int i, irq;
+       struct irq_chip_generic *gc;
+       struct irq_chip_type *ct;
+       unsigned int irq_base;
 
-       __raw_writew(0, IRQ01_MASK);       /* disable all irqs */
-       __raw_writew(0x2000, 0xb03fffec);  /* mrshpc irq enable */
+       irq_base = irq_linear_revmap(se7722_irq_domain, 0);
 
-       for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) {
-               irq = create_irq();
-               if (irq < 0)
-                       return;
-               se7722_fpga_irq[i] = irq;
+       gc = irq_alloc_generic_chip(DRV_NAME, 1, irq_base, se7722_irq_regs,
+                                   handle_level_irq);
+       if (unlikely(!gc))
+               return;
 
-               irq_set_chip_and_handler_name(se7722_fpga_irq[i],
-                                             &se7722_irq_chip,
-                                             handle_level_irq,
-                                             "level");
+       ct = gc->chip_types;
+       ct->chip.irq_mask = irq_gc_mask_set_bit;
+       ct->chip.irq_unmask = irq_gc_mask_clr_bit;
 
-               irq_set_chip_data(se7722_fpga_irq[i], (void *)i);
-       }
+       ct->regs.mask = IRQ01_MASK_REG;
+
+       irq_setup_generic_chip(gc, IRQ_MSK(SE7722_FPGA_IRQ_NR),
+                              IRQ_GC_INIT_MASK_CACHE,
+                              IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 
        irq_set_chained_handler(IRQ0_IRQ, se7722_irq_demux);
        irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
@@ -81,3 +98,25 @@ void __init init_se7722_IRQ(void)
        irq_set_chained_handler(IRQ1_IRQ, se7722_irq_demux);
        irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
 }
+
+/*
+ * Initialize FPGA IRQs
+ */
+void __init init_se7722_IRQ(void)
+{
+       se7722_irq_regs = ioremap(IRQ01_BASE_ADDR, SZ_16);
+       if (unlikely(!se7722_irq_regs)) {
+               printk("Failed to remap IRQ01 regs\n");
+               return;
+       }
+
+       /*
+        * All FPGA IRQs disabled by default
+        */
+       iowrite16(0, se7722_irq_regs + IRQ01_MASK_REG);
+
+       __raw_writew(0x2000, 0xb03fffec);  /* mrshpc irq enable */
+
+       se7722_domain_init();
+       se7722_gc_init();
+}
index 8f7f0550cfded7dcc2751db7e63e933d353bd510..e04e2bc4698481374b2e6c16f9580d70021e9382 100644 (file)
@@ -2,6 +2,7 @@
  * linux/arch/sh/boards/se/7722/setup.c
  *
  * Copyright (C) 2007 Nobuhiro Iwamatsu
+ * Copyright (C) 2012 Paul Mundt
  *
  * Hitachi UL SolutionEngine 7722 Support.
  *
@@ -15,6 +16,7 @@
 #include <linux/ata_platform.h>
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
+#include <linux/irqdomain.h>
 #include <linux/smc91x.h>
 #include <linux/sh_intc.h>
 #include <mach-se/mach/se7722.h>
@@ -143,10 +145,10 @@ static int __init se7722_devices_setup(void)
 
        /* Wire-up dynamic vectors */
        cf_ide_resources[2].start = cf_ide_resources[2].end =
-               se7722_fpga_irq[SE7722_FPGA_IRQ_MRSHPC0];
+               irq_find_mapping(se7722_irq_domain, SE7722_FPGA_IRQ_MRSHPC0);
 
        smc91x_eth_resources[1].start = smc91x_eth_resources[1].end =
-               se7722_fpga_irq[SE7722_FPGA_IRQ_SMC];
+               irq_find_mapping(se7722_irq_domain, SE7722_FPGA_IRQ_SMC);
 
        return platform_add_devices(se7722_devices, ARRAY_SIZE(se7722_devices));
 }
index c6342ce7768df0432b4e67190a50cc808bb65da6..5d1d3ec9a6cdd26de792e3538020fb7c45a9f073 100644 (file)
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <asm/irq.h>
-#include <asm/io.h>
+#include <linux/export.h>
+#include <linux/topology.h>
+#include <linux/io.h>
+#include <linux/err.h>
 #include <mach-se/mach/se7724.h>
 
 struct fpga_irq {
@@ -111,7 +113,7 @@ static void se7724_irq_demux(unsigned int irq, struct irq_desc *desc)
  */
 void __init init_se7724_IRQ(void)
 {
-       int i, nid = cpu_to_node(boot_cpu_data);
+       int irq_base, i;
 
        __raw_writew(0xffff, IRQ0_MR);  /* mask all */
        __raw_writew(0xffff, IRQ1_MR);  /* mask all */
@@ -121,28 +123,16 @@ void __init init_se7724_IRQ(void)
        __raw_writew(0x0000, IRQ2_SR);  /* clear irq */
        __raw_writew(0x002a, IRQ_MODE); /* set irq type */
 
-       for (i = 0; i < SE7724_FPGA_IRQ_NR; i++) {
-               int irq, wanted;
-
-               wanted = SE7724_FPGA_IRQ_BASE + i;
-
-               irq = create_irq_nr(wanted, nid);
-               if (unlikely(irq == 0)) {
-                       pr_err("%s: failed hooking irq %d for FPGA\n",
-                              __func__, wanted);
-                       return;
-               }
-
-               if (unlikely(irq != wanted)) {
-                       pr_err("%s: got irq %d but wanted %d, bailing.\n",
-                              __func__, irq, wanted);
-                       destroy_irq(irq);
-                       return;
-               }
+       irq_base = irq_alloc_descs(SE7724_FPGA_IRQ_BASE, SE7724_FPGA_IRQ_BASE,
+                                  SE7724_FPGA_IRQ_NR, numa_node_id());
+       if (IS_ERR_VALUE(irq_base)) {
+               pr_err("%s: failed hooking irqs for FPGA\n", __func__);
+               return;
+       }
 
-               irq_set_chip_and_handler_name(irq, &se7724_irq_chip,
+       for (i = 0; i < SE7724_FPGA_IRQ_NR; i++)
+               irq_set_chip_and_handler_name(irq_base + i, &se7724_irq_chip,
                                              handle_level_irq, "level");
-       }
 
        irq_set_chained_handler(IRQ0_IRQ, se7724_irq_demux);
        irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
index f33b2b57019c298dd9a6622085fe85ef107bf8d9..3ea65e9b56e80ed34e5aad1055ce31df6666acb3 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Renesas SH-X3 Prototype Baseboard GPIO Support.
  *
- * Copyright (C) 2010  Paul Mundt
+ * Copyright (C) 2010 - 2012  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -17,6 +17,7 @@
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
+#include <linux/irqdomain.h>
 #include <linux/io.h>
 #include <mach/ilsel.h>
 #include <mach/hardware.h>
@@ -26,7 +27,7 @@
 #define KEYDETR 0xb81c0004
 
 static DEFINE_SPINLOCK(x3proto_gpio_lock);
-static unsigned int x3proto_gpio_irq_map[NR_BASEBOARD_GPIOS] = { 0, };
+static struct irq_domain *x3proto_irq_domain;
 
 static int x3proto_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
 {
@@ -49,7 +50,14 @@ static int x3proto_gpio_get(struct gpio_chip *chip, unsigned gpio)
 
 static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
 {
-       return x3proto_gpio_irq_map[gpio];
+       int virq;
+
+       if (gpio < chip->ngpio)
+               virq = irq_create_mapping(x3proto_irq_domain, gpio);
+       else
+               virq = -ENXIO;
+
+       return virq;
 }
 
 static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
@@ -62,9 +70,8 @@ static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
        chip->irq_mask_ack(data);
 
        mask = __raw_readw(KEYDETR);
-
        for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS)
-               generic_handle_irq(x3proto_gpio_to_irq(NULL, pin));
+               generic_handle_irq(irq_linear_revmap(x3proto_irq_domain, pin));
 
        chip->irq_unmask(data);
 }
@@ -78,10 +85,23 @@ struct gpio_chip x3proto_gpio_chip = {
        .ngpio                  = NR_BASEBOARD_GPIOS,
 };
 
+static int x3proto_gpio_irq_map(struct irq_domain *domain, unsigned int virq,
+                               irq_hw_number_t hwirq)
+{
+       irq_set_chip_and_handler_name(virq, &dummy_irq_chip, handle_simple_irq,
+                                     "gpio");
+
+       return 0;
+}
+
+static struct irq_domain_ops x3proto_gpio_irq_ops = {
+       .map    = x3proto_gpio_irq_map,
+       .xlate  = irq_domain_xlate_twocell,
+};
+
 int __init x3proto_gpio_setup(void)
 {
-       int ilsel;
-       int ret, i;
+       int ilsel, ret;
 
        ilsel = ilsel_enable(ILSEL_KEY);
        if (unlikely(ilsel < 0))
@@ -91,21 +111,10 @@ int __init x3proto_gpio_setup(void)
        if (unlikely(ret))
                goto err_gpio;
 
-       for (i = 0; i < NR_BASEBOARD_GPIOS; i++) {
-               unsigned long flags;
-               int irq = create_irq();
-
-               if (unlikely(irq < 0)) {
-                       ret = -EINVAL;
-                       goto err_irq;
-               }
-
-               spin_lock_irqsave(&x3proto_gpio_lock, flags);
-               x3proto_gpio_irq_map[i] = irq;
-               irq_set_chip_and_handler_name(irq, &dummy_irq_chip,
-                                             handle_simple_irq, "gpio");
-               spin_unlock_irqrestore(&x3proto_gpio_lock, flags);
-       }
+       x3proto_irq_domain = irq_domain_add_linear(NULL, NR_BASEBOARD_GPIOS,
+                                                  &x3proto_gpio_irq_ops, NULL);
+       if (unlikely(!x3proto_irq_domain))
+               goto err_irq;
 
        pr_info("registering '%s' support, handling GPIOs %u -> %u, "
                "bound to IRQ %u\n",
@@ -119,10 +128,6 @@ int __init x3proto_gpio_setup(void)
        return 0;
 
 err_irq:
-       for (; i >= 0; --i)
-               if (x3proto_gpio_irq_map[i])
-                       destroy_irq(x3proto_gpio_irq_map[i]);
-
        ret = gpiochip_remove(&x3proto_gpio_chip);
        if (unlikely(ret))
                pr_err("Failed deregistering GPIO\n");
index eb4ea4d44d59527c0cc4e691904b1c516deb24e7..e9735616bdc8ac96bb5fee14923ba53a0d5f12dd 100644 (file)
@@ -73,10 +73,7 @@ static void hd64461_irq_demux(unsigned int irq, struct irq_desc *desc)
 
 int __init setup_hd64461(void)
 {
-       int i, nid = cpu_to_node(boot_cpu_data);
-
-       if (!MACH_HD64461)
-               return 0;
+       int irq_base, i;
 
        printk(KERN_INFO
               "HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n",
@@ -89,28 +86,16 @@ int __init setup_hd64461(void)
 #endif
        __raw_writew(0xffff, HD64461_NIMR);
 
-       /*  IRQ 80 -> 95 belongs to HD64461  */
-       for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) {
-               unsigned int irq;
-
-               irq = create_irq_nr(i, nid);
-               if (unlikely(irq == 0)) {
-                       pr_err("%s: failed hooking irq %d for HD64461\n",
-                              __func__, i);
-                       return -EBUSY;
-               }
-
-               if (unlikely(irq != i)) {
-                       pr_err("%s: got irq %d but wanted %d, bailing.\n",
-                              __func__, irq, i);
-                       destroy_irq(irq);
-                       return -EINVAL;
-               }
-
-               irq_set_chip_and_handler(i, &hd64461_irq_chip,
-                                        handle_level_irq);
+       irq_base = irq_alloc_descs(HD64461_IRQBASE, HD64461_IRQBASE, 16, -1);
+       if (IS_ERR_VALUE(irq_base)) {
+               pr_err("%s: failed hooking irqs for HD64461\n", __func__);
+               return irq_base;
        }
 
+       for (i = 0; i < 16; i++)
+               irq_set_chip_and_handler(irq_base + i, &hd64461_irq_chip,
+                                        handle_level_irq);
+
        irq_set_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux);
        irq_set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW);
 
index 2b87d86bfc4169384ce529af620c5db9e5238acf..dcf278075429fcb2774cbfaeb586a7dc43bf10ab 100644 (file)
@@ -110,6 +110,10 @@ do {                                                       \
 #include <asm-generic/bug.h>
 
 struct pt_regs;
+
+/* arch/sh/kernel/traps.c */
 extern void die(const char *str, struct pt_regs *regs, long err) __attribute__ ((noreturn));
+extern void die_if_kernel(const char *str, struct pt_regs *regs, long err);
+extern void die_if_no_fixup(const char *str, struct pt_regs *regs, long err);
 
 #endif /* __ASM_SH_BUG_H */
index a6201f10c2730878ae987cec8c01142f96569561..8d6a831e7ba1501a54ce9292e110720b7ce38ee6 100644 (file)
@@ -10,6 +10,8 @@ enum die_val {
        DIE_SSTEP,
 };
 
+/* arch/sh/kernel/dumpstack.c */
 extern void printk_address(unsigned long address, int reliable);
+extern void dump_mem(const char *str, unsigned long bottom, unsigned long top);
 
 #endif /* __ASM_SH_KDEBUG_H */
index 50b5d575dff090ccf0b081e3ab4b41fb98cd976c..542521c970c6ef4a0deee858c57c664c2155bd6d 100644 (file)
@@ -50,9 +50,6 @@
 #define PA_LED         0xb0C00000      /* LED */
 #define LED_SHIFT       0
 #define PA_DIPSW       0xb0900000      /* Dip switch 31 */
-#define PA_CPLD_MODESET        0xb1400004      /* CPLD Mode set register */
-#define PA_CPLD_ST     0xb1400008      /* CPLD Interrupt status register */
-#define PA_CPLD_IMSK   0xb140000a      /* CPLD Interrupt mask register */
 /* Area 5 */
 #define PA_EXT5                0x14000000
 #define PA_EXT5_SIZE   0x04000000
 
 #define SE7343_FPGA_IRQ_NR     12
 
+struct irq_domain;
+
 /* arch/sh/boards/se/7343/irq.c */
-extern unsigned int se7343_fpga_irq[];
+extern struct irq_domain *se7343_irq_domain;
 
 void init_7343se_IRQ(void);
 
index 201081ebdbce7f8ef881a591d23029f93777739e..637e7ac753f84c8187d7ef1800d673cd3050f071 100644 (file)
 #define IRQ0_IRQ        evt2irq(0x600)
 #define IRQ1_IRQ        evt2irq(0x620)
 
-#define IRQ01_MODE      0xb1800000
-#define IRQ01_STS       0xb1800004
-#define IRQ01_MASK      0xb1800008
-
-/* Bits in IRQ01_* registers */
-
 #define SE7722_FPGA_IRQ_USB    0 /* IRQ0 */
 #define SE7722_FPGA_IRQ_SMC    1 /* IRQ0 */
 #define SE7722_FPGA_IRQ_MRSHPC0        2 /* IRQ1 */
 #define SE7722_FPGA_IRQ_MRSHPC3        5 /* IRQ1 */
 #define SE7722_FPGA_IRQ_NR     6
 
+struct irq_domain;
+
 /* arch/sh/boards/se/7722/irq.c */
-extern unsigned int se7722_fpga_irq[];
+extern struct irq_domain *se7722_irq_domain;
 
 void init_se7722_IRQ(void);
 
index b205b25eaf45d6d6b0b791703ee83fe3f9e45f8b..10aed41757fc8247f9e1c271623907b31192607b 100644 (file)
@@ -16,6 +16,8 @@
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 #include <asm/io.h>
+#include <asm/unwinder.h>
+#include <asm/stacktrace.h>
 
 static u8 regcache[63];
 
@@ -199,8 +201,11 @@ static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc,
        return 0;
 }
 
-/* Don't put this on the stack since we'll want to call sh64_unwind
- * when we're close to underflowing the stack anyway. */
+/*
+ * Don't put this on the stack since we'll want to call in to
+ * sh64_unwinder_dump() when we're close to underflowing the stack
+ * anyway.
+ */
 static struct pt_regs here_regs;
 
 extern const char syscall_ret;
@@ -208,17 +213,19 @@ extern const char ret_from_syscall;
 extern const char ret_from_exception;
 extern const char ret_from_irq;
 
-static void sh64_unwind_inner(struct pt_regs *regs);
+static void sh64_unwind_inner(const struct stacktrace_ops *ops,
+                             void *data, struct pt_regs *regs);
 
-static void unwind_nested (unsigned long pc, unsigned long fp)
+static inline void unwind_nested(const struct stacktrace_ops *ops, void *data,
+                                unsigned long pc, unsigned long fp)
 {
        if ((fp >= __MEMORY_START) &&
-           ((fp & 7) == 0)) {
-               sh64_unwind_inner((struct pt_regs *) fp);
-       }
+           ((fp & 7) == 0))
+               sh64_unwind_inner(ops, data, (struct pt_regs *)fp);
 }
 
-static void sh64_unwind_inner(struct pt_regs *regs)
+static void sh64_unwind_inner(const struct stacktrace_ops *ops,
+                             void *data, struct pt_regs *regs)
 {
        unsigned long pc, fp;
        int ofs = 0;
@@ -232,29 +239,29 @@ static void sh64_unwind_inner(struct pt_regs *regs)
                int cond;
                unsigned long next_fp, next_pc;
 
-               if (pc == ((unsigned long) &syscall_ret & ~1)) {
+               if (pc == ((unsigned long)&syscall_ret & ~1)) {
                        printk("SYSCALL\n");
-                       unwind_nested(pc,fp);
+                       unwind_nested(ops, data, pc, fp);
                        return;
                }
 
-               if (pc == ((unsigned long) &ret_from_syscall & ~1)) {
+               if (pc == ((unsigned long)&ret_from_syscall & ~1)) {
                        printk("SYSCALL (PREEMPTED)\n");
-                       unwind_nested(pc,fp);
+                       unwind_nested(ops, data, pc, fp);
                        return;
                }
 
                /* In this case, the PC is discovered by lookup_prev_stack_frame but
                   it has 4 taken off it to look like the 'caller' */
-               if (pc == ((unsigned long) &ret_from_exception & ~1)) {
+               if (pc == ((unsigned long)&ret_from_exception & ~1)) {
                        printk("EXCEPTION\n");
-                       unwind_nested(pc,fp);
+                       unwind_nested(ops, data, pc, fp);
                        return;
                }
 
-               if (pc == ((unsigned long) &ret_from_irq & ~1)) {
+               if (pc == ((unsigned long)&ret_from_irq & ~1)) {
                        printk("IRQ\n");
-                       unwind_nested(pc,fp);
+                       unwind_nested(ops, data, pc, fp);
                        return;
                }
 
@@ -263,8 +270,7 @@ static void sh64_unwind_inner(struct pt_regs *regs)
 
                pc -= ofs;
 
-               printk("[<%08lx>] ", pc);
-               print_symbol("%s\n", pc);
+               ops->address(data, pc, 1);
 
                if (first_pass) {
                        /* If the innermost frame is a leaf function, it's
@@ -287,10 +293,13 @@ static void sh64_unwind_inner(struct pt_regs *regs)
        }
 
        printk("\n");
-
 }
 
-void sh64_unwind(struct pt_regs *regs)
+static void sh64_unwinder_dump(struct task_struct *task,
+                              struct pt_regs *regs,
+                              unsigned long *sp,
+                              const struct stacktrace_ops *ops,
+                              void *data)
 {
        if (!regs) {
                /*
@@ -320,7 +329,17 @@ void sh64_unwind(struct pt_regs *regs)
                );
        }
 
-       printk("\nCall Trace:\n");
-       sh64_unwind_inner(regs);
+       sh64_unwind_inner(ops, data, regs);
 }
 
+static struct unwinder sh64_unwinder = {
+       .name   = "sh64-unwinder",
+       .dump   = sh64_unwinder_dump,
+       .rating = 150,
+};
+
+static int __init sh64_unwinder_init(void)
+{
+       return unwinder_register(&sh64_unwinder);
+}
+early_initcall(sh64_unwinder_init);
index 694158b9a50f5655aba0c2bf50551261d13b554b..7617dc4129ac05acf7ade8e12f4791cda212d732 100644 (file)
@@ -2,13 +2,48 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
  *  Copyright (C) 2009  Matt Fleming
+ *  Copyright (C) 2002 - 2012  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  */
 #include <linux/kallsyms.h>
 #include <linux/ftrace.h>
 #include <linux/debug_locks.h>
+#include <linux/kdebug.h>
+#include <linux/export.h>
+#include <linux/uaccess.h>
 #include <asm/unwinder.h>
 #include <asm/stacktrace.h>
 
+void dump_mem(const char *str, unsigned long bottom, unsigned long top)
+{
+       unsigned long p;
+       int i;
+
+       printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
+
+       for (p = bottom & ~31; p < top; ) {
+               printk("%04lx: ", p & 0xffff);
+
+               for (i = 0; i < 8; i++, p += 4) {
+                       unsigned int val;
+
+                       if (p < bottom || p >= top)
+                               printk("         ");
+                       else {
+                               if (__get_user(val, (unsigned int __user *)p)) {
+                                       printk("\n");
+                                       return;
+                               }
+                               printk("%08x ", val);
+                       }
+               }
+               printk("\n");
+       }
+}
+
 void printk_address(unsigned long address, int reliable)
 {
        printk(" [<%p>] %s%pS\n", (void *) address,
@@ -106,3 +141,26 @@ void show_trace(struct task_struct *tsk, unsigned long *sp,
 
        debug_show_held_locks(tsk);
 }
+
+void show_stack(struct task_struct *tsk, unsigned long *sp)
+{
+       unsigned long stack;
+
+       if (!tsk)
+               tsk = current;
+       if (tsk == current)
+               sp = (unsigned long *)current_stack_pointer;
+       else
+               sp = (unsigned long *)tsk->thread.sp;
+
+       stack = (unsigned long)sp;
+       dump_mem("Stack: ", stack, THREAD_SIZE +
+                (unsigned long)task_stack_page(tsk));
+       show_trace(tsk, sp, NULL);
+}
+
+void dump_stack(void)
+{
+       show_stack(NULL, NULL);
+}
+EXPORT_SYMBOL(dump_stack);
index dadce735f7465ee449b83070bf10148303c1b3c8..063af10ff3c1eb9e76c4724d3977b6bd9421b9fe 100644 (file)
@@ -231,16 +231,6 @@ void __init init_IRQ(void)
        irq_ctx_init(smp_processor_id());
 }
 
-#ifdef CONFIG_SPARSE_IRQ
-int __init arch_probe_nr_irqs(void)
-{
-       /*
-        * No pre-allocated IRQs.
-        */
-       return 0;
-}
-#endif
-
 #ifdef CONFIG_HOTPLUG_CPU
 static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu)
 {
index a87e58a9e38fe17ffe37219d56d854ddf0be48b4..72246bc06884c8dee333544ee2c0161090b814db 100644 (file)
@@ -6,9 +6,80 @@
 #include <linux/sched.h>
 #include <linux/uaccess.h>
 #include <linux/hardirq.h>
+#include <linux/kernel.h>
+#include <linux/kexec.h>
+#include <linux/module.h>
 #include <asm/unwinder.h>
 #include <asm/traps.h>
 
+static DEFINE_SPINLOCK(die_lock);
+
+void die(const char *str, struct pt_regs *regs, long err)
+{
+       static int die_counter;
+
+       oops_enter();
+
+       spin_lock_irq(&die_lock);
+       console_verbose();
+       bust_spinlocks(1);
+
+       printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+       print_modules();
+       show_regs(regs);
+
+       printk("Process: %s (pid: %d, stack limit = %p)\n", current->comm,
+                       task_pid_nr(current), task_stack_page(current) + 1);
+
+       if (!user_mode(regs) || in_interrupt())
+               dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
+                        (unsigned long)task_stack_page(current));
+
+       notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV);
+
+       bust_spinlocks(0);
+       add_taint(TAINT_DIE);
+       spin_unlock_irq(&die_lock);
+       oops_exit();
+
+       if (kexec_should_crash(current))
+               crash_kexec(regs);
+
+       if (in_interrupt())
+               panic("Fatal exception in interrupt");
+
+       if (panic_on_oops)
+               panic("Fatal exception");
+
+       do_exit(SIGSEGV);
+}
+
+void die_if_kernel(const char *str, struct pt_regs *regs, long err)
+{
+       if (!user_mode(regs))
+               die(str, regs, err);
+}
+
+/*
+ * try and fix up kernelspace address errors
+ * - userspace errors just cause EFAULT to be returned, resulting in SEGV
+ * - kernel/userspace interfaces cause a jump to an appropriate handler
+ * - other kernel errors are bad
+ */
+void die_if_no_fixup(const char *str, struct pt_regs *regs, long err)
+{
+       if (!user_mode(regs)) {
+               const struct exception_table_entry *fixup;
+               fixup = search_exception_tables(regs->pc);
+               if (fixup) {
+                       regs->pc = fixup->fixup;
+                       return;
+               }
+
+               die(str, regs, err);
+       }
+}
+
 #ifdef CONFIG_GENERIC_BUG
 static void handle_BUG(struct pt_regs *regs)
 {
index a37175deb73fdfa672c604ddab07297c41559981..5f513a64dedfc8f3afa1593a253505d3ce2254eb 100644 (file)
 #include <linux/hardirq.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
 #include <linux/kallsyms.h>
 #include <linux/io.h>
 #include <linux/bug.h>
 #include <linux/debug_locks.h>
 #include <linux/kdebug.h>
-#include <linux/kexec.h>
 #include <linux/limits.h>
 #include <linux/sysfs.h>
 #include <linux/uaccess.h>
 #define TRAP_ILLEGAL_SLOT_INST 13
 #endif
 
-static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
-{
-       unsigned long p;
-       int i;
-
-       printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
-
-       for (p = bottom & ~31; p < top; ) {
-               printk("%04lx: ", p & 0xffff);
-
-               for (i = 0; i < 8; i++, p += 4) {
-                       unsigned int val;
-
-                       if (p < bottom || p >= top)
-                               printk("         ");
-                       else {
-                               if (__get_user(val, (unsigned int __user *)p)) {
-                                       printk("\n");
-                                       return;
-                               }
-                               printk("%08x ", val);
-                       }
-               }
-               printk("\n");
-       }
-}
-
-static DEFINE_SPINLOCK(die_lock);
-
-void die(const char * str, struct pt_regs * regs, long err)
-{
-       static int die_counter;
-
-       oops_enter();
-
-       spin_lock_irq(&die_lock);
-       console_verbose();
-       bust_spinlocks(1);
-
-       printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
-       print_modules();
-       show_regs(regs);
-
-       printk("Process: %s (pid: %d, stack limit = %p)\n", current->comm,
-                       task_pid_nr(current), task_stack_page(current) + 1);
-
-       if (!user_mode(regs) || in_interrupt())
-               dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
-                        (unsigned long)task_stack_page(current));
-
-       notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV);
-
-       bust_spinlocks(0);
-       add_taint(TAINT_DIE);
-       spin_unlock_irq(&die_lock);
-       oops_exit();
-
-       if (kexec_should_crash(current))
-               crash_kexec(regs);
-
-       if (in_interrupt())
-               panic("Fatal exception in interrupt");
-
-       if (panic_on_oops)
-               panic("Fatal exception");
-
-       do_exit(SIGSEGV);
-}
-
-static inline void die_if_kernel(const char *str, struct pt_regs *regs,
-                                long err)
-{
-       if (!user_mode(regs))
-               die(str, regs, err);
-}
-
-/*
- * try and fix up kernelspace address errors
- * - userspace errors just cause EFAULT to be returned, resulting in SEGV
- * - kernel/userspace interfaces cause a jump to an appropriate handler
- * - other kernel errors are bad
- */
-static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
-{
-       if (!user_mode(regs)) {
-               const struct exception_table_entry *fixup;
-               fixup = search_exception_tables(regs->pc);
-               if (fixup) {
-                       regs->pc = fixup->fixup;
-                       return;
-               }
-
-               die(str, regs, err);
-       }
-}
-
 static inline void sign_extend(unsigned int count, unsigned char *dst)
 {
 #ifdef __LITTLE_ENDIAN__
@@ -900,26 +802,3 @@ void __init trap_init(void)
        set_exception_table_vec(TRAP_UBC, breakpoint_trap_handler);
 #endif
 }
-
-void show_stack(struct task_struct *tsk, unsigned long *sp)
-{
-       unsigned long stack;
-
-       if (!tsk)
-               tsk = current;
-       if (tsk == current)
-               sp = (unsigned long *)current_stack_pointer;
-       else
-               sp = (unsigned long *)tsk->thread.sp;
-
-       stack = (unsigned long)sp;
-       dump_mem("Stack: ", stack, THREAD_SIZE +
-                (unsigned long)task_stack_page(tsk));
-       show_trace(tsk, sp, NULL);
-}
-
-void dump_stack(void)
-{
-       show_stack(NULL, NULL);
-}
-EXPORT_SYMBOL(dump_stack);
index 8dae93ed8aff77586c50df0f6830e23f48f13c75..f87d20da17916cc0c3cf8c6cfb286cbbb0d50d5b 100644 (file)
 #include <linux/perf_event.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <linux/atomic.h>
+#include <asm/alignment.h>
 #include <asm/processor.h>
 #include <asm/pgtable.h>
 #include <asm/fpu.h>
 
-#undef DEBUG_EXCEPTION
-#ifdef DEBUG_EXCEPTION
-/* implemented in ../lib/dbg.c */
-extern void show_excp_regs(char *fname, int trapnr, int signr,
-                          struct pt_regs *regs);
-#else
-#define show_excp_regs(a, b, c, d)
-#endif
-
-static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name,
-               unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk);
-
-#define DO_ERROR(trapnr, signr, str, name, tsk) \
-asmlinkage void do_##name(unsigned long error_code, struct pt_regs *regs) \
-{ \
-       do_unhandled_exception(trapnr, signr, str, __stringify(name), error_code, regs, current); \
-}
-
-static DEFINE_SPINLOCK(die_lock);
-
-void die(const char * str, struct pt_regs * regs, long err)
-{
-       console_verbose();
-       spin_lock_irq(&die_lock);
-       printk("%s: %lx\n", str, (err & 0xffffff));
-       show_regs(regs);
-       spin_unlock_irq(&die_lock);
-       do_exit(SIGSEGV);
-}
-
-static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
-{
-       if (!user_mode(regs))
-               die(str, regs, err);
-}
-
-static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
-{
-       if (!user_mode(regs)) {
-               const struct exception_table_entry *fixup;
-               fixup = search_exception_tables(regs->pc);
-               if (fixup) {
-                       regs->pc = fixup->fixup;
-                       return;
-               }
-               die(str, regs, err);
-       }
-}
-
-DO_ERROR(13, SIGILL,  "illegal slot instruction", illegal_slot_inst, current)
-DO_ERROR(87, SIGSEGV, "address error (exec)", address_error_exec, current)
-
-
-/* Implement misaligned load/store handling for kernel (and optionally for user
-   mode too).  Limitation : only SHmedia mode code is handled - there is no
-   handling at all for misaligned accesses occurring in SHcompact code yet. */
-
-static int misaligned_fixup(struct pt_regs *regs);
-
-asmlinkage void do_address_error_load(unsigned long error_code, struct pt_regs *regs)
-{
-       if (misaligned_fixup(regs) < 0) {
-               do_unhandled_exception(7, SIGSEGV, "address error(load)",
-                               "do_address_error_load",
-                               error_code, regs, current);
-       }
-       return;
-}
-
-asmlinkage void do_address_error_store(unsigned long error_code, struct pt_regs *regs)
-{
-       if (misaligned_fixup(regs) < 0) {
-               do_unhandled_exception(8, SIGSEGV, "address error(store)",
-                               "do_address_error_store",
-                               error_code, regs, current);
-       }
-       return;
-}
-
-#if defined(CONFIG_SH64_ID2815_WORKAROUND)
-
-#define OPCODE_INVALID      0
-#define OPCODE_USER_VALID   1
-#define OPCODE_PRIV_VALID   2
-
-/* getcon/putcon - requires checking which control register is referenced. */
-#define OPCODE_CTRL_REG     3
-
-/* Table of valid opcodes for SHmedia mode.
-   Form a 10-bit value by concatenating the major/minor opcodes i.e.
-   opcode[31:26,20:16].  The 6 MSBs of this value index into the following
-   array.  The 4 LSBs select the bit-pair in the entry (bits 1:0 correspond to
-   LSBs==4'b0000 etc). */
-static unsigned long shmedia_opcode_table[64] = {
-       0x55554044,0x54445055,0x15141514,0x14541414,0x00000000,0x10001000,0x01110055,0x04050015,
-       0x00000444,0xc0000000,0x44545515,0x40405555,0x55550015,0x10005555,0x55555505,0x04050000,
-       0x00000555,0x00000404,0x00040445,0x15151414,0x00000000,0x00000000,0x00000000,0x00000000,
-       0x00000055,0x40404444,0x00000404,0xc0009495,0x00000000,0x00000000,0x00000000,0x00000000,
-       0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
-       0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
-       0x80005050,0x04005055,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
-       0x81055554,0x00000404,0x55555555,0x55555555,0x00000000,0x00000000,0x00000000,0x00000000
-};
-
-void do_reserved_inst(unsigned long error_code, struct pt_regs *regs)
-{
-       /* Workaround SH5-101 cut2 silicon defect #2815 :
-          in some situations, inter-mode branches from SHcompact -> SHmedia
-          which should take ITLBMISS or EXECPROT exceptions at the target
-          falsely take RESINST at the target instead. */
-
-       unsigned long opcode = 0x6ff4fff0; /* guaranteed reserved opcode */
-       unsigned long pc, aligned_pc;
-       int get_user_error;
-       int trapnr = 12;
-       int signr = SIGILL;
-       char *exception_name = "reserved_instruction";
-
-       pc = regs->pc;
-       if ((pc & 3) == 1) {
-               /* SHmedia : check for defect.  This requires executable vmas
-                  to be readable too. */
-               aligned_pc = pc & ~3;
-               if (!access_ok(VERIFY_READ, aligned_pc, sizeof(unsigned long))) {
-                       get_user_error = -EFAULT;
-               } else {
-                       get_user_error = __get_user(opcode, (unsigned long *)aligned_pc);
-               }
-               if (get_user_error >= 0) {
-                       unsigned long index, shift;
-                       unsigned long major, minor, combined;
-                       unsigned long reserved_field;
-                       reserved_field = opcode & 0xf; /* These bits are currently reserved as zero in all valid opcodes */
-                       major = (opcode >> 26) & 0x3f;
-                       minor = (opcode >> 16) & 0xf;
-                       combined = (major << 4) | minor;
-                       index = major;
-                       shift = minor << 1;
-                       if (reserved_field == 0) {
-                               int opcode_state = (shmedia_opcode_table[index] >> shift) & 0x3;
-                               switch (opcode_state) {
-                                       case OPCODE_INVALID:
-                                               /* Trap. */
-                                               break;
-                                       case OPCODE_USER_VALID:
-                                               /* Restart the instruction : the branch to the instruction will now be from an RTE
-                                                  not from SHcompact so the silicon defect won't be triggered. */
-                                               return;
-                                       case OPCODE_PRIV_VALID:
-                                               if (!user_mode(regs)) {
-                                                       /* Should only ever get here if a module has
-                                                          SHcompact code inside it.  If so, the same fix up is needed. */
-                                                       return; /* same reason */
-                                               }
-                                               /* Otherwise, user mode trying to execute a privileged instruction -
-                                                  fall through to trap. */
-                                               break;
-                                       case OPCODE_CTRL_REG:
-                                               /* If in privileged mode, return as above. */
-                                               if (!user_mode(regs)) return;
-                                               /* In user mode ... */
-                                               if (combined == 0x9f) { /* GETCON */
-                                                       unsigned long regno = (opcode >> 20) & 0x3f;
-                                                       if (regno >= 62) {
-                                                               return;
-                                                       }
-                                                       /* Otherwise, reserved or privileged control register, => trap */
-                                               } else if (combined == 0x1bf) { /* PUTCON */
-                                                       unsigned long regno = (opcode >> 4) & 0x3f;
-                                                       if (regno >= 62) {
-                                                               return;
-                                                       }
-                                                       /* Otherwise, reserved or privileged control register, => trap */
-                                               } else {
-                                                       /* Trap */
-                                               }
-                                               break;
-                                       default:
-                                               /* Fall through to trap. */
-                                               break;
-                               }
-                       }
-                       /* fall through to normal resinst processing */
-               } else {
-                       /* Error trying to read opcode.  This typically means a
-                          real fault, not a RESINST any more.  So change the
-                          codes. */
-                       trapnr = 87;
-                       exception_name = "address error (exec)";
-                       signr = SIGSEGV;
-               }
-       }
-
-       do_unhandled_exception(trapnr, signr, exception_name, "do_reserved_inst", error_code, regs, current);
-}
-
-#else /* CONFIG_SH64_ID2815_WORKAROUND */
-
-/* If the workaround isn't needed, this is just a straightforward reserved
-   instruction */
-DO_ERROR(12, SIGILL,  "reserved instruction", reserved_inst, current)
-
-#endif /* CONFIG_SH64_ID2815_WORKAROUND */
-
-/* Called with interrupts disabled */
-asmlinkage void do_exception_error(unsigned long ex, struct pt_regs *regs)
-{
-       show_excp_regs(__func__, -1, -1, regs);
-       die_if_kernel("exception", regs, ex);
-}
-
-int do_unknown_trapa(unsigned long scId, struct pt_regs *regs)
-{
-       /* Syscall debug */
-        printk("System call ID error: [0x1#args:8 #syscall:16  0x%lx]\n", scId);
-
-       die_if_kernel("unknown trapa", regs, scId);
-
-       return -ENOSYS;
-}
-
-void show_stack(struct task_struct *tsk, unsigned long *sp)
-{
-#ifdef CONFIG_KALLSYMS
-       extern void sh64_unwind(struct pt_regs *regs);
-       struct pt_regs *regs;
-
-       regs = tsk ? tsk->thread.kregs : NULL;
-
-       sh64_unwind(regs);
-#else
-       printk(KERN_ERR "Can't backtrace on sh64 without CONFIG_KALLSYMS\n");
-#endif
-}
-
-void show_task(unsigned long *sp)
-{
-       show_stack(NULL, sp);
-}
-
-void dump_stack(void)
-{
-       show_task(NULL);
-}
-/* Needed by any user of WARN_ON in view of the defn in include/asm-sh/bug.h */
-EXPORT_SYMBOL(dump_stack);
-
-static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name,
-               unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk)
-{
-       show_excp_regs(fn_name, trapnr, signr, regs);
-
-       if (user_mode(regs))
-               force_sig(signr, tsk);
-
-       die_if_no_fixup(str, regs, error_code);
-}
-
-static int read_opcode(unsigned long long pc, unsigned long *result_opcode, int from_user_mode)
+static int read_opcode(reg_size_t pc, insn_size_t *result_opcode, int from_user_mode)
 {
        int get_user_error;
        unsigned long aligned_pc;
-       unsigned long opcode;
+       insn_size_t opcode;
 
        if ((pc & 3) == 1) {
                /* SHmedia */
                aligned_pc = pc & ~3;
                if (from_user_mode) {
-                       if (!access_ok(VERIFY_READ, aligned_pc, sizeof(unsigned long))) {
+                       if (!access_ok(VERIFY_READ, aligned_pc, sizeof(insn_size_t))) {
                                get_user_error = -EFAULT;
                        } else {
-                               get_user_error = __get_user(opcode, (unsigned long *)aligned_pc);
+                               get_user_error = __get_user(opcode, (insn_size_t *)aligned_pc);
                                *result_opcode = opcode;
                        }
                        return get_user_error;
@@ -311,7 +53,7 @@ static int read_opcode(unsigned long long pc, unsigned long *result_opcode, int
                        /* If the fault was in the kernel, we can either read
                         * this directly, or if not, we fault.
                        */
-                       *result_opcode = *(unsigned long *) aligned_pc;
+                       *result_opcode = *(insn_size_t *)aligned_pc;
                        return 0;
                }
        } else if ((pc & 1) == 0) {
@@ -337,17 +79,23 @@ static int address_is_sign_extended(__u64 a)
 #endif
 }
 
+/* return -1 for fault, 0 for OK */
 static int generate_and_check_address(struct pt_regs *regs,
-                                     __u32 opcode,
+                                     insn_size_t opcode,
                                      int displacement_not_indexed,
                                      int width_shift,
                                      __u64 *address)
 {
-       /* return -1 for fault, 0 for OK */
-
        __u64 base_address, addr;
        int basereg;
 
+       switch (1 << width_shift) {
+       case 1: inc_unaligned_byte_access(); break;
+       case 2: inc_unaligned_word_access(); break;
+       case 4: inc_unaligned_dword_access(); break;
+       case 8: inc_unaligned_multi_access(); break;
+       }
+
        basereg = (opcode >> 20) & 0x3f;
        base_address = regs->regs[basereg];
        if (displacement_not_indexed) {
@@ -364,28 +112,28 @@ static int generate_and_check_address(struct pt_regs *regs,
        }
 
        /* Check sign extended */
-       if (!address_is_sign_extended(addr)) {
+       if (!address_is_sign_extended(addr))
                return -1;
-       }
 
        /* Check accessible.  For misaligned access in the kernel, assume the
           address is always accessible (and if not, just fault when the
           load/store gets done.) */
        if (user_mode(regs)) {
-               if (addr >= TASK_SIZE) {
+               inc_unaligned_user_access();
+
+               if (addr >= TASK_SIZE)
                        return -1;
-               }
-               /* Do access_ok check later - it depends on whether it's a load or a store. */
-       }
+       } else
+               inc_unaligned_kernel_access();
 
        *address = addr;
+
+       perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, addr);
+       unaligned_fixups_notify(current, opcode, regs);
+
        return 0;
 }
 
-static int user_mode_unaligned_fixup_count = 10;
-static int user_mode_unaligned_fixup_enable = 1;
-static int kernel_mode_unaligned_fixup_count = 32;
-
 static void misaligned_kernel_word_load(__u64 address, int do_sign_extend, __u64 *result)
 {
        unsigned short x;
@@ -415,7 +163,7 @@ static void misaligned_kernel_word_store(__u64 address, __u64 value)
 }
 
 static int misaligned_load(struct pt_regs *regs,
-                          __u32 opcode,
+                          insn_size_t opcode,
                           int displacement_not_indexed,
                           int width_shift,
                           int do_sign_extend)
@@ -427,11 +175,8 @@ static int misaligned_load(struct pt_regs *regs,
 
        error = generate_and_check_address(regs, opcode,
                        displacement_not_indexed, width_shift, &address);
-       if (error < 0) {
+       if (error < 0)
                return error;
-       }
-
-       perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, address);
 
        destreg = (opcode >> 4) & 0x3f;
        if (user_mode(regs)) {
@@ -490,11 +235,10 @@ static int misaligned_load(struct pt_regs *regs,
        }
 
        return 0;
-
 }
 
 static int misaligned_store(struct pt_regs *regs,
-                           __u32 opcode,
+                           insn_size_t opcode,
                            int displacement_not_indexed,
                            int width_shift)
 {
@@ -505,11 +249,8 @@ static int misaligned_store(struct pt_regs *regs,
 
        error = generate_and_check_address(regs, opcode,
                        displacement_not_indexed, width_shift, &address);
-       if (error < 0) {
+       if (error < 0)
                return error;
-       }
-
-       perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, address);
 
        srcreg = (opcode >> 4) & 0x3f;
        if (user_mode(regs)) {
@@ -563,13 +304,12 @@ static int misaligned_store(struct pt_regs *regs,
        }
 
        return 0;
-
 }
 
 /* Never need to fix up misaligned FPU accesses within the kernel since that's a real
    error. */
 static int misaligned_fpu_load(struct pt_regs *regs,
-                          __u32 opcode,
+                          insn_size_t opcode,
                           int displacement_not_indexed,
                           int width_shift,
                           int do_paired_load)
@@ -581,11 +321,8 @@ static int misaligned_fpu_load(struct pt_regs *regs,
 
        error = generate_and_check_address(regs, opcode,
                        displacement_not_indexed, width_shift, &address);
-       if (error < 0) {
+       if (error < 0)
                return error;
-       }
-
-       perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, address);
 
        destreg = (opcode >> 4) & 0x3f;
        if (user_mode(regs)) {
@@ -641,12 +378,10 @@ static int misaligned_fpu_load(struct pt_regs *regs,
                die ("Misaligned FPU load inside kernel", regs, 0);
                return -1;
        }
-
-
 }
 
 static int misaligned_fpu_store(struct pt_regs *regs,
-                          __u32 opcode,
+                          insn_size_t opcode,
                           int displacement_not_indexed,
                           int width_shift,
                           int do_paired_load)
@@ -658,11 +393,8 @@ static int misaligned_fpu_store(struct pt_regs *regs,
 
        error = generate_and_check_address(regs, opcode,
                        displacement_not_indexed, width_shift, &address);
-       if (error < 0) {
+       if (error < 0)
                return error;
-       }
-
-       perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, address);
 
        srcreg = (opcode >> 4) & 0x3f;
        if (user_mode(regs)) {
@@ -723,11 +455,13 @@ static int misaligned_fpu_store(struct pt_regs *regs,
 
 static int misaligned_fixup(struct pt_regs *regs)
 {
-       unsigned long opcode;
+       insn_size_t opcode;
        int error;
        int major, minor;
+       unsigned int user_action;
 
-       if (!user_mode_unaligned_fixup_enable)
+       user_action = unaligned_user_action();
+       if (!(user_action & UM_FIXUP))
                return -1;
 
        error = read_opcode(regs->pc, &opcode, user_mode(regs));
@@ -737,23 +471,6 @@ static int misaligned_fixup(struct pt_regs *regs)
        major = (opcode >> 26) & 0x3f;
        minor = (opcode >> 16) & 0xf;
 
-       if (user_mode(regs) && (user_mode_unaligned_fixup_count > 0)) {
-               --user_mode_unaligned_fixup_count;
-               /* Only do 'count' worth of these reports, to remove a potential DoS against syslog */
-               printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n",
-                      current->comm, task_pid_nr(current), (__u32)regs->pc, opcode);
-       } else if (!user_mode(regs) && (kernel_mode_unaligned_fixup_count > 0)) {
-               --kernel_mode_unaligned_fixup_count;
-               if (in_interrupt()) {
-                       printk("Fixing up unaligned kernelspace access in interrupt pc=0x%08x ins=0x%08lx\n",
-                              (__u32)regs->pc, opcode);
-               } else {
-                       printk("Fixing up unaligned kernelspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n",
-                              current->comm, task_pid_nr(current), (__u32)regs->pc, opcode);
-               }
-       }
-
-
        switch (major) {
                case (0x84>>2): /* LD.W */
                        error = misaligned_load(regs, opcode, 1, 1, 1);
@@ -878,59 +595,202 @@ static int misaligned_fixup(struct pt_regs *regs)
                regs->pc += 4; /* Skip the instruction that's just been emulated */
                return 0;
        }
+}
+
+static void do_unhandled_exception(int signr, char *str, unsigned long error,
+                                  struct pt_regs *regs)
+{
+       if (user_mode(regs))
+               force_sig(signr, current);
 
+       die_if_no_fixup(str, regs, error);
 }
 
-static ctl_table unaligned_table[] = {
-       {
-               .procname       = "kernel_reports",
-               .data           = &kernel_mode_unaligned_fixup_count,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec
-       },
-       {
-               .procname       = "user_reports",
-               .data           = &user_mode_unaligned_fixup_count,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec
-       },
-       {
-               .procname       = "user_enable",
-               .data           = &user_mode_unaligned_fixup_enable,
-               .maxlen         = sizeof(int),
-               .mode           = 0644,
-               .proc_handler   = proc_dointvec},
-       {}
-};
+#define DO_ERROR(signr, str, name) \
+asmlinkage void do_##name(unsigned long error_code, struct pt_regs *regs) \
+{ \
+       do_unhandled_exception(signr, str, error_code, regs); \
+}
 
-static ctl_table unaligned_root[] = {
-       {
-               .procname       = "unaligned_fixup",
-               .mode           = 0555,
-               .child          = unaligned_table
-       },
-       {}
-};
+DO_ERROR(SIGILL,  "illegal slot instruction", illegal_slot_inst)
+DO_ERROR(SIGSEGV, "address error (exec)", address_error_exec)
+
+#if defined(CONFIG_SH64_ID2815_WORKAROUND)
+
+#define OPCODE_INVALID      0
+#define OPCODE_USER_VALID   1
+#define OPCODE_PRIV_VALID   2
 
-static ctl_table sh64_root[] = {
-       {
-               .procname       = "sh64",
-               .mode           = 0555,
-               .child          = unaligned_root
-       },
-       {}
+/* getcon/putcon - requires checking which control register is referenced. */
+#define OPCODE_CTRL_REG     3
+
+/* Table of valid opcodes for SHmedia mode.
+   Form a 10-bit value by concatenating the major/minor opcodes i.e.
+   opcode[31:26,20:16].  The 6 MSBs of this value index into the following
+   array.  The 4 LSBs select the bit-pair in the entry (bits 1:0 correspond to
+   LSBs==4'b0000 etc). */
+static unsigned long shmedia_opcode_table[64] = {
+       0x55554044,0x54445055,0x15141514,0x14541414,0x00000000,0x10001000,0x01110055,0x04050015,
+       0x00000444,0xc0000000,0x44545515,0x40405555,0x55550015,0x10005555,0x55555505,0x04050000,
+       0x00000555,0x00000404,0x00040445,0x15151414,0x00000000,0x00000000,0x00000000,0x00000000,
+       0x00000055,0x40404444,0x00000404,0xc0009495,0x00000000,0x00000000,0x00000000,0x00000000,
+       0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
+       0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
+       0x80005050,0x04005055,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,
+       0x81055554,0x00000404,0x55555555,0x55555555,0x00000000,0x00000000,0x00000000,0x00000000
 };
-static struct ctl_table_header *sysctl_header;
-static int __init init_sysctl(void)
+
+/* Workaround SH5-101 cut2 silicon defect #2815 :
+   in some situations, inter-mode branches from SHcompact -> SHmedia
+   which should take ITLBMISS or EXECPROT exceptions at the target
+   falsely take RESINST at the target instead. */
+void do_reserved_inst(unsigned long error_code, struct pt_regs *regs)
 {
-       sysctl_header = register_sysctl_table(sh64_root);
-       return 0;
+       insn_size_t opcode = 0x6ff4fff0; /* guaranteed reserved opcode */
+       unsigned long pc, aligned_pc;
+       unsigned long index, shift;
+       unsigned long major, minor, combined;
+       unsigned long reserved_field;
+       int opcode_state;
+       int get_user_error;
+       int signr = SIGILL;
+       char *exception_name = "reserved_instruction";
+
+       pc = regs->pc;
+
+       /* SHcompact is not handled */
+       if (unlikely((pc & 3) == 0))
+               goto out;
+
+       /* SHmedia : check for defect.  This requires executable vmas
+          to be readable too. */
+       aligned_pc = pc & ~3;
+       if (!access_ok(VERIFY_READ, aligned_pc, sizeof(insn_size_t)))
+               get_user_error = -EFAULT;
+       else
+               get_user_error = __get_user(opcode, (insn_size_t *)aligned_pc);
+
+       if (get_user_error < 0) {
+               /*
+                * Error trying to read opcode.  This typically means a
+                * real fault, not a RESINST any more.  So change the
+                * codes.
+                */
+               exception_name = "address error (exec)";
+               signr = SIGSEGV;
+               goto out;
+       }
+
+       /* These bits are currently reserved as zero in all valid opcodes */
+       reserved_field = opcode & 0xf;
+       if (unlikely(reserved_field))
+               goto out;       /* invalid opcode */
+
+       major = (opcode >> 26) & 0x3f;
+       minor = (opcode >> 16) & 0xf;
+       combined = (major << 4) | minor;
+       index = major;
+       shift = minor << 1;
+       opcode_state = (shmedia_opcode_table[index] >> shift) & 0x3;
+       switch (opcode_state) {
+       case OPCODE_INVALID:
+               /* Trap. */
+               break;
+       case OPCODE_USER_VALID:
+               /*
+                * Restart the instruction: the branch to the instruction
+                * will now be from an RTE not from SHcompact so the
+                * silicon defect won't be triggered.
+                */
+               return;
+       case OPCODE_PRIV_VALID:
+               if (!user_mode(regs)) {
+                       /*
+                        * Should only ever get here if a module has
+                        * SHcompact code inside it. If so, the same fix
+                        * up is needed.
+                        */
+                       return; /* same reason */
+               }
+
+               /*
+                * Otherwise, user mode trying to execute a privileged
+                * instruction - fall through to trap.
+                */
+               break;
+       case OPCODE_CTRL_REG:
+               /* If in privileged mode, return as above. */
+               if (!user_mode(regs))
+                       return;
+
+               /* In user mode ... */
+               if (combined == 0x9f) { /* GETCON */
+                       unsigned long regno = (opcode >> 20) & 0x3f;
+
+                       if (regno >= 62)
+                               return;
+
+                       /* reserved/privileged control register => trap */
+               } else if (combined == 0x1bf) { /* PUTCON */
+                       unsigned long regno = (opcode >> 4) & 0x3f;
+
+                       if (regno >= 62)
+                               return;
+
+                       /* reserved/privileged control register => trap */
+               }
+
+               break;
+       default:
+               /* Fall through to trap. */
+               break;
+       }
+
+out:
+       do_unhandled_exception(signr, exception_name, error_code, regs);
 }
 
-__initcall(init_sysctl);
+#else /* CONFIG_SH64_ID2815_WORKAROUND */
 
+/* If the workaround isn't needed, this is just a straightforward reserved
+   instruction */
+DO_ERROR(SIGILL, "reserved instruction", reserved_inst)
+
+#endif /* CONFIG_SH64_ID2815_WORKAROUND */
+
+/* Called with interrupts disabled */
+asmlinkage void do_exception_error(unsigned long ex, struct pt_regs *regs)
+{
+       die_if_kernel("exception", regs, ex);
+}
+
+asmlinkage int do_unknown_trapa(unsigned long scId, struct pt_regs *regs)
+{
+       /* Syscall debug */
+       printk("System call ID error: [0x1#args:8 #syscall:16  0x%lx]\n", scId);
+
+       die_if_kernel("unknown trapa", regs, scId);
+
+       return -ENOSYS;
+}
+
+/* Implement misaligned load/store handling for kernel (and optionally for user
+   mode too).  Limitation : only SHmedia mode code is handled - there is no
+   handling at all for misaligned accesses occurring in SHcompact code yet. */
+
+asmlinkage void do_address_error_load(unsigned long error_code, struct pt_regs *regs)
+{
+       if (misaligned_fixup(regs) < 0)
+               do_unhandled_exception(SIGSEGV, "address error(load)",
+                                      error_code, regs);
+}
+
+asmlinkage void do_address_error_store(unsigned long error_code, struct pt_regs *regs)
+{
+       if (misaligned_fixup(regs) < 0)
+               do_unhandled_exception(SIGSEGV, "address error(store)",
+                               error_code, regs);
+}
 
 asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs)
 {
@@ -942,10 +802,9 @@ asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs)
           of access we make to them - just go direct to their physical
           addresses. */
        exp_cause = peek_real_address_q(DM_EXP_CAUSE_PHY);
-       if (exp_cause & ~4) {
+       if (exp_cause & ~4)
                printk("DM.EXP_CAUSE had unexpected bits set (=%08lx)\n",
                        (unsigned long)(exp_cause & 0xffffffff));
-       }
        show_state();
        /* Clear all DEBUGINT causes */
        poke_real_address_q(DM_EXP_CAUSE_PHY, 0x0);
index 1fee75aa1f989719ebd19298f7af2ae9f65aa9f8..69779ff741dfeb4c6e5f19ed3af6198d47ac06b2 100644 (file)
@@ -10,7 +10,7 @@
 #
 
 # Panic should really be compiled as PIC
-lib-y  := udelay.o dbg.o panic.o memcpy.o memset.o \
+lib-y  := udelay.o panic.o memcpy.o memset.o \
          copy_user_memcpy.o copy_page.o strcpy.o strlen.o
 
 # Extracted from libgcc
diff --git a/arch/sh/lib64/dbg.c b/arch/sh/lib64/dbg.c
deleted file mode 100644 (file)
index 6152a6a..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-/*--------------------------------------------------------------------------
---
--- Identity : Linux50 Debug Funcions
---
--- File     : arch/sh/lib64/dbg.c
---
--- Copyright 2000, 2001 STMicroelectronics Limited.
--- Copyright 2004 Richard Curnow (evt_debug etc)
---
---------------------------------------------------------------------------*/
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <asm/mmu_context.h>
-
-typedef u64 regType_t;
-
-static regType_t getConfigReg(u64 id)
-{
-       register u64 reg __asm__("r2");
-       asm volatile ("getcfg   %1, 0, %0":"=r" (reg):"r"(id));
-       return (reg);
-}
-
-/* ======================================================================= */
-
-static char *szTab[] = { "4k", "64k", "1M", "512M" };
-static char *protTab[] = { "----",
-       "---R",
-       "--X-",
-       "--XR",
-       "-W--",
-       "-W-R",
-       "-WX-",
-       "-WXR",
-       "U---",
-       "U--R",
-       "U-X-",
-       "U-XR",
-       "UW--",
-       "UW-R",
-       "UWX-",
-       "UWXR"
-};
-#define  ITLB_BASE     0x00000000
-#define  DTLB_BASE     0x00800000
-#define  MAX_TLBs              64
-/* PTE High */
-#define  GET_VALID(pte)        ((pte) & 0x1)
-#define  GET_SHARED(pte)       ((pte) & 0x2)
-#define  GET_ASID(pte)         ((pte >> 2) & 0x0ff)
-#define  GET_EPN(pte)          ((pte) & 0xfffff000)
-
-/* PTE Low */
-#define  GET_CBEHAVIOR(pte)    ((pte) & 0x3)
-#define  GET_PAGE_SIZE(pte)    szTab[((pte >> 3) & 0x3)]
-#define  GET_PROTECTION(pte)   protTab[((pte >> 6) & 0xf)]
-#define  GET_PPN(pte)          ((pte) & 0xfffff000)
-
-#define PAGE_1K_MASK           0x00000000
-#define PAGE_4K_MASK           0x00000010
-#define PAGE_64K_MASK          0x00000080
-#define MMU_PAGESIZE_MASK      (PAGE_64K_MASK | PAGE_4K_MASK)
-#define PAGE_1MB_MASK          MMU_PAGESIZE_MASK
-#define PAGE_1K                (1024)
-#define PAGE_4K                (1024 * 4)
-#define PAGE_64K               (1024 * 64)
-#define PAGE_1MB               (1024 * 1024)
-
-#define HOW_TO_READ_TLB_CONTENT  \
-       "[ ID]  PPN         EPN        ASID  Share  CB  P.Size   PROT.\n"
-
-void print_single_tlb(unsigned long tlb, int single_print)
-{
-       regType_t pteH;
-       regType_t pteL;
-       unsigned int valid, shared, asid, epn, cb, ppn;
-       char *pSize;
-       char *pProt;
-
-       /*
-          ** in case of single print <single_print> is true, this implies:
-          **   1) print the TLB in any case also if NOT VALID
-          **   2) print out the header
-        */
-
-       pteH = getConfigReg(tlb);
-       valid = GET_VALID(pteH);
-       if (single_print)
-               printk(HOW_TO_READ_TLB_CONTENT);
-       else if (!valid)
-               return;
-
-       pteL = getConfigReg(tlb + 1);
-
-       shared = GET_SHARED(pteH);
-       asid = GET_ASID(pteH);
-       epn = GET_EPN(pteH);
-       cb = GET_CBEHAVIOR(pteL);
-       pSize = GET_PAGE_SIZE(pteL);
-       pProt = GET_PROTECTION(pteL);
-       ppn = GET_PPN(pteL);
-       printk("[%c%2ld]  0x%08x  0x%08x  %03d   %02x    %02x   %4s    %s\n",
-              ((valid) ? ' ' : 'u'), ((tlb & 0x0ffff) / TLB_STEP),
-              ppn, epn, asid, shared, cb, pSize, pProt);
-}
-
-void print_dtlb(void)
-{
-       int count;
-       unsigned long tlb;
-
-       printk(" ================= SH-5 D-TLBs Status ===================\n");
-       printk(HOW_TO_READ_TLB_CONTENT);
-       tlb = DTLB_BASE;
-       for (count = 0; count < MAX_TLBs; count++, tlb += TLB_STEP)
-               print_single_tlb(tlb, 0);
-       printk
-           (" =============================================================\n");
-}
-
-void print_itlb(void)
-{
-       int count;
-       unsigned long tlb;
-
-       printk(" ================= SH-5 I-TLBs Status ===================\n");
-       printk(HOW_TO_READ_TLB_CONTENT);
-       tlb = ITLB_BASE;
-       for (count = 0; count < MAX_TLBs; count++, tlb += TLB_STEP)
-               print_single_tlb(tlb, 0);
-       printk
-           (" =============================================================\n");
-}
-
-void show_excp_regs(char *from, int trapnr, int signr, struct pt_regs *regs)
-{
-
-       unsigned long long ah, al, bh, bl, ch, cl;
-
-       printk("\n");
-       printk("EXCEPTION - %s: task %d; Linux trap # %d; signal = %d\n",
-              ((from) ? from : "???"), current->pid, trapnr, signr);
-
-       asm volatile ("getcon   " __EXPEVT ", %0":"=r"(ah));
-       asm volatile ("getcon   " __EXPEVT ", %0":"=r"(al));
-       ah = (ah) >> 32;
-       al = (al) & 0xffffffff;
-       asm volatile ("getcon   " __KCR1 ", %0":"=r"(bh));
-       asm volatile ("getcon   " __KCR1 ", %0":"=r"(bl));
-       bh = (bh) >> 32;
-       bl = (bl) & 0xffffffff;
-       asm volatile ("getcon   " __INTEVT ", %0":"=r"(ch));
-       asm volatile ("getcon   " __INTEVT ", %0":"=r"(cl));
-       ch = (ch) >> 32;
-       cl = (cl) & 0xffffffff;
-       printk("EXPE: %08Lx%08Lx KCR1: %08Lx%08Lx INTE: %08Lx%08Lx\n",
-              ah, al, bh, bl, ch, cl);
-
-       asm volatile ("getcon   " __PEXPEVT ", %0":"=r"(ah));
-       asm volatile ("getcon   " __PEXPEVT ", %0":"=r"(al));
-       ah = (ah) >> 32;
-       al = (al) & 0xffffffff;
-       asm volatile ("getcon   " __PSPC ", %0":"=r"(bh));
-       asm volatile ("getcon   " __PSPC ", %0":"=r"(bl));
-       bh = (bh) >> 32;
-       bl = (bl) & 0xffffffff;
-       asm volatile ("getcon   " __PSSR ", %0":"=r"(ch));
-       asm volatile ("getcon   " __PSSR ", %0":"=r"(cl));
-       ch = (ch) >> 32;
-       cl = (cl) & 0xffffffff;
-       printk("PEXP: %08Lx%08Lx PSPC: %08Lx%08Lx PSSR: %08Lx%08Lx\n",
-              ah, al, bh, bl, ch, cl);
-
-       ah = (regs->pc) >> 32;
-       al = (regs->pc) & 0xffffffff;
-       bh = (regs->regs[18]) >> 32;
-       bl = (regs->regs[18]) & 0xffffffff;
-       ch = (regs->regs[15]) >> 32;
-       cl = (regs->regs[15]) & 0xffffffff;
-       printk("PC  : %08Lx%08Lx LINK: %08Lx%08Lx SP  : %08Lx%08Lx\n",
-              ah, al, bh, bl, ch, cl);
-
-       ah = (regs->sr) >> 32;
-       al = (regs->sr) & 0xffffffff;
-       asm volatile ("getcon   " __TEA ", %0":"=r"(bh));
-       asm volatile ("getcon   " __TEA ", %0":"=r"(bl));
-       bh = (bh) >> 32;
-       bl = (bl) & 0xffffffff;
-       asm volatile ("getcon   " __KCR0 ", %0":"=r"(ch));
-       asm volatile ("getcon   " __KCR0 ", %0":"=r"(cl));
-       ch = (ch) >> 32;
-       cl = (cl) & 0xffffffff;
-       printk("SR  : %08Lx%08Lx TEA : %08Lx%08Lx KCR0: %08Lx%08Lx\n",
-              ah, al, bh, bl, ch, cl);
-
-       ah = (regs->regs[0]) >> 32;
-       al = (regs->regs[0]) & 0xffffffff;
-       bh = (regs->regs[1]) >> 32;
-       bl = (regs->regs[1]) & 0xffffffff;
-       ch = (regs->regs[2]) >> 32;
-       cl = (regs->regs[2]) & 0xffffffff;
-       printk("R0  : %08Lx%08Lx R1  : %08Lx%08Lx R2  : %08Lx%08Lx\n",
-              ah, al, bh, bl, ch, cl);
-
-       ah = (regs->regs[3]) >> 32;
-       al = (regs->regs[3]) & 0xffffffff;
-       bh = (regs->regs[4]) >> 32;
-       bl = (regs->regs[4]) & 0xffffffff;
-       ch = (regs->regs[5]) >> 32;
-       cl = (regs->regs[5]) & 0xffffffff;
-       printk("R3  : %08Lx%08Lx R4  : %08Lx%08Lx R5  : %08Lx%08Lx\n",
-              ah, al, bh, bl, ch, cl);
-
-       ah = (regs->regs[6]) >> 32;
-       al = (regs->regs[6]) & 0xffffffff;
-       bh = (regs->regs[7]) >> 32;
-       bl = (regs->regs[7]) & 0xffffffff;
-       ch = (regs->regs[8]) >> 32;
-       cl = (regs->regs[8]) & 0xffffffff;
-       printk("R6  : %08Lx%08Lx R7  : %08Lx%08Lx R8  : %08Lx%08Lx\n",
-              ah, al, bh, bl, ch, cl);
-
-       ah = (regs->regs[9]) >> 32;
-       al = (regs->regs[9]) & 0xffffffff;
-       bh = (regs->regs[10]) >> 32;
-       bl = (regs->regs[10]) & 0xffffffff;
-       ch = (regs->regs[11]) >> 32;
-       cl = (regs->regs[11]) & 0xffffffff;
-       printk("R9  : %08Lx%08Lx R10 : %08Lx%08Lx R11 : %08Lx%08Lx\n",
-              ah, al, bh, bl, ch, cl);
-       printk("....\n");
-
-       ah = (regs->tregs[0]) >> 32;
-       al = (regs->tregs[0]) & 0xffffffff;
-       bh = (regs->tregs[1]) >> 32;
-       bl = (regs->tregs[1]) & 0xffffffff;
-       ch = (regs->tregs[2]) >> 32;
-       cl = (regs->tregs[2]) & 0xffffffff;
-       printk("T0  : %08Lx%08Lx T1  : %08Lx%08Lx T2  : %08Lx%08Lx\n",
-              ah, al, bh, bl, ch, cl);
-       printk("....\n");
-
-       print_dtlb();
-       print_itlb();
-}
index 3aea25dc431ae27e24547e3e8b2c9f455790e4f8..ff1c40a31cbc05ea888721f601f1ca581a2fbae4 100644 (file)
@@ -17,7 +17,7 @@
 /**
  * sh64_tlb_init - Perform initial setup for the DTLB and ITLB.
  */
-int __init sh64_tlb_init(void)
+int __cpuinit sh64_tlb_init(void)
 {
        /* Assign some sane DTLB defaults */
        cpu_data->dtlb.entries  = 64;
index f591598d92f67b165ebccdf4e3448a74df3c8cd2..781bcb10b8bd6f0ac34e1df6cf079dd0d3d59106 100644 (file)
@@ -103,8 +103,6 @@ void __cpuinit smp_callin(void)
        if (cheetah_pcache_forced_on)
                cheetah_enable_pcache();
 
-       local_irq_enable();
-
        callin_flag = 1;
        __asm__ __volatile__("membar #Sync\n\t"
                             "flush  %%g6" : : : "memory");
@@ -124,9 +122,8 @@ void __cpuinit smp_callin(void)
        while (!cpumask_test_cpu(cpuid, &smp_commenced_mask))
                rmb();
 
-       ipi_call_lock_irq();
        set_cpu_online(cpuid, true);
-       ipi_call_unlock_irq();
+       local_irq_enable();
 
        /* idle thread is expected to have preempt disabled */
        preempt_disable();
@@ -1308,9 +1305,7 @@ int __cpu_disable(void)
        mdelay(1);
        local_irq_disable();
 
-       ipi_call_lock();
        set_cpu_online(cpu, false);
-       ipi_call_unlock();
 
        cpu_map_rebuild();
 
index fe128816c448a5f593f419c8b695461bebcd74ec..932e4430f7f3323ef9be06d2f4b1f8ac98ae611f 100644 (file)
@@ -3,6 +3,8 @@
 
 config TILE
        def_bool y
+       select HAVE_DMA_ATTRS
+       select HAVE_DMA_API_DEBUG
        select HAVE_KVM if !TILEGX
        select GENERIC_FIND_FIRST_BIT
        select USE_GENERIC_SMP_HELPERS
@@ -79,6 +81,9 @@ config ARCH_DMA_ADDR_T_64BIT
 config NEED_DMA_MAP_STATE
        def_bool y
 
+config ARCH_HAS_DMA_SET_COHERENT_MASK
+       bool
+
 config LOCKDEP_SUPPORT
        def_bool y
 
@@ -212,6 +217,22 @@ config HIGHMEM
 
          If unsure, say "true".
 
+config ZONE_DMA
+       def_bool y
+
+config IOMMU_HELPER
+       bool
+
+config NEED_SG_DMA_LENGTH
+       bool
+
+config SWIOTLB
+       bool
+       default TILEGX
+       select IOMMU_HELPER
+       select NEED_SG_DMA_LENGTH
+       select ARCH_HAS_DMA_SET_COHERENT_MASK
+
 # We do not currently support disabling NUMA.
 config NUMA
        bool # "NUMA Memory Allocation and Scheduler Support"
@@ -345,6 +366,8 @@ config KERNEL_PL
          kernel will be built to run at.  Generally you should use
          the default value here.
 
+source "arch/tile/gxio/Kconfig"
+
 endmenu  # Tilera-specific configuration
 
 menu "Bus options"
@@ -354,6 +377,9 @@ config PCI
        default y
        select PCI_DOMAINS
        select GENERIC_PCI_IOMAP
+       select TILE_GXIO_TRIO if TILEGX
+       select ARCH_SUPPORTS_MSI if TILEGX
+       select PCI_MSI if TILEGX
        ---help---
          Enable PCI root complex support, so PCIe endpoint devices can
          be attached to the Tile chip.  Many, but not all, PCI devices
@@ -370,6 +396,22 @@ config NO_IOPORT
 
 source "drivers/pci/Kconfig"
 
+config TILE_USB
+       tristate "Tilera USB host adapter support"
+       default y
+       depends on USB
+       depends on TILEGX
+       select TILE_GXIO_USB_HOST
+       ---help---
+         Provides USB host adapter support for the built-in EHCI and OHCI
+         interfaces on TILE-Gx chips.
+
+# USB OHCI needs the bounce pool since tilegx will often have more
+# than 4GB of memory, but we don't currently use the IOTLB to present
+# a 32-bit address to OHCI.  So we need to use a bounce pool instead.
+config NEED_BOUNCE_POOL
+       def_bool USB_OHCI_HCD
+
 config HOTPLUG
        bool "Support for hot-pluggable devices"
        ---help---
index e20b0a0b64a17cf6cf6e796a57b5cecdbad0e871..55640cf92597b11f943173928b4d7d7437d4be14 100644 (file)
@@ -59,6 +59,8 @@ libs-y                += $(LIBGCC_PATH)
 # See arch/tile/Kbuild for content of core part of the kernel
 core-y         += arch/tile/
 
+core-$(CONFIG_TILE_GXIO) += arch/tile/gxio/
+
 ifdef TILERA_ROOT
 INSTALL_PATH ?= $(TILERA_ROOT)/tile/boot
 endif
diff --git a/arch/tile/gxio/Kconfig b/arch/tile/gxio/Kconfig
new file mode 100644 (file)
index 0000000..d221f8d
--- /dev/null
@@ -0,0 +1,28 @@
+# Support direct access to TILE-Gx hardware from user space, via the
+# gxio library, or from kernel space, via kernel IORPC support.
+config TILE_GXIO
+       bool
+       depends on TILEGX
+
+# Support direct access to the common I/O DMA facility within the
+# TILE-Gx mPIPE and Trio hardware from kernel space.
+config TILE_GXIO_DMA
+       bool
+       select TILE_GXIO
+
+# Support direct access to the TILE-Gx mPIPE hardware from kernel space.
+config TILE_GXIO_MPIPE
+       bool
+       select TILE_GXIO
+       select TILE_GXIO_DMA
+
+# Support direct access to the TILE-Gx TRIO hardware from kernel space.
+config TILE_GXIO_TRIO
+       bool
+       select TILE_GXIO
+       select TILE_GXIO_DMA
+
+# Support direct access to the TILE-Gx USB hardware from kernel space.
+config TILE_GXIO_USB_HOST
+       bool
+       select TILE_GXIO
diff --git a/arch/tile/gxio/Makefile b/arch/tile/gxio/Makefile
new file mode 100644 (file)
index 0000000..8684bca
--- /dev/null
@@ -0,0 +1,9 @@
+#
+# Makefile for the Tile-Gx device access support.
+#
+
+obj-$(CONFIG_TILE_GXIO) += iorpc_globals.o kiorpc.o
+obj-$(CONFIG_TILE_GXIO_DMA) += dma_queue.o
+obj-$(CONFIG_TILE_GXIO_MPIPE) += mpipe.o iorpc_mpipe.o iorpc_mpipe_info.o
+obj-$(CONFIG_TILE_GXIO_TRIO) += trio.o iorpc_trio.o
+obj-$(CONFIG_TILE_GXIO_USB_HOST) += usb_host.o iorpc_usb_host.o
diff --git a/arch/tile/gxio/dma_queue.c b/arch/tile/gxio/dma_queue.c
new file mode 100644 (file)
index 0000000..baa6035
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#include <linux/io.h>
+#include <linux/atomic.h>
+#include <linux/module.h>
+#include <gxio/dma_queue.h>
+
+/* Wait for a memory read to complete. */
+#define wait_for_value(val)                             \
+  __asm__ __volatile__("move %0, %0" :: "r"(val))
+
+/* The index is in the low 16. */
+#define DMA_QUEUE_INDEX_MASK ((1 << 16) - 1)
+
+/*
+ * The hardware descriptor-ring type.
+ * This matches the types used by mpipe (MPIPE_EDMA_POST_REGION_VAL_t)
+ * and trio (TRIO_PUSH_DMA_REGION_VAL_t or TRIO_PULL_DMA_REGION_VAL_t).
+ * See those types for more documentation on the individual fields.
+ */
+typedef union {
+       struct {
+#ifndef __BIG_ENDIAN__
+               uint64_t ring_idx:16;
+               uint64_t count:16;
+               uint64_t gen:1;
+               uint64_t __reserved:31;
+#else
+               uint64_t __reserved:31;
+               uint64_t gen:1;
+               uint64_t count:16;
+               uint64_t ring_idx:16;
+#endif
+       };
+       uint64_t word;
+} __gxio_ring_t;
+
+void __gxio_dma_queue_init(__gxio_dma_queue_t *dma_queue,
+                          void *post_region_addr, unsigned int num_entries)
+{
+       /*
+        * Limit 65536 entry rings to 65535 credits because we only have a
+        * 16 bit completion counter.
+        */
+       int64_t credits = (num_entries < 65536) ? num_entries : 65535;
+
+       memset(dma_queue, 0, sizeof(*dma_queue));
+
+       dma_queue->post_region_addr = post_region_addr;
+       dma_queue->hw_complete_count = 0;
+       dma_queue->credits_and_next_index = credits << DMA_QUEUE_CREDIT_SHIFT;
+}
+
+EXPORT_SYMBOL_GPL(__gxio_dma_queue_init);
+
+void __gxio_dma_queue_update_credits(__gxio_dma_queue_t *dma_queue)
+{
+       __gxio_ring_t val;
+       uint64_t count;
+       uint64_t delta;
+       uint64_t new_count;
+
+       /*
+        * Read the 64-bit completion count without touching the cache, so
+        * we later avoid having to evict any sharers of this cache line
+        * when we update it below.
+        */
+       uint64_t orig_hw_complete_count =
+               cmpxchg(&dma_queue->hw_complete_count,
+                       -1, -1);
+
+       /* Make sure the load completes before we access the hardware. */
+       wait_for_value(orig_hw_complete_count);
+
+       /* Read the 16-bit count of how many packets it has completed. */
+       val.word = __gxio_mmio_read(dma_queue->post_region_addr);
+       count = val.count;
+
+       /*
+        * Calculate the number of completions since we last updated the
+        * 64-bit counter.  It's safe to ignore the high bits because the
+        * maximum credit value is 65535.
+        */
+       delta = (count - orig_hw_complete_count) & 0xffff;
+       if (delta == 0)
+               return;
+
+       /*
+        * Try to write back the count, advanced by delta.  If we race with
+        * another thread, this might fail, in which case we return
+        * immediately on the assumption that some credits are (or at least
+        * were) available.
+        */
+       new_count = orig_hw_complete_count + delta;
+       if (cmpxchg(&dma_queue->hw_complete_count,
+                   orig_hw_complete_count,
+                   new_count) != orig_hw_complete_count)
+               return;
+
+       /*
+        * We succeeded in advancing the completion count; add back the
+        * corresponding number of egress credits.
+        */
+       __insn_fetchadd(&dma_queue->credits_and_next_index,
+                       (delta << DMA_QUEUE_CREDIT_SHIFT));
+}
+
+EXPORT_SYMBOL_GPL(__gxio_dma_queue_update_credits);
+
+/*
+ * A separate 'blocked' method for put() so that backtraces and
+ * profiles will clearly indicate that we're wasting time spinning on
+ * egress availability rather than actually posting commands.
+ */
+int64_t __gxio_dma_queue_wait_for_credits(__gxio_dma_queue_t *dma_queue,
+                                         int64_t modifier)
+{
+       int backoff = 16;
+       int64_t old;
+
+       do {
+               int i;
+               /* Back off to avoid spamming memory networks. */
+               for (i = backoff; i > 0; i--)
+                       __insn_mfspr(SPR_PASS);
+
+               /* Check credits again. */
+               __gxio_dma_queue_update_credits(dma_queue);
+               old = __insn_fetchaddgez(&dma_queue->credits_and_next_index,
+                                        modifier);
+
+               /* Calculate bounded exponential backoff for next iteration. */
+               if (backoff < 256)
+                       backoff *= 2;
+       } while (old + modifier < 0);
+
+       return old;
+}
+
+EXPORT_SYMBOL_GPL(__gxio_dma_queue_wait_for_credits);
+
+int64_t __gxio_dma_queue_reserve_aux(__gxio_dma_queue_t *dma_queue,
+                                    unsigned int num, int wait)
+{
+       return __gxio_dma_queue_reserve(dma_queue, num, wait != 0, true);
+}
+
+EXPORT_SYMBOL_GPL(__gxio_dma_queue_reserve_aux);
+
+int __gxio_dma_queue_is_complete(__gxio_dma_queue_t *dma_queue,
+                                int64_t completion_slot, int update)
+{
+       if (update) {
+               if (ACCESS_ONCE(dma_queue->hw_complete_count) >
+                   completion_slot)
+                       return 1;
+
+               __gxio_dma_queue_update_credits(dma_queue);
+       }
+
+       return ACCESS_ONCE(dma_queue->hw_complete_count) > completion_slot;
+}
+
+EXPORT_SYMBOL_GPL(__gxio_dma_queue_is_complete);
diff --git a/arch/tile/gxio/iorpc_globals.c b/arch/tile/gxio/iorpc_globals.c
new file mode 100644 (file)
index 0000000..e178e90
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* This file is machine-generated; DO NOT EDIT! */
+#include "gxio/iorpc_globals.h"
+
+struct arm_pollfd_param {
+       union iorpc_pollfd pollfd;
+};
+
+int __iorpc_arm_pollfd(int fd, int pollfd_cookie)
+{
+       struct arm_pollfd_param temp;
+       struct arm_pollfd_param *params = &temp;
+
+       params->pollfd.kernel.cookie = pollfd_cookie;
+
+       return hv_dev_pwrite(fd, 0, (HV_VirtAddr) params, sizeof(*params),
+                            IORPC_OP_ARM_POLLFD);
+}
+
+EXPORT_SYMBOL(__iorpc_arm_pollfd);
+
+struct close_pollfd_param {
+       union iorpc_pollfd pollfd;
+};
+
+int __iorpc_close_pollfd(int fd, int pollfd_cookie)
+{
+       struct close_pollfd_param temp;
+       struct close_pollfd_param *params = &temp;
+
+       params->pollfd.kernel.cookie = pollfd_cookie;
+
+       return hv_dev_pwrite(fd, 0, (HV_VirtAddr) params, sizeof(*params),
+                            IORPC_OP_CLOSE_POLLFD);
+}
+
+EXPORT_SYMBOL(__iorpc_close_pollfd);
+
+struct get_mmio_base_param {
+       HV_PTE base;
+};
+
+int __iorpc_get_mmio_base(int fd, HV_PTE *base)
+{
+       int __result;
+       struct get_mmio_base_param temp;
+       struct get_mmio_base_param *params = &temp;
+
+       __result =
+           hv_dev_pread(fd, 0, (HV_VirtAddr) params, sizeof(*params),
+                        IORPC_OP_GET_MMIO_BASE);
+       *base = params->base;
+
+       return __result;
+}
+
+EXPORT_SYMBOL(__iorpc_get_mmio_base);
+
+struct check_mmio_offset_param {
+       unsigned long offset;
+       unsigned long size;
+};
+
+int __iorpc_check_mmio_offset(int fd, unsigned long offset, unsigned long size)
+{
+       struct check_mmio_offset_param temp;
+       struct check_mmio_offset_param *params = &temp;
+
+       params->offset = offset;
+       params->size = size;
+
+       return hv_dev_pwrite(fd, 0, (HV_VirtAddr) params, sizeof(*params),
+                            IORPC_OP_CHECK_MMIO_OFFSET);
+}
+
+EXPORT_SYMBOL(__iorpc_check_mmio_offset);
diff --git a/arch/tile/gxio/iorpc_mpipe.c b/arch/tile/gxio/iorpc_mpipe.c
new file mode 100644 (file)
index 0000000..31b87bf
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* This file is machine-generated; DO NOT EDIT! */
+#include "gxio/iorpc_mpipe.h"
+
+struct alloc_buffer_stacks_param {
+       unsigned int count;
+       unsigned int first;
+       unsigned int flags;
+};
+
+int gxio_mpipe_alloc_buffer_stacks(gxio_mpipe_context_t * context,
+                                  unsigned int count, unsigned int first,
+                                  unsigned int flags)
+{
+       struct alloc_buffer_stacks_param temp;
+       struct alloc_buffer_stacks_param *params = &temp;
+
+       params->count = count;
+       params->first = first;
+       params->flags = flags;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params),
+                            GXIO_MPIPE_OP_ALLOC_BUFFER_STACKS);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_alloc_buffer_stacks);
+
+struct init_buffer_stack_aux_param {
+       union iorpc_mem_buffer buffer;
+       unsigned int stack;
+       unsigned int buffer_size_enum;
+};
+
+int gxio_mpipe_init_buffer_stack_aux(gxio_mpipe_context_t * context,
+                                    void *mem_va, size_t mem_size,
+                                    unsigned int mem_flags, unsigned int stack,
+                                    unsigned int buffer_size_enum)
+{
+       int __result;
+       unsigned long long __cpa;
+       pte_t __pte;
+       struct init_buffer_stack_aux_param temp;
+       struct init_buffer_stack_aux_param *params = &temp;
+
+       __result = va_to_cpa_and_pte(mem_va, &__cpa, &__pte);
+       if (__result != 0)
+               return __result;
+       params->buffer.kernel.cpa = __cpa;
+       params->buffer.kernel.size = mem_size;
+       params->buffer.kernel.pte = __pte;
+       params->buffer.kernel.flags = mem_flags;
+       params->stack = stack;
+       params->buffer_size_enum = buffer_size_enum;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params),
+                            GXIO_MPIPE_OP_INIT_BUFFER_STACK_AUX);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_init_buffer_stack_aux);
+
+
+struct alloc_notif_rings_param {
+       unsigned int count;
+       unsigned int first;
+       unsigned int flags;
+};
+
+int gxio_mpipe_alloc_notif_rings(gxio_mpipe_context_t * context,
+                                unsigned int count, unsigned int first,
+                                unsigned int flags)
+{
+       struct alloc_notif_rings_param temp;
+       struct alloc_notif_rings_param *params = &temp;
+
+       params->count = count;
+       params->first = first;
+       params->flags = flags;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_MPIPE_OP_ALLOC_NOTIF_RINGS);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_alloc_notif_rings);
+
+struct init_notif_ring_aux_param {
+       union iorpc_mem_buffer buffer;
+       unsigned int ring;
+};
+
+int gxio_mpipe_init_notif_ring_aux(gxio_mpipe_context_t * context, void *mem_va,
+                                  size_t mem_size, unsigned int mem_flags,
+                                  unsigned int ring)
+{
+       int __result;
+       unsigned long long __cpa;
+       pte_t __pte;
+       struct init_notif_ring_aux_param temp;
+       struct init_notif_ring_aux_param *params = &temp;
+
+       __result = va_to_cpa_and_pte(mem_va, &__cpa, &__pte);
+       if (__result != 0)
+               return __result;
+       params->buffer.kernel.cpa = __cpa;
+       params->buffer.kernel.size = mem_size;
+       params->buffer.kernel.pte = __pte;
+       params->buffer.kernel.flags = mem_flags;
+       params->ring = ring;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params),
+                            GXIO_MPIPE_OP_INIT_NOTIF_RING_AUX);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_init_notif_ring_aux);
+
+struct request_notif_ring_interrupt_param {
+       union iorpc_interrupt interrupt;
+       unsigned int ring;
+};
+
+int gxio_mpipe_request_notif_ring_interrupt(gxio_mpipe_context_t * context,
+                                           int inter_x, int inter_y,
+                                           int inter_ipi, int inter_event,
+                                           unsigned int ring)
+{
+       struct request_notif_ring_interrupt_param temp;
+       struct request_notif_ring_interrupt_param *params = &temp;
+
+       params->interrupt.kernel.x = inter_x;
+       params->interrupt.kernel.y = inter_y;
+       params->interrupt.kernel.ipi = inter_ipi;
+       params->interrupt.kernel.event = inter_event;
+       params->ring = ring;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params),
+                            GXIO_MPIPE_OP_REQUEST_NOTIF_RING_INTERRUPT);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_request_notif_ring_interrupt);
+
+struct enable_notif_ring_interrupt_param {
+       unsigned int ring;
+};
+
+int gxio_mpipe_enable_notif_ring_interrupt(gxio_mpipe_context_t * context,
+                                          unsigned int ring)
+{
+       struct enable_notif_ring_interrupt_param temp;
+       struct enable_notif_ring_interrupt_param *params = &temp;
+
+       params->ring = ring;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params),
+                            GXIO_MPIPE_OP_ENABLE_NOTIF_RING_INTERRUPT);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_enable_notif_ring_interrupt);
+
+struct alloc_notif_groups_param {
+       unsigned int count;
+       unsigned int first;
+       unsigned int flags;
+};
+
+int gxio_mpipe_alloc_notif_groups(gxio_mpipe_context_t * context,
+                                 unsigned int count, unsigned int first,
+                                 unsigned int flags)
+{
+       struct alloc_notif_groups_param temp;
+       struct alloc_notif_groups_param *params = &temp;
+
+       params->count = count;
+       params->first = first;
+       params->flags = flags;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_MPIPE_OP_ALLOC_NOTIF_GROUPS);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_alloc_notif_groups);
+
+struct init_notif_group_param {
+       unsigned int group;
+       gxio_mpipe_notif_group_bits_t bits;
+};
+
+int gxio_mpipe_init_notif_group(gxio_mpipe_context_t * context,
+                               unsigned int group,
+                               gxio_mpipe_notif_group_bits_t bits)
+{
+       struct init_notif_group_param temp;
+       struct init_notif_group_param *params = &temp;
+
+       params->group = group;
+       params->bits = bits;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_MPIPE_OP_INIT_NOTIF_GROUP);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_init_notif_group);
+
+struct alloc_buckets_param {
+       unsigned int count;
+       unsigned int first;
+       unsigned int flags;
+};
+
+int gxio_mpipe_alloc_buckets(gxio_mpipe_context_t * context, unsigned int count,
+                            unsigned int first, unsigned int flags)
+{
+       struct alloc_buckets_param temp;
+       struct alloc_buckets_param *params = &temp;
+
+       params->count = count;
+       params->first = first;
+       params->flags = flags;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_MPIPE_OP_ALLOC_BUCKETS);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_alloc_buckets);
+
+struct init_bucket_param {
+       unsigned int bucket;
+       MPIPE_LBL_INIT_DAT_BSTS_TBL_t bucket_info;
+};
+
+int gxio_mpipe_init_bucket(gxio_mpipe_context_t * context, unsigned int bucket,
+                          MPIPE_LBL_INIT_DAT_BSTS_TBL_t bucket_info)
+{
+       struct init_bucket_param temp;
+       struct init_bucket_param *params = &temp;
+
+       params->bucket = bucket;
+       params->bucket_info = bucket_info;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_MPIPE_OP_INIT_BUCKET);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_init_bucket);
+
+struct alloc_edma_rings_param {
+       unsigned int count;
+       unsigned int first;
+       unsigned int flags;
+};
+
+int gxio_mpipe_alloc_edma_rings(gxio_mpipe_context_t * context,
+                               unsigned int count, unsigned int first,
+                               unsigned int flags)
+{
+       struct alloc_edma_rings_param temp;
+       struct alloc_edma_rings_param *params = &temp;
+
+       params->count = count;
+       params->first = first;
+       params->flags = flags;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_MPIPE_OP_ALLOC_EDMA_RINGS);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_alloc_edma_rings);
+
+struct init_edma_ring_aux_param {
+       union iorpc_mem_buffer buffer;
+       unsigned int ring;
+       unsigned int channel;
+};
+
+int gxio_mpipe_init_edma_ring_aux(gxio_mpipe_context_t * context, void *mem_va,
+                                 size_t mem_size, unsigned int mem_flags,
+                                 unsigned int ring, unsigned int channel)
+{
+       int __result;
+       unsigned long long __cpa;
+       pte_t __pte;
+       struct init_edma_ring_aux_param temp;
+       struct init_edma_ring_aux_param *params = &temp;
+
+       __result = va_to_cpa_and_pte(mem_va, &__cpa, &__pte);
+       if (__result != 0)
+               return __result;
+       params->buffer.kernel.cpa = __cpa;
+       params->buffer.kernel.size = mem_size;
+       params->buffer.kernel.pte = __pte;
+       params->buffer.kernel.flags = mem_flags;
+       params->ring = ring;
+       params->channel = channel;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_MPIPE_OP_INIT_EDMA_RING_AUX);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_init_edma_ring_aux);
+
+
+int gxio_mpipe_commit_rules(gxio_mpipe_context_t * context, const void *blob,
+                           size_t blob_size)
+{
+       const void *params = blob;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params, blob_size,
+                            GXIO_MPIPE_OP_COMMIT_RULES);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_commit_rules);
+
+struct register_client_memory_param {
+       unsigned int iotlb;
+       HV_PTE pte;
+       unsigned int flags;
+};
+
+int gxio_mpipe_register_client_memory(gxio_mpipe_context_t * context,
+                                     unsigned int iotlb, HV_PTE pte,
+                                     unsigned int flags)
+{
+       struct register_client_memory_param temp;
+       struct register_client_memory_param *params = &temp;
+
+       params->iotlb = iotlb;
+       params->pte = pte;
+       params->flags = flags;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params),
+                            GXIO_MPIPE_OP_REGISTER_CLIENT_MEMORY);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_register_client_memory);
+
+struct link_open_aux_param {
+       _gxio_mpipe_link_name_t name;
+       unsigned int flags;
+};
+
+int gxio_mpipe_link_open_aux(gxio_mpipe_context_t * context,
+                            _gxio_mpipe_link_name_t name, unsigned int flags)
+{
+       struct link_open_aux_param temp;
+       struct link_open_aux_param *params = &temp;
+
+       params->name = name;
+       params->flags = flags;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_MPIPE_OP_LINK_OPEN_AUX);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_link_open_aux);
+
+struct link_close_aux_param {
+       int mac;
+};
+
+int gxio_mpipe_link_close_aux(gxio_mpipe_context_t * context, int mac)
+{
+       struct link_close_aux_param temp;
+       struct link_close_aux_param *params = &temp;
+
+       params->mac = mac;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_MPIPE_OP_LINK_CLOSE_AUX);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_link_close_aux);
+
+
+struct get_timestamp_aux_param {
+       uint64_t sec;
+       uint64_t nsec;
+       uint64_t cycles;
+};
+
+int gxio_mpipe_get_timestamp_aux(gxio_mpipe_context_t * context, uint64_t * sec,
+                                uint64_t * nsec, uint64_t * cycles)
+{
+       int __result;
+       struct get_timestamp_aux_param temp;
+       struct get_timestamp_aux_param *params = &temp;
+
+       __result =
+           hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, sizeof(*params),
+                        GXIO_MPIPE_OP_GET_TIMESTAMP_AUX);
+       *sec = params->sec;
+       *nsec = params->nsec;
+       *cycles = params->cycles;
+
+       return __result;
+}
+
+EXPORT_SYMBOL(gxio_mpipe_get_timestamp_aux);
+
+struct set_timestamp_aux_param {
+       uint64_t sec;
+       uint64_t nsec;
+       uint64_t cycles;
+};
+
+int gxio_mpipe_set_timestamp_aux(gxio_mpipe_context_t * context, uint64_t sec,
+                                uint64_t nsec, uint64_t cycles)
+{
+       struct set_timestamp_aux_param temp;
+       struct set_timestamp_aux_param *params = &temp;
+
+       params->sec = sec;
+       params->nsec = nsec;
+       params->cycles = cycles;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_MPIPE_OP_SET_TIMESTAMP_AUX);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_set_timestamp_aux);
+
+struct adjust_timestamp_aux_param {
+       int64_t nsec;
+};
+
+int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t * context,
+                                   int64_t nsec)
+{
+       struct adjust_timestamp_aux_param temp;
+       struct adjust_timestamp_aux_param *params = &temp;
+
+       params->nsec = nsec;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params),
+                            GXIO_MPIPE_OP_ADJUST_TIMESTAMP_AUX);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_adjust_timestamp_aux);
+
+struct arm_pollfd_param {
+       union iorpc_pollfd pollfd;
+};
+
+int gxio_mpipe_arm_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie)
+{
+       struct arm_pollfd_param temp;
+       struct arm_pollfd_param *params = &temp;
+
+       params->pollfd.kernel.cookie = pollfd_cookie;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_MPIPE_OP_ARM_POLLFD);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_arm_pollfd);
+
+struct close_pollfd_param {
+       union iorpc_pollfd pollfd;
+};
+
+int gxio_mpipe_close_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie)
+{
+       struct close_pollfd_param temp;
+       struct close_pollfd_param *params = &temp;
+
+       params->pollfd.kernel.cookie = pollfd_cookie;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_MPIPE_OP_CLOSE_POLLFD);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_close_pollfd);
+
+struct get_mmio_base_param {
+       HV_PTE base;
+};
+
+int gxio_mpipe_get_mmio_base(gxio_mpipe_context_t * context, HV_PTE *base)
+{
+       int __result;
+       struct get_mmio_base_param temp;
+       struct get_mmio_base_param *params = &temp;
+
+       __result =
+           hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, sizeof(*params),
+                        GXIO_MPIPE_OP_GET_MMIO_BASE);
+       *base = params->base;
+
+       return __result;
+}
+
+EXPORT_SYMBOL(gxio_mpipe_get_mmio_base);
+
+struct check_mmio_offset_param {
+       unsigned long offset;
+       unsigned long size;
+};
+
+int gxio_mpipe_check_mmio_offset(gxio_mpipe_context_t * context,
+                                unsigned long offset, unsigned long size)
+{
+       struct check_mmio_offset_param temp;
+       struct check_mmio_offset_param *params = &temp;
+
+       params->offset = offset;
+       params->size = size;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_MPIPE_OP_CHECK_MMIO_OFFSET);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_check_mmio_offset);
diff --git a/arch/tile/gxio/iorpc_mpipe_info.c b/arch/tile/gxio/iorpc_mpipe_info.c
new file mode 100644 (file)
index 0000000..d0254aa
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* This file is machine-generated; DO NOT EDIT! */
+#include "gxio/iorpc_mpipe_info.h"
+
+
+struct enumerate_aux_param {
+       _gxio_mpipe_link_name_t name;
+       _gxio_mpipe_link_mac_t mac;
+};
+
+int gxio_mpipe_info_enumerate_aux(gxio_mpipe_info_context_t * context,
+                                 unsigned int idx,
+                                 _gxio_mpipe_link_name_t * name,
+                                 _gxio_mpipe_link_mac_t * mac)
+{
+       int __result;
+       struct enumerate_aux_param temp;
+       struct enumerate_aux_param *params = &temp;
+
+       __result =
+           hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, sizeof(*params),
+                        (((uint64_t) idx << 32) |
+                         GXIO_MPIPE_INFO_OP_ENUMERATE_AUX));
+       *name = params->name;
+       *mac = params->mac;
+
+       return __result;
+}
+
+EXPORT_SYMBOL(gxio_mpipe_info_enumerate_aux);
+
+struct get_mmio_base_param {
+       HV_PTE base;
+};
+
+int gxio_mpipe_info_get_mmio_base(gxio_mpipe_info_context_t * context,
+                                 HV_PTE *base)
+{
+       int __result;
+       struct get_mmio_base_param temp;
+       struct get_mmio_base_param *params = &temp;
+
+       __result =
+           hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, sizeof(*params),
+                        GXIO_MPIPE_INFO_OP_GET_MMIO_BASE);
+       *base = params->base;
+
+       return __result;
+}
+
+EXPORT_SYMBOL(gxio_mpipe_info_get_mmio_base);
+
+struct check_mmio_offset_param {
+       unsigned long offset;
+       unsigned long size;
+};
+
+int gxio_mpipe_info_check_mmio_offset(gxio_mpipe_info_context_t * context,
+                                     unsigned long offset, unsigned long size)
+{
+       struct check_mmio_offset_param temp;
+       struct check_mmio_offset_param *params = &temp;
+
+       params->offset = offset;
+       params->size = size;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params),
+                            GXIO_MPIPE_INFO_OP_CHECK_MMIO_OFFSET);
+}
+
+EXPORT_SYMBOL(gxio_mpipe_info_check_mmio_offset);
diff --git a/arch/tile/gxio/iorpc_trio.c b/arch/tile/gxio/iorpc_trio.c
new file mode 100644 (file)
index 0000000..cef4b22
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* This file is machine-generated; DO NOT EDIT! */
+#include "gxio/iorpc_trio.h"
+
+struct alloc_asids_param {
+       unsigned int count;
+       unsigned int first;
+       unsigned int flags;
+};
+
+int gxio_trio_alloc_asids(gxio_trio_context_t * context, unsigned int count,
+                         unsigned int first, unsigned int flags)
+{
+       struct alloc_asids_param temp;
+       struct alloc_asids_param *params = &temp;
+
+       params->count = count;
+       params->first = first;
+       params->flags = flags;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_TRIO_OP_ALLOC_ASIDS);
+}
+
+EXPORT_SYMBOL(gxio_trio_alloc_asids);
+
+
+struct alloc_memory_maps_param {
+       unsigned int count;
+       unsigned int first;
+       unsigned int flags;
+};
+
+int gxio_trio_alloc_memory_maps(gxio_trio_context_t * context,
+                               unsigned int count, unsigned int first,
+                               unsigned int flags)
+{
+       struct alloc_memory_maps_param temp;
+       struct alloc_memory_maps_param *params = &temp;
+
+       params->count = count;
+       params->first = first;
+       params->flags = flags;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_TRIO_OP_ALLOC_MEMORY_MAPS);
+}
+
+EXPORT_SYMBOL(gxio_trio_alloc_memory_maps);
+
+
+struct alloc_pio_regions_param {
+       unsigned int count;
+       unsigned int first;
+       unsigned int flags;
+};
+
+int gxio_trio_alloc_pio_regions(gxio_trio_context_t * context,
+                               unsigned int count, unsigned int first,
+                               unsigned int flags)
+{
+       struct alloc_pio_regions_param temp;
+       struct alloc_pio_regions_param *params = &temp;
+
+       params->count = count;
+       params->first = first;
+       params->flags = flags;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_TRIO_OP_ALLOC_PIO_REGIONS);
+}
+
+EXPORT_SYMBOL(gxio_trio_alloc_pio_regions);
+
+struct init_pio_region_aux_param {
+       unsigned int pio_region;
+       unsigned int mac;
+       uint32_t bus_address_hi;
+       unsigned int flags;
+};
+
+int gxio_trio_init_pio_region_aux(gxio_trio_context_t * context,
+                                 unsigned int pio_region, unsigned int mac,
+                                 uint32_t bus_address_hi, unsigned int flags)
+{
+       struct init_pio_region_aux_param temp;
+       struct init_pio_region_aux_param *params = &temp;
+
+       params->pio_region = pio_region;
+       params->mac = mac;
+       params->bus_address_hi = bus_address_hi;
+       params->flags = flags;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_TRIO_OP_INIT_PIO_REGION_AUX);
+}
+
+EXPORT_SYMBOL(gxio_trio_init_pio_region_aux);
+
+
+struct init_memory_map_mmu_aux_param {
+       unsigned int map;
+       unsigned long va;
+       uint64_t size;
+       unsigned int asid;
+       unsigned int mac;
+       uint64_t bus_address;
+       unsigned int node;
+       unsigned int order_mode;
+};
+
+int gxio_trio_init_memory_map_mmu_aux(gxio_trio_context_t * context,
+                                     unsigned int map, unsigned long va,
+                                     uint64_t size, unsigned int asid,
+                                     unsigned int mac, uint64_t bus_address,
+                                     unsigned int node,
+                                     unsigned int order_mode)
+{
+       struct init_memory_map_mmu_aux_param temp;
+       struct init_memory_map_mmu_aux_param *params = &temp;
+
+       params->map = map;
+       params->va = va;
+       params->size = size;
+       params->asid = asid;
+       params->mac = mac;
+       params->bus_address = bus_address;
+       params->node = node;
+       params->order_mode = order_mode;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params),
+                            GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX);
+}
+
+EXPORT_SYMBOL(gxio_trio_init_memory_map_mmu_aux);
+
+struct get_port_property_param {
+       struct pcie_trio_ports_property trio_ports;
+};
+
+int gxio_trio_get_port_property(gxio_trio_context_t * context,
+                               struct pcie_trio_ports_property *trio_ports)
+{
+       int __result;
+       struct get_port_property_param temp;
+       struct get_port_property_param *params = &temp;
+
+       __result =
+           hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, sizeof(*params),
+                        GXIO_TRIO_OP_GET_PORT_PROPERTY);
+       *trio_ports = params->trio_ports;
+
+       return __result;
+}
+
+EXPORT_SYMBOL(gxio_trio_get_port_property);
+
+struct config_legacy_intr_param {
+       union iorpc_interrupt interrupt;
+       unsigned int mac;
+       unsigned int intx;
+};
+
+int gxio_trio_config_legacy_intr(gxio_trio_context_t * context, int inter_x,
+                                int inter_y, int inter_ipi, int inter_event,
+                                unsigned int mac, unsigned int intx)
+{
+       struct config_legacy_intr_param temp;
+       struct config_legacy_intr_param *params = &temp;
+
+       params->interrupt.kernel.x = inter_x;
+       params->interrupt.kernel.y = inter_y;
+       params->interrupt.kernel.ipi = inter_ipi;
+       params->interrupt.kernel.event = inter_event;
+       params->mac = mac;
+       params->intx = intx;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_TRIO_OP_CONFIG_LEGACY_INTR);
+}
+
+EXPORT_SYMBOL(gxio_trio_config_legacy_intr);
+
+struct config_msi_intr_param {
+       union iorpc_interrupt interrupt;
+       unsigned int mac;
+       unsigned int mem_map;
+       uint64_t mem_map_base;
+       uint64_t mem_map_limit;
+       unsigned int asid;
+};
+
+int gxio_trio_config_msi_intr(gxio_trio_context_t * context, int inter_x,
+                             int inter_y, int inter_ipi, int inter_event,
+                             unsigned int mac, unsigned int mem_map,
+                             uint64_t mem_map_base, uint64_t mem_map_limit,
+                             unsigned int asid)
+{
+       struct config_msi_intr_param temp;
+       struct config_msi_intr_param *params = &temp;
+
+       params->interrupt.kernel.x = inter_x;
+       params->interrupt.kernel.y = inter_y;
+       params->interrupt.kernel.ipi = inter_ipi;
+       params->interrupt.kernel.event = inter_event;
+       params->mac = mac;
+       params->mem_map = mem_map;
+       params->mem_map_base = mem_map_base;
+       params->mem_map_limit = mem_map_limit;
+       params->asid = asid;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_TRIO_OP_CONFIG_MSI_INTR);
+}
+
+EXPORT_SYMBOL(gxio_trio_config_msi_intr);
+
+
+struct set_mps_mrs_param {
+       uint16_t mps;
+       uint16_t mrs;
+       unsigned int mac;
+};
+
+int gxio_trio_set_mps_mrs(gxio_trio_context_t * context, uint16_t mps,
+                         uint16_t mrs, unsigned int mac)
+{
+       struct set_mps_mrs_param temp;
+       struct set_mps_mrs_param *params = &temp;
+
+       params->mps = mps;
+       params->mrs = mrs;
+       params->mac = mac;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_TRIO_OP_SET_MPS_MRS);
+}
+
+EXPORT_SYMBOL(gxio_trio_set_mps_mrs);
+
+struct force_rc_link_up_param {
+       unsigned int mac;
+};
+
+int gxio_trio_force_rc_link_up(gxio_trio_context_t * context, unsigned int mac)
+{
+       struct force_rc_link_up_param temp;
+       struct force_rc_link_up_param *params = &temp;
+
+       params->mac = mac;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_TRIO_OP_FORCE_RC_LINK_UP);
+}
+
+EXPORT_SYMBOL(gxio_trio_force_rc_link_up);
+
+struct force_ep_link_up_param {
+       unsigned int mac;
+};
+
+int gxio_trio_force_ep_link_up(gxio_trio_context_t * context, unsigned int mac)
+{
+       struct force_ep_link_up_param temp;
+       struct force_ep_link_up_param *params = &temp;
+
+       params->mac = mac;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_TRIO_OP_FORCE_EP_LINK_UP);
+}
+
+EXPORT_SYMBOL(gxio_trio_force_ep_link_up);
+
+struct get_mmio_base_param {
+       HV_PTE base;
+};
+
+int gxio_trio_get_mmio_base(gxio_trio_context_t * context, HV_PTE *base)
+{
+       int __result;
+       struct get_mmio_base_param temp;
+       struct get_mmio_base_param *params = &temp;
+
+       __result =
+           hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, sizeof(*params),
+                        GXIO_TRIO_OP_GET_MMIO_BASE);
+       *base = params->base;
+
+       return __result;
+}
+
+EXPORT_SYMBOL(gxio_trio_get_mmio_base);
+
+struct check_mmio_offset_param {
+       unsigned long offset;
+       unsigned long size;
+};
+
+int gxio_trio_check_mmio_offset(gxio_trio_context_t * context,
+                               unsigned long offset, unsigned long size)
+{
+       struct check_mmio_offset_param temp;
+       struct check_mmio_offset_param *params = &temp;
+
+       params->offset = offset;
+       params->size = size;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_TRIO_OP_CHECK_MMIO_OFFSET);
+}
+
+EXPORT_SYMBOL(gxio_trio_check_mmio_offset);
diff --git a/arch/tile/gxio/iorpc_usb_host.c b/arch/tile/gxio/iorpc_usb_host.c
new file mode 100644 (file)
index 0000000..cf3c3cc
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* This file is machine-generated; DO NOT EDIT! */
+#include "gxio/iorpc_usb_host.h"
+
+struct cfg_interrupt_param {
+       union iorpc_interrupt interrupt;
+};
+
+int gxio_usb_host_cfg_interrupt(gxio_usb_host_context_t * context, int inter_x,
+                               int inter_y, int inter_ipi, int inter_event)
+{
+       struct cfg_interrupt_param temp;
+       struct cfg_interrupt_param *params = &temp;
+
+       params->interrupt.kernel.x = inter_x;
+       params->interrupt.kernel.y = inter_y;
+       params->interrupt.kernel.ipi = inter_ipi;
+       params->interrupt.kernel.event = inter_event;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params), GXIO_USB_HOST_OP_CFG_INTERRUPT);
+}
+
+EXPORT_SYMBOL(gxio_usb_host_cfg_interrupt);
+
+struct register_client_memory_param {
+       HV_PTE pte;
+       unsigned int flags;
+};
+
+int gxio_usb_host_register_client_memory(gxio_usb_host_context_t * context,
+                                        HV_PTE pte, unsigned int flags)
+{
+       struct register_client_memory_param temp;
+       struct register_client_memory_param *params = &temp;
+
+       params->pte = pte;
+       params->flags = flags;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params),
+                            GXIO_USB_HOST_OP_REGISTER_CLIENT_MEMORY);
+}
+
+EXPORT_SYMBOL(gxio_usb_host_register_client_memory);
+
+struct get_mmio_base_param {
+       HV_PTE base;
+};
+
+int gxio_usb_host_get_mmio_base(gxio_usb_host_context_t * context, HV_PTE *base)
+{
+       int __result;
+       struct get_mmio_base_param temp;
+       struct get_mmio_base_param *params = &temp;
+
+       __result =
+           hv_dev_pread(context->fd, 0, (HV_VirtAddr) params, sizeof(*params),
+                        GXIO_USB_HOST_OP_GET_MMIO_BASE);
+       *base = params->base;
+
+       return __result;
+}
+
+EXPORT_SYMBOL(gxio_usb_host_get_mmio_base);
+
+struct check_mmio_offset_param {
+       unsigned long offset;
+       unsigned long size;
+};
+
+int gxio_usb_host_check_mmio_offset(gxio_usb_host_context_t * context,
+                                   unsigned long offset, unsigned long size)
+{
+       struct check_mmio_offset_param temp;
+       struct check_mmio_offset_param *params = &temp;
+
+       params->offset = offset;
+       params->size = size;
+
+       return hv_dev_pwrite(context->fd, 0, (HV_VirtAddr) params,
+                            sizeof(*params),
+                            GXIO_USB_HOST_OP_CHECK_MMIO_OFFSET);
+}
+
+EXPORT_SYMBOL(gxio_usb_host_check_mmio_offset);
diff --git a/arch/tile/gxio/kiorpc.c b/arch/tile/gxio/kiorpc.c
new file mode 100644 (file)
index 0000000..c8096aa
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ * TILE-Gx IORPC support for kernel I/O drivers.
+ */
+
+#include <linux/mmzone.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <gxio/iorpc_globals.h>
+#include <gxio/kiorpc.h>
+
+#ifdef DEBUG_IORPC
+#define TRACE(FMT, ...) pr_info(SIMPLE_MSG_LINE FMT, ## __VA_ARGS__)
+#else
+#define TRACE(...)
+#endif
+
+/* Create kernel-VA-space MMIO mapping for an on-chip IO device. */
+void __iomem *iorpc_ioremap(int hv_fd, resource_size_t offset,
+                           unsigned long size)
+{
+       pgprot_t mmio_base, prot = { 0 };
+       unsigned long pfn;
+       int err;
+
+       /* Look up the shim's lotar and base PA. */
+       err = __iorpc_get_mmio_base(hv_fd, &mmio_base);
+       if (err) {
+               TRACE("get_mmio_base() failure: %d\n", err);
+               return NULL;
+       }
+
+       /* Make sure the HV driver approves of our offset and size. */
+       err = __iorpc_check_mmio_offset(hv_fd, offset, size);
+       if (err) {
+               TRACE("check_mmio_offset() failure: %d\n", err);
+               return NULL;
+       }
+
+       /*
+        * mmio_base contains a base pfn and homing coordinates.  Turn
+        * it into an MMIO pgprot and offset pfn.
+        */
+       prot = hv_pte_set_lotar(prot, hv_pte_get_lotar(mmio_base));
+       pfn = pte_pfn(mmio_base) + PFN_DOWN(offset);
+
+       return ioremap_prot(PFN_PHYS(pfn), size, prot);
+}
+
+EXPORT_SYMBOL(iorpc_ioremap);
diff --git a/arch/tile/gxio/mpipe.c b/arch/tile/gxio/mpipe.c
new file mode 100644 (file)
index 0000000..e71c633
--- /dev/null
@@ -0,0 +1,545 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/*
+ * Implementation of mpipe gxio calls.
+ */
+
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/module.h>
+
+#include <gxio/iorpc_globals.h>
+#include <gxio/iorpc_mpipe.h>
+#include <gxio/iorpc_mpipe_info.h>
+#include <gxio/kiorpc.h>
+#include <gxio/mpipe.h>
+
+/* HACK: Avoid pointless "shadow" warnings. */
+#define link link_shadow
+
+int gxio_mpipe_init(gxio_mpipe_context_t *context, unsigned int mpipe_index)
+{
+       char file[32];
+
+       int fd;
+       int i;
+
+       snprintf(file, sizeof(file), "mpipe/%d/iorpc", mpipe_index);
+       fd = hv_dev_open((HV_VirtAddr) file, 0);
+       if (fd < 0) {
+               if (fd >= GXIO_ERR_MIN && fd <= GXIO_ERR_MAX)
+                       return fd;
+               else
+                       return -ENODEV;
+       }
+
+       context->fd = fd;
+
+       /* Map in the MMIO space. */
+       context->mmio_cfg_base = (void __force *)
+               iorpc_ioremap(fd, HV_MPIPE_CONFIG_MMIO_OFFSET,
+                             HV_MPIPE_CONFIG_MMIO_SIZE);
+       if (context->mmio_cfg_base == NULL)
+               goto cfg_failed;
+
+       context->mmio_fast_base = (void __force *)
+               iorpc_ioremap(fd, HV_MPIPE_FAST_MMIO_OFFSET,
+                             HV_MPIPE_FAST_MMIO_SIZE);
+       if (context->mmio_fast_base == NULL)
+               goto fast_failed;
+
+       /* Initialize the stacks. */
+       for (i = 0; i < 8; i++)
+               context->__stacks.stacks[i] = 255;
+
+       return 0;
+
+      fast_failed:
+       iounmap((void __force __iomem *)(context->mmio_cfg_base));
+      cfg_failed:
+       hv_dev_close(context->fd);
+       return -ENODEV;
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_init);
+
+int gxio_mpipe_destroy(gxio_mpipe_context_t *context)
+{
+       iounmap((void __force __iomem *)(context->mmio_cfg_base));
+       iounmap((void __force __iomem *)(context->mmio_fast_base));
+       return hv_dev_close(context->fd);
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_destroy);
+
+static int16_t gxio_mpipe_buffer_sizes[8] =
+       { 128, 256, 512, 1024, 1664, 4096, 10368, 16384 };
+
+gxio_mpipe_buffer_size_enum_t gxio_mpipe_buffer_size_to_buffer_size_enum(size_t
+                                                                        size)
+{
+       int i;
+       for (i = 0; i < 7; i++)
+               if (size <= gxio_mpipe_buffer_sizes[i])
+                       break;
+       return i;
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_buffer_size_to_buffer_size_enum);
+
+size_t gxio_mpipe_buffer_size_enum_to_buffer_size(gxio_mpipe_buffer_size_enum_t
+                                                 buffer_size_enum)
+{
+       if (buffer_size_enum > 7)
+               buffer_size_enum = 7;
+
+       return gxio_mpipe_buffer_sizes[buffer_size_enum];
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_buffer_size_enum_to_buffer_size);
+
+size_t gxio_mpipe_calc_buffer_stack_bytes(unsigned long buffers)
+{
+       const int BUFFERS_PER_LINE = 12;
+
+       /* Count the number of cachlines. */
+       unsigned long lines =
+               (buffers + BUFFERS_PER_LINE - 1) / BUFFERS_PER_LINE;
+
+       /* Convert to bytes. */
+       return lines * CHIP_L2_LINE_SIZE();
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_calc_buffer_stack_bytes);
+
+int gxio_mpipe_init_buffer_stack(gxio_mpipe_context_t *context,
+                                unsigned int stack,
+                                gxio_mpipe_buffer_size_enum_t
+                                buffer_size_enum, void *mem, size_t mem_size,
+                                unsigned int mem_flags)
+{
+       int result;
+
+       memset(mem, 0, mem_size);
+
+       result = gxio_mpipe_init_buffer_stack_aux(context, mem, mem_size,
+                                                 mem_flags, stack,
+                                                 buffer_size_enum);
+       if (result < 0)
+               return result;
+
+       /* Save the stack. */
+       context->__stacks.stacks[buffer_size_enum] = stack;
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_init_buffer_stack);
+
+int gxio_mpipe_init_notif_ring(gxio_mpipe_context_t *context,
+                              unsigned int ring,
+                              void *mem, size_t mem_size,
+                              unsigned int mem_flags)
+{
+       return gxio_mpipe_init_notif_ring_aux(context, mem, mem_size,
+                                             mem_flags, ring);
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_init_notif_ring);
+
+int gxio_mpipe_init_notif_group_and_buckets(gxio_mpipe_context_t *context,
+                                           unsigned int group,
+                                           unsigned int ring,
+                                           unsigned int num_rings,
+                                           unsigned int bucket,
+                                           unsigned int num_buckets,
+                                           gxio_mpipe_bucket_mode_t mode)
+{
+       int i;
+       int result;
+
+       gxio_mpipe_bucket_info_t bucket_info = { {
+                                                 .group = group,
+                                                 .mode = mode,
+                                                 }
+       };
+
+       gxio_mpipe_notif_group_bits_t bits = { {0} };
+
+       for (i = 0; i < num_rings; i++)
+               gxio_mpipe_notif_group_add_ring(&bits, ring + i);
+
+       result = gxio_mpipe_init_notif_group(context, group, bits);
+       if (result != 0)
+               return result;
+
+       for (i = 0; i < num_buckets; i++) {
+               bucket_info.notifring = ring + (i % num_rings);
+
+               result = gxio_mpipe_init_bucket(context, bucket + i,
+                                               bucket_info);
+               if (result != 0)
+                       return result;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_init_notif_group_and_buckets);
+
+int gxio_mpipe_init_edma_ring(gxio_mpipe_context_t *context,
+                             unsigned int ring, unsigned int channel,
+                             void *mem, size_t mem_size,
+                             unsigned int mem_flags)
+{
+       memset(mem, 0, mem_size);
+
+       return gxio_mpipe_init_edma_ring_aux(context, mem, mem_size, mem_flags,
+                                            ring, channel);
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_init_edma_ring);
+
+void gxio_mpipe_rules_init(gxio_mpipe_rules_t *rules,
+                          gxio_mpipe_context_t *context)
+{
+       rules->context = context;
+       memset(&rules->list, 0, sizeof(rules->list));
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_rules_init);
+
+int gxio_mpipe_rules_begin(gxio_mpipe_rules_t *rules,
+                          unsigned int bucket, unsigned int num_buckets,
+                          gxio_mpipe_rules_stacks_t *stacks)
+{
+       int i;
+       int stack = 255;
+
+       gxio_mpipe_rules_list_t *list = &rules->list;
+
+       /* Current rule. */
+       gxio_mpipe_rules_rule_t *rule =
+               (gxio_mpipe_rules_rule_t *) (list->rules + list->head);
+
+       unsigned int head = list->tail;
+
+       /*
+        * Align next rule properly.
+        *Note that "dmacs_and_vlans" will also be aligned.
+        */
+       unsigned int pad = 0;
+       while (((head + pad) % __alignof__(gxio_mpipe_rules_rule_t)) != 0)
+               pad++;
+
+       /*
+        * Verify room.
+        * ISSUE: Mark rules as broken on error?
+        */
+       if (head + pad + sizeof(*rule) >= sizeof(list->rules))
+               return GXIO_MPIPE_ERR_RULES_FULL;
+
+       /* Verify num_buckets is a power of 2. */
+       if (__builtin_popcount(num_buckets) != 1)
+               return GXIO_MPIPE_ERR_RULES_INVALID;
+
+       /* Add padding to previous rule. */
+       rule->size += pad;
+
+       /* Start a new rule. */
+       list->head = head + pad;
+
+       rule = (gxio_mpipe_rules_rule_t *) (list->rules + list->head);
+
+       /* Default some values. */
+       rule->headroom = 2;
+       rule->tailroom = 0;
+       rule->capacity = 16384;
+
+       /* Save the bucket info. */
+       rule->bucket_mask = num_buckets - 1;
+       rule->bucket_first = bucket;
+
+       for (i = 8 - 1; i >= 0; i--) {
+               int maybe =
+                       stacks ? stacks->stacks[i] : rules->context->__stacks.
+                       stacks[i];
+               if (maybe != 255)
+                       stack = maybe;
+               rule->stacks.stacks[i] = stack;
+       }
+
+       if (stack == 255)
+               return GXIO_MPIPE_ERR_RULES_INVALID;
+
+       /* NOTE: Only entries at the end of the array can be 255. */
+       for (i = 8 - 1; i > 0; i--) {
+               if (rule->stacks.stacks[i] == 255) {
+                       rule->stacks.stacks[i] = stack;
+                       rule->capacity =
+                               gxio_mpipe_buffer_size_enum_to_buffer_size(i -
+                                                                          1);
+               }
+       }
+
+       rule->size = sizeof(*rule);
+       list->tail = list->head + rule->size;
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_rules_begin);
+
+int gxio_mpipe_rules_add_channel(gxio_mpipe_rules_t *rules,
+                                unsigned int channel)
+{
+       gxio_mpipe_rules_list_t *list = &rules->list;
+
+       gxio_mpipe_rules_rule_t *rule =
+               (gxio_mpipe_rules_rule_t *) (list->rules + list->head);
+
+       /* Verify channel. */
+       if (channel >= 32)
+               return GXIO_MPIPE_ERR_RULES_INVALID;
+
+       /* Verify begun. */
+       if (list->tail == 0)
+               return GXIO_MPIPE_ERR_RULES_EMPTY;
+
+       rule->channel_bits |= (1UL << channel);
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_rules_add_channel);
+
+int gxio_mpipe_rules_set_headroom(gxio_mpipe_rules_t *rules, uint8_t headroom)
+{
+       gxio_mpipe_rules_list_t *list = &rules->list;
+
+       gxio_mpipe_rules_rule_t *rule =
+               (gxio_mpipe_rules_rule_t *) (list->rules + list->head);
+
+       /* Verify begun. */
+       if (list->tail == 0)
+               return GXIO_MPIPE_ERR_RULES_EMPTY;
+
+       rule->headroom = headroom;
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_rules_set_headroom);
+
+int gxio_mpipe_rules_commit(gxio_mpipe_rules_t *rules)
+{
+       gxio_mpipe_rules_list_t *list = &rules->list;
+       unsigned int size =
+               offsetof(gxio_mpipe_rules_list_t, rules) + list->tail;
+       return gxio_mpipe_commit_rules(rules->context, list, size);
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_rules_commit);
+
+int gxio_mpipe_iqueue_init(gxio_mpipe_iqueue_t *iqueue,
+                          gxio_mpipe_context_t *context,
+                          unsigned int ring,
+                          void *mem, size_t mem_size, unsigned int mem_flags)
+{
+       /* The init call below will verify that "mem_size" is legal. */
+       unsigned int num_entries = mem_size / sizeof(gxio_mpipe_idesc_t);
+
+       iqueue->context = context;
+       iqueue->idescs = (gxio_mpipe_idesc_t *)mem;
+       iqueue->ring = ring;
+       iqueue->num_entries = num_entries;
+       iqueue->mask_num_entries = num_entries - 1;
+       iqueue->log2_num_entries = __builtin_ctz(num_entries);
+       iqueue->head = 1;
+#ifdef __BIG_ENDIAN__
+       iqueue->swapped = 0;
+#endif
+
+       /* Initialize the "tail". */
+       __gxio_mmio_write(mem, iqueue->head);
+
+       return gxio_mpipe_init_notif_ring(context, ring, mem, mem_size,
+                                         mem_flags);
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_iqueue_init);
+
+int gxio_mpipe_equeue_init(gxio_mpipe_equeue_t *equeue,
+                          gxio_mpipe_context_t *context,
+                          unsigned int edma_ring_id,
+                          unsigned int channel,
+                          void *mem, unsigned int mem_size,
+                          unsigned int mem_flags)
+{
+       /* The init call below will verify that "mem_size" is legal. */
+       unsigned int num_entries = mem_size / sizeof(gxio_mpipe_edesc_t);
+
+       /* Offset used to read number of completed commands. */
+       MPIPE_EDMA_POST_REGION_ADDR_t offset;
+
+       int result = gxio_mpipe_init_edma_ring(context, edma_ring_id, channel,
+                                              mem, mem_size, mem_flags);
+       if (result < 0)
+               return result;
+
+       memset(equeue, 0, sizeof(*equeue));
+
+       offset.word = 0;
+       offset.region =
+               MPIPE_MMIO_ADDR__REGION_VAL_EDMA -
+               MPIPE_MMIO_ADDR__REGION_VAL_IDMA;
+       offset.ring = edma_ring_id;
+
+       __gxio_dma_queue_init(&equeue->dma_queue,
+                             context->mmio_fast_base + offset.word,
+                             num_entries);
+       equeue->edescs = mem;
+       equeue->mask_num_entries = num_entries - 1;
+       equeue->log2_num_entries = __builtin_ctz(num_entries);
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_equeue_init);
+
+int gxio_mpipe_set_timestamp(gxio_mpipe_context_t *context,
+                            const struct timespec *ts)
+{
+       cycles_t cycles = get_cycles();
+       return gxio_mpipe_set_timestamp_aux(context, (uint64_t)ts->tv_sec,
+                                           (uint64_t)ts->tv_nsec,
+                                           (uint64_t)cycles);
+}
+
+int gxio_mpipe_get_timestamp(gxio_mpipe_context_t *context,
+                            struct timespec *ts)
+{
+       int ret;
+       cycles_t cycles_prev, cycles_now, clock_rate;
+       cycles_prev = get_cycles();
+       ret = gxio_mpipe_get_timestamp_aux(context, (uint64_t *)&ts->tv_sec,
+                                          (uint64_t *)&ts->tv_nsec,
+                                          (uint64_t *)&cycles_now);
+       if (ret < 0) {
+               return ret;
+       }
+
+       clock_rate = get_clock_rate();
+       ts->tv_nsec -= (cycles_now - cycles_prev) * 1000000000LL / clock_rate;
+       if (ts->tv_nsec < 0) {
+               ts->tv_nsec += 1000000000LL;
+               ts->tv_sec -= 1;
+       }
+       return ret;
+}
+
+int gxio_mpipe_adjust_timestamp(gxio_mpipe_context_t *context, int64_t delta)
+{
+       return gxio_mpipe_adjust_timestamp_aux(context, delta);
+}
+
+/* Get our internal context used for link name access.  This context is
+ *  special in that it is not associated with an mPIPE service domain.
+ */
+static gxio_mpipe_context_t *_gxio_get_link_context(void)
+{
+       static gxio_mpipe_context_t context;
+       static gxio_mpipe_context_t *contextp;
+       static int tried_open = 0;
+       static DEFINE_MUTEX(mutex);
+
+       mutex_lock(&mutex);
+
+       if (!tried_open) {
+               int i = 0;
+               tried_open = 1;
+
+               /*
+                * "4" here is the maximum possible number of mPIPE shims; it's
+                * an exaggeration but we shouldn't ever go beyond 2 anyway.
+                */
+               for (i = 0; i < 4; i++) {
+                       char file[80];
+
+                       snprintf(file, sizeof(file), "mpipe/%d/iorpc_info", i);
+                       context.fd = hv_dev_open((HV_VirtAddr) file, 0);
+                       if (context.fd < 0)
+                               continue;
+
+                       contextp = &context;
+                       break;
+               }
+       }
+
+       mutex_unlock(&mutex);
+
+       return contextp;
+}
+
+int gxio_mpipe_link_enumerate_mac(int idx, char *link_name, uint8_t *link_mac)
+{
+       int rv;
+       _gxio_mpipe_link_name_t name;
+       _gxio_mpipe_link_mac_t mac;
+
+       gxio_mpipe_context_t *context = _gxio_get_link_context();
+       if (!context)
+               return GXIO_ERR_NO_DEVICE;
+
+       rv = gxio_mpipe_info_enumerate_aux(context, idx, &name, &mac);
+       if (rv >= 0) {
+               strncpy(link_name, name.name, sizeof(name.name));
+               memcpy(link_mac, mac.mac, sizeof(mac.mac));
+       }
+
+       return rv;
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_link_enumerate_mac);
+
+int gxio_mpipe_link_open(gxio_mpipe_link_t *link,
+                        gxio_mpipe_context_t *context, const char *link_name,
+                        unsigned int flags)
+{
+       _gxio_mpipe_link_name_t name;
+       int rv;
+
+       strncpy(name.name, link_name, sizeof(name.name));
+       name.name[GXIO_MPIPE_LINK_NAME_LEN - 1] = '\0';
+
+       rv = gxio_mpipe_link_open_aux(context, name, flags);
+       if (rv < 0)
+               return rv;
+
+       link->context = context;
+       link->channel = rv >> 8;
+       link->mac = rv & 0xFF;
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_link_open);
+
+int gxio_mpipe_link_close(gxio_mpipe_link_t *link)
+{
+       return gxio_mpipe_link_close_aux(link->context, link->mac);
+}
+
+EXPORT_SYMBOL_GPL(gxio_mpipe_link_close);
diff --git a/arch/tile/gxio/trio.c b/arch/tile/gxio/trio.c
new file mode 100644 (file)
index 0000000..69f0b8d
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/*
+ * Implementation of trio gxio calls.
+ */
+
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/module.h>
+
+#include <gxio/trio.h>
+#include <gxio/iorpc_globals.h>
+#include <gxio/iorpc_trio.h>
+#include <gxio/kiorpc.h>
+
+int gxio_trio_init(gxio_trio_context_t *context, unsigned int trio_index)
+{
+       char file[32];
+       int fd;
+
+       snprintf(file, sizeof(file), "trio/%d/iorpc", trio_index);
+       fd = hv_dev_open((HV_VirtAddr) file, 0);
+       if (fd < 0) {
+               context->fd = -1;
+
+               if (fd >= GXIO_ERR_MIN && fd <= GXIO_ERR_MAX)
+                       return fd;
+               else
+                       return -ENODEV;
+       }
+
+       context->fd = fd;
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(gxio_trio_init);
diff --git a/arch/tile/gxio/usb_host.c b/arch/tile/gxio/usb_host.c
new file mode 100644 (file)
index 0000000..66b002f
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/*
+ *
+ * Implementation of USB gxio calls.
+ */
+
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+
+#include <gxio/iorpc_globals.h>
+#include <gxio/iorpc_usb_host.h>
+#include <gxio/kiorpc.h>
+#include <gxio/usb_host.h>
+
+int gxio_usb_host_init(gxio_usb_host_context_t * context, int usb_index,
+                      int is_ehci)
+{
+       char file[32];
+       int fd;
+
+       if (is_ehci)
+               snprintf(file, sizeof(file), "usb_host/%d/iorpc/ehci",
+                        usb_index);
+       else
+               snprintf(file, sizeof(file), "usb_host/%d/iorpc/ohci",
+                        usb_index);
+
+       fd = hv_dev_open((HV_VirtAddr) file, 0);
+       if (fd < 0) {
+               if (fd >= GXIO_ERR_MIN && fd <= GXIO_ERR_MAX)
+                       return fd;
+               else
+                       return -ENODEV;
+       }
+
+       context->fd = fd;
+
+       // Map in the MMIO space.
+       context->mmio_base =
+               (void __force *)iorpc_ioremap(fd, 0, HV_USB_HOST_MMIO_SIZE);
+
+       if (context->mmio_base == NULL) {
+               hv_dev_close(context->fd);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(gxio_usb_host_init);
+
+int gxio_usb_host_destroy(gxio_usb_host_context_t * context)
+{
+       iounmap((void __force __iomem *)(context->mmio_base));
+       hv_dev_close(context->fd);
+
+       context->mmio_base = NULL;
+       context->fd = -1;
+
+       return 0;
+}
+
+EXPORT_SYMBOL_GPL(gxio_usb_host_destroy);
+
+void *gxio_usb_host_get_reg_start(gxio_usb_host_context_t * context)
+{
+       return context->mmio_base;
+}
+
+EXPORT_SYMBOL_GPL(gxio_usb_host_get_reg_start);
+
+size_t gxio_usb_host_get_reg_len(gxio_usb_host_context_t * context)
+{
+       return HV_USB_HOST_MMIO_SIZE;
+}
+
+EXPORT_SYMBOL_GPL(gxio_usb_host_get_reg_len);
diff --git a/arch/tile/include/arch/mpipe.h b/arch/tile/include/arch/mpipe.h
new file mode 100644 (file)
index 0000000..8a33912
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_MPIPE_H__
+#define __ARCH_MPIPE_H__
+
+#include <arch/abi.h>
+#include <arch/mpipe_def.h>
+
+#ifndef __ASSEMBLER__
+
+/*
+ * MMIO Ingress DMA Release Region Address.
+ * This is a description of the physical addresses used to manipulate ingress
+ * credit counters.  Accesses to this address space should use an address of
+ * this form and a value like that specified in IDMA_RELEASE_REGION_VAL.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /* Reserved. */
+    uint_reg_t __reserved_0  : 3;
+    /* NotifRing to be released */
+    uint_reg_t ring          : 8;
+    /* Bucket to be released */
+    uint_reg_t bucket        : 13;
+    /* Enable NotifRing release */
+    uint_reg_t ring_enable   : 1;
+    /* Enable Bucket release */
+    uint_reg_t bucket_enable : 1;
+    /*
+     * This field of the address selects the region (address space) to be
+     * accessed.  For the iDMA release region, this field must be 4.
+     */
+    uint_reg_t region        : 3;
+    /* Reserved. */
+    uint_reg_t __reserved_1  : 6;
+    /* This field of the address indexes the 32 entry service domain table. */
+    uint_reg_t svc_dom       : 5;
+    /* Reserved. */
+    uint_reg_t __reserved_2  : 24;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved_2  : 24;
+    uint_reg_t svc_dom       : 5;
+    uint_reg_t __reserved_1  : 6;
+    uint_reg_t region        : 3;
+    uint_reg_t bucket_enable : 1;
+    uint_reg_t ring_enable   : 1;
+    uint_reg_t bucket        : 13;
+    uint_reg_t ring          : 8;
+    uint_reg_t __reserved_0  : 3;
+#endif
+  };
+
+  uint_reg_t word;
+} MPIPE_IDMA_RELEASE_REGION_ADDR_t;
+
+/*
+ * MMIO Ingress DMA Release Region Value - Release NotifRing and/or Bucket.
+ * Provides release of the associated NotifRing.  The address of the MMIO
+ * operation is described in IDMA_RELEASE_REGION_ADDR.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /*
+     * Number of packets being released.  The load balancer's count of
+     * inflight packets will be decremented by this amount for the associated
+     * Bucket and/or NotifRing
+     */
+    uint_reg_t count      : 16;
+    /* Reserved. */
+    uint_reg_t __reserved : 48;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved : 48;
+    uint_reg_t count      : 16;
+#endif
+  };
+
+  uint_reg_t word;
+} MPIPE_IDMA_RELEASE_REGION_VAL_t;
+
+/*
+ * MMIO Buffer Stack Manager Region Address.
+ * This MMIO region is used for posting or fetching buffers to/from the
+ * buffer stack manager.  On an MMIO load, this pops a buffer descriptor from
+ * the top of stack if one is available.  On an MMIO store, this pushes a
+ * buffer to the stack.  The value read or written is described in
+ * BSM_REGION_VAL.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /* Reserved. */
+    uint_reg_t __reserved_0 : 3;
+    /* BufferStack being accessed. */
+    uint_reg_t stack        : 5;
+    /* Reserved. */
+    uint_reg_t __reserved_1 : 18;
+    /*
+     * This field of the address selects the region (address space) to be
+     * accessed.  For the buffer stack manager region, this field must be 6.
+     */
+    uint_reg_t region       : 3;
+    /* Reserved. */
+    uint_reg_t __reserved_2 : 6;
+    /* This field of the address indexes the 32 entry service domain table. */
+    uint_reg_t svc_dom      : 5;
+    /* Reserved. */
+    uint_reg_t __reserved_3 : 24;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved_3 : 24;
+    uint_reg_t svc_dom      : 5;
+    uint_reg_t __reserved_2 : 6;
+    uint_reg_t region       : 3;
+    uint_reg_t __reserved_1 : 18;
+    uint_reg_t stack        : 5;
+    uint_reg_t __reserved_0 : 3;
+#endif
+  };
+
+  uint_reg_t word;
+} MPIPE_BSM_REGION_ADDR_t;
+
+/*
+ * MMIO Buffer Stack Manager Region Value.
+ * This MMIO region is used for posting or fetching buffers to/from the
+ * buffer stack manager.  On an MMIO load, this pops a buffer descriptor from
+ * the top of stack if one is available. On an MMIO store, this pushes a
+ * buffer to the stack.  The address of the MMIO operation is described in
+ * BSM_REGION_ADDR.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /* Reserved. */
+    uint_reg_t __reserved_0 : 7;
+    /*
+     * Base virtual address of the buffer.  Must be sign extended by consumer.
+     */
+    int_reg_t va           : 35;
+    /* Reserved. */
+    uint_reg_t __reserved_1 : 6;
+    /*
+     * Index of the buffer stack to which this buffer belongs.  Ignored on
+     * writes since the offset bits specify the stack being accessed.
+     */
+    uint_reg_t stack_idx    : 5;
+    /* Reserved. */
+    uint_reg_t __reserved_2 : 5;
+    /*
+     * Reads as one to indicate that this is a hardware managed buffer.
+     * Ignored on writes since all buffers on a given stack are the same size.
+     */
+    uint_reg_t hwb          : 1;
+    /*
+     * Encoded size of buffer (ignored on writes):
+     * 0 = 128 bytes
+     * 1 = 256 bytes
+     * 2 = 512 bytes
+     * 3 = 1024 bytes
+     * 4 = 1664 bytes
+     * 5 = 4096 bytes
+     * 6 = 10368 bytes
+     * 7 = 16384 bytes
+     */
+    uint_reg_t size         : 3;
+    /*
+     * Valid indication for the buffer.  Ignored on writes.
+     * 0 : Valid buffer descriptor popped from stack.
+     * 3 : Could not pop a buffer from the stack.  Either the stack is empty,
+     * or the hardware's prefetch buffer is empty for this stack.
+     */
+    uint_reg_t c            : 2;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t c            : 2;
+    uint_reg_t size         : 3;
+    uint_reg_t hwb          : 1;
+    uint_reg_t __reserved_2 : 5;
+    uint_reg_t stack_idx    : 5;
+    uint_reg_t __reserved_1 : 6;
+    int_reg_t va           : 35;
+    uint_reg_t __reserved_0 : 7;
+#endif
+  };
+
+  uint_reg_t word;
+} MPIPE_BSM_REGION_VAL_t;
+
+/*
+ * MMIO Egress DMA Post Region Address.
+ * Used to post descriptor locations to the eDMA descriptor engine.  The
+ * value to be written is described in EDMA_POST_REGION_VAL
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /* Reserved. */
+    uint_reg_t __reserved_0 : 3;
+    /* eDMA ring being accessed */
+    uint_reg_t ring         : 5;
+    /* Reserved. */
+    uint_reg_t __reserved_1 : 18;
+    /*
+     * This field of the address selects the region (address space) to be
+     * accessed.  For the egress DMA post region, this field must be 5.
+     */
+    uint_reg_t region       : 3;
+    /* Reserved. */
+    uint_reg_t __reserved_2 : 6;
+    /* This field of the address indexes the 32 entry service domain table. */
+    uint_reg_t svc_dom      : 5;
+    /* Reserved. */
+    uint_reg_t __reserved_3 : 24;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved_3 : 24;
+    uint_reg_t svc_dom      : 5;
+    uint_reg_t __reserved_2 : 6;
+    uint_reg_t region       : 3;
+    uint_reg_t __reserved_1 : 18;
+    uint_reg_t ring         : 5;
+    uint_reg_t __reserved_0 : 3;
+#endif
+  };
+
+  uint_reg_t word;
+} MPIPE_EDMA_POST_REGION_ADDR_t;
+
+/*
+ * MMIO Egress DMA Post Region Value.
+ * Used to post descriptor locations to the eDMA descriptor engine.  The
+ * address is described in EDMA_POST_REGION_ADDR.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /*
+     * For writes, this specifies the current ring tail pointer prior to any
+     * post.  For example, to post 1 or more descriptors starting at location
+     * 23, this would contain 23 (not 24).  On writes, this index must be
+     * masked based on the ring size.  The new tail pointer after this post
+     * is COUNT+RING_IDX (masked by the ring size).
+     *
+     * For reads, this provides the hardware descriptor fetcher's head
+     * pointer.  The descriptors prior to the head pointer, however, may not
+     * yet have been processed so this indicator is only used to determine
+     * how full the ring is and if software may post more descriptors.
+     */
+    uint_reg_t ring_idx   : 16;
+    /*
+     * For writes, this specifies number of contiguous descriptors that are
+     * being posted.  Software may post up to RingSize descriptors with a
+     * single MMIO store.  A zero in this field on a write will "wake up" an
+     * eDMA ring and cause it fetch descriptors regardless of the hardware's
+     * current view of the state of the tail pointer.
+     *
+     * For reads, this field provides a rolling count of the number of
+     * descriptors that have been completely processed.  This may be used by
+     * software to determine when buffers associated with a descriptor may be
+     * returned or reused.  When the ring's flush bit is cleared by software
+     * (after having been set by HW or SW), the COUNT will be cleared.
+     */
+    uint_reg_t count      : 16;
+    /*
+     * For writes, this specifies the generation number of the tail being
+     * posted. Note that if tail+cnt wraps to the beginning of the ring, the
+     * eDMA hardware assumes that the descriptors posted at the beginning of
+     * the ring are also valid so it is okay to post around the wrap point.
+     *
+     * For reads, this is the current generation number.  Valid descriptors
+     * will have the inverse of this generation number.
+     */
+    uint_reg_t gen        : 1;
+    /* Reserved. */
+    uint_reg_t __reserved : 31;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved : 31;
+    uint_reg_t gen        : 1;
+    uint_reg_t count      : 16;
+    uint_reg_t ring_idx   : 16;
+#endif
+  };
+
+  uint_reg_t word;
+} MPIPE_EDMA_POST_REGION_VAL_t;
+
+/*
+ * Load Balancer Bucket Status Data.
+ * Read/Write data for load balancer Bucket-Status Table. 4160 entries
+ * indexed by LBL_INIT_CTL.IDX when LBL_INIT_CTL.STRUCT_SEL is BSTS_TBL
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /* NotifRing currently assigned to this bucket. */
+    uint_reg_t notifring  : 8;
+    /* Current reference count. */
+    uint_reg_t count      : 16;
+    /* Group associated with this bucket. */
+    uint_reg_t group      : 5;
+    /* Mode select for this bucket. */
+    uint_reg_t mode       : 3;
+    /* Reserved. */
+    uint_reg_t __reserved : 32;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved : 32;
+    uint_reg_t mode       : 3;
+    uint_reg_t group      : 5;
+    uint_reg_t count      : 16;
+    uint_reg_t notifring  : 8;
+#endif
+  };
+
+  uint_reg_t word;
+} MPIPE_LBL_INIT_DAT_BSTS_TBL_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_MPIPE_H__) */
diff --git a/arch/tile/include/arch/mpipe_constants.h b/arch/tile/include/arch/mpipe_constants.h
new file mode 100644 (file)
index 0000000..410a040
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+
+#ifndef __ARCH_MPIPE_CONSTANTS_H__
+#define __ARCH_MPIPE_CONSTANTS_H__
+
+#define MPIPE_NUM_CLASSIFIERS 10
+#define MPIPE_CLS_MHZ 1200
+
+#define MPIPE_NUM_EDMA_RINGS 32
+
+#define MPIPE_NUM_SGMII_MACS 16
+#define MPIPE_NUM_XAUI_MACS 4
+#define MPIPE_NUM_LOOPBACK_CHANNELS 4
+#define MPIPE_NUM_NON_LB_CHANNELS 28
+
+#define MPIPE_NUM_IPKT_BLOCKS 1536
+
+#define MPIPE_NUM_BUCKETS 4160
+
+#define MPIPE_NUM_NOTIF_RINGS 256
+
+#define MPIPE_NUM_NOTIF_GROUPS 32
+
+#define MPIPE_NUM_TLBS_PER_ASID 16
+#define MPIPE_TLB_IDX_WIDTH 4
+
+#define MPIPE_MMIO_NUM_SVC_DOM 32
+
+#endif /* __ARCH_MPIPE_CONSTANTS_H__ */
diff --git a/arch/tile/include/arch/mpipe_def.h b/arch/tile/include/arch/mpipe_def.h
new file mode 100644 (file)
index 0000000..c3d3021
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_MPIPE_DEF_H__
+#define __ARCH_MPIPE_DEF_H__
+#define MPIPE_MMIO_ADDR__REGION_SHIFT 26
+#define MPIPE_MMIO_ADDR__REGION_VAL_CFG 0x0
+#define MPIPE_MMIO_ADDR__REGION_VAL_IDMA 0x4
+#define MPIPE_MMIO_ADDR__REGION_VAL_EDMA 0x5
+#define MPIPE_MMIO_ADDR__REGION_VAL_BSM 0x6
+#define MPIPE_BSM_REGION_VAL__VA_SHIFT 7
+#define MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_128 0x0
+#define MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_256 0x1
+#define MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_512 0x2
+#define MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_1024 0x3
+#define MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_1664 0x4
+#define MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_4096 0x5
+#define MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_10368 0x6
+#define MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_16384 0x7
+#define MPIPE_LBL_INIT_DAT_BSTS_TBL__MODE_VAL_DFA 0x0
+#define MPIPE_LBL_INIT_DAT_BSTS_TBL__MODE_VAL_FIXED 0x1
+#define MPIPE_LBL_INIT_DAT_BSTS_TBL__MODE_VAL_ALWAYS_PICK 0x2
+#define MPIPE_LBL_INIT_DAT_BSTS_TBL__MODE_VAL_STICKY 0x3
+#define MPIPE_LBL_INIT_DAT_BSTS_TBL__MODE_VAL_STICKY_RAND 0x7
+#define MPIPE_LBL_NR_STATE__FIRST_WORD 0x2138
+#endif /* !defined(__ARCH_MPIPE_DEF_H__) */
diff --git a/arch/tile/include/arch/mpipe_shm.h b/arch/tile/include/arch/mpipe_shm.h
new file mode 100644 (file)
index 0000000..f2e9e12
--- /dev/null
@@ -0,0 +1,509 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+
+#ifndef __ARCH_MPIPE_SHM_H__
+#define __ARCH_MPIPE_SHM_H__
+
+#include <arch/abi.h>
+#include <arch/mpipe_shm_def.h>
+
+#ifndef __ASSEMBLER__
+/**
+ * MPIPE eDMA Descriptor.
+ * The eDMA descriptor is written by software and consumed by hardware.  It
+ * is used to specify the location of egress packet data to be sent out of
+ * the chip via one of the packet interfaces.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+    /* Word 0 */
+
+#ifndef __BIG_ENDIAN__
+    /**
+     * Generation number.  Used to indicate a valid descriptor in ring.  When
+     * a new descriptor is written into the ring, software must toggle this
+     * bit.  The net effect is that the GEN bit being written into new
+     * descriptors toggles each time the ring tail pointer wraps.
+     */
+    uint_reg_t gen        : 1;
+    /** Reserved.  Must be zero. */
+    uint_reg_t r0         : 7;
+    /** Checksum generation enabled for this transfer. */
+    uint_reg_t csum       : 1;
+    /**
+     * Nothing to be sent.  Used, for example, when software has dropped a
+     * packet but still wishes to return all of the associated buffers.
+     */
+    uint_reg_t ns         : 1;
+    /**
+     * Notification interrupt will be delivered when packet has been egressed.
+     */
+    uint_reg_t notif      : 1;
+    /**
+     * Boundary indicator.  When 1, this transfer includes the EOP for this
+     * command.  Must be clear on all but the last descriptor for an egress
+     * packet.
+     */
+    uint_reg_t bound      : 1;
+    /** Reserved.  Must be zero. */
+    uint_reg_t r1         : 4;
+    /**
+     * Number of bytes to be sent for this descriptor.  When zero, no data
+     * will be moved and the buffer descriptor will be ignored.  If the
+     * buffer descriptor indicates that it is chained, the low 7 bits of the
+     * VA indicate the offset within the first buffer (e.g. 127 bytes is the
+     * maximum offset into the first buffer).  If the size exceeds a single
+     * buffer, subsequent buffer descriptors will be fetched prior to
+     * processing the next eDMA descriptor in the ring.
+     */
+    uint_reg_t xfer_size  : 14;
+    /** Reserved.  Must be zero. */
+    uint_reg_t r2         : 2;
+    /**
+     * Destination of checksum relative to CSUM_START relative to the first
+     * byte moved by this descriptor.  Must be zero if CSUM=0 in this
+     * descriptor.  Must be less than XFER_SIZE (e.g. the first byte of the
+     * CSUM_DEST must be within the span of this descriptor).
+     */
+    uint_reg_t csum_dest  : 8;
+    /**
+     * Start byte of checksum relative to the first byte moved by this
+     * descriptor.  If this is not the first descriptor for the egress
+     * packet, CSUM_START is still relative to the first byte in this
+     * descriptor.  Must be zero if CSUM=0 in this descriptor.
+     */
+    uint_reg_t csum_start : 8;
+    /**
+     * Initial value for 16-bit 1's compliment checksum if enabled via CSUM.
+     * Specified in network order.  That is, bits[7:0] will be added to the
+     * byte pointed to by CSUM_START and bits[15:8] will be added to the byte
+     * pointed to by CSUM_START+1 (with appropriate 1's compliment carries).
+     * Must be zero if CSUM=0 in this descriptor.
+     */
+    uint_reg_t csum_seed  : 16;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t csum_seed  : 16;
+    uint_reg_t csum_start : 8;
+    uint_reg_t csum_dest  : 8;
+    uint_reg_t r2         : 2;
+    uint_reg_t xfer_size  : 14;
+    uint_reg_t r1         : 4;
+    uint_reg_t bound      : 1;
+    uint_reg_t notif      : 1;
+    uint_reg_t ns         : 1;
+    uint_reg_t csum       : 1;
+    uint_reg_t r0         : 7;
+    uint_reg_t gen        : 1;
+#endif
+
+    /* Word 1 */
+
+#ifndef __BIG_ENDIAN__
+    /** Virtual address.  Must be sign extended by consumer. */
+    int_reg_t va           : 42;
+    /** Reserved. */
+    uint_reg_t __reserved_0 : 6;
+    /** Index of the buffer stack to which this buffer belongs. */
+    uint_reg_t stack_idx    : 5;
+    /** Reserved. */
+    uint_reg_t __reserved_1 : 3;
+    /**
+     * Instance ID.  For devices that support more than one mPIPE instance,
+     * this field indicates the buffer owner.  If the INST field does not
+     * match the mPIPE's instance number when a packet is egressed, buffers
+     * with HWB set will be returned to the other mPIPE instance.
+     */
+    uint_reg_t inst         : 1;
+    /** Reserved. */
+    uint_reg_t __reserved_2 : 1;
+    /**
+     * Always set to one by hardware in iDMA packet descriptors.  For eDMA,
+     * indicates whether the buffer will be released to the buffer stack
+     * manager.  When 0, software is responsible for releasing the buffer.
+     */
+    uint_reg_t hwb          : 1;
+    /**
+     * Encoded size of buffer.  Set by the ingress hardware for iDMA packet
+     * descriptors.  For eDMA descriptors, indicates the buffer size if .c
+     * indicates a chained packet.  If an eDMA descriptor is not chained and
+     * the .hwb bit is not set, this field is ignored and the size is
+     * specified by the .xfer_size field.
+     * 0 = 128 bytes
+     * 1 = 256 bytes
+     * 2 = 512 bytes
+     * 3 = 1024 bytes
+     * 4 = 1664 bytes
+     * 5 = 4096 bytes
+     * 6 = 10368 bytes
+     * 7 = 16384 bytes
+     */
+    uint_reg_t size         : 3;
+    /**
+     * Chaining configuration for the buffer.  Indicates that an ingress
+     * packet or egress command is chained across multiple buffers, with each
+     * buffer's size indicated by the .size field.
+     */
+    uint_reg_t c            : 2;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t c            : 2;
+    uint_reg_t size         : 3;
+    uint_reg_t hwb          : 1;
+    uint_reg_t __reserved_2 : 1;
+    uint_reg_t inst         : 1;
+    uint_reg_t __reserved_1 : 3;
+    uint_reg_t stack_idx    : 5;
+    uint_reg_t __reserved_0 : 6;
+    int_reg_t va           : 42;
+#endif
+
+  };
+
+  /** Word access */
+  uint_reg_t words[2];
+} MPIPE_EDMA_DESC_t;
+
+/**
+ * MPIPE Packet Descriptor.
+ * The packet descriptor is filled by the mPIPE's classification,
+ * load-balancing, and buffer management services.  Some fields are consumed
+ * by mPIPE hardware, and others are consumed by Tile software.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+    /* Word 0 */
+
+#ifndef __BIG_ENDIAN__
+    /**
+     * Notification ring into which this packet descriptor is written.
+     * Typically written by load balancer, but can be overridden by
+     * classification program if NR is asserted.
+     */
+    uint_reg_t notif_ring   : 8;
+    /** Source channel for this packet.  Written by mPIPE DMA hardware. */
+    uint_reg_t channel      : 5;
+    /** Reserved. */
+    uint_reg_t __reserved_0 : 1;
+    /**
+     * MAC Error.
+     * Generated by the MAC interface.  Asserted if there was an overrun of
+     * the MAC's receive FIFO.  This condition generally only occurs if the
+     * mPIPE clock is running too slowly.
+     */
+    uint_reg_t me           : 1;
+    /**
+     * Truncation Error.
+     * Written by the iDMA hardware.  Asserted if packet was truncated due to
+     * insufficient space in iPkt buffer
+     */
+    uint_reg_t tr           : 1;
+    /**
+     * Written by the iDMA hardware.  Indicates the number of bytes written
+     * to Tile memory.  In general, this is the actual size of the packet as
+     * received from the MAC.  But if the packet is truncated due to running
+     * out of buffers or due to the iPkt buffer filling up, then the L2_SIZE
+     * will be reduced to reflect the actual number of valid bytes written to
+     * Tile memory.
+     */
+    uint_reg_t l2_size      : 14;
+    /**
+     * CRC Error.
+     * Generated by the MAC.  Asserted if MAC indicated an L2 CRC error or
+     * other L2 error (bad length etc.) on the packet.
+     */
+    uint_reg_t ce           : 1;
+    /**
+     * Cut Through.
+     * Written by the iDMA hardware.  Asserted if packet was not completely
+     * received before being sent to classifier.  L2_Size will indicate
+     * number of bytes received so far.
+     */
+    uint_reg_t ct           : 1;
+    /**
+     * Written by the classification program.  Used by the load balancer to
+     * select the ring into which this packet descriptor is written.
+     */
+    uint_reg_t bucket_id    : 13;
+    /** Reserved. */
+    uint_reg_t __reserved_1 : 3;
+    /**
+     * Checksum.
+     * Written by classification program.  When 1, the checksum engine will
+     * perform checksum based on the CSUM_SEED, CSUM_START, and CSUM_BYTES
+     * fields.  The result will be placed in CSUM_VAL.
+     */
+    uint_reg_t cs           : 1;
+    /**
+     * Notification Ring Select.
+     * Written by the classification program.  When 1, the NotifRingIDX is
+     * set by classification program rather than being set by load balancer.
+     */
+    uint_reg_t nr           : 1;
+    /**
+     * Written by classification program.  Indicates whether packet and
+     * descriptor should both be dropped, both be delivered, or only the
+     * descriptor should be delivered.
+     */
+    uint_reg_t dest         : 2;
+    /**
+     * General Purpose Sequence Number Enable.
+     * Written by the classification program.  When 1, the GP_SQN_SEL field
+     * contains the sequence number selector and the GP_SQN field will be
+     * replaced with the associated sequence number.  When clear, the GP_SQN
+     * field is left intact and be used as "Custom" bytes.
+     */
+    uint_reg_t sq           : 1;
+    /**
+     * TimeStamp Enable.
+     * Enable TimeStamp insertion.  When clear, timestamp field may be filled
+     * with custom data by classifier.  When set, hardware inserts the
+     * timestamp when the start of packet is received from the MAC.
+     */
+    uint_reg_t ts           : 1;
+    /**
+     * Packet Sequence Number Enable.
+     * Enable PacketSQN insertion.  When clear, PacketSQN field may be filled
+     * with custom data by classifier.  When set, hardware inserts the packet
+     * sequence number when the packet descriptor is written to a
+     * notification ring.
+     */
+    uint_reg_t ps           : 1;
+    /**
+     * Buffer Error.
+     * Written by the iDMA hardware.  Asserted if iDMA ran out of buffers
+     * while writing the packet. Software must still return any buffer
+     * descriptors whose C field indicates a valid descriptor was consumed.
+     */
+    uint_reg_t be           : 1;
+    /**
+     * Written by  the classification program.  The associated counter is
+     * incremented when the packet is sent.
+     */
+    uint_reg_t ctr0         : 5;
+    /** Reserved. */
+    uint_reg_t __reserved_2 : 3;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved_2 : 3;
+    uint_reg_t ctr0         : 5;
+    uint_reg_t be           : 1;
+    uint_reg_t ps           : 1;
+    uint_reg_t ts           : 1;
+    uint_reg_t sq           : 1;
+    uint_reg_t dest         : 2;
+    uint_reg_t nr           : 1;
+    uint_reg_t cs           : 1;
+    uint_reg_t __reserved_1 : 3;
+    uint_reg_t bucket_id    : 13;
+    uint_reg_t ct           : 1;
+    uint_reg_t ce           : 1;
+    uint_reg_t l2_size      : 14;
+    uint_reg_t tr           : 1;
+    uint_reg_t me           : 1;
+    uint_reg_t __reserved_0 : 1;
+    uint_reg_t channel      : 5;
+    uint_reg_t notif_ring   : 8;
+#endif
+
+    /* Word 1 */
+
+#ifndef __BIG_ENDIAN__
+    /**
+     * Written by  the classification program.  The associated counter is
+     * incremented when the packet is sent.
+     */
+    uint_reg_t ctr1          : 5;
+    /** Reserved. */
+    uint_reg_t __reserved_3  : 3;
+    /**
+     * Written by classification program.  Indicates the start byte for
+     * checksum.  Relative to 1st byte received from MAC.
+     */
+    uint_reg_t csum_start    : 8;
+    /**
+     * Checksum seed written by classification program.  Overwritten with
+     * resultant checksum if CS bit is asserted.  The endianness of the CSUM
+     * value bits when viewed by Tile software match the packet byte order.
+     * That is, bits[7:0] of the resulting checksum value correspond to
+     * earlier (more significant) bytes in the packet.  To avoid classifier
+     * software from having to byte swap the CSUM_SEED, the iDMA checksum
+     * engine byte swaps the classifier's result before seeding the checksum
+     * calculation.  Thus, the CSUM_START byte of packet data is added to
+     * bits[15:8] of the CSUM_SEED field generated by the classifier.  This
+     * byte swap will be visible to Tile software if the CS bit is clear.
+     */
+    uint_reg_t csum_seed_val : 16;
+    /**
+     * Written by  the classification program.  Not interpreted by mPIPE
+     * hardware.
+     */
+    uint_reg_t custom0       : 32;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t custom0       : 32;
+    uint_reg_t csum_seed_val : 16;
+    uint_reg_t csum_start    : 8;
+    uint_reg_t __reserved_3  : 3;
+    uint_reg_t ctr1          : 5;
+#endif
+
+    /* Word 2 */
+
+#ifndef __BIG_ENDIAN__
+    /**
+     * Written by  the classification program.  Not interpreted by mPIPE
+     * hardware.
+     */
+    uint_reg_t custom1 : 64;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t custom1 : 64;
+#endif
+
+    /* Word 3 */
+
+#ifndef __BIG_ENDIAN__
+    /**
+     * Written by  the classification program.  Not interpreted by mPIPE
+     * hardware.
+     */
+    uint_reg_t custom2 : 64;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t custom2 : 64;
+#endif
+
+    /* Word 4 */
+
+#ifndef __BIG_ENDIAN__
+    /**
+     * Written by  the classification program.  Not interpreted by mPIPE
+     * hardware.
+     */
+    uint_reg_t custom3 : 64;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t custom3 : 64;
+#endif
+
+    /* Word 5 */
+
+#ifndef __BIG_ENDIAN__
+    /**
+     * Sequence number applied when packet is distributed.   Classifier
+     * selects which sequence number is to be applied by writing the 13-bit
+     * SQN-selector into this field.
+     */
+    uint_reg_t gp_sqn     : 16;
+    /**
+     * Written by notification hardware.  The packet sequence number is
+     * incremented for each packet that wasn't dropped.
+     */
+    uint_reg_t packet_sqn : 48;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t packet_sqn : 48;
+    uint_reg_t gp_sqn     : 16;
+#endif
+
+    /* Word 6 */
+
+#ifndef __BIG_ENDIAN__
+    /**
+     * Written by hardware when the start-of-packet is received by the mPIPE
+     * from the MAC.  This is the nanoseconds part of the packet timestamp.
+     */
+    uint_reg_t time_stamp_ns  : 32;
+    /**
+     * Written by hardware when the start-of-packet is received by the mPIPE
+     * from the MAC.  This is the seconds part of the packet timestamp.
+     */
+    uint_reg_t time_stamp_sec : 32;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t time_stamp_sec : 32;
+    uint_reg_t time_stamp_ns  : 32;
+#endif
+
+    /* Word 7 */
+
+#ifndef __BIG_ENDIAN__
+    /** Virtual address.  Must be sign extended by consumer. */
+    int_reg_t va           : 42;
+    /** Reserved. */
+    uint_reg_t __reserved_4 : 6;
+    /** Index of the buffer stack to which this buffer belongs. */
+    uint_reg_t stack_idx    : 5;
+    /** Reserved. */
+    uint_reg_t __reserved_5 : 3;
+    /**
+     * Instance ID.  For devices that support more than one mPIPE instance,
+     * this field indicates the buffer owner.  If the INST field does not
+     * match the mPIPE's instance number when a packet is egressed, buffers
+     * with HWB set will be returned to the other mPIPE instance.
+     */
+    uint_reg_t inst         : 1;
+    /** Reserved. */
+    uint_reg_t __reserved_6 : 1;
+    /**
+     * Always set to one by hardware in iDMA packet descriptors.  For eDMA,
+     * indicates whether the buffer will be released to the buffer stack
+     * manager.  When 0, software is responsible for releasing the buffer.
+     */
+    uint_reg_t hwb          : 1;
+    /**
+     * Encoded size of buffer.  Set by the ingress hardware for iDMA packet
+     * descriptors.  For eDMA descriptors, indicates the buffer size if .c
+     * indicates a chained packet.  If an eDMA descriptor is not chained and
+     * the .hwb bit is not set, this field is ignored and the size is
+     * specified by the .xfer_size field.
+     * 0 = 128 bytes
+     * 1 = 256 bytes
+     * 2 = 512 bytes
+     * 3 = 1024 bytes
+     * 4 = 1664 bytes
+     * 5 = 4096 bytes
+     * 6 = 10368 bytes
+     * 7 = 16384 bytes
+     */
+    uint_reg_t size         : 3;
+    /**
+     * Chaining configuration for the buffer.  Indicates that an ingress
+     * packet or egress command is chained across multiple buffers, with each
+     * buffer's size indicated by the .size field.
+     */
+    uint_reg_t c            : 2;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t c            : 2;
+    uint_reg_t size         : 3;
+    uint_reg_t hwb          : 1;
+    uint_reg_t __reserved_6 : 1;
+    uint_reg_t inst         : 1;
+    uint_reg_t __reserved_5 : 3;
+    uint_reg_t stack_idx    : 5;
+    uint_reg_t __reserved_4 : 6;
+    int_reg_t va           : 42;
+#endif
+
+  };
+
+  /** Word access */
+  uint_reg_t words[8];
+} MPIPE_PDESC_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_MPIPE_SHM_H__) */
diff --git a/arch/tile/include/arch/mpipe_shm_def.h b/arch/tile/include/arch/mpipe_shm_def.h
new file mode 100644 (file)
index 0000000..6124d39
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_MPIPE_SHM_DEF_H__
+#define __ARCH_MPIPE_SHM_DEF_H__
+#define MPIPE_EDMA_DESC_WORD1__C_VAL_UNCHAINED 0x0
+#define MPIPE_EDMA_DESC_WORD1__C_VAL_CHAINED 0x1
+#define MPIPE_EDMA_DESC_WORD1__C_VAL_NOT_RDY 0x2
+#define MPIPE_EDMA_DESC_WORD1__C_VAL_INVALID 0x3
+#endif /* !defined(__ARCH_MPIPE_SHM_DEF_H__) */
diff --git a/arch/tile/include/arch/trio.h b/arch/tile/include/arch/trio.h
new file mode 100644 (file)
index 0000000..d3000a8
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_H__
+#define __ARCH_TRIO_H__
+
+#include <arch/abi.h>
+#include <arch/trio_def.h>
+
+#ifndef __ASSEMBLER__
+
+/*
+ * Tile PIO Region Configuration - CFG Address Format.
+ * This register describes the address format for PIO accesses when the
+ * associated region is setup with TYPE=CFG.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /* Register Address (full byte address). */
+    uint_reg_t reg_addr     : 12;
+    /* Function Number */
+    uint_reg_t fn           : 3;
+    /* Device Number */
+    uint_reg_t dev          : 5;
+    /* BUS Number */
+    uint_reg_t bus          : 8;
+    /* Config Type: 0 for access to directly-attached device.  1 otherwise. */
+    uint_reg_t type         : 1;
+    /* Reserved. */
+    uint_reg_t __reserved_0 : 1;
+    /*
+     * MAC select.  This must match the configuration in
+     * TILE_PIO_REGION_SETUP.MAC.
+     */
+    uint_reg_t mac          : 2;
+    /* Reserved. */
+    uint_reg_t __reserved_1 : 32;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved_1 : 32;
+    uint_reg_t mac          : 2;
+    uint_reg_t __reserved_0 : 1;
+    uint_reg_t type         : 1;
+    uint_reg_t bus          : 8;
+    uint_reg_t dev          : 5;
+    uint_reg_t fn           : 3;
+    uint_reg_t reg_addr     : 12;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_TRIO_H__) */
diff --git a/arch/tile/include/arch/trio_constants.h b/arch/tile/include/arch/trio_constants.h
new file mode 100644 (file)
index 0000000..628b045
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+
+#ifndef __ARCH_TRIO_CONSTANTS_H__
+#define __ARCH_TRIO_CONSTANTS_H__
+
+#define TRIO_NUM_ASIDS 16
+#define TRIO_NUM_TLBS_PER_ASID 16
+
+#define TRIO_NUM_TPIO_REGIONS 8
+#define TRIO_LOG2_NUM_TPIO_REGIONS 3
+
+#define TRIO_NUM_MAP_MEM_REGIONS 16
+#define TRIO_LOG2_NUM_MAP_MEM_REGIONS 4
+#define TRIO_NUM_MAP_SQ_REGIONS 8
+#define TRIO_LOG2_NUM_MAP_SQ_REGIONS 3
+
+#define TRIO_LOG2_NUM_SQ_FIFO_ENTRIES 6
+
+#define TRIO_NUM_PUSH_DMA_RINGS 32
+
+#define TRIO_NUM_PULL_DMA_RINGS 32
+
+#endif /* __ARCH_TRIO_CONSTANTS_H__ */
diff --git a/arch/tile/include/arch/trio_def.h b/arch/tile/include/arch/trio_def.h
new file mode 100644 (file)
index 0000000..e805003
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_DEF_H__
+#define __ARCH_TRIO_DEF_H__
+#define TRIO_CFG_REGION_ADDR__REG_SHIFT 0
+#define TRIO_CFG_REGION_ADDR__INTFC_SHIFT 16
+#define TRIO_CFG_REGION_ADDR__INTFC_VAL_TRIO 0x0
+#define TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE 0x1
+#define TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD 0x2
+#define TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_PROTECTED 0x3
+#define TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT 18
+#define TRIO_CFG_REGION_ADDR__PROT_SHIFT 20
+#define TRIO_PIO_REGIONS_ADDR__REGION_SHIFT 32
+#define TRIO_MAP_MEM_REG_INT0 0x1000000000
+#define TRIO_MAP_MEM_REG_INT1 0x1000000008
+#define TRIO_MAP_MEM_REG_INT2 0x1000000010
+#define TRIO_MAP_MEM_REG_INT3 0x1000000018
+#define TRIO_MAP_MEM_REG_INT4 0x1000000020
+#define TRIO_MAP_MEM_REG_INT5 0x1000000028
+#define TRIO_MAP_MEM_REG_INT6 0x1000000030
+#define TRIO_MAP_MEM_REG_INT7 0x1000000038
+#define TRIO_MAP_MEM_LIM__ADDR_SHIFT 12
+#define TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_UNORDERED 0x0
+#define TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_STRICT 0x1
+#define TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_REL_ORD 0x2
+#define TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT 30
+#endif /* !defined(__ARCH_TRIO_DEF_H__) */
diff --git a/arch/tile/include/arch/trio_pcie_intfc.h b/arch/tile/include/arch/trio_pcie_intfc.h
new file mode 100644 (file)
index 0000000..0487fdb
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_PCIE_INTFC_H__
+#define __ARCH_TRIO_PCIE_INTFC_H__
+
+#include <arch/abi.h>
+#include <arch/trio_pcie_intfc_def.h>
+
+#ifndef __ASSEMBLER__
+
+/*
+ * Port Configuration.
+ * Configuration of the PCIe Port
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /* Provides the state of the strapping pins for this port. */
+    uint_reg_t strap_state      : 3;
+    /* Reserved. */
+    uint_reg_t __reserved_0     : 1;
+    /*
+     * When 1, the device type will be overridden using OVD_DEV_TYPE_VAL.
+     * When 0, the device type is determined based on the STRAP_STATE.
+     */
+    uint_reg_t ovd_dev_type     : 1;
+    /* Provides the device type when OVD_DEV_TYPE is 1. */
+    uint_reg_t ovd_dev_type_val : 4;
+    /* Determines how link is trained. */
+    uint_reg_t train_mode       : 2;
+    /* Reserved. */
+    uint_reg_t __reserved_1     : 1;
+    /*
+     * For PCIe, used to flip physical RX lanes that were not properly wired.
+     *  This is not the same as lane reversal which is handled automatically
+     * during link training.  When 0, RX Lane0 must be wired to the link
+     * partner (either to its Lane0 or it's LaneN).  When RX_LANE_FLIP is 1,
+     * the highest numbered lane for this port becomes Lane0 and Lane0 does
+     * NOT have to be wired to the link partner.
+     */
+    uint_reg_t rx_lane_flip     : 1;
+    /*
+     * For PCIe, used to flip physical TX lanes that were not properly wired.
+     *  This is not the same as lane reversal which is handled automatically
+     * during link training.  When 0, TX Lane0 must be wired to the link
+     * partner (either to its Lane0 or it's LaneN).  When TX_LANE_FLIP is 1,
+     * the highest numbered lane for this port becomes Lane0 and Lane0 does
+     * NOT have to be wired to the link partner.
+     */
+    uint_reg_t tx_lane_flip     : 1;
+    /*
+     * For StreamIO port, configures the width of the port when TRAIN_MODE is
+     * not STRAP.
+     */
+    uint_reg_t stream_width     : 2;
+    /*
+     * For StreamIO port, configures the rate of the port when TRAIN_MODE is
+     * not STRAP.
+     */
+    uint_reg_t stream_rate      : 2;
+    /* Reserved. */
+    uint_reg_t __reserved_2     : 46;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved_2     : 46;
+    uint_reg_t stream_rate      : 2;
+    uint_reg_t stream_width     : 2;
+    uint_reg_t tx_lane_flip     : 1;
+    uint_reg_t rx_lane_flip     : 1;
+    uint_reg_t __reserved_1     : 1;
+    uint_reg_t train_mode       : 2;
+    uint_reg_t ovd_dev_type_val : 4;
+    uint_reg_t ovd_dev_type     : 1;
+    uint_reg_t __reserved_0     : 1;
+    uint_reg_t strap_state      : 3;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_INTFC_PORT_CONFIG_t;
+
+/*
+ * Port Status.
+ * Status of the PCIe Port.  This register applies to the StreamIO port when
+ * StreamIO is enabled.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /*
+     * Indicates the DL state of the port.  When 1, the port is up and ready
+     * to receive traffic.
+     */
+    uint_reg_t dl_up        : 1;
+    /*
+     * Indicates the number of times the link has gone down.  Clears on read.
+     */
+    uint_reg_t dl_down_cnt  : 7;
+    /* Indicates the SERDES PLL has spun up and is providing a valid clock. */
+    uint_reg_t clock_ready  : 1;
+    /* Reserved. */
+    uint_reg_t __reserved_0 : 7;
+    /* Device revision ID. */
+    uint_reg_t device_rev   : 8;
+    /* Link state (PCIe). */
+    uint_reg_t ltssm_state  : 6;
+    /* Link power management state (PCIe). */
+    uint_reg_t pm_state     : 3;
+    /* Reserved. */
+    uint_reg_t __reserved_1 : 31;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved_1 : 31;
+    uint_reg_t pm_state     : 3;
+    uint_reg_t ltssm_state  : 6;
+    uint_reg_t device_rev   : 8;
+    uint_reg_t __reserved_0 : 7;
+    uint_reg_t clock_ready  : 1;
+    uint_reg_t dl_down_cnt  : 7;
+    uint_reg_t dl_up        : 1;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_INTFC_PORT_STATUS_t;
+
+/*
+ * Transmit FIFO Control.
+ * Contains TX FIFO thresholds.  These registers are for diagnostics purposes
+ * only.  Changing these values causes undefined behavior.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /*
+     * Almost-Empty level for TX0 data.  Typically set to at least
+     * roundup(38.0*M/N) where N=tclk frequency and M=MAC symbol rate in MHz
+     * for a x4 port (250MHz).
+     */
+    uint_reg_t tx0_data_ae_lvl : 7;
+    /* Reserved. */
+    uint_reg_t __reserved_0    : 1;
+    /* Almost-Empty level for TX1 data. */
+    uint_reg_t tx1_data_ae_lvl : 7;
+    /* Reserved. */
+    uint_reg_t __reserved_1    : 1;
+    /* Almost-Full level for TX0 data. */
+    uint_reg_t tx0_data_af_lvl : 7;
+    /* Reserved. */
+    uint_reg_t __reserved_2    : 1;
+    /* Almost-Full level for TX1 data. */
+    uint_reg_t tx1_data_af_lvl : 7;
+    /* Reserved. */
+    uint_reg_t __reserved_3    : 1;
+    /* Almost-Full level for TX0 info. */
+    uint_reg_t tx0_info_af_lvl : 5;
+    /* Reserved. */
+    uint_reg_t __reserved_4    : 3;
+    /* Almost-Full level for TX1 info. */
+    uint_reg_t tx1_info_af_lvl : 5;
+    /* Reserved. */
+    uint_reg_t __reserved_5    : 3;
+    /*
+     * This register provides performance adjustment for high bandwidth
+     * flows.  The MAC will assert almost-full to TRIO if non-posted credits
+     * fall below this level.  Note that setting this larger than the initial
+     * PORT_CREDIT.NPH value will cause READS to never be sent.  If the
+     * initial credit value from the link partner is smaller than this value
+     * when the link comes up, the value will be reset to the initial credit
+     * value to prevent lockup.
+     */
+    uint_reg_t min_np_credits  : 8;
+    /*
+     * This register provides performance adjustment for high bandwidth
+     * flows.  The MAC will assert almost-full to TRIO if posted credits fall
+     * below this level.  Note that setting this larger than the initial
+     * PORT_CREDIT.PH value will cause WRITES to never be sent.  If the
+     * initial credit value from the link partner is smaller than this value
+     * when the link comes up, the value will be reset to the initial credit
+     * value to prevent lockup.
+     */
+    uint_reg_t min_p_credits   : 8;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t min_p_credits   : 8;
+    uint_reg_t min_np_credits  : 8;
+    uint_reg_t __reserved_5    : 3;
+    uint_reg_t tx1_info_af_lvl : 5;
+    uint_reg_t __reserved_4    : 3;
+    uint_reg_t tx0_info_af_lvl : 5;
+    uint_reg_t __reserved_3    : 1;
+    uint_reg_t tx1_data_af_lvl : 7;
+    uint_reg_t __reserved_2    : 1;
+    uint_reg_t tx0_data_af_lvl : 7;
+    uint_reg_t __reserved_1    : 1;
+    uint_reg_t tx1_data_ae_lvl : 7;
+    uint_reg_t __reserved_0    : 1;
+    uint_reg_t tx0_data_ae_lvl : 7;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_INTFC_TX_FIFO_CTL_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_TRIO_PCIE_INTFC_H__) */
diff --git a/arch/tile/include/arch/trio_pcie_intfc_def.h b/arch/tile/include/arch/trio_pcie_intfc_def.h
new file mode 100644 (file)
index 0000000..d3fd678
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_PCIE_INTFC_DEF_H__
+#define __ARCH_TRIO_PCIE_INTFC_DEF_H__
+#define TRIO_PCIE_INTFC_MAC_INT_STS 0x0000
+#define TRIO_PCIE_INTFC_MAC_INT_STS__INT_LEVEL_MASK  0xf000
+#define TRIO_PCIE_INTFC_PORT_CONFIG 0x0018
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_DISABLED 0x0
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT 0x1
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC 0x2
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT_G1 0x3
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC_G1 0x4
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_XLINK 0x5
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_STREAM_X1 0x6
+#define TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_STREAM_X4 0x7
+#define TRIO_PCIE_INTFC_PORT_STATUS 0x0020
+#define TRIO_PCIE_INTFC_TX_FIFO_CTL 0x0050
+#endif /* !defined(__ARCH_TRIO_PCIE_INTFC_DEF_H__) */
diff --git a/arch/tile/include/arch/trio_pcie_rc.h b/arch/tile/include/arch/trio_pcie_rc.h
new file mode 100644 (file)
index 0000000..6a25d0a
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_PCIE_RC_H__
+#define __ARCH_TRIO_PCIE_RC_H__
+
+#include <arch/abi.h>
+#include <arch/trio_pcie_rc_def.h>
+
+#ifndef __ASSEMBLER__
+
+/* Device Capabilities Register. */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /*
+     * Max_Payload_Size Supported, writablethrough the MAC_STANDARD interface
+     */
+    uint_reg_t mps_sup                    : 3;
+    /*
+     * This field is writable through the MAC_STANDARD interface.  However,
+     * Phantom Function is not  supported. Therefore, the application must
+     * not write any value other than 0x0 to this  field.
+     */
+    uint_reg_t phantom_function_supported : 2;
+    /* This bit is writable through the MAC_STANDARD interface. */
+    uint_reg_t ext_tag_field_supported    : 1;
+    /* Reserved. */
+    uint_reg_t __reserved_0               : 3;
+    /* Endpoint L1 Acceptable Latency Must be 0x0 for non-Endpoint devices. */
+    uint_reg_t l1_lat                     : 3;
+    /*
+     * Undefined since PCI Express 1.1 (Was Attention Button Present for PCI
+     * Express 1.0a)
+     */
+    uint_reg_t r1                         : 1;
+    /*
+     * Undefined since PCI Express 1.1 (Was Attention Indicator Present for
+     * PCI  Express 1.0a)
+     */
+    uint_reg_t r2                         : 1;
+    /*
+     * Undefined since PCI Express 1.1 (Was Power Indicator Present for PCI
+     * Express 1.0a)
+     */
+    uint_reg_t r3                         : 1;
+    /*
+     * Role-Based Error Reporting, writable through the MAC_STANDARD
+     * interface.  Required to be set for device compliant to 1.1  spec and
+     * later.
+     */
+    uint_reg_t rer                        : 1;
+    /* Reserved. */
+    uint_reg_t __reserved_1               : 2;
+    /* Captured Slot Power Limit Value Upstream port only. */
+    uint_reg_t slot_pwr_lim               : 8;
+    /* Captured Slot Power Limit Scale Upstream port only. */
+    uint_reg_t slot_pwr_scale             : 2;
+    /* Reserved. */
+    uint_reg_t __reserved_2               : 4;
+    /* Endpoint L0s Acceptable LatencyMust be 0x0 for non-Endpoint devices. */
+    uint_reg_t l0s_lat                    : 1;
+    /* Reserved. */
+    uint_reg_t __reserved_3               : 31;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved_3               : 31;
+    uint_reg_t l0s_lat                    : 1;
+    uint_reg_t __reserved_2               : 4;
+    uint_reg_t slot_pwr_scale             : 2;
+    uint_reg_t slot_pwr_lim               : 8;
+    uint_reg_t __reserved_1               : 2;
+    uint_reg_t rer                        : 1;
+    uint_reg_t r3                         : 1;
+    uint_reg_t r2                         : 1;
+    uint_reg_t r1                         : 1;
+    uint_reg_t l1_lat                     : 3;
+    uint_reg_t __reserved_0               : 3;
+    uint_reg_t ext_tag_field_supported    : 1;
+    uint_reg_t phantom_function_supported : 2;
+    uint_reg_t mps_sup                    : 3;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_RC_DEVICE_CAP_t;
+
+/* Device Control Register. */
+
+__extension__
+typedef union
+{
+  struct
+  {
+#ifndef __BIG_ENDIAN__
+    /* Correctable Error Reporting Enable */
+    uint_reg_t cor_err_ena      : 1;
+    /* Non-Fatal Error Reporting Enable */
+    uint_reg_t nf_err_ena       : 1;
+    /* Fatal Error Reporting Enable */
+    uint_reg_t fatal_err_ena    : 1;
+    /* Unsupported Request Reporting Enable */
+    uint_reg_t ur_ena           : 1;
+    /* Relaxed orderring enable */
+    uint_reg_t ro_ena           : 1;
+    /* Max Payload Size */
+    uint_reg_t max_payload_size : 3;
+    /* Extended Tag Field Enable */
+    uint_reg_t ext_tag          : 1;
+    /* Phantom Function Enable */
+    uint_reg_t ph_fn_ena        : 1;
+    /* AUX Power PM Enable */
+    uint_reg_t aux_pm_ena       : 1;
+    /* Enable NoSnoop */
+    uint_reg_t no_snoop         : 1;
+    /* Max read request size */
+    uint_reg_t max_read_req_sz  : 3;
+    /* Reserved. */
+    uint_reg_t __reserved       : 49;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t __reserved       : 49;
+    uint_reg_t max_read_req_sz  : 3;
+    uint_reg_t no_snoop         : 1;
+    uint_reg_t aux_pm_ena       : 1;
+    uint_reg_t ph_fn_ena        : 1;
+    uint_reg_t ext_tag          : 1;
+    uint_reg_t max_payload_size : 3;
+    uint_reg_t ro_ena           : 1;
+    uint_reg_t ur_ena           : 1;
+    uint_reg_t fatal_err_ena    : 1;
+    uint_reg_t nf_err_ena       : 1;
+    uint_reg_t cor_err_ena      : 1;
+#endif
+  };
+
+  uint_reg_t word;
+} TRIO_PCIE_RC_DEVICE_CONTROL_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_TRIO_PCIE_RC_H__) */
diff --git a/arch/tile/include/arch/trio_pcie_rc_def.h b/arch/tile/include/arch/trio_pcie_rc_def.h
new file mode 100644 (file)
index 0000000..74081a6
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_PCIE_RC_DEF_H__
+#define __ARCH_TRIO_PCIE_RC_DEF_H__
+#define TRIO_PCIE_RC_DEVICE_CAP 0x0074
+#define TRIO_PCIE_RC_DEVICE_CONTROL 0x0078
+#define TRIO_PCIE_RC_DEVICE_ID_VEN_ID 0x0000
+#define TRIO_PCIE_RC_DEVICE_ID_VEN_ID__DEV_ID_SHIFT 16
+#define TRIO_PCIE_RC_REVISION_ID 0x0008
+#endif /* !defined(__ARCH_TRIO_PCIE_RC_DEF_H__) */
diff --git a/arch/tile/include/arch/trio_shm.h b/arch/tile/include/arch/trio_shm.h
new file mode 100644 (file)
index 0000000..3382e38
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+
+#ifndef __ARCH_TRIO_SHM_H__
+#define __ARCH_TRIO_SHM_H__
+
+#include <arch/abi.h>
+#include <arch/trio_shm_def.h>
+
+#ifndef __ASSEMBLER__
+/**
+ * TRIO DMA Descriptor.
+ * The TRIO DMA descriptor is written by software and consumed by hardware.
+ * It is used to specify the location of transaction data in the IO and Tile
+ * domains.
+ */
+
+__extension__
+typedef union
+{
+  struct
+  {
+    /* Word 0 */
+
+#ifndef __BIG_ENDIAN__
+    /** Tile side virtual address. */
+    int_reg_t va           : 42;
+    /**
+     * Encoded size of buffer used on push DMA when C=1:
+     * 0 = 128 bytes
+     * 1 = 256 bytes
+     * 2 = 512 bytes
+     * 3 = 1024 bytes
+     * 4 = 1664 bytes
+     * 5 = 4096 bytes
+     * 6 = 10368 bytes
+     * 7 = 16384 bytes
+     */
+    uint_reg_t bsz          : 3;
+    /**
+     * Chaining designation.  Always zero for pull DMA
+     * 0 : Unchained buffer pointer
+     * 1 : Chained buffer pointer.  Next buffer descriptor (e.g. VA) stored
+     * in 1st 8-bytes in buffer.  For chained buffers, first 8-bytes of each
+     * buffer contain the next buffer descriptor formatted exactly like a PDE
+     * buffer descriptor.  This allows a chained PDE buffer to be sent using
+     * push DMA.
+     */
+    uint_reg_t c            : 1;
+    /**
+     * Notification interrupt will be delivered when the transaction has
+     * completed (all data has been read from or written to the Tile-side
+     * buffer).
+     */
+    uint_reg_t notif        : 1;
+    /**
+     * When 0, the XSIZE field specifies the total byte count for the
+     * transaction.  When 1, the XSIZE field is encoded as 2^(N+14) for N in
+     * {0..6}:
+     * 0 = 16KB
+     * 1 = 32KB
+     * 2 = 64KB
+     * 3 = 128KB
+     * 4 = 256KB
+     * 5 = 512KB
+     * 6 = 1MB
+     * All other encodings of the XSIZE field are reserved when SMOD=1
+     */
+    uint_reg_t smod         : 1;
+    /**
+     * Total number of bytes to move for this transaction.   When SMOD=1,
+     * this field is encoded - see SMOD description.
+     */
+    uint_reg_t xsize        : 14;
+    /** Reserved. */
+    uint_reg_t __reserved_0 : 1;
+    /**
+     * Generation number.  Used to indicate a valid descriptor in ring.  When
+     * a new descriptor is written into the ring, software must toggle this
+     * bit.  The net effect is that the GEN bit being written into new
+     * descriptors toggles each time the ring tail pointer wraps.
+     */
+    uint_reg_t gen          : 1;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t gen          : 1;
+    uint_reg_t __reserved_0 : 1;
+    uint_reg_t xsize        : 14;
+    uint_reg_t smod         : 1;
+    uint_reg_t notif        : 1;
+    uint_reg_t c            : 1;
+    uint_reg_t bsz          : 3;
+    int_reg_t va           : 42;
+#endif
+
+    /* Word 1 */
+
+#ifndef __BIG_ENDIAN__
+    /** IO-side address */
+    uint_reg_t io_address : 64;
+#else   /* __BIG_ENDIAN__ */
+    uint_reg_t io_address : 64;
+#endif
+
+  };
+
+  /** Word access */
+  uint_reg_t words[2];
+} TRIO_DMA_DESC_t;
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_TRIO_SHM_H__) */
diff --git a/arch/tile/include/arch/trio_shm_def.h b/arch/tile/include/arch/trio_shm_def.h
new file mode 100644 (file)
index 0000000..72a59c8
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_TRIO_SHM_DEF_H__
+#define __ARCH_TRIO_SHM_DEF_H__
+#endif /* !defined(__ARCH_TRIO_SHM_DEF_H__) */
diff --git a/arch/tile/include/arch/usb_host.h b/arch/tile/include/arch/usb_host.h
new file mode 100644 (file)
index 0000000..d09f326
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_USB_HOST_H__
+#define __ARCH_USB_HOST_H__
+
+#include <arch/abi.h>
+#include <arch/usb_host_def.h>
+
+#ifndef __ASSEMBLER__
+#endif /* !defined(__ASSEMBLER__) */
+
+#endif /* !defined(__ARCH_USB_HOST_H__) */
diff --git a/arch/tile/include/arch/usb_host_def.h b/arch/tile/include/arch/usb_host_def.h
new file mode 100644 (file)
index 0000000..aeed775
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* Machine-generated file; do not edit. */
+
+#ifndef __ARCH_USB_HOST_DEF_H__
+#define __ARCH_USB_HOST_DEF_H__
+#endif /* !defined(__ARCH_USB_HOST_DEF_H__) */
index 143473e3a0bbae936da9347cafe91c53cad61304..fb7c65ae8de055f03a3245db759e914697c2b3f6 100644 (file)
@@ -9,7 +9,6 @@ header-y += hardwall.h
 generic-y += bug.h
 generic-y += bugs.h
 generic-y += cputime.h
-generic-y += device.h
 generic-y += div64.h
 generic-y += emergency-restart.h
 generic-y += errno.h
index 392e5333dd8b06a31afdd045298f273451ec4d2e..a9a529964e07d379b5c5ef1c9019e34498f71bae 100644 (file)
 #define L2_CACHE_ALIGN(x)      (((x)+(L2_CACHE_BYTES-1)) & -L2_CACHE_BYTES)
 
 /*
- * TILE-Gx is fully coherent so we don't need to define ARCH_DMA_MINALIGN.
+ * TILEPro I/O is not always coherent (networking typically uses coherent
+ * I/O, but PCI traffic does not) and setting ARCH_DMA_MINALIGN to the
+ * L2 cacheline size helps ensure that kernel heap allocations are aligned.
+ * TILE-Gx I/O is always coherent when used on hash-for-home pages.
+ *
+ * However, it's possible at runtime to request not to use hash-for-home
+ * for the kernel heap, in which case the kernel will use flush-and-inval
+ * to manage coherence.  As a result, we use L2_CACHE_BYTES for the
+ * DMA minimum alignment to avoid false sharing in the kernel heap.
  */
-#ifndef __tilegx__
 #define ARCH_DMA_MINALIGN      L2_CACHE_BYTES
-#endif
 
 /* use the cache line size for the L2, which is where it counts */
 #define SMP_CACHE_BYTES_SHIFT  L2_CACHE_SHIFT
index a120766c7264ce1b7e8ee7f9167ea1da23b11a72..b21a2fdec9f7acef9946b557f61690f2b4ecb7ac 100644 (file)
 __wsum do_csum(const unsigned char *buff, int len);
 #define do_csum do_csum
 
+/*
+ * Return the sum of all the 16-bit subwords in a long.
+ * This sums two subwords on a 32-bit machine, and four on 64 bits.
+ * The implementation does two vector adds to capture any overflow.
+ */
+static inline unsigned int csum_long(unsigned long x)
+{
+       unsigned long ret;
+#ifdef __tilegx__
+       ret = __insn_v2sadu(x, 0);
+       ret = __insn_v2sadu(ret, 0);
+#else
+       ret = __insn_sadh_u(x, 0);
+       ret = __insn_sadh_u(ret, 0);
+#endif
+       return ret;
+}
+
 #endif /* _ASM_TILE_CHECKSUM_H */
diff --git a/arch/tile/include/asm/device.h b/arch/tile/include/asm/device.h
new file mode 100644 (file)
index 0000000..5182705
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ * Arch specific extensions to struct device
+ */
+
+#ifndef _ASM_TILE_DEVICE_H
+#define _ASM_TILE_DEVICE_H
+
+struct dev_archdata {
+       /* DMA operations on that device */
+        struct dma_map_ops     *dma_ops;
+
+       /* Offset of the DMA address from the PA. */
+       dma_addr_t              dma_offset;
+
+       /* Highest DMA address that can be generated by this device. */
+       dma_addr_t              max_direct_dma_addr;
+};
+
+struct pdev_archdata {
+};
+
+#endif /* _ASM_TILE_DEVICE_H */
index eaa06d175b39d3af86d91f2761058ffb6fc1fc27..4b6247d1a315ae24331887a146758bcdbec8e570 100644 (file)
 #include <linux/cache.h>
 #include <linux/io.h>
 
-/*
- * Note that on x86 and powerpc, there is a "struct dma_mapping_ops"
- * that is used for all the DMA operations.  For now, we don't have an
- * equivalent on tile, because we only have a single way of doing DMA.
- * (Tilera bug 7994 to use dma_mapping_ops.)
- */
+extern struct dma_map_ops *tile_dma_map_ops;
+extern struct dma_map_ops *gx_pci_dma_map_ops;
+extern struct dma_map_ops *gx_legacy_pci_dma_map_ops;
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+       if (dev && dev->archdata.dma_ops)
+               return dev->archdata.dma_ops;
+       else
+               return tile_dma_map_ops;
+}
+
+static inline dma_addr_t get_dma_offset(struct device *dev)
+{
+       return dev->archdata.dma_offset;
+}
+
+static inline void set_dma_offset(struct device *dev, dma_addr_t off)
+{
+       dev->archdata.dma_offset = off;
+}
 
-#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
-#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
-
-extern dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
-                         enum dma_data_direction);
-extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
-                            size_t size, enum dma_data_direction);
-extern int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-              enum dma_data_direction);
-extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
-                        int nhwentries, enum dma_data_direction);
-extern dma_addr_t dma_map_page(struct device *dev, struct page *page,
-                              unsigned long offset, size_t size,
-                              enum dma_data_direction);
-extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
-                          size_t size, enum dma_data_direction);
-extern void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
-                               int nelems, enum dma_data_direction);
-extern void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
-                                  int nelems, enum dma_data_direction);
-
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
-                          dma_addr_t *dma_handle, gfp_t flag);
-
-void dma_free_coherent(struct device *dev, size_t size,
-                        void *vaddr, dma_addr_t dma_handle);
-
-extern void dma_sync_single_for_cpu(struct device *, dma_addr_t, size_t,
-                                   enum dma_data_direction);
-extern void dma_sync_single_for_device(struct device *, dma_addr_t,
-                                      size_t, enum dma_data_direction);
-extern void dma_sync_single_range_for_cpu(struct device *, dma_addr_t,
-                                         unsigned long offset, size_t,
-                                         enum dma_data_direction);
-extern void dma_sync_single_range_for_device(struct device *, dma_addr_t,
-                                            unsigned long offset, size_t,
-                                            enum dma_data_direction);
-extern void dma_cache_sync(struct device *dev, void *vaddr, size_t,
-                          enum dma_data_direction);
+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+       return paddr + get_dma_offset(dev);
+}
+
+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+       return daddr - get_dma_offset(dev);
+}
+
+static inline void dma_mark_clean(void *addr, size_t size) {}
+
+#include <asm-generic/dma-mapping-common.h>
+
+static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
+{
+       dev->archdata.dma_ops = ops;
+}
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+       if (!dev->dma_mask)
+               return 0;
+
+       return addr + size - 1 <= *dev->dma_mask;
+}
 
 static inline int
 dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
-       return 0;
+       return get_dma_ops(dev)->mapping_error(dev, dma_addr);
 }
 
 static inline int
 dma_supported(struct device *dev, u64 mask)
 {
-       return 1;
+       return get_dma_ops(dev)->dma_supported(dev, mask);
 }
 
 static inline int
 dma_set_mask(struct device *dev, u64 mask)
 {
+       struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+       /* Handle legacy PCI devices with limited memory addressability. */
+       if ((dma_ops == gx_pci_dma_map_ops) && (mask <= DMA_BIT_MASK(32))) {
+               set_dma_ops(dev, gx_legacy_pci_dma_map_ops);
+               set_dma_offset(dev, 0);
+               if (mask > dev->archdata.max_direct_dma_addr)
+                       mask = dev->archdata.max_direct_dma_addr;
+       }
+
        if (!dev->dma_mask || !dma_supported(dev, mask))
                return -EIO;
 
@@ -91,4 +102,43 @@ dma_set_mask(struct device *dev, u64 mask)
        return 0;
 }
 
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+                                   dma_addr_t *dma_handle, gfp_t flag,
+                                   struct dma_attrs *attrs)
+{
+       struct dma_map_ops *dma_ops = get_dma_ops(dev);
+       void *cpu_addr;
+
+       cpu_addr = dma_ops->alloc(dev, size, dma_handle, flag, attrs);
+
+       debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
+
+       return cpu_addr;
+}
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+                                 void *cpu_addr, dma_addr_t dma_handle,
+                                 struct dma_attrs *attrs)
+{
+       struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+       debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+
+       dma_ops->free(dev, size, cpu_addr, dma_handle, attrs);
+}
+
+#define dma_alloc_coherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
+#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_attrs(d, s, h, f, NULL)
+#define dma_free_coherent(d, s, v, h) dma_free_attrs(d, s, v, h, NULL)
+#define dma_free_noncoherent(d, s, v, h) dma_free_attrs(d, s, v, h, NULL)
+
+/*
+ * dma_alloc_noncoherent() is #defined to return coherent memory,
+ * so there's no need to do any flushing here.
+ */
+static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
+                                 enum dma_data_direction direction)
+{
+}
+
 #endif /* _ASM_TILE_DMA_MAPPING_H */
index c66f7933beaa0952c31601c17559a7eaa83206c2..e16dbf929cb549c0cc344415cf0f561f57f2ba8f 100644 (file)
  *
  * TLB entries of such buffers will not be flushed across
  * task switches.
- *
- * We don't bother with a FIX_HOLE since above the fixmaps
- * is unmapped memory in any case.
  */
 enum fixed_addresses {
+#ifdef __tilegx__
+       /*
+        * TILEPro has unmapped memory above so the hole isn't needed,
+        * and in any case the hole pushes us over a single 16MB pmd.
+        */
+       FIX_HOLE,
+#endif
 #ifdef CONFIG_HIGHMEM
        FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
        FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+#endif
+#ifdef __tilegx__  /* see homecache.c */
+       FIX_HOMECACHE_BEGIN,
+       FIX_HOMECACHE_END = FIX_HOMECACHE_BEGIN+(NR_CPUS)-1,
 #endif
        __end_of_permanent_fixed_addresses,
 
index a8243865d49ee7b7248dc1389e23fe317f6fecef..7b777132864293aac11e15bf81b7141f1d63b498 100644 (file)
@@ -79,10 +79,17 @@ extern void homecache_change_page_home(struct page *, int order, int home);
 /*
  * Flush a page out of whatever cache(s) it is in.
  * This is more than just finv, since it properly handles waiting
- * for the data to reach memory on tilepro, but it can be quite
- * heavyweight, particularly on hash-for-home memory.
+ * for the data to reach memory, but it can be quite
+ * heavyweight, particularly on incoherent or immutable memory.
  */
-extern void homecache_flush_cache(struct page *, int order);
+extern void homecache_finv_page(struct page *);
+
+/*
+ * Flush a page out of the specified home cache.
+ * Note that the specified home need not be the actual home of the page,
+ * as for example might be the case when coordinating with I/O devices.
+ */
+extern void homecache_finv_map_page(struct page *, int home);
 
 /*
  * Allocate a page with the given GFP flags, home, and optionally
@@ -104,10 +111,10 @@ extern struct page *homecache_alloc_pages_node(int nid, gfp_t gfp_mask,
  * routines use homecache_change_page_home() to reset the home
  * back to the default before returning the page to the allocator.
  */
+void __homecache_free_pages(struct page *, unsigned int order);
 void homecache_free_pages(unsigned long addr, unsigned int order);
-#define homecache_free_page(page) \
-  homecache_free_pages((page), 0)
-
+#define __homecache_free_page(page) __homecache_free_pages((page), 0)
+#define homecache_free_page(page) homecache_free_pages((page), 0)
 
 
 /*
index d2152deb1f3cf6a3bc352d92d445df4157a0924e..2a9b293fece6c00f2c71d8c5829340bb842970e5 100644 (file)
@@ -62,6 +62,92 @@ extern void iounmap(volatile void __iomem *addr);
 #define mm_ptov(addr)          ((void *)phys_to_virt(addr))
 #define mm_vtop(addr)          ((unsigned long)virt_to_phys(addr))
 
+#if CHIP_HAS_MMIO()
+
+/*
+ * We use inline assembly to guarantee that the compiler does not
+ * split an access into multiple byte-sized accesses as it might
+ * sometimes do if a register data structure is marked "packed".
+ * Obviously on tile we can't tolerate such an access being
+ * actually unaligned, but we want to avoid the case where the
+ * compiler conservatively would generate multiple accesses even
+ * for an aligned read or write.
+ */
+
+static inline u8 __raw_readb(const volatile void __iomem *addr)
+{
+       return *(const volatile u8 __force *)addr;
+}
+
+static inline u16 __raw_readw(const volatile void __iomem *addr)
+{
+       u16 ret;
+       asm volatile("ld2u %0, %1" : "=r" (ret) : "r" (addr));
+       barrier();
+       return le16_to_cpu(ret);
+}
+
+static inline u32 __raw_readl(const volatile void __iomem *addr)
+{
+       u32 ret;
+       /* Sign-extend to conform to u32 ABI sign-extension convention. */
+       asm volatile("ld4s %0, %1" : "=r" (ret) : "r" (addr));
+       barrier();
+       return le32_to_cpu(ret);
+}
+
+static inline u64 __raw_readq(const volatile void __iomem *addr)
+{
+       u64 ret;
+       asm volatile("ld %0, %1" : "=r" (ret) : "r" (addr));
+       barrier();
+       return le64_to_cpu(ret);
+}
+
+static inline void __raw_writeb(u8 val, volatile void __iomem *addr)
+{
+       *(volatile u8 __force *)addr = val;
+}
+
+static inline void __raw_writew(u16 val, volatile void __iomem *addr)
+{
+       asm volatile("st2 %0, %1" :: "r" (addr), "r" (cpu_to_le16(val)));
+}
+
+static inline void __raw_writel(u32 val, volatile void __iomem *addr)
+{
+       asm volatile("st4 %0, %1" :: "r" (addr), "r" (cpu_to_le32(val)));
+}
+
+static inline void __raw_writeq(u64 val, volatile void __iomem *addr)
+{
+       asm volatile("st %0, %1" :: "r" (addr), "r" (cpu_to_le64(val)));
+}
+
+/*
+ * The on-chip I/O hardware on tilegx is configured with VA=PA for the
+ * kernel's PA range.  The low-level APIs and field names use "va" and
+ * "void *" nomenclature, to be consistent with the general notion
+ * that the addresses in question are virtualizable, but in the kernel
+ * context we are actually manipulating PA values.  (In other contexts,
+ * e.g. access from user space, we do in fact use real virtual addresses
+ * in the va fields.)  To allow readers of the code to understand what's
+ * happening, we direct their attention to this comment by using the
+ * following two functions that just duplicate __va() and __pa().
+ */
+typedef unsigned long tile_io_addr_t;
+static inline tile_io_addr_t va_to_tile_io_addr(void *va)
+{
+       BUILD_BUG_ON(sizeof(phys_addr_t) != sizeof(tile_io_addr_t));
+       return __pa(va);
+}
+static inline void *tile_io_addr_to_va(tile_io_addr_t tile_io_addr)
+{
+       return __va(tile_io_addr);
+}
+
+#else /* CHIP_HAS_MMIO() */
+
 #ifdef CONFIG_PCI
 
 extern u8 _tile_readb(unsigned long addr);
@@ -73,10 +159,19 @@ extern void _tile_writew(u16 val, unsigned long addr);
 extern void _tile_writel(u32 val, unsigned long addr);
 extern void _tile_writeq(u64 val, unsigned long addr);
 
-#else
+#define __raw_readb(addr) _tile_readb((unsigned long)addr)
+#define __raw_readw(addr) _tile_readw((unsigned long)addr)
+#define __raw_readl(addr) _tile_readl((unsigned long)addr)
+#define __raw_readq(addr) _tile_readq((unsigned long)addr)
+#define __raw_writeb(val, addr) _tile_writeb(val, (unsigned long)addr)
+#define __raw_writew(val, addr) _tile_writew(val, (unsigned long)addr)
+#define __raw_writel(val, addr) _tile_writel(val, (unsigned long)addr)
+#define __raw_writeq(val, addr) _tile_writeq(val, (unsigned long)addr)
+
+#else /* CONFIG_PCI */
 
 /*
- * The Tile architecture does not support IOMEM unless PCI is enabled.
+ * The tilepro architecture does not support IOMEM unless PCI is enabled.
  * Unfortunately we can't yet simply not declare these methods,
  * since some generic code that compiles into the kernel, but
  * we never run, uses them unconditionally.
@@ -88,65 +183,58 @@ static inline int iomem_panic(void)
        return 0;
 }
 
-static inline u8 _tile_readb(unsigned long addr)
+static inline u8 readb(unsigned long addr)
 {
        return iomem_panic();
 }
 
-static inline u16 _tile_readw(unsigned long addr)
+static inline u16 _readw(unsigned long addr)
 {
        return iomem_panic();
 }
 
-static inline u32 _tile_readl(unsigned long addr)
+static inline u32 readl(unsigned long addr)
 {
        return iomem_panic();
 }
 
-static inline u64 _tile_readq(unsigned long addr)
+static inline u64 readq(unsigned long addr)
 {
        return iomem_panic();
 }
 
-static inline void _tile_writeb(u8  val, unsigned long addr)
+static inline void writeb(u8  val, unsigned long addr)
 {
        iomem_panic();
 }
 
-static inline void _tile_writew(u16 val, unsigned long addr)
+static inline void writew(u16 val, unsigned long addr)
 {
        iomem_panic();
 }
 
-static inline void _tile_writel(u32 val, unsigned long addr)
+static inline void writel(u32 val, unsigned long addr)
 {
        iomem_panic();
 }
 
-static inline void _tile_writeq(u64 val, unsigned long addr)
+static inline void writeq(u64 val, unsigned long addr)
 {
        iomem_panic();
 }
 
-#endif
+#endif /* CONFIG_PCI */
+
+#endif /* CHIP_HAS_MMIO() */
 
-#define readb(addr) _tile_readb((unsigned long)addr)
-#define readw(addr) _tile_readw((unsigned long)addr)
-#define readl(addr) _tile_readl((unsigned long)addr)
-#define readq(addr) _tile_readq((unsigned long)addr)
-#define writeb(val, addr) _tile_writeb(val, (unsigned long)addr)
-#define writew(val, addr) _tile_writew(val, (unsigned long)addr)
-#define writel(val, addr) _tile_writel(val, (unsigned long)addr)
-#define writeq(val, addr) _tile_writeq(val, (unsigned long)addr)
-
-#define __raw_readb readb
-#define __raw_readw readw
-#define __raw_readl readl
-#define __raw_readq readq
-#define __raw_writeb writeb
-#define __raw_writew writew
-#define __raw_writel writel
-#define __raw_writeq writeq
+#define readb __raw_readb
+#define readw __raw_readw
+#define readl __raw_readl
+#define readq __raw_readq
+#define writeb __raw_writeb
+#define writew __raw_writew
+#define writel __raw_writel
+#define writeq __raw_writeq
 
 #define readb_relaxed readb
 #define readw_relaxed readw
diff --git a/arch/tile/include/asm/memprof.h b/arch/tile/include/asm/memprof.h
deleted file mode 100644 (file)
index 359949b..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2010 Tilera 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
- *   as published by the Free Software Foundation, version 2.
- *
- *   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, GOOD TITLE or
- *   NON INFRINGEMENT.  See the GNU General Public License for
- *   more details.
- *
- * The hypervisor's memory controller profiling infrastructure allows
- * the programmer to find out what fraction of the available memory
- * bandwidth is being consumed at each memory controller.  The
- * profiler provides start, stop, and clear operations to allows
- * profiling over a specific time window, as well as an interface for
- * reading the most recent profile values.
- *
- * This header declares IOCTL codes necessary to control memprof.
- */
-#ifndef _ASM_TILE_MEMPROF_H
-#define _ASM_TILE_MEMPROF_H
-
-#include <linux/ioctl.h>
-
-#define MEMPROF_IOCTL_TYPE 0xB4
-#define MEMPROF_IOCTL_START _IO(MEMPROF_IOCTL_TYPE, 0)
-#define MEMPROF_IOCTL_STOP _IO(MEMPROF_IOCTL_TYPE, 1)
-#define MEMPROF_IOCTL_CLEAR _IO(MEMPROF_IOCTL_TYPE, 2)
-
-#endif /* _ASM_TILE_MEMPROF_H */
index 9d9131e5c5529fbb67aee9d19d9dcab6e81f6c68..dd033a4fd627ce5d08b52477b7f3d9ca2723a513 100644 (file)
@@ -174,7 +174,9 @@ static inline __attribute_const__ int get_order(unsigned long size)
 #define MEM_LOW_END            (HALF_VA_SPACE - 1)         /* low half */
 #define MEM_HIGH_START         (-HALF_VA_SPACE)            /* high half */
 #define PAGE_OFFSET            MEM_HIGH_START
-#define _VMALLOC_START         _AC(0xfffffff500000000, UL) /* 4 GB */
+#define FIXADDR_BASE           _AC(0xfffffff400000000, UL) /* 4 GB */
+#define FIXADDR_TOP            _AC(0xfffffff500000000, UL) /* 4 GB */
+#define _VMALLOC_START         FIXADDR_TOP
 #define HUGE_VMAP_BASE         _AC(0xfffffff600000000, UL) /* 4 GB */
 #define MEM_SV_START           _AC(0xfffffff700000000, UL) /* 256 MB */
 #define MEM_SV_INTRPT          MEM_SV_START
@@ -185,9 +187,6 @@ static inline __attribute_const__ int get_order(unsigned long size)
 /* Highest DTLB address we will use */
 #define KERNEL_HIGH_VADDR      MEM_SV_START
 
-/* Since we don't currently provide any fixmaps, we use an impossible VA. */
-#define FIXADDR_TOP             MEM_HV_START
-
 #else /* !__tilegx__ */
 
 /*
index 32e6cbe8dff3350d1d7e236691fced9a47bd2c8d..302cdf71ceed044811731e212f5d499807a38d11 100644 (file)
 #ifndef _ASM_TILE_PCI_H
 #define _ASM_TILE_PCI_H
 
+#include <linux/dma-mapping.h>
 #include <linux/pci.h>
+#include <linux/numa.h>
 #include <asm-generic/pci_iomap.h>
 
+#ifndef __tilegx__
+
 /*
  * Structure of a PCI controller (host bridge)
  */
@@ -40,6 +44,16 @@ struct pci_controller {
        struct resource mem_resources[3];
 };
 
+/*
+ * This flag tells if the platform is TILEmpower that needs
+ * special configuration for the PLX switch chip.
+ */
+extern int tile_plx_gen1;
+
+static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {}
+
+#define        TILE_NUM_PCIE   2
+
 /*
  * The hypervisor maps the entirety of CPA-space as bus addresses, so
  * bus addresses are physical addresses.  The networking and block
@@ -47,15 +61,135 @@ struct pci_controller {
  */
 #define PCI_DMA_BUS_IS_PHYS     1
 
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
+#else
+
+#include <asm/page.h>
+#include <gxio/trio.h>
+
+/**
+ * We reserve the hugepage-size address range at the top of the 64-bit address
+ * space to serve as the PCI window, emulating the BAR0 space of an endpoint
+ * device. This window is used by the chip-to-chip applications running on
+ * the RC node. The reason for carving out this window is that Mem-Maps that
+ * back up this window will not overlap with those that map the real physical
+ * memory.
+ */
+#define PCIE_HOST_BAR0_SIZE            HPAGE_SIZE
+#define PCIE_HOST_BAR0_START           HPAGE_MASK
+
+/**
+ * The first PAGE_SIZE of the above "BAR" window is mapped to the
+ * gxpci_host_regs structure.
+ */
+#define PCIE_HOST_REGS_SIZE            PAGE_SIZE
+
+/*
+ * This is the PCI address where the Mem-Map interrupt regions start.
+ * We use the 2nd to the last huge page of the 64-bit address space.
+ * The last huge page is used for the rootcomplex "bar", for C2C purpose.
+ */
+#define        MEM_MAP_INTR_REGIONS_BASE       (HPAGE_MASK - HPAGE_SIZE)
+
+/*
+ * Each Mem-Map interrupt region occupies 4KB.
+ */
+#define        MEM_MAP_INTR_REGION_SIZE        (1 << TRIO_MAP_MEM_LIM__ADDR_SHIFT)
+
+/*
+ * Allocate the PCI BAR window right below 4GB.
+ */
+#define        TILE_PCI_BAR_WINDOW_TOP         (1ULL << 32)
+
+/*
+ * Allocate 1GB for the PCI BAR window.
+ */
+#define        TILE_PCI_BAR_WINDOW_SIZE        (1 << 30)
+
+/*
+ * This is the highest bus address targeting the host memory that
+ * can be generated by legacy PCI devices with 32-bit or less
+ * DMA capability, dictated by the BAR window size and location.
+ */
+#define        TILE_PCI_MAX_DIRECT_DMA_ADDRESS \
+       (TILE_PCI_BAR_WINDOW_TOP - TILE_PCI_BAR_WINDOW_SIZE - 1)
+
+/*
+ * We shift the PCI bus range for all the physical memory up by the whole PA
+ * range. The corresponding CPA of an incoming PCI request will be the PCI
+ * address minus TILE_PCI_MEM_MAP_BASE_OFFSET. This also implies
+ * that the 64-bit capable devices will be given DMA addresses as
+ * the CPA plus TILE_PCI_MEM_MAP_BASE_OFFSET. To support 32-bit
+ * devices, we create a separate map region that handles the low
+ * 4GB.
+ */
+#define        TILE_PCI_MEM_MAP_BASE_OFFSET    (1ULL << CHIP_PA_WIDTH())
+
+/*
+ * Start of the PCI memory resource, which starts at the end of the
+ * maximum system physical RAM address.
+ */
+#define        TILE_PCI_MEM_START      (1ULL << CHIP_PA_WIDTH())
+
+/*
+ * Structure of a PCI controller (host bridge) on Gx.
+ */
+struct pci_controller {
+
+       /* Pointer back to the TRIO that this PCIe port is connected to. */
+       gxio_trio_context_t *trio;
+       int mac;                /* PCIe mac index on the TRIO shim */
+       int trio_index;         /* Index of TRIO shim that contains the MAC. */
+
+       int pio_mem_index;      /* PIO region index for memory access */
+
+       /*
+        * Mem-Map regions for all the memory controllers so that Linux can
+        * map all of its physical memory space to the PCI bus.
+        */
+       int mem_maps[MAX_NUMNODES];
+
+       int index;              /* PCI domain number */
+       struct pci_bus *root_bus;
+
+       /* PCI memory space resource for this controller. */
+       struct resource mem_space;
+       char mem_space_name[32];
+
+       uint64_t mem_offset;    /* cpu->bus memory mapping offset. */
+
+       int first_busno;
+
+       struct pci_ops *ops;
+
+       /* Table that maps the INTx numbers to Linux irq numbers. */
+       int irq_intx_table[4];
+
+       /* Address ranges that are routed to this controller/bridge. */
+       struct resource mem_resources[3];
+};
+
+extern struct pci_controller pci_controllers[TILEGX_NUM_TRIO * TILEGX_TRIO_PCIES];
+extern gxio_trio_context_t trio_contexts[TILEGX_NUM_TRIO];
+
+extern void pci_iounmap(struct pci_dev *dev, void __iomem *);
+
+/*
+ * The PCI address space does not equal the physical memory address
+ * space (we have an IOMMU). The IDE and SCSI device layers use this
+ * boolean for bounce buffer decisions.
+ */
+#define PCI_DMA_BUS_IS_PHYS     0
+
+#endif /* __tilegx__ */
+
 int __init tile_pci_init(void);
 int __init pcibios_init(void);
 
-static inline void pci_iounmap(struct pci_dev *dev, void __iomem *addr) {}
-
 void __devinit pcibios_fixup_bus(struct pci_bus *bus);
 
-#define        TILE_NUM_PCIE   2
-
 #define pci_domain_nr(bus) (((struct pci_controller *)(bus)->sysdata)->index)
 
 /*
@@ -79,19 +213,10 @@ static inline int pcibios_assign_all_busses(void)
 #define PCIBIOS_MIN_MEM                0
 #define PCIBIOS_MIN_IO         0
 
-/*
- * This flag tells if the platform is TILEmpower that needs
- * special configuration for the PLX switch chip.
- */
-extern int tile_plx_gen1;
-
 /* Use any cpu for PCI. */
 #define cpumask_of_pcibus(bus) cpu_online_mask
 
 /* implement the pci_ DMA API in terms of the generic device dma_ one */
 #include <asm-generic/pci-dma-compat.h>
 
-/* generic pci stuff */
-#include <asm-generic/pci.h>
-
 #endif /* _ASM_TILE_PCI_H */
diff --git a/arch/tile/include/gxio/common.h b/arch/tile/include/gxio/common.h
new file mode 100644 (file)
index 0000000..724595a
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#ifndef _GXIO_COMMON_H_
+#define _GXIO_COMMON_H_
+
+/*
+ * Routines shared between the various GXIO device components.
+ */
+
+#include <hv/iorpc.h>
+
+#include <linux/types.h>
+#include <linux/compiler.h>
+#include <linux/io.h>
+
+/* Define the standard gxio MMIO functions using kernel functions. */
+#define __gxio_mmio_read8(addr)                readb(addr)
+#define __gxio_mmio_read16(addr)       readw(addr)
+#define __gxio_mmio_read32(addr)       readl(addr)
+#define __gxio_mmio_read64(addr)       readq(addr)
+#define __gxio_mmio_write8(addr, val)  writeb((val), (addr))
+#define __gxio_mmio_write16(addr, val) writew((val), (addr))
+#define __gxio_mmio_write32(addr, val) writel((val), (addr))
+#define __gxio_mmio_write64(addr, val) writeq((val), (addr))
+#define __gxio_mmio_read(addr)         __gxio_mmio_read64(addr)
+#define __gxio_mmio_write(addr, val)   __gxio_mmio_write64((addr), (val))
+
+#endif /* !_GXIO_COMMON_H_ */
diff --git a/arch/tile/include/gxio/dma_queue.h b/arch/tile/include/gxio/dma_queue.h
new file mode 100644 (file)
index 0000000..00654fe
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#ifndef _GXIO_DMA_QUEUE_H_
+#define _GXIO_DMA_QUEUE_H_
+
+/*
+ * DMA queue management APIs shared between TRIO and mPIPE.
+ */
+
+#include "common.h"
+
+/* The credit counter lives in the high 32 bits. */
+#define DMA_QUEUE_CREDIT_SHIFT 32
+
+/*
+ * State object that tracks a DMA queue's head and tail indices, as
+ * well as the number of commands posted and completed.  The
+ * structure is accessed via a thread-safe, lock-free algorithm.
+ */
+typedef struct {
+       /*
+        * Address of a MPIPE_EDMA_POST_REGION_VAL_t,
+        * TRIO_PUSH_DMA_REGION_VAL_t, or TRIO_PULL_DMA_REGION_VAL_t
+        * register.  These register have identical encodings and provide
+        * information about how many commands have been processed.
+        */
+       void *post_region_addr;
+
+       /*
+        * A lazily-updated count of how many edescs the hardware has
+        * completed.
+        */
+       uint64_t hw_complete_count __attribute__ ((aligned(64)));
+
+       /*
+        * High 32 bits are a count of available egress command credits,
+        * low 24 bits are the next egress "slot".
+        */
+       int64_t credits_and_next_index;
+
+} __gxio_dma_queue_t;
+
+/* Initialize a dma queue. */
+extern void __gxio_dma_queue_init(__gxio_dma_queue_t *dma_queue,
+                                 void *post_region_addr,
+                                 unsigned int num_entries);
+
+/*
+ * Update the "credits_and_next_index" and "hw_complete_count" fields
+ * based on pending hardware completions.  Note that some other thread
+ * may have already done this and, importantly, may still be in the
+ * process of updating "credits_and_next_index".
+ */
+extern void __gxio_dma_queue_update_credits(__gxio_dma_queue_t *dma_queue);
+
+/* Wait for credits to become available. */
+extern int64_t __gxio_dma_queue_wait_for_credits(__gxio_dma_queue_t *dma_queue,
+                                                int64_t modifier);
+
+/* Reserve slots in the queue, optionally waiting for slots to become
+ * available, and optionally returning a "completion_slot" suitable for
+ * direct comparison to "hw_complete_count".
+ */
+static inline int64_t __gxio_dma_queue_reserve(__gxio_dma_queue_t *dma_queue,
+                                              unsigned int num, bool wait,
+                                              bool completion)
+{
+       uint64_t slot;
+
+       /*
+        * Try to reserve 'num' egress command slots.  We do this by
+        * constructing a constant that subtracts N credits and adds N to
+        * the index, and using fetchaddgez to only apply it if the credits
+        * count doesn't go negative.
+        */
+       int64_t modifier = (((int64_t)(-num)) << DMA_QUEUE_CREDIT_SHIFT) | num;
+       int64_t old =
+               __insn_fetchaddgez(&dma_queue->credits_and_next_index,
+                                  modifier);
+
+       if (unlikely(old + modifier < 0)) {
+               /*
+                * We're out of credits.  Try once to get more by checking for
+                * completed egress commands.  If that fails, wait or fail.
+                */
+               __gxio_dma_queue_update_credits(dma_queue);
+               old = __insn_fetchaddgez(&dma_queue->credits_and_next_index,
+                                        modifier);
+               if (old + modifier < 0) {
+                       if (wait)
+                               old = __gxio_dma_queue_wait_for_credits
+                                       (dma_queue, modifier);
+                       else
+                               return GXIO_ERR_DMA_CREDITS;
+               }
+       }
+
+       /* The bottom 24 bits of old encode the "slot". */
+       slot = (old & 0xffffff);
+
+       if (completion) {
+               /*
+                * A "completion_slot" is a "slot" which can be compared to
+                * "hw_complete_count" at any time in the future.  To convert
+                * "slot" into a "completion_slot", we access "hw_complete_count"
+                * once (knowing that we have reserved a slot, and thus, it will
+                * be "basically" accurate), and combine its high 40 bits with
+                * the 24 bit "slot", and handle "wrapping" by adding "1 << 24"
+                * if the result is LESS than "hw_complete_count".
+                */
+               uint64_t complete;
+               complete = ACCESS_ONCE(dma_queue->hw_complete_count);
+               slot |= (complete & 0xffffffffff000000);
+               if (slot < complete)
+                       slot += 0x1000000;
+       }
+
+       /*
+        * If any of our slots mod 256 were equivalent to 0, go ahead and
+        * collect some egress credits, and update "hw_complete_count", and
+        * make sure the index doesn't overflow into the credits.
+        */
+       if (unlikely(((old + num) & 0xff) < num)) {
+               __gxio_dma_queue_update_credits(dma_queue);
+
+               /* Make sure the index doesn't overflow into the credits. */
+#ifdef __BIG_ENDIAN__
+               *(((uint8_t *)&dma_queue->credits_and_next_index) + 4) = 0;
+#else
+               *(((uint8_t *)&dma_queue->credits_and_next_index) + 3) = 0;
+#endif
+       }
+
+       return slot;
+}
+
+/* Non-inlinable "__gxio_dma_queue_reserve(..., true)". */
+extern int64_t __gxio_dma_queue_reserve_aux(__gxio_dma_queue_t *dma_queue,
+                                           unsigned int num, int wait);
+
+/* Check whether a particular "completion slot" has completed.
+ *
+ * Note that this function requires a "completion slot", and thus
+ * cannot be used with the result of any "reserve_fast" function.
+ */
+extern int __gxio_dma_queue_is_complete(__gxio_dma_queue_t *dma_queue,
+                                       int64_t completion_slot, int update);
+
+#endif /* !_GXIO_DMA_QUEUE_H_ */
diff --git a/arch/tile/include/gxio/iorpc_globals.h b/arch/tile/include/gxio/iorpc_globals.h
new file mode 100644 (file)
index 0000000..52c721f
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* This file is machine-generated; DO NOT EDIT! */
+#ifndef __IORPC_LINUX_RPC_H__
+#define __IORPC_LINUX_RPC_H__
+
+#include <hv/iorpc.h>
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <asm/pgtable.h>
+
+#define IORPC_OP_ARM_POLLFD            IORPC_OPCODE(IORPC_FORMAT_KERNEL_POLLFD, 0x9000)
+#define IORPC_OP_CLOSE_POLLFD          IORPC_OPCODE(IORPC_FORMAT_KERNEL_POLLFD, 0x9001)
+#define IORPC_OP_GET_MMIO_BASE         IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
+#define IORPC_OP_CHECK_MMIO_OFFSET     IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
+
+int __iorpc_arm_pollfd(int fd, int pollfd_cookie);
+
+int __iorpc_close_pollfd(int fd, int pollfd_cookie);
+
+int __iorpc_get_mmio_base(int fd, HV_PTE *base);
+
+int __iorpc_check_mmio_offset(int fd, unsigned long offset, unsigned long size);
+
+#endif /* !__IORPC_LINUX_RPC_H__ */
diff --git a/arch/tile/include/gxio/iorpc_mpipe.h b/arch/tile/include/gxio/iorpc_mpipe.h
new file mode 100644 (file)
index 0000000..9d50fce
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* This file is machine-generated; DO NOT EDIT! */
+#ifndef __GXIO_MPIPE_LINUX_RPC_H__
+#define __GXIO_MPIPE_LINUX_RPC_H__
+
+#include <hv/iorpc.h>
+
+#include <hv/drv_mpipe_intf.h>
+#include <asm/page.h>
+#include <gxio/kiorpc.h>
+#include <gxio/mpipe.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <asm/pgtable.h>
+
+#define GXIO_MPIPE_OP_ALLOC_BUFFER_STACKS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1200)
+#define GXIO_MPIPE_OP_INIT_BUFFER_STACK_AUX IORPC_OPCODE(IORPC_FORMAT_KERNEL_MEM, 0x1201)
+
+#define GXIO_MPIPE_OP_ALLOC_NOTIF_RINGS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1203)
+#define GXIO_MPIPE_OP_INIT_NOTIF_RING_AUX IORPC_OPCODE(IORPC_FORMAT_KERNEL_MEM, 0x1204)
+#define GXIO_MPIPE_OP_REQUEST_NOTIF_RING_INTERRUPT IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1205)
+#define GXIO_MPIPE_OP_ENABLE_NOTIF_RING_INTERRUPT IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1206)
+#define GXIO_MPIPE_OP_ALLOC_NOTIF_GROUPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1207)
+#define GXIO_MPIPE_OP_INIT_NOTIF_GROUP IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1208)
+#define GXIO_MPIPE_OP_ALLOC_BUCKETS    IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1209)
+#define GXIO_MPIPE_OP_INIT_BUCKET      IORPC_OPCODE(IORPC_FORMAT_NONE, 0x120a)
+#define GXIO_MPIPE_OP_ALLOC_EDMA_RINGS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x120b)
+#define GXIO_MPIPE_OP_INIT_EDMA_RING_AUX IORPC_OPCODE(IORPC_FORMAT_KERNEL_MEM, 0x120c)
+
+#define GXIO_MPIPE_OP_COMMIT_RULES     IORPC_OPCODE(IORPC_FORMAT_NONE, 0x120f)
+#define GXIO_MPIPE_OP_REGISTER_CLIENT_MEMORY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1210)
+#define GXIO_MPIPE_OP_LINK_OPEN_AUX    IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1211)
+#define GXIO_MPIPE_OP_LINK_CLOSE_AUX   IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1212)
+
+#define GXIO_MPIPE_OP_GET_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x121e)
+#define GXIO_MPIPE_OP_SET_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x121f)
+#define GXIO_MPIPE_OP_ADJUST_TIMESTAMP_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1220)
+#define GXIO_MPIPE_OP_ARM_POLLFD       IORPC_OPCODE(IORPC_FORMAT_KERNEL_POLLFD, 0x9000)
+#define GXIO_MPIPE_OP_CLOSE_POLLFD     IORPC_OPCODE(IORPC_FORMAT_KERNEL_POLLFD, 0x9001)
+#define GXIO_MPIPE_OP_GET_MMIO_BASE    IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
+#define GXIO_MPIPE_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
+
+int gxio_mpipe_alloc_buffer_stacks(gxio_mpipe_context_t * context,
+                                  unsigned int count, unsigned int first,
+                                  unsigned int flags);
+
+int gxio_mpipe_init_buffer_stack_aux(gxio_mpipe_context_t * context,
+                                    void *mem_va, size_t mem_size,
+                                    unsigned int mem_flags, unsigned int stack,
+                                    unsigned int buffer_size_enum);
+
+
+int gxio_mpipe_alloc_notif_rings(gxio_mpipe_context_t * context,
+                                unsigned int count, unsigned int first,
+                                unsigned int flags);
+
+int gxio_mpipe_init_notif_ring_aux(gxio_mpipe_context_t * context, void *mem_va,
+                                  size_t mem_size, unsigned int mem_flags,
+                                  unsigned int ring);
+
+int gxio_mpipe_request_notif_ring_interrupt(gxio_mpipe_context_t * context,
+                                           int inter_x, int inter_y,
+                                           int inter_ipi, int inter_event,
+                                           unsigned int ring);
+
+int gxio_mpipe_enable_notif_ring_interrupt(gxio_mpipe_context_t * context,
+                                          unsigned int ring);
+
+int gxio_mpipe_alloc_notif_groups(gxio_mpipe_context_t * context,
+                                 unsigned int count, unsigned int first,
+                                 unsigned int flags);
+
+int gxio_mpipe_init_notif_group(gxio_mpipe_context_t * context,
+                               unsigned int group,
+                               gxio_mpipe_notif_group_bits_t bits);
+
+int gxio_mpipe_alloc_buckets(gxio_mpipe_context_t * context, unsigned int count,
+                            unsigned int first, unsigned int flags);
+
+int gxio_mpipe_init_bucket(gxio_mpipe_context_t * context, unsigned int bucket,
+                          MPIPE_LBL_INIT_DAT_BSTS_TBL_t bucket_info);
+
+int gxio_mpipe_alloc_edma_rings(gxio_mpipe_context_t * context,
+                               unsigned int count, unsigned int first,
+                               unsigned int flags);
+
+int gxio_mpipe_init_edma_ring_aux(gxio_mpipe_context_t * context, void *mem_va,
+                                 size_t mem_size, unsigned int mem_flags,
+                                 unsigned int ring, unsigned int channel);
+
+
+int gxio_mpipe_commit_rules(gxio_mpipe_context_t * context, const void *blob,
+                           size_t blob_size);
+
+int gxio_mpipe_register_client_memory(gxio_mpipe_context_t * context,
+                                     unsigned int iotlb, HV_PTE pte,
+                                     unsigned int flags);
+
+int gxio_mpipe_link_open_aux(gxio_mpipe_context_t * context,
+                            _gxio_mpipe_link_name_t name, unsigned int flags);
+
+int gxio_mpipe_link_close_aux(gxio_mpipe_context_t * context, int mac);
+
+
+int gxio_mpipe_get_timestamp_aux(gxio_mpipe_context_t * context, uint64_t * sec,
+                                uint64_t * nsec, uint64_t * cycles);
+
+int gxio_mpipe_set_timestamp_aux(gxio_mpipe_context_t * context, uint64_t sec,
+                                uint64_t nsec, uint64_t cycles);
+
+int gxio_mpipe_adjust_timestamp_aux(gxio_mpipe_context_t * context,
+                                   int64_t nsec);
+
+int gxio_mpipe_arm_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie);
+
+int gxio_mpipe_close_pollfd(gxio_mpipe_context_t * context, int pollfd_cookie);
+
+int gxio_mpipe_get_mmio_base(gxio_mpipe_context_t * context, HV_PTE *base);
+
+int gxio_mpipe_check_mmio_offset(gxio_mpipe_context_t * context,
+                                unsigned long offset, unsigned long size);
+
+#endif /* !__GXIO_MPIPE_LINUX_RPC_H__ */
diff --git a/arch/tile/include/gxio/iorpc_mpipe_info.h b/arch/tile/include/gxio/iorpc_mpipe_info.h
new file mode 100644 (file)
index 0000000..0bcf3f7
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* This file is machine-generated; DO NOT EDIT! */
+#ifndef __GXIO_MPIPE_INFO_LINUX_RPC_H__
+#define __GXIO_MPIPE_INFO_LINUX_RPC_H__
+
+#include <hv/iorpc.h>
+
+#include <hv/drv_mpipe_intf.h>
+#include <asm/page.h>
+#include <gxio/kiorpc.h>
+#include <gxio/mpipe.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <asm/pgtable.h>
+
+
+#define GXIO_MPIPE_INFO_OP_ENUMERATE_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1251)
+#define GXIO_MPIPE_INFO_OP_GET_MMIO_BASE IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
+#define GXIO_MPIPE_INFO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
+
+
+int gxio_mpipe_info_enumerate_aux(gxio_mpipe_info_context_t * context,
+                                 unsigned int idx,
+                                 _gxio_mpipe_link_name_t * name,
+                                 _gxio_mpipe_link_mac_t * mac);
+
+int gxio_mpipe_info_get_mmio_base(gxio_mpipe_info_context_t * context,
+                                 HV_PTE *base);
+
+int gxio_mpipe_info_check_mmio_offset(gxio_mpipe_info_context_t * context,
+                                     unsigned long offset, unsigned long size);
+
+#endif /* !__GXIO_MPIPE_INFO_LINUX_RPC_H__ */
diff --git a/arch/tile/include/gxio/iorpc_trio.h b/arch/tile/include/gxio/iorpc_trio.h
new file mode 100644 (file)
index 0000000..15fb779
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* This file is machine-generated; DO NOT EDIT! */
+#ifndef __GXIO_TRIO_LINUX_RPC_H__
+#define __GXIO_TRIO_LINUX_RPC_H__
+
+#include <hv/iorpc.h>
+
+#include <hv/drv_trio_intf.h>
+#include <gxio/trio.h>
+#include <gxio/kiorpc.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <asm/pgtable.h>
+
+#define GXIO_TRIO_OP_ALLOC_ASIDS       IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400)
+
+#define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1402)
+
+#define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140e)
+#define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140f)
+
+#define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1417)
+#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1418)
+#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1419)
+#define GXIO_TRIO_OP_CONFIG_MSI_INTR   IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141a)
+
+#define GXIO_TRIO_OP_SET_MPS_MRS       IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141c)
+#define GXIO_TRIO_OP_FORCE_RC_LINK_UP  IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141d)
+#define GXIO_TRIO_OP_FORCE_EP_LINK_UP  IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e)
+#define GXIO_TRIO_OP_GET_MMIO_BASE     IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
+#define GXIO_TRIO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
+
+int gxio_trio_alloc_asids(gxio_trio_context_t * context, unsigned int count,
+                         unsigned int first, unsigned int flags);
+
+
+int gxio_trio_alloc_memory_maps(gxio_trio_context_t * context,
+                               unsigned int count, unsigned int first,
+                               unsigned int flags);
+
+
+int gxio_trio_alloc_pio_regions(gxio_trio_context_t * context,
+                               unsigned int count, unsigned int first,
+                               unsigned int flags);
+
+int gxio_trio_init_pio_region_aux(gxio_trio_context_t * context,
+                                 unsigned int pio_region, unsigned int mac,
+                                 uint32_t bus_address_hi, unsigned int flags);
+
+
+int gxio_trio_init_memory_map_mmu_aux(gxio_trio_context_t * context,
+                                     unsigned int map, unsigned long va,
+                                     uint64_t size, unsigned int asid,
+                                     unsigned int mac, uint64_t bus_address,
+                                     unsigned int node,
+                                     unsigned int order_mode);
+
+int gxio_trio_get_port_property(gxio_trio_context_t * context,
+                               struct pcie_trio_ports_property *trio_ports);
+
+int gxio_trio_config_legacy_intr(gxio_trio_context_t * context, int inter_x,
+                                int inter_y, int inter_ipi, int inter_event,
+                                unsigned int mac, unsigned int intx);
+
+int gxio_trio_config_msi_intr(gxio_trio_context_t * context, int inter_x,
+                             int inter_y, int inter_ipi, int inter_event,
+                             unsigned int mac, unsigned int mem_map,
+                             uint64_t mem_map_base, uint64_t mem_map_limit,
+                             unsigned int asid);
+
+
+int gxio_trio_set_mps_mrs(gxio_trio_context_t * context, uint16_t mps,
+                         uint16_t mrs, unsigned int mac);
+
+int gxio_trio_force_rc_link_up(gxio_trio_context_t * context, unsigned int mac);
+
+int gxio_trio_force_ep_link_up(gxio_trio_context_t * context, unsigned int mac);
+
+int gxio_trio_get_mmio_base(gxio_trio_context_t * context, HV_PTE *base);
+
+int gxio_trio_check_mmio_offset(gxio_trio_context_t * context,
+                               unsigned long offset, unsigned long size);
+
+#endif /* !__GXIO_TRIO_LINUX_RPC_H__ */
diff --git a/arch/tile/include/gxio/iorpc_usb_host.h b/arch/tile/include/gxio/iorpc_usb_host.h
new file mode 100644 (file)
index 0000000..8622e7d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/* This file is machine-generated; DO NOT EDIT! */
+#ifndef __GXIO_USB_HOST_LINUX_RPC_H__
+#define __GXIO_USB_HOST_LINUX_RPC_H__
+
+#include <hv/iorpc.h>
+
+#include <hv/drv_usb_host_intf.h>
+#include <asm/page.h>
+#include <gxio/kiorpc.h>
+#include <gxio/usb_host.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <asm/pgtable.h>
+
+#define GXIO_USB_HOST_OP_CFG_INTERRUPT IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1800)
+#define GXIO_USB_HOST_OP_REGISTER_CLIENT_MEMORY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1801)
+#define GXIO_USB_HOST_OP_GET_MMIO_BASE IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
+#define GXIO_USB_HOST_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
+
+int gxio_usb_host_cfg_interrupt(gxio_usb_host_context_t * context, int inter_x,
+                               int inter_y, int inter_ipi, int inter_event);
+
+int gxio_usb_host_register_client_memory(gxio_usb_host_context_t * context,
+                                        HV_PTE pte, unsigned int flags);
+
+int gxio_usb_host_get_mmio_base(gxio_usb_host_context_t * context,
+                               HV_PTE *base);
+
+int gxio_usb_host_check_mmio_offset(gxio_usb_host_context_t * context,
+                                   unsigned long offset, unsigned long size);
+
+#endif /* !__GXIO_USB_HOST_LINUX_RPC_H__ */
diff --git a/arch/tile/include/gxio/kiorpc.h b/arch/tile/include/gxio/kiorpc.h
new file mode 100644 (file)
index 0000000..ee58209
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ * Support routines for kernel IORPC drivers.
+ */
+
+#ifndef _GXIO_KIORPC_H
+#define _GXIO_KIORPC_H
+
+#include <linux/types.h>
+#include <asm/page.h>
+#include <arch/chip.h>
+
+#if CHIP_HAS_MMIO()
+void __iomem *iorpc_ioremap(int hv_fd, resource_size_t offset,
+                           unsigned long size);
+#endif
+
+#endif /* _GXIO_KIORPC_H */
diff --git a/arch/tile/include/gxio/mpipe.h b/arch/tile/include/gxio/mpipe.h
new file mode 100644 (file)
index 0000000..78c5986
--- /dev/null
@@ -0,0 +1,1736 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#ifndef _GXIO_MPIPE_H_
+#define _GXIO_MPIPE_H_
+
+/*
+ *
+ * An API for allocating, configuring, and manipulating mPIPE hardware
+ * resources.
+ */
+
+#include "common.h"
+#include "dma_queue.h"
+
+#include <linux/time.h>
+
+#include <arch/mpipe_def.h>
+#include <arch/mpipe_shm.h>
+
+#include <hv/drv_mpipe_intf.h>
+#include <hv/iorpc.h>
+
+/*
+ *
+ * The TILE-Gx mPIPE&tm; shim provides Ethernet connectivity, packet
+ * classification, and packet load balancing services.  The
+ * gxio_mpipe_ API, declared in <gxio/mpipe.h>, allows applications to
+ * allocate mPIPE IO channels, configure packet distribution
+ * parameters, and send and receive Ethernet packets.  The API is
+ * designed to be a minimal wrapper around the mPIPE hardware, making
+ * system calls only where necessary to preserve inter-process
+ * protection guarantees.
+ *
+ * The APIs described below allow the programmer to allocate and
+ * configure mPIPE resources.  As described below, the mPIPE is a
+ * single shared hardware device that provides partitionable resources
+ * that are shared between all applications in the system.  The
+ * gxio_mpipe_ API allows userspace code to make resource request
+ * calls to the hypervisor, which in turns keeps track of the
+ * resources in use by all applications, maintains protection
+ * guarantees, and resets resources upon application shutdown.
+ *
+ * We strongly recommend reading the mPIPE section of the IO Device
+ * Guide (UG404) before working with this API.  Most functions in the
+ * gxio_mpipe_ API are directly analogous to hardware interfaces and
+ * the documentation assumes that the reader understands those
+ * hardware interfaces.
+ *
+ * @section mpipe__ingress mPIPE Ingress Hardware Resources
+ *
+ * The mPIPE ingress hardware provides extensive hardware offload for
+ * tasks like packet header parsing, load balancing, and memory
+ * management.  This section provides a brief introduction to the
+ * hardware components and the gxio_mpipe_ calls used to manage them;
+ * see the IO Device Guide for a much more detailed description of the
+ * mPIPE's capabilities.
+ *
+ * When a packet arrives at one of the mPIPE's Ethernet MACs, it is
+ * assigned a channel number indicating which MAC received it.  It
+ * then proceeds through the following hardware pipeline:
+ *
+ * @subsection mpipe__classification Classification
+ *
+ * A set of classification processors run header parsing code on each
+ * incoming packet, extracting information including the destination
+ * MAC address, VLAN, Ethernet type, and five-tuple hash.  Some of
+ * this information is then used to choose which buffer stack will be
+ * used to hold the packet, and which bucket will be used by the load
+ * balancer to determine which application will receive the packet.
+ *
+ * The rules by which the buffer stack and bucket are chosen can be
+ * configured via the @ref gxio_mpipe_classifier API.  A given app can
+ * specify multiple rules, each one specifying a bucket range, and a
+ * set of buffer stacks, to be used for packets matching the rule.
+ * Each rule can optionally specify a restricted set of channels,
+ * VLANs, and/or dMACs, in which it is interested.  By default, a
+ * given rule starts out matching all channels associated with the
+ * mPIPE context's set of open links; all VLANs; and all dMACs.
+ * Subsequent restrictions can then be added.
+ *
+ * @subsection mpipe__load_balancing Load Balancing
+ *
+ * The mPIPE load balancer is responsible for choosing the NotifRing
+ * to which the packet will be delivered.  This decision is based on
+ * the bucket number indicated by the classification program.  In
+ * general, the bucket number is based on some number of low bits of
+ * the packet's flow hash (applications that aren't interested in flow
+ * hashing use a single bucket).  Each load balancer bucket keeps a
+ * record of the NotifRing to which packets directed to that bucket
+ * are currently being delivered.  Based on the bucket's load
+ * balancing mode (@ref gxio_mpipe_bucket_mode_t), the load balancer
+ * either forwards the packet to the previously assigned NotifRing or
+ * decides to choose a new NotifRing.  If a new NotifRing is required,
+ * the load balancer chooses the least loaded ring in the NotifGroup
+ * associated with the bucket.
+ *
+ * The load balancer is a shared resource.  Each application needs to
+ * explicitly allocate NotifRings, NotifGroups, and buckets, using
+ * gxio_mpipe_alloc_notif_rings(), gxio_mpipe_alloc_notif_groups(),
+ * and gxio_mpipe_alloc_buckets().  Then the application needs to
+ * configure them using gxio_mpipe_init_notif_ring() and
+ * gxio_mpipe_init_notif_group_and_buckets().
+ *
+ * @subsection mpipe__buffers Buffer Selection and Packet Delivery
+ *
+ * Once the load balancer has chosen the destination NotifRing, the
+ * mPIPE DMA engine pops at least one buffer off of the 'buffer stack'
+ * chosen by the classification program and DMAs the packet data into
+ * that buffer.  Each buffer stack provides a hardware-accelerated
+ * stack of data buffers with the same size.  If the packet data is
+ * larger than the buffers provided by the chosen buffer stack, the
+ * mPIPE hardware pops off multiple buffers and chains the packet data
+ * through a multi-buffer linked list.  Once the packet data is
+ * delivered to the buffer(s), the mPIPE hardware writes the
+ * ::gxio_mpipe_idesc_t metadata object (calculated by the classifier)
+ * into the NotifRing and increments the number of packets delivered
+ * to that ring.
+ *
+ * Applications can push buffers onto a buffer stack by calling
+ * gxio_mpipe_push_buffer() or by egressing a packet with the
+ * ::gxio_mpipe_edesc_t::hwb bit set, indicating that the egressed
+ * buffers should be returned to the stack.
+ *
+ * Applications can allocate and initialize buffer stacks with the
+ * gxio_mpipe_alloc_buffer_stacks() and gxio_mpipe_init_buffer_stack()
+ * APIs.
+ *
+ * The application must also register the memory pages that will hold
+ * packets.  This requires calling gxio_mpipe_register_page() for each
+ * memory page that will hold packets allocated by the application for
+ * a given buffer stack.  Since each buffer stack is limited to 16
+ * registered pages, it may be necessary to use huge pages, or even
+ * extremely huge pages, to hold all the buffers.
+ *
+ * @subsection mpipe__iqueue NotifRings
+ *
+ * Each NotifRing is a region of shared memory, allocated by the
+ * application, to which the mPIPE delivers packet descriptors
+ * (::gxio_mpipe_idesc_t).  The application can allocate them via
+ * gxio_mpipe_alloc_notif_rings().  The application can then either
+ * explicitly initialize them with gxio_mpipe_init_notif_ring() and
+ * then read from them manually, or can make use of the convenience
+ * wrappers provided by @ref gxio_mpipe_wrappers.
+ *
+ * @section mpipe__egress mPIPE Egress Hardware
+ *
+ * Applications use eDMA rings to queue packets for egress.  The
+ * application can allocate them via gxio_mpipe_alloc_edma_rings().
+ * The application can then either explicitly initialize them with
+ * gxio_mpipe_init_edma_ring() and then write to them manually, or
+ * can make use of the convenience wrappers provided by
+ * @ref gxio_mpipe_wrappers.
+ *
+ * @section gxio__shortcomings Plans for Future API Revisions
+ *
+ * The API defined here is only an initial version of the mPIPE API.
+ * Future plans include:
+ *
+ * - Higher level wrapper functions to provide common initialization
+ * patterns.  This should help users start writing mPIPE programs
+ * without having to learn the details of the hardware.
+ *
+ * - Support for reset and deallocation of resources, including
+ * cleanup upon application shutdown.
+ *
+ * - Support for calling these APIs in the BME.
+ *
+ * - Support for IO interrupts.
+ *
+ * - Clearer definitions of thread safety guarantees.
+ *
+ * @section gxio__mpipe_examples Examples
+ *
+ * See the following mPIPE example programs for more information about
+ * allocating mPIPE resources and using them in real applications:
+ *
+ * - @ref mpipe/ingress/app.c : Receiving packets.
+ *
+ * - @ref mpipe/forward/app.c : Forwarding packets.
+ *
+ * Note that there are several more examples.
+ */
+
+/* Flags that can be passed to resource allocation functions. */
+enum gxio_mpipe_alloc_flags_e {
+       /* Require an allocation to start at a specified resource index. */
+       GXIO_MPIPE_ALLOC_FIXED = HV_MPIPE_ALLOC_FIXED,
+};
+
+/* Flags that can be passed to memory registration functions. */
+enum gxio_mpipe_mem_flags_e {
+       /* Do not fill L3 when writing, and invalidate lines upon egress. */
+       GXIO_MPIPE_MEM_FLAG_NT_HINT = IORPC_MEM_BUFFER_FLAG_NT_HINT,
+
+       /* L3 cache fills should only populate IO cache ways. */
+       GXIO_MPIPE_MEM_FLAG_IO_PIN = IORPC_MEM_BUFFER_FLAG_IO_PIN,
+};
+
+/* An ingress packet descriptor.  When a packet arrives, the mPIPE
+ * hardware generates this structure and writes it into a NotifRing.
+ */
+typedef MPIPE_PDESC_t gxio_mpipe_idesc_t;
+
+/* An egress command descriptor.  Applications write this structure
+ * into eDMA rings and the hardware performs the indicated operation
+ * (normally involving egressing some bytes).  Note that egressing a
+ * single packet may involve multiple egress command descriptors.
+ */
+typedef MPIPE_EDMA_DESC_t gxio_mpipe_edesc_t;
+
+/* Get the "va" field from an "idesc".
+ *
+ * This is the address at which the ingress hardware copied the first
+ * byte of the packet.
+ *
+ * If the classifier detected a custom header, then this will point to
+ * the custom header, and gxio_mpipe_idesc_get_l2_start() will point
+ * to the actual L2 header.
+ *
+ * Note that this value may be misleading if "idesc->be" is set.
+ *
+ * @param idesc An ingress packet descriptor.
+ */
+static inline unsigned char *gxio_mpipe_idesc_get_va(gxio_mpipe_idesc_t *idesc)
+{
+       return (unsigned char *)(long)idesc->va;
+}
+
+/* Get the "xfer_size" from an "idesc".
+ *
+ * This is the actual number of packet bytes transferred into memory
+ * by the hardware.
+ *
+ * Note that this value may be misleading if "idesc->be" is set.
+ *
+ * @param idesc An ingress packet descriptor.
+ *
+ * ISSUE: Is this the best name for this?
+ * FIXME: Add more docs about chaining, clipping, etc.
+ */
+static inline unsigned int gxio_mpipe_idesc_get_xfer_size(gxio_mpipe_idesc_t
+                                                         *idesc)
+{
+       return idesc->l2_size;
+}
+
+/* Get the "l2_offset" from an "idesc".
+ *
+ * Extremely customized classifiers might not support this function.
+ *
+ * This is the number of bytes between the "va" and the L2 header.
+ *
+ * The L2 header consists of a destination mac address, a source mac
+ * address, and an initial ethertype.  Various initial ethertypes
+ * allow encoding extra information in the L2 header, often including
+ * a vlan, and/or a new ethertype.
+ *
+ * Note that the "l2_offset" will be non-zero if (and only if) the
+ * classifier processed a custom header for the packet.
+ *
+ * @param idesc An ingress packet descriptor.
+ */
+static inline uint8_t gxio_mpipe_idesc_get_l2_offset(gxio_mpipe_idesc_t *idesc)
+{
+       return (idesc->custom1 >> 32) & 0xFF;
+}
+
+/* Get the "l2_start" from an "idesc".
+ *
+ * This is simply gxio_mpipe_idesc_get_va() plus
+ * gxio_mpipe_idesc_get_l2_offset().
+ *
+ * @param idesc An ingress packet descriptor.
+ */
+static inline unsigned char *gxio_mpipe_idesc_get_l2_start(gxio_mpipe_idesc_t
+                                                          *idesc)
+{
+       unsigned char *va = gxio_mpipe_idesc_get_va(idesc);
+       return va + gxio_mpipe_idesc_get_l2_offset(idesc);
+}
+
+/* Get the "l2_length" from an "idesc".
+ *
+ * This is simply gxio_mpipe_idesc_get_xfer_size() minus
+ * gxio_mpipe_idesc_get_l2_offset().
+ *
+ * @param idesc An ingress packet descriptor.
+ */
+static inline unsigned int gxio_mpipe_idesc_get_l2_length(gxio_mpipe_idesc_t
+                                                         *idesc)
+{
+       unsigned int xfer_size = idesc->l2_size;
+       return xfer_size - gxio_mpipe_idesc_get_l2_offset(idesc);
+}
+
+/* A context object used to manage mPIPE hardware resources. */
+typedef struct {
+
+       /* File descriptor for calling up to Linux (and thus the HV). */
+       int fd;
+
+       /* The VA at which configuration registers are mapped. */
+       char *mmio_cfg_base;
+
+       /* The VA at which IDMA, EDMA, and buffer manager are mapped. */
+       char *mmio_fast_base;
+
+       /* The "initialized" buffer stacks. */
+       gxio_mpipe_rules_stacks_t __stacks;
+
+} gxio_mpipe_context_t;
+
+/* This is only used internally, but it's most easily made visible here. */
+typedef gxio_mpipe_context_t gxio_mpipe_info_context_t;
+
+/* Initialize an mPIPE context.
+ *
+ * This function allocates an mPIPE "service domain" and maps the MMIO
+ * registers into the caller's VA space.
+ *
+ * @param context Context object to be initialized.
+ * @param mpipe_instance Instance number of mPIPE shim to be controlled via
+ *  context.
+ */
+extern int gxio_mpipe_init(gxio_mpipe_context_t *context,
+                          unsigned int mpipe_instance);
+
+/* Destroy an mPIPE context.
+ *
+ * This function frees the mPIPE "service domain" and unmaps the MMIO
+ * registers from the caller's VA space.
+ *
+ * If a user process exits without calling this routine, the kernel
+ * will destroy the mPIPE context as part of process teardown.
+ *
+ * @param context Context object to be destroyed.
+ */
+extern int gxio_mpipe_destroy(gxio_mpipe_context_t *context);
+
+/*****************************************************************
+ *                         Buffer Stacks                          *
+ ******************************************************************/
+
+/* Allocate a set of buffer stacks.
+ *
+ * The return value is NOT interesting if count is zero.
+ *
+ * @param context An initialized mPIPE context.
+ * @param count Number of stacks required.
+ * @param first Index of first stack if ::GXIO_MPIPE_ALLOC_FIXED flag is set,
+ *   otherwise ignored.
+ * @param flags Flag bits from ::gxio_mpipe_alloc_flags_e.
+ * @return Index of first allocated buffer stack, or
+ * ::GXIO_MPIPE_ERR_NO_BUFFER_STACK if allocation failed.
+ */
+extern int gxio_mpipe_alloc_buffer_stacks(gxio_mpipe_context_t *context,
+                                         unsigned int count,
+                                         unsigned int first,
+                                         unsigned int flags);
+
+/* Enum codes for buffer sizes supported by mPIPE. */
+typedef enum {
+       /* 128 byte packet data buffer. */
+       GXIO_MPIPE_BUFFER_SIZE_128 = MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_128,
+       /* 256 byte packet data buffer. */
+       GXIO_MPIPE_BUFFER_SIZE_256 = MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_256,
+       /* 512 byte packet data buffer. */
+       GXIO_MPIPE_BUFFER_SIZE_512 = MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_512,
+       /* 1024 byte packet data buffer. */
+       GXIO_MPIPE_BUFFER_SIZE_1024 = MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_1024,
+       /* 1664 byte packet data buffer. */
+       GXIO_MPIPE_BUFFER_SIZE_1664 = MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_1664,
+       /* 4096 byte packet data buffer. */
+       GXIO_MPIPE_BUFFER_SIZE_4096 = MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_4096,
+       /* 10368 byte packet data buffer. */
+       GXIO_MPIPE_BUFFER_SIZE_10368 =
+               MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_10368,
+       /* 16384 byte packet data buffer. */
+       GXIO_MPIPE_BUFFER_SIZE_16384 = MPIPE_BSM_INIT_DAT_1__SIZE_VAL_BSZ_16384
+} gxio_mpipe_buffer_size_enum_t;
+
+/* Convert a buffer size in bytes into a buffer size enum. */
+extern gxio_mpipe_buffer_size_enum_t
+gxio_mpipe_buffer_size_to_buffer_size_enum(size_t size);
+
+/* Convert a buffer size enum into a buffer size in bytes. */
+extern size_t
+gxio_mpipe_buffer_size_enum_to_buffer_size(gxio_mpipe_buffer_size_enum_t
+                                          buffer_size_enum);
+
+/* Calculate the number of bytes required to store a given number of
+ * buffers in the memory registered with a buffer stack via
+ * gxio_mpipe_init_buffer_stack().
+ */
+extern size_t gxio_mpipe_calc_buffer_stack_bytes(unsigned long buffers);
+
+/* Initialize a buffer stack.  This function binds a region of memory
+ * to be used by the hardware for storing buffer addresses pushed via
+ * gxio_mpipe_push_buffer() or as the result of sending a buffer out
+ * the egress with the 'push to stack when done' bit set.  Once this
+ * function returns, the memory region's contents may be arbitrarily
+ * modified by the hardware at any time and software should not access
+ * the memory region again.
+ *
+ * @param context An initialized mPIPE context.
+ * @param stack The buffer stack index.
+ * @param buffer_size_enum The size of each buffer in the buffer stack,
+ * as an enum.
+ * @param mem The address of the buffer stack.  This memory must be
+ * physically contiguous and aligned to a 64kB boundary.
+ * @param mem_size The size of the buffer stack, in bytes.
+ * @param mem_flags ::gxio_mpipe_mem_flags_e memory flags.
+ * @return Zero on success, ::GXIO_MPIPE_ERR_INVAL_BUFFER_SIZE if
+ * buffer_size_enum is invalid, ::GXIO_MPIPE_ERR_BAD_BUFFER_STACK if
+ * stack has not been allocated.
+ */
+extern int gxio_mpipe_init_buffer_stack(gxio_mpipe_context_t *context,
+                                       unsigned int stack,
+                                       gxio_mpipe_buffer_size_enum_t
+                                       buffer_size_enum, void *mem,
+                                       size_t mem_size,
+                                       unsigned int mem_flags);
+
+/* Push a buffer onto a previously initialized buffer stack.
+ *
+ * The size of the buffer being pushed must match the size that was
+ * registered with gxio_mpipe_init_buffer_stack().  All packet buffer
+ * addresses are 128-byte aligned; the low 7 bits of the specified
+ * buffer address will be ignored.
+ *
+ * @param context An initialized mPIPE context.
+ * @param stack The buffer stack index.
+ * @param buffer The buffer (the low seven bits are ignored).
+ */
+static inline void gxio_mpipe_push_buffer(gxio_mpipe_context_t *context,
+                                         unsigned int stack, void *buffer)
+{
+       MPIPE_BSM_REGION_ADDR_t offset = { {0} };
+       MPIPE_BSM_REGION_VAL_t val = { {0} };
+
+       /*
+        * The mmio_fast_base region starts at the IDMA region, so subtract
+        * off that initial offset.
+        */
+       offset.region =
+               MPIPE_MMIO_ADDR__REGION_VAL_BSM -
+               MPIPE_MMIO_ADDR__REGION_VAL_IDMA;
+       offset.stack = stack;
+
+#if __SIZEOF_POINTER__ == 4
+       val.va = ((ulong) buffer) >> MPIPE_BSM_REGION_VAL__VA_SHIFT;
+#else
+       val.va = ((long)buffer) >> MPIPE_BSM_REGION_VAL__VA_SHIFT;
+#endif
+
+       __gxio_mmio_write(context->mmio_fast_base + offset.word, val.word);
+}
+
+/* Pop a buffer off of a previously initialized buffer stack.
+ *
+ * @param context An initialized mPIPE context.
+ * @param stack The buffer stack index.
+ * @return The buffer, or NULL if the stack is empty.
+ */
+static inline void *gxio_mpipe_pop_buffer(gxio_mpipe_context_t *context,
+                                         unsigned int stack)
+{
+       MPIPE_BSM_REGION_ADDR_t offset = { {0} };
+
+       /*
+        * The mmio_fast_base region starts at the IDMA region, so subtract
+        * off that initial offset.
+        */
+       offset.region =
+               MPIPE_MMIO_ADDR__REGION_VAL_BSM -
+               MPIPE_MMIO_ADDR__REGION_VAL_IDMA;
+       offset.stack = stack;
+
+       while (1) {
+               /*
+                * Case 1: val.c == ..._UNCHAINED, va is non-zero.
+                * Case 2: val.c == ..._INVALID, va is zero.
+                * Case 3: val.c == ..._NOT_RDY, va is zero.
+                */
+               MPIPE_BSM_REGION_VAL_t val;
+               val.word =
+                       __gxio_mmio_read(context->mmio_fast_base +
+                                        offset.word);
+
+               /*
+                * Handle case 1 and 2 by returning the buffer (or NULL).
+                * Handle case 3 by waiting for the prefetch buffer to refill.
+                */
+               if (val.c != MPIPE_EDMA_DESC_WORD1__C_VAL_NOT_RDY)
+                       return (void *)((unsigned long)val.
+                                       va << MPIPE_BSM_REGION_VAL__VA_SHIFT);
+       }
+}
+
+/*****************************************************************
+ *                          NotifRings                            *
+ ******************************************************************/
+
+/* Allocate a set of NotifRings.
+ *
+ * The return value is NOT interesting if count is zero.
+ *
+ * Note that NotifRings are allocated in chunks, so allocating one at
+ * a time is much less efficient than allocating several at once.
+ *
+ * @param context An initialized mPIPE context.
+ * @param count Number of NotifRings required.
+ * @param first Index of first NotifRing if ::GXIO_MPIPE_ALLOC_FIXED flag
+ *   is set, otherwise ignored.
+ * @param flags Flag bits from ::gxio_mpipe_alloc_flags_e.
+ * @return Index of first allocated buffer NotifRing, or
+ * ::GXIO_MPIPE_ERR_NO_NOTIF_RING if allocation failed.
+ */
+extern int gxio_mpipe_alloc_notif_rings(gxio_mpipe_context_t *context,
+                                       unsigned int count, unsigned int first,
+                                       unsigned int flags);
+
+/* Initialize a NotifRing, using the given memory and size.
+ *
+ * @param context An initialized mPIPE context.
+ * @param ring The NotifRing index.
+ * @param mem A physically contiguous region of memory to be filled
+ * with a ring of ::gxio_mpipe_idesc_t structures.
+ * @param mem_size Number of bytes in the ring.  Must be 128, 512,
+ * 2048, or 65536 * sizeof(gxio_mpipe_idesc_t).
+ * @param mem_flags ::gxio_mpipe_mem_flags_e memory flags.
+ *
+ * @return 0 on success, ::GXIO_MPIPE_ERR_BAD_NOTIF_RING or
+ * ::GXIO_ERR_INVAL_MEMORY_SIZE on failure.
+ */
+extern int gxio_mpipe_init_notif_ring(gxio_mpipe_context_t *context,
+                                     unsigned int ring,
+                                     void *mem, size_t mem_size,
+                                     unsigned int mem_flags);
+
+/* Configure an interrupt to be sent to a tile on incoming NotifRing
+ *  traffic.  Once an interrupt is sent for a particular ring, no more
+ *  will be sent until gxio_mica_enable_notif_ring_interrupt() is called.
+ *
+ * @param context An initialized mPIPE context.
+ * @param x X coordinate of interrupt target tile.
+ * @param y Y coordinate of interrupt target tile.
+ * @param i Index of the IPI register which will receive the interrupt.
+ * @param e Specific event which will be set in the target IPI register when
+ * the interrupt occurs.
+ * @param ring The NotifRing index.
+ * @return Zero on success, GXIO_ERR_INVAL if params are out of range.
+ */
+extern int gxio_mpipe_request_notif_ring_interrupt(gxio_mpipe_context_t
+                                                  *context, int x, int y,
+                                                  int i, int e,
+                                                  unsigned int ring);
+
+/* Enable an interrupt on incoming NotifRing traffic.
+ *
+ * @param context An initialized mPIPE context.
+ * @param ring The NotifRing index.
+ * @return Zero on success, GXIO_ERR_INVAL if params are out of range.
+ */
+extern int gxio_mpipe_enable_notif_ring_interrupt(gxio_mpipe_context_t
+                                                 *context, unsigned int ring);
+
+/* Map all of a client's memory via the given IOTLB.
+ * @param context An initialized mPIPE context.
+ * @param iotlb IOTLB index.
+ * @param pte Page table entry.
+ * @param flags Flags.
+ * @return Zero on success, or a negative error code.
+ */
+extern int gxio_mpipe_register_client_memory(gxio_mpipe_context_t *context,
+                                            unsigned int iotlb, HV_PTE pte,
+                                            unsigned int flags);
+
+/*****************************************************************
+ *                        Notif Groups                            *
+ ******************************************************************/
+
+/* Allocate a set of NotifGroups.
+ *
+ * The return value is NOT interesting if count is zero.
+ *
+ * @param context An initialized mPIPE context.
+ * @param count Number of NotifGroups required.
+ * @param first Index of first NotifGroup if ::GXIO_MPIPE_ALLOC_FIXED flag
+ *   is set, otherwise ignored.
+ * @param flags Flag bits from ::gxio_mpipe_alloc_flags_e.
+ * @return Index of first allocated buffer NotifGroup, or
+ * ::GXIO_MPIPE_ERR_NO_NOTIF_GROUP if allocation failed.
+ */
+extern int gxio_mpipe_alloc_notif_groups(gxio_mpipe_context_t *context,
+                                        unsigned int count,
+                                        unsigned int first,
+                                        unsigned int flags);
+
+/* Add a NotifRing to a NotifGroup.  This only sets a bit in the
+ * application's 'group' object; the hardware NotifGroup can be
+ * initialized by passing 'group' to gxio_mpipe_init_notif_group() or
+ * gxio_mpipe_init_notif_group_and_buckets().
+ */
+static inline void
+gxio_mpipe_notif_group_add_ring(gxio_mpipe_notif_group_bits_t *bits, int ring)
+{
+       bits->ring_mask[ring / 64] |= (1ull << (ring % 64));
+}
+
+/* Set a particular NotifGroup bitmask.  Since the load balancer
+ * makes decisions based on both bucket and NotifGroup state, most
+ * applications should use gxio_mpipe_init_notif_group_and_buckets()
+ * rather than using this function to configure just a NotifGroup.
+ */
+extern int gxio_mpipe_init_notif_group(gxio_mpipe_context_t *context,
+                                      unsigned int group,
+                                      gxio_mpipe_notif_group_bits_t bits);
+
+/*****************************************************************
+ *                         Load Balancer                          *
+ ******************************************************************/
+
+/* Allocate a set of load balancer buckets.
+ *
+ * The return value is NOT interesting if count is zero.
+ *
+ * Note that buckets are allocated in chunks, so allocating one at
+ * a time is much less efficient than allocating several at once.
+ *
+ * Note that the buckets are actually divided into two sub-ranges, of
+ * different sizes, and different chunk sizes, and the range you get
+ * by default is determined by the size of the request.  Allocations
+ * cannot span the two sub-ranges.
+ *
+ * @param context An initialized mPIPE context.
+ * @param count Number of buckets required.
+ * @param first Index of first bucket if ::GXIO_MPIPE_ALLOC_FIXED flag is set,
+ *   otherwise ignored.
+ * @param flags Flag bits from ::gxio_mpipe_alloc_flags_e.
+ * @return Index of first allocated buffer bucket, or
+ * ::GXIO_MPIPE_ERR_NO_BUCKET if allocation failed.
+ */
+extern int gxio_mpipe_alloc_buckets(gxio_mpipe_context_t *context,
+                                   unsigned int count, unsigned int first,
+                                   unsigned int flags);
+
+/* The legal modes for gxio_mpipe_bucket_info_t and
+ * gxio_mpipe_init_notif_group_and_buckets().
+ *
+ * All modes except ::GXIO_MPIPE_BUCKET_ROUND_ROBIN expect that the user
+ * will allocate a power-of-two number of buckets and initialize them
+ * to the same mode.  The classifier program then uses the appropriate
+ * number of low bits from the incoming packet's flow hash to choose a
+ * load balancer bucket.  Based on that bucket's load balancing mode,
+ * reference count, and currently active NotifRing, the load balancer
+ * chooses the NotifRing to which the packet will be delivered.
+ */
+typedef enum {
+       /* All packets for a bucket go to the same NotifRing unless the
+        * NotifRing gets full, in which case packets will be dropped.  If
+        * the bucket reference count ever reaches zero, a new NotifRing may
+        * be chosen.
+        */
+       GXIO_MPIPE_BUCKET_DYNAMIC_FLOW_AFFINITY =
+               MPIPE_LBL_INIT_DAT_BSTS_TBL__MODE_VAL_DFA,
+
+       /* All packets for a bucket always go to the same NotifRing.
+        */
+       GXIO_MPIPE_BUCKET_STATIC_FLOW_AFFINITY =
+               MPIPE_LBL_INIT_DAT_BSTS_TBL__MODE_VAL_FIXED,
+
+       /* All packets for a bucket go to the least full NotifRing in the
+        * group, providing load balancing round robin behavior.
+        */
+       GXIO_MPIPE_BUCKET_ROUND_ROBIN =
+               MPIPE_LBL_INIT_DAT_BSTS_TBL__MODE_VAL_ALWAYS_PICK,
+
+       /* All packets for a bucket go to the same NotifRing unless the
+        * NotifRing gets full, at which point the bucket starts using the
+        * least full NotifRing in the group.  If all NotifRings in the
+        * group are full, packets will be dropped.
+        */
+       GXIO_MPIPE_BUCKET_STICKY_FLOW_LOCALITY =
+               MPIPE_LBL_INIT_DAT_BSTS_TBL__MODE_VAL_STICKY,
+
+       /* All packets for a bucket go to the same NotifRing unless the
+        * NotifRing gets full, or a random timer fires, at which point the
+        * bucket starts using the least full NotifRing in the group.  If
+        * all NotifRings in the group are full, packets will be dropped.
+        * WARNING: This mode is BROKEN on chips with fewer than 64 tiles.
+        */
+       GXIO_MPIPE_BUCKET_PREFER_FLOW_LOCALITY =
+               MPIPE_LBL_INIT_DAT_BSTS_TBL__MODE_VAL_STICKY_RAND,
+
+} gxio_mpipe_bucket_mode_t;
+
+/* Copy a set of bucket initialization values into the mPIPE
+ * hardware.  Since the load balancer makes decisions based on both
+ * bucket and NotifGroup state, most applications should use
+ * gxio_mpipe_init_notif_group_and_buckets() rather than using this
+ * function to configure a single bucket.
+ *
+ * @param context An initialized mPIPE context.
+ * @param bucket Bucket index to be initialized.
+ * @param bucket_info Initial reference count, NotifRing index, and mode.
+ * @return 0 on success, ::GXIO_MPIPE_ERR_BAD_BUCKET on failure.
+ */
+extern int gxio_mpipe_init_bucket(gxio_mpipe_context_t *context,
+                                 unsigned int bucket,
+                                 gxio_mpipe_bucket_info_t bucket_info);
+
+/* Initializes a group and range of buckets and range of rings such
+ * that the load balancer runs a particular load balancing function.
+ *
+ * First, the group is initialized with the given rings.
+ *
+ * Second, each bucket is initialized with the mode and group, and a
+ * ring chosen round-robin from the given rings.
+ *
+ * Normally, the classifier picks a bucket, and then the load balancer
+ * picks a ring, based on the bucket's mode, group, and current ring,
+ * possibly updating the bucket's ring.
+ *
+ * @param context An initialized mPIPE context.
+ * @param group The group.
+ * @param ring The first ring.
+ * @param num_rings The number of rings.
+ * @param bucket The first bucket.
+ * @param num_buckets The number of buckets.
+ * @param mode The load balancing mode.
+ *
+ * @return 0 on success, ::GXIO_MPIPE_ERR_BAD_BUCKET,
+ * ::GXIO_MPIPE_ERR_BAD_NOTIF_GROUP, or
+ * ::GXIO_MPIPE_ERR_BAD_NOTIF_RING on failure.
+ */
+extern int gxio_mpipe_init_notif_group_and_buckets(gxio_mpipe_context_t
+                                                  *context,
+                                                  unsigned int group,
+                                                  unsigned int ring,
+                                                  unsigned int num_rings,
+                                                  unsigned int bucket,
+                                                  unsigned int num_buckets,
+                                                  gxio_mpipe_bucket_mode_t
+                                                  mode);
+
+/* Return credits to a NotifRing and/or bucket.
+ *
+ * @param context An initialized mPIPE context.
+ * @param ring The NotifRing index, or -1.
+ * @param bucket The bucket, or -1.
+ * @param count The number of credits to return.
+ */
+static inline void gxio_mpipe_credit(gxio_mpipe_context_t *context,
+                                    int ring, int bucket, unsigned int count)
+{
+       /* NOTE: Fancy struct initialization would break "C89" header test. */
+
+       MPIPE_IDMA_RELEASE_REGION_ADDR_t offset = { {0} };
+       MPIPE_IDMA_RELEASE_REGION_VAL_t val = { {0} };
+
+       /*
+        * The mmio_fast_base region starts at the IDMA region, so subtract
+        * off that initial offset.
+        */
+       offset.region =
+               MPIPE_MMIO_ADDR__REGION_VAL_IDMA -
+               MPIPE_MMIO_ADDR__REGION_VAL_IDMA;
+       offset.ring = ring;
+       offset.bucket = bucket;
+       offset.ring_enable = (ring >= 0);
+       offset.bucket_enable = (bucket >= 0);
+       val.count = count;
+
+       __gxio_mmio_write(context->mmio_fast_base + offset.word, val.word);
+}
+
+/*****************************************************************
+ *                         Egress Rings                           *
+ ******************************************************************/
+
+/* Allocate a set of eDMA rings.
+ *
+ * The return value is NOT interesting if count is zero.
+ *
+ * @param context An initialized mPIPE context.
+ * @param count Number of eDMA rings required.
+ * @param first Index of first eDMA ring if ::GXIO_MPIPE_ALLOC_FIXED flag
+ *   is set, otherwise ignored.
+ * @param flags Flag bits from ::gxio_mpipe_alloc_flags_e.
+ * @return Index of first allocated buffer eDMA ring, or
+ * ::GXIO_MPIPE_ERR_NO_EDMA_RING if allocation failed.
+ */
+extern int gxio_mpipe_alloc_edma_rings(gxio_mpipe_context_t *context,
+                                      unsigned int count, unsigned int first,
+                                      unsigned int flags);
+
+/* Initialize an eDMA ring, using the given memory and size.
+ *
+ * @param context An initialized mPIPE context.
+ * @param ring The eDMA ring index.
+ * @param channel The channel to use.  This must be one of the channels
+ * associated with the context's set of open links.
+ * @param mem A physically contiguous region of memory to be filled
+ * with a ring of ::gxio_mpipe_edesc_t structures.
+ * @param mem_size Number of bytes in the ring.  Must be 512, 2048,
+ * 8192 or 65536, times 16 (i.e. sizeof(gxio_mpipe_edesc_t)).
+ * @param mem_flags ::gxio_mpipe_mem_flags_e memory flags.
+ *
+ * @return 0 on success, ::GXIO_MPIPE_ERR_BAD_EDMA_RING or
+ * ::GXIO_ERR_INVAL_MEMORY_SIZE on failure.
+ */
+extern int gxio_mpipe_init_edma_ring(gxio_mpipe_context_t *context,
+                                    unsigned int ring, unsigned int channel,
+                                    void *mem, size_t mem_size,
+                                    unsigned int mem_flags);
+
+/*****************************************************************
+ *                      Classifier Program                        *
+ ******************************************************************/
+
+/*
+ *
+ * Functions for loading or configuring the mPIPE classifier program.
+ *
+ * The mPIPE classification processors all run a special "classifier"
+ * program which, for each incoming packet, parses the packet headers,
+ * encodes some packet metadata in the "idesc", and either drops the
+ * packet, or picks a notif ring to handle the packet, and a buffer
+ * stack to contain the packet, usually based on the channel, VLAN,
+ * dMAC, flow hash, and packet size, under the guidance of the "rules"
+ * API described below.
+ *
+ * @section gxio_mpipe_classifier_default Default Classifier
+ *
+ * The MDE provides a simple "default" classifier program.  It is
+ * shipped as source in "$TILERA_ROOT/src/sys/mpipe/classifier.c",
+ * which serves as its official documentation.  It is shipped as a
+ * binary program in "$TILERA_ROOT/tile/boot/classifier", which is
+ * automatically included in bootroms created by "tile-monitor", and
+ * is automatically loaded by the hypervisor at boot time.
+ *
+ * The L2 analysis handles LLC packets, SNAP packets, and "VLAN
+ * wrappers" (keeping the outer VLAN).
+ *
+ * The L3 analysis handles IPv4 and IPv6, dropping packets with bad
+ * IPv4 header checksums, requesting computation of a TCP/UDP checksum
+ * if appropriate, and hashing the dest and src IP addresses, plus the
+ * ports for TCP/UDP packets, into the flow hash.  No special analysis
+ * is done for "fragmented" packets or "tunneling" protocols.  Thus,
+ * the first fragment of a fragmented TCP/UDP packet is hashed using
+ * src/dest IP address and ports and all subsequent fragments are only
+ * hashed according to src/dest IP address.
+ *
+ * The L3 analysis handles other packets too, hashing the dMAC
+ * smac into a flow hash.
+ *
+ * The channel, VLAN, and dMAC used to pick a "rule" (see the
+ * "rules" APIs below), which in turn is used to pick a buffer stack
+ * (based on the packet size) and a bucket (based on the flow hash).
+ *
+ * To receive traffic matching a particular (channel/VLAN/dMAC
+ * pattern, an application should allocate its own buffer stacks and
+ * load balancer buckets, and map traffic to those stacks and buckets,
+ * as decribed by the "rules" API below.
+ *
+ * Various packet metadata is encoded in the idesc.  The flow hash is
+ * four bytes at 0x0C.  The VLAN is two bytes at 0x10.  The ethtype is
+ * two bytes at 0x12.  The l3 start is one byte at 0x14.  The l4 start
+ * is one byte at 0x15 for IPv4 and IPv6 packets, and otherwise zero.
+ * The protocol is one byte at 0x16 for IPv4 and IPv6 packets, and
+ * otherwise zero.
+ *
+ * @section gxio_mpipe_classifier_custom Custom Classifiers.
+ *
+ * A custom classifier may be created using "tile-mpipe-cc" with a
+ * customized version of the default classifier sources.
+ *
+ * The custom classifier may be included in bootroms using the
+ * "--classifier" option to "tile-monitor", or loaded dynamically
+ * using gxio_mpipe_classifier_load_from_file().
+ *
+ * Be aware that "extreme" customizations may break the assumptions of
+ * the "rules" APIs described below, but simple customizations, such
+ * as adding new packet metadata, should be fine.
+ */
+
+/* A set of classifier rules, plus a context. */
+typedef struct {
+
+       /* The context. */
+       gxio_mpipe_context_t *context;
+
+       /* The actual rules. */
+       gxio_mpipe_rules_list_t list;
+
+} gxio_mpipe_rules_t;
+
+/* Initialize a classifier program rules list.
+ *
+ * This function can be called on a previously initialized rules list
+ * to discard any previously added rules.
+ *
+ * @param rules Rules list to initialize.
+ * @param context An initialized mPIPE context.
+ */
+extern void gxio_mpipe_rules_init(gxio_mpipe_rules_t *rules,
+                                 gxio_mpipe_context_t *context);
+
+/* Begin a new rule on the indicated rules list.
+ *
+ * Note that an empty rule matches all packets, but an empty rule list
+ * matches no packets.
+ *
+ * @param rules Rules list to which new rule is appended.
+ * @param bucket First load balancer bucket to which packets will be
+ * delivered.
+ * @param num_buckets Number of buckets (must be a power of two) across
+ * which packets will be distributed based on the "flow hash".
+ * @param stacks Either NULL, to assign each packet to the smallest
+ * initialized buffer stack which does not induce chaining (and to
+ * drop packets which exceed the largest initialized buffer stack
+ * buffer size), or an array, with each entry indicating which buffer
+ * stack should be used for packets up to that size (with 255
+ * indicating that those packets should be dropped).
+ * @return 0 on success, or a negative error code on failure.
+ */
+extern int gxio_mpipe_rules_begin(gxio_mpipe_rules_t *rules,
+                                 unsigned int bucket,
+                                 unsigned int num_buckets,
+                                 gxio_mpipe_rules_stacks_t *stacks);
+
+/* Set the headroom of the current rule.
+ *
+ * @param rules Rules list whose current rule will be modified.
+ * @param headroom The headroom.
+ * @return 0 on success, or a negative error code on failure.
+ */
+extern int gxio_mpipe_rules_set_headroom(gxio_mpipe_rules_t *rules,
+                                        uint8_t headroom);
+
+/* Indicate that packets from a particular channel can be delivered
+ * to the buckets and buffer stacks associated with the current rule.
+ *
+ * Channels added must be associated with links opened by the mPIPE context
+ * used in gxio_mpipe_rules_init().  A rule with no channels is equivalent
+ * to a rule naming all such associated channels.
+ *
+ * @param rules Rules list whose current rule will be modified.
+ * @param channel The channel to add.
+ * @return 0 on success, or a negative error code on failure.
+ */
+extern int gxio_mpipe_rules_add_channel(gxio_mpipe_rules_t *rules,
+                                       unsigned int channel);
+
+/* Commit rules.
+ *
+ * The rules are sent to the hypervisor, where they are combined with
+ * the rules from other apps, and used to program the hardware classifier.
+ *
+ * Note that if this function returns an error, then the rules will NOT
+ * have been committed, even if the error is due to interactions with
+ * rules from another app.
+ *
+ * @param rules Rules list to commit.
+ * @return 0 on success, or a negative error code on failure.
+ */
+extern int gxio_mpipe_rules_commit(gxio_mpipe_rules_t *rules);
+
+/*****************************************************************
+ *                     Ingress Queue Wrapper                      *
+ ******************************************************************/
+
+/*
+ *
+ * Convenience functions for receiving packets from a NotifRing and
+ * sending packets via an eDMA ring.
+ *
+ * The mpipe ingress and egress hardware uses shared memory packet
+ * descriptors to describe packets that have arrived on ingress or
+ * are destined for egress.  These descriptors are stored in shared
+ * memory ring buffers and written or read by hardware as necessary.
+ * The gxio library provides wrapper functions that manage the head and
+ * tail pointers for these rings, allowing the user to easily read or
+ * write packet descriptors.
+ *
+ * The initialization interface for ingress and egress rings is quite
+ * similar.  For example, to create an ingress queue, the user passes
+ * a ::gxio_mpipe_iqueue_t state object, a ring number from
+ * gxio_mpipe_alloc_notif_rings(), and the address of memory to hold a
+ * ring buffer to the gxio_mpipe_iqueue_init() function.  The function
+ * returns success when the state object has been initialized and the
+ * hardware configured to deliver packets to the specified ring
+ * buffer.  Similarly, gxio_mpipe_equeue_init() takes a
+ * ::gxio_mpipe_equeue_t state object, a ring number from
+ * gxio_mpipe_alloc_edma_rings(), and a shared memory buffer.
+ *
+ * @section gxio_mpipe_iqueue Working with Ingress Queues
+ *
+ * Once initialized, the gxio_mpipe_iqueue_t API provides two flows
+ * for getting the ::gxio_mpipe_idesc_t packet descriptor associated
+ * with incoming packets.  The simplest is to call
+ * gxio_mpipe_iqueue_get() or gxio_mpipe_iqueue_try_get().  These
+ * functions copy the oldest packet descriptor out of the NotifRing and
+ * into a descriptor provided by the caller.  They also immediately
+ * inform the hardware that a descriptor has been processed.
+ *
+ * For applications with stringent performance requirements, higher
+ * efficiency can be achieved by avoiding the packet descriptor copy
+ * and processing multiple descriptors at once.  The
+ * gxio_mpipe_iqueue_peek() and gxio_mpipe_iqueue_try_peek() functions
+ * allow such optimizations.  These functions provide a pointer to the
+ * next valid ingress descriptor in the NotifRing's shared memory ring
+ * buffer, and a count of how many contiguous descriptors are ready to
+ * be processed.  The application can then process any number of those
+ * descriptors in place, calling gxio_mpipe_iqueue_consume() to inform
+ * the hardware after each one has been processed.
+ *
+ * @section gxio_mpipe_equeue Working with Egress Queues
+ *
+ * Similarly, the egress queue API provides a high-performance
+ * interface plus a simple wrapper for use in posting
+ * ::gxio_mpipe_edesc_t egress packet descriptors.  The simple
+ * version, gxio_mpipe_equeue_put(), allows the programmer to wait for
+ * an eDMA ring slot to become available and write a single descriptor
+ * into the ring.
+ *
+ * Alternatively, you can reserve slots in the eDMA ring using
+ * gxio_mpipe_equeue_reserve() or gxio_mpipe_equeue_try_reserve(), and
+ * then fill in each slot using gxio_mpipe_equeue_put_at().  This
+ * capability can be used to amortize the cost of reserving slots
+ * across several packets.  It also allows gather operations to be
+ * performed on a shared equeue, by ensuring that the edescs for all
+ * the fragments are all contiguous in the eDMA ring.
+ *
+ * The gxio_mpipe_equeue_reserve() and gxio_mpipe_equeue_try_reserve()
+ * functions return a 63-bit "completion slot", which is actually a
+ * sequence number, the low bits of which indicate the ring buffer
+ * index and the high bits the number of times the application has
+ * gone around the egress ring buffer.  The extra bits allow an
+ * application to check for egress completion by calling
+ * gxio_mpipe_equeue_is_complete() to see whether a particular 'slot'
+ * number has finished.  Given the maximum packet rates of the Gx
+ * processor, the 63-bit slot number will never wrap.
+ *
+ * In practice, most applications use the ::gxio_mpipe_edesc_t::hwb
+ * bit to indicate that the buffers containing egress packet data
+ * should be pushed onto a buffer stack when egress is complete.  Such
+ * applications generally do not need to know when an egress operation
+ * completes (since there is no need to free a buffer post-egress),
+ * and thus can use the optimized gxio_mpipe_equeue_reserve_fast() or
+ * gxio_mpipe_equeue_try_reserve_fast() functions, which return a 24
+ * bit "slot", instead of a 63-bit "completion slot".
+ *
+ * Once a slot has been "reserved", it MUST be filled.  If the
+ * application reserves a slot and then decides that it does not
+ * actually need it, it can set the ::gxio_mpipe_edesc_t::ns (no send)
+ * bit on the descriptor passed to gxio_mpipe_equeue_put_at() to
+ * indicate that no data should be sent.  This technique can also be
+ * used to drop an incoming packet, instead of forwarding it, since
+ * any buffer will still be pushed onto the buffer stack when the
+ * egress descriptor is processed.
+ */
+
+/* A convenient interface to a NotifRing, for use by a single thread.
+ */
+typedef struct {
+
+       /* The context. */
+       gxio_mpipe_context_t *context;
+
+       /* The actual NotifRing. */
+       gxio_mpipe_idesc_t *idescs;
+
+       /* The number of entries. */
+       unsigned long num_entries;
+
+       /* The number of entries minus one. */
+       unsigned long mask_num_entries;
+
+       /* The log2() of the number of entries. */
+       unsigned long log2_num_entries;
+
+       /* The next entry. */
+       unsigned int head;
+
+       /* The NotifRing id. */
+       unsigned int ring;
+
+#ifdef __BIG_ENDIAN__
+       /* The number of byteswapped entries. */
+       unsigned int swapped;
+#endif
+
+} gxio_mpipe_iqueue_t;
+
+/* Initialize an "iqueue".
+ *
+ * Takes the iqueue plus the same args as gxio_mpipe_init_notif_ring().
+ */
+extern int gxio_mpipe_iqueue_init(gxio_mpipe_iqueue_t *iqueue,
+                                 gxio_mpipe_context_t *context,
+                                 unsigned int ring,
+                                 void *mem, size_t mem_size,
+                                 unsigned int mem_flags);
+
+/* Advance over some old entries in an iqueue.
+ *
+ * Please see the documentation for gxio_mpipe_iqueue_consume().
+ *
+ * @param iqueue An ingress queue initialized via gxio_mpipe_iqueue_init().
+ * @param count The number of entries to advance over.
+ */
+static inline void gxio_mpipe_iqueue_advance(gxio_mpipe_iqueue_t *iqueue,
+                                            int count)
+{
+       /* Advance with proper wrap. */
+       int head = iqueue->head + count;
+       iqueue->head =
+               (head & iqueue->mask_num_entries) +
+               (head >> iqueue->log2_num_entries);
+
+#ifdef __BIG_ENDIAN__
+       /* HACK: Track swapped entries. */
+       iqueue->swapped -= count;
+#endif
+}
+
+/* Release the ring and bucket for an old entry in an iqueue.
+ *
+ * Releasing the ring allows more packets to be delivered to the ring.
+ *
+ * Releasing the bucket allows flows using the bucket to be moved to a
+ * new ring when using GXIO_MPIPE_BUCKET_DYNAMIC_FLOW_AFFINITY.
+ *
+ * This function is shorthand for "gxio_mpipe_credit(iqueue->context,
+ * iqueue->ring, idesc->bucket_id, 1)", and it may be more convenient
+ * to make that underlying call, using those values, instead of
+ * tracking the entire "idesc".
+ *
+ * If packet processing is deferred, optimal performance requires that
+ * the releasing be deferred as well.
+ *
+ * Please see the documentation for gxio_mpipe_iqueue_consume().
+ *
+ * @param iqueue An ingress queue initialized via gxio_mpipe_iqueue_init().
+ * @param idesc The descriptor which was processed.
+ */
+static inline void gxio_mpipe_iqueue_release(gxio_mpipe_iqueue_t *iqueue,
+                                            gxio_mpipe_idesc_t *idesc)
+{
+       gxio_mpipe_credit(iqueue->context, iqueue->ring, idesc->bucket_id, 1);
+}
+
+/* Consume a packet from an "iqueue".
+ *
+ * After processing packets peeked at via gxio_mpipe_iqueue_peek()
+ * or gxio_mpipe_iqueue_try_peek(), you must call this function, or
+ * gxio_mpipe_iqueue_advance() plus gxio_mpipe_iqueue_release(), to
+ * advance over those entries, and release their rings and buckets.
+ *
+ * You may call this function as each packet is processed, or you can
+ * wait until several packets have been processed.
+ *
+ * Note that if you are using a single bucket, and you are handling
+ * batches of N packets, then you can replace several calls to this
+ * function with calls to "gxio_mpipe_iqueue_advance(iqueue, N)" and
+ * "gxio_mpipe_credit(iqueue->context, iqueue->ring, bucket, N)".
+ *
+ * Note that if your classifier sets "idesc->nr", then you should
+ * explicitly call "gxio_mpipe_iqueue_advance(iqueue, idesc)" plus
+ * "gxio_mpipe_credit(iqueue->context, iqueue->ring, -1, 1)", to
+ * avoid incorrectly crediting the (unused) bucket.
+ *
+ * @param iqueue An ingress queue initialized via gxio_mpipe_iqueue_init().
+ * @param idesc The descriptor which was processed.
+ */
+static inline void gxio_mpipe_iqueue_consume(gxio_mpipe_iqueue_t *iqueue,
+                                            gxio_mpipe_idesc_t *idesc)
+{
+       gxio_mpipe_iqueue_advance(iqueue, 1);
+       gxio_mpipe_iqueue_release(iqueue, idesc);
+}
+
+/* Peek at the next packet(s) in an "iqueue", without waiting.
+ *
+ * If no packets are available, fills idesc_ref with NULL, and then
+ * returns ::GXIO_MPIPE_ERR_IQUEUE_EMPTY.  Otherwise, fills idesc_ref
+ * with the address of the next valid packet descriptor, and returns
+ * the maximum number of valid descriptors which can be processed.
+ * You may process fewer descriptors if desired.
+ *
+ * Call gxio_mpipe_iqueue_consume() on each packet once it has been
+ * processed (or dropped), to allow more packets to be delivered.
+ *
+ * @param iqueue An ingress queue initialized via gxio_mpipe_iqueue_init().
+ * @param idesc_ref A pointer to a packet descriptor pointer.
+ * @return The (positive) number of packets which can be processed,
+ * or ::GXIO_MPIPE_ERR_IQUEUE_EMPTY if no packets are available.
+ */
+static inline int gxio_mpipe_iqueue_try_peek(gxio_mpipe_iqueue_t *iqueue,
+                                            gxio_mpipe_idesc_t **idesc_ref)
+{
+       gxio_mpipe_idesc_t *next;
+
+       uint64_t head = iqueue->head;
+       uint64_t tail = __gxio_mmio_read(iqueue->idescs);
+
+       /* Available entries. */
+       uint64_t avail =
+               (tail >= head) ? (tail - head) : (iqueue->num_entries - head);
+
+       if (avail == 0) {
+               *idesc_ref = NULL;
+               return GXIO_MPIPE_ERR_IQUEUE_EMPTY;
+       }
+
+       next = &iqueue->idescs[head];
+
+       /* ISSUE: Is this helpful? */
+       __insn_prefetch(next);
+
+#ifdef __BIG_ENDIAN__
+       /* HACK: Swap new entries directly in memory. */
+       {
+               int i, j;
+               for (i = iqueue->swapped; i < avail; i++) {
+                       for (j = 0; j < 8; j++)
+                               next[i].words[j] =
+                                       __builtin_bswap64(next[i].words[j]);
+               }
+               iqueue->swapped = avail;
+       }
+#endif
+
+       *idesc_ref = next;
+
+       return avail;
+}
+
+/* Drop a packet by pushing its buffer (if appropriate).
+ *
+ * NOTE: The caller must still call gxio_mpipe_iqueue_consume() if idesc
+ * came from gxio_mpipe_iqueue_try_peek() or gxio_mpipe_iqueue_peek().
+ *
+ * @param iqueue An ingress queue initialized via gxio_mpipe_iqueue_init().
+ * @param idesc A packet descriptor.
+ */
+static inline void gxio_mpipe_iqueue_drop(gxio_mpipe_iqueue_t *iqueue,
+                                         gxio_mpipe_idesc_t *idesc)
+{
+       /* FIXME: Handle "chaining" properly. */
+
+       if (!idesc->be) {
+               unsigned char *va = gxio_mpipe_idesc_get_va(idesc);
+               gxio_mpipe_push_buffer(iqueue->context, idesc->stack_idx, va);
+       }
+}
+
+/*****************************************************************
+ *                      Egress Queue Wrapper                      *
+ ******************************************************************/
+
+/* A convenient, thread-safe interface to an eDMA ring. */
+typedef struct {
+
+       /* State object for tracking head and tail pointers. */
+       __gxio_dma_queue_t dma_queue;
+
+       /* The ring entries. */
+       gxio_mpipe_edesc_t *edescs;
+
+       /* The number of entries minus one. */
+       unsigned long mask_num_entries;
+
+       /* The log2() of the number of entries. */
+       unsigned long log2_num_entries;
+
+} gxio_mpipe_equeue_t;
+
+/* Initialize an "equeue".
+ *
+ * Takes the equeue plus the same args as gxio_mpipe_init_edma_ring().
+ */
+extern int gxio_mpipe_equeue_init(gxio_mpipe_equeue_t *equeue,
+                                 gxio_mpipe_context_t *context,
+                                 unsigned int edma_ring_id,
+                                 unsigned int channel,
+                                 void *mem, unsigned int mem_size,
+                                 unsigned int mem_flags);
+
+/* Reserve completion slots for edescs.
+ *
+ * Use gxio_mpipe_equeue_put_at() to actually populate the slots.
+ *
+ * This function is slower than gxio_mpipe_equeue_reserve_fast(), but
+ * returns a full 64 bit completion slot, which can be used with
+ * gxio_mpipe_equeue_is_complete().
+ *
+ * @param equeue An egress queue initialized via gxio_mpipe_equeue_init().
+ * @param num Number of slots to reserve (must be non-zero).
+ * @return The first reserved completion slot, or a negative error code.
+ */
+static inline int64_t gxio_mpipe_equeue_reserve(gxio_mpipe_equeue_t *equeue,
+                                               unsigned int num)
+{
+       return __gxio_dma_queue_reserve_aux(&equeue->dma_queue, num, true);
+}
+
+/* Reserve completion slots for edescs, if possible.
+ *
+ * Use gxio_mpipe_equeue_put_at() to actually populate the slots.
+ *
+ * This function is slower than gxio_mpipe_equeue_try_reserve_fast(),
+ * but returns a full 64 bit completion slot, which can be used with
+ * gxio_mpipe_equeue_is_complete().
+ *
+ * @param equeue An egress queue initialized via gxio_mpipe_equeue_init().
+ * @param num Number of slots to reserve (must be non-zero).
+ * @return The first reserved completion slot, or a negative error code.
+ */
+static inline int64_t gxio_mpipe_equeue_try_reserve(gxio_mpipe_equeue_t
+                                                   *equeue, unsigned int num)
+{
+       return __gxio_dma_queue_reserve_aux(&equeue->dma_queue, num, false);
+}
+
+/* Reserve slots for edescs.
+ *
+ * Use gxio_mpipe_equeue_put_at() to actually populate the slots.
+ *
+ * This function is faster than gxio_mpipe_equeue_reserve(), but
+ * returns a 24 bit slot (instead of a 64 bit completion slot), which
+ * thus cannot be used with gxio_mpipe_equeue_is_complete().
+ *
+ * @param equeue An egress queue initialized via gxio_mpipe_equeue_init().
+ * @param num Number of slots to reserve (should be non-zero).
+ * @return The first reserved slot, or a negative error code.
+ */
+static inline int64_t gxio_mpipe_equeue_reserve_fast(gxio_mpipe_equeue_t
+                                                    *equeue, unsigned int num)
+{
+       return __gxio_dma_queue_reserve(&equeue->dma_queue, num, true, false);
+}
+
+/* Reserve slots for edescs, if possible.
+ *
+ * Use gxio_mpipe_equeue_put_at() to actually populate the slots.
+ *
+ * This function is faster than gxio_mpipe_equeue_try_reserve(), but
+ * returns a 24 bit slot (instead of a 64 bit completion slot), which
+ * thus cannot be used with gxio_mpipe_equeue_is_complete().
+ *
+ * @param equeue An egress queue initialized via gxio_mpipe_equeue_init().
+ * @param num Number of slots to reserve (should be non-zero).
+ * @return The first reserved slot, or a negative error code.
+ */
+static inline int64_t gxio_mpipe_equeue_try_reserve_fast(gxio_mpipe_equeue_t
+                                                        *equeue,
+                                                        unsigned int num)
+{
+       return __gxio_dma_queue_reserve(&equeue->dma_queue, num, false, false);
+}
+
+/*
+ * HACK: This helper function tricks gcc 4.6 into avoiding saving
+ * a copy of "edesc->words[0]" on the stack for no obvious reason.
+ */
+
+static inline void gxio_mpipe_equeue_put_at_aux(gxio_mpipe_equeue_t *equeue,
+                                               uint_reg_t ew[2],
+                                               unsigned long slot)
+{
+       unsigned long edma_slot = slot & equeue->mask_num_entries;
+       gxio_mpipe_edesc_t *edesc_p = &equeue->edescs[edma_slot];
+
+       /*
+        * ISSUE: Could set eDMA ring to be on generation 1 at start, which
+        * would avoid the negation here, perhaps allowing "__insn_bfins()".
+        */
+       ew[0] |= !((slot >> equeue->log2_num_entries) & 1);
+
+       /*
+        * NOTE: We use "__gxio_mpipe_write()", plus the fact that the eDMA
+        * queue alignment restrictions ensure that these two words are on
+        * the same cacheline, to force proper ordering between the stores.
+        */
+       __gxio_mmio_write64(&edesc_p->words[1], ew[1]);
+       __gxio_mmio_write64(&edesc_p->words[0], ew[0]);
+}
+
+/* Post an edesc to a given slot in an equeue.
+ *
+ * This function copies the supplied edesc into entry "slot mod N" in
+ * the underlying ring, setting the "gen" bit to the appropriate value
+ * based on "(slot mod N*2)", where "N" is the size of the ring.  Note
+ * that the higher bits of slot are unused, and thus, this function
+ * can handle "slots" as well as "completion slots".
+ *
+ * Normally this function is used to fill in slots reserved by
+ * gxio_mpipe_equeue_try_reserve(), gxio_mpipe_equeue_reserve(),
+ * gxio_mpipe_equeue_try_reserve_fast(), or
+ * gxio_mpipe_equeue_reserve_fast(),
+ *
+ * This function can also be used without "reserving" slots, if the
+ * application KNOWS that the ring can never overflow, for example, by
+ * pushing fewer buffers into the buffer stacks than there are total
+ * slots in the equeue, but this is NOT recommended.
+ *
+ * @param equeue An egress queue initialized via gxio_mpipe_equeue_init().
+ * @param edesc The egress descriptor to be posted.
+ * @param slot An egress slot (only the low bits are actually used).
+ */
+static inline void gxio_mpipe_equeue_put_at(gxio_mpipe_equeue_t *equeue,
+                                           gxio_mpipe_edesc_t edesc,
+                                           unsigned long slot)
+{
+       gxio_mpipe_equeue_put_at_aux(equeue, edesc.words, slot);
+}
+
+/* Post an edesc to the next slot in an equeue.
+ *
+ * This is a convenience wrapper around
+ * gxio_mpipe_equeue_reserve_fast() and gxio_mpipe_equeue_put_at().
+ *
+ * @param equeue An egress queue initialized via gxio_mpipe_equeue_init().
+ * @param edesc The egress descriptor to be posted.
+ * @return 0 on success.
+ */
+static inline int gxio_mpipe_equeue_put(gxio_mpipe_equeue_t *equeue,
+                                       gxio_mpipe_edesc_t edesc)
+{
+       int64_t slot = gxio_mpipe_equeue_reserve_fast(equeue, 1);
+       if (slot < 0)
+               return (int)slot;
+
+       gxio_mpipe_equeue_put_at(equeue, edesc, slot);
+
+       return 0;
+}
+
+/* Ask the mPIPE hardware to egress outstanding packets immediately.
+ *
+ * This call is not necessary, but may slightly reduce overall latency.
+ *
+ * Technically, you should flush all gxio_mpipe_equeue_put_at() writes
+ * to memory before calling this function, to ensure the descriptors
+ * are visible in memory before the mPIPE hardware actually looks for
+ * them.  But this should be very rare, and the only side effect would
+ * be increased latency, so it is up to the caller to decide whether
+ * or not to flush memory.
+ *
+ * @param equeue An egress queue initialized via gxio_mpipe_equeue_init().
+ */
+static inline void gxio_mpipe_equeue_flush(gxio_mpipe_equeue_t *equeue)
+{
+       /* Use "ring_idx = 0" and "count = 0" to "wake up" the eDMA ring. */
+       MPIPE_EDMA_POST_REGION_VAL_t val = { {0} };
+       /* Flush the write buffers. */
+       __insn_flushwb();
+       __gxio_mmio_write(equeue->dma_queue.post_region_addr, val.word);
+}
+
+/* Determine if a given edesc has been completed.
+ *
+ * Note that this function requires a "completion slot", and thus may
+ * NOT be used with a "slot" from gxio_mpipe_equeue_reserve_fast() or
+ * gxio_mpipe_equeue_try_reserve_fast().
+ *
+ * @param equeue An egress queue initialized via gxio_mpipe_equeue_init().
+ * @param completion_slot The completion slot used by the edesc.
+ * @param update If true, and the desc does not appear to have completed
+ * yet, then update any software cache of the hardware completion counter,
+ * and check again.  This should normally be true.
+ * @return True iff the given edesc has been completed.
+ */
+static inline int gxio_mpipe_equeue_is_complete(gxio_mpipe_equeue_t *equeue,
+                                               int64_t completion_slot,
+                                               int update)
+{
+       return __gxio_dma_queue_is_complete(&equeue->dma_queue,
+                                           completion_slot, update);
+}
+
+/*****************************************************************
+ *                        Link Management                         *
+ ******************************************************************/
+
+/*
+ *
+ * Functions for manipulating and sensing the state and configuration
+ * of physical network links.
+ *
+ * @section gxio_mpipe_link_perm Link Permissions
+ *
+ * Opening a link (with gxio_mpipe_link_open()) requests a set of link
+ * permissions, which control what may be done with the link, and potentially
+ * what permissions may be granted to other processes.
+ *
+ * Data permission allows the process to receive packets from the link by
+ * specifying the link's channel number in mPIPE packet distribution rules,
+ * and to send packets to the link by using the link's channel number as
+ * the target for an eDMA ring.
+ *
+ * Stats permission allows the process to retrieve link attributes (such as
+ * the speeds it is capable of running at, or whether it is currently up), and
+ * to read and write certain statistics-related registers in the link's MAC.
+ *
+ * Control permission allows the process to retrieve and modify link attributes
+ * (so that it may, for example, bring the link up and take it down), and
+ * read and write many registers in the link's MAC and PHY.
+ *
+ * Any permission may be requested as shared, which allows other processes
+ * to also request shared permission, or exclusive, which prevents other
+ * processes from requesting it.  In keeping with GXIO's typical usage in
+ * an embedded environment, the defaults for all permissions are shared.
+ *
+ * Permissions are granted on a first-come, first-served basis, so if two
+ * applications request an exclusive permission on the same link, the one
+ * to run first will win.  Note, however, that some system components, like
+ * the kernel Ethernet driver, may get an opportunity to open links before
+ * any applications run.
+ *
+ * @section gxio_mpipe_link_names Link Names
+ *
+ * Link names are of the form gbe<em>number</em> (for Gigabit Ethernet),
+ * xgbe<em>number</em> (for 10 Gigabit Ethernet), loop<em>number</em> (for
+ * internal mPIPE loopback), or ilk<em>number</em>/<em>channel</em>
+ * (for Interlaken links); for instance, gbe0, xgbe1, loop3, and
+ * ilk0/12 are all possible link names.  The correspondence between
+ * the link name and an mPIPE instance number or mPIPE channel number is
+ * system-dependent; all links will not exist on all systems, and the set
+ * of numbers used for a particular link type may not start at zero and may
+ * not be contiguous.  Use gxio_mpipe_link_enumerate() to retrieve the set of
+ * links which exist on a system, and always use gxio_mpipe_link_instance()
+ * to determine which mPIPE controls a particular link.
+ *
+ * Note that in some cases, links may share hardware, such as PHYs, or
+ * internal mPIPE buffers; in these cases, only one of the links may be
+ * opened at a time.  This is especially common with xgbe and gbe ports,
+ * since each xgbe port uses 4 SERDES lanes, each of which may also be
+ * configured as one gbe port.
+ *
+ * @section gxio_mpipe_link_states Link States
+ *
+ * The mPIPE link management model revolves around three different states,
+ * which are maintained for each link:
+ *
+ * 1. The <em>current</em> link state: is the link up now, and if so, at
+ *    what speed?
+ *
+ * 2. The <em>desired</em> link state: what do we want the link state to be?
+ *    The system is always working to make this state the current state;
+ *    thus, if the desired state is up, and the link is down, we'll be
+ *    constantly trying to bring it up, automatically.
+ *
+ * 3. The <em>possible</em> link state: what speeds are valid for this
+ *    particular link?  Or, in other words, what are the capabilities of
+ *    the link hardware?
+ *
+ * These link states are not, strictly speaking, related to application
+ * state; they may be manipulated at any time, whether or not the link
+ * is currently being used for data transfer.  However, for convenience,
+ * gxio_mpipe_link_open() and gxio_mpipe_link_close() (or application exit)
+ * can affect the link state.  These implicit link management operations
+ * may be modified or disabled by the use of link open flags.
+ *
+ * From an application, you can use gxio_mpipe_link_get_attr()
+ * and gxio_mpipe_link_set_attr() to manipulate the link states.
+ * gxio_mpipe_link_get_attr() with ::GXIO_MPIPE_LINK_POSSIBLE_STATE
+ * gets you the possible link state.  gxio_mpipe_link_get_attr() with
+ * ::GXIO_MPIPE_LINK_CURRENT_STATE gets you the current link state.
+ * Finally, gxio_mpipe_link_set_attr() and gxio_mpipe_link_get_attr()
+ * with ::GXIO_MPIPE_LINK_DESIRED_STATE allow you to modify or retrieve
+ * the desired link state.
+ *
+ * If you want to manage a link from a part of your application which isn't
+ * involved in packet processing, you can use the ::GXIO_MPIPE_LINK_NO_DATA
+ * flags on a gxio_mpipe_link_open() call.  This opens the link, but does
+ * not request data permission, so it does not conflict with any exclusive
+ * permissions which may be held by other processes.  You can then can use
+ * gxio_mpipe_link_get_attr() and gxio_mpipe_link_set_attr() on this link
+ * object to bring up or take down the link.
+ *
+ * Some links support link state bits which support various loopback
+ * modes. ::GXIO_MPIPE_LINK_LOOP_MAC tests datapaths within the Tile
+ * Processor itself; ::GXIO_MPIPE_LINK_LOOP_PHY tests the datapath between
+ * the Tile Processor and the external physical layer interface chip; and
+ * ::GXIO_MPIPE_LINK_LOOP_EXT tests the entire network datapath with the
+ * aid of an external loopback connector.  In addition to enabling hardware
+ * testing, such configuration can be useful for software testing, as well.
+ *
+ * When LOOP_MAC or LOOP_PHY is enabled, packets transmitted on a channel
+ * will be received by that channel, instead of being emitted on the
+ * physical link, and packets received on the physical link will be ignored.
+ * Other than that, all standard GXIO operations work as you might expect.
+ * Note that loopback operation requires that the link be brought up using
+ * one or more of the GXIO_MPIPE_LINK_SPEED_xxx link state bits.
+ *
+ * Those familiar with previous versions of the MDE on TILEPro hardware
+ * will notice significant similarities between the NetIO link management
+ * model and the mPIPE link management model.  However, the NetIO model
+ * was developed in stages, and some of its features -- for instance,
+ * the default setting of certain flags -- were shaped by the need to be
+ * compatible with previous versions of NetIO.  Since the features provided
+ * by the mPIPE hardware and the mPIPE GXIO library are significantly
+ * different than those provided by NetIO, in some cases, we have made
+ * different choices in the mPIPE link management API.  Thus, please read
+ * this documentation carefully before assuming that mPIPE link management
+ * operations are exactly equivalent to their NetIO counterparts.
+ */
+
+/* An object used to manage mPIPE link state and resources. */
+typedef struct {
+       /* The overall mPIPE context. */
+       gxio_mpipe_context_t *context;
+
+       /* The channel number used by this link. */
+       uint8_t channel;
+
+       /* The MAC index used by this link. */
+       uint8_t mac;
+} gxio_mpipe_link_t;
+
+/* Retrieve one of this system's legal link names, and its MAC address.
+ *
+ * @param index Link name index.  If a system supports N legal link names,
+ *  then indices between 0 and N - 1, inclusive, each correspond to one of
+ *  those names.  Thus, to retrieve all of a system's legal link names,
+ *  call this function in a loop, starting with an index of zero, and
+ *  incrementing it once per iteration until -1 is returned.
+ * @param link_name Pointer to the buffer which will receive the retrieved
+ *  link name.  The buffer should contain space for at least
+ *  ::GXIO_MPIPE_LINK_NAME_LEN bytes; the returned name, including the
+ *  terminating null byte, will be no longer than that.
+ * @param link_name Pointer to the buffer which will receive the retrieved
+ *  MAC address.  The buffer should contain space for at least 6 bytes.
+ * @return Zero if a link name was successfully retrieved; -1 if one was
+ *  not.
+ */
+extern int gxio_mpipe_link_enumerate_mac(int index, char *link_name,
+                                        uint8_t *mac_addr);
+
+/* Open an mPIPE link.
+ *
+ *  A link must be opened before it may be used to send or receive packets,
+ *  and before its state may be examined or changed.  Depending up on the
+ *  link's intended use, one or more link permissions may be requested via
+ *  the flags parameter; see @ref gxio_mpipe_link_perm.  In addition, flags
+ *  may request that the link's state be modified at open time.  See @ref
+ *  gxio_mpipe_link_states and @ref gxio_mpipe_link_open_flags for more detail.
+ *
+ * @param link A link state object, which will be initialized if this
+ *  function completes successfully.
+ * @param context An initialized mPIPE context.
+ * @param link_name Name of the link.
+ * @param flags Zero or more @ref gxio_mpipe_link_open_flags, ORed together.
+ * @return 0 if the link was successfully opened, or a negative error code.
+ *
+ */
+extern int gxio_mpipe_link_open(gxio_mpipe_link_t *link,
+                               gxio_mpipe_context_t *context,
+                               const char *link_name, unsigned int flags);
+
+/* Close an mPIPE link.
+ *
+ *  Closing a link makes it available for use by other processes.  Once
+ *  a link has been closed, packets may no longer be sent on or received
+ *  from the link, and its state may not be examined or changed.
+ *
+ * @param link A link state object, which will no longer be initialized
+ *  if this function completes successfully.
+ * @return 0 if the link was successfully closed, or a negative error code.
+ *
+ */
+extern int gxio_mpipe_link_close(gxio_mpipe_link_t *link);
+
+/* Return a link's channel number.
+ *
+ * @param link A properly initialized link state object.
+ * @return The channel number for the link.
+ */
+static inline int gxio_mpipe_link_channel(gxio_mpipe_link_t *link)
+{
+       return link->channel;
+}
+
+///////////////////////////////////////////////////////////////////
+//                             Timestamp                         //
+///////////////////////////////////////////////////////////////////
+
+/* Get the timestamp of mPIPE when this routine is called.
+ *
+ * @param context An initialized mPIPE context.
+ * @param ts A timespec structure to store the current clock.
+ * @return If the call was successful, zero; otherwise, a negative error
+ *  code.
+ */
+extern int gxio_mpipe_get_timestamp(gxio_mpipe_context_t *context,
+                                   struct timespec *ts);
+
+/* Set the timestamp of mPIPE.
+ *
+ * @param context An initialized mPIPE context.
+ * @param ts A timespec structure to store the requested clock.
+ * @return If the call was successful, zero; otherwise, a negative error
+ *  code.
+ */
+extern int gxio_mpipe_set_timestamp(gxio_mpipe_context_t *context,
+                                   const struct timespec *ts);
+
+/* Adjust the timestamp of mPIPE.
+ *
+ * @param context An initialized mPIPE context.
+ * @param delta A signed time offset to adjust, in nanoseconds.
+ * The absolute value of this parameter must be less than or
+ * equal to 1000000000.
+ * @return If the call was successful, zero; otherwise, a negative error
+ *  code.
+ */
+extern int gxio_mpipe_adjust_timestamp(gxio_mpipe_context_t *context,
+                                      int64_t delta);
+
+#endif /* !_GXIO_MPIPE_H_ */
diff --git a/arch/tile/include/gxio/trio.h b/arch/tile/include/gxio/trio.h
new file mode 100644 (file)
index 0000000..77b80cd
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/*
+ *
+ * An API for allocating, configuring, and manipulating TRIO hardware
+ * resources
+ */
+
+/*
+ *
+ * The TILE-Gx TRIO shim provides connections to external devices via
+ * PCIe or other transaction IO standards.  The gxio_trio_ API,
+ * declared in <gxio/trio.h>, allows applications to allocate and
+ * configure TRIO IO resources like DMA command rings, memory map
+ * windows, and device interrupts.  The following sections introduce
+ * the various components of the API.  We strongly recommend reading
+ * the TRIO section of the IO Device Guide (UG404) before working with
+ * this API.
+ *
+ * @section trio__ingress TRIO Ingress Hardware Resources
+ *
+ * The TRIO ingress hardware is responsible for examining incoming
+ * PCIe or StreamIO packets and choosing a processing mechanism based
+ * on the packets' bus address.  The gxio_trio_ API can be used to
+ * configure different handlers for different ranges of bus address
+ * space.  The user can configure "mapped memory" and "scatter queue"
+ * regions to match incoming packets within 4kB-aligned ranges of bus
+ * addresses.  Each range specifies a different set of mapping
+ * parameters to be applied when handling the ingress packet.  The
+ * following sections describe how to work with MapMem and scatter
+ * queue regions.
+ *
+ * @subsection trio__mapmem TRIO MapMem Regions
+ *
+ * TRIO mapped memory (or MapMem) regions allow the user to map
+ * incoming read and write requests directly to the application's
+ * memory space.  MapMem regions are allocated via
+ * gxio_trio_alloc_memory_maps().  Given an integer MapMem number,
+ * applications can use gxio_trio_init_memory_map() to specify the
+ * range of bus addresses that will match the region and the range of
+ * virtual addresses to which those packets will be applied.
+ *
+ * As with many other gxio APIs, the programmer must be sure to
+ * register memory pages that will be used with MapMem regions.  Pages
+ * can be registered with TRIO by allocating an ASID (address space
+ * identifier) and then using gxio_trio_register_page() to register up to
+ * 16 pages with the hardware.  The initialization functions for
+ * resources that require registered memory (MapMem, scatter queues,
+ * push DMA, and pull DMA) then take an 'asid' parameter in order to
+ * configure which set of registered pages is used by each resource.
+ *
+ * @subsection trio__scatter_queue TRIO Scatter Queues
+ *
+ * The TRIO shim's scatter queue regions allow users to dynamically
+ * map buffers from a large address space into a small range of bus
+ * addresses.  This is particularly helpful for PCIe endpoint devices,
+ * where the host generally limits the size of BARs to tens of
+ * megabytes.
+ *
+ * Each scatter queue consists of a memory map region, a queue of
+ * tile-side buffer VAs to be mapped to that region, and a bus-mapped
+ * "doorbell" register that the remote endpoint can write to trigger a
+ * dequeue of the current buffer VA, thus swapping in a new buffer.
+ * The VAs pushed onto a scatter queue must be 4kB aligned, so
+ * applications may need to use higher-level protocols to inform
+ * remote entities that they should apply some additional, sub-4kB
+ * offset when reading or writing the scatter queue region.  For more
+ * information, see the IO Device Guide (UG404).
+ *
+ * @section trio__egress TRIO Egress Hardware Resources
+ *
+ * The TRIO shim supports two mechanisms for egress packet generation:
+ * programmed IO (PIO) and push/pull DMA.  PIO allows applications to
+ * create MMIO mappings for PCIe or StreamIO address space, such that
+ * the application can generate word-sized read or write transactions
+ * by issuing load or store instructions.  Push and pull DMA are tuned
+ * for larger transactions; they use specialized hardware engines to
+ * transfer large blocks of data at line rate.
+ *
+ * @subsection trio__pio TRIO Programmed IO
+ *
+ * Programmed IO allows applications to create MMIO mappings for PCIe
+ * or StreamIO address space.  The hardware PIO regions support access
+ * to PCIe configuration, IO, and memory space, but the gxio_trio API
+ * only supports memory space accesses.  PIO regions are allocated
+ * with gxio_trio_alloc_pio_regions() and initialized via
+ * gxio_trio_init_pio_region().  Once a region is bound to a range of
+ * bus address via the initialization function, the application can
+ * use gxio_trio_map_pio_region() to create MMIO mappings from its VA
+ * space onto the range of bus addresses supported by the PIO region.
+ *
+ * @subsection trio_dma TRIO Push and Pull DMA
+ *
+ * The TRIO push and pull DMA engines allow users to copy blocks of
+ * data between application memory and the bus.  Push DMA generates
+ * write packets that copy from application memory to the bus and pull
+ * DMA generates read packets that copy from the bus into application
+ * memory.  The DMA engines are managed via an API that is very
+ * similar to the mPIPE eDMA interface.  For a detailed explanation of
+ * the eDMA queue API, see @ref gxio_mpipe_wrappers.
+ *
+ * Push and pull DMA queues are allocated via
+ * gxio_trio_alloc_push_dma_ring() / gxio_trio_alloc_pull_dma_ring().
+ * Once allocated, users generally use a ::gxio_trio_dma_queue_t
+ * object to manage the queue, providing easy wrappers for reserving
+ * command slots in the DMA command ring, filling those slots, and
+ * waiting for commands to complete.  DMA queues can be initialized
+ * via gxio_trio_init_push_dma_queue() or
+ * gxio_trio_init_pull_dma_queue().
+ *
+ * See @ref trio/push_dma/app.c for an example of how to use push DMA.
+ *
+ * @section trio_shortcomings Plans for Future API Revisions
+ *
+ * The simulation framework is incomplete.  Future features include:
+ *
+ * - Support for reset and deallocation of resources.
+ *
+ * - Support for pull DMA.
+ *
+ * - Support for interrupt regions and user-space interrupt delivery.
+ *
+ * - Support for getting BAR mappings and reserving regions of BAR
+ *   address space.
+ */
+#ifndef _GXIO_TRIO_H_
+#define _GXIO_TRIO_H_
+
+#include <linux/types.h>
+
+#include "common.h"
+#include "dma_queue.h"
+
+#include <arch/trio_constants.h>
+#include <arch/trio.h>
+#include <arch/trio_pcie_intfc.h>
+#include <arch/trio_pcie_rc.h>
+#include <arch/trio_shm.h>
+#include <hv/drv_trio_intf.h>
+#include <hv/iorpc.h>
+
+/* A context object used to manage TRIO hardware resources. */
+typedef struct {
+
+       /* File descriptor for calling up to Linux (and thus the HV). */
+       int fd;
+
+       /* The VA at which the MAC MMIO registers are mapped. */
+       char *mmio_base_mac;
+
+       /* The VA at which the PIO config space are mapped for each PCIe MAC.
+          Gx36 has max 3 PCIe MACs per TRIO shim. */
+       char *mmio_base_pio_cfg[TILEGX_TRIO_PCIES];
+
+#ifdef USE_SHARED_PCIE_CONFIG_REGION
+       /* Index of the shared PIO region for PCI config access. */
+       int pio_cfg_index;
+#else
+       /* Index of the PIO region for PCI config access per MAC. */
+       int pio_cfg_index[TILEGX_TRIO_PCIES];
+#endif
+
+       /*  The VA at which the push DMA MMIO registers are mapped. */
+       char *mmio_push_dma[TRIO_NUM_PUSH_DMA_RINGS];
+
+       /*  The VA at which the pull DMA MMIO registers are mapped. */
+       char *mmio_pull_dma[TRIO_NUM_PUSH_DMA_RINGS];
+
+       /* Application space ID. */
+       unsigned int asid;
+
+} gxio_trio_context_t;
+
+/* Command descriptor for push or pull DMA. */
+typedef TRIO_DMA_DESC_t gxio_trio_dma_desc_t;
+
+/* A convenient, thread-safe interface to an eDMA ring. */
+typedef struct {
+
+       /* State object for tracking head and tail pointers. */
+       __gxio_dma_queue_t dma_queue;
+
+       /* The ring entries. */
+       gxio_trio_dma_desc_t *dma_descs;
+
+       /* The number of entries minus one. */
+       unsigned long mask_num_entries;
+
+       /* The log2() of the number of entries. */
+       unsigned int log2_num_entries;
+
+} gxio_trio_dma_queue_t;
+
+/* Initialize a TRIO context.
+ *
+ * This function allocates a TRIO "service domain" and maps the MMIO
+ * registers into the the caller's VA space.
+ *
+ * @param trio_index Which TRIO shim; Gx36 must pass 0.
+ * @param context Context object to be initialized.
+ */
+extern int gxio_trio_init(gxio_trio_context_t *context,
+                         unsigned int trio_index);
+
+/* This indicates that an ASID hasn't been allocated. */
+#define GXIO_ASID_NULL -1
+
+/* Ordering modes for map memory regions and scatter queue regions. */
+typedef enum gxio_trio_order_mode_e {
+       /* Writes are not ordered.  Reads always wait for previous writes. */
+       GXIO_TRIO_ORDER_MODE_UNORDERED =
+               TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_UNORDERED,
+       /* Both writes and reads wait for previous transactions to complete. */
+       GXIO_TRIO_ORDER_MODE_STRICT =
+               TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_STRICT,
+       /* Writes are ordered unless the incoming packet has the
+          relaxed-ordering attributes set. */
+       GXIO_TRIO_ORDER_MODE_OBEY_PACKET =
+               TRIO_MAP_MEM_SETUP__ORDER_MODE_VAL_REL_ORD
+} gxio_trio_order_mode_t;
+
+/* Initialize a memory mapping region.
+ *
+ * @param context An initialized TRIO context.
+ * @param map A Memory map region allocated by gxio_trio_alloc_memory_map().
+ * @param target_mem VA of backing memory, should be registered via
+ *   gxio_trio_register_page() and aligned to 4kB.
+ * @param target_size Length of the memory mapping, must be a multiple
+ * of 4kB.
+ * @param asid ASID to be used for Tile-side address translation.
+ * @param mac MAC number.
+ * @param bus_address Bus address at which the mapping starts.
+ * @param order_mode Memory ordering mode for this mapping.
+ * @return Zero on success, else ::GXIO_TRIO_ERR_BAD_MEMORY_MAP,
+ * GXIO_TRIO_ERR_BAD_ASID, or ::GXIO_TRIO_ERR_BAD_BUS_RANGE.
+ */
+extern int gxio_trio_init_memory_map(gxio_trio_context_t *context,
+                                    unsigned int map, void *target_mem,
+                                    size_t target_size, unsigned int asid,
+                                    unsigned int mac, uint64_t bus_address,
+                                    gxio_trio_order_mode_t order_mode);
+
+/* Flags that can be passed to resource allocation functions. */
+enum gxio_trio_alloc_flags_e {
+       GXIO_TRIO_ALLOC_FIXED = HV_TRIO_ALLOC_FIXED,
+};
+
+/* Flags that can be passed to memory registration functions. */
+enum gxio_trio_mem_flags_e {
+       /* Do not fill L3 when writing, and invalidate lines upon egress. */
+       GXIO_TRIO_MEM_FLAG_NT_HINT = IORPC_MEM_BUFFER_FLAG_NT_HINT,
+
+       /* L3 cache fills should only populate IO cache ways. */
+       GXIO_TRIO_MEM_FLAG_IO_PIN = IORPC_MEM_BUFFER_FLAG_IO_PIN,
+};
+
+/* Flag indicating a request generator uses a special traffic
+    class. */
+#define GXIO_TRIO_FLAG_TRAFFIC_CLASS(N) HV_TRIO_FLAG_TC(N)
+
+/* Flag indicating a request generator uses a virtual function
+    number. */
+#define GXIO_TRIO_FLAG_VFUNC(N) HV_TRIO_FLAG_VFUNC(N)
+
+/*****************************************************************
+ *                       Memory Registration                      *
+ ******************************************************************/
+
+/* Allocate Application Space Identifiers (ASIDs).  Each ASID can
+ * register up to 16 page translations.  ASIDs are used by memory map
+ * regions, scatter queues, and DMA queues to translate application
+ * VAs into memory system PAs.
+ *
+ * @param context An initialized TRIO context.
+ * @param count Number of ASIDs required.
+ * @param first Index of first ASID if ::GXIO_TRIO_ALLOC_FIXED flag
+ *   is set, otherwise ignored.
+ * @param flags Flag bits, including bits from ::gxio_trio_alloc_flags_e.
+ * @return Index of first ASID, or ::GXIO_TRIO_ERR_NO_ASID if allocation
+ *   failed.
+ */
+extern int gxio_trio_alloc_asids(gxio_trio_context_t *context,
+                                unsigned int count, unsigned int first,
+                                unsigned int flags);
+
+#endif /* ! _GXIO_TRIO_H_ */
diff --git a/arch/tile/include/gxio/usb_host.h b/arch/tile/include/gxio/usb_host.h
new file mode 100644 (file)
index 0000000..a60a126
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+#ifndef _GXIO_USB_H_
+#define _GXIO_USB_H_
+
+#include "common.h"
+
+#include <hv/drv_usb_host_intf.h>
+#include <hv/iorpc.h>
+
+/*
+ *
+ * An API for manipulating general-purpose I/O pins.
+ */
+
+/*
+ *
+ * The USB shim allows access to the processor's Universal Serial Bus
+ * connections.
+ */
+
+/* A context object used to manage USB hardware resources. */
+typedef struct {
+
+       /* File descriptor for calling up to the hypervisor. */
+       int fd;
+
+       /* The VA at which our MMIO registers are mapped. */
+       char *mmio_base;
+} gxio_usb_host_context_t;
+
+/* Initialize a USB context.
+ *
+ *  A properly initialized context must be obtained before any of the other
+ *  gxio_usb_host routines may be used.
+ *
+ * @param context Pointer to a gxio_usb_host_context_t, which will be
+ *  initialized by this routine, if it succeeds.
+ * @param usb_index Index of the USB shim to use.
+ * @param is_ehci Nonzero to use the EHCI interface; zero to use the OHCI
+ *  intereface.
+ * @return Zero if the context was successfully initialized, else a
+ *  GXIO_ERR_xxx error code.
+ */
+extern int gxio_usb_host_init(gxio_usb_host_context_t * context, int usb_index,
+                             int is_ehci);
+
+/* Destroy a USB context.
+ *
+ *  Once destroyed, a context may not be used with any gxio_usb_host routines
+ *  other than gxio_usb_host_init().  After this routine returns, no further
+ *  interrupts or signals requested on this context will be delivered.  The
+ *  state and configuration of the pins which had been attached to this
+ *  context are unchanged by this operation.
+ *
+ * @param context Pointer to a gxio_usb_host_context_t.
+ * @return Zero if the context was successfully destroyed, else a
+ *  GXIO_ERR_xxx error code.
+ */
+extern int gxio_usb_host_destroy(gxio_usb_host_context_t * context);
+
+/* Retrieve the address of the shim's MMIO registers.
+ *
+ * @param context Pointer to a properly initialized gxio_usb_host_context_t.
+ * @return The address of the shim's MMIO registers.
+ */
+extern void *gxio_usb_host_get_reg_start(gxio_usb_host_context_t * context);
+
+/* Retrieve the length of the shim's MMIO registers.
+ *
+ * @param context Pointer to a properly initialized gxio_usb_host_context_t.
+ * @return The length of the shim's MMIO registers.
+ */
+extern size_t gxio_usb_host_get_reg_len(gxio_usb_host_context_t * context);
+
+#endif /* _GXIO_USB_H_ */
diff --git a/arch/tile/include/hv/drv_mpipe_intf.h b/arch/tile/include/hv/drv_mpipe_intf.h
new file mode 100644 (file)
index 0000000..6cdae3b
--- /dev/null
@@ -0,0 +1,602 @@
+/*
+ * Copyright 2011 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/**
+ * Interface definitions for the mpipe driver.
+ */
+
+#ifndef _SYS_HV_DRV_MPIPE_INTF_H
+#define _SYS_HV_DRV_MPIPE_INTF_H
+
+#include <arch/mpipe.h>
+#include <arch/mpipe_constants.h>
+
+
+/** Number of buffer stacks (32). */
+#define HV_MPIPE_NUM_BUFFER_STACKS \
+  (MPIPE_MMIO_INIT_DAT_GX36_1__BUFFER_STACK_MASK_WIDTH)
+
+/** Number of NotifRings (256). */
+#define HV_MPIPE_NUM_NOTIF_RINGS (MPIPE_NUM_NOTIF_RINGS)
+
+/** Number of NotifGroups (32). */
+#define HV_MPIPE_NUM_NOTIF_GROUPS (MPIPE_NUM_NOTIF_GROUPS)
+
+/** Number of buckets (4160). */
+#define HV_MPIPE_NUM_BUCKETS (MPIPE_NUM_BUCKETS)
+
+/** Number of "lo" buckets (4096). */
+#define HV_MPIPE_NUM_LO_BUCKETS 4096
+
+/** Number of "hi" buckets (64). */
+#define HV_MPIPE_NUM_HI_BUCKETS \
+  (HV_MPIPE_NUM_BUCKETS - HV_MPIPE_NUM_LO_BUCKETS)
+
+/** Number of edma rings (24). */
+#define HV_MPIPE_NUM_EDMA_RINGS \
+  (MPIPE_MMIO_INIT_DAT_GX36_1__EDMA_POST_MASK_WIDTH)
+
+
+
+
+/** A flag bit indicating a fixed resource allocation. */
+#define HV_MPIPE_ALLOC_FIXED 0x01
+
+/** Offset for the config register MMIO region. */
+#define HV_MPIPE_CONFIG_MMIO_OFFSET \
+  (MPIPE_MMIO_ADDR__REGION_VAL_CFG << MPIPE_MMIO_ADDR__REGION_SHIFT)
+
+/** Size of the config register MMIO region. */
+#define HV_MPIPE_CONFIG_MMIO_SIZE (64 * 1024)
+
+/** Offset for the config register MMIO region. */
+#define HV_MPIPE_FAST_MMIO_OFFSET \
+  (MPIPE_MMIO_ADDR__REGION_VAL_IDMA << MPIPE_MMIO_ADDR__REGION_SHIFT)
+
+/** Size of the fast register MMIO region (IDMA, EDMA, buffer stack). */
+#define HV_MPIPE_FAST_MMIO_SIZE \
+  ((MPIPE_MMIO_ADDR__REGION_VAL_BSM + 1 - MPIPE_MMIO_ADDR__REGION_VAL_IDMA) \
+   << MPIPE_MMIO_ADDR__REGION_SHIFT)
+
+
+/*
+ * Each type of resource allocation comes in quantized chunks, where
+ * XXX_BITS is the number of chunks, and XXX_RES_PER_BIT is the number
+ * of resources in each chunk.
+ */
+
+/** Number of buffer stack chunks available (32). */
+#define HV_MPIPE_ALLOC_BUFFER_STACKS_BITS \
+  MPIPE_MMIO_INIT_DAT_GX36_1__BUFFER_STACK_MASK_WIDTH
+
+/** Granularity of buffer stack allocation (1). */
+#define HV_MPIPE_ALLOC_BUFFER_STACKS_RES_PER_BIT \
+  (HV_MPIPE_NUM_BUFFER_STACKS / HV_MPIPE_ALLOC_BUFFER_STACKS_BITS)
+
+/** Number of NotifRing chunks available (32). */
+#define HV_MPIPE_ALLOC_NOTIF_RINGS_BITS \
+  MPIPE_MMIO_INIT_DAT_GX36_0__NOTIF_RING_MASK_WIDTH
+
+/** Granularity of NotifRing allocation (8). */
+#define HV_MPIPE_ALLOC_NOTIF_RINGS_RES_PER_BIT \
+  (HV_MPIPE_NUM_NOTIF_RINGS / HV_MPIPE_ALLOC_NOTIF_RINGS_BITS)
+
+/** Number of NotifGroup chunks available (32). */
+#define HV_MPIPE_ALLOC_NOTIF_GROUPS_BITS \
+  HV_MPIPE_NUM_NOTIF_GROUPS
+
+/** Granularity of NotifGroup allocation (1). */
+#define HV_MPIPE_ALLOC_NOTIF_GROUPS_RES_PER_BIT \
+  (HV_MPIPE_NUM_NOTIF_GROUPS / HV_MPIPE_ALLOC_NOTIF_GROUPS_BITS)
+
+/** Number of lo bucket chunks available (16). */
+#define HV_MPIPE_ALLOC_LO_BUCKETS_BITS \
+  MPIPE_MMIO_INIT_DAT_GX36_0__BUCKET_RELEASE_MASK_LO_WIDTH
+
+/** Granularity of lo bucket allocation (256). */
+#define HV_MPIPE_ALLOC_LO_BUCKETS_RES_PER_BIT \
+  (HV_MPIPE_NUM_LO_BUCKETS / HV_MPIPE_ALLOC_LO_BUCKETS_BITS)
+
+/** Number of hi bucket chunks available (16). */
+#define HV_MPIPE_ALLOC_HI_BUCKETS_BITS \
+  MPIPE_MMIO_INIT_DAT_GX36_0__BUCKET_RELEASE_MASK_HI_WIDTH
+
+/** Granularity of hi bucket allocation (4). */
+#define HV_MPIPE_ALLOC_HI_BUCKETS_RES_PER_BIT \
+  (HV_MPIPE_NUM_HI_BUCKETS / HV_MPIPE_ALLOC_HI_BUCKETS_BITS)
+
+/** Number of eDMA ring chunks available (24). */
+#define HV_MPIPE_ALLOC_EDMA_RINGS_BITS \
+  MPIPE_MMIO_INIT_DAT_GX36_1__EDMA_POST_MASK_WIDTH
+
+/** Granularity of eDMA ring allocation (1). */
+#define HV_MPIPE_ALLOC_EDMA_RINGS_RES_PER_BIT \
+  (HV_MPIPE_NUM_EDMA_RINGS / HV_MPIPE_ALLOC_EDMA_RINGS_BITS)
+
+
+
+
+/** Bit vector encoding which NotifRings are in a NotifGroup. */
+typedef struct
+{
+  /** The actual bits. */
+  uint64_t ring_mask[4];
+
+} gxio_mpipe_notif_group_bits_t;
+
+
+/** Another name for MPIPE_LBL_INIT_DAT_BSTS_TBL_t. */
+typedef MPIPE_LBL_INIT_DAT_BSTS_TBL_t gxio_mpipe_bucket_info_t;
+
+
+
+/** Eight buffer stack ids. */
+typedef struct
+{
+  /** The stacks. */
+  uint8_t stacks[8];
+
+} gxio_mpipe_rules_stacks_t;
+
+
+/** A destination mac address. */
+typedef struct
+{
+  /** The octets. */
+  uint8_t octets[6];
+
+} gxio_mpipe_rules_dmac_t;
+
+
+/** A vlan. */
+typedef uint16_t gxio_mpipe_rules_vlan_t;
+
+
+
+/** Maximum number of characters in a link name. */
+#define GXIO_MPIPE_LINK_NAME_LEN  32
+
+
+/** Structure holding a link name.  Only needed, and only typedef'ed,
+ *  because the IORPC stub generator only handles types which are single
+ *  words coming before the parameter name. */
+typedef struct
+{
+  /** The name itself. */
+  char name[GXIO_MPIPE_LINK_NAME_LEN];
+}
+_gxio_mpipe_link_name_t;
+
+/** Maximum number of characters in a symbol name. */
+#define GXIO_MPIPE_SYMBOL_NAME_LEN  128
+
+
+/** Structure holding a symbol name.  Only needed, and only typedef'ed,
+ *  because the IORPC stub generator only handles types which are single
+ *  words coming before the parameter name. */
+typedef struct
+{
+  /** The name itself. */
+  char name[GXIO_MPIPE_SYMBOL_NAME_LEN];
+}
+_gxio_mpipe_symbol_name_t;
+
+
+/** Structure holding a MAC address. */
+typedef struct
+{
+  /** The address. */
+  uint8_t mac[6];
+}
+_gxio_mpipe_link_mac_t;
+
+
+
+/** Request shared data permission -- that is, the ability to send and
+ *  receive packets -- on the specified link.  Other processes may also
+ *  request shared data permission on the same link.
+ *
+ *  No more than one of ::GXIO_MPIPE_LINK_DATA, ::GXIO_MPIPE_LINK_NO_DATA,
+ *  or ::GXIO_MPIPE_LINK_EXCL_DATA may be specifed in a gxio_mpipe_link_open()
+ *  call.  If none are specified, ::GXIO_MPIPE_LINK_DATA is assumed.
+ */
+#define GXIO_MPIPE_LINK_DATA               0x00000001UL
+
+/** Do not request data permission on the specified link.
+ *
+ *  No more than one of ::GXIO_MPIPE_LINK_DATA, ::GXIO_MPIPE_LINK_NO_DATA,
+ *  or ::GXIO_MPIPE_LINK_EXCL_DATA may be specifed in a gxio_mpipe_link_open()
+ *  call.  If none are specified, ::GXIO_MPIPE_LINK_DATA is assumed.
+ */
+#define GXIO_MPIPE_LINK_NO_DATA            0x00000002UL
+
+/** Request exclusive data permission -- that is, the ability to send and
+ *  receive packets -- on the specified link.  No other processes may
+ *  request data permission on this link, and if any process already has
+ *  data permission on it, this open will fail.
+ *
+ *  No more than one of ::GXIO_MPIPE_LINK_DATA, ::GXIO_MPIPE_LINK_NO_DATA,
+ *  or ::GXIO_MPIPE_LINK_EXCL_DATA may be specifed in a gxio_mpipe_link_open()
+ *  call.  If none are specified, ::GXIO_MPIPE_LINK_DATA is assumed.
+ */
+#define GXIO_MPIPE_LINK_EXCL_DATA          0x00000004UL
+
+/** Request shared stats permission -- that is, the ability to read and write
+ *  registers which contain link statistics, and to get link attributes --
+ *  on the specified link.  Other processes may also request shared stats
+ *  permission on the same link.
+ *
+ *  No more than one of ::GXIO_MPIPE_LINK_STATS, ::GXIO_MPIPE_LINK_NO_STATS,
+ *  or ::GXIO_MPIPE_LINK_EXCL_STATS may be specifed in a gxio_mpipe_link_open()
+ *  call.  If none are specified, ::GXIO_MPIPE_LINK_STATS is assumed.
+ */
+#define GXIO_MPIPE_LINK_STATS              0x00000008UL
+
+/** Do not request stats permission on the specified link.
+ *
+ *  No more than one of ::GXIO_MPIPE_LINK_STATS, ::GXIO_MPIPE_LINK_NO_STATS,
+ *  or ::GXIO_MPIPE_LINK_EXCL_STATS may be specifed in a gxio_mpipe_link_open()
+ *  call.  If none are specified, ::GXIO_MPIPE_LINK_STATS is assumed.
+ */
+#define GXIO_MPIPE_LINK_NO_STATS           0x00000010UL
+
+/** Request exclusive stats permission -- that is, the ability to read and
+ *  write registers which contain link statistics, and to get link
+ *  attributes -- on the specified link.  No other processes may request
+ *  stats permission on this link, and if any process already
+ *  has stats permission on it, this open will fail.
+ *
+ *  Requesting exclusive stats permission is normally a very bad idea, since
+ *  it prevents programs like mpipe-stat from providing information on this
+ *  link.  Applications should only do this if they use MAC statistics
+ *  registers, and cannot tolerate any of the clear-on-read registers being
+ *  reset by other statistics programs.
+ *
+ *  No more than one of ::GXIO_MPIPE_LINK_STATS, ::GXIO_MPIPE_LINK_NO_STATS,
+ *  or ::GXIO_MPIPE_LINK_EXCL_STATS may be specifed in a gxio_mpipe_link_open()
+ *  call.  If none are specified, ::GXIO_MPIPE_LINK_STATS is assumed.
+ */
+#define GXIO_MPIPE_LINK_EXCL_STATS         0x00000020UL
+
+/** Request shared control permission -- that is, the ability to modify link
+ *  attributes, and read and write MAC and MDIO registers -- on the
+ *  specified link.  Other processes may also request shared control
+ *  permission on the same link.
+ *
+ *  No more than one of ::GXIO_MPIPE_LINK_CTL, ::GXIO_MPIPE_LINK_NO_CTL,
+ *  or ::GXIO_MPIPE_LINK_EXCL_CTL may be specifed in a gxio_mpipe_link_open()
+ *  call.  If none are specified, ::GXIO_MPIPE_LINK_CTL is assumed.
+ */
+#define GXIO_MPIPE_LINK_CTL                0x00000040UL
+
+/** Do not request control permission on the specified link.
+ *
+ *  No more than one of ::GXIO_MPIPE_LINK_CTL, ::GXIO_MPIPE_LINK_NO_CTL,
+ *  or ::GXIO_MPIPE_LINK_EXCL_CTL may be specifed in a gxio_mpipe_link_open()
+ *  call.  If none are specified, ::GXIO_MPIPE_LINK_CTL is assumed.
+ */
+#define GXIO_MPIPE_LINK_NO_CTL             0x00000080UL
+
+/** Request exclusive control permission -- that is, the ability to modify
+ *  link attributes, and read and write MAC and MDIO registers -- on the
+ *  specified link.  No other processes may request control permission on
+ *  this link, and if any process already has control permission on it,
+ *  this open will fail.
+ *
+ *  Requesting exclusive control permission is not always a good idea, since
+ *  it prevents programs like mpipe-link from configuring the link.
+ *
+ *  No more than one of ::GXIO_MPIPE_LINK_CTL, ::GXIO_MPIPE_LINK_NO_CTL,
+ *  or ::GXIO_MPIPE_LINK_EXCL_CTL may be specifed in a gxio_mpipe_link_open()
+ *  call.  If none are specified, ::GXIO_MPIPE_LINK_CTL is assumed.
+ */
+#define GXIO_MPIPE_LINK_EXCL_CTL           0x00000100UL
+
+/** Set the desired state of the link to up, allowing any speeds which are
+ *  supported by the link hardware, as part of this open operation; do not
+ *  change the desired state of the link when it is closed or the process
+ *  exits.  No more than one of ::GXIO_MPIPE_LINK_AUTO_UP,
+ *  ::GXIO_MPIPE_LINK_AUTO_UPDOWN, ::GXIO_MPIPE_LINK_AUTO_DOWN, or
+ *  ::GXIO_MPIPE_LINK_AUTO_NONE may be specifed in a gxio_mpipe_link_open()
+ *  call.  If none are specified, ::GXIO_MPIPE_LINK_AUTO_UPDOWN is assumed.
+ */
+#define GXIO_MPIPE_LINK_AUTO_UP            0x00000200UL
+
+/** Set the desired state of the link to up, allowing any speeds which are
+ *  supported by the link hardware, as part of this open operation; when the
+ *  link is closed or this process exits, if no other process has the link
+ *  open, set the desired state of the link to down.  No more than one of
+ *  ::GXIO_MPIPE_LINK_AUTO_UP, ::GXIO_MPIPE_LINK_AUTO_UPDOWN,
+ *  ::GXIO_MPIPE_LINK_AUTO_DOWN, or ::GXIO_MPIPE_LINK_AUTO_NONE may be
+ *  specifed in a gxio_mpipe_link_open() call.  If none are specified,
+ *  ::GXIO_MPIPE_LINK_AUTO_UPDOWN is assumed.
+ */
+#define GXIO_MPIPE_LINK_AUTO_UPDOWN        0x00000400UL
+
+/** Do not change the desired state of the link as part of the open
+ *  operation; when the link is closed or this process exits, if no other
+ *  process has the link open, set the desired state of the link to down.
+ *  No more than one of ::GXIO_MPIPE_LINK_AUTO_UP,
+ *  ::GXIO_MPIPE_LINK_AUTO_UPDOWN, ::GXIO_MPIPE_LINK_AUTO_DOWN, or
+ *  ::GXIO_MPIPE_LINK_AUTO_NONE may be specifed in a gxio_mpipe_link_open()
+ *  call.  If none are specified, ::GXIO_MPIPE_LINK_AUTO_UPDOWN is assumed.
+ */
+#define GXIO_MPIPE_LINK_AUTO_DOWN          0x00000800UL
+
+/** Do not change the desired state of the link as part of the open
+ *  operation; do not change the desired state of the link when it is
+ *  closed or the process exits.  No more than one of
+ *  ::GXIO_MPIPE_LINK_AUTO_UP, ::GXIO_MPIPE_LINK_AUTO_UPDOWN,
+ *  ::GXIO_MPIPE_LINK_AUTO_DOWN, or ::GXIO_MPIPE_LINK_AUTO_NONE may be
+ *  specifed in a gxio_mpipe_link_open() call.  If none are specified,
+ *  ::GXIO_MPIPE_LINK_AUTO_UPDOWN is assumed.
+ */
+#define GXIO_MPIPE_LINK_AUTO_NONE          0x00001000UL
+
+/** Request that this open call not complete until the network link is up.
+ *  The process will wait as long as necessary for this to happen;
+ *  applications which wish to abandon waiting for the link after a
+ *  specific time period should not specify this flag when opening a link,
+ *  but should instead call gxio_mpipe_link_wait() afterward.  The link
+ *  must be opened with stats permission.  Note that this flag by itself
+ *  does not change the desired link state; if other open flags or previous
+ *  link state changes have not requested a desired state of up, the open
+ *  call will never complete.  This flag is not available to kernel
+ *  clients.
+ */
+#define GXIO_MPIPE_LINK_WAIT               0x00002000UL
+
+
+/*
+ * Note: link attributes must fit in 24 bits, since we use the top 8 bits
+ * of the IORPC offset word for the channel number.
+ */
+
+/** Determine whether jumbo frames may be received.  If this attribute's
+ *  value value is nonzero, the MAC will accept frames of up to 10240 bytes.
+ *  If the value is zero, the MAC will only accept frames of up to 1544
+ *  bytes.  The default value is zero. */
+#define GXIO_MPIPE_LINK_RECEIVE_JUMBO      0x010000
+
+/** Determine whether to send pause frames on this link if the mPIPE packet
+ *  FIFO is nearly full.  If the value is zero, pause frames are not sent.
+ *  If the value is nonzero, it is the delay value which will be sent in any
+ *  pause frames which are output, in units of 512 bit times.
+ *
+ *  Bear in mind that in almost all circumstances, the mPIPE packet FIFO
+ *  will never fill up, since mPIPE will empty it as fast as or faster than
+ *  the incoming data rate, by either delivering or dropping packets.  The
+ *  only situation in which this is not true is if the memory and cache
+ *  subsystem is extremely heavily loaded, and mPIPE cannot perform DMA of
+ *  packet data to memory in a timely fashion.  In particular, pause frames
+ *  will <em>not</em> be sent if packets cannot be delivered because
+ *  NotifRings are full, buckets are full, or buffers are not available in
+ *  a buffer stack. */
+#define GXIO_MPIPE_LINK_SEND_PAUSE         0x020000
+
+/** Determine whether to suspend output on the receipt of pause frames.
+ *  If the value is nonzero, mPIPE shim will suspend output on the link's
+ *  channel when a pause frame is received.  If the value is zero, pause
+ *  frames will be ignored.  The default value is zero. */
+#define GXIO_MPIPE_LINK_RECEIVE_PAUSE      0x030000
+
+/** Interface MAC address.  The value is a 6-byte MAC address, in the least
+ *  significant 48 bits of the value; in other words, an address which would
+ *  be printed as '12:34:56:78:90:AB' in IEEE 802 canonical format would
+ *  be returned as 0x12345678ab.
+ *
+ *  Depending upon the overall system design, a MAC address may or may not
+ *  be available for each interface.  Note that the interface's MAC address
+ *  does not limit the packets received on its channel, although the
+ *  classifier's rules could be configured to do that.  Similarly, the MAC
+ *  address is not used when transmitting packets, although applications
+ *  could certainly decide to use the assigned address as a source MAC
+ *  address when doing so.  This attribute may only be retrieved with
+ *  gxio_mpipe_link_get_attr(); it may not be modified.
+ */
+#define GXIO_MPIPE_LINK_MAC                0x040000
+
+/** Determine whether to discard egress packets on link down. If this value
+ *  is nonzero, packets sent on this link while the link is down will be
+ *  discarded.  If this value is zero, no packets will be sent on this link
+ *  while it is down.  The default value is one. */
+#define GXIO_MPIPE_LINK_DISCARD_IF_DOWN    0x050000
+
+/** Possible link state.  The value is a combination of link state flags,
+ *  ORed together, that indicate link modes which are actually supported by
+ *  the hardware.  This attribute may only be retrieved with
+ *  gxio_mpipe_link_get_attr(); it may not be modified. */
+#define GXIO_MPIPE_LINK_POSSIBLE_STATE     0x060000
+
+/** Current link state.  The value is a combination of link state flags,
+ *  ORed together, that indicate the current state of the hardware.  If the
+ *  link is down, the value ANDed with ::GXIO_MPIPE_LINK_SPEED will be zero;
+ *  if the link is up, the value ANDed with ::GXIO_MPIPE_LINK_SPEED will
+ *  result in exactly one of the speed values, indicating the current speed.
+ *  This attribute may only be retrieved with gxio_mpipe_link_get_attr(); it
+ *  may not be modified. */
+#define GXIO_MPIPE_LINK_CURRENT_STATE      0x070000
+
+/** Desired link state. The value is a conbination of flags, which specify
+ *  the desired state for the link.  With gxio_mpipe_link_set_attr(), this
+ *  will, in the background, attempt to bring up the link using whichever of
+ *  the requested flags are reasonable, or take down the link if the flags
+ *  are zero.  The actual link up or down operation may happen after this
+ *  call completes.  If the link state changes in the future, the system
+ *  will continue to try to get back to the desired link state; for
+ *  instance, if the link is brought up successfully, and then the network
+ *  cable is disconnected, the link will go down.  However, the desired
+ *  state of the link is still up, so if the cable is reconnected, the link
+ *  will be brought up again.
+ *
+ *  With gxio_mpipe_link_set_attr(), this will indicate the desired state
+ *  for the link, as set with a previous gxio_mpipe_link_set_attr() call,
+ *  or implicitly by a gxio_mpipe_link_open() or link close operation.
+ *  This may not reflect the current state of the link; to get that, use
+ *  ::GXIO_MPIPE_LINK_CURRENT_STATE.
+ */
+#define GXIO_MPIPE_LINK_DESIRED_STATE      0x080000
+
+
+
+/** Link can run, should run, or is running at 10 Mbps. */
+#define GXIO_MPIPE_LINK_10M        0x0000000000000001UL
+
+/** Link can run, should run, or is running at 100 Mbps. */
+#define GXIO_MPIPE_LINK_100M       0x0000000000000002UL
+
+/** Link can run, should run, or is running at 1 Gbps. */
+#define GXIO_MPIPE_LINK_1G         0x0000000000000004UL
+
+/** Link can run, should run, or is running at 10 Gbps. */
+#define GXIO_MPIPE_LINK_10G        0x0000000000000008UL
+
+/** Link can run, should run, or is running at 20 Gbps. */
+#define GXIO_MPIPE_LINK_20G        0x0000000000000010UL
+
+/** Link can run, should run, or is running at 25 Gbps. */
+#define GXIO_MPIPE_LINK_25G        0x0000000000000020UL
+
+/** Link can run, should run, or is running at 50 Gbps. */
+#define GXIO_MPIPE_LINK_50G        0x0000000000000040UL
+
+/** Link should run at the highest speed supported by the link and by
+ *  the device connected to the link.  Only usable as a value for
+ *  the link's desired state; never returned as a value for the current
+ *  or possible states. */
+#define GXIO_MPIPE_LINK_ANYSPEED   0x0000000000000800UL
+
+/** All legal link speeds.  This value is provided for use in extracting
+ *  the speed-related subset of the link state flags; it is not intended
+ *  to be set directly as a value for one of the GXIO_MPIPE_LINK_xxx_STATE
+ *  attributes.  A link is up or is requested to be up if its current or
+ *  desired state, respectively, ANDED with this value, is nonzero. */
+#define GXIO_MPIPE_LINK_SPEED_MASK 0x0000000000000FFFUL
+
+/** Link can run, should run, or is running in MAC loopback mode.  This
+ *  loops transmitted packets back to the receiver, inside the Tile
+ *  Processor. */
+#define GXIO_MPIPE_LINK_LOOP_MAC   0x0000000000001000UL
+
+/** Link can run, should run, or is running in PHY loopback mode.  This
+ *  loops transmitted packets back to the receiver, inside the external
+ *  PHY chip. */
+#define GXIO_MPIPE_LINK_LOOP_PHY   0x0000000000002000UL
+
+/** Link can run, should run, or is running in external loopback mode.
+ *  This requires that an external loopback plug be installed on the
+ *  Ethernet port.  Note that only some links require that this be
+ *  configured via the gxio_mpipe_link routines; other links can do
+ *  external loopack with the plug and no special configuration. */
+#define GXIO_MPIPE_LINK_LOOP_EXT   0x0000000000004000UL
+
+/** All legal loopback types. */
+#define GXIO_MPIPE_LINK_LOOP_MASK  0x000000000000F000UL
+
+/** Link can run, should run, or is running in full-duplex mode.
+ *  If neither ::GXIO_MPIPE_LINK_FDX nor ::GXIO_MPIPE_LINK_HDX are
+ *  specified in a set of desired state flags, both are assumed. */
+#define GXIO_MPIPE_LINK_FDX        0x0000000000010000UL
+
+/** Link can run, should run, or is running in half-duplex mode.
+ *  If neither ::GXIO_MPIPE_LINK_FDX nor ::GXIO_MPIPE_LINK_HDX are
+ *  specified in a set of desired state flags, both are assumed. */
+#define GXIO_MPIPE_LINK_HDX        0x0000000000020000UL
+
+
+/** An individual rule. */
+typedef struct
+{
+  /** The total size. */
+  uint16_t size;
+
+  /** The priority. */
+  int16_t priority;
+
+  /** The "headroom" in each buffer. */
+  uint8_t headroom;
+
+  /** The "tailroom" in each buffer. */
+  uint8_t tailroom;
+
+  /** The "capacity" of the largest buffer. */
+  uint16_t capacity;
+
+  /** The mask for converting a flow hash into a bucket. */
+  uint16_t bucket_mask;
+
+  /** The offset for converting a flow hash into a bucket. */
+  uint16_t bucket_first;
+
+  /** The buffer stack ids. */
+  gxio_mpipe_rules_stacks_t stacks;
+
+  /** The actual channels. */
+  uint32_t channel_bits;
+
+  /** The number of dmacs. */
+  uint16_t num_dmacs;
+
+  /** The number of vlans. */
+  uint16_t num_vlans;
+
+  /** The actual dmacs and vlans. */
+  uint8_t dmacs_and_vlans[];
+
+} gxio_mpipe_rules_rule_t;
+
+
+/** A list of classifier rules. */
+typedef struct
+{
+  /** The offset to the end of the current rule. */
+  uint16_t tail;
+
+  /** The offset to the start of the current rule. */
+  uint16_t head;
+
+  /** The actual rules. */
+  uint8_t rules[4096 - 4];
+
+} gxio_mpipe_rules_list_t;
+
+
+
+
+/** mPIPE statistics structure. These counters include all relevant
+ *  events occurring on all links within the mPIPE shim. */
+typedef struct
+{
+  /** Number of ingress packets dropped for any reason. */
+  uint64_t ingress_drops;
+  /** Number of ingress packets dropped because a buffer stack was empty. */
+  uint64_t ingress_drops_no_buf;
+  /** Number of ingress packets dropped or truncated due to lack of space in
+   *  the iPkt buffer. */
+  uint64_t ingress_drops_ipkt;
+  /** Number of ingress packets dropped by the classifier or load balancer */
+  uint64_t ingress_drops_cls_lb;
+  /** Total number of ingress packets. */
+  uint64_t ingress_packets;
+  /** Total number of egress packets. */
+  uint64_t egress_packets;
+  /** Total number of ingress bytes. */
+  uint64_t ingress_bytes;
+  /** Total number of egress bytes. */
+  uint64_t egress_bytes;
+}
+gxio_mpipe_stats_t;
+
+
+#endif /* _SYS_HV_DRV_MPIPE_INTF_H */
diff --git a/arch/tile/include/hv/drv_trio_intf.h b/arch/tile/include/hv/drv_trio_intf.h
new file mode 100644 (file)
index 0000000..ef9f3f5
--- /dev/null
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/**
+ * Interface definitions for the trio driver.
+ */
+
+#ifndef _SYS_HV_DRV_TRIO_INTF_H
+#define _SYS_HV_DRV_TRIO_INTF_H
+
+#include <arch/trio.h>
+
+/** The vendor ID for all Tilera processors. */
+#define TILERA_VENDOR_ID 0x1a41
+
+/** The device ID for the Gx36 processor. */
+#define TILERA_GX36_DEV_ID 0x0200
+
+/** Device ID for our internal bridge when running as RC. */
+#define TILERA_GX36_RC_DEV_ID 0x2000
+
+/** Maximum number of TRIO interfaces. */
+#define TILEGX_NUM_TRIO         2
+
+/** Gx36 has max 3 PCIe MACs per TRIO interface. */
+#define TILEGX_TRIO_PCIES       3
+
+/** Specify port properties for a PCIe MAC. */
+struct pcie_port_property
+{
+  /** If true, the link can be configured in PCIe root complex mode. */
+  uint8_t allow_rc: 1;
+
+  /** If true, the link can be configured in PCIe endpoint mode. */
+  uint8_t allow_ep: 1;
+
+  /** If true, the link can be configured in StreamIO mode. */
+  uint8_t allow_sio: 1;
+
+  /** If true, the link is allowed to support 1-lane operation. Software
+   *  will not consider it an error if the link comes up as a x1 link. */
+  uint8_t allow_x1: 1;
+
+  /** If true, the link is allowed to support 2-lane operation. Software
+   *  will not consider it an error if the link comes up as a x2 link. */
+  uint8_t allow_x2: 1;
+
+  /** If true, the link is allowed to support 4-lane operation. Software
+   *  will not consider it an error if the link comes up as a x4 link. */
+  uint8_t allow_x4: 1;
+
+  /** If true, the link is allowed to support 8-lane operation. Software
+   *  will not consider it an error if the link comes up as a x8 link. */
+  uint8_t allow_x8: 1;
+
+  /** Reserved. */
+  uint8_t reserved: 1;
+
+};
+
+/** Configurations can be issued to configure a char stream interrupt. */
+typedef enum pcie_stream_intr_config_sel_e
+{
+  /** Interrupt configuration for memory map regions. */
+  MEM_MAP_SEL,
+
+  /** Interrupt configuration for push DMAs. */
+  PUSH_DMA_SEL,
+
+  /** Interrupt configuration for pull DMAs. */
+  PULL_DMA_SEL,
+}
+pcie_stream_intr_config_sel_t;
+
+
+/** The mmap file offset (PA) of the TRIO config region. */
+#define HV_TRIO_CONFIG_OFFSET                                        \
+  ((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_CFG <<   \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT)
+
+/** The maximum size of the TRIO config region. */
+#define HV_TRIO_CONFIG_SIZE                                 \
+  (1ULL << TRIO_CFG_REGION_ADDR__REGION_SHIFT)
+
+/** Size of the config region mapped into client. We can't use
+ *  TRIO_MMIO_ADDRESS_SPACE__OFFSET_WIDTH because it
+ *  will require the kernel to allocate 4GB VA space
+ *  from the VMALLOC region which has a total range
+ *  of 4GB.
+ */
+#define HV_TRIO_CONFIG_IOREMAP_SIZE                            \
+  ((uint64_t) 1 << TRIO_CFG_REGION_ADDR__PROT_SHIFT)
+
+/** The mmap file offset (PA) of a scatter queue region. */
+#define HV_TRIO_SQ_OFFSET(queue)                                        \
+  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_MAP_SQ <<   \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
+   ((queue) << TRIO_MAP_SQ_REGION_ADDR__SQ_SEL_SHIFT))
+
+/** The maximum size of a scatter queue region. */
+#define HV_TRIO_SQ_SIZE                                 \
+  (1ULL << TRIO_MAP_SQ_REGION_ADDR__SQ_SEL_SHIFT)
+
+
+/** The "hardware MMIO region" of the first PIO region. */
+#define HV_TRIO_FIRST_PIO_REGION 8
+
+/** The mmap file offset (PA) of a PIO region. */
+#define HV_TRIO_PIO_OFFSET(region)                           \
+  (((unsigned long long)(region) + HV_TRIO_FIRST_PIO_REGION) \
+   << TRIO_PIO_REGIONS_ADDR__REGION_SHIFT)
+
+/** The maximum size of a PIO region. */
+#define HV_TRIO_PIO_SIZE (1ULL << TRIO_PIO_REGIONS_ADDR__ADDR_WIDTH)
+
+
+/** The mmap file offset (PA) of a push DMA region. */
+#define HV_TRIO_PUSH_DMA_OFFSET(ring)                                   \
+  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_PUSH_DMA << \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
+   ((ring) << TRIO_PUSH_DMA_REGION_ADDR__RING_SEL_SHIFT))
+
+/** The mmap file offset (PA) of a pull DMA region. */
+#define HV_TRIO_PULL_DMA_OFFSET(ring)                                   \
+  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_PULL_DMA << \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
+   ((ring) << TRIO_PULL_DMA_REGION_ADDR__RING_SEL_SHIFT))
+
+/** The maximum size of a DMA region. */
+#define HV_TRIO_DMA_REGION_SIZE                         \
+  (1ULL << TRIO_PUSH_DMA_REGION_ADDR__RING_SEL_SHIFT)
+
+
+/** The mmap file offset (PA) of a Mem-Map interrupt region. */
+#define HV_TRIO_MEM_MAP_INTR_OFFSET(map)                                 \
+  (((unsigned long long)TRIO_MMIO_ADDRESS_SPACE__REGION_VAL_MAP_MEM <<   \
+    TRIO_MMIO_ADDRESS_SPACE__REGION_SHIFT) |                            \
+   ((map) << TRIO_MAP_MEM_REGION_ADDR__MAP_SEL_SHIFT))
+
+/** The maximum size of a Mem-Map interrupt region. */
+#define HV_TRIO_MEM_MAP_INTR_SIZE                                 \
+  (1ULL << TRIO_MAP_MEM_REGION_ADDR__MAP_SEL_SHIFT)
+
+
+/** A flag bit indicating a fixed resource allocation. */
+#define HV_TRIO_ALLOC_FIXED 0x01
+
+/** TRIO requires that all mappings have 4kB aligned start addresses. */
+#define HV_TRIO_PAGE_SHIFT 12
+
+/** TRIO requires that all mappings have 4kB aligned start addresses. */
+#define HV_TRIO_PAGE_SIZE (1ull << HV_TRIO_PAGE_SHIFT)
+
+
+/* Specify all PCIe port properties for a TRIO. */
+struct pcie_trio_ports_property
+{
+  struct pcie_port_property ports[TILEGX_TRIO_PCIES];
+};
+
+/* Flags indicating traffic class. */
+#define HV_TRIO_FLAG_TC_SHIFT 4
+#define HV_TRIO_FLAG_TC_RMASK 0xf
+#define HV_TRIO_FLAG_TC(N) \
+  ((((N) & HV_TRIO_FLAG_TC_RMASK) + 1) << HV_TRIO_FLAG_TC_SHIFT)
+
+/* Flags indicating virtual functions. */
+#define HV_TRIO_FLAG_VFUNC_SHIFT 8
+#define HV_TRIO_FLAG_VFUNC_RMASK 0xff
+#define HV_TRIO_FLAG_VFUNC(N) \
+  ((((N) & HV_TRIO_FLAG_VFUNC_RMASK) + 1) << HV_TRIO_FLAG_VFUNC_SHIFT)
+
+
+/* Flag indicating an ordered PIO region. */
+#define HV_TRIO_PIO_FLAG_ORDERED (1 << 16)
+
+/* Flags indicating special types of PIO regions. */
+#define HV_TRIO_PIO_FLAG_SPACE_SHIFT 17
+#define HV_TRIO_PIO_FLAG_SPACE_MASK (0x3 << HV_TRIO_PIO_FLAG_SPACE_SHIFT)
+#define HV_TRIO_PIO_FLAG_CONFIG_SPACE (0x1 << HV_TRIO_PIO_FLAG_SPACE_SHIFT)
+#define HV_TRIO_PIO_FLAG_IO_SPACE (0x2 << HV_TRIO_PIO_FLAG_SPACE_SHIFT)
+
+
+#endif /* _SYS_HV_DRV_TRIO_INTF_H */
diff --git a/arch/tile/include/hv/drv_usb_host_intf.h b/arch/tile/include/hv/drv_usb_host_intf.h
new file mode 100644 (file)
index 0000000..24ce774
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/**
+ * Interface definitions for the USB host driver.
+ */
+
+#ifndef _SYS_HV_DRV_USB_HOST_INTF_H
+#define _SYS_HV_DRV_USB_HOST_INTF_H
+
+#include <arch/usb_host.h>
+
+
+/** Offset for the EHCI register MMIO region. */
+#define HV_USB_HOST_MMIO_OFFSET_EHCI ((uint64_t) USB_HOST_HCCAPBASE_REG)
+
+/** Offset for the OHCI register MMIO region. */
+#define HV_USB_HOST_MMIO_OFFSET_OHCI ((uint64_t) USB_HOST_OHCD_HC_REVISION_REG)
+
+/** Size of the register MMIO region.  This turns out to be the same for
+ *  both EHCI and OHCI. */
+#define HV_USB_HOST_MMIO_SIZE ((uint64_t) 0x1000)
+
+/** The number of service domains supported by the USB host shim. */
+#define HV_USB_HOST_NUM_SVC_DOM 1
+
+
+#endif /* _SYS_HV_DRV_USB_HOST_INTF_H */
diff --git a/arch/tile/include/hv/iorpc.h b/arch/tile/include/hv/iorpc.h
new file mode 100644 (file)
index 0000000..89c72a5
--- /dev/null
@@ -0,0 +1,714 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+#ifndef _HV_IORPC_H_
+#define _HV_IORPC_H_
+
+/**
+ *
+ * Error codes and struct definitions for the IO RPC library.
+ *
+ * The hypervisor's IO RPC component provides a convenient way for
+ * driver authors to proxy system calls between user space, linux, and
+ * the hypervisor driver.  The core of the system is a set of Python
+ * files that take ".idl" files as input and generates the following
+ * source code:
+ *
+ * - _rpc_call() routines for use in userspace IO libraries.  These
+ * routines take an argument list specified in the .idl file, pack the
+ * arguments in to a buffer, and read or write that buffer via the
+ * Linux iorpc driver.
+ *
+ * - dispatch_read() and dispatch_write() routines that hypervisor
+ * drivers can use to implement most of their dev_pread() and
+ * dev_pwrite() methods.  These routines decode the incoming parameter
+ * blob, permission check and translate parameters where appropriate,
+ * and then invoke a callback routine for whichever RPC call has
+ * arrived.  The driver simply implements the set of callback
+ * routines.
+ *
+ * The IO RPC system also includes the Linux 'iorpc' driver, which
+ * proxies calls between the userspace library and the hypervisor
+ * driver.  The Linux driver is almost entirely device agnostic; it
+ * watches for special flags indicating cases where a memory buffer
+ * address might need to be translated, etc.  As a result, driver
+ * writers can avoid many of the problem cases related to registering
+ * hardware resources like memory pages or interrupts.  However, the
+ * drivers must be careful to obey the conventions documented below in
+ * order to work properly with the generic Linux iorpc driver.
+ *
+ * @section iorpc_domains Service Domains
+ *
+ * All iorpc-based drivers must support a notion of service domains.
+ * A service domain is basically an application context - state
+ * indicating resources that are allocated to that particular app
+ * which it may access and (perhaps) other applications may not
+ * access.  Drivers can support any number of service domains they
+ * choose.  In some cases the design is limited by a number of service
+ * domains supported by the IO hardware; in other cases the service
+ * domains are a purely software concept and the driver chooses a
+ * maximum number of domains based on how much state memory it is
+ * willing to preallocate.
+ *
+ * For example, the mPIPE driver only supports as many service domains
+ * as are supported by the mPIPE hardware.  This limitation is
+ * required because the hardware implements its own MMIO protection
+ * scheme to allow large MMIO mappings while still protecting small
+ * register ranges within the page that should only be accessed by the
+ * hypervisor.
+ *
+ * In contrast, drivers with no hardware service domain limitations
+ * (for instance the TRIO shim) can implement an arbitrary number of
+ * service domains.  In these cases, each service domain is limited to
+ * a carefully restricted set of legal MMIO addresses if necessary to
+ * keep one application from corrupting another application's state.
+ *
+ * @section iorpc_conventions System Call Conventions
+ *
+ * The driver's open routine is responsible for allocating a new
+ * service domain for each hv_dev_open() call.  By convention, the
+ * return value from open() should be the service domain number on
+ * success, or GXIO_ERR_NO_SVC_DOM if no more service domains are
+ * available.
+ *
+ * The implementations of hv_dev_pread() and hv_dev_pwrite() are
+ * responsible for validating the devhdl value passed up by the
+ * client.  Since the device handle returned by hv_dev_open() should
+ * embed the positive service domain number, drivers should make sure
+ * that DRV_HDL2BITS(devhdl) is a legal service domain.  If the client
+ * passes an illegal service domain number, the routine should return
+ * GXIO_ERR_INVAL_SVC_DOM.  Once the service domain number has been
+ * validated, the driver can copy to/from the client buffer and call
+ * the dispatch_read() or dispatch_write() methods created by the RPC
+ * generator.
+ *
+ * The hv_dev_close() implementation should reset all service domain
+ * state and put the service domain back on a free list for
+ * reallocation by a future application.  In most cases, this will
+ * require executing a hardware reset or drain flow and denying any
+ * MMIO regions that were created for the service domain.
+ *
+ * @section iorpc_data Special Data Types
+ *
+ * The .idl file syntax allows the creation of syscalls with special
+ * parameters that require permission checks or translations as part
+ * of the system call path.  Because of limitations in the code
+ * generator, APIs are generally limited to just one of these special
+ * parameters per system call, and they are sometimes required to be
+ * the first or last parameter to the call.  Special parameters
+ * include:
+ *
+ * @subsection iorpc_mem_buffer MEM_BUFFER
+ *
+ * The MEM_BUFFER() datatype allows user space to "register" memory
+ * buffers with a device.  Registering memory accomplishes two tasks:
+ * Linux keeps track of all buffers that might be modified by a
+ * hardware device, and the hardware device drivers bind registered
+ * buffers to particular hardware resources like ingress NotifRings.
+ * The MEM_BUFFER() idl syntax can take extra flags like ALIGN_64KB,
+ * ALIGN_SELF_SIZE, and FLAGS indicating that memory buffers must have
+ * certain alignment or that the user should be able to pass a "memory
+ * flags" word specifying attributes like nt_hint or IO cache pinning.
+ * The parser will accept multiple MEM_BUFFER() flags.
+ *
+ * Implementations must obey the following conventions when
+ * registering memory buffers via the iorpc flow.  These rules are a
+ * result of the Linux driver implementation, which needs to keep
+ * track of how many times a particular page has been registered with
+ * the hardware so that it can release the page when all those
+ * registrations are cleared.
+ *
+ * - Memory registrations that refer to a resource which has already
+ * been bound must return GXIO_ERR_ALREADY_INIT.  Thus, it is an
+ * error to register memory twice without resetting (i.e. closing) the
+ * resource in between.  This convention keeps the Linux driver from
+ * having to track which particular devices a page is bound to.
+ *
+ * - At present, a memory registration is only cleared when the
+ * service domain is reset.  In this case, the Linux driver simply
+ * closes the HV device file handle and then decrements the reference
+ * counts of all pages that were previously registered with the
+ * device.
+ *
+ * - In the future, we may add a mechanism for unregistering memory.
+ * One possible implementation would require that the user specify
+ * which buffer is currently registered.  The HV would then verify
+ * that that page was actually the one currently mapped and return
+ * success or failure to Linux, which would then only decrement the
+ * page reference count if the addresses were mapped.  Another scheme
+ * might allow Linux to pass a token to the HV to be returned when the
+ * resource is unmapped.
+ *
+ * @subsection iorpc_interrupt INTERRUPT
+ *
+ * The INTERRUPT .idl datatype allows the client to bind hardware
+ * interrupts to a particular combination of IPI parameters - CPU, IPI
+ * PL, and event bit number.  This data is passed via a special
+ * datatype so that the Linux driver can validate the CPU and PL and
+ * the HV generic iorpc code can translate client CPUs to real CPUs.
+ *
+ * @subsection iorpc_pollfd_setup POLLFD_SETUP
+ *
+ * The POLLFD_SETUP .idl datatype allows the client to set up hardware
+ * interrupt bindings which are received by Linux but which are made
+ * visible to user processes as state transitions on a file descriptor;
+ * this allows user processes to use Linux primitives, such as poll(), to
+ * await particular hardware events.  This data is passed via a special
+ * datatype so that the Linux driver may recognize the pollable file
+ * descriptor and translate it to a set of interrupt target information,
+ * and so that the HV generic iorpc code can translate client CPUs to real
+ * CPUs.
+ *
+ * @subsection iorpc_pollfd POLLFD
+ *
+ * The POLLFD .idl datatype allows manipulation of hardware interrupt
+ * bindings set up via the POLLFD_SETUP datatype; common operations are
+ * resetting the state of the requested interrupt events, and unbinding any
+ * bound interrupts.  This data is passed via a special datatype so that
+ * the Linux driver may recognize the pollable file descriptor and
+ * translate it to an interrupt identifier previously supplied by the
+ * hypervisor as the result of an earlier pollfd_setup operation.
+ *
+ * @subsection iorpc_blob BLOB
+ *
+ * The BLOB .idl datatype allows the client to write an arbitrary
+ * length string of bytes up to the hypervisor driver.  This can be
+ * useful for passing up large, arbitrarily structured data like
+ * classifier programs.  The iorpc stack takes care of validating the
+ * buffer VA and CPA as the data passes up to the hypervisor.  Unlike
+ * MEM_BUFFER(), the buffer is not registered - Linux does not bump
+ * page refcounts and the HV driver should not reuse the buffer once
+ * the system call is complete.
+ *
+ * @section iorpc_translation Translating User Space Calls
+ *
+ * The ::iorpc_offset structure describes the formatting of the offset
+ * that is passed to pread() or pwrite() as part of the generated RPC code.
+ * When the user calls up to Linux, the rpc code fills in all the fields of
+ * the offset, including a 16-bit opcode, a 16 bit format indicator, and 32
+ * bits of user-specified "sub-offset".  The opcode indicates which syscall
+ * is being requested.  The format indicates whether there is a "prefix
+ * struct" at the start of the memory buffer passed to pwrite(), and if so
+ * what data is in that prefix struct.  These prefix structs are used to
+ * implement special datatypes like MEM_BUFFER() and INTERRUPT - we arrange
+ * to put data that needs translation and permission checks at the start of
+ * the buffer so that the Linux driver and generic portions of the HV iorpc
+ * code can easily access the data.  The 32 bits of user-specified
+ * "sub-offset" are most useful for pread() calls where the user needs to
+ * also pass in a few bits indicating which register to read, etc.
+ *
+ * The Linux iorpc driver watches for system calls that contain prefix
+ * structs so that it can translate parameters and bump reference
+ * counts as appropriate.  It does not (currently) have any knowledge
+ * of the per-device opcodes - it doesn't care what operation you're
+ * doing to mPIPE, so long as it can do all the generic book-keeping.
+ * The hv/iorpc.h header file defines all of the generic encoding bits
+ * needed to translate iorpc calls without knowing which particular
+ * opcode is being issued.
+ *
+ * @section iorpc_globals Global iorpc Calls
+ *
+ * Implementing mmap() required adding some special iorpc syscalls
+ * that are only called by the Linux driver, never by userspace.
+ * These include get_mmio_base() and check_mmio_offset().  These
+ * routines are described in globals.idl and must be included in every
+ * iorpc driver.  By providing these routines in every driver, Linux's
+ * mmap implementation can easily get the PTE bits it needs and
+ * validate the PA offset without needing to know the per-device
+ * opcodes to perform those tasks.
+ *
+ * @section iorpc_kernel Supporting gxio APIs in the Kernel
+ *
+ * The iorpc code generator also supports generation of kernel code
+ * implementing the gxio APIs.  This capability is currently used by
+ * the mPIPE network driver, and will likely be used by the TRIO root
+ * complex and endpoint drivers and perhaps an in-kernel crypto
+ * driver.  Each driver that wants to instantiate iorpc calls in the
+ * kernel needs to generate a kernel version of the generate rpc code
+ * and (probably) copy any related gxio source files into the kernel.
+ * The mPIPE driver provides a good example of this pattern.
+ */
+
+#ifdef __KERNEL__
+#include <linux/stddef.h>
+#else
+#include <stddef.h>
+#endif
+
+#if defined(__HV__)
+#include <hv/hypervisor.h>
+#elif defined(__KERNEL__)
+#include "hypervisor.h"
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#endif
+
+
+/** Code indicating translation services required within the RPC path.
+ * These indicate whether there is a translatable struct at the start
+ * of the RPC buffer and what information that struct contains.
+ */
+enum iorpc_format_e
+{
+  /** No translation required, no prefix struct. */
+  IORPC_FORMAT_NONE,
+
+  /** No translation required, no prefix struct, no access to this
+   *  operation from user space. */
+  IORPC_FORMAT_NONE_NOUSER,
+
+  /** Prefix struct contains user VA and size. */
+  IORPC_FORMAT_USER_MEM,
+
+  /** Prefix struct contains CPA, size, and homing bits. */
+  IORPC_FORMAT_KERNEL_MEM,
+
+  /** Prefix struct contains interrupt. */
+  IORPC_FORMAT_KERNEL_INTERRUPT,
+
+  /** Prefix struct contains user-level interrupt. */
+  IORPC_FORMAT_USER_INTERRUPT,
+
+  /** Prefix struct contains pollfd_setup (interrupt information). */
+  IORPC_FORMAT_KERNEL_POLLFD_SETUP,
+
+  /** Prefix struct contains user-level pollfd_setup (file descriptor). */
+  IORPC_FORMAT_USER_POLLFD_SETUP,
+
+  /** Prefix struct contains pollfd (interrupt cookie). */
+  IORPC_FORMAT_KERNEL_POLLFD,
+
+  /** Prefix struct contains user-level pollfd (file descriptor). */
+  IORPC_FORMAT_USER_POLLFD,
+};
+
+
+/** Generate an opcode given format and code. */
+#define IORPC_OPCODE(FORMAT, CODE) (((FORMAT) << 16) | (CODE))
+
+/** The offset passed through the read() and write() system calls
+    combines an opcode with 32 bits of user-specified offset. */
+union iorpc_offset
+{
+#ifndef __BIG_ENDIAN__
+  uint64_t offset;              /**< All bits. */
+
+  struct
+  {
+    uint16_t code;              /**< RPC code. */
+    uint16_t format;            /**< iorpc_format_e */
+    uint32_t sub_offset;        /**< caller-specified offset. */
+  };
+
+  uint32_t opcode;              /**< Opcode combines code & format. */
+#else
+  uint64_t offset;              /**< All bits. */
+
+  struct
+  {
+    uint32_t sub_offset;        /**< caller-specified offset. */
+    uint16_t format;            /**< iorpc_format_e */
+    uint16_t code;              /**< RPC code. */
+  };
+
+  struct
+  {
+    uint32_t padding;
+    uint32_t opcode;              /**< Opcode combines code & format. */
+  };
+#endif
+};
+
+
+/** Homing and cache hinting bits that can be used by IO devices. */
+struct iorpc_mem_attr
+{
+  unsigned int lotar_x:4;       /**< lotar X bits (or Gx page_mask). */
+  unsigned int lotar_y:4;       /**< lotar Y bits (or Gx page_offset). */
+  unsigned int hfh:1;           /**< Uses hash-for-home. */
+  unsigned int nt_hint:1;       /**< Non-temporal hint. */
+  unsigned int io_pin:1;        /**< Only fill 'IO' cache ways. */
+};
+
+/** Set the nt_hint bit. */
+#define IORPC_MEM_BUFFER_FLAG_NT_HINT (1 << 0)
+
+/** Set the IO pin bit. */
+#define IORPC_MEM_BUFFER_FLAG_IO_PIN (1 << 1)
+
+
+/** A structure used to describe memory registration.  Different
+    protection levels describe memory differently, so this union
+    contains all the different possible descriptions.  As a request
+    moves up the call chain, each layer translates from one
+    description format to the next.  In particular, the Linux iorpc
+    driver translates user VAs into CPAs and homing parameters. */
+union iorpc_mem_buffer
+{
+  struct
+  {
+    uint64_t va;                /**< User virtual address. */
+    uint64_t size;              /**< Buffer size. */
+    unsigned int flags;         /**< nt_hint, IO pin. */
+  }
+  user;                         /**< Buffer as described by user apps. */
+
+  struct
+  {
+    unsigned long long cpa;     /**< Client physical address. */
+#if defined(__KERNEL__) || defined(__HV__)
+    size_t size;                /**< Buffer size. */
+    HV_PTE pte;                 /**< PTE describing memory homing. */
+#else
+    uint64_t size;
+    uint64_t pte;
+#endif
+    unsigned int flags;         /**< nt_hint, IO pin. */
+  }
+  kernel;                       /**< Buffer as described by kernel. */
+
+  struct
+  {
+    unsigned long long pa;      /**< Physical address. */
+    size_t size;                /**< Buffer size. */
+    struct iorpc_mem_attr attr;      /**< Homing and locality hint bits. */
+  }
+  hv;                           /**< Buffer parameters for HV driver. */
+};
+
+
+/** A structure used to describe interrupts.  The format differs slightly
+ *  for user and kernel interrupts.  As with the mem_buffer_t, translation
+ *  between the formats is done at each level. */
+union iorpc_interrupt
+{
+  struct
+  {
+    int cpu;   /**< CPU. */
+    int event; /**< evt_num */
+  }
+  user;        /**< Interrupt as described by user applications. */
+
+  struct
+  {
+    int x;     /**< X coord. */
+    int y;     /**< Y coord. */
+    int ipi;   /**< int_num */
+    int event; /**< evt_num */
+  }
+  kernel;      /**< Interrupt as described by the kernel. */
+
+};
+
+
+/** A structure used to describe interrupts used with poll().  The format
+ *  differs significantly for requests from user to kernel, and kernel to
+ *  hypervisor.  As with the mem_buffer_t, translation between the formats
+ *  is done at each level. */
+union iorpc_pollfd_setup
+{
+  struct
+  {
+    int fd;    /**< Pollable file descriptor. */
+  }
+  user;        /**< pollfd_setup as described by user applications. */
+
+  struct
+  {
+    int x;     /**< X coord. */
+    int y;     /**< Y coord. */
+    int ipi;   /**< int_num */
+    int event; /**< evt_num */
+  }
+  kernel;      /**< pollfd_setup as described by the kernel. */
+
+};
+
+
+/** A structure used to describe previously set up interrupts used with
+ *  poll().  The format differs significantly for requests from user to
+ *  kernel, and kernel to hypervisor.  As with the mem_buffer_t, translation
+ *  between the formats is done at each level. */
+union iorpc_pollfd
+{
+  struct
+  {
+    int fd;    /**< Pollable file descriptor. */
+  }
+  user;        /**< pollfd as described by user applications. */
+
+  struct
+  {
+    int cookie; /**< hv cookie returned by the pollfd_setup operation. */
+  }
+  kernel;      /**< pollfd as described by the kernel. */
+
+};
+
+
+/** The various iorpc devices use error codes from -1100 to -1299.
+ *
+ * This range is distinct from netio (-700 to -799), the hypervisor
+ * (-800 to -899), tilepci (-900 to -999), ilib (-1000 to -1099),
+ * gxcr (-1300 to -1399) and gxpci (-1400 to -1499).
+ */
+enum gxio_err_e {
+
+  /** Largest iorpc error number. */
+  GXIO_ERR_MAX = -1101,
+
+
+  /********************************************************/
+  /*                   Generic Error Codes                */
+  /********************************************************/
+
+  /** Bad RPC opcode - possible version incompatibility. */
+  GXIO_ERR_OPCODE = -1101,
+
+  /** Invalid parameter. */
+  GXIO_ERR_INVAL = -1102,
+
+  /** Memory buffer did not meet alignment requirements. */
+  GXIO_ERR_ALIGNMENT = -1103,
+
+  /** Memory buffers must be coherent and cacheable. */
+  GXIO_ERR_COHERENCE = -1104,
+
+  /** Resource already initialized. */
+  GXIO_ERR_ALREADY_INIT = -1105,
+
+  /** No service domains available. */
+  GXIO_ERR_NO_SVC_DOM = -1106,
+
+  /** Illegal service domain number. */
+  GXIO_ERR_INVAL_SVC_DOM = -1107,
+
+  /** Illegal MMIO address. */
+  GXIO_ERR_MMIO_ADDRESS = -1108,
+
+  /** Illegal interrupt binding. */
+  GXIO_ERR_INTERRUPT = -1109,
+
+  /** Unreasonable client memory. */
+  GXIO_ERR_CLIENT_MEMORY = -1110,
+
+  /** No more IOTLB entries. */
+  GXIO_ERR_IOTLB_ENTRY = -1111,
+
+  /** Invalid memory size. */
+  GXIO_ERR_INVAL_MEMORY_SIZE = -1112,
+
+  /** Unsupported operation. */
+  GXIO_ERR_UNSUPPORTED_OP = -1113,
+
+  /** Insufficient DMA credits. */
+  GXIO_ERR_DMA_CREDITS = -1114,
+
+  /** Operation timed out. */
+  GXIO_ERR_TIMEOUT = -1115,
+
+  /** No such device or object. */
+  GXIO_ERR_NO_DEVICE = -1116,
+
+  /** Device or resource busy. */
+  GXIO_ERR_BUSY = -1117,
+
+  /** I/O error. */
+  GXIO_ERR_IO = -1118,
+
+  /** Permissions error. */
+  GXIO_ERR_PERM = -1119,
+
+
+
+  /********************************************************/
+  /*                 Test Device Error Codes              */
+  /********************************************************/
+
+  /** Illegal register number. */
+  GXIO_TEST_ERR_REG_NUMBER = -1120,
+
+  /** Illegal buffer slot. */
+  GXIO_TEST_ERR_BUFFER_SLOT = -1121,
+
+
+  /********************************************************/
+  /*                    MPIPE Error Codes                 */
+  /********************************************************/
+
+
+  /** Invalid buffer size. */
+  GXIO_MPIPE_ERR_INVAL_BUFFER_SIZE = -1131,
+
+  /** Cannot allocate buffer stack. */
+  GXIO_MPIPE_ERR_NO_BUFFER_STACK = -1140,
+
+  /** Invalid buffer stack number. */
+  GXIO_MPIPE_ERR_BAD_BUFFER_STACK = -1141,
+
+  /** Cannot allocate NotifRing. */
+  GXIO_MPIPE_ERR_NO_NOTIF_RING = -1142,
+
+  /** Invalid NotifRing number. */
+  GXIO_MPIPE_ERR_BAD_NOTIF_RING = -1143,
+
+  /** Cannot allocate NotifGroup. */
+  GXIO_MPIPE_ERR_NO_NOTIF_GROUP = -1144,
+
+  /** Invalid NotifGroup number. */
+  GXIO_MPIPE_ERR_BAD_NOTIF_GROUP = -1145,
+
+  /** Cannot allocate bucket. */
+  GXIO_MPIPE_ERR_NO_BUCKET = -1146,
+
+  /** Invalid bucket number. */
+  GXIO_MPIPE_ERR_BAD_BUCKET = -1147,
+
+  /** Cannot allocate eDMA ring. */
+  GXIO_MPIPE_ERR_NO_EDMA_RING = -1148,
+
+  /** Invalid eDMA ring number. */
+  GXIO_MPIPE_ERR_BAD_EDMA_RING = -1149,
+
+  /** Invalid channel number. */
+  GXIO_MPIPE_ERR_BAD_CHANNEL = -1150,
+
+  /** Bad configuration. */
+  GXIO_MPIPE_ERR_BAD_CONFIG = -1151,
+
+  /** Empty iqueue. */
+  GXIO_MPIPE_ERR_IQUEUE_EMPTY = -1152,
+
+  /** Empty rules. */
+  GXIO_MPIPE_ERR_RULES_EMPTY = -1160,
+
+  /** Full rules. */
+  GXIO_MPIPE_ERR_RULES_FULL = -1161,
+
+  /** Corrupt rules. */
+  GXIO_MPIPE_ERR_RULES_CORRUPT = -1162,
+
+  /** Invalid rules. */
+  GXIO_MPIPE_ERR_RULES_INVALID = -1163,
+
+  /** Classifier is too big. */
+  GXIO_MPIPE_ERR_CLASSIFIER_TOO_BIG = -1170,
+
+  /** Classifier is too complex. */
+  GXIO_MPIPE_ERR_CLASSIFIER_TOO_COMPLEX = -1171,
+
+  /** Classifier has bad header. */
+  GXIO_MPIPE_ERR_CLASSIFIER_BAD_HEADER = -1172,
+
+  /** Classifier has bad contents. */
+  GXIO_MPIPE_ERR_CLASSIFIER_BAD_CONTENTS = -1173,
+
+  /** Classifier encountered invalid symbol. */
+  GXIO_MPIPE_ERR_CLASSIFIER_INVAL_SYMBOL = -1174,
+
+  /** Classifier encountered invalid bounds. */
+  GXIO_MPIPE_ERR_CLASSIFIER_INVAL_BOUNDS = -1175,
+
+  /** Classifier encountered invalid relocation. */
+  GXIO_MPIPE_ERR_CLASSIFIER_INVAL_RELOCATION = -1176,
+
+  /** Classifier encountered undefined symbol. */
+  GXIO_MPIPE_ERR_CLASSIFIER_UNDEF_SYMBOL = -1177,
+
+
+  /********************************************************/
+  /*                    TRIO  Error Codes                 */
+  /********************************************************/
+
+  /** Cannot allocate memory map region. */
+  GXIO_TRIO_ERR_NO_MEMORY_MAP = -1180,
+
+  /** Invalid memory map region number. */
+  GXIO_TRIO_ERR_BAD_MEMORY_MAP = -1181,
+
+  /** Cannot allocate scatter queue. */
+  GXIO_TRIO_ERR_NO_SCATTER_QUEUE = -1182,
+
+  /** Invalid scatter queue number. */
+  GXIO_TRIO_ERR_BAD_SCATTER_QUEUE = -1183,
+
+  /** Cannot allocate push DMA ring. */
+  GXIO_TRIO_ERR_NO_PUSH_DMA_RING = -1184,
+
+  /** Invalid push DMA ring index. */
+  GXIO_TRIO_ERR_BAD_PUSH_DMA_RING = -1185,
+
+  /** Cannot allocate pull DMA ring. */
+  GXIO_TRIO_ERR_NO_PULL_DMA_RING = -1186,
+
+  /** Invalid pull DMA ring index. */
+  GXIO_TRIO_ERR_BAD_PULL_DMA_RING = -1187,
+
+  /** Cannot allocate PIO region. */
+  GXIO_TRIO_ERR_NO_PIO = -1188,
+
+  /** Invalid PIO region index. */
+  GXIO_TRIO_ERR_BAD_PIO = -1189,
+
+  /** Cannot allocate ASID. */
+  GXIO_TRIO_ERR_NO_ASID = -1190,
+
+  /** Invalid ASID. */
+  GXIO_TRIO_ERR_BAD_ASID = -1191,
+
+
+  /********************************************************/
+  /*                    MICA Error Codes                  */
+  /********************************************************/
+
+  /** No such accelerator type. */
+  GXIO_MICA_ERR_BAD_ACCEL_TYPE = -1220,
+
+  /** Cannot allocate context. */
+  GXIO_MICA_ERR_NO_CONTEXT = -1221,
+
+  /** PKA command queue is full, can't add another command. */
+  GXIO_MICA_ERR_PKA_CMD_QUEUE_FULL = -1222,
+
+  /** PKA result queue is empty, can't get a result from the queue. */
+  GXIO_MICA_ERR_PKA_RESULT_QUEUE_EMPTY = -1223,
+
+  /********************************************************/
+  /*                    GPIO Error Codes                  */
+  /********************************************************/
+
+  /** Pin not available.  Either the physical pin does not exist, or
+   *  it is reserved by the hypervisor for system usage. */
+  GXIO_GPIO_ERR_PIN_UNAVAILABLE = -1240,
+
+  /** Pin busy.  The pin exists, and is available for use via GXIO, but
+   *  it has been attached by some other process or driver. */
+  GXIO_GPIO_ERR_PIN_BUSY = -1241,
+
+  /** Cannot access unattached pin.  One or more of the pins being
+   *  manipulated by this call are not attached to the requesting
+   *  context. */
+  GXIO_GPIO_ERR_PIN_UNATTACHED = -1242,
+
+  /** Invalid I/O mode for pin.  The wiring of the pin in the system
+   *  is such that the I/O mode or electrical control parameters
+   *  requested could cause damage. */
+  GXIO_GPIO_ERR_PIN_INVALID_MODE = -1243,
+
+  /** Smallest iorpc error number. */
+  GXIO_ERR_MIN = -1299
+};
+
+
+#endif /* !_HV_IORPC_H_ */
index 5de99248d8df1a018aa200f48b249765690bc383..5334be8e253822c6c1b14741dc39d9ac49c4fdb7 100644 (file)
@@ -14,4 +14,9 @@ obj-$(CONFIG_SMP)             += smpboot.o smp.o tlb.o
 obj-$(CONFIG_MODULES)          += module.o
 obj-$(CONFIG_EARLY_PRINTK)     += early_printk.o
 obj-$(CONFIG_KEXEC)            += machine_kexec.o relocate_kernel_$(BITS).o
+ifdef CONFIG_TILEGX
+obj-$(CONFIG_PCI)              += pci_gx.o
+else
 obj-$(CONFIG_PCI)              += pci.o
+endif
+obj-$(CONFIG_TILE_USB)         += usb.o
index b3ed19f8779c4a9058ea818bc8fb31a6a75ef34b..b9fe80ec108989fa341060542816d9760fd62d63 100644 (file)
@@ -14,6 +14,7 @@
 
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <linux/swiotlb.h>
 #include <linux/vmalloc.h>
 #include <linux/export.h>
 #include <asm/tlbflush.h>
 /* Generic DMA mapping functions: */
 
 /*
- * Allocate what Linux calls "coherent" memory, which for us just
- * means uncached.
+ * Allocate what Linux calls "coherent" memory.  On TILEPro this is
+ * uncached memory; on TILE-Gx it is hash-for-home memory.
  */
-void *dma_alloc_coherent(struct device *dev,
-                        size_t size,
-                        dma_addr_t *dma_handle,
-                        gfp_t gfp)
+#ifdef __tilepro__
+#define PAGE_HOME_DMA PAGE_HOME_UNCACHED
+#else
+#define PAGE_HOME_DMA PAGE_HOME_HASH
+#endif
+
+static void *tile_dma_alloc_coherent(struct device *dev, size_t size,
+                                    dma_addr_t *dma_handle, gfp_t gfp,
+                                    struct dma_attrs *attrs)
 {
        u64 dma_mask = dev->coherent_dma_mask ?: DMA_BIT_MASK(32);
        int node = dev_to_node(dev);
@@ -39,39 +45,42 @@ void *dma_alloc_coherent(struct device *dev,
        gfp |= __GFP_ZERO;
 
        /*
-        * By forcing NUMA node 0 for 32-bit masks we ensure that the
-        * high 32 bits of the resulting PA will be zero.  If the mask
-        * size is, e.g., 24, we may still not be able to guarantee a
-        * suitable memory address, in which case we will return NULL.
-        * But such devices are uncommon.
+        * If the mask specifies that the memory be in the first 4 GB, then
+        * we force the allocation to come from the DMA zone.  We also
+        * force the node to 0 since that's the only node where the DMA
+        * zone isn't empty.  If the mask size is smaller than 32 bits, we
+        * may still not be able to guarantee a suitable memory address, in
+        * which case we will return NULL.  But such devices are uncommon.
         */
-       if (dma_mask <= DMA_BIT_MASK(32))
+       if (dma_mask <= DMA_BIT_MASK(32)) {
+               gfp |= GFP_DMA;
                node = 0;
+       }
 
-       pg = homecache_alloc_pages_node(node, gfp, order, PAGE_HOME_UNCACHED);
+       pg = homecache_alloc_pages_node(node, gfp, order, PAGE_HOME_DMA);
        if (pg == NULL)
                return NULL;
 
        addr = page_to_phys(pg);
        if (addr + size > dma_mask) {
-               homecache_free_pages(addr, order);
+               __homecache_free_pages(pg, order);
                return NULL;
        }
 
        *dma_handle = addr;
+
        return page_address(pg);
 }
-EXPORT_SYMBOL(dma_alloc_coherent);
 
 /*
- * Free memory that was allocated with dma_alloc_coherent.
+ * Free memory that was allocated with tile_dma_alloc_coherent.
  */
-void dma_free_coherent(struct device *dev, size_t size,
-                 void *vaddr, dma_addr_t dma_handle)
+static void tile_dma_free_coherent(struct device *dev, size_t size,
+                                  void *vaddr, dma_addr_t dma_handle,
+                                  struct dma_attrs *attrs)
 {
        homecache_free_pages((unsigned long)vaddr, get_order(size));
 }
-EXPORT_SYMBOL(dma_free_coherent);
 
 /*
  * The map routines "map" the specified address range for DMA
@@ -87,52 +96,285 @@ EXPORT_SYMBOL(dma_free_coherent);
  * can count on nothing having been touched.
  */
 
-/* Flush a PA range from cache page by page. */
-static void __dma_map_pa_range(dma_addr_t dma_addr, size_t size)
+/* Set up a single page for DMA access. */
+static void __dma_prep_page(struct page *page, unsigned long offset,
+                           size_t size, enum dma_data_direction direction)
+{
+       /*
+        * Flush the page from cache if necessary.
+        * On tilegx, data is delivered to hash-for-home L3; on tilepro,
+        * data is delivered direct to memory.
+        *
+        * NOTE: If we were just doing DMA_TO_DEVICE we could optimize
+        * this to be a "flush" not a "finv" and keep some of the
+        * state in cache across the DMA operation, but it doesn't seem
+        * worth creating the necessary flush_buffer_xxx() infrastructure.
+        */
+       int home = page_home(page);
+       switch (home) {
+       case PAGE_HOME_HASH:
+#ifdef __tilegx__
+               return;
+#endif
+               break;
+       case PAGE_HOME_UNCACHED:
+#ifdef __tilepro__
+               return;
+#endif
+               break;
+       case PAGE_HOME_IMMUTABLE:
+               /* Should be going to the device only. */
+               BUG_ON(direction == DMA_FROM_DEVICE ||
+                      direction == DMA_BIDIRECTIONAL);
+               return;
+       case PAGE_HOME_INCOHERENT:
+               /* Incoherent anyway, so no need to work hard here. */
+               return;
+       default:
+               BUG_ON(home < 0 || home >= NR_CPUS);
+               break;
+       }
+       homecache_finv_page(page);
+
+#ifdef DEBUG_ALIGNMENT
+       /* Warn if the region isn't cacheline aligned. */
+       if (offset & (L2_CACHE_BYTES - 1) || (size & (L2_CACHE_BYTES - 1)))
+               pr_warn("Unaligned DMA to non-hfh memory: PA %#llx/%#lx\n",
+                       PFN_PHYS(page_to_pfn(page)) + offset, size);
+#endif
+}
+
+/* Make the page ready to be read by the core. */
+static void __dma_complete_page(struct page *page, unsigned long offset,
+                               size_t size, enum dma_data_direction direction)
+{
+#ifdef __tilegx__
+       switch (page_home(page)) {
+       case PAGE_HOME_HASH:
+               /* I/O device delivered data the way the cpu wanted it. */
+               break;
+       case PAGE_HOME_INCOHERENT:
+               /* Incoherent anyway, so no need to work hard here. */
+               break;
+       case PAGE_HOME_IMMUTABLE:
+               /* Extra read-only copies are not a problem. */
+               break;
+       default:
+               /* Flush the bogus hash-for-home I/O entries to memory. */
+               homecache_finv_map_page(page, PAGE_HOME_HASH);
+               break;
+       }
+#endif
+}
+
+static void __dma_prep_pa_range(dma_addr_t dma_addr, size_t size,
+                               enum dma_data_direction direction)
 {
        struct page *page = pfn_to_page(PFN_DOWN(dma_addr));
-       size_t bytesleft = PAGE_SIZE - (dma_addr & (PAGE_SIZE - 1));
+       unsigned long offset = dma_addr & (PAGE_SIZE - 1);
+       size_t bytes = min(size, (size_t)(PAGE_SIZE - offset));
+
+       while (size != 0) {
+               __dma_prep_page(page, offset, bytes, direction);
+               size -= bytes;
+               ++page;
+               offset = 0;
+               bytes = min((size_t)PAGE_SIZE, size);
+       }
+}
 
-       while ((ssize_t)size > 0) {
-               /* Flush the page. */
-               homecache_flush_cache(page++, 0);
+static void __dma_complete_pa_range(dma_addr_t dma_addr, size_t size,
+                                   enum dma_data_direction direction)
+{
+       struct page *page = pfn_to_page(PFN_DOWN(dma_addr));
+       unsigned long offset = dma_addr & (PAGE_SIZE - 1);
+       size_t bytes = min(size, (size_t)(PAGE_SIZE - offset));
+
+       while (size != 0) {
+               __dma_complete_page(page, offset, bytes, direction);
+               size -= bytes;
+               ++page;
+               offset = 0;
+               bytes = min((size_t)PAGE_SIZE, size);
+       }
+}
+
+static int tile_dma_map_sg(struct device *dev, struct scatterlist *sglist,
+                          int nents, enum dma_data_direction direction,
+                          struct dma_attrs *attrs)
+{
+       struct scatterlist *sg;
+       int i;
+
+       BUG_ON(!valid_dma_direction(direction));
+
+       WARN_ON(nents == 0 || sglist->length == 0);
 
-               /* Figure out if we need to continue on the next page. */
-               size -= bytesleft;
-               bytesleft = PAGE_SIZE;
+       for_each_sg(sglist, sg, nents, i) {
+               sg->dma_address = sg_phys(sg);
+               __dma_prep_pa_range(sg->dma_address, sg->length, direction);
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+               sg->dma_length = sg->length;
+#endif
        }
+
+       return nents;
 }
 
-/*
- * dma_map_single can be passed any memory address, and there appear
- * to be no alignment constraints.
- *
- * There is a chance that the start of the buffer will share a cache
- * line with some other data that has been touched in the meantime.
- */
-dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
-              enum dma_data_direction direction)
+static void tile_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
+                             int nents, enum dma_data_direction direction,
+                             struct dma_attrs *attrs)
+{
+       struct scatterlist *sg;
+       int i;
+
+       BUG_ON(!valid_dma_direction(direction));
+       for_each_sg(sglist, sg, nents, i) {
+               sg->dma_address = sg_phys(sg);
+               __dma_complete_pa_range(sg->dma_address, sg->length,
+                                       direction);
+       }
+}
+
+static dma_addr_t tile_dma_map_page(struct device *dev, struct page *page,
+                                   unsigned long offset, size_t size,
+                                   enum dma_data_direction direction,
+                                   struct dma_attrs *attrs)
 {
-       dma_addr_t dma_addr = __pa(ptr);
+       BUG_ON(!valid_dma_direction(direction));
+
+       BUG_ON(offset + size > PAGE_SIZE);
+       __dma_prep_page(page, offset, size, direction);
 
+       return page_to_pa(page) + offset;
+}
+
+static void tile_dma_unmap_page(struct device *dev, dma_addr_t dma_address,
+                               size_t size, enum dma_data_direction direction,
+                               struct dma_attrs *attrs)
+{
        BUG_ON(!valid_dma_direction(direction));
-       WARN_ON(size == 0);
 
-       __dma_map_pa_range(dma_addr, size);
+       __dma_complete_page(pfn_to_page(PFN_DOWN(dma_address)),
+                           dma_address & PAGE_OFFSET, size, direction);
+}
 
-       return dma_addr;
+static void tile_dma_sync_single_for_cpu(struct device *dev,
+                                        dma_addr_t dma_handle,
+                                        size_t size,
+                                        enum dma_data_direction direction)
+{
+       BUG_ON(!valid_dma_direction(direction));
+
+       __dma_complete_pa_range(dma_handle, size, direction);
+}
+
+static void tile_dma_sync_single_for_device(struct device *dev,
+                                           dma_addr_t dma_handle, size_t size,
+                                           enum dma_data_direction direction)
+{
+       __dma_prep_pa_range(dma_handle, size, direction);
 }
-EXPORT_SYMBOL(dma_map_single);
 
-void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
-                enum dma_data_direction direction)
+static void tile_dma_sync_sg_for_cpu(struct device *dev,
+                                    struct scatterlist *sglist, int nelems,
+                                    enum dma_data_direction direction)
 {
+       struct scatterlist *sg;
+       int i;
+
+       BUG_ON(!valid_dma_direction(direction));
+       WARN_ON(nelems == 0 || sglist->length == 0);
+
+       for_each_sg(sglist, sg, nelems, i) {
+               dma_sync_single_for_cpu(dev, sg->dma_address,
+                                       sg_dma_len(sg), direction);
+       }
+}
+
+static void tile_dma_sync_sg_for_device(struct device *dev,
+                                       struct scatterlist *sglist, int nelems,
+                                       enum dma_data_direction direction)
+{
+       struct scatterlist *sg;
+       int i;
+
        BUG_ON(!valid_dma_direction(direction));
+       WARN_ON(nelems == 0 || sglist->length == 0);
+
+       for_each_sg(sglist, sg, nelems, i) {
+               dma_sync_single_for_device(dev, sg->dma_address,
+                                          sg_dma_len(sg), direction);
+       }
+}
+
+static inline int
+tile_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+       return 0;
+}
+
+static inline int
+tile_dma_supported(struct device *dev, u64 mask)
+{
+       return 1;
+}
+
+static struct dma_map_ops tile_default_dma_map_ops = {
+       .alloc = tile_dma_alloc_coherent,
+       .free = tile_dma_free_coherent,
+       .map_page = tile_dma_map_page,
+       .unmap_page = tile_dma_unmap_page,
+       .map_sg = tile_dma_map_sg,
+       .unmap_sg = tile_dma_unmap_sg,
+       .sync_single_for_cpu = tile_dma_sync_single_for_cpu,
+       .sync_single_for_device = tile_dma_sync_single_for_device,
+       .sync_sg_for_cpu = tile_dma_sync_sg_for_cpu,
+       .sync_sg_for_device = tile_dma_sync_sg_for_device,
+       .mapping_error = tile_dma_mapping_error,
+       .dma_supported = tile_dma_supported
+};
+
+struct dma_map_ops *tile_dma_map_ops = &tile_default_dma_map_ops;
+EXPORT_SYMBOL(tile_dma_map_ops);
+
+/* Generic PCI DMA mapping functions */
+
+static void *tile_pci_dma_alloc_coherent(struct device *dev, size_t size,
+                                        dma_addr_t *dma_handle, gfp_t gfp,
+                                        struct dma_attrs *attrs)
+{
+       int node = dev_to_node(dev);
+       int order = get_order(size);
+       struct page *pg;
+       dma_addr_t addr;
+
+       gfp |= __GFP_ZERO;
+
+       pg = homecache_alloc_pages_node(node, gfp, order, PAGE_HOME_DMA);
+       if (pg == NULL)
+               return NULL;
+
+       addr = page_to_phys(pg);
+
+       *dma_handle = phys_to_dma(dev, addr);
+
+       return page_address(pg);
+}
+
+/*
+ * Free memory that was allocated with tile_pci_dma_alloc_coherent.
+ */
+static void tile_pci_dma_free_coherent(struct device *dev, size_t size,
+                                      void *vaddr, dma_addr_t dma_handle,
+                                      struct dma_attrs *attrs)
+{
+       homecache_free_pages((unsigned long)vaddr, get_order(size));
 }
-EXPORT_SYMBOL(dma_unmap_single);
 
-int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
-          enum dma_data_direction direction)
+static int tile_pci_dma_map_sg(struct device *dev, struct scatterlist *sglist,
+                              int nents, enum dma_data_direction direction,
+                              struct dma_attrs *attrs)
 {
        struct scatterlist *sg;
        int i;
@@ -143,73 +385,103 @@ int dma_map_sg(struct device *dev, struct scatterlist *sglist, int nents,
 
        for_each_sg(sglist, sg, nents, i) {
                sg->dma_address = sg_phys(sg);
-               __dma_map_pa_range(sg->dma_address, sg->length);
+               __dma_prep_pa_range(sg->dma_address, sg->length, direction);
+
+               sg->dma_address = phys_to_dma(dev, sg->dma_address);
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+               sg->dma_length = sg->length;
+#endif
        }
 
        return nents;
 }
-EXPORT_SYMBOL(dma_map_sg);
 
-void dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries,
-            enum dma_data_direction direction)
+static void tile_pci_dma_unmap_sg(struct device *dev,
+                                 struct scatterlist *sglist, int nents,
+                                 enum dma_data_direction direction,
+                                 struct dma_attrs *attrs)
 {
+       struct scatterlist *sg;
+       int i;
+
        BUG_ON(!valid_dma_direction(direction));
+       for_each_sg(sglist, sg, nents, i) {
+               sg->dma_address = sg_phys(sg);
+               __dma_complete_pa_range(sg->dma_address, sg->length,
+                                       direction);
+       }
 }
-EXPORT_SYMBOL(dma_unmap_sg);
 
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
-                       unsigned long offset, size_t size,
-                       enum dma_data_direction direction)
+static dma_addr_t tile_pci_dma_map_page(struct device *dev, struct page *page,
+                                       unsigned long offset, size_t size,
+                                       enum dma_data_direction direction,
+                                       struct dma_attrs *attrs)
 {
        BUG_ON(!valid_dma_direction(direction));
 
        BUG_ON(offset + size > PAGE_SIZE);
-       homecache_flush_cache(page, 0);
+       __dma_prep_page(page, offset, size, direction);
 
-       return page_to_pa(page) + offset;
+       return phys_to_dma(dev, page_to_pa(page) + offset);
 }
-EXPORT_SYMBOL(dma_map_page);
 
-void dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
-              enum dma_data_direction direction)
+static void tile_pci_dma_unmap_page(struct device *dev, dma_addr_t dma_address,
+                                   size_t size,
+                                   enum dma_data_direction direction,
+                                   struct dma_attrs *attrs)
 {
        BUG_ON(!valid_dma_direction(direction));
+
+       dma_address = dma_to_phys(dev, dma_address);
+
+       __dma_complete_page(pfn_to_page(PFN_DOWN(dma_address)),
+                           dma_address & PAGE_OFFSET, size, direction);
 }
-EXPORT_SYMBOL(dma_unmap_page);
 
-void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
-                            size_t size, enum dma_data_direction direction)
+static void tile_pci_dma_sync_single_for_cpu(struct device *dev,
+                                            dma_addr_t dma_handle,
+                                            size_t size,
+                                            enum dma_data_direction direction)
 {
        BUG_ON(!valid_dma_direction(direction));
+
+       dma_handle = dma_to_phys(dev, dma_handle);
+
+       __dma_complete_pa_range(dma_handle, size, direction);
 }
-EXPORT_SYMBOL(dma_sync_single_for_cpu);
 
-void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
-                               size_t size, enum dma_data_direction direction)
+static void tile_pci_dma_sync_single_for_device(struct device *dev,
+                                               dma_addr_t dma_handle,
+                                               size_t size,
+                                               enum dma_data_direction
+                                               direction)
 {
-       unsigned long start = PFN_DOWN(dma_handle);
-       unsigned long end = PFN_DOWN(dma_handle + size - 1);
-       unsigned long i;
+       dma_handle = dma_to_phys(dev, dma_handle);
 
-       BUG_ON(!valid_dma_direction(direction));
-       for (i = start; i <= end; ++i)
-               homecache_flush_cache(pfn_to_page(i), 0);
+       __dma_prep_pa_range(dma_handle, size, direction);
 }
-EXPORT_SYMBOL(dma_sync_single_for_device);
 
-void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
-                   enum dma_data_direction direction)
+static void tile_pci_dma_sync_sg_for_cpu(struct device *dev,
+                                        struct scatterlist *sglist,
+                                        int nelems,
+                                        enum dma_data_direction direction)
 {
+       struct scatterlist *sg;
+       int i;
+
        BUG_ON(!valid_dma_direction(direction));
-       WARN_ON(nelems == 0 || sg[0].length == 0);
+       WARN_ON(nelems == 0 || sglist->length == 0);
+
+       for_each_sg(sglist, sg, nelems, i) {
+               dma_sync_single_for_cpu(dev, sg->dma_address,
+                                       sg_dma_len(sg), direction);
+       }
 }
-EXPORT_SYMBOL(dma_sync_sg_for_cpu);
 
-/*
- * Flush and invalidate cache for scatterlist.
- */
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist,
-                           int nelems, enum dma_data_direction direction)
+static void tile_pci_dma_sync_sg_for_device(struct device *dev,
+                                           struct scatterlist *sglist,
+                                           int nelems,
+                                           enum dma_data_direction direction)
 {
        struct scatterlist *sg;
        int i;
@@ -222,31 +494,93 @@ void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sglist,
                                           sg_dma_len(sg), direction);
        }
 }
-EXPORT_SYMBOL(dma_sync_sg_for_device);
 
-void dma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
-                                  unsigned long offset, size_t size,
-                                  enum dma_data_direction direction)
+static inline int
+tile_pci_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 {
-       dma_sync_single_for_cpu(dev, dma_handle + offset, size, direction);
+       return 0;
 }
-EXPORT_SYMBOL(dma_sync_single_range_for_cpu);
 
-void dma_sync_single_range_for_device(struct device *dev,
-                                     dma_addr_t dma_handle,
-                                     unsigned long offset, size_t size,
-                                     enum dma_data_direction direction)
+static inline int
+tile_pci_dma_supported(struct device *dev, u64 mask)
 {
-       dma_sync_single_for_device(dev, dma_handle + offset, size, direction);
+       return 1;
 }
-EXPORT_SYMBOL(dma_sync_single_range_for_device);
 
-/*
- * dma_alloc_noncoherent() returns non-cacheable memory, so there's no
- * need to do any flushing here.
- */
-void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
-                   enum dma_data_direction direction)
+static struct dma_map_ops tile_pci_default_dma_map_ops = {
+       .alloc = tile_pci_dma_alloc_coherent,
+       .free = tile_pci_dma_free_coherent,
+       .map_page = tile_pci_dma_map_page,
+       .unmap_page = tile_pci_dma_unmap_page,
+       .map_sg = tile_pci_dma_map_sg,
+       .unmap_sg = tile_pci_dma_unmap_sg,
+       .sync_single_for_cpu = tile_pci_dma_sync_single_for_cpu,
+       .sync_single_for_device = tile_pci_dma_sync_single_for_device,
+       .sync_sg_for_cpu = tile_pci_dma_sync_sg_for_cpu,
+       .sync_sg_for_device = tile_pci_dma_sync_sg_for_device,
+       .mapping_error = tile_pci_dma_mapping_error,
+       .dma_supported = tile_pci_dma_supported
+};
+
+struct dma_map_ops *gx_pci_dma_map_ops = &tile_pci_default_dma_map_ops;
+EXPORT_SYMBOL(gx_pci_dma_map_ops);
+
+/* PCI DMA mapping functions for legacy PCI devices */
+
+#ifdef CONFIG_SWIOTLB
+static void *tile_swiotlb_alloc_coherent(struct device *dev, size_t size,
+                                        dma_addr_t *dma_handle, gfp_t gfp,
+                                        struct dma_attrs *attrs)
 {
+       gfp |= GFP_DMA;
+       return swiotlb_alloc_coherent(dev, size, dma_handle, gfp);
+}
+
+static void tile_swiotlb_free_coherent(struct device *dev, size_t size,
+                                      void *vaddr, dma_addr_t dma_addr,
+                                      struct dma_attrs *attrs)
+{
+       swiotlb_free_coherent(dev, size, vaddr, dma_addr);
+}
+
+static struct dma_map_ops pci_swiotlb_dma_ops = {
+       .alloc = tile_swiotlb_alloc_coherent,
+       .free = tile_swiotlb_free_coherent,
+       .map_page = swiotlb_map_page,
+       .unmap_page = swiotlb_unmap_page,
+       .map_sg = swiotlb_map_sg_attrs,
+       .unmap_sg = swiotlb_unmap_sg_attrs,
+       .sync_single_for_cpu = swiotlb_sync_single_for_cpu,
+       .sync_single_for_device = swiotlb_sync_single_for_device,
+       .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+       .sync_sg_for_device = swiotlb_sync_sg_for_device,
+       .dma_supported = swiotlb_dma_supported,
+       .mapping_error = swiotlb_dma_mapping_error,
+};
+
+struct dma_map_ops *gx_legacy_pci_dma_map_ops = &pci_swiotlb_dma_ops;
+#else
+struct dma_map_ops *gx_legacy_pci_dma_map_ops;
+#endif
+EXPORT_SYMBOL(gx_legacy_pci_dma_map_ops);
+
+#ifdef CONFIG_ARCH_HAS_DMA_SET_COHERENT_MASK
+int dma_set_coherent_mask(struct device *dev, u64 mask)
+{
+       struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+       /* Handle legacy PCI devices with limited memory addressability. */
+       if (((dma_ops == gx_pci_dma_map_ops) ||
+           (dma_ops == gx_legacy_pci_dma_map_ops)) &&
+           (mask <= DMA_BIT_MASK(32))) {
+               if (mask > dev->archdata.max_direct_dma_addr)
+                       mask = dev->archdata.max_direct_dma_addr;
+       }
+
+       if (!dma_supported(dev, mask))
+               return -EIO;
+       dev->coherent_dma_mask = mask;
+       return 0;
 }
-EXPORT_SYMBOL(dma_cache_sync);
+EXPORT_SYMBOL(dma_set_coherent_mask);
+#endif
diff --git a/arch/tile/kernel/pci_gx.c b/arch/tile/kernel/pci_gx.c
new file mode 100644 (file)
index 0000000..fa75264
--- /dev/null
@@ -0,0 +1,1543 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mmzone.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/capability.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/irq.h>
+#include <linux/msi.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/ctype.h>
+
+#include <asm/processor.h>
+#include <asm/sections.h>
+#include <asm/byteorder.h>
+
+#include <gxio/iorpc_globals.h>
+#include <gxio/kiorpc.h>
+#include <gxio/trio.h>
+#include <gxio/iorpc_trio.h>
+#include <hv/drv_trio_intf.h>
+
+#include <arch/sim.h>
+
+/*
+ * This file containes the routines to search for PCI buses,
+ * enumerate the buses, and configure any attached devices.
+ */
+
+#define DEBUG_PCI_CFG  0
+
+#if DEBUG_PCI_CFG
+#define TRACE_CFG_WR(size, val, bus, dev, func, offset) \
+       pr_info("CFG WR %d-byte VAL %#x to bus %d dev %d func %d addr %u\n", \
+               size, val, bus, dev, func, offset & 0xFFF);
+#define TRACE_CFG_RD(size, val, bus, dev, func, offset) \
+       pr_info("CFG RD %d-byte VAL %#x from bus %d dev %d func %d addr %u\n", \
+               size, val, bus, dev, func, offset & 0xFFF);
+#else
+#define TRACE_CFG_WR(...)
+#define TRACE_CFG_RD(...)
+#endif
+
+static int __devinitdata pci_probe = 1;
+
+/* Information on the PCIe RC ports configuration. */
+static int __devinitdata pcie_rc[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
+
+/*
+ * On some platforms with one or more Gx endpoint ports, we need to
+ * delay the PCIe RC port probe for a few seconds to work around
+ * a HW PCIe link-training bug. The exact delay is specified with
+ * a kernel boot argument in the form of "pcie_rc_delay=T,P,S",
+ * where T is the TRIO instance number, P is the port number and S is
+ * the delay in seconds. If the delay is not provided, the value
+ * will be DEFAULT_RC_DELAY.
+ */
+static int __devinitdata rc_delay[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
+
+/* Default number of seconds that the PCIe RC port probe can be delayed. */
+#define DEFAULT_RC_DELAY       10
+
+/* Max number of seconds that the PCIe RC port probe can be delayed. */
+#define MAX_RC_DELAY           20
+
+/* Array of the PCIe ports configuration info obtained from the BIB. */
+struct pcie_port_property pcie_ports[TILEGX_NUM_TRIO][TILEGX_TRIO_PCIES];
+
+/* All drivers share the TRIO contexts defined here. */
+gxio_trio_context_t trio_contexts[TILEGX_NUM_TRIO];
+
+/* Pointer to an array of PCIe RC controllers. */
+struct pci_controller pci_controllers[TILEGX_NUM_TRIO * TILEGX_TRIO_PCIES];
+int num_rc_controllers;
+static int num_ep_controllers;
+
+static struct pci_ops tile_cfg_ops;
+
+/* Mask of CPUs that should receive PCIe interrupts. */
+static struct cpumask intr_cpus_map;
+
+/*
+ * We don't need to worry about the alignment of resources.
+ */
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+                               resource_size_t size, resource_size_t align)
+{
+       return res->start;
+}
+EXPORT_SYMBOL(pcibios_align_resource);
+
+
+/*
+ * Pick a CPU to receive and handle the PCIe interrupts, based on the IRQ #.
+ * For now, we simply send interrupts to non-dataplane CPUs.
+ * We may implement methods to allow user to specify the target CPUs,
+ * e.g. via boot arguments.
+ */
+static int tile_irq_cpu(int irq)
+{
+       unsigned int count;
+       int i = 0;
+       int cpu;
+
+       count = cpumask_weight(&intr_cpus_map);
+       if (unlikely(count == 0)) {
+               pr_warning("intr_cpus_map empty, interrupts will be"
+                          " delievered to dataplane tiles\n");
+               return irq % (smp_height * smp_width);
+       }
+
+       count = irq % count;
+       for_each_cpu(cpu, &intr_cpus_map) {
+               if (i++ == count)
+                       break;
+       }
+       return cpu;
+}
+
+/*
+ * Open a file descriptor to the TRIO shim.
+ */
+static int __devinit tile_pcie_open(int trio_index)
+{
+       gxio_trio_context_t *context = &trio_contexts[trio_index];
+       int ret;
+
+       /*
+        * This opens a file descriptor to the TRIO shim.
+        */
+       ret = gxio_trio_init(context, trio_index);
+       if (ret < 0)
+               return ret;
+
+       /*
+        * Allocate an ASID for the kernel.
+        */
+       ret = gxio_trio_alloc_asids(context, 1, 0, 0);
+       if (ret < 0) {
+               pr_err("PCI: ASID alloc failure on TRIO %d, give up\n",
+                       trio_index);
+               goto asid_alloc_failure;
+       }
+
+       context->asid = ret;
+
+#ifdef USE_SHARED_PCIE_CONFIG_REGION
+       /*
+        * Alloc a PIO region for config access, shared by all MACs per TRIO.
+        * This shouldn't fail since the kernel is supposed to the first
+        * client of the TRIO's PIO regions.
+        */
+       ret = gxio_trio_alloc_pio_regions(context, 1, 0, 0);
+       if (ret < 0) {
+               pr_err("PCI: CFG PIO alloc failure on TRIO %d, give up\n",
+                       trio_index);
+               goto pio_alloc_failure;
+       }
+
+       context->pio_cfg_index = ret;
+
+       /*
+        * For PIO CFG, the bus_address_hi parameter is 0. The mac parameter
+        * is also 0 because it is specified in PIO_REGION_SETUP_CFG_ADDR.
+        */
+       ret = gxio_trio_init_pio_region_aux(context, context->pio_cfg_index,
+               0, 0, HV_TRIO_PIO_FLAG_CONFIG_SPACE);
+       if (ret < 0) {
+               pr_err("PCI: CFG PIO init failure on TRIO %d, give up\n",
+                       trio_index);
+               goto pio_alloc_failure;
+       }
+#endif
+
+       return ret;
+
+asid_alloc_failure:
+#ifdef USE_SHARED_PCIE_CONFIG_REGION
+pio_alloc_failure:
+#endif
+       hv_dev_close(context->fd);
+
+       return ret;
+}
+
+static void
+tilegx_legacy_irq_ack(struct irq_data *d)
+{
+       __insn_mtspr(SPR_IPI_EVENT_RESET_K, 1UL << d->irq);
+}
+
+static void
+tilegx_legacy_irq_mask(struct irq_data *d)
+{
+       __insn_mtspr(SPR_IPI_MASK_SET_K, 1UL << d->irq);
+}
+
+static void
+tilegx_legacy_irq_unmask(struct irq_data *d)
+{
+       __insn_mtspr(SPR_IPI_MASK_RESET_K, 1UL << d->irq);
+}
+
+static struct irq_chip tilegx_legacy_irq_chip = {
+       .name                   = "tilegx_legacy_irq",
+       .irq_ack                = tilegx_legacy_irq_ack,
+       .irq_mask               = tilegx_legacy_irq_mask,
+       .irq_unmask             = tilegx_legacy_irq_unmask,
+
+       /* TBD: support set_affinity. */
+};
+
+/*
+ * This is a wrapper function of the kernel level-trigger interrupt
+ * handler handle_level_irq() for PCI legacy interrupts. The TRIO
+ * is configured such that only INTx Assert interrupts are proxied
+ * to Linux which just calls handle_level_irq() after clearing the
+ * MAC INTx Assert status bit associated with this interrupt.
+ */
+static void
+trio_handle_level_irq(unsigned int irq, struct irq_desc *desc)
+{
+       struct pci_controller *controller = irq_desc_get_handler_data(desc);
+       gxio_trio_context_t *trio_context = controller->trio;
+       uint64_t intx = (uint64_t)irq_desc_get_chip_data(desc);
+       int mac = controller->mac;
+       unsigned int reg_offset;
+       uint64_t level_mask;
+
+       handle_level_irq(irq, desc);
+
+       /*
+        * Clear the INTx Level status, otherwise future interrupts are
+        * not sent.
+        */
+       reg_offset = (TRIO_PCIE_INTFC_MAC_INT_STS <<
+               TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+               (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
+               TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+               (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+       level_mask = TRIO_PCIE_INTFC_MAC_INT_STS__INT_LEVEL_MASK << intx;
+
+       __gxio_mmio_write(trio_context->mmio_base_mac + reg_offset, level_mask);
+}
+
+/*
+ * Create kernel irqs and set up the handlers for the legacy interrupts.
+ * Also some minimum initialization for the MSI support.
+ */
+static int __devinit tile_init_irqs(struct pci_controller *controller)
+{
+       int i;
+       int j;
+       int irq;
+       int result;
+
+       cpumask_copy(&intr_cpus_map, cpu_online_mask);
+
+
+       for (i = 0; i < 4; i++) {
+               gxio_trio_context_t *context = controller->trio;
+               int cpu;
+
+               /* Ask the kernel to allocate an IRQ. */
+               irq = create_irq();
+               if (irq < 0) {
+                       pr_err("PCI: no free irq vectors, failed for %d\n", i);
+
+                       goto free_irqs;
+               }
+               controller->irq_intx_table[i] = irq;
+
+               /* Distribute the 4 IRQs to different tiles. */
+               cpu = tile_irq_cpu(irq);
+
+               /* Configure the TRIO intr binding for this IRQ. */
+               result = gxio_trio_config_legacy_intr(context, cpu_x(cpu),
+                                                     cpu_y(cpu), KERNEL_PL,
+                                                     irq, controller->mac, i);
+               if (result < 0) {
+                       pr_err("PCI: MAC intx config failed for %d\n", i);
+
+                       goto free_irqs;
+               }
+
+               /*
+                * Register the IRQ handler with the kernel.
+                */
+               irq_set_chip_and_handler(irq, &tilegx_legacy_irq_chip,
+                                       trio_handle_level_irq);
+               irq_set_chip_data(irq, (void *)(uint64_t)i);
+               irq_set_handler_data(irq, controller);
+       }
+
+       return 0;
+
+free_irqs:
+       for (j = 0; j < i; j++)
+               destroy_irq(controller->irq_intx_table[j]);
+
+       return -1;
+}
+
+/*
+ * Find valid controllers and fill in pci_controller structs for each
+ * of them.
+ *
+ * Returns the number of controllers discovered.
+ */
+int __init tile_pci_init(void)
+{
+       int num_trio_shims = 0;
+       int ctl_index = 0;
+       int i, j;
+
+       if (!pci_probe) {
+               pr_info("PCI: disabled by boot argument\n");
+               return 0;
+       }
+
+       pr_info("PCI: Searching for controllers...\n");
+
+       /*
+        * We loop over all the TRIO shims.
+        */
+       for (i = 0; i < TILEGX_NUM_TRIO; i++) {
+               int ret;
+
+               ret = tile_pcie_open(i);
+               if (ret < 0)
+                       continue;
+
+               num_trio_shims++;
+       }
+
+       if (num_trio_shims == 0 || sim_is_simulator())
+               return 0;
+
+       /*
+        * Now determine which PCIe ports are configured to operate in RC mode.
+        * We look at the Board Information Block first and then see if there
+        * are any overriding configuration by the HW strapping pin.
+        */
+       for (i = 0; i < TILEGX_NUM_TRIO; i++) {
+               gxio_trio_context_t *context = &trio_contexts[i];
+               int ret;
+
+               if (context->fd < 0)
+                       continue;
+
+               ret = hv_dev_pread(context->fd, 0,
+                       (HV_VirtAddr)&pcie_ports[i][0],
+                       sizeof(struct pcie_port_property) * TILEGX_TRIO_PCIES,
+                       GXIO_TRIO_OP_GET_PORT_PROPERTY);
+               if (ret < 0) {
+                       pr_err("PCI: PCIE_GET_PORT_PROPERTY failure, error %d,"
+                               " on TRIO %d\n", ret, i);
+                       continue;
+               }
+
+               for (j = 0; j < TILEGX_TRIO_PCIES; j++) {
+                       if (pcie_ports[i][j].allow_rc) {
+                               pcie_rc[i][j] = 1;
+                               num_rc_controllers++;
+                       }
+                       else if (pcie_ports[i][j].allow_ep) {
+                               num_ep_controllers++;
+                       }
+               }
+       }
+
+       /*
+        * Return if no PCIe ports are configured to operate in RC mode.
+        */
+       if (num_rc_controllers == 0)
+               return 0;
+
+       /*
+        * Set the TRIO pointer and MAC index for each PCIe RC port.
+        */
+       for (i = 0; i < TILEGX_NUM_TRIO; i++) {
+               for (j = 0; j < TILEGX_TRIO_PCIES; j++) {
+                       if (pcie_rc[i][j]) {
+                               pci_controllers[ctl_index].trio =
+                                       &trio_contexts[i];
+                               pci_controllers[ctl_index].mac = j;
+                               pci_controllers[ctl_index].trio_index = i;
+                               ctl_index++;
+                               if (ctl_index == num_rc_controllers)
+                                       goto out;
+                       }
+               }
+       }
+
+out:
+       /*
+        * Configure each PCIe RC port.
+        */
+       for (i = 0; i < num_rc_controllers; i++) {
+               /*
+                * Configure the PCIe MAC to run in RC mode.
+                */
+
+               struct pci_controller *controller = &pci_controllers[i];
+
+               controller->index = i;
+               controller->ops = &tile_cfg_ops;
+
+               /*
+                * The PCI memory resource is located above the PA space.
+                * For every host bridge, the BAR window or the MMIO aperture
+                * is in range [3GB, 4GB - 1] of a 4GB space beyond the
+                * PA space.
+                */
+
+               controller->mem_offset = TILE_PCI_MEM_START +
+                       (i * TILE_PCI_BAR_WINDOW_TOP);
+               controller->mem_space.start = controller->mem_offset +
+                       TILE_PCI_BAR_WINDOW_TOP - TILE_PCI_BAR_WINDOW_SIZE;
+               controller->mem_space.end = controller->mem_offset +
+                       TILE_PCI_BAR_WINDOW_TOP - 1;
+               controller->mem_space.flags = IORESOURCE_MEM;
+               snprintf(controller->mem_space_name,
+                        sizeof(controller->mem_space_name),
+                        "PCI mem domain %d", i);
+               controller->mem_space.name = controller->mem_space_name;
+       }
+
+       return num_rc_controllers;
+}
+
+/*
+ * (pin - 1) converts from the PCI standard's [1:4] convention to
+ * a normal [0:3] range.
+ */
+static int tile_map_irq(const struct pci_dev *dev, u8 device, u8 pin)
+{
+       struct pci_controller *controller =
+               (struct pci_controller *)dev->sysdata;
+       return controller->irq_intx_table[pin - 1];
+}
+
+
+static void __devinit fixup_read_and_payload_sizes(struct pci_controller *
+                                               controller)
+{
+       gxio_trio_context_t *trio_context = controller->trio;
+       struct pci_bus *root_bus = controller->root_bus;
+       TRIO_PCIE_RC_DEVICE_CONTROL_t dev_control;
+       TRIO_PCIE_RC_DEVICE_CAP_t rc_dev_cap;
+       unsigned int reg_offset;
+       struct pci_bus *child;
+       int mac;
+       int err;
+
+       mac = controller->mac;
+
+       /*
+        * Set our max read request size to be 4KB.
+        */
+       reg_offset =
+               (TRIO_PCIE_RC_DEVICE_CONTROL <<
+                       TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+               (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
+                       TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+               (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+       dev_control.word = __gxio_mmio_read32(trio_context->mmio_base_mac +
+                                               reg_offset);
+       dev_control.max_read_req_sz = 5;
+       __gxio_mmio_write32(trio_context->mmio_base_mac + reg_offset,
+                                               dev_control.word);
+
+       /*
+        * Set the max payload size supported by this Gx PCIe MAC.
+        * Though Gx PCIe supports Max Payload Size of up to 1024 bytes,
+        * experiments have shown that setting MPS to 256 yields the
+        * best performance.
+        */
+       reg_offset =
+               (TRIO_PCIE_RC_DEVICE_CAP <<
+                       TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+               (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
+                       TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+               (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+       rc_dev_cap.word = __gxio_mmio_read32(trio_context->mmio_base_mac +
+                                               reg_offset);
+       rc_dev_cap.mps_sup = 1;
+       __gxio_mmio_write32(trio_context->mmio_base_mac + reg_offset,
+                                               rc_dev_cap.word);
+
+       /* Configure PCI Express MPS setting. */
+       list_for_each_entry(child, &root_bus->children, node) {
+               struct pci_dev *self = child->self;
+               if (!self)
+                       continue;
+
+               pcie_bus_configure_settings(child, self->pcie_mpss);
+       }
+
+       /*
+        * Set the mac_config register in trio based on the MPS/MRS of the link.
+        */
+       reg_offset =
+               (TRIO_PCIE_RC_DEVICE_CONTROL <<
+                       TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+               (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
+                       TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+               (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+       dev_control.word = __gxio_mmio_read32(trio_context->mmio_base_mac +
+                                               reg_offset);
+
+       err = gxio_trio_set_mps_mrs(trio_context,
+                                   dev_control.max_payload_size,
+                                   dev_control.max_read_req_sz,
+                                   mac);
+        if (err < 0) {
+               pr_err("PCI: PCIE_CONFIGURE_MAC_MPS_MRS failure, "
+                       "MAC %d on TRIO %d\n",
+                       mac, controller->trio_index);
+       }
+}
+
+static int __devinit setup_pcie_rc_delay(char *str)
+{
+       unsigned long delay = 0;
+       unsigned long trio_index;
+       unsigned long mac;
+
+       if (str == NULL || !isdigit(*str))
+               return -EINVAL;
+       trio_index = simple_strtoul(str, (char **)&str, 10);
+       if (trio_index >= TILEGX_NUM_TRIO)
+               return -EINVAL;
+
+       if (*str != ',')
+               return -EINVAL;
+
+       str++;
+       if (!isdigit(*str))
+               return -EINVAL;
+       mac = simple_strtoul(str, (char **)&str, 10);
+       if (mac >= TILEGX_TRIO_PCIES)
+               return -EINVAL;
+
+       if (*str != '\0') {
+               if (*str != ',')
+                       return -EINVAL;
+
+               str++;
+               if (!isdigit(*str))
+                       return -EINVAL;
+               delay = simple_strtoul(str, (char **)&str, 10);
+               if (delay > MAX_RC_DELAY)
+                       return -EINVAL;
+       }
+
+       rc_delay[trio_index][mac] = delay ? : DEFAULT_RC_DELAY;
+       pr_info("Delaying PCIe RC link training for %u sec"
+               " on MAC %lu on TRIO %lu\n", rc_delay[trio_index][mac],
+               mac, trio_index);
+       return 0;
+}
+early_param("pcie_rc_delay", setup_pcie_rc_delay);
+
+/*
+ * PCI initialization entry point, called by subsys_initcall.
+ */
+int __init pcibios_init(void)
+{
+       resource_size_t offset;
+       LIST_HEAD(resources);
+       int next_busno;
+       int i;
+
+       tile_pci_init();
+
+       if (num_rc_controllers == 0 && num_ep_controllers == 0)
+               return 0;
+
+       /*
+        * We loop over all the TRIO shims and set up the MMIO mappings.
+        */
+       for (i = 0; i < TILEGX_NUM_TRIO; i++) {
+               gxio_trio_context_t *context = &trio_contexts[i];
+
+               if (context->fd < 0)
+                       continue;
+
+               /*
+                * Map in the MMIO space for the MAC.
+                */
+               offset = 0;
+               context->mmio_base_mac =
+                       iorpc_ioremap(context->fd, offset,
+                                     HV_TRIO_CONFIG_IOREMAP_SIZE);
+               if (context->mmio_base_mac == NULL) {
+                       pr_err("PCI: MAC map failure on TRIO %d\n", i);
+
+                       hv_dev_close(context->fd);
+                       context->fd = -1;
+                       continue;
+               }
+       }
+
+       /*
+        * Delay a bit in case devices aren't ready.  Some devices are
+        * known to require at least 20ms here, but we use a more
+        * conservative value.
+        */
+       msleep(250);
+
+       /* Scan all of the recorded PCI controllers.  */
+       for (next_busno = 0, i = 0; i < num_rc_controllers; i++) {
+               struct pci_controller *controller = &pci_controllers[i];
+               gxio_trio_context_t *trio_context = controller->trio;
+               TRIO_PCIE_INTFC_PORT_CONFIG_t port_config;
+               TRIO_PCIE_INTFC_PORT_STATUS_t port_status;
+               TRIO_PCIE_INTFC_TX_FIFO_CTL_t tx_fifo_ctl;
+               struct pci_bus *bus;
+               unsigned int reg_offset;
+               unsigned int class_code_revision;
+               int trio_index;
+               int mac;
+               int ret;
+
+               if (trio_context->fd < 0)
+                       continue;
+
+               trio_index = controller->trio_index;
+               mac = controller->mac;
+
+               /*
+                * Check the port strap state which will override the BIB
+                * setting.
+                */
+
+               reg_offset =
+                       (TRIO_PCIE_INTFC_PORT_CONFIG <<
+                               TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+                       (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
+                               TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+                       (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+               port_config.word =
+                       __gxio_mmio_read(trio_context->mmio_base_mac +
+                                        reg_offset);
+
+               if ((port_config.strap_state !=
+                       TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC) &&
+                       (port_config.strap_state !=
+                       TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_RC_G1)) {
+                       /*
+                        * If this is really intended to be an EP port,
+                        * record it so that the endpoint driver will know about it.
+                        */
+                       if (port_config.strap_state ==
+                       TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT ||
+                       port_config.strap_state ==
+                       TRIO_PCIE_INTFC_PORT_CONFIG__STRAP_STATE_VAL_AUTO_CONFIG_ENDPOINT_G1)
+                               pcie_ports[trio_index][mac].allow_ep = 1;
+
+                       continue;
+               }
+
+               /*
+                * Delay the RC link training if needed.
+                */
+               if (rc_delay[trio_index][mac])
+                       msleep(rc_delay[trio_index][mac] * 1000);
+
+               ret = gxio_trio_force_rc_link_up(trio_context, mac);
+               if (ret < 0)
+                       pr_err("PCI: PCIE_FORCE_LINK_UP failure, "
+                               "MAC %d on TRIO %d\n", mac, trio_index);
+
+               pr_info("PCI: Found PCI controller #%d on TRIO %d MAC %d\n", i,
+                       trio_index, controller->mac);
+
+               /*
+                * Wait a bit here because some EP devices take longer
+                * to come up.
+                */
+               msleep(1000);
+
+               /*
+                * Check for PCIe link-up status.
+                */
+
+               reg_offset =
+                       (TRIO_PCIE_INTFC_PORT_STATUS <<
+                               TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+                       (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
+                               TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+                       (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+               port_status.word =
+                       __gxio_mmio_read(trio_context->mmio_base_mac +
+                                        reg_offset);
+               if (!port_status.dl_up) {
+                       pr_err("PCI: link is down, MAC %d on TRIO %d\n",
+                               mac, trio_index);
+                       continue;
+               }
+
+               /*
+                * Ensure that the link can come out of L1 power down state.
+                * Strictly speaking, this is needed only in the case of
+                * heavy RC-initiated DMAs.
+                */
+               reg_offset =
+                       (TRIO_PCIE_INTFC_TX_FIFO_CTL <<
+                               TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+                       (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_INTERFACE <<
+                               TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+                       (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+               tx_fifo_ctl.word =
+                       __gxio_mmio_read(trio_context->mmio_base_mac +
+                                        reg_offset);
+               tx_fifo_ctl.min_p_credits = 0;
+               __gxio_mmio_write(trio_context->mmio_base_mac + reg_offset,
+                                 tx_fifo_ctl.word);
+
+               /*
+                * Change the device ID so that Linux bus crawl doesn't confuse
+                * the internal bridge with any Tilera endpoints.
+                */
+
+               reg_offset =
+                       (TRIO_PCIE_RC_DEVICE_ID_VEN_ID <<
+                               TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+                       (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
+                               TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+                       (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+               __gxio_mmio_write32(trio_context->mmio_base_mac + reg_offset,
+                                   (TILERA_GX36_RC_DEV_ID <<
+                                   TRIO_PCIE_RC_DEVICE_ID_VEN_ID__DEV_ID_SHIFT) |
+                                   TILERA_VENDOR_ID);
+
+               /*
+                * Set the internal P2P bridge class code.
+                */
+
+               reg_offset =
+                       (TRIO_PCIE_RC_REVISION_ID <<
+                               TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+                       (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_STANDARD <<
+                               TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+                       (mac << TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+               class_code_revision =
+                       __gxio_mmio_read32(trio_context->mmio_base_mac +
+                                          reg_offset);
+               class_code_revision = (class_code_revision & 0xff ) |
+                                       (PCI_CLASS_BRIDGE_PCI << 16);
+
+               __gxio_mmio_write32(trio_context->mmio_base_mac +
+                                   reg_offset, class_code_revision);
+
+#ifdef USE_SHARED_PCIE_CONFIG_REGION
+
+               /*
+                * Map in the MMIO space for the PIO region.
+                */
+               offset = HV_TRIO_PIO_OFFSET(trio_context->pio_cfg_index) |
+                       (((unsigned long long)mac) <<
+                       TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT);
+
+#else
+
+               /*
+                * Alloc a PIO region for PCI config access per MAC.
+                */
+               ret = gxio_trio_alloc_pio_regions(trio_context, 1, 0, 0);
+               if (ret < 0) {
+                       pr_err("PCI: PCI CFG PIO alloc failure for mac %d "
+                               "on TRIO %d, give up\n", mac, trio_index);
+
+                       continue;
+               }
+
+               trio_context->pio_cfg_index[mac] = ret;
+
+               /*
+                * For PIO CFG, the bus_address_hi parameter is 0.
+                */
+               ret = gxio_trio_init_pio_region_aux(trio_context,
+                       trio_context->pio_cfg_index[mac],
+                       mac, 0, HV_TRIO_PIO_FLAG_CONFIG_SPACE);
+               if (ret < 0) {
+                       pr_err("PCI: PCI CFG PIO init failure for mac %d "
+                               "on TRIO %d, give up\n", mac, trio_index);
+
+                       continue;
+               }
+
+               offset = HV_TRIO_PIO_OFFSET(trio_context->pio_cfg_index[mac]) |
+                       (((unsigned long long)mac) <<
+                       TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT);
+
+#endif
+
+               trio_context->mmio_base_pio_cfg[mac] =
+                       iorpc_ioremap(trio_context->fd, offset,
+                       (1 << TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR__MAC_SHIFT));
+               if (trio_context->mmio_base_pio_cfg[mac] == NULL) {
+                       pr_err("PCI: PIO map failure for mac %d on TRIO %d\n",
+                               mac, trio_index);
+
+                       continue;
+               }
+
+               /*
+                * Initialize the PCIe interrupts.
+                */
+               if (tile_init_irqs(controller)) {
+                       pr_err("PCI: IRQs init failure for mac %d on TRIO %d\n",
+                               mac, trio_index);
+
+                       continue;
+               }
+
+               /*
+                * The PCI memory resource is located above the PA space.
+                * The memory range for the PCI root bus should not overlap
+                * with the physical RAM
+                */
+               pci_add_resource_offset(&resources, &controller->mem_space,
+                                       controller->mem_offset);
+
+               controller->first_busno = next_busno;
+               bus = pci_scan_root_bus(NULL, next_busno, controller->ops,
+                                       controller, &resources);
+               controller->root_bus = bus;
+               next_busno = bus->subordinate + 1;
+
+       }
+
+       /* Do machine dependent PCI interrupt routing */
+       pci_fixup_irqs(pci_common_swizzle, tile_map_irq);
+
+       /*
+        * This comes from the generic Linux PCI driver.
+        *
+        * It allocates all of the resources (I/O memory, etc)
+        * associated with the devices read in above.
+        */
+
+       pci_assign_unassigned_resources();
+
+       /* Record the I/O resources in the PCI controller structure. */
+       for (i = 0; i < num_rc_controllers; i++) {
+               struct pci_controller *controller = &pci_controllers[i];
+               gxio_trio_context_t *trio_context = controller->trio;
+               struct pci_bus *root_bus = pci_controllers[i].root_bus;
+               struct pci_bus *next_bus;
+               uint32_t bus_address_hi;
+               struct pci_dev *dev;
+               int ret;
+               int j;
+
+               /*
+                * Skip controllers that are not properly initialized or
+                * have down links.
+                */
+               if (root_bus == NULL)
+                       continue;
+
+               /* Configure the max_payload_size values for this domain. */
+               fixup_read_and_payload_sizes(controller);
+
+               list_for_each_entry(dev, &root_bus->devices, bus_list) {
+                       /* Find the PCI host controller, ie. the 1st bridge. */
+                       if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI &&
+                               (PCI_SLOT(dev->devfn) == 0)) {
+                               next_bus = dev->subordinate;
+                               pci_controllers[i].mem_resources[0] =
+                                       *next_bus->resource[0];
+                               pci_controllers[i].mem_resources[1] =
+                                        *next_bus->resource[1];
+                               pci_controllers[i].mem_resources[2] =
+                                        *next_bus->resource[2];
+
+                               break;
+                       }
+               }
+
+               if (pci_controllers[i].mem_resources[1].flags & IORESOURCE_MEM)
+                       bus_address_hi =
+                               pci_controllers[i].mem_resources[1].start >> 32;
+               else if (pci_controllers[i].mem_resources[2].flags & IORESOURCE_PREFETCH)
+                       bus_address_hi =
+                               pci_controllers[i].mem_resources[2].start >> 32;
+               else {
+                       /* This is unlikely. */
+                       pr_err("PCI: no memory resources on TRIO %d mac %d\n",
+                               controller->trio_index, controller->mac);
+                       continue;
+               }
+
+               /*
+                * Alloc a PIO region for PCI memory access for each RC port.
+                */
+               ret = gxio_trio_alloc_pio_regions(trio_context, 1, 0, 0);
+               if (ret < 0) {
+                       pr_err("PCI: MEM PIO alloc failure on TRIO %d mac %d, "
+                               "give up\n", controller->trio_index,
+                               controller->mac);
+
+                       continue;
+               }
+
+               controller->pio_mem_index = ret;
+
+               /*
+                * For PIO MEM, the bus_address_hi parameter is hard-coded 0
+                * because we always assign 32-bit PCI bus BAR ranges.
+                */
+               ret = gxio_trio_init_pio_region_aux(trio_context,
+                                                   controller->pio_mem_index,
+                                                   controller->mac,
+                                                   0,
+                                                   0);
+               if (ret < 0) {
+                       pr_err("PCI: MEM PIO init failure on TRIO %d mac %d, "
+                               "give up\n", controller->trio_index,
+                               controller->mac);
+
+                       continue;
+               }
+
+               /*
+                * Configure a Mem-Map region for each memory controller so
+                * that Linux can map all of its PA space to the PCI bus.
+                * Use the IOMMU to handle hash-for-home memory.
+                */
+               for_each_online_node(j) {
+                       unsigned long start_pfn = node_start_pfn[j];
+                       unsigned long end_pfn = node_end_pfn[j];
+                       unsigned long nr_pages = end_pfn - start_pfn;
+
+                       ret = gxio_trio_alloc_memory_maps(trio_context, 1, 0,
+                                                         0);
+                       if (ret < 0) {
+                               pr_err("PCI: Mem-Map alloc failure on TRIO %d "
+                                       "mac %d for MC %d, give up\n",
+                                       controller->trio_index,
+                                       controller->mac, j);
+
+                               goto alloc_mem_map_failed;
+                       }
+
+                       controller->mem_maps[j] = ret;
+
+                       /*
+                        * Initialize the Mem-Map and the I/O MMU so that all
+                        * the physical memory can be accessed by the endpoint
+                        * devices. The base bus address is set to the base CPA
+                        * of this memory controller plus an offset (see pci.h).
+                        * The region's base VA is set to the base CPA. The
+                        * I/O MMU table essentially translates the CPA to
+                        * the real PA. Implicitly, for node 0, we create
+                        * a separate Mem-Map region that serves as the inbound
+                        * window for legacy 32-bit devices. This is a direct
+                        * map of the low 4GB CPA space.
+                        */
+                       ret = gxio_trio_init_memory_map_mmu_aux(trio_context,
+                               controller->mem_maps[j],
+                               start_pfn << PAGE_SHIFT,
+                               nr_pages << PAGE_SHIFT,
+                               trio_context->asid,
+                               controller->mac,
+                               (start_pfn << PAGE_SHIFT) +
+                               TILE_PCI_MEM_MAP_BASE_OFFSET,
+                               j,
+                               GXIO_TRIO_ORDER_MODE_UNORDERED);
+                       if (ret < 0) {
+                               pr_err("PCI: Mem-Map init failure on TRIO %d "
+                                       "mac %d for MC %d, give up\n",
+                                       controller->trio_index,
+                                       controller->mac, j);
+
+                               goto alloc_mem_map_failed;
+                       }
+                       continue;
+
+alloc_mem_map_failed:
+                       break;
+               }
+
+       }
+
+       return 0;
+}
+subsys_initcall(pcibios_init);
+
+/* Note: to be deleted after Linux 3.6 merge. */
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+}
+
+/*
+ * This can be called from the generic PCI layer, but doesn't need to
+ * do anything.
+ */
+char __devinit *pcibios_setup(char *str)
+{
+       if (!strcmp(str, "off")) {
+               pci_probe = 0;
+               return NULL;
+       }
+       return str;
+}
+
+/*
+ * This is called from the generic Linux layer.
+ */
+void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+       pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+/*
+ * Enable memory address decoding, as appropriate, for the
+ * device described by the 'dev' struct. The I/O decoding
+ * is disabled, though the TILE-Gx supports I/O addressing.
+ *
+ * This is called from the generic PCI layer, and can be called
+ * for bridges or endpoints.
+ */
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+       return pci_enable_resources(dev, mask);
+}
+
+/* Called for each device after PCI setup is done. */
+static void __init
+pcibios_fixup_final(struct pci_dev *pdev)
+{
+       set_dma_ops(&pdev->dev, gx_pci_dma_map_ops);
+       set_dma_offset(&pdev->dev, TILE_PCI_MEM_MAP_BASE_OFFSET);
+       pdev->dev.archdata.max_direct_dma_addr =
+               TILE_PCI_MAX_DIRECT_DMA_ADDRESS;
+}
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, pcibios_fixup_final);
+
+/* Map a PCI MMIO bus address into VA space. */
+void __iomem *ioremap(resource_size_t phys_addr, unsigned long size)
+{
+       struct pci_controller *controller = NULL;
+       resource_size_t bar_start;
+       resource_size_t bar_end;
+       resource_size_t offset;
+       resource_size_t start;
+       resource_size_t end;
+       int trio_fd;
+       int i, j;
+
+       start = phys_addr;
+       end = phys_addr + size - 1;
+
+       /*
+        * In the following, each PCI controller's mem_resources[1]
+        * represents its (non-prefetchable) PCI memory resource and
+        * mem_resources[2] refers to its prefetchable PCI memory resource.
+        * By searching phys_addr in each controller's mem_resources[], we can
+        * determine the controller that should accept the PCI memory access.
+        */
+
+       for (i = 0; i < num_rc_controllers; i++) {
+               /*
+                * Skip controllers that are not properly initialized or
+                * have down links.
+                */
+               if (pci_controllers[i].root_bus == NULL)
+                       continue;
+
+               for (j = 1; j < 3; j++) {
+                       bar_start =
+                               pci_controllers[i].mem_resources[j].start;
+                       bar_end =
+                               pci_controllers[i].mem_resources[j].end;
+
+                       if ((start >= bar_start) && (end <= bar_end)) {
+
+                               controller = &pci_controllers[i];
+
+                               goto got_it;
+                       }
+               }
+       }
+
+       if (controller == NULL)
+               return NULL;
+
+got_it:
+       trio_fd = controller->trio->fd;
+
+       /* Convert the resource start to the bus address offset. */
+       start = phys_addr - controller->mem_offset;
+
+       offset = HV_TRIO_PIO_OFFSET(controller->pio_mem_index) + start;
+
+       /*
+        * We need to keep the PCI bus address's in-page offset in the VA.
+        */
+       return iorpc_ioremap(trio_fd, offset, size) +
+               (phys_addr & (PAGE_SIZE - 1));
+}
+EXPORT_SYMBOL(ioremap);
+
+void pci_iounmap(struct pci_dev *dev, void __iomem *addr)
+{
+       iounmap(addr);
+}
+EXPORT_SYMBOL(pci_iounmap);
+
+/****************************************************************
+ *
+ * Tile PCI config space read/write routines
+ *
+ ****************************************************************/
+
+/*
+ * These are the normal read and write ops
+ * These are expanded with macros from  pci_bus_read_config_byte() etc.
+ *
+ * devfn is the combined PCI device & function.
+ *
+ * offset is in bytes, from the start of config space for the
+ * specified bus & device.
+ */
+
+static int __devinit tile_cfg_read(struct pci_bus *bus,
+                                  unsigned int devfn,
+                                  int offset,
+                                  int size,
+                                  u32 *val)
+{
+       struct pci_controller *controller = bus->sysdata;
+       gxio_trio_context_t *trio_context = controller->trio;
+       int busnum = bus->number & 0xff;
+       int device = PCI_SLOT(devfn);
+       int function = PCI_FUNC(devfn);
+       int config_type = 1;
+       TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR_t cfg_addr;
+       void *mmio_addr;
+
+       /*
+        * Map all accesses to the local device on root bus into the
+        * MMIO space of the MAC. Accesses to the downstream devices
+        * go to the PIO space.
+        */
+       if (pci_is_root_bus(bus)) {
+               if (device == 0) {
+                       /*
+                        * This is the internal downstream P2P bridge,
+                        * access directly.
+                        */
+                       unsigned int reg_offset;
+
+                       reg_offset = ((offset & 0xFFF) <<
+                               TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+                               (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_PROTECTED
+                               << TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+                               (controller->mac <<
+                                       TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+                       mmio_addr = trio_context->mmio_base_mac + reg_offset;
+
+                       goto valid_device;
+
+               } else {
+                       /*
+                        * We fake an empty device for (device > 0),
+                        * since there is only one device on bus 0.
+                        */
+                       goto invalid_device;
+               }
+       }
+
+       /*
+        * Accesses to the directly attached device have to be
+        * sent as type-0 configs.
+        */
+
+       if (busnum == (controller->first_busno + 1)) {
+               /*
+                * There is only one device off of our built-in P2P bridge.
+                */
+               if (device != 0)
+                       goto invalid_device;
+
+               config_type = 0;
+       }
+
+       cfg_addr.word = 0;
+       cfg_addr.reg_addr = (offset & 0xFFF);
+       cfg_addr.fn = function;
+       cfg_addr.dev = device;
+       cfg_addr.bus = busnum;
+       cfg_addr.type = config_type;
+
+       /*
+        * Note that we don't set the mac field in cfg_addr because the
+        * mapping is per port.
+        */
+
+       mmio_addr = trio_context->mmio_base_pio_cfg[controller->mac] +
+                       cfg_addr.word;
+
+valid_device:
+
+       switch (size) {
+       case 4:
+               *val = __gxio_mmio_read32(mmio_addr);
+               break;
+
+       case 2:
+               *val = __gxio_mmio_read16(mmio_addr);
+               break;
+
+       case 1:
+               *val = __gxio_mmio_read8(mmio_addr);
+               break;
+
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+
+       TRACE_CFG_RD(size, *val, busnum, device, function, offset);
+
+       return 0;
+
+invalid_device:
+
+       switch (size) {
+       case 4:
+               *val = 0xFFFFFFFF;
+               break;
+
+       case 2:
+               *val = 0xFFFF;
+               break;
+
+       case 1:
+               *val = 0xFF;
+               break;
+
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+
+       return 0;
+}
+
+
+/*
+ * See tile_cfg_read() for relevent comments.
+ * Note that "val" is the value to write, not a pointer to that value.
+ */
+static int __devinit tile_cfg_write(struct pci_bus *bus,
+                                   unsigned int devfn,
+                                   int offset,
+                                   int size,
+                                   u32 val)
+{
+       struct pci_controller *controller = bus->sysdata;
+       gxio_trio_context_t *trio_context = controller->trio;
+       int busnum = bus->number & 0xff;
+       int device = PCI_SLOT(devfn);
+       int function = PCI_FUNC(devfn);
+       int config_type = 1;
+       TRIO_TILE_PIO_REGION_SETUP_CFG_ADDR_t cfg_addr;
+       void *mmio_addr;
+       u32 val_32 = (u32)val;
+       u16 val_16 = (u16)val;
+       u8 val_8 = (u8)val;
+
+       /*
+        * Map all accesses to the local device on root bus into the
+        * MMIO space of the MAC. Accesses to the downstream devices
+        * go to the PIO space.
+        */
+       if (pci_is_root_bus(bus)) {
+               if (device == 0) {
+                       /*
+                        * This is the internal downstream P2P bridge,
+                        * access directly.
+                        */
+                       unsigned int reg_offset;
+
+                       reg_offset = ((offset & 0xFFF) <<
+                               TRIO_CFG_REGION_ADDR__REG_SHIFT) |
+                               (TRIO_CFG_REGION_ADDR__INTFC_VAL_MAC_PROTECTED
+                               << TRIO_CFG_REGION_ADDR__INTFC_SHIFT ) |
+                               (controller->mac <<
+                                       TRIO_CFG_REGION_ADDR__MAC_SEL_SHIFT);
+
+                       mmio_addr = trio_context->mmio_base_mac + reg_offset;
+
+                       goto valid_device;
+
+               } else {
+                       /*
+                        * We fake an empty device for (device > 0),
+                        * since there is only one device on bus 0.
+                        */
+                       goto invalid_device;
+               }
+       }
+
+       /*
+        * Accesses to the directly attached device have to be
+        * sent as type-0 configs.
+        */
+
+       if (busnum == (controller->first_busno + 1)) {
+               /*
+                * There is only one device off of our built-in P2P bridge.
+                */
+               if (device != 0)
+                       goto invalid_device;
+
+               config_type = 0;
+       }
+
+       cfg_addr.word = 0;
+       cfg_addr.reg_addr = (offset & 0xFFF);
+       cfg_addr.fn = function;
+       cfg_addr.dev = device;
+       cfg_addr.bus = busnum;
+       cfg_addr.type = config_type;
+
+       /*
+        * Note that we don't set the mac field in cfg_addr because the
+        * mapping is per port.
+        */
+
+       mmio_addr = trio_context->mmio_base_pio_cfg[controller->mac] +
+                       cfg_addr.word;
+
+valid_device:
+
+       switch (size) {
+       case 4:
+               __gxio_mmio_write32(mmio_addr, val_32);
+               TRACE_CFG_WR(size, val_32, busnum, device, function, offset);
+               break;
+
+       case 2:
+               __gxio_mmio_write16(mmio_addr, val_16);
+               TRACE_CFG_WR(size, val_16, busnum, device, function, offset);
+               break;
+
+       case 1:
+               __gxio_mmio_write8(mmio_addr, val_8);
+               TRACE_CFG_WR(size, val_8, busnum, device, function, offset);
+               break;
+
+       default:
+               return PCIBIOS_FUNC_NOT_SUPPORTED;
+       }
+
+invalid_device:
+
+       return 0;
+}
+
+
+static struct pci_ops tile_cfg_ops = {
+       .read =         tile_cfg_read,
+       .write =        tile_cfg_write,
+};
+
+
+/*
+ * MSI support starts here.
+ */
+static unsigned int
+tilegx_msi_startup(struct irq_data *d)
+{
+       if (d->msi_desc)
+               unmask_msi_irq(d);
+
+       return 0;
+}
+
+static void
+tilegx_msi_ack(struct irq_data *d)
+{
+       __insn_mtspr(SPR_IPI_EVENT_RESET_K, 1UL << d->irq);
+}
+
+static void
+tilegx_msi_mask(struct irq_data *d)
+{
+       mask_msi_irq(d);
+       __insn_mtspr(SPR_IPI_MASK_SET_K, 1UL << d->irq);
+}
+
+static void
+tilegx_msi_unmask(struct irq_data *d)
+{
+       __insn_mtspr(SPR_IPI_MASK_RESET_K, 1UL << d->irq);
+       unmask_msi_irq(d);
+}
+
+static struct irq_chip tilegx_msi_chip = {
+       .name                   = "tilegx_msi",
+       .irq_startup            = tilegx_msi_startup,
+       .irq_ack                = tilegx_msi_ack,
+       .irq_mask               = tilegx_msi_mask,
+       .irq_unmask             = tilegx_msi_unmask,
+
+       /* TBD: support set_affinity. */
+};
+
+int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
+{
+       struct pci_controller *controller;
+       gxio_trio_context_t *trio_context;
+       struct msi_msg msg;
+       int default_irq;
+       uint64_t mem_map_base;
+       uint64_t mem_map_limit;
+       u64 msi_addr;
+       int mem_map;
+       int cpu;
+       int irq;
+       int ret;
+
+       irq = create_irq();
+       if (irq < 0)
+               return irq;
+
+       /*
+        * Since we use a 64-bit Mem-Map to accept the MSI write, we fail
+        * devices that are not capable of generating a 64-bit message address.
+        * These devices will fall back to using the legacy interrupts.
+        * Most PCIe endpoint devices do support 64-bit message addressing.
+        */
+       if (desc->msi_attrib.is_64 == 0) {
+               dev_printk(KERN_INFO, &pdev->dev,
+                       "64-bit MSI message address not supported, "
+                       "falling back to legacy interrupts.\n");
+
+               ret = -ENOMEM;
+               goto is_64_failure;
+       }
+
+       default_irq = desc->msi_attrib.default_irq;
+       controller = irq_get_handler_data(default_irq);
+
+       BUG_ON(!controller);
+
+       trio_context = controller->trio;
+
+       /*
+        * Allocate the Mem-Map that will accept the MSI write and
+        * trigger the TILE-side interrupts.
+        */
+       mem_map = gxio_trio_alloc_memory_maps(trio_context, 1, 0, 0);
+       if (mem_map < 0) {
+               dev_printk(KERN_INFO, &pdev->dev,
+                       "%s Mem-Map alloc failure. "
+                       "Failed to initialize MSI interrupts. "
+                       "Falling back to legacy interrupts.\n",
+                       desc->msi_attrib.is_msix ? "MSI-X" : "MSI");
+
+               ret = -ENOMEM;
+               goto msi_mem_map_alloc_failure;
+       }
+
+       /* We try to distribute different IRQs to different tiles. */
+       cpu = tile_irq_cpu(irq);
+
+       /*
+        * Now call up to the HV to configure the Mem-Map interrupt and
+        * set up the IPI binding.
+        */
+       mem_map_base = MEM_MAP_INTR_REGIONS_BASE +
+               mem_map * MEM_MAP_INTR_REGION_SIZE;
+       mem_map_limit = mem_map_base + MEM_MAP_INTR_REGION_SIZE - 1;
+
+       ret = gxio_trio_config_msi_intr(trio_context, cpu_x(cpu), cpu_y(cpu),
+                                       KERNEL_PL, irq, controller->mac,
+                                       mem_map, mem_map_base, mem_map_limit,
+                                       trio_context->asid);
+       if (ret < 0) {
+               dev_printk(KERN_INFO, &pdev->dev, "HV MSI config failed.\n");
+
+               goto hv_msi_config_failure;
+       }
+
+       irq_set_msi_desc(irq, desc);
+
+       msi_addr = mem_map_base + TRIO_MAP_MEM_REG_INT3 - TRIO_MAP_MEM_REG_INT0;
+
+       msg.address_hi = msi_addr >> 32;
+       msg.address_lo = msi_addr & 0xffffffff;
+
+       msg.data = mem_map;
+
+       write_msi_msg(irq, &msg);
+       irq_set_chip_and_handler(irq, &tilegx_msi_chip, handle_level_irq);
+       irq_set_handler_data(irq, controller);
+
+       return 0;
+
+hv_msi_config_failure:
+       /* Free mem-map */
+msi_mem_map_alloc_failure:
+is_64_failure:
+       destroy_irq(irq);
+       return ret;
+}
+
+void arch_teardown_msi_irq(unsigned int irq)
+{
+       destroy_irq(irq);
+}
index dd87f342039064a0e545382acdf65321d0815ac1..6a649a4462d35ee7b70f0b2305e58bd90028ed87 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/irq.h>
 #include <linux/kexec.h>
 #include <linux/pci.h>
+#include <linux/swiotlb.h>
 #include <linux/initrd.h>
 #include <linux/io.h>
 #include <linux/highmem.h>
@@ -109,7 +110,7 @@ static unsigned int __initdata maxnodemem_pfn[MAX_NUMNODES] = {
 };
 static nodemask_t __initdata isolnodes;
 
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(__tilegx__)
 enum { DEFAULT_PCI_RESERVE_MB = 64 };
 static unsigned int __initdata pci_reserve_mb = DEFAULT_PCI_RESERVE_MB;
 unsigned long __initdata pci_reserve_start_pfn = -1U;
@@ -160,7 +161,7 @@ static int __init setup_isolnodes(char *str)
 }
 early_param("isolnodes", setup_isolnodes);
 
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(__tilegx__)
 static int __init setup_pci_reserve(char* str)
 {
        unsigned long mb;
@@ -171,7 +172,7 @@ static int __init setup_pci_reserve(char* str)
 
        pci_reserve_mb = mb;
        pr_info("Reserving %dMB for PCIE root complex mappings\n",
-              pci_reserve_mb);
+               pci_reserve_mb);
        return 0;
 }
 early_param("pci_reserve", setup_pci_reserve);
@@ -411,7 +412,7 @@ static void __init setup_memory(void)
                        continue;
                }
 #endif
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(__tilegx__)
                /*
                 * Blocks that overlap the pci reserved region must
                 * have enough space to hold the maximum percpu data
@@ -604,11 +605,9 @@ static void __init setup_bootmem_allocator_node(int i)
        /* Free all the space back into the allocator. */
        free_bootmem(PFN_PHYS(start), PFN_PHYS(end - start));
 
-#if defined(CONFIG_PCI)
+#if defined(CONFIG_PCI) && !defined(__tilegx__)
        /*
-        * Throw away any memory aliased by the PCI region.  FIXME: this
-        * is a temporary hack to work around bug 10502, and needs to be
-        * fixed properly.
+        * Throw away any memory aliased by the PCI region.
         */
        if (pci_reserve_start_pfn < end && pci_reserve_end_pfn > start)
                reserve_bootmem(PFN_PHYS(pci_reserve_start_pfn),
@@ -658,6 +657,8 @@ static void __init zone_sizes_init(void)
        unsigned long zones_size[MAX_NR_ZONES] = { 0 };
        int size = percpu_size();
        int num_cpus = smp_height * smp_width;
+       const unsigned long dma_end = (1UL << (32 - PAGE_SHIFT));
+
        int i;
 
        for (i = 0; i < num_cpus; ++i)
@@ -729,6 +730,14 @@ static void __init zone_sizes_init(void)
                zones_size[ZONE_NORMAL] = end - start;
 #endif
 
+               if (start < dma_end) {
+                       zones_size[ZONE_DMA] = min(zones_size[ZONE_NORMAL],
+                                                  dma_end - start);
+                       zones_size[ZONE_NORMAL] -= zones_size[ZONE_DMA];
+               } else {
+                       zones_size[ZONE_DMA] = 0;
+               }
+
                /* Take zone metadata from controller 0 if we're isolnode. */
                if (node_isset(i, isolnodes))
                        NODE_DATA(i)->bdata = &bootmem_node_data[0];
@@ -738,7 +747,7 @@ static void __init zone_sizes_init(void)
                       PFN_UP(node_percpu[i]));
 
                /* Track the type of memory on each node */
-               if (zones_size[ZONE_NORMAL])
+               if (zones_size[ZONE_NORMAL] || zones_size[ZONE_DMA])
                        node_set_state(i, N_NORMAL_MEMORY);
 #ifdef CONFIG_HIGHMEM
                if (end != start)
@@ -1343,7 +1352,7 @@ void __init setup_arch(char **cmdline_p)
        setup_cpu_maps();
 
 
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(__tilegx__)
        /*
         * Initialize the PCI structures.  This is done before memory
         * setup so that we know whether or not a pci_reserve region
@@ -1372,6 +1381,10 @@ void __init setup_arch(char **cmdline_p)
         * any memory using the bootmem allocator.
         */
 
+#ifdef CONFIG_SWIOTLB
+       swiotlb_init(0);
+#endif
+
        paging_init();
        setup_numa_mapping();
        zone_sizes_init();
@@ -1522,11 +1535,10 @@ static struct resource code_resource = {
 };
 
 /*
- * We reserve all resources above 4GB so that PCI won't try to put
- * mappings above 4GB; the standard allows that for some devices but
- * the probing code trunates values to 32 bits.
+ * On Pro, we reserve all resources above 4GB so that PCI won't try to put
+ * mappings above 4GB.
  */
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(__tilegx__)
 static struct resource* __init
 insert_non_bus_resource(void)
 {
@@ -1571,8 +1583,7 @@ static int __init request_standard_resources(void)
        int i;
        enum { CODE_DELTA = MEM_SV_INTRPT - PAGE_OFFSET };
 
-       iomem_resource.end = -1LL;
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(__tilegx__)
        insert_non_bus_resource();
 #endif
 
@@ -1580,7 +1591,7 @@ static int __init request_standard_resources(void)
                u64 start_pfn = node_start_pfn[i];
                u64 end_pfn = node_end_pfn[i];
 
-#ifdef CONFIG_PCI
+#if defined(CONFIG_PCI) && !defined(__tilegx__)
                if (start_pfn <= pci_reserve_start_pfn &&
                    end_pfn > pci_reserve_start_pfn) {
                        if (end_pfn > pci_reserve_end_pfn)
index 84873fbe8f2769b0bfa22faaed187ae0919c523d..e686c5ac90be36bcf14d33019ac97bb5e46bc4ee 100644 (file)
@@ -198,17 +198,7 @@ void __cpuinit online_secondary(void)
 
        notify_cpu_starting(smp_processor_id());
 
-       /*
-        * We need to hold call_lock, so there is no inconsistency
-        * between the time smp_call_function() determines number of
-        * IPI recipients, and the time when the determination is made
-        * for which cpus receive the IPI. Holding this
-        * lock helps us to not include this cpu in a currently in progress
-        * smp_call_function().
-        */
-       ipi_call_lock();
        set_cpu_online(smp_processor_id(), 1);
-       ipi_call_unlock();
        __get_cpu_var(cpu_state) = CPU_ONLINE;
 
        /* Set up tile-specific state for this cpu. */
diff --git a/arch/tile/kernel/usb.c b/arch/tile/kernel/usb.c
new file mode 100644 (file)
index 0000000..5af8deb
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ * Register the Tile-Gx USB interfaces as platform devices.
+ *
+ * The actual USB driver is just some glue (in
+ * drivers/usb/host/[eo]hci-tilegx.c) which makes the registers available
+ * to the standard kernel EHCI and OHCI drivers.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/usb/tilegx.h>
+#include <linux/types.h>
+
+static u64 ehci_dmamask = DMA_BIT_MASK(32);
+
+#define USB_HOST_DEF(unit, type, dmamask) \
+       static struct \
+           tilegx_usb_platform_data tilegx_usb_platform_data_ ## type ## \
+               hci ## unit = { \
+               .dev_index = unit, \
+       }; \
+       \
+       static struct platform_device tilegx_usb_ ## type ## hci ## unit = { \
+               .name           = "tilegx-" #type "hci", \
+               .id             = unit, \
+               .dev = { \
+                       .dma_mask               = dmamask, \
+                       .coherent_dma_mask      = DMA_BIT_MASK(32), \
+                       .platform_data = \
+                               &tilegx_usb_platform_data_ ## type ## hci ## \
+                               unit, \
+               }, \
+       };
+
+USB_HOST_DEF(0, e, &ehci_dmamask)
+USB_HOST_DEF(0, o, NULL)
+USB_HOST_DEF(1, e, &ehci_dmamask)
+USB_HOST_DEF(1, o, NULL)
+
+#undef USB_HOST_DEF
+
+static struct platform_device *tilegx_usb_devices[] __initdata = {
+       &tilegx_usb_ehci0,
+       &tilegx_usb_ehci1,
+       &tilegx_usb_ohci0,
+       &tilegx_usb_ohci1,
+};
+
+/** Add our set of possible USB devices. */
+static int __init tilegx_usb_init(void)
+{
+       platform_add_devices(tilegx_usb_devices,
+                            ARRAY_SIZE(tilegx_usb_devices));
+
+       return 0;
+}
+arch_initcall(tilegx_usb_init);
index e4bab5bd3f316a54d050e56abe14bc31ba31aaff..c3ca3e64d9d906b453a6be36979ef8d5e976447a 100644 (file)
 #include <net/checksum.h>
 #include <linux/module.h>
 
-static inline unsigned int longto16(unsigned long x)
-{
-       unsigned long ret;
-#ifdef __tilegx__
-       ret = __insn_v2sadu(x, 0);
-       ret = __insn_v2sadu(ret, 0);
-#else
-       ret = __insn_sadh_u(x, 0);
-       ret = __insn_sadh_u(ret, 0);
-#endif
-       return ret;
-}
-
 __wsum do_csum(const unsigned char *buff, int len)
 {
        int odd, count;
@@ -94,7 +81,7 @@ __wsum do_csum(const unsigned char *buff, int len)
        }
        if (len & 1)
                result += *buff;
-       result = longto16(result);
+       result = csum_long(result);
        if (odd)
                result = swab16(result);
 out:
index dbcbdf7b8aa81fe9ed18d4d2613f03e763116b6e..5f7868dcd6d482abc42e00b6349f5234d0c63c3b 100644 (file)
@@ -64,10 +64,6 @@ early_param("noallocl2", set_noallocl2);
 
 #endif
 
-/* Provide no-op versions of these routines to keep flush_remote() cleaner. */
-#define mark_caches_evicted_start() 0
-#define mark_caches_evicted_finish(mask, timestamp) do {} while (0)
-
 
 /*
  * Update the irq_stat for cpus that we are going to interrupt
@@ -107,7 +103,6 @@ static void hv_flush_update(const struct cpumask *cache_cpumask,
  *    there's never any good reason for hv_flush_remote() to fail.
  *  - Accepts a 32-bit PFN rather than a 64-bit PA, which generally
  *    is the type that Linux wants to pass around anyway.
- *  - Centralizes the mark_caches_evicted() handling.
  *  - Canonicalizes that lengths of zero make cpumasks NULL.
  *  - Handles deferring TLB flushes for dataplane tiles.
  *  - Tracks remote interrupts in the per-cpu irq_cpustat_t.
@@ -126,7 +121,6 @@ void flush_remote(unsigned long cache_pfn, unsigned long cache_control,
                  HV_Remote_ASID *asids, int asidcount)
 {
        int rc;
-       int timestamp = 0;  /* happy compiler */
        struct cpumask cache_cpumask_copy, tlb_cpumask_copy;
        struct cpumask *cache_cpumask, *tlb_cpumask;
        HV_PhysAddr cache_pa;
@@ -157,15 +151,11 @@ void flush_remote(unsigned long cache_pfn, unsigned long cache_control,
        hv_flush_update(cache_cpumask, tlb_cpumask, tlb_va, tlb_length,
                        asids, asidcount);
        cache_pa = (HV_PhysAddr)cache_pfn << PAGE_SHIFT;
-       if (cache_control & HV_FLUSH_EVICT_L2)
-               timestamp = mark_caches_evicted_start();
        rc = hv_flush_remote(cache_pa, cache_control,
                             cpumask_bits(cache_cpumask),
                             tlb_va, tlb_length, tlb_pgsize,
                             cpumask_bits(tlb_cpumask),
                             asids, asidcount);
-       if (cache_control & HV_FLUSH_EVICT_L2)
-               mark_caches_evicted_finish(cache_cpumask, timestamp);
        if (rc == 0)
                return;
        cpumask_scnprintf(cache_buf, sizeof(cache_buf), &cache_cpumask_copy);
@@ -180,85 +170,86 @@ void flush_remote(unsigned long cache_pfn, unsigned long cache_control,
        panic("Unsafe to continue.");
 }
 
-void flush_remote_page(struct page *page, int order)
+static void homecache_finv_page_va(void* va, int home)
 {
-       int i, pages = (1 << order);
-       for (i = 0; i < pages; ++i, ++page) {
-               void *p = kmap_atomic(page);
-               int hfh = 0;
-               int home = page_home(page);
-#if CHIP_HAS_CBOX_HOME_MAP()
-               if (home == PAGE_HOME_HASH)
-                       hfh = 1;
-               else
-#endif
-                       BUG_ON(home < 0 || home >= NR_CPUS);
-               finv_buffer_remote(p, PAGE_SIZE, hfh);
-               kunmap_atomic(p);
+       if (home == smp_processor_id()) {
+               finv_buffer_local(va, PAGE_SIZE);
+       } else if (home == PAGE_HOME_HASH) {
+               finv_buffer_remote(va, PAGE_SIZE, 1);
+       } else {
+               BUG_ON(home < 0 || home >= NR_CPUS);
+               finv_buffer_remote(va, PAGE_SIZE, 0);
        }
 }
 
-void homecache_evict(const struct cpumask *mask)
+void homecache_finv_map_page(struct page *page, int home)
 {
-       flush_remote(0, HV_FLUSH_EVICT_L2, mask, 0, 0, 0, NULL, NULL, 0);
+       unsigned long flags;
+       unsigned long va;
+       pte_t *ptep;
+       pte_t pte;
+
+       if (home == PAGE_HOME_UNCACHED)
+               return;
+       local_irq_save(flags);
+#ifdef CONFIG_HIGHMEM
+       va = __fix_to_virt(FIX_KMAP_BEGIN + kmap_atomic_idx_push() +
+                          (KM_TYPE_NR * smp_processor_id()));
+#else
+       va = __fix_to_virt(FIX_HOMECACHE_BEGIN + smp_processor_id());
+#endif
+       ptep = virt_to_pte(NULL, (unsigned long)va);
+       pte = pfn_pte(page_to_pfn(page), PAGE_KERNEL);
+       __set_pte(ptep, pte_set_home(pte, home));
+       homecache_finv_page_va((void *)va, home);
+       __pte_clear(ptep);
+       hv_flush_page(va, PAGE_SIZE);
+#ifdef CONFIG_HIGHMEM
+       kmap_atomic_idx_pop();
+#endif
+       local_irq_restore(flags);
 }
 
-/*
- * Return a mask of the cpus whose caches currently own these pages.
- * The return value is whether the pages are all coherently cached
- * (i.e. none are immutable, incoherent, or uncached).
- */
-static int homecache_mask(struct page *page, int pages,
-                         struct cpumask *home_mask)
+static void homecache_finv_page_home(struct page *page, int home)
 {
-       int i;
-       int cached_coherently = 1;
-       cpumask_clear(home_mask);
-       for (i = 0; i < pages; ++i) {
-               int home = page_home(&page[i]);
-               if (home == PAGE_HOME_IMMUTABLE ||
-                   home == PAGE_HOME_INCOHERENT) {
-                       cpumask_copy(home_mask, cpu_possible_mask);
-                       return 0;
-               }
-#if CHIP_HAS_CBOX_HOME_MAP()
-               if (home == PAGE_HOME_HASH) {
-                       cpumask_or(home_mask, home_mask, &hash_for_home_map);
-                       continue;
-               }
-#endif
-               if (home == PAGE_HOME_UNCACHED) {
-                       cached_coherently = 0;
-                       continue;
-               }
-               BUG_ON(home < 0 || home >= NR_CPUS);
-               cpumask_set_cpu(home, home_mask);
-       }
-       return cached_coherently;
+       if (!PageHighMem(page) && home == page_home(page))
+               homecache_finv_page_va(page_address(page), home);
+       else
+               homecache_finv_map_page(page, home);
 }
 
-/*
- * Return the passed length, or zero if it's long enough that we
- * believe we should evict the whole L2 cache.
- */
-static unsigned long cache_flush_length(unsigned long length)
+static inline bool incoherent_home(int home)
 {
-       return (length >= CHIP_L2_CACHE_SIZE()) ? HV_FLUSH_EVICT_L2 : length;
+       return home == PAGE_HOME_IMMUTABLE || home == PAGE_HOME_INCOHERENT;
 }
 
-/* Flush a page out of whatever cache(s) it is in. */
-void homecache_flush_cache(struct page *page, int order)
+static void homecache_finv_page_internal(struct page *page, int force_map)
 {
-       int pages = 1 << order;
-       int length = cache_flush_length(pages * PAGE_SIZE);
-       unsigned long pfn = page_to_pfn(page);
-       struct cpumask home_mask;
-
-       homecache_mask(page, pages, &home_mask);
-       flush_remote(pfn, length, &home_mask, 0, 0, 0, NULL, NULL, 0);
-       sim_validate_lines_evicted(PFN_PHYS(pfn), pages * PAGE_SIZE);
+       int home = page_home(page);
+       if (home == PAGE_HOME_UNCACHED)
+               return;
+       if (incoherent_home(home)) {
+               int cpu;
+               for_each_cpu(cpu, &cpu_cacheable_map)
+                       homecache_finv_map_page(page, cpu);
+       } else if (force_map) {
+               /* Force if, e.g., the normal mapping is migrating. */
+               homecache_finv_map_page(page, home);
+       } else {
+               homecache_finv_page_home(page, home);
+       }
+       sim_validate_lines_evicted(PFN_PHYS(page_to_pfn(page)), PAGE_SIZE);
 }
 
+void homecache_finv_page(struct page *page)
+{
+       homecache_finv_page_internal(page, 0);
+}
+
+void homecache_evict(const struct cpumask *mask)
+{
+       flush_remote(0, HV_FLUSH_EVICT_L2, mask, 0, 0, 0, NULL, NULL, 0);
+}
 
 /* Report the home corresponding to a given PTE. */
 static int pte_to_home(pte_t pte)
@@ -441,15 +432,8 @@ struct page *homecache_alloc_pages_node(int nid, gfp_t gfp_mask,
        return page;
 }
 
-void homecache_free_pages(unsigned long addr, unsigned int order)
+void __homecache_free_pages(struct page *page, unsigned int order)
 {
-       struct page *page;
-
-       if (addr == 0)
-               return;
-
-       VM_BUG_ON(!virt_addr_valid((void *)addr));
-       page = virt_to_page((void *)addr);
        if (put_page_testzero(page)) {
                homecache_change_page_home(page, order, initial_page_home());
                if (order == 0) {
@@ -460,3 +444,13 @@ void homecache_free_pages(unsigned long addr, unsigned int order)
                }
        }
 }
+EXPORT_SYMBOL(__homecache_free_pages);
+
+void homecache_free_pages(unsigned long addr, unsigned int order)
+{
+       if (addr != 0) {
+               VM_BUG_ON(!virt_addr_valid((void *)addr));
+               __homecache_free_pages(virt_to_page((void *)addr), order);
+       }
+}
+EXPORT_SYMBOL(homecache_free_pages);
index 630dd2ce2afef5237829f83804cea010f18a7dd9..ef29d6c5e10e9b76216b61e4cf7d2722c824d8e9 100644 (file)
@@ -150,7 +150,21 @@ void __init shatter_pmd(pmd_t *pmd)
        assign_pte(pmd, pte);
 }
 
-#ifdef CONFIG_HIGHMEM
+#ifdef __tilegx__
+static pmd_t *__init get_pmd(pgd_t pgtables[], unsigned long va)
+{
+       pud_t *pud = pud_offset(&pgtables[pgd_index(va)], va);
+       if (pud_none(*pud))
+               assign_pmd(pud, alloc_pmd());
+       return pmd_offset(pud, va);
+}
+#else
+static pmd_t *__init get_pmd(pgd_t pgtables[], unsigned long va)
+{
+       return pmd_offset(pud_offset(&pgtables[pgd_index(va)], va), va);
+}
+#endif
+
 /*
  * This function initializes a certain range of kernel virtual memory
  * with new bootmem page tables, everywhere page tables are missing in
@@ -163,24 +177,17 @@ void __init shatter_pmd(pmd_t *pmd)
  * checking the pgd every time.
  */
 static void __init page_table_range_init(unsigned long start,
-                                        unsigned long end, pgd_t *pgd_base)
+                                        unsigned long end, pgd_t *pgd)
 {
-       pgd_t *pgd;
-       int pgd_idx;
        unsigned long vaddr;
-
-       vaddr = start;
-       pgd_idx = pgd_index(vaddr);
-       pgd = pgd_base + pgd_idx;
-
-       for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
-               pmd_t *pmd = pmd_offset(pud_offset(pgd, vaddr), vaddr);
+       start = round_down(start, PMD_SIZE);
+       end = round_up(end, PMD_SIZE);
+       for (vaddr = start; vaddr < end; vaddr += PMD_SIZE) {
+               pmd_t *pmd = get_pmd(pgd, vaddr);
                if (pmd_none(*pmd))
                        assign_pte(pmd, alloc_pte());
-               vaddr += PMD_SIZE;
        }
 }
-#endif /* CONFIG_HIGHMEM */
 
 
 #if CHIP_HAS_CBOX_HOME_MAP()
@@ -404,21 +411,6 @@ static inline pgprot_t ktext_set_nocache(pgprot_t prot)
        return prot;
 }
 
-#ifndef __tilegx__
-static pmd_t *__init get_pmd(pgd_t pgtables[], unsigned long va)
-{
-       return pmd_offset(pud_offset(&pgtables[pgd_index(va)], va), va);
-}
-#else
-static pmd_t *__init get_pmd(pgd_t pgtables[], unsigned long va)
-{
-       pud_t *pud = pud_offset(&pgtables[pgd_index(va)], va);
-       if (pud_none(*pud))
-               assign_pmd(pud, alloc_pmd());
-       return pmd_offset(pud, va);
-}
-#endif
-
 /* Temporary page table we use for staging. */
 static pgd_t pgtables[PTRS_PER_PGD]
  __attribute__((aligned(HV_PAGE_TABLE_ALIGN)));
@@ -741,16 +733,15 @@ static void __init set_non_bootmem_pages_init(void)
        for_each_zone(z) {
                unsigned long start, end;
                int nid = z->zone_pgdat->node_id;
+#ifdef CONFIG_HIGHMEM
                int idx = zone_idx(z);
+#endif
 
                start = z->zone_start_pfn;
-               if (start == 0)
-                       continue;  /* bootmem */
                end = start + z->spanned_pages;
-               if (idx == ZONE_NORMAL) {
-                       BUG_ON(start != node_start_pfn[nid]);
-                       start = node_free_pfn[nid];
-               }
+               start = max(start, node_free_pfn[nid]);
+               start = max(start, max_low_pfn);
+
 #ifdef CONFIG_HIGHMEM
                if (idx == ZONE_HIGHMEM)
                        totalhigh_pages += z->spanned_pages;
@@ -779,9 +770,6 @@ static void __init set_non_bootmem_pages_init(void)
  */
 void __init paging_init(void)
 {
-#ifdef CONFIG_HIGHMEM
-       unsigned long vaddr, end;
-#endif
 #ifdef __tilegx__
        pud_t *pud;
 #endif
@@ -789,14 +777,14 @@ void __init paging_init(void)
 
        kernel_physical_mapping_init(pgd_base);
 
-#ifdef CONFIG_HIGHMEM
        /*
         * Fixed mappings, only the page table structure has to be
         * created - mappings will be set by set_fixmap():
         */
-       vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
-       end = (FIXADDR_TOP + PMD_SIZE - 1) & PMD_MASK;
-       page_table_range_init(vaddr, end, pgd_base);
+       page_table_range_init(fix_to_virt(__end_of_fixed_addresses - 1),
+                             FIXADDR_TOP, pgd_base);
+
+#ifdef CONFIG_HIGHMEM
        permanent_kmaps_init(pgd_base);
 #endif
 
index 345edfed9fcd4cb36b35f70d083e9038803bae4a..de0de0c0e8a19946bcc6c0f14c486776d8091097 100644 (file)
@@ -575,13 +575,6 @@ void __iomem *ioremap_prot(resource_size_t phys_addr, unsigned long size,
 }
 EXPORT_SYMBOL(ioremap_prot);
 
-/* Map a PCI MMIO bus address into VA space. */
-void __iomem *ioremap(resource_size_t phys_addr, unsigned long size)
-{
-       panic("ioremap for PCI MMIO is not supported");
-}
-EXPORT_SYMBOL(ioremap);
-
 /* Unmap an MMIO VA mapping. */
 void iounmap(volatile void __iomem *addr_in)
 {
index 1f25214345548584447a607676e61093301df8c8..b0c5276861ec8cc3b5713b6f83335746f812edde 100644 (file)
@@ -49,6 +49,9 @@ else
         KBUILD_AFLAGS += -m64
         KBUILD_CFLAGS += -m64
 
+       # Use -mpreferred-stack-boundary=3 if supported.
+       KBUILD_CFLAGS += $(call cc-option,-mno-sse -mpreferred-stack-boundary=3)
+
         # FIXME - should be integrated in Makefile.cpu (Makefile_32.cpu)
         cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8)
         cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona)
index 49331bedc158830ce55a9e24ba24933b94b5f7ee..70780689599acf830b322be2cad0f835ac2bac03 100644 (file)
@@ -75,23 +75,54 @@ static inline int alternatives_text_reserved(void *start, void *end)
 }
 #endif /* CONFIG_SMP */
 
+#define OLDINSTR(oldinstr)     "661:\n\t" oldinstr "\n662:\n"
+
+#define b_replacement(number)  "663"#number
+#define e_replacement(number)  "664"#number
+
+#define alt_slen "662b-661b"
+#define alt_rlen(number) e_replacement(number)"f-"b_replacement(number)"f"
+
+#define ALTINSTR_ENTRY(feature, number)                                              \
+       " .long 661b - .\n"                             /* label           */ \
+       " .long " b_replacement(number)"f - .\n"        /* new instruction */ \
+       " .word " __stringify(feature) "\n"             /* feature bit     */ \
+       " .byte " alt_slen "\n"                         /* source len      */ \
+       " .byte " alt_rlen(number) "\n"                 /* replacement len */
+
+#define DISCARD_ENTRY(number)                          /* rlen <= slen */    \
+       " .byte 0xff + (" alt_rlen(number) ") - (" alt_slen ")\n"
+
+#define ALTINSTR_REPLACEMENT(newinstr, feature, number)        /* replacement */     \
+       b_replacement(number)":\n\t" newinstr "\n" e_replacement(number) ":\n\t"
+
 /* alternative assembly primitive: */
 #define ALTERNATIVE(oldinstr, newinstr, feature)                       \
-                                                                       \
-      "661:\n\t" oldinstr "\n662:\n"                                   \
-      ".section .altinstructions,\"a\"\n"                              \
-      "         .long 661b - .\n"                      /* label           */   \
-      "         .long 663f - .\n"                      /* new instruction */   \
-      "         .word " __stringify(feature) "\n"      /* feature bit     */   \
-      "         .byte 662b-661b\n"                     /* sourcelen       */   \
-      "         .byte 664f-663f\n"                     /* replacementlen  */   \
-      ".previous\n"                                                    \
-      ".section .discard,\"aw\",@progbits\n"                           \
-      "         .byte 0xff + (664f-663f) - (662b-661b)\n" /* rlen <= slen */   \
-      ".previous\n"                                                    \
-      ".section .altinstr_replacement, \"ax\"\n"                       \
-      "663:\n\t" newinstr "\n664:\n"           /* replacement     */   \
-      ".previous"
+       OLDINSTR(oldinstr)                                              \
+       ".section .altinstructions,\"a\"\n"                             \
+       ALTINSTR_ENTRY(feature, 1)                                      \
+       ".previous\n"                                                   \
+       ".section .discard,\"aw\",@progbits\n"                          \
+       DISCARD_ENTRY(1)                                                \
+       ".previous\n"                                                   \
+       ".section .altinstr_replacement, \"ax\"\n"                      \
+       ALTINSTR_REPLACEMENT(newinstr, feature, 1)                      \
+       ".previous"
+
+#define ALTERNATIVE_2(oldinstr, newinstr1, feature1, newinstr2, feature2)\
+       OLDINSTR(oldinstr)                                              \
+       ".section .altinstructions,\"a\"\n"                             \
+       ALTINSTR_ENTRY(feature1, 1)                                     \
+       ALTINSTR_ENTRY(feature2, 2)                                     \
+       ".previous\n"                                                   \
+       ".section .discard,\"aw\",@progbits\n"                          \
+       DISCARD_ENTRY(1)                                                \
+       DISCARD_ENTRY(2)                                                \
+       ".previous\n"                                                   \
+       ".section .altinstr_replacement, \"ax\"\n"                      \
+       ALTINSTR_REPLACEMENT(newinstr1, feature1, 1)                    \
+       ALTINSTR_REPLACEMENT(newinstr2, feature2, 2)                    \
+       ".previous"
 
 /*
  * This must be included *after* the definition of ALTERNATIVE due to
@@ -139,6 +170,19 @@ static inline int alternatives_text_reserved(void *start, void *end)
        asm volatile (ALTERNATIVE("call %P[old]", "call %P[new]", feature) \
                : output : [old] "i" (oldfunc), [new] "i" (newfunc), ## input)
 
+/*
+ * Like alternative_call, but there are two features and respective functions.
+ * If CPU has feature2, function2 is used.
+ * Otherwise, if CPU has feature1, function1 is used.
+ * Otherwise, old function is used.
+ */
+#define alternative_call_2(oldfunc, newfunc1, feature1, newfunc2, feature2,   \
+                          output, input...)                                  \
+       asm volatile (ALTERNATIVE_2("call %P[old]", "call %P[new1]", feature1,\
+               "call %P[new2]", feature2)                                    \
+               : output : [old] "i" (oldfunc), [new1] "i" (newfunc1),        \
+               [new2] "i" (newfunc2), ## input)
+
 /*
  * use this macro(s) if you need more than one output parameter
  * in alternative_io
index 49ad773f4b9f5f4631e4e5bed590c8d6356e4e0f..b3341e9cd8fdee3a25e7582563564d813594b6a3 100644 (file)
@@ -26,10 +26,31 @@ struct amd_l3_cache {
        u8       subcaches[4];
 };
 
+struct threshold_block {
+       unsigned int            block;
+       unsigned int            bank;
+       unsigned int            cpu;
+       u32                     address;
+       u16                     interrupt_enable;
+       bool                    interrupt_capable;
+       u16                     threshold_limit;
+       struct kobject          kobj;
+       struct list_head        miscj;
+};
+
+struct threshold_bank {
+       struct kobject          *kobj;
+       struct threshold_block  *blocks;
+
+       /* initialized to the number of CPUs on the node sharing this bank */
+       atomic_t                cpus;
+};
+
 struct amd_northbridge {
        struct pci_dev *misc;
        struct pci_dev *link;
        struct amd_l3_cache l3_cache;
+       struct threshold_bank *bank4;
 };
 
 struct amd_northbridge_info {
index eaff4790ed96c207d2ac51e0c89901707b5285ec..88093c1d44fd4c99064315eff9f169a8ef33235a 100644 (file)
@@ -306,7 +306,8 @@ struct apic {
        unsigned long (*check_apicid_used)(physid_mask_t *map, int apicid);
        unsigned long (*check_apicid_present)(int apicid);
 
-       void (*vector_allocation_domain)(int cpu, struct cpumask *retmask);
+       void (*vector_allocation_domain)(int cpu, struct cpumask *retmask,
+                                        const struct cpumask *mask);
        void (*init_apic_ldr)(void);
 
        void (*ioapic_phys_id_map)(physid_mask_t *phys_map, physid_mask_t *retmap);
@@ -331,9 +332,9 @@ struct apic {
        unsigned long (*set_apic_id)(unsigned int id);
        unsigned long apic_id_mask;
 
-       unsigned int (*cpu_mask_to_apicid)(const struct cpumask *cpumask);
-       unsigned int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask,
-                                              const struct cpumask *andmask);
+       int (*cpu_mask_to_apicid_and)(const struct cpumask *cpumask,
+                                     const struct cpumask *andmask,
+                                     unsigned int *apicid);
 
        /* ipi */
        void (*send_IPI_mask)(const struct cpumask *mask, int vector);
@@ -537,6 +538,11 @@ static inline const struct cpumask *default_target_cpus(void)
 #endif
 }
 
+static inline const struct cpumask *online_target_cpus(void)
+{
+       return cpu_online_mask;
+}
+
 DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid);
 
 
@@ -586,21 +592,50 @@ static inline int default_phys_pkg_id(int cpuid_apic, int index_msb)
 
 #endif
 
-static inline unsigned int
-default_cpu_mask_to_apicid(const struct cpumask *cpumask)
+static inline int
+flat_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+                           const struct cpumask *andmask,
+                           unsigned int *apicid)
 {
-       return cpumask_bits(cpumask)[0] & APIC_ALL_CPUS;
+       unsigned long cpu_mask = cpumask_bits(cpumask)[0] &
+                                cpumask_bits(andmask)[0] &
+                                cpumask_bits(cpu_online_mask)[0] &
+                                APIC_ALL_CPUS;
+
+       if (likely(cpu_mask)) {
+               *apicid = (unsigned int)cpu_mask;
+               return 0;
+       } else {
+               return -EINVAL;
+       }
 }
 
-static inline unsigned int
+extern int
 default_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                              const struct cpumask *andmask)
+                              const struct cpumask *andmask,
+                              unsigned int *apicid);
+
+static inline void
+flat_vector_allocation_domain(int cpu, struct cpumask *retmask,
+                             const struct cpumask *mask)
 {
-       unsigned long mask1 = cpumask_bits(cpumask)[0];
-       unsigned long mask2 = cpumask_bits(andmask)[0];
-       unsigned long mask3 = cpumask_bits(cpu_online_mask)[0];
+       /* Careful. Some cpus do not strictly honor the set of cpus
+        * specified in the interrupt destination when using lowest
+        * priority interrupt delivery mode.
+        *
+        * In particular there was a hyperthreading cpu observed to
+        * deliver interrupts to the wrong hyperthread when only one
+        * hyperthread was specified in the interrupt desitination.
+        */
+       cpumask_clear(retmask);
+       cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
+}
 
-       return (unsigned int)(mask1 & mask2 & mask3);
+static inline void
+default_vector_allocation_domain(int cpu, struct cpumask *retmask,
+                                const struct cpumask *mask)
+{
+       cpumask_copy(retmask, cpumask_of(cpu));
 }
 
 static inline unsigned long default_check_apicid_used(physid_mask_t *map, int apicid)
index cc70c1c78ca47545bb7b927f878d3cb02275f142..75ce3f47d20412b5ab4e445e84978dc29ff7fc83 100644 (file)
@@ -4,9 +4,7 @@
 enum reboot_type {
        BOOT_TRIPLE = 't',
        BOOT_KBD = 'k',
-#ifdef CONFIG_X86_32
        BOOT_BIOS = 'b',
-#endif
        BOOT_ACPI = 'a',
        BOOT_EFI = 'e',
        BOOT_CF9 = 'p',
index dbe82a5c5eacde33f9cdf3791dfe159228f151b6..d3d74698dce9c09151a6421176224885454901df 100644 (file)
@@ -99,7 +99,7 @@ static irqreturn_t floppy_hardint(int irq, void *dev_id)
                virtual_dma_residue += virtual_dma_count;
                virtual_dma_count = 0;
 #ifdef TRACE_FLPY_INT
-               printk("count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n",
+               printk(KERN_DEBUG "count=%x, residue=%x calls=%d bytes=%d dma_wait=%d\n",
                       virtual_dma_count, virtual_dma_residue, calls, bytes,
                       dma_wait);
                calls = 0;
index db7c1f2709a270a03429ee1c9089209942647ff5..2da88c0cda1446f9e18a5ded4a64013e2a60dcbf 100644 (file)
@@ -313,8 +313,8 @@ struct kvm_pmu {
        u64 counter_bitmask[2];
        u64 global_ctrl_mask;
        u8 version;
-       struct kvm_pmc gp_counters[X86_PMC_MAX_GENERIC];
-       struct kvm_pmc fixed_counters[X86_PMC_MAX_FIXED];
+       struct kvm_pmc gp_counters[INTEL_PMC_MAX_GENERIC];
+       struct kvm_pmc fixed_counters[INTEL_PMC_MAX_FIXED];
        struct irq_work irq_work;
        u64 reprogram_pmi;
 };
index 084ef95274cd78ceb51b1ea7a208a7a5e486199a..813ed103f45edc0ac13042e8c18a922b909a8710 100644 (file)
@@ -115,8 +115,8 @@ notrace static inline int native_write_msr_safe(unsigned int msr,
 
 extern unsigned long long native_read_tsc(void);
 
-extern int native_rdmsr_safe_regs(u32 regs[8]);
-extern int native_wrmsr_safe_regs(u32 regs[8]);
+extern int rdmsr_safe_regs(u32 regs[8]);
+extern int wrmsr_safe_regs(u32 regs[8]);
 
 static __always_inline unsigned long long __native_read_tsc(void)
 {
@@ -187,43 +187,6 @@ static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
        return err;
 }
 
-static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
-{
-       u32 gprs[8] = { 0 };
-       int err;
-
-       gprs[1] = msr;
-       gprs[7] = 0x9c5a203a;
-
-       err = native_rdmsr_safe_regs(gprs);
-
-       *p = gprs[0] | ((u64)gprs[2] << 32);
-
-       return err;
-}
-
-static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
-{
-       u32 gprs[8] = { 0 };
-
-       gprs[0] = (u32)val;
-       gprs[1] = msr;
-       gprs[2] = val >> 32;
-       gprs[7] = 0x9c5a203a;
-
-       return native_wrmsr_safe_regs(gprs);
-}
-
-static inline int rdmsr_safe_regs(u32 regs[8])
-{
-       return native_rdmsr_safe_regs(regs);
-}
-
-static inline int wrmsr_safe_regs(u32 regs[8])
-{
-       return native_wrmsr_safe_regs(regs);
-}
-
 #define rdtscl(low)                                            \
        ((low) = (u32)__native_read_tsc())
 
@@ -237,6 +200,8 @@ do {                                                        \
        (high) = (u32)(_l >> 32);                       \
 } while (0)
 
+#define rdpmcl(counter, val) ((val) = native_read_pmc(counter))
+
 #define rdtscp(low, high, aux)                                 \
 do {                                                            \
        unsigned long long _val = native_read_tscp(&(aux));     \
@@ -248,8 +213,7 @@ do {                                                            \
 
 #endif /* !CONFIG_PARAVIRT */
 
-
-#define checking_wrmsrl(msr, val) wrmsr_safe((msr), (u32)(val),                \
+#define wrmsrl_safe(msr, val) wrmsr_safe((msr), (u32)(val),            \
                                             (u32)((val) >> 32))
 
 #define write_tsc(val1, val2) wrmsr(MSR_IA32_TSC, (val1), (val2))
index dc580c42851c223a1f21142bbb3a0b8983e18975..c0fa356e90de24ea60ba8a0ac90c39e6bb05d73b 100644 (file)
@@ -44,28 +44,14 @@ struct nmiaction {
        const char              *name;
 };
 
-#define register_nmi_handler(t, fn, fg, n)             \
+#define register_nmi_handler(t, fn, fg, n, init...)    \
 ({                                                     \
-       static struct nmiaction fn##_na = {             \
+       static struct nmiaction init fn##_na = {        \
                .handler = (fn),                        \
                .name = (n),                            \
                .flags = (fg),                          \
        };                                              \
-       __register_nmi_handler((t), &fn##_na);  \
-})
-
-/*
- * For special handlers that register/unregister in the
- * init section only.  This should be considered rare.
- */
-#define register_nmi_handler_initonly(t, fn, fg, n)            \
-({                                                     \
-       static struct nmiaction fn##_na __initdata = {          \
-               .handler = (fn),                        \
-               .name = (n),                            \
-               .flags = (fg),                          \
-       };                                              \
-       __register_nmi_handler((t), &fn##_na);  \
+       __register_nmi_handler((t), &fn##_na);          \
 })
 
 int __register_nmi_handler(unsigned int, struct nmiaction *);
index 6cbbabf52707f9d492a3e3d6687c37b24369cdfb..0b47ddb6f00b300366253a343c4a78424a8fc280 100644 (file)
@@ -128,21 +128,11 @@ static inline u64 paravirt_read_msr(unsigned msr, int *err)
        return PVOP_CALL2(u64, pv_cpu_ops.read_msr, msr, err);
 }
 
-static inline int paravirt_rdmsr_regs(u32 *regs)
-{
-       return PVOP_CALL1(int, pv_cpu_ops.rdmsr_regs, regs);
-}
-
 static inline int paravirt_write_msr(unsigned msr, unsigned low, unsigned high)
 {
        return PVOP_CALL3(int, pv_cpu_ops.write_msr, msr, low, high);
 }
 
-static inline int paravirt_wrmsr_regs(u32 *regs)
-{
-       return PVOP_CALL1(int, pv_cpu_ops.wrmsr_regs, regs);
-}
-
 /* These should all do BUG_ON(_err), but our headers are too tangled. */
 #define rdmsr(msr, val1, val2)                 \
 do {                                           \
@@ -176,9 +166,6 @@ do {                                                \
        _err;                                   \
 })
 
-#define rdmsr_safe_regs(regs)  paravirt_rdmsr_regs(regs)
-#define wrmsr_safe_regs(regs)  paravirt_wrmsr_regs(regs)
-
 static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
 {
        int err;
@@ -186,32 +173,6 @@ static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
        *p = paravirt_read_msr(msr, &err);
        return err;
 }
-static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
-{
-       u32 gprs[8] = { 0 };
-       int err;
-
-       gprs[1] = msr;
-       gprs[7] = 0x9c5a203a;
-
-       err = paravirt_rdmsr_regs(gprs);
-
-       *p = gprs[0] | ((u64)gprs[2] << 32);
-
-       return err;
-}
-
-static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
-{
-       u32 gprs[8] = { 0 };
-
-       gprs[0] = (u32)val;
-       gprs[1] = msr;
-       gprs[2] = val >> 32;
-       gprs[7] = 0x9c5a203a;
-
-       return paravirt_wrmsr_regs(gprs);
-}
 
 static inline u64 paravirt_read_tsc(void)
 {
@@ -252,6 +213,8 @@ do {                                                \
        high = _l >> 32;                        \
 } while (0)
 
+#define rdpmcl(counter, val) ((val) = paravirt_read_pmc(counter))
+
 static inline unsigned long long paravirt_rdtscp(unsigned int *aux)
 {
        return PVOP_CALL1(u64, pv_cpu_ops.read_tscp, aux);
index 8e8b9a4987ee0225d0a7e38504436f53f4c81d30..8613cbb7ba41e63d8626e2bae1356793ca279a1d 100644 (file)
@@ -153,9 +153,7 @@ struct pv_cpu_ops {
        /* MSR, PMC and TSR operations.
           err = 0/-EFAULT.  wrmsr returns 0/-EFAULT. */
        u64 (*read_msr)(unsigned int msr, int *err);
-       int (*rdmsr_regs)(u32 *regs);
        int (*write_msr)(unsigned int msr, unsigned low, unsigned high);
-       int (*wrmsr_regs)(u32 *regs);
 
        u64 (*read_tsc)(void);
        u64 (*read_pmc)(int counter);
index b3a531746026105ba70b4d29293696bc02e32779..5ad24a89b19b323eefbf775a92b7287c1cc95c65 100644 (file)
@@ -7,9 +7,13 @@
 #undef DEBUG
 
 #ifdef DEBUG
-#define DBG(x...) printk(x)
+#define DBG(fmt, ...) printk(fmt, ##__VA_ARGS__)
 #else
-#define DBG(x...)
+#define DBG(fmt, ...)                          \
+do {                                           \
+       if (0)                                  \
+               printk(fmt, ##__VA_ARGS__);     \
+} while (0)
 #endif
 
 #define PCI_PROBE_BIOS         0x0001
index 588f52ea810e78d1440013fd8b8043eff2353fb9..c78f14a0df0029a35cbedcb22594fafa1c9110be 100644 (file)
@@ -5,11 +5,10 @@
  * Performance event hw details:
  */
 
-#define X86_PMC_MAX_GENERIC                                   32
-#define X86_PMC_MAX_FIXED                                      3
+#define INTEL_PMC_MAX_GENERIC                                 32
+#define INTEL_PMC_MAX_FIXED                                    3
+#define INTEL_PMC_IDX_FIXED                                   32
 
-#define X86_PMC_IDX_GENERIC                                    0
-#define X86_PMC_IDX_FIXED                                     32
 #define X86_PMC_IDX_MAX                                               64
 
 #define MSR_ARCH_PERFMON_PERFCTR0                            0xc1
@@ -48,8 +47,7 @@
        (X86_RAW_EVENT_MASK          |  \
         AMD64_EVENTSEL_EVENT)
 #define AMD64_NUM_COUNTERS                             4
-#define AMD64_NUM_COUNTERS_F15H                                6
-#define AMD64_NUM_COUNTERS_MAX                         AMD64_NUM_COUNTERS_F15H
+#define AMD64_NUM_COUNTERS_CORE                                6
 
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL          0x3c
 #define ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK                (0x00 << 8)
@@ -121,16 +119,16 @@ struct x86_pmu_capability {
 
 /* Instr_Retired.Any: */
 #define MSR_ARCH_PERFMON_FIXED_CTR0    0x309
-#define X86_PMC_IDX_FIXED_INSTRUCTIONS (X86_PMC_IDX_FIXED + 0)
+#define INTEL_PMC_IDX_FIXED_INSTRUCTIONS       (INTEL_PMC_IDX_FIXED + 0)
 
 /* CPU_CLK_Unhalted.Core: */
 #define MSR_ARCH_PERFMON_FIXED_CTR1    0x30a
-#define X86_PMC_IDX_FIXED_CPU_CYCLES   (X86_PMC_IDX_FIXED + 1)
+#define INTEL_PMC_IDX_FIXED_CPU_CYCLES (INTEL_PMC_IDX_FIXED + 1)
 
 /* CPU_CLK_Unhalted.Ref: */
 #define MSR_ARCH_PERFMON_FIXED_CTR2    0x30b
-#define X86_PMC_IDX_FIXED_REF_CYCLES   (X86_PMC_IDX_FIXED + 2)
-#define X86_PMC_MSK_FIXED_REF_CYCLES   (1ULL << X86_PMC_IDX_FIXED_REF_CYCLES)
+#define INTEL_PMC_IDX_FIXED_REF_CYCLES (INTEL_PMC_IDX_FIXED + 2)
+#define INTEL_PMC_MSK_FIXED_REF_CYCLES (1ULL << INTEL_PMC_IDX_FIXED_REF_CYCLES)
 
 /*
  * We model BTS tracing as another fixed-mode PMC.
@@ -139,7 +137,7 @@ struct x86_pmu_capability {
  * values are used by actual fixed events and higher values are used
  * to indicate other overflow conditions in the PERF_GLOBAL_STATUS msr.
  */
-#define X86_PMC_IDX_FIXED_BTS                          (X86_PMC_IDX_FIXED + 16)
+#define INTEL_PMC_IDX_FIXED_BTS                                (INTEL_PMC_IDX_FIXED + 16)
 
 /*
  * IBS cpuid feature detection
@@ -234,6 +232,7 @@ struct perf_guest_switch_msr {
 
 extern struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr);
 extern void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap);
+extern void perf_check_microcode(void);
 #else
 static inline perf_guest_switch_msr *perf_guest_get_msrs(int *nr)
 {
@@ -247,6 +246,7 @@ static inline void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)
 }
 
 static inline void perf_events_lapic_init(void)        { }
+static inline void perf_check_microcode(void) { }
 #endif
 
 #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_AMD)
index 98391db840c6d05113768c42be494f4205966741..f2b489cf1602349092d26d6ea68109cca3589c4d 100644 (file)
@@ -2,9 +2,9 @@
 #define _ASM_X86_PGTABLE_2LEVEL_H
 
 #define pte_ERROR(e) \
-       printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low)
+       pr_err("%s:%d: bad pte %08lx\n", __FILE__, __LINE__, (e).pte_low)
 #define pgd_ERROR(e) \
-       printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+       pr_err("%s:%d: bad pgd %08lx\n", __FILE__, __LINE__, pgd_val(e))
 
 /*
  * Certain architectures need to do special things when PTEs
index cb00ccc7d571f2b5245f935bde849c5c5e289635..4cc9f2b7cdc35a854f185b2ab91d49a9fcd1be4f 100644 (file)
@@ -9,13 +9,13 @@
  */
 
 #define pte_ERROR(e)                                                   \
-       printk("%s:%d: bad pte %p(%08lx%08lx).\n",                      \
+       pr_err("%s:%d: bad pte %p(%08lx%08lx)\n",                       \
               __FILE__, __LINE__, &(e), (e).pte_high, (e).pte_low)
 #define pmd_ERROR(e)                                                   \
-       printk("%s:%d: bad pmd %p(%016Lx).\n",                          \
+       pr_err("%s:%d: bad pmd %p(%016Lx)\n",                           \
               __FILE__, __LINE__, &(e), pmd_val(e))
 #define pgd_ERROR(e)                                                   \
-       printk("%s:%d: bad pgd %p(%016Lx).\n",                          \
+       pr_err("%s:%d: bad pgd %p(%016Lx)\n",                           \
               __FILE__, __LINE__, &(e), pgd_val(e))
 
 /* Rules for using set_pte: the pte being assigned *must* be
index 975f709e09ae5cf9e6c3fcf7440cbc4496e036a1..8251be02301ef2be43f0e73d638c0f264aedb936 100644 (file)
@@ -26,16 +26,16 @@ extern pgd_t init_level4_pgt[];
 extern void paging_init(void);
 
 #define pte_ERROR(e)                                   \
-       printk("%s:%d: bad pte %p(%016lx).\n",          \
+       pr_err("%s:%d: bad pte %p(%016lx)\n",           \
               __FILE__, __LINE__, &(e), pte_val(e))
 #define pmd_ERROR(e)                                   \
-       printk("%s:%d: bad pmd %p(%016lx).\n",          \
+       pr_err("%s:%d: bad pmd %p(%016lx)\n",           \
               __FILE__, __LINE__, &(e), pmd_val(e))
 #define pud_ERROR(e)                                   \
-       printk("%s:%d: bad pud %p(%016lx).\n",          \
+       pr_err("%s:%d: bad pud %p(%016lx)\n",           \
               __FILE__, __LINE__, &(e), pud_val(e))
 #define pgd_ERROR(e)                                   \
-       printk("%s:%d: bad pgd %p(%016lx).\n",          \
+       pr_err("%s:%d: bad pgd %p(%016lx)\n",           \
               __FILE__, __LINE__, &(e), pgd_val(e))
 
 struct mm_struct;
index fce3f4ae5bd6d93fc6b2b2f0599600b4914395f8..fe1ec5bcd84644b4c4c0b68660be85dae0bd39ad 100644 (file)
@@ -21,8 +21,9 @@ struct real_mode_header {
        u32     wakeup_header;
 #endif
        /* APM/BIOS reboot */
-#ifdef CONFIG_X86_32
        u32     machine_real_restart_asm;
+#ifdef CONFIG_X86_64
+       u32     machine_real_restart_seg;
 #endif
 };
 
index 92f297069e87c6c6befa12c7ada4fd21b7436365..a82c4f1b4d83e96daf1d99126a290c45ffa38a6c 100644 (file)
@@ -18,8 +18,8 @@ extern struct machine_ops machine_ops;
 
 void native_machine_crash_shutdown(struct pt_regs *regs);
 void native_machine_shutdown(void);
-void machine_real_restart(unsigned int type);
-/* These must match dispatch_table in reboot_32.S */
+void __noreturn machine_real_restart(unsigned int type);
+/* These must match dispatch in arch/x86/realmore/rm/reboot.S */
 #define MRR_BIOS       0
 #define MRR_APM                1
 
index f48394513c377b3d540c6c0ec7da258645d3b06e..2ffa95dc2333bcc5a36efb898fd7ad12e95f5842 100644 (file)
@@ -169,11 +169,6 @@ void x86_idle_thread_init(unsigned int cpu, struct task_struct *idle);
 void smp_store_cpu_info(int id);
 #define cpu_physical_id(cpu)   per_cpu(x86_cpu_to_apicid, cpu)
 
-/* We don't mark CPUs online until __cpu_up(), so we need another measure */
-static inline int num_booting_cpus(void)
-{
-       return cpumask_weight(cpu_callout_mask);
-}
 #else /* !CONFIG_SMP */
 #define wbinvd_on_cpu(cpu)     wbinvd()
 static inline int wbinvd_on_all_cpus(void)
index 8e796fbbf9c66e439418dd84580e855a173b4a12..d8def8b3dba0b46a9d52b06d65262560a8c3cca2 100644 (file)
@@ -17,6 +17,8 @@
 
 /* Handles exceptions in both to and from, but doesn't do access_ok */
 __must_check unsigned long
+copy_user_enhanced_fast_string(void *to, const void *from, unsigned len);
+__must_check unsigned long
 copy_user_generic_string(void *to, const void *from, unsigned len);
 __must_check unsigned long
 copy_user_generic_unrolled(void *to, const void *from, unsigned len);
@@ -26,9 +28,16 @@ copy_user_generic(void *to, const void *from, unsigned len)
 {
        unsigned ret;
 
-       alternative_call(copy_user_generic_unrolled,
+       /*
+        * If CPU has ERMS feature, use copy_user_enhanced_fast_string.
+        * Otherwise, if CPU has rep_good feature, use copy_user_generic_string.
+        * Otherwise, use copy_user_generic_unrolled.
+        */
+       alternative_call_2(copy_user_generic_unrolled,
                         copy_user_generic_string,
                         X86_FEATURE_REP_GOOD,
+                        copy_user_enhanced_fast_string,
+                        X86_FEATURE_ERMS,
                         ASM_OUTPUT2("=a" (ret), "=D" (to), "=S" (from),
                                     "=d" (len)),
                         "1" (to), "2" (from), "3" (len)
index 1e9bed14f7aecd9bfe6bf7ad2df2f8772cd5d5f2..f3971bbcd1de3ee52ddda97b8bd02fbcc815aef1 100644 (file)
@@ -48,7 +48,7 @@ struct arch_uprobe_task {
 #endif
 };
 
-extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm);
+extern int  arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr);
 extern int  arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs);
 extern int  arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs);
 extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk);
index 6149b476d9dffe06bcd1e3e3136bc335fd3dbf98..a06983cdc125d842c58ca13dfc6817282413ee54 100644 (file)
 #define IPI_RESET_LIMIT                        1
 /* after this # consecutive successes, bump up the throttle if it was lowered */
 #define COMPLETE_THRESHOLD             5
+/* after this # of giveups (fall back to kernel IPI's) disable the use of
+   the BAU for a period of time */
+#define GIVEUP_LIMIT                   100
 
 #define UV_LB_SUBNODEID                        0x10
 
 #define FLUSH_RETRY_TIMEOUT            2
 #define FLUSH_GIVEUP                   3
 #define FLUSH_COMPLETE                 4
-#define FLUSH_RETRY_BUSYBUG            5
 
 /*
  * tuning the action when the numalink network is extremely delayed
                                                   microseconds */
 #define CONGESTED_REPS                 10      /* long delays averaged over
                                                   this many broadcasts */
-#define CONGESTED_PERIOD               30      /* time for the bau to be
+#define DISABLED_PERIOD                        10      /* time for the bau to be
                                                   disabled, in seconds */
 /* see msg_type: */
 #define MSG_NOOP                       0
@@ -520,6 +522,12 @@ struct ptc_stats {
        unsigned long   s_uv2_wars;             /* uv2 workaround, perm. busy */
        unsigned long   s_uv2_wars_hw;          /* uv2 workaround, hiwater */
        unsigned long   s_uv2_war_waits;        /* uv2 workaround, long waits */
+       unsigned long   s_overipilimit;         /* over the ipi reset limit */
+       unsigned long   s_giveuplimit;          /* disables, over giveup limit*/
+       unsigned long   s_enters;               /* entries to the driver */
+       unsigned long   s_ipifordisabled;       /* fall back to IPI; disabled */
+       unsigned long   s_plugged;              /* plugged by h/w bug*/
+       unsigned long   s_congested;            /* giveup on long wait */
        /* destination statistics */
        unsigned long   d_alltlb;               /* times all tlb's on this
                                                   cpu were flushed */
@@ -586,8 +594,8 @@ struct bau_control {
        int                     timeout_tries;
        int                     ipi_attempts;
        int                     conseccompletes;
-       int                     baudisabled;
-       int                     set_bau_off;
+       short                   nobau;
+       short                   baudisabled;
        short                   cpu;
        short                   osnode;
        short                   uvhub_cpu;
@@ -596,14 +604,16 @@ struct bau_control {
        short                   cpus_in_socket;
        short                   cpus_in_uvhub;
        short                   partition_base_pnode;
-       short                   using_desc; /* an index, like uvhub_cpu */
-       unsigned int            inuse_map;
+       short                   busy;       /* all were busy (war) */
        unsigned short          message_number;
        unsigned short          uvhub_quiesce;
        short                   socket_acknowledge_count[DEST_Q_SIZE];
        cycles_t                send_message;
+       cycles_t                period_end;
+       cycles_t                period_time;
        spinlock_t              uvhub_lock;
        spinlock_t              queue_lock;
+       spinlock_t              disable_lock;
        /* tunables */
        int                     max_concurr;
        int                     max_concurr_const;
@@ -614,9 +624,9 @@ struct bau_control {
        int                     complete_threshold;
        int                     cong_response_us;
        int                     cong_reps;
-       int                     cong_period;
-       unsigned long           clocks_per_100_usec;
-       cycles_t                period_time;
+       cycles_t                disabled_period;
+       int                     period_giveups;
+       int                     giveup_limit;
        long                    period_requests;
        struct hub_and_pnode    *thp;
 };
index 92e54abf89e0bc31aae93b298ae5d42b7994fef7..f90f0a587c66c34f235ea741596c737789f92cf0 100644 (file)
@@ -9,15 +9,6 @@
 #include <asm/ipi.h>
 #include <linux/cpumask.h>
 
-/*
- * Need to use more than cpu 0, because we need more vectors
- * when MSI-X are used.
- */
-static const struct cpumask *x2apic_target_cpus(void)
-{
-       return cpu_online_mask;
-}
-
 static int x2apic_apic_id_valid(int apicid)
 {
        return 1;
@@ -28,15 +19,6 @@ static int x2apic_apic_id_registered(void)
        return 1;
 }
 
-/*
- * For now each logical cpu is in its own vector allocation domain.
- */
-static void x2apic_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       cpumask_clear(retmask);
-       cpumask_set_cpu(cpu, retmask);
-}
-
 static void
 __x2apic_send_IPI_dest(unsigned int apicid, int vector, unsigned int dest)
 {
index c090af10ac7dcc7a6914c915562cc378cd188605..38155f667144ce365f83cd13572d98f78bff5446 100644 (file)
@@ -156,7 +156,6 @@ struct x86_cpuinit_ops {
 /**
  * struct x86_platform_ops - platform specific runtime functions
  * @calibrate_tsc:             calibrate TSC
- * @wallclock_init:            init the wallclock device
  * @get_wallclock:             get time from HW clock like RTC etc.
  * @set_wallclock:             set time back to HW clock
  * @is_untracked_pat_range     exclude from PAT logic
@@ -164,10 +163,10 @@ struct x86_cpuinit_ops {
  * @i8042_detect               pre-detect if i8042 controller exists
  * @save_sched_clock_state:    save state for sched_clock() on suspend
  * @restore_sched_clock_state: restore state for sched_clock() on resume
+ * @apic_post_init:            adjust apic if neeeded
  */
 struct x86_platform_ops {
        unsigned long (*calibrate_tsc)(void);
-       void (*wallclock_init)(void);
        unsigned long (*get_wallclock)(void);
        int (*set_wallclock)(unsigned long nowtime);
        void (*iommu_shutdown)(void);
@@ -177,6 +176,7 @@ struct x86_platform_ops {
        int (*i8042_detect)(void);
        void (*save_sched_clock_state)(void);
        void (*restore_sched_clock_state)(void);
+       void (*apic_post_init)(void);
 };
 
 struct pci_dev;
index 1f84794f0759327c387d602cddccb3d479188f92..931280ff8299471df09b60033cdb06b46a361677 100644 (file)
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt) "SMP alternatives: " fmt
+
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/mutex.h>
@@ -63,8 +65,11 @@ static int __init setup_noreplace_paravirt(char *str)
 __setup("noreplace-paravirt", setup_noreplace_paravirt);
 #endif
 
-#define DPRINTK(fmt, args...) if (debug_alternative) \
-       printk(KERN_DEBUG fmt, args)
+#define DPRINTK(fmt, ...)                              \
+do {                                                   \
+       if (debug_alternative)                          \
+               printk(KERN_DEBUG fmt, ##__VA_ARGS__);  \
+} while (0)
 
 /*
  * Each GENERIC_NOPX is of X bytes, and defined as an array of bytes
@@ -428,7 +433,7 @@ void alternatives_smp_switch(int smp)
         * If this still occurs then you should see a hang
         * or crash shortly after this line:
         */
-       printk("lockdep: fixing up alternatives.\n");
+       pr_info("lockdep: fixing up alternatives\n");
 #endif
 
        if (noreplace_smp || smp_alt_once || skip_smp_alternatives)
@@ -444,14 +449,14 @@ void alternatives_smp_switch(int smp)
        if (smp == smp_mode) {
                /* nothing */
        } else if (smp) {
-               printk(KERN_INFO "SMP alternatives: switching to SMP code\n");
+               pr_info("switching to SMP code\n");
                clear_cpu_cap(&boot_cpu_data, X86_FEATURE_UP);
                clear_cpu_cap(&cpu_data(0), X86_FEATURE_UP);
                list_for_each_entry(mod, &smp_alt_modules, next)
                        alternatives_smp_lock(mod->locks, mod->locks_end,
                                              mod->text, mod->text_end);
        } else {
-               printk(KERN_INFO "SMP alternatives: switching to UP code\n");
+               pr_info("switching to UP code\n");
                set_cpu_cap(&boot_cpu_data, X86_FEATURE_UP);
                set_cpu_cap(&cpu_data(0), X86_FEATURE_UP);
                list_for_each_entry(mod, &smp_alt_modules, next)
@@ -546,7 +551,7 @@ void __init alternative_instructions(void)
 #ifdef CONFIG_SMP
        if (smp_alt_once) {
                if (1 == num_possible_cpus()) {
-                       printk(KERN_INFO "SMP alternatives: switching to UP code\n");
+                       pr_info("switching to UP code\n");
                        set_cpu_cap(&boot_cpu_data, X86_FEATURE_UP);
                        set_cpu_cap(&cpu_data(0), X86_FEATURE_UP);
 
@@ -664,7 +669,7 @@ static int __kprobes stop_machine_text_poke(void *data)
        struct text_poke_param *p;
        int i;
 
-       if (atomic_dec_and_test(&stop_machine_first)) {
+       if (atomic_xchg(&stop_machine_first, 0)) {
                for (i = 0; i < tpp->nparams; i++) {
                        p = &tpp->params[i];
                        text_poke(p->addr, p->opcode, p->len);
index be16854591cc26a2b0349b6f7d9e0cc446340e32..aadf3359e2a77660b5ee68ac549b5a82fcad8695 100644 (file)
@@ -2,6 +2,9 @@
  * Shared support code for AMD K8 northbridges and derivates.
  * Copyright 2006 Andi Kleen, SUSE Labs. Subject to GPLv2.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/types.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -16,6 +19,7 @@ const struct pci_device_id amd_nb_misc_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
        {}
 };
 EXPORT_SYMBOL(amd_nb_misc_ids);
@@ -258,7 +262,7 @@ void amd_flush_garts(void)
        }
        spin_unlock_irqrestore(&gart_lock, flags);
        if (!flushed)
-               printk("nothing to flush?\n");
+               pr_notice("nothing to flush?\n");
 }
 EXPORT_SYMBOL_GPL(amd_flush_garts);
 
@@ -269,11 +273,10 @@ static __init int init_amd_nbs(void)
        err = amd_cache_northbridges();
 
        if (err < 0)
-               printk(KERN_NOTICE "AMD NB: Cannot enumerate AMD northbridges.\n");
+               pr_notice("Cannot enumerate AMD northbridges\n");
 
        if (amd_cache_gart() < 0)
-               printk(KERN_NOTICE "AMD NB: Cannot initialize GART flush words, "
-                      "GART support disabled.\n");
+               pr_notice("Cannot initialize GART flush words, GART support disabled\n");
 
        return err;
 }
index 39a222e094af0b1ac3c0904a9c977be9b2a95795..c421512ca5eb33ceb79de6ce3b4284a96356ede4 100644 (file)
@@ -2123,6 +2123,25 @@ void default_init_apic_ldr(void)
        apic_write(APIC_LDR, val);
 }
 
+int default_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+                                  const struct cpumask *andmask,
+                                  unsigned int *apicid)
+{
+       unsigned int cpu;
+
+       for_each_cpu_and(cpu, cpumask, andmask) {
+               if (cpumask_test_cpu(cpu, cpu_online_mask))
+                       break;
+       }
+
+       if (likely(cpu < nr_cpu_ids)) {
+               *apicid = per_cpu(x86_cpu_to_apicid, cpu);
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
 /*
  * Power management
  */
index 0e881c46e8c856ed41f6fc095e0381853b7e781b..00c77cf78e9e1839973923076053fdf92d75a54e 100644 (file)
@@ -36,25 +36,6 @@ static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
        return 1;
 }
 
-static const struct cpumask *flat_target_cpus(void)
-{
-       return cpu_online_mask;
-}
-
-static void flat_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       /* Careful. Some cpus do not strictly honor the set of cpus
-        * specified in the interrupt destination when using lowest
-        * priority interrupt delivery mode.
-        *
-        * In particular there was a hyperthreading cpu observed to
-        * deliver interrupts to the wrong hyperthread when only one
-        * hyperthread was specified in the interrupt desitination.
-        */
-       cpumask_clear(retmask);
-       cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
-}
-
 /*
  * Set up the logical destination ID.
  *
@@ -92,7 +73,7 @@ static void flat_send_IPI_mask(const struct cpumask *cpumask, int vector)
 }
 
 static void
- flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
+flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
 {
        unsigned long mask = cpumask_bits(cpumask)[0];
        int cpu = smp_processor_id();
@@ -186,7 +167,7 @@ static struct apic apic_flat =  {
        .irq_delivery_mode              = dest_LowestPrio,
        .irq_dest_mode                  = 1, /* logical */
 
-       .target_cpus                    = flat_target_cpus,
+       .target_cpus                    = online_target_cpus,
        .disable_esr                    = 0,
        .dest_logical                   = APIC_DEST_LOGICAL,
        .check_apicid_used              = NULL,
@@ -210,8 +191,7 @@ static struct apic apic_flat =  {
        .set_apic_id                    = set_apic_id,
        .apic_id_mask                   = 0xFFu << 24,
 
-       .cpu_mask_to_apicid             = default_cpu_mask_to_apicid,
-       .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
+       .cpu_mask_to_apicid_and         = flat_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = flat_send_IPI_mask,
        .send_IPI_mask_allbutself       = flat_send_IPI_mask_allbutself,
@@ -262,17 +242,6 @@ static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
        return 0;
 }
 
-static const struct cpumask *physflat_target_cpus(void)
-{
-       return cpu_online_mask;
-}
-
-static void physflat_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       cpumask_clear(retmask);
-       cpumask_set_cpu(cpu, retmask);
-}
-
 static void physflat_send_IPI_mask(const struct cpumask *cpumask, int vector)
 {
        default_send_IPI_mask_sequence_phys(cpumask, vector);
@@ -294,38 +263,6 @@ static void physflat_send_IPI_all(int vector)
        physflat_send_IPI_mask(cpu_online_mask, vector);
 }
 
-static unsigned int physflat_cpu_mask_to_apicid(const struct cpumask *cpumask)
-{
-       int cpu;
-
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       cpu = cpumask_first(cpumask);
-       if ((unsigned)cpu < nr_cpu_ids)
-               return per_cpu(x86_cpu_to_apicid, cpu);
-       else
-               return BAD_APICID;
-}
-
-static unsigned int
-physflat_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                               const struct cpumask *andmask)
-{
-       int cpu;
-
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       for_each_cpu_and(cpu, cpumask, andmask) {
-               if (cpumask_test_cpu(cpu, cpu_online_mask))
-                       break;
-       }
-       return per_cpu(x86_cpu_to_apicid, cpu);
-}
-
 static int physflat_probe(void)
 {
        if (apic == &apic_physflat || num_possible_cpus() > 8)
@@ -345,13 +282,13 @@ static struct apic apic_physflat =  {
        .irq_delivery_mode              = dest_Fixed,
        .irq_dest_mode                  = 0, /* physical */
 
-       .target_cpus                    = physflat_target_cpus,
+       .target_cpus                    = online_target_cpus,
        .disable_esr                    = 0,
        .dest_logical                   = 0,
        .check_apicid_used              = NULL,
        .check_apicid_present           = NULL,
 
-       .vector_allocation_domain       = physflat_vector_allocation_domain,
+       .vector_allocation_domain       = default_vector_allocation_domain,
        /* not needed, but shouldn't hurt: */
        .init_apic_ldr                  = flat_init_apic_ldr,
 
@@ -370,8 +307,7 @@ static struct apic apic_physflat =  {
        .set_apic_id                    = set_apic_id,
        .apic_id_mask                   = 0xFFu << 24,
 
-       .cpu_mask_to_apicid             = physflat_cpu_mask_to_apicid,
-       .cpu_mask_to_apicid_and         = physflat_cpu_mask_to_apicid_and,
+       .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = physflat_send_IPI_mask,
        .send_IPI_mask_allbutself       = physflat_send_IPI_mask_allbutself,
index a6e4c6e06c08feaca0752c76619ec8c482a5a77d..e145f28b40993d4753d714f9247a46a8507fa959 100644 (file)
@@ -100,12 +100,12 @@ static unsigned long noop_check_apicid_present(int bit)
        return physid_isset(bit, phys_cpu_present_map);
 }
 
-static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask)
+static void noop_vector_allocation_domain(int cpu, struct cpumask *retmask,
+                                         const struct cpumask *mask)
 {
        if (cpu != 0)
                pr_warning("APIC: Vector allocated for non-BSP cpu\n");
-       cpumask_clear(retmask);
-       cpumask_set_cpu(cpu, retmask);
+       cpumask_copy(retmask, cpumask_of(cpu));
 }
 
 static u32 noop_apic_read(u32 reg)
@@ -159,8 +159,7 @@ struct apic apic_noop = {
        .set_apic_id                    = NULL,
        .apic_id_mask                   = 0x0F << 24,
 
-       .cpu_mask_to_apicid             = default_cpu_mask_to_apicid,
-       .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
+       .cpu_mask_to_apicid_and         = flat_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = noop_send_IPI_mask,
        .send_IPI_mask_allbutself       = noop_send_IPI_mask_allbutself,
index 6ec6d5d297c3a7f01dca9e6c64cd11f44e1a295e..bc552cff257834bee7a8c1078112ea46380892d4 100644 (file)
@@ -72,17 +72,6 @@ static int numachip_phys_pkg_id(int initial_apic_id, int index_msb)
        return initial_apic_id >> index_msb;
 }
 
-static const struct cpumask *numachip_target_cpus(void)
-{
-       return cpu_online_mask;
-}
-
-static void numachip_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       cpumask_clear(retmask);
-       cpumask_set_cpu(cpu, retmask);
-}
-
 static int __cpuinit numachip_wakeup_secondary(int phys_apicid, unsigned long start_rip)
 {
        union numachip_csr_g3_ext_irq_gen int_gen;
@@ -157,38 +146,6 @@ static void numachip_send_IPI_self(int vector)
        __default_send_IPI_shortcut(APIC_DEST_SELF, vector, APIC_DEST_PHYSICAL);
 }
 
-static unsigned int numachip_cpu_mask_to_apicid(const struct cpumask *cpumask)
-{
-       int cpu;
-
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       cpu = cpumask_first(cpumask);
-       if (likely((unsigned)cpu < nr_cpu_ids))
-               return per_cpu(x86_cpu_to_apicid, cpu);
-
-       return BAD_APICID;
-}
-
-static unsigned int
-numachip_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                               const struct cpumask *andmask)
-{
-       int cpu;
-
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       for_each_cpu_and(cpu, cpumask, andmask) {
-               if (cpumask_test_cpu(cpu, cpu_online_mask))
-                       break;
-       }
-       return per_cpu(x86_cpu_to_apicid, cpu);
-}
-
 static int __init numachip_probe(void)
 {
        return apic == &apic_numachip;
@@ -253,13 +210,13 @@ static struct apic apic_numachip __refconst = {
        .irq_delivery_mode              = dest_Fixed,
        .irq_dest_mode                  = 0, /* physical */
 
-       .target_cpus                    = numachip_target_cpus,
+       .target_cpus                    = online_target_cpus,
        .disable_esr                    = 0,
        .dest_logical                   = 0,
        .check_apicid_used              = NULL,
        .check_apicid_present           = NULL,
 
-       .vector_allocation_domain       = numachip_vector_allocation_domain,
+       .vector_allocation_domain       = default_vector_allocation_domain,
        .init_apic_ldr                  = flat_init_apic_ldr,
 
        .ioapic_phys_id_map             = NULL,
@@ -277,8 +234,7 @@ static struct apic apic_numachip __refconst = {
        .set_apic_id                    = set_apic_id,
        .apic_id_mask                   = 0xffU << 24,
 
-       .cpu_mask_to_apicid             = numachip_cpu_mask_to_apicid,
-       .cpu_mask_to_apicid_and         = numachip_cpu_mask_to_apicid_and,
+       .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = numachip_send_IPI_mask,
        .send_IPI_mask_allbutself       = numachip_send_IPI_mask_allbutself,
index 31fbdbfbf9607982c8769b58804b32b2c6ac29f5..d50e3640d5aed53daf4110ef68193cf0cbdac826 100644 (file)
@@ -26,15 +26,6 @@ static int bigsmp_apic_id_registered(void)
        return 1;
 }
 
-static const struct cpumask *bigsmp_target_cpus(void)
-{
-#ifdef CONFIG_SMP
-       return cpu_online_mask;
-#else
-       return cpumask_of(0);
-#endif
-}
-
 static unsigned long bigsmp_check_apicid_used(physid_mask_t *map, int apicid)
 {
        return 0;
@@ -105,32 +96,6 @@ static int bigsmp_check_phys_apicid_present(int phys_apicid)
        return 1;
 }
 
-/* As we are using single CPU as destination, pick only one CPU here */
-static unsigned int bigsmp_cpu_mask_to_apicid(const struct cpumask *cpumask)
-{
-       int cpu = cpumask_first(cpumask);
-
-       if (cpu < nr_cpu_ids)
-               return cpu_physical_id(cpu);
-       return BAD_APICID;
-}
-
-static unsigned int bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                             const struct cpumask *andmask)
-{
-       int cpu;
-
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       for_each_cpu_and(cpu, cpumask, andmask) {
-               if (cpumask_test_cpu(cpu, cpu_online_mask))
-                       return cpu_physical_id(cpu);
-       }
-       return BAD_APICID;
-}
-
 static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb)
 {
        return cpuid_apic >> index_msb;
@@ -177,12 +142,6 @@ static const struct dmi_system_id bigsmp_dmi_table[] = {
        { } /* NULL entry stops DMI scanning */
 };
 
-static void bigsmp_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       cpumask_clear(retmask);
-       cpumask_set_cpu(cpu, retmask);
-}
-
 static int probe_bigsmp(void)
 {
        if (def_to_bigsmp)
@@ -205,13 +164,13 @@ static struct apic apic_bigsmp = {
        /* phys delivery to target CPU: */
        .irq_dest_mode                  = 0,
 
-       .target_cpus                    = bigsmp_target_cpus,
+       .target_cpus                    = default_target_cpus,
        .disable_esr                    = 1,
        .dest_logical                   = 0,
        .check_apicid_used              = bigsmp_check_apicid_used,
        .check_apicid_present           = bigsmp_check_apicid_present,
 
-       .vector_allocation_domain       = bigsmp_vector_allocation_domain,
+       .vector_allocation_domain       = default_vector_allocation_domain,
        .init_apic_ldr                  = bigsmp_init_apic_ldr,
 
        .ioapic_phys_id_map             = bigsmp_ioapic_phys_id_map,
@@ -229,8 +188,7 @@ static struct apic apic_bigsmp = {
        .set_apic_id                    = NULL,
        .apic_id_mask                   = 0xFF << 24,
 
-       .cpu_mask_to_apicid             = bigsmp_cpu_mask_to_apicid,
-       .cpu_mask_to_apicid_and         = bigsmp_cpu_mask_to_apicid_and,
+       .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = bigsmp_send_IPI_mask,
        .send_IPI_mask_allbutself       = NULL,
index db4ab1be3c79470045fc9ebe44a11315b2416309..0874799a98c6fbe37ee34baaad7cbdc3bd616744 100644 (file)
@@ -394,21 +394,6 @@ static void es7000_enable_apic_mode(void)
                WARN(1, "Command failed, status = %x\n", mip_status);
 }
 
-static void es7000_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       /* Careful. Some cpus do not strictly honor the set of cpus
-        * specified in the interrupt destination when using lowest
-        * priority interrupt delivery mode.
-        *
-        * In particular there was a hyperthreading cpu observed to
-        * deliver interrupts to the wrong hyperthread when only one
-        * hyperthread was specified in the interrupt desitination.
-        */
-       cpumask_clear(retmask);
-       cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
-}
-
-
 static void es7000_wait_for_init_deassert(atomic_t *deassert)
 {
        while (!atomic_read(deassert))
@@ -540,45 +525,49 @@ static int es7000_check_phys_apicid_present(int cpu_physical_apicid)
        return 1;
 }
 
-static unsigned int es7000_cpu_mask_to_apicid(const struct cpumask *cpumask)
+static inline int
+es7000_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id)
 {
        unsigned int round = 0;
-       int cpu, uninitialized_var(apicid);
+       unsigned int cpu, uninitialized_var(apicid);
 
        /*
         * The cpus in the mask must all be on the apic cluster.
         */
-       for_each_cpu(cpu, cpumask) {
+       for_each_cpu_and(cpu, cpumask, cpu_online_mask) {
                int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
 
                if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
                        WARN(1, "Not a valid mask!");
 
-                       return BAD_APICID;
+                       return -EINVAL;
                }
-               apicid = new_apicid;
+               apicid |= new_apicid;
                round++;
        }
-       return apicid;
+       if (!round)
+               return -EINVAL;
+       *dest_id = apicid;
+       return 0;
 }
 
-static unsigned int
+static int
 es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask,
-                             const struct cpumask *andmask)
+                             const struct cpumask *andmask,
+                             unsigned int *apicid)
 {
-       int apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0);
        cpumask_var_t cpumask;
+       *apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0);
 
        if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
-               return apicid;
+               return 0;
 
        cpumask_and(cpumask, inmask, andmask);
-       cpumask_and(cpumask, cpumask, cpu_online_mask);
-       apicid = es7000_cpu_mask_to_apicid(cpumask);
+       es7000_cpu_mask_to_apicid(cpumask, apicid);
 
        free_cpumask_var(cpumask);
 
-       return apicid;
+       return 0;
 }
 
 static int es7000_phys_pkg_id(int cpuid_apic, int index_msb)
@@ -638,7 +627,7 @@ static struct apic __refdata apic_es7000_cluster = {
        .check_apicid_used              = es7000_check_apicid_used,
        .check_apicid_present           = es7000_check_apicid_present,
 
-       .vector_allocation_domain       = es7000_vector_allocation_domain,
+       .vector_allocation_domain       = flat_vector_allocation_domain,
        .init_apic_ldr                  = es7000_init_apic_ldr_cluster,
 
        .ioapic_phys_id_map             = es7000_ioapic_phys_id_map,
@@ -656,7 +645,6 @@ static struct apic __refdata apic_es7000_cluster = {
        .set_apic_id                    = NULL,
        .apic_id_mask                   = 0xFF << 24,
 
-       .cpu_mask_to_apicid             = es7000_cpu_mask_to_apicid,
        .cpu_mask_to_apicid_and         = es7000_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = es7000_send_IPI_mask,
@@ -705,7 +693,7 @@ static struct apic __refdata apic_es7000 = {
        .check_apicid_used              = es7000_check_apicid_used,
        .check_apicid_present           = es7000_check_apicid_present,
 
-       .vector_allocation_domain       = es7000_vector_allocation_domain,
+       .vector_allocation_domain       = flat_vector_allocation_domain,
        .init_apic_ldr                  = es7000_init_apic_ldr,
 
        .ioapic_phys_id_map             = es7000_ioapic_phys_id_map,
@@ -723,7 +711,6 @@ static struct apic __refdata apic_es7000 = {
        .set_apic_id                    = NULL,
        .apic_id_mask                   = 0xFF << 24,
 
-       .cpu_mask_to_apicid             = es7000_cpu_mask_to_apicid,
        .cpu_mask_to_apicid_and         = es7000_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = es7000_send_IPI_mask,
index 5f0ff597437c17add5334629458f8c2b35ffa148..406eee7846849990d8f87d53243e6cd171944e17 100644 (file)
@@ -448,8 +448,8 @@ static int __add_pin_to_irq_node(struct irq_cfg *cfg, int node, int apic, int pi
 
        entry = alloc_irq_pin_list(node);
        if (!entry) {
-               printk(KERN_ERR "can not alloc irq_pin_list (%d,%d,%d)\n",
-                               node, apic, pin);
+               pr_err("can not alloc irq_pin_list (%d,%d,%d)\n",
+                      node, apic, pin);
                return -ENOMEM;
        }
        entry->apic = apic;
@@ -661,7 +661,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
        ioapic_mask_entry(apic, pin);
        entry = ioapic_read_entry(apic, pin);
        if (entry.irr)
-               printk(KERN_ERR "Unable to reset IRR for apic: %d, pin :%d\n",
+               pr_err("Unable to reset IRR for apic: %d, pin :%d\n",
                       mpc_ioapic_id(apic), pin);
 }
 
@@ -895,7 +895,7 @@ static int irq_polarity(int idx)
                }
                case 2: /* reserved */
                {
-                       printk(KERN_WARNING "broken BIOS!!\n");
+                       pr_warn("broken BIOS!!\n");
                        polarity = 1;
                        break;
                }
@@ -906,7 +906,7 @@ static int irq_polarity(int idx)
                }
                default: /* invalid */
                {
-                       printk(KERN_WARNING "broken BIOS!!\n");
+                       pr_warn("broken BIOS!!\n");
                        polarity = 1;
                        break;
                }
@@ -948,7 +948,7 @@ static int irq_trigger(int idx)
                                }
                                default:
                                {
-                                       printk(KERN_WARNING "broken BIOS!!\n");
+                                       pr_warn("broken BIOS!!\n");
                                        trigger = 1;
                                        break;
                                }
@@ -962,7 +962,7 @@ static int irq_trigger(int idx)
                }
                case 2: /* reserved */
                {
-                       printk(KERN_WARNING "broken BIOS!!\n");
+                       pr_warn("broken BIOS!!\n");
                        trigger = 1;
                        break;
                }
@@ -973,7 +973,7 @@ static int irq_trigger(int idx)
                }
                default: /* invalid */
                {
-                       printk(KERN_WARNING "broken BIOS!!\n");
+                       pr_warn("broken BIOS!!\n");
                        trigger = 0;
                        break;
                }
@@ -991,7 +991,7 @@ static int pin_2_irq(int idx, int apic, int pin)
         * Debugging check, we are in big trouble if this message pops up!
         */
        if (mp_irqs[idx].dstirq != pin)
-               printk(KERN_ERR "broken BIOS or MPTABLE parser, ayiee!!\n");
+               pr_err("broken BIOS or MPTABLE parser, ayiee!!\n");
 
        if (test_bit(bus, mp_bus_not_pci)) {
                irq = mp_irqs[idx].srcbusirq;
@@ -1112,8 +1112,7 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
         * 0x80, because int 0x80 is hm, kind of importantish. ;)
         */
        static int current_vector = FIRST_EXTERNAL_VECTOR + VECTOR_OFFSET_START;
-       static int current_offset = VECTOR_OFFSET_START % 8;
-       unsigned int old_vector;
+       static int current_offset = VECTOR_OFFSET_START % 16;
        int cpu, err;
        cpumask_var_t tmp_mask;
 
@@ -1123,35 +1122,45 @@ __assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask)
        if (!alloc_cpumask_var(&tmp_mask, GFP_ATOMIC))
                return -ENOMEM;
 
-       old_vector = cfg->vector;
-       if (old_vector) {
-               cpumask_and(tmp_mask, mask, cpu_online_mask);
-               cpumask_and(tmp_mask, cfg->domain, tmp_mask);
-               if (!cpumask_empty(tmp_mask)) {
-                       free_cpumask_var(tmp_mask);
-                       return 0;
-               }
-       }
-
        /* Only try and allocate irqs on cpus that are present */
        err = -ENOSPC;
-       for_each_cpu_and(cpu, mask, cpu_online_mask) {
-               int new_cpu;
-               int vector, offset;
+       cpumask_clear(cfg->old_domain);
+       cpu = cpumask_first_and(mask, cpu_online_mask);
+       while (cpu < nr_cpu_ids) {
+               int new_cpu, vector, offset;
 
-               apic->vector_allocation_domain(cpu, tmp_mask);
+               apic->vector_allocation_domain(cpu, tmp_mask, mask);
+
+               if (cpumask_subset(tmp_mask, cfg->domain)) {
+                       err = 0;
+                       if (cpumask_equal(tmp_mask, cfg->domain))
+                               break;
+                       /*
+                        * New cpumask using the vector is a proper subset of
+                        * the current in use mask. So cleanup the vector
+                        * allocation for the members that are not used anymore.
+                        */
+                       cpumask_andnot(cfg->old_domain, cfg->domain, tmp_mask);
+                       cfg->move_in_progress = 1;
+                       cpumask_and(cfg->domain, cfg->domain, tmp_mask);
+                       break;
+               }
 
                vector = current_vector;
                offset = current_offset;
 next:
-               vector += 8;
+               vector += 16;
                if (vector >= first_system_vector) {
-                       /* If out of vectors on large boxen, must share them. */
-                       offset = (offset + 1) % 8;
+                       offset = (offset + 1) % 16;
                        vector = FIRST_EXTERNAL_VECTOR + offset;
                }
-               if (unlikely(current_vector == vector))
+
+               if (unlikely(current_vector == vector)) {
+                       cpumask_or(cfg->old_domain, cfg->old_domain, tmp_mask);
+                       cpumask_andnot(tmp_mask, mask, cfg->old_domain);
+                       cpu = cpumask_first_and(tmp_mask, cpu_online_mask);
                        continue;
+               }
 
                if (test_bit(vector, used_vectors))
                        goto next;
@@ -1162,7 +1171,7 @@ next:
                /* Found one! */
                current_vector = vector;
                current_offset = offset;
-               if (old_vector) {
+               if (cfg->vector) {
                        cfg->move_in_progress = 1;
                        cpumask_copy(cfg->old_domain, cfg->domain);
                }
@@ -1346,18 +1355,18 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,
 
        if (!IO_APIC_IRQ(irq))
                return;
-       /*
-        * For legacy irqs, cfg->domain starts with cpu 0 for legacy
-        * controllers like 8259. Now that IO-APIC can handle this irq, update
-        * the cfg->domain.
-        */
-       if (irq < legacy_pic->nr_legacy_irqs && cpumask_test_cpu(0, cfg->domain))
-               apic->vector_allocation_domain(0, cfg->domain);
 
        if (assign_irq_vector(irq, cfg, apic->target_cpus()))
                return;
 
-       dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
+       if (apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus(),
+                                        &dest)) {
+               pr_warn("Failed to obtain apicid for ioapic %d, pin %d\n",
+                       mpc_ioapic_id(attr->ioapic), attr->ioapic_pin);
+               __clear_irq_vector(irq, cfg);
+
+               return;
+       }
 
        apic_printk(APIC_VERBOSE,KERN_DEBUG
                    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
@@ -1366,7 +1375,7 @@ static void setup_ioapic_irq(unsigned int irq, struct irq_cfg *cfg,
                    cfg->vector, irq, attr->trigger, attr->polarity, dest);
 
        if (setup_ioapic_entry(irq, &entry, dest, cfg->vector, attr)) {
-               pr_warn("Failed to setup ioapic entry for ioapic  %d, pin %d\n",
+               pr_warn("Failed to setup ioapic entry for ioapic %d, pin %d\n",
                        mpc_ioapic_id(attr->ioapic), attr->ioapic_pin);
                __clear_irq_vector(irq, cfg);
 
@@ -1469,9 +1478,10 @@ void setup_IO_APIC_irq_extra(u32 gsi)
  * Set up the timer pin, possibly with the 8259A-master behind.
  */
 static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
-                                        unsigned int pin, int vector)
+                                       unsigned int pin, int vector)
 {
        struct IO_APIC_route_entry entry;
+       unsigned int dest;
 
        if (irq_remapping_enabled)
                return;
@@ -1482,9 +1492,13 @@ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx,
         * We use logical delivery to get the timer IRQ
         * to the first CPU.
         */
+       if (unlikely(apic->cpu_mask_to_apicid_and(apic->target_cpus(),
+                                                 apic->target_cpus(), &dest)))
+               dest = BAD_APICID;
+
        entry.dest_mode = apic->irq_dest_mode;
        entry.mask = 0;                 /* don't mask IRQ for edge */
-       entry.dest = apic->cpu_mask_to_apicid(apic->target_cpus());
+       entry.dest = dest;
        entry.delivery_mode = apic->irq_delivery_mode;
        entry.polarity = 0;
        entry.trigger = 0;
@@ -1521,7 +1535,6 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx)
                reg_03.raw = io_apic_read(ioapic_idx, 3);
        raw_spin_unlock_irqrestore(&ioapic_lock, flags);
 
-       printk("\n");
        printk(KERN_DEBUG "IO APIC #%d......\n", mpc_ioapic_id(ioapic_idx));
        printk(KERN_DEBUG ".... register #00: %08X\n", reg_00.raw);
        printk(KERN_DEBUG ".......    : physical APIC id: %02X\n", reg_00.bits.ID);
@@ -1578,7 +1591,7 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx)
                                i,
                                ir_entry->index
                        );
-                       printk("%1d   %1d    %1d    %1d   %1d   "
+                       pr_cont("%1d   %1d    %1d    %1d   %1d   "
                                "%1d    %1d     %X    %02X\n",
                                ir_entry->format,
                                ir_entry->mask,
@@ -1598,7 +1611,7 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx)
                                i,
                                entry.dest
                        );
-                       printk("%1d    %1d    %1d   %1d   %1d    "
+                       pr_cont("%1d    %1d    %1d   %1d   %1d    "
                                "%1d    %1d    %02X\n",
                                entry.mask,
                                entry.trigger,
@@ -1651,8 +1664,8 @@ __apicdebuginit(void) print_IO_APICs(void)
                        continue;
                printk(KERN_DEBUG "IRQ%d ", irq);
                for_each_irq_pin(entry, cfg->irq_2_pin)
-                       printk("-> %d:%d", entry->apic, entry->pin);
-               printk("\n");
+                       pr_cont("-> %d:%d", entry->apic, entry->pin);
+               pr_cont("\n");
        }
 
        printk(KERN_INFO ".................................... done.\n");
@@ -1665,9 +1678,9 @@ __apicdebuginit(void) print_APIC_field(int base)
        printk(KERN_DEBUG);
 
        for (i = 0; i < 8; i++)
-               printk(KERN_CONT "%08x", apic_read(base + i*0x10));
+               pr_cont("%08x", apic_read(base + i*0x10));
 
-       printk(KERN_CONT "\n");
+       pr_cont("\n");
 }
 
 __apicdebuginit(void) print_local_APIC(void *dummy)
@@ -1769,7 +1782,7 @@ __apicdebuginit(void) print_local_APIC(void *dummy)
                        printk(KERN_DEBUG "... APIC EILVT%d: %08x\n", i, v);
                }
        }
-       printk("\n");
+       pr_cont("\n");
 }
 
 __apicdebuginit(void) print_local_APICs(int maxcpu)
@@ -2065,7 +2078,7 @@ void __init setup_ioapic_ids_from_mpc_nocheck(void)
                reg_00.raw = io_apic_read(ioapic_idx, 0);
                raw_spin_unlock_irqrestore(&ioapic_lock, flags);
                if (reg_00.bits.ID != mpc_ioapic_id(ioapic_idx))
-                       printk("could not set ID!\n");
+                       pr_cont("could not set ID!\n");
                else
                        apic_printk(APIC_VERBOSE, " ok.\n");
        }
@@ -2210,71 +2223,6 @@ void send_cleanup_vector(struct irq_cfg *cfg)
        cfg->move_in_progress = 0;
 }
 
-static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
-{
-       int apic, pin;
-       struct irq_pin_list *entry;
-       u8 vector = cfg->vector;
-
-       for_each_irq_pin(entry, cfg->irq_2_pin) {
-               unsigned int reg;
-
-               apic = entry->apic;
-               pin = entry->pin;
-               /*
-                * With interrupt-remapping, destination information comes
-                * from interrupt-remapping table entry.
-                */
-               if (!irq_remapped(cfg))
-                       io_apic_write(apic, 0x11 + pin*2, dest);
-               reg = io_apic_read(apic, 0x10 + pin*2);
-               reg &= ~IO_APIC_REDIR_VECTOR_MASK;
-               reg |= vector;
-               io_apic_modify(apic, 0x10 + pin*2, reg);
-       }
-}
-
-/*
- * Either sets data->affinity to a valid value, and returns
- * ->cpu_mask_to_apicid of that in dest_id, or returns -1 and
- * leaves data->affinity untouched.
- */
-int __ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
-                         unsigned int *dest_id)
-{
-       struct irq_cfg *cfg = data->chip_data;
-
-       if (!cpumask_intersects(mask, cpu_online_mask))
-               return -1;
-
-       if (assign_irq_vector(data->irq, data->chip_data, mask))
-               return -1;
-
-       cpumask_copy(data->affinity, mask);
-
-       *dest_id = apic->cpu_mask_to_apicid_and(mask, cfg->domain);
-       return 0;
-}
-
-static int
-ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
-                   bool force)
-{
-       unsigned int dest, irq = data->irq;
-       unsigned long flags;
-       int ret;
-
-       raw_spin_lock_irqsave(&ioapic_lock, flags);
-       ret = __ioapic_set_affinity(data, mask, &dest);
-       if (!ret) {
-               /* Only the high 8 bits are valid. */
-               dest = SET_APIC_LOGICAL_ID(dest);
-               __target_IO_APIC_irq(irq, dest, data->chip_data);
-       }
-       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-       return ret;
-}
-
 asmlinkage void smp_irq_move_cleanup_interrupt(void)
 {
        unsigned vector, me;
@@ -2362,6 +2310,87 @@ void irq_force_complete_move(int irq)
 static inline void irq_complete_move(struct irq_cfg *cfg) { }
 #endif
 
+static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
+{
+       int apic, pin;
+       struct irq_pin_list *entry;
+       u8 vector = cfg->vector;
+
+       for_each_irq_pin(entry, cfg->irq_2_pin) {
+               unsigned int reg;
+
+               apic = entry->apic;
+               pin = entry->pin;
+               /*
+                * With interrupt-remapping, destination information comes
+                * from interrupt-remapping table entry.
+                */
+               if (!irq_remapped(cfg))
+                       io_apic_write(apic, 0x11 + pin*2, dest);
+               reg = io_apic_read(apic, 0x10 + pin*2);
+               reg &= ~IO_APIC_REDIR_VECTOR_MASK;
+               reg |= vector;
+               io_apic_modify(apic, 0x10 + pin*2, reg);
+       }
+}
+
+/*
+ * Either sets data->affinity to a valid value, and returns
+ * ->cpu_mask_to_apicid of that in dest_id, or returns -1 and
+ * leaves data->affinity untouched.
+ */
+int __ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+                         unsigned int *dest_id)
+{
+       struct irq_cfg *cfg = data->chip_data;
+       unsigned int irq = data->irq;
+       int err;
+
+       if (!config_enabled(CONFIG_SMP))
+               return -1;
+
+       if (!cpumask_intersects(mask, cpu_online_mask))
+               return -EINVAL;
+
+       err = assign_irq_vector(irq, cfg, mask);
+       if (err)
+               return err;
+
+       err = apic->cpu_mask_to_apicid_and(mask, cfg->domain, dest_id);
+       if (err) {
+               if (assign_irq_vector(irq, cfg, data->affinity))
+                       pr_err("Failed to recover vector for irq %d\n", irq);
+               return err;
+       }
+
+       cpumask_copy(data->affinity, mask);
+
+       return 0;
+}
+
+static int
+ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+                   bool force)
+{
+       unsigned int dest, irq = data->irq;
+       unsigned long flags;
+       int ret;
+
+       if (!config_enabled(CONFIG_SMP))
+               return -1;
+
+       raw_spin_lock_irqsave(&ioapic_lock, flags);
+       ret = __ioapic_set_affinity(data, mask, &dest);
+       if (!ret) {
+               /* Only the high 8 bits are valid. */
+               dest = SET_APIC_LOGICAL_ID(dest);
+               __target_IO_APIC_irq(irq, dest, data->chip_data);
+               ret = IRQ_SET_MASK_OK_NOCOPY;
+       }
+       raw_spin_unlock_irqrestore(&ioapic_lock, flags);
+       return ret;
+}
+
 static void ack_apic_edge(struct irq_data *data)
 {
        irq_complete_move(data->chip_data);
@@ -2541,9 +2570,7 @@ static void irq_remap_modify_chip_defaults(struct irq_chip *chip)
        chip->irq_ack = ir_ack_apic_edge;
        chip->irq_eoi = ir_ack_apic_level;
 
-#ifdef CONFIG_SMP
        chip->irq_set_affinity = set_remapped_irq_affinity;
-#endif
 }
 #endif /* CONFIG_IRQ_REMAP */
 
@@ -2554,9 +2581,7 @@ static struct irq_chip ioapic_chip __read_mostly = {
        .irq_unmask             = unmask_ioapic_irq,
        .irq_ack                = ack_apic_edge,
        .irq_eoi                = ack_apic_level,
-#ifdef CONFIG_SMP
        .irq_set_affinity       = ioapic_set_affinity,
-#endif
        .irq_retrigger          = ioapic_retrigger_irq,
 };
 
@@ -3038,7 +3063,10 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
        if (err)
                return err;
 
-       dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
+       err = apic->cpu_mask_to_apicid_and(cfg->domain,
+                                          apic->target_cpus(), &dest);
+       if (err)
+               return err;
 
        if (irq_remapped(cfg)) {
                compose_remapped_msi_msg(pdev, irq, dest, msg, hpet_id);
@@ -3072,7 +3100,6 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq,
        return err;
 }
 
-#ifdef CONFIG_SMP
 static int
 msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
 {
@@ -3092,9 +3119,8 @@ msi_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
 
        __write_msi_msg(data->msi_desc, &msg);
 
-       return 0;
+       return IRQ_SET_MASK_OK_NOCOPY;
 }
-#endif /* CONFIG_SMP */
 
 /*
  * IRQ Chip for MSI PCI/PCI-X/PCI-Express Devices,
@@ -3105,9 +3131,7 @@ static struct irq_chip msi_chip = {
        .irq_unmask             = unmask_msi_irq,
        .irq_mask               = mask_msi_irq,
        .irq_ack                = ack_apic_edge,
-#ifdef CONFIG_SMP
        .irq_set_affinity       = msi_set_affinity,
-#endif
        .irq_retrigger          = ioapic_retrigger_irq,
 };
 
@@ -3192,7 +3216,6 @@ void native_teardown_msi_irq(unsigned int irq)
 }
 
 #ifdef CONFIG_DMAR_TABLE
-#ifdef CONFIG_SMP
 static int
 dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
                      bool force)
@@ -3214,19 +3237,15 @@ dmar_msi_set_affinity(struct irq_data *data, const struct cpumask *mask,
 
        dmar_msi_write(irq, &msg);
 
-       return 0;
+       return IRQ_SET_MASK_OK_NOCOPY;
 }
 
-#endif /* CONFIG_SMP */
-
 static struct irq_chip dmar_msi_type = {
        .name                   = "DMAR_MSI",
        .irq_unmask             = dmar_msi_unmask,
        .irq_mask               = dmar_msi_mask,
        .irq_ack                = ack_apic_edge,
-#ifdef CONFIG_SMP
        .irq_set_affinity       = dmar_msi_set_affinity,
-#endif
        .irq_retrigger          = ioapic_retrigger_irq,
 };
 
@@ -3247,7 +3266,6 @@ int arch_setup_dmar_msi(unsigned int irq)
 
 #ifdef CONFIG_HPET_TIMER
 
-#ifdef CONFIG_SMP
 static int hpet_msi_set_affinity(struct irq_data *data,
                                 const struct cpumask *mask, bool force)
 {
@@ -3267,19 +3285,15 @@ static int hpet_msi_set_affinity(struct irq_data *data,
 
        hpet_msi_write(data->handler_data, &msg);
 
-       return 0;
+       return IRQ_SET_MASK_OK_NOCOPY;
 }
 
-#endif /* CONFIG_SMP */
-
 static struct irq_chip hpet_msi_type = {
        .name = "HPET_MSI",
        .irq_unmask = hpet_msi_unmask,
        .irq_mask = hpet_msi_mask,
        .irq_ack = ack_apic_edge,
-#ifdef CONFIG_SMP
        .irq_set_affinity = hpet_msi_set_affinity,
-#endif
        .irq_retrigger = ioapic_retrigger_irq,
 };
 
@@ -3314,8 +3328,6 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
  */
 #ifdef CONFIG_HT_IRQ
 
-#ifdef CONFIG_SMP
-
 static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
 {
        struct ht_irq_msg msg;
@@ -3340,25 +3352,23 @@ ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force)
                return -1;
 
        target_ht_irq(data->irq, dest, cfg->vector);
-       return 0;
+       return IRQ_SET_MASK_OK_NOCOPY;
 }
 
-#endif
-
 static struct irq_chip ht_irq_chip = {
        .name                   = "PCI-HT",
        .irq_mask               = mask_ht_irq,
        .irq_unmask             = unmask_ht_irq,
        .irq_ack                = ack_apic_edge,
-#ifdef CONFIG_SMP
        .irq_set_affinity       = ht_set_affinity,
-#endif
        .irq_retrigger          = ioapic_retrigger_irq,
 };
 
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 {
        struct irq_cfg *cfg;
+       struct ht_irq_msg msg;
+       unsigned dest;
        int err;
 
        if (disable_apic)
@@ -3366,36 +3376,37 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 
        cfg = irq_cfg(irq);
        err = assign_irq_vector(irq, cfg, apic->target_cpus());
-       if (!err) {
-               struct ht_irq_msg msg;
-               unsigned dest;
+       if (err)
+               return err;
+
+       err = apic->cpu_mask_to_apicid_and(cfg->domain,
+                                          apic->target_cpus(), &dest);
+       if (err)
+               return err;
 
-               dest = apic->cpu_mask_to_apicid_and(cfg->domain,
-                                                   apic->target_cpus());
+       msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
 
-               msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
+       msg.address_lo =
+               HT_IRQ_LOW_BASE |
+               HT_IRQ_LOW_DEST_ID(dest) |
+               HT_IRQ_LOW_VECTOR(cfg->vector) |
+               ((apic->irq_dest_mode == 0) ?
+                       HT_IRQ_LOW_DM_PHYSICAL :
+                       HT_IRQ_LOW_DM_LOGICAL) |
+               HT_IRQ_LOW_RQEOI_EDGE |
+               ((apic->irq_delivery_mode != dest_LowestPrio) ?
+                       HT_IRQ_LOW_MT_FIXED :
+                       HT_IRQ_LOW_MT_ARBITRATED) |
+               HT_IRQ_LOW_IRQ_MASKED;
 
-               msg.address_lo =
-                       HT_IRQ_LOW_BASE |
-                       HT_IRQ_LOW_DEST_ID(dest) |
-                       HT_IRQ_LOW_VECTOR(cfg->vector) |
-                       ((apic->irq_dest_mode == 0) ?
-                               HT_IRQ_LOW_DM_PHYSICAL :
-                               HT_IRQ_LOW_DM_LOGICAL) |
-                       HT_IRQ_LOW_RQEOI_EDGE |
-                       ((apic->irq_delivery_mode != dest_LowestPrio) ?
-                               HT_IRQ_LOW_MT_FIXED :
-                               HT_IRQ_LOW_MT_ARBITRATED) |
-                       HT_IRQ_LOW_IRQ_MASKED;
+       write_ht_irq_msg(irq, &msg);
 
-               write_ht_irq_msg(irq, &msg);
+       irq_set_chip_and_handler_name(irq, &ht_irq_chip,
+                                     handle_edge_irq, "edge");
 
-               irq_set_chip_and_handler_name(irq, &ht_irq_chip,
-                                             handle_edge_irq, "edge");
+       dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq);
 
-               dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq);
-       }
-       return err;
+       return 0;
 }
 #endif /* CONFIG_HT_IRQ */
 
@@ -3563,7 +3574,8 @@ static int __init io_apic_get_unique_id(int ioapic, int apic_id)
 
                /* Sanity check */
                if (reg_00.bits.ID != apic_id) {
-                       printk("IOAPIC[%d]: Unable to change apic_id!\n", ioapic);
+                       pr_err("IOAPIC[%d]: Unable to change apic_id!\n",
+                              ioapic);
                        return -1;
                }
        }
index f00a68cca37a9bbd9ebc613b78fd4519e632cb4b..d661ee95cabfa0b2619b94f75971cfd33cd3ea7f 100644 (file)
@@ -406,16 +406,13 @@ static inline int numaq_check_phys_apicid_present(int phys_apicid)
  * We use physical apicids here, not logical, so just return the default
  * physical broadcast to stop people from breaking us
  */
-static unsigned int numaq_cpu_mask_to_apicid(const struct cpumask *cpumask)
-{
-       return 0x0F;
-}
-
-static inline unsigned int
+static int
 numaq_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                            const struct cpumask *andmask)
+                            const struct cpumask *andmask,
+                            unsigned int *apicid)
 {
-       return 0x0F;
+       *apicid = 0x0F;
+       return 0;
 }
 
 /* No NUMA-Q box has a HT CPU, but it can't hurt to use the default code. */
@@ -441,20 +438,6 @@ static int probe_numaq(void)
        return found_numaq;
 }
 
-static void numaq_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       /* Careful. Some cpus do not strictly honor the set of cpus
-        * specified in the interrupt destination when using lowest
-        * priority interrupt delivery mode.
-        *
-        * In particular there was a hyperthreading cpu observed to
-        * deliver interrupts to the wrong hyperthread when only one
-        * hyperthread was specified in the interrupt desitination.
-        */
-       cpumask_clear(retmask);
-       cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
-}
-
 static void numaq_setup_portio_remap(void)
 {
        int num_quads = num_online_nodes();
@@ -491,7 +474,7 @@ static struct apic __refdata apic_numaq = {
        .check_apicid_used              = numaq_check_apicid_used,
        .check_apicid_present           = numaq_check_apicid_present,
 
-       .vector_allocation_domain       = numaq_vector_allocation_domain,
+       .vector_allocation_domain       = flat_vector_allocation_domain,
        .init_apic_ldr                  = numaq_init_apic_ldr,
 
        .ioapic_phys_id_map             = numaq_ioapic_phys_id_map,
@@ -509,7 +492,6 @@ static struct apic __refdata apic_numaq = {
        .set_apic_id                    = NULL,
        .apic_id_mask                   = 0x0F << 24,
 
-       .cpu_mask_to_apicid             = numaq_cpu_mask_to_apicid,
        .cpu_mask_to_apicid_and         = numaq_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = numaq_send_IPI_mask,
index 1b291da09e6029750e0613c9b6b873d1bce2a6a6..eb35ef9ee63f779bde870822a01dcc98bd503b01 100644 (file)
@@ -66,21 +66,6 @@ static void setup_apic_flat_routing(void)
 #endif
 }
 
-static void default_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       /*
-        * Careful. Some cpus do not strictly honor the set of cpus
-        * specified in the interrupt destination when using lowest
-        * priority interrupt delivery mode.
-        *
-        * In particular there was a hyperthreading cpu observed to
-        * deliver interrupts to the wrong hyperthread when only one
-        * hyperthread was specified in the interrupt desitination.
-        */
-       cpumask_clear(retmask);
-       cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
-}
-
 /* should be called last. */
 static int probe_default(void)
 {
@@ -105,7 +90,7 @@ static struct apic apic_default = {
        .check_apicid_used              = default_check_apicid_used,
        .check_apicid_present           = default_check_apicid_present,
 
-       .vector_allocation_domain       = default_vector_allocation_domain,
+       .vector_allocation_domain       = flat_vector_allocation_domain,
        .init_apic_ldr                  = default_init_apic_ldr,
 
        .ioapic_phys_id_map             = default_ioapic_phys_id_map,
@@ -123,8 +108,7 @@ static struct apic apic_default = {
        .set_apic_id                    = NULL,
        .apic_id_mask                   = 0x0F << 24,
 
-       .cpu_mask_to_apicid             = default_cpu_mask_to_apicid,
-       .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
+       .cpu_mask_to_apicid_and         = flat_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = default_send_IPI_mask_logical,
        .send_IPI_mask_allbutself       = default_send_IPI_mask_allbutself_logical,
@@ -208,6 +192,9 @@ void __init default_setup_apic_routing(void)
 
        if (apic->setup_apic_routing)
                apic->setup_apic_routing();
+
+       if (x86_platform.apic_post_init)
+               x86_platform.apic_post_init();
 }
 
 void __init generic_apic_probe(void)
index 3fe98669892905c48d3b8eea6ee11bda7100e75d..1793dba7a741bcf22271b71848fa92293bddde70 100644 (file)
 #include <asm/ipi.h>
 #include <asm/setup.h>
 
-static int apicid_phys_pkg_id(int initial_apic_id, int index_msb)
-{
-       return hard_smp_processor_id() >> index_msb;
-}
-
 /*
  * Check the APIC IDs in bios_cpu_apicid and choose the APIC mode.
  */
@@ -48,10 +43,8 @@ void __init default_setup_apic_routing(void)
                }
        }
 
-       if (is_vsmp_box()) {
-               /* need to update phys_pkg_id */
-               apic->phys_pkg_id = apicid_phys_pkg_id;
-       }
+       if (x86_platform.apic_post_init)
+               x86_platform.apic_post_init();
 }
 
 /* Same for both flat and physical. */
index 659897c007553916d129a5da1462b9e733cd6eff..77c95c0e1bf77d2ba06aa737ef22bebb8a0a1c22 100644 (file)
@@ -26,6 +26,8 @@
  *
  */
 
+#define pr_fmt(fmt) "summit: %s: " fmt, __func__
+
 #include <linux/mm.h>
 #include <linux/init.h>
 #include <asm/io.h>
@@ -235,8 +237,8 @@ static int summit_apic_id_registered(void)
 
 static void summit_setup_apic_routing(void)
 {
-       printk("Enabling APIC mode:  Summit.  Using %d I/O APICs\n",
-                                               nr_ioapics);
+       pr_info("Enabling APIC mode:  Summit.  Using %d I/O APICs\n",
+               nr_ioapics);
 }
 
 static int summit_cpu_present_to_apicid(int mps_cpu)
@@ -263,43 +265,48 @@ static int summit_check_phys_apicid_present(int physical_apicid)
        return 1;
 }
 
-static unsigned int summit_cpu_mask_to_apicid(const struct cpumask *cpumask)
+static inline int
+summit_cpu_mask_to_apicid(const struct cpumask *cpumask, unsigned int *dest_id)
 {
        unsigned int round = 0;
-       int cpu, apicid = 0;
+       unsigned int cpu, apicid = 0;
 
        /*
         * The cpus in the mask must all be on the apic cluster.
         */
-       for_each_cpu(cpu, cpumask) {
+       for_each_cpu_and(cpu, cpumask, cpu_online_mask) {
                int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
 
                if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
-                       printk("%s: Not a valid mask!\n", __func__);
-                       return BAD_APICID;
+                       pr_err("Not a valid mask!\n");
+                       return -EINVAL;
                }
                apicid |= new_apicid;
                round++;
        }
-       return apicid;
+       if (!round)
+               return -EINVAL;
+       *dest_id = apicid;
+       return 0;
 }
 
-static unsigned int summit_cpu_mask_to_apicid_and(const struct cpumask *inmask,
-                             const struct cpumask *andmask)
+static int
+summit_cpu_mask_to_apicid_and(const struct cpumask *inmask,
+                             const struct cpumask *andmask,
+                             unsigned int *apicid)
 {
-       int apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0);
        cpumask_var_t cpumask;
+       *apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0);
 
        if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
-               return apicid;
+               return 0;
 
        cpumask_and(cpumask, inmask, andmask);
-       cpumask_and(cpumask, cpumask, cpu_online_mask);
-       apicid = summit_cpu_mask_to_apicid(cpumask);
+       summit_cpu_mask_to_apicid(cpumask, apicid);
 
        free_cpumask_var(cpumask);
 
-       return apicid;
+       return 0;
 }
 
 /*
@@ -320,20 +327,6 @@ static int probe_summit(void)
        return 0;
 }
 
-static void summit_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       /* Careful. Some cpus do not strictly honor the set of cpus
-        * specified in the interrupt destination when using lowest
-        * priority interrupt delivery mode.
-        *
-        * In particular there was a hyperthreading cpu observed to
-        * deliver interrupts to the wrong hyperthread when only one
-        * hyperthread was specified in the interrupt desitination.
-        */
-       cpumask_clear(retmask);
-       cpumask_bits(retmask)[0] = APIC_ALL_CPUS;
-}
-
 #ifdef CONFIG_X86_SUMMIT_NUMA
 static struct rio_table_hdr *rio_table_hdr;
 static struct scal_detail   *scal_devs[MAX_NUMNODES];
@@ -355,7 +348,7 @@ static int setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
                }
        }
        if (i == rio_table_hdr->num_rio_dev) {
-               printk(KERN_ERR "%s: Couldn't find owner Cyclone for Winnipeg!\n", __func__);
+               pr_err("Couldn't find owner Cyclone for Winnipeg!\n");
                return last_bus;
        }
 
@@ -366,7 +359,7 @@ static int setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
                }
        }
        if (i == rio_table_hdr->num_scal_dev) {
-               printk(KERN_ERR "%s: Couldn't find owner Twister for Cyclone!\n", __func__);
+               pr_err("Couldn't find owner Twister for Cyclone!\n");
                return last_bus;
        }
 
@@ -396,7 +389,7 @@ static int setup_pci_node_map_for_wpeg(int wpeg_num, int last_bus)
                num_buses = 9;
                break;
        default:
-               printk(KERN_INFO "%s: Unsupported Winnipeg type!\n", __func__);
+               pr_info("Unsupported Winnipeg type!\n");
                return last_bus;
        }
 
@@ -411,13 +404,15 @@ static int build_detail_arrays(void)
        int i, scal_detail_size, rio_detail_size;
 
        if (rio_table_hdr->num_scal_dev > MAX_NUMNODES) {
-               printk(KERN_WARNING "%s: MAX_NUMNODES too low!  Defined as %d, but system has %d nodes.\n", __func__, MAX_NUMNODES, rio_table_hdr->num_scal_dev);
+               pr_warn("MAX_NUMNODES too low!  Defined as %d, but system has %d nodes\n",
+                       MAX_NUMNODES, rio_table_hdr->num_scal_dev);
                return 0;
        }
 
        switch (rio_table_hdr->version) {
        default:
-               printk(KERN_WARNING "%s: Invalid Rio Grande Table Version: %d\n", __func__, rio_table_hdr->version);
+               pr_warn("Invalid Rio Grande Table Version: %d\n",
+                       rio_table_hdr->version);
                return 0;
        case 2:
                scal_detail_size = 11;
@@ -462,7 +457,7 @@ void setup_summit(void)
                offset = *((unsigned short *)(ptr + offset));
        }
        if (!rio_table_hdr) {
-               printk(KERN_ERR "%s: Unable to locate Rio Grande Table in EBDA - bailing!\n", __func__);
+               pr_err("Unable to locate Rio Grande Table in EBDA - bailing!\n");
                return;
        }
 
@@ -509,7 +504,7 @@ static struct apic apic_summit = {
        .check_apicid_used              = summit_check_apicid_used,
        .check_apicid_present           = summit_check_apicid_present,
 
-       .vector_allocation_domain       = summit_vector_allocation_domain,
+       .vector_allocation_domain       = flat_vector_allocation_domain,
        .init_apic_ldr                  = summit_init_apic_ldr,
 
        .ioapic_phys_id_map             = summit_ioapic_phys_id_map,
@@ -527,7 +522,6 @@ static struct apic apic_summit = {
        .set_apic_id                    = NULL,
        .apic_id_mask                   = 0xFF << 24,
 
-       .cpu_mask_to_apicid             = summit_cpu_mask_to_apicid,
        .cpu_mask_to_apicid_and         = summit_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = summit_send_IPI_mask,
index ff35cff0e1a7e6f4f16b628504c821c5e544bacf..c88baa4ff0e5650061dbed84fca55b89d4c1b55e 100644 (file)
@@ -81,7 +81,7 @@ static void x2apic_send_IPI_mask(const struct cpumask *mask, int vector)
 }
 
 static void
- x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector)
+x2apic_send_IPI_mask_allbutself(const struct cpumask *mask, int vector)
 {
        __x2apic_send_IPI_mask(mask, vector, APIC_DEST_ALLBUT);
 }
@@ -96,36 +96,37 @@ static void x2apic_send_IPI_all(int vector)
        __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC);
 }
 
-static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask)
+static int
+x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
+                             const struct cpumask *andmask,
+                             unsigned int *apicid)
 {
-       /*
-        * We're using fixed IRQ delivery, can only return one logical APIC ID.
-        * May as well be the first.
-        */
-       int cpu = cpumask_first(cpumask);
+       u32 dest = 0;
+       u16 cluster;
+       int i;
 
-       if ((unsigned)cpu < nr_cpu_ids)
-               return per_cpu(x86_cpu_to_logical_apicid, cpu);
-       else
-               return BAD_APICID;
-}
+       for_each_cpu_and(i, cpumask, andmask) {
+               if (!cpumask_test_cpu(i, cpu_online_mask))
+                       continue;
+               dest = per_cpu(x86_cpu_to_logical_apicid, i);
+               cluster = x2apic_cluster(i);
+               break;
+       }
 
-static unsigned int
-x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                             const struct cpumask *andmask)
-{
-       int cpu;
+       if (!dest)
+               return -EINVAL;
 
-       /*
-        * We're using fixed IRQ delivery, can only return one logical APIC ID.
-        * May as well be the first.
-        */
-       for_each_cpu_and(cpu, cpumask, andmask) {
-               if (cpumask_test_cpu(cpu, cpu_online_mask))
-                       break;
+       for_each_cpu_and(i, cpumask, andmask) {
+               if (!cpumask_test_cpu(i, cpu_online_mask))
+                       continue;
+               if (cluster != x2apic_cluster(i))
+                       continue;
+               dest |= per_cpu(x86_cpu_to_logical_apicid, i);
        }
 
-       return per_cpu(x86_cpu_to_logical_apicid, cpu);
+       *apicid = dest;
+
+       return 0;
 }
 
 static void init_x2apic_ldr(void)
@@ -208,6 +209,32 @@ static int x2apic_cluster_probe(void)
                return 0;
 }
 
+static const struct cpumask *x2apic_cluster_target_cpus(void)
+{
+       return cpu_all_mask;
+}
+
+/*
+ * Each x2apic cluster is an allocation domain.
+ */
+static void cluster_vector_allocation_domain(int cpu, struct cpumask *retmask,
+                                            const struct cpumask *mask)
+{
+       /*
+        * To minimize vector pressure, default case of boot, device bringup
+        * etc will use a single cpu for the interrupt destination.
+        *
+        * On explicit migration requests coming from irqbalance etc,
+        * interrupts will be routed to the x2apic cluster (cluster-id
+        * derived from the first cpu in the mask) members specified
+        * in the mask.
+        */
+       if (mask == x2apic_cluster_target_cpus())
+               cpumask_copy(retmask, cpumask_of(cpu));
+       else
+               cpumask_and(retmask, mask, per_cpu(cpus_in_cluster, cpu));
+}
+
 static struct apic apic_x2apic_cluster = {
 
        .name                           = "cluster x2apic",
@@ -219,13 +246,13 @@ static struct apic apic_x2apic_cluster = {
        .irq_delivery_mode              = dest_LowestPrio,
        .irq_dest_mode                  = 1, /* logical */
 
-       .target_cpus                    = x2apic_target_cpus,
+       .target_cpus                    = x2apic_cluster_target_cpus,
        .disable_esr                    = 0,
        .dest_logical                   = APIC_DEST_LOGICAL,
        .check_apicid_used              = NULL,
        .check_apicid_present           = NULL,
 
-       .vector_allocation_domain       = x2apic_vector_allocation_domain,
+       .vector_allocation_domain       = cluster_vector_allocation_domain,
        .init_apic_ldr                  = init_x2apic_ldr,
 
        .ioapic_phys_id_map             = NULL,
@@ -243,7 +270,6 @@ static struct apic apic_x2apic_cluster = {
        .set_apic_id                    = x2apic_set_apic_id,
        .apic_id_mask                   = 0xFFFFFFFFu,
 
-       .cpu_mask_to_apicid             = x2apic_cpu_mask_to_apicid,
        .cpu_mask_to_apicid_and         = x2apic_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = x2apic_send_IPI_mask,
index c17e982db2759ad5913e8c586a7100267f014c32..e03a1e180e81789bb334918f7f92c2886142d491 100644 (file)
@@ -76,38 +76,6 @@ static void x2apic_send_IPI_all(int vector)
        __x2apic_send_IPI_mask(cpu_online_mask, vector, APIC_DEST_ALLINC);
 }
 
-static unsigned int x2apic_cpu_mask_to_apicid(const struct cpumask *cpumask)
-{
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       int cpu = cpumask_first(cpumask);
-
-       if ((unsigned)cpu < nr_cpu_ids)
-               return per_cpu(x86_cpu_to_apicid, cpu);
-       else
-               return BAD_APICID;
-}
-
-static unsigned int
-x2apic_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                             const struct cpumask *andmask)
-{
-       int cpu;
-
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       for_each_cpu_and(cpu, cpumask, andmask) {
-               if (cpumask_test_cpu(cpu, cpu_online_mask))
-                       break;
-       }
-
-       return per_cpu(x86_cpu_to_apicid, cpu);
-}
-
 static void init_x2apic_ldr(void)
 {
 }
@@ -131,13 +99,13 @@ static struct apic apic_x2apic_phys = {
        .irq_delivery_mode              = dest_Fixed,
        .irq_dest_mode                  = 0, /* physical */
 
-       .target_cpus                    = x2apic_target_cpus,
+       .target_cpus                    = online_target_cpus,
        .disable_esr                    = 0,
        .dest_logical                   = 0,
        .check_apicid_used              = NULL,
        .check_apicid_present           = NULL,
 
-       .vector_allocation_domain       = x2apic_vector_allocation_domain,
+       .vector_allocation_domain       = default_vector_allocation_domain,
        .init_apic_ldr                  = init_x2apic_ldr,
 
        .ioapic_phys_id_map             = NULL,
@@ -155,8 +123,7 @@ static struct apic apic_x2apic_phys = {
        .set_apic_id                    = x2apic_set_apic_id,
        .apic_id_mask                   = 0xFFFFFFFFu,
 
-       .cpu_mask_to_apicid             = x2apic_cpu_mask_to_apicid,
-       .cpu_mask_to_apicid_and         = x2apic_cpu_mask_to_apicid_and,
+       .cpu_mask_to_apicid_and         = default_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = x2apic_send_IPI_mask,
        .send_IPI_mask_allbutself       = x2apic_send_IPI_mask_allbutself,
index c6d03f7a4401324444d33c0adf201ec13fbb7aea..8cfade9510a41b10a03a8964a6ff9ed7c914cb2f 100644 (file)
@@ -185,17 +185,6 @@ EXPORT_SYMBOL_GPL(uv_possible_blades);
 unsigned long sn_rtc_cycles_per_second;
 EXPORT_SYMBOL(sn_rtc_cycles_per_second);
 
-static const struct cpumask *uv_target_cpus(void)
-{
-       return cpu_online_mask;
-}
-
-static void uv_vector_allocation_domain(int cpu, struct cpumask *retmask)
-{
-       cpumask_clear(retmask);
-       cpumask_set_cpu(cpu, retmask);
-}
-
 static int __cpuinit uv_wakeup_secondary(int phys_apicid, unsigned long start_rip)
 {
 #ifdef CONFIG_SMP
@@ -280,25 +269,12 @@ static void uv_init_apic_ldr(void)
 {
 }
 
-static unsigned int uv_cpu_mask_to_apicid(const struct cpumask *cpumask)
-{
-       /*
-        * We're using fixed IRQ delivery, can only return one phys APIC ID.
-        * May as well be the first.
-        */
-       int cpu = cpumask_first(cpumask);
-
-       if ((unsigned)cpu < nr_cpu_ids)
-               return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits;
-       else
-               return BAD_APICID;
-}
-
-static unsigned int
+static int
 uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
-                         const struct cpumask *andmask)
+                         const struct cpumask *andmask,
+                         unsigned int *apicid)
 {
-       int cpu;
+       int unsigned cpu;
 
        /*
         * We're using fixed IRQ delivery, can only return one phys APIC ID.
@@ -308,7 +284,13 @@ uv_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
                if (cpumask_test_cpu(cpu, cpu_online_mask))
                        break;
        }
-       return per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits;
+
+       if (likely(cpu < nr_cpu_ids)) {
+               *apicid = per_cpu(x86_cpu_to_apicid, cpu) | uv_apicid_hibits;
+               return 0;
+       }
+
+       return -EINVAL;
 }
 
 static unsigned int x2apic_get_apic_id(unsigned long x)
@@ -362,13 +344,13 @@ static struct apic __refdata apic_x2apic_uv_x = {
        .irq_delivery_mode              = dest_Fixed,
        .irq_dest_mode                  = 0, /* physical */
 
-       .target_cpus                    = uv_target_cpus,
+       .target_cpus                    = online_target_cpus,
        .disable_esr                    = 0,
        .dest_logical                   = APIC_DEST_LOGICAL,
        .check_apicid_used              = NULL,
        .check_apicid_present           = NULL,
 
-       .vector_allocation_domain       = uv_vector_allocation_domain,
+       .vector_allocation_domain       = default_vector_allocation_domain,
        .init_apic_ldr                  = uv_init_apic_ldr,
 
        .ioapic_phys_id_map             = NULL,
@@ -386,7 +368,6 @@ static struct apic __refdata apic_x2apic_uv_x = {
        .set_apic_id                    = set_apic_id,
        .apic_id_mask                   = 0xFFFFFFFFu,
 
-       .cpu_mask_to_apicid             = uv_cpu_mask_to_apicid,
        .cpu_mask_to_apicid_and         = uv_cpu_mask_to_apicid_and,
 
        .send_IPI_mask                  = uv_send_IPI_mask,
index 07b0c0db466c4d794cf206358ced2b5e2c2b9e6b..d65464e4350343c9d379aa6d44a1ed03a1ca1f2c 100644 (file)
  *    http://www.microsoft.com/whdc/archive/amp_12.mspx]
  */
 
+#define pr_fmt(fmt) "apm: " fmt
+
 #include <linux/module.h>
 
 #include <linux/poll.h>
@@ -485,11 +487,11 @@ static void apm_error(char *str, int err)
                if (error_table[i].key == err)
                        break;
        if (i < ERROR_COUNT)
-               printk(KERN_NOTICE "apm: %s: %s\n", str, error_table[i].msg);
+               pr_notice("%s: %s\n", str, error_table[i].msg);
        else if (err < 0)
-               printk(KERN_NOTICE "apm: %s: linux error code %i\n", str, err);
+               pr_notice("%s: linux error code %i\n", str, err);
        else
-               printk(KERN_NOTICE "apm: %s: unknown error code %#2.2x\n",
+               pr_notice("%s: unknown error code %#2.2x\n",
                       str, err);
 }
 
@@ -1184,7 +1186,7 @@ static void queue_event(apm_event_t event, struct apm_user *sender)
                        static int notified;
 
                        if (notified++ == 0)
-                           printk(KERN_ERR "apm: an event queue overflowed\n");
+                               pr_err("an event queue overflowed\n");
                        if (++as->event_tail >= APM_MAX_EVENTS)
                                as->event_tail = 0;
                }
@@ -1447,7 +1449,7 @@ static void apm_mainloop(void)
 static int check_apm_user(struct apm_user *as, const char *func)
 {
        if (as == NULL || as->magic != APM_BIOS_MAGIC) {
-               printk(KERN_ERR "apm: %s passed bad filp\n", func);
+               pr_err("%s passed bad filp\n", func);
                return 1;
        }
        return 0;
@@ -1586,7 +1588,7 @@ static int do_release(struct inode *inode, struct file *filp)
                     as1 = as1->next)
                        ;
                if (as1 == NULL)
-                       printk(KERN_ERR "apm: filp not in user list\n");
+                       pr_err("filp not in user list\n");
                else
                        as1->next = as->next;
        }
@@ -1600,11 +1602,9 @@ static int do_open(struct inode *inode, struct file *filp)
        struct apm_user *as;
 
        as = kmalloc(sizeof(*as), GFP_KERNEL);
-       if (as == NULL) {
-               printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
-                      sizeof(*as));
+       if (as == NULL)
                return -ENOMEM;
-       }
+
        as->magic = APM_BIOS_MAGIC;
        as->event_tail = as->event_head = 0;
        as->suspends_pending = as->standbys_pending = 0;
@@ -2313,16 +2313,16 @@ static int __init apm_init(void)
        }
 
        if (apm_info.disabled) {
-               printk(KERN_NOTICE "apm: disabled on user request.\n");
+               pr_notice("disabled on user request.\n");
                return -ENODEV;
        }
        if ((num_online_cpus() > 1) && !power_off && !smp) {
-               printk(KERN_NOTICE "apm: disabled - APM is not SMP safe.\n");
+               pr_notice("disabled - APM is not SMP safe.\n");
                apm_info.disabled = 1;
                return -ENODEV;
        }
        if (!acpi_disabled) {
-               printk(KERN_NOTICE "apm: overridden by ACPI.\n");
+               pr_notice("overridden by ACPI.\n");
                apm_info.disabled = 1;
                return -ENODEV;
        }
@@ -2356,8 +2356,7 @@ static int __init apm_init(void)
 
        kapmd_task = kthread_create(apm, NULL, "kapmd");
        if (IS_ERR(kapmd_task)) {
-               printk(KERN_ERR "apm: disabled - Unable to start kernel "
-                               "thread.\n");
+               pr_err("disabled - Unable to start kernel thread\n");
                err = PTR_ERR(kapmd_task);
                kapmd_task = NULL;
                remove_proc_entry("apm", NULL);
index 6ab6aa2fdfdd21ef0192b0eb11a99c1a0531f8ab..bac4c3804cc7530e179630e87facca153576d026 100644 (file)
@@ -32,7 +32,9 @@ obj-$(CONFIG_PERF_EVENTS)             += perf_event.o
 
 ifdef CONFIG_PERF_EVENTS
 obj-$(CONFIG_CPU_SUP_AMD)              += perf_event_amd.o
-obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_p6.o perf_event_p4.o perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o
+obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_p6.o perf_event_p4.o
+obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_lbr.o perf_event_intel_ds.o perf_event_intel.o
+obj-$(CONFIG_CPU_SUP_INTEL)            += perf_event_intel_uncore.o
 endif
 
 obj-$(CONFIG_X86_MCE)                  += mcheck/
index 146bb6218eec3daa3cdbe0472c04bcfac7500e8a..9d92e19039f05f84b4c172de7c1c243a4dad72e0 100644 (file)
 
 #include "cpu.h"
 
+static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
+{
+       struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
+       u32 gprs[8] = { 0 };
+       int err;
+
+       WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__);
+
+       gprs[1] = msr;
+       gprs[7] = 0x9c5a203a;
+
+       err = rdmsr_safe_regs(gprs);
+
+       *p = gprs[0] | ((u64)gprs[2] << 32);
+
+       return err;
+}
+
+static inline int wrmsrl_amd_safe(unsigned msr, unsigned long long val)
+{
+       struct cpuinfo_x86 *c = &cpu_data(smp_processor_id());
+       u32 gprs[8] = { 0 };
+
+       WARN_ONCE((c->x86 != 0xf), "%s should only be used on K8!\n", __func__);
+
+       gprs[0] = (u32)val;
+       gprs[1] = msr;
+       gprs[2] = val >> 32;
+       gprs[7] = 0x9c5a203a;
+
+       return wrmsr_safe_regs(gprs);
+}
+
 #ifdef CONFIG_X86_32
 /*
  *     B step AMD K6 before B 9730xxxx have hardware bugs that can cause
@@ -586,9 +619,9 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
            !cpu_has(c, X86_FEATURE_TOPOEXT)) {
                u64 val;
 
-               if (!rdmsrl_amd_safe(0xc0011005, &val)) {
+               if (!rdmsrl_safe(0xc0011005, &val)) {
                        val |= 1ULL << 54;
-                       wrmsrl_amd_safe(0xc0011005, val);
+                       wrmsrl_safe(0xc0011005, val);
                        rdmsrl(0xc0011005, val);
                        if (val & (1ULL << 54)) {
                                set_cpu_cap(c, X86_FEATURE_TOPOEXT);
@@ -679,7 +712,7 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c)
                err = rdmsrl_safe(MSR_AMD64_MCx_MASK(4), &mask);
                if (err == 0) {
                        mask |= (1 << 10);
-                       checking_wrmsrl(MSR_AMD64_MCx_MASK(4), mask);
+                       wrmsrl_safe(MSR_AMD64_MCx_MASK(4), mask);
                }
        }
 
index 46674fbb62baac1826c8b23b43903630909ce579..c97bb7b5a9f878332e81d119bae0a571c17d8ea0 100644 (file)
@@ -55,8 +55,8 @@ static void __init check_fpu(void)
 
        if (!boot_cpu_data.hard_math) {
 #ifndef CONFIG_MATH_EMULATION
-               printk(KERN_EMERG "No coprocessor found and no math emulation present.\n");
-               printk(KERN_EMERG "Giving up.\n");
+               pr_emerg("No coprocessor found and no math emulation present\n");
+               pr_emerg("Giving up\n");
                for (;;) ;
 #endif
                return;
@@ -86,7 +86,7 @@ static void __init check_fpu(void)
 
        boot_cpu_data.fdiv_bug = fdiv_bug;
        if (boot_cpu_data.fdiv_bug)
-               printk(KERN_WARNING "Hmm, FPU with FDIV bug.\n");
+               pr_warn("Hmm, FPU with FDIV bug\n");
 }
 
 static void __init check_hlt(void)
@@ -94,16 +94,16 @@ static void __init check_hlt(void)
        if (boot_cpu_data.x86 >= 5 || paravirt_enabled())
                return;
 
-       printk(KERN_INFO "Checking 'hlt' instruction... ");
+       pr_info("Checking 'hlt' instruction... ");
        if (!boot_cpu_data.hlt_works_ok) {
-               printk("disabled\n");
+               pr_cont("disabled\n");
                return;
        }
        halt();
        halt();
        halt();
        halt();
-       printk(KERN_CONT "OK.\n");
+       pr_cont("OK\n");
 }
 
 /*
@@ -116,7 +116,7 @@ static void __init check_popad(void)
 #ifndef CONFIG_X86_POPAD_OK
        int res, inp = (int) &res;
 
-       printk(KERN_INFO "Checking for popad bug... ");
+       pr_info("Checking for popad bug... ");
        __asm__ __volatile__(
          "movl $12345678,%%eax; movl $0,%%edi; pusha; popa; movl (%%edx,%%edi),%%ecx "
          : "=&a" (res)
@@ -127,9 +127,9 @@ static void __init check_popad(void)
         * CPU hard. Too bad.
         */
        if (res != 12345678)
-               printk(KERN_CONT "Buggy.\n");
+               pr_cont("Buggy\n");
        else
-               printk(KERN_CONT "OK.\n");
+               pr_cont("OK\n");
 #endif
 }
 
@@ -161,7 +161,7 @@ void __init check_bugs(void)
 {
        identify_boot_cpu();
 #ifndef CONFIG_SMP
-       printk(KERN_INFO "CPU: ");
+       pr_info("CPU: ");
        print_cpu_info(&boot_cpu_data);
 #endif
        check_config();
index 6b9333b429ba1910637bf29c63bbe0712064022e..5bbc082c47ad8d1fef9950c5dda873f1fdd5975c 100644 (file)
@@ -947,7 +947,7 @@ static void __cpuinit __print_cpu_msr(void)
                index_max = msr_range_array[i].max;
 
                for (index = index_min; index < index_max; index++) {
-                       if (rdmsrl_amd_safe(index, &val))
+                       if (rdmsrl_safe(index, &val))
                                continue;
                        printk(KERN_INFO " MSR%08x: %016llx\n", index, val);
                }
index da27c5d2168a74c29e3d1da16d108ef7017113c8..9473e8772fd19bba99ac568a2d7afda3af86aa6f 100644 (file)
@@ -7,6 +7,9 @@
  * Copyright 2008 Intel Corporation
  * Author: Andi Kleen
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/thread_info.h>
 #include <linux/capability.h>
 #include <linux/miscdevice.h>
@@ -210,7 +213,7 @@ static void drain_mcelog_buffer(void)
                                cpu_relax();
 
                                if (!m->finished && retries >= 4) {
-                                       pr_err("MCE: skipping error being logged currently!\n");
+                                       pr_err("skipping error being logged currently!\n");
                                        break;
                                }
                        }
@@ -1167,8 +1170,9 @@ int memory_failure(unsigned long pfn, int vector, int flags)
 {
        /* mce_severity() should not hand us an ACTION_REQUIRED error */
        BUG_ON(flags & MF_ACTION_REQUIRED);
-       printk(KERN_ERR "Uncorrected memory error in page 0x%lx ignored\n"
-               "Rebuild kernel with CONFIG_MEMORY_FAILURE=y for smarter handling\n", pfn);
+       pr_err("Uncorrected memory error in page 0x%lx ignored\n"
+              "Rebuild kernel with CONFIG_MEMORY_FAILURE=y for smarter handling\n",
+              pfn);
 
        return 0;
 }
@@ -1186,6 +1190,7 @@ void mce_notify_process(void)
 {
        unsigned long pfn;
        struct mce_info *mi = mce_find_info();
+       int flags = MF_ACTION_REQUIRED;
 
        if (!mi)
                mce_panic("Lost physical address for unconsumed uncorrectable error", NULL, NULL);
@@ -1200,8 +1205,9 @@ void mce_notify_process(void)
         * doomed. We still need to mark the page as poisoned and alert any
         * other users of the page.
         */
-       if (memory_failure(pfn, MCE_VECTOR, MF_ACTION_REQUIRED) < 0 ||
-                          mi->restartable == 0) {
+       if (!mi->restartable)
+               flags |= MF_MUST_KILL;
+       if (memory_failure(pfn, MCE_VECTOR, flags) < 0) {
                pr_err("Memory error not recovered");
                force_sig(SIGBUS, current);
        }
@@ -1358,11 +1364,10 @@ static int __cpuinit __mcheck_cpu_cap_init(void)
 
        b = cap & MCG_BANKCNT_MASK;
        if (!banks)
-               printk(KERN_INFO "mce: CPU supports %d MCE banks\n", b);
+               pr_info("CPU supports %d MCE banks\n", b);
 
        if (b > MAX_NR_BANKS) {
-               printk(KERN_WARNING
-                      "MCE: Using only %u machine check banks out of %u\n",
+               pr_warn("Using only %u machine check banks out of %u\n",
                        MAX_NR_BANKS, b);
                b = MAX_NR_BANKS;
        }
@@ -1419,7 +1424,7 @@ static void __mcheck_cpu_init_generic(void)
 static int __cpuinit __mcheck_cpu_apply_quirks(struct cpuinfo_x86 *c)
 {
        if (c->x86_vendor == X86_VENDOR_UNKNOWN) {
-               pr_info("MCE: unknown CPU type - not enabling MCE support.\n");
+               pr_info("unknown CPU type - not enabling MCE support\n");
                return -EOPNOTSUPP;
        }
 
@@ -1574,7 +1579,7 @@ static void __mcheck_cpu_init_timer(void)
 /* Handle unconfigured int18 (should never happen) */
 static void unexpected_machine_check(struct pt_regs *regs, long error_code)
 {
-       printk(KERN_ERR "CPU#%d: Unexpected int18 (Machine Check).\n",
+       pr_err("CPU#%d: Unexpected int18 (Machine Check)\n",
               smp_processor_id());
 }
 
@@ -1893,8 +1898,7 @@ static int __init mcheck_enable(char *str)
                        get_option(&str, &monarch_timeout);
                }
        } else {
-               printk(KERN_INFO "mce argument %s ignored. Please use /sys\n",
-                      str);
+               pr_info("mce argument %s ignored. Please use /sys\n", str);
                return 0;
        }
        return 1;
index f4873a64f46dcb2dac8db0c3585afecc642e70ee..671b95a2ffb5fd45381e59f1a3e1198f5a46e834 100644 (file)
@@ -1,15 +1,17 @@
 /*
- *  (c) 2005, 2006 Advanced Micro Devices, Inc.
+ *  (c) 2005-2012 Advanced Micro Devices, Inc.
  *  Your use of this code is subject to the terms and conditions of the
  *  GNU general public license version 2. See "COPYING" or
  *  http://www.gnu.org/licenses/gpl.html
  *
  *  Written by Jacob Shin - AMD, Inc.
  *
- *  Support : jacob.shin@amd.com
+ *  Support: borislav.petkov@amd.com
  *
  *  April 2006
  *     - added support for AMD Family 0x10 processors
+ *  May 2012
+ *     - major scrubbing
  *
  *  All MC4_MISCi registers are shared between multi-cores
  */
@@ -25,6 +27,7 @@
 #include <linux/cpu.h>
 #include <linux/smp.h>
 
+#include <asm/amd_nb.h>
 #include <asm/apic.h>
 #include <asm/idle.h>
 #include <asm/mce.h>
 #define MASK_BLKPTR_LO    0xFF000000
 #define MCG_XBLK_ADDR     0xC0000400
 
-struct threshold_block {
-       unsigned int            block;
-       unsigned int            bank;
-       unsigned int            cpu;
-       u32                     address;
-       u16                     interrupt_enable;
-       bool                    interrupt_capable;
-       u16                     threshold_limit;
-       struct kobject          kobj;
-       struct list_head        miscj;
+static const char * const th_names[] = {
+       "load_store",
+       "insn_fetch",
+       "combined_unit",
+       "",
+       "northbridge",
+       "execution_unit",
 };
 
-struct threshold_bank {
-       struct kobject          *kobj;
-       struct threshold_block  *blocks;
-       cpumask_var_t           cpus;
-};
 static DEFINE_PER_CPU(struct threshold_bank * [NR_BANKS], threshold_banks);
 
 static unsigned char shared_bank[NR_BANKS] = {
@@ -84,6 +79,26 @@ struct thresh_restart {
        u16                     old_limit;
 };
 
+static const char * const bank4_names(struct threshold_block *b)
+{
+       switch (b->address) {
+       /* MSR4_MISC0 */
+       case 0x00000413:
+               return "dram";
+
+       case 0xc0000408:
+               return "ht_links";
+
+       case 0xc0000409:
+               return "l3_cache";
+
+       default:
+               WARN(1, "Funny MSR: 0x%08x\n", b->address);
+               return "";
+       }
+};
+
+
 static bool lvt_interrupt_supported(unsigned int bank, u32 msr_high_bits)
 {
        /*
@@ -224,8 +239,6 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
 
                        if (!block)
                                per_cpu(bank_map, cpu) |= (1 << bank);
-                       if (shared_bank[bank] && c->cpu_core_id)
-                               break;
 
                        memset(&b, 0, sizeof(b));
                        b.cpu                   = cpu;
@@ -326,7 +339,7 @@ struct threshold_attr {
 #define SHOW_FIELDS(name)                                              \
 static ssize_t show_ ## name(struct threshold_block *b, char *buf)     \
 {                                                                      \
-       return sprintf(buf, "%lx\n", (unsigned long) b->name);          \
+       return sprintf(buf, "%lu\n", (unsigned long) b->name);          \
 }
 SHOW_FIELDS(interrupt_enable)
 SHOW_FIELDS(threshold_limit)
@@ -377,38 +390,21 @@ store_threshold_limit(struct threshold_block *b, const char *buf, size_t size)
        return size;
 }
 
-struct threshold_block_cross_cpu {
-       struct threshold_block  *tb;
-       long                    retval;
-};
-
-static void local_error_count_handler(void *_tbcc)
-{
-       struct threshold_block_cross_cpu *tbcc = _tbcc;
-       struct threshold_block *b = tbcc->tb;
-       u32 low, high;
-
-       rdmsr(b->address, low, high);
-       tbcc->retval = (high & 0xFFF) - (THRESHOLD_MAX - b->threshold_limit);
-}
-
 static ssize_t show_error_count(struct threshold_block *b, char *buf)
 {
-       struct threshold_block_cross_cpu tbcc = { .tb = b, };
+       u32 lo, hi;
 
-       smp_call_function_single(b->cpu, local_error_count_handler, &tbcc, 1);
-       return sprintf(buf, "%lx\n", tbcc.retval);
-}
+       rdmsr_on_cpu(b->cpu, b->address, &lo, &hi);
 
-static ssize_t store_error_count(struct threshold_block *b,
-                                const char *buf, size_t count)
-{
-       struct thresh_restart tr = { .b = b, .reset = 1, .old_limit = 0 };
-
-       smp_call_function_single(b->cpu, threshold_restart_bank, &tr, 1);
-       return 1;
+       return sprintf(buf, "%u\n", ((hi & THRESHOLD_MAX) -
+                                    (THRESHOLD_MAX - b->threshold_limit)));
 }
 
+static struct threshold_attr error_count = {
+       .attr = {.name = __stringify(error_count), .mode = 0444 },
+       .show = show_error_count,
+};
+
 #define RW_ATTR(val)                                                   \
 static struct threshold_attr val = {                                   \
        .attr   = {.name = __stringify(val), .mode = 0644 },            \
@@ -418,7 +414,6 @@ static struct threshold_attr val = {                                        \
 
 RW_ATTR(interrupt_enable);
 RW_ATTR(threshold_limit);
-RW_ATTR(error_count);
 
 static struct attribute *default_attrs[] = {
        &threshold_limit.attr,
@@ -517,7 +512,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
 
        err = kobject_init_and_add(&b->kobj, &threshold_ktype,
                                   per_cpu(threshold_banks, cpu)[bank]->kobj,
-                                  "misc%i", block);
+                                  (bank == 4 ? bank4_names(b) : th_names[bank]));
        if (err)
                goto out_free;
 recurse:
@@ -548,98 +543,91 @@ out_free:
        return err;
 }
 
-static __cpuinit long
-local_allocate_threshold_blocks(int cpu, unsigned int bank)
+static __cpuinit int __threshold_add_blocks(struct threshold_bank *b)
 {
-       return allocate_threshold_blocks(cpu, bank, 0,
-                                        MSR_IA32_MC0_MISC + bank * 4);
+       struct list_head *head = &b->blocks->miscj;
+       struct threshold_block *pos = NULL;
+       struct threshold_block *tmp = NULL;
+       int err = 0;
+
+       err = kobject_add(&b->blocks->kobj, b->kobj, b->blocks->kobj.name);
+       if (err)
+               return err;
+
+       list_for_each_entry_safe(pos, tmp, head, miscj) {
+
+               err = kobject_add(&pos->kobj, b->kobj, pos->kobj.name);
+               if (err) {
+                       list_for_each_entry_safe_reverse(pos, tmp, head, miscj)
+                               kobject_del(&pos->kobj);
+
+                       return err;
+               }
+       }
+       return err;
 }
 
-/* symlinks sibling shared banks to first core.  first core owns dir/files. */
 static __cpuinit int threshold_create_bank(unsigned int cpu, unsigned int bank)
 {
-       int i, err = 0;
-       struct threshold_bank *b = NULL;
        struct device *dev = per_cpu(mce_device, cpu);
-       char name[32];
-
-       sprintf(name, "threshold_bank%i", bank);
+       struct amd_northbridge *nb = NULL;
+       struct threshold_bank *b = NULL;
+       const char *name = th_names[bank];
+       int err = 0;
 
-#ifdef CONFIG_SMP
-       if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) {   /* symlink */
-               i = cpumask_first(cpu_llc_shared_mask(cpu));
+       if (shared_bank[bank]) {
 
-               /* first core not up yet */
-               if (cpu_data(i).cpu_core_id)
-                       goto out;
+               nb = node_to_amd_nb(amd_get_nb_id(cpu));
+               WARN_ON(!nb);
 
-               /* already linked */
-               if (per_cpu(threshold_banks, cpu)[bank])
-                       goto out;
+               /* threshold descriptor already initialized on this node? */
+               if (nb->bank4) {
+                       /* yes, use it */
+                       b = nb->bank4;
+                       err = kobject_add(b->kobj, &dev->kobj, name);
+                       if (err)
+                               goto out;
 
-               b = per_cpu(threshold_banks, i)[bank];
+                       per_cpu(threshold_banks, cpu)[bank] = b;
+                       atomic_inc(&b->cpus);
 
-               if (!b)
-                       goto out;
+                       err = __threshold_add_blocks(b);
 
-               err = sysfs_create_link(&dev->kobj, b->kobj, name);
-               if (err)
                        goto out;
-
-               cpumask_copy(b->cpus, cpu_llc_shared_mask(cpu));
-               per_cpu(threshold_banks, cpu)[bank] = b;
-
-               goto out;
+               }
        }
-#endif
 
        b = kzalloc(sizeof(struct threshold_bank), GFP_KERNEL);
        if (!b) {
                err = -ENOMEM;
                goto out;
        }
-       if (!zalloc_cpumask_var(&b->cpus, GFP_KERNEL)) {
-               kfree(b);
-               err = -ENOMEM;
-               goto out;
-       }
 
        b->kobj = kobject_create_and_add(name, &dev->kobj);
-       if (!b->kobj)
+       if (!b->kobj) {
+               err = -EINVAL;
                goto out_free;
-
-#ifndef CONFIG_SMP
-       cpumask_setall(b->cpus);
-#else
-       cpumask_set_cpu(cpu, b->cpus);
-#endif
+       }
 
        per_cpu(threshold_banks, cpu)[bank] = b;
 
-       err = local_allocate_threshold_blocks(cpu, bank);
-       if (err)
-               goto out_free;
-
-       for_each_cpu(i, b->cpus) {
-               if (i == cpu)
-                       continue;
+       if (shared_bank[bank]) {
+               atomic_set(&b->cpus, 1);
 
-               dev = per_cpu(mce_device, i);
-               if (dev)
-                       err = sysfs_create_link(&dev->kobj,b->kobj, name);
-               if (err)
-                       goto out;
-
-               per_cpu(threshold_banks, i)[bank] = b;
+               /* nb is already initialized, see above */
+               WARN_ON(nb->bank4);
+               nb->bank4 = b;
        }
 
-       goto out;
+       err = allocate_threshold_blocks(cpu, bank, 0,
+                                       MSR_IA32_MC0_MISC + bank * 4);
+       if (!err)
+               goto out;
 
-out_free:
-       per_cpu(threshold_banks, cpu)[bank] = NULL;
-       free_cpumask_var(b->cpus);
+ out_free:
        kfree(b);
-out:
+
+ out:
        return err;
 }
 
@@ -660,12 +648,6 @@ static __cpuinit int threshold_create_device(unsigned int cpu)
        return err;
 }
 
-/*
- * let's be hotplug friendly.
- * in case of multiple core processors, the first core always takes ownership
- *   of shared sysfs dir/files, and rest of the cores will be symlinked to it.
- */
-
 static void deallocate_threshold_block(unsigned int cpu,
                                                 unsigned int bank)
 {
@@ -686,41 +668,42 @@ static void deallocate_threshold_block(unsigned int cpu,
        per_cpu(threshold_banks, cpu)[bank]->blocks = NULL;
 }
 
+static void __threshold_remove_blocks(struct threshold_bank *b)
+{
+       struct threshold_block *pos = NULL;
+       struct threshold_block *tmp = NULL;
+
+       kobject_del(b->kobj);
+
+       list_for_each_entry_safe(pos, tmp, &b->blocks->miscj, miscj)
+               kobject_del(&pos->kobj);
+}
+
 static void threshold_remove_bank(unsigned int cpu, int bank)
 {
+       struct amd_northbridge *nb;
        struct threshold_bank *b;
-       struct device *dev;
-       char name[32];
-       int i = 0;
 
        b = per_cpu(threshold_banks, cpu)[bank];
        if (!b)
                return;
+
        if (!b->blocks)
                goto free_out;
 
-       sprintf(name, "threshold_bank%i", bank);
-
-#ifdef CONFIG_SMP
-       /* sibling symlink */
-       if (shared_bank[bank] && b->blocks->cpu != cpu) {
-               dev = per_cpu(mce_device, cpu);
-               sysfs_remove_link(&dev->kobj, name);
-               per_cpu(threshold_banks, cpu)[bank] = NULL;
-
-               return;
-       }
-#endif
-
-       /* remove all sibling symlinks before unregistering */
-       for_each_cpu(i, b->cpus) {
-               if (i == cpu)
-                       continue;
-
-               dev = per_cpu(mce_device, i);
-               if (dev)
-                       sysfs_remove_link(&dev->kobj, name);
-               per_cpu(threshold_banks, i)[bank] = NULL;
+       if (shared_bank[bank]) {
+               if (!atomic_dec_and_test(&b->cpus)) {
+                       __threshold_remove_blocks(b);
+                       per_cpu(threshold_banks, cpu)[bank] = NULL;
+                       return;
+               } else {
+                       /*
+                        * the last CPU on this node using the shared bank is
+                        * going away, remove that bank now.
+                        */
+                       nb = node_to_amd_nb(amd_get_nb_id(cpu));
+                       nb->bank4 = NULL;
+               }
        }
 
        deallocate_threshold_block(cpu, bank);
@@ -728,7 +711,6 @@ static void threshold_remove_bank(unsigned int cpu, int bank)
 free_out:
        kobject_del(b->kobj);
        kobject_put(b->kobj);
-       free_cpumask_var(b->cpus);
        kfree(b);
        per_cpu(threshold_banks, cpu)[bank] = NULL;
 }
index bdda2e6c673bf71afb30ed670071a9d02dbdcbfa..35ffda5d0727d19b11cccccdde0e0d461b9e15ee 100644 (file)
@@ -258,11 +258,11 @@ range_to_mtrr(unsigned int reg, unsigned long range_startk,
 
                /* Compute the maximum size with which we can make a range: */
                if (range_startk)
-                       max_align = ffs(range_startk) - 1;
+                       max_align = __ffs(range_startk);
                else
-                       max_align = 32;
+                       max_align = BITS_PER_LONG - 1;
 
-               align = fls(range_sizek) - 1;
+               align = __fls(range_sizek);
                if (align > max_align)
                        align = max_align;
 
index 75772ae6c65f81cbc2268120b1fdcf3bad80028f..e9fe907cd2495c9ad6a687f9b45a49c39a5ebd26 100644 (file)
@@ -361,11 +361,7 @@ static void __init print_mtrr_state(void)
        }
        pr_debug("MTRR variable ranges %sabled:\n",
                 mtrr_state.enabled & 2 ? "en" : "dis");
-       if (size_or_mask & 0xffffffffUL)
-               high_width = ffs(size_or_mask & 0xffffffffUL) - 1;
-       else
-               high_width = ffs(size_or_mask>>32) + 32 - 1;
-       high_width = (high_width - (32 - PAGE_SHIFT) + 3) / 4;
+       high_width = (__ffs64(size_or_mask) - (32 - PAGE_SHIFT) + 3) / 4;
 
        for (i = 0; i < num_var_ranges; ++i) {
                if (mtrr_state.var_ranges[i].mask_lo & (1 << 11))
index c4706cf9c011d8fd068d205ed0b669142c112400..29557aa06dda6a724add1d6be6f7744f2d801d34 100644 (file)
 
 #include "perf_event.h"
 
-#if 0
-#undef wrmsrl
-#define wrmsrl(msr, val)                                       \
-do {                                                           \
-       trace_printk("wrmsrl(%lx, %lx)\n", (unsigned long)(msr),\
-                       (unsigned long)(val));                  \
-       native_write_msr((msr), (u32)((u64)(val)),              \
-                       (u32)((u64)(val) >> 32));               \
-} while (0)
-#endif
-
 struct x86_pmu x86_pmu __read_mostly;
 
 DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
@@ -74,7 +63,7 @@ u64 x86_perf_event_update(struct perf_event *event)
        int idx = hwc->idx;
        s64 delta;
 
-       if (idx == X86_PMC_IDX_FIXED_BTS)
+       if (idx == INTEL_PMC_IDX_FIXED_BTS)
                return 0;
 
        /*
@@ -86,7 +75,7 @@ u64 x86_perf_event_update(struct perf_event *event)
         */
 again:
        prev_raw_count = local64_read(&hwc->prev_count);
-       rdmsrl(hwc->event_base, new_raw_count);
+       rdpmcl(hwc->event_base_rdpmc, new_raw_count);
 
        if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
                                        new_raw_count) != prev_raw_count)
@@ -189,7 +178,7 @@ static void release_pmc_hardware(void) {}
 
 static bool check_hw_exists(void)
 {
-       u64 val, val_new = 0;
+       u64 val, val_new = ~0;
        int i, reg, ret = 0;
 
        /*
@@ -222,8 +211,9 @@ static bool check_hw_exists(void)
         * that don't trap on the MSR access and always return 0s.
         */
        val = 0xabcdUL;
-       ret = checking_wrmsrl(x86_pmu_event_addr(0), val);
-       ret |= rdmsrl_safe(x86_pmu_event_addr(0), &val_new);
+       reg = x86_pmu_event_addr(0);
+       ret = wrmsrl_safe(reg, val);
+       ret |= rdmsrl_safe(reg, &val_new);
        if (ret || val != val_new)
                goto msr_fail;
 
@@ -240,6 +230,7 @@ bios_fail:
 
 msr_fail:
        printk(KERN_CONT "Broken PMU hardware detected, using software events only.\n");
+       printk(KERN_ERR "Failed to access perfctr msr (MSR %x is %Lx)\n", reg, val_new);
 
        return false;
 }
@@ -388,7 +379,7 @@ int x86_pmu_hw_config(struct perf_event *event)
                int precise = 0;
 
                /* Support for constant skid */
-               if (x86_pmu.pebs_active) {
+               if (x86_pmu.pebs_active && !x86_pmu.pebs_broken) {
                        precise++;
 
                        /* Support for IP fixup */
@@ -637,8 +628,8 @@ static bool __perf_sched_find_counter(struct perf_sched *sched)
        c = sched->constraints[sched->state.event];
 
        /* Prefer fixed purpose counters */
-       if (x86_pmu.num_counters_fixed) {
-               idx = X86_PMC_IDX_FIXED;
+       if (c->idxmsk64 & (~0ULL << INTEL_PMC_IDX_FIXED)) {
+               idx = INTEL_PMC_IDX_FIXED;
                for_each_set_bit_from(idx, c->idxmsk, X86_PMC_IDX_MAX) {
                        if (!__test_and_set_bit(idx, sched->state.used))
                                goto done;
@@ -646,7 +637,7 @@ static bool __perf_sched_find_counter(struct perf_sched *sched)
        }
        /* Grab the first unused counter starting with idx */
        idx = sched->state.counter;
-       for_each_set_bit_from(idx, c->idxmsk, X86_PMC_IDX_FIXED) {
+       for_each_set_bit_from(idx, c->idxmsk, INTEL_PMC_IDX_FIXED) {
                if (!__test_and_set_bit(idx, sched->state.used))
                        goto done;
        }
@@ -704,8 +695,8 @@ static bool perf_sched_next_event(struct perf_sched *sched)
 /*
  * Assign a counter for each event.
  */
-static int perf_assign_events(struct event_constraint **constraints, int n,
-                             int wmin, int wmax, int *assign)
+int perf_assign_events(struct event_constraint **constraints, int n,
+                       int wmin, int wmax, int *assign)
 {
        struct perf_sched sched;
 
@@ -824,15 +815,17 @@ static inline void x86_assign_hw_event(struct perf_event *event,
        hwc->last_cpu = smp_processor_id();
        hwc->last_tag = ++cpuc->tags[i];
 
-       if (hwc->idx == X86_PMC_IDX_FIXED_BTS) {
+       if (hwc->idx == INTEL_PMC_IDX_FIXED_BTS) {
                hwc->config_base = 0;
                hwc->event_base = 0;
-       } else if (hwc->idx >= X86_PMC_IDX_FIXED) {
+       } else if (hwc->idx >= INTEL_PMC_IDX_FIXED) {
                hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
-               hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0 + (hwc->idx - X86_PMC_IDX_FIXED);
+               hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0 + (hwc->idx - INTEL_PMC_IDX_FIXED);
+               hwc->event_base_rdpmc = (hwc->idx - INTEL_PMC_IDX_FIXED) | 1<<30;
        } else {
                hwc->config_base = x86_pmu_config_addr(hwc->idx);
                hwc->event_base  = x86_pmu_event_addr(hwc->idx);
+               hwc->event_base_rdpmc = hwc->idx;
        }
 }
 
@@ -930,7 +923,7 @@ int x86_perf_event_set_period(struct perf_event *event)
        s64 period = hwc->sample_period;
        int ret = 0, idx = hwc->idx;
 
-       if (idx == X86_PMC_IDX_FIXED_BTS)
+       if (idx == INTEL_PMC_IDX_FIXED_BTS)
                return 0;
 
        /*
@@ -1316,7 +1309,6 @@ static struct attribute_group x86_pmu_format_group = {
 static int __init init_hw_perf_events(void)
 {
        struct x86_pmu_quirk *quirk;
-       struct event_constraint *c;
        int err;
 
        pr_info("Performance Events: ");
@@ -1347,21 +1339,8 @@ static int __init init_hw_perf_events(void)
        for (quirk = x86_pmu.quirks; quirk; quirk = quirk->next)
                quirk->func();
 
-       if (x86_pmu.num_counters > X86_PMC_MAX_GENERIC) {
-               WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!",
-                    x86_pmu.num_counters, X86_PMC_MAX_GENERIC);
-               x86_pmu.num_counters = X86_PMC_MAX_GENERIC;
-       }
-       x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
-
-       if (x86_pmu.num_counters_fixed > X86_PMC_MAX_FIXED) {
-               WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
-                    x86_pmu.num_counters_fixed, X86_PMC_MAX_FIXED);
-               x86_pmu.num_counters_fixed = X86_PMC_MAX_FIXED;
-       }
-
-       x86_pmu.intel_ctrl |=
-               ((1LL << x86_pmu.num_counters_fixed)-1) << X86_PMC_IDX_FIXED;
+       if (!x86_pmu.intel_ctrl)
+               x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
 
        perf_events_lapic_init();
        register_nmi_handler(NMI_LOCAL, perf_event_nmi_handler, 0, "PMI");
@@ -1370,22 +1349,6 @@ static int __init init_hw_perf_events(void)
                __EVENT_CONSTRAINT(0, (1ULL << x86_pmu.num_counters) - 1,
                                   0, x86_pmu.num_counters, 0);
 
-       if (x86_pmu.event_constraints) {
-               /*
-                * event on fixed counter2 (REF_CYCLES) only works on this
-                * counter, so do not extend mask to generic counters
-                */
-               for_each_event_constraint(c, x86_pmu.event_constraints) {
-                       if (c->cmask != X86_RAW_EVENT_MASK
-                           || c->idxmsk64 == X86_PMC_MSK_FIXED_REF_CYCLES) {
-                               continue;
-                       }
-
-                       c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1;
-                       c->weight += x86_pmu.num_counters;
-               }
-       }
-
        x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
        x86_pmu_format_group.attrs = x86_pmu.format_attrs;
 
@@ -1620,8 +1583,8 @@ static int x86_pmu_event_idx(struct perf_event *event)
        if (!x86_pmu.attr_rdpmc)
                return 0;
 
-       if (x86_pmu.num_counters_fixed && idx >= X86_PMC_IDX_FIXED) {
-               idx -= X86_PMC_IDX_FIXED;
+       if (x86_pmu.num_counters_fixed && idx >= INTEL_PMC_IDX_FIXED) {
+               idx -= INTEL_PMC_IDX_FIXED;
                idx |= 1 << 30;
        }
 
@@ -1649,7 +1612,12 @@ static ssize_t set_attr_rdpmc(struct device *cdev,
                              struct device_attribute *attr,
                              const char *buf, size_t count)
 {
-       unsigned long val = simple_strtoul(buf, NULL, 0);
+       unsigned long val;
+       ssize_t ret;
+
+       ret = kstrtoul(buf, 0, &val);
+       if (ret)
+               return ret;
 
        if (!!val != !!x86_pmu.attr_rdpmc) {
                x86_pmu.attr_rdpmc = !!val;
@@ -1682,13 +1650,20 @@ static void x86_pmu_flush_branch_stack(void)
                x86_pmu.flush_branch_stack();
 }
 
+void perf_check_microcode(void)
+{
+       if (x86_pmu.check_microcode)
+               x86_pmu.check_microcode();
+}
+EXPORT_SYMBOL_GPL(perf_check_microcode);
+
 static struct pmu pmu = {
        .pmu_enable             = x86_pmu_enable,
        .pmu_disable            = x86_pmu_disable,
 
-       .attr_groups    = x86_pmu_attr_groups,
+       .attr_groups            = x86_pmu_attr_groups,
 
-       .event_init     = x86_pmu_event_init,
+       .event_init             = x86_pmu_event_init,
 
        .add                    = x86_pmu_add,
        .del                    = x86_pmu_del,
@@ -1696,11 +1671,11 @@ static struct pmu pmu = {
        .stop                   = x86_pmu_stop,
        .read                   = x86_pmu_read,
 
-       .start_txn      = x86_pmu_start_txn,
-       .cancel_txn     = x86_pmu_cancel_txn,
-       .commit_txn     = x86_pmu_commit_txn,
+       .start_txn              = x86_pmu_start_txn,
+       .cancel_txn             = x86_pmu_cancel_txn,
+       .commit_txn             = x86_pmu_commit_txn,
 
-       .event_idx      = x86_pmu_event_idx,
+       .event_idx              = x86_pmu_event_idx,
        .flush_branch_stack     = x86_pmu_flush_branch_stack,
 };
 
@@ -1863,7 +1838,7 @@ unsigned long perf_misc_flags(struct pt_regs *regs)
                else
                        misc |= PERF_RECORD_MISC_GUEST_KERNEL;
        } else {
-               if (user_mode(regs))
+               if (!kernel_ip(regs->ip))
                        misc |= PERF_RECORD_MISC_USER;
                else
                        misc |= PERF_RECORD_MISC_KERNEL;
index 7241e2fc3c17c87b766c35f8d412b8692436b825..a15df4be151fc924e3cf8a9b25ab18c991c0b58c 100644 (file)
 
 #include <linux/perf_event.h>
 
+#if 0
+#undef wrmsrl
+#define wrmsrl(msr, val)                                               \
+do {                                                                   \
+       unsigned int _msr = (msr);                                      \
+       u64 _val = (val);                                               \
+       trace_printk("wrmsrl(%x, %Lx)\n", (unsigned int)(_msr),         \
+                       (unsigned long long)(_val));                    \
+       native_write_msr((_msr), (u32)(_val), (u32)(_val >> 32));       \
+} while (0)
+#endif
+
 /*
  *          |   NHM/WSM    |      SNB     |
  * register -------------------------------
@@ -57,7 +69,7 @@ struct amd_nb {
 };
 
 /* The maximal number of PEBS events: */
-#define MAX_PEBS_EVENTS                4
+#define MAX_PEBS_EVENTS                8
 
 /*
  * A debug store configuration.
@@ -349,6 +361,8 @@ struct x86_pmu {
        void            (*cpu_starting)(int cpu);
        void            (*cpu_dying)(int cpu);
        void            (*cpu_dead)(int cpu);
+
+       void            (*check_microcode)(void);
        void            (*flush_branch_stack)(void);
 
        /*
@@ -360,12 +374,16 @@ struct x86_pmu {
        /*
         * Intel DebugStore bits
         */
-       int             bts, pebs;
-       int             bts_active, pebs_active;
+       int             bts             :1,
+                       bts_active      :1,
+                       pebs            :1,
+                       pebs_active     :1,
+                       pebs_broken     :1;
        int             pebs_record_size;
        void            (*drain_pebs)(struct pt_regs *regs);
        struct event_constraint *pebs_constraints;
        void            (*pebs_aliases)(struct perf_event *event);
+       int             max_pebs_events;
 
        /*
         * Intel LBR
@@ -468,6 +486,8 @@ static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
 
 void x86_pmu_enable_all(int added);
 
+int perf_assign_events(struct event_constraint **constraints, int n,
+                       int wmin, int wmax, int *assign);
 int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign);
 
 void x86_pmu_stop(struct perf_event *event, int flags);
index 11a4eb9131d5cbddc70ca663ab4c3eb27add8143..4528ae7b6ec4c96aaeb9822b3ea82bad59c4fc7a 100644 (file)
@@ -366,7 +366,7 @@ static void amd_pmu_cpu_starting(int cpu)
 
        cpuc->perf_ctr_virt_mask = AMD_PERFMON_EVENTSEL_HOSTONLY;
 
-       if (boot_cpu_data.x86_max_cores < 2 || boot_cpu_data.x86 == 0x15)
+       if (boot_cpu_data.x86_max_cores < 2)
                return;
 
        nb_id = amd_get_nb_id(cpu);
@@ -422,35 +422,6 @@ static struct attribute *amd_format_attr[] = {
        NULL,
 };
 
-static __initconst const struct x86_pmu amd_pmu = {
-       .name                   = "AMD",
-       .handle_irq             = x86_pmu_handle_irq,
-       .disable_all            = x86_pmu_disable_all,
-       .enable_all             = x86_pmu_enable_all,
-       .enable                 = x86_pmu_enable_event,
-       .disable                = x86_pmu_disable_event,
-       .hw_config              = amd_pmu_hw_config,
-       .schedule_events        = x86_schedule_events,
-       .eventsel               = MSR_K7_EVNTSEL0,
-       .perfctr                = MSR_K7_PERFCTR0,
-       .event_map              = amd_pmu_event_map,
-       .max_events             = ARRAY_SIZE(amd_perfmon_event_map),
-       .num_counters           = AMD64_NUM_COUNTERS,
-       .cntval_bits            = 48,
-       .cntval_mask            = (1ULL << 48) - 1,
-       .apic                   = 1,
-       /* use highest bit to detect overflow */
-       .max_period             = (1ULL << 47) - 1,
-       .get_event_constraints  = amd_get_event_constraints,
-       .put_event_constraints  = amd_put_event_constraints,
-
-       .format_attrs           = amd_format_attr,
-
-       .cpu_prepare            = amd_pmu_cpu_prepare,
-       .cpu_starting           = amd_pmu_cpu_starting,
-       .cpu_dead               = amd_pmu_cpu_dead,
-};
-
 /* AMD Family 15h */
 
 #define AMD_EVENT_TYPE_MASK    0x000000F0ULL
@@ -597,8 +568,8 @@ amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *ev
        }
 }
 
-static __initconst const struct x86_pmu amd_pmu_f15h = {
-       .name                   = "AMD Family 15h",
+static __initconst const struct x86_pmu amd_pmu = {
+       .name                   = "AMD",
        .handle_irq             = x86_pmu_handle_irq,
        .disable_all            = x86_pmu_disable_all,
        .enable_all             = x86_pmu_enable_all,
@@ -606,50 +577,68 @@ static __initconst const struct x86_pmu amd_pmu_f15h = {
        .disable                = x86_pmu_disable_event,
        .hw_config              = amd_pmu_hw_config,
        .schedule_events        = x86_schedule_events,
-       .eventsel               = MSR_F15H_PERF_CTL,
-       .perfctr                = MSR_F15H_PERF_CTR,
+       .eventsel               = MSR_K7_EVNTSEL0,
+       .perfctr                = MSR_K7_PERFCTR0,
        .event_map              = amd_pmu_event_map,
        .max_events             = ARRAY_SIZE(amd_perfmon_event_map),
-       .num_counters           = AMD64_NUM_COUNTERS_F15H,
+       .num_counters           = AMD64_NUM_COUNTERS,
        .cntval_bits            = 48,
        .cntval_mask            = (1ULL << 48) - 1,
        .apic                   = 1,
        /* use highest bit to detect overflow */
        .max_period             = (1ULL << 47) - 1,
-       .get_event_constraints  = amd_get_event_constraints_f15h,
-       /* nortbridge counters not yet implemented: */
-#if 0
+       .get_event_constraints  = amd_get_event_constraints,
        .put_event_constraints  = amd_put_event_constraints,
 
+       .format_attrs           = amd_format_attr,
+
        .cpu_prepare            = amd_pmu_cpu_prepare,
-       .cpu_dead               = amd_pmu_cpu_dead,
-#endif
        .cpu_starting           = amd_pmu_cpu_starting,
-       .format_attrs           = amd_format_attr,
+       .cpu_dead               = amd_pmu_cpu_dead,
 };
 
+static int setup_event_constraints(void)
+{
+       if (boot_cpu_data.x86 >= 0x15)
+               x86_pmu.get_event_constraints = amd_get_event_constraints_f15h;
+       return 0;
+}
+
+static int setup_perfctr_core(void)
+{
+       if (!cpu_has_perfctr_core) {
+               WARN(x86_pmu.get_event_constraints == amd_get_event_constraints_f15h,
+                    KERN_ERR "Odd, counter constraints enabled but no core perfctrs detected!");
+               return -ENODEV;
+       }
+
+       WARN(x86_pmu.get_event_constraints == amd_get_event_constraints,
+            KERN_ERR "hw perf events core counters need constraints handler!");
+
+       /*
+        * If core performance counter extensions exists, we must use
+        * MSR_F15H_PERF_CTL/MSR_F15H_PERF_CTR msrs. See also
+        * x86_pmu_addr_offset().
+        */
+       x86_pmu.eventsel        = MSR_F15H_PERF_CTL;
+       x86_pmu.perfctr         = MSR_F15H_PERF_CTR;
+       x86_pmu.num_counters    = AMD64_NUM_COUNTERS_CORE;
+
+       printk(KERN_INFO "perf: AMD core performance counters detected\n");
+
+       return 0;
+}
+
 __init int amd_pmu_init(void)
 {
        /* Performance-monitoring supported from K7 and later: */
        if (boot_cpu_data.x86 < 6)
                return -ENODEV;
 
-       /*
-        * If core performance counter extensions exists, it must be
-        * family 15h, otherwise fail. See x86_pmu_addr_offset().
-        */
-       switch (boot_cpu_data.x86) {
-       case 0x15:
-               if (!cpu_has_perfctr_core)
-                       return -ENODEV;
-               x86_pmu = amd_pmu_f15h;
-               break;
-       default:
-               if (cpu_has_perfctr_core)
-                       return -ENODEV;
-               x86_pmu = amd_pmu;
-               break;
-       }
+       x86_pmu = amd_pmu;
+
+       setup_event_constraints();
+       setup_perfctr_core();
 
        /* Events are common for all AMDs */
        memcpy(hw_cache_event_ids, amd_hw_cache_event_ids,
index 187c294bc6583424e8613df62a883740ab8fca1a..7a8b9d0abcaa33c754481cf38c3f26c366f701c9 100644 (file)
@@ -5,6 +5,8 @@
  * among events on a single PMU.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/stddef.h>
 #include <linux/types.h>
 #include <linux/init.h>
  */
 static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly =
 {
-  [PERF_COUNT_HW_CPU_CYCLES]           = 0x003c,
-  [PERF_COUNT_HW_INSTRUCTIONS]         = 0x00c0,
-  [PERF_COUNT_HW_CACHE_REFERENCES]     = 0x4f2e,
-  [PERF_COUNT_HW_CACHE_MISSES]         = 0x412e,
-  [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]  = 0x00c4,
-  [PERF_COUNT_HW_BRANCH_MISSES]                = 0x00c5,
-  [PERF_COUNT_HW_BUS_CYCLES]           = 0x013c,
-  [PERF_COUNT_HW_REF_CPU_CYCLES]       = 0x0300, /* pseudo-encoding */
+       [PERF_COUNT_HW_CPU_CYCLES]              = 0x003c,
+       [PERF_COUNT_HW_INSTRUCTIONS]            = 0x00c0,
+       [PERF_COUNT_HW_CACHE_REFERENCES]        = 0x4f2e,
+       [PERF_COUNT_HW_CACHE_MISSES]            = 0x412e,
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS]     = 0x00c4,
+       [PERF_COUNT_HW_BRANCH_MISSES]           = 0x00c5,
+       [PERF_COUNT_HW_BUS_CYCLES]              = 0x013c,
+       [PERF_COUNT_HW_REF_CPU_CYCLES]          = 0x0300, /* pseudo-encoding */
 };
 
 static struct event_constraint intel_core_event_constraints[] __read_mostly =
@@ -747,7 +749,7 @@ static void intel_pmu_disable_all(void)
 
        wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL, 0);
 
-       if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask))
+       if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask))
                intel_pmu_disable_bts();
 
        intel_pmu_pebs_disable_all();
@@ -763,9 +765,9 @@ static void intel_pmu_enable_all(int added)
        wrmsrl(MSR_CORE_PERF_GLOBAL_CTRL,
                        x86_pmu.intel_ctrl & ~cpuc->intel_ctrl_guest_mask);
 
-       if (test_bit(X86_PMC_IDX_FIXED_BTS, cpuc->active_mask)) {
+       if (test_bit(INTEL_PMC_IDX_FIXED_BTS, cpuc->active_mask)) {
                struct perf_event *event =
-                       cpuc->events[X86_PMC_IDX_FIXED_BTS];
+                       cpuc->events[INTEL_PMC_IDX_FIXED_BTS];
 
                if (WARN_ON_ONCE(!event))
                        return;
@@ -871,7 +873,7 @@ static inline void intel_pmu_ack_status(u64 ack)
 
 static void intel_pmu_disable_fixed(struct hw_perf_event *hwc)
 {
-       int idx = hwc->idx - X86_PMC_IDX_FIXED;
+       int idx = hwc->idx - INTEL_PMC_IDX_FIXED;
        u64 ctrl_val, mask;
 
        mask = 0xfULL << (idx * 4);
@@ -886,7 +888,7 @@ static void intel_pmu_disable_event(struct perf_event *event)
        struct hw_perf_event *hwc = &event->hw;
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
-       if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) {
+       if (unlikely(hwc->idx == INTEL_PMC_IDX_FIXED_BTS)) {
                intel_pmu_disable_bts();
                intel_pmu_drain_bts_buffer();
                return;
@@ -915,7 +917,7 @@ static void intel_pmu_disable_event(struct perf_event *event)
 
 static void intel_pmu_enable_fixed(struct hw_perf_event *hwc)
 {
-       int idx = hwc->idx - X86_PMC_IDX_FIXED;
+       int idx = hwc->idx - INTEL_PMC_IDX_FIXED;
        u64 ctrl_val, bits, mask;
 
        /*
@@ -949,7 +951,7 @@ static void intel_pmu_enable_event(struct perf_event *event)
        struct hw_perf_event *hwc = &event->hw;
        struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 
-       if (unlikely(hwc->idx == X86_PMC_IDX_FIXED_BTS)) {
+       if (unlikely(hwc->idx == INTEL_PMC_IDX_FIXED_BTS)) {
                if (!__this_cpu_read(cpu_hw_events.enabled))
                        return;
 
@@ -1000,14 +1002,14 @@ static void intel_pmu_reset(void)
 
        local_irq_save(flags);
 
-       printk("clearing PMU state on CPU#%d\n", smp_processor_id());
+       pr_info("clearing PMU state on CPU#%d\n", smp_processor_id());
 
        for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-               checking_wrmsrl(x86_pmu_config_addr(idx), 0ull);
-               checking_wrmsrl(x86_pmu_event_addr(idx),  0ull);
+               wrmsrl_safe(x86_pmu_config_addr(idx), 0ull);
+               wrmsrl_safe(x86_pmu_event_addr(idx),  0ull);
        }
        for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++)
-               checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull);
+               wrmsrl_safe(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull);
 
        if (ds)
                ds->bts_index = ds->bts_buffer_base;
@@ -1707,16 +1709,61 @@ static __init void intel_clovertown_quirk(void)
         * But taken together it might just make sense to not enable PEBS on
         * these chips.
         */
-       printk(KERN_WARNING "PEBS disabled due to CPU errata.\n");
+       pr_warn("PEBS disabled due to CPU errata\n");
        x86_pmu.pebs = 0;
        x86_pmu.pebs_constraints = NULL;
 }
 
+static int intel_snb_pebs_broken(int cpu)
+{
+       u32 rev = UINT_MAX; /* default to broken for unknown models */
+
+       switch (cpu_data(cpu).x86_model) {
+       case 42: /* SNB */
+               rev = 0x28;
+               break;
+
+       case 45: /* SNB-EP */
+               switch (cpu_data(cpu).x86_mask) {
+               case 6: rev = 0x618; break;
+               case 7: rev = 0x70c; break;
+               }
+       }
+
+       return (cpu_data(cpu).microcode < rev);
+}
+
+static void intel_snb_check_microcode(void)
+{
+       int pebs_broken = 0;
+       int cpu;
+
+       get_online_cpus();
+       for_each_online_cpu(cpu) {
+               if ((pebs_broken = intel_snb_pebs_broken(cpu)))
+                       break;
+       }
+       put_online_cpus();
+
+       if (pebs_broken == x86_pmu.pebs_broken)
+               return;
+
+       /*
+        * Serialized by the microcode lock..
+        */
+       if (x86_pmu.pebs_broken) {
+               pr_info("PEBS enabled due to microcode update\n");
+               x86_pmu.pebs_broken = 0;
+       } else {
+               pr_info("PEBS disabled due to CPU errata, please upgrade microcode\n");
+               x86_pmu.pebs_broken = 1;
+       }
+}
+
 static __init void intel_sandybridge_quirk(void)
 {
-       printk(KERN_WARNING "PEBS disabled due to CPU errata.\n");
-       x86_pmu.pebs = 0;
-       x86_pmu.pebs_constraints = NULL;
+       x86_pmu.check_microcode = intel_snb_check_microcode;
+       intel_snb_check_microcode();
 }
 
 static const struct { int id; char *name; } intel_arch_events_map[] __initconst = {
@@ -1736,8 +1783,8 @@ static __init void intel_arch_events_quirk(void)
        /* disable event that reported as not presend by cpuid */
        for_each_set_bit(bit, x86_pmu.events_mask, ARRAY_SIZE(intel_arch_events_map)) {
                intel_perfmon_event_map[intel_arch_events_map[bit].id] = 0;
-               printk(KERN_WARNING "CPUID marked event: \'%s\' unavailable\n",
-                               intel_arch_events_map[bit].name);
+               pr_warn("CPUID marked event: \'%s\' unavailable\n",
+                       intel_arch_events_map[bit].name);
        }
 }
 
@@ -1756,7 +1803,7 @@ static __init void intel_nehalem_quirk(void)
                intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89;
                ebx.split.no_branch_misses_retired = 0;
                x86_pmu.events_maskl = ebx.full;
-               printk(KERN_INFO "CPU erratum AAJ80 worked around\n");
+               pr_info("CPU erratum AAJ80 worked around\n");
        }
 }
 
@@ -1765,6 +1812,7 @@ __init int intel_pmu_init(void)
        union cpuid10_edx edx;
        union cpuid10_eax eax;
        union cpuid10_ebx ebx;
+       struct event_constraint *c;
        unsigned int unused;
        int version;
 
@@ -1800,6 +1848,8 @@ __init int intel_pmu_init(void)
        x86_pmu.events_maskl            = ebx.full;
        x86_pmu.events_mask_len         = eax.split.mask_length;
 
+       x86_pmu.max_pebs_events         = min_t(unsigned, MAX_PEBS_EVENTS, x86_pmu.num_counters);
+
        /*
         * Quirk: v2 perfmon does not report fixed-purpose events, so
         * assume at least 3 events:
@@ -1951,5 +2001,37 @@ __init int intel_pmu_init(void)
                }
        }
 
+       if (x86_pmu.num_counters > INTEL_PMC_MAX_GENERIC) {
+               WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!",
+                    x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC);
+               x86_pmu.num_counters = INTEL_PMC_MAX_GENERIC;
+       }
+       x86_pmu.intel_ctrl = (1 << x86_pmu.num_counters) - 1;
+
+       if (x86_pmu.num_counters_fixed > INTEL_PMC_MAX_FIXED) {
+               WARN(1, KERN_ERR "hw perf events fixed %d > max(%d), clipping!",
+                    x86_pmu.num_counters_fixed, INTEL_PMC_MAX_FIXED);
+               x86_pmu.num_counters_fixed = INTEL_PMC_MAX_FIXED;
+       }
+
+       x86_pmu.intel_ctrl |=
+               ((1LL << x86_pmu.num_counters_fixed)-1) << INTEL_PMC_IDX_FIXED;
+
+       if (x86_pmu.event_constraints) {
+               /*
+                * event on fixed counter2 (REF_CYCLES) only works on this
+                * counter, so do not extend mask to generic counters
+                */
+               for_each_event_constraint(c, x86_pmu.event_constraints) {
+                       if (c->cmask != X86_RAW_EVENT_MASK
+                           || c->idxmsk64 == INTEL_PMC_MSK_FIXED_REF_CYCLES) {
+                               continue;
+                       }
+
+                       c->idxmsk64 |= (1ULL << x86_pmu.num_counters) - 1;
+                       c->weight += x86_pmu.num_counters;
+               }
+       }
+
        return 0;
 }
index 35e2192df9f4ae078ae8ecff742f72f30881816b..629ae0b7ad901c88706716966b1fd71415debe19 100644 (file)
@@ -248,7 +248,7 @@ void reserve_ds_buffers(void)
  */
 
 struct event_constraint bts_constraint =
-       EVENT_CONSTRAINT(0, 1ULL << X86_PMC_IDX_FIXED_BTS, 0);
+       EVENT_CONSTRAINT(0, 1ULL << INTEL_PMC_IDX_FIXED_BTS, 0);
 
 void intel_pmu_enable_bts(u64 config)
 {
@@ -295,7 +295,7 @@ int intel_pmu_drain_bts_buffer(void)
                u64     to;
                u64     flags;
        };
-       struct perf_event *event = cpuc->events[X86_PMC_IDX_FIXED_BTS];
+       struct perf_event *event = cpuc->events[INTEL_PMC_IDX_FIXED_BTS];
        struct bts_record *at, *top;
        struct perf_output_handle handle;
        struct perf_event_header header;
@@ -620,7 +620,7 @@ static void intel_pmu_drain_pebs_core(struct pt_regs *iregs)
         * Should not happen, we program the threshold at 1 and do not
         * set a reset value.
         */
-       WARN_ON_ONCE(n > 1);
+       WARN_ONCE(n > 1, "bad leftover pebs %d\n", n);
        at += n - 1;
 
        __intel_pmu_pebs_event(event, iregs, at);
@@ -651,10 +651,10 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
         * Should not happen, we program the threshold at 1 and do not
         * set a reset value.
         */
-       WARN_ON_ONCE(n > MAX_PEBS_EVENTS);
+       WARN_ONCE(n > x86_pmu.max_pebs_events, "Unexpected number of pebs records %d\n", n);
 
        for ( ; at < top; at++) {
-               for_each_set_bit(bit, (unsigned long *)&at->status, MAX_PEBS_EVENTS) {
+               for_each_set_bit(bit, (unsigned long *)&at->status, x86_pmu.max_pebs_events) {
                        event = cpuc->events[bit];
                        if (!test_bit(bit, cpuc->active_mask))
                                continue;
@@ -670,7 +670,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs)
                        break;
                }
 
-               if (!event || bit >= MAX_PEBS_EVENTS)
+               if (!event || bit >= x86_pmu.max_pebs_events)
                        continue;
 
                __intel_pmu_pebs_event(event, iregs, at);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c
new file mode 100644 (file)
index 0000000..19faffc
--- /dev/null
@@ -0,0 +1,1850 @@
+#include "perf_event_intel_uncore.h"
+
+static struct intel_uncore_type *empty_uncore[] = { NULL, };
+static struct intel_uncore_type **msr_uncores = empty_uncore;
+static struct intel_uncore_type **pci_uncores = empty_uncore;
+/* pci bus to socket mapping */
+static int pcibus_to_physid[256] = { [0 ... 255] = -1, };
+
+static DEFINE_RAW_SPINLOCK(uncore_box_lock);
+
+/* mask of cpus that collect uncore events */
+static cpumask_t uncore_cpu_mask;
+
+/* constraint for the fixed counter */
+static struct event_constraint constraint_fixed =
+       EVENT_CONSTRAINT(~0ULL, 1 << UNCORE_PMC_IDX_FIXED, ~0ULL);
+static struct event_constraint constraint_empty =
+       EVENT_CONSTRAINT(0, 0, 0);
+
+DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
+DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
+DEFINE_UNCORE_FORMAT_ATTR(edge, edge, "config:18");
+DEFINE_UNCORE_FORMAT_ATTR(tid_en, tid_en, "config:19");
+DEFINE_UNCORE_FORMAT_ATTR(inv, inv, "config:23");
+DEFINE_UNCORE_FORMAT_ATTR(cmask5, cmask, "config:24-28");
+DEFINE_UNCORE_FORMAT_ATTR(cmask8, cmask, "config:24-31");
+DEFINE_UNCORE_FORMAT_ATTR(thresh8, thresh, "config:24-31");
+DEFINE_UNCORE_FORMAT_ATTR(thresh5, thresh, "config:24-28");
+DEFINE_UNCORE_FORMAT_ATTR(occ_sel, occ_sel, "config:14-15");
+DEFINE_UNCORE_FORMAT_ATTR(occ_invert, occ_invert, "config:30");
+DEFINE_UNCORE_FORMAT_ATTR(occ_edge, occ_edge, "config:14-51");
+DEFINE_UNCORE_FORMAT_ATTR(filter_tid, filter_tid, "config1:0-4");
+DEFINE_UNCORE_FORMAT_ATTR(filter_nid, filter_nid, "config1:10-17");
+DEFINE_UNCORE_FORMAT_ATTR(filter_state, filter_state, "config1:18-22");
+DEFINE_UNCORE_FORMAT_ATTR(filter_opc, filter_opc, "config1:23-31");
+DEFINE_UNCORE_FORMAT_ATTR(filter_brand0, filter_brand0, "config1:0-7");
+DEFINE_UNCORE_FORMAT_ATTR(filter_brand1, filter_brand1, "config1:8-15");
+DEFINE_UNCORE_FORMAT_ATTR(filter_brand2, filter_brand2, "config1:16-23");
+DEFINE_UNCORE_FORMAT_ATTR(filter_brand3, filter_brand3, "config1:24-31");
+
+/* Sandy Bridge-EP uncore support */
+static struct intel_uncore_type snbep_uncore_cbox;
+static struct intel_uncore_type snbep_uncore_pcu;
+
+static void snbep_uncore_pci_disable_box(struct intel_uncore_box *box)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       int box_ctl = uncore_pci_box_ctl(box);
+       u32 config;
+
+       pci_read_config_dword(pdev, box_ctl, &config);
+       config |= SNBEP_PMON_BOX_CTL_FRZ;
+       pci_write_config_dword(pdev, box_ctl, config);
+}
+
+static void snbep_uncore_pci_enable_box(struct intel_uncore_box *box)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       int box_ctl = uncore_pci_box_ctl(box);
+       u32 config;
+
+       pci_read_config_dword(pdev, box_ctl, &config);
+       config &= ~SNBEP_PMON_BOX_CTL_FRZ;
+       pci_write_config_dword(pdev, box_ctl, config);
+}
+
+static void snbep_uncore_pci_enable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+
+       pci_write_config_dword(pdev, hwc->config_base, hwc->config |
+                               SNBEP_PMON_CTL_EN);
+}
+
+static void snbep_uncore_pci_disable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+
+       pci_write_config_dword(pdev, hwc->config_base, hwc->config);
+}
+
+static u64 snbep_uncore_pci_read_counter(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       struct hw_perf_event *hwc = &event->hw;
+       u64 count;
+
+       pci_read_config_dword(pdev, hwc->event_base, (u32 *)&count);
+       pci_read_config_dword(pdev, hwc->event_base + 4, (u32 *)&count + 1);
+       return count;
+}
+
+static void snbep_uncore_pci_init_box(struct intel_uncore_box *box)
+{
+       struct pci_dev *pdev = box->pci_dev;
+       pci_write_config_dword(pdev, SNBEP_PCI_PMON_BOX_CTL,
+                               SNBEP_PMON_BOX_CTL_INT);
+}
+
+static void snbep_uncore_msr_disable_box(struct intel_uncore_box *box)
+{
+       u64 config;
+       unsigned msr;
+
+       msr = uncore_msr_box_ctl(box);
+       if (msr) {
+               rdmsrl(msr, config);
+               config |= SNBEP_PMON_BOX_CTL_FRZ;
+               wrmsrl(msr, config);
+               return;
+       }
+}
+
+static void snbep_uncore_msr_enable_box(struct intel_uncore_box *box)
+{
+       u64 config;
+       unsigned msr;
+
+       msr = uncore_msr_box_ctl(box);
+       if (msr) {
+               rdmsrl(msr, config);
+               config &= ~SNBEP_PMON_BOX_CTL_FRZ;
+               wrmsrl(msr, config);
+               return;
+       }
+}
+
+static void snbep_uncore_msr_enable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+
+       if (reg1->idx != EXTRA_REG_NONE)
+               wrmsrl(reg1->reg, reg1->config);
+
+       wrmsrl(hwc->config_base, hwc->config | SNBEP_PMON_CTL_EN);
+}
+
+static void snbep_uncore_msr_disable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       wrmsrl(hwc->config_base, hwc->config);
+}
+
+static u64 snbep_uncore_msr_read_counter(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       u64 count;
+
+       rdmsrl(hwc->event_base, count);
+       return count;
+}
+
+static void snbep_uncore_msr_init_box(struct intel_uncore_box *box)
+{
+       unsigned msr = uncore_msr_box_ctl(box);
+       if (msr)
+               wrmsrl(msr, SNBEP_PMON_BOX_CTL_INT);
+}
+
+static struct event_constraint *
+snbep_uncore_get_constraint(struct intel_uncore_box *box,
+                           struct perf_event *event)
+{
+       struct intel_uncore_extra_reg *er;
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+       unsigned long flags;
+       bool ok = false;
+
+       if (reg1->idx == EXTRA_REG_NONE || (box->phys_id >= 0 && reg1->alloc))
+               return NULL;
+
+       er = &box->shared_regs[reg1->idx];
+       raw_spin_lock_irqsave(&er->lock, flags);
+       if (!atomic_read(&er->ref) || er->config1 == reg1->config) {
+               atomic_inc(&er->ref);
+               er->config1 = reg1->config;
+               ok = true;
+       }
+       raw_spin_unlock_irqrestore(&er->lock, flags);
+
+       if (ok) {
+               if (box->phys_id >= 0)
+                       reg1->alloc = 1;
+               return NULL;
+       }
+       return &constraint_empty;
+}
+
+static void snbep_uncore_put_constraint(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct intel_uncore_extra_reg *er;
+       struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
+
+       if (box->phys_id < 0 || !reg1->alloc)
+               return;
+
+       er = &box->shared_regs[reg1->idx];
+       atomic_dec(&er->ref);
+       reg1->alloc = 0;
+}
+
+static int snbep_uncore_hw_config(struct intel_uncore_box *box,
+                                 struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+       struct hw_perf_event_extra *reg1 = &hwc->extra_reg;
+
+       if (box->pmu->type == &snbep_uncore_cbox) {
+               reg1->reg = SNBEP_C0_MSR_PMON_BOX_FILTER +
+                       SNBEP_CBO_MSR_OFFSET * box->pmu->pmu_idx;
+               reg1->config = event->attr.config1 &
+                       SNBEP_CB0_MSR_PMON_BOX_FILTER_MASK;
+       } else if (box->pmu->type == &snbep_uncore_pcu) {
+               reg1->reg = SNBEP_PCU_MSR_PMON_BOX_FILTER;
+               reg1->config = event->attr.config1 &
+                       SNBEP_PCU_MSR_PMON_BOX_FILTER_MASK;
+       } else {
+               return 0;
+       }
+       reg1->idx = 0;
+       return 0;
+}
+
+static struct attribute *snbep_uncore_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh8.attr,
+       NULL,
+};
+
+static struct attribute *snbep_uncore_ubox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh5.attr,
+       NULL,
+};
+
+static struct attribute *snbep_uncore_cbox_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_tid_en.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh8.attr,
+       &format_attr_filter_tid.attr,
+       &format_attr_filter_nid.attr,
+       &format_attr_filter_state.attr,
+       &format_attr_filter_opc.attr,
+       NULL,
+};
+
+static struct attribute *snbep_uncore_pcu_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_occ_sel.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_thresh5.attr,
+       &format_attr_occ_invert.attr,
+       &format_attr_occ_edge.attr,
+       &format_attr_filter_brand0.attr,
+       &format_attr_filter_brand1.attr,
+       &format_attr_filter_brand2.attr,
+       &format_attr_filter_brand3.attr,
+       NULL,
+};
+
+static struct uncore_event_desc snbep_uncore_imc_events[] = {
+       INTEL_UNCORE_EVENT_DESC(clockticks,      "event=0xff,umask=0x00"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_read,  "event=0x04,umask=0x03"),
+       INTEL_UNCORE_EVENT_DESC(cas_count_write, "event=0x04,umask=0x0c"),
+       { /* end: all zeroes */ },
+};
+
+static struct uncore_event_desc snbep_uncore_qpi_events[] = {
+       INTEL_UNCORE_EVENT_DESC(clockticks,       "event=0x14"),
+       INTEL_UNCORE_EVENT_DESC(txl_flits_active, "event=0x00,umask=0x06"),
+       INTEL_UNCORE_EVENT_DESC(drs_data,         "event=0x02,umask=0x08"),
+       INTEL_UNCORE_EVENT_DESC(ncb_data,         "event=0x03,umask=0x04"),
+       { /* end: all zeroes */ },
+};
+
+static struct attribute_group snbep_uncore_format_group = {
+       .name = "format",
+       .attrs = snbep_uncore_formats_attr,
+};
+
+static struct attribute_group snbep_uncore_ubox_format_group = {
+       .name = "format",
+       .attrs = snbep_uncore_ubox_formats_attr,
+};
+
+static struct attribute_group snbep_uncore_cbox_format_group = {
+       .name = "format",
+       .attrs = snbep_uncore_cbox_formats_attr,
+};
+
+static struct attribute_group snbep_uncore_pcu_format_group = {
+       .name = "format",
+       .attrs = snbep_uncore_pcu_formats_attr,
+};
+
+static struct intel_uncore_ops snbep_uncore_msr_ops = {
+       .init_box       = snbep_uncore_msr_init_box,
+       .disable_box    = snbep_uncore_msr_disable_box,
+       .enable_box     = snbep_uncore_msr_enable_box,
+       .disable_event  = snbep_uncore_msr_disable_event,
+       .enable_event   = snbep_uncore_msr_enable_event,
+       .read_counter   = snbep_uncore_msr_read_counter,
+       .get_constraint = snbep_uncore_get_constraint,
+       .put_constraint = snbep_uncore_put_constraint,
+       .hw_config      = snbep_uncore_hw_config,
+};
+
+static struct intel_uncore_ops snbep_uncore_pci_ops = {
+       .init_box       = snbep_uncore_pci_init_box,
+       .disable_box    = snbep_uncore_pci_disable_box,
+       .enable_box     = snbep_uncore_pci_enable_box,
+       .disable_event  = snbep_uncore_pci_disable_event,
+       .enable_event   = snbep_uncore_pci_enable_event,
+       .read_counter   = snbep_uncore_pci_read_counter,
+};
+
+static struct event_constraint snbep_uncore_cbox_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x01, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x02, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x04, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x05, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x07, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x13, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x1b, 0xc),
+       UNCORE_EVENT_CONSTRAINT(0x1c, 0xc),
+       UNCORE_EVENT_CONSTRAINT(0x1d, 0xc),
+       UNCORE_EVENT_CONSTRAINT(0x1e, 0xc),
+       EVENT_CONSTRAINT_OVERLAP(0x1f, 0xe, 0xff),
+       UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x35, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x36, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x38, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x39, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x3b, 0x1),
+       EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint snbep_uncore_r2pcie_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x12, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x24, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
+       EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint snbep_uncore_r3qpi_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x10, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x11, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x12, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x13, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x20, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x21, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x22, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x23, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x24, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x25, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x26, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x30, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x31, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x32, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x33, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x34, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x36, 0x3),
+       UNCORE_EVENT_CONSTRAINT(0x37, 0x3),
+       EVENT_CONSTRAINT_END
+};
+
+static struct intel_uncore_type snbep_uncore_ubox = {
+       .name           = "ubox",
+       .num_counters   = 2,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 44,
+       .fixed_ctr_bits = 48,
+       .perf_ctr       = SNBEP_U_MSR_PMON_CTR0,
+       .event_ctl      = SNBEP_U_MSR_PMON_CTL0,
+       .event_mask     = SNBEP_U_MSR_PMON_RAW_EVENT_MASK,
+       .fixed_ctr      = SNBEP_U_MSR_PMON_UCLK_FIXED_CTR,
+       .fixed_ctl      = SNBEP_U_MSR_PMON_UCLK_FIXED_CTL,
+       .ops            = &snbep_uncore_msr_ops,
+       .format_group   = &snbep_uncore_ubox_format_group,
+};
+
+static struct intel_uncore_type snbep_uncore_cbox = {
+       .name                   = "cbox",
+       .num_counters           = 4,
+       .num_boxes              = 8,
+       .perf_ctr_bits          = 44,
+       .event_ctl              = SNBEP_C0_MSR_PMON_CTL0,
+       .perf_ctr               = SNBEP_C0_MSR_PMON_CTR0,
+       .event_mask             = SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_C0_MSR_PMON_BOX_CTL,
+       .msr_offset             = SNBEP_CBO_MSR_OFFSET,
+       .num_shared_regs        = 1,
+       .constraints            = snbep_uncore_cbox_constraints,
+       .ops                    = &snbep_uncore_msr_ops,
+       .format_group           = &snbep_uncore_cbox_format_group,
+};
+
+static struct intel_uncore_type snbep_uncore_pcu = {
+       .name                   = "pcu",
+       .num_counters           = 4,
+       .num_boxes              = 1,
+       .perf_ctr_bits          = 48,
+       .perf_ctr               = SNBEP_PCU_MSR_PMON_CTR0,
+       .event_ctl              = SNBEP_PCU_MSR_PMON_CTL0,
+       .event_mask             = SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK,
+       .box_ctl                = SNBEP_PCU_MSR_PMON_BOX_CTL,
+       .num_shared_regs        = 1,
+       .ops                    = &snbep_uncore_msr_ops,
+       .format_group           = &snbep_uncore_pcu_format_group,
+};
+
+static struct intel_uncore_type *snbep_msr_uncores[] = {
+       &snbep_uncore_ubox,
+       &snbep_uncore_cbox,
+       &snbep_uncore_pcu,
+       NULL,
+};
+
+#define SNBEP_UNCORE_PCI_COMMON_INIT()                         \
+       .perf_ctr       = SNBEP_PCI_PMON_CTR0,                  \
+       .event_ctl      = SNBEP_PCI_PMON_CTL0,                  \
+       .event_mask     = SNBEP_PMON_RAW_EVENT_MASK,            \
+       .box_ctl        = SNBEP_PCI_PMON_BOX_CTL,               \
+       .ops            = &snbep_uncore_pci_ops,                \
+       .format_group   = &snbep_uncore_format_group
+
+static struct intel_uncore_type snbep_uncore_ha = {
+       .name           = "ha",
+       .num_counters   = 4,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 48,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type snbep_uncore_imc = {
+       .name           = "imc",
+       .num_counters   = 4,
+       .num_boxes      = 4,
+       .perf_ctr_bits  = 48,
+       .fixed_ctr_bits = 48,
+       .fixed_ctr      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTR,
+       .fixed_ctl      = SNBEP_MC_CHy_PCI_PMON_FIXED_CTL,
+       .event_descs    = snbep_uncore_imc_events,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type snbep_uncore_qpi = {
+       .name           = "qpi",
+       .num_counters   = 4,
+       .num_boxes      = 2,
+       .perf_ctr_bits  = 48,
+       .event_descs    = snbep_uncore_qpi_events,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+
+static struct intel_uncore_type snbep_uncore_r2pcie = {
+       .name           = "r2pcie",
+       .num_counters   = 4,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 44,
+       .constraints    = snbep_uncore_r2pcie_constraints,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type snbep_uncore_r3qpi = {
+       .name           = "r3qpi",
+       .num_counters   = 3,
+       .num_boxes      = 2,
+       .perf_ctr_bits  = 44,
+       .constraints    = snbep_uncore_r3qpi_constraints,
+       SNBEP_UNCORE_PCI_COMMON_INIT(),
+};
+
+static struct intel_uncore_type *snbep_pci_uncores[] = {
+       &snbep_uncore_ha,
+       &snbep_uncore_imc,
+       &snbep_uncore_qpi,
+       &snbep_uncore_r2pcie,
+       &snbep_uncore_r3qpi,
+       NULL,
+};
+
+static DEFINE_PCI_DEVICE_TABLE(snbep_uncore_pci_ids) = {
+       { /* Home Agent */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_HA),
+               .driver_data = (unsigned long)&snbep_uncore_ha,
+       },
+       { /* MC Channel 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC0),
+               .driver_data = (unsigned long)&snbep_uncore_imc,
+       },
+       { /* MC Channel 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC1),
+               .driver_data = (unsigned long)&snbep_uncore_imc,
+       },
+       { /* MC Channel 2 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC2),
+               .driver_data = (unsigned long)&snbep_uncore_imc,
+       },
+       { /* MC Channel 3 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_IMC3),
+               .driver_data = (unsigned long)&snbep_uncore_imc,
+       },
+       { /* QPI Port 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_QPI0),
+               .driver_data = (unsigned long)&snbep_uncore_qpi,
+       },
+       { /* QPI Port 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_QPI1),
+               .driver_data = (unsigned long)&snbep_uncore_qpi,
+       },
+       { /* P2PCIe */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R2PCIE),
+               .driver_data = (unsigned long)&snbep_uncore_r2pcie,
+       },
+       { /* R3QPI Link 0 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R3QPI0),
+               .driver_data = (unsigned long)&snbep_uncore_r3qpi,
+       },
+       { /* R3QPI Link 1 */
+               PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_UNC_R3QPI1),
+               .driver_data = (unsigned long)&snbep_uncore_r3qpi,
+       },
+       { /* end: all zeroes */ }
+};
+
+static struct pci_driver snbep_uncore_pci_driver = {
+       .name           = "snbep_uncore",
+       .id_table       = snbep_uncore_pci_ids,
+};
+
+/*
+ * build pci bus to socket mapping
+ */
+static void snbep_pci2phy_map_init(void)
+{
+       struct pci_dev *ubox_dev = NULL;
+       int i, bus, nodeid;
+       u32 config;
+
+       while (1) {
+               /* find the UBOX device */
+               ubox_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
+                                       PCI_DEVICE_ID_INTEL_JAKETOWN_UBOX,
+                                       ubox_dev);
+               if (!ubox_dev)
+                       break;
+               bus = ubox_dev->bus->number;
+               /* get the Node ID of the local register */
+               pci_read_config_dword(ubox_dev, 0x40, &config);
+               nodeid = config;
+               /* get the Node ID mapping */
+               pci_read_config_dword(ubox_dev, 0x54, &config);
+               /*
+                * every three bits in the Node ID mapping register maps
+                * to a particular node.
+                */
+               for (i = 0; i < 8; i++) {
+                       if (nodeid == ((config >> (3 * i)) & 0x7)) {
+                               pcibus_to_physid[bus] = i;
+                               break;
+                       }
+               }
+       };
+       return;
+}
+/* end of Sandy Bridge-EP uncore support */
+
+
+/* Sandy Bridge uncore support */
+static void snb_uncore_msr_enable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (hwc->idx < UNCORE_PMC_IDX_FIXED)
+               wrmsrl(hwc->config_base, hwc->config | SNB_UNC_CTL_EN);
+       else
+               wrmsrl(hwc->config_base, SNB_UNC_CTL_EN);
+}
+
+static void snb_uncore_msr_disable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       wrmsrl(event->hw.config_base, 0);
+}
+
+static u64 snb_uncore_msr_read_counter(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       u64 count;
+       rdmsrl(event->hw.event_base, count);
+       return count;
+}
+
+static void snb_uncore_msr_init_box(struct intel_uncore_box *box)
+{
+       if (box->pmu->pmu_idx == 0) {
+               wrmsrl(SNB_UNC_PERF_GLOBAL_CTL,
+                       SNB_UNC_GLOBAL_CTL_EN | SNB_UNC_GLOBAL_CTL_CORE_ALL);
+       }
+}
+
+static struct attribute *snb_uncore_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_cmask5.attr,
+       NULL,
+};
+
+static struct attribute_group snb_uncore_format_group = {
+       .name = "format",
+       .attrs = snb_uncore_formats_attr,
+};
+
+static struct intel_uncore_ops snb_uncore_msr_ops = {
+       .init_box       = snb_uncore_msr_init_box,
+       .disable_event  = snb_uncore_msr_disable_event,
+       .enable_event   = snb_uncore_msr_enable_event,
+       .read_counter   = snb_uncore_msr_read_counter,
+};
+
+static struct event_constraint snb_uncore_cbox_constraints[] = {
+       UNCORE_EVENT_CONSTRAINT(0x80, 0x1),
+       UNCORE_EVENT_CONSTRAINT(0x83, 0x1),
+       EVENT_CONSTRAINT_END
+};
+
+static struct intel_uncore_type snb_uncore_cbox = {
+       .name           = "cbox",
+       .num_counters   = 2,
+       .num_boxes      = 4,
+       .perf_ctr_bits  = 44,
+       .fixed_ctr_bits = 48,
+       .perf_ctr       = SNB_UNC_CBO_0_PER_CTR0,
+       .event_ctl      = SNB_UNC_CBO_0_PERFEVTSEL0,
+       .fixed_ctr      = SNB_UNC_FIXED_CTR,
+       .fixed_ctl      = SNB_UNC_FIXED_CTR_CTRL,
+       .single_fixed   = 1,
+       .event_mask     = SNB_UNC_RAW_EVENT_MASK,
+       .msr_offset     = SNB_UNC_CBO_MSR_OFFSET,
+       .constraints    = snb_uncore_cbox_constraints,
+       .ops            = &snb_uncore_msr_ops,
+       .format_group   = &snb_uncore_format_group,
+};
+
+static struct intel_uncore_type *snb_msr_uncores[] = {
+       &snb_uncore_cbox,
+       NULL,
+};
+/* end of Sandy Bridge uncore support */
+
+/* Nehalem uncore support */
+static void nhm_uncore_msr_disable_box(struct intel_uncore_box *box)
+{
+       wrmsrl(NHM_UNC_PERF_GLOBAL_CTL, 0);
+}
+
+static void nhm_uncore_msr_enable_box(struct intel_uncore_box *box)
+{
+       wrmsrl(NHM_UNC_PERF_GLOBAL_CTL,
+               NHM_UNC_GLOBAL_CTL_EN_PC_ALL | NHM_UNC_GLOBAL_CTL_EN_FC);
+}
+
+static void nhm_uncore_msr_enable_event(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (hwc->idx < UNCORE_PMC_IDX_FIXED)
+               wrmsrl(hwc->config_base, hwc->config | SNB_UNC_CTL_EN);
+       else
+               wrmsrl(hwc->config_base, NHM_UNC_FIXED_CTR_CTL_EN);
+}
+
+static struct attribute *nhm_uncore_formats_attr[] = {
+       &format_attr_event.attr,
+       &format_attr_umask.attr,
+       &format_attr_edge.attr,
+       &format_attr_inv.attr,
+       &format_attr_cmask8.attr,
+       NULL,
+};
+
+static struct attribute_group nhm_uncore_format_group = {
+       .name = "format",
+       .attrs = nhm_uncore_formats_attr,
+};
+
+static struct uncore_event_desc nhm_uncore_events[] = {
+       INTEL_UNCORE_EVENT_DESC(clockticks,                "event=0xff,umask=0x00"),
+       INTEL_UNCORE_EVENT_DESC(qmc_writes_full_any,       "event=0x2f,umask=0x0f"),
+       INTEL_UNCORE_EVENT_DESC(qmc_normal_reads_any,      "event=0x2c,umask=0x0f"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_ioh_reads,     "event=0x20,umask=0x01"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_ioh_writes,    "event=0x20,umask=0x02"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_remote_reads,  "event=0x20,umask=0x04"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_remote_writes, "event=0x20,umask=0x08"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_local_reads,   "event=0x20,umask=0x10"),
+       INTEL_UNCORE_EVENT_DESC(qhl_request_local_writes,  "event=0x20,umask=0x20"),
+       { /* end: all zeroes */ },
+};
+
+static struct intel_uncore_ops nhm_uncore_msr_ops = {
+       .disable_box    = nhm_uncore_msr_disable_box,
+       .enable_box     = nhm_uncore_msr_enable_box,
+       .disable_event  = snb_uncore_msr_disable_event,
+       .enable_event   = nhm_uncore_msr_enable_event,
+       .read_counter   = snb_uncore_msr_read_counter,
+};
+
+static struct intel_uncore_type nhm_uncore = {
+       .name           = "",
+       .num_counters   = 8,
+       .num_boxes      = 1,
+       .perf_ctr_bits  = 48,
+       .fixed_ctr_bits = 48,
+       .event_ctl      = NHM_UNC_PERFEVTSEL0,
+       .perf_ctr       = NHM_UNC_UNCORE_PMC0,
+       .fixed_ctr      = NHM_UNC_FIXED_CTR,
+       .fixed_ctl      = NHM_UNC_FIXED_CTR_CTRL,
+       .event_mask     = NHM_UNC_RAW_EVENT_MASK,
+       .event_descs    = nhm_uncore_events,
+       .ops            = &nhm_uncore_msr_ops,
+       .format_group   = &nhm_uncore_format_group,
+};
+
+static struct intel_uncore_type *nhm_msr_uncores[] = {
+       &nhm_uncore,
+       NULL,
+};
+/* end of Nehalem uncore support */
+
+static void uncore_assign_hw_event(struct intel_uncore_box *box,
+                               struct perf_event *event, int idx)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       hwc->idx = idx;
+       hwc->last_tag = ++box->tags[idx];
+
+       if (hwc->idx == UNCORE_PMC_IDX_FIXED) {
+               hwc->event_base = uncore_fixed_ctr(box);
+               hwc->config_base = uncore_fixed_ctl(box);
+               return;
+       }
+
+       hwc->config_base = uncore_event_ctl(box, hwc->idx);
+       hwc->event_base  = uncore_perf_ctr(box, hwc->idx);
+}
+
+static void uncore_perf_event_update(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       u64 prev_count, new_count, delta;
+       int shift;
+
+       if (event->hw.idx >= UNCORE_PMC_IDX_FIXED)
+               shift = 64 - uncore_fixed_ctr_bits(box);
+       else
+               shift = 64 - uncore_perf_ctr_bits(box);
+
+       /* the hrtimer might modify the previous event value */
+again:
+       prev_count = local64_read(&event->hw.prev_count);
+       new_count = uncore_read_counter(box, event);
+       if (local64_xchg(&event->hw.prev_count, new_count) != prev_count)
+               goto again;
+
+       delta = (new_count << shift) - (prev_count << shift);
+       delta >>= shift;
+
+       local64_add(delta, &event->count);
+}
+
+/*
+ * The overflow interrupt is unavailable for SandyBridge-EP, is broken
+ * for SandyBridge. So we use hrtimer to periodically poll the counter
+ * to avoid overflow.
+ */
+static enum hrtimer_restart uncore_pmu_hrtimer(struct hrtimer *hrtimer)
+{
+       struct intel_uncore_box *box;
+       unsigned long flags;
+       int bit;
+
+       box = container_of(hrtimer, struct intel_uncore_box, hrtimer);
+       if (!box->n_active || box->cpu != smp_processor_id())
+               return HRTIMER_NORESTART;
+       /*
+        * disable local interrupt to prevent uncore_pmu_event_start/stop
+        * to interrupt the update process
+        */
+       local_irq_save(flags);
+
+       for_each_set_bit(bit, box->active_mask, UNCORE_PMC_IDX_MAX)
+               uncore_perf_event_update(box, box->events[bit]);
+
+       local_irq_restore(flags);
+
+       hrtimer_forward_now(hrtimer, ns_to_ktime(UNCORE_PMU_HRTIMER_INTERVAL));
+       return HRTIMER_RESTART;
+}
+
+static void uncore_pmu_start_hrtimer(struct intel_uncore_box *box)
+{
+       __hrtimer_start_range_ns(&box->hrtimer,
+                       ns_to_ktime(UNCORE_PMU_HRTIMER_INTERVAL), 0,
+                       HRTIMER_MODE_REL_PINNED, 0);
+}
+
+static void uncore_pmu_cancel_hrtimer(struct intel_uncore_box *box)
+{
+       hrtimer_cancel(&box->hrtimer);
+}
+
+static void uncore_pmu_init_hrtimer(struct intel_uncore_box *box)
+{
+       hrtimer_init(&box->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       box->hrtimer.function = uncore_pmu_hrtimer;
+}
+
+struct intel_uncore_box *uncore_alloc_box(struct intel_uncore_type *type,
+                                         int cpu)
+{
+       struct intel_uncore_box *box;
+       int i, size;
+
+       size = sizeof(*box) + type->num_shared_regs *
+               sizeof(struct intel_uncore_extra_reg);
+
+       box = kmalloc_node(size, GFP_KERNEL | __GFP_ZERO, cpu_to_node(cpu));
+       if (!box)
+               return NULL;
+
+       for (i = 0; i < type->num_shared_regs; i++)
+               raw_spin_lock_init(&box->shared_regs[i].lock);
+
+       uncore_pmu_init_hrtimer(box);
+       atomic_set(&box->refcnt, 1);
+       box->cpu = -1;
+       box->phys_id = -1;
+
+       return box;
+}
+
+static struct intel_uncore_box *
+uncore_pmu_to_box(struct intel_uncore_pmu *pmu, int cpu)
+{
+       static struct intel_uncore_box *box;
+
+       box = *per_cpu_ptr(pmu->box, cpu);
+       if (box)
+               return box;
+
+       raw_spin_lock(&uncore_box_lock);
+       list_for_each_entry(box, &pmu->box_list, list) {
+               if (box->phys_id == topology_physical_package_id(cpu)) {
+                       atomic_inc(&box->refcnt);
+                       *per_cpu_ptr(pmu->box, cpu) = box;
+                       break;
+               }
+       }
+       raw_spin_unlock(&uncore_box_lock);
+
+       return *per_cpu_ptr(pmu->box, cpu);
+}
+
+static struct intel_uncore_pmu *uncore_event_to_pmu(struct perf_event *event)
+{
+       return container_of(event->pmu, struct intel_uncore_pmu, pmu);
+}
+
+static struct intel_uncore_box *uncore_event_to_box(struct perf_event *event)
+{
+       /*
+        * perf core schedules event on the basis of cpu, uncore events are
+        * collected by one of the cpus inside a physical package.
+        */
+       return uncore_pmu_to_box(uncore_event_to_pmu(event),
+                                smp_processor_id());
+}
+
+static int uncore_collect_events(struct intel_uncore_box *box,
+                               struct perf_event *leader, bool dogrp)
+{
+       struct perf_event *event;
+       int n, max_count;
+
+       max_count = box->pmu->type->num_counters;
+       if (box->pmu->type->fixed_ctl)
+               max_count++;
+
+       if (box->n_events >= max_count)
+               return -EINVAL;
+
+       n = box->n_events;
+       box->event_list[n] = leader;
+       n++;
+       if (!dogrp)
+               return n;
+
+       list_for_each_entry(event, &leader->sibling_list, group_entry) {
+               if (event->state <= PERF_EVENT_STATE_OFF)
+                       continue;
+
+               if (n >= max_count)
+                       return -EINVAL;
+
+               box->event_list[n] = event;
+               n++;
+       }
+       return n;
+}
+
+static struct event_constraint *
+uncore_get_event_constraint(struct intel_uncore_box *box,
+                           struct perf_event *event)
+{
+       struct intel_uncore_type *type = box->pmu->type;
+       struct event_constraint *c;
+
+       if (type->ops->get_constraint) {
+               c = type->ops->get_constraint(box, event);
+               if (c)
+                       return c;
+       }
+
+       if (event->hw.config == ~0ULL)
+               return &constraint_fixed;
+
+       if (type->constraints) {
+               for_each_event_constraint(c, type->constraints) {
+                       if ((event->hw.config & c->cmask) == c->code)
+                               return c;
+               }
+       }
+
+       return &type->unconstrainted;
+}
+
+static void uncore_put_event_constraint(struct intel_uncore_box *box,
+                                       struct perf_event *event)
+{
+       if (box->pmu->type->ops->put_constraint)
+               box->pmu->type->ops->put_constraint(box, event);
+}
+
+static int uncore_assign_events(struct intel_uncore_box *box,
+                               int assign[], int n)
+{
+       unsigned long used_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)];
+       struct event_constraint *c, *constraints[UNCORE_PMC_IDX_MAX];
+       int i, wmin, wmax, ret = 0;
+       struct hw_perf_event *hwc;
+
+       bitmap_zero(used_mask, UNCORE_PMC_IDX_MAX);
+
+       for (i = 0, wmin = UNCORE_PMC_IDX_MAX, wmax = 0; i < n; i++) {
+               c = uncore_get_event_constraint(box, box->event_list[i]);
+               constraints[i] = c;
+               wmin = min(wmin, c->weight);
+               wmax = max(wmax, c->weight);
+       }
+
+       /* fastpath, try to reuse previous register */
+       for (i = 0; i < n; i++) {
+               hwc = &box->event_list[i]->hw;
+               c = constraints[i];
+
+               /* never assigned */
+               if (hwc->idx == -1)
+                       break;
+
+               /* constraint still honored */
+               if (!test_bit(hwc->idx, c->idxmsk))
+                       break;
+
+               /* not already used */
+               if (test_bit(hwc->idx, used_mask))
+                       break;
+
+               __set_bit(hwc->idx, used_mask);
+               if (assign)
+                       assign[i] = hwc->idx;
+       }
+       /* slow path */
+       if (i != n)
+               ret = perf_assign_events(constraints, n, wmin, wmax, assign);
+
+       if (!assign || ret) {
+               for (i = 0; i < n; i++)
+                       uncore_put_event_constraint(box, box->event_list[i]);
+       }
+       return ret ? -EINVAL : 0;
+}
+
+static void uncore_pmu_event_start(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       int idx = event->hw.idx;
+
+       if (WARN_ON_ONCE(!(event->hw.state & PERF_HES_STOPPED)))
+               return;
+
+       if (WARN_ON_ONCE(idx == -1 || idx >= UNCORE_PMC_IDX_MAX))
+               return;
+
+       event->hw.state = 0;
+       box->events[idx] = event;
+       box->n_active++;
+       __set_bit(idx, box->active_mask);
+
+       local64_set(&event->hw.prev_count, uncore_read_counter(box, event));
+       uncore_enable_event(box, event);
+
+       if (box->n_active == 1) {
+               uncore_enable_box(box);
+               uncore_pmu_start_hrtimer(box);
+       }
+}
+
+static void uncore_pmu_event_stop(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       struct hw_perf_event *hwc = &event->hw;
+
+       if (__test_and_clear_bit(hwc->idx, box->active_mask)) {
+               uncore_disable_event(box, event);
+               box->n_active--;
+               box->events[hwc->idx] = NULL;
+               WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
+               hwc->state |= PERF_HES_STOPPED;
+
+               if (box->n_active == 0) {
+                       uncore_disable_box(box);
+                       uncore_pmu_cancel_hrtimer(box);
+               }
+       }
+
+       if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
+               /*
+                * Drain the remaining delta count out of a event
+                * that we are disabling:
+                */
+               uncore_perf_event_update(box, event);
+               hwc->state |= PERF_HES_UPTODATE;
+       }
+}
+
+static int uncore_pmu_event_add(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       struct hw_perf_event *hwc = &event->hw;
+       int assign[UNCORE_PMC_IDX_MAX];
+       int i, n, ret;
+
+       if (!box)
+               return -ENODEV;
+
+       ret = n = uncore_collect_events(box, event, false);
+       if (ret < 0)
+               return ret;
+
+       hwc->state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
+       if (!(flags & PERF_EF_START))
+               hwc->state |= PERF_HES_ARCH;
+
+       ret = uncore_assign_events(box, assign, n);
+       if (ret)
+               return ret;
+
+       /* save events moving to new counters */
+       for (i = 0; i < box->n_events; i++) {
+               event = box->event_list[i];
+               hwc = &event->hw;
+
+               if (hwc->idx == assign[i] &&
+                       hwc->last_tag == box->tags[assign[i]])
+                       continue;
+               /*
+                * Ensure we don't accidentally enable a stopped
+                * counter simply because we rescheduled.
+                */
+               if (hwc->state & PERF_HES_STOPPED)
+                       hwc->state |= PERF_HES_ARCH;
+
+               uncore_pmu_event_stop(event, PERF_EF_UPDATE);
+       }
+
+       /* reprogram moved events into new counters */
+       for (i = 0; i < n; i++) {
+               event = box->event_list[i];
+               hwc = &event->hw;
+
+               if (hwc->idx != assign[i] ||
+                       hwc->last_tag != box->tags[assign[i]])
+                       uncore_assign_hw_event(box, event, assign[i]);
+               else if (i < box->n_events)
+                       continue;
+
+               if (hwc->state & PERF_HES_ARCH)
+                       continue;
+
+               uncore_pmu_event_start(event, 0);
+       }
+       box->n_events = n;
+
+       return 0;
+}
+
+static void uncore_pmu_event_del(struct perf_event *event, int flags)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       int i;
+
+       uncore_pmu_event_stop(event, PERF_EF_UPDATE);
+
+       for (i = 0; i < box->n_events; i++) {
+               if (event == box->event_list[i]) {
+                       uncore_put_event_constraint(box, event);
+
+                       while (++i < box->n_events)
+                               box->event_list[i - 1] = box->event_list[i];
+
+                       --box->n_events;
+                       break;
+               }
+       }
+
+       event->hw.idx = -1;
+       event->hw.last_tag = ~0ULL;
+}
+
+static void uncore_pmu_event_read(struct perf_event *event)
+{
+       struct intel_uncore_box *box = uncore_event_to_box(event);
+       uncore_perf_event_update(box, event);
+}
+
+/*
+ * validation ensures the group can be loaded onto the
+ * PMU if it was the only group available.
+ */
+static int uncore_validate_group(struct intel_uncore_pmu *pmu,
+                               struct perf_event *event)
+{
+       struct perf_event *leader = event->group_leader;
+       struct intel_uncore_box *fake_box;
+       int ret = -EINVAL, n;
+
+       fake_box = uncore_alloc_box(pmu->type, smp_processor_id());
+       if (!fake_box)
+               return -ENOMEM;
+
+       fake_box->pmu = pmu;
+       /*
+        * the event is not yet connected with its
+        * siblings therefore we must first collect
+        * existing siblings, then add the new event
+        * before we can simulate the scheduling
+        */
+       n = uncore_collect_events(fake_box, leader, true);
+       if (n < 0)
+               goto out;
+
+       fake_box->n_events = n;
+       n = uncore_collect_events(fake_box, event, false);
+       if (n < 0)
+               goto out;
+
+       fake_box->n_events = n;
+
+       ret = uncore_assign_events(fake_box, NULL, n);
+out:
+       kfree(fake_box);
+       return ret;
+}
+
+int uncore_pmu_event_init(struct perf_event *event)
+{
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       struct hw_perf_event *hwc = &event->hw;
+       int ret;
+
+       if (event->attr.type != event->pmu->type)
+               return -ENOENT;
+
+       pmu = uncore_event_to_pmu(event);
+       /* no device found for this pmu */
+       if (pmu->func_id < 0)
+               return -ENOENT;
+
+       /*
+        * Uncore PMU does measure at all privilege level all the time.
+        * So it doesn't make sense to specify any exclude bits.
+        */
+       if (event->attr.exclude_user || event->attr.exclude_kernel ||
+                       event->attr.exclude_hv || event->attr.exclude_idle)
+               return -EINVAL;
+
+       /* Sampling not supported yet */
+       if (hwc->sample_period)
+               return -EINVAL;
+
+       /*
+        * Place all uncore events for a particular physical package
+        * onto a single cpu
+        */
+       if (event->cpu < 0)
+               return -EINVAL;
+       box = uncore_pmu_to_box(pmu, event->cpu);
+       if (!box || box->cpu < 0)
+               return -EINVAL;
+       event->cpu = box->cpu;
+
+       event->hw.idx = -1;
+       event->hw.last_tag = ~0ULL;
+       event->hw.extra_reg.idx = EXTRA_REG_NONE;
+
+       if (event->attr.config == UNCORE_FIXED_EVENT) {
+               /* no fixed counter */
+               if (!pmu->type->fixed_ctl)
+                       return -EINVAL;
+               /*
+                * if there is only one fixed counter, only the first pmu
+                * can access the fixed counter
+                */
+               if (pmu->type->single_fixed && pmu->pmu_idx > 0)
+                       return -EINVAL;
+               hwc->config = ~0ULL;
+       } else {
+               hwc->config = event->attr.config & pmu->type->event_mask;
+               if (pmu->type->ops->hw_config) {
+                       ret = pmu->type->ops->hw_config(box, event);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       if (event->group_leader != event)
+               ret = uncore_validate_group(pmu, event);
+       else
+               ret = 0;
+
+       return ret;
+}
+
+static int __init uncore_pmu_register(struct intel_uncore_pmu *pmu)
+{
+       int ret;
+
+       pmu->pmu = (struct pmu) {
+               .attr_groups    = pmu->type->attr_groups,
+               .task_ctx_nr    = perf_invalid_context,
+               .event_init     = uncore_pmu_event_init,
+               .add            = uncore_pmu_event_add,
+               .del            = uncore_pmu_event_del,
+               .start          = uncore_pmu_event_start,
+               .stop           = uncore_pmu_event_stop,
+               .read           = uncore_pmu_event_read,
+       };
+
+       if (pmu->type->num_boxes == 1) {
+               if (strlen(pmu->type->name) > 0)
+                       sprintf(pmu->name, "uncore_%s", pmu->type->name);
+               else
+                       sprintf(pmu->name, "uncore");
+       } else {
+               sprintf(pmu->name, "uncore_%s_%d", pmu->type->name,
+                       pmu->pmu_idx);
+       }
+
+       ret = perf_pmu_register(&pmu->pmu, pmu->name, -1);
+       return ret;
+}
+
+static void __init uncore_type_exit(struct intel_uncore_type *type)
+{
+       int i;
+
+       for (i = 0; i < type->num_boxes; i++)
+               free_percpu(type->pmus[i].box);
+       kfree(type->pmus);
+       type->pmus = NULL;
+       kfree(type->attr_groups[1]);
+       type->attr_groups[1] = NULL;
+}
+
+static void uncore_types_exit(struct intel_uncore_type **types)
+{
+       int i;
+       for (i = 0; types[i]; i++)
+               uncore_type_exit(types[i]);
+}
+
+static int __init uncore_type_init(struct intel_uncore_type *type)
+{
+       struct intel_uncore_pmu *pmus;
+       struct attribute_group *events_group;
+       struct attribute **attrs;
+       int i, j;
+
+       pmus = kzalloc(sizeof(*pmus) * type->num_boxes, GFP_KERNEL);
+       if (!pmus)
+               return -ENOMEM;
+
+       type->unconstrainted = (struct event_constraint)
+               __EVENT_CONSTRAINT(0, (1ULL << type->num_counters) - 1,
+                               0, type->num_counters, 0);
+
+       for (i = 0; i < type->num_boxes; i++) {
+               pmus[i].func_id = -1;
+               pmus[i].pmu_idx = i;
+               pmus[i].type = type;
+               INIT_LIST_HEAD(&pmus[i].box_list);
+               pmus[i].box = alloc_percpu(struct intel_uncore_box *);
+               if (!pmus[i].box)
+                       goto fail;
+       }
+
+       if (type->event_descs) {
+               i = 0;
+               while (type->event_descs[i].attr.attr.name)
+                       i++;
+
+               events_group = kzalloc(sizeof(struct attribute *) * (i + 1) +
+                                       sizeof(*events_group), GFP_KERNEL);
+               if (!events_group)
+                       goto fail;
+
+               attrs = (struct attribute **)(events_group + 1);
+               events_group->name = "events";
+               events_group->attrs = attrs;
+
+               for (j = 0; j < i; j++)
+                       attrs[j] = &type->event_descs[j].attr.attr;
+
+               type->attr_groups[1] = events_group;
+       }
+
+       type->pmus = pmus;
+       return 0;
+fail:
+       uncore_type_exit(type);
+       return -ENOMEM;
+}
+
+static int __init uncore_types_init(struct intel_uncore_type **types)
+{
+       int i, ret;
+
+       for (i = 0; types[i]; i++) {
+               ret = uncore_type_init(types[i]);
+               if (ret)
+                       goto fail;
+       }
+       return 0;
+fail:
+       while (--i >= 0)
+               uncore_type_exit(types[i]);
+       return ret;
+}
+
+static struct pci_driver *uncore_pci_driver;
+static bool pcidrv_registered;
+
+/*
+ * add a pci uncore device
+ */
+static int __devinit uncore_pci_add(struct intel_uncore_type *type,
+                                   struct pci_dev *pdev)
+{
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       int i, phys_id;
+
+       phys_id = pcibus_to_physid[pdev->bus->number];
+       if (phys_id < 0)
+               return -ENODEV;
+
+       box = uncore_alloc_box(type, 0);
+       if (!box)
+               return -ENOMEM;
+
+       /*
+        * for performance monitoring unit with multiple boxes,
+        * each box has a different function id.
+        */
+       for (i = 0; i < type->num_boxes; i++) {
+               pmu = &type->pmus[i];
+               if (pmu->func_id == pdev->devfn)
+                       break;
+               if (pmu->func_id < 0) {
+                       pmu->func_id = pdev->devfn;
+                       break;
+               }
+               pmu = NULL;
+       }
+
+       if (!pmu) {
+               kfree(box);
+               return -EINVAL;
+       }
+
+       box->phys_id = phys_id;
+       box->pci_dev = pdev;
+       box->pmu = pmu;
+       uncore_box_init(box);
+       pci_set_drvdata(pdev, box);
+
+       raw_spin_lock(&uncore_box_lock);
+       list_add_tail(&box->list, &pmu->box_list);
+       raw_spin_unlock(&uncore_box_lock);
+
+       return 0;
+}
+
+static void uncore_pci_remove(struct pci_dev *pdev)
+{
+       struct intel_uncore_box *box = pci_get_drvdata(pdev);
+       struct intel_uncore_pmu *pmu = box->pmu;
+       int cpu, phys_id = pcibus_to_physid[pdev->bus->number];
+
+       if (WARN_ON_ONCE(phys_id != box->phys_id))
+               return;
+
+       raw_spin_lock(&uncore_box_lock);
+       list_del(&box->list);
+       raw_spin_unlock(&uncore_box_lock);
+
+       for_each_possible_cpu(cpu) {
+               if (*per_cpu_ptr(pmu->box, cpu) == box) {
+                       *per_cpu_ptr(pmu->box, cpu) = NULL;
+                       atomic_dec(&box->refcnt);
+               }
+       }
+
+       WARN_ON_ONCE(atomic_read(&box->refcnt) != 1);
+       kfree(box);
+}
+
+static int __devinit uncore_pci_probe(struct pci_dev *pdev,
+                               const struct pci_device_id *id)
+{
+       struct intel_uncore_type *type;
+
+       type = (struct intel_uncore_type *)id->driver_data;
+       return uncore_pci_add(type, pdev);
+}
+
+static int __init uncore_pci_init(void)
+{
+       int ret;
+
+       switch (boot_cpu_data.x86_model) {
+       case 45: /* Sandy Bridge-EP */
+               pci_uncores = snbep_pci_uncores;
+               uncore_pci_driver = &snbep_uncore_pci_driver;
+               snbep_pci2phy_map_init();
+               break;
+       default:
+               return 0;
+       }
+
+       ret = uncore_types_init(pci_uncores);
+       if (ret)
+               return ret;
+
+       uncore_pci_driver->probe = uncore_pci_probe;
+       uncore_pci_driver->remove = uncore_pci_remove;
+
+       ret = pci_register_driver(uncore_pci_driver);
+       if (ret == 0)
+               pcidrv_registered = true;
+       else
+               uncore_types_exit(pci_uncores);
+
+       return ret;
+}
+
+static void __init uncore_pci_exit(void)
+{
+       if (pcidrv_registered) {
+               pcidrv_registered = false;
+               pci_unregister_driver(uncore_pci_driver);
+               uncore_types_exit(pci_uncores);
+       }
+}
+
+static void __cpuinit uncore_cpu_dying(int cpu)
+{
+       struct intel_uncore_type *type;
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       int i, j;
+
+       for (i = 0; msr_uncores[i]; i++) {
+               type = msr_uncores[i];
+               for (j = 0; j < type->num_boxes; j++) {
+                       pmu = &type->pmus[j];
+                       box = *per_cpu_ptr(pmu->box, cpu);
+                       *per_cpu_ptr(pmu->box, cpu) = NULL;
+                       if (box && atomic_dec_and_test(&box->refcnt))
+                               kfree(box);
+               }
+       }
+}
+
+static int __cpuinit uncore_cpu_starting(int cpu)
+{
+       struct intel_uncore_type *type;
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box, *exist;
+       int i, j, k, phys_id;
+
+       phys_id = topology_physical_package_id(cpu);
+
+       for (i = 0; msr_uncores[i]; i++) {
+               type = msr_uncores[i];
+               for (j = 0; j < type->num_boxes; j++) {
+                       pmu = &type->pmus[j];
+                       box = *per_cpu_ptr(pmu->box, cpu);
+                       /* called by uncore_cpu_init? */
+                       if (box && box->phys_id >= 0) {
+                               uncore_box_init(box);
+                               continue;
+                       }
+
+                       for_each_online_cpu(k) {
+                               exist = *per_cpu_ptr(pmu->box, k);
+                               if (exist && exist->phys_id == phys_id) {
+                                       atomic_inc(&exist->refcnt);
+                                       *per_cpu_ptr(pmu->box, cpu) = exist;
+                                       kfree(box);
+                                       box = NULL;
+                                       break;
+                               }
+                       }
+
+                       if (box) {
+                               box->phys_id = phys_id;
+                               uncore_box_init(box);
+                       }
+               }
+       }
+       return 0;
+}
+
+static int __cpuinit uncore_cpu_prepare(int cpu, int phys_id)
+{
+       struct intel_uncore_type *type;
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       int i, j;
+
+       for (i = 0; msr_uncores[i]; i++) {
+               type = msr_uncores[i];
+               for (j = 0; j < type->num_boxes; j++) {
+                       pmu = &type->pmus[j];
+                       if (pmu->func_id < 0)
+                               pmu->func_id = j;
+
+                       box = uncore_alloc_box(type, cpu);
+                       if (!box)
+                               return -ENOMEM;
+
+                       box->pmu = pmu;
+                       box->phys_id = phys_id;
+                       *per_cpu_ptr(pmu->box, cpu) = box;
+               }
+       }
+       return 0;
+}
+
+static void __cpuinit uncore_change_context(struct intel_uncore_type **uncores,
+                                           int old_cpu, int new_cpu)
+{
+       struct intel_uncore_type *type;
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_box *box;
+       int i, j;
+
+       for (i = 0; uncores[i]; i++) {
+               type = uncores[i];
+               for (j = 0; j < type->num_boxes; j++) {
+                       pmu = &type->pmus[j];
+                       if (old_cpu < 0)
+                               box = uncore_pmu_to_box(pmu, new_cpu);
+                       else
+                               box = uncore_pmu_to_box(pmu, old_cpu);
+                       if (!box)
+                               continue;
+
+                       if (old_cpu < 0) {
+                               WARN_ON_ONCE(box->cpu != -1);
+                               box->cpu = new_cpu;
+                               continue;
+                       }
+
+                       WARN_ON_ONCE(box->cpu != old_cpu);
+                       if (new_cpu >= 0) {
+                               uncore_pmu_cancel_hrtimer(box);
+                               perf_pmu_migrate_context(&pmu->pmu,
+                                               old_cpu, new_cpu);
+                               box->cpu = new_cpu;
+                       } else {
+                               box->cpu = -1;
+                       }
+               }
+       }
+}
+
+static void __cpuinit uncore_event_exit_cpu(int cpu)
+{
+       int i, phys_id, target;
+
+       /* if exiting cpu is used for collecting uncore events */
+       if (!cpumask_test_and_clear_cpu(cpu, &uncore_cpu_mask))
+               return;
+
+       /* find a new cpu to collect uncore events */
+       phys_id = topology_physical_package_id(cpu);
+       target = -1;
+       for_each_online_cpu(i) {
+               if (i == cpu)
+                       continue;
+               if (phys_id == topology_physical_package_id(i)) {
+                       target = i;
+                       break;
+               }
+       }
+
+       /* migrate uncore events to the new cpu */
+       if (target >= 0)
+               cpumask_set_cpu(target, &uncore_cpu_mask);
+
+       uncore_change_context(msr_uncores, cpu, target);
+       uncore_change_context(pci_uncores, cpu, target);
+}
+
+static void __cpuinit uncore_event_init_cpu(int cpu)
+{
+       int i, phys_id;
+
+       phys_id = topology_physical_package_id(cpu);
+       for_each_cpu(i, &uncore_cpu_mask) {
+               if (phys_id == topology_physical_package_id(i))
+                       return;
+       }
+
+       cpumask_set_cpu(cpu, &uncore_cpu_mask);
+
+       uncore_change_context(msr_uncores, -1, cpu);
+       uncore_change_context(pci_uncores, -1, cpu);
+}
+
+static int __cpuinit uncore_cpu_notifier(struct notifier_block *self,
+                                        unsigned long action, void *hcpu)
+{
+       unsigned int cpu = (long)hcpu;
+
+       /* allocate/free data structure for uncore box */
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_UP_PREPARE:
+               uncore_cpu_prepare(cpu, -1);
+               break;
+       case CPU_STARTING:
+               uncore_cpu_starting(cpu);
+               break;
+       case CPU_UP_CANCELED:
+       case CPU_DYING:
+               uncore_cpu_dying(cpu);
+               break;
+       default:
+               break;
+       }
+
+       /* select the cpu that collects uncore events */
+       switch (action & ~CPU_TASKS_FROZEN) {
+       case CPU_DOWN_FAILED:
+       case CPU_STARTING:
+               uncore_event_init_cpu(cpu);
+               break;
+       case CPU_DOWN_PREPARE:
+               uncore_event_exit_cpu(cpu);
+               break;
+       default:
+               break;
+       }
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block uncore_cpu_nb __cpuinitdata = {
+       .notifier_call = uncore_cpu_notifier,
+       /*
+        * to migrate uncore events, our notifier should be executed
+        * before perf core's notifier.
+        */
+       .priority = CPU_PRI_PERF + 1,
+};
+
+static void __init uncore_cpu_setup(void *dummy)
+{
+       uncore_cpu_starting(smp_processor_id());
+}
+
+static int __init uncore_cpu_init(void)
+{
+       int ret, cpu, max_cores;
+
+       max_cores = boot_cpu_data.x86_max_cores;
+       switch (boot_cpu_data.x86_model) {
+       case 26: /* Nehalem */
+       case 30:
+       case 37: /* Westmere */
+       case 44:
+               msr_uncores = nhm_msr_uncores;
+               break;
+       case 42: /* Sandy Bridge */
+               if (snb_uncore_cbox.num_boxes > max_cores)
+                       snb_uncore_cbox.num_boxes = max_cores;
+               msr_uncores = snb_msr_uncores;
+               break;
+       case 45: /* Sandy Birdge-EP */
+               if (snbep_uncore_cbox.num_boxes > max_cores)
+                       snbep_uncore_cbox.num_boxes = max_cores;
+               msr_uncores = snbep_msr_uncores;
+               break;
+       default:
+               return 0;
+       }
+
+       ret = uncore_types_init(msr_uncores);
+       if (ret)
+               return ret;
+
+       get_online_cpus();
+
+       for_each_online_cpu(cpu) {
+               int i, phys_id = topology_physical_package_id(cpu);
+
+               for_each_cpu(i, &uncore_cpu_mask) {
+                       if (phys_id == topology_physical_package_id(i)) {
+                               phys_id = -1;
+                               break;
+                       }
+               }
+               if (phys_id < 0)
+                       continue;
+
+               uncore_cpu_prepare(cpu, phys_id);
+               uncore_event_init_cpu(cpu);
+       }
+       on_each_cpu(uncore_cpu_setup, NULL, 1);
+
+       register_cpu_notifier(&uncore_cpu_nb);
+
+       put_online_cpus();
+
+       return 0;
+}
+
+static int __init uncore_pmus_register(void)
+{
+       struct intel_uncore_pmu *pmu;
+       struct intel_uncore_type *type;
+       int i, j;
+
+       for (i = 0; msr_uncores[i]; i++) {
+               type = msr_uncores[i];
+               for (j = 0; j < type->num_boxes; j++) {
+                       pmu = &type->pmus[j];
+                       uncore_pmu_register(pmu);
+               }
+       }
+
+       for (i = 0; pci_uncores[i]; i++) {
+               type = pci_uncores[i];
+               for (j = 0; j < type->num_boxes; j++) {
+                       pmu = &type->pmus[j];
+                       uncore_pmu_register(pmu);
+               }
+       }
+
+       return 0;
+}
+
+static int __init intel_uncore_init(void)
+{
+       int ret;
+
+       if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
+               return -ENODEV;
+
+       ret = uncore_pci_init();
+       if (ret)
+               goto fail;
+       ret = uncore_cpu_init();
+       if (ret) {
+               uncore_pci_exit();
+               goto fail;
+       }
+
+       uncore_pmus_register();
+       return 0;
+fail:
+       return ret;
+}
+device_initcall(intel_uncore_init);
diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.h b/arch/x86/kernel/cpu/perf_event_intel_uncore.h
new file mode 100644 (file)
index 0000000..b13e9ea
--- /dev/null
@@ -0,0 +1,424 @@
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/perf_event.h>
+#include "perf_event.h"
+
+#define UNCORE_PMU_NAME_LEN            32
+#define UNCORE_BOX_HASH_SIZE           8
+
+#define UNCORE_PMU_HRTIMER_INTERVAL    (60 * NSEC_PER_SEC)
+
+#define UNCORE_FIXED_EVENT             0xff
+#define UNCORE_PMC_IDX_MAX_GENERIC     8
+#define UNCORE_PMC_IDX_FIXED           UNCORE_PMC_IDX_MAX_GENERIC
+#define UNCORE_PMC_IDX_MAX             (UNCORE_PMC_IDX_FIXED + 1)
+
+#define UNCORE_EVENT_CONSTRAINT(c, n) EVENT_CONSTRAINT(c, n, 0xff)
+
+/* SNB event control */
+#define SNB_UNC_CTL_EV_SEL_MASK                        0x000000ff
+#define SNB_UNC_CTL_UMASK_MASK                 0x0000ff00
+#define SNB_UNC_CTL_EDGE_DET                   (1 << 18)
+#define SNB_UNC_CTL_EN                         (1 << 22)
+#define SNB_UNC_CTL_INVERT                     (1 << 23)
+#define SNB_UNC_CTL_CMASK_MASK                 0x1f000000
+#define NHM_UNC_CTL_CMASK_MASK                 0xff000000
+#define NHM_UNC_FIXED_CTR_CTL_EN               (1 << 0)
+
+#define SNB_UNC_RAW_EVENT_MASK                 (SNB_UNC_CTL_EV_SEL_MASK | \
+                                                SNB_UNC_CTL_UMASK_MASK | \
+                                                SNB_UNC_CTL_EDGE_DET | \
+                                                SNB_UNC_CTL_INVERT | \
+                                                SNB_UNC_CTL_CMASK_MASK)
+
+#define NHM_UNC_RAW_EVENT_MASK                 (SNB_UNC_CTL_EV_SEL_MASK | \
+                                                SNB_UNC_CTL_UMASK_MASK | \
+                                                SNB_UNC_CTL_EDGE_DET | \
+                                                SNB_UNC_CTL_INVERT | \
+                                                NHM_UNC_CTL_CMASK_MASK)
+
+/* SNB global control register */
+#define SNB_UNC_PERF_GLOBAL_CTL                 0x391
+#define SNB_UNC_FIXED_CTR_CTRL                  0x394
+#define SNB_UNC_FIXED_CTR                       0x395
+
+/* SNB uncore global control */
+#define SNB_UNC_GLOBAL_CTL_CORE_ALL             ((1 << 4) - 1)
+#define SNB_UNC_GLOBAL_CTL_EN                   (1 << 29)
+
+/* SNB Cbo register */
+#define SNB_UNC_CBO_0_PERFEVTSEL0               0x700
+#define SNB_UNC_CBO_0_PER_CTR0                  0x706
+#define SNB_UNC_CBO_MSR_OFFSET                  0x10
+
+/* NHM global control register */
+#define NHM_UNC_PERF_GLOBAL_CTL                 0x391
+#define NHM_UNC_FIXED_CTR                       0x394
+#define NHM_UNC_FIXED_CTR_CTRL                  0x395
+
+/* NHM uncore global control */
+#define NHM_UNC_GLOBAL_CTL_EN_PC_ALL            ((1ULL << 8) - 1)
+#define NHM_UNC_GLOBAL_CTL_EN_FC                (1ULL << 32)
+
+/* NHM uncore register */
+#define NHM_UNC_PERFEVTSEL0                     0x3c0
+#define NHM_UNC_UNCORE_PMC0                     0x3b0
+
+/* SNB-EP Box level control */
+#define SNBEP_PMON_BOX_CTL_RST_CTRL    (1 << 0)
+#define SNBEP_PMON_BOX_CTL_RST_CTRS    (1 << 1)
+#define SNBEP_PMON_BOX_CTL_FRZ         (1 << 8)
+#define SNBEP_PMON_BOX_CTL_FRZ_EN      (1 << 16)
+#define SNBEP_PMON_BOX_CTL_INT         (SNBEP_PMON_BOX_CTL_RST_CTRL | \
+                                        SNBEP_PMON_BOX_CTL_RST_CTRS | \
+                                        SNBEP_PMON_BOX_CTL_FRZ_EN)
+/* SNB-EP event control */
+#define SNBEP_PMON_CTL_EV_SEL_MASK     0x000000ff
+#define SNBEP_PMON_CTL_UMASK_MASK      0x0000ff00
+#define SNBEP_PMON_CTL_RST             (1 << 17)
+#define SNBEP_PMON_CTL_EDGE_DET                (1 << 18)
+#define SNBEP_PMON_CTL_EV_SEL_EXT      (1 << 21)       /* only for QPI */
+#define SNBEP_PMON_CTL_EN              (1 << 22)
+#define SNBEP_PMON_CTL_INVERT          (1 << 23)
+#define SNBEP_PMON_CTL_TRESH_MASK      0xff000000
+#define SNBEP_PMON_RAW_EVENT_MASK      (SNBEP_PMON_CTL_EV_SEL_MASK | \
+                                        SNBEP_PMON_CTL_UMASK_MASK | \
+                                        SNBEP_PMON_CTL_EDGE_DET | \
+                                        SNBEP_PMON_CTL_INVERT | \
+                                        SNBEP_PMON_CTL_TRESH_MASK)
+
+/* SNB-EP Ubox event control */
+#define SNBEP_U_MSR_PMON_CTL_TRESH_MASK                0x1f000000
+#define SNBEP_U_MSR_PMON_RAW_EVENT_MASK                \
+                               (SNBEP_PMON_CTL_EV_SEL_MASK | \
+                                SNBEP_PMON_CTL_UMASK_MASK | \
+                                SNBEP_PMON_CTL_EDGE_DET | \
+                                SNBEP_PMON_CTL_INVERT | \
+                                SNBEP_U_MSR_PMON_CTL_TRESH_MASK)
+
+#define SNBEP_CBO_PMON_CTL_TID_EN              (1 << 19)
+#define SNBEP_CBO_MSR_PMON_RAW_EVENT_MASK      (SNBEP_PMON_RAW_EVENT_MASK | \
+                                                SNBEP_CBO_PMON_CTL_TID_EN)
+
+/* SNB-EP PCU event control */
+#define SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK    0x0000c000
+#define SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK      0x1f000000
+#define SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT      (1 << 30)
+#define SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET    (1 << 31)
+#define SNBEP_PCU_MSR_PMON_RAW_EVENT_MASK      \
+                               (SNBEP_PMON_CTL_EV_SEL_MASK | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_SEL_MASK | \
+                                SNBEP_PMON_CTL_EDGE_DET | \
+                                SNBEP_PMON_CTL_INVERT | \
+                                SNBEP_PCU_MSR_PMON_CTL_TRESH_MASK | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_INVERT | \
+                                SNBEP_PCU_MSR_PMON_CTL_OCC_EDGE_DET)
+
+/* SNB-EP pci control register */
+#define SNBEP_PCI_PMON_BOX_CTL                 0xf4
+#define SNBEP_PCI_PMON_CTL0                    0xd8
+/* SNB-EP pci counter register */
+#define SNBEP_PCI_PMON_CTR0                    0xa0
+
+/* SNB-EP home agent register */
+#define SNBEP_HA_PCI_PMON_BOX_ADDRMATCH0       0x40
+#define SNBEP_HA_PCI_PMON_BOX_ADDRMATCH1       0x44
+#define SNBEP_HA_PCI_PMON_BOX_OPCODEMATCH      0x48
+/* SNB-EP memory controller register */
+#define SNBEP_MC_CHy_PCI_PMON_FIXED_CTL                0xf0
+#define SNBEP_MC_CHy_PCI_PMON_FIXED_CTR                0xd0
+/* SNB-EP QPI register */
+#define SNBEP_Q_Py_PCI_PMON_PKT_MATCH0         0x228
+#define SNBEP_Q_Py_PCI_PMON_PKT_MATCH1         0x22c
+#define SNBEP_Q_Py_PCI_PMON_PKT_MASK0          0x238
+#define SNBEP_Q_Py_PCI_PMON_PKT_MASK1          0x23c
+
+/* SNB-EP Ubox register */
+#define SNBEP_U_MSR_PMON_CTR0                  0xc16
+#define SNBEP_U_MSR_PMON_CTL0                  0xc10
+
+#define SNBEP_U_MSR_PMON_UCLK_FIXED_CTL                0xc08
+#define SNBEP_U_MSR_PMON_UCLK_FIXED_CTR                0xc09
+
+/* SNB-EP Cbo register */
+#define SNBEP_C0_MSR_PMON_CTR0                 0xd16
+#define SNBEP_C0_MSR_PMON_CTL0                 0xd10
+#define SNBEP_C0_MSR_PMON_BOX_CTL              0xd04
+#define SNBEP_C0_MSR_PMON_BOX_FILTER           0xd14
+#define SNBEP_CB0_MSR_PMON_BOX_FILTER_MASK     0xfffffc1f
+#define SNBEP_CBO_MSR_OFFSET                   0x20
+
+/* SNB-EP PCU register */
+#define SNBEP_PCU_MSR_PMON_CTR0                        0xc36
+#define SNBEP_PCU_MSR_PMON_CTL0                        0xc30
+#define SNBEP_PCU_MSR_PMON_BOX_CTL             0xc24
+#define SNBEP_PCU_MSR_PMON_BOX_FILTER          0xc34
+#define SNBEP_PCU_MSR_PMON_BOX_FILTER_MASK     0xffffffff
+#define SNBEP_PCU_MSR_CORE_C3_CTR              0x3fc
+#define SNBEP_PCU_MSR_CORE_C6_CTR              0x3fd
+
+struct intel_uncore_ops;
+struct intel_uncore_pmu;
+struct intel_uncore_box;
+struct uncore_event_desc;
+
+struct intel_uncore_type {
+       const char *name;
+       int num_counters;
+       int num_boxes;
+       int perf_ctr_bits;
+       int fixed_ctr_bits;
+       unsigned perf_ctr;
+       unsigned event_ctl;
+       unsigned event_mask;
+       unsigned fixed_ctr;
+       unsigned fixed_ctl;
+       unsigned box_ctl;
+       unsigned msr_offset;
+       unsigned num_shared_regs:8;
+       unsigned single_fixed:1;
+       struct event_constraint unconstrainted;
+       struct event_constraint *constraints;
+       struct intel_uncore_pmu *pmus;
+       struct intel_uncore_ops *ops;
+       struct uncore_event_desc *event_descs;
+       const struct attribute_group *attr_groups[3];
+};
+
+#define format_group attr_groups[0]
+
+struct intel_uncore_ops {
+       void (*init_box)(struct intel_uncore_box *);
+       void (*disable_box)(struct intel_uncore_box *);
+       void (*enable_box)(struct intel_uncore_box *);
+       void (*disable_event)(struct intel_uncore_box *, struct perf_event *);
+       void (*enable_event)(struct intel_uncore_box *, struct perf_event *);
+       u64 (*read_counter)(struct intel_uncore_box *, struct perf_event *);
+       int (*hw_config)(struct intel_uncore_box *, struct perf_event *);
+       struct event_constraint *(*get_constraint)(struct intel_uncore_box *,
+                                                  struct perf_event *);
+       void (*put_constraint)(struct intel_uncore_box *, struct perf_event *);
+};
+
+struct intel_uncore_pmu {
+       struct pmu pmu;
+       char name[UNCORE_PMU_NAME_LEN];
+       int pmu_idx;
+       int func_id;
+       struct intel_uncore_type *type;
+       struct intel_uncore_box ** __percpu box;
+       struct list_head box_list;
+};
+
+struct intel_uncore_extra_reg {
+       raw_spinlock_t lock;
+       u64 config1;
+       atomic_t ref;
+};
+
+struct intel_uncore_box {
+       int phys_id;
+       int n_active;   /* number of active events */
+       int n_events;
+       int cpu;        /* cpu to collect events */
+       unsigned long flags;
+       atomic_t refcnt;
+       struct perf_event *events[UNCORE_PMC_IDX_MAX];
+       struct perf_event *event_list[UNCORE_PMC_IDX_MAX];
+       unsigned long active_mask[BITS_TO_LONGS(UNCORE_PMC_IDX_MAX)];
+       u64 tags[UNCORE_PMC_IDX_MAX];
+       struct pci_dev *pci_dev;
+       struct intel_uncore_pmu *pmu;
+       struct hrtimer hrtimer;
+       struct list_head list;
+       struct intel_uncore_extra_reg shared_regs[0];
+};
+
+#define UNCORE_BOX_FLAG_INITIATED      0
+
+struct uncore_event_desc {
+       struct kobj_attribute attr;
+       const char *config;
+};
+
+#define INTEL_UNCORE_EVENT_DESC(_name, _config)                        \
+{                                                              \
+       .attr   = __ATTR(_name, 0444, uncore_event_show, NULL), \
+       .config = _config,                                      \
+}
+
+#define DEFINE_UNCORE_FORMAT_ATTR(_var, _name, _format)                        \
+static ssize_t __uncore_##_var##_show(struct kobject *kobj,            \
+                               struct kobj_attribute *attr,            \
+                               char *page)                             \
+{                                                                      \
+       BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE);                     \
+       return sprintf(page, _format "\n");                             \
+}                                                                      \
+static struct kobj_attribute format_attr_##_var =                      \
+       __ATTR(_name, 0444, __uncore_##_var##_show, NULL)
+
+
+static ssize_t uncore_event_show(struct kobject *kobj,
+                               struct kobj_attribute *attr, char *buf)
+{
+       struct uncore_event_desc *event =
+               container_of(attr, struct uncore_event_desc, attr);
+       return sprintf(buf, "%s", event->config);
+}
+
+static inline unsigned uncore_pci_box_ctl(struct intel_uncore_box *box)
+{
+       return box->pmu->type->box_ctl;
+}
+
+static inline unsigned uncore_pci_fixed_ctl(struct intel_uncore_box *box)
+{
+       return box->pmu->type->fixed_ctl;
+}
+
+static inline unsigned uncore_pci_fixed_ctr(struct intel_uncore_box *box)
+{
+       return box->pmu->type->fixed_ctr;
+}
+
+static inline
+unsigned uncore_pci_event_ctl(struct intel_uncore_box *box, int idx)
+{
+       return idx * 4 + box->pmu->type->event_ctl;
+}
+
+static inline
+unsigned uncore_pci_perf_ctr(struct intel_uncore_box *box, int idx)
+{
+       return idx * 8 + box->pmu->type->perf_ctr;
+}
+
+static inline
+unsigned uncore_msr_box_ctl(struct intel_uncore_box *box)
+{
+       if (!box->pmu->type->box_ctl)
+               return 0;
+       return box->pmu->type->box_ctl +
+               box->pmu->type->msr_offset * box->pmu->pmu_idx;
+}
+
+static inline
+unsigned uncore_msr_fixed_ctl(struct intel_uncore_box *box)
+{
+       if (!box->pmu->type->fixed_ctl)
+               return 0;
+       return box->pmu->type->fixed_ctl +
+               box->pmu->type->msr_offset * box->pmu->pmu_idx;
+}
+
+static inline
+unsigned uncore_msr_fixed_ctr(struct intel_uncore_box *box)
+{
+       return box->pmu->type->fixed_ctr +
+               box->pmu->type->msr_offset * box->pmu->pmu_idx;
+}
+
+static inline
+unsigned uncore_msr_event_ctl(struct intel_uncore_box *box, int idx)
+{
+       return idx + box->pmu->type->event_ctl +
+               box->pmu->type->msr_offset * box->pmu->pmu_idx;
+}
+
+static inline
+unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx)
+{
+       return idx + box->pmu->type->perf_ctr +
+               box->pmu->type->msr_offset * box->pmu->pmu_idx;
+}
+
+static inline
+unsigned uncore_fixed_ctl(struct intel_uncore_box *box)
+{
+       if (box->pci_dev)
+               return uncore_pci_fixed_ctl(box);
+       else
+               return uncore_msr_fixed_ctl(box);
+}
+
+static inline
+unsigned uncore_fixed_ctr(struct intel_uncore_box *box)
+{
+       if (box->pci_dev)
+               return uncore_pci_fixed_ctr(box);
+       else
+               return uncore_msr_fixed_ctr(box);
+}
+
+static inline
+unsigned uncore_event_ctl(struct intel_uncore_box *box, int idx)
+{
+       if (box->pci_dev)
+               return uncore_pci_event_ctl(box, idx);
+       else
+               return uncore_msr_event_ctl(box, idx);
+}
+
+static inline
+unsigned uncore_perf_ctr(struct intel_uncore_box *box, int idx)
+{
+       if (box->pci_dev)
+               return uncore_pci_perf_ctr(box, idx);
+       else
+               return uncore_msr_perf_ctr(box, idx);
+}
+
+static inline int uncore_perf_ctr_bits(struct intel_uncore_box *box)
+{
+       return box->pmu->type->perf_ctr_bits;
+}
+
+static inline int uncore_fixed_ctr_bits(struct intel_uncore_box *box)
+{
+       return box->pmu->type->fixed_ctr_bits;
+}
+
+static inline int uncore_num_counters(struct intel_uncore_box *box)
+{
+       return box->pmu->type->num_counters;
+}
+
+static inline void uncore_disable_box(struct intel_uncore_box *box)
+{
+       if (box->pmu->type->ops->disable_box)
+               box->pmu->type->ops->disable_box(box);
+}
+
+static inline void uncore_enable_box(struct intel_uncore_box *box)
+{
+       if (box->pmu->type->ops->enable_box)
+               box->pmu->type->ops->enable_box(box);
+}
+
+static inline void uncore_disable_event(struct intel_uncore_box *box,
+                               struct perf_event *event)
+{
+       box->pmu->type->ops->disable_event(box, event);
+}
+
+static inline void uncore_enable_event(struct intel_uncore_box *box,
+                               struct perf_event *event)
+{
+       box->pmu->type->ops->enable_event(box, event);
+}
+
+static inline u64 uncore_read_counter(struct intel_uncore_box *box,
+                               struct perf_event *event)
+{
+       return box->pmu->type->ops->read_counter(box, event);
+}
+
+static inline void uncore_box_init(struct intel_uncore_box *box)
+{
+       if (!test_and_set_bit(UNCORE_BOX_FLAG_INITIATED, &box->flags)) {
+               if (box->pmu->type->ops->init_box)
+                       box->pmu->type->ops->init_box(box);
+       }
+}
index 47124a73dd73098e1179f174a0a6cb56ea07f227..92c7e39a079ffd738ae33fc9a721631111bb5596 100644 (file)
@@ -895,8 +895,8 @@ static void p4_pmu_disable_pebs(void)
         * So at moment let leave metrics turned on forever -- it's
         * ok for now but need to be revisited!
         *
-        * (void)checking_wrmsrl(MSR_IA32_PEBS_ENABLE, (u64)0);
-        * (void)checking_wrmsrl(MSR_P4_PEBS_MATRIX_VERT, (u64)0);
+        * (void)wrmsrl_safe(MSR_IA32_PEBS_ENABLE, (u64)0);
+        * (void)wrmsrl_safe(MSR_P4_PEBS_MATRIX_VERT, (u64)0);
         */
 }
 
@@ -909,7 +909,7 @@ static inline void p4_pmu_disable_event(struct perf_event *event)
         * state we need to clear P4_CCCR_OVF, otherwise interrupt get
         * asserted again and again
         */
-       (void)checking_wrmsrl(hwc->config_base,
+       (void)wrmsrl_safe(hwc->config_base,
                (u64)(p4_config_unpack_cccr(hwc->config)) &
                        ~P4_CCCR_ENABLE & ~P4_CCCR_OVF & ~P4_CCCR_RESERVED);
 }
@@ -943,8 +943,8 @@ static void p4_pmu_enable_pebs(u64 config)
 
        bind = &p4_pebs_bind_map[idx];
 
-       (void)checking_wrmsrl(MSR_IA32_PEBS_ENABLE,     (u64)bind->metric_pebs);
-       (void)checking_wrmsrl(MSR_P4_PEBS_MATRIX_VERT,  (u64)bind->metric_vert);
+       (void)wrmsrl_safe(MSR_IA32_PEBS_ENABLE, (u64)bind->metric_pebs);
+       (void)wrmsrl_safe(MSR_P4_PEBS_MATRIX_VERT,      (u64)bind->metric_vert);
 }
 
 static void p4_pmu_enable_event(struct perf_event *event)
@@ -978,8 +978,8 @@ static void p4_pmu_enable_event(struct perf_event *event)
         */
        p4_pmu_enable_pebs(hwc->config);
 
-       (void)checking_wrmsrl(escr_addr, escr_conf);
-       (void)checking_wrmsrl(hwc->config_base,
+       (void)wrmsrl_safe(escr_addr, escr_conf);
+       (void)wrmsrl_safe(hwc->config_base,
                                (cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE);
 }
 
@@ -1325,7 +1325,7 @@ __init int p4_pmu_init(void)
        unsigned int low, high;
 
        /* If we get stripped -- indexing fails */
-       BUILD_BUG_ON(ARCH_P4_MAX_CCCR > X86_PMC_MAX_GENERIC);
+       BUILD_BUG_ON(ARCH_P4_MAX_CCCR > INTEL_PMC_MAX_GENERIC);
 
        rdmsr(MSR_IA32_MISC_ENABLE, low, high);
        if (!(low & (1 << 7))) {
index 32bcfc7dd2300d2043245e22a2351dfa65615484..e4dd0f7a04535f09b83d47d95868bcc1c152dff3 100644 (file)
@@ -71,7 +71,7 @@ p6_pmu_disable_event(struct perf_event *event)
        if (cpuc->enabled)
                val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
-       (void)checking_wrmsrl(hwc->config_base, val);
+       (void)wrmsrl_safe(hwc->config_base, val);
 }
 
 static void p6_pmu_enable_event(struct perf_event *event)
@@ -84,7 +84,7 @@ static void p6_pmu_enable_event(struct perf_event *event)
        if (cpuc->enabled)
                val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
-       (void)checking_wrmsrl(hwc->config_base, val);
+       (void)wrmsrl_safe(hwc->config_base, val);
 }
 
 PMU_FORMAT_ATTR(event, "config:0-7"    );
index 571246d81edf38da34a533391ec3841c54b45d8b..ae42418bc50f23f83d92f68e4e771daf36652978 100644 (file)
@@ -27,8 +27,8 @@ static int die_counter;
 
 void printk_address(unsigned long address, int reliable)
 {
-       printk(" [<%p>] %s%pB\n", (void *) address,
-                       reliable ? "" : "? ", (void *) address);
+       pr_cont(" [<%p>] %s%pB\n",
+               (void *)address, reliable ? "" : "? ", (void *)address);
 }
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -271,6 +271,7 @@ int __kprobes __die(const char *str, struct pt_regs *regs, long err)
                        current->thread.trap_nr, SIGSEGV) == NOTIFY_STOP)
                return 1;
 
+       print_modules();
        show_regs(regs);
 #ifdef CONFIG_X86_32
        if (user_mode_vm(regs)) {
index e0b1d783daabfb94fcd2b85ff54ffcc7709a2a16..1038a417ea531f18fcfeacddd589440989a2a1d0 100644 (file)
@@ -73,11 +73,11 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
                if (kstack_end(stack))
                        break;
                if (i && ((i % STACKSLOTS_PER_LINE) == 0))
-                       printk(KERN_CONT "\n");
-               printk(KERN_CONT " %08lx", *stack++);
+                       pr_cont("\n");
+               pr_cont(" %08lx", *stack++);
                touch_nmi_watchdog();
        }
-       printk(KERN_CONT "\n");
+       pr_cont("\n");
        show_trace_log_lvl(task, regs, sp, bp, log_lvl);
 }
 
@@ -86,12 +86,11 @@ void show_regs(struct pt_regs *regs)
 {
        int i;
 
-       print_modules();
        __show_regs(regs, !user_mode_vm(regs));
 
-       printk(KERN_EMERG "Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)\n",
-               TASK_COMM_LEN, current->comm, task_pid_nr(current),
-               current_thread_info(), current, task_thread_info(current));
+       pr_emerg("Process %.*s (pid: %d, ti=%p task=%p task.ti=%p)\n",
+                TASK_COMM_LEN, current->comm, task_pid_nr(current),
+                current_thread_info(), current, task_thread_info(current));
        /*
         * When in-kernel, we also print out the stack and code at the
         * time of the fault..
@@ -102,10 +101,10 @@ void show_regs(struct pt_regs *regs)
                unsigned char c;
                u8 *ip;
 
-               printk(KERN_EMERG "Stack:\n");
+               pr_emerg("Stack:\n");
                show_stack_log_lvl(NULL, regs, &regs->sp, 0, KERN_EMERG);
 
-               printk(KERN_EMERG "Code: ");
+               pr_emerg("Code:");
 
                ip = (u8 *)regs->ip - code_prologue;
                if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
@@ -116,16 +115,16 @@ void show_regs(struct pt_regs *regs)
                for (i = 0; i < code_len; i++, ip++) {
                        if (ip < (u8 *)PAGE_OFFSET ||
                                        probe_kernel_address(ip, c)) {
-                               printk(KERN_CONT " Bad EIP value.");
+                               pr_cont("  Bad EIP value.");
                                break;
                        }
                        if (ip == (u8 *)regs->ip)
-                               printk(KERN_CONT "<%02x> ", c);
+                               pr_cont(" <%02x>", c);
                        else
-                               printk(KERN_CONT "%02x ", c);
+                               pr_cont(" %02x", c);
                }
        }
-       printk(KERN_CONT "\n");
+       pr_cont("\n");
 }
 
 int is_valid_bugaddr(unsigned long ip)
index 791b76122aa8b0b627eb39e3ac6028701a9a868c..b653675d5288476c2f864772fa63e4739f9de06f 100644 (file)
@@ -228,20 +228,20 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
                if (stack >= irq_stack && stack <= irq_stack_end) {
                        if (stack == irq_stack_end) {
                                stack = (unsigned long *) (irq_stack_end[-1]);
-                               printk(KERN_CONT " <EOI> ");
+                               pr_cont(" <EOI> ");
                        }
                } else {
                if (((long) stack & (THREAD_SIZE-1)) == 0)
                        break;
                }
                if (i && ((i % STACKSLOTS_PER_LINE) == 0))
-                       printk(KERN_CONT "\n");
-               printk(KERN_CONT " %016lx", *stack++);
+                       pr_cont("\n");
+               pr_cont(" %016lx", *stack++);
                touch_nmi_watchdog();
        }
        preempt_enable();
 
-       printk(KERN_CONT "\n");
+       pr_cont("\n");
        show_trace_log_lvl(task, regs, sp, bp, log_lvl);
 }
 
@@ -254,10 +254,9 @@ void show_regs(struct pt_regs *regs)
 
        sp = regs->sp;
        printk("CPU %d ", cpu);
-       print_modules();
        __show_regs(regs, 1);
-       printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
-               cur->comm, cur->pid, task_thread_info(cur), cur);
+       printk(KERN_DEFAULT "Process %s (pid: %d, threadinfo %p, task %p)\n",
+              cur->comm, cur->pid, task_thread_info(cur), cur);
 
        /*
         * When in-kernel, we also print out the stack and code at the
@@ -284,16 +283,16 @@ void show_regs(struct pt_regs *regs)
                for (i = 0; i < code_len; i++, ip++) {
                        if (ip < (u8 *)PAGE_OFFSET ||
                                        probe_kernel_address(ip, c)) {
-                               printk(KERN_CONT " Bad RIP value.");
+                               pr_cont(" Bad RIP value.");
                                break;
                        }
                        if (ip == (u8 *)regs->ip)
-                               printk(KERN_CONT "<%02x> ", c);
+                               pr_cont("<%02x> ", c);
                        else
-                               printk(KERN_CONT "%02x ", c);
+                               pr_cont("%02x ", c);
                }
        }
-       printk(KERN_CONT "\n");
+       pr_cont("\n");
 }
 
 int is_valid_bugaddr(unsigned long ip)
index 7d65133b51bede19fc529fd82691de2c01926f60..111f6bbd8b38afb1a175d65dbbde7a981a0de6f7 100644 (file)
@@ -1758,10 +1758,30 @@ end_repeat_nmi:
         */
        call save_paranoid
        DEFAULT_FRAME 0
+
+       /*
+        * Save off the CR2 register. If we take a page fault in the NMI then
+        * it could corrupt the CR2 value. If the NMI preempts a page fault
+        * handler before it was able to read the CR2 register, and then the
+        * NMI itself takes a page fault, the page fault that was preempted
+        * will read the information from the NMI page fault and not the
+        * origin fault. Save it off and restore it if it changes.
+        * Use the r12 callee-saved register.
+        */
+       movq %cr2, %r12
+
        /* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */
        movq %rsp,%rdi
        movq $-1,%rsi
        call do_nmi
+
+       /* Did the NMI take a page fault? Restore cr2 if it did */
+       movq %cr2, %rcx
+       cmpq %rcx, %r12
+       je 1f
+       movq %r12, %cr2
+1:
+       
        testl %ebx,%ebx                         /* swapgs needed? */
        jnz nmi_restore
 nmi_swapgs:
index 3dafc6003b7c4a5c177238f3f21d652cdb20ca30..1f5f1d5d2a022b21a6871c083af70f09b9def90f 100644 (file)
@@ -294,9 +294,9 @@ void fixup_irqs(void)
                raw_spin_unlock(&desc->lock);
 
                if (break_affinity && set_affinity)
-                       printk("Broke affinity for irq %i\n", irq);
+                       pr_notice("Broke affinity for irq %i\n", irq);
                else if (!set_affinity)
-                       printk("Cannot set affinity for irq %i\n", irq);
+                       pr_notice("Cannot set affinity for irq %i\n", irq);
        }
 
        /*
index fbdfc6917180f8f5379033cc408d164573d027e5..4873e62db6a18468b23736c5f4adfd2de8b3b85b 100644 (file)
@@ -87,6 +87,7 @@
 #include <asm/microcode.h>
 #include <asm/processor.h>
 #include <asm/cpu_device_id.h>
+#include <asm/perf_event.h>
 
 MODULE_DESCRIPTION("Microcode Update Driver");
 MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
@@ -277,7 +278,6 @@ static int reload_for_cpu(int cpu)
        struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
        int err = 0;
 
-       mutex_lock(&microcode_mutex);
        if (uci->valid) {
                enum ucode_state ustate;
 
@@ -288,7 +288,6 @@ static int reload_for_cpu(int cpu)
                        if (ustate == UCODE_ERROR)
                                err = -EINVAL;
        }
-       mutex_unlock(&microcode_mutex);
 
        return err;
 }
@@ -298,19 +297,31 @@ static ssize_t reload_store(struct device *dev,
                            const char *buf, size_t size)
 {
        unsigned long val;
-       int cpu = dev->id;
-       ssize_t ret = 0;
+       int cpu;
+       ssize_t ret = 0, tmp_ret;
 
        ret = kstrtoul(buf, 0, &val);
        if (ret)
                return ret;
 
-       if (val == 1) {
-               get_online_cpus();
-               if (cpu_online(cpu))
-                       ret = reload_for_cpu(cpu);
-               put_online_cpus();
+       if (val != 1)
+               return size;
+
+       get_online_cpus();
+       mutex_lock(&microcode_mutex);
+       for_each_online_cpu(cpu) {
+               tmp_ret = reload_for_cpu(cpu);
+               if (tmp_ret != 0)
+                       pr_warn("Error reloading microcode on CPU %d\n", cpu);
+
+               /* save retval of the first encountered reload error */
+               if (!ret)
+                       ret = tmp_ret;
        }
+       if (!ret)
+               perf_check_microcode();
+       mutex_unlock(&microcode_mutex);
+       put_online_cpus();
 
        if (!ret)
                ret = size;
@@ -339,7 +350,6 @@ static DEVICE_ATTR(version, 0400, version_show, NULL);
 static DEVICE_ATTR(processor_flags, 0400, pf_show, NULL);
 
 static struct attribute *mc_default_attrs[] = {
-       &dev_attr_reload.attr,
        &dev_attr_version.attr,
        &dev_attr_processor_flags.attr,
        NULL
@@ -504,7 +514,7 @@ static struct notifier_block __refdata mc_cpu_notifier = {
 
 #ifdef MODULE
 /* Autoload on Intel and AMD systems */
-static const struct x86_cpu_id microcode_id[] = {
+static const struct x86_cpu_id __initconst microcode_id[] = {
 #ifdef CONFIG_MICROCODE_INTEL
        { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, },
 #endif
@@ -516,6 +526,16 @@ static const struct x86_cpu_id microcode_id[] = {
 MODULE_DEVICE_TABLE(x86cpu, microcode_id);
 #endif
 
+static struct attribute *cpu_root_microcode_attrs[] = {
+       &dev_attr_reload.attr,
+       NULL
+};
+
+static struct attribute_group cpu_root_microcode_group = {
+       .name  = "microcode",
+       .attrs = cpu_root_microcode_attrs,
+};
+
 static int __init microcode_init(void)
 {
        struct cpuinfo_x86 *c = &cpu_data(0);
@@ -540,16 +560,25 @@ static int __init microcode_init(void)
        mutex_lock(&microcode_mutex);
 
        error = subsys_interface_register(&mc_cpu_interface);
-
+       if (!error)
+               perf_check_microcode();
        mutex_unlock(&microcode_mutex);
        put_online_cpus();
 
        if (error)
                goto out_pdev;
 
+       error = sysfs_create_group(&cpu_subsys.dev_root->kobj,
+                                  &cpu_root_microcode_group);
+
+       if (error) {
+               pr_err("Error creating microcode group!\n");
+               goto out_driver;
+       }
+
        error = microcode_dev_init();
        if (error)
-               goto out_driver;
+               goto out_ucode_group;
 
        register_syscore_ops(&mc_syscore_ops);
        register_hotcpu_notifier(&mc_cpu_notifier);
@@ -559,7 +588,11 @@ static int __init microcode_init(void)
 
        return 0;
 
-out_driver:
+ out_ucode_group:
+       sysfs_remove_group(&cpu_subsys.dev_root->kobj,
+                          &cpu_root_microcode_group);
+
+ out_driver:
        get_online_cpus();
        mutex_lock(&microcode_mutex);
 
@@ -568,7 +601,7 @@ out_driver:
        mutex_unlock(&microcode_mutex);
        put_online_cpus();
 
-out_pdev:
+ out_pdev:
        platform_device_unregister(microcode_pdev);
        return error;
 
@@ -584,6 +617,9 @@ static void __exit microcode_exit(void)
        unregister_hotcpu_notifier(&mc_cpu_notifier);
        unregister_syscore_ops(&mc_syscore_ops);
 
+       sysfs_remove_group(&cpu_subsys.dev_root->kobj,
+                          &cpu_root_microcode_group);
+
        get_online_cpus();
        mutex_lock(&microcode_mutex);
 
index f21fd94ac89700b912ce5392c1bc7381ced99601..202494d2ec6e26ab5216ac469eaeebf29594cb7e 100644 (file)
@@ -15,6 +15,9 @@
     along with this program; if not, write to the Free Software
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/moduleloader.h>
 #include <linux/elf.h>
 #include <linux/vmalloc.h>
 #include <asm/pgtable.h>
 
 #if 0
-#define DEBUGP printk
+#define DEBUGP(fmt, ...)                               \
+       printk(KERN_DEBUG fmt, ##__VA_ARGS__)
 #else
-#define DEBUGP(fmt...)
+#define DEBUGP(fmt, ...)                               \
+do {                                                   \
+       if (0)                                          \
+               printk(KERN_DEBUG fmt, ##__VA_ARGS__);  \
+} while (0)
 #endif
 
 void *module_alloc(unsigned long size)
@@ -56,8 +64,8 @@ int apply_relocate(Elf32_Shdr *sechdrs,
        Elf32_Sym *sym;
        uint32_t *location;
 
-       DEBUGP("Applying relocate section %u to %u\n", relsec,
-              sechdrs[relsec].sh_info);
+       DEBUGP("Applying relocate section %u to %u\n",
+              relsec, sechdrs[relsec].sh_info);
        for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
                /* This is where to make the change */
                location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
@@ -77,7 +85,7 @@ int apply_relocate(Elf32_Shdr *sechdrs,
                        *location += sym->st_value - (uint32_t)location;
                        break;
                default:
-                       printk(KERN_ERR "module %s: Unknown relocation: %u\n",
+                       pr_err("%s: Unknown relocation: %u\n",
                               me->name, ELF32_R_TYPE(rel[i].r_info));
                        return -ENOEXEC;
                }
@@ -97,8 +105,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
        void *loc;
        u64 val;
 
-       DEBUGP("Applying relocate section %u to %u\n", relsec,
-              sechdrs[relsec].sh_info);
+       DEBUGP("Applying relocate section %u to %u\n",
+              relsec, sechdrs[relsec].sh_info);
        for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
                /* This is where to make the change */
                loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
@@ -110,8 +118,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
                        + ELF64_R_SYM(rel[i].r_info);
 
                DEBUGP("type %d st_value %Lx r_addend %Lx loc %Lx\n",
-                       (int)ELF64_R_TYPE(rel[i].r_info),
-                       sym->st_value, rel[i].r_addend, (u64)loc);
+                      (int)ELF64_R_TYPE(rel[i].r_info),
+                      sym->st_value, rel[i].r_addend, (u64)loc);
 
                val = sym->st_value + rel[i].r_addend;
 
@@ -140,7 +148,7 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
 #endif
                        break;
                default:
-                       printk(KERN_ERR "module %s: Unknown rela relocation: %llu\n",
+                       pr_err("%s: Unknown rela relocation: %llu\n",
                               me->name, ELF64_R_TYPE(rel[i].r_info));
                        return -ENOEXEC;
                }
@@ -148,9 +156,9 @@ int apply_relocate_add(Elf64_Shdr *sechdrs,
        return 0;
 
 overflow:
-       printk(KERN_ERR "overflow in relocation type %d val %Lx\n",
+       pr_err("overflow in relocation type %d val %Lx\n",
               (int)ELF64_R_TYPE(rel[i].r_info), val);
-       printk(KERN_ERR "`%s' likely not compiled with -mcmodel=kernel\n",
+       pr_err("`%s' likely not compiled with -mcmodel=kernel\n",
               me->name);
        return -ENOEXEC;
 }
index a0b2f84457bebfb88de00f547c9b8db930abca5a..f84f5c57de35b0bb5693067c3799de8093ad237e 100644 (file)
@@ -365,8 +365,9 @@ static __kprobes void default_do_nmi(struct pt_regs *regs)
 #ifdef CONFIG_X86_32
 /*
  * For i386, NMIs use the same stack as the kernel, and we can
- * add a workaround to the iret problem in C. Simply have 3 states
- * the NMI can be in.
+ * add a workaround to the iret problem in C (preventing nested
+ * NMIs if an NMI takes a trap). Simply have 3 states the NMI
+ * can be in:
  *
  *  1) not running
  *  2) executing
@@ -383,32 +384,50 @@ static __kprobes void default_do_nmi(struct pt_regs *regs)
  * If an NMI hits a breakpoint that executes an iret, another
  * NMI can preempt it. We do not want to allow this new NMI
  * to run, but we want to execute it when the first one finishes.
- * We set the state to "latched", and the first NMI will perform
- * an cmpxchg on the state, and if it doesn't successfully
- * reset the state to "not running" it will restart the next
- * NMI.
+ * We set the state to "latched", and the exit of the first NMI will
+ * perform a dec_return, if the result is zero (NOT_RUNNING), then
+ * it will simply exit the NMI handler. If not, the dec_return
+ * would have set the state to NMI_EXECUTING (what we want it to
+ * be when we are running). In this case, we simply jump back
+ * to rerun the NMI handler again, and restart the 'latched' NMI.
+ *
+ * No trap (breakpoint or page fault) should be hit before nmi_restart,
+ * thus there is no race between the first check of state for NOT_RUNNING
+ * and setting it to NMI_EXECUTING. The HW will prevent nested NMIs
+ * at this point.
+ *
+ * In case the NMI takes a page fault, we need to save off the CR2
+ * because the NMI could have preempted another page fault and corrupt
+ * the CR2 that is about to be read. As nested NMIs must be restarted
+ * and they can not take breakpoints or page faults, the update of the
+ * CR2 must be done before converting the nmi state back to NOT_RUNNING.
+ * Otherwise, there would be a race of another nested NMI coming in
+ * after setting state to NOT_RUNNING but before updating the nmi_cr2.
  */
 enum nmi_states {
-       NMI_NOT_RUNNING,
+       NMI_NOT_RUNNING = 0,
        NMI_EXECUTING,
        NMI_LATCHED,
 };
 static DEFINE_PER_CPU(enum nmi_states, nmi_state);
+static DEFINE_PER_CPU(unsigned long, nmi_cr2);
 
 #define nmi_nesting_preprocess(regs)                                   \
        do {                                                            \
-               if (__get_cpu_var(nmi_state) != NMI_NOT_RUNNING) {      \
-                       __get_cpu_var(nmi_state) = NMI_LATCHED;         \
+               if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) {      \
+                       this_cpu_write(nmi_state, NMI_LATCHED);         \
                        return;                                         \
                }                                                       \
-       nmi_restart:                                                    \
-               __get_cpu_var(nmi_state) = NMI_EXECUTING;               \
-       } while (0)
+               this_cpu_write(nmi_state, NMI_EXECUTING);               \
+               this_cpu_write(nmi_cr2, read_cr2());                    \
+       } while (0);                                                    \
+       nmi_restart:
 
 #define nmi_nesting_postprocess()                                      \
        do {                                                            \
-               if (cmpxchg(&__get_cpu_var(nmi_state),                  \
-                   NMI_EXECUTING, NMI_NOT_RUNNING) != NMI_EXECUTING)   \
+               if (unlikely(this_cpu_read(nmi_cr2) != read_cr2()))     \
+                       write_cr2(this_cpu_read(nmi_cr2));              \
+               if (this_cpu_dec_return(nmi_state))                     \
                        goto nmi_restart;                               \
        } while (0)
 #else /* x86_64 */
index 149b8d9c6ad45a199cfa1f55b17df3562afe4127..6d9582ec0324936646da2b537602ae267b6a4a64 100644 (file)
@@ -42,7 +42,8 @@ static int __init nmi_unk_cb(unsigned int val, struct pt_regs *regs)
 static void __init init_nmi_testsuite(void)
 {
        /* trap all the unknown NMIs we may generate */
-       register_nmi_handler_initonly(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk");
+       register_nmi_handler(NMI_UNKNOWN, nmi_unk_cb, 0, "nmi_selftest_unk",
+                       __initdata);
 }
 
 static void __init cleanup_nmi_testsuite(void)
@@ -64,8 +65,8 @@ static void __init test_nmi_ipi(struct cpumask *mask)
 {
        unsigned long timeout;
 
-       if (register_nmi_handler_initonly(NMI_LOCAL, test_nmi_ipi_callback,
-                                NMI_FLAG_FIRST, "nmi_selftest")) {
+       if (register_nmi_handler(NMI_LOCAL, test_nmi_ipi_callback,
+                                NMI_FLAG_FIRST, "nmi_selftest", __initdata)) {
                nmi_fail = FAILURE;
                return;
        }
index 9ce885996fd718bc80b5f0bf52efec81e27b3b2d..17fff18a103104431c0e10e1543af6f027f64f72 100644 (file)
@@ -352,9 +352,7 @@ struct pv_cpu_ops pv_cpu_ops = {
 #endif
        .wbinvd = native_wbinvd,
        .read_msr = native_read_msr_safe,
-       .rdmsr_regs = native_rdmsr_safe_regs,
        .write_msr = native_write_msr_safe,
-       .wrmsr_regs = native_wrmsr_safe_regs,
        .read_tsc = native_read_tsc,
        .read_pmc = native_read_pmc,
        .read_tscp = native_read_tscp,
index b72838bae64ab296bfd0bdd9e63297132d6c56e5..299d49302e7d2a46cedcd00230f8a4ed8b027c5b 100644 (file)
@@ -22,6 +22,8 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  */
 
+#define pr_fmt(fmt) "Calgary: " fmt
+
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
@@ -245,7 +247,7 @@ static unsigned long iommu_range_alloc(struct device *dev,
                offset = iommu_area_alloc(tbl->it_map, tbl->it_size, 0,
                                          npages, 0, boundary_size, 0);
                if (offset == ~0UL) {
-                       printk(KERN_WARNING "Calgary: IOMMU full.\n");
+                       pr_warn("IOMMU full\n");
                        spin_unlock_irqrestore(&tbl->it_lock, flags);
                        if (panic_on_overflow)
                                panic("Calgary: fix the allocator.\n");
@@ -271,8 +273,8 @@ static dma_addr_t iommu_alloc(struct device *dev, struct iommu_table *tbl,
        entry = iommu_range_alloc(dev, tbl, npages);
 
        if (unlikely(entry == DMA_ERROR_CODE)) {
-               printk(KERN_WARNING "Calgary: failed to allocate %u pages in "
-                      "iommu %p\n", npages, tbl);
+               pr_warn("failed to allocate %u pages in iommu %p\n",
+                       npages, tbl);
                return DMA_ERROR_CODE;
        }
 
@@ -561,8 +563,7 @@ static void calgary_tce_cache_blast(struct iommu_table *tbl)
                i++;
        } while ((val & 0xff) != 0xff && i < 100);
        if (i == 100)
-               printk(KERN_WARNING "Calgary: PCI bus not quiesced, "
-                      "continuing anyway\n");
+               pr_warn("PCI bus not quiesced, continuing anyway\n");
 
        /* invalidate TCE cache */
        target = calgary_reg(bbar, tar_offset(tbl->it_busno));
@@ -604,8 +605,7 @@ begin:
                i++;
        } while ((val64 & 0xff) != 0xff && i < 100);
        if (i == 100)
-               printk(KERN_WARNING "CalIOC2: PCI bus not quiesced, "
-                      "continuing anyway\n");
+               pr_warn("CalIOC2: PCI bus not quiesced, continuing anyway\n");
 
        /* 3. poll Page Migration DEBUG for SoftStopFault */
        target = calgary_reg(bbar, phb_offset(bus) | PHB_PAGE_MIG_DEBUG);
@@ -617,8 +617,7 @@ begin:
                if (++count < 100)
                        goto begin;
                else {
-                       printk(KERN_WARNING "CalIOC2: too many SoftStopFaults, "
-                              "aborting TCE cache flush sequence!\n");
+                       pr_warn("CalIOC2: too many SoftStopFaults, aborting TCE cache flush sequence!\n");
                        return; /* pray for the best */
                }
        }
@@ -840,8 +839,8 @@ static void calgary_dump_error_regs(struct iommu_table *tbl)
        plssr = be32_to_cpu(readl(target));
 
        /* If no error, the agent ID in the CSR is not valid */
-       printk(KERN_EMERG "Calgary: DMA error on Calgary PHB 0x%x, "
-              "0x%08x@CSR 0x%08x@PLSSR\n", tbl->it_busno, csr, plssr);
+       pr_emerg("DMA error on Calgary PHB 0x%x, 0x%08x@CSR 0x%08x@PLSSR\n",
+                tbl->it_busno, csr, plssr);
 }
 
 static void calioc2_dump_error_regs(struct iommu_table *tbl)
@@ -867,22 +866,21 @@ static void calioc2_dump_error_regs(struct iommu_table *tbl)
        target = calgary_reg(bbar, phboff | 0x800);
        mck = be32_to_cpu(readl(target));
 
-       printk(KERN_EMERG "Calgary: DMA error on CalIOC2 PHB 0x%x\n",
-              tbl->it_busno);
+       pr_emerg("DMA error on CalIOC2 PHB 0x%x\n", tbl->it_busno);
 
-       printk(KERN_EMERG "Calgary: 0x%08x@CSR 0x%08x@PLSSR 0x%08x@CSMR 0x%08x@MCK\n",
-              csr, plssr, csmr, mck);
+       pr_emerg("0x%08x@CSR 0x%08x@PLSSR 0x%08x@CSMR 0x%08x@MCK\n",
+                csr, plssr, csmr, mck);
 
        /* dump rest of error regs */
-       printk(KERN_EMERG "Calgary: ");
+       pr_emerg("");
        for (i = 0; i < ARRAY_SIZE(errregs); i++) {
                /* err regs are at 0x810 - 0x870 */
                erroff = (0x810 + (i * 0x10));
                target = calgary_reg(bbar, phboff | erroff);
                errregs[i] = be32_to_cpu(readl(target));
-               printk("0x%08x@0x%lx ", errregs[i], erroff);
+               pr_cont("0x%08x@0x%lx ", errregs[i], erroff);
        }
-       printk("\n");
+       pr_cont("\n");
 
        /* root complex status */
        target = calgary_reg(bbar, phboff | PHB_ROOT_COMPLEX_STATUS);
index 735279e54e59a56d3f3ce97288f2d81fc98491d6..ef6a8456f719b320e36707becfa08697803f4547 100644 (file)
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/errno.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
@@ -145,16 +147,14 @@ void show_regs_common(void)
        /* Board Name is optional */
        board = dmi_get_system_info(DMI_BOARD_NAME);
 
-       printk(KERN_CONT "\n");
-       printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s",
-               current->pid, current->comm, print_tainted(),
-               init_utsname()->release,
-               (int)strcspn(init_utsname()->version, " "),
-               init_utsname()->version);
-       printk(KERN_CONT " %s %s", vendor, product);
-       if (board)
-               printk(KERN_CONT "/%s", board);
-       printk(KERN_CONT "\n");
+       printk(KERN_DEFAULT "Pid: %d, comm: %.20s %s %s %.*s %s %s%s%s\n",
+              current->pid, current->comm, print_tainted(),
+              init_utsname()->release,
+              (int)strcspn(init_utsname()->version, " "),
+              init_utsname()->version,
+              vendor, product,
+              board ? "/" : "",
+              board ? board : "");
 }
 
 void flush_thread(void)
@@ -645,7 +645,7 @@ static void amd_e400_idle(void)
                        amd_e400_c1e_detected = true;
                        if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
                                mark_tsc_unstable("TSC halt in AMD C1E");
-                       printk(KERN_INFO "System has AMD C1E enabled\n");
+                       pr_info("System has AMD C1E enabled\n");
                }
        }
 
@@ -659,8 +659,7 @@ static void amd_e400_idle(void)
                         */
                        clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_FORCE,
                                           &cpu);
-                       printk(KERN_INFO "Switch to broadcast mode on CPU%d\n",
-                              cpu);
+                       pr_info("Switch to broadcast mode on CPU%d\n", cpu);
                }
                clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
 
@@ -681,8 +680,7 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_SMP
        if (pm_idle == poll_idle && smp_num_siblings > 1) {
-               printk_once(KERN_WARNING "WARNING: polling idle and HT enabled,"
-                       " performance may degrade.\n");
+               pr_warn_once("WARNING: polling idle and HT enabled, performance may degrade\n");
        }
 #endif
        if (pm_idle)
@@ -692,11 +690,11 @@ void __cpuinit select_idle_routine(const struct cpuinfo_x86 *c)
                /*
                 * One CPU supports mwait => All CPUs supports mwait
                 */
-               printk(KERN_INFO "using mwait in idle threads.\n");
+               pr_info("using mwait in idle threads\n");
                pm_idle = mwait_idle;
        } else if (cpu_has_amd_erratum(amd_erratum_400)) {
                /* E400: APIC timer interrupt does not wake up CPU from C1e */
-               printk(KERN_INFO "using AMD E400 aware idle routine\n");
+               pr_info("using AMD E400 aware idle routine\n");
                pm_idle = amd_e400_idle;
        } else
                pm_idle = default_idle;
@@ -715,7 +713,7 @@ static int __init idle_setup(char *str)
                return -EINVAL;
 
        if (!strcmp(str, "poll")) {
-               printk("using polling idle threads.\n");
+               pr_info("using polling idle threads\n");
                pm_idle = poll_idle;
                boot_option_idle_override = IDLE_POLL;
        } else if (!strcmp(str, "mwait")) {
index 61cdf7fdf09961757d7a6f8ba595df63a5a123b3..0a980c9d7cb885abb3a46d9b9572ce1ed8acca20 100644 (file)
@@ -117,10 +117,10 @@ void release_thread(struct task_struct *dead_task)
 {
        if (dead_task->mm) {
                if (dead_task->mm->context.size) {
-                       printk("WARNING: dead process %8s still has LDT? <%p/%d>\n",
-                                       dead_task->comm,
-                                       dead_task->mm->context.ldt,
-                                       dead_task->mm->context.size);
+                       pr_warn("WARNING: dead process %8s still has LDT? <%p/%d>\n",
+                               dead_task->comm,
+                               dead_task->mm->context.ldt,
+                               dead_task->mm->context.size);
                        BUG();
                }
        }
@@ -466,7 +466,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
                        task->thread.gs = addr;
                        if (doit) {
                                load_gs_index(0);
-                               ret = checking_wrmsrl(MSR_KERNEL_GS_BASE, addr);
+                               ret = wrmsrl_safe(MSR_KERNEL_GS_BASE, addr);
                        }
                }
                put_cpu();
@@ -494,7 +494,7 @@ long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
                                /* set the selector to 0 to not confuse
                                   __switch_to */
                                loadsegment(fs, 0);
-                               ret = checking_wrmsrl(MSR_FS_BASE, addr);
+                               ret = wrmsrl_safe(MSR_FS_BASE, addr);
                        }
                }
                put_cpu();
index 5de92f1abd76fc4d055a42af0c690284c65b7f2d..52190a938b4ac0d26a85704e6db4c131dd938aca 100644 (file)
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/reboot.h>
 #include <linux/init.h>
 #include <asm/virtext.h>
 #include <asm/cpu.h>
 #include <asm/nmi.h>
+#include <asm/smp.h>
 
-#ifdef CONFIG_X86_32
-# include <linux/ctype.h>
-# include <linux/mc146818rtc.h>
-# include <asm/realmode.h>
-#else
-# include <asm/x86_init.h>
-#endif
+#include <linux/ctype.h>
+#include <linux/mc146818rtc.h>
+#include <asm/realmode.h>
+#include <asm/x86_init.h>
 
 /*
  * Power off function, if any
@@ -49,7 +49,7 @@ int reboot_force;
  */
 static int reboot_default = 1;
 
-#if defined(CONFIG_X86_32) && defined(CONFIG_SMP)
+#ifdef CONFIG_SMP
 static int reboot_cpu = -1;
 #endif
 
@@ -67,8 +67,8 @@ bool port_cf9_safe = false;
  * reboot=b[ios] | s[mp] | t[riple] | k[bd] | e[fi] [, [w]arm | [c]old] | p[ci]
  * warm   Don't set the cold reboot flag
  * cold   Set the cold reboot flag
- * bios   Reboot by jumping through the BIOS (only for X86_32)
- * smp    Reboot by executing reset on BSP or other CPU (only for X86_32)
+ * bios   Reboot by jumping through the BIOS
+ * smp    Reboot by executing reset on BSP or other CPU
  * triple Force a triple fault (init)
  * kbd    Use the keyboard controller. cold reset (default)
  * acpi   Use the RESET_REG in the FADT
@@ -95,7 +95,6 @@ static int __init reboot_setup(char *str)
                        reboot_mode = 0;
                        break;
 
-#ifdef CONFIG_X86_32
 #ifdef CONFIG_SMP
                case 's':
                        if (isdigit(*(str+1))) {
@@ -112,7 +111,6 @@ static int __init reboot_setup(char *str)
 #endif /* CONFIG_SMP */
 
                case 'b':
-#endif
                case 'a':
                case 'k':
                case 't':
@@ -138,7 +136,6 @@ static int __init reboot_setup(char *str)
 __setup("reboot=", reboot_setup);
 
 
-#ifdef CONFIG_X86_32
 /*
  * Reboot options and system auto-detection code provided by
  * Dell Inc. so their systems "just work". :-)
@@ -152,16 +149,14 @@ static int __init set_bios_reboot(const struct dmi_system_id *d)
 {
        if (reboot_type != BOOT_BIOS) {
                reboot_type = BOOT_BIOS;
-               printk(KERN_INFO "%s series board detected. Selecting BIOS-method for reboots.\n", d->ident);
+               pr_info("%s series board detected. Selecting %s-method for reboots.\n",
+                       "BIOS", d->ident);
        }
        return 0;
 }
 
-void machine_real_restart(unsigned int type)
+void __noreturn machine_real_restart(unsigned int type)
 {
-       void (*restart_lowmem)(unsigned int) = (void (*)(unsigned int))
-               real_mode_header->machine_real_restart_asm;
-
        local_irq_disable();
 
        /*
@@ -181,25 +176,28 @@ void machine_real_restart(unsigned int type)
        /*
         * Switch back to the initial page table.
         */
+#ifdef CONFIG_X86_32
        load_cr3(initial_page_table);
-
-       /*
-        * Write 0x1234 to absolute memory location 0x472.  The BIOS reads
-        * this on booting to tell it to "Bypass memory test (also warm
-        * boot)".  This seems like a fairly standard thing that gets set by
-        * REBOOT.COM programs, and the previous reset routine did this
-        * too. */
-       *((unsigned short *)0x472) = reboot_mode;
+#else
+       write_cr3(real_mode_header->trampoline_pgd);
+#endif
 
        /* Jump to the identity-mapped low memory code */
-       restart_lowmem(type);
+#ifdef CONFIG_X86_32
+       asm volatile("jmpl *%0" : :
+                    "rm" (real_mode_header->machine_real_restart_asm),
+                    "a" (type));
+#else
+       asm volatile("ljmpl *%0" : :
+                    "m" (real_mode_header->machine_real_restart_asm),
+                    "D" (type));
+#endif
+       unreachable();
 }
 #ifdef CONFIG_APM_MODULE
 EXPORT_SYMBOL(machine_real_restart);
 #endif
 
-#endif /* CONFIG_X86_32 */
-
 /*
  * Some Apple MacBook and MacBookPro's needs reboot=p to be able to reboot
  */
@@ -207,8 +205,8 @@ static int __init set_pci_reboot(const struct dmi_system_id *d)
 {
        if (reboot_type != BOOT_CF9) {
                reboot_type = BOOT_CF9;
-               printk(KERN_INFO "%s series board detected. "
-                      "Selecting PCI-method for reboots.\n", d->ident);
+               pr_info("%s series board detected. Selecting %s-method for reboots.\n",
+                       "PCI", d->ident);
        }
        return 0;
 }
@@ -217,17 +215,16 @@ static int __init set_kbd_reboot(const struct dmi_system_id *d)
 {
        if (reboot_type != BOOT_KBD) {
                reboot_type = BOOT_KBD;
-               printk(KERN_INFO "%s series board detected. Selecting KBD-method for reboot.\n", d->ident);
+               pr_info("%s series board detected. Selecting %s-method for reboot.\n",
+                       "KBD", d->ident);
        }
        return 0;
 }
 
 /*
- * This is a single dmi_table handling all reboot quirks.  Note that
- * REBOOT_BIOS is only available for 32bit
+ * This is a single dmi_table handling all reboot quirks.
  */
 static struct dmi_system_id __initdata reboot_dmi_table[] = {
-#ifdef CONFIG_X86_32
        {       /* Handle problems with rebooting on Dell E520's */
                .callback = set_bios_reboot,
                .ident = "Dell E520",
@@ -377,7 +374,6 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "P4S800"),
                },
        },
-#endif /* CONFIG_X86_32 */
 
        {       /* Handle reboot issue on Acer Aspire one */
                .callback = set_kbd_reboot,
@@ -584,13 +580,11 @@ static void native_machine_emergency_restart(void)
                        reboot_type = BOOT_KBD;
                        break;
 
-#ifdef CONFIG_X86_32
                case BOOT_BIOS:
                        machine_real_restart(MRR_BIOS);
 
                        reboot_type = BOOT_KBD;
                        break;
-#endif
 
                case BOOT_ACPI:
                        acpi_reboot();
@@ -632,12 +626,10 @@ void native_machine_shutdown(void)
        /* The boot cpu is always logical cpu 0 */
        int reboot_cpu_id = 0;
 
-#ifdef CONFIG_X86_32
        /* See if there has been given a command line override */
        if ((reboot_cpu != -1) && (reboot_cpu < nr_cpu_ids) &&
                cpu_online(reboot_cpu))
                reboot_cpu_id = reboot_cpu;
-#endif
 
        /* Make certain the cpu I'm about to reboot on is online */
        if (!cpu_online(reboot_cpu_id))
@@ -678,7 +670,7 @@ static void __machine_emergency_restart(int emergency)
 
 static void native_machine_restart(char *__unused)
 {
-       printk("machine restart\n");
+       pr_notice("machine restart\n");
 
        if (!reboot_force)
                machine_shutdown();
index 16be6dc14db1b67c108475466ee494312e82d665..f4b9b80e1b95e2a9d0341fd62ed4412949b52243 100644 (file)
@@ -1031,8 +1031,6 @@ void __init setup_arch(char **cmdline_p)
 
        x86_init.timers.wallclock_init();
 
-       x86_platform.wallclock_init();
-
        mcheck_init();
 
        arch_init_ideal_nops();
index 21af737053aad05fb726a0e1023dfad428064518..b280908a376e20efc6773b76c6e80353ef8680f4 100644 (file)
@@ -6,6 +6,9 @@
  *  2000-06-20  Pentium III FXSR, SSE support by Gareth Hughes
  *  2000-2002   x86-64 support by Andi Kleen
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
@@ -814,7 +817,7 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where)
                       me->comm, me->pid, where, frame,
                       regs->ip, regs->sp, regs->orig_ax);
                print_vma_addr(" in ", regs->ip);
-               printk(KERN_CONT "\n");
+               pr_cont("\n");
        }
 
        force_sig(SIGSEGV, me);
index 7bd8a0823654115cdb476b1693cb3eaeb6affba3..c1a310fb8309b471301330abeda28b040fca5824 100644 (file)
@@ -1,4 +1,4 @@
-/*
+ /*
  *     x86 SMP booting functions
  *
  *     (c) 1995 Alan Cox, Building #3 <alan@lxorguk.ukuu.org.uk>
@@ -39,6 +39,8 @@
  *     Glauber Costa           :       i386 and x86_64 integration
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/module.h>
@@ -184,7 +186,7 @@ static void __cpuinit smp_callin(void)
         * boards)
         */
 
-       pr_debug("CALLIN, before setup_local_APIC().\n");
+       pr_debug("CALLIN, before setup_local_APIC()\n");
        if (apic->smp_callin_clear_local_apic)
                apic->smp_callin_clear_local_apic();
        setup_local_APIC();
@@ -255,22 +257,13 @@ notrace static void __cpuinit start_secondary(void *unused)
        check_tsc_sync_target();
 
        /*
-        * We need to hold call_lock, so there is no inconsistency
-        * between the time smp_call_function() determines number of
-        * IPI recipients, and the time when the determination is made
-        * for which cpus receive the IPI. Holding this
-        * lock helps us to not include this cpu in a currently in progress
-        * smp_call_function().
-        *
         * We need to hold vector_lock so there the set of online cpus
         * does not change while we are assigning vectors to cpus.  Holding
         * this lock ensures we don't half assign or remove an irq from a cpu.
         */
-       ipi_call_lock();
        lock_vector_lock();
        set_cpu_online(smp_processor_id(), true);
        unlock_vector_lock();
-       ipi_call_unlock();
        per_cpu(cpu_state, smp_processor_id()) = CPU_ONLINE;
        x86_platform.nmi_init();
 
@@ -432,17 +425,16 @@ static void impress_friends(void)
        /*
         * Allow the user to impress friends.
         */
-       pr_debug("Before bogomips.\n");
+       pr_debug("Before bogomips\n");
        for_each_possible_cpu(cpu)
                if (cpumask_test_cpu(cpu, cpu_callout_mask))
                        bogosum += cpu_data(cpu).loops_per_jiffy;
-       printk(KERN_INFO
-               "Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
+       pr_info("Total of %d processors activated (%lu.%02lu BogoMIPS)\n",
                num_online_cpus(),
                bogosum/(500000/HZ),
                (bogosum/(5000/HZ))%100);
 
-       pr_debug("Before bogocount - setting activated=1.\n");
+       pr_debug("Before bogocount - setting activated=1\n");
 }
 
 void __inquire_remote_apic(int apicid)
@@ -452,18 +444,17 @@ void __inquire_remote_apic(int apicid)
        int timeout;
        u32 status;
 
-       printk(KERN_INFO "Inquiring remote APIC 0x%x...\n", apicid);
+       pr_info("Inquiring remote APIC 0x%x...\n", apicid);
 
        for (i = 0; i < ARRAY_SIZE(regs); i++) {
-               printk(KERN_INFO "... APIC 0x%x %s: ", apicid, names[i]);
+               pr_info("... APIC 0x%x %s: ", apicid, names[i]);
 
                /*
                 * Wait for idle.
                 */
                status = safe_apic_wait_icr_idle();
                if (status)
-                       printk(KERN_CONT
-                              "a previous APIC delivery may have failed\n");
+                       pr_cont("a previous APIC delivery may have failed\n");
 
                apic_icr_write(APIC_DM_REMRD | regs[i], apicid);
 
@@ -476,10 +467,10 @@ void __inquire_remote_apic(int apicid)
                switch (status) {
                case APIC_ICR_RR_VALID:
                        status = apic_read(APIC_RRR);
-                       printk(KERN_CONT "%08x\n", status);
+                       pr_cont("%08x\n", status);
                        break;
                default:
-                       printk(KERN_CONT "failed\n");
+                       pr_cont("failed\n");
                }
        }
 }
@@ -513,12 +504,12 @@ wakeup_secondary_cpu_via_nmi(int logical_apicid, unsigned long start_eip)
                        apic_write(APIC_ESR, 0);
                accept_status = (apic_read(APIC_ESR) & 0xEF);
        }
-       pr_debug("NMI sent.\n");
+       pr_debug("NMI sent\n");
 
        if (send_status)
-               printk(KERN_ERR "APIC never delivered???\n");
+               pr_err("APIC never delivered???\n");
        if (accept_status)
-               printk(KERN_ERR "APIC delivery error (%lx).\n", accept_status);
+               pr_err("APIC delivery error (%lx)\n", accept_status);
 
        return (send_status | accept_status);
 }
@@ -540,7 +531,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
                apic_read(APIC_ESR);
        }
 
-       pr_debug("Asserting INIT.\n");
+       pr_debug("Asserting INIT\n");
 
        /*
         * Turn INIT on target chip
@@ -556,7 +547,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
 
        mdelay(10);
 
-       pr_debug("Deasserting INIT.\n");
+       pr_debug("Deasserting INIT\n");
 
        /* Target chip */
        /* Send IPI */
@@ -589,14 +580,14 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
        /*
         * Run STARTUP IPI loop.
         */
-       pr_debug("#startup loops: %d.\n", num_starts);
+       pr_debug("#startup loops: %d\n", num_starts);
 
        for (j = 1; j <= num_starts; j++) {
-               pr_debug("Sending STARTUP #%d.\n", j);
+               pr_debug("Sending STARTUP #%d\n", j);
                if (maxlvt > 3)         /* Due to the Pentium erratum 3AP.  */
                        apic_write(APIC_ESR, 0);
                apic_read(APIC_ESR);
-               pr_debug("After apic_write.\n");
+               pr_debug("After apic_write\n");
 
                /*
                 * STARTUP IPI
@@ -613,7 +604,7 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
                 */
                udelay(300);
 
-               pr_debug("Startup point 1.\n");
+               pr_debug("Startup point 1\n");
 
                pr_debug("Waiting for send to finish...\n");
                send_status = safe_apic_wait_icr_idle();
@@ -628,12 +619,12 @@ wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip)
                if (send_status || accept_status)
                        break;
        }
-       pr_debug("After Startup.\n");
+       pr_debug("After Startup\n");
 
        if (send_status)
-               printk(KERN_ERR "APIC never delivered???\n");
+               pr_err("APIC never delivered???\n");
        if (accept_status)
-               printk(KERN_ERR "APIC delivery error (%lx).\n", accept_status);
+               pr_err("APIC delivery error (%lx)\n", accept_status);
 
        return (send_status | accept_status);
 }
@@ -647,11 +638,11 @@ static void __cpuinit announce_cpu(int cpu, int apicid)
        if (system_state == SYSTEM_BOOTING) {
                if (node != current_node) {
                        if (current_node > (-1))
-                               pr_cont(" Ok.\n");
+                               pr_cont(" OK\n");
                        current_node = node;
                        pr_info("Booting Node %3d, Processors ", node);
                }
-               pr_cont(" #%d%s", cpu, cpu == (nr_cpu_ids - 1) ? " Ok.\n" : "");
+               pr_cont(" #%d%s", cpu, cpu == (nr_cpu_ids - 1) ? " OK\n" : "");
                return;
        } else
                pr_info("Booting Node %d Processor %d APIC 0x%x\n",
@@ -731,9 +722,9 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
                /*
                 * allow APs to start initializing.
                 */
-               pr_debug("Before Callout %d.\n", cpu);
+               pr_debug("Before Callout %d\n", cpu);
                cpumask_set_cpu(cpu, cpu_callout_mask);
-               pr_debug("After Callout %d.\n", cpu);
+               pr_debug("After Callout %d\n", cpu);
 
                /*
                 * Wait 5s total for a response
@@ -761,7 +752,7 @@ static int __cpuinit do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
                                pr_err("CPU%d: Stuck ??\n", cpu);
                        else
                                /* trampoline code not run */
-                               pr_err("CPU%d: Not responding.\n", cpu);
+                               pr_err("CPU%d: Not responding\n", cpu);
                        if (apic->inquire_remote_apic)
                                apic->inquire_remote_apic(apicid);
                }
@@ -806,7 +797,7 @@ int __cpuinit native_cpu_up(unsigned int cpu, struct task_struct *tidle)
        if (apicid == BAD_APICID || apicid == boot_cpu_physical_apicid ||
            !physid_isset(apicid, phys_cpu_present_map) ||
            !apic->apic_id_valid(apicid)) {
-               printk(KERN_ERR "%s: bad cpu %d\n", __func__, cpu);
+               pr_err("%s: bad cpu %d\n", __func__, cpu);
                return -EINVAL;
        }
 
@@ -887,9 +878,8 @@ static int __init smp_sanity_check(unsigned max_cpus)
                unsigned int cpu;
                unsigned nr;
 
-               printk(KERN_WARNING
-                      "More than 8 CPUs detected - skipping them.\n"
-                      "Use CONFIG_X86_BIGSMP.\n");
+               pr_warn("More than 8 CPUs detected - skipping them\n"
+                       "Use CONFIG_X86_BIGSMP\n");
 
                nr = 0;
                for_each_present_cpu(cpu) {
@@ -910,8 +900,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
 #endif
 
        if (!physid_isset(hard_smp_processor_id(), phys_cpu_present_map)) {
-               printk(KERN_WARNING
-                       "weird, boot CPU (#%d) not listed by the BIOS.\n",
+               pr_warn("weird, boot CPU (#%d) not listed by the BIOS\n",
                        hard_smp_processor_id());
 
                physid_set(hard_smp_processor_id(), phys_cpu_present_map);
@@ -923,11 +912,10 @@ static int __init smp_sanity_check(unsigned max_cpus)
         */
        if (!smp_found_config && !acpi_lapic) {
                preempt_enable();
-               printk(KERN_NOTICE "SMP motherboard not detected.\n");
+               pr_notice("SMP motherboard not detected\n");
                disable_smp();
                if (APIC_init_uniprocessor())
-                       printk(KERN_NOTICE "Local APIC not detected."
-                                          " Using dummy APIC emulation.\n");
+                       pr_notice("Local APIC not detected. Using dummy APIC emulation.\n");
                return -1;
        }
 
@@ -936,9 +924,8 @@ static int __init smp_sanity_check(unsigned max_cpus)
         * CPU too, but we do it for the sake of robustness anyway.
         */
        if (!apic->check_phys_apicid_present(boot_cpu_physical_apicid)) {
-               printk(KERN_NOTICE
-                       "weird, boot CPU (#%d) not listed by the BIOS.\n",
-                       boot_cpu_physical_apicid);
+               pr_notice("weird, boot CPU (#%d) not listed by the BIOS\n",
+                         boot_cpu_physical_apicid);
                physid_set(hard_smp_processor_id(), phys_cpu_present_map);
        }
        preempt_enable();
@@ -951,8 +938,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
                if (!disable_apic) {
                        pr_err("BIOS bug, local APIC #%d not detected!...\n",
                                boot_cpu_physical_apicid);
-                       pr_err("... forcing use of dummy APIC emulation."
-                               "(tell your hw vendor)\n");
+                       pr_err("... forcing use of dummy APIC emulation (tell your hw vendor)\n");
                }
                smpboot_clear_io_apic();
                disable_ioapic_support();
@@ -965,7 +951,7 @@ static int __init smp_sanity_check(unsigned max_cpus)
         * If SMP should be disabled, then really disable it!
         */
        if (!max_cpus) {
-               printk(KERN_INFO "SMP mode deactivated.\n");
+               pr_info("SMP mode deactivated\n");
                smpboot_clear_io_apic();
 
                connect_bsp_APIC();
@@ -1017,7 +1003,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
 
 
        if (smp_sanity_check(max_cpus) < 0) {
-               printk(KERN_INFO "SMP disabled\n");
+               pr_info("SMP disabled\n");
                disable_smp();
                goto out;
        }
@@ -1055,7 +1041,7 @@ void __init native_smp_prepare_cpus(unsigned int max_cpus)
         * Set up local APIC timer on boot CPU.
         */
 
-       printk(KERN_INFO "CPU%d: ", 0);
+       pr_info("CPU%d: ", 0);
        print_cpu_info(&cpu_data(0));
        x86_init.timers.setup_percpu_clockev();
 
@@ -1105,7 +1091,7 @@ void __init native_smp_prepare_boot_cpu(void)
 
 void __init native_smp_cpus_done(unsigned int max_cpus)
 {
-       pr_debug("Boot done.\n");
+       pr_debug("Boot done\n");
 
        nmi_selftest();
        impress_friends();
@@ -1166,8 +1152,7 @@ __init void prefill_possible_map(void)
 
        /* nr_cpu_ids could be reduced via nr_cpus= */
        if (possible > nr_cpu_ids) {
-               printk(KERN_WARNING
-                       "%d Processors exceeds NR_CPUS limit of %d\n",
+               pr_warn("%d Processors exceeds NR_CPUS limit of %d\n",
                        possible, nr_cpu_ids);
                possible = nr_cpu_ids;
        }
@@ -1176,13 +1161,12 @@ __init void prefill_possible_map(void)
        if (!setup_max_cpus)
 #endif
        if (possible > i) {
-               printk(KERN_WARNING
-                       "%d Processors exceeds max_cpus limit of %u\n",
+               pr_warn("%d Processors exceeds max_cpus limit of %u\n",
                        possible, setup_max_cpus);
                possible = i;
        }
 
-       printk(KERN_INFO "SMP: Allowing %d CPUs, %d hotplug CPUs\n",
+       pr_info("Allowing %d CPUs, %d hotplug CPUs\n",
                possible, max_t(int, possible - num_processors, 0));
 
        for (i = 0; i < possible; i++)
index 05b31d92f69cdf7b7e9ccc22c82835a5e6286bbc..b481341c9369da649908b57c3e8c39b1586b0111 100644 (file)
@@ -9,6 +9,9 @@
 /*
  * Handle hardware traps and faults.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/interrupt.h>
 #include <linux/kallsyms.h>
 #include <linux/spinlock.h>
@@ -143,12 +146,11 @@ trap_signal:
 #ifdef CONFIG_X86_64
        if (show_unhandled_signals && unhandled_signal(tsk, signr) &&
            printk_ratelimit()) {
-               printk(KERN_INFO
-                      "%s[%d] trap %s ip:%lx sp:%lx error:%lx",
-                      tsk->comm, tsk->pid, str,
-                      regs->ip, regs->sp, error_code);
+               pr_info("%s[%d] trap %s ip:%lx sp:%lx error:%lx",
+                       tsk->comm, tsk->pid, str,
+                       regs->ip, regs->sp, error_code);
                print_vma_addr(" in ", regs->ip);
-               printk("\n");
+               pr_cont("\n");
        }
 #endif
 
@@ -269,12 +271,11 @@ do_general_protection(struct pt_regs *regs, long error_code)
 
        if (show_unhandled_signals && unhandled_signal(tsk, SIGSEGV) &&
                        printk_ratelimit()) {
-               printk(KERN_INFO
-                       "%s[%d] general protection ip:%lx sp:%lx error:%lx",
+               pr_info("%s[%d] general protection ip:%lx sp:%lx error:%lx",
                        tsk->comm, task_pid_nr(tsk),
                        regs->ip, regs->sp, error_code);
                print_vma_addr(" in ", regs->ip);
-               printk("\n");
+               pr_cont("\n");
        }
 
        force_sig(SIGSEGV, tsk);
@@ -570,7 +571,7 @@ do_spurious_interrupt_bug(struct pt_regs *regs, long error_code)
        conditional_sti(regs);
 #if 0
        /* No need to warn about this any longer. */
-       printk(KERN_INFO "Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
+       pr_info("Ignoring P6 Local APIC Spurious Interrupt Bug...\n");
 #endif
 }
 
index fc0a147e372726fb019b8873969dc1fca3e43109..cfa5d4f7ca56c06934c8b8bfa6e9815fe8e606b4 100644 (file)
@@ -1,3 +1,5 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/init.h>
@@ -84,8 +86,7 @@ EXPORT_SYMBOL_GPL(check_tsc_unstable);
 #ifdef CONFIG_X86_TSC
 int __init notsc_setup(char *str)
 {
-       printk(KERN_WARNING "notsc: Kernel compiled with CONFIG_X86_TSC, "
-                       "cannot disable TSC completely.\n");
+       pr_warn("Kernel compiled with CONFIG_X86_TSC, cannot disable TSC completely\n");
        tsc_disabled = 1;
        return 1;
 }
@@ -373,7 +374,7 @@ static unsigned long quick_pit_calibrate(void)
                        goto success;
                }
        }
-       printk("Fast TSC calibration failed\n");
+       pr_err("Fast TSC calibration failed\n");
        return 0;
 
 success:
@@ -392,7 +393,7 @@ success:
         */
        delta *= PIT_TICK_RATE;
        do_div(delta, i*256*1000);
-       printk("Fast TSC calibration using PIT\n");
+       pr_info("Fast TSC calibration using PIT\n");
        return delta;
 }
 
@@ -487,9 +488,8 @@ unsigned long native_calibrate_tsc(void)
                 * use the reference value, as it is more precise.
                 */
                if (delta >= 90 && delta <= 110) {
-                       printk(KERN_INFO
-                              "TSC: PIT calibration matches %s. %d loops\n",
-                              hpet ? "HPET" : "PMTIMER", i + 1);
+                       pr_info("PIT calibration matches %s. %d loops\n",
+                               hpet ? "HPET" : "PMTIMER", i + 1);
                        return tsc_ref_min;
                }
 
@@ -511,38 +511,36 @@ unsigned long native_calibrate_tsc(void)
         */
        if (tsc_pit_min == ULONG_MAX) {
                /* PIT gave no useful value */
-               printk(KERN_WARNING "TSC: Unable to calibrate against PIT\n");
+               pr_warn("Unable to calibrate against PIT\n");
 
                /* We don't have an alternative source, disable TSC */
                if (!hpet && !ref1 && !ref2) {
-                       printk("TSC: No reference (HPET/PMTIMER) available\n");
+                       pr_notice("No reference (HPET/PMTIMER) available\n");
                        return 0;
                }
 
                /* The alternative source failed as well, disable TSC */
                if (tsc_ref_min == ULONG_MAX) {
-                       printk(KERN_WARNING "TSC: HPET/PMTIMER calibration "
-                              "failed.\n");
+                       pr_warn("HPET/PMTIMER calibration failed\n");
                        return 0;
                }
 
                /* Use the alternative source */
-               printk(KERN_INFO "TSC: using %s reference calibration\n",
-                      hpet ? "HPET" : "PMTIMER");
+               pr_info("using %s reference calibration\n",
+                       hpet ? "HPET" : "PMTIMER");
 
                return tsc_ref_min;
        }
 
        /* We don't have an alternative source, use the PIT calibration value */
        if (!hpet && !ref1 && !ref2) {
-               printk(KERN_INFO "TSC: Using PIT calibration value\n");
+               pr_info("Using PIT calibration value\n");
                return tsc_pit_min;
        }
 
        /* The alternative source failed, use the PIT calibration value */
        if (tsc_ref_min == ULONG_MAX) {
-               printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed. "
-                      "Using PIT calibration\n");
+               pr_warn("HPET/PMTIMER calibration failed. Using PIT calibration.\n");
                return tsc_pit_min;
        }
 
@@ -551,9 +549,9 @@ unsigned long native_calibrate_tsc(void)
         * the PIT value as we know that there are PMTIMERs around
         * running at double speed. At least we let the user know:
         */
-       printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n",
-              hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min);
-       printk(KERN_INFO "TSC: Using PIT calibration value\n");
+       pr_warn("PIT calibration deviates from %s: %lu %lu\n",
+               hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min);
+       pr_info("Using PIT calibration value\n");
        return tsc_pit_min;
 }
 
@@ -785,7 +783,7 @@ void mark_tsc_unstable(char *reason)
                tsc_unstable = 1;
                sched_clock_stable = 0;
                disable_sched_clock_irqtime();
-               printk(KERN_INFO "Marking TSC unstable due to %s\n", reason);
+               pr_info("Marking TSC unstable due to %s\n", reason);
                /* Change only the rating, when not registered */
                if (clocksource_tsc.mult)
                        clocksource_mark_unstable(&clocksource_tsc);
@@ -912,9 +910,9 @@ static void tsc_refine_calibration_work(struct work_struct *work)
                goto out;
 
        tsc_khz = freq;
-       printk(KERN_INFO "Refined TSC clocksource calibration: "
-               "%lu.%03lu MHz.\n", (unsigned long)tsc_khz / 1000,
-                                       (unsigned long)tsc_khz % 1000);
+       pr_info("Refined TSC clocksource calibration: %lu.%03lu MHz\n",
+               (unsigned long)tsc_khz / 1000,
+               (unsigned long)tsc_khz % 1000);
 
 out:
        clocksource_register_khz(&clocksource_tsc, tsc_khz);
@@ -970,9 +968,9 @@ void __init tsc_init(void)
                return;
        }
 
-       printk("Detected %lu.%03lu MHz processor.\n",
-                       (unsigned long)cpu_khz / 1000,
-                       (unsigned long)cpu_khz % 1000);
+       pr_info("Detected %lu.%03lu MHz processor\n",
+               (unsigned long)cpu_khz / 1000,
+               (unsigned long)cpu_khz % 1000);
 
        /*
         * Secondary CPUs do not run through tsc_init(), so set up
index dc4e910a7d964c76dd4935c2986c33e37b1a595b..36fd42091fa7283d71e189ddb55cf29a5e940790 100644 (file)
@@ -409,9 +409,10 @@ static int validate_insn_bits(struct arch_uprobe *auprobe, struct mm_struct *mm,
  * arch_uprobe_analyze_insn - instruction analysis including validity and fixups.
  * @mm: the probed address space.
  * @arch_uprobe: the probepoint information.
+ * @addr: virtual address at which to install the probepoint
  * Return 0 on success or a -ve number on error.
  */
-int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm)
+int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long addr)
 {
        int ret;
        struct insn insn;
index 255f58ae71e8991838080eac595786a60f372a62..54abcc0baf23f0f4181106a7b2a83312c01ed03f 100644 (file)
@@ -28,6 +28,8 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/capability.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
@@ -137,14 +139,14 @@ struct pt_regs *save_v86_state(struct kernel_vm86_regs *regs)
        local_irq_enable();
 
        if (!current->thread.vm86_info) {
-               printk("no vm86_info: BAD\n");
+               pr_alert("no vm86_info: BAD\n");
                do_exit(SIGSEGV);
        }
        set_flags(regs->pt.flags, VEFLAGS, X86_EFLAGS_VIF | current->thread.v86mask);
        tmp = copy_vm86_regs_to_user(&current->thread.vm86_info->regs, regs);
        tmp += put_user(current->thread.screen_bitmap, &current->thread.vm86_info->screen_bitmap);
        if (tmp) {
-               printk("vm86: could not access userspace vm86_info\n");
+               pr_alert("could not access userspace vm86_info\n");
                do_exit(SIGSEGV);
        }
 
index 8eeb55a551b423fdce43eb432c8f8f5599246848..992f890283e9260980349ff128f33446f339810a 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/pci_ids.h>
 #include <linux/pci_regs.h>
 #include <linux/smp.h>
+#include <linux/irq.h>
 
 #include <asm/apic.h>
 #include <asm/pci-direct.h>
@@ -95,6 +96,18 @@ static void __init set_vsmp_pv_ops(void)
        ctl = readl(address + 4);
        printk(KERN_INFO "vSMP CTL: capabilities:0x%08x  control:0x%08x\n",
               cap, ctl);
+
+       /* If possible, let the vSMP foundation route the interrupt optimally */
+#ifdef CONFIG_SMP
+       if (cap & ctl & BIT(8)) {
+               ctl &= ~BIT(8);
+#ifdef CONFIG_PROC_FS
+               /* Don't let users change irq affinity via procfs */
+               no_irq_affinity = 1;
+#endif
+       }
+#endif
+
        if (cap & ctl & (1 << 4)) {
                /* Setup irq ops and turn on vSMP  IRQ fastpath handling */
                pv_irq_ops.irq_disable = PV_CALLEE_SAVE(vsmp_irq_disable);
@@ -102,12 +115,11 @@ static void __init set_vsmp_pv_ops(void)
                pv_irq_ops.save_fl  = PV_CALLEE_SAVE(vsmp_save_fl);
                pv_irq_ops.restore_fl  = PV_CALLEE_SAVE(vsmp_restore_fl);
                pv_init_ops.patch = vsmp_patch;
-
                ctl &= ~(1 << 4);
-               writel(ctl, address + 4);
-               ctl = readl(address + 4);
-               printk(KERN_INFO "vSMP CTL: control set to:0x%08x\n", ctl);
        }
+       writel(ctl, address + 4);
+       ctl = readl(address + 4);
+       pr_info("vSMP CTL: control set to:0x%08x\n", ctl);
 
        early_iounmap(address, 8);
 }
@@ -187,12 +199,36 @@ static void __init vsmp_cap_cpus(void)
 #endif
 }
 
+static int apicid_phys_pkg_id(int initial_apic_id, int index_msb)
+{
+       return hard_smp_processor_id() >> index_msb;
+}
+
+/*
+ * In vSMP, all cpus should be capable of handling interrupts, regardless of
+ * the APIC used.
+ */
+static void fill_vector_allocation_domain(int cpu, struct cpumask *retmask,
+                                         const struct cpumask *mask)
+{
+       cpumask_setall(retmask);
+}
+
+static void vsmp_apic_post_init(void)
+{
+       /* need to update phys_pkg_id */
+       apic->phys_pkg_id = apicid_phys_pkg_id;
+       apic->vector_allocation_domain = fill_vector_allocation_domain;
+}
+
 void __init vsmp_init(void)
 {
        detect_vsmp_box();
        if (!is_vsmp_box())
                return;
 
+       x86_platform.apic_post_init = vsmp_apic_post_init;
+
        vsmp_cap_cpus();
 
        set_vsmp_pv_ops();
index 5db36caf4289cdab3fe04bf899f4826504ced389..8d141b30904657871358a4fb8deb927c7a022257 100644 (file)
@@ -18,6 +18,8 @@
  *  use the vDSO.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/time.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -111,18 +113,13 @@ void update_vsyscall(struct timespec *wall_time, struct timespec *wtm,
 static void warn_bad_vsyscall(const char *level, struct pt_regs *regs,
                              const char *message)
 {
-       static DEFINE_RATELIMIT_STATE(rs, DEFAULT_RATELIMIT_INTERVAL, DEFAULT_RATELIMIT_BURST);
-       struct task_struct *tsk;
-
-       if (!show_unhandled_signals || !__ratelimit(&rs))
+       if (!show_unhandled_signals)
                return;
 
-       tsk = current;
-
-       printk("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
-              level, tsk->comm, task_pid_nr(tsk),
-              message, regs->ip, regs->cs,
-              regs->sp, regs->ax, regs->si, regs->di);
+       pr_notice_ratelimited("%s%s[%d] %s ip:%lx cs:%lx sp:%lx ax:%lx si:%lx di:%lx\n",
+                             level, current->comm, task_pid_nr(current),
+                             message, regs->ip, regs->cs,
+                             regs->sp, regs->ax, regs->si, regs->di);
 }
 
 static int addr_to_vsyscall_nr(unsigned long addr)
index 9796c2f3d0745e8b73b690fff13f7529b5792507..6020f6f5927cbc1035b7f86b1f19f1422ded0acf 100644 (file)
@@ -28,6 +28,7 @@ EXPORT_SYMBOL(__put_user_8);
 
 EXPORT_SYMBOL(copy_user_generic_string);
 EXPORT_SYMBOL(copy_user_generic_unrolled);
+EXPORT_SYMBOL(copy_user_enhanced_fast_string);
 EXPORT_SYMBOL(__copy_user_nocache);
 EXPORT_SYMBOL(_copy_from_user);
 EXPORT_SYMBOL(_copy_to_user);
index 35c5e543f55023f32b1316e08ce0d405e671e095..9f3167e891ef4af9f92c57ac8092790412906ee3 100644 (file)
@@ -29,7 +29,6 @@ void __init x86_init_uint_noop(unsigned int unused) { }
 void __init x86_init_pgd_noop(pgd_t *unused) { }
 int __init iommu_init_noop(void) { return 0; }
 void iommu_shutdown_noop(void) { }
-void wallclock_init_noop(void) { }
 
 /*
  * The platform setup functions are preset with the default functions
@@ -101,7 +100,6 @@ static int default_i8042_detect(void) { return 1; };
 
 struct x86_platform_ops x86_platform = {
        .calibrate_tsc                  = native_calibrate_tsc,
-       .wallclock_init                 = wallclock_init_noop,
        .get_wallclock                  = mach_get_cmos_time,
        .set_wallclock                  = mach_set_rtc_mmss,
        .iommu_shutdown                 = iommu_shutdown_noop,
index bd18149b2b0f09532870075a274ff1576b5de1d7..3d3e2070911971eb8aa3625e2708b2de34852f1d 100644 (file)
@@ -3,6 +3,9 @@
  *
  * Author: Suresh Siddha <suresh.b.siddha@intel.com>
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/bootmem.h>
 #include <linux/compat.h>
 #include <asm/i387.h>
@@ -162,7 +165,7 @@ int save_i387_xstate(void __user *buf)
        BUG_ON(sig_xstate_size < xstate_size);
 
        if ((unsigned long)buf % 64)
-               printk("save_i387_xstate: bad fpstate %p\n", buf);
+               pr_err("%s: bad fpstate %p\n", __func__, buf);
 
        if (!used_math())
                return 0;
@@ -422,7 +425,7 @@ static void __init xstate_enable_boot_cpu(void)
        pcntxt_mask = eax + ((u64)edx << 32);
 
        if ((pcntxt_mask & XSTATE_FPSSE) != XSTATE_FPSSE) {
-               printk(KERN_ERR "FP/SSE not shown under xsave features 0x%llx\n",
+               pr_err("FP/SSE not shown under xsave features 0x%llx\n",
                       pcntxt_mask);
                BUG();
        }
@@ -445,9 +448,8 @@ static void __init xstate_enable_boot_cpu(void)
 
        setup_xstate_init();
 
-       printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%llx, "
-              "cntxt size 0x%x\n",
-              pcntxt_mask, xstate_size);
+       pr_info("enabled xstate_bv 0x%llx, cntxt size 0x%x\n",
+               pcntxt_mask, xstate_size);
 }
 
 /*
index 2e88438ffd83186c0d7a6b136cc97ae5c943ae4a..9b7ec1150ab01ad1390217cc04176d255c5d8382 100644 (file)
@@ -80,10 +80,10 @@ static inline struct kvm_pmc *get_fixed_pmc_idx(struct kvm_pmu *pmu, int idx)
 
 static struct kvm_pmc *global_idx_to_pmc(struct kvm_pmu *pmu, int idx)
 {
-       if (idx < X86_PMC_IDX_FIXED)
+       if (idx < INTEL_PMC_IDX_FIXED)
                return get_gp_pmc(pmu, MSR_P6_EVNTSEL0 + idx, MSR_P6_EVNTSEL0);
        else
-               return get_fixed_pmc_idx(pmu, idx - X86_PMC_IDX_FIXED);
+               return get_fixed_pmc_idx(pmu, idx - INTEL_PMC_IDX_FIXED);
 }
 
 void kvm_deliver_pmi(struct kvm_vcpu *vcpu)
@@ -291,7 +291,7 @@ static void reprogram_idx(struct kvm_pmu *pmu, int idx)
        if (pmc_is_gp(pmc))
                reprogram_gp_counter(pmc, pmc->eventsel);
        else {
-               int fidx = idx - X86_PMC_IDX_FIXED;
+               int fidx = idx - INTEL_PMC_IDX_FIXED;
                reprogram_fixed_counter(pmc,
                                fixed_en_pmi(pmu->fixed_ctr_ctrl, fidx), fidx);
        }
@@ -452,7 +452,7 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu)
                return;
 
        pmu->nr_arch_gp_counters = min((int)(entry->eax >> 8) & 0xff,
-                       X86_PMC_MAX_GENERIC);
+                       INTEL_PMC_MAX_GENERIC);
        pmu->counter_bitmask[KVM_PMC_GP] =
                ((u64)1 << ((entry->eax >> 16) & 0xff)) - 1;
        bitmap_len = (entry->eax >> 24) & 0xff;
@@ -462,13 +462,13 @@ void kvm_pmu_cpuid_update(struct kvm_vcpu *vcpu)
                pmu->nr_arch_fixed_counters = 0;
        } else {
                pmu->nr_arch_fixed_counters = min((int)(entry->edx & 0x1f),
-                               X86_PMC_MAX_FIXED);
+                               INTEL_PMC_MAX_FIXED);
                pmu->counter_bitmask[KVM_PMC_FIXED] =
                        ((u64)1 << ((entry->edx >> 5) & 0xff)) - 1;
        }
 
        pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) |
-               (((1ull << pmu->nr_arch_fixed_counters) - 1) << X86_PMC_IDX_FIXED);
+               (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED);
        pmu->global_ctrl_mask = ~pmu->global_ctrl;
 }
 
@@ -478,15 +478,15 @@ void kvm_pmu_init(struct kvm_vcpu *vcpu)
        struct kvm_pmu *pmu = &vcpu->arch.pmu;
 
        memset(pmu, 0, sizeof(*pmu));
-       for (i = 0; i < X86_PMC_MAX_GENERIC; i++) {
+       for (i = 0; i < INTEL_PMC_MAX_GENERIC; i++) {
                pmu->gp_counters[i].type = KVM_PMC_GP;
                pmu->gp_counters[i].vcpu = vcpu;
                pmu->gp_counters[i].idx = i;
        }
-       for (i = 0; i < X86_PMC_MAX_FIXED; i++) {
+       for (i = 0; i < INTEL_PMC_MAX_FIXED; i++) {
                pmu->fixed_counters[i].type = KVM_PMC_FIXED;
                pmu->fixed_counters[i].vcpu = vcpu;
-               pmu->fixed_counters[i].idx = i + X86_PMC_IDX_FIXED;
+               pmu->fixed_counters[i].idx = i + INTEL_PMC_IDX_FIXED;
        }
        init_irq_work(&pmu->irq_work, trigger_pmi);
        kvm_pmu_cpuid_update(vcpu);
@@ -498,13 +498,13 @@ void kvm_pmu_reset(struct kvm_vcpu *vcpu)
        int i;
 
        irq_work_sync(&pmu->irq_work);
-       for (i = 0; i < X86_PMC_MAX_GENERIC; i++) {
+       for (i = 0; i < INTEL_PMC_MAX_GENERIC; i++) {
                struct kvm_pmc *pmc = &pmu->gp_counters[i];
                stop_counter(pmc);
                pmc->counter = pmc->eventsel = 0;
        }
 
-       for (i = 0; i < X86_PMC_MAX_FIXED; i++)
+       for (i = 0; i < INTEL_PMC_MAX_FIXED; i++)
                stop_counter(&pmu->fixed_counters[i]);
 
        pmu->fixed_ctr_ctrl = pmu->global_ctrl = pmu->global_status =
index 911d2641f14c5cba355abc25e00f38f07ced1df9..62d02e3c3ed625ec6d0a5f89ceb325ee1eab7236 100644 (file)
@@ -710,16 +710,6 @@ TRACE_EVENT(kvm_skinit,
                  __entry->rip, __entry->slb)
 );
 
-#define __print_insn(insn, ilen) ({                             \
-       int i;                                                   \
-       const char *ret = p->buffer + p->len;                    \
-                                                                \
-       for (i = 0; i < ilen; ++i)                               \
-               trace_seq_printf(p, " %02x", insn[i]);           \
-       trace_seq_printf(p, "%c", 0);                            \
-       ret;                                                     \
-       })
-
 #define KVM_EMUL_INSN_F_CR0_PE (1 << 0)
 #define KVM_EMUL_INSN_F_EFL_VM (1 << 1)
 #define KVM_EMUL_INSN_F_CS_D   (1 << 2)
@@ -786,7 +776,7 @@ TRACE_EVENT(kvm_emulate_insn,
 
        TP_printk("%x:%llx:%s (%s)%s",
                  __entry->csbase, __entry->rip,
-                 __print_insn(__entry->insn, __entry->len),
+                 __print_hex(__entry->insn, __entry->len),
                  __print_symbolic(__entry->flags,
                                   kvm_trace_symbol_emul_flags),
                  __entry->failed ? " failed" : ""
index a311cc59b65d9769e05af4e566f6c997b3139bc4..8d6ef78b5d01c3a180959bd54f7da26ddf325188 100644 (file)
@@ -1,5 +1,5 @@
 #include <linux/module.h>
 #include <asm/msr.h>
 
-EXPORT_SYMBOL(native_rdmsr_safe_regs);
-EXPORT_SYMBOL(native_wrmsr_safe_regs);
+EXPORT_SYMBOL(rdmsr_safe_regs);
+EXPORT_SYMBOL(wrmsr_safe_regs);
index 69fa10623f2181b23740bdf0a4ad5f7919120809..f6d13eefad1063d5e525dbc0cfff1ccc12b34bc9 100644 (file)
@@ -6,13 +6,13 @@
 
 #ifdef CONFIG_X86_64
 /*
- * int native_{rdmsr,wrmsr}_safe_regs(u32 gprs[8]);
+ * int {rdmsr,wrmsr}_safe_regs(u32 gprs[8]);
  *
  * reg layout: u32 gprs[eax, ecx, edx, ebx, esp, ebp, esi, edi]
  *
  */
 .macro op_safe_regs op
-ENTRY(native_\op\()_safe_regs)
+ENTRY(\op\()_safe_regs)
        CFI_STARTPROC
        pushq_cfi %rbx
        pushq_cfi %rbp
@@ -45,13 +45,13 @@ ENTRY(native_\op\()_safe_regs)
 
        _ASM_EXTABLE(1b, 3b)
        CFI_ENDPROC
-ENDPROC(native_\op\()_safe_regs)
+ENDPROC(\op\()_safe_regs)
 .endm
 
 #else /* X86_32 */
 
 .macro op_safe_regs op
-ENTRY(native_\op\()_safe_regs)
+ENTRY(\op\()_safe_regs)
        CFI_STARTPROC
        pushl_cfi %ebx
        pushl_cfi %ebp
@@ -92,7 +92,7 @@ ENTRY(native_\op\()_safe_regs)
 
        _ASM_EXTABLE(1b, 3b)
        CFI_ENDPROC
-ENDPROC(native_\op\()_safe_regs)
+ENDPROC(\op\()_safe_regs)
 .endm
 
 #endif
index bc4e9d84157fc0c9aa85e71837998da166c1fa57..e0e6990723e982e12f425f2fdd26113725f2d52a 100644 (file)
@@ -385,7 +385,7 @@ void free_initmem(void)
 }
 
 #ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
+void __init free_initrd_mem(unsigned long start, unsigned long end)
 {
        /*
         * end could be not aligned, and We can not align that,
index 303f0863782637ba3a1099397d796355f79982ff..b2b94438ff05cb3da0289f3b8800acfb77808f66 100644 (file)
@@ -312,7 +312,7 @@ static int op_amd_fill_in_addresses(struct op_msrs * const msrs)
                        goto fail;
                }
                /* both registers must be reserved */
-               if (num_counters == AMD64_NUM_COUNTERS_F15H) {
+               if (num_counters == AMD64_NUM_COUNTERS_CORE) {
                        msrs->counters[i].addr = MSR_F15H_PERF_CTR + (i << 1);
                        msrs->controls[i].addr = MSR_F15H_PERF_CTL + (i << 1);
                } else {
@@ -514,7 +514,7 @@ static int op_amd_init(struct oprofile_operations *ops)
        ops->create_files = setup_ibs_files;
 
        if (boot_cpu_data.x86 == 0x15) {
-               num_counters = AMD64_NUM_COUNTERS_F15H;
+               num_counters = AMD64_NUM_COUNTERS_CORE;
        } else {
                num_counters = AMD64_NUM_COUNTERS;
        }
index 23e5b9d7977b6e528821682f2278289c73a534a2..599be499fdf7a8aff278e7e7f16ca9593fde8c41 100644 (file)
@@ -203,7 +203,7 @@ static int xo15_sci_remove(struct acpi_device *device, int type)
        return 0;
 }
 
-static int xo15_sci_resume(struct acpi_device *device)
+static int xo15_sci_resume(struct device *dev)
 {
        /* Enable all EC events */
        olpc_ec_mask_write(EC_SCI_SRC_ALL);
@@ -215,6 +215,8 @@ static int xo15_sci_resume(struct acpi_device *device)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(xo15_sci_pm, NULL, xo15_sci_resume);
+
 static const struct acpi_device_id xo15_sci_device_ids[] = {
        {"XO15EC", 0},
        {"", 0},
@@ -227,8 +229,8 @@ static struct acpi_driver xo15_sci_drv = {
        .ops = {
                .add = xo15_sci_add,
                .remove = xo15_sci_remove,
-               .resume = xo15_sci_resume,
        },
+       .drv.pm = &xo15_sci_pm,
 };
 
 static int __init xo15_sci_init(void)
index 59880afa851fc37d6995e3fd665fca1f1d3d91b3..71b5d5a07d7bbd7c26a5f9ae99cf5f0e8cacacbf 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     SGI UltraViolet TLB flush routines.
  *
- *     (c) 2008-2011 Cliff Wickman <cpw@sgi.com>, SGI.
+ *     (c) 2008-2012 Cliff Wickman <cpw@sgi.com>, SGI.
  *
  *     This code is released under the GNU General Public License version 2 or
  *     later.
@@ -38,8 +38,7 @@ static int timeout_base_ns[] = {
 
 static int timeout_us;
 static int nobau;
-static int baudisabled;
-static spinlock_t disable_lock;
+static int nobau_perm;
 static cycles_t congested_cycles;
 
 /* tunables: */
@@ -47,12 +46,13 @@ static int max_concurr              = MAX_BAU_CONCURRENT;
 static int max_concurr_const   = MAX_BAU_CONCURRENT;
 static int plugged_delay       = PLUGGED_DELAY;
 static int plugsb4reset                = PLUGSB4RESET;
+static int giveup_limit                = GIVEUP_LIMIT;
 static int timeoutsb4reset     = TIMEOUTSB4RESET;
 static int ipi_reset_limit     = IPI_RESET_LIMIT;
 static int complete_threshold  = COMPLETE_THRESHOLD;
 static int congested_respns_us = CONGESTED_RESPONSE_US;
 static int congested_reps      = CONGESTED_REPS;
-static int congested_period    = CONGESTED_PERIOD;
+static int disabled_period     = DISABLED_PERIOD;
 
 static struct tunables tunables[] = {
        {&max_concurr, MAX_BAU_CONCURRENT}, /* must be [0] */
@@ -63,7 +63,8 @@ static struct tunables tunables[] = {
        {&complete_threshold, COMPLETE_THRESHOLD},
        {&congested_respns_us, CONGESTED_RESPONSE_US},
        {&congested_reps, CONGESTED_REPS},
-       {&congested_period, CONGESTED_PERIOD}
+       {&disabled_period, DISABLED_PERIOD},
+       {&giveup_limit, GIVEUP_LIMIT}
 };
 
 static struct dentry *tunables_dir;
@@ -120,6 +121,40 @@ static DEFINE_PER_CPU(struct ptc_stats, ptcstats);
 static DEFINE_PER_CPU(struct bau_control, bau_control);
 static DEFINE_PER_CPU(cpumask_var_t, uv_flush_tlb_mask);
 
+static void
+set_bau_on(void)
+{
+       int cpu;
+       struct bau_control *bcp;
+
+       if (nobau_perm) {
+               pr_info("BAU not initialized; cannot be turned on\n");
+               return;
+       }
+       nobau = 0;
+       for_each_present_cpu(cpu) {
+               bcp = &per_cpu(bau_control, cpu);
+               bcp->nobau = 0;
+       }
+       pr_info("BAU turned on\n");
+       return;
+}
+
+static void
+set_bau_off(void)
+{
+       int cpu;
+       struct bau_control *bcp;
+
+       nobau = 1;
+       for_each_present_cpu(cpu) {
+               bcp = &per_cpu(bau_control, cpu);
+               bcp->nobau = 1;
+       }
+       pr_info("BAU turned off\n");
+       return;
+}
+
 /*
  * Determine the first node on a uvhub. 'Nodes' are used for kernel
  * memory allocation.
@@ -278,7 +313,7 @@ static void bau_process_message(struct msg_desc *mdp, struct bau_control *bcp,
                 * Both sockets dump their completed count total into
                 * the message's count.
                 */
-               smaster->socket_acknowledge_count[mdp->msg_slot] = 0;
+               *sp = 0;
                asp = (struct atomic_short *)&msg->acknowledge_count;
                msg_ack_count = atom_asr(socket_ack_count, asp);
 
@@ -491,16 +526,15 @@ static int uv1_wait_completion(struct bau_desc *bau_desc,
 }
 
 /*
- * UV2 has an extra bit of status in the ACTIVATION_STATUS_2 register.
+ * UV2 could have an extra bit of status in the ACTIVATION_STATUS_2 register.
+ * But not currently used.
  */
 static unsigned long uv2_read_status(unsigned long offset, int rshft, int desc)
 {
        unsigned long descriptor_status;
-       unsigned long descriptor_status2;
 
-       descriptor_status = ((read_lmmr(offset) >> rshft) & UV_ACT_STATUS_MASK);
-       descriptor_status2 = (read_mmr_uv2_status() >> desc) & 0x1UL;
-       descriptor_status = (descriptor_status << 1) | descriptor_status2;
+       descriptor_status =
+               ((read_lmmr(offset) >> rshft) & UV_ACT_STATUS_MASK) << 1;
        return descriptor_status;
 }
 
@@ -531,87 +565,11 @@ int normal_busy(struct bau_control *bcp)
  */
 int handle_uv2_busy(struct bau_control *bcp)
 {
-       int busy_one = bcp->using_desc;
-       int normal = bcp->uvhub_cpu;
-       int selected = -1;
-       int i;
-       unsigned long descriptor_status;
-       unsigned long status;
-       int mmr_offset;
-       struct bau_desc *bau_desc_old;
-       struct bau_desc *bau_desc_new;
-       struct bau_control *hmaster = bcp->uvhub_master;
        struct ptc_stats *stat = bcp->statp;
-       cycles_t ttm;
 
        stat->s_uv2_wars++;
-       spin_lock(&hmaster->uvhub_lock);
-       /* try for the original first */
-       if (busy_one != normal) {
-               if (!normal_busy(bcp))
-                       selected = normal;
-       }
-       if (selected < 0) {
-               /* can't use the normal, select an alternate */
-               mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_1;
-               descriptor_status = read_lmmr(mmr_offset);
-
-               /* scan available descriptors 32-63 */
-               for (i = 0; i < UV_CPUS_PER_AS; i++) {
-                       if ((hmaster->inuse_map & (1 << i)) == 0) {
-                               status = ((descriptor_status >>
-                                               (i * UV_ACT_STATUS_SIZE)) &
-                                               UV_ACT_STATUS_MASK) << 1;
-                               if (status != UV2H_DESC_BUSY) {
-                                       selected = i + UV_CPUS_PER_AS;
-                                       break;
-                               }
-                       }
-               }
-       }
-
-       if (busy_one != normal)
-               /* mark the busy alternate as not in-use */
-               hmaster->inuse_map &= ~(1 << (busy_one - UV_CPUS_PER_AS));
-
-       if (selected >= 0) {
-               /* switch to the selected descriptor */
-               if (selected != normal) {
-                       /* set the selected alternate as in-use */
-                       hmaster->inuse_map |=
-                                       (1 << (selected - UV_CPUS_PER_AS));
-                       if (selected > stat->s_uv2_wars_hw)
-                               stat->s_uv2_wars_hw = selected;
-               }
-               bau_desc_old = bcp->descriptor_base;
-               bau_desc_old += (ITEMS_PER_DESC * busy_one);
-               bcp->using_desc = selected;
-               bau_desc_new = bcp->descriptor_base;
-               bau_desc_new += (ITEMS_PER_DESC * selected);
-               *bau_desc_new = *bau_desc_old;
-       } else {
-               /*
-                * All are busy. Wait for the normal one for this cpu to
-                * free up.
-                */
-               stat->s_uv2_war_waits++;
-               spin_unlock(&hmaster->uvhub_lock);
-               ttm = get_cycles();
-               do {
-                       cpu_relax();
-               } while (normal_busy(bcp));
-               spin_lock(&hmaster->uvhub_lock);
-               /* switch to the original descriptor */
-               bcp->using_desc = normal;
-               bau_desc_old = bcp->descriptor_base;
-               bau_desc_old += (ITEMS_PER_DESC * bcp->using_desc);
-               bcp->using_desc = (ITEMS_PER_DESC * normal);
-               bau_desc_new = bcp->descriptor_base;
-               bau_desc_new += (ITEMS_PER_DESC * normal);
-               *bau_desc_new = *bau_desc_old; /* copy the entire descriptor */
-       }
-       spin_unlock(&hmaster->uvhub_lock);
-       return FLUSH_RETRY_BUSYBUG;
+       bcp->busy = 1;
+       return FLUSH_GIVEUP;
 }
 
 static int uv2_wait_completion(struct bau_desc *bau_desc,
@@ -620,7 +578,7 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
 {
        unsigned long descriptor_stat;
        cycles_t ttm;
-       int desc = bcp->using_desc;
+       int desc = bcp->uvhub_cpu;
        long busy_reps = 0;
        struct ptc_stats *stat = bcp->statp;
 
@@ -628,24 +586,38 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
 
        /* spin on the status MMR, waiting for it to go idle */
        while (descriptor_stat != UV2H_DESC_IDLE) {
-               /*
-                * Our software ack messages may be blocked because
-                * there are no swack resources available.  As long
-                * as none of them has timed out hardware will NACK
-                * our message and its state will stay IDLE.
-                */
-               if ((descriptor_stat == UV2H_DESC_SOURCE_TIMEOUT) ||
-                   (descriptor_stat == UV2H_DESC_DEST_PUT_ERR)) {
+               if ((descriptor_stat == UV2H_DESC_SOURCE_TIMEOUT)) {
+                       /*
+                        * A h/w bug on the destination side may
+                        * have prevented the message being marked
+                        * pending, thus it doesn't get replied to
+                        * and gets continually nacked until it times
+                        * out with a SOURCE_TIMEOUT.
+                        */
                        stat->s_stimeout++;
                        return FLUSH_GIVEUP;
-               } else if (descriptor_stat == UV2H_DESC_DEST_STRONG_NACK) {
-                       stat->s_strongnacks++;
-                       bcp->conseccompletes = 0;
-                       return FLUSH_GIVEUP;
                } else if (descriptor_stat == UV2H_DESC_DEST_TIMEOUT) {
+                       ttm = get_cycles();
+
+                       /*
+                        * Our retries may be blocked by all destination
+                        * swack resources being consumed, and a timeout
+                        * pending.  In that case hardware returns the
+                        * ERROR that looks like a destination timeout.
+                        * Without using the extended status we have to
+                        * deduce from the short time that this was a
+                        * strong nack.
+                        */
+                       if (cycles_2_us(ttm - bcp->send_message) < timeout_us) {
+                               bcp->conseccompletes = 0;
+                               stat->s_plugged++;
+                               /* FLUSH_RETRY_PLUGGED causes hang on boot */
+                               return FLUSH_GIVEUP;
+                       }
                        stat->s_dtimeout++;
                        bcp->conseccompletes = 0;
-                       return FLUSH_RETRY_TIMEOUT;
+                       /* FLUSH_RETRY_TIMEOUT causes hang on boot */
+                       return FLUSH_GIVEUP;
                } else {
                        busy_reps++;
                        if (busy_reps > 1000000) {
@@ -653,9 +625,8 @@ static int uv2_wait_completion(struct bau_desc *bau_desc,
                                busy_reps = 0;
                                ttm = get_cycles();
                                if ((ttm - bcp->send_message) >
-                                       (bcp->clocks_per_100_usec)) {
+                                               bcp->timeout_interval)
                                        return handle_uv2_busy(bcp);
-                               }
                        }
                        /*
                         * descriptor_stat is still BUSY
@@ -679,7 +650,7 @@ static int wait_completion(struct bau_desc *bau_desc,
 {
        int right_shift;
        unsigned long mmr_offset;
-       int desc = bcp->using_desc;
+       int desc = bcp->uvhub_cpu;
 
        if (desc < UV_CPUS_PER_AS) {
                mmr_offset = UVH_LB_BAU_SB_ACTIVATION_STATUS_0;
@@ -758,33 +729,31 @@ static void destination_timeout(struct bau_desc *bau_desc,
 }
 
 /*
- * Completions are taking a very long time due to a congested numalink
- * network.
+ * Stop all cpus on a uvhub from using the BAU for a period of time.
+ * This is reversed by check_enable.
  */
-static void disable_for_congestion(struct bau_control *bcp,
-                                       struct ptc_stats *stat)
+static void disable_for_period(struct bau_control *bcp, struct ptc_stats *stat)
 {
-       /* let only one cpu do this disabling */
-       spin_lock(&disable_lock);
-
-       if (!baudisabled && bcp->period_requests &&
-           ((bcp->period_time / bcp->period_requests) > congested_cycles)) {
-               int tcpu;
-               struct bau_control *tbcp;
-               /* it becomes this cpu's job to turn on the use of the
-                  BAU again */
-               baudisabled = 1;
-               bcp->set_bau_off = 1;
-               bcp->set_bau_on_time = get_cycles();
-               bcp->set_bau_on_time += sec_2_cycles(bcp->cong_period);
+       int tcpu;
+       struct bau_control *tbcp;
+       struct bau_control *hmaster;
+       cycles_t tm1;
+
+       hmaster = bcp->uvhub_master;
+       spin_lock(&hmaster->disable_lock);
+       if (!bcp->baudisabled) {
                stat->s_bau_disabled++;
+               tm1 = get_cycles();
                for_each_present_cpu(tcpu) {
                        tbcp = &per_cpu(bau_control, tcpu);
-                       tbcp->baudisabled = 1;
+                       if (tbcp->uvhub_master == hmaster) {
+                               tbcp->baudisabled = 1;
+                               tbcp->set_bau_on_time =
+                                       tm1 + bcp->disabled_period;
+                       }
                }
        }
-
-       spin_unlock(&disable_lock);
+       spin_unlock(&hmaster->disable_lock);
 }
 
 static void count_max_concurr(int stat, struct bau_control *bcp,
@@ -815,16 +784,30 @@ static void record_send_stats(cycles_t time1, cycles_t time2,
                        bcp->period_requests++;
                        bcp->period_time += elapsed;
                        if ((elapsed > congested_cycles) &&
-                           (bcp->period_requests > bcp->cong_reps))
-                               disable_for_congestion(bcp, stat);
+                           (bcp->period_requests > bcp->cong_reps) &&
+                           ((bcp->period_time / bcp->period_requests) >
+                                                       congested_cycles)) {
+                               stat->s_congested++;
+                               disable_for_period(bcp, stat);
+                       }
                }
        } else
                stat->s_requestor--;
 
        if (completion_status == FLUSH_COMPLETE && try > 1)
                stat->s_retriesok++;
-       else if (completion_status == FLUSH_GIVEUP)
+       else if (completion_status == FLUSH_GIVEUP) {
                stat->s_giveup++;
+               if (get_cycles() > bcp->period_end)
+                       bcp->period_giveups = 0;
+               bcp->period_giveups++;
+               if (bcp->period_giveups == 1)
+                       bcp->period_end = get_cycles() + bcp->disabled_period;
+               if (bcp->period_giveups > bcp->giveup_limit) {
+                       disable_for_period(bcp, stat);
+                       stat->s_giveuplimit++;
+               }
+       }
 }
 
 /*
@@ -868,7 +851,8 @@ static void handle_cmplt(int completion_status, struct bau_desc *bau_desc,
  * Returns 1 if it gives up entirely and the original cpu mask is to be
  * returned to the kernel.
  */
-int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp)
+int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp,
+       struct bau_desc *bau_desc)
 {
        int seq_number = 0;
        int completion_stat = 0;
@@ -881,24 +865,23 @@ int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp)
        struct bau_control *hmaster = bcp->uvhub_master;
        struct uv1_bau_msg_header *uv1_hdr = NULL;
        struct uv2_bau_msg_header *uv2_hdr = NULL;
-       struct bau_desc *bau_desc;
 
-       if (bcp->uvhub_version == 1)
+       if (bcp->uvhub_version == 1) {
+               uv1 = 1;
                uv1_throttle(hmaster, stat);
+       }
 
        while (hmaster->uvhub_quiesce)
                cpu_relax();
 
        time1 = get_cycles();
+       if (uv1)
+               uv1_hdr = &bau_desc->header.uv1_hdr;
+       else
+               uv2_hdr = &bau_desc->header.uv2_hdr;
+
        do {
-               bau_desc = bcp->descriptor_base;
-               bau_desc += (ITEMS_PER_DESC * bcp->using_desc);
-               if (bcp->uvhub_version == 1) {
-                       uv1 = 1;
-                       uv1_hdr = &bau_desc->header.uv1_hdr;
-               } else
-                       uv2_hdr = &bau_desc->header.uv2_hdr;
-               if ((try == 0) || (completion_stat == FLUSH_RETRY_BUSYBUG)) {
+               if (try == 0) {
                        if (uv1)
                                uv1_hdr->msg_type = MSG_REGULAR;
                        else
@@ -916,25 +899,24 @@ int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp)
                        uv1_hdr->sequence = seq_number;
                else
                        uv2_hdr->sequence = seq_number;
-               index = (1UL << AS_PUSH_SHIFT) | bcp->using_desc;
+               index = (1UL << AS_PUSH_SHIFT) | bcp->uvhub_cpu;
                bcp->send_message = get_cycles();
 
                write_mmr_activation(index);
 
                try++;
                completion_stat = wait_completion(bau_desc, bcp, try);
-               /* UV2: wait_completion() may change the bcp->using_desc */
 
                handle_cmplt(completion_stat, bau_desc, bcp, hmaster, stat);
 
                if (bcp->ipi_attempts >= bcp->ipi_reset_limit) {
                        bcp->ipi_attempts = 0;
+                       stat->s_overipilimit++;
                        completion_stat = FLUSH_GIVEUP;
                        break;
                }
                cpu_relax();
        } while ((completion_stat == FLUSH_RETRY_PLUGGED) ||
-                (completion_stat == FLUSH_RETRY_BUSYBUG) ||
                 (completion_stat == FLUSH_RETRY_TIMEOUT));
 
        time2 = get_cycles();
@@ -955,28 +937,33 @@ int uv_flush_send_and_wait(struct cpumask *flush_mask, struct bau_control *bcp)
 }
 
 /*
- * The BAU is disabled. When the disabled time period has expired, the cpu
- * that disabled it must re-enable it.
- * Return 0 if it is re-enabled for all cpus.
+ * The BAU is disabled for this uvhub. When the disabled time period has
+ * expired re-enable it.
+ * Return 0 if it is re-enabled for all cpus on this uvhub.
  */
 static int check_enable(struct bau_control *bcp, struct ptc_stats *stat)
 {
        int tcpu;
        struct bau_control *tbcp;
+       struct bau_control *hmaster;
 
-       if (bcp->set_bau_off) {
-               if (get_cycles() >= bcp->set_bau_on_time) {
-                       stat->s_bau_reenabled++;
-                       baudisabled = 0;
-                       for_each_present_cpu(tcpu) {
-                               tbcp = &per_cpu(bau_control, tcpu);
+       hmaster = bcp->uvhub_master;
+       spin_lock(&hmaster->disable_lock);
+       if (bcp->baudisabled && (get_cycles() >= bcp->set_bau_on_time)) {
+               stat->s_bau_reenabled++;
+               for_each_present_cpu(tcpu) {
+                       tbcp = &per_cpu(bau_control, tcpu);
+                       if (tbcp->uvhub_master == hmaster) {
                                tbcp->baudisabled = 0;
                                tbcp->period_requests = 0;
                                tbcp->period_time = 0;
+                               tbcp->period_giveups = 0;
                        }
-                       return 0;
                }
+               spin_unlock(&hmaster->disable_lock);
+               return 0;
        }
+       spin_unlock(&hmaster->disable_lock);
        return -1;
 }
 
@@ -1078,18 +1065,32 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
        struct cpumask *flush_mask;
        struct ptc_stats *stat;
        struct bau_control *bcp;
-
-       /* kernel was booted 'nobau' */
-       if (nobau)
-               return cpumask;
+       unsigned long descriptor_status;
+       unsigned long status;
 
        bcp = &per_cpu(bau_control, cpu);
        stat = bcp->statp;
+       stat->s_enters++;
+
+       if (bcp->nobau)
+               return cpumask;
+
+       if (bcp->busy) {
+               descriptor_status =
+                       read_lmmr(UVH_LB_BAU_SB_ACTIVATION_STATUS_0);
+               status = ((descriptor_status >> (bcp->uvhub_cpu *
+                       UV_ACT_STATUS_SIZE)) & UV_ACT_STATUS_MASK) << 1;
+               if (status == UV2H_DESC_BUSY)
+                       return cpumask;
+               bcp->busy = 0;
+       }
 
        /* bau was disabled due to slow response */
        if (bcp->baudisabled) {
-               if (check_enable(bcp, stat))
+               if (check_enable(bcp, stat)) {
+                       stat->s_ipifordisabled++;
                        return cpumask;
+               }
        }
 
        /*
@@ -1105,7 +1106,7 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
                stat->s_ntargself++;
 
        bau_desc = bcp->descriptor_base;
-       bau_desc += (ITEMS_PER_DESC * bcp->using_desc);
+       bau_desc += (ITEMS_PER_DESC * bcp->uvhub_cpu);
        bau_uvhubs_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE);
        if (set_distrib_bits(flush_mask, bcp, bau_desc, &locals, &remotes))
                return NULL;
@@ -1118,25 +1119,27 @@ const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
         * uv_flush_send_and_wait returns 0 if all cpu's were messaged,
         * or 1 if it gave up and the original cpumask should be returned.
         */
-       if (!uv_flush_send_and_wait(flush_mask, bcp))
+       if (!uv_flush_send_and_wait(flush_mask, bcp, bau_desc))
                return NULL;
        else
                return cpumask;
 }
 
 /*
- * Search the message queue for any 'other' message with the same software
- * acknowledge resource bit vector.
+ * Search the message queue for any 'other' unprocessed message with the
+ * same software acknowledge resource bit vector as the 'msg' message.
  */
 struct bau_pq_entry *find_another_by_swack(struct bau_pq_entry *msg,
-                       struct bau_control *bcp, unsigned char swack_vec)
+                                          struct bau_control *bcp)
 {
        struct bau_pq_entry *msg_next = msg + 1;
+       unsigned char swack_vec = msg->swack_vec;
 
        if (msg_next > bcp->queue_last)
                msg_next = bcp->queue_first;
-       while ((msg_next->swack_vec != 0) && (msg_next != msg)) {
-               if (msg_next->swack_vec == swack_vec)
+       while (msg_next != msg) {
+               if ((msg_next->canceled == 0) && (msg_next->replied_to == 0) &&
+                               (msg_next->swack_vec == swack_vec))
                        return msg_next;
                msg_next++;
                if (msg_next > bcp->queue_last)
@@ -1165,32 +1168,30 @@ void process_uv2_message(struct msg_desc *mdp, struct bau_control *bcp)
                 * This message was assigned a swack resource, but no
                 * reserved acknowlegment is pending.
                 * The bug has prevented this message from setting the MMR.
-                * And no other message has used the same sw_ack resource.
-                * Do the requested shootdown but do not reply to the msg.
-                * (the 0 means make no acknowledge)
                 */
-               bau_process_message(mdp, bcp, 0);
-               return;
-       }
-
-       /*
-        * Some message has set the MMR 'pending' bit; it might have been
-        * another message.  Look for that message.
-        */
-       other_msg = find_another_by_swack(msg, bcp, msg->swack_vec);
-       if (other_msg) {
-               /* There is another.  Do not ack the current one. */
-               bau_process_message(mdp, bcp, 0);
                /*
-                * Let the natural processing of that message acknowledge
-                * it. Don't get the processing of sw_ack's out of order.
+                * Some message has set the MMR 'pending' bit; it might have
+                * been another message.  Look for that message.
                 */
-               return;
+               other_msg = find_another_by_swack(msg, bcp);
+               if (other_msg) {
+                       /*
+                        * There is another. Process this one but do not
+                        * ack it.
+                        */
+                       bau_process_message(mdp, bcp, 0);
+                       /*
+                        * Let the natural processing of that other message
+                        * acknowledge it. Don't get the processing of sw_ack's
+                        * out of order.
+                        */
+                       return;
+               }
        }
 
        /*
-        * There is no other message using this sw_ack, so it is safe to
-        * acknowledge it.
+        * Either the MMR shows this one pending a reply or there is no
+        * other message using this sw_ack, so it is safe to acknowledge it.
         */
        bau_process_message(mdp, bcp, 1);
 
@@ -1295,7 +1296,8 @@ static void __init enable_timeouts(void)
                 */
                mmr_image |= (1L << SOFTACK_MSHIFT);
                if (is_uv2_hub()) {
-                       mmr_image |= (1L << UV2_EXT_SHFT);
+                       /* hw bug workaround; do not use extended status */
+                       mmr_image &= ~(1L << UV2_EXT_SHFT);
                }
                write_mmr_misc_control(pnode, mmr_image);
        }
@@ -1338,29 +1340,34 @@ static inline unsigned long long usec_2_cycles(unsigned long microsec)
 static int ptc_seq_show(struct seq_file *file, void *data)
 {
        struct ptc_stats *stat;
+       struct bau_control *bcp;
        int cpu;
 
        cpu = *(loff_t *)data;
        if (!cpu) {
                seq_printf(file,
-                       "# cpu sent stime self locals remotes ncpus localhub ");
+                "# cpu bauoff sent stime self locals remotes ncpus localhub ");
                seq_printf(file,
                        "remotehub numuvhubs numuvhubs16 numuvhubs8 ");
                seq_printf(file,
-                   "numuvhubs4 numuvhubs2 numuvhubs1 dto snacks retries rok ");
+                       "numuvhubs4 numuvhubs2 numuvhubs1 dto snacks retries ");
+               seq_printf(file,
+                       "rok resetp resett giveup sto bz throt disable ");
                seq_printf(file,
-                       "resetp resett giveup sto bz throt swack recv rtime ");
+                       "enable wars warshw warwaits enters ipidis plugged ");
                seq_printf(file,
-                       "all one mult none retry canc nocan reset rcan ");
+                       "ipiover glim cong swack recv rtime all one mult ");
                seq_printf(file,
-                       "disable enable wars warshw warwaits\n");
+                       "none retry canc nocan reset rcan\n");
        }
        if (cpu < num_possible_cpus() && cpu_online(cpu)) {
-               stat = &per_cpu(ptcstats, cpu);
+               bcp = &per_cpu(bau_control, cpu);
+               stat = bcp->statp;
                /* source side statistics */
                seq_printf(file,
-                       "cpu %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ",
-                          cpu, stat->s_requestor, cycles_2_us(stat->s_time),
+                       "cpu %d %d %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ",
+                          cpu, bcp->nobau, stat->s_requestor,
+                          cycles_2_us(stat->s_time),
                           stat->s_ntargself, stat->s_ntarglocals,
                           stat->s_ntargremotes, stat->s_ntargcpu,
                           stat->s_ntarglocaluvhub, stat->s_ntargremoteuvhub,
@@ -1374,20 +1381,23 @@ static int ptc_seq_show(struct seq_file *file, void *data)
                           stat->s_resets_plug, stat->s_resets_timeout,
                           stat->s_giveup, stat->s_stimeout,
                           stat->s_busy, stat->s_throttles);
+               seq_printf(file, "%ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ",
+                          stat->s_bau_disabled, stat->s_bau_reenabled,
+                          stat->s_uv2_wars, stat->s_uv2_wars_hw,
+                          stat->s_uv2_war_waits, stat->s_enters,
+                          stat->s_ipifordisabled, stat->s_plugged,
+                          stat->s_overipilimit, stat->s_giveuplimit,
+                          stat->s_congested);
 
                /* destination side statistics */
                seq_printf(file,
-                          "%lx %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld ",
+                       "%lx %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld %ld\n",
                           read_gmmr_sw_ack(uv_cpu_to_pnode(cpu)),
                           stat->d_requestee, cycles_2_us(stat->d_time),
                           stat->d_alltlb, stat->d_onetlb, stat->d_multmsg,
                           stat->d_nomsg, stat->d_retries, stat->d_canceled,
                           stat->d_nocanceled, stat->d_resets,
                           stat->d_rcanceled);
-               seq_printf(file, "%ld %ld %ld %ld %ld\n",
-                       stat->s_bau_disabled, stat->s_bau_reenabled,
-                       stat->s_uv2_wars, stat->s_uv2_wars_hw,
-                       stat->s_uv2_war_waits);
        }
        return 0;
 }
@@ -1401,13 +1411,14 @@ static ssize_t tunables_read(struct file *file, char __user *userbuf,
        char *buf;
        int ret;
 
-       buf = kasprintf(GFP_KERNEL, "%s %s %s\n%d %d %d %d %d %d %d %d %d\n",
-               "max_concur plugged_delay plugsb4reset",
-               "timeoutsb4reset ipi_reset_limit complete_threshold",
-               "congested_response_us congested_reps congested_period",
+       buf = kasprintf(GFP_KERNEL, "%s %s %s\n%d %d %d %d %d %d %d %d %d %d\n",
+               "max_concur plugged_delay plugsb4reset timeoutsb4reset",
+               "ipi_reset_limit complete_threshold congested_response_us",
+               "congested_reps disabled_period giveup_limit",
                max_concurr, plugged_delay, plugsb4reset,
                timeoutsb4reset, ipi_reset_limit, complete_threshold,
-               congested_respns_us, congested_reps, congested_period);
+               congested_respns_us, congested_reps, disabled_period,
+               giveup_limit);
 
        if (!buf)
                return -ENOMEM;
@@ -1438,6 +1449,14 @@ static ssize_t ptc_proc_write(struct file *file, const char __user *user,
                return -EFAULT;
        optstr[count - 1] = '\0';
 
+       if (!strcmp(optstr, "on")) {
+               set_bau_on();
+               return count;
+       } else if (!strcmp(optstr, "off")) {
+               set_bau_off();
+               return count;
+       }
+
        if (strict_strtol(optstr, 10, &input_arg) < 0) {
                printk(KERN_DEBUG "%s is invalid\n", optstr);
                return -EINVAL;
@@ -1570,7 +1589,8 @@ static ssize_t tunables_write(struct file *file, const char __user *user,
                bcp->complete_threshold =       complete_threshold;
                bcp->cong_response_us =         congested_respns_us;
                bcp->cong_reps =                congested_reps;
-               bcp->cong_period =              congested_period;
+               bcp->disabled_period =          sec_2_cycles(disabled_period);
+               bcp->giveup_limit =             giveup_limit;
        }
        return count;
 }
@@ -1699,6 +1719,10 @@ static void activation_descriptor_init(int node, int pnode, int base_pnode)
                         *   fairness chaining multilevel count replied_to
                         */
                } else {
+                       /*
+                        * BIOS uses legacy mode, but UV2 hardware always
+                        * uses native mode for selective broadcasts.
+                        */
                        uv2_hdr = &bd2->header.uv2_hdr;
                        uv2_hdr->swack_flag =   1;
                        uv2_hdr->base_dest_nasid =
@@ -1811,8 +1835,8 @@ static int calculate_destination_timeout(void)
                index = (mmr_image >> BAU_URGENCY_7_SHIFT) & BAU_URGENCY_7_MASK;
                mmr_image = uv_read_local_mmr(UVH_TRANSACTION_TIMEOUT);
                mult2 = (mmr_image >> BAU_TRANS_SHIFT) & BAU_TRANS_MASK;
-               base = timeout_base_ns[index];
-               ts_ns = base * mult1 * mult2;
+               ts_ns = timeout_base_ns[index];
+               ts_ns *= (mult1 * mult2);
                ret = ts_ns / 1000;
        } else {
                /* 4 bits  0/1 for 10/80us base, 3 bits of multiplier */
@@ -1836,6 +1860,8 @@ static void __init init_per_cpu_tunables(void)
        for_each_present_cpu(cpu) {
                bcp = &per_cpu(bau_control, cpu);
                bcp->baudisabled                = 0;
+               if (nobau)
+                       bcp->nobau              = 1;
                bcp->statp                      = &per_cpu(ptcstats, cpu);
                /* time interval to catch a hardware stay-busy bug */
                bcp->timeout_interval           = usec_2_cycles(2*timeout_us);
@@ -1848,10 +1874,11 @@ static void __init init_per_cpu_tunables(void)
                bcp->complete_threshold         = complete_threshold;
                bcp->cong_response_us           = congested_respns_us;
                bcp->cong_reps                  = congested_reps;
-               bcp->cong_period                = congested_period;
-               bcp->clocks_per_100_usec =      usec_2_cycles(100);
+               bcp->disabled_period =          sec_2_cycles(disabled_period);
+               bcp->giveup_limit =             giveup_limit;
                spin_lock_init(&bcp->queue_lock);
                spin_lock_init(&bcp->uvhub_lock);
+               spin_lock_init(&bcp->disable_lock);
        }
 }
 
@@ -1972,7 +1999,6 @@ static int scan_sock(struct socket_desc *sdp, struct uvhub_desc *bdp,
                }
                bcp->uvhub_master = *hmasterp;
                bcp->uvhub_cpu = uv_cpu_hub_info(cpu)->blade_processor_id;
-               bcp->using_desc = bcp->uvhub_cpu;
                if (bcp->uvhub_cpu >= MAX_CPUS_PER_UVHUB) {
                        printk(KERN_EMERG "%d cpus per uvhub invalid\n",
                                bcp->uvhub_cpu);
@@ -2069,16 +2095,12 @@ static int __init uv_bau_init(void)
        if (!is_uv_system())
                return 0;
 
-       if (nobau)
-               return 0;
-
        for_each_possible_cpu(cur_cpu) {
                mask = &per_cpu(uv_flush_tlb_mask, cur_cpu);
                zalloc_cpumask_var_node(mask, GFP_KERNEL, cpu_to_node(cur_cpu));
        }
 
        nuvhubs = uv_num_possible_blades();
-       spin_lock_init(&disable_lock);
        congested_cycles = usec_2_cycles(congested_respns_us);
 
        uv_base_pnode = 0x7fffffff;
@@ -2091,7 +2113,8 @@ static int __init uv_bau_init(void)
        enable_timeouts();
 
        if (init_per_cpu(nuvhubs, uv_base_pnode)) {
-               nobau = 1;
+               set_bau_off();
+               nobau_perm = 1;
                return 0;
        }
 
index f25c2765a5c9b48bbac24551dc2e82fc9e2d2ce2..acf7752da952f52cc43b56f5133f4d8fe97e56e4 100644 (file)
@@ -135,6 +135,7 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
        unsigned long mmr_value;
        struct uv_IO_APIC_route_entry *entry;
        int mmr_pnode, err;
+       unsigned int dest;
 
        BUILD_BUG_ON(sizeof(struct uv_IO_APIC_route_entry) !=
                        sizeof(unsigned long));
@@ -143,6 +144,10 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
        if (err != 0)
                return err;
 
+       err = apic->cpu_mask_to_apicid_and(eligible_cpu, eligible_cpu, &dest);
+       if (err != 0)
+               return err;
+
        if (limit == UV_AFFINITY_CPU)
                irq_set_status_flags(irq, IRQ_NO_BALANCING);
        else
@@ -159,7 +164,7 @@ arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
        entry->polarity         = 0;
        entry->trigger          = 0;
        entry->mask             = 0;
-       entry->dest             = apic->cpu_mask_to_apicid(eligible_cpu);
+       entry->dest             = dest;
 
        mmr_pnode = uv_blade_to_pnode(mmr_blade);
        uv_write_global_mmr64(mmr_pnode, mmr_offset, mmr_value);
@@ -222,7 +227,7 @@ uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask,
        if (cfg->move_in_progress)
                send_cleanup_vector(cfg);
 
-       return 0;
+       return IRQ_SET_MASK_OK_NOCOPY;
 }
 
 /*
index 5b84a2d308885d9ce8c7e3f861fe269b721f1982..b2d534cab25fc1500c456efbde000779d794e229 100644 (file)
@@ -22,7 +22,7 @@ wakeup-objs   += video-bios.o
 realmode-y                     += header.o
 realmode-y                     += trampoline_$(BITS).o
 realmode-y                     += stack.o
-realmode-$(CONFIG_X86_32)      += reboot_32.o
+realmode-y                     += reboot.o
 realmode-$(CONFIG_ACPI_SLEEP)  += $(wakeup-objs)
 
 targets        += $(realmode-y)
index fadf48378adac71fdd9d4ef76f74b876e0572aa7..a28221d94e69eb60fc18aab9c5997ed52a7a763f 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <linux/linkage.h>
 #include <asm/page_types.h>
+#include <asm/segment.h>
 
 #include "realmode.h"
        
@@ -28,8 +29,9 @@ GLOBAL(real_mode_header)
        .long   pa_wakeup_header
 #endif
        /* APM/BIOS reboot */
-#ifdef CONFIG_X86_32
        .long   pa_machine_real_restart_asm
+#ifdef CONFIG_X86_64
+       .long   __KERNEL32_CS
 #endif
 END(real_mode_header)
 
diff --git a/arch/x86/realmode/rm/reboot.S b/arch/x86/realmode/rm/reboot.S
new file mode 100644 (file)
index 0000000..f932ea6
--- /dev/null
@@ -0,0 +1,156 @@
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/segment.h>
+#include <asm/page_types.h>
+#include <asm/processor-flags.h>
+#include <asm/msr-index.h>
+#include "realmode.h"
+
+/*
+ * The following code and data reboots the machine by switching to real
+ * mode and jumping to the BIOS reset entry point, as if the CPU has
+ * really been reset.  The previous version asked the keyboard
+ * controller to pulse the CPU reset line, which is more thorough, but
+ * doesn't work with at least one type of 486 motherboard.  It is easy
+ * to stop this code working; hence the copious comments.
+ *
+ * This code is called with the restart type (0 = BIOS, 1 = APM) in
+ * the primary argument register (%eax for 32 bit, %edi for 64 bit).
+ */
+       .section ".text32", "ax"
+       .code32
+ENTRY(machine_real_restart_asm)
+
+#ifdef CONFIG_X86_64
+       /* Switch to trampoline GDT as it is guaranteed < 4 GiB */
+       movl    $__KERNEL_DS, %eax
+       movl    %eax, %ds
+       lgdtl   pa_tr_gdt
+
+       /* Disable paging to drop us out of long mode */
+       movl    %cr0, %eax
+       andl    $~X86_CR0_PG, %eax
+       movl    %eax, %cr0
+       ljmpl   $__KERNEL32_CS, $pa_machine_real_restart_paging_off
+
+GLOBAL(machine_real_restart_paging_off)
+       xorl    %eax, %eax
+       xorl    %edx, %edx
+       movl    $MSR_EFER, %ecx
+       wrmsr
+
+       movl    %edi, %eax
+       
+#endif /* CONFIG_X86_64 */
+       
+       /* Set up the IDT for real mode. */
+       lidtl   pa_machine_real_restart_idt
+
+       /*
+        * Set up a GDT from which we can load segment descriptors for real
+        * mode.  The GDT is not used in real mode; it is just needed here to
+        * prepare the descriptors.
+        */
+       lgdtl   pa_machine_real_restart_gdt
+
+       /*
+        * Load the data segment registers with 16-bit compatible values
+        */
+       movl    $16, %ecx
+       movl    %ecx, %ds
+       movl    %ecx, %es
+       movl    %ecx, %fs
+       movl    %ecx, %gs
+       movl    %ecx, %ss
+       ljmpw   $8, $1f
+
+/*
+ * This is 16-bit protected mode code to disable paging and the cache,
+ * switch to real mode and jump to the BIOS reset code.
+ *
+ * The instruction that switches to real mode by writing to CR0 must be
+ * followed immediately by a far jump instruction, which set CS to a
+ * valid value for real mode, and flushes the prefetch queue to avoid
+ * running instructions that have already been decoded in protected
+ * mode.
+ *
+ * Clears all the flags except ET, especially PG (paging), PE
+ * (protected-mode enable) and TS (task switch for coprocessor state
+ * save).  Flushes the TLB after paging has been disabled.  Sets CD and
+ * NW, to disable the cache on a 486, and invalidates the cache.  This
+ * is more like the state of a 486 after reset.  I don't know if
+ * something else should be done for other chips.
+ *
+ * More could be done here to set up the registers as if a CPU reset had
+ * occurred; hopefully real BIOSs don't assume much.  This is not the
+ * actual BIOS entry point, anyway (that is at 0xfffffff0).
+ *
+ * Most of this work is probably excessive, but it is what is tested.
+ */
+       .text
+       .code16
+
+       .balign 16
+machine_real_restart_asm16:
+1:
+       xorl    %ecx, %ecx
+       movl    %cr0, %edx
+       andl    $0x00000011, %edx
+       orl     $0x60000000, %edx
+       movl    %edx, %cr0
+       movl    %ecx, %cr3
+       movl    %cr0, %edx
+       testl   $0x60000000, %edx       /* If no cache bits -> no wbinvd */
+       jz      2f
+       wbinvd
+2:
+       andb    $0x10, %dl
+       movl    %edx, %cr0
+       LJMPW_RM(3f)
+3:
+       andw    %ax, %ax
+       jz      bios
+
+apm:
+       movw    $0x1000, %ax
+       movw    %ax, %ss
+       movw    $0xf000, %sp
+       movw    $0x5307, %ax
+       movw    $0x0001, %bx
+       movw    $0x0003, %cx
+       int     $0x15
+       /* This should never return... */
+
+bios:
+       ljmpw   $0xf000, $0xfff0
+
+       .section ".rodata", "a"
+
+       .balign 16
+GLOBAL(machine_real_restart_idt)
+       .word   0xffff          /* Length - real mode default value */
+       .long   0               /* Base - real mode default value */
+END(machine_real_restart_idt)
+
+       .balign 16
+GLOBAL(machine_real_restart_gdt)
+       /* Self-pointer */
+       .word   0xffff          /* Length - real mode default value */
+       .long   pa_machine_real_restart_gdt
+       .word   0
+
+       /*
+        * 16-bit code segment pointing to real_mode_seg
+        * Selector value 8
+        */
+       .word   0xffff          /* Limit */
+       .long   0x9b000000 + pa_real_mode_base
+       .word   0
+
+       /*
+        * 16-bit data segment with the selector value 16 = 0x10 and
+        * base value 0x100; since this is consistent with real mode
+        * semantics we don't have to reload the segments once CR0.PE = 0.
+        */
+       .quad   GDT_ENTRY(0x0093, 0x100, 0xffff)
+END(machine_real_restart_gdt)
diff --git a/arch/x86/realmode/rm/reboot_32.S b/arch/x86/realmode/rm/reboot_32.S
deleted file mode 100644 (file)
index 1140448..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/segment.h>
-#include <asm/page_types.h>
-#include "realmode.h"
-
-/*
- * The following code and data reboots the machine by switching to real
- * mode and jumping to the BIOS reset entry point, as if the CPU has
- * really been reset.  The previous version asked the keyboard
- * controller to pulse the CPU reset line, which is more thorough, but
- * doesn't work with at least one type of 486 motherboard.  It is easy
- * to stop this code working; hence the copious comments.
- *
- * This code is called with the restart type (0 = BIOS, 1 = APM) in %eax.
- */
-       .section ".text32", "ax"
-       .code32
-
-       .balign 16
-ENTRY(machine_real_restart_asm)
-       /* Set up the IDT for real mode. */
-       lidtl   pa_machine_real_restart_idt
-
-       /*
-        * Set up a GDT from which we can load segment descriptors for real
-        * mode.  The GDT is not used in real mode; it is just needed here to
-        * prepare the descriptors.
-        */
-       lgdtl   pa_machine_real_restart_gdt
-
-       /*
-        * Load the data segment registers with 16-bit compatible values
-        */
-       movl    $16, %ecx
-       movl    %ecx, %ds
-       movl    %ecx, %es
-       movl    %ecx, %fs
-       movl    %ecx, %gs
-       movl    %ecx, %ss
-       ljmpw   $8, $1f
-
-/*
- * This is 16-bit protected mode code to disable paging and the cache,
- * switch to real mode and jump to the BIOS reset code.
- *
- * The instruction that switches to real mode by writing to CR0 must be
- * followed immediately by a far jump instruction, which set CS to a
- * valid value for real mode, and flushes the prefetch queue to avoid
- * running instructions that have already been decoded in protected
- * mode.
- *
- * Clears all the flags except ET, especially PG (paging), PE
- * (protected-mode enable) and TS (task switch for coprocessor state
- * save).  Flushes the TLB after paging has been disabled.  Sets CD and
- * NW, to disable the cache on a 486, and invalidates the cache.  This
- * is more like the state of a 486 after reset.  I don't know if
- * something else should be done for other chips.
- *
- * More could be done here to set up the registers as if a CPU reset had
- * occurred; hopefully real BIOSs don't assume much.  This is not the
- * actual BIOS entry point, anyway (that is at 0xfffffff0).
- *
- * Most of this work is probably excessive, but it is what is tested.
- */
-       .text
-       .code16
-
-       .balign 16
-machine_real_restart_asm16:
-1:
-       xorl    %ecx, %ecx
-       movl    %cr0, %edx
-       andl    $0x00000011, %edx
-       orl     $0x60000000, %edx
-       movl    %edx, %cr0
-       movl    %ecx, %cr3
-       movl    %cr0, %edx
-       testl   $0x60000000, %edx       /* If no cache bits -> no wbinvd */
-       jz      2f
-       wbinvd
-2:
-       andb    $0x10, %dl
-       movl    %edx, %cr0
-       LJMPW_RM(3f)
-3:
-       andw    %ax, %ax
-       jz      bios
-
-apm:
-       movw    $0x1000, %ax
-       movw    %ax, %ss
-       movw    $0xf000, %sp
-       movw    $0x5307, %ax
-       movw    $0x0001, %bx
-       movw    $0x0003, %cx
-       int     $0x15
-       /* This should never return... */
-
-bios:
-       ljmpw   $0xf000, $0xfff0
-
-       .section ".rodata", "a"
-
-       .balign 16
-GLOBAL(machine_real_restart_idt)
-       .word   0xffff          /* Length - real mode default value */
-       .long   0               /* Base - real mode default value */
-END(machine_real_restart_idt)
-
-       .balign 16
-GLOBAL(machine_real_restart_gdt)
-       /* Self-pointer */
-       .word   0xffff          /* Length - real mode default value */
-       .long   pa_machine_real_restart_gdt
-       .word   0
-
-       /*
-        * 16-bit code segment pointing to real_mode_seg
-        * Selector value 8
-        */
-       .word   0xffff          /* Limit */
-       .long   0x9b000000 + pa_real_mode_base
-       .word   0
-
-       /*
-        * 16-bit data segment with the selector value 16 = 0x10 and
-        * base value 0x100; since this is consistent with real mode
-        * semantics we don't have to reload the segments once CR0.PE = 0.
-        */
-       .quad   GDT_ENTRY(0x0093, 0x100, 0xffff)
-END(machine_real_restart_gdt)
index 66e6d93598262a2877666f1d1163125207f9c89a..0faad646f5fda8eb40c64a95e685c2c919daadf6 100644 (file)
@@ -205,9 +205,9 @@ void syscall32_cpu_init(void)
 {
        /* Load these always in case some future AMD CPU supports
           SYSENTER from compat mode too. */
-       checking_wrmsrl(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
-       checking_wrmsrl(MSR_IA32_SYSENTER_ESP, 0ULL);
-       checking_wrmsrl(MSR_IA32_SYSENTER_EIP, (u64)ia32_sysenter_target);
+       wrmsrl_safe(MSR_IA32_SYSENTER_CS, (u64)__KERNEL_CS);
+       wrmsrl_safe(MSR_IA32_SYSENTER_ESP, 0ULL);
+       wrmsrl_safe(MSR_IA32_SYSENTER_EIP, (u64)ia32_sysenter_target);
 
        wrmsrl(MSR_CSTAR, ia32_cstar_target);
 }
index ff962d4b821e5162415fa06ddf75e8c57d498b51..ed7d54985d0cb558b6e4177d2891a9609fa3e1e6 100644 (file)
@@ -1124,9 +1124,7 @@ static const struct pv_cpu_ops xen_cpu_ops __initconst = {
        .wbinvd = native_wbinvd,
 
        .read_msr = native_read_msr_safe,
-       .rdmsr_regs = native_rdmsr_safe_regs,
        .write_msr = xen_write_msr_safe,
-       .wrmsr_regs = native_wrmsr_safe_regs,
 
        .read_tsc = native_read_tsc,
        .read_pmc = native_read_pmc,
index afb250d22a6b2e29cf96f54e48bc6f619dab2ca7..f58dca7a6e52cef85503753f4b500d4d8f7ec369 100644 (file)
@@ -80,9 +80,7 @@ static void __cpuinit cpu_bringup(void)
 
        notify_cpu_starting(cpu);
 
-       ipi_call_lock();
        set_cpu_online(cpu, true);
-       ipi_call_unlock();
 
        this_cpu_write(cpu_state, CPU_ONLINE);
 
index 6512b20aeccdce0184a6a5c524af85c6f7f6db91..ff9f6bd483013b44d1dd152ad17df1e3030a8a9d 100644 (file)
@@ -61,7 +61,6 @@ static int acpi_ac_open_fs(struct inode *inode, struct file *file);
 
 static int acpi_ac_add(struct acpi_device *device);
 static int acpi_ac_remove(struct acpi_device *device, int type);
-static int acpi_ac_resume(struct acpi_device *device);
 static void acpi_ac_notify(struct acpi_device *device, u32 event);
 
 static const struct acpi_device_id ac_device_ids[] = {
@@ -70,6 +69,9 @@ static const struct acpi_device_id ac_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, ac_device_ids);
 
+static int acpi_ac_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_ac_pm, NULL, acpi_ac_resume);
+
 static struct acpi_driver acpi_ac_driver = {
        .name = "ac",
        .class = ACPI_AC_CLASS,
@@ -78,9 +80,9 @@ static struct acpi_driver acpi_ac_driver = {
        .ops = {
                .add = acpi_ac_add,
                .remove = acpi_ac_remove,
-               .resume = acpi_ac_resume,
                .notify = acpi_ac_notify,
                },
+       .drv.pm = &acpi_ac_pm,
 };
 
 struct acpi_ac {
@@ -309,13 +311,18 @@ static int acpi_ac_add(struct acpi_device *device)
        return result;
 }
 
-static int acpi_ac_resume(struct acpi_device *device)
+static int acpi_ac_resume(struct device *dev)
 {
        struct acpi_ac *ac;
        unsigned old_state;
-       if (!device || !acpi_driver_data(device))
+
+       if (!dev)
                return -EINVAL;
-       ac = acpi_driver_data(device);
+
+       ac = acpi_driver_data(to_acpi_device(dev));
+       if (!ac)
+               return -EINVAL;
+
        old_state = ac->state;
        if (acpi_ac_get_state(ac))
                return 0;
index 7dd3f9fb9f3f21b808e30b8aa78f65fce7b2275a..023f9c8534d0607c3d6532b43e696961800d9e6c 100644 (file)
@@ -1044,17 +1044,24 @@ static int acpi_battery_remove(struct acpi_device *device, int type)
 }
 
 /* this is needed to learn about changes made in suspended state */
-static int acpi_battery_resume(struct acpi_device *device)
+static int acpi_battery_resume(struct device *dev)
 {
        struct acpi_battery *battery;
-       if (!device)
+
+       if (!dev)
                return -EINVAL;
-       battery = acpi_driver_data(device);
+
+       battery = acpi_driver_data(to_acpi_device(dev));
+       if (!battery)
+               return -EINVAL;
+
        battery->update_time = 0;
        acpi_battery_update(battery);
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume);
+
 static struct acpi_driver acpi_battery_driver = {
        .name = "battery",
        .class = ACPI_BATTERY_CLASS,
@@ -1062,10 +1069,10 @@ static struct acpi_driver acpi_battery_driver = {
        .flags = ACPI_DRIVER_ALL_NOTIFY_EVENTS,
        .ops = {
                .add = acpi_battery_add,
-               .resume = acpi_battery_resume,
                .remove = acpi_battery_remove,
                .notify = acpi_battery_notify,
                },
+       .drv.pm = &acpi_battery_pm,
 };
 
 static void __init acpi_battery_init_async(void *unused, async_cookie_t cookie)
index d27d072472f9a638fac8da78d507438b0bb3bf5e..79d4c22f7a6d82c21e786b591f02f8bfe28b0f43 100644 (file)
@@ -76,19 +76,21 @@ MODULE_DEVICE_TABLE(acpi, button_device_ids);
 
 static int acpi_button_add(struct acpi_device *device);
 static int acpi_button_remove(struct acpi_device *device, int type);
-static int acpi_button_resume(struct acpi_device *device);
 static void acpi_button_notify(struct acpi_device *device, u32 event);
 
+static int acpi_button_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume);
+
 static struct acpi_driver acpi_button_driver = {
        .name = "button",
        .class = ACPI_BUTTON_CLASS,
        .ids = button_device_ids,
        .ops = {
                .add = acpi_button_add,
-               .resume = acpi_button_resume,
                .remove = acpi_button_remove,
                .notify = acpi_button_notify,
        },
+       .drv.pm = &acpi_button_pm,
 };
 
 struct acpi_button {
@@ -308,8 +310,9 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
        }
 }
 
-static int acpi_button_resume(struct acpi_device *device)
+static int acpi_button_resume(struct device *dev)
 {
+       struct acpi_device *device = to_acpi_device(dev);
        struct acpi_button *button = acpi_driver_data(device);
 
        if (button->type == ACPI_BUTTON_TYPE_LID)
index 0f0356ca1a9e99c24bd17f63e910538e63fc7a79..669d9ee80d1678b7665a3b4b8b2ad709743a44aa 100644 (file)
@@ -46,8 +46,6 @@ MODULE_LICENSE("GPL");
 
 static int acpi_fan_add(struct acpi_device *device);
 static int acpi_fan_remove(struct acpi_device *device, int type);
-static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state);
-static int acpi_fan_resume(struct acpi_device *device);
 
 static const struct acpi_device_id fan_device_ids[] = {
        {"PNP0C0B", 0},
@@ -55,6 +53,10 @@ static const struct acpi_device_id fan_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, fan_device_ids);
 
+static int acpi_fan_suspend(struct device *dev);
+static int acpi_fan_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_fan_pm, acpi_fan_suspend, acpi_fan_resume);
+
 static struct acpi_driver acpi_fan_driver = {
        .name = "fan",
        .class = ACPI_FAN_CLASS,
@@ -62,9 +64,8 @@ static struct acpi_driver acpi_fan_driver = {
        .ops = {
                .add = acpi_fan_add,
                .remove = acpi_fan_remove,
-               .suspend = acpi_fan_suspend,
-               .resume = acpi_fan_resume,
                },
+       .drv.pm = &acpi_fan_pm,
 };
 
 /* thermal cooling device callbacks */
@@ -183,24 +184,24 @@ static int acpi_fan_remove(struct acpi_device *device, int type)
        return 0;
 }
 
-static int acpi_fan_suspend(struct acpi_device *device, pm_message_t state)
+static int acpi_fan_suspend(struct device *dev)
 {
-       if (!device)
+       if (!dev)
                return -EINVAL;
 
-       acpi_bus_set_power(device->handle, ACPI_STATE_D0);
+       acpi_bus_set_power(to_acpi_device(dev)->handle, ACPI_STATE_D0);
 
        return AE_OK;
 }
 
-static int acpi_fan_resume(struct acpi_device *device)
+static int acpi_fan_resume(struct device *dev)
 {
        int result;
 
-       if (!device)
+       if (!dev)
                return -EINVAL;
 
-       result = acpi_bus_update_power(device->handle, NULL);
+       result = acpi_bus_update_power(to_acpi_device(dev)->handle, NULL);
        if (result)
                printk(KERN_ERR PREFIX "Error updating fan power state\n");
 
index dd6d6a3c6780d7e787c1c3427b808618d8c64fa4..894d45c6bc67793d84198416fe1940e2fe42dc19 100644 (file)
@@ -60,7 +60,6 @@ ACPI_MODULE_NAME("power");
 
 static int acpi_power_add(struct acpi_device *device);
 static int acpi_power_remove(struct acpi_device *device, int type);
-static int acpi_power_resume(struct acpi_device *device);
 
 static const struct acpi_device_id power_device_ids[] = {
        {ACPI_POWER_HID, 0},
@@ -68,6 +67,9 @@ static const struct acpi_device_id power_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, power_device_ids);
 
+static int acpi_power_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_power_pm, NULL, acpi_power_resume);
+
 static struct acpi_driver acpi_power_driver = {
        .name = "power",
        .class = ACPI_POWER_CLASS,
@@ -75,8 +77,8 @@ static struct acpi_driver acpi_power_driver = {
        .ops = {
                .add = acpi_power_add,
                .remove = acpi_power_remove,
-               .resume = acpi_power_resume,
                },
+       .drv.pm = &acpi_power_pm,
 };
 
 /*
@@ -771,14 +773,16 @@ static int acpi_power_remove(struct acpi_device *device, int type)
        return 0;
 }
 
-static int acpi_power_resume(struct acpi_device *device)
+static int acpi_power_resume(struct device *dev)
 {
        int result = 0, state;
+       struct acpi_device *device;
        struct acpi_power_resource *resource;
 
-       if (!device)
+       if (!dev)
                return -EINVAL;
 
+       device = to_acpi_device(dev);
        resource = acpi_driver_data(device);
        if (!resource)
                return -EINVAL;
index 0734086537b89732ba805158389b904e94ae7ecf..7048b97853e0f547acb2347b76393193c4809e4e 100644 (file)
@@ -93,6 +93,9 @@ static const struct acpi_device_id processor_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, processor_device_ids);
 
+static SIMPLE_DEV_PM_OPS(acpi_processor_pm,
+                        acpi_processor_suspend, acpi_processor_resume);
+
 static struct acpi_driver acpi_processor_driver = {
        .name = "processor",
        .class = ACPI_PROCESSOR_CLASS,
@@ -100,10 +103,9 @@ static struct acpi_driver acpi_processor_driver = {
        .ops = {
                .add = acpi_processor_add,
                .remove = acpi_processor_remove,
-               .suspend = acpi_processor_suspend,
-               .resume = acpi_processor_resume,
                .notify = acpi_processor_notify,
                },
+       .drv.pm = &acpi_processor_pm,
 };
 
 #define INSTALL_NOTIFY_HANDLER         1
@@ -427,18 +429,11 @@ static int acpi_cpu_soft_notify(struct notifier_block *nfb,
                 * Initialize missing things
                 */
                if (pr->flags.need_hotplug_init) {
-                       struct cpuidle_driver *idle_driver =
-                               cpuidle_get_driver();
-
                        printk(KERN_INFO "Will online and init hotplugged "
                               "CPU: %d\n", pr->id);
                        WARN(acpi_processor_start(pr), "Failed to start CPU:"
                                " %d\n", pr->id);
                        pr->flags.need_hotplug_init = 0;
-                       if (idle_driver && !strcmp(idle_driver->name,
-                                                  "intel_idle")) {
-                               intel_idle_cpu_init(pr->id);
-                       }
                /* Normal CPU soft online event */
                } else {
                        acpi_processor_ppc_has_changed(pr, 0);
index 47a8caa89dbe58fc00bafa17bc75e2dba079eb8a..e589c1985248b6832b0756b861ca32f894468ad9 100644 (file)
@@ -221,10 +221,6 @@ static void lapic_timer_state_broadcast(struct acpi_processor *pr,
 
 #endif
 
-/*
- * Suspend / resume control
- */
-static int acpi_idle_suspend;
 static u32 saved_bm_rld;
 
 static void acpi_idle_bm_rld_save(void)
@@ -241,23 +237,15 @@ static void acpi_idle_bm_rld_restore(void)
                acpi_write_bit_register(ACPI_BITREG_BUS_MASTER_RLD, saved_bm_rld);
 }
 
-int acpi_processor_suspend(struct acpi_device * device, pm_message_t state)
+int acpi_processor_suspend(struct device *dev)
 {
-       if (acpi_idle_suspend == 1)
-               return 0;
-
        acpi_idle_bm_rld_save();
-       acpi_idle_suspend = 1;
        return 0;
 }
 
-int acpi_processor_resume(struct acpi_device * device)
+int acpi_processor_resume(struct device *dev)
 {
-       if (acpi_idle_suspend == 0)
-               return 0;
-
        acpi_idle_bm_rld_restore();
-       acpi_idle_suspend = 0;
        return 0;
 }
 
@@ -595,7 +583,6 @@ static void acpi_processor_power_verify_c3(struct acpi_processor *pr,
         */
        cx->valid = 1;
 
-       cx->latency_ticks = cx->latency;
        /*
         * On older chipsets, BM_RLD needs to be set
         * in order for Bus Master activity to wake the
@@ -628,7 +615,6 @@ static int acpi_processor_power_verify(struct acpi_processor *pr)
                        if (!cx->address)
                                break;
                        cx->valid = 1; 
-                       cx->latency_ticks = cx->latency; /* Normalize latency */
                        break;
 
                case ACPI_STATE_C3:
@@ -763,11 +749,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
 
        local_irq_disable();
 
-       if (acpi_idle_suspend) {
-               local_irq_enable();
-               cpu_relax();
-               return -EBUSY;
-       }
 
        lapic_timer_state_broadcast(pr, cx, 1);
        kt1 = ktime_get_real();
@@ -779,7 +760,6 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev,
        dev->last_residency = (int)idle_time;
 
        local_irq_enable();
-       cx->usage++;
        lapic_timer_state_broadcast(pr, cx, 0);
 
        return index;
@@ -838,11 +818,6 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
 
        local_irq_disable();
 
-       if (acpi_idle_suspend) {
-               local_irq_enable();
-               cpu_relax();
-               return -EBUSY;
-       }
 
        if (cx->entry_method != ACPI_CSTATE_FFH) {
                current_thread_info()->status &= ~TS_POLLING;
@@ -887,10 +862,7 @@ static int acpi_idle_enter_simple(struct cpuidle_device *dev,
        if (cx->entry_method != ACPI_CSTATE_FFH)
                current_thread_info()->status |= TS_POLLING;
 
-       cx->usage++;
-
        lapic_timer_state_broadcast(pr, cx, 0);
-       cx->time += idle_time;
        return index;
 }
 
@@ -928,8 +900,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
                                                drv, drv->safe_state_index);
                } else {
                        local_irq_disable();
-                       if (!acpi_idle_suspend)
-                               acpi_safe_halt();
+                       acpi_safe_halt();
                        local_irq_enable();
                        return -EBUSY;
                }
@@ -937,11 +908,6 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
 
        local_irq_disable();
 
-       if (acpi_idle_suspend) {
-               local_irq_enable();
-               cpu_relax();
-               return -EBUSY;
-       }
 
        if (cx->entry_method != ACPI_CSTATE_FFH) {
                current_thread_info()->status &= ~TS_POLLING;
@@ -1014,10 +980,7 @@ static int acpi_idle_enter_bm(struct cpuidle_device *dev,
        if (cx->entry_method != ACPI_CSTATE_FFH)
                current_thread_info()->status |= TS_POLLING;
 
-       cx->usage++;
-
        lapic_timer_state_broadcast(pr, cx, 0);
-       cx->time += idle_time;
        return index;
 }
 
index 6e36d0c0057c1303464aca74ba0a2b1d9ad3bc25..c0b9aa5faf4cdfd8d354fa89e8204704714cccf1 100644 (file)
@@ -988,16 +988,18 @@ static void acpi_sbs_rmdirs(void)
 #endif
 }
 
-static int acpi_sbs_resume(struct acpi_device *device)
+static int acpi_sbs_resume(struct device *dev)
 {
        struct acpi_sbs *sbs;
-       if (!device)
+       if (!dev)
                return -EINVAL;
-       sbs = device->driver_data;
+       sbs = to_acpi_device(dev)->driver_data;
        acpi_sbs_callback(sbs);
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(acpi_sbs_pm, NULL, acpi_sbs_resume);
+
 static struct acpi_driver acpi_sbs_driver = {
        .name = "sbs",
        .class = ACPI_SBS_CLASS,
@@ -1005,8 +1007,8 @@ static struct acpi_driver acpi_sbs_driver = {
        .ops = {
                .add = acpi_sbs_add,
                .remove = acpi_sbs_remove,
-               .resume = acpi_sbs_resume,
                },
+       .drv.pm = &acpi_sbs_pm,
 };
 
 static int __init acpi_sbs_init(void)
index c8a1f3b68110b86dd2c6b0ddddc91ee2085e93b1..fdda49336560acd2b0eb766430a811d6d842bf0c 100644 (file)
@@ -290,26 +290,6 @@ static void acpi_device_release(struct device *dev)
        kfree(acpi_dev);
 }
 
-static int acpi_device_suspend(struct device *dev, pm_message_t state)
-{
-       struct acpi_device *acpi_dev = to_acpi_device(dev);
-       struct acpi_driver *acpi_drv = acpi_dev->driver;
-
-       if (acpi_drv && acpi_drv->ops.suspend)
-               return acpi_drv->ops.suspend(acpi_dev, state);
-       return 0;
-}
-
-static int acpi_device_resume(struct device *dev)
-{
-       struct acpi_device *acpi_dev = to_acpi_device(dev);
-       struct acpi_driver *acpi_drv = acpi_dev->driver;
-
-       if (acpi_drv && acpi_drv->ops.resume)
-               return acpi_drv->ops.resume(acpi_dev);
-       return 0;
-}
-
 static int acpi_bus_match(struct device *dev, struct device_driver *drv)
 {
        struct acpi_device *acpi_dev = to_acpi_device(dev);
@@ -441,8 +421,6 @@ static int acpi_device_remove(struct device * dev)
 
 struct bus_type acpi_bus_type = {
        .name           = "acpi",
-       .suspend        = acpi_device_suspend,
-       .resume         = acpi_device_resume,
        .match          = acpi_bus_match,
        .probe          = acpi_device_probe,
        .remove         = acpi_device_remove,
index 7dbebea1ec31302bcb3eaac60d0aa3dd8fb9f7af..21dd4c268aefca37746498da131edee6a8c574f0 100644 (file)
@@ -98,7 +98,6 @@ MODULE_PARM_DESC(psv, "Disable or override all passive trip points.");
 
 static int acpi_thermal_add(struct acpi_device *device);
 static int acpi_thermal_remove(struct acpi_device *device, int type);
-static int acpi_thermal_resume(struct acpi_device *device);
 static void acpi_thermal_notify(struct acpi_device *device, u32 event);
 
 static const struct acpi_device_id  thermal_device_ids[] = {
@@ -107,6 +106,9 @@ static const struct acpi_device_id  thermal_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, thermal_device_ids);
 
+static int acpi_thermal_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_thermal_pm, NULL, acpi_thermal_resume);
+
 static struct acpi_driver acpi_thermal_driver = {
        .name = "thermal",
        .class = ACPI_THERMAL_CLASS,
@@ -114,9 +116,9 @@ static struct acpi_driver acpi_thermal_driver = {
        .ops = {
                .add = acpi_thermal_add,
                .remove = acpi_thermal_remove,
-               .resume = acpi_thermal_resume,
                .notify = acpi_thermal_notify,
                },
+       .drv.pm = &acpi_thermal_pm,
 };
 
 struct acpi_thermal_state {
@@ -1041,16 +1043,17 @@ static int acpi_thermal_remove(struct acpi_device *device, int type)
        return 0;
 }
 
-static int acpi_thermal_resume(struct acpi_device *device)
+static int acpi_thermal_resume(struct device *dev)
 {
-       struct acpi_thermal *tz = NULL;
+       struct acpi_thermal *tz;
        int i, j, power_state, result;
 
-
-       if (!device || !acpi_driver_data(device))
+       if (!dev)
                return -EINVAL;
 
-       tz = acpi_driver_data(device);
+       tz = acpi_driver_data(to_acpi_device(dev));
+       if (!tz)
+               return -EINVAL;
 
        for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE; i++) {
                if (!(&tz->trips.active[i]))
index aa0b1f16052875a9af91dcc46cbc755259a7baa3..0b6f0b28a4872b2aa32fe6f1e656ff1ae4ca213d 100644 (file)
@@ -264,11 +264,6 @@ static int __devinit tegra_ahb_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit tegra_ahb_remove(struct platform_device *pdev)
-{
-       return 0;
-}
-
 static const struct of_device_id tegra_ahb_of_match[] __devinitconst = {
        { .compatible = "nvidia,tegra30-ahb", },
        { .compatible = "nvidia,tegra20-ahb", },
@@ -277,7 +272,6 @@ static const struct of_device_id tegra_ahb_of_match[] __devinitconst = {
 
 static struct platform_driver tegra_ahb_driver = {
        .probe = tegra_ahb_probe,
-       .remove = __devexit_p(tegra_ahb_remove),
        .driver = {
                .name = DRV_NAME,
                .owner = THIS_MODULE,
index 765c3a28077af1998e264b932a9781afe633427d..d91a3a0b23258a516f352162a5d051df17959e80 100644 (file)
@@ -227,33 +227,24 @@ static int handle_create(const char *nodename, umode_t mode, struct device *dev)
 
 static int dev_rmdir(const char *name)
 {
-       struct nameidata nd;
+       struct path parent;
        struct dentry *dentry;
        int err;
 
-       err = kern_path_parent(name, &nd);
-       if (err)
-               return err;
-
-       mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
-       dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
-       if (!IS_ERR(dentry)) {
-               if (dentry->d_inode) {
-                       if (dentry->d_inode->i_private == &thread)
-                               err = vfs_rmdir(nd.path.dentry->d_inode,
-                                               dentry);
-                       else
-                               err = -EPERM;
-               } else {
-                       err = -ENOENT;
-               }
-               dput(dentry);
+       dentry = kern_path_locked(name, &parent);
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
+       if (dentry->d_inode) {
+               if (dentry->d_inode->i_private == &thread)
+                       err = vfs_rmdir(parent.dentry->d_inode, dentry);
+               else
+                       err = -EPERM;
        } else {
-               err = PTR_ERR(dentry);
+               err = -ENOENT;
        }
-
-       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-       path_put(&nd.path);
+       dput(dentry);
+       mutex_unlock(&parent.dentry->d_inode->i_mutex);
+       path_put(&parent);
        return err;
 }
 
@@ -305,50 +296,43 @@ static int dev_mynode(struct device *dev, struct inode *inode, struct kstat *sta
 
 static int handle_remove(const char *nodename, struct device *dev)
 {
-       struct nameidata nd;
+       struct path parent;
        struct dentry *dentry;
-       struct kstat stat;
        int deleted = 1;
        int err;
 
-       err = kern_path_parent(nodename, &nd);
-       if (err)
-               return err;
+       dentry = kern_path_locked(nodename, &parent);
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
 
-       mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
-       dentry = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
-       if (!IS_ERR(dentry)) {
-               if (dentry->d_inode) {
-                       err = vfs_getattr(nd.path.mnt, dentry, &stat);
-                       if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
-                               struct iattr newattrs;
-                               /*
-                                * before unlinking this node, reset permissions
-                                * of possible references like hardlinks
-                                */
-                               newattrs.ia_uid = 0;
-                               newattrs.ia_gid = 0;
-                               newattrs.ia_mode = stat.mode & ~0777;
-                               newattrs.ia_valid =
-                                       ATTR_UID|ATTR_GID|ATTR_MODE;
-                               mutex_lock(&dentry->d_inode->i_mutex);
-                               notify_change(dentry, &newattrs);
-                               mutex_unlock(&dentry->d_inode->i_mutex);
-                               err = vfs_unlink(nd.path.dentry->d_inode,
-                                                dentry);
-                               if (!err || err == -ENOENT)
-                                       deleted = 1;
-                       }
-               } else {
-                       err = -ENOENT;
+       if (dentry->d_inode) {
+               struct kstat stat;
+               err = vfs_getattr(parent.mnt, dentry, &stat);
+               if (!err && dev_mynode(dev, dentry->d_inode, &stat)) {
+                       struct iattr newattrs;
+                       /*
+                        * before unlinking this node, reset permissions
+                        * of possible references like hardlinks
+                        */
+                       newattrs.ia_uid = 0;
+                       newattrs.ia_gid = 0;
+                       newattrs.ia_mode = stat.mode & ~0777;
+                       newattrs.ia_valid =
+                               ATTR_UID|ATTR_GID|ATTR_MODE;
+                       mutex_lock(&dentry->d_inode->i_mutex);
+                       notify_change(dentry, &newattrs);
+                       mutex_unlock(&dentry->d_inode->i_mutex);
+                       err = vfs_unlink(parent.dentry->d_inode, dentry);
+                       if (!err || err == -ENOENT)
+                               deleted = 1;
                }
-               dput(dentry);
        } else {
-               err = PTR_ERR(dentry);
+               err = -ENOENT;
        }
-       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+       dput(dentry);
+       mutex_unlock(&parent.dentry->d_inode->i_mutex);
 
-       path_put(&nd.path);
+       path_put(&parent);
        if (deleted && strchr(nodename, '/'))
                delete_path(nodename);
        return err;
index 83aa694a8efe582f92365f193a07afcb5210b80d..ba3487c9835b67fa64daad5f6e23016f23a7f569 100644 (file)
@@ -75,19 +75,6 @@ static int genpd_start_dev(struct generic_pm_domain *genpd, struct device *dev)
                                        start_latency_ns, "start");
 }
 
-static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
-{
-       return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev,
-                                       save_state_latency_ns, "state save");
-}
-
-static int genpd_restore_dev(struct generic_pm_domain *genpd, struct device *dev)
-{
-       return GENPD_DEV_TIMED_CALLBACK(genpd, int, restore_state, dev,
-                                       restore_state_latency_ns,
-                                       "state restore");
-}
-
 static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd)
 {
        bool ret = false;
@@ -139,6 +126,19 @@ static void genpd_set_active(struct generic_pm_domain *genpd)
                genpd->status = GPD_STATE_ACTIVE;
 }
 
+static void genpd_recalc_cpu_exit_latency(struct generic_pm_domain *genpd)
+{
+       s64 usecs64;
+
+       if (!genpd->cpu_data)
+               return;
+
+       usecs64 = genpd->power_on_latency_ns;
+       do_div(usecs64, NSEC_PER_USEC);
+       usecs64 += genpd->cpu_data->saved_exit_latency;
+       genpd->cpu_data->idle_state->exit_latency = usecs64;
+}
+
 /**
  * __pm_genpd_poweron - Restore power to a given PM domain and its masters.
  * @genpd: PM domain to power up.
@@ -146,7 +146,7 @@ static void genpd_set_active(struct generic_pm_domain *genpd)
  * Restore power to @genpd and all of its masters so that it is possible to
  * resume a device belonging to it.
  */
-int __pm_genpd_poweron(struct generic_pm_domain *genpd)
+static int __pm_genpd_poweron(struct generic_pm_domain *genpd)
        __releases(&genpd->lock) __acquires(&genpd->lock)
 {
        struct gpd_link *link;
@@ -176,6 +176,13 @@ int __pm_genpd_poweron(struct generic_pm_domain *genpd)
                return 0;
        }
 
+       if (genpd->cpu_data) {
+               cpuidle_pause_and_lock();
+               genpd->cpu_data->idle_state->disabled = true;
+               cpuidle_resume_and_unlock();
+               goto out;
+       }
+
        /*
         * The list is guaranteed not to change while the loop below is being
         * executed, unless one of the masters' .power_on() callbacks fiddles
@@ -215,6 +222,7 @@ int __pm_genpd_poweron(struct generic_pm_domain *genpd)
                if (elapsed_ns > genpd->power_on_latency_ns) {
                        genpd->power_on_latency_ns = elapsed_ns;
                        genpd->max_off_time_changed = true;
+                       genpd_recalc_cpu_exit_latency(genpd);
                        if (genpd->name)
                                pr_warning("%s: Power-on latency exceeded, "
                                        "new value %lld ns\n", genpd->name,
@@ -222,6 +230,7 @@ int __pm_genpd_poweron(struct generic_pm_domain *genpd)
                }
        }
 
+ out:
        genpd_set_active(genpd);
 
        return 0;
@@ -251,6 +260,19 @@ int pm_genpd_poweron(struct generic_pm_domain *genpd)
 
 #ifdef CONFIG_PM_RUNTIME
 
+static int genpd_save_dev(struct generic_pm_domain *genpd, struct device *dev)
+{
+       return GENPD_DEV_TIMED_CALLBACK(genpd, int, save_state, dev,
+                                       save_state_latency_ns, "state save");
+}
+
+static int genpd_restore_dev(struct generic_pm_domain *genpd, struct device *dev)
+{
+       return GENPD_DEV_TIMED_CALLBACK(genpd, int, restore_state, dev,
+                                       restore_state_latency_ns,
+                                       "state restore");
+}
+
 static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
                                     unsigned long val, void *ptr)
 {
@@ -275,7 +297,7 @@ static int genpd_dev_pm_qos_notifier(struct notifier_block *nb,
 
                pdd = dev->power.subsys_data ?
                                dev->power.subsys_data->domain_data : NULL;
-               if (pdd) {
+               if (pdd && pdd->dev) {
                        to_gpd_data(pdd)->td.constraint_changed = true;
                        genpd = dev_to_genpd(dev);
                } else {
@@ -339,19 +361,16 @@ static void __pm_genpd_restore_device(struct pm_domain_data *pdd,
 {
        struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
        struct device *dev = pdd->dev;
+       bool need_restore = gpd_data->need_restore;
 
-       if (!gpd_data->need_restore)
-               return;
-
+       gpd_data->need_restore = false;
        mutex_unlock(&genpd->lock);
 
        genpd_start_dev(genpd, dev);
-       genpd_restore_dev(genpd, dev);
-       genpd_stop_dev(genpd, dev);
+       if (need_restore)
+               genpd_restore_dev(genpd, dev);
 
        mutex_lock(&genpd->lock);
-
-       gpd_data->need_restore = false;
 }
 
 /**
@@ -458,6 +477,21 @@ static int pm_genpd_poweroff(struct generic_pm_domain *genpd)
                }
        }
 
+       if (genpd->cpu_data) {
+               /*
+                * If cpu_data is set, cpuidle should turn the domain off when
+                * the CPU in it is idle.  In that case we don't decrement the
+                * subdomain counts of the master domains, so that power is not
+                * removed from the current domain prematurely as a result of
+                * cutting off the masters' power.
+                */
+               genpd->status = GPD_STATE_POWER_OFF;
+               cpuidle_pause_and_lock();
+               genpd->cpu_data->idle_state->disabled = false;
+               cpuidle_resume_and_unlock();
+               goto out;
+       }
+
        if (genpd->power_off) {
                ktime_t time_start;
                s64 elapsed_ns;
@@ -595,7 +629,7 @@ static int pm_genpd_runtime_resume(struct device *dev)
 
        /* If power.irq_safe, the PM domain is never powered off. */
        if (dev->power.irq_safe)
-               goto out;
+               return genpd_start_dev(genpd, dev);
 
        mutex_lock(&genpd->lock);
        ret = __pm_genpd_poweron(genpd);
@@ -628,9 +662,6 @@ static int pm_genpd_runtime_resume(struct device *dev)
        wake_up_all(&genpd->status_wait_queue);
        mutex_unlock(&genpd->lock);
 
- out:
-       genpd_start_dev(genpd, dev);
-
        return 0;
 }
 
@@ -1235,6 +1266,27 @@ static void pm_genpd_complete(struct device *dev)
 
 #endif /* CONFIG_PM_SLEEP */
 
+static struct generic_pm_domain_data *__pm_genpd_alloc_dev_data(struct device *dev)
+{
+       struct generic_pm_domain_data *gpd_data;
+
+       gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
+       if (!gpd_data)
+               return NULL;
+
+       mutex_init(&gpd_data->lock);
+       gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier;
+       dev_pm_qos_add_notifier(dev, &gpd_data->nb);
+       return gpd_data;
+}
+
+static void __pm_genpd_free_dev_data(struct device *dev,
+                                    struct generic_pm_domain_data *gpd_data)
+{
+       dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
+       kfree(gpd_data);
+}
+
 /**
  * __pm_genpd_add_device - Add a device to an I/O PM domain.
  * @genpd: PM domain to add the device to.
@@ -1244,7 +1296,7 @@ static void pm_genpd_complete(struct device *dev)
 int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
                          struct gpd_timing_data *td)
 {
-       struct generic_pm_domain_data *gpd_data;
+       struct generic_pm_domain_data *gpd_data_new, *gpd_data = NULL;
        struct pm_domain_data *pdd;
        int ret = 0;
 
@@ -1253,14 +1305,10 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
        if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev))
                return -EINVAL;
 
-       gpd_data = kzalloc(sizeof(*gpd_data), GFP_KERNEL);
-       if (!gpd_data)
+       gpd_data_new = __pm_genpd_alloc_dev_data(dev);
+       if (!gpd_data_new)
                return -ENOMEM;
 
-       mutex_init(&gpd_data->lock);
-       gpd_data->nb.notifier_call = genpd_dev_pm_qos_notifier;
-       dev_pm_qos_add_notifier(dev, &gpd_data->nb);
-
        genpd_acquire_lock(genpd);
 
        if (genpd->prepared_count > 0) {
@@ -1274,35 +1322,42 @@ int __pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev,
                        goto out;
                }
 
+       ret = dev_pm_get_subsys_data(dev);
+       if (ret)
+               goto out;
+
        genpd->device_count++;
        genpd->max_off_time_changed = true;
 
-       dev_pm_get_subsys_data(dev);
-
-       mutex_lock(&gpd_data->lock);
        spin_lock_irq(&dev->power.lock);
+
        dev->pm_domain = &genpd->domain;
-       dev->power.subsys_data->domain_data = &gpd_data->base;
-       gpd_data->base.dev = dev;
-       list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
-       gpd_data->need_restore = genpd->status == GPD_STATE_POWER_OFF;
+       if (dev->power.subsys_data->domain_data) {
+               gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
+       } else {
+               gpd_data = gpd_data_new;
+               dev->power.subsys_data->domain_data = &gpd_data->base;
+       }
+       gpd_data->refcount++;
        if (td)
                gpd_data->td = *td;
 
+       spin_unlock_irq(&dev->power.lock);
+
+       mutex_lock(&gpd_data->lock);
+       gpd_data->base.dev = dev;
+       list_add_tail(&gpd_data->base.list_node, &genpd->dev_list);
+       gpd_data->need_restore = genpd->status == GPD_STATE_POWER_OFF;
        gpd_data->td.constraint_changed = true;
        gpd_data->td.effective_constraint_ns = -1;
-       spin_unlock_irq(&dev->power.lock);
        mutex_unlock(&gpd_data->lock);
 
-       genpd_release_lock(genpd);
-
-       return 0;
-
  out:
        genpd_release_lock(genpd);
 
-       dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
-       kfree(gpd_data);
+       if (gpd_data != gpd_data_new)
+               __pm_genpd_free_dev_data(dev, gpd_data_new);
+
        return ret;
 }
 
@@ -1348,6 +1403,7 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
 {
        struct generic_pm_domain_data *gpd_data;
        struct pm_domain_data *pdd;
+       bool remove = false;
        int ret = 0;
 
        dev_dbg(dev, "%s()\n", __func__);
@@ -1368,22 +1424,28 @@ int pm_genpd_remove_device(struct generic_pm_domain *genpd,
        genpd->max_off_time_changed = true;
 
        spin_lock_irq(&dev->power.lock);
+
        dev->pm_domain = NULL;
        pdd = dev->power.subsys_data->domain_data;
        list_del_init(&pdd->list_node);
-       dev->power.subsys_data->domain_data = NULL;
+       gpd_data = to_gpd_data(pdd);
+       if (--gpd_data->refcount == 0) {
+               dev->power.subsys_data->domain_data = NULL;
+               remove = true;
+       }
+
        spin_unlock_irq(&dev->power.lock);
 
-       gpd_data = to_gpd_data(pdd);
        mutex_lock(&gpd_data->lock);
        pdd->dev = NULL;
        mutex_unlock(&gpd_data->lock);
 
        genpd_release_lock(genpd);
 
-       dev_pm_qos_remove_notifier(dev, &gpd_data->nb);
-       kfree(gpd_data);
        dev_pm_put_subsys_data(dev);
+       if (remove)
+               __pm_genpd_free_dev_data(dev, gpd_data);
+
        return 0;
 
  out:
@@ -1541,33 +1603,52 @@ int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd,
  * @dev: Device to add the callbacks to.
  * @ops: Set of callbacks to add.
  * @td: Timing data to add to the device along with the callbacks (optional).
+ *
+ * Every call to this routine should be balanced with a call to
+ * __pm_genpd_remove_callbacks() and they must not be nested.
  */
 int pm_genpd_add_callbacks(struct device *dev, struct gpd_dev_ops *ops,
                           struct gpd_timing_data *td)
 {
-       struct pm_domain_data *pdd;
+       struct generic_pm_domain_data *gpd_data_new, *gpd_data = NULL;
        int ret = 0;
 
-       if (!(dev && dev->power.subsys_data && ops))
+       if (!(dev && ops))
                return -EINVAL;
 
+       gpd_data_new = __pm_genpd_alloc_dev_data(dev);
+       if (!gpd_data_new)
+               return -ENOMEM;
+
        pm_runtime_disable(dev);
        device_pm_lock();
 
-       pdd = dev->power.subsys_data->domain_data;
-       if (pdd) {
-               struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
+       ret = dev_pm_get_subsys_data(dev);
+       if (ret)
+               goto out;
 
-               gpd_data->ops = *ops;
-               if (td)
-                       gpd_data->td = *td;
+       spin_lock_irq(&dev->power.lock);
+
+       if (dev->power.subsys_data->domain_data) {
+               gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
        } else {
-               ret = -EINVAL;
+               gpd_data = gpd_data_new;
+               dev->power.subsys_data->domain_data = &gpd_data->base;
        }
+       gpd_data->refcount++;
+       gpd_data->ops = *ops;
+       if (td)
+               gpd_data->td = *td;
+
+       spin_unlock_irq(&dev->power.lock);
 
+ out:
        device_pm_unlock();
        pm_runtime_enable(dev);
 
+       if (gpd_data != gpd_data_new)
+               __pm_genpd_free_dev_data(dev, gpd_data_new);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(pm_genpd_add_callbacks);
@@ -1576,10 +1657,13 @@ EXPORT_SYMBOL_GPL(pm_genpd_add_callbacks);
  * __pm_genpd_remove_callbacks - Remove PM domain callbacks from a given device.
  * @dev: Device to remove the callbacks from.
  * @clear_td: If set, clear the device's timing data too.
+ *
+ * This routine can only be called after pm_genpd_add_callbacks().
  */
 int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td)
 {
-       struct pm_domain_data *pdd;
+       struct generic_pm_domain_data *gpd_data = NULL;
+       bool remove = false;
        int ret = 0;
 
        if (!(dev && dev->power.subsys_data))
@@ -1588,24 +1672,118 @@ int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td)
        pm_runtime_disable(dev);
        device_pm_lock();
 
-       pdd = dev->power.subsys_data->domain_data;
-       if (pdd) {
-               struct generic_pm_domain_data *gpd_data = to_gpd_data(pdd);
+       spin_lock_irq(&dev->power.lock);
 
-               gpd_data->ops = (struct gpd_dev_ops){ 0 };
+       if (dev->power.subsys_data->domain_data) {
+               gpd_data = to_gpd_data(dev->power.subsys_data->domain_data);
+               gpd_data->ops = (struct gpd_dev_ops){ NULL };
                if (clear_td)
                        gpd_data->td = (struct gpd_timing_data){ 0 };
+
+               if (--gpd_data->refcount == 0) {
+                       dev->power.subsys_data->domain_data = NULL;
+                       remove = true;
+               }
        } else {
                ret = -EINVAL;
        }
 
+       spin_unlock_irq(&dev->power.lock);
+
        device_pm_unlock();
        pm_runtime_enable(dev);
 
-       return ret;
+       if (ret)
+               return ret;
+
+       dev_pm_put_subsys_data(dev);
+       if (remove)
+               __pm_genpd_free_dev_data(dev, gpd_data);
+
+       return 0;
 }
 EXPORT_SYMBOL_GPL(__pm_genpd_remove_callbacks);
 
+int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state)
+{
+       struct cpuidle_driver *cpuidle_drv;
+       struct gpd_cpu_data *cpu_data;
+       struct cpuidle_state *idle_state;
+       int ret = 0;
+
+       if (IS_ERR_OR_NULL(genpd) || state < 0)
+               return -EINVAL;
+
+       genpd_acquire_lock(genpd);
+
+       if (genpd->cpu_data) {
+               ret = -EEXIST;
+               goto out;
+       }
+       cpu_data = kzalloc(sizeof(*cpu_data), GFP_KERNEL);
+       if (!cpu_data) {
+               ret = -ENOMEM;
+               goto out;
+       }
+       cpuidle_drv = cpuidle_driver_ref();
+       if (!cpuidle_drv) {
+               ret = -ENODEV;
+               goto out;
+       }
+       if (cpuidle_drv->state_count <= state) {
+               ret = -EINVAL;
+               goto err;
+       }
+       idle_state = &cpuidle_drv->states[state];
+       if (!idle_state->disabled) {
+               ret = -EAGAIN;
+               goto err;
+       }
+       cpu_data->idle_state = idle_state;
+       cpu_data->saved_exit_latency = idle_state->exit_latency;
+       genpd->cpu_data = cpu_data;
+       genpd_recalc_cpu_exit_latency(genpd);
+
+ out:
+       genpd_release_lock(genpd);
+       return ret;
+
+ err:
+       cpuidle_driver_unref();
+       goto out;
+}
+
+int genpd_detach_cpuidle(struct generic_pm_domain *genpd)
+{
+       struct gpd_cpu_data *cpu_data;
+       struct cpuidle_state *idle_state;
+       int ret = 0;
+
+       if (IS_ERR_OR_NULL(genpd))
+               return -EINVAL;
+
+       genpd_acquire_lock(genpd);
+
+       cpu_data = genpd->cpu_data;
+       if (!cpu_data) {
+               ret = -ENODEV;
+               goto out;
+       }
+       idle_state = cpu_data->idle_state;
+       if (!idle_state->disabled) {
+               ret = -EAGAIN;
+               goto out;
+       }
+       idle_state->exit_latency = cpu_data->saved_exit_latency;
+       cpuidle_driver_unref();
+       genpd->cpu_data = NULL;
+       kfree(cpu_data);
+
+ out:
+       genpd_release_lock(genpd);
+       return ret;
+}
+
 /* Default device callbacks for generic PM domains. */
 
 /**
@@ -1615,16 +1793,24 @@ EXPORT_SYMBOL_GPL(__pm_genpd_remove_callbacks);
 static int pm_genpd_default_save_state(struct device *dev)
 {
        int (*cb)(struct device *__dev);
-       struct device_driver *drv = dev->driver;
 
        cb = dev_gpd_data(dev)->ops.save_state;
        if (cb)
                return cb(dev);
 
-       if (drv && drv->pm && drv->pm->runtime_suspend)
-               return drv->pm->runtime_suspend(dev);
+       if (dev->type && dev->type->pm)
+               cb = dev->type->pm->runtime_suspend;
+       else if (dev->class && dev->class->pm)
+               cb = dev->class->pm->runtime_suspend;
+       else if (dev->bus && dev->bus->pm)
+               cb = dev->bus->pm->runtime_suspend;
+       else
+               cb = NULL;
 
-       return 0;
+       if (!cb && dev->driver && dev->driver->pm)
+               cb = dev->driver->pm->runtime_suspend;
+
+       return cb ? cb(dev) : 0;
 }
 
 /**
@@ -1634,16 +1820,24 @@ static int pm_genpd_default_save_state(struct device *dev)
 static int pm_genpd_default_restore_state(struct device *dev)
 {
        int (*cb)(struct device *__dev);
-       struct device_driver *drv = dev->driver;
 
        cb = dev_gpd_data(dev)->ops.restore_state;
        if (cb)
                return cb(dev);
 
-       if (drv && drv->pm && drv->pm->runtime_resume)
-               return drv->pm->runtime_resume(dev);
+       if (dev->type && dev->type->pm)
+               cb = dev->type->pm->runtime_resume;
+       else if (dev->class && dev->class->pm)
+               cb = dev->class->pm->runtime_resume;
+       else if (dev->bus && dev->bus->pm)
+               cb = dev->bus->pm->runtime_resume;
+       else
+               cb = NULL;
 
-       return 0;
+       if (!cb && dev->driver && dev->driver->pm)
+               cb = dev->driver->pm->runtime_resume;
+
+       return cb ? cb(dev) : 0;
 }
 
 #ifdef CONFIG_PM_SLEEP
index 9cb845e49334c78d27a958066cf33dfc665c4ac1..0113adc310dccc4a62a325cccde4221f34c5ce7e 100644 (file)
@@ -28,7 +28,7 @@
 #include <linux/sched.h>
 #include <linux/async.h>
 #include <linux/suspend.h>
-
+#include <linux/cpuidle.h>
 #include "../base.h"
 #include "power.h"
 
@@ -45,10 +45,10 @@ typedef int (*pm_callback_t)(struct device *);
  */
 
 LIST_HEAD(dpm_list);
-LIST_HEAD(dpm_prepared_list);
-LIST_HEAD(dpm_suspended_list);
-LIST_HEAD(dpm_late_early_list);
-LIST_HEAD(dpm_noirq_list);
+static LIST_HEAD(dpm_prepared_list);
+static LIST_HEAD(dpm_suspended_list);
+static LIST_HEAD(dpm_late_early_list);
+static LIST_HEAD(dpm_noirq_list);
 
 struct suspend_stats suspend_stats;
 static DEFINE_MUTEX(dpm_list_mtx);
@@ -166,7 +166,7 @@ static ktime_t initcall_debug_start(struct device *dev)
 {
        ktime_t calltime = ktime_set(0, 0);
 
-       if (initcall_debug) {
+       if (pm_print_times_enabled) {
                pr_info("calling  %s+ @ %i, parent: %s\n",
                        dev_name(dev), task_pid_nr(current),
                        dev->parent ? dev_name(dev->parent) : "none");
@@ -181,7 +181,7 @@ static void initcall_debug_report(struct device *dev, ktime_t calltime,
 {
        ktime_t delta, rettime;
 
-       if (initcall_debug) {
+       if (pm_print_times_enabled) {
                rettime = ktime_get();
                delta = ktime_sub(rettime, calltime);
                pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
@@ -467,6 +467,7 @@ static void dpm_resume_noirq(pm_message_t state)
        mutex_unlock(&dpm_list_mtx);
        dpm_show_time(starttime, state, "noirq");
        resume_device_irqs();
+       cpuidle_resume();
 }
 
 /**
@@ -867,6 +868,7 @@ static int dpm_suspend_noirq(pm_message_t state)
        ktime_t starttime = ktime_get();
        int error = 0;
 
+       cpuidle_pause();
        suspend_device_irqs();
        mutex_lock(&dpm_list_mtx);
        while (!list_empty(&dpm_late_early_list)) {
@@ -989,8 +991,16 @@ static int dpm_suspend_late(pm_message_t state)
 int dpm_suspend_end(pm_message_t state)
 {
        int error = dpm_suspend_late(state);
+       if (error)
+               return error;
+
+       error = dpm_suspend_noirq(state);
+       if (error) {
+               dpm_resume_early(state);
+               return error;
+       }
 
-       return error ? : dpm_suspend_noirq(state);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(dpm_suspend_end);
 
index fd849a2c4fa8fdaa4ae3ac10a8ce853b9e14bec7..74a67e0019a2d246820ccb2858399bca193ff789 100644 (file)
@@ -462,7 +462,7 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request);
 static void __dev_pm_qos_drop_user_request(struct device *dev)
 {
        dev_pm_qos_remove_request(dev->power.pq_req);
-       dev->power.pq_req = 0;
+       dev->power.pq_req = NULL;
 }
 
 /**
index 48be2ad4dd2cb4f54c592bfdcaf99f2aa509ca8c..b91dc6f1e91476484584b5eb08f9dbb4b8811030 100644 (file)
@@ -474,6 +474,8 @@ static DEVICE_ATTR(runtime_enabled, 0444, rtpm_enabled_show, NULL);
 
 #endif
 
+#ifdef CONFIG_PM_SLEEP
+
 static ssize_t async_show(struct device *dev, struct device_attribute *attr,
                          char *buf)
 {
@@ -500,6 +502,8 @@ static ssize_t async_store(struct device *dev, struct device_attribute *attr,
 }
 
 static DEVICE_ATTR(async, 0644, async_show, async_store);
+
+#endif
 #endif /* CONFIG_PM_ADVANCED_DEBUG */
 
 static struct attribute *power_attrs[] = {
index b986b8660b0c4e72da132a0a32ab2960ca99e183..80f9ab9c3aa4b7eba89b436d0dcd6a96b3623558 100644 (file)
@@ -95,6 +95,9 @@ struct regmap {
 
        /* if set, converts bulk rw to single rw */
        bool use_single_rw;
+
+       struct rb_root range_tree;
+       void *selector_work_buf;        /* Scratch buffer used for selector */
 };
 
 struct regcache_ops {
@@ -115,6 +118,20 @@ bool regmap_precious(struct regmap *map, unsigned int reg);
 int _regmap_write(struct regmap *map, unsigned int reg,
                  unsigned int val);
 
+struct regmap_range_node {
+       struct rb_node node;
+
+       unsigned int range_min;
+       unsigned int range_max;
+
+       unsigned int selector_reg;
+       unsigned int selector_mask;
+       int selector_shift;
+
+       unsigned int window_start;
+       unsigned int window_len;
+};
+
 #ifdef CONFIG_DEBUG_FS
 extern void regmap_debugfs_initcall(void);
 extern void regmap_debugfs_init(struct regmap *map, const char *name);
index 4fac4b9be88f7ca5b7144396e5908b5b8f1bb593..a89734621e517e367b15b925ccd507da04daca89 100644 (file)
@@ -24,14 +24,18 @@ struct regmap_irq_chip_data {
        struct mutex lock;
 
        struct regmap *map;
-       struct regmap_irq_chip *chip;
+       const struct regmap_irq_chip *chip;
 
        int irq_base;
        struct irq_domain *domain;
 
+       int irq;
+       int wake_count;
+
        unsigned int *status_buf;
        unsigned int *mask_buf;
        unsigned int *mask_buf_def;
+       unsigned int *wake_buf;
 
        unsigned int irq_reg_stride;
 };
@@ -71,6 +75,16 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
                                d->chip->mask_base + (i * map->reg_stride));
        }
 
+       /* If we've changed our wakeup count propagate it to the parent */
+       if (d->wake_count < 0)
+               for (i = d->wake_count; i < 0; i++)
+                       irq_set_irq_wake(d->irq, 0);
+       else if (d->wake_count > 0)
+               for (i = 0; i < d->wake_count; i++)
+                       irq_set_irq_wake(d->irq, 1);
+
+       d->wake_count = 0;
+
        mutex_unlock(&d->lock);
 }
 
@@ -92,18 +106,41 @@ static void regmap_irq_disable(struct irq_data *data)
        d->mask_buf[irq_data->reg_offset / map->reg_stride] |= irq_data->mask;
 }
 
+static int regmap_irq_set_wake(struct irq_data *data, unsigned int on)
+{
+       struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
+       struct regmap *map = d->map;
+       const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq);
+
+       if (!d->chip->wake_base)
+               return -EINVAL;
+
+       if (on) {
+               d->wake_buf[irq_data->reg_offset / map->reg_stride]
+                       &= ~irq_data->mask;
+               d->wake_count++;
+       } else {
+               d->wake_buf[irq_data->reg_offset / map->reg_stride]
+                       |= irq_data->mask;
+               d->wake_count--;
+       }
+
+       return 0;
+}
+
 static struct irq_chip regmap_irq_chip = {
        .name                   = "regmap",
        .irq_bus_lock           = regmap_irq_lock,
        .irq_bus_sync_unlock    = regmap_irq_sync_unlock,
        .irq_disable            = regmap_irq_disable,
        .irq_enable             = regmap_irq_enable,
+       .irq_set_wake           = regmap_irq_set_wake,
 };
 
 static irqreturn_t regmap_irq_thread(int irq, void *d)
 {
        struct regmap_irq_chip_data *data = d;
-       struct regmap_irq_chip *chip = data->chip;
+       const struct regmap_irq_chip *chip = data->chip;
        struct regmap *map = data->map;
        int ret, i;
        bool handled = false;
@@ -195,7 +232,7 @@ static struct irq_domain_ops regmap_domain_ops = {
  * register values used by the IRQ controller over suspend and resume.
  */
 int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
-                       int irq_base, struct regmap_irq_chip *chip,
+                       int irq_base, const struct regmap_irq_chip *chip,
                        struct regmap_irq_chip_data **data)
 {
        struct regmap_irq_chip_data *d;
@@ -240,6 +277,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
        if (!d->mask_buf_def)
                goto err_alloc;
 
+       if (chip->wake_base) {
+               d->wake_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
+                                     GFP_KERNEL);
+               if (!d->wake_buf)
+                       goto err_alloc;
+       }
+
+       d->irq = irq;
        d->map = map;
        d->chip = chip;
        d->irq_base = irq_base;
@@ -294,6 +339,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
 err_domain:
        /* Should really dispose of the domain but... */
 err_alloc:
+       kfree(d->wake_buf);
        kfree(d->mask_buf_def);
        kfree(d->mask_buf);
        kfree(d->status_buf);
@@ -315,6 +361,7 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d)
 
        free_irq(irq, d);
        /* We should unmap the domain but... */
+       kfree(d->wake_buf);
        kfree(d->mask_buf_def);
        kfree(d->mask_buf);
        kfree(d->status_buf);
@@ -346,6 +393,10 @@ EXPORT_SYMBOL_GPL(regmap_irq_chip_get_base);
  */
 int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq)
 {
+       /* Handle holes in the IRQ list */
+       if (!data->chip->irqs[irq].mask)
+               return -EINVAL;
+
        return irq_create_mapping(data->domain, irq);
 }
 EXPORT_SYMBOL_GPL(regmap_irq_get_virq);
index febd6de6c8ac20c3b4a5c86ac903f5c909461f4f..f05fc74dd84a5f46b8cb32ed3943972fffe056e7 100644 (file)
@@ -37,7 +37,7 @@ static int regmap_mmio_gather_write(void *context,
 
        BUG_ON(reg_size != 4);
 
-       offset = be32_to_cpup(reg);
+       offset = *(u32 *)reg;
 
        while (val_size) {
                switch (ctx->val_bytes) {
@@ -45,14 +45,14 @@ static int regmap_mmio_gather_write(void *context,
                        writeb(*(u8 *)val, ctx->regs + offset);
                        break;
                case 2:
-                       writew(be16_to_cpup(val), ctx->regs + offset);
+                       writew(*(u16 *)val, ctx->regs + offset);
                        break;
                case 4:
-                       writel(be32_to_cpup(val), ctx->regs + offset);
+                       writel(*(u32 *)val, ctx->regs + offset);
                        break;
 #ifdef CONFIG_64BIT
                case 8:
-                       writeq(be64_to_cpup(val), ctx->regs + offset);
+                       writeq(*(u64 *)val, ctx->regs + offset);
                        break;
 #endif
                default:
@@ -83,7 +83,7 @@ static int regmap_mmio_read(void *context,
 
        BUG_ON(reg_size != 4);
 
-       offset = be32_to_cpup(reg);
+       offset = *(u32 *)reg;
 
        while (val_size) {
                switch (ctx->val_bytes) {
@@ -91,14 +91,14 @@ static int regmap_mmio_read(void *context,
                        *(u8 *)val = readb(ctx->regs + offset);
                        break;
                case 2:
-                       *(u16 *)val = cpu_to_be16(readw(ctx->regs + offset));
+                       *(u16 *)val = readw(ctx->regs + offset);
                        break;
                case 4:
-                       *(u32 *)val = cpu_to_be32(readl(ctx->regs + offset));
+                       *(u32 *)val = readl(ctx->regs + offset);
                        break;
 #ifdef CONFIG_64BIT
                case 8:
-                       *(u64 *)val = cpu_to_be32(readq(ctx->regs + offset));
+                       *(u64 *)val = readq(ctx->regs + offset);
                        break;
 #endif
                default:
@@ -124,9 +124,11 @@ static struct regmap_bus regmap_mmio = {
        .gather_write = regmap_mmio_gather_write,
        .read = regmap_mmio_read,
        .free_context = regmap_mmio_free_context,
+       .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+       .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
 };
 
-struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,
+static struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,
                                        const struct regmap_config *config)
 {
        struct regmap_mmio_context *ctx;
@@ -162,7 +164,15 @@ struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs,
        if (config->reg_stride < min_stride)
                return ERR_PTR(-EINVAL);
 
-       ctx = kzalloc(GFP_KERNEL, sizeof(*ctx));
+       switch (config->reg_format_endian) {
+       case REGMAP_ENDIAN_DEFAULT:
+       case REGMAP_ENDIAN_NATIVE:
+               break;
+       default:
+               return ERR_PTR(-EINVAL);
+       }
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return ERR_PTR(-ENOMEM);
 
index c89aa01fb1de8262838998dc68f778d5d7473d91..c241ae2f2f10b91e8998e5b657d5f739cc0c0b7b 100644 (file)
 #include <linux/export.h>
 #include <linux/mutex.h>
 #include <linux/err.h>
+#include <linux/rbtree.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/regmap.h>
 
 #include "internal.h"
 
+/*
+ * Sometimes for failures during very early init the trace
+ * infrastructure isn't available early enough to be used.  For this
+ * sort of problem defining LOG_DEVICE will add printks for basic
+ * register I/O on a specific device.
+ */
+#undef LOG_DEVICE
+
+static int _regmap_update_bits(struct regmap *map, unsigned int reg,
+                              unsigned int mask, unsigned int val,
+                              bool *change);
+
 bool regmap_writeable(struct regmap *map, unsigned int reg)
 {
        if (map->max_register && reg > map->max_register)
@@ -119,13 +132,19 @@ static void regmap_format_8(void *buf, unsigned int val, unsigned int shift)
        b[0] = val << shift;
 }
 
-static void regmap_format_16(void *buf, unsigned int val, unsigned int shift)
+static void regmap_format_16_be(void *buf, unsigned int val, unsigned int shift)
 {
        __be16 *b = buf;
 
        b[0] = cpu_to_be16(val << shift);
 }
 
+static void regmap_format_16_native(void *buf, unsigned int val,
+                                   unsigned int shift)
+{
+       *(u16 *)buf = val << shift;
+}
+
 static void regmap_format_24(void *buf, unsigned int val, unsigned int shift)
 {
        u8 *b = buf;
@@ -137,13 +156,19 @@ static void regmap_format_24(void *buf, unsigned int val, unsigned int shift)
        b[2] = val;
 }
 
-static void regmap_format_32(void *buf, unsigned int val, unsigned int shift)
+static void regmap_format_32_be(void *buf, unsigned int val, unsigned int shift)
 {
        __be32 *b = buf;
 
        b[0] = cpu_to_be32(val << shift);
 }
 
+static void regmap_format_32_native(void *buf, unsigned int val,
+                                   unsigned int shift)
+{
+       *(u32 *)buf = val << shift;
+}
+
 static unsigned int regmap_parse_8(void *buf)
 {
        u8 *b = buf;
@@ -151,7 +176,7 @@ static unsigned int regmap_parse_8(void *buf)
        return b[0];
 }
 
-static unsigned int regmap_parse_16(void *buf)
+static unsigned int regmap_parse_16_be(void *buf)
 {
        __be16 *b = buf;
 
@@ -160,6 +185,11 @@ static unsigned int regmap_parse_16(void *buf)
        return b[0];
 }
 
+static unsigned int regmap_parse_16_native(void *buf)
+{
+       return *(u16 *)buf;
+}
+
 static unsigned int regmap_parse_24(void *buf)
 {
        u8 *b = buf;
@@ -170,7 +200,7 @@ static unsigned int regmap_parse_24(void *buf)
        return ret;
 }
 
-static unsigned int regmap_parse_32(void *buf)
+static unsigned int regmap_parse_32_be(void *buf)
 {
        __be32 *b = buf;
 
@@ -179,6 +209,11 @@ static unsigned int regmap_parse_32(void *buf)
        return b[0];
 }
 
+static unsigned int regmap_parse_32_native(void *buf)
+{
+       return *(u32 *)buf;
+}
+
 static void regmap_lock_mutex(struct regmap *map)
 {
        mutex_lock(&map->mutex);
@@ -208,6 +243,67 @@ static void dev_get_regmap_release(struct device *dev, void *res)
         */
 }
 
+static bool _regmap_range_add(struct regmap *map,
+                             struct regmap_range_node *data)
+{
+       struct rb_root *root = &map->range_tree;
+       struct rb_node **new = &(root->rb_node), *parent = NULL;
+
+       while (*new) {
+               struct regmap_range_node *this =
+                       container_of(*new, struct regmap_range_node, node);
+
+               parent = *new;
+               if (data->range_max < this->range_min)
+                       new = &((*new)->rb_left);
+               else if (data->range_min > this->range_max)
+                       new = &((*new)->rb_right);
+               else
+                       return false;
+       }
+
+       rb_link_node(&data->node, parent, new);
+       rb_insert_color(&data->node, root);
+
+       return true;
+}
+
+static struct regmap_range_node *_regmap_range_lookup(struct regmap *map,
+                                                     unsigned int reg)
+{
+       struct rb_node *node = map->range_tree.rb_node;
+
+       while (node) {
+               struct regmap_range_node *this =
+                       container_of(node, struct regmap_range_node, node);
+
+               if (reg < this->range_min)
+                       node = node->rb_left;
+               else if (reg > this->range_max)
+                       node = node->rb_right;
+               else
+                       return this;
+       }
+
+       return NULL;
+}
+
+static void regmap_range_exit(struct regmap *map)
+{
+       struct rb_node *next;
+       struct regmap_range_node *range_node;
+
+       next = rb_first(&map->range_tree);
+       while (next) {
+               range_node = rb_entry(next, struct regmap_range_node, node);
+               next = rb_next(&range_node->node);
+               rb_erase(&range_node->node, &map->range_tree);
+               kfree(range_node);
+       }
+
+       kfree(map->selector_work_buf);
+}
+
 /**
  * regmap_init(): Initialise register map
  *
@@ -227,6 +323,8 @@ struct regmap *regmap_init(struct device *dev,
 {
        struct regmap *map, **m;
        int ret = -EINVAL;
+       enum regmap_endian reg_endian, val_endian;
+       int i, j;
 
        if (!bus || !config)
                goto err;
@@ -275,6 +373,18 @@ struct regmap *regmap_init(struct device *dev,
                map->read_flag_mask = bus->read_flag_mask;
        }
 
+       reg_endian = config->reg_format_endian;
+       if (reg_endian == REGMAP_ENDIAN_DEFAULT)
+               reg_endian = bus->reg_format_endian_default;
+       if (reg_endian == REGMAP_ENDIAN_DEFAULT)
+               reg_endian = REGMAP_ENDIAN_BIG;
+
+       val_endian = config->val_format_endian;
+       if (val_endian == REGMAP_ENDIAN_DEFAULT)
+               val_endian = bus->val_format_endian_default;
+       if (val_endian == REGMAP_ENDIAN_DEFAULT)
+               val_endian = REGMAP_ENDIAN_BIG;
+
        switch (config->reg_bits + map->reg_shift) {
        case 2:
                switch (config->val_bits) {
@@ -321,11 +431,29 @@ struct regmap *regmap_init(struct device *dev,
                break;
 
        case 16:
-               map->format.format_reg = regmap_format_16;
+               switch (reg_endian) {
+               case REGMAP_ENDIAN_BIG:
+                       map->format.format_reg = regmap_format_16_be;
+                       break;
+               case REGMAP_ENDIAN_NATIVE:
+                       map->format.format_reg = regmap_format_16_native;
+                       break;
+               default:
+                       goto err_map;
+               }
                break;
 
        case 32:
-               map->format.format_reg = regmap_format_32;
+               switch (reg_endian) {
+               case REGMAP_ENDIAN_BIG:
+                       map->format.format_reg = regmap_format_32_be;
+                       break;
+               case REGMAP_ENDIAN_NATIVE:
+                       map->format.format_reg = regmap_format_32_native;
+                       break;
+               default:
+                       goto err_map;
+               }
                break;
 
        default:
@@ -338,21 +466,47 @@ struct regmap *regmap_init(struct device *dev,
                map->format.parse_val = regmap_parse_8;
                break;
        case 16:
-               map->format.format_val = regmap_format_16;
-               map->format.parse_val = regmap_parse_16;
+               switch (val_endian) {
+               case REGMAP_ENDIAN_BIG:
+                       map->format.format_val = regmap_format_16_be;
+                       map->format.parse_val = regmap_parse_16_be;
+                       break;
+               case REGMAP_ENDIAN_NATIVE:
+                       map->format.format_val = regmap_format_16_native;
+                       map->format.parse_val = regmap_parse_16_native;
+                       break;
+               default:
+                       goto err_map;
+               }
                break;
        case 24:
+               if (val_endian != REGMAP_ENDIAN_BIG)
+                       goto err_map;
                map->format.format_val = regmap_format_24;
                map->format.parse_val = regmap_parse_24;
                break;
        case 32:
-               map->format.format_val = regmap_format_32;
-               map->format.parse_val = regmap_parse_32;
+               switch (val_endian) {
+               case REGMAP_ENDIAN_BIG:
+                       map->format.format_val = regmap_format_32_be;
+                       map->format.parse_val = regmap_parse_32_be;
+                       break;
+               case REGMAP_ENDIAN_NATIVE:
+                       map->format.format_val = regmap_format_32_native;
+                       map->format.parse_val = regmap_parse_32_native;
+                       break;
+               default:
+                       goto err_map;
+               }
                break;
        }
 
-       if (map->format.format_write)
+       if (map->format.format_write) {
+               if ((reg_endian != REGMAP_ENDIAN_BIG) ||
+                   (val_endian != REGMAP_ENDIAN_BIG))
+                       goto err_map;
                map->use_single_rw = true;
+       }
 
        if (!map->format.format_write &&
            !(map->format.format_reg && map->format.format_val))
@@ -364,27 +518,88 @@ struct regmap *regmap_init(struct device *dev,
                goto err_map;
        }
 
-       regmap_debugfs_init(map, config->name);
+       map->range_tree = RB_ROOT;
+       for (i = 0; i < config->n_ranges; i++) {
+               const struct regmap_range_cfg *range_cfg = &config->ranges[i];
+               struct regmap_range_node *new;
+
+               /* Sanity check */
+               if (range_cfg->range_max < range_cfg->range_min ||
+                   range_cfg->range_max > map->max_register ||
+                   range_cfg->selector_reg > map->max_register ||
+                   range_cfg->window_len == 0)
+                       goto err_range;
+
+               /* Make sure, that this register range has no selector
+                  or data window within its boundary */
+               for (j = 0; j < config->n_ranges; j++) {
+                       unsigned sel_reg = config->ranges[j].selector_reg;
+                       unsigned win_min = config->ranges[j].window_start;
+                       unsigned win_max = win_min +
+                                          config->ranges[j].window_len - 1;
+
+                       if (range_cfg->range_min <= sel_reg &&
+                           sel_reg <= range_cfg->range_max) {
+                               goto err_range;
+                       }
+
+                       if (!(win_max < range_cfg->range_min ||
+                             win_min > range_cfg->range_max)) {
+                               goto err_range;
+                       }
+               }
+
+               new = kzalloc(sizeof(*new), GFP_KERNEL);
+               if (new == NULL) {
+                       ret = -ENOMEM;
+                       goto err_range;
+               }
+
+               new->range_min = range_cfg->range_min;
+               new->range_max = range_cfg->range_max;
+               new->selector_reg = range_cfg->selector_reg;
+               new->selector_mask = range_cfg->selector_mask;
+               new->selector_shift = range_cfg->selector_shift;
+               new->window_start = range_cfg->window_start;
+               new->window_len = range_cfg->window_len;
+
+               if (_regmap_range_add(map, new) == false) {
+                       kfree(new);
+                       goto err_range;
+               }
+
+               if (map->selector_work_buf == NULL) {
+                       map->selector_work_buf =
+                               kzalloc(map->format.buf_size, GFP_KERNEL);
+                       if (map->selector_work_buf == NULL) {
+                               ret = -ENOMEM;
+                               goto err_range;
+                       }
+               }
+       }
 
        ret = regcache_init(map, config);
        if (ret < 0)
-               goto err_debugfs;
+               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) {
                ret = -ENOMEM;
-               goto err_cache;
+               goto err_debugfs;
        }
        *m = map;
        devres_add(dev, m);
 
        return map;
 
-err_cache:
-       regcache_exit(map);
 err_debugfs:
        regmap_debugfs_exit(map);
+       regcache_exit(map);
+err_range:
+       regmap_range_exit(map);
        kfree(map->work_buf);
 err_map:
        kfree(map);
@@ -481,6 +696,7 @@ void regmap_exit(struct regmap *map)
 {
        regcache_exit(map);
        regmap_debugfs_exit(map);
+       regmap_range_exit(map);
        if (map->bus->free_context)
                map->bus->free_context(map->bus_context);
        kfree(map->work_buf);
@@ -526,6 +742,57 @@ struct regmap *dev_get_regmap(struct device *dev, const char *name)
 }
 EXPORT_SYMBOL_GPL(dev_get_regmap);
 
+static int _regmap_select_page(struct regmap *map, unsigned int *reg,
+                              unsigned int val_num)
+{
+       struct regmap_range_node *range;
+       void *orig_work_buf;
+       unsigned int win_offset;
+       unsigned int win_page;
+       bool page_chg;
+       int ret;
+
+       range = _regmap_range_lookup(map, *reg);
+       if (range) {
+               win_offset = (*reg - range->range_min) % range->window_len;
+               win_page = (*reg - range->range_min) / range->window_len;
+
+               if (val_num > 1) {
+                       /* Bulk write shouldn't cross range boundary */
+                       if (*reg + val_num - 1 > range->range_max)
+                               return -EINVAL;
+
+                       /* ... or single page boundary */
+                       if (val_num > range->window_len - win_offset)
+                               return -EINVAL;
+               }
+
+               /* It is possible to have selector register inside data window.
+                  In that case, selector register is located on every page and
+                  it needs no page switching, when accessed alone. */
+               if (val_num > 1 ||
+                   range->window_start + win_offset != range->selector_reg) {
+                       /* Use separate work_buf during page switching */
+                       orig_work_buf = map->work_buf;
+                       map->work_buf = map->selector_work_buf;
+
+                       ret = _regmap_update_bits(map, range->selector_reg,
+                                       range->selector_mask,
+                                       win_page << range->selector_shift,
+                                       &page_chg);
+
+                       map->work_buf = orig_work_buf;
+
+                       if (ret < 0)
+                               return ret;
+               }
+
+               *reg = range->window_start + win_offset;
+       }
+
+       return 0;
+}
+
 static int _regmap_raw_write(struct regmap *map, unsigned int reg,
                             const void *val, size_t val_len)
 {
@@ -563,6 +830,10 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg,
                }
        }
 
+       ret = _regmap_select_page(map, &reg, val_len / map->format.val_bytes);
+       if (ret < 0)
+               return ret;
+
        map->format.format_reg(map->work_buf, reg, map->reg_shift);
 
        u8[0] |= map->write_flag_mask;
@@ -623,9 +894,18 @@ int _regmap_write(struct regmap *map, unsigned int reg,
                }
        }
 
+#ifdef LOG_DEVICE
+       if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0)
+               dev_info(map->dev, "%x <= %x\n", reg, val);
+#endif
+
        trace_regmap_reg_write(map->dev, reg, val);
 
        if (map->format.format_write) {
+               ret = _regmap_select_page(map, &reg, 1);
+               if (ret < 0)
+                       return ret;
+
                map->format.format_write(map, reg, val);
 
                trace_regmap_hw_write_start(map->dev, reg, 1);
@@ -783,6 +1063,10 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val,
        u8 *u8 = map->work_buf;
        int ret;
 
+       ret = _regmap_select_page(map, &reg, val_len / map->format.val_bytes);
+       if (ret < 0)
+               return ret;
+
        map->format.format_reg(map->work_buf, reg, map->reg_shift);
 
        /*
@@ -826,6 +1110,12 @@ static int _regmap_read(struct regmap *map, unsigned int reg,
        ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes);
        if (ret == 0) {
                *val = map->format.parse_val(map->work_buf);
+
+#ifdef LOG_DEVICE
+               if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0)
+                       dev_info(map->dev, "%x => %x\n", reg, *val);
+#endif
+
                trace_regmap_reg_read(map->dev, reg, *val);
        }
 
@@ -982,11 +1272,9 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
        int ret;
        unsigned int tmp, orig;
 
-       map->lock(map);
-
        ret = _regmap_read(map, reg, &orig);
        if (ret != 0)
-               goto out;
+               return ret;
 
        tmp = orig & ~mask;
        tmp |= val & mask;
@@ -998,9 +1286,6 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg,
                *change = false;
        }
 
-out:
-       map->unlock(map);
-
        return ret;
 }
 
@@ -1018,7 +1303,13 @@ int regmap_update_bits(struct regmap *map, unsigned int reg,
                       unsigned int mask, unsigned int val)
 {
        bool change;
-       return _regmap_update_bits(map, reg, mask, val, &change);
+       int ret;
+
+       map->lock(map);
+       ret = _regmap_update_bits(map, reg, mask, val, &change);
+       map->unlock(map);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(regmap_update_bits);
 
@@ -1038,7 +1329,12 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg,
                             unsigned int mask, unsigned int val,
                             bool *change)
 {
-       return _regmap_update_bits(map, reg, mask, val, change);
+       int ret;
+
+       map->lock(map);
+       ret = _regmap_update_bits(map, reg, mask, val, change);
+       map->unlock(map);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(regmap_update_bits_check);
 
index 76fa3deaee84059d4431f7763981311210f16f06..1788f491e0fb50e13cefb2f81c286d41721e75ef 100644 (file)
@@ -780,9 +780,9 @@ static const struct block_device_operations mg_disk_ops = {
        .getgeo = mg_getgeo
 };
 
-static int mg_suspend(struct platform_device *plat_dev, pm_message_t state)
+static int mg_suspend(struct device *dev)
 {
-       struct mg_drv_data *prv_data = plat_dev->dev.platform_data;
+       struct mg_drv_data *prv_data = dev->platform_data;
        struct mg_host *host = prv_data->host;
 
        if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD))
@@ -804,9 +804,9 @@ static int mg_suspend(struct platform_device *plat_dev, pm_message_t state)
        return 0;
 }
 
-static int mg_resume(struct platform_device *plat_dev)
+static int mg_resume(struct device *dev)
 {
-       struct mg_drv_data *prv_data = plat_dev->dev.platform_data;
+       struct mg_drv_data *prv_data = dev->platform_data;
        struct mg_host *host = prv_data->host;
 
        if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD))
@@ -825,6 +825,8 @@ static int mg_resume(struct platform_device *plat_dev)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(mg_pm, mg_suspend, mg_resume);
+
 static int mg_probe(struct platform_device *plat_dev)
 {
        struct mg_host *host;
@@ -1074,11 +1076,10 @@ static int mg_remove(struct platform_device *plat_dev)
 static struct platform_driver mg_disk_driver = {
        .probe = mg_probe,
        .remove = mg_remove,
-       .suspend = mg_suspend,
-       .resume = mg_resume,
        .driver = {
                .name = MG_DEV_NAME,
                .owner = THIS_MODULE,
+               .pm = &mg_pm,
        }
 };
 
index 65665c9c42c62ba5805324df96292e560f16b04a..8f428a8ab003d8c7a029036eea6a1666a96d7dd3 100644 (file)
@@ -499,7 +499,7 @@ static int rbd_header_from_disk(struct rbd_image_header *header,
                         / sizeof (*ondisk))
                return -EINVAL;
        header->snapc = kmalloc(sizeof(struct ceph_snap_context) +
-                               snap_count * sizeof (*ondisk),
+                               snap_count * sizeof(u64),
                                gfp_flags);
        if (!header->snapc)
                return -ENOMEM;
@@ -977,7 +977,7 @@ static void rbd_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg)
        op = (void *)(replyhead + 1);
        rc = le32_to_cpu(replyhead->result);
        bytes = le64_to_cpu(op->extent.length);
-       read_op = (le32_to_cpu(op->op) == CEPH_OSD_OP_READ);
+       read_op = (le16_to_cpu(op->op) == CEPH_OSD_OP_READ);
 
        dout("rbd_req_cb bytes=%lld readop=%d rc=%d\n", bytes, read_op, rc);
 
index 1412565c01afb213407fea17469ce0037f301610..d706bd0e9e800fd791e198b4b573b64296f3f40e 100644 (file)
@@ -162,22 +162,24 @@ static int __exit omap_rng_remove(struct platform_device *pdev)
 
 #ifdef CONFIG_PM
 
-static int omap_rng_suspend(struct platform_device *pdev, pm_message_t message)
+static int omap_rng_suspend(struct device *dev)
 {
        omap_rng_write_reg(RNG_MASK_REG, 0x0);
        return 0;
 }
 
-static int omap_rng_resume(struct platform_device *pdev)
+static int omap_rng_resume(struct device *dev)
 {
        omap_rng_write_reg(RNG_MASK_REG, 0x1);
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(omap_rng_pm, omap_rng_suspend, omap_rng_resume);
+#define        OMAP_RNG_PM     (&omap_rng_pm)
+
 #else
 
-#define        omap_rng_suspend        NULL
-#define        omap_rng_resume         NULL
+#define        OMAP_RNG_PM     NULL
 
 #endif
 
@@ -188,11 +190,10 @@ static struct platform_driver omap_rng_driver = {
        .driver = {
                .name           = "omap_rng",
                .owner          = THIS_MODULE,
+               .pm             = OMAP_RNG_PM,
        },
        .probe          = omap_rng_probe,
        .remove         = __exit_p(omap_rng_remove),
-       .suspend        = omap_rng_suspend,
-       .resume         = omap_rng_resume
 };
 
 static int __init omap_rng_init(void)
index 1e638fff40ea2cb01d99d33745ae5f6526787237..83f85cf7fb1b424afd4dde0b104af0ea21a51f7b 100644 (file)
@@ -2503,18 +2503,6 @@ static void __devexit ipmi_pci_remove(struct pci_dev *pdev)
        cleanup_one_si(info);
 }
 
-#ifdef CONFIG_PM
-static int ipmi_pci_suspend(struct pci_dev *pdev, pm_message_t state)
-{
-       return 0;
-}
-
-static int ipmi_pci_resume(struct pci_dev *pdev)
-{
-       return 0;
-}
-#endif
-
 static struct pci_device_id ipmi_pci_devices[] = {
        { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) },
        { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) },
@@ -2527,10 +2515,6 @@ static struct pci_driver ipmi_pci_driver = {
        .id_table =     ipmi_pci_devices,
        .probe =        ipmi_pci_probe,
        .remove =       __devexit_p(ipmi_pci_remove),
-#ifdef CONFIG_PM
-       .suspend =      ipmi_pci_suspend,
-       .resume =       ipmi_pci_resume,
-#endif
 };
 #endif /* CONFIG_PCI */
 
index 67c3371723cc3b2f953fe528c6c4eef3af8f0e3a..e5eedfa24c91010bd8358db7b7076e4f0af6ad1b 100644 (file)
 #include <linux/splice.h>
 #include <linux/pfn.h>
 #include <linux/export.h>
+#include <linux/io.h>
 
 #include <asm/uaccess.h>
-#include <asm/io.h>
 
 #ifdef CONFIG_IA64
 # include <linux/efi.h>
 #endif
 
+#define DEVPORT_MINOR  4
+
 static inline unsigned long size_inside_page(unsigned long start,
                                             unsigned long size)
 {
@@ -894,6 +896,13 @@ static int __init chr_dev_init(void)
        for (minor = 1; minor < ARRAY_SIZE(devlist); minor++) {
                if (!devlist[minor].name)
                        continue;
+
+               /*
+                * Create /dev/port? 
+                */
+               if ((minor == DEVPORT_MINOR) && !arch_has_dev_port())
+                       continue;
+
                device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor),
                              NULL, devlist[minor].name);
        }
index 45713f0e7d61adc208511a197691d2560557c489..f87780502b4199712a933103723128054eb5a5ab 100644 (file)
@@ -1459,7 +1459,7 @@ static int __devexit sonypi_remove(struct platform_device *dev)
 #ifdef CONFIG_PM
 static int old_camera_power;
 
-static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
+static int sonypi_suspend(struct device *dev)
 {
        old_camera_power = sonypi_device.camera_power;
        sonypi_disable();
@@ -1467,14 +1467,16 @@ static int sonypi_suspend(struct platform_device *dev, pm_message_t state)
        return 0;
 }
 
-static int sonypi_resume(struct platform_device *dev)
+static int sonypi_resume(struct device *dev)
 {
        sonypi_enable(old_camera_power);
        return 0;
 }
+
+static SIMPLE_DEV_PM_OPS(sonypi_pm, sonypi_suspend, sonypi_resume);
+#define SONYPI_PM      (&sonypi_pm)
 #else
-#define sonypi_suspend NULL
-#define sonypi_resume  NULL
+#define SONYPI_PM      NULL
 #endif
 
 static void sonypi_shutdown(struct platform_device *dev)
@@ -1486,12 +1488,11 @@ static struct platform_driver sonypi_driver = {
        .driver         = {
                .name   = "sonypi",
                .owner  = THIS_MODULE,
+               .pm     = SONYPI_PM,
        },
        .probe          = sonypi_probe,
        .remove         = __devexit_p(sonypi_remove),
        .shutdown       = sonypi_shutdown,
-       .suspend        = sonypi_suspend,
-       .resume         = sonypi_resume,
 };
 
 static struct platform_device *sonypi_platform_device;
index ad7c7320dd1ba13f6ef55cf8f06ff88203904d49..817f0ee202b6861e87e146e2cc8864bc2de33ede 100644 (file)
@@ -827,10 +827,10 @@ EXPORT_SYMBOL_GPL(tpm_pcr_extend);
 int tpm_do_selftest(struct tpm_chip *chip)
 {
        int rc;
-       u8 digest[TPM_DIGEST_SIZE];
        unsigned int loops;
        unsigned int delay_msec = 1000;
        unsigned long duration;
+       struct tpm_cmd_t cmd;
 
        duration = tpm_calc_ordinal_duration(chip,
                                             TPM_ORD_CONTINUE_SELFTEST);
@@ -845,7 +845,15 @@ int tpm_do_selftest(struct tpm_chip *chip)
                return rc;
 
        do {
-               rc = __tpm_pcr_read(chip, 0, digest);
+               /* Attempt to read a PCR value */
+               cmd.header.in = pcrread_header;
+               cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0);
+               rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE);
+
+               if (rc < TPM_HEADER_SIZE)
+                       return -EFAULT;
+
+               rc = be32_to_cpu(cmd.header.out.return_code);
                if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) {
                        dev_info(chip->dev,
                                 "TPM is disabled/deactivated (0x%X)\n", rc);
@@ -1274,7 +1282,7 @@ static struct tpm_input_header savestate_header = {
  * We are about to suspend. Save the TPM state
  * so that it can be restored.
  */
-int tpm_pm_suspend(struct device *dev, pm_message_t pm_state)
+int tpm_pm_suspend(struct device *dev)
 {
        struct tpm_chip *chip = dev_get_drvdata(dev);
        struct tpm_cmd_t cmd;
@@ -1322,6 +1330,9 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume);
 
 void tpm_dev_vendor_release(struct tpm_chip *chip)
 {
+       if (!chip)
+               return;
+
        if (chip->vendor.release)
                chip->vendor.release(chip->dev);
 
@@ -1339,6 +1350,9 @@ void tpm_dev_release(struct device *dev)
 {
        struct tpm_chip *chip = dev_get_drvdata(dev);
 
+       if (!chip)
+               return;
+
        tpm_dev_vendor_release(chip);
 
        chip->release(dev);
@@ -1405,15 +1419,12 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
                        "unable to misc_register %s, minor %d\n",
                        chip->vendor.miscdev.name,
                        chip->vendor.miscdev.minor);
-               put_device(chip->dev);
-               return NULL;
+               goto put_device;
        }
 
        if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) {
                misc_deregister(&chip->vendor.miscdev);
-               put_device(chip->dev);
-
-               return NULL;
+               goto put_device;
        }
 
        chip->bios_dir = tpm_bios_log_setup(devname);
@@ -1425,6 +1436,8 @@ struct tpm_chip *tpm_register_hardware(struct device *dev,
 
        return chip;
 
+put_device:
+       put_device(chip->dev);
 out_free:
        kfree(chip);
        kfree(devname);
index b1c5280ac15946fa453dcba5ac2566416985195d..917f727e674059b7e7daa2fc36a9920a306deef6 100644 (file)
@@ -299,7 +299,7 @@ extern ssize_t tpm_write(struct file *, const char __user *, size_t,
                         loff_t *);
 extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
 extern void tpm_remove_hardware(struct device *);
-extern int tpm_pm_suspend(struct device *, pm_message_t);
+extern int tpm_pm_suspend(struct device *);
 extern int tpm_pm_resume(struct device *);
 extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
                             wait_queue_head_t *);
index c64a1bc65349cc3959c488034fbfd892e7ac04cf..678d57019dc46990d4433afbc1637ff2f9208919 100644 (file)
@@ -168,22 +168,14 @@ static void atml_plat_remove(void)
        }
 }
 
-static int tpm_atml_suspend(struct platform_device *dev, pm_message_t msg)
-{
-       return tpm_pm_suspend(&dev->dev, msg);
-}
+static SIMPLE_DEV_PM_OPS(tpm_atml_pm, tpm_pm_suspend, tpm_pm_resume);
 
-static int tpm_atml_resume(struct platform_device *dev)
-{
-       return tpm_pm_resume(&dev->dev);
-}
 static struct platform_driver atml_drv = {
        .driver = {
                .name = "tpm_atmel",
                .owner          = THIS_MODULE,
+               .pm             = &tpm_atml_pm,
        },
-       .suspend = tpm_atml_suspend,
-       .resume = tpm_atml_resume,
 };
 
 static int __init init_atmel(void)
index 76da32e11f181e1aaf9e74c8db11ff0afaba3eb6..3251a44e8ceb5f68fa1e68f275095dbb48c925e5 100644 (file)
@@ -4,8 +4,8 @@
  * SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module
  * Specifications at www.trustedcomputinggroup.org
  *
- * Copyright (C) 2005, Marcel Selhorst <m.selhorst@sirrix.com>
- * Sirrix AG - security technologies, http://www.sirrix.com and
+ * Copyright (C) 2005, Marcel Selhorst <tpmdd@selhorst.net>
+ * Sirrix AG - security technologies <tpmdd@sirrix.com> and
  * Applied Data Security Group, Ruhr-University Bochum, Germany
  * Project-Homepage: http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/ 
  *
@@ -671,7 +671,7 @@ static void __exit cleanup_inf(void)
 module_init(init_inf);
 module_exit(cleanup_inf);
 
-MODULE_AUTHOR("Marcel Selhorst <m.selhorst@sirrix.com>");
+MODULE_AUTHOR("Marcel Selhorst <tpmdd@sirrix.com>");
 MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
 MODULE_VERSION("1.9.2");
 MODULE_LICENSE("GPL");
index 4d2464871ada87cab9b5beacc1ec817ee5a93d31..640c9a427b59b1f788a6541e4d81e88e9f9f9f42 100644 (file)
@@ -274,22 +274,13 @@ static void tpm_nsc_remove(struct device *dev)
        }
 }
 
-static int tpm_nsc_suspend(struct platform_device *dev, pm_message_t msg)
-{
-       return tpm_pm_suspend(&dev->dev, msg);
-}
-
-static int tpm_nsc_resume(struct platform_device *dev)
-{
-       return tpm_pm_resume(&dev->dev);
-}
+static SIMPLE_DEV_PM_OPS(tpm_nsc_pm, tpm_pm_suspend, tpm_pm_resume);
 
 static struct platform_driver nsc_drv = {
-       .suspend         = tpm_nsc_suspend,
-       .resume          = tpm_nsc_resume,
        .driver          = {
                .name    = "tpm_nsc",
                .owner   = THIS_MODULE,
+               .pm      = &tpm_nsc_pm,
        },
 };
 
index d2a70cae76df758b8db05b0f53142e427b0f6be3..89682fa8801ea0fafb1f8e9556ca148ab0b4f6f9 100644 (file)
@@ -750,7 +750,7 @@ static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev,
 
 static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg)
 {
-       return tpm_pm_suspend(&dev->dev, msg);
+       return tpm_pm_suspend(&dev->dev);
 }
 
 static int tpm_tis_pnp_resume(struct pnp_dev *dev)
@@ -806,27 +806,25 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id,
                    sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444);
 MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe");
 #endif
-static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg)
-{
-       return tpm_pm_suspend(&dev->dev, msg);
-}
 
-static int tpm_tis_resume(struct platform_device *dev)
+static int tpm_tis_resume(struct device *dev)
 {
-       struct tpm_chip *chip = dev_get_drvdata(&dev->dev);
+       struct tpm_chip *chip = dev_get_drvdata(dev);
 
        if (chip->vendor.irq)
                tpm_tis_reenable_interrupts(chip);
 
-       return tpm_pm_resume(&dev->dev);
+       return tpm_pm_resume(dev);
 }
+
+static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume);
+
 static struct platform_driver tis_drv = {
        .driver = {
                .name = "tpm_tis",
                .owner          = THIS_MODULE,
+               .pm             = &tpm_tis_pm,
        },
-       .suspend = tpm_tis_suspend,
-       .resume = tpm_tis_resume,
 };
 
 static struct platform_device *pdev;
index b9a5158a30b1272452dd99e543c18781d797d404..3669761d1bac7e683ebc95055e75469e65d5e63d 100644 (file)
@@ -3,5 +3,7 @@ obj-$(CONFIG_CLKDEV_LOOKUP)     += clkdev.o
 obj-$(CONFIG_COMMON_CLK)       += clk.o clk-fixed-rate.o clk-gate.o \
                                   clk-mux.o clk-divider.o clk-fixed-factor.o
 # SoCs specific
+obj-$(CONFIG_ARCH_NOMADIK)     += clk-nomadik.o
 obj-$(CONFIG_ARCH_MXS)         += mxs/
+obj-$(CONFIG_ARCH_SOCFPGA)     += socfpga/
 obj-$(CONFIG_PLAT_SPEAR)       += spear/
diff --git a/drivers/clk/clk-nomadik.c b/drivers/clk/clk-nomadik.c
new file mode 100644 (file)
index 0000000..517a8ff
--- /dev/null
@@ -0,0 +1,47 @@
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/clk-provider.h>
+
+/*
+ * The Nomadik clock tree is described in the STN8815A12 DB V4.2
+ * reference manual for the chip, page 94 ff.
+ */
+
+void __init nomadik_clk_init(void)
+{
+       struct clk *clk;
+
+       clk = clk_register_fixed_rate(NULL, "apb_pclk", NULL, CLK_IS_ROOT, 0);
+       clk_register_clkdev(clk, "apb_pclk", NULL);
+       clk_register_clkdev(clk, NULL, "gpio.0");
+       clk_register_clkdev(clk, NULL, "gpio.1");
+       clk_register_clkdev(clk, NULL, "gpio.2");
+       clk_register_clkdev(clk, NULL, "gpio.3");
+       clk_register_clkdev(clk, NULL, "rng");
+
+       /*
+        * The 2.4 MHz TIMCLK reference clock is active at boot time, this is
+        * actually the MXTALCLK @19.2 MHz divided by 8. This clock is used
+        * by the timers and watchdog. See page 105 ff.
+        */
+       clk = clk_register_fixed_rate(NULL, "TIMCLK", NULL, CLK_IS_ROOT,
+                                     2400000);
+       clk_register_clkdev(clk, NULL, "mtu0");
+       clk_register_clkdev(clk, NULL, "mtu1");
+
+       /*
+        * At boot time, PLL2 is set to generate a set of fixed clocks,
+        * one of them is CLK48, the 48 MHz clock, routed to the UART, MMC/SD
+        * I2C, IrDA, USB and SSP blocks.
+        */
+       clk = clk_register_fixed_rate(NULL, "CLK48", NULL, CLK_IS_ROOT,
+                                     48000000);
+       clk_register_clkdev(clk, NULL, "uart0");
+       clk_register_clkdev(clk, NULL, "uart1");
+       clk_register_clkdev(clk, NULL, "mmci");
+       clk_register_clkdev(clk, NULL, "ssp");
+       clk_register_clkdev(clk, NULL, "nmk-i2c.0");
+       clk_register_clkdev(clk, NULL, "nmk-i2c.1");
+}
diff --git a/drivers/clk/socfpga/Makefile b/drivers/clk/socfpga/Makefile
new file mode 100644 (file)
index 0000000..0303c0b
--- /dev/null
@@ -0,0 +1 @@
+obj-y += clk.o
diff --git a/drivers/clk/socfpga/clk.c b/drivers/clk/socfpga/clk.c
new file mode 100644 (file)
index 0000000..2c855a6
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ *  Copyright (C) 2012 Altera Corporation <www.altera.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/clk-provider.h>
+
+#define SOCFPGA_OSC1_CLK       10000000
+#define SOCFPGA_MPU_CLK                800000000
+#define SOCFPGA_MAIN_QSPI_CLK          432000000
+#define SOCFPGA_MAIN_NAND_SDMMC_CLK    250000000
+#define SOCFPGA_S2F_USR_CLK            125000000
+
+void __init socfpga_init_clocks(void)
+{
+       struct clk *clk;
+
+       clk = clk_register_fixed_rate(NULL, "osc1_clk", NULL, CLK_IS_ROOT, SOCFPGA_OSC1_CLK);
+       clk_register_clkdev(clk, "osc1_clk", NULL);
+
+       clk = clk_register_fixed_rate(NULL, "mpu_clk", NULL, CLK_IS_ROOT, SOCFPGA_MPU_CLK);
+       clk_register_clkdev(clk, "mpu_clk", NULL);
+
+       clk = clk_register_fixed_rate(NULL, "main_clk", NULL, CLK_IS_ROOT, SOCFPGA_MPU_CLK/2);
+       clk_register_clkdev(clk, "main_clk", NULL);
+
+       clk = clk_register_fixed_rate(NULL, "dbg_base_clk", NULL, CLK_IS_ROOT, SOCFPGA_MPU_CLK/2);
+       clk_register_clkdev(clk, "dbg_base_clk", NULL);
+
+       clk = clk_register_fixed_rate(NULL, "main_qspi_clk", NULL, CLK_IS_ROOT, SOCFPGA_MAIN_QSPI_CLK);
+       clk_register_clkdev(clk, "main_qspi_clk", NULL);
+
+       clk = clk_register_fixed_rate(NULL, "main_nand_sdmmc_clk", NULL, CLK_IS_ROOT, SOCFPGA_MAIN_NAND_SDMMC_CLK);
+       clk_register_clkdev(clk, "main_nand_sdmmc_clk", NULL);
+
+       clk = clk_register_fixed_rate(NULL, "s2f_usr_clk", NULL, CLK_IS_ROOT, SOCFPGA_S2F_USR_CLK);
+       clk_register_clkdev(clk, "s2f_usr_clk", NULL);
+}
index 99c6b203e6cde5c2d969c0411233b39ee00651ec..d53cd0afc20026c1e409110b47d5646f9995f785 100644 (file)
@@ -16,6 +16,12 @@ config CLKSRC_MMIO
 config DW_APB_TIMER
        bool
 
+config DW_APB_TIMER_OF
+       bool
+
+config ARMADA_370_XP_TIMER
+       bool
+
 config CLKSRC_DBX500_PRCMU
        bool "Clocksource PRCMU Timer"
        depends on UX500_SOC_DB8500
index dd3e661a124d2ba9161a9872360495beef40cd76..b65d0c56ab3523d1f777d37aa17338073220a2b3 100644 (file)
@@ -10,4 +10,6 @@ obj-$(CONFIG_EM_TIMER_STI)    += em_sti.o
 obj-$(CONFIG_CLKBLD_I8253)     += i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)      += mmio.o
 obj-$(CONFIG_DW_APB_TIMER)     += dw_apb_timer.o
-obj-$(CONFIG_CLKSRC_DBX500_PRCMU)      += clksrc-dbx500-prcmu.o
\ No newline at end of file
+obj-$(CONFIG_DW_APB_TIMER_OF)  += dw_apb_timer_of.o
+obj-$(CONFIG_CLKSRC_DBX500_PRCMU)      += clksrc-dbx500-prcmu.o
+obj-$(CONFIG_ARMADA_370_XP_TIMER)      += time-armada-370-xp.o
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c
new file mode 100644 (file)
index 0000000..f7dba5b
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2012 Altera Corporation
+ * Copyright (c) 2011 Picochip Ltd., Jamie Iles
+ *
+ * Modified from mach-picoxcell/time.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/dw_apb_timer.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+
+#include <asm/mach/time.h>
+#include <asm/sched_clock.h>
+
+static void timer_get_base_and_rate(struct device_node *np,
+                                   void __iomem **base, u32 *rate)
+{
+       *base = of_iomap(np, 0);
+
+       if (!*base)
+               panic("Unable to map regs for %s", np->name);
+
+       if (of_property_read_u32(np, "clock-freq", rate) &&
+               of_property_read_u32(np, "clock-frequency", rate))
+               panic("No clock-frequency property for %s", np->name);
+}
+
+static void add_clockevent(struct device_node *event_timer)
+{
+       void __iomem *iobase;
+       struct dw_apb_clock_event_device *ced;
+       u32 irq, rate;
+
+       irq = irq_of_parse_and_map(event_timer, 0);
+       if (irq == NO_IRQ)
+               panic("No IRQ for clock event timer");
+
+       timer_get_base_and_rate(event_timer, &iobase, &rate);
+
+       ced = dw_apb_clockevent_init(0, event_timer->name, 300, iobase, irq,
+                                    rate);
+       if (!ced)
+               panic("Unable to initialise clockevent device");
+
+       dw_apb_clockevent_register(ced);
+}
+
+static void add_clocksource(struct device_node *source_timer)
+{
+       void __iomem *iobase;
+       struct dw_apb_clocksource *cs;
+       u32 rate;
+
+       timer_get_base_and_rate(source_timer, &iobase, &rate);
+
+       cs = dw_apb_clocksource_init(300, source_timer->name, iobase, rate);
+       if (!cs)
+               panic("Unable to initialise clocksource device");
+
+       dw_apb_clocksource_start(cs);
+       dw_apb_clocksource_register(cs);
+}
+
+static void __iomem *sched_io_base;
+
+static u32 read_sched_clock(void)
+{
+       return __raw_readl(sched_io_base);
+}
+
+static const struct of_device_id sptimer_ids[] __initconst = {
+       { .compatible = "picochip,pc3x2-rtc" },
+       { .compatible = "snps,dw-apb-timer-sp" },
+       { /* Sentinel */ },
+};
+
+static void init_sched_clock(void)
+{
+       struct device_node *sched_timer;
+       u32 rate;
+
+       sched_timer = of_find_matching_node(NULL, sptimer_ids);
+       if (!sched_timer)
+               panic("No RTC for sched clock to use");
+
+       timer_get_base_and_rate(sched_timer, &sched_io_base, &rate);
+       of_node_put(sched_timer);
+
+       setup_sched_clock(read_sched_clock, 32, rate);
+}
+
+static const struct of_device_id osctimer_ids[] __initconst = {
+       { .compatible = "picochip,pc3x2-timer" },
+       { .compatible = "snps,dw-apb-timer-osc" },
+       {},
+};
+
+static void __init timer_init(void)
+{
+       struct device_node *event_timer, *source_timer;
+
+       event_timer = of_find_matching_node(NULL, osctimer_ids);
+       if (!event_timer)
+               panic("No timer for clockevent");
+       add_clockevent(event_timer);
+
+       source_timer = of_find_matching_node(event_timer, osctimer_ids);
+       if (!source_timer)
+               panic("No timer for clocksource");
+       add_clocksource(source_timer);
+
+       of_node_put(source_timer);
+
+       init_sched_clock();
+}
+
+struct sys_timer dw_apb_timer = {
+       .init = timer_init,
+};
diff --git a/drivers/clocksource/time-armada-370-xp.c b/drivers/clocksource/time-armada-370-xp.c
new file mode 100644 (file)
index 0000000..4674f94
--- /dev/null
@@ -0,0 +1,226 @@
+/*
+ * Marvell Armada 370/XP SoC timer handling.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Timer 0 is used as free-running clocksource, while timer 1 is
+ * used as clock_event_device.
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/timer.h>
+#include <linux/clockchips.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <asm/sched_clock.h>
+
+/*
+ * Timer block registers.
+ */
+#define TIMER_CTRL_OFF         0x0000
+#define  TIMER0_EN              0x0001
+#define  TIMER0_RELOAD_EN       0x0002
+#define  TIMER0_25MHZ            0x0800
+#define  TIMER0_DIV(div)         ((div) << 19)
+#define  TIMER1_EN              0x0004
+#define  TIMER1_RELOAD_EN       0x0008
+#define  TIMER1_25MHZ            0x1000
+#define  TIMER1_DIV(div)         ((div) << 22)
+#define TIMER_EVENTS_STATUS    0x0004
+#define  TIMER0_CLR_MASK         (~0x1)
+#define  TIMER1_CLR_MASK         (~0x100)
+#define TIMER0_RELOAD_OFF      0x0010
+#define TIMER0_VAL_OFF         0x0014
+#define TIMER1_RELOAD_OFF      0x0018
+#define TIMER1_VAL_OFF         0x001c
+
+/* Global timers are connected to the coherency fabric clock, and the
+   below divider reduces their incrementing frequency. */
+#define TIMER_DIVIDER_SHIFT     5
+#define TIMER_DIVIDER           (1 << TIMER_DIVIDER_SHIFT)
+
+/*
+ * SoC-specific data.
+ */
+static void __iomem *timer_base;
+static int timer_irq;
+
+/*
+ * Number of timer ticks per jiffy.
+ */
+static u32 ticks_per_jiffy;
+
+static u32 notrace armada_370_xp_read_sched_clock(void)
+{
+       return ~readl(timer_base + TIMER0_VAL_OFF);
+}
+
+/*
+ * Clockevent handling.
+ */
+static int
+armada_370_xp_clkevt_next_event(unsigned long delta,
+                               struct clock_event_device *dev)
+{
+       u32 u;
+
+       /*
+        * Clear clockevent timer interrupt.
+        */
+       writel(TIMER1_CLR_MASK, timer_base + TIMER_EVENTS_STATUS);
+
+       /*
+        * Setup new clockevent timer value.
+        */
+       writel(delta, timer_base + TIMER1_VAL_OFF);
+
+       /*
+        * Enable the timer.
+        */
+       u = readl(timer_base + TIMER_CTRL_OFF);
+       u = ((u & ~TIMER1_RELOAD_EN) | TIMER1_EN |
+            TIMER1_DIV(TIMER_DIVIDER_SHIFT));
+       writel(u, timer_base + TIMER_CTRL_OFF);
+
+       return 0;
+}
+
+static void
+armada_370_xp_clkevt_mode(enum clock_event_mode mode,
+                         struct clock_event_device *dev)
+{
+       u32 u;
+
+       if (mode == CLOCK_EVT_MODE_PERIODIC) {
+               /*
+                * Setup timer to fire at 1/HZ intervals.
+                */
+               writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD_OFF);
+               writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL_OFF);
+
+               /*
+                * Enable timer.
+                */
+               u = readl(timer_base + TIMER_CTRL_OFF);
+
+               writel((u | TIMER1_EN | TIMER1_RELOAD_EN |
+                       TIMER1_DIV(TIMER_DIVIDER_SHIFT)),
+                      timer_base + TIMER_CTRL_OFF);
+       } else {
+               /*
+                * Disable timer.
+                */
+               u = readl(timer_base + TIMER_CTRL_OFF);
+               writel(u & ~TIMER1_EN, timer_base + TIMER_CTRL_OFF);
+
+               /*
+                * ACK pending timer interrupt.
+                */
+               writel(TIMER1_CLR_MASK, timer_base + TIMER_EVENTS_STATUS);
+
+       }
+}
+
+static struct clock_event_device armada_370_xp_clkevt = {
+       .name           = "armada_370_xp_tick",
+       .features       = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
+       .shift          = 32,
+       .rating         = 300,
+       .set_next_event = armada_370_xp_clkevt_next_event,
+       .set_mode       = armada_370_xp_clkevt_mode,
+};
+
+static irqreturn_t armada_370_xp_timer_interrupt(int irq, void *dev_id)
+{
+       /*
+        * ACK timer interrupt and call event handler.
+        */
+
+       writel(TIMER1_CLR_MASK, timer_base + TIMER_EVENTS_STATUS);
+       armada_370_xp_clkevt.event_handler(&armada_370_xp_clkevt);
+
+       return IRQ_HANDLED;
+}
+
+static struct irqaction armada_370_xp_timer_irq = {
+       .name           = "armada_370_xp_tick",
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .handler        = armada_370_xp_timer_interrupt
+};
+
+void __init armada_370_xp_timer_init(void)
+{
+       u32 u;
+       struct device_node *np;
+       unsigned int timer_clk;
+       int ret;
+       np = of_find_compatible_node(NULL, NULL, "marvell,armada-370-xp-timer");
+       timer_base = of_iomap(np, 0);
+       WARN_ON(!timer_base);
+
+       if (of_find_property(np, "marvell,timer-25Mhz", NULL)) {
+               /* The fixed 25MHz timer is available so let's use it */
+               u = readl(timer_base + TIMER_CTRL_OFF);
+               writel(u | TIMER0_25MHZ | TIMER1_25MHZ,
+                      timer_base + TIMER_CTRL_OFF);
+               timer_clk = 25000000;
+       } else {
+               u32 clk = 0;
+               ret = of_property_read_u32(np, "clock-frequency", &clk);
+               WARN_ON(!clk || ret < 0);
+               u = readl(timer_base + TIMER_CTRL_OFF);
+               writel(u & ~(TIMER0_25MHZ | TIMER1_25MHZ),
+                      timer_base + TIMER_CTRL_OFF);
+               timer_clk = clk / TIMER_DIVIDER;
+       }
+
+       /* We use timer 0 as clocksource, and timer 1 for
+          clockevents */
+       timer_irq = irq_of_parse_and_map(np, 1);
+
+       ticks_per_jiffy = (timer_clk + HZ / 2) / HZ;
+
+       /*
+        * Set scale and timer for sched_clock.
+        */
+       setup_sched_clock(armada_370_xp_read_sched_clock, 32, timer_clk);
+
+       /*
+        * Setup free-running clocksource timer (interrupts
+        * disabled).
+        */
+       writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
+       writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
+
+       u = readl(timer_base + TIMER_CTRL_OFF);
+
+       writel((u | TIMER0_EN | TIMER0_RELOAD_EN |
+               TIMER0_DIV(TIMER_DIVIDER_SHIFT)), timer_base + TIMER_CTRL_OFF);
+
+       clocksource_mmio_init(timer_base + TIMER0_VAL_OFF,
+                             "armada_370_xp_clocksource",
+                             timer_clk, 300, 32, clocksource_mmio_readl_down);
+
+       /*
+        * Setup clockevent timer (interrupt-driven).
+        */
+       setup_irq(timer_irq, &armada_370_xp_timer_irq);
+       armada_370_xp_clkevt.cpumask = cpumask_of(0);
+       clockevents_config_and_register(&armada_370_xp_clkevt,
+                                       timer_clk, 1, 0xfffffffe);
+}
+
index 7f2f149ae40fd4efa933052aa1caf9e1c3834b45..fb8a5279c5d829898d37336c8b4e023ee55f36a5 100644 (file)
@@ -138,7 +138,7 @@ void disable_cpufreq(void)
 static LIST_HEAD(cpufreq_governor_list);
 static DEFINE_MUTEX(cpufreq_governor_mutex);
 
-struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
+static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs)
 {
        struct cpufreq_policy *data;
        unsigned long flags;
@@ -162,7 +162,7 @@ struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
        if (!data)
                goto err_out_put_module;
 
-       if (!kobject_get(&data->kobj))
+       if (!sysfs && !kobject_get(&data->kobj))
                goto err_out_put_module;
 
        spin_unlock_irqrestore(&cpufreq_driver_lock, flags);
@@ -175,16 +175,35 @@ err_out_unlock:
 err_out:
        return NULL;
 }
+
+struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu)
+{
+       return __cpufreq_cpu_get(cpu, false);
+}
 EXPORT_SYMBOL_GPL(cpufreq_cpu_get);
 
+static struct cpufreq_policy *cpufreq_cpu_get_sysfs(unsigned int cpu)
+{
+       return __cpufreq_cpu_get(cpu, true);
+}
 
-void cpufreq_cpu_put(struct cpufreq_policy *data)
+static void __cpufreq_cpu_put(struct cpufreq_policy *data, bool sysfs)
 {
-       kobject_put(&data->kobj);
+       if (!sysfs)
+               kobject_put(&data->kobj);
        module_put(cpufreq_driver->owner);
 }
+
+void cpufreq_cpu_put(struct cpufreq_policy *data)
+{
+       __cpufreq_cpu_put(data, false);
+}
 EXPORT_SYMBOL_GPL(cpufreq_cpu_put);
 
+static void cpufreq_cpu_put_sysfs(struct cpufreq_policy *data)
+{
+       __cpufreq_cpu_put(data, true);
+}
 
 /*********************************************************************
  *            EXTERNALLY AFFECTING FREQUENCY CHANGES                 *
@@ -617,7 +636,7 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
        struct cpufreq_policy *policy = to_policy(kobj);
        struct freq_attr *fattr = to_attr(attr);
        ssize_t ret = -EINVAL;
-       policy = cpufreq_cpu_get(policy->cpu);
+       policy = cpufreq_cpu_get_sysfs(policy->cpu);
        if (!policy)
                goto no_policy;
 
@@ -631,7 +650,7 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf)
 
        unlock_policy_rwsem_read(policy->cpu);
 fail:
-       cpufreq_cpu_put(policy);
+       cpufreq_cpu_put_sysfs(policy);
 no_policy:
        return ret;
 }
@@ -642,7 +661,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
        struct cpufreq_policy *policy = to_policy(kobj);
        struct freq_attr *fattr = to_attr(attr);
        ssize_t ret = -EINVAL;
-       policy = cpufreq_cpu_get(policy->cpu);
+       policy = cpufreq_cpu_get_sysfs(policy->cpu);
        if (!policy)
                goto no_policy;
 
@@ -656,7 +675,7 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
 
        unlock_policy_rwsem_write(policy->cpu);
 fail:
-       cpufreq_cpu_put(policy);
+       cpufreq_cpu_put_sysfs(policy);
 no_policy:
        return ret;
 }
index b243a7ee01f6d51876ca8b8fdc5d6d721ac08bb9..af2d81e10f71dfd1ec2432dba8531292b243932c 100644 (file)
@@ -62,8 +62,18 @@ static int exynos_target(struct cpufreq_policy *policy,
                goto out;
        }
 
-       if (cpufreq_frequency_table_target(policy, freq_table,
-                                          freqs.old, relation, &old_index)) {
+       /*
+        * The policy max have been changed so that we cannot get proper
+        * old_index with cpufreq_frequency_table_target(). Thus, ignore
+        * policy and get the index from the raw freqeuncy table.
+        */
+       for (old_index = 0;
+               freq_table[old_index].frequency != CPUFREQ_TABLE_END;
+               old_index++)
+               if (freq_table[old_index].frequency == freqs.old)
+                       break;
+
+       if (freq_table[old_index].frequency == CPUFREQ_TABLE_END) {
                ret = -EINVAL;
                goto out;
        }
index d90519cec8807da1952825da4e9b3dd9f540bad2..d6a533e68e0f1ec804299f54c22055d6e6e534c9 100644 (file)
@@ -201,6 +201,22 @@ void cpuidle_resume_and_unlock(void)
 
 EXPORT_SYMBOL_GPL(cpuidle_resume_and_unlock);
 
+/* Currently used in suspend/resume path to suspend cpuidle */
+void cpuidle_pause(void)
+{
+       mutex_lock(&cpuidle_lock);
+       cpuidle_uninstall_idle_handler();
+       mutex_unlock(&cpuidle_lock);
+}
+
+/* Currently used in suspend/resume path to resume cpuidle */
+void cpuidle_resume(void)
+{
+       mutex_lock(&cpuidle_lock);
+       cpuidle_install_idle_handler();
+       mutex_unlock(&cpuidle_lock);
+}
+
 /**
  * cpuidle_wrap_enter - performs timekeeping and irqen around enter function
  * @dev: pointer to a valid cpuidle_device object
@@ -265,7 +281,7 @@ static void poll_idle_init(struct cpuidle_driver *drv)
        state->power_usage = -1;
        state->flags = 0;
        state->enter = poll_idle;
-       state->disable = 0;
+       state->disabled = false;
 }
 #else
 static void poll_idle_init(struct cpuidle_driver *drv) {}
index 40cd3f3024df4031f65a118a43e147e8e1b678bf..58bf3b1ac9c46035c2a3fae79271954f6d436442 100644 (file)
@@ -16,6 +16,7 @@
 
 static struct cpuidle_driver *cpuidle_curr_driver;
 DEFINE_SPINLOCK(cpuidle_driver_lock);
+int cpuidle_driver_refcount;
 
 static void __cpuidle_register_driver(struct cpuidle_driver *drv)
 {
@@ -89,8 +90,34 @@ void cpuidle_unregister_driver(struct cpuidle_driver *drv)
        }
 
        spin_lock(&cpuidle_driver_lock);
-       cpuidle_curr_driver = NULL;
+
+       if (!WARN_ON(cpuidle_driver_refcount > 0))
+               cpuidle_curr_driver = NULL;
+
        spin_unlock(&cpuidle_driver_lock);
 }
 
 EXPORT_SYMBOL_GPL(cpuidle_unregister_driver);
+
+struct cpuidle_driver *cpuidle_driver_ref(void)
+{
+       struct cpuidle_driver *drv;
+
+       spin_lock(&cpuidle_driver_lock);
+
+       drv = cpuidle_curr_driver;
+       cpuidle_driver_refcount++;
+
+       spin_unlock(&cpuidle_driver_lock);
+       return drv;
+}
+
+void cpuidle_driver_unref(void)
+{
+       spin_lock(&cpuidle_driver_lock);
+
+       if (!WARN_ON(cpuidle_driver_refcount <= 0))
+               cpuidle_driver_refcount--;
+
+       spin_unlock(&cpuidle_driver_lock);
+}
index 06335756ea14269bcaaeebc14c0089939a49fff0..5b1f2c372c1f1956c73f3548a25f25a82997e9f2 100644 (file)
@@ -281,7 +281,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
         * unless the timer is happening really really soon.
         */
        if (data->expected_us > 5 &&
-               drv->states[CPUIDLE_DRIVER_STATE_START].disable == 0)
+           !drv->states[CPUIDLE_DRIVER_STATE_START].disabled &&
+               dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0)
                data->last_state_idx = CPUIDLE_DRIVER_STATE_START;
 
        /*
@@ -290,8 +291,9 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev)
         */
        for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
                struct cpuidle_state *s = &drv->states[i];
+               struct cpuidle_state_usage *su = &dev->states_usage[i];
 
-               if (s->disable)
+               if (s->disabled || su->disable)
                        continue;
                if (s->target_residency > data->predicted_us)
                        continue;
index 88032b4dc6d271e8b75a7242ef8a127d5d74ec49..5f809e337b89d04dde3d2cb3ffee098e6dff6e86 100644 (file)
@@ -217,7 +217,8 @@ struct cpuidle_state_attr {
        struct attribute attr;
        ssize_t (*show)(struct cpuidle_state *, \
                                        struct cpuidle_state_usage *, char *);
-       ssize_t (*store)(struct cpuidle_state *, const char *, size_t);
+       ssize_t (*store)(struct cpuidle_state *, \
+                       struct cpuidle_state_usage *, const char *, size_t);
 };
 
 #define define_one_state_ro(_name, show) \
@@ -233,21 +234,22 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \
        return sprintf(buf, "%u\n", state->_name);\
 }
 
-#define define_store_state_function(_name) \
+#define define_store_state_ull_function(_name) \
 static ssize_t store_state_##_name(struct cpuidle_state *state, \
+               struct cpuidle_state_usage *state_usage, \
                const char *buf, size_t size) \
 { \
-       long value; \
+       unsigned long long value; \
        int err; \
        if (!capable(CAP_SYS_ADMIN)) \
                return -EPERM; \
-       err = kstrtol(buf, 0, &value); \
+       err = kstrtoull(buf, 0, &value); \
        if (err) \
                return err; \
        if (value) \
-               state->disable = 1; \
+               state_usage->_name = 1; \
        else \
-               state->disable = 0; \
+               state_usage->_name = 0; \
        return size; \
 }
 
@@ -273,8 +275,8 @@ define_show_state_ull_function(usage)
 define_show_state_ull_function(time)
 define_show_state_str_function(name)
 define_show_state_str_function(desc)
-define_show_state_function(disable)
-define_store_state_function(disable)
+define_show_state_ull_function(disable)
+define_store_state_ull_function(disable)
 
 define_one_state_ro(name, show_state_name);
 define_one_state_ro(desc, show_state_desc);
@@ -318,10 +320,11 @@ static ssize_t cpuidle_state_store(struct kobject *kobj,
 {
        int ret = -EIO;
        struct cpuidle_state *state = kobj_to_state(kobj);
+       struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj);
        struct cpuidle_state_attr *cattr = attr_to_stateattr(attr);
 
        if (cattr->store)
-               ret = cattr->store(state, buf, size);
+               ret = cattr->store(state, state_usage, buf, size);
 
        return ret;
 }
index 422a9766c7c9f68b742302d710a79bc578e57aee..ac236f6724f4bf11d1130b1258af8eff0b731044 100644 (file)
@@ -572,7 +572,7 @@ static void aes_workqueue_handler(struct work_struct *work)
        struct tegra_aes_dev *dd = aes_dev;
        int ret;
 
-       ret = clk_enable(dd->aes_clk);
+       ret = clk_prepare_enable(dd->aes_clk);
        if (ret)
                BUG_ON("clock enable failed");
 
@@ -581,7 +581,7 @@ static void aes_workqueue_handler(struct work_struct *work)
                ret = tegra_aes_handle_req(dd);
        } while (!ret);
 
-       clk_disable(dd->aes_clk);
+       clk_disable_unprepare(dd->aes_clk);
 }
 
 static irqreturn_t aes_irq(int irq, void *dev_id)
@@ -673,7 +673,7 @@ static int tegra_aes_get_random(struct crypto_rng *tfm, u8 *rdata,
        /* take mutex to access the aes hw */
        mutex_lock(&aes_lock);
 
-       ret = clk_enable(dd->aes_clk);
+       ret = clk_prepare_enable(dd->aes_clk);
        if (ret)
                return ret;
 
@@ -700,7 +700,7 @@ static int tegra_aes_get_random(struct crypto_rng *tfm, u8 *rdata,
        }
 
 out:
-       clk_disable(dd->aes_clk);
+       clk_disable_unprepare(dd->aes_clk);
        mutex_unlock(&aes_lock);
 
        dev_dbg(dd->dev, "%s: done\n", __func__);
@@ -758,7 +758,7 @@ static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed,
 
        dd->flags = FLAGS_ENCRYPT | FLAGS_RNG;
 
-       ret = clk_enable(dd->aes_clk);
+       ret = clk_prepare_enable(dd->aes_clk);
        if (ret)
                return ret;
 
@@ -788,7 +788,7 @@ static int tegra_aes_rng_reset(struct crypto_rng *tfm, u8 *seed,
        memcpy(dd->dt, dt, DEFAULT_RNG_BLK_SZ);
 
 out:
-       clk_disable(dd->aes_clk);
+       clk_disable_unprepare(dd->aes_clk);
        mutex_unlock(&aes_lock);
 
        dev_dbg(dd->dev, "%s: done\n", __func__);
index 7cac12793a4b092289dd3f34891f4e1f85999151..1c307e1b840c80f2a2bbe6c959a9803afcb77f3e 100644 (file)
@@ -1661,27 +1661,26 @@ static void ux500_cryp_shutdown(struct platform_device *pdev)
 
 }
 
-static int ux500_cryp_suspend(struct platform_device *pdev, pm_message_t state)
+static int ux500_cryp_suspend(struct device *dev)
 {
        int ret;
+       struct platform_device *pdev = to_platform_device(dev);
        struct cryp_device_data *device_data;
        struct resource *res_irq;
        struct cryp_ctx *temp_ctx = NULL;
 
-       dev_dbg(&pdev->dev, "[%s]", __func__);
+       dev_dbg(dev, "[%s]", __func__);
 
        /* Handle state? */
        device_data = platform_get_drvdata(pdev);
        if (!device_data) {
-               dev_err(&pdev->dev, "[%s]: platform_get_drvdata() failed!",
-                       __func__);
+               dev_err(dev, "[%s]: platform_get_drvdata() failed!", __func__);
                return -ENOMEM;
        }
 
        res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
        if (!res_irq)
-               dev_err(&pdev->dev, "[%s]: IORESOURCE_IRQ, unavailable",
-                       __func__);
+               dev_err(dev, "[%s]: IORESOURCE_IRQ, unavailable", __func__);
        else
                disable_irq(res_irq->start);
 
@@ -1692,32 +1691,32 @@ static int ux500_cryp_suspend(struct platform_device *pdev, pm_message_t state)
 
        if (device_data->current_ctx == ++temp_ctx) {
                if (down_interruptible(&driver_data.device_allocation))
-                       dev_dbg(&pdev->dev, "[%s]: down_interruptible() "
-                                       "failed", __func__);
-               ret = cryp_disable_power(&pdev->dev, device_data, false);
+                       dev_dbg(dev, "[%s]: down_interruptible() failed",
+                               __func__);
+               ret = cryp_disable_power(dev, device_data, false);
 
        } else
-               ret = cryp_disable_power(&pdev->dev, device_data, true);
+               ret = cryp_disable_power(dev, device_data, true);
 
        if (ret)
-               dev_err(&pdev->dev, "[%s]: cryp_disable_power()", __func__);
+               dev_err(dev, "[%s]: cryp_disable_power()", __func__);
 
        return ret;
 }
 
-static int ux500_cryp_resume(struct platform_device *pdev)
+static int ux500_cryp_resume(struct device *dev)
 {
        int ret = 0;
+       struct platform_device *pdev = to_platform_device(dev);
        struct cryp_device_data *device_data;
        struct resource *res_irq;
        struct cryp_ctx *temp_ctx = NULL;
 
-       dev_dbg(&pdev->dev, "[%s]", __func__);
+       dev_dbg(dev, "[%s]", __func__);
 
        device_data = platform_get_drvdata(pdev);
        if (!device_data) {
-               dev_err(&pdev->dev, "[%s]: platform_get_drvdata() failed!",
-                       __func__);
+               dev_err(dev, "[%s]: platform_get_drvdata() failed!", __func__);
                return -ENOMEM;
        }
 
@@ -1730,11 +1729,10 @@ static int ux500_cryp_resume(struct platform_device *pdev)
        if (!device_data->current_ctx)
                up(&driver_data.device_allocation);
        else
-               ret = cryp_enable_power(&pdev->dev, device_data, true);
+               ret = cryp_enable_power(dev, device_data, true);
 
        if (ret)
-               dev_err(&pdev->dev, "[%s]: cryp_enable_power() failed!",
-                       __func__);
+               dev_err(dev, "[%s]: cryp_enable_power() failed!", __func__);
        else {
                res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
                if (res_irq)
@@ -1744,15 +1742,16 @@ static int ux500_cryp_resume(struct platform_device *pdev)
        return ret;
 }
 
+static SIMPLE_DEV_PM_OPS(ux500_cryp_pm, ux500_cryp_suspend, ux500_cryp_resume);
+
 static struct platform_driver cryp_driver = {
        .probe  = ux500_cryp_probe,
        .remove = ux500_cryp_remove,
        .shutdown = ux500_cryp_shutdown,
-       .suspend  = ux500_cryp_suspend,
-       .resume   = ux500_cryp_resume,
        .driver = {
                .owner = THIS_MODULE,
                .name  = "cryp1"
+               .pm    = &ux500_cryp_pm,
        }
 };
 
index 6dbb9ec709a388c4fe5c52a6db0441f812110970..08d5032cb56426f939fea9760620e22d7154abc3 100644 (file)
@@ -1894,19 +1894,17 @@ static void ux500_hash_shutdown(struct platform_device *pdev)
 
 /**
  * ux500_hash_suspend - Function that suspends the hash device.
- * @pdev:      The platform device.
- * @state:     -
+ * @dev:       Device to suspend.
  */
-static int ux500_hash_suspend(struct platform_device *pdev, pm_message_t state)
+static int ux500_hash_suspend(struct device *dev)
 {
        int ret;
        struct hash_device_data *device_data;
        struct hash_ctx *temp_ctx = NULL;
 
-       device_data = platform_get_drvdata(pdev);
+       device_data = dev_get_drvdata(dev);
        if (!device_data) {
-               dev_err(&pdev->dev, "[%s] platform_get_drvdata() failed!",
-                               __func__);
+               dev_err(dev, "[%s] platform_get_drvdata() failed!", __func__);
                return -ENOMEM;
        }
 
@@ -1917,33 +1915,32 @@ static int ux500_hash_suspend(struct platform_device *pdev, pm_message_t state)
 
        if (device_data->current_ctx == ++temp_ctx) {
                if (down_interruptible(&driver_data.device_allocation))
-                       dev_dbg(&pdev->dev, "[%s]: down_interruptible() "
-                                       "failed", __func__);
+                       dev_dbg(dev, "[%s]: down_interruptible() failed",
+                               __func__);
                ret = hash_disable_power(device_data, false);
 
        } else
                ret = hash_disable_power(device_data, true);
 
        if (ret)
-               dev_err(&pdev->dev, "[%s]: hash_disable_power()", __func__);
+               dev_err(dev, "[%s]: hash_disable_power()", __func__);
 
        return ret;
 }
 
 /**
  * ux500_hash_resume - Function that resume the hash device.
- * @pdev:      The platform device.
+ * @dev:       Device to resume.
  */
-static int ux500_hash_resume(struct platform_device *pdev)
+static int ux500_hash_resume(struct device *dev)
 {
        int ret = 0;
        struct hash_device_data *device_data;
        struct hash_ctx *temp_ctx = NULL;
 
-       device_data = platform_get_drvdata(pdev);
+       device_data = dev_get_drvdata(dev);
        if (!device_data) {
-               dev_err(&pdev->dev, "[%s] platform_get_drvdata() failed!",
-                               __func__);
+               dev_err(dev, "[%s] platform_get_drvdata() failed!", __func__);
                return -ENOMEM;
        }
 
@@ -1958,21 +1955,21 @@ static int ux500_hash_resume(struct platform_device *pdev)
                ret = hash_enable_power(device_data, true);
 
        if (ret)
-               dev_err(&pdev->dev, "[%s]: hash_enable_power() failed!",
-                       __func__);
+               dev_err(dev, "[%s]: hash_enable_power() failed!", __func__);
 
        return ret;
 }
 
+static SIMPLE_DEV_PM_OPS(ux500_hash_pm, ux500_hash_suspend, ux500_hash_resume);
+
 static struct platform_driver hash_driver = {
        .probe  = ux500_hash_probe,
        .remove = ux500_hash_remove,
        .shutdown = ux500_hash_shutdown,
-       .suspend  = ux500_hash_suspend,
-       .resume   = ux500_hash_resume,
        .driver = {
                .owner = THIS_MODULE,
                .name  = "hash1",
+               .pm    = &ux500_hash_pm,
        }
 };
 
index 5ec72044ea4c13a5849eef9675c10335c4307416..c7573e50aa14110118426c9d56c49cdb890cd651 100644 (file)
@@ -1663,7 +1663,6 @@ static void __exit ipu_idmac_exit(struct ipu *ipu)
 
 static int __init ipu_probe(struct platform_device *pdev)
 {
-       struct ipu_platform_data *pdata = pdev->dev.platform_data;
        struct resource *mem_ipu, *mem_ic;
        int ret;
 
@@ -1671,7 +1670,7 @@ static int __init ipu_probe(struct platform_device *pdev)
 
        mem_ipu = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        mem_ic  = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!pdata || !mem_ipu || !mem_ic)
+       if (!mem_ipu || !mem_ic)
                return -EINVAL;
 
        ipu_data.dev = &pdev->dev;
@@ -1688,10 +1687,9 @@ static int __init ipu_probe(struct platform_device *pdev)
                goto err_noirq;
 
        ipu_data.irq_err = ret;
-       ipu_data.irq_base = pdata->irq_base;
 
-       dev_dbg(&pdev->dev, "fn irq %u, err irq %u, irq-base %u\n",
-               ipu_data.irq_fn, ipu_data.irq_err, ipu_data.irq_base);
+       dev_dbg(&pdev->dev, "fn irq %u, err irq %u\n",
+               ipu_data.irq_fn, ipu_data.irq_err);
 
        /* Remap IPU common registers */
        ipu_data.reg_ipu = ioremap(mem_ipu->start, resource_size(mem_ipu));
index a71f55e72be9cf407217d1f164e59ac677bd46d4..fa95bcc3de1f66b107a4cddf38e97d5fa68286b2 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/clk.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/module.h>
 
 #include <mach/ipu.h>
 
@@ -354,10 +355,12 @@ static struct irq_chip ipu_irq_chip = {
 /* Install the IRQ handler */
 int __init ipu_irq_attach_irq(struct ipu *ipu, struct platform_device *dev)
 {
-       struct ipu_platform_data *pdata = dev->dev.platform_data;
-       unsigned int irq, irq_base, i;
+       unsigned int irq, i;
+       int irq_base = irq_alloc_descs(-1, 0, CONFIG_MX3_IPU_IRQS,
+                                      numa_node_id());
 
-       irq_base = pdata->irq_base;
+       if (irq_base < 0)
+               return irq_base;
 
        for (i = 0; i < IPU_IRQ_NR_BANKS; i++)
                irq_bank[i].ipu = ipu;
@@ -387,15 +390,16 @@ int __init ipu_irq_attach_irq(struct ipu *ipu, struct platform_device *dev)
        irq_set_handler_data(ipu->irq_err, ipu);
        irq_set_chained_handler(ipu->irq_err, ipu_irq_err);
 
+       ipu->irq_base = irq_base;
+
        return 0;
 }
 
 void ipu_irq_detach_irq(struct ipu *ipu, struct platform_device *dev)
 {
-       struct ipu_platform_data *pdata = dev->dev.platform_data;
        unsigned int irq, irq_base;
 
-       irq_base = pdata->irq_base;
+       irq_base = ipu->irq_base;
 
        irq_set_chained_handler(ipu->irq_fn, NULL);
        irq_set_handler_data(ipu->irq_fn, NULL);
index c89c4c1e668d97cf170f4fc07dc5911d83cb52d9..04691d3abe6061feade251bf9c363fc998b1f21c 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqdomain.h>
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
@@ -33,8 +34,6 @@
 #include <asm-generic/bug.h>
 #include <asm/mach/irq.h>
 
-#define irq_to_gpio(irq)       ((irq) - MXC_GPIO_IRQ_START)
-
 enum mxc_gpio_hwtype {
        IMX1_GPIO,      /* runs on i.mx1 */
        IMX21_GPIO,     /* runs on i.mx21 and i.mx27 */
@@ -61,7 +60,7 @@ struct mxc_gpio_port {
        void __iomem *base;
        int irq;
        int irq_high;
-       int virtual_irq_start;
+       struct irq_domain *domain;
        struct bgpio_chip bgc;
        u32 both_edges;
 };
@@ -144,14 +143,15 @@ static LIST_HEAD(mxc_gpio_ports);
 
 static int gpio_set_irq_type(struct irq_data *d, u32 type)
 {
-       u32 gpio = irq_to_gpio(d->irq);
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mxc_gpio_port *port = gc->private;
        u32 bit, val;
+       u32 gpio_idx = d->hwirq;
+       u32 gpio = port->bgc.gc.base + gpio_idx;
        int edge;
        void __iomem *reg = port->base;
 
-       port->both_edges &= ~(1 << (gpio & 31));
+       port->both_edges &= ~(1 << gpio_idx);
        switch (type) {
        case IRQ_TYPE_EDGE_RISING:
                edge = GPIO_INT_RISE_EDGE;
@@ -168,7 +168,7 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
                        edge = GPIO_INT_HIGH_LEV;
                        pr_debug("mxc: set GPIO %d to high trigger\n", gpio);
                }
-               port->both_edges |= 1 << (gpio & 31);
+               port->both_edges |= 1 << gpio_idx;
                break;
        case IRQ_TYPE_LEVEL_LOW:
                edge = GPIO_INT_LOW_LEV;
@@ -180,11 +180,11 @@ static int gpio_set_irq_type(struct irq_data *d, u32 type)
                return -EINVAL;
        }
 
-       reg += GPIO_ICR1 + ((gpio & 0x10) >> 2); /* lower or upper register */
-       bit = gpio & 0xf;
+       reg += GPIO_ICR1 + ((gpio_idx & 0x10) >> 2); /* ICR1 or ICR2 */
+       bit = gpio_idx & 0xf;
        val = readl(reg) & ~(0x3 << (bit << 1));
        writel(val | (edge << (bit << 1)), reg);
-       writel(1 << (gpio & 0x1f), port->base + GPIO_ISR);
+       writel(1 << gpio_idx, port->base + GPIO_ISR);
 
        return 0;
 }
@@ -217,15 +217,13 @@ static void mxc_flip_edge(struct mxc_gpio_port *port, u32 gpio)
 /* handle 32 interrupts in one status register */
 static void mxc_gpio_irq_handler(struct mxc_gpio_port *port, u32 irq_stat)
 {
-       u32 gpio_irq_no_base = port->virtual_irq_start;
-
        while (irq_stat != 0) {
                int irqoffset = fls(irq_stat) - 1;
 
                if (port->both_edges & (1 << irqoffset))
                        mxc_flip_edge(port, irqoffset);
 
-               generic_handle_irq(gpio_irq_no_base + irqoffset);
+               generic_handle_irq(irq_find_mapping(port->domain, irqoffset));
 
                irq_stat &= ~(1 << irqoffset);
        }
@@ -276,10 +274,9 @@ static void mx2_gpio_irq_handler(u32 irq, struct irq_desc *desc)
  */
 static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
 {
-       u32 gpio = irq_to_gpio(d->irq);
-       u32 gpio_idx = gpio & 0x1F;
        struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d);
        struct mxc_gpio_port *port = gc->private;
+       u32 gpio_idx = d->hwirq;
 
        if (enable) {
                if (port->irq_high && (gpio_idx >= 16))
@@ -296,12 +293,12 @@ static int gpio_set_wake_irq(struct irq_data *d, u32 enable)
        return 0;
 }
 
-static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port)
+static void __init mxc_gpio_init_gc(struct mxc_gpio_port *port, int irq_base)
 {
        struct irq_chip_generic *gc;
        struct irq_chip_type *ct;
 
-       gc = irq_alloc_generic_chip("gpio-mxc", 1, port->virtual_irq_start,
+       gc = irq_alloc_generic_chip("gpio-mxc", 1, irq_base,
                                    port->base, handle_level_irq);
        gc->private = port;
 
@@ -352,7 +349,7 @@ static int mxc_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
        struct mxc_gpio_port *port =
                container_of(bgc, struct mxc_gpio_port, bgc);
 
-       return port->virtual_irq_start + offset;
+       return irq_find_mapping(port->domain, offset);
 }
 
 static int __devinit mxc_gpio_probe(struct platform_device *pdev)
@@ -360,6 +357,7 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev)
        struct device_node *np = pdev->dev.of_node;
        struct mxc_gpio_port *port;
        struct resource *iores;
+       int irq_base;
        int err;
 
        mxc_gpio_get_hw(pdev);
@@ -432,20 +430,30 @@ static int __devinit mxc_gpio_probe(struct platform_device *pdev)
        if (err)
                goto out_bgpio_remove;
 
-       /*
-        * In dt case, we use gpio number range dynamically
-        * allocated by gpio core.
-        */
-       port->virtual_irq_start = MXC_GPIO_IRQ_START + (np ? port->bgc.gc.base :
-                                                            pdev->id * 32);
+       irq_base = irq_alloc_descs(-1, 0, 32, numa_node_id());
+       if (irq_base < 0) {
+               err = irq_base;
+               goto out_gpiochip_remove;
+       }
+
+       port->domain = irq_domain_add_legacy(np, 32, irq_base, 0,
+                                            &irq_domain_simple_ops, NULL);
+       if (!port->domain) {
+               err = -ENODEV;
+               goto out_irqdesc_free;
+       }
 
        /* gpio-mxc can be a generic irq chip */
-       mxc_gpio_init_gc(port);
+       mxc_gpio_init_gc(port, irq_base);
 
        list_add_tail(&port->node, &mxc_gpio_ports);
 
        return 0;
 
+out_irqdesc_free:
+       irq_free_descs(irq_base, 32);
+out_gpiochip_remove:
+       WARN_ON(gpiochip_remove(&port->bgc.gc) < 0);
 out_bgpio_remove:
        bgpio_remove(&port->bgc);
 out_iounmap:
index 34ad5a27a7e9fcd68b7597f799a99387f421c835..e3fcf81468349ea5de8bd6cb99f1d9a0617dab72 100644 (file)
@@ -929,20 +929,25 @@ static int acpi_power_meter_remove(struct acpi_device *device, int type)
        return 0;
 }
 
-static int acpi_power_meter_resume(struct acpi_device *device)
+static int acpi_power_meter_resume(struct device *dev)
 {
        struct acpi_power_meter_resource *resource;
 
-       if (!device || !acpi_driver_data(device))
+       if (!dev)
+               return -EINVAL;
+
+       resource = acpi_driver_data(to_acpi_device(dev));
+       if (!resource)
                return -EINVAL;
 
-       resource = acpi_driver_data(device);
        free_capabilities(resource);
        read_capabilities(resource);
 
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(acpi_power_meter_pm, NULL, acpi_power_meter_resume);
+
 static struct acpi_driver acpi_power_meter_driver = {
        .name = "power_meter",
        .class = ACPI_POWER_METER_CLASS,
@@ -950,9 +955,9 @@ static struct acpi_driver acpi_power_meter_driver = {
        .ops = {
                .add = acpi_power_meter_add,
                .remove = acpi_power_meter_remove,
-               .resume = acpi_power_meter_resume,
                .notify = acpi_power_meter_notify,
                },
+       .drv.pm = &acpi_power_meter_pm,
 };
 
 /* Module init/exit routines */
index 7356b5ec8f6733bd9b4cc9a96f6f790831c60f6b..f2fe8078633b1d6fe996a69b518c3ad1987cff9f 100644 (file)
@@ -33,9 +33,6 @@ static bool force;
 module_param(force, bool, 0444);
 MODULE_PARM_DESC(force, "force loading on processors with erratum 319");
 
-/* PCI-IDs for Northbridge devices not used anywhere else */
-#define PCI_DEVICE_ID_AMD_15H_M10H_NB_F3       0x1403
-
 /* CPUID function 0x80000001, ebx */
 #define CPUID_PKGTYPE_MASK     0xf0000000
 #define CPUID_PKGTYPE_F                0x00000000
@@ -213,7 +210,7 @@ static DEFINE_PCI_DEVICE_TABLE(k10temp_id_table) = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
-       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_NB_F3) },
+       { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_F3) },
        {}
 };
 MODULE_DEVICE_TABLE(pci, k10temp_id_table);
index 8d6b504d65c44e72800514db4ac3027ce3673636..370031ac8200d4765606437b1ffc8b61967dac12 100644 (file)
@@ -53,7 +53,6 @@
 #include <linux/of_i2c.h>
 #include <linux/pinctrl/consumer.h>
 
-#include <mach/irqs.h>
 #include <mach/hardware.h>
 #include <mach/i2c.h>
 
index 5267ab93d55073e43c53f5fb073d6d8aec438811..a92440dbef078ba18c6c5561a74f7f8265ba72c4 100644 (file)
@@ -965,8 +965,7 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev)
        adap->owner     = THIS_MODULE;
        adap->class     = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        adap->algo      = &nmk_i2c_algo;
-       adap->timeout   = pdata->timeout ? msecs_to_jiffies(pdata->timeout) :
-               msecs_to_jiffies(20000);
+       adap->timeout   = msecs_to_jiffies(pdata->timeout);
        snprintf(adap->name, sizeof(adap->name),
                 "Nomadik I2C%d at %lx", pdev->id, (unsigned long)res->start);
 
index 31c47e18d83c5f9fdf3bdb8927c57bc3ef12cd84..5285f8565de4d14c1e8265fc12c5ee18b0c670ae 100644 (file)
@@ -227,28 +227,138 @@ static int __devexit i2c_powermac_remove(struct platform_device *dev)
        return 0;
 }
 
+static u32 __devinit i2c_powermac_get_addr(struct i2c_adapter *adap,
+                                          struct pmac_i2c_bus *bus,
+                                          struct device_node *node)
+{
+       const __be32 *prop;
+       int len;
+
+       /* First check for valid "reg" */
+       prop = of_get_property(node, "reg", &len);
+       if (prop && (len >= sizeof(int)))
+               return (be32_to_cpup(prop) & 0xff) >> 1;
+
+       /* Then check old-style "i2c-address" */
+       prop = of_get_property(node, "i2c-address", &len);
+       if (prop && (len >= sizeof(int)))
+               return (be32_to_cpup(prop) & 0xff) >> 1;
+
+       /* Now handle some devices with missing "reg" properties */
+       if (!strcmp(node->name, "cereal"))
+               return 0x60;
+       else if (!strcmp(node->name, "deq"))
+               return 0x34;
+
+       dev_warn(&adap->dev, "No i2c address for %s\n", node->full_name);
+
+       return 0xffffffff;
+}
+
+static void __devinit i2c_powermac_create_one(struct i2c_adapter *adap,
+                                             const char *type,
+                                             u32 addr)
+{
+       struct i2c_board_info info = {};
+       struct i2c_client *newdev;
+
+       strncpy(info.type, type, sizeof(info.type));
+       info.addr = addr;
+       newdev = i2c_new_device(adap, &info);
+       if (!newdev)
+               dev_err(&adap->dev,
+                       "i2c-powermac: Failure to register missing %s\n",
+                       type);
+}
+
+static void __devinit i2c_powermac_add_missing(struct i2c_adapter *adap,
+                                              struct pmac_i2c_bus *bus,
+                                              bool found_onyx)
+{
+       struct device_node *busnode = pmac_i2c_get_bus_node(bus);
+       int rc;
+
+       /* Check for the onyx audio codec */
+#define ONYX_REG_CONTROL               67
+       if (of_device_is_compatible(busnode, "k2-i2c") && !found_onyx) {
+               union i2c_smbus_data data;
+
+               rc = i2c_smbus_xfer(adap, 0x46, 0, I2C_SMBUS_READ,
+                                   ONYX_REG_CONTROL, I2C_SMBUS_BYTE_DATA,
+                                   &data);
+               if (rc >= 0)
+                       i2c_powermac_create_one(adap, "MAC,pcm3052", 0x46);
+
+               rc = i2c_smbus_xfer(adap, 0x47, 0, I2C_SMBUS_READ,
+                                   ONYX_REG_CONTROL, I2C_SMBUS_BYTE_DATA,
+                                   &data);
+               if (rc >= 0)
+                       i2c_powermac_create_one(adap, "MAC,pcm3052", 0x47);
+       }
+}
+
+static bool __devinit i2c_powermac_get_type(struct i2c_adapter *adap,
+                                           struct device_node *node,
+                                           u32 addr, char *type, int type_size)
+{
+       char tmp[16];
+
+       /* Note: we to _NOT_ want the standard
+        * i2c drivers to match with any of our powermac stuff
+        * unless they have been specifically modified to handle
+        * it on a case by case basis. For example, for thermal
+        * control, things like lm75 etc... shall match with their
+        * corresponding windfarm drivers, _NOT_ the generic ones,
+        * so we force a prefix of AAPL, onto the modalias to
+        * make that happen
+        */
+
+       /* First try proper modalias */
+       if (of_modalias_node(node, tmp, sizeof(tmp)) >= 0) {
+               snprintf(type, type_size, "MAC,%s", tmp);
+               return true;
+       }
+
+       /* Now look for known workarounds */
+       if (!strcmp(node->name, "deq")) {
+               /* Apple uses address 0x34 for TAS3001 and 0x35 for TAS3004 */
+               if (addr == 0x34) {
+                       snprintf(type, type_size, "MAC,tas3001");
+                       return true;
+               } else if (addr == 0x35) {
+                       snprintf(type, type_size, "MAC,tas3004");
+                       return true;
+               }
+       }
+
+       dev_err(&adap->dev, "i2c-powermac: modalias failure"
+               " on %s\n", node->full_name);
+       return false;
+}
+
 static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap,
                                                    struct pmac_i2c_bus *bus)
 {
        struct i2c_client *newdev;
        struct device_node *node;
+       bool found_onyx = 0;
+
+       /*
+        * In some cases we end up with the via-pmu node itself, in this
+        * case we skip this function completely as the device-tree will
+        * not contain anything useful.
+        */
+       if (!strcmp(adap->dev.of_node->name, "via-pmu"))
+               return;
 
        for_each_child_of_node(adap->dev.of_node, node) {
                struct i2c_board_info info = {};
-               struct dev_archdata dev_ad = {};
-               const __be32 *reg;
-               char tmp[16];
                u32 addr;
-               int len;
 
                /* Get address & channel */
-               reg = of_get_property(node, "reg", &len);
-               if (!reg || (len < sizeof(int))) {
-                       dev_err(&adap->dev, "i2c-powermac: invalid reg on %s\n",
-                               node->full_name);
+               addr = i2c_powermac_get_addr(adap, bus, node);
+               if (addr == 0xffffffff)
                        continue;
-               }
-               addr = be32_to_cpup(reg);
 
                /* Multibus setup, check channel */
                if (!pmac_i2c_match_adapter(node, adap))
@@ -257,27 +367,23 @@ static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap,
                dev_dbg(&adap->dev, "i2c-powermac: register %s\n",
                        node->full_name);
 
-               /* Make up a modalias. Note: we to _NOT_ want the standard
-                * i2c drivers to match with any of our powermac stuff
-                * unless they have been specifically modified to handle
-                * it on a case by case basis. For example, for thermal
-                * control, things like lm75 etc... shall match with their
-                * corresponding windfarm drivers, _NOT_ the generic ones,
-                * so we force a prefix of AAPL, onto the modalias to
-                * make that happen
+               /*
+                * Keep track of some device existence to handle
+                * workarounds later.
                 */
-               if (of_modalias_node(node, tmp, sizeof(tmp)) < 0) {
-                       dev_err(&adap->dev, "i2c-powermac: modalias failure"
-                               " on %s\n", node->full_name);
+               if (of_device_is_compatible(node, "pcm3052"))
+                       found_onyx = true;
+
+               /* Make up a modalias */
+               if (!i2c_powermac_get_type(adap, node, addr,
+                                          info.type, sizeof(info.type))) {
                        continue;
                }
-               snprintf(info.type, sizeof(info.type), "MAC,%s", tmp);
 
                /* Fill out the rest of the info structure */
-               info.addr = (addr & 0xff) >> 1;
+               info.addr = addr;
                info.irq = irq_of_parse_and_map(node, 0);
                info.of_node = of_node_get(node);
-               info.archdata = &dev_ad;
 
                newdev = i2c_new_device(adap, &info);
                if (!newdev) {
@@ -292,6 +398,9 @@ static void __devinit i2c_powermac_register_devices(struct i2c_adapter *adap,
                        continue;
                }
        }
+
+       /* Additional workarounds */
+       i2c_powermac_add_missing(adap, bus, found_onyx);
 }
 
 static int __devinit i2c_powermac_probe(struct platform_device *dev)
index 8b2e555a9563204476be25184d442d0422a49920..3da7ee3eb505e0816d809093958f0259816c3450 100644 (file)
@@ -341,7 +341,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
        u32 val;
        int err = 0;
 
-       clk_enable(i2c_dev->clk);
+       clk_prepare_enable(i2c_dev->clk);
 
        tegra_periph_reset_assert(i2c_dev->clk);
        udelay(2);
@@ -372,7 +372,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
        if (tegra_i2c_flush_fifos(i2c_dev))
                err = -ETIMEDOUT;
 
-       clk_disable(i2c_dev->clk);
+       clk_disable_unprepare(i2c_dev->clk);
 
        if (i2c_dev->irq_disabled) {
                i2c_dev->irq_disabled = 0;
@@ -546,14 +546,14 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
        if (i2c_dev->is_suspended)
                return -EBUSY;
 
-       clk_enable(i2c_dev->clk);
+       clk_prepare_enable(i2c_dev->clk);
        for (i = 0; i < num; i++) {
                int stop = (i == (num - 1)) ? 1  : 0;
                ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], stop);
                if (ret)
                        break;
        }
-       clk_disable(i2c_dev->clk);
+       clk_disable_unprepare(i2c_dev->clk);
        return ret ?: i;
 }
 
@@ -666,7 +666,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev)
                goto err_free;
        }
 
-       clk_enable(i2c_dev->i2c_clk);
+       clk_prepare_enable(i2c_dev->i2c_clk);
 
        i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
        i2c_dev->adapter.owner = THIS_MODULE;
index d0f59c3f87eff08c9af04bd7d13f2b91e6f3ea17..fe95d5464a0251470cb9f094f4e7bc5922f1e3c8 100644 (file)
@@ -96,6 +96,7 @@ static const struct idle_cpu *icpu;
 static struct cpuidle_device __percpu *intel_idle_cpuidle_devices;
 static int intel_idle(struct cpuidle_device *dev,
                        struct cpuidle_driver *drv, int index);
+static int intel_idle_cpu_init(int cpu);
 
 static struct cpuidle_state *cpuidle_state_table;
 
@@ -302,22 +303,35 @@ static void __setup_broadcast_timer(void *arg)
        clockevents_notify(reason, &cpu);
 }
 
-static int setup_broadcast_cpuhp_notify(struct notifier_block *n,
-               unsigned long action, void *hcpu)
+static int cpu_hotplug_notify(struct notifier_block *n,
+                             unsigned long action, void *hcpu)
 {
        int hotcpu = (unsigned long)hcpu;
+       struct cpuidle_device *dev;
 
        switch (action & 0xf) {
        case CPU_ONLINE:
-               smp_call_function_single(hotcpu, __setup_broadcast_timer,
-                       (void *)true, 1);
+
+               if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
+                       smp_call_function_single(hotcpu, __setup_broadcast_timer,
+                                                (void *)true, 1);
+
+               /*
+                * Some systems can hotplug a cpu at runtime after
+                * the kernel has booted, we have to initialize the
+                * driver in this case
+                */
+               dev = per_cpu_ptr(intel_idle_cpuidle_devices, hotcpu);
+               if (!dev->registered)
+                       intel_idle_cpu_init(hotcpu);
+
                break;
        }
        return NOTIFY_OK;
 }
 
-static struct notifier_block setup_broadcast_notifier = {
-       .notifier_call = setup_broadcast_cpuhp_notify,
+static struct notifier_block cpu_hotplug_notifier = {
+       .notifier_call = cpu_hotplug_notify,
 };
 
 static void auto_demotion_disable(void *dummy)
@@ -405,10 +419,10 @@ static int intel_idle_probe(void)
 
        if (boot_cpu_has(X86_FEATURE_ARAT))     /* Always Reliable APIC Timer */
                lapic_timer_reliable_states = LAPIC_TIMER_ALWAYS_RELIABLE;
-       else {
+       else
                on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
-               register_cpu_notifier(&setup_broadcast_notifier);
-       }
+
+       register_cpu_notifier(&cpu_hotplug_notifier);
 
        pr_debug(PREFIX "v" INTEL_IDLE_VERSION
                " model 0x%X\n", boot_cpu_data.x86_model);
@@ -494,7 +508,7 @@ static int intel_idle_cpuidle_driver_init(void)
  * allocate, initialize, register cpuidle_devices
  * @cpu: cpu/core to initialize
  */
-int intel_idle_cpu_init(int cpu)
+static int intel_idle_cpu_init(int cpu)
 {
        int cstate;
        struct cpuidle_device *dev;
@@ -539,7 +553,6 @@ int intel_idle_cpu_init(int cpu)
 
        return 0;
 }
-EXPORT_SYMBOL_GPL(intel_idle_cpu_init);
 
 static int __init intel_idle_init(void)
 {
@@ -581,10 +594,10 @@ static void __exit intel_idle_exit(void)
        intel_idle_cpuidle_devices_uninit();
        cpuidle_unregister_driver(&intel_idle_driver);
 
-       if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE) {
+
+       if (lapic_timer_reliable_states != LAPIC_TIMER_ALWAYS_RELIABLE)
                on_each_cpu(__setup_broadcast_timer, (void *)false, 1);
-               unregister_cpu_notifier(&setup_broadcast_notifier);
-       }
+       unregister_cpu_notifier(&cpu_hotplug_notifier);
 
        return;
 }
index 5f6b7f63cdef28cf37ce3e350c3d5e099d273b16..7a0ce8d42887e225e81d20702892d8ed0d056f39 100644 (file)
@@ -1377,10 +1377,14 @@ static int srpt_abort_cmd(struct srpt_send_ioctx *ioctx)
                break;
        case SRPT_STATE_NEED_DATA:
                /* DMA_TO_DEVICE (write) - RDMA read error. */
+
+               /* XXX(hch): this is a horrible layering violation.. */
                spin_lock_irqsave(&ioctx->cmd.t_state_lock, flags);
                ioctx->cmd.transport_state |= CMD_T_LUN_STOP;
+               ioctx->cmd.transport_state &= ~CMD_T_ACTIVE;
                spin_unlock_irqrestore(&ioctx->cmd.t_state_lock, flags);
-               transport_generic_handle_data(&ioctx->cmd);
+
+               complete(&ioctx->cmd.transport_lun_stop_comp);
                break;
        case SRPT_STATE_CMD_RSP_SENT:
                /*
@@ -1463,9 +1467,10 @@ static void srpt_handle_send_comp(struct srpt_rdma_ch *ch,
 /**
  * srpt_handle_rdma_comp() - Process an IB RDMA completion notification.
  *
- * Note: transport_generic_handle_data() is asynchronous so unmapping the
- * data that has been transferred via IB RDMA must be postponed until the
- * check_stop_free() callback.
+ * XXX: what is now target_execute_cmd used to be asynchronous, and unmapping
+ * the data that has been transferred via IB RDMA had to be postponed until the
+ * check_stop_free() callback.  None of this is nessecary anymore and needs to
+ * be cleaned up.
  */
 static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
                                  struct srpt_send_ioctx *ioctx,
@@ -1477,7 +1482,7 @@ static void srpt_handle_rdma_comp(struct srpt_rdma_ch *ch,
        if (opcode == SRPT_RDMA_READ_LAST) {
                if (srpt_test_and_set_cmd_state(ioctx, SRPT_STATE_NEED_DATA,
                                                SRPT_STATE_DATA_IN))
-                       transport_generic_handle_data(&ioctx->cmd);
+                       target_execute_cmd(&ioctx->cmd);
                else
                        printk(KERN_ERR "%s[%d]: wrong state = %d\n", __func__,
                               __LINE__, srpt_get_cmd_state(ioctx));
index 4ffe64d53107f48336999d4753299a3cc03fa8ae..2c1c9ed1bd9f6ad194405c73d1d14a368ee3ade9 100644 (file)
@@ -492,7 +492,7 @@ static int tegra_kbc_start(struct tegra_kbc *kbc)
        unsigned int debounce_cnt;
        u32 val = 0;
 
-       clk_enable(kbc->clk);
+       clk_prepare_enable(kbc->clk);
 
        /* Reset the KBC controller to clear all previous status.*/
        tegra_periph_reset_assert(kbc->clk);
@@ -556,7 +556,7 @@ static void tegra_kbc_stop(struct tegra_kbc *kbc)
        disable_irq(kbc->irq);
        del_timer_sync(&kbc->timer);
 
-       clk_disable(kbc->clk);
+       clk_disable_unprepare(kbc->clk);
 }
 
 static int tegra_kbc_open(struct input_dev *dev)
index 3a74e4410fc0737d47e1f294378fdb7dc07e27ad..86e2f4a62b9a95fed887dda18b6bd5bdd2cdacda 100644 (file)
@@ -26,6 +26,8 @@
  * These routines are used by both DMA-remapping and Interrupt-remapping
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt /* has to precede printk.h */
+
 #include <linux/pci.h>
 #include <linux/dmar.h>
 #include <linux/iova.h>
@@ -39,8 +41,6 @@
 #include <asm/irq_remapping.h>
 #include <asm/iommu_table.h>
 
-#define PREFIX "DMAR: "
-
 /* No locks are needed as DMA remapping hardware unit
  * list is constructed at boot time and hotplug of
  * these units are not supported by the architecture.
@@ -83,16 +83,12 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
                 * ignore it
                 */
                if (!bus) {
-                       printk(KERN_WARNING
-                       PREFIX "Device scope bus [%d] not found\n",
-                       scope->bus);
+                       pr_warn("Device scope bus [%d] not found\n", scope->bus);
                        break;
                }
                pdev = pci_get_slot(bus, PCI_DEVFN(path->dev, path->fn));
                if (!pdev) {
-                       printk(KERN_WARNING PREFIX
-                       "Device scope device [%04x:%02x:%02x.%02x] not found\n",
-                               segment, bus->number, path->dev, path->fn);
+                       /* warning will be printed below */
                        break;
                }
                path ++;
@@ -100,9 +96,8 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
                bus = pdev->subordinate;
        }
        if (!pdev) {
-               printk(KERN_WARNING PREFIX
-               "Device scope device [%04x:%02x:%02x.%02x] not found\n",
-               segment, scope->bus, path->dev, path->fn);
+               pr_warn("Device scope device [%04x:%02x:%02x.%02x] not found\n",
+                       segment, scope->bus, path->dev, path->fn);
                *dev = NULL;
                return 0;
        }
@@ -110,9 +105,8 @@ static int __init dmar_parse_one_dev_scope(struct acpi_dmar_device_scope *scope,
                        pdev->subordinate) || (scope->entry_type == \
                        ACPI_DMAR_SCOPE_TYPE_BRIDGE && !pdev->subordinate)) {
                pci_dev_put(pdev);
-               printk(KERN_WARNING PREFIX
-                       "Device scope type does not match for %s\n",
-                        pci_name(pdev));
+               pr_warn("Device scope type does not match for %s\n",
+                       pci_name(pdev));
                return -EINVAL;
        }
        *dev = pdev;
@@ -134,8 +128,7 @@ int __init dmar_parse_dev_scope(void *start, void *end, int *cnt,
                    scope->entry_type == ACPI_DMAR_SCOPE_TYPE_BRIDGE)
                        (*cnt)++;
                else if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_IOAPIC) {
-                       printk(KERN_WARNING PREFIX
-                              "Unsupported device scope\n");
+                       pr_warn("Unsupported device scope\n");
                }
                start += scope->length;
        }
@@ -261,25 +254,23 @@ dmar_table_print_dmar_entry(struct acpi_dmar_header *header)
        case ACPI_DMAR_TYPE_HARDWARE_UNIT:
                drhd = container_of(header, struct acpi_dmar_hardware_unit,
                                    header);
-               printk (KERN_INFO PREFIX
-                       "DRHD base: %#016Lx flags: %#x\n",
+               pr_info("DRHD base: %#016Lx flags: %#x\n",
                        (unsigned long long)drhd->address, drhd->flags);
                break;
        case ACPI_DMAR_TYPE_RESERVED_MEMORY:
                rmrr = container_of(header, struct acpi_dmar_reserved_memory,
                                    header);
-               printk (KERN_INFO PREFIX
-                       "RMRR base: %#016Lx end: %#016Lx\n",
+               pr_info("RMRR base: %#016Lx end: %#016Lx\n",
                        (unsigned long long)rmrr->base_address,
                        (unsigned long long)rmrr->end_address);
                break;
        case ACPI_DMAR_TYPE_ATSR:
                atsr = container_of(header, struct acpi_dmar_atsr, header);
-               printk(KERN_INFO PREFIX "ATSR flags: %#x\n", atsr->flags);
+               pr_info("ATSR flags: %#x\n", atsr->flags);
                break;
        case ACPI_DMAR_HARDWARE_AFFINITY:
                rhsa = container_of(header, struct acpi_dmar_rhsa, header);
-               printk(KERN_INFO PREFIX "RHSA base: %#016Lx proximity domain: %#x\n",
+               pr_info("RHSA base: %#016Lx proximity domain: %#x\n",
                       (unsigned long long)rhsa->base_address,
                       rhsa->proximity_domain);
                break;
@@ -299,7 +290,7 @@ static int __init dmar_table_detect(void)
                                &dmar_tbl_size);
 
        if (ACPI_SUCCESS(status) && !dmar_tbl) {
-               printk (KERN_WARNING PREFIX "Unable to map DMAR\n");
+               pr_warn("Unable to map DMAR\n");
                status = AE_NOT_FOUND;
        }
 
@@ -333,20 +324,18 @@ parse_dmar_table(void)
                return -ENODEV;
 
        if (dmar->width < PAGE_SHIFT - 1) {
-               printk(KERN_WARNING PREFIX "Invalid DMAR haw\n");
+               pr_warn("Invalid DMAR haw\n");
                return -EINVAL;
        }
 
-       printk (KERN_INFO PREFIX "Host address width %d\n",
-               dmar->width + 1);
+       pr_info("Host address width %d\n", dmar->width + 1);
 
        entry_header = (struct acpi_dmar_header *)(dmar + 1);
        while (((unsigned long)entry_header) <
                        (((unsigned long)dmar) + dmar_tbl->length)) {
                /* Avoid looping forever on bad ACPI tables */
                if (entry_header->length == 0) {
-                       printk(KERN_WARNING PREFIX
-                               "Invalid 0-length structure\n");
+                       pr_warn("Invalid 0-length structure\n");
                        ret = -EINVAL;
                        break;
                }
@@ -369,8 +358,7 @@ parse_dmar_table(void)
 #endif
                        break;
                default:
-                       printk(KERN_WARNING PREFIX
-                               "Unknown DMAR structure type %d\n",
+                       pr_warn("Unknown DMAR structure type %d\n",
                                entry_header->type);
                        ret = 0; /* for forward compatibility */
                        break;
@@ -469,12 +457,12 @@ int __init dmar_table_init(void)
        ret = parse_dmar_table();
        if (ret) {
                if (ret != -ENODEV)
-                       printk(KERN_INFO PREFIX "parse DMAR table failure.\n");
+                       pr_info("parse DMAR table failure.\n");
                return ret;
        }
 
        if (list_empty(&dmar_drhd_units)) {
-               printk(KERN_INFO PREFIX "No DMAR devices found\n");
+               pr_info("No DMAR devices found\n");
                return -ENODEV;
        }
 
@@ -506,8 +494,7 @@ int __init check_zero_address(void)
                        (((unsigned long)dmar) + dmar_tbl->length)) {
                /* Avoid looping forever on bad ACPI tables */
                if (entry_header->length == 0) {
-                       printk(KERN_WARNING PREFIX
-                               "Invalid 0-length structure\n");
+                       pr_warn("Invalid 0-length structure\n");
                        return 0;
                }
 
@@ -558,8 +545,7 @@ int __init detect_intel_iommu(void)
 
                if (ret && irq_remapping_enabled && cpu_has_x2apic &&
                    dmar->flags & 0x1)
-                       printk(KERN_INFO
-                              "Queued invalidation will be enabled to support x2apic and Intr-remapping.\n");
+                       pr_info("Queued invalidation will be enabled to support x2apic and Intr-remapping.\n");
 
                if (ret && !no_iommu && !iommu_detected && !dmar_disabled) {
                        iommu_detected = 1;
@@ -579,14 +565,89 @@ int __init detect_intel_iommu(void)
 }
 
 
+static void unmap_iommu(struct intel_iommu *iommu)
+{
+       iounmap(iommu->reg);
+       release_mem_region(iommu->reg_phys, iommu->reg_size);
+}
+
+/**
+ * map_iommu: map the iommu's registers
+ * @iommu: the iommu to map
+ * @phys_addr: the physical address of the base resgister
+ *
+ * Memory map the iommu's registers.  Start w/ a single page, and
+ * possibly expand if that turns out to be insufficent.
+ */
+static int map_iommu(struct intel_iommu *iommu, u64 phys_addr)
+{
+       int map_size, err=0;
+
+       iommu->reg_phys = phys_addr;
+       iommu->reg_size = VTD_PAGE_SIZE;
+
+       if (!request_mem_region(iommu->reg_phys, iommu->reg_size, iommu->name)) {
+               pr_err("IOMMU: can't reserve memory\n");
+               err = -EBUSY;
+               goto out;
+       }
+
+       iommu->reg = ioremap(iommu->reg_phys, iommu->reg_size);
+       if (!iommu->reg) {
+               pr_err("IOMMU: can't map the region\n");
+               err = -ENOMEM;
+               goto release;
+       }
+
+       iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
+       iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
+
+       if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
+               err = -EINVAL;
+               warn_invalid_dmar(phys_addr, " returns all ones");
+               goto unmap;
+       }
+
+       /* the registers might be more than one page */
+       map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
+                        cap_max_fault_reg_offset(iommu->cap));
+       map_size = VTD_PAGE_ALIGN(map_size);
+       if (map_size > iommu->reg_size) {
+               iounmap(iommu->reg);
+               release_mem_region(iommu->reg_phys, iommu->reg_size);
+               iommu->reg_size = map_size;
+               if (!request_mem_region(iommu->reg_phys, iommu->reg_size,
+                                       iommu->name)) {
+                       pr_err("IOMMU: can't reserve memory\n");
+                       err = -EBUSY;
+                       goto out;
+               }
+               iommu->reg = ioremap(iommu->reg_phys, iommu->reg_size);
+               if (!iommu->reg) {
+                       pr_err("IOMMU: can't map the region\n");
+                       err = -ENOMEM;
+                       goto release;
+               }
+       }
+       err = 0;
+       goto out;
+
+unmap:
+       iounmap(iommu->reg);
+release:
+       release_mem_region(iommu->reg_phys, iommu->reg_size);
+out:
+       return err;
+}
+
 int alloc_iommu(struct dmar_drhd_unit *drhd)
 {
        struct intel_iommu *iommu;
-       int map_size;
        u32 ver;
        static int iommu_allocated = 0;
        int agaw = 0;
        int msagaw = 0;
+       int err;
 
        if (!drhd->reg_base_addr) {
                warn_invalid_dmar(0, "");
@@ -600,30 +661,22 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
        iommu->seq_id = iommu_allocated++;
        sprintf (iommu->name, "dmar%d", iommu->seq_id);
 
-       iommu->reg = ioremap(drhd->reg_base_addr, VTD_PAGE_SIZE);
-       if (!iommu->reg) {
-               printk(KERN_ERR "IOMMU: can't map the region\n");
+       err = map_iommu(iommu, drhd->reg_base_addr);
+       if (err) {
+               pr_err("IOMMU: failed to map %s\n", iommu->name);
                goto error;
        }
-       iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG);
-       iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG);
-
-       if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) {
-               warn_invalid_dmar(drhd->reg_base_addr, " returns all ones");
-               goto err_unmap;
-       }
 
+       err = -EINVAL;
        agaw = iommu_calculate_agaw(iommu);
        if (agaw < 0) {
-               printk(KERN_ERR
-                      "Cannot get a valid agaw for iommu (seq_id = %d)\n",
-                      iommu->seq_id);
+               pr_err("Cannot get a valid agaw for iommu (seq_id = %d)\n",
+                       iommu->seq_id);
                goto err_unmap;
        }
        msagaw = iommu_calculate_max_sagaw(iommu);
        if (msagaw < 0) {
-               printk(KERN_ERR
-                       "Cannot get a valid max agaw for iommu (seq_id = %d)\n",
+               pr_err("Cannot get a valid max agaw for iommu (seq_id = %d)\n",
                        iommu->seq_id);
                goto err_unmap;
        }
@@ -632,19 +685,6 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
 
        iommu->node = -1;
 
-       /* the registers might be more than one page */
-       map_size = max_t(int, ecap_max_iotlb_offset(iommu->ecap),
-               cap_max_fault_reg_offset(iommu->cap));
-       map_size = VTD_PAGE_ALIGN(map_size);
-       if (map_size > VTD_PAGE_SIZE) {
-               iounmap(iommu->reg);
-               iommu->reg = ioremap(drhd->reg_base_addr, map_size);
-               if (!iommu->reg) {
-                       printk(KERN_ERR "IOMMU: can't map the region\n");
-                       goto error;
-               }
-       }
-
        ver = readl(iommu->reg + DMAR_VER_REG);
        pr_info("IOMMU %d: reg_base_addr %llx ver %d:%d cap %llx ecap %llx\n",
                iommu->seq_id,
@@ -659,10 +699,10 @@ int alloc_iommu(struct dmar_drhd_unit *drhd)
        return 0;
 
  err_unmap:
-       iounmap(iommu->reg);
+       unmap_iommu(iommu);
  error:
        kfree(iommu);
-       return -1;
+       return err;
 }
 
 void free_iommu(struct intel_iommu *iommu)
@@ -673,7 +713,8 @@ void free_iommu(struct intel_iommu *iommu)
        free_dmar_iommu(iommu);
 
        if (iommu->reg)
-               iounmap(iommu->reg);
+               unmap_iommu(iommu);
+
        kfree(iommu);
 }
 
@@ -710,7 +751,7 @@ static int qi_check_fault(struct intel_iommu *iommu, int index)
        if (fault & DMA_FSTS_IQE) {
                head = readl(iommu->reg + DMAR_IQH_REG);
                if ((head >> DMAR_IQ_SHIFT) == index) {
-                       printk(KERN_ERR "VT-d detected invalid descriptor: "
+                       pr_err("VT-d detected invalid descriptor: "
                                "low=%llx, high=%llx\n",
                                (unsigned long long)qi->desc[index].low,
                                (unsigned long long)qi->desc[index].high);
@@ -1129,15 +1170,14 @@ static int dmar_fault_do_one(struct intel_iommu *iommu, int type,
        reason = dmar_get_fault_reason(fault_reason, &fault_type);
 
        if (fault_type == INTR_REMAP)
-               printk(KERN_ERR "INTR-REMAP: Request device [[%02x:%02x.%d] "
+               pr_err("INTR-REMAP: Request device [[%02x:%02x.%d] "
                       "fault index %llx\n"
                        "INTR-REMAP:[fault reason %02d] %s\n",
                        (source_id >> 8), PCI_SLOT(source_id & 0xFF),
                        PCI_FUNC(source_id & 0xFF), addr >> 48,
                        fault_reason, reason);
        else
-               printk(KERN_ERR
-                      "DMAR:[%s] Request device [%02x:%02x.%d] "
+               pr_err("DMAR:[%s] Request device [%02x:%02x.%d] "
                       "fault addr %llx \n"
                       "DMAR:[fault reason %02d] %s\n",
                       (type ? "DMA Read" : "DMA Write"),
@@ -1157,8 +1197,7 @@ irqreturn_t dmar_fault(int irq, void *dev_id)
        raw_spin_lock_irqsave(&iommu->register_lock, flag);
        fault_status = readl(iommu->reg + DMAR_FSTS_REG);
        if (fault_status)
-               printk(KERN_ERR "DRHD: handling fault status reg %x\n",
-                      fault_status);
+               pr_err("DRHD: handling fault status reg %x\n", fault_status);
 
        /* TBD: ignore advanced fault log currently */
        if (!(fault_status & DMA_FSTS_PPF))
@@ -1224,7 +1263,7 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
 
        irq = create_irq();
        if (!irq) {
-               printk(KERN_ERR "IOMMU: no free vectors\n");
+               pr_err("IOMMU: no free vectors\n");
                return -EINVAL;
        }
 
@@ -1241,7 +1280,7 @@ int dmar_set_interrupt(struct intel_iommu *iommu)
 
        ret = request_irq(irq, dmar_fault, IRQF_NO_THREAD, iommu->name, iommu);
        if (ret)
-               printk(KERN_ERR "IOMMU: can't request irq\n");
+               pr_err("IOMMU: can't request irq\n");
        return ret;
 }
 
@@ -1258,8 +1297,7 @@ int __init enable_drhd_fault_handling(void)
                ret = dmar_set_interrupt(iommu);
 
                if (ret) {
-                       printk(KERN_ERR "DRHD %Lx: failed to enable fault, "
-                              " interrupt, ret %d\n",
+                       pr_err("DRHD %Lx: failed to enable fault, interrupt, ret %d\n",
                               (unsigned long long)drhd->reg_base_addr, ret);
                        return -1;
                }
index 6d347064b8b0f1a097958907cb402596acdbe0b9..e0b18f3ae9a862a22a8bc2ebe2eccc224c456252 100644 (file)
@@ -902,7 +902,6 @@ static int intel_setup_ioapic_entry(int irq,
        return 0;
 }
 
-#ifdef CONFIG_SMP
 /*
  * Migrate the IO-APIC irq in the presence of intr-remapping.
  *
@@ -924,6 +923,10 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
        struct irq_cfg *cfg = data->chip_data;
        unsigned int dest, irq = data->irq;
        struct irte irte;
+       int err;
+
+       if (!config_enabled(CONFIG_SMP))
+               return -EINVAL;
 
        if (!cpumask_intersects(mask, cpu_online_mask))
                return -EINVAL;
@@ -931,10 +934,16 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
        if (get_irte(irq, &irte))
                return -EBUSY;
 
-       if (assign_irq_vector(irq, cfg, mask))
-               return -EBUSY;
+       err = assign_irq_vector(irq, cfg, mask);
+       if (err)
+               return err;
 
-       dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
+       err = apic->cpu_mask_to_apicid_and(cfg->domain, mask, &dest);
+       if (err) {
+               if (assign_irq_vector(irq, cfg, data->affinity))
+                       pr_err("Failed to recover vector for irq %d\n", irq);
+               return err;
+       }
 
        irte.vector = cfg->vector;
        irte.dest_id = IRTE_DEST(dest);
@@ -956,7 +965,6 @@ intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
        cpumask_copy(data->affinity, mask);
        return 0;
 }
-#endif
 
 static void intel_compose_msi_msg(struct pci_dev *pdev,
                                  unsigned int irq, unsigned int dest,
@@ -1058,9 +1066,7 @@ struct irq_remap_ops intel_irq_remap_ops = {
        .reenable               = reenable_irq_remapping,
        .enable_faulting        = enable_drhd_fault_handling,
        .setup_ioapic_entry     = intel_setup_ioapic_entry,
-#ifdef CONFIG_SMP
        .set_affinity           = intel_ioapic_set_affinity,
-#endif
        .free_irq               = free_irte,
        .compose_msi_msg        = intel_compose_msi_msg,
        .msi_alloc_irq          = intel_msi_alloc_irq,
index 40cda8e98d8748a59fdd47b533445e0ba259e7a2..1d29b1c66e722b473e37c4849da76ca53c2a2121 100644 (file)
@@ -111,16 +111,15 @@ int setup_ioapic_remapped_entry(int irq,
                                             vector, attr);
 }
 
-#ifdef CONFIG_SMP
 int set_remapped_irq_affinity(struct irq_data *data, const struct cpumask *mask,
                              bool force)
 {
-       if (!remap_ops || !remap_ops->set_affinity)
+       if (!config_enabled(CONFIG_SMP) || !remap_ops ||
+           !remap_ops->set_affinity)
                return 0;
 
        return remap_ops->set_affinity(data, mask, force);
 }
-#endif
 
 void free_remapped_irq(int irq)
 {
index be9d72950c519d422f8114a0981d6e3594f5b5d7..b12974cc1dfe73be3b4366651c26382f1ef8ea23 100644 (file)
@@ -59,11 +59,9 @@ struct irq_remap_ops {
                                  unsigned int, int,
                                  struct io_apic_irq_attr *);
 
-#ifdef CONFIG_SMP
        /* Set the CPU affinity of a remapped interrupt */
        int (*set_affinity)(struct irq_data *data, const struct cpumask *mask,
                            bool force);
-#endif
 
        /* Free an IRQ */
        int (*free_irq)(int);
index d039de8322f0a314fca492df4b932289d9033e0d..b58b7a33914abd721e3508835a61afd699221dbf 100644 (file)
@@ -1084,6 +1084,7 @@ static int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        ti->split_io = dm_rh_get_region_size(ms->rh);
        ti->num_flush_requests = 1;
        ti->num_discard_requests = 1;
+       ti->discard_zeroes_data_unsupported = 1;
 
        ms->kmirrord_wq = alloc_workqueue("kmirrord",
                                          WQ_NON_REENTRANT | WQ_MEM_RECLAIM, 0);
@@ -1214,7 +1215,7 @@ static int mirror_end_io(struct dm_target *ti, struct bio *bio,
         * We need to dec pending if this was a write.
         */
        if (rw == WRITE) {
-               if (!(bio->bi_rw & REQ_FLUSH))
+               if (!(bio->bi_rw & (REQ_FLUSH | REQ_DISCARD)))
                        dm_rh_dec(ms->rh, map_context->ll);
                return error;
        }
index 7771ed2121820ac50c026f45e2f6c0a288ffba85..69732e03eb3490d636a0183bd22303742ab65c65 100644 (file)
@@ -404,6 +404,9 @@ void dm_rh_mark_nosync(struct dm_region_hash *rh, struct bio *bio)
                return;
        }
 
+       if (bio->bi_rw & REQ_DISCARD)
+               return;
+
        /* We must inform the log that the sync count has changed. */
        log->type->set_region_sync(log, region, 0);
 
@@ -524,7 +527,7 @@ void dm_rh_inc_pending(struct dm_region_hash *rh, struct bio_list *bios)
        struct bio *bio;
 
        for (bio = bios->head; bio; bio = bio->bi_next) {
-               if (bio->bi_rw & REQ_FLUSH)
+               if (bio->bi_rw & (REQ_FLUSH | REQ_DISCARD))
                        continue;
                rh_inc(rh, dm_rh_bio_to_region(rh, bio));
        }
index ce59824fb41401963113a17af05ac660954bbef2..68694da0d21d0566a61649339cb3a4f3a3bbc943 100644 (file)
@@ -1245,7 +1245,10 @@ static void process_discard(struct thin_c *tc, struct bio *bio)
 
                        cell_release_singleton(cell, bio);
                        cell_release_singleton(cell2, bio);
-                       remap_and_issue(tc, bio, lookup_result.block);
+                       if ((!lookup_result.shared) && pool->pf.discard_passdown)
+                               remap_and_issue(tc, bio, lookup_result.block);
+                       else
+                               bio_endio(bio, 0);
                }
                break;
 
@@ -2628,6 +2631,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
        if (tc->pool->pf.discard_enabled) {
                ti->discards_supported = 1;
                ti->num_discard_requests = 1;
+               ti->discard_zeroes_data_unsupported = 1;
        }
 
        dm_put(pool_md);
index 4296a8350298320a08a07ba2605e4ca67fbd250a..d2e6f82ecfac080cc951d1aa59014f58dbb35487 100644 (file)
@@ -43,6 +43,7 @@
 #include <asm/fiq.h>
 #include <mach/dma-mx1-mx2.h>
 #include <mach/hardware.h>
+#include <mach/irqs.h>
 #include <mach/mx1_camera.h>
 
 /*
index d7166afc255edf06ea7396b6efc12b91da92fca3..ca2754a3cd63d83eefb8927ae072f6732e852716 100644 (file)
@@ -172,8 +172,10 @@ struct zoran_jpg_settings {
        struct v4l2_jpegcompression jpg_comp;   /* JPEG-specific capture settings */
 };
 
+struct zoran_fh;
+
 struct zoran_mapping {
-       struct file *file;
+       struct zoran_fh *fh;
        int count;
 };
 
index c573109318108cac4ffea8d27488943ab3b7bac8..c6ccdeb6d8d6e50bb0db8c624c97e7b19ca9b7ac 100644 (file)
@@ -2811,7 +2811,7 @@ static void
 zoran_vm_close (struct vm_area_struct *vma)
 {
        struct zoran_mapping *map = vma->vm_private_data;
-       struct zoran_fh *fh = map->file->private_data;
+       struct zoran_fh *fh = map->fh;
        struct zoran *zr = fh->zr;
        int i;
 
@@ -2938,7 +2938,7 @@ zoran_mmap (struct file           *file,
                res = -ENOMEM;
                goto mmap_unlock_and_return;
        }
-       map->file = file;
+       map->fh = fh;
        map->count = 1;
 
        vma->vm_ops = &zoran_vm_ops;
index db194e433c085358b8d4716f062af3700bba1956..61c097a98f5de7eb45fd0ccb8fdc44dd53c869fa 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/slab.h>
 #include <linux/regmap.h>
 #include <linux/err.h>
+#include <linux/regulator/of_regulator.h>
 
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps65217.h>
@@ -132,6 +133,61 @@ int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg,
 }
 EXPORT_SYMBOL_GPL(tps65217_clear_bits);
 
+#ifdef CONFIG_OF
+static struct of_regulator_match reg_matches[] = {
+       { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 },
+       { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 },
+       { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 },
+       { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 },
+       { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 },
+       { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 },
+       { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 },
+};
+
+static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client)
+{
+       struct device_node *node = client->dev.of_node;
+       struct tps65217_board *pdata;
+       struct device_node *regs;
+       int count = ARRAY_SIZE(reg_matches);
+       int ret, i;
+
+       regs = of_find_node_by_name(node, "regulators");
+       if (!regs)
+               return NULL;
+
+       ret = of_regulator_match(&client->dev, regs, reg_matches, count);
+       of_node_put(regs);
+       if ((ret < 0) || (ret > count))
+               return NULL;
+
+       count = ret;
+       pdata = devm_kzalloc(&client->dev, count * sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return NULL;
+
+       for (i = 0; i < count; i++) {
+               if (!reg_matches[i].init_data || !reg_matches[i].of_node)
+                       continue;
+
+               pdata->tps65217_init_data[i] = reg_matches[i].init_data;
+               pdata->of_node[i] = reg_matches[i].of_node;
+       }
+
+       return pdata;
+}
+
+static struct of_device_id tps65217_of_match[] = {
+       { .compatible = "ti,tps65217", },
+       { },
+};
+#else
+static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client)
+{
+       return NULL;
+}
+#endif
+
 static struct regmap_config tps65217_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
@@ -141,10 +197,14 @@ static int __devinit tps65217_probe(struct i2c_client *client,
                                const struct i2c_device_id *ids)
 {
        struct tps65217 *tps;
+       struct regulator_init_data *reg_data;
        struct tps65217_board *pdata = client->dev.platform_data;
        int i, ret;
        unsigned int version;
 
+       if (!pdata && client->dev.of_node)
+               pdata = tps65217_parse_dt(client);
+
        tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
        if (!tps)
                return -ENOMEM;
@@ -182,8 +242,9 @@ static int __devinit tps65217_probe(struct i2c_client *client,
                }
 
                pdev->dev.parent = tps->dev;
-               platform_device_add_data(pdev, &pdata->tps65217_init_data[i],
-                                       sizeof(pdata->tps65217_init_data[i]));
+               pdev->dev.of_node = pdata->of_node[i];
+               reg_data = pdata->tps65217_init_data[i];
+               platform_device_add_data(pdev, reg_data, sizeof(*reg_data));
                tps->regulator_pdev[i] = pdev;
 
                platform_device_add(pdev);
@@ -212,6 +273,8 @@ MODULE_DEVICE_TABLE(i2c, tps65217_id_table);
 static struct i2c_driver tps65217_driver = {
        .driver         = {
                .name   = "tps65217",
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(tps65217_of_match),
        },
        .id_table       = tps65217_id_table,
        .probe          = tps65217_probe,
index 276d21ce6bc1ba6a18c844258331d6417f6278d7..f1c84decb192638e02aa13488e58c855d7335704 100644 (file)
@@ -850,9 +850,7 @@ out:
                goto retry;
        if (!err)
                mmc_blk_reset_success(md, type);
-       spin_lock_irq(&md->lock);
-       __blk_end_request(req, err, blk_rq_bytes(req));
-       spin_unlock_irq(&md->lock);
+       blk_end_request(req, err, blk_rq_bytes(req));
 
        return err ? 0 : 1;
 }
@@ -934,9 +932,7 @@ out_retry:
        if (!err)
                mmc_blk_reset_success(md, type);
 out:
-       spin_lock_irq(&md->lock);
-       __blk_end_request(req, err, blk_rq_bytes(req));
-       spin_unlock_irq(&md->lock);
+       blk_end_request(req, err, blk_rq_bytes(req));
 
        return err ? 0 : 1;
 }
@@ -951,9 +947,7 @@ static int mmc_blk_issue_flush(struct mmc_queue *mq, struct request *req)
        if (ret)
                ret = -EIO;
 
-       spin_lock_irq(&md->lock);
-       __blk_end_request_all(req, ret);
-       spin_unlock_irq(&md->lock);
+       blk_end_request_all(req, ret);
 
        return ret ? 0 : 1;
 }
@@ -1252,14 +1246,10 @@ static int mmc_blk_cmd_err(struct mmc_blk_data *md, struct mmc_card *card,
 
                blocks = mmc_sd_num_wr_blocks(card);
                if (blocks != (u32)-1) {
-                       spin_lock_irq(&md->lock);
-                       ret = __blk_end_request(req, 0, blocks << 9);
-                       spin_unlock_irq(&md->lock);
+                       ret = blk_end_request(req, 0, blocks << 9);
                }
        } else {
-               spin_lock_irq(&md->lock);
-               ret = __blk_end_request(req, 0, brq->data.bytes_xfered);
-               spin_unlock_irq(&md->lock);
+               ret = blk_end_request(req, 0, brq->data.bytes_xfered);
        }
        return ret;
 }
@@ -1311,10 +1301,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
                         * A block was successfully transferred.
                         */
                        mmc_blk_reset_success(md, type);
-                       spin_lock_irq(&md->lock);
-                       ret = __blk_end_request(req, 0,
+                       ret = blk_end_request(req, 0,
                                                brq->data.bytes_xfered);
-                       spin_unlock_irq(&md->lock);
                        /*
                         * If the blk_end_request function returns non-zero even
                         * though all data has been transferred and no errors
@@ -1364,10 +1352,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
                         * time, so we only reach here after trying to
                         * read a single sector.
                         */
-                       spin_lock_irq(&md->lock);
-                       ret = __blk_end_request(req, -EIO,
+                       ret = blk_end_request(req, -EIO,
                                                brq->data.blksz);
-                       spin_unlock_irq(&md->lock);
                        if (!ret)
                                goto start_new_req;
                        break;
@@ -1388,12 +1374,10 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
        return 1;
 
  cmd_abort:
-       spin_lock_irq(&md->lock);
        if (mmc_card_removed(card))
                req->cmd_flags |= REQ_QUIET;
        while (ret)
-               ret = __blk_end_request(req, -EIO, blk_rq_cur_bytes(req));
-       spin_unlock_irq(&md->lock);
+               ret = blk_end_request(req, -EIO, blk_rq_cur_bytes(req));
 
  start_new_req:
        if (rqc) {
@@ -1417,9 +1401,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
        ret = mmc_blk_part_switch(card, md);
        if (ret) {
                if (req) {
-                       spin_lock_irq(&md->lock);
-                       __blk_end_request_all(req, -EIO);
-                       spin_unlock_irq(&md->lock);
+                       blk_end_request_all(req, -EIO);
                }
                ret = 0;
                goto out;
index dca4428380f15c53adf73ce79810e7e26c0543f9..38ed210ce2f3b38475f3baf6e08f331e25a73675 100644 (file)
@@ -7,6 +7,6 @@ mmc_core-y                      := core.o bus.o host.o \
                                   mmc.o mmc_ops.o sd.o sd_ops.o \
                                   sdio.o sdio_ops.o sdio_bus.o \
                                   sdio_cis.o sdio_io.o sdio_irq.o \
-                                  quirks.o cd-gpio.o
+                                  quirks.o slot-gpio.o
 
 mmc_core-$(CONFIG_DEBUG_FS)    += debugfs.o
diff --git a/drivers/mmc/core/cd-gpio.c b/drivers/mmc/core/cd-gpio.c
deleted file mode 100644 (file)
index 8f5dc08..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Generic GPIO card-detect helper
- *
- * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/err.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/jiffies.h>
-#include <linux/mmc/cd-gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-
-struct mmc_cd_gpio {
-       unsigned int gpio;
-       char label[0];
-};
-
-static irqreturn_t mmc_cd_gpio_irqt(int irq, void *dev_id)
-{
-       /* Schedule a card detection after a debounce timeout */
-       mmc_detect_change(dev_id, msecs_to_jiffies(100));
-       return IRQ_HANDLED;
-}
-
-int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio)
-{
-       size_t len = strlen(dev_name(host->parent)) + 4;
-       struct mmc_cd_gpio *cd;
-       int irq = gpio_to_irq(gpio);
-       int ret;
-
-       if (irq < 0)
-               return irq;
-
-       cd = kmalloc(sizeof(*cd) + len, GFP_KERNEL);
-       if (!cd)
-               return -ENOMEM;
-
-       snprintf(cd->label, len, "%s cd", dev_name(host->parent));
-
-       ret = gpio_request_one(gpio, GPIOF_DIR_IN, cd->label);
-       if (ret < 0)
-               goto egpioreq;
-
-       ret = request_threaded_irq(irq, NULL, mmc_cd_gpio_irqt,
-                                  IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING |
-                                  IRQF_ONESHOT, cd->label, host);
-       if (ret < 0)
-               goto eirqreq;
-
-       cd->gpio = gpio;
-       host->hotplug.irq = irq;
-       host->hotplug.handler_priv = cd;
-
-       return 0;
-
-eirqreq:
-       gpio_free(gpio);
-egpioreq:
-       kfree(cd);
-       return ret;
-}
-EXPORT_SYMBOL(mmc_cd_gpio_request);
-
-void mmc_cd_gpio_free(struct mmc_host *host)
-{
-       struct mmc_cd_gpio *cd = host->hotplug.handler_priv;
-
-       if (!cd)
-               return;
-
-       free_irq(host->hotplug.irq, host);
-       gpio_free(cd->gpio);
-       kfree(cd);
-}
-EXPORT_SYMBOL(mmc_cd_gpio_free);
index 0b6141d29dbd1d9a3f146f2bb1b9923be9e0ad84..8ac5246e2ab2bc85a6ba82ee0a0eab732130fdf6 100644 (file)
@@ -404,6 +404,7 @@ int mmc_interrupt_hpi(struct mmc_card *card)
 {
        int err;
        u32 status;
+       unsigned long prg_wait;
 
        BUG_ON(!card);
 
@@ -419,30 +420,38 @@ int mmc_interrupt_hpi(struct mmc_card *card)
                goto out;
        }
 
-       /*
-        * If the card status is in PRG-state, we can send the HPI command.
-        */
-       if (R1_CURRENT_STATE(status) == R1_STATE_PRG) {
-               do {
-                       /*
-                        * We don't know when the HPI command will finish
-                        * processing, so we need to resend HPI until out
-                        * of prg-state, and keep checking the card status
-                        * with SEND_STATUS.  If a timeout error occurs when
-                        * sending the HPI command, we are already out of
-                        * prg-state.
-                        */
-                       err = mmc_send_hpi_cmd(card, &status);
-                       if (err)
-                               pr_debug("%s: abort HPI (%d error)\n",
-                                        mmc_hostname(card->host), err);
+       switch (R1_CURRENT_STATE(status)) {
+       case R1_STATE_IDLE:
+       case R1_STATE_READY:
+       case R1_STATE_STBY:
+               /*
+                * In idle states, HPI is not needed and the caller
+                * can issue the next intended command immediately
+                */
+               goto out;
+       case R1_STATE_PRG:
+               break;
+       default:
+               /* In all other states, it's illegal to issue HPI */
+               pr_debug("%s: HPI cannot be sent. Card state=%d\n",
+                       mmc_hostname(card->host), R1_CURRENT_STATE(status));
+               err = -EINVAL;
+               goto out;
+       }
 
-                       err = mmc_send_status(card, &status);
-                       if (err)
-                               break;
-               } while (R1_CURRENT_STATE(status) == R1_STATE_PRG);
-       } else
-               pr_debug("%s: Left prg-state\n", mmc_hostname(card->host));
+       err = mmc_send_hpi_cmd(card, &status);
+       if (err)
+               goto out;
+
+       prg_wait = jiffies + msecs_to_jiffies(card->ext_csd.out_of_int_time);
+       do {
+               err = mmc_send_status(card, &status);
+
+               if (!err && R1_CURRENT_STATE(status) == R1_STATE_TRAN)
+                       break;
+               if (time_after(jiffies, prg_wait))
+                       err = -ETIMEDOUT;
+       } while (!err);
 
 out:
        mmc_release_host(card->host);
@@ -941,7 +950,7 @@ int mmc_regulator_get_ocrmask(struct regulator *supply)
 
        return result;
 }
-EXPORT_SYMBOL(mmc_regulator_get_ocrmask);
+EXPORT_SYMBOL_GPL(mmc_regulator_get_ocrmask);
 
 /**
  * mmc_regulator_set_ocr - set regulator to match host->ios voltage
@@ -1011,7 +1020,30 @@ int mmc_regulator_set_ocr(struct mmc_host *mmc,
                        "could not set regulator OCR (%d)\n", result);
        return result;
 }
-EXPORT_SYMBOL(mmc_regulator_set_ocr);
+EXPORT_SYMBOL_GPL(mmc_regulator_set_ocr);
+
+int mmc_regulator_get_supply(struct mmc_host *mmc)
+{
+       struct device *dev = mmc_dev(mmc);
+       struct regulator *supply;
+       int ret;
+
+       supply = devm_regulator_get(dev, "vmmc");
+       mmc->supply.vmmc = supply;
+       mmc->supply.vqmmc = devm_regulator_get(dev, "vqmmc");
+
+       if (IS_ERR(supply))
+               return PTR_ERR(supply);
+
+       ret = mmc_regulator_get_ocrmask(supply);
+       if (ret > 0)
+               mmc->ocr_avail = ret;
+       else
+               dev_warn(mmc_dev(mmc), "Failed getting OCR mask: %d\n", ret);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mmc_regulator_get_supply);
 
 #endif /* CONFIG_REGULATOR */
 
@@ -1180,6 +1212,9 @@ static void mmc_power_up(struct mmc_host *host)
        host->ios.timing = MMC_TIMING_LEGACY;
        mmc_set_ios(host);
 
+       /* Set signal voltage to 3.3V */
+       mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, false);
+
        /*
         * This delay should be sufficient to allow the power supply
         * to reach the minimum voltage.
@@ -1931,9 +1966,6 @@ static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq)
         */
        mmc_hw_reset_for_init(host);
 
-       /* Initialization should be done at 3.3 V I/O voltage. */
-       mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
        /*
         * sdio_reset sends CMD52 to reset card.  Since we do not know
         * if the card is being re-initialized, just send it.  CMD52
@@ -2075,6 +2107,7 @@ void mmc_rescan(struct work_struct *work)
 void mmc_start_host(struct mmc_host *host)
 {
        host->f_init = max(freqs[0], host->f_min);
+       host->rescan_disable = 0;
        mmc_power_up(host);
        mmc_detect_change(host, 0);
 }
@@ -2088,6 +2121,7 @@ void mmc_stop_host(struct mmc_host *host)
        spin_unlock_irqrestore(&host->lock, flags);
 #endif
 
+       host->rescan_disable = 1;
        cancel_delayed_work_sync(&host->detect);
        mmc_flush_scheduled_work();
 
index 91c84c7a1829e8693c4e9dc652758512df22b4d6..597f189b44278caa4edd682ef27b6c57066eb1f2 100644 (file)
@@ -32,6 +32,7 @@
 static void mmc_host_classdev_release(struct device *dev)
 {
        struct mmc_host *host = cls_dev_to_mmc_host(dev);
+       mutex_destroy(&host->slot.lock);
        kfree(host);
 }
 
@@ -312,6 +313,8 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
        if (!host)
                return NULL;
 
+       /* scanning will be enabled when we're ready */
+       host->rescan_disable = 1;
        spin_lock(&mmc_host_lock);
        err = idr_get_new(&mmc_host_idr, host, &host->index);
        spin_unlock(&mmc_host_lock);
@@ -327,6 +330,9 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
 
        mmc_host_clk_init(host);
 
+       mutex_init(&host->slot.lock);
+       host->slot.cd_irq = -EINVAL;
+
        spin_lock_init(&host->lock);
        init_waitqueue_head(&host->wq);
        INIT_DELAYED_WORK(&host->detect, mmc_rescan);
index 4f4489aa6baede795ae21c222e0aa9e99e7b5800..396b25891bb90b59083adeb85769971b6c3057b0 100644 (file)
@@ -818,9 +818,6 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr,
        if (!mmc_host_is_spi(host))
                mmc_set_bus_mode(host, MMC_BUSMODE_OPENDRAIN);
 
-       /* Initialization should be done at 3.3 V I/O voltage. */
-       mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
        /*
         * Since we're changing the OCR value, we seem to
         * need to tell some cards to go back to the idle
index 69370f494e054f7951d287bba8b1d570510dc33d..0ed2cc5f35b662dcded214fba101fa2f5a042c92 100644 (file)
@@ -569,7 +569,6 @@ int mmc_send_hpi_cmd(struct mmc_card *card, u32 *status)
 
        cmd.opcode = opcode;
        cmd.arg = card->rca << 16 | 1;
-       cmd.cmd_timeout_ms = card->ext_csd.out_of_int_time;
 
        err = mmc_wait_for_cmd(card->host, &cmd, 0);
        if (err) {
index b2b43f624b9edd13a8ad4d836ec2229636de2a9c..74972c241dff38751d5be3e0e653336e7e8892a5 100644 (file)
@@ -244,7 +244,7 @@ static int mmc_read_ssr(struct mmc_card *card)
         * bitfield positions accordingly.
         */
        au = UNSTUFF_BITS(ssr, 428 - 384, 4);
-       if (au > 0 || au <= 9) {
+       if (au > 0 && au <= 9) {
                card->ssr.au = 1 << (au + 4);
                es = UNSTUFF_BITS(ssr, 408 - 384, 16);
                et = UNSTUFF_BITS(ssr, 402 - 384, 6);
@@ -290,8 +290,12 @@ static int mmc_read_switch(struct mmc_card *card)
                return -ENOMEM;
        }
 
-       /* Find out the supported Bus Speed Modes. */
-       err = mmc_sd_switch(card, 0, 0, 1, status);
+       /*
+        * Find out the card's support bits with a mode 0 operation.
+        * The argument does not matter, as the support bits do not
+        * change with the arguments.
+        */
+       err = mmc_sd_switch(card, 0, 0, 0, status);
        if (err) {
                /*
                 * If the host or the card can't do the switch,
@@ -312,46 +316,8 @@ static int mmc_read_switch(struct mmc_card *card)
 
        if (card->scr.sda_spec3) {
                card->sw_caps.sd3_bus_mode = status[13];
-
-               /* Find out Driver Strengths supported by the card */
-               err = mmc_sd_switch(card, 0, 2, 1, status);
-               if (err) {
-                       /*
-                        * If the host or the card can't do the switch,
-                        * fail more gracefully.
-                        */
-                       if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
-                               goto out;
-
-                       pr_warning("%s: problem reading "
-                               "Driver Strength.\n",
-                               mmc_hostname(card->host));
-                       err = 0;
-
-                       goto out;
-               }
-
+               /* Driver Strengths supported by the card */
                card->sw_caps.sd3_drv_type = status[9];
-
-               /* Find out Current Limits supported by the card */
-               err = mmc_sd_switch(card, 0, 3, 1, status);
-               if (err) {
-                       /*
-                        * If the host or the card can't do the switch,
-                        * fail more gracefully.
-                        */
-                       if (err != -EINVAL && err != -ENOSYS && err != -EFAULT)
-                               goto out;
-
-                       pr_warning("%s: problem reading "
-                               "Current Limit.\n",
-                               mmc_hostname(card->host));
-                       err = 0;
-
-                       goto out;
-               }
-
-               card->sw_caps.sd3_curr_limit = status[7];
        }
 
 out:
@@ -551,60 +517,80 @@ static int sd_set_bus_speed_mode(struct mmc_card *card, u8 *status)
        return 0;
 }
 
+/* Get host's max current setting at its current voltage */
+static u32 sd_get_host_max_current(struct mmc_host *host)
+{
+       u32 voltage, max_current;
+
+       voltage = 1 << host->ios.vdd;
+       switch (voltage) {
+       case MMC_VDD_165_195:
+               max_current = host->max_current_180;
+               break;
+       case MMC_VDD_29_30:
+       case MMC_VDD_30_31:
+               max_current = host->max_current_300;
+               break;
+       case MMC_VDD_32_33:
+       case MMC_VDD_33_34:
+               max_current = host->max_current_330;
+               break;
+       default:
+               max_current = 0;
+       }
+
+       return max_current;
+}
+
 static int sd_set_current_limit(struct mmc_card *card, u8 *status)
 {
-       int current_limit = 0;
+       int current_limit = SD_SET_CURRENT_NO_CHANGE;
        int err;
+       u32 max_current;
 
        /*
         * Current limit switch is only defined for SDR50, SDR104, and DDR50
-        * bus speed modes. For other bus speed modes, we set the default
-        * current limit of 200mA.
+        * bus speed modes. For other bus speed modes, we do not change the
+        * current limit.
         */
-       if ((card->sd_bus_speed == UHS_SDR50_BUS_SPEED) ||
-           (card->sd_bus_speed == UHS_SDR104_BUS_SPEED) ||
-           (card->sd_bus_speed == UHS_DDR50_BUS_SPEED)) {
-               if (card->host->caps & MMC_CAP_MAX_CURRENT_800) {
-                       if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_800)
-                               current_limit = SD_SET_CURRENT_LIMIT_800;
-                       else if (card->sw_caps.sd3_curr_limit &
-                                       SD_MAX_CURRENT_600)
-                               current_limit = SD_SET_CURRENT_LIMIT_600;
-                       else if (card->sw_caps.sd3_curr_limit &
-                                       SD_MAX_CURRENT_400)
-                               current_limit = SD_SET_CURRENT_LIMIT_400;
-                       else if (card->sw_caps.sd3_curr_limit &
-                                       SD_MAX_CURRENT_200)
-                               current_limit = SD_SET_CURRENT_LIMIT_200;
-               } else if (card->host->caps & MMC_CAP_MAX_CURRENT_600) {
-                       if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_600)
-                               current_limit = SD_SET_CURRENT_LIMIT_600;
-                       else if (card->sw_caps.sd3_curr_limit &
-                                       SD_MAX_CURRENT_400)
-                               current_limit = SD_SET_CURRENT_LIMIT_400;
-                       else if (card->sw_caps.sd3_curr_limit &
-                                       SD_MAX_CURRENT_200)
-                               current_limit = SD_SET_CURRENT_LIMIT_200;
-               } else if (card->host->caps & MMC_CAP_MAX_CURRENT_400) {
-                       if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_400)
-                               current_limit = SD_SET_CURRENT_LIMIT_400;
-                       else if (card->sw_caps.sd3_curr_limit &
-                                       SD_MAX_CURRENT_200)
-                               current_limit = SD_SET_CURRENT_LIMIT_200;
-               } else if (card->host->caps & MMC_CAP_MAX_CURRENT_200) {
-                       if (card->sw_caps.sd3_curr_limit & SD_MAX_CURRENT_200)
-                               current_limit = SD_SET_CURRENT_LIMIT_200;
-               }
-       } else
+       if ((card->sd_bus_speed != UHS_SDR50_BUS_SPEED) &&
+           (card->sd_bus_speed != UHS_SDR104_BUS_SPEED) &&
+           (card->sd_bus_speed != UHS_DDR50_BUS_SPEED))
+               return 0;
+
+       /*
+        * Host has different current capabilities when operating at
+        * different voltages, so find out its max current first.
+        */
+       max_current = sd_get_host_max_current(card->host);
+
+       /*
+        * We only check host's capability here, if we set a limit that is
+        * higher than the card's maximum current, the card will be using its
+        * maximum current, e.g. if the card's maximum current is 300ma, and
+        * when we set current limit to 200ma, the card will draw 200ma, and
+        * when we set current limit to 400/600/800ma, the card will draw its
+        * maximum 300ma from the host.
+        */
+       if (max_current >= 800)
+               current_limit = SD_SET_CURRENT_LIMIT_800;
+       else if (max_current >= 600)
+               current_limit = SD_SET_CURRENT_LIMIT_600;
+       else if (max_current >= 400)
+               current_limit = SD_SET_CURRENT_LIMIT_400;
+       else if (max_current >= 200)
                current_limit = SD_SET_CURRENT_LIMIT_200;
 
-       err = mmc_sd_switch(card, 1, 3, current_limit, status);
-       if (err)
-               return err;
+       if (current_limit != SD_SET_CURRENT_NO_CHANGE) {
+               err = mmc_sd_switch(card, 1, 3, current_limit, status);
+               if (err)
+                       return err;
 
-       if (((status[15] >> 4) & 0x0F) != current_limit)
-               pr_warning("%s: Problem setting current limit!\n",
-                       mmc_hostname(card->host));
+               if (((status[15] >> 4) & 0x0F) != current_limit)
+                       pr_warning("%s: Problem setting current limit!\n",
+                               mmc_hostname(card->host));
+
+       }
 
        return 0;
 }
@@ -726,6 +712,7 @@ struct device_type sd_type = {
 int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
 {
        int err;
+       u32 max_current;
 
        /*
         * Since we're changing the OCR value, we seem to
@@ -753,9 +740,12 @@ int mmc_sd_get_cid(struct mmc_host *host, u32 ocr, u32 *cid, u32 *rocr)
            MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104 | MMC_CAP_UHS_DDR50))
                ocr |= SD_OCR_S18R;
 
-       /* If the host can supply more than 150mA, XPC should be set to 1. */
-       if (host->caps & (MMC_CAP_SET_XPC_330 | MMC_CAP_SET_XPC_300 |
-           MMC_CAP_SET_XPC_180))
+       /*
+        * If the host can supply more than 150mA at current voltage,
+        * XPC should be set to 1.
+        */
+       max_current = sd_get_host_max_current(host);
+       if (max_current > 150)
                ocr |= SD_OCR_XPC;
 
 try_again:
@@ -911,9 +901,6 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
        BUG_ON(!host);
        WARN_ON(!host->claimed);
 
-       /* The initialization should be done at 3.3 V I/O voltage. */
-       mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
        err = mmc_sd_get_cid(host, ocr, cid, &rocr);
        if (err)
                return err;
index 41c5fd8848f4d72c171d9e001b2171607e13eb83..d4619e2ec030bcf878dee7a0d43425046d52c2fe 100644 (file)
@@ -591,9 +591,6 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
         * Inform the card of the voltage
         */
        if (!powered_resume) {
-               /* The initialization should be done at 3.3 V I/O voltage. */
-               mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
                err = mmc_send_io_op_cond(host, host->ocr, &ocr);
                if (err)
                        goto err;
@@ -1006,10 +1003,6 @@ static int mmc_sdio_power_restore(struct mmc_host *host)
         * restore the correct voltage setting of the card.
         */
 
-       /* The initialization should be done at 3.3 V I/O voltage. */
-       if (!mmc_card_keep_power(host))
-               mmc_set_signal_voltage(host, MMC_SIGNAL_VOLTAGE_330, 0);
-
        sdio_reset(host);
        mmc_go_idle(host);
        mmc_send_if_cond(host, host->ocr_avail);
index f1c7ed8f4d85a2a58b41c7b44d7899f115edaa02..8e94e555b788d4bc56364c488f1af0894e4db50a 100644 (file)
@@ -313,7 +313,7 @@ static int sdio_read_cis(struct mmc_card *card, struct sdio_func *func)
 
                        if (ret == -ENOENT) {
                                /* warn about unknown tuples */
-                               pr_warning("%s: queuing unknown"
+                               pr_warn_ratelimited("%s: queuing unknown"
                                       " CIS tuple 0x%02x (%u bytes)\n",
                                       mmc_hostname(card->host),
                                       tpl_code, tpl_link);
diff --git a/drivers/mmc/core/slot-gpio.c b/drivers/mmc/core/slot-gpio.c
new file mode 100644 (file)
index 0000000..0582429
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Generic GPIO card-detect helper
+ *
+ * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/slot-gpio.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+struct mmc_gpio {
+       int ro_gpio;
+       int cd_gpio;
+       char *ro_label;
+       char cd_label[0];
+};
+
+static irqreturn_t mmc_gpio_cd_irqt(int irq, void *dev_id)
+{
+       /* Schedule a card detection after a debounce timeout */
+       mmc_detect_change(dev_id, msecs_to_jiffies(100));
+       return IRQ_HANDLED;
+}
+
+static int mmc_gpio_alloc(struct mmc_host *host)
+{
+       size_t len = strlen(dev_name(host->parent)) + 4;
+       struct mmc_gpio *ctx;
+
+       mutex_lock(&host->slot.lock);
+
+       ctx = host->slot.handler_priv;
+       if (!ctx) {
+               /*
+                * devm_kzalloc() can be called after device_initialize(), even
+                * before device_add(), i.e., between mmc_alloc_host() and
+                * mmc_add_host()
+                */
+               ctx = devm_kzalloc(&host->class_dev, sizeof(*ctx) + 2 * len,
+                                  GFP_KERNEL);
+               if (ctx) {
+                       ctx->ro_label = ctx->cd_label + len;
+                       snprintf(ctx->cd_label, len, "%s cd", dev_name(host->parent));
+                       snprintf(ctx->ro_label, len, "%s ro", dev_name(host->parent));
+                       ctx->cd_gpio = -EINVAL;
+                       ctx->ro_gpio = -EINVAL;
+                       host->slot.handler_priv = ctx;
+               }
+       }
+
+       mutex_unlock(&host->slot.lock);
+
+       return ctx ? 0 : -ENOMEM;
+}
+
+int mmc_gpio_get_ro(struct mmc_host *host)
+{
+       struct mmc_gpio *ctx = host->slot.handler_priv;
+
+       if (!ctx || !gpio_is_valid(ctx->ro_gpio))
+               return -ENOSYS;
+
+       return !gpio_get_value_cansleep(ctx->ro_gpio) ^
+               !!(host->caps2 & MMC_CAP2_RO_ACTIVE_HIGH);
+}
+EXPORT_SYMBOL(mmc_gpio_get_ro);
+
+int mmc_gpio_get_cd(struct mmc_host *host)
+{
+       struct mmc_gpio *ctx = host->slot.handler_priv;
+
+       if (!ctx || !gpio_is_valid(ctx->cd_gpio))
+               return -ENOSYS;
+
+       return !gpio_get_value_cansleep(ctx->cd_gpio) ^
+               !!(host->caps2 & MMC_CAP2_CD_ACTIVE_HIGH);
+}
+EXPORT_SYMBOL(mmc_gpio_get_cd);
+
+int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio)
+{
+       struct mmc_gpio *ctx;
+       int ret;
+
+       if (!gpio_is_valid(gpio))
+               return -EINVAL;
+
+       ret = mmc_gpio_alloc(host);
+       if (ret < 0)
+               return ret;
+
+       ctx = host->slot.handler_priv;
+
+       return gpio_request_one(gpio, GPIOF_DIR_IN, ctx->ro_label);
+}
+EXPORT_SYMBOL(mmc_gpio_request_ro);
+
+int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio)
+{
+       struct mmc_gpio *ctx;
+       int irq = gpio_to_irq(gpio);
+       int ret;
+
+       ret = mmc_gpio_alloc(host);
+       if (ret < 0)
+               return ret;
+
+       ctx = host->slot.handler_priv;
+
+       ret = gpio_request_one(gpio, GPIOF_DIR_IN, ctx->cd_label);
+       if (ret < 0)
+               /*
+                * don't bother freeing memory. It might still get used by other
+                * slot functions, in any case it will be freed, when the device
+                * is destroyed.
+                */
+               return ret;
+
+       /*
+        * Even if gpio_to_irq() returns a valid IRQ number, the platform might
+        * still prefer to poll, e.g., because that IRQ number is already used
+        * by another unit and cannot be shared.
+        */
+       if (irq >= 0 && host->caps & MMC_CAP_NEEDS_POLL)
+               irq = -EINVAL;
+
+       if (irq >= 0) {
+               ret = request_threaded_irq(irq, NULL, mmc_gpio_cd_irqt,
+                       IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+                       ctx->cd_label, host);
+               if (ret < 0)
+                       irq = ret;
+       }
+
+       host->slot.cd_irq = irq;
+
+       if (irq < 0)
+               host->caps |= MMC_CAP_NEEDS_POLL;
+
+       ctx->cd_gpio = gpio;
+
+       return 0;
+}
+EXPORT_SYMBOL(mmc_gpio_request_cd);
+
+void mmc_gpio_free_ro(struct mmc_host *host)
+{
+       struct mmc_gpio *ctx = host->slot.handler_priv;
+       int gpio;
+
+       if (!ctx || !gpio_is_valid(ctx->ro_gpio))
+               return;
+
+       gpio = ctx->ro_gpio;
+       ctx->ro_gpio = -EINVAL;
+
+       gpio_free(gpio);
+}
+EXPORT_SYMBOL(mmc_gpio_free_ro);
+
+void mmc_gpio_free_cd(struct mmc_host *host)
+{
+       struct mmc_gpio *ctx = host->slot.handler_priv;
+       int gpio;
+
+       if (!ctx || !gpio_is_valid(ctx->cd_gpio))
+               return;
+
+       if (host->slot.cd_irq >= 0) {
+               free_irq(host->slot.cd_irq, host);
+               host->slot.cd_irq = -EINVAL;
+       }
+
+       gpio = ctx->cd_gpio;
+       ctx->cd_gpio = -EINVAL;
+
+       gpio_free(gpio);
+}
+EXPORT_SYMBOL(mmc_gpio_free_cd);
index f2c115e064387715a3c2f2cf796c5ae8b70bddd0..322412cec4eeb8ca6970d2d12f37c7c83bbba42e 100644 (file)
@@ -391,11 +391,17 @@ static int atmci_regs_show(struct seq_file *s, void *v)
        clk_disable(host->mck);
        spin_unlock_bh(&host->lock);
 
-       seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n",
+       seq_printf(s, "MR:\t0x%08x%s%s ",
                        buf[ATMCI_MR / 4],
                        buf[ATMCI_MR / 4] & ATMCI_MR_RDPROOF ? " RDPROOF" : "",
-                       buf[ATMCI_MR / 4] & ATMCI_MR_WRPROOF ? " WRPROOF" : "",
-                       buf[ATMCI_MR / 4] & 0xff);
+                       buf[ATMCI_MR / 4] & ATMCI_MR_WRPROOF ? " WRPROOF" : "");
+       if (host->caps.has_odd_clk_div)
+               seq_printf(s, "{CLKDIV,CLKODD}=%u\n",
+                               ((buf[ATMCI_MR / 4] & 0xff) << 1)
+                               | ((buf[ATMCI_MR / 4] >> 16) & 1));
+       else
+               seq_printf(s, "CLKDIV=%u\n",
+                               (buf[ATMCI_MR / 4] & 0xff));
        seq_printf(s, "DTOR:\t0x%08x\n", buf[ATMCI_DTOR / 4]);
        seq_printf(s, "SDCR:\t0x%08x\n", buf[ATMCI_SDCR / 4]);
        seq_printf(s, "ARGR:\t0x%08x\n", buf[ATMCI_ARGR / 4]);
@@ -1685,7 +1691,6 @@ static void atmci_tasklet_func(unsigned long priv)
 
                        dev_dbg(&host->pdev->dev, "FSM: cmd ready\n");
                        host->cmd = NULL;
-                       host->data = NULL;
                        data->bytes_xfered = data->blocks * data->blksz;
                        data->error = 0;
                        atmci_command_complete(host, mrq->stop);
@@ -1699,6 +1704,7 @@ static void atmci_tasklet_func(unsigned long priv)
                                atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
                                state = STATE_WAITING_NOTBUSY;
                        }
+                       host->data = NULL;
                        break;
 
                case STATE_END_REQUEST:
index 1ca5e72ceb651e84544a8cc451698ea54de6aafd..72dc3cde646d063513f3a55fc8ba0ec74197261b 100644 (file)
@@ -405,11 +405,23 @@ static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len)
 static int dw_mci_idmac_init(struct dw_mci *host)
 {
        struct idmac_desc *p;
-       int i;
+       int i, dma_support;
 
        /* Number of descriptors in the ring buffer */
        host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc);
 
+       /* Check if Hardware Configuration Register has support for DMA */
+       dma_support = (mci_readl(host, HCON) >> 16) & 0x3;
+
+       if (!dma_support || dma_support > 2) {
+               dev_err(&host->dev,
+                       "Host Controller does not support IDMA Tx.\n");
+               host->dma_ops = NULL;
+               return -ENODEV;
+       }
+
+       dev_info(&host->dev, "Using internal DMA controller.\n");
+
        /* Forward link the descriptor list */
        for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++)
                p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1));
@@ -1876,7 +1888,6 @@ static void dw_mci_init_dma(struct dw_mci *host)
        /* Determine which DMA interface to use */
 #ifdef CONFIG_MMC_DW_IDMAC
        host->dma_ops = &dw_mci_idmac_ops;
-       dev_info(&host->dev, "Using internal DMA controller.\n");
 #endif
 
        if (!host->dma_ops)
@@ -2175,7 +2186,7 @@ int dw_mci_resume(struct dw_mci *host)
                return ret;
        }
 
-       if (host->dma_ops->init)
+       if (host->use_dma && host->dma_ops->init)
                host->dma_ops->init(host);
 
        /* Restore the old value at FIFOTH register */
index 277161d279b8048600e6b7333d05d9c022562886..a51f9309ffbb1e49947939fb60d6c6dcc8e3be93 100644 (file)
@@ -164,16 +164,23 @@ struct mxs_mmc_host {
        spinlock_t                      lock;
        int                             sdio_irq_en;
        int                             wp_gpio;
+       bool                            wp_inverted;
 };
 
 static int mxs_mmc_get_ro(struct mmc_host *mmc)
 {
        struct mxs_mmc_host *host = mmc_priv(mmc);
+       int ret;
 
        if (!gpio_is_valid(host->wp_gpio))
                return -EINVAL;
 
-       return gpio_get_value(host->wp_gpio);
+       ret = gpio_get_value(host->wp_gpio);
+
+       if (host->wp_inverted)
+               ret = !ret;
+
+       return ret;
 }
 
 static int mxs_mmc_get_cd(struct mmc_host *mmc)
@@ -707,6 +714,8 @@ static int mxs_mmc_probe(struct platform_device *pdev)
        struct pinctrl *pinctrl;
        int ret = 0, irq_err, irq_dma;
        dma_cap_mask_t mask;
+       struct regulator *reg_vmmc;
+       enum of_gpio_flags flags;
 
        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
@@ -747,6 +756,16 @@ static int mxs_mmc_probe(struct platform_device *pdev)
        host->mmc = mmc;
        host->sdio_irq_en = 0;
 
+       reg_vmmc = devm_regulator_get(&pdev->dev, "vmmc");
+       if (!IS_ERR(reg_vmmc)) {
+               ret = regulator_enable(reg_vmmc);
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "Failed to enable vmmc regulator: %d\n", ret);
+                       goto out_mmc_free;
+               }
+       }
+
        pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
        if (IS_ERR(pinctrl)) {
                ret = PTR_ERR(pinctrl);
@@ -785,7 +804,10 @@ static int mxs_mmc_probe(struct platform_device *pdev)
                        mmc->caps |= MMC_CAP_4_BIT_DATA;
                else if (bus_width == 8)
                        mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
-               host->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
+               host->wp_gpio = of_get_named_gpio_flags(np, "wp-gpios", 0,
+                                                       &flags);
+               if (flags & OF_GPIO_ACTIVE_LOW)
+                       host->wp_inverted = 1;
        } else {
                if (pdata->flags & SLOTF_8_BIT_CAPABLE)
                        mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
index 389a3eedfc24505de5034e7d842f6e5678e4bc25..bc28627af66b961372f0f38cc0bbe61d621cc99a 100644 (file)
@@ -1089,7 +1089,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)
        /* Disable the clocks */
        pm_runtime_put_sync(host->dev);
        if (host->dbclk)
-               clk_disable(host->dbclk);
+               clk_disable_unprepare(host->dbclk);
 
        /* Turn the power off */
        ret = mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
@@ -1100,7 +1100,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd)
                                               vdd);
        pm_runtime_get_sync(host->dev);
        if (host->dbclk)
-               clk_enable(host->dbclk);
+               clk_prepare_enable(host->dbclk);
 
        if (ret != 0)
                goto err;
@@ -1899,7 +1899,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
        if (IS_ERR(host->dbclk)) {
                dev_warn(mmc_dev(host->mmc), "Failed to get debounce clk\n");
                host->dbclk = NULL;
-       } else if (clk_enable(host->dbclk) != 0) {
+       } else if (clk_prepare_enable(host->dbclk) != 0) {
                dev_warn(mmc_dev(host->mmc), "Failed to enable debounce clk\n");
                clk_put(host->dbclk);
                host->dbclk = NULL;
@@ -1931,6 +1931,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
        res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
        if (!res) {
                dev_err(mmc_dev(host->mmc), "cannot get DMA TX channel\n");
+               ret = -ENXIO;
                goto err_irq;
        }
        host->dma_line_tx = res->start;
@@ -1938,6 +1939,7 @@ static int __devinit omap_hsmmc_probe(struct platform_device *pdev)
        res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
        if (!res) {
                dev_err(mmc_dev(host->mmc), "cannot get DMA RX channel\n");
+               ret = -ENXIO;
                goto err_irq;
        }
        host->dma_line_rx = res->start;
@@ -2023,7 +2025,7 @@ err_irq:
        pm_runtime_disable(host->dev);
        clk_put(host->fclk);
        if (host->dbclk) {
-               clk_disable(host->dbclk);
+               clk_disable_unprepare(host->dbclk);
                clk_put(host->dbclk);
        }
 err1:
@@ -2058,7 +2060,7 @@ static int __devexit omap_hsmmc_remove(struct platform_device *pdev)
        pm_runtime_disable(host->dev);
        clk_put(host->fclk);
        if (host->dbclk) {
-               clk_disable(host->dbclk);
+               clk_disable_unprepare(host->dbclk);
                clk_put(host->dbclk);
        }
 
@@ -2116,7 +2118,7 @@ static int omap_hsmmc_suspend(struct device *dev)
        }
 
        if (host->dbclk)
-               clk_disable(host->dbclk);
+               clk_disable_unprepare(host->dbclk);
 err:
        pm_runtime_put_sync(host->dev);
        return ret;
@@ -2137,7 +2139,7 @@ static int omap_hsmmc_resume(struct device *dev)
        pm_runtime_get_sync(host->dev);
 
        if (host->dbclk)
-               clk_enable(host->dbclk);
+               clk_prepare_enable(host->dbclk);
 
        if (!(host->mmc->pm_flags & MMC_PM_KEEP_POWER))
                omap_hsmmc_conf_bus_power(host);
index c3622a69f432b34e63f218ad1e003ea48bc69922..bd5a5cce122c7eb199a67cad4098175ff6a9b351 100644 (file)
@@ -26,7 +26,6 @@
 #include <mach/dma.h>
 
 #include <mach/regs-sdi.h>
-#include <mach/regs-gpio.h>
 
 #include <plat/mci.h>
 
@@ -1237,12 +1236,9 @@ static void s3cmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
        switch (ios->power_mode) {
        case MMC_POWER_ON:
        case MMC_POWER_UP:
-               s3c2410_gpio_cfgpin(S3C2410_GPE(5), S3C2410_GPE5_SDCLK);
-               s3c2410_gpio_cfgpin(S3C2410_GPE(6), S3C2410_GPE6_SDCMD);
-               s3c2410_gpio_cfgpin(S3C2410_GPE(7), S3C2410_GPE7_SDDAT0);
-               s3c2410_gpio_cfgpin(S3C2410_GPE(8), S3C2410_GPE8_SDDAT1);
-               s3c2410_gpio_cfgpin(S3C2410_GPE(9), S3C2410_GPE9_SDDAT2);
-               s3c2410_gpio_cfgpin(S3C2410_GPE(10), S3C2410_GPE10_SDDAT3);
+               /* Configure GPE5...GPE10 pins in SD mode */
+               s3c_gpio_cfgall_range(S3C2410_GPE(5), 6, S3C_GPIO_SFN(2),
+                                     S3C_GPIO_PULL_NONE);
 
                if (host->pdata->set_power)
                        host->pdata->set_power(ios->power_mode, ios->vdd);
index 177f697b5835529aa3a4079966229c751f7bc428..a6e53a1ebb0888639a49d75c72f562f45b48e4f1 100644 (file)
  */
 
 #include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
 #include <linux/module.h>
 #include <linux/mmc/host.h>
 
 #include "sdhci-pltfm.h"
 
+struct sdhci_dove_priv {
+       struct clk *clk;
+};
+
 static u16 sdhci_dove_readw(struct sdhci_host *host, int reg)
 {
        u16 ret;
@@ -66,16 +72,57 @@ static struct sdhci_pltfm_data sdhci_dove_pdata = {
        .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
                  SDHCI_QUIRK_NO_BUSY_IRQ |
                  SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
-                 SDHCI_QUIRK_FORCE_DMA,
+                 SDHCI_QUIRK_FORCE_DMA |
+                 SDHCI_QUIRK_NO_HISPD_BIT,
 };
 
 static int __devinit sdhci_dove_probe(struct platform_device *pdev)
 {
-       return sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
+       struct sdhci_host *host;
+       struct sdhci_pltfm_host *pltfm_host;
+       struct sdhci_dove_priv *priv;
+       int ret;
+
+       ret = sdhci_pltfm_register(pdev, &sdhci_dove_pdata);
+       if (ret)
+               goto sdhci_dove_register_fail;
+
+       priv = devm_kzalloc(&pdev->dev, sizeof(struct sdhci_dove_priv),
+                           GFP_KERNEL);
+       if (!priv) {
+               dev_err(&pdev->dev, "unable to allocate private data");
+               ret = -ENOMEM;
+               goto sdhci_dove_allocate_fail;
+       }
+
+       host = platform_get_drvdata(pdev);
+       pltfm_host = sdhci_priv(host);
+       pltfm_host->priv = priv;
+
+       priv->clk = clk_get(&pdev->dev, NULL);
+       if (!IS_ERR(priv->clk))
+               clk_prepare_enable(priv->clk);
+       return 0;
+
+sdhci_dove_allocate_fail:
+       sdhci_pltfm_unregister(pdev);
+sdhci_dove_register_fail:
+       return ret;
 }
 
 static int __devexit sdhci_dove_remove(struct platform_device *pdev)
 {
+       struct sdhci_host *host = platform_get_drvdata(pdev);
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct sdhci_dove_priv *priv = pltfm_host->priv;
+
+       if (priv->clk) {
+               if (!IS_ERR(priv->clk)) {
+                       clk_disable_unprepare(priv->clk);
+                       clk_put(priv->clk);
+               }
+               devm_kfree(&pdev->dev, priv->clk);
+       }
        return sdhci_pltfm_unregister(pdev);
 }
 
index ebbe984e5d002c5dfe98d7215309676a8a183789..e23f8134591c7f5a080f73ffcacbf6fccb63516e 100644 (file)
@@ -299,6 +299,8 @@ static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 
 static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
 {
+       struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+       struct pltfm_imx_data *imx_data = pltfm_host->priv;
        u32 new_val;
 
        switch (reg) {
@@ -315,8 +317,11 @@ static void esdhc_writeb_le(struct sdhci_host *host, u8 val, int reg)
                                SDHCI_CTRL_D3CD);
                /* ensure the endianess */
                new_val |= ESDHC_HOST_CONTROL_LE;
-               /* DMA mode bits are shifted */
-               new_val |= (val & SDHCI_CTRL_DMA_MASK) << 5;
+               /* bits 8&9 are reserved on mx25 */
+               if (!is_imx25_esdhc(imx_data)) {
+                       /* DMA mode bits are shifted */
+                       new_val |= (val & SDHCI_CTRL_DMA_MASK) << 5;
+               }
 
                esdhc_clrset_le(host, 0xffff, new_val, reg);
                return;
index 69ef0beae104f3a83d4a36277b129e20ba5db207..504da715a41ae30f3e5670ff305801167ee60935 100644 (file)
@@ -157,6 +157,7 @@ static const struct sdhci_pci_fixes sdhci_ene_714 = {
 static const struct sdhci_pci_fixes sdhci_cafe = {
        .quirks         = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
                          SDHCI_QUIRK_NO_BUSY_IRQ |
+                         SDHCI_QUIRK_BROKEN_CARD_DETECTION |
                          SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
 };
 
index dbb75bfbcffb3e181f6d0af195209e5187c3b210..b6ee8857e226fc163d53c1a66d52eda26121735d 100644 (file)
@@ -28,6 +28,9 @@
 #include <linux/mmc/host.h>
 #include <linux/platform_data/pxa_sdhci.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
 #include "sdhci.h"
 #include "sdhci-pltfm.h"
 
@@ -121,6 +124,48 @@ static struct sdhci_ops pxav2_sdhci_ops = {
        .platform_8bit_width = pxav2_mmc_set_width,
 };
 
+#ifdef CONFIG_OF
+static const struct of_device_id sdhci_pxav2_of_match[] = {
+       {
+               .compatible = "mrvl,pxav2-mmc",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, sdhci_pxav2_of_match);
+
+static struct sdhci_pxa_platdata *pxav2_get_mmc_pdata(struct device *dev)
+{
+       struct sdhci_pxa_platdata *pdata;
+       struct device_node *np = dev->of_node;
+       u32 bus_width;
+       u32 clk_delay_cycles;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return NULL;
+
+       if (of_find_property(np, "non-removable", NULL))
+               pdata->flags |= PXA_FLAG_CARD_PERMANENT;
+
+       of_property_read_u32(np, "bus-width", &bus_width);
+       if (bus_width == 8)
+               pdata->flags |= PXA_FLAG_SD_8_BIT_CAPABLE_SLOT;
+
+       of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles);
+       if (clk_delay_cycles > 0) {
+               pdata->clk_delay_sel = 1;
+               pdata->clk_delay_cycles = clk_delay_cycles;
+       }
+
+       return pdata;
+}
+#else
+static inline struct sdhci_pxa_platdata *pxav2_get_mmc_pdata(struct device *dev)
+{
+       return NULL;
+}
+#endif
+
 static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
 {
        struct sdhci_pltfm_host *pltfm_host;
@@ -128,6 +173,8 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct sdhci_host *host = NULL;
        struct sdhci_pxa *pxa = NULL;
+       const struct of_device_id *match;
+
        int ret;
        struct clk *clk;
 
@@ -156,6 +203,10 @@ static int __devinit sdhci_pxav2_probe(struct platform_device *pdev)
                | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL
                | SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN;
 
+       match = of_match_device(of_match_ptr(sdhci_pxav2_of_match), &pdev->dev);
+       if (match) {
+               pdata = pxav2_get_mmc_pdata(dev);
+       }
        if (pdata) {
                if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
                        /* on-chip device */
@@ -218,6 +269,9 @@ static struct platform_driver sdhci_pxav2_driver = {
        .driver         = {
                .name   = "sdhci-pxav2",
                .owner  = THIS_MODULE,
+#ifdef CONFIG_OF
+               .of_match_table = sdhci_pxav2_of_match,
+#endif
                .pm     = SDHCI_PLTFM_PMOPS,
        },
        .probe          = sdhci_pxav2_probe,
index f29695683556df8f7c01ad6f145a9fc36583e410..07fe3834fe0b224119d0591672de48949dd18105 100644 (file)
@@ -28,6 +28,9 @@
 #include <linux/slab.h>
 #include <linux/delay.h>
 #include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+
 #include "sdhci.h"
 #include "sdhci-pltfm.h"
 
@@ -164,6 +167,46 @@ static struct sdhci_ops pxav3_sdhci_ops = {
        .platform_send_init_74_clocks = pxav3_gen_init_74_clocks,
 };
 
+#ifdef CONFIG_OF
+static const struct of_device_id sdhci_pxav3_of_match[] = {
+       {
+               .compatible = "mrvl,pxav3-mmc",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, sdhci_pxav3_of_match);
+
+static struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
+{
+       struct sdhci_pxa_platdata *pdata;
+       struct device_node *np = dev->of_node;
+       u32 bus_width;
+       u32 clk_delay_cycles;
+
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return NULL;
+
+       if (of_find_property(np, "non-removable", NULL))
+               pdata->flags |= PXA_FLAG_CARD_PERMANENT;
+
+       of_property_read_u32(np, "bus-width", &bus_width);
+       if (bus_width == 8)
+               pdata->flags |= PXA_FLAG_SD_8_BIT_CAPABLE_SLOT;
+
+       of_property_read_u32(np, "mrvl,clk-delay-cycles", &clk_delay_cycles);
+       if (clk_delay_cycles > 0)
+               pdata->clk_delay_cycles = clk_delay_cycles;
+
+       return pdata;
+}
+#else
+static inline struct sdhci_pxa_platdata *pxav3_get_mmc_pdata(struct device *dev)
+{
+       return NULL;
+}
+#endif
+
 static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
 {
        struct sdhci_pltfm_host *pltfm_host;
@@ -171,6 +214,8 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct sdhci_host *host = NULL;
        struct sdhci_pxa *pxa = NULL;
+       const struct of_device_id *match;
+
        int ret;
        struct clk *clk;
 
@@ -202,6 +247,10 @@ static int __devinit sdhci_pxav3_probe(struct platform_device *pdev)
        /* enable 1/8V DDR capable */
        host->mmc->caps |= MMC_CAP_1_8V_DDR;
 
+       match = of_match_device(of_match_ptr(sdhci_pxav3_of_match), &pdev->dev);
+       if (match)
+               pdata = pxav3_get_mmc_pdata(dev);
+
        if (pdata) {
                if (pdata->flags & PXA_FLAG_CARD_PERMANENT) {
                        /* on-chip device */
@@ -263,6 +312,9 @@ static int __devexit sdhci_pxav3_remove(struct platform_device *pdev)
 static struct platform_driver sdhci_pxav3_driver = {
        .driver         = {
                .name   = "sdhci-pxav3",
+#ifdef CONFIG_OF
+               .of_match_table = sdhci_pxav3_of_match,
+#endif
                .owner  = THIS_MODULE,
                .pm     = SDHCI_PLTFM_PMOPS,
        },
index b38d8a78f6a033ad28c6b50d30309c2c48ff03c8..0810ccc23d7e8fb951fecf7b75774b2ae4e5984e 100644 (file)
@@ -223,6 +223,7 @@ static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(
 {
        struct tegra_sdhci_platform_data *plat;
        struct device_node *np = pdev->dev.of_node;
+       u32 bus_width;
 
        if (!np)
                return NULL;
@@ -236,7 +237,9 @@ static struct tegra_sdhci_platform_data * __devinit sdhci_tegra_dt_parse_pdata(
        plat->cd_gpio = of_get_named_gpio(np, "cd-gpios", 0);
        plat->wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
        plat->power_gpio = of_get_named_gpio(np, "power-gpios", 0);
-       if (of_find_property(np, "support-8bit", NULL))
+
+       if (of_property_read_u32(np, "bus-width", &bus_width) == 0 &&
+           bus_width == 8)
                plat->is_8bit = 1;
 
        return plat;
@@ -334,7 +337,7 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
                rc = PTR_ERR(clk);
                goto err_clk_get;
        }
-       clk_enable(clk);
+       clk_prepare_enable(clk);
        pltfm_host->clk = clk;
 
        host->mmc->pm_caps = plat->pm_flags;
@@ -349,7 +352,7 @@ static int __devinit sdhci_tegra_probe(struct platform_device *pdev)
        return 0;
 
 err_add_host:
-       clk_disable(pltfm_host->clk);
+       clk_disable_unprepare(pltfm_host->clk);
        clk_put(pltfm_host->clk);
 err_clk_get:
        if (gpio_is_valid(plat->wp_gpio))
@@ -390,7 +393,7 @@ static int __devexit sdhci_tegra_remove(struct platform_device *pdev)
        if (gpio_is_valid(plat->power_gpio))
                gpio_free(plat->power_gpio);
 
-       clk_disable(pltfm_host->clk);
+       clk_disable_unprepare(pltfm_host->clk);
        clk_put(pltfm_host->clk);
 
        sdhci_pltfm_free(pdev);
index f4b8b4db3a9acd8ccc1c3fdf32c18efc2a8bc88d..9a11dc39921c06ebdf67a3ed602fbba79cc38b89 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
 
 #include "sdhci.h"
 
@@ -244,6 +245,19 @@ static void sdhci_init(struct sdhci_host *host, int soft)
 static void sdhci_reinit(struct sdhci_host *host)
 {
        sdhci_init(host, 0);
+       /*
+        * Retuning stuffs are affected by different cards inserted and only
+        * applicable to UHS-I cards. So reset these fields to their initial
+        * value when card is removed.
+        */
+       if (host->flags & SDHCI_USING_RETUNING_TIMER) {
+               host->flags &= ~SDHCI_USING_RETUNING_TIMER;
+
+               del_timer_sync(&host->tuning_timer);
+               host->flags &= ~SDHCI_NEEDS_RETUNING;
+               host->mmc->max_blk_count =
+                       (host->quirks & SDHCI_QUIRK_NO_MULTIBLOCK) ? 1 : 65535;
+       }
        sdhci_enable_card_detection(host);
 }
 
@@ -1245,6 +1259,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
        struct sdhci_host *host;
        bool present;
        unsigned long flags;
+       u32 tuning_opcode;
 
        host = mmc_priv(mmc);
 
@@ -1292,8 +1307,12 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
                 */
                if ((host->flags & SDHCI_NEEDS_RETUNING) &&
                    !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) {
+                       /* eMMC uses cmd21 while sd and sdio use cmd19 */
+                       tuning_opcode = mmc->card->type == MMC_TYPE_MMC ?
+                               MMC_SEND_TUNING_BLOCK_HS200 :
+                               MMC_SEND_TUNING_BLOCK;
                        spin_unlock_irqrestore(&host->lock, flags);
-                       sdhci_execute_tuning(mmc, mrq->cmd->opcode);
+                       sdhci_execute_tuning(mmc, tuning_opcode);
                        spin_lock_irqsave(&host->lock, flags);
 
                        /* Restore original mmc_request structure */
@@ -1663,11 +1682,15 @@ static int sdhci_do_start_signal_voltage_switch(struct sdhci_host *host,
                pwr = sdhci_readb(host, SDHCI_POWER_CONTROL);
                pwr &= ~SDHCI_POWER_ON;
                sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+               if (host->vmmc)
+                       regulator_disable(host->vmmc);
 
                /* Wait for 1ms as per the spec */
                usleep_range(1000, 1500);
                pwr |= SDHCI_POWER_ON;
                sdhci_writeb(host, pwr, SDHCI_POWER_CONTROL);
+               if (host->vmmc)
+                       regulator_enable(host->vmmc);
 
                pr_info(DRIVER_NAME ": Switching to 1.8V signalling "
                        "voltage failed, retrying with S18R set to 0\n");
@@ -1855,6 +1878,7 @@ out:
         */
        if (!(host->flags & SDHCI_NEEDS_RETUNING) && host->tuning_count &&
            (host->tuning_mode == SDHCI_TUNING_MODE_1)) {
+               host->flags |= SDHCI_USING_RETUNING_TIMER;
                mod_timer(&host->tuning_timer, jiffies +
                        host->tuning_count * HZ);
                /* Tuning mode 1 limits the maximum data length to 4MB */
@@ -1872,10 +1896,10 @@ out:
         * try tuning again at a later time, when the re-tuning timer expires.
         * So for these controllers, we return 0. Since there might be other
         * controllers who do not have this capability, we return error for
-        * them.
+        * them. SDHCI_USING_RETUNING_TIMER means the host is currently using
+        * a retuning timer to do the retuning for the card.
         */
-       if (err && host->tuning_count &&
-           host->tuning_mode == SDHCI_TUNING_MODE_1)
+       if (err && (host->flags & SDHCI_USING_RETUNING_TIMER))
                err = 0;
 
        sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier);
@@ -2382,7 +2406,6 @@ out:
 int sdhci_suspend_host(struct sdhci_host *host)
 {
        int ret;
-       bool has_tuning_timer;
 
        if (host->ops->platform_suspend)
                host->ops->platform_suspend(host);
@@ -2390,16 +2413,14 @@ int sdhci_suspend_host(struct sdhci_host *host)
        sdhci_disable_card_detection(host);
 
        /* Disable tuning since we are suspending */
-       has_tuning_timer = host->version >= SDHCI_SPEC_300 &&
-               host->tuning_count && host->tuning_mode == SDHCI_TUNING_MODE_1;
-       if (has_tuning_timer) {
+       if (host->flags & SDHCI_USING_RETUNING_TIMER) {
                del_timer_sync(&host->tuning_timer);
                host->flags &= ~SDHCI_NEEDS_RETUNING;
        }
 
        ret = mmc_suspend_host(host->mmc);
        if (ret) {
-               if (has_tuning_timer) {
+               if (host->flags & SDHCI_USING_RETUNING_TIMER) {
                        host->flags |= SDHCI_NEEDS_RETUNING;
                        mod_timer(&host->tuning_timer, jiffies +
                                        host->tuning_count * HZ);
@@ -2450,8 +2471,7 @@ int sdhci_resume_host(struct sdhci_host *host)
                host->ops->platform_resume(host);
 
        /* Set the re-tuning expiration flag */
-       if ((host->version >= SDHCI_SPEC_300) && host->tuning_count &&
-           (host->tuning_mode == SDHCI_TUNING_MODE_1))
+       if (host->flags & SDHCI_USING_RETUNING_TIMER)
                host->flags |= SDHCI_NEEDS_RETUNING;
 
        return ret;
@@ -2490,8 +2510,7 @@ int sdhci_runtime_suspend_host(struct sdhci_host *host)
        int ret = 0;
 
        /* Disable tuning since we are suspending */
-       if (host->version >= SDHCI_SPEC_300 &&
-           host->tuning_mode == SDHCI_TUNING_MODE_1) {
+       if (host->flags & SDHCI_USING_RETUNING_TIMER) {
                del_timer_sync(&host->tuning_timer);
                host->flags &= ~SDHCI_NEEDS_RETUNING;
        }
@@ -2532,8 +2551,7 @@ int sdhci_runtime_resume_host(struct sdhci_host *host)
                sdhci_do_enable_preset_value(host, true);
 
        /* Set the re-tuning expiration flag */
-       if ((host->version >= SDHCI_SPEC_300) && host->tuning_count &&
-           (host->tuning_mode == SDHCI_TUNING_MODE_1))
+       if (host->flags & SDHCI_USING_RETUNING_TIMER)
                host->flags |= SDHCI_NEEDS_RETUNING;
 
        spin_lock_irqsave(&host->lock, flags);
@@ -2584,7 +2602,7 @@ EXPORT_SYMBOL_GPL(sdhci_alloc_host);
 int sdhci_add_host(struct sdhci_host *host)
 {
        struct mmc_host *mmc;
-       u32 caps[2];
+       u32 caps[2] = {0, 0};
        u32 max_current_caps;
        unsigned int ocr_avail;
        int ret;
@@ -2614,8 +2632,10 @@ int sdhci_add_host(struct sdhci_host *host)
        caps[0] = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ? host->caps :
                sdhci_readl(host, SDHCI_CAPABILITIES);
 
-       caps[1] = (host->version >= SDHCI_SPEC_300) ?
-               sdhci_readl(host, SDHCI_CAPABILITIES_1) : 0;
+       if (host->version >= SDHCI_SPEC_300)
+               caps[1] = (host->quirks & SDHCI_QUIRK_MISSING_CAPS) ?
+                       host->caps1 :
+                       sdhci_readl(host, SDHCI_CAPABILITIES_1);
 
        if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
                host->flags |= SDHCI_USE_SDMA;
@@ -2779,7 +2799,7 @@ int sdhci_add_host(struct sdhci_host *host)
                mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
 
        if ((host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION) &&
-           mmc_card_is_removable(mmc))
+           !(host->mmc->caps & MMC_CAP_NONREMOVABLE))
                mmc->caps |= MMC_CAP_NEEDS_POLL;
 
        /* Any UHS-I mode in caps implies SDR12 and SDR25 support. */
@@ -2837,6 +2857,30 @@ int sdhci_add_host(struct sdhci_host *host)
                             SDHCI_RETUNING_MODE_SHIFT;
 
        ocr_avail = 0;
+
+       host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
+       if (IS_ERR(host->vmmc)) {
+               pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
+               host->vmmc = NULL;
+       }
+
+#ifdef CONFIG_REGULATOR
+       if (host->vmmc) {
+               ret = regulator_is_supported_voltage(host->vmmc, 3300000,
+                       3300000);
+               if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_330)))
+                       caps[0] &= ~SDHCI_CAN_VDD_330;
+               ret = regulator_is_supported_voltage(host->vmmc, 3000000,
+                       3000000);
+               if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_300)))
+                       caps[0] &= ~SDHCI_CAN_VDD_300;
+               ret = regulator_is_supported_voltage(host->vmmc, 1800000,
+                       1800000);
+               if ((ret <= 0) || (!(caps[0] & SDHCI_CAN_VDD_180)))
+                       caps[0] &= ~SDHCI_CAN_VDD_180;
+       }
+#endif /* CONFIG_REGULATOR */
+
        /*
         * According to SD Host Controller spec v3.00, if the Host System
         * can afford more than 150mA, Host Driver should set XPC to 1. Also
@@ -2845,55 +2889,45 @@ int sdhci_add_host(struct sdhci_host *host)
         * value.
         */
        max_current_caps = sdhci_readl(host, SDHCI_MAX_CURRENT);
+       if (!max_current_caps && host->vmmc) {
+               u32 curr = regulator_get_current_limit(host->vmmc);
+               if (curr > 0) {
+
+                       /* convert to SDHCI_MAX_CURRENT format */
+                       curr = curr/1000;  /* convert to mA */
+                       curr = curr/SDHCI_MAX_CURRENT_MULTIPLIER;
+
+                       curr = min_t(u32, curr, SDHCI_MAX_CURRENT_LIMIT);
+                       max_current_caps =
+                               (curr << SDHCI_MAX_CURRENT_330_SHIFT) |
+                               (curr << SDHCI_MAX_CURRENT_300_SHIFT) |
+                               (curr << SDHCI_MAX_CURRENT_180_SHIFT);
+               }
+       }
 
        if (caps[0] & SDHCI_CAN_VDD_330) {
-               int max_current_330;
-
                ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34;
 
-               max_current_330 = ((max_current_caps &
+               mmc->max_current_330 = ((max_current_caps &
                                   SDHCI_MAX_CURRENT_330_MASK) >>
                                   SDHCI_MAX_CURRENT_330_SHIFT) *
                                   SDHCI_MAX_CURRENT_MULTIPLIER;
-
-               if (max_current_330 > 150)
-                       mmc->caps |= MMC_CAP_SET_XPC_330;
        }
        if (caps[0] & SDHCI_CAN_VDD_300) {
-               int max_current_300;
-
                ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31;
 
-               max_current_300 = ((max_current_caps &
+               mmc->max_current_300 = ((max_current_caps &
                                   SDHCI_MAX_CURRENT_300_MASK) >>
                                   SDHCI_MAX_CURRENT_300_SHIFT) *
                                   SDHCI_MAX_CURRENT_MULTIPLIER;
-
-               if (max_current_300 > 150)
-                       mmc->caps |= MMC_CAP_SET_XPC_300;
        }
        if (caps[0] & SDHCI_CAN_VDD_180) {
-               int max_current_180;
-
                ocr_avail |= MMC_VDD_165_195;
 
-               max_current_180 = ((max_current_caps &
+               mmc->max_current_180 = ((max_current_caps &
                                   SDHCI_MAX_CURRENT_180_MASK) >>
                                   SDHCI_MAX_CURRENT_180_SHIFT) *
                                   SDHCI_MAX_CURRENT_MULTIPLIER;
-
-               if (max_current_180 > 150)
-                       mmc->caps |= MMC_CAP_SET_XPC_180;
-
-               /* Maximum current capabilities of the host at 1.8V */
-               if (max_current_180 >= 800)
-                       mmc->caps |= MMC_CAP_MAX_CURRENT_800;
-               else if (max_current_180 >= 600)
-                       mmc->caps |= MMC_CAP_MAX_CURRENT_600;
-               else if (max_current_180 >= 400)
-                       mmc->caps |= MMC_CAP_MAX_CURRENT_400;
-               else
-                       mmc->caps |= MMC_CAP_MAX_CURRENT_200;
        }
 
        mmc->ocr_avail = ocr_avail;
@@ -2992,13 +3026,10 @@ int sdhci_add_host(struct sdhci_host *host)
 
        ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED,
                mmc_hostname(mmc), host);
-       if (ret)
+       if (ret) {
+               pr_err("%s: Failed to request IRQ %d: %d\n",
+                      mmc_hostname(mmc), host->irq, ret);
                goto untasklet;
-
-       host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
-       if (IS_ERR(host->vmmc)) {
-               pr_info("%s: no vmmc regulator found\n", mmc_hostname(mmc));
-               host->vmmc = NULL;
        }
 
        sdhci_init(host, 0);
@@ -3016,8 +3047,11 @@ int sdhci_add_host(struct sdhci_host *host)
        host->led.brightness_set = sdhci_led_control;
 
        ret = led_classdev_register(mmc_dev(mmc), &host->led);
-       if (ret)
+       if (ret) {
+               pr_err("%s: Failed to register LED device: %d\n",
+                      mmc_hostname(mmc), ret);
                goto reset;
+       }
 #endif
 
        mmiowb();
@@ -3081,8 +3115,6 @@ void sdhci_remove_host(struct sdhci_host *host, int dead)
        free_irq(host->irq, host);
 
        del_timer_sync(&host->timer);
-       if (host->version >= SDHCI_SPEC_300)
-               del_timer_sync(&host->tuning_timer);
 
        tasklet_kill(&host->card_tasklet);
        tasklet_kill(&host->finish_tasklet);
index f761f23d2a28ccb287e1da22b2433478833b82f1..97653ea8942ba82393f47b6291942e28c2435204 100644 (file)
 #define SDHCI_CAPABILITIES_1   0x44
 
 #define SDHCI_MAX_CURRENT              0x48
+#define  SDHCI_MAX_CURRENT_LIMIT       0xFF
 #define  SDHCI_MAX_CURRENT_330_MASK    0x0000FF
 #define  SDHCI_MAX_CURRENT_330_SHIFT   0
 #define  SDHCI_MAX_CURRENT_300_MASK    0x00FF00
index 724b35e85a265f70faa11fe8f603931a687f04af..b2af7136cd27445d33225e36d5314005dcfb39b6 100644 (file)
@@ -54,6 +54,8 @@
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/sdio.h>
 #include <linux/mmc/sh_mmcif.h>
+#include <linux/mmc/slot-gpio.h>
+#include <linux/mod_devicetable.h>
 #include <linux/pagemap.h>
 #include <linux/platform_device.h>
 #include <linux/pm_qos.h>
@@ -384,6 +386,9 @@ static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
        struct sh_dmae_slave *tx, *rx;
        host->dma_active = false;
 
+       if (!pdata)
+               return;
+
        /* We can only either use DMA for both Tx and Rx or not use it at all */
        if (pdata->dma) {
                dev_warn(&host->pd->dev,
@@ -444,13 +449,14 @@ static void sh_mmcif_release_dma(struct sh_mmcif_host *host)
 static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
 {
        struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
+       bool sup_pclk = p ? p->sup_pclk : false;
 
        sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_ENABLE);
        sh_mmcif_bitclr(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR);
 
        if (!clk)
                return;
-       if (p->sup_pclk && clk == host->clk)
+       if (sup_pclk && clk == host->clk)
                sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_SUP_PCLK);
        else
                sh_mmcif_bitset(host, MMCIF_CE_CLK_CTRL, CLK_CLEAR &
@@ -892,21 +898,15 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
 
        switch (mrq->cmd->opcode) {
        /* MMCIF does not support SD/SDIO command */
-       case SD_IO_SEND_OP_COND:
+       case MMC_SLEEP_AWAKE: /* = SD_IO_SEND_OP_COND (5) */
+       case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */
+               if ((mrq->cmd->flags & MMC_CMD_MASK) != MMC_CMD_BCR)
+                       break;
        case MMC_APP_CMD:
                host->state = STATE_IDLE;
                mrq->cmd->error = -ETIMEDOUT;
                mmc_request_done(mmc, mrq);
                return;
-       case MMC_SEND_EXT_CSD: /* = SD_SEND_IF_COND (8) */
-               if (!mrq->data) {
-                       /* send_if_cond cmd (not support) */
-                       host->state = STATE_IDLE;
-                       mrq->cmd->error = -ETIMEDOUT;
-                       mmc_request_done(mmc, mrq);
-                       return;
-               }
-               break;
        default:
                break;
        }
@@ -916,10 +916,35 @@ static void sh_mmcif_request(struct mmc_host *mmc, struct mmc_request *mrq)
        sh_mmcif_start_cmd(host, mrq);
 }
 
+static int sh_mmcif_clk_update(struct sh_mmcif_host *host)
+{
+       int ret = clk_enable(host->hclk);
+
+       if (!ret) {
+               host->clk = clk_get_rate(host->hclk);
+               host->mmc->f_max = host->clk / 2;
+               host->mmc->f_min = host->clk / 512;
+       }
+
+       return ret;
+}
+
+static void sh_mmcif_set_power(struct sh_mmcif_host *host, struct mmc_ios *ios)
+{
+       struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data;
+       struct mmc_host *mmc = host->mmc;
+
+       if (pd && pd->set_pwr)
+               pd->set_pwr(host->pd, ios->power_mode != MMC_POWER_OFF);
+       if (!IS_ERR(mmc->supply.vmmc))
+               /* Errors ignored... */
+               mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
+                                     ios->power_mode ? ios->vdd : 0);
+}
+
 static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
        struct sh_mmcif_host *host = mmc_priv(mmc);
-       struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
        unsigned long flags;
 
        spin_lock_irqsave(&host->lock, flags);
@@ -937,6 +962,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                        sh_mmcif_request_dma(host, host->pd->dev.platform_data);
                        host->card_present = true;
                }
+               sh_mmcif_set_power(host, ios);
        } else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
                /* clock stop */
                sh_mmcif_clock_control(host, 0);
@@ -948,9 +974,10 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                }
                if (host->power) {
                        pm_runtime_put(&host->pd->dev);
+                       clk_disable(host->hclk);
                        host->power = false;
-                       if (p->down_pwr && ios->power_mode == MMC_POWER_OFF)
-                               p->down_pwr(host->pd);
+                       if (ios->power_mode == MMC_POWER_OFF)
+                               sh_mmcif_set_power(host, ios);
                }
                host->state = STATE_IDLE;
                return;
@@ -958,8 +985,7 @@ static void sh_mmcif_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 
        if (ios->clock) {
                if (!host->power) {
-                       if (p->set_pwr)
-                               p->set_pwr(host->pd, ios->power_mode);
+                       sh_mmcif_clk_update(host);
                        pm_runtime_get_sync(&host->pd->dev);
                        host->power = true;
                        sh_mmcif_sync_reset(host);
@@ -975,8 +1001,12 @@ static int sh_mmcif_get_cd(struct mmc_host *mmc)
 {
        struct sh_mmcif_host *host = mmc_priv(mmc);
        struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
+       int ret = mmc_gpio_get_cd(mmc);
+
+       if (ret >= 0)
+               return ret;
 
-       if (!p->get_cd)
+       if (!p || !p->get_cd)
                return -ENOSYS;
        else
                return p->get_cd(host->pd);
@@ -1242,12 +1272,28 @@ static void mmcif_timeout_work(struct work_struct *work)
        mmc_request_done(host->mmc, mrq);
 }
 
+static void sh_mmcif_init_ocr(struct sh_mmcif_host *host)
+{
+       struct sh_mmcif_plat_data *pd = host->pd->dev.platform_data;
+       struct mmc_host *mmc = host->mmc;
+
+       mmc_regulator_get_supply(mmc);
+
+       if (!pd)
+               return;
+
+       if (!mmc->ocr_avail)
+               mmc->ocr_avail = pd->ocr;
+       else if (pd->ocr)
+               dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
+}
+
 static int __devinit sh_mmcif_probe(struct platform_device *pdev)
 {
        int ret = 0, irq[2];
        struct mmc_host *mmc;
        struct sh_mmcif_host *host;
-       struct sh_mmcif_plat_data *pd;
+       struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;
        struct resource *res;
        void __iomem *reg;
        char clk_name[8];
@@ -1268,42 +1314,26 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "ioremap error.\n");
                return -ENOMEM;
        }
-       pd = pdev->dev.platform_data;
-       if (!pd) {
-               dev_err(&pdev->dev, "sh_mmcif plat data error.\n");
-               ret = -ENXIO;
-               goto clean_up;
-       }
+
        mmc = mmc_alloc_host(sizeof(struct sh_mmcif_host), &pdev->dev);
        if (!mmc) {
                ret = -ENOMEM;
-               goto clean_up;
+               goto ealloch;
        }
        host            = mmc_priv(mmc);
        host->mmc       = mmc;
        host->addr      = reg;
        host->timeout   = 1000;
 
-       snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
-       host->hclk = clk_get(&pdev->dev, clk_name);
-       if (IS_ERR(host->hclk)) {
-               dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
-               ret = PTR_ERR(host->hclk);
-               goto clean_up1;
-       }
-       clk_enable(host->hclk);
-       host->clk = clk_get_rate(host->hclk);
        host->pd = pdev;
 
        spin_lock_init(&host->lock);
 
        mmc->ops = &sh_mmcif_ops;
-       mmc->f_max = host->clk / 2;
-       mmc->f_min = host->clk / 512;
-       if (pd->ocr)
-               mmc->ocr_avail = pd->ocr;
+       sh_mmcif_init_ocr(host);
+
        mmc->caps = MMC_CAP_MMC_HIGHSPEED;
-       if (pd->caps)
+       if (pd && pd->caps)
                mmc->caps |= pd->caps;
        mmc->max_segs = 32;
        mmc->max_blk_size = 512;
@@ -1311,34 +1341,52 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
        mmc->max_blk_count = mmc->max_req_size / mmc->max_blk_size;
        mmc->max_seg_size = mmc->max_req_size;
 
-       sh_mmcif_sync_reset(host);
        platform_set_drvdata(pdev, host);
 
        pm_runtime_enable(&pdev->dev);
        host->power = false;
 
+       snprintf(clk_name, sizeof(clk_name), "mmc%d", pdev->id);
+       host->hclk = clk_get(&pdev->dev, clk_name);
+       if (IS_ERR(host->hclk)) {
+               ret = PTR_ERR(host->hclk);
+               dev_err(&pdev->dev, "cannot get clock \"%s\": %d\n", clk_name, ret);
+               goto eclkget;
+       }
+       ret = sh_mmcif_clk_update(host);
+       if (ret < 0)
+               goto eclkupdate;
+
        ret = pm_runtime_resume(&pdev->dev);
        if (ret < 0)
-               goto clean_up2;
+               goto eresume;
 
        INIT_DELAYED_WORK(&host->timeout_work, mmcif_timeout_work);
 
+       sh_mmcif_sync_reset(host);
        sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
 
        ret = request_threaded_irq(irq[0], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:error", host);
        if (ret) {
                dev_err(&pdev->dev, "request_irq error (sh_mmc:error)\n");
-               goto clean_up3;
+               goto ereqirq0;
        }
        ret = request_threaded_irq(irq[1], sh_mmcif_intr, sh_mmcif_irqt, 0, "sh_mmc:int", host);
        if (ret) {
                dev_err(&pdev->dev, "request_irq error (sh_mmc:int)\n");
-               goto clean_up4;
+               goto ereqirq1;
+       }
+
+       if (pd && pd->use_cd_gpio) {
+               ret = mmc_gpio_request_cd(mmc, pd->cd_gpio);
+               if (ret < 0)
+                       goto erqcd;
        }
 
+       clk_disable(host->hclk);
        ret = mmc_add_host(mmc);
        if (ret < 0)
-               goto clean_up5;
+               goto emmcaddh;
 
        dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
 
@@ -1347,33 +1395,42 @@ static int __devinit sh_mmcif_probe(struct platform_device *pdev)
                sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
        return ret;
 
-clean_up5:
+emmcaddh:
+       if (pd && pd->use_cd_gpio)
+               mmc_gpio_free_cd(mmc);
+erqcd:
        free_irq(irq[1], host);
-clean_up4:
+ereqirq1:
        free_irq(irq[0], host);
-clean_up3:
+ereqirq0:
        pm_runtime_suspend(&pdev->dev);
-clean_up2:
-       pm_runtime_disable(&pdev->dev);
+eresume:
        clk_disable(host->hclk);
-clean_up1:
+eclkupdate:
+       clk_put(host->hclk);
+eclkget:
+       pm_runtime_disable(&pdev->dev);
        mmc_free_host(mmc);
-clean_up:
-       if (reg)
-               iounmap(reg);
+ealloch:
+       iounmap(reg);
        return ret;
 }
 
 static int __devexit sh_mmcif_remove(struct platform_device *pdev)
 {
        struct sh_mmcif_host *host = platform_get_drvdata(pdev);
+       struct sh_mmcif_plat_data *pd = pdev->dev.platform_data;
        int irq[2];
 
        host->dying = true;
+       clk_enable(host->hclk);
        pm_runtime_get_sync(&pdev->dev);
 
        dev_pm_qos_hide_latency_limit(&pdev->dev);
 
+       if (pd && pd->use_cd_gpio)
+               mmc_gpio_free_cd(host->mmc);
+
        mmc_remove_host(host->mmc);
        sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
 
@@ -1395,9 +1452,9 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, NULL);
 
-       clk_disable(host->hclk);
        mmc_free_host(host->mmc);
        pm_runtime_put_sync(&pdev->dev);
+       clk_disable(host->hclk);
        pm_runtime_disable(&pdev->dev);
 
        return 0;
@@ -1406,24 +1463,18 @@ static int __devexit sh_mmcif_remove(struct platform_device *pdev)
 #ifdef CONFIG_PM
 static int sh_mmcif_suspend(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct sh_mmcif_host *host = platform_get_drvdata(pdev);
+       struct sh_mmcif_host *host = dev_get_drvdata(dev);
        int ret = mmc_suspend_host(host->mmc);
 
-       if (!ret) {
+       if (!ret)
                sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
-               clk_disable(host->hclk);
-       }
 
        return ret;
 }
 
 static int sh_mmcif_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
-       struct sh_mmcif_host *host = platform_get_drvdata(pdev);
-
-       clk_enable(host->hclk);
+       struct sh_mmcif_host *host = dev_get_drvdata(dev);
 
        return mmc_resume_host(host->mmc);
 }
@@ -1432,6 +1483,12 @@ static int sh_mmcif_resume(struct device *dev)
 #define sh_mmcif_resume                NULL
 #endif /* CONFIG_PM */
 
+static const struct of_device_id mmcif_of_match[] = {
+       { .compatible = "renesas,sh-mmcif" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, mmcif_of_match);
+
 static const struct dev_pm_ops sh_mmcif_dev_pm_ops = {
        .suspend = sh_mmcif_suspend,
        .resume = sh_mmcif_resume,
@@ -1443,6 +1500,8 @@ static struct platform_driver sh_mmcif_driver = {
        .driver         = {
                .name   = DRIVER_NAME,
                .pm     = &sh_mmcif_dev_pm_ops,
+               .owner  = THIS_MODULE,
+               .of_match_table = mmcif_of_match,
        },
 };
 
index 934b68e9efc34e50796495ea61a37d2ed598e155..a842939e46555295f32418ac05f96c495d734ea2 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/mmc/host.h>
@@ -39,22 +40,39 @@ struct sh_mobile_sdhi {
        struct tmio_mmc_dma dma_priv;
 };
 
+static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int *f)
+{
+       struct mmc_host *mmc = dev_get_drvdata(&pdev->dev);
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+       struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
+       int ret = clk_enable(priv->clk);
+       if (ret < 0)
+               return ret;
+
+       *f = clk_get_rate(priv->clk);
+       return 0;
+}
+
+static void sh_mobile_sdhi_clk_disable(struct platform_device *pdev)
+{
+       struct mmc_host *mmc = dev_get_drvdata(&pdev->dev);
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+       struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
+       clk_disable(priv->clk);
+}
+
 static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)
 {
        struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
 
-       if (p && p->set_pwr)
-               p->set_pwr(pdev, state);
+       p->set_pwr(pdev, state);
 }
 
 static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)
 {
        struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
 
-       if (p && p->get_cd)
-               return p->get_cd(pdev);
-       else
-               return -ENOSYS;
+       return p->get_cd(pdev);
 }
 
 static int sh_mobile_sdhi_wait_idle(struct tmio_mmc_host *host)
@@ -116,12 +134,14 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
        }
 
        mmc_data = &priv->mmc_data;
-       p->pdata = mmc_data;
 
-       if (p->init) {
-               ret = p->init(pdev, &sdhi_ops);
-               if (ret)
-                       goto einit;
+       if (p) {
+               p->pdata = mmc_data;
+               if (p->init) {
+                       ret = p->init(pdev, &sdhi_ops);
+                       if (ret)
+                               goto einit;
+               }
        }
 
        snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id);
@@ -132,9 +152,8 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
                goto eclkget;
        }
 
-       mmc_data->hclk = clk_get_rate(priv->clk);
-       mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
-       mmc_data->get_cd = sh_mobile_sdhi_get_cd;
+       mmc_data->clk_enable = sh_mobile_sdhi_clk_enable;
+       mmc_data->clk_disable = sh_mobile_sdhi_clk_disable;
        mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
        if (p) {
                mmc_data->flags = p->tmio_flags;
@@ -142,7 +161,12 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
                        mmc_data->write16_hook = sh_mobile_sdhi_write16_hook;
                mmc_data->ocr_mask = p->tmio_ocr_mask;
                mmc_data->capabilities |= p->tmio_caps;
+               mmc_data->capabilities2 |= p->tmio_caps2;
                mmc_data->cd_gpio = p->cd_gpio;
+               if (p->set_pwr)
+                       mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
+               if (p->get_cd)
+                       mmc_data->get_cd = sh_mobile_sdhi_get_cd;
 
                if (p->dma_slave_tx > 0 && p->dma_slave_rx > 0) {
                        priv->param_tx.slave_id = p->dma_slave_tx;
@@ -248,7 +272,7 @@ eirq_card_detect:
 eprobe:
        clk_put(priv->clk);
 eclkget:
-       if (p->cleanup)
+       if (p && p->cleanup)
                p->cleanup(pdev);
 einit:
        kfree(priv);
@@ -263,7 +287,8 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
        struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
        int i = 0, irq;
 
-       p->pdata = NULL;
+       if (p)
+               p->pdata = NULL;
 
        tmio_mmc_host_remove(host);
 
@@ -276,7 +301,7 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
 
        clk_put(priv->clk);
 
-       if (p->cleanup)
+       if (p && p->cleanup)
                p->cleanup(pdev);
 
        kfree(priv);
@@ -291,11 +316,18 @@ static const struct dev_pm_ops tmio_mmc_dev_pm_ops = {
        .runtime_resume = tmio_mmc_host_runtime_resume,
 };
 
+static const struct of_device_id sh_mobile_sdhi_of_match[] = {
+       { .compatible = "renesas,shmobile-sdhi" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, sh_mobile_sdhi_of_match);
+
 static struct platform_driver sh_mobile_sdhi_driver = {
        .driver         = {
                .name   = "sh_mobile_sdhi",
                .owner  = THIS_MODULE,
                .pm     = &tmio_mmc_dev_pm_ops,
+               .of_match_table = sh_mobile_sdhi_of_match,
        },
        .probe          = sh_mobile_sdhi_probe,
        .remove         = __devexit_p(sh_mobile_sdhi_remove),
index 9a7996ade58e8aaa597ca81758898669726a305d..0d8a9bbe30bed368226a5020435d00e8218a0b2f 100644 (file)
@@ -34,8 +34,9 @@
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/mfd/tmio.h>
-#include <linux/mmc/cd-gpio.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/slot-gpio.h>
 #include <linux/mmc/tmio.h>
 #include <linux/module.h>
 #include <linux/pagemap.h>
@@ -305,8 +306,8 @@ static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command
        int c = cmd->opcode;
        u32 irq_mask = TMIO_MASK_CMD;
 
-       /* Command 12 is handled by hardware */
-       if (cmd->opcode == 12 && !cmd->arg) {
+       /* CMD12 is handled by hardware */
+       if (cmd->opcode == MMC_STOP_TRANSMISSION && !cmd->arg) {
                sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x001);
                return 0;
        }
@@ -449,7 +450,7 @@ void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
        }
 
        if (stop) {
-               if (stop->opcode == 12 && !stop->arg)
+               if (stop->opcode == MMC_STOP_TRANSMISSION && !stop->arg)
                        sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000);
                else
                        BUG();
@@ -751,6 +752,34 @@ fail:
        mmc_request_done(mmc, mrq);
 }
 
+static int tmio_mmc_clk_update(struct mmc_host *mmc)
+{
+       struct tmio_mmc_host *host = mmc_priv(mmc);
+       struct tmio_mmc_data *pdata = host->pdata;
+       int ret;
+
+       if (!pdata->clk_enable)
+               return -ENOTSUPP;
+
+       ret = pdata->clk_enable(host->pdev, &mmc->f_max);
+       if (!ret)
+               mmc->f_min = mmc->f_max / 512;
+
+       return ret;
+}
+
+static void tmio_mmc_set_power(struct tmio_mmc_host *host, struct mmc_ios *ios)
+{
+       struct mmc_host *mmc = host->mmc;
+
+       if (host->set_pwr)
+               host->set_pwr(host->pdev, ios->power_mode != MMC_POWER_OFF);
+       if (!IS_ERR(mmc->supply.vmmc))
+               /* Errors ignored... */
+               mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
+                                     ios->power_mode ? ios->vdd : 0);
+}
+
 /* Set MMC clock / power.
  * Note: This controller uses a simple divider scheme therefore it cannot
  * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
@@ -797,32 +826,37 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
         */
        if (ios->power_mode == MMC_POWER_ON && ios->clock) {
                if (!host->power) {
+                       tmio_mmc_clk_update(mmc);
                        pm_runtime_get_sync(dev);
                        host->power = true;
                }
                tmio_mmc_set_clock(host, ios->clock);
                /* power up SD bus */
-               if (host->set_pwr)
-                       host->set_pwr(host->pdev, 1);
+               tmio_mmc_set_power(host, ios);
                /* start bus clock */
                tmio_mmc_clk_start(host);
        } else if (ios->power_mode != MMC_POWER_UP) {
-               if (host->set_pwr && ios->power_mode == MMC_POWER_OFF)
-                       host->set_pwr(host->pdev, 0);
+               if (ios->power_mode == MMC_POWER_OFF)
+                       tmio_mmc_set_power(host, ios);
                if (host->power) {
+                       struct tmio_mmc_data *pdata = host->pdata;
+                       tmio_mmc_clk_stop(host);
                        host->power = false;
                        pm_runtime_put(dev);
+                       if (pdata->clk_disable)
+                               pdata->clk_disable(host->pdev);
                }
-               tmio_mmc_clk_stop(host);
        }
 
-       switch (ios->bus_width) {
-       case MMC_BUS_WIDTH_1:
-               sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
-       break;
-       case MMC_BUS_WIDTH_4:
-               sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
-       break;
+       if (host->power) {
+               switch (ios->bus_width) {
+               case MMC_BUS_WIDTH_1:
+                       sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
+               break;
+               case MMC_BUS_WIDTH_4:
+                       sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
+               break;
+               }
        }
 
        /* Let things settle. delay taken from winCE driver */
@@ -841,6 +875,9 @@ static int tmio_mmc_get_ro(struct mmc_host *mmc)
 {
        struct tmio_mmc_host *host = mmc_priv(mmc);
        struct tmio_mmc_data *pdata = host->pdata;
+       int ret = mmc_gpio_get_ro(mmc);
+       if (ret >= 0)
+               return ret;
 
        return !((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
                 (sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT));
@@ -850,6 +887,9 @@ static int tmio_mmc_get_cd(struct mmc_host *mmc)
 {
        struct tmio_mmc_host *host = mmc_priv(mmc);
        struct tmio_mmc_data *pdata = host->pdata;
+       int ret = mmc_gpio_get_cd(mmc);
+       if (ret >= 0)
+               return ret;
 
        if (!pdata->get_cd)
                return -ENOSYS;
@@ -865,6 +905,19 @@ static const struct mmc_host_ops tmio_mmc_ops = {
        .enable_sdio_irq = tmio_mmc_enable_sdio_irq,
 };
 
+static void tmio_mmc_init_ocr(struct tmio_mmc_host *host)
+{
+       struct tmio_mmc_data *pdata = host->pdata;
+       struct mmc_host *mmc = host->mmc;
+
+       mmc_regulator_get_supply(mmc);
+
+       if (!mmc->ocr_avail)
+               mmc->ocr_avail = pdata->ocr_mask ? : MMC_VDD_32_33 | MMC_VDD_33_34;
+       else if (pdata->ocr_mask)
+               dev_warn(mmc_dev(mmc), "Platform OCR mask is ignored\n");
+}
+
 int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
                                  struct platform_device *pdev,
                                  struct tmio_mmc_data *pdata)
@@ -904,18 +957,14 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
 
        mmc->ops = &tmio_mmc_ops;
        mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities;
-       mmc->f_max = pdata->hclk;
-       mmc->f_min = mmc->f_max / 512;
+       mmc->caps2 = pdata->capabilities2;
        mmc->max_segs = 32;
        mmc->max_blk_size = 512;
        mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) *
                mmc->max_segs;
        mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
        mmc->max_seg_size = mmc->max_req_size;
-       if (pdata->ocr_mask)
-               mmc->ocr_avail = pdata->ocr_mask;
-       else
-               mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+       tmio_mmc_init_ocr(_host);
 
        _host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD ||
                                  mmc->caps & MMC_CAP_NEEDS_POLL ||
@@ -927,6 +976,11 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
        if (ret < 0)
                goto pm_disable;
 
+       if (tmio_mmc_clk_update(mmc) < 0) {
+               mmc->f_max = pdata->hclk;
+               mmc->f_min = mmc->f_max / 512;
+       }
+
        /*
         * There are 4 different scenarios for the card detection:
         *  1) an external gpio irq handles the cd (best for power savings)
@@ -937,7 +991,6 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
         *  While we increment the runtime PM counter for all scenarios when
         *  the mmc core activates us by calling an appropriate set_ios(), we
         *  must additionally ensure that in case 2) the tmio mmc hardware stays
-        *  additionally ensure that in case 2) the tmio mmc hardware stays
         *  powered on during runtime for the card detection to work.
         */
        if (_host->native_hotplug)
@@ -948,6 +1001,17 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
 
        _host->sdcard_irq_mask = sd_ctrl_read32(_host, CTL_IRQ_MASK);
        tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL);
+
+       /* Unmask the IRQs we want to know about */
+       if (!_host->chan_rx)
+               irq_mask |= TMIO_MASK_READOP;
+       if (!_host->chan_tx)
+               irq_mask |= TMIO_MASK_WRITEOP;
+       if (!_host->native_hotplug)
+               irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT);
+
+       _host->sdcard_irq_mask &= ~irq_mask;
+
        if (pdata->flags & TMIO_MMC_SDIO_IRQ)
                tmio_mmc_enable_sdio_irq(mmc, 0);
 
@@ -961,22 +1025,18 @@ int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
        /* See if we also get DMA */
        tmio_mmc_request_dma(_host, pdata);
 
-       mmc_add_host(mmc);
+       ret = mmc_add_host(mmc);
+       if (pdata->clk_disable)
+               pdata->clk_disable(pdev);
+       if (ret < 0) {
+               tmio_mmc_host_remove(_host);
+               return ret;
+       }
 
        dev_pm_qos_expose_latency_limit(&pdev->dev, 100);
 
-       /* Unmask the IRQs we want to know about */
-       if (!_host->chan_rx)
-               irq_mask |= TMIO_MASK_READOP;
-       if (!_host->chan_tx)
-               irq_mask |= TMIO_MASK_WRITEOP;
-       if (!_host->native_hotplug)
-               irq_mask &= ~(TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT);
-
-       tmio_mmc_enable_mmc_irqs(_host, irq_mask);
-
        if (pdata->flags & TMIO_MMC_USE_GPIO_CD) {
-               ret = mmc_cd_gpio_request(mmc, pdata->cd_gpio);
+               ret = mmc_gpio_request_cd(mmc, pdata->cd_gpio);
                if (ret < 0) {
                        tmio_mmc_host_remove(_host);
                        return ret;
@@ -1008,7 +1068,7 @@ void tmio_mmc_host_remove(struct tmio_mmc_host *host)
                 * This means we can miss a card-eject, but this is anyway
                 * possible, because of delayed processing of hotplug events.
                 */
-               mmc_cd_gpio_free(mmc);
+               mmc_gpio_free_cd(mmc);
 
        if (!host->native_hotplug)
                pm_runtime_get_sync(&pdev->dev);
index a90bfe79916d29c6f7c2460e9dc644dadc46904e..334da5f583c021124ea2e64ae7860f513bd9816f 100644 (file)
@@ -63,7 +63,7 @@ static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags,
        struct super_block *sb;
        int ret;
 
-       sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, mtd);
+       sb = sget(fs_type, get_sb_mtd_compare, get_sb_mtd_set, flags, mtd);
        if (IS_ERR(sb))
                goto out_error;
 
@@ -74,8 +74,6 @@ static struct dentry *mount_mtd_aux(struct file_system_type *fs_type, int flags,
        pr_debug("MTDSB: New superblock for device %d (\"%s\")\n",
              mtd->index, mtd->name);
 
-       sb->s_flags = flags;
-
        ret = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
        if (ret < 0) {
                deactivate_locked_super(sb);
index 738ee8dc16cdfb06e2f82d45fecc602d6254ad42..ea4b95b5451c8b6c2ec25a0905c5e4af7e1e76ee 100644 (file)
@@ -29,7 +29,7 @@ config MTD_UBI_WL_THRESHOLD
 
 config MTD_UBI_BEB_RESERVE
        int "Percentage of reserved eraseblocks for bad eraseblocks handling"
-       default 1
+       default 2
        range 0 25
        help
          If the MTD device admits of bad eraseblocks (e.g. NAND flash), UBI
index acec85deb6afe3dd05a5f6d6102c91b4de43d53b..fb55678781813da69b91f81c4aaa5430aef93974 100644 (file)
@@ -1026,7 +1026,7 @@ static long ctrl_cdev_ioctl(struct file *file, unsigned int cmd,
        {
                int ubi_num;
 
-               dbg_gen("dettach MTD device");
+               dbg_gen("detach MTD device");
                err = get_user(ubi_num, (__user int32_t *)argp);
                if (err) {
                        err = -EFAULT;
index f6a7d7ac4b98a6fb1f2dd3b8d2f0abad4b06bd45..8bbfb444b89525cbb9c0a071914a4de0af65f1fe 100644 (file)
@@ -92,7 +92,30 @@ int ubi_check_volume(struct ubi_device *ubi, int vol_id)
 }
 
 /**
- * ubi_calculate_rsvd_pool - calculate how many PEBs must be reserved for bad
+ * ubi_update_reserved - update bad eraseblock handling accounting data.
+ * @ubi: UBI device description object
+ *
+ * This function calculates the gap between current number of PEBs reserved for
+ * bad eraseblock handling and the required level of PEBs that must be
+ * reserved, and if necessary, reserves more PEBs to fill that gap, according
+ * to availability. Should be called with ubi->volumes_lock held.
+ */
+void ubi_update_reserved(struct ubi_device *ubi)
+{
+       int need = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;
+
+       if (need <= 0 || ubi->avail_pebs == 0)
+               return;
+
+       need = min_t(int, need, ubi->avail_pebs);
+       ubi->avail_pebs -= need;
+       ubi->rsvd_pebs += need;
+       ubi->beb_rsvd_pebs += need;
+       ubi_msg("reserved more %d PEBs for bad PEB handling", need);
+}
+
+/**
+ * ubi_calculate_reserved - calculate how many PEBs must be reserved for bad
  * eraseblock handling.
  * @ubi: UBI device description object
  */
index a1a81c9ea8ce2a8aa7f56accfad3aa7394a51044..84f66e3fa05d7d39ef265a657ec296fd1be1448c 100644 (file)
@@ -647,6 +647,7 @@ int ubi_more_leb_change_data(struct ubi_device *ubi, struct ubi_volume *vol,
 int ubi_calc_data_len(const struct ubi_device *ubi, const void *buf,
                      int length);
 int ubi_check_volume(struct ubi_device *ubi, int vol_id);
+void ubi_update_reserved(struct ubi_device *ubi);
 void ubi_calculate_reserved(struct ubi_device *ubi);
 int ubi_check_pattern(const void *buf, uint8_t patt, int size);
 
index 0669cff8ac3c7d233e40ca6cb1c87878d7fd1457..9169e58c262ec47eaf9b5abb543b12e476af705a 100644 (file)
@@ -443,15 +443,7 @@ int ubi_remove_volume(struct ubi_volume_desc *desc, int no_vtbl)
        spin_lock(&ubi->volumes_lock);
        ubi->rsvd_pebs -= reserved_pebs;
        ubi->avail_pebs += reserved_pebs;
-       i = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;
-       if (i > 0) {
-               i = ubi->avail_pebs >= i ? i : ubi->avail_pebs;
-               ubi->avail_pebs -= i;
-               ubi->rsvd_pebs += i;
-               ubi->beb_rsvd_pebs += i;
-               if (i > 0)
-                       ubi_msg("reserve more %d PEBs", i);
-       }
+       ubi_update_reserved(ubi);
        ubi->vol_count -= 1;
        spin_unlock(&ubi->volumes_lock);
 
@@ -558,15 +550,7 @@ int ubi_resize_volume(struct ubi_volume_desc *desc, int reserved_pebs)
                spin_lock(&ubi->volumes_lock);
                ubi->rsvd_pebs += pebs;
                ubi->avail_pebs -= pebs;
-               pebs = ubi->beb_rsvd_level - ubi->beb_rsvd_pebs;
-               if (pebs > 0) {
-                       pebs = ubi->avail_pebs >= pebs ? pebs : ubi->avail_pebs;
-                       ubi->avail_pebs -= pebs;
-                       ubi->rsvd_pebs += pebs;
-                       ubi->beb_rsvd_pebs += pebs;
-                       if (pebs > 0)
-                               ubi_msg("reserve more %d PEBs", pebs);
-               }
+               ubi_update_reserved(ubi);
                for (i = 0; i < reserved_pebs; i++)
                        new_mapping[i] = vol->eba_tbl[i];
                kfree(vol->eba_tbl);
index d9bfd49b193503f61977a7a1c253e0a981ba07b1..a14f109dcd130844aeb4afb7e646a3055824c302 100644 (file)
@@ -1051,7 +1051,8 @@ int prom_remove_property(struct device_node *np, struct property *prop)
 }
 
 /*
- * prom_update_property - Update a property in a node.
+ * prom_update_property - Update a property in a node, if the property does
+ * not exist, add it.
  *
  * Note that we don't actually remove it, since we have given out
  * who-knows-how-many pointers to the data using get-property.
@@ -1059,13 +1060,19 @@ int prom_remove_property(struct device_node *np, struct property *prop)
  * and add the new property to the property list
  */
 int prom_update_property(struct device_node *np,
-                        struct property *newprop,
-                        struct property *oldprop)
+                        struct property *newprop)
 {
-       struct property **next;
+       struct property **next, *oldprop;
        unsigned long flags;
        int found = 0;
 
+       if (!newprop->name)
+               return -EINVAL;
+
+       oldprop = of_find_property(np, newprop->name, NULL);
+       if (!oldprop)
+               return prom_add_property(np, newprop);
+
        write_lock_irqsave(&devtree_lock, flags);
        next = &np->properties;
        while (*next) {
index efc4b7f308cfd6e1c37a44a0407c6e070f9d514e..f3cfa0b9adfa30fb9a95593d4f422ef25c2f4836 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright 2010 ARM Ltd.
+ * Copyright 2012 Advanced Micro Devices, Inc., Robert Richter
  *
  * Perf-events backend for OProfile.
  */
@@ -25,7 +26,7 @@ static int oprofile_perf_enabled;
 static DEFINE_MUTEX(oprofile_perf_mutex);
 
 static struct op_counter_config *counter_config;
-static struct perf_event **perf_events[NR_CPUS];
+static DEFINE_PER_CPU(struct perf_event **, perf_events);
 static int num_counters;
 
 /*
@@ -38,7 +39,7 @@ static void op_overflow_handler(struct perf_event *event,
        u32 cpu = smp_processor_id();
 
        for (id = 0; id < num_counters; ++id)
-               if (perf_events[cpu][id] == event)
+               if (per_cpu(perf_events, cpu)[id] == event)
                        break;
 
        if (id != num_counters)
@@ -74,7 +75,7 @@ static int op_create_counter(int cpu, int event)
 {
        struct perf_event *pevent;
 
-       if (!counter_config[event].enabled || perf_events[cpu][event])
+       if (!counter_config[event].enabled || per_cpu(perf_events, cpu)[event])
                return 0;
 
        pevent = perf_event_create_kernel_counter(&counter_config[event].attr,
@@ -91,18 +92,18 @@ static int op_create_counter(int cpu, int event)
                return -EBUSY;
        }
 
-       perf_events[cpu][event] = pevent;
+       per_cpu(perf_events, cpu)[event] = pevent;
 
        return 0;
 }
 
 static void op_destroy_counter(int cpu, int event)
 {
-       struct perf_event *pevent = perf_events[cpu][event];
+       struct perf_event *pevent = per_cpu(perf_events, cpu)[event];
 
        if (pevent) {
                perf_event_release_kernel(pevent);
-               perf_events[cpu][event] = NULL;
+               per_cpu(perf_events, cpu)[event] = NULL;
        }
 }
 
@@ -257,12 +258,12 @@ void oprofile_perf_exit(void)
 
        for_each_possible_cpu(cpu) {
                for (id = 0; id < num_counters; ++id) {
-                       event = perf_events[cpu][id];
+                       event = per_cpu(perf_events, cpu)[id];
                        if (event)
                                perf_event_release_kernel(event);
                }
 
-               kfree(perf_events[cpu]);
+               kfree(per_cpu(perf_events, cpu));
        }
 
        kfree(counter_config);
@@ -277,8 +278,6 @@ int __init oprofile_perf_init(struct oprofile_operations *ops)
        if (ret)
                return ret;
 
-       memset(&perf_events, 0, sizeof(perf_events));
-
        num_counters = perf_num_counters();
        if (num_counters <= 0) {
                pr_info("oprofile: no performance counters\n");
@@ -298,9 +297,9 @@ int __init oprofile_perf_init(struct oprofile_operations *ops)
        }
 
        for_each_possible_cpu(cpu) {
-               perf_events[cpu] = kcalloc(num_counters,
+               per_cpu(perf_events, cpu) = kcalloc(num_counters,
                                sizeof(struct perf_event *), GFP_KERNEL);
-               if (!perf_events[cpu]) {
+               if (!per_cpu(perf_events, cpu)) {
                        pr_info("oprofile: failed to allocate %d perf events "
                                        "for cpu %d\n", num_counters, cpu);
                        ret = -ENOMEM;
index 2a75216775410df88e19fd9faa21e0045c16d15d..d41d4c522960535fbea3a5986f558393d045fea2 100644 (file)
@@ -2143,9 +2143,9 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82865_HB,
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82875_HB,
                        quirk_unhide_mch_dev6);
 
-#ifdef CONFIG_TILE
+#ifdef CONFIG_TILEPRO
 /*
- * The Tilera TILEmpower platform needs to set the link speed
+ * The Tilera TILEmpower tilepro platform needs to set the link speed
  * to 2.5GT(Giga-Transfers)/s (Gen 1). The default link speed
  * setting is 5GT/s (Gen 2). 0x98 is the Link Control2 PCIe
  * capability register of the PEX8624 PCIe switch. The switch
@@ -2160,7 +2160,7 @@ static void __devinit quirk_tile_plx_gen1(struct pci_dev *dev)
        }
 }
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8624, quirk_tile_plx_gen1);
-#endif /* CONFIG_TILE */
+#endif /* CONFIG_TILEPRO */
 
 #ifdef CONFIG_PCI_MSI
 /* Some chipsets do not support MSI. We cannot easily rely on setting
index 3e7e47d6b38526178b0985bf0e7162f8fab16d70..dd9e6f26416da777dfb66231aca0c9f86bade9a0 100644 (file)
@@ -1198,7 +1198,7 @@ static int __devinit nmk_gpio_probe(struct platform_device *dev)
                if (!pdata)
                        return -ENOMEM;
 
-               if (of_get_property(np, "supports-sleepmode", NULL))
+               if (of_get_property(np, "st,supports-sleepmode", NULL))
                        pdata->supports_sleepmode = true;
 
                if (of_property_read_u32(np, "gpio-bank", &dev->id)) {
index e9f8e7d110018c14d6011ccf8903e086af983ce3..2aae8a8978e99b4224ef0f0baff84b5745e913dd 100644 (file)
@@ -8,24 +8,61 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/slab.h>
 #include <linux/err.h>
+#include <linux/irqdomain.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/bitops.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
 
 #define DRIVER_NAME "pinmux-sirf"
 
 #define SIRFSOC_NUM_PADS    622
-#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
 #define SIRFSOC_RSC_PIN_MUX 0x4
 
+#define SIRFSOC_GPIO_PAD_EN(g) ((g)*0x100 + 0x84)
+#define SIRFSOC_GPIO_CTRL(g, i)                        ((g)*0x100 + (i)*4)
+#define SIRFSOC_GPIO_DSP_EN0                   (0x80)
+#define SIRFSOC_GPIO_PAD_EN(g)                 ((g)*0x100 + 0x84)
+#define SIRFSOC_GPIO_INT_STATUS(g)             ((g)*0x100 + 0x8C)
+
+#define SIRFSOC_GPIO_CTL_INTR_LOW_MASK         0x1
+#define SIRFSOC_GPIO_CTL_INTR_HIGH_MASK                0x2
+#define SIRFSOC_GPIO_CTL_INTR_TYPE_MASK                0x4
+#define SIRFSOC_GPIO_CTL_INTR_EN_MASK          0x8
+#define SIRFSOC_GPIO_CTL_INTR_STS_MASK         0x10
+#define SIRFSOC_GPIO_CTL_OUT_EN_MASK           0x20
+#define SIRFSOC_GPIO_CTL_DATAOUT_MASK          0x40
+#define SIRFSOC_GPIO_CTL_DATAIN_MASK           0x80
+#define SIRFSOC_GPIO_CTL_PULL_MASK             0x100
+#define SIRFSOC_GPIO_CTL_PULL_HIGH             0x200
+#define SIRFSOC_GPIO_CTL_DSP_INT               0x400
+
+#define SIRFSOC_GPIO_NO_OF_BANKS        5
+#define SIRFSOC_GPIO_BANK_SIZE          32
+#define SIRFSOC_GPIO_NUM(bank, index)  (((bank)*(32)) + (index))
+
+struct sirfsoc_gpio_bank {
+       struct of_mm_gpio_chip chip;
+       struct irq_domain *domain;
+       int id;
+       int parent_irq;
+       spinlock_t lock;
+};
+
+static struct sirfsoc_gpio_bank sgpio_bank[SIRFSOC_GPIO_NO_OF_BANKS];
+static DEFINE_SPINLOCK(sgpio_lock);
+
 /*
  * pad list for the pinmux subsystem
  * refer to CS-131858-DC-6A.xls
@@ -1204,7 +1241,457 @@ static int __init sirfsoc_pinmux_init(void)
 }
 arch_initcall(sirfsoc_pinmux_init);
 
+static inline int sirfsoc_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+       struct sirfsoc_gpio_bank *bank = container_of(to_of_mm_gpio_chip(chip),
+               struct sirfsoc_gpio_bank, chip);
+
+       return irq_find_mapping(bank->domain, offset);
+}
+
+static inline int sirfsoc_gpio_to_offset(unsigned int gpio)
+{
+       return gpio % SIRFSOC_GPIO_BANK_SIZE;
+}
+
+static inline struct sirfsoc_gpio_bank *sirfsoc_gpio_to_bank(unsigned int gpio)
+{
+       return &sgpio_bank[gpio / SIRFSOC_GPIO_BANK_SIZE];
+}
+
+void sirfsoc_gpio_set_pull(unsigned gpio, unsigned mode)
+{
+       struct sirfsoc_gpio_bank *bank = sirfsoc_gpio_to_bank(gpio);
+       int idx = sirfsoc_gpio_to_offset(gpio);
+       u32 val, offset;
+       unsigned long flags;
+
+       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
+
+       spin_lock_irqsave(&sgpio_lock, flags);
+
+       val = readl(bank->chip.regs + offset);
+
+       switch (mode) {
+       case SIRFSOC_GPIO_PULL_NONE:
+               val &= ~SIRFSOC_GPIO_CTL_PULL_MASK;
+               break;
+       case SIRFSOC_GPIO_PULL_UP:
+               val |= SIRFSOC_GPIO_CTL_PULL_MASK;
+               val |= SIRFSOC_GPIO_CTL_PULL_HIGH;
+               break;
+       case SIRFSOC_GPIO_PULL_DOWN:
+               val |= SIRFSOC_GPIO_CTL_PULL_MASK;
+               val &= ~SIRFSOC_GPIO_CTL_PULL_HIGH;
+               break;
+       default:
+               break;
+       }
+
+       writel(val, bank->chip.regs + offset);
+
+       spin_unlock_irqrestore(&sgpio_lock, flags);
+}
+EXPORT_SYMBOL(sirfsoc_gpio_set_pull);
+
+static inline struct sirfsoc_gpio_bank *sirfsoc_irqchip_to_bank(struct gpio_chip *chip)
+{
+       return container_of(to_of_mm_gpio_chip(chip), struct sirfsoc_gpio_bank, chip);
+}
+
+static void sirfsoc_gpio_irq_ack(struct irq_data *d)
+{
+       struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
+       u32 val, offset;
+       unsigned long flags;
+
+       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
+
+       spin_lock_irqsave(&sgpio_lock, flags);
+
+       val = readl(bank->chip.regs + offset);
+
+       writel(val, bank->chip.regs + offset);
+
+       spin_unlock_irqrestore(&sgpio_lock, flags);
+}
+
+static void __sirfsoc_gpio_irq_mask(struct sirfsoc_gpio_bank *bank, int idx)
+{
+       u32 val, offset;
+       unsigned long flags;
+
+       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
+
+       spin_lock_irqsave(&sgpio_lock, flags);
+
+       val = readl(bank->chip.regs + offset);
+       val &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
+       val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
+       writel(val, bank->chip.regs + offset);
+
+       spin_unlock_irqrestore(&sgpio_lock, flags);
+}
+
+static void sirfsoc_gpio_irq_mask(struct irq_data *d)
+{
+       struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+
+       __sirfsoc_gpio_irq_mask(bank, d->hwirq % SIRFSOC_GPIO_BANK_SIZE);
+}
+
+static void sirfsoc_gpio_irq_unmask(struct irq_data *d)
+{
+       struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
+       u32 val, offset;
+       unsigned long flags;
+
+       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
+
+       spin_lock_irqsave(&sgpio_lock, flags);
+
+       val = readl(bank->chip.regs + offset);
+       val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
+       val |= SIRFSOC_GPIO_CTL_INTR_EN_MASK;
+       writel(val, bank->chip.regs + offset);
+
+       spin_unlock_irqrestore(&sgpio_lock, flags);
+}
+
+static int sirfsoc_gpio_irq_type(struct irq_data *d, unsigned type)
+{
+       struct sirfsoc_gpio_bank *bank = irq_data_get_irq_chip_data(d);
+       int idx = d->hwirq % SIRFSOC_GPIO_BANK_SIZE;
+       u32 val, offset;
+       unsigned long flags;
+
+       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
+
+       spin_lock_irqsave(&sgpio_lock, flags);
+
+       val = readl(bank->chip.regs + offset);
+       val &= ~SIRFSOC_GPIO_CTL_INTR_STS_MASK;
+
+       switch (type) {
+       case IRQ_TYPE_NONE:
+               break;
+       case IRQ_TYPE_EDGE_RISING:
+               val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
+               val &= ~SIRFSOC_GPIO_CTL_INTR_LOW_MASK;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               val &= ~SIRFSOC_GPIO_CTL_INTR_HIGH_MASK;
+               val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
+               break;
+       case IRQ_TYPE_EDGE_BOTH:
+               val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_LOW_MASK |
+                        SIRFSOC_GPIO_CTL_INTR_TYPE_MASK;
+               break;
+       case IRQ_TYPE_LEVEL_LOW:
+               val &= ~(SIRFSOC_GPIO_CTL_INTR_HIGH_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
+               val |= SIRFSOC_GPIO_CTL_INTR_LOW_MASK;
+               break;
+       case IRQ_TYPE_LEVEL_HIGH:
+               val |= SIRFSOC_GPIO_CTL_INTR_HIGH_MASK;
+               val &= ~(SIRFSOC_GPIO_CTL_INTR_LOW_MASK | SIRFSOC_GPIO_CTL_INTR_TYPE_MASK);
+               break;
+       }
+
+       writel(val, bank->chip.regs + offset);
+
+       spin_unlock_irqrestore(&sgpio_lock, flags);
+
+       return 0;
+}
+
+static struct irq_chip sirfsoc_irq_chip = {
+       .name = "sirf-gpio-irq",
+       .irq_ack = sirfsoc_gpio_irq_ack,
+       .irq_mask = sirfsoc_gpio_irq_mask,
+       .irq_unmask = sirfsoc_gpio_irq_unmask,
+       .irq_set_type = sirfsoc_gpio_irq_type,
+};
+
+static void sirfsoc_gpio_handle_irq(unsigned int irq, struct irq_desc *desc)
+{
+       struct sirfsoc_gpio_bank *bank = irq_get_handler_data(irq);
+       u32 status, ctrl;
+       int idx = 0;
+       unsigned int first_irq;
+
+       status = readl(bank->chip.regs + SIRFSOC_GPIO_INT_STATUS(bank->id));
+       if (!status) {
+               printk(KERN_WARNING
+                       "%s: gpio id %d status %#x no interrupt is flaged\n",
+                       __func__, bank->id, status);
+               handle_bad_irq(irq, desc);
+               return;
+       }
+
+       first_irq = bank->domain->revmap_data.legacy.first_irq;
+
+       while (status) {
+               ctrl = readl(bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, idx));
+
+               /*
+                * Here we must check whether the corresponding GPIO's interrupt
+                * has been enabled, otherwise just skip it
+                */
+               if ((status & 0x1) && (ctrl & SIRFSOC_GPIO_CTL_INTR_EN_MASK)) {
+                       pr_debug("%s: gpio id %d idx %d happens\n",
+                               __func__, bank->id, idx);
+                       generic_handle_irq(first_irq + idx);
+               }
+
+               idx++;
+               status = status >> 1;
+       }
+}
+
+static inline void sirfsoc_gpio_set_input(struct sirfsoc_gpio_bank *bank, unsigned ctrl_offset)
+{
+       u32 val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       val = readl(bank->chip.regs + ctrl_offset);
+       val &= ~SIRFSOC_GPIO_CTL_OUT_EN_MASK;
+       writel(val, bank->chip.regs + ctrl_offset);
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static int sirfsoc_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+       struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
+       unsigned long flags;
+
+       if (pinctrl_request_gpio(chip->base + offset))
+               return -ENODEV;
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       /*
+        * default status:
+        * set direction as input and mask irq
+        */
+       sirfsoc_gpio_set_input(bank, SIRFSOC_GPIO_CTRL(bank->id, offset));
+       __sirfsoc_gpio_irq_mask(bank, offset);
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return 0;
+}
+
+static void sirfsoc_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+       struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       __sirfsoc_gpio_irq_mask(bank, offset);
+       sirfsoc_gpio_set_input(bank, SIRFSOC_GPIO_CTRL(bank->id, offset));
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       pinctrl_free_gpio(chip->base + offset);
+}
+
+static int sirfsoc_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
+{
+       struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
+       int idx = sirfsoc_gpio_to_offset(gpio);
+       unsigned long flags;
+       unsigned offset;
+
+       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       sirfsoc_gpio_set_input(bank, offset);
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return 0;
+}
+
+static inline void sirfsoc_gpio_set_output(struct sirfsoc_gpio_bank *bank, unsigned offset,
+       int value)
+{
+       u32 out_ctrl;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       out_ctrl = readl(bank->chip.regs + offset);
+       if (value)
+               out_ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK;
+       else
+               out_ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK;
+
+       out_ctrl &= ~SIRFSOC_GPIO_CTL_INTR_EN_MASK;
+       out_ctrl |= SIRFSOC_GPIO_CTL_OUT_EN_MASK;
+       writel(out_ctrl, bank->chip.regs + offset);
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+static int sirfsoc_gpio_direction_output(struct gpio_chip *chip, unsigned gpio, int value)
+{
+       struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
+       int idx = sirfsoc_gpio_to_offset(gpio);
+       u32 offset;
+       unsigned long flags;
+
+       offset = SIRFSOC_GPIO_CTRL(bank->id, idx);
+
+       spin_lock_irqsave(&sgpio_lock, flags);
+
+       sirfsoc_gpio_set_output(bank, offset, value);
+
+       spin_unlock_irqrestore(&sgpio_lock, flags);
+
+       return 0;
+}
+
+static int sirfsoc_gpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+       struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
+       u32 val;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       val = readl(bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+
+       return !!(val & SIRFSOC_GPIO_CTL_DATAIN_MASK);
+}
+
+static void sirfsoc_gpio_set_value(struct gpio_chip *chip, unsigned offset,
+       int value)
+{
+       struct sirfsoc_gpio_bank *bank = sirfsoc_irqchip_to_bank(chip);
+       u32 ctrl;
+       unsigned long flags;
+
+       spin_lock_irqsave(&bank->lock, flags);
+
+       ctrl = readl(bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
+       if (value)
+               ctrl |= SIRFSOC_GPIO_CTL_DATAOUT_MASK;
+       else
+               ctrl &= ~SIRFSOC_GPIO_CTL_DATAOUT_MASK;
+       writel(ctrl, bank->chip.regs + SIRFSOC_GPIO_CTRL(bank->id, offset));
+
+       spin_unlock_irqrestore(&bank->lock, flags);
+}
+
+int sirfsoc_gpio_irq_map(struct irq_domain *d, unsigned int irq,
+       irq_hw_number_t hwirq)
+{
+       struct sirfsoc_gpio_bank *bank = d->host_data;
+
+       if (!bank)
+               return -EINVAL;
+
+       irq_set_chip(irq, &sirfsoc_irq_chip);
+       irq_set_handler(irq, handle_level_irq);
+       irq_set_chip_data(irq, bank);
+       set_irq_flags(irq, IRQF_VALID);
+
+       return 0;
+}
+
+const struct irq_domain_ops sirfsoc_gpio_irq_simple_ops = {
+       .map = sirfsoc_gpio_irq_map,
+       .xlate = irq_domain_xlate_twocell,
+};
+
+static int __devinit sirfsoc_gpio_probe(struct device_node *np)
+{
+       int i, err = 0;
+       struct sirfsoc_gpio_bank *bank;
+       void *regs;
+       struct platform_device *pdev;
+
+       pdev = of_find_device_by_node(np);
+       if (!pdev)
+               return -ENODEV;
+
+       regs = of_iomap(np, 0);
+       if (!regs)
+               return -ENOMEM;
+
+       for (i = 0; i < SIRFSOC_GPIO_NO_OF_BANKS; i++) {
+               bank = &sgpio_bank[i];
+               spin_lock_init(&bank->lock);
+               bank->chip.gc.request = sirfsoc_gpio_request;
+               bank->chip.gc.free = sirfsoc_gpio_free;
+               bank->chip.gc.direction_input = sirfsoc_gpio_direction_input;
+               bank->chip.gc.get = sirfsoc_gpio_get_value;
+               bank->chip.gc.direction_output = sirfsoc_gpio_direction_output;
+               bank->chip.gc.set = sirfsoc_gpio_set_value;
+               bank->chip.gc.to_irq = sirfsoc_gpio_to_irq;
+               bank->chip.gc.base = i * SIRFSOC_GPIO_BANK_SIZE;
+               bank->chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE;
+               bank->chip.gc.label = kstrdup(np->full_name, GFP_KERNEL);
+               bank->chip.gc.of_node = np;
+               bank->chip.regs = regs;
+               bank->id = i;
+               bank->parent_irq = platform_get_irq(pdev, i);
+               if (bank->parent_irq < 0) {
+                       err = bank->parent_irq;
+                       goto out;
+               }
+
+               err = gpiochip_add(&bank->chip.gc);
+               if (err) {
+                       pr_err("%s: error in probe function with status %d\n",
+                               np->full_name, err);
+                       goto out;
+               }
+
+               bank->domain = irq_domain_add_legacy(np, SIRFSOC_GPIO_BANK_SIZE,
+                       SIRFSOC_GPIO_IRQ_START + i * SIRFSOC_GPIO_BANK_SIZE, 0,
+                       &sirfsoc_gpio_irq_simple_ops, bank);
+
+               if (!bank->domain) {
+                       pr_err("%s: Failed to create irqdomain\n", np->full_name);
+                       err = -ENOSYS;
+                       goto out;
+               }
+
+               irq_set_chained_handler(bank->parent_irq, sirfsoc_gpio_handle_irq);
+               irq_set_handler_data(bank->parent_irq, bank);
+       }
+
+out:
+       iounmap(regs);
+       return err;
+}
+
+static int __init sirfsoc_gpio_init(void)
+{
+
+       struct device_node *np;
+
+       np = of_find_matching_node(NULL, pinmux_ids);
+
+       if (!np)
+               return -ENODEV;
+
+       return sirfsoc_gpio_probe(np);
+}
+subsys_initcall(sirfsoc_gpio_init);
+
 MODULE_AUTHOR("Rongjun Ying <rongjun.ying@csr.com>, "
+       "Yuping Luo <yuping.luo@csr.com>, "
        "Barry Song <baohua.song@csr.com>");
 MODULE_DESCRIPTION("SIRFSOC pin control driver");
 MODULE_LICENSE("GPL");
index ce875dc365e5f2ed0fa61dda0162fd1bb5be3cd1..c8f40c9c0428310c8dcf7db2110c73a119dc3150 100644 (file)
@@ -1877,8 +1877,7 @@ static int acer_platform_remove(struct platform_device *device)
        return 0;
 }
 
-static int acer_platform_suspend(struct platform_device *dev,
-pm_message_t state)
+static int acer_suspend(struct device *dev)
 {
        u32 value;
        struct acer_data *data = &interface->data;
@@ -1900,7 +1899,7 @@ pm_message_t state)
        return 0;
 }
 
-static int acer_platform_resume(struct platform_device *device)
+static int acer_resume(struct device *dev)
 {
        struct acer_data *data = &interface->data;
 
@@ -1916,6 +1915,8 @@ static int acer_platform_resume(struct platform_device *device)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(acer_pm, acer_suspend, acer_resume);
+
 static void acer_platform_shutdown(struct platform_device *device)
 {
        struct acer_data *data = &interface->data;
@@ -1931,11 +1932,10 @@ static struct platform_driver acer_platform_driver = {
        .driver = {
                .name = "acer-wmi",
                .owner = THIS_MODULE,
+               .pm = &acer_pm,
        },
        .probe = acer_platform_probe,
        .remove = acer_platform_remove,
-       .suspend = acer_platform_suspend,
-       .resume = acer_platform_resume,
        .shutdown = acer_platform_shutdown,
 };
 
index 94f93b621d7b67474808fb6c33cdf81248ca3936..e2230a2b2f8e3e82056ef7d197eb877999f337e9 100644 (file)
@@ -362,15 +362,18 @@ static int cmpc_tablet_remove(struct acpi_device *acpi, int type)
        return cmpc_remove_acpi_notify_device(acpi);
 }
 
-static int cmpc_tablet_resume(struct acpi_device *acpi)
+static int cmpc_tablet_resume(struct device *dev)
 {
-       struct input_dev *inputdev = dev_get_drvdata(&acpi->dev);
+       struct input_dev *inputdev = dev_get_drvdata(dev);
+
        unsigned long long val = 0;
-       if (ACPI_SUCCESS(cmpc_get_tablet(acpi->handle, &val)))
+       if (ACPI_SUCCESS(cmpc_get_tablet(to_acpi_device(dev)->handle, &val)))
                input_report_switch(inputdev, SW_TABLET_MODE, !val);
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(cmpc_tablet_pm, NULL, cmpc_tablet_resume);
+
 static const struct acpi_device_id cmpc_tablet_device_ids[] = {
        {CMPC_TABLET_HID, 0},
        {"", 0}
@@ -384,9 +387,9 @@ static struct acpi_driver cmpc_tablet_acpi_driver = {
        .ops = {
                .add = cmpc_tablet_add,
                .remove = cmpc_tablet_remove,
-               .resume = cmpc_tablet_resume,
                .notify = cmpc_tablet_handler,
-       }
+       },
+       .drv.pm = &cmpc_tablet_pm,
 };
 
 
index da267eae8ba85bc151fef55a0255a9d850429141..d2e41735a47b2d6178ef290211e0d13373ece570 100644 (file)
@@ -440,12 +440,14 @@ static int __devexit acpi_fujitsu_remove(struct acpi_device *adev, int type)
        return 0;
 }
 
-static int acpi_fujitsu_resume(struct acpi_device *adev)
+static int acpi_fujitsu_resume(struct device *dev)
 {
        fujitsu_reset();
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(acpi_fujitsu_pm, NULL, acpi_fujitsu_resume);
+
 static struct acpi_driver acpi_fujitsu_driver = {
        .name  = MODULENAME,
        .class = "hotkey",
@@ -453,8 +455,8 @@ static struct acpi_driver acpi_fujitsu_driver = {
        .ops   = {
                .add    = acpi_fujitsu_add,
                .remove = acpi_fujitsu_remove,
-               .resume = acpi_fujitsu_resume,
-       }
+       },
+       .drv.pm = &acpi_fujitsu_pm,
 };
 
 static int __init fujitsu_module_init(void)
index 24a3ae065f1b9ffce58f6c6aaa595f2384c11bac..d9ab6f64dcec0185148075dca8f4ef8fda1319bf 100644 (file)
@@ -305,17 +305,19 @@ static int hdaps_probe(struct platform_device *dev)
        return 0;
 }
 
-static int hdaps_resume(struct platform_device *dev)
+static int hdaps_resume(struct device *dev)
 {
        return hdaps_device_init();
 }
 
+static SIMPLE_DEV_PM_OPS(hdaps_pm, NULL, hdaps_resume);
+
 static struct platform_driver hdaps_driver = {
        .probe = hdaps_probe,
-       .resume = hdaps_resume,
        .driver = {
                .name = "hdaps",
                .owner = THIS_MODULE,
+               .pm = &hdaps_pm,
        },
 };
 
index 22b2dfa731480769ffbf18f6e447ee8ac54c5741..f4d91154ad67cca5d260cc681c5f7464dea0e87c 100644 (file)
@@ -353,20 +353,22 @@ static int lis3lv02d_remove(struct acpi_device *device, int type)
 
 
 #ifdef CONFIG_PM
-static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
+static int lis3lv02d_suspend(struct device *dev)
 {
        /* make sure the device is off when we suspend */
        lis3lv02d_poweroff(&lis3_dev);
        return 0;
 }
 
-static int lis3lv02d_resume(struct acpi_device *device)
+static int lis3lv02d_resume(struct device *dev)
 {
        return lis3lv02d_poweron(&lis3_dev);
 }
+
+static SIMPLE_DEV_PM_OPS(hp_accel_pm, lis3lv02d_suspend, lis3lv02d_resume);
+#define HP_ACCEL_PM (&hp_accel_pm)
 #else
-#define lis3lv02d_suspend NULL
-#define lis3lv02d_resume NULL
+#define HP_ACCEL_PM NULL
 #endif
 
 /* For the HP MDPS aka 3D Driveguard */
@@ -377,9 +379,8 @@ static struct acpi_driver lis3lv02d_driver = {
        .ops = {
                .add     = lis3lv02d_add,
                .remove  = lis3lv02d_remove,
-               .suspend = lis3lv02d_suspend,
-               .resume  = lis3lv02d_resume,
-       }
+       },
+       .drv.pm = HP_ACCEL_PM,
 };
 
 static int __init lis3lv02d_init_module(void)
index 9af4257d49018443b19e447455969787b480a944..5051aa970e0af3144c294516a92282ead76bb06b 100644 (file)
@@ -1719,21 +1719,6 @@ static void ips_remove(struct pci_dev *dev)
        dev_dbg(&dev->dev, "IPS driver removed\n");
 }
 
-#ifdef CONFIG_PM
-static int ips_suspend(struct pci_dev *dev, pm_message_t state)
-{
-       return 0;
-}
-
-static int ips_resume(struct pci_dev *dev)
-{
-       return 0;
-}
-#else
-#define ips_suspend NULL
-#define ips_resume NULL
-#endif /* CONFIG_PM */
-
 static void ips_shutdown(struct pci_dev *dev)
 {
 }
@@ -1743,8 +1728,6 @@ static struct pci_driver ips_pci_driver = {
        .id_table = ips_id_table,
        .probe = ips_probe,
        .remove = ips_remove,
-       .suspend = ips_suspend,
-       .resume = ips_resume,
        .shutdown = ips_shutdown,
 };
 
index 5ae9cd9c7e6e10f4da2dc254725f397286598731..ea7422f6fa0343328c2074e4df63d60488d55f9b 100644 (file)
@@ -418,23 +418,23 @@ static struct thermal_device_info *initialize_sensor(int index)
 
 /**
  * mid_thermal_resume - resume routine
- * @pdev: platform device structure
+ * @dev: device structure
  *
  * mid thermal resume: re-initializes the adc. Can sleep.
  */
-static int mid_thermal_resume(struct platform_device *pdev)
+static int mid_thermal_resume(struct device *dev)
 {
-       return mid_initialize_adc(&pdev->dev);
+       return mid_initialize_adc(dev);
 }
 
 /**
  * mid_thermal_suspend - suspend routine
- * @pdev: platform device structure
+ * @dev: device structure
  *
  * mid thermal suspend implements the suspend functionality
  * by stopping the ADC. Can sleep.
  */
-static int mid_thermal_suspend(struct platform_device *pdev, pm_message_t mesg)
+static int mid_thermal_suspend(struct device *dev)
 {
        /*
         * This just stops the ADC and does not disable it.
@@ -444,6 +444,9 @@ static int mid_thermal_suspend(struct platform_device *pdev, pm_message_t mesg)
        return configure_adc(0);
 }
 
+static SIMPLE_DEV_PM_OPS(mid_thermal_pm,
+                        mid_thermal_suspend, mid_thermal_resume);
+
 /**
  * read_curr_temp - reads the current temperature and stores in temp
  * @temp: holds the current temperature value after reading
@@ -557,10 +560,9 @@ static struct platform_driver mid_thermal_driver = {
        .driver = {
                .name = DRIVER_NAME,
                .owner = THIS_MODULE,
+               .pm = &mid_thermal_pm,
        },
        .probe = mid_thermal_probe,
-       .suspend = mid_thermal_suspend,
-       .resume = mid_thermal_resume,
        .remove = __devexit_p(mid_thermal_remove),
        .id_table = therm_id_table,
 };
index bb5132128b339235f599969d75a692bd4099dfce..f64441844317f513c6ec8db521fb0bad37afbda8 100644 (file)
@@ -85,7 +85,8 @@
 #define MSI_STANDARD_EC_TOUCHPAD_ADDRESS       0xe4
 #define MSI_STANDARD_EC_TOUCHPAD_MASK          (1 << 4)
 
-static int msi_laptop_resume(struct platform_device *device);
+static int msi_laptop_resume(struct device *device);
+static SIMPLE_DEV_PM_OPS(msi_laptop_pm, NULL, msi_laptop_resume);
 
 #define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS 0x2f
 
@@ -437,8 +438,8 @@ static struct platform_driver msipf_driver = {
        .driver = {
                .name = "msi-laptop-pf",
                .owner = THIS_MODULE,
+               .pm = &msi_laptop_pm,
        },
-       .resume = msi_laptop_resume,
 };
 
 static struct platform_device *msipf_device;
@@ -752,7 +753,7 @@ err_bluetooth:
        return retval;
 }
 
-static int msi_laptop_resume(struct platform_device *device)
+static int msi_laptop_resume(struct device *device)
 {
        u8 data;
        int result;
index ffff8b4b4949502dbc56997f873594da7314b4b4..24480074bcf047c40b219dcf5b055ce829d865d7 100644 (file)
@@ -177,7 +177,6 @@ enum SINF_BITS { SINF_NUM_BATTERIES = 0,
 
 static int acpi_pcc_hotkey_add(struct acpi_device *device);
 static int acpi_pcc_hotkey_remove(struct acpi_device *device, int type);
-static int acpi_pcc_hotkey_resume(struct acpi_device *device);
 static void acpi_pcc_hotkey_notify(struct acpi_device *device, u32 event);
 
 static const struct acpi_device_id pcc_device_ids[] = {
@@ -189,6 +188,9 @@ static const struct acpi_device_id pcc_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, pcc_device_ids);
 
+static int acpi_pcc_hotkey_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(acpi_pcc_hotkey_pm, NULL, acpi_pcc_hotkey_resume);
+
 static struct acpi_driver acpi_pcc_driver = {
        .name =         ACPI_PCC_DRIVER_NAME,
        .class =        ACPI_PCC_CLASS,
@@ -196,9 +198,9 @@ static struct acpi_driver acpi_pcc_driver = {
        .ops =          {
                                .add =          acpi_pcc_hotkey_add,
                                .remove =       acpi_pcc_hotkey_remove,
-                               .resume =       acpi_pcc_hotkey_resume,
                                .notify =       acpi_pcc_hotkey_notify,
                        },
+       .drv.pm =       &acpi_pcc_hotkey_pm,
 };
 
 static const struct key_entry panasonic_keymap[] = {
@@ -538,11 +540,15 @@ static void acpi_pcc_destroy_input(struct pcc_acpi *pcc)
 
 /* kernel module interface */
 
-static int acpi_pcc_hotkey_resume(struct acpi_device *device)
+static int acpi_pcc_hotkey_resume(struct device *dev)
 {
-       struct pcc_acpi *pcc = acpi_driver_data(device);
+       struct pcc_acpi *pcc;
+
+       if (!dev)
+               return -EINVAL;
 
-       if (device == NULL || pcc == NULL)
+       pcc = acpi_driver_data(to_acpi_device(dev));
+       if (!pcc)
                return -EINVAL;
 
        ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Sticky mode restore: %d\n",
index d456ff0c73b73614339d4109c1bc282037c64e08..9363969ad07adf65cefe1a6aa918ca47363ca907 100644 (file)
@@ -1477,7 +1477,7 @@ static void sony_nc_function_resume(void)
                                &result);
 }
 
-static int sony_nc_resume(struct acpi_device *device)
+static int sony_nc_resume(struct device *dev)
 {
        struct sony_nc_value *item;
        acpi_handle handle;
@@ -1509,6 +1509,8 @@ static int sony_nc_resume(struct acpi_device *device)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(sony_nc_pm, NULL, sony_nc_resume);
+
 static void sony_nc_rfkill_cleanup(void)
 {
        int i;
@@ -2770,9 +2772,9 @@ static struct acpi_driver sony_nc_driver = {
        .ops = {
                .add = sony_nc_add,
                .remove = sony_nc_remove,
-               .resume = sony_nc_resume,
                .notify = sony_nc_notify,
                },
+       .drv.pm = &sony_nc_pm,
 };
 
 /*********** SPIC (SNY6001) Device ***********/
@@ -4285,19 +4287,22 @@ err_free_resources:
        return result;
 }
 
-static int sony_pic_suspend(struct acpi_device *device, pm_message_t state)
+static int sony_pic_suspend(struct device *dev)
 {
-       if (sony_pic_disable(device))
+       if (sony_pic_disable(to_acpi_device(dev)))
                return -ENXIO;
        return 0;
 }
 
-static int sony_pic_resume(struct acpi_device *device)
+static int sony_pic_resume(struct device *dev)
 {
-       sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
+       sony_pic_enable(to_acpi_device(dev),
+                       spic_dev.cur_ioport, spic_dev.cur_irq);
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(sony_pic_pm, sony_pic_suspend, sony_pic_resume);
+
 static const struct acpi_device_id sony_pic_device_ids[] = {
        {SONY_PIC_HID, 0},
        {"", 0},
@@ -4311,9 +4316,8 @@ static struct acpi_driver sony_pic_driver = {
        .ops = {
                .add = sony_pic_add,
                .remove = sony_pic_remove,
-               .suspend = sony_pic_suspend,
-               .resume = sony_pic_resume,
                },
+       .drv.pm = &sony_pic_pm,
 };
 
 static struct dmi_system_id __initdata sonypi_dmi_table[] = {
index 8b5610d884186b63b693b6b7aee2ceb705fc47ee..d5fd4a1193f84e9fd3db93835962a86bd8aefbac 100644 (file)
@@ -277,7 +277,7 @@ struct ibm_struct {
        int (*write) (char *);
        void (*exit) (void);
        void (*resume) (void);
-       void (*suspend) (pm_message_t state);
+       void (*suspend) (void);
        void (*shutdown) (void);
 
        struct list_head all_drivers;
@@ -922,8 +922,7 @@ static struct input_dev *tpacpi_inputdev;
 static struct mutex tpacpi_inputdev_send_mutex;
 static LIST_HEAD(tpacpi_all_drivers);
 
-static int tpacpi_suspend_handler(struct platform_device *pdev,
-                                 pm_message_t state)
+static int tpacpi_suspend_handler(struct device *dev)
 {
        struct ibm_struct *ibm, *itmp;
 
@@ -931,13 +930,13 @@ static int tpacpi_suspend_handler(struct platform_device *pdev,
                                 &tpacpi_all_drivers,
                                 all_drivers) {
                if (ibm->suspend)
-                       (ibm->suspend)(state);
+                       (ibm->suspend)();
        }
 
        return 0;
 }
 
-static int tpacpi_resume_handler(struct platform_device *pdev)
+static int tpacpi_resume_handler(struct device *dev)
 {
        struct ibm_struct *ibm, *itmp;
 
@@ -951,6 +950,9 @@ static int tpacpi_resume_handler(struct platform_device *pdev)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(tpacpi_pm,
+                        tpacpi_suspend_handler, tpacpi_resume_handler);
+
 static void tpacpi_shutdown_handler(struct platform_device *pdev)
 {
        struct ibm_struct *ibm, *itmp;
@@ -967,9 +969,8 @@ static struct platform_driver tpacpi_pdriver = {
        .driver = {
                .name = TPACPI_DRVR_NAME,
                .owner = THIS_MODULE,
+               .pm = &tpacpi_pm,
        },
-       .suspend = tpacpi_suspend_handler,
-       .resume = tpacpi_resume_handler,
        .shutdown = tpacpi_shutdown_handler,
 };
 
@@ -3758,7 +3759,7 @@ static void hotkey_notify(struct ibm_struct *ibm, u32 event)
        }
 }
 
-static void hotkey_suspend(pm_message_t state)
+static void hotkey_suspend(void)
 {
        /* Do these on suspend, we get the events on early resume! */
        hotkey_wakeup_reason = TP_ACPI_WAKEUP_NONE;
@@ -6329,7 +6330,7 @@ static int __init brightness_init(struct ibm_init_struct *iibm)
        return 0;
 }
 
-static void brightness_suspend(pm_message_t state)
+static void brightness_suspend(void)
 {
        tpacpi_brightness_checkpoint_nvram();
 }
@@ -6748,7 +6749,7 @@ static struct snd_kcontrol_new volume_alsa_control_mute __devinitdata = {
        .get = volume_alsa_mute_get,
 };
 
-static void volume_suspend(pm_message_t state)
+static void volume_suspend(void)
 {
        tpacpi_volume_checkpoint_nvram();
 }
@@ -8107,7 +8108,7 @@ static void fan_exit(void)
        flush_workqueue(tpacpi_wq);
 }
 
-static void fan_suspend(pm_message_t state)
+static void fan_suspend(void)
 {
        int rc;
 
index dab10f6edcd43186e2af9a397d909a0ce607694f..c13ba5bac93f1c594f22ecb1b6e701586793a081 100644 (file)
@@ -1296,10 +1296,9 @@ static void toshiba_acpi_notify(struct acpi_device *acpi_dev, u32 event)
        }
 }
 
-static int toshiba_acpi_suspend(struct acpi_device *acpi_dev,
-                               pm_message_t state)
+static int toshiba_acpi_suspend(struct device *device)
 {
-       struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
+       struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device));
        u32 result;
 
        if (dev->hotkey_dev)
@@ -1308,9 +1307,9 @@ static int toshiba_acpi_suspend(struct acpi_device *acpi_dev,
        return 0;
 }
 
-static int toshiba_acpi_resume(struct acpi_device *acpi_dev)
+static int toshiba_acpi_resume(struct device *device)
 {
-       struct toshiba_acpi_dev *dev = acpi_driver_data(acpi_dev);
+       struct toshiba_acpi_dev *dev = acpi_driver_data(to_acpi_device(device));
        u32 result;
 
        if (dev->hotkey_dev)
@@ -1319,6 +1318,9 @@ static int toshiba_acpi_resume(struct acpi_device *acpi_dev)
        return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(toshiba_acpi_pm,
+                        toshiba_acpi_suspend, toshiba_acpi_resume);
+
 static struct acpi_driver toshiba_acpi_driver = {
        .name   = "Toshiba ACPI driver",
        .owner  = THIS_MODULE,
@@ -1328,9 +1330,8 @@ static struct acpi_driver toshiba_acpi_driver = {
                .add            = toshiba_acpi_add,
                .remove         = toshiba_acpi_remove,
                .notify         = toshiba_acpi_notify,
-               .suspend        = toshiba_acpi_suspend,
-               .resume         = toshiba_acpi_resume,
        },
+       .drv.pm = &toshiba_acpi_pm,
 };
 
 static int __init toshiba_acpi_init(void)
index 5fb7186694df034f85d47fd6c3d5e8a03ac5a51b..715a43cb5e3c49020c24a07c302ec3792fcce84a 100644 (file)
@@ -34,7 +34,6 @@ MODULE_LICENSE("GPL");
 static int toshiba_bt_rfkill_add(struct acpi_device *device);
 static int toshiba_bt_rfkill_remove(struct acpi_device *device, int type);
 static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event);
-static int toshiba_bt_resume(struct acpi_device *device);
 
 static const struct acpi_device_id bt_device_ids[] = {
        { "TOS6205", 0},
@@ -42,6 +41,9 @@ static const struct acpi_device_id bt_device_ids[] = {
 };
 MODULE_DEVICE_TABLE(acpi, bt_device_ids);
 
+static int toshiba_bt_resume(struct device *dev);
+static SIMPLE_DEV_PM_OPS(toshiba_bt_pm, NULL, toshiba_bt_resume);
+
 static struct acpi_driver toshiba_bt_rfkill_driver = {
        .name =         "Toshiba BT",
        .class =        "Toshiba",
@@ -50,9 +52,9 @@ static struct acpi_driver toshiba_bt_rfkill_driver = {
                                .add =          toshiba_bt_rfkill_add,
                                .remove =       toshiba_bt_rfkill_remove,
                                .notify =       toshiba_bt_rfkill_notify,
-                               .resume =       toshiba_bt_resume,
                        },
        .owner =        THIS_MODULE,
+       .drv.pm =       &toshiba_bt_pm,
 };
 
 
@@ -88,9 +90,9 @@ static void toshiba_bt_rfkill_notify(struct acpi_device *device, u32 event)
        toshiba_bluetooth_enable(device->handle);
 }
 
-static int toshiba_bt_resume(struct acpi_device *device)
+static int toshiba_bt_resume(struct device *dev)
 {
-       return toshiba_bluetooth_enable(device->handle);
+       return toshiba_bluetooth_enable(to_acpi_device(dev)->handle);
 }
 
 static int toshiba_bt_rfkill_add(struct acpi_device *device)
index fad153dc0355e33db828fe6d3e12ef97bea2b429..849c07c13bf6cae790c3e99dfb402f55b88a2a1f 100644 (file)
@@ -77,11 +77,13 @@ static void ebook_switch_notify(struct acpi_device *device, u32 event)
        }
 }
 
-static int ebook_switch_resume(struct acpi_device *device)
+static int ebook_switch_resume(struct device *dev)
 {
-       return ebook_send_state(device);
+       return ebook_send_state(to_acpi_device(dev));
 }
 
+static SIMPLE_DEV_PM_OPS(ebook_switch_pm, NULL, ebook_switch_resume);
+
 static int ebook_switch_add(struct acpi_device *device)
 {
        struct ebook_switch *button;
@@ -161,10 +163,10 @@ static struct acpi_driver xo15_ebook_driver = {
        .ids = ebook_device_ids,
        .ops = {
                .add = ebook_switch_add,
-               .resume = ebook_switch_resume,
                .remove = ebook_switch_remove,
                .notify = ebook_switch_notify,
        },
+       .drv.pm = &ebook_switch_pm,
 };
 
 static int __init xo15_ebook_init(void)
index e3a3b4956f08408741fe5856a562b8defe7294a1..70b4a979a6fff01fbef9bd29ba7cd5982cd3a1d3 100644 (file)
@@ -310,3 +310,5 @@ config AB8500_BATTERY_THERM_ON_BATCTRL
          Say Y to enable battery temperature measurements using
          thermistor connected on BATCTRL ADC.
 endif # POWER_SUPPLY
+
+source "drivers/power/avs/Kconfig"
index b6b243416c0ee1947a47efd85b205341dc0f1463..ee58afb1e71f41358b27c7ace8ed6b57a803ee9f 100644 (file)
@@ -43,4 +43,5 @@ obj-$(CONFIG_CHARGER_GPIO)    += gpio-charger.o
 obj-$(CONFIG_CHARGER_MANAGER)  += charger-manager.o
 obj-$(CONFIG_CHARGER_MAX8997)  += max8997_charger.o
 obj-$(CONFIG_CHARGER_MAX8998)  += max8998_charger.o
+obj-$(CONFIG_POWER_AVS)                += avs/
 obj-$(CONFIG_CHARGER_SMB347)   += smb347-charger.o
diff --git a/drivers/power/avs/Kconfig b/drivers/power/avs/Kconfig
new file mode 100644 (file)
index 0000000..2a1008b
--- /dev/null
@@ -0,0 +1,12 @@
+menuconfig POWER_AVS
+       bool "Adaptive Voltage Scaling class support"
+       help
+         AVS is a power management technique which finely controls the
+         operating voltage of a device in order to optimize (i.e. reduce)
+         its power consumption.
+         At a given operating point the voltage is adapted depending on
+         static factors (chip manufacturing process) and dynamic factors
+         (temperature depending performance).
+         AVS is also called SmartReflex on OMAP devices.
+
+         Say Y here to enable Adaptive Voltage Scaling class support.
diff --git a/drivers/power/avs/Makefile b/drivers/power/avs/Makefile
new file mode 100644 (file)
index 0000000..0843386
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_POWER_AVS_OMAP)           += smartreflex.o
diff --git a/drivers/power/avs/smartreflex.c b/drivers/power/avs/smartreflex.c
new file mode 100644 (file)
index 0000000..44efc6e
--- /dev/null
@@ -0,0 +1,1126 @@
+/*
+ * OMAP SmartReflex Voltage Control
+ *
+ * Author: Thara Gopinath      <thara@ti.com>
+ *
+ * Copyright (C) 2012 Texas Instruments, Inc.
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <x0080970@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <linux/power/smartreflex.h>
+
+#define SMARTREFLEX_NAME_LEN   16
+#define NVALUE_NAME_LEN                40
+#define SR_DISABLE_TIMEOUT     200
+
+/* sr_list contains all the instances of smartreflex module */
+static LIST_HEAD(sr_list);
+
+static struct omap_sr_class_data *sr_class;
+static struct omap_sr_pmic_data *sr_pmic_data;
+static struct dentry           *sr_dbg_dir;
+
+static inline void sr_write_reg(struct omap_sr *sr, unsigned offset, u32 value)
+{
+       __raw_writel(value, (sr->base + offset));
+}
+
+static inline void sr_modify_reg(struct omap_sr *sr, unsigned offset, u32 mask,
+                                       u32 value)
+{
+       u32 reg_val;
+
+       /*
+        * Smartreflex error config register is special as it contains
+        * certain status bits which if written a 1 into means a clear
+        * of those bits. So in order to make sure no accidental write of
+        * 1 happens to those status bits, do a clear of them in the read
+        * value. This mean this API doesn't rewrite values in these bits
+        * if they are currently set, but does allow the caller to write
+        * those bits.
+        */
+       if (sr->ip_type == SR_TYPE_V1 && offset == ERRCONFIG_V1)
+               mask |= ERRCONFIG_STATUS_V1_MASK;
+       else if (sr->ip_type == SR_TYPE_V2 && offset == ERRCONFIG_V2)
+               mask |= ERRCONFIG_VPBOUNDINTST_V2;
+
+       reg_val = __raw_readl(sr->base + offset);
+       reg_val &= ~mask;
+
+       value &= mask;
+
+       reg_val |= value;
+
+       __raw_writel(reg_val, (sr->base + offset));
+}
+
+static inline u32 sr_read_reg(struct omap_sr *sr, unsigned offset)
+{
+       return __raw_readl(sr->base + offset);
+}
+
+static struct omap_sr *_sr_lookup(struct voltagedomain *voltdm)
+{
+       struct omap_sr *sr_info;
+
+       if (!voltdm) {
+               pr_err("%s: Null voltage domain passed!\n", __func__);
+               return ERR_PTR(-EINVAL);
+       }
+
+       list_for_each_entry(sr_info, &sr_list, node) {
+               if (voltdm == sr_info->voltdm)
+                       return sr_info;
+       }
+
+       return ERR_PTR(-ENODATA);
+}
+
+static irqreturn_t sr_interrupt(int irq, void *data)
+{
+       struct omap_sr *sr_info = data;
+       u32 status = 0;
+
+       switch (sr_info->ip_type) {
+       case SR_TYPE_V1:
+               /* Read the status bits */
+               status = sr_read_reg(sr_info, ERRCONFIG_V1);
+
+               /* Clear them by writing back */
+               sr_write_reg(sr_info, ERRCONFIG_V1, status);
+               break;
+       case SR_TYPE_V2:
+               /* Read the status bits */
+               status = sr_read_reg(sr_info, IRQSTATUS);
+
+               /* Clear them by writing back */
+               sr_write_reg(sr_info, IRQSTATUS, status);
+               break;
+       default:
+               dev_err(&sr_info->pdev->dev, "UNKNOWN IP type %d\n",
+                       sr_info->ip_type);
+               return IRQ_NONE;
+       }
+
+       if (sr_class->notify)
+               sr_class->notify(sr_info, status);
+
+       return IRQ_HANDLED;
+}
+
+static void sr_set_clk_length(struct omap_sr *sr)
+{
+       struct clk *sys_ck;
+       u32 sys_clk_speed;
+
+       if (cpu_is_omap34xx())
+               sys_ck = clk_get(NULL, "sys_ck");
+       else
+               sys_ck = clk_get(NULL, "sys_clkin_ck");
+
+       if (IS_ERR(sys_ck)) {
+               dev_err(&sr->pdev->dev, "%s: unable to get sys clk\n",
+                       __func__);
+               return;
+       }
+
+       sys_clk_speed = clk_get_rate(sys_ck);
+       clk_put(sys_ck);
+
+       switch (sys_clk_speed) {
+       case 12000000:
+               sr->clk_length = SRCLKLENGTH_12MHZ_SYSCLK;
+               break;
+       case 13000000:
+               sr->clk_length = SRCLKLENGTH_13MHZ_SYSCLK;
+               break;
+       case 19200000:
+               sr->clk_length = SRCLKLENGTH_19MHZ_SYSCLK;
+               break;
+       case 26000000:
+               sr->clk_length = SRCLKLENGTH_26MHZ_SYSCLK;
+               break;
+       case 38400000:
+               sr->clk_length = SRCLKLENGTH_38MHZ_SYSCLK;
+               break;
+       default:
+               dev_err(&sr->pdev->dev, "%s: Invalid sysclk value: %d\n",
+                       __func__, sys_clk_speed);
+               break;
+       }
+}
+
+static void sr_set_regfields(struct omap_sr *sr)
+{
+       /*
+        * For time being these values are defined in smartreflex.h
+        * and populated during init. May be they can be moved to board
+        * file or pmic specific data structure. In that case these structure
+        * fields will have to be populated using the pdata or pmic structure.
+        */
+       if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+               sr->err_weight = OMAP3430_SR_ERRWEIGHT;
+               sr->err_maxlimit = OMAP3430_SR_ERRMAXLIMIT;
+               sr->accum_data = OMAP3430_SR_ACCUMDATA;
+               if (!(strcmp(sr->name, "smartreflex_mpu_iva"))) {
+                       sr->senn_avgweight = OMAP3430_SR1_SENNAVGWEIGHT;
+                       sr->senp_avgweight = OMAP3430_SR1_SENPAVGWEIGHT;
+               } else {
+                       sr->senn_avgweight = OMAP3430_SR2_SENNAVGWEIGHT;
+                       sr->senp_avgweight = OMAP3430_SR2_SENPAVGWEIGHT;
+               }
+       }
+}
+
+static void sr_start_vddautocomp(struct omap_sr *sr)
+{
+       if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
+               dev_warn(&sr->pdev->dev,
+                       "%s: smartreflex class driver not registered\n",
+                       __func__);
+               return;
+       }
+
+       if (!sr_class->enable(sr))
+               sr->autocomp_active = true;
+}
+
+static void sr_stop_vddautocomp(struct omap_sr *sr)
+{
+       if (!sr_class || !(sr_class->disable)) {
+               dev_warn(&sr->pdev->dev,
+                       "%s: smartreflex class driver not registered\n",
+                       __func__);
+               return;
+       }
+
+       if (sr->autocomp_active) {
+               sr_class->disable(sr, 1);
+               sr->autocomp_active = false;
+       }
+}
+
+/*
+ * This function handles the intializations which have to be done
+ * only when both sr device and class driver regiter has
+ * completed. This will be attempted to be called from both sr class
+ * driver register and sr device intializtion API's. Only one call
+ * will ultimately succeed.
+ *
+ * Currently this function registers interrupt handler for a particular SR
+ * if smartreflex class driver is already registered and has
+ * requested for interrupts and the SR interrupt line in present.
+ */
+static int sr_late_init(struct omap_sr *sr_info)
+{
+       struct omap_sr_data *pdata = sr_info->pdev->dev.platform_data;
+       struct resource *mem;
+       int ret = 0;
+
+       if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
+               ret = request_irq(sr_info->irq, sr_interrupt,
+                                 0, sr_info->name, sr_info);
+               if (ret)
+                       goto error;
+               disable_irq(sr_info->irq);
+       }
+
+       if (pdata && pdata->enable_on_init)
+               sr_start_vddautocomp(sr_info);
+
+       return ret;
+
+error:
+       iounmap(sr_info->base);
+       mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
+       release_mem_region(mem->start, resource_size(mem));
+       list_del(&sr_info->node);
+       dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
+               "interrupt handler. Smartreflex will"
+               "not function as desired\n", __func__);
+       kfree(sr_info);
+
+       return ret;
+}
+
+static void sr_v1_disable(struct omap_sr *sr)
+{
+       int timeout = 0;
+       int errconf_val = ERRCONFIG_MCUACCUMINTST | ERRCONFIG_MCUVALIDINTST |
+                       ERRCONFIG_MCUBOUNDINTST;
+
+       /* Enable MCUDisableAcknowledge interrupt */
+       sr_modify_reg(sr, ERRCONFIG_V1,
+                       ERRCONFIG_MCUDISACKINTEN, ERRCONFIG_MCUDISACKINTEN);
+
+       /* SRCONFIG - disable SR */
+       sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
+
+       /* Disable all other SR interrupts and clear the status as needed */
+       if (sr_read_reg(sr, ERRCONFIG_V1) & ERRCONFIG_VPBOUNDINTST_V1)
+               errconf_val |= ERRCONFIG_VPBOUNDINTST_V1;
+       sr_modify_reg(sr, ERRCONFIG_V1,
+                       (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
+                       ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_VPBOUNDINTEN_V1),
+                       errconf_val);
+
+       /*
+        * Wait for SR to be disabled.
+        * wait until ERRCONFIG.MCUDISACKINTST = 1. Typical latency is 1us.
+        */
+       sr_test_cond_timeout((sr_read_reg(sr, ERRCONFIG_V1) &
+                            ERRCONFIG_MCUDISACKINTST), SR_DISABLE_TIMEOUT,
+                            timeout);
+
+       if (timeout >= SR_DISABLE_TIMEOUT)
+               dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
+                       __func__);
+
+       /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
+       sr_modify_reg(sr, ERRCONFIG_V1, ERRCONFIG_MCUDISACKINTEN,
+                       ERRCONFIG_MCUDISACKINTST);
+}
+
+static void sr_v2_disable(struct omap_sr *sr)
+{
+       int timeout = 0;
+
+       /* Enable MCUDisableAcknowledge interrupt */
+       sr_write_reg(sr, IRQENABLE_SET, IRQENABLE_MCUDISABLEACKINT);
+
+       /* SRCONFIG - disable SR */
+       sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, 0x0);
+
+       /*
+        * Disable all other SR interrupts and clear the status
+        * write to status register ONLY on need basis - only if status
+        * is set.
+        */
+       if (sr_read_reg(sr, ERRCONFIG_V2) & ERRCONFIG_VPBOUNDINTST_V2)
+               sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
+                       ERRCONFIG_VPBOUNDINTST_V2);
+       else
+               sr_modify_reg(sr, ERRCONFIG_V2, ERRCONFIG_VPBOUNDINTEN_V2,
+                               0x0);
+       sr_write_reg(sr, IRQENABLE_CLR, (IRQENABLE_MCUACCUMINT |
+                       IRQENABLE_MCUVALIDINT |
+                       IRQENABLE_MCUBOUNDSINT));
+       sr_write_reg(sr, IRQSTATUS, (IRQSTATUS_MCUACCUMINT |
+                       IRQSTATUS_MCVALIDINT |
+                       IRQSTATUS_MCBOUNDSINT));
+
+       /*
+        * Wait for SR to be disabled.
+        * wait until IRQSTATUS.MCUDISACKINTST = 1. Typical latency is 1us.
+        */
+       sr_test_cond_timeout((sr_read_reg(sr, IRQSTATUS) &
+                            IRQSTATUS_MCUDISABLEACKINT), SR_DISABLE_TIMEOUT,
+                            timeout);
+
+       if (timeout >= SR_DISABLE_TIMEOUT)
+               dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
+                       __func__);
+
+       /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
+       sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT);
+       sr_write_reg(sr, IRQSTATUS, IRQSTATUS_MCUDISABLEACKINT);
+}
+
+static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row(
+                               struct omap_sr *sr, u32 efuse_offs)
+{
+       int i;
+
+       if (!sr->nvalue_table) {
+               dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n",
+                       __func__);
+               return NULL;
+       }
+
+       for (i = 0; i < sr->nvalue_count; i++) {
+               if (sr->nvalue_table[i].efuse_offs == efuse_offs)
+                       return &sr->nvalue_table[i];
+       }
+
+       return NULL;
+}
+
+/* Public Functions */
+
+/**
+ * sr_configure_errgen() - Configures the smrtreflex to perform AVS using the
+ *                      error generator module.
+ * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * configure the error generator module inside the smartreflex module.
+ * SR settings if using the ERROR module inside Smartreflex.
+ * SR CLASS 3 by default uses only the ERROR module where as
+ * SR CLASS 2 can choose between ERROR module and MINMAXAVG
+ * module. Returns 0 on success and error value in case of failure.
+ */
+int sr_configure_errgen(struct voltagedomain *voltdm)
+{
+       u32 sr_config, sr_errconfig, errconfig_offs;
+       u32 vpboundint_en, vpboundint_st;
+       u32 senp_en = 0, senn_en = 0;
+       u8 senp_shift, senn_shift;
+       struct omap_sr *sr = _sr_lookup(voltdm);
+
+       if (IS_ERR(sr)) {
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
+               return PTR_ERR(sr);
+       }
+
+       if (!sr->clk_length)
+               sr_set_clk_length(sr);
+
+       senp_en = sr->senp_mod;
+       senn_en = sr->senn_mod;
+
+       sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
+               SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN;
+
+       switch (sr->ip_type) {
+       case SR_TYPE_V1:
+               sr_config |= SRCONFIG_DELAYCTRL;
+               senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
+               senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
+               errconfig_offs = ERRCONFIG_V1;
+               vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
+               vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
+               break;
+       case SR_TYPE_V2:
+               senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
+               senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
+               errconfig_offs = ERRCONFIG_V2;
+               vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
+               vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
+               break;
+       default:
+               dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
+                       "module without specifying the ip\n", __func__);
+               return -EINVAL;
+       }
+
+       sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
+       sr_write_reg(sr, SRCONFIG, sr_config);
+       sr_errconfig = (sr->err_weight << ERRCONFIG_ERRWEIGHT_SHIFT) |
+               (sr->err_maxlimit << ERRCONFIG_ERRMAXLIMIT_SHIFT) |
+               (sr->err_minlimit <<  ERRCONFIG_ERRMINLIMIT_SHIFT);
+       sr_modify_reg(sr, errconfig_offs, (SR_ERRWEIGHT_MASK |
+               SR_ERRMAXLIMIT_MASK | SR_ERRMINLIMIT_MASK),
+               sr_errconfig);
+
+       /* Enabling the interrupts if the ERROR module is used */
+       sr_modify_reg(sr, errconfig_offs, (vpboundint_en | vpboundint_st),
+                     vpboundint_en);
+
+       return 0;
+}
+
+/**
+ * sr_disable_errgen() - Disables SmartReflex AVS module's errgen component
+ * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * disable the error generator module inside the smartreflex module.
+ *
+ * Returns 0 on success and error value in case of failure.
+ */
+int sr_disable_errgen(struct voltagedomain *voltdm)
+{
+       u32 errconfig_offs;
+       u32 vpboundint_en, vpboundint_st;
+       struct omap_sr *sr = _sr_lookup(voltdm);
+
+       if (IS_ERR(sr)) {
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
+               return PTR_ERR(sr);
+       }
+
+       switch (sr->ip_type) {
+       case SR_TYPE_V1:
+               errconfig_offs = ERRCONFIG_V1;
+               vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V1;
+               vpboundint_st = ERRCONFIG_VPBOUNDINTST_V1;
+               break;
+       case SR_TYPE_V2:
+               errconfig_offs = ERRCONFIG_V2;
+               vpboundint_en = ERRCONFIG_VPBOUNDINTEN_V2;
+               vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
+               break;
+       default:
+               dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
+                       "module without specifying the ip\n", __func__);
+               return -EINVAL;
+       }
+
+       /* Disable the interrupts of ERROR module */
+       sr_modify_reg(sr, errconfig_offs, vpboundint_en | vpboundint_st, 0);
+
+       /* Disable the Sensor and errorgen */
+       sr_modify_reg(sr, SRCONFIG, SRCONFIG_SENENABLE | SRCONFIG_ERRGEN_EN, 0);
+
+       return 0;
+}
+
+/**
+ * sr_configure_minmax() - Configures the smrtreflex to perform AVS using the
+ *                      minmaxavg module.
+ * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * configure the minmaxavg module inside the smartreflex module.
+ * SR settings if using the ERROR module inside Smartreflex.
+ * SR CLASS 3 by default uses only the ERROR module where as
+ * SR CLASS 2 can choose between ERROR module and MINMAXAVG
+ * module. Returns 0 on success and error value in case of failure.
+ */
+int sr_configure_minmax(struct voltagedomain *voltdm)
+{
+       u32 sr_config, sr_avgwt;
+       u32 senp_en = 0, senn_en = 0;
+       u8 senp_shift, senn_shift;
+       struct omap_sr *sr = _sr_lookup(voltdm);
+
+       if (IS_ERR(sr)) {
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
+               return PTR_ERR(sr);
+       }
+
+       if (!sr->clk_length)
+               sr_set_clk_length(sr);
+
+       senp_en = sr->senp_mod;
+       senn_en = sr->senn_mod;
+
+       sr_config = (sr->clk_length << SRCONFIG_SRCLKLENGTH_SHIFT) |
+               SRCONFIG_SENENABLE |
+               (sr->accum_data << SRCONFIG_ACCUMDATA_SHIFT);
+
+       switch (sr->ip_type) {
+       case SR_TYPE_V1:
+               sr_config |= SRCONFIG_DELAYCTRL;
+               senn_shift = SRCONFIG_SENNENABLE_V1_SHIFT;
+               senp_shift = SRCONFIG_SENPENABLE_V1_SHIFT;
+               break;
+       case SR_TYPE_V2:
+               senn_shift = SRCONFIG_SENNENABLE_V2_SHIFT;
+               senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
+               break;
+       default:
+               dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
+                       "module without specifying the ip\n", __func__);
+               return -EINVAL;
+       }
+
+       sr_config |= ((senn_en << senn_shift) | (senp_en << senp_shift));
+       sr_write_reg(sr, SRCONFIG, sr_config);
+       sr_avgwt = (sr->senp_avgweight << AVGWEIGHT_SENPAVGWEIGHT_SHIFT) |
+               (sr->senn_avgweight << AVGWEIGHT_SENNAVGWEIGHT_SHIFT);
+       sr_write_reg(sr, AVGWEIGHT, sr_avgwt);
+
+       /*
+        * Enabling the interrupts if MINMAXAVG module is used.
+        * TODO: check if all the interrupts are mandatory
+        */
+       switch (sr->ip_type) {
+       case SR_TYPE_V1:
+               sr_modify_reg(sr, ERRCONFIG_V1,
+                       (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUVALIDINTEN |
+                       ERRCONFIG_MCUBOUNDINTEN),
+                       (ERRCONFIG_MCUACCUMINTEN | ERRCONFIG_MCUACCUMINTST |
+                        ERRCONFIG_MCUVALIDINTEN | ERRCONFIG_MCUVALIDINTST |
+                        ERRCONFIG_MCUBOUNDINTEN | ERRCONFIG_MCUBOUNDINTST));
+               break;
+       case SR_TYPE_V2:
+               sr_write_reg(sr, IRQSTATUS,
+                       IRQSTATUS_MCUACCUMINT | IRQSTATUS_MCVALIDINT |
+                       IRQSTATUS_MCBOUNDSINT | IRQSTATUS_MCUDISABLEACKINT);
+               sr_write_reg(sr, IRQENABLE_SET,
+                       IRQENABLE_MCUACCUMINT | IRQENABLE_MCUVALIDINT |
+                       IRQENABLE_MCUBOUNDSINT | IRQENABLE_MCUDISABLEACKINT);
+               break;
+       default:
+               dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex"
+                       "module without specifying the ip\n", __func__);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+/**
+ * sr_enable() - Enables the smartreflex module.
+ * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
+ * @volt:      The voltage at which the Voltage domain associated with
+ *             the smartreflex module is operating at.
+ *             This is required only to program the correct Ntarget value.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * enable a smartreflex module. Returns 0 on success. Returns error
+ * value if the voltage passed is wrong or if ntarget value is wrong.
+ */
+int sr_enable(struct voltagedomain *voltdm, unsigned long volt)
+{
+       struct omap_volt_data *volt_data;
+       struct omap_sr *sr = _sr_lookup(voltdm);
+       struct omap_sr_nvalue_table *nvalue_row;
+       int ret;
+
+       if (IS_ERR(sr)) {
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
+               return PTR_ERR(sr);
+       }
+
+       volt_data = omap_voltage_get_voltdata(sr->voltdm, volt);
+
+       if (IS_ERR(volt_data)) {
+               dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table"
+                       "for nominal voltage %ld\n", __func__, volt);
+               return PTR_ERR(volt_data);
+       }
+
+       nvalue_row = sr_retrieve_nvalue_row(sr, volt_data->sr_efuse_offs);
+
+       if (!nvalue_row) {
+               dev_warn(&sr->pdev->dev, "%s: failure getting SR data for this voltage %ld\n",
+                        __func__, volt);
+               return -ENODATA;
+       }
+
+       /* errminlimit is opp dependent and hence linked to voltage */
+       sr->err_minlimit = nvalue_row->errminlimit;
+
+       pm_runtime_get_sync(&sr->pdev->dev);
+
+       /* Check if SR is already enabled. If yes do nothing */
+       if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE)
+               return 0;
+
+       /* Configure SR */
+       ret = sr_class->configure(sr);
+       if (ret)
+               return ret;
+
+       sr_write_reg(sr, NVALUERECIPROCAL, nvalue_row->nvalue);
+
+       /* SRCONFIG - enable SR */
+       sr_modify_reg(sr, SRCONFIG, SRCONFIG_SRENABLE, SRCONFIG_SRENABLE);
+       return 0;
+}
+
+/**
+ * sr_disable() - Disables the smartreflex module.
+ * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the smartreflex class driver to
+ * disable a smartreflex module.
+ */
+void sr_disable(struct voltagedomain *voltdm)
+{
+       struct omap_sr *sr = _sr_lookup(voltdm);
+
+       if (IS_ERR(sr)) {
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
+               return;
+       }
+
+       /* Check if SR clocks are already disabled. If yes do nothing */
+       if (pm_runtime_suspended(&sr->pdev->dev))
+               return;
+
+       /*
+        * Disable SR if only it is indeed enabled. Else just
+        * disable the clocks.
+        */
+       if (sr_read_reg(sr, SRCONFIG) & SRCONFIG_SRENABLE) {
+               switch (sr->ip_type) {
+               case SR_TYPE_V1:
+                       sr_v1_disable(sr);
+                       break;
+               case SR_TYPE_V2:
+                       sr_v2_disable(sr);
+                       break;
+               default:
+                       dev_err(&sr->pdev->dev, "UNKNOWN IP type %d\n",
+                               sr->ip_type);
+               }
+       }
+
+       pm_runtime_put_sync_suspend(&sr->pdev->dev);
+}
+
+/**
+ * sr_register_class() - API to register a smartreflex class parameters.
+ * @class_data:        The structure containing various sr class specific data.
+ *
+ * This API is to be called by the smartreflex class driver to register itself
+ * with the smartreflex driver during init. Returns 0 on success else the
+ * error value.
+ */
+int sr_register_class(struct omap_sr_class_data *class_data)
+{
+       struct omap_sr *sr_info;
+
+       if (!class_data) {
+               pr_warning("%s:, Smartreflex class data passed is NULL\n",
+                       __func__);
+               return -EINVAL;
+       }
+
+       if (sr_class) {
+               pr_warning("%s: Smartreflex class driver already registered\n",
+                       __func__);
+               return -EBUSY;
+       }
+
+       sr_class = class_data;
+
+       /*
+        * Call into late init to do intializations that require
+        * both sr driver and sr class driver to be initiallized.
+        */
+       list_for_each_entry(sr_info, &sr_list, node)
+               sr_late_init(sr_info);
+
+       return 0;
+}
+
+/**
+ * omap_sr_enable() -  API to enable SR clocks and to call into the
+ *                     registered smartreflex class enable API.
+ * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the kernel in order to enable
+ * a particular smartreflex module. This API will do the initial
+ * configurations to turn on the smartreflex module and in turn call
+ * into the registered smartreflex class enable API.
+ */
+void omap_sr_enable(struct voltagedomain *voltdm)
+{
+       struct omap_sr *sr = _sr_lookup(voltdm);
+
+       if (IS_ERR(sr)) {
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
+               return;
+       }
+
+       if (!sr->autocomp_active)
+               return;
+
+       if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
+               dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
+                       "registered\n", __func__);
+               return;
+       }
+
+       sr_class->enable(sr);
+}
+
+/**
+ * omap_sr_disable() - API to disable SR without resetting the voltage
+ *                     processor voltage
+ * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the kernel in order to disable
+ * a particular smartreflex module. This API will in turn call
+ * into the registered smartreflex class disable API. This API will tell
+ * the smartreflex class disable not to reset the VP voltage after
+ * disabling smartreflex.
+ */
+void omap_sr_disable(struct voltagedomain *voltdm)
+{
+       struct omap_sr *sr = _sr_lookup(voltdm);
+
+       if (IS_ERR(sr)) {
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
+               return;
+       }
+
+       if (!sr->autocomp_active)
+               return;
+
+       if (!sr_class || !(sr_class->disable)) {
+               dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
+                       "registered\n", __func__);
+               return;
+       }
+
+       sr_class->disable(sr, 0);
+}
+
+/**
+ * omap_sr_disable_reset_volt() - API to disable SR and reset the
+ *                             voltage processor voltage
+ * @voltdm:    VDD pointer to which the SR module to be configured belongs to.
+ *
+ * This API is to be called from the kernel in order to disable
+ * a particular smartreflex module. This API will in turn call
+ * into the registered smartreflex class disable API. This API will tell
+ * the smartreflex class disable to reset the VP voltage after
+ * disabling smartreflex.
+ */
+void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
+{
+       struct omap_sr *sr = _sr_lookup(voltdm);
+
+       if (IS_ERR(sr)) {
+               pr_warning("%s: omap_sr struct for voltdm not found\n", __func__);
+               return;
+       }
+
+       if (!sr->autocomp_active)
+               return;
+
+       if (!sr_class || !(sr_class->disable)) {
+               dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not"
+                       "registered\n", __func__);
+               return;
+       }
+
+       sr_class->disable(sr, 1);
+}
+
+/**
+ * omap_sr_register_pmic() - API to register pmic specific info.
+ * @pmic_data: The structure containing pmic specific data.
+ *
+ * This API is to be called from the PMIC specific code to register with
+ * smartreflex driver pmic specific info. Currently the only info required
+ * is the smartreflex init on the PMIC side.
+ */
+void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data)
+{
+       if (!pmic_data) {
+               pr_warning("%s: Trying to register NULL PMIC data structure"
+                       "with smartreflex\n", __func__);
+               return;
+       }
+
+       sr_pmic_data = pmic_data;
+}
+
+/* PM Debug FS entries to enable and disable smartreflex. */
+static int omap_sr_autocomp_show(void *data, u64 *val)
+{
+       struct omap_sr *sr_info = data;
+
+       if (!sr_info) {
+               pr_warning("%s: omap_sr struct not found\n", __func__);
+               return -EINVAL;
+       }
+
+       *val = sr_info->autocomp_active;
+
+       return 0;
+}
+
+static int omap_sr_autocomp_store(void *data, u64 val)
+{
+       struct omap_sr *sr_info = data;
+
+       if (!sr_info) {
+               pr_warning("%s: omap_sr struct not found\n", __func__);
+               return -EINVAL;
+       }
+
+       /* Sanity check */
+       if (val > 1) {
+               pr_warning("%s: Invalid argument %lld\n", __func__, val);
+               return -EINVAL;
+       }
+
+       /* control enable/disable only if there is a delta in value */
+       if (sr_info->autocomp_active != val) {
+               if (!val)
+                       sr_stop_vddautocomp(sr_info);
+               else
+                       sr_start_vddautocomp(sr_info);
+       }
+
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(pm_sr_fops, omap_sr_autocomp_show,
+                       omap_sr_autocomp_store, "%llu\n");
+
+static int __init omap_sr_probe(struct platform_device *pdev)
+{
+       struct omap_sr *sr_info;
+       struct omap_sr_data *pdata = pdev->dev.platform_data;
+       struct resource *mem, *irq;
+       struct dentry *nvalue_dir;
+       int i, ret = 0;
+
+       sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
+       if (!sr_info) {
+               dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
+                       __func__);
+               return -ENOMEM;
+       }
+
+       platform_set_drvdata(pdev, sr_info);
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
+               ret = -EINVAL;
+               goto err_free_devinfo;
+       }
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!mem) {
+               dev_err(&pdev->dev, "%s: no mem resource\n", __func__);
+               ret = -ENODEV;
+               goto err_free_devinfo;
+       }
+
+       mem = request_mem_region(mem->start, resource_size(mem),
+                                       dev_name(&pdev->dev));
+       if (!mem) {
+               dev_err(&pdev->dev, "%s: no mem region\n", __func__);
+               ret = -EBUSY;
+               goto err_free_devinfo;
+       }
+
+       irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_irq_safe(&pdev->dev);
+
+       sr_info->name = kasprintf(GFP_KERNEL, "%s", pdata->name);
+       if (!sr_info->name) {
+               dev_err(&pdev->dev, "%s: Unable to alloc SR instance name\n",
+                       __func__);
+               ret = -ENOMEM;
+               goto err_release_region;
+       }
+
+       sr_info->pdev = pdev;
+       sr_info->srid = pdev->id;
+       sr_info->voltdm = pdata->voltdm;
+       sr_info->nvalue_table = pdata->nvalue_table;
+       sr_info->nvalue_count = pdata->nvalue_count;
+       sr_info->senn_mod = pdata->senn_mod;
+       sr_info->senp_mod = pdata->senp_mod;
+       sr_info->autocomp_active = false;
+       sr_info->ip_type = pdata->ip_type;
+       sr_info->base = ioremap(mem->start, resource_size(mem));
+       if (!sr_info->base) {
+               dev_err(&pdev->dev, "%s: ioremap fail\n", __func__);
+               ret = -ENOMEM;
+               goto err_release_region;
+       }
+
+       if (irq)
+               sr_info->irq = irq->start;
+
+       sr_set_clk_length(sr_info);
+       sr_set_regfields(sr_info);
+
+       list_add(&sr_info->node, &sr_list);
+
+       /*
+        * Call into late init to do intializations that require
+        * both sr driver and sr class driver to be initiallized.
+        */
+       if (sr_class) {
+               ret = sr_late_init(sr_info);
+               if (ret) {
+                       pr_warning("%s: Error in SR late init\n", __func__);
+                       goto err_iounmap;
+               }
+       }
+
+       dev_info(&pdev->dev, "%s: SmartReflex driver initialized\n", __func__);
+       if (!sr_dbg_dir) {
+               sr_dbg_dir = debugfs_create_dir("smartreflex", NULL);
+               if (IS_ERR_OR_NULL(sr_dbg_dir)) {
+                       ret = PTR_ERR(sr_dbg_dir);
+                       pr_err("%s:sr debugfs dir creation failed(%d)\n",
+                               __func__, ret);
+                       goto err_iounmap;
+               }
+       }
+
+       sr_info->dbg_dir = debugfs_create_dir(sr_info->name, sr_dbg_dir);
+       if (IS_ERR_OR_NULL(sr_info->dbg_dir)) {
+               dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
+                       __func__);
+               ret = PTR_ERR(sr_info->dbg_dir);
+               goto err_free_name;
+       }
+
+       (void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR,
+                       sr_info->dbg_dir, (void *)sr_info, &pm_sr_fops);
+       (void) debugfs_create_x32("errweight", S_IRUGO, sr_info->dbg_dir,
+                       &sr_info->err_weight);
+       (void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr_info->dbg_dir,
+                       &sr_info->err_maxlimit);
+
+       nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir);
+       if (IS_ERR_OR_NULL(nvalue_dir)) {
+               dev_err(&pdev->dev, "%s: Unable to create debugfs directory"
+                       "for n-values\n", __func__);
+               ret = PTR_ERR(nvalue_dir);
+               goto err_debugfs;
+       }
+
+       if (sr_info->nvalue_count == 0 || !sr_info->nvalue_table) {
+               dev_warn(&pdev->dev, "%s: %s: No Voltage table for the corresponding vdd. Cannot create debugfs entries for n-values\n",
+                        __func__, sr_info->name);
+
+               ret = -ENODATA;
+               goto err_debugfs;
+       }
+
+       for (i = 0; i < sr_info->nvalue_count; i++) {
+               char name[NVALUE_NAME_LEN + 1];
+
+               snprintf(name, sizeof(name), "volt_%lu",
+                               sr_info->nvalue_table[i].volt_nominal);
+               (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
+                               &(sr_info->nvalue_table[i].nvalue));
+               snprintf(name, sizeof(name), "errminlimit_%lu",
+                        sr_info->nvalue_table[i].volt_nominal);
+               (void) debugfs_create_x32(name, S_IRUGO | S_IWUSR, nvalue_dir,
+                               &(sr_info->nvalue_table[i].errminlimit));
+
+       }
+
+       return ret;
+
+err_debugfs:
+       debugfs_remove_recursive(sr_info->dbg_dir);
+err_free_name:
+       kfree(sr_info->name);
+err_iounmap:
+       list_del(&sr_info->node);
+       iounmap(sr_info->base);
+err_release_region:
+       release_mem_region(mem->start, resource_size(mem));
+err_free_devinfo:
+       kfree(sr_info);
+
+       return ret;
+}
+
+static int __devexit omap_sr_remove(struct platform_device *pdev)
+{
+       struct omap_sr_data *pdata = pdev->dev.platform_data;
+       struct omap_sr *sr_info;
+       struct resource *mem;
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
+               return -EINVAL;
+       }
+
+       sr_info = _sr_lookup(pdata->voltdm);
+       if (IS_ERR(sr_info)) {
+               dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
+                       __func__);
+               return PTR_ERR(sr_info);
+       }
+
+       if (sr_info->autocomp_active)
+               sr_stop_vddautocomp(sr_info);
+       if (sr_info->dbg_dir)
+               debugfs_remove_recursive(sr_info->dbg_dir);
+
+       list_del(&sr_info->node);
+       iounmap(sr_info->base);
+       kfree(sr_info->name);
+       kfree(sr_info);
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       release_mem_region(mem->start, resource_size(mem));
+
+       return 0;
+}
+
+static void __devexit omap_sr_shutdown(struct platform_device *pdev)
+{
+       struct omap_sr_data *pdata = pdev->dev.platform_data;
+       struct omap_sr *sr_info;
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "%s: platform data missing\n", __func__);
+               return;
+       }
+
+       sr_info = _sr_lookup(pdata->voltdm);
+       if (IS_ERR(sr_info)) {
+               dev_warn(&pdev->dev, "%s: omap_sr struct not found\n",
+                       __func__);
+               return;
+       }
+
+       if (sr_info->autocomp_active)
+               sr_stop_vddautocomp(sr_info);
+
+       return;
+}
+
+static struct platform_driver smartreflex_driver = {
+       .remove         = __devexit_p(omap_sr_remove),
+       .shutdown       = __devexit_p(omap_sr_shutdown),
+       .driver         = {
+               .name   = "smartreflex",
+       },
+};
+
+static int __init sr_init(void)
+{
+       int ret = 0;
+
+       /*
+        * sr_init is a late init. If by then a pmic specific API is not
+        * registered either there is no need for anything to be done on
+        * the PMIC side or somebody has forgotten to register a PMIC
+        * handler. Warn for the second condition.
+        */
+       if (sr_pmic_data && sr_pmic_data->sr_pmic_init)
+               sr_pmic_data->sr_pmic_init();
+       else
+               pr_warning("%s: No PMIC hook to init smartreflex\n", __func__);
+
+       ret = platform_driver_probe(&smartreflex_driver, omap_sr_probe);
+       if (ret) {
+               pr_err("%s: platform driver register failed for SR\n",
+                       __func__);
+               return ret;
+       }
+
+       return 0;
+}
+late_initcall(sr_init);
+
+static void __exit sr_exit(void)
+{
+       platform_driver_unregister(&smartreflex_driver);
+}
+module_exit(sr_exit);
+
+MODULE_DESCRIPTION("OMAP Smartreflex Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
+MODULE_AUTHOR("Texas Instruments Inc");
index c86b8864e411feceb66924be2b8cc4170c0db74c..f34c3be6c9fed92bdaf227016f4540b8edda0f89 100644 (file)
@@ -20,6 +20,7 @@ menuconfig REGULATOR
 
          If unsure, say no.
 
+
 if REGULATOR
 
 config REGULATOR_DEBUG
@@ -88,6 +89,13 @@ config REGULATOR_AAT2870
          If you have a AnalogicTech AAT2870 say Y to enable the
          regulator driver.
 
+config REGULATOR_ARIZONA
+       tristate "Wolfson Arizona class devices"
+       depends on MFD_ARIZONA
+       help
+         Support for the regulators found on Wolfson Arizona class
+         devices.
+
 config REGULATOR_DA903X
        tristate "Dialog Semiconductor DA9030/DA9034 regulators"
        depends on PMIC_DA903X
@@ -195,6 +203,14 @@ config REGULATOR_MAX8998
          via I2C bus. The provided regulator is suitable for S3C6410
          and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages.
 
+config REGULATOR_MAX77686
+       tristate "Maxim 77686 regulator"
+       depends on MFD_MAX77686
+       help
+         This driver controls a Maxim 77686 regulator
+         via I2C bus. The provided regulator is suitable for
+         Exynos-4 chips to control VARM and VINT voltages.
+
 config REGULATOR_PCAP
        tristate "Motorola PCAP2 regulator driver"
        depends on EZX_PCAP
@@ -216,6 +232,19 @@ config REGULATOR_LP3972
         Say Y here to support the voltage regulators and convertors
         on National Semiconductors LP3972 PMIC
 
+config REGULATOR_LP872X
+       bool "TI/National Semiconductor LP8720/LP8725 voltage regulators"
+       depends on I2C=y
+       select REGMAP_I2C
+       help
+         This driver supports LP8720/LP8725 PMIC
+
+config REGULATOR_LP8788
+       bool "TI LP8788 Power Regulators"
+       depends on MFD_LP8788
+       help
+         This driver supports LP8788 voltage regulator chip.
+
 config REGULATOR_PCF50633
        tristate "NXP PCF50633 regulator driver"
         depends on MFD_PCF50633
@@ -233,6 +262,14 @@ config REGULATOR_RC5T583
          through regulator interface. The device supports multiple DCDC/LDO
          outputs which can be controlled by i2c communication.
 
+config REGULATOR_S2MPS11
+       tristate "Samsung S2MPS11 voltage regulator"
+       depends on MFD_SEC_CORE
+       help
+        This driver supports a Samsung S2MPS11 voltage output regulator
+        via I2C bus. S2MPS11 is comprised of high efficient Buck converters
+        including Dual-Phase Buck converter, Buck-Boost converter, various LDOs.
+
 config REGULATOR_S5M8767
        tristate "Samsung S5M8767A voltage regulator"
        depends on MFD_S5M_CORE
index 977fd46909abdb9b9bd2c62f9d26737465613c7a..3342615cf25e165b50ff8a1ab56f3a556207f41b 100644 (file)
@@ -15,6 +15,7 @@ obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
 obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o
 obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
 obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
+obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
 obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
 obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
 obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
@@ -23,6 +24,9 @@ obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
 obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o
 obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o
 obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o
+obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o
+obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o
+obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o
 obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o
 obj-$(CONFIG_REGULATOR_MAX8649)        += max8649.o
 obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
@@ -30,6 +34,7 @@ obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
 obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
 obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
+obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
 obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
 obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
 obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
@@ -37,6 +42,7 @@ obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
 obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
 obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
 obj-$(CONFIG_REGULATOR_RC5T583)  += rc5t583-regulator.o
+obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
 obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
 obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
index 06776ca945f2a57b12501c11fa70febd3c55a389..6f45bfd22e832f71f04c337c686bc762672d7842 100644 (file)
@@ -33,11 +33,6 @@ struct aat2870_regulator {
        struct aat2870_data *aat2870;
        struct regulator_desc desc;
 
-       const int *voltages; /* uV */
-
-       int min_uV;
-       int max_uV;
-
        u8 enable_addr;
        u8 enable_shift;
        u8 enable_mask;
@@ -47,14 +42,6 @@ struct aat2870_regulator {
        u8 voltage_mask;
 };
 
-static int aat2870_ldo_list_voltage(struct regulator_dev *rdev,
-                                   unsigned selector)
-{
-       struct aat2870_regulator *ri = rdev_get_drvdata(rdev);
-
-       return ri->voltages[selector];
-}
-
 static int aat2870_ldo_set_voltage_sel(struct regulator_dev *rdev,
                                       unsigned selector)
 {
@@ -111,7 +98,7 @@ static int aat2870_ldo_is_enabled(struct regulator_dev *rdev)
 }
 
 static struct regulator_ops aat2870_ldo_ops = {
-       .list_voltage = aat2870_ldo_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .set_voltage_sel = aat2870_ldo_set_voltage_sel,
        .get_voltage_sel = aat2870_ldo_get_voltage_sel,
        .enable = aat2870_ldo_enable,
@@ -119,7 +106,7 @@ static struct regulator_ops aat2870_ldo_ops = {
        .is_enabled = aat2870_ldo_is_enabled,
 };
 
-static const int aat2870_ldo_voltages[] = {
+static const unsigned int aat2870_ldo_voltages[] = {
        1200000, 1300000, 1500000, 1600000,
        1800000, 2000000, 2200000, 2500000,
        2600000, 2700000, 2800000, 2900000,
@@ -132,13 +119,11 @@ static const int aat2870_ldo_voltages[] = {
                        .name = #ids,                   \
                        .id = AAT2870_ID_##ids,         \
                        .n_voltages = ARRAY_SIZE(aat2870_ldo_voltages), \
+                       .volt_table = aat2870_ldo_voltages, \
                        .ops = &aat2870_ldo_ops,        \
                        .type = REGULATOR_VOLTAGE,      \
                        .owner = THIS_MODULE,           \
                },                                      \
-               .voltages = aat2870_ldo_voltages,       \
-               .min_uV = 1200000,                      \
-               .max_uV = 3300000,                      \
        }
 
 static struct aat2870_regulator aat2870_regulators[] = {
index 03f4d9c604ec19717abfb2d57f64b8c49c6e42af..182b553059c9c82a15f8ff164d64c5d37e708c52 100644 (file)
  * @dev: handle to the device
  * @plfdata: AB3100 platform data passed in at probe time
  * @regreg: regulator register number in the AB3100
- * @fixed_voltage: a fixed voltage for this regulator, if this
- *          0 the voltages array is used instead.
- * @typ_voltages: an array of available typical voltages for
- *          this regulator
- * @voltages_len: length of the array of available voltages
  */
 struct ab3100_regulator {
        struct regulator_dev *rdev;
        struct device *dev;
        struct ab3100_platform_data *plfdata;
        u8 regreg;
-       int fixed_voltage;
-       int const *typ_voltages;
-       u8 voltages_len;
 };
 
 /* The order in which registers are initialized */
@@ -80,7 +72,7 @@ static const u8 ab3100_reg_init_order[AB3100_NUM_REGULATORS+2] = {
 #define LDO_C_VOLTAGE 2650000
 #define LDO_D_VOLTAGE 2650000
 
-static const int ldo_e_buck_typ_voltages[] = {
+static const unsigned int ldo_e_buck_typ_voltages[] = {
        1800000,
        1400000,
        1300000,
@@ -90,7 +82,7 @@ static const int ldo_e_buck_typ_voltages[] = {
        900000,
 };
 
-static const int ldo_f_typ_voltages[] = {
+static const unsigned int ldo_f_typ_voltages[] = {
        1800000,
        1400000,
        1300000,
@@ -101,21 +93,21 @@ static const int ldo_f_typ_voltages[] = {
        2650000,
 };
 
-static const int ldo_g_typ_voltages[] = {
+static const unsigned int ldo_g_typ_voltages[] = {
        2850000,
        2750000,
        1800000,
        1500000,
 };
 
-static const int ldo_h_typ_voltages[] = {
+static const unsigned int ldo_h_typ_voltages[] = {
        2750000,
        1800000,
        1500000,
        1200000,
 };
 
-static const int ldo_k_typ_voltages[] = {
+static const unsigned int ldo_k_typ_voltages[] = {
        2750000,
        1800000,
 };
@@ -126,40 +118,27 @@ static struct ab3100_regulator
 ab3100_regulators[AB3100_NUM_REGULATORS] = {
        {
                .regreg = AB3100_LDO_A,
-               .fixed_voltage = LDO_A_VOLTAGE,
        },
        {
                .regreg = AB3100_LDO_C,
-               .fixed_voltage = LDO_C_VOLTAGE,
        },
        {
                .regreg = AB3100_LDO_D,
-               .fixed_voltage = LDO_D_VOLTAGE,
        },
        {
                .regreg = AB3100_LDO_E,
-               .typ_voltages = ldo_e_buck_typ_voltages,
-               .voltages_len = ARRAY_SIZE(ldo_e_buck_typ_voltages),
        },
        {
                .regreg = AB3100_LDO_F,
-               .typ_voltages = ldo_f_typ_voltages,
-               .voltages_len = ARRAY_SIZE(ldo_f_typ_voltages),
        },
        {
                .regreg = AB3100_LDO_G,
-               .typ_voltages = ldo_g_typ_voltages,
-               .voltages_len = ARRAY_SIZE(ldo_g_typ_voltages),
        },
        {
                .regreg = AB3100_LDO_H,
-               .typ_voltages = ldo_h_typ_voltages,
-               .voltages_len = ARRAY_SIZE(ldo_h_typ_voltages),
        },
        {
                .regreg = AB3100_LDO_K,
-               .typ_voltages = ldo_k_typ_voltages,
-               .voltages_len = ARRAY_SIZE(ldo_k_typ_voltages),
        },
        {
                .regreg = AB3100_LDO_EXT,
@@ -167,8 +146,6 @@ ab3100_regulators[AB3100_NUM_REGULATORS] = {
        },
        {
                .regreg = AB3100_BUCK,
-               .typ_voltages = ldo_e_buck_typ_voltages,
-               .voltages_len = ARRAY_SIZE(ldo_e_buck_typ_voltages),
        },
 };
 
@@ -178,7 +155,7 @@ ab3100_regulators[AB3100_NUM_REGULATORS] = {
  */
 static int ab3100_enable_regulator(struct regulator_dev *reg)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
+       struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
        int err;
        u8 regval;
 
@@ -209,7 +186,7 @@ static int ab3100_enable_regulator(struct regulator_dev *reg)
 
 static int ab3100_disable_regulator(struct regulator_dev *reg)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
+       struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
        int err;
        u8 regval;
 
@@ -242,7 +219,7 @@ static int ab3100_disable_regulator(struct regulator_dev *reg)
 
 static int ab3100_is_enabled_regulator(struct regulator_dev *reg)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
+       struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
        u8 regval;
        int err;
 
@@ -257,26 +234,12 @@ static int ab3100_is_enabled_regulator(struct regulator_dev *reg)
        return regval & AB3100_REG_ON_MASK;
 }
 
-static int ab3100_list_voltage_regulator(struct regulator_dev *reg,
-                                        unsigned selector)
-{
-       struct ab3100_regulator *abreg = reg->reg_data;
-
-       if (selector >= abreg->voltages_len)
-               return -EINVAL;
-       return abreg->typ_voltages[selector];
-}
-
 static int ab3100_get_voltage_regulator(struct regulator_dev *reg)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
+       struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
        u8 regval;
        int err;
 
-       /* Return the voltage for fixed regulators immediately */
-       if (abreg->fixed_voltage)
-               return abreg->fixed_voltage;
-
        /*
         * For variable types, read out setting and index into
         * supplied voltage list.
@@ -294,20 +257,20 @@ static int ab3100_get_voltage_regulator(struct regulator_dev *reg)
        regval &= 0xE0;
        regval >>= 5;
 
-       if (regval >= abreg->voltages_len) {
+       if (regval >= reg->desc->n_voltages) {
                dev_err(&reg->dev,
                        "regulator register %02x contains an illegal voltage setting\n",
                        abreg->regreg);
                return -EINVAL;
        }
 
-       return abreg->typ_voltages[regval];
+       return reg->desc->volt_table[regval];
 }
 
 static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg,
                                            unsigned selector)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
+       struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
        u8 regval;
        int err;
 
@@ -336,7 +299,7 @@ static int ab3100_set_voltage_regulator_sel(struct regulator_dev *reg,
 static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,
                                                int uV)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
+       struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
        u8 regval;
        int err;
        int bestindex;
@@ -379,42 +342,22 @@ static int ab3100_set_suspend_voltage_regulator(struct regulator_dev *reg,
  */
 static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
+       struct ab3100_regulator *abreg = rdev_get_drvdata(reg);
 
        return abreg->plfdata->external_voltage;
 }
 
-static int ab3100_enable_time_regulator(struct regulator_dev *reg)
+static int ab3100_get_fixed_voltage_regulator(struct regulator_dev *reg)
 {
-       struct ab3100_regulator *abreg = reg->reg_data;
-
-       /* Per-regulator power on delay from spec */
-       switch (abreg->regreg) {
-       case AB3100_LDO_A: /* Fallthrough */
-       case AB3100_LDO_C: /* Fallthrough */
-       case AB3100_LDO_D: /* Fallthrough */
-       case AB3100_LDO_E: /* Fallthrough */
-       case AB3100_LDO_H: /* Fallthrough */
-       case AB3100_LDO_K:
-               return 200;
-       case AB3100_LDO_F:
-               return 600;
-       case AB3100_LDO_G:
-               return 400;
-       case AB3100_BUCK:
-               return 1000;
-       default:
-               break;
-       }
-       return 0;
+       return reg->desc->min_uV;
 }
 
 static struct regulator_ops regulator_ops_fixed = {
+       .list_voltage = regulator_list_voltage_linear,
        .enable      = ab3100_enable_regulator,
        .disable     = ab3100_disable_regulator,
        .is_enabled  = ab3100_is_enabled_regulator,
-       .get_voltage = ab3100_get_voltage_regulator,
-       .enable_time = ab3100_enable_time_regulator,
+       .get_voltage = ab3100_get_fixed_voltage_regulator,
 };
 
 static struct regulator_ops regulator_ops_variable = {
@@ -423,8 +366,7 @@ static struct regulator_ops regulator_ops_variable = {
        .is_enabled  = ab3100_is_enabled_regulator,
        .get_voltage = ab3100_get_voltage_regulator,
        .set_voltage_sel = ab3100_set_voltage_regulator_sel,
-       .list_voltage = ab3100_list_voltage_regulator,
-       .enable_time = ab3100_enable_time_regulator,
+       .list_voltage = regulator_list_voltage_table,
 };
 
 static struct regulator_ops regulator_ops_variable_sleepable = {
@@ -434,8 +376,7 @@ static struct regulator_ops regulator_ops_variable_sleepable = {
        .get_voltage = ab3100_get_voltage_regulator,
        .set_voltage_sel = ab3100_set_voltage_regulator_sel,
        .set_suspend_voltage = ab3100_set_suspend_voltage_regulator,
-       .list_voltage = ab3100_list_voltage_regulator,
-       .enable_time = ab3100_enable_time_regulator,
+       .list_voltage = regulator_list_voltage_table,
 };
 
 /*
@@ -457,62 +398,81 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
                .name = "LDO_A",
                .id   = AB3100_LDO_A,
                .ops  = &regulator_ops_fixed,
+               .n_voltages = 1,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .min_uV = LDO_A_VOLTAGE,
+               .enable_time = 200,
        },
        {
                .name = "LDO_C",
                .id   = AB3100_LDO_C,
                .ops  = &regulator_ops_fixed,
+               .n_voltages = 1,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .min_uV = LDO_C_VOLTAGE,
+               .enable_time = 200,
        },
        {
                .name = "LDO_D",
                .id   = AB3100_LDO_D,
                .ops  = &regulator_ops_fixed,
+               .n_voltages = 1,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .min_uV = LDO_D_VOLTAGE,
+               .enable_time = 200,
        },
        {
                .name = "LDO_E",
                .id   = AB3100_LDO_E,
                .ops  = &regulator_ops_variable_sleepable,
                .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages),
+               .volt_table = ldo_e_buck_typ_voltages,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .enable_time = 200,
        },
        {
                .name = "LDO_F",
                .id   = AB3100_LDO_F,
                .ops  = &regulator_ops_variable,
                .n_voltages = ARRAY_SIZE(ldo_f_typ_voltages),
+               .volt_table = ldo_f_typ_voltages,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .enable_time = 600,
        },
        {
                .name = "LDO_G",
                .id   = AB3100_LDO_G,
                .ops  = &regulator_ops_variable,
                .n_voltages = ARRAY_SIZE(ldo_g_typ_voltages),
+               .volt_table = ldo_g_typ_voltages,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .enable_time = 400,
        },
        {
                .name = "LDO_H",
                .id   = AB3100_LDO_H,
                .ops  = &regulator_ops_variable,
                .n_voltages = ARRAY_SIZE(ldo_h_typ_voltages),
+               .volt_table = ldo_h_typ_voltages,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .enable_time = 200,
        },
        {
                .name = "LDO_K",
                .id   = AB3100_LDO_K,
                .ops  = &regulator_ops_variable,
                .n_voltages = ARRAY_SIZE(ldo_k_typ_voltages),
+               .volt_table = ldo_k_typ_voltages,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .enable_time = 200,
        },
        {
                .name = "LDO_EXT",
@@ -528,6 +488,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
                .n_voltages = ARRAY_SIZE(ldo_e_buck_typ_voltages),
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
+               .enable_time = 1000,
        },
 };
 
index a739f5ca936a878481f408d67e0a7edf8688a42e..13d424fc1c14c675958014846b48391ff468dec7 100644 (file)
@@ -30,9 +30,6 @@
  * @dev: device pointer
  * @desc: regulator description
  * @regulator_dev: regulator device
- * @max_uV: maximum voltage (for variable voltage supplies)
- * @min_uV: minimum voltage (for variable voltage supplies)
- * @fixed_uV: typical voltage (for fixed voltage supplies)
  * @update_bank: bank to control on/off
  * @update_reg: register to control on/off
  * @update_mask: mask to enable/disable regulator
  * @voltage_bank: bank to control regulator voltage
  * @voltage_reg: register to control regulator voltage
  * @voltage_mask: mask to control regulator voltage
- * @voltages: supported voltage table
- * @voltages_len: number of supported voltages for the regulator
  * @delay: startup/set voltage delay in us
  */
 struct ab8500_regulator_info {
        struct device           *dev;
        struct regulator_desc   desc;
        struct regulator_dev    *regulator;
-       int max_uV;
-       int min_uV;
-       int fixed_uV;
        u8 update_bank;
        u8 update_reg;
        u8 update_mask;
@@ -58,13 +50,11 @@ struct ab8500_regulator_info {
        u8 voltage_bank;
        u8 voltage_reg;
        u8 voltage_mask;
-       int const *voltages;
-       int voltages_len;
        unsigned int delay;
 };
 
 /* voltage tables for the vauxn/vintcore supplies */
-static const int ldo_vauxn_voltages[] = {
+static const unsigned int ldo_vauxn_voltages[] = {
        1100000,
        1200000,
        1300000,
@@ -83,7 +73,7 @@ static const int ldo_vauxn_voltages[] = {
        3300000,
 };
 
-static const int ldo_vaux3_voltages[] = {
+static const unsigned int ldo_vaux3_voltages[] = {
        1200000,
        1500000,
        1800000,
@@ -94,7 +84,7 @@ static const int ldo_vaux3_voltages[] = {
        2910000,
 };
 
-static const int ldo_vintcore_voltages[] = {
+static const unsigned int ldo_vintcore_voltages[] = {
        1200000,
        1225000,
        1250000,
@@ -185,25 +175,6 @@ static int ab8500_regulator_is_enabled(struct regulator_dev *rdev)
                return false;
 }
 
-static int ab8500_list_voltage(struct regulator_dev *rdev, unsigned selector)
-{
-       struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
-
-       if (info == NULL) {
-               dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
-               return -EINVAL;
-       }
-
-       /* return the uV for the fixed regulators */
-       if (info->fixed_uV)
-               return info->fixed_uV;
-
-       if (selector >= info->voltages_len)
-               return -EINVAL;
-
-       return info->voltages[selector];
-}
-
 static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev)
 {
        int ret, val;
@@ -279,14 +250,7 @@ static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
                                             unsigned int new_sel)
 {
        struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
-       int ret;
 
-       /* If the regulator isn't on, it won't take time here */
-       ret = ab8500_regulator_is_enabled(rdev);
-       if (ret < 0)
-               return ret;
-       if (!ret)
-               return 0;
        return info->delay;
 }
 
@@ -296,21 +260,14 @@ static struct regulator_ops ab8500_regulator_ops = {
        .is_enabled     = ab8500_regulator_is_enabled,
        .get_voltage_sel = ab8500_regulator_get_voltage_sel,
        .set_voltage_sel = ab8500_regulator_set_voltage_sel,
-       .list_voltage   = ab8500_list_voltage,
+       .list_voltage   = regulator_list_voltage_table,
        .enable_time    = ab8500_regulator_enable_time,
        .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
 };
 
 static int ab8500_fixed_get_voltage(struct regulator_dev *rdev)
 {
-       struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
-
-       if (info == NULL) {
-               dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
-               return -EINVAL;
-       }
-
-       return info->fixed_uV;
+       return rdev->desc->min_uV;
 }
 
 static struct regulator_ops ab8500_regulator_fixed_ops = {
@@ -318,9 +275,8 @@ static struct regulator_ops ab8500_regulator_fixed_ops = {
        .disable        = ab8500_regulator_disable,
        .is_enabled     = ab8500_regulator_is_enabled,
        .get_voltage    = ab8500_fixed_get_voltage,
-       .list_voltage   = ab8500_list_voltage,
+       .list_voltage   = regulator_list_voltage_linear,
        .enable_time    = ab8500_regulator_enable_time,
-       .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
 };
 
 static struct ab8500_regulator_info
@@ -329,7 +285,7 @@ static struct ab8500_regulator_info
         * Variable Voltage Regulators
         *   name, min mV, max mV,
         *   update bank, reg, mask, enable val
-        *   volt bank, reg, mask, table, table length
+        *   volt bank, reg, mask
         */
        [AB8500_LDO_AUX1] = {
                .desc = {
@@ -339,9 +295,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_AUX1,
                        .owner          = THIS_MODULE,
                        .n_voltages     = ARRAY_SIZE(ldo_vauxn_voltages),
+                       .volt_table     = ldo_vauxn_voltages,
                },
-               .min_uV                 = 1100000,
-               .max_uV                 = 3300000,
                .update_bank            = 0x04,
                .update_reg             = 0x09,
                .update_mask            = 0x03,
@@ -349,8 +304,6 @@ static struct ab8500_regulator_info
                .voltage_bank           = 0x04,
                .voltage_reg            = 0x1f,
                .voltage_mask           = 0x0f,
-               .voltages               = ldo_vauxn_voltages,
-               .voltages_len           = ARRAY_SIZE(ldo_vauxn_voltages),
        },
        [AB8500_LDO_AUX2] = {
                .desc = {
@@ -360,9 +313,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_AUX2,
                        .owner          = THIS_MODULE,
                        .n_voltages     = ARRAY_SIZE(ldo_vauxn_voltages),
+                       .volt_table     = ldo_vauxn_voltages,
                },
-               .min_uV                 = 1100000,
-               .max_uV                 = 3300000,
                .update_bank            = 0x04,
                .update_reg             = 0x09,
                .update_mask            = 0x0c,
@@ -370,8 +322,6 @@ static struct ab8500_regulator_info
                .voltage_bank           = 0x04,
                .voltage_reg            = 0x20,
                .voltage_mask           = 0x0f,
-               .voltages               = ldo_vauxn_voltages,
-               .voltages_len           = ARRAY_SIZE(ldo_vauxn_voltages),
        },
        [AB8500_LDO_AUX3] = {
                .desc = {
@@ -381,9 +331,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_AUX3,
                        .owner          = THIS_MODULE,
                        .n_voltages     = ARRAY_SIZE(ldo_vaux3_voltages),
+                       .volt_table     = ldo_vaux3_voltages,
                },
-               .min_uV                 = 1100000,
-               .max_uV                 = 3300000,
                .update_bank            = 0x04,
                .update_reg             = 0x0a,
                .update_mask            = 0x03,
@@ -391,8 +340,6 @@ static struct ab8500_regulator_info
                .voltage_bank           = 0x04,
                .voltage_reg            = 0x21,
                .voltage_mask           = 0x07,
-               .voltages               = ldo_vaux3_voltages,
-               .voltages_len           = ARRAY_SIZE(ldo_vaux3_voltages),
        },
        [AB8500_LDO_INTCORE] = {
                .desc = {
@@ -402,9 +349,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_INTCORE,
                        .owner          = THIS_MODULE,
                        .n_voltages     = ARRAY_SIZE(ldo_vintcore_voltages),
+                       .volt_table     = ldo_vintcore_voltages,
                },
-               .min_uV                 = 1100000,
-               .max_uV                 = 3300000,
                .update_bank            = 0x03,
                .update_reg             = 0x80,
                .update_mask            = 0x44,
@@ -412,8 +358,6 @@ static struct ab8500_regulator_info
                .voltage_bank           = 0x03,
                .voltage_reg            = 0x80,
                .voltage_mask           = 0x38,
-               .voltages               = ldo_vintcore_voltages,
-               .voltages_len           = ARRAY_SIZE(ldo_vintcore_voltages),
        },
 
        /*
@@ -429,9 +373,9 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_TVOUT,
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
+                       .min_uV         = 2000000,
                },
                .delay                  = 10000,
-               .fixed_uV               = 2000000,
                .update_bank            = 0x03,
                .update_reg             = 0x80,
                .update_mask            = 0x82,
@@ -445,8 +389,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_USB,
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
+                       .min_uV         = 3300000,
                },
-               .fixed_uV               = 3300000,
                .update_bank            = 0x03,
                .update_reg             = 0x82,
                .update_mask            = 0x03,
@@ -460,8 +404,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_AUDIO,
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
+                       .min_uV         = 2000000,
                },
-               .fixed_uV               = 2000000,
                .update_bank            = 0x03,
                .update_reg             = 0x83,
                .update_mask            = 0x02,
@@ -475,8 +419,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_ANAMIC1,
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
+                       .min_uV         = 2050000,
                },
-               .fixed_uV               = 2050000,
                .update_bank            = 0x03,
                .update_reg             = 0x83,
                .update_mask            = 0x08,
@@ -490,8 +434,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_ANAMIC2,
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
+                       .min_uV         = 2050000,
                },
-               .fixed_uV               = 2050000,
                .update_bank            = 0x03,
                .update_reg             = 0x83,
                .update_mask            = 0x10,
@@ -505,8 +449,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_DMIC,
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
+                       .min_uV         = 1800000,
                },
-               .fixed_uV               = 1800000,
                .update_bank            = 0x03,
                .update_reg             = 0x83,
                .update_mask            = 0x04,
@@ -520,8 +464,8 @@ static struct ab8500_regulator_info
                        .id             = AB8500_LDO_ANA,
                        .owner          = THIS_MODULE,
                        .n_voltages     = 1,
+                       .min_uV         = 1200000,
                },
-               .fixed_uV               = 1200000,
                .update_bank            = 0x04,
                .update_reg             = 0x06,
                .update_mask            = 0x0c,
@@ -769,9 +713,7 @@ static __devinit int ab8500_regulator_register(struct platform_device *pdev,
                if (info->desc.id == AB8500_LDO_AUX3) {
                        info->desc.n_voltages =
                                ARRAY_SIZE(ldo_vauxn_voltages);
-                       info->voltages = ldo_vauxn_voltages;
-                       info->voltages_len =
-                               ARRAY_SIZE(ldo_vauxn_voltages);
+                       info->desc.volt_table = ldo_vauxn_voltages;
                        info->voltage_mask = 0xf;
                }
        }
index 46d05f38baf8ee9bbc1cf9b7e1cd80c59651fafe..f123f7e3b7525acd164ed639e022f25dc46711cf 100644 (file)
@@ -89,9 +89,12 @@ static int ad5398_set_current_limit(struct regulator_dev *rdev, int min_uA, int
        unsigned short data;
        int ret;
 
-       if (min_uA > chip->max_uA || min_uA < chip->min_uA)
-               return -EINVAL;
-       if (max_uA > chip->max_uA || max_uA < chip->min_uA)
+       if (min_uA < chip->min_uA)
+               min_uA = chip->min_uA;
+       if (max_uA > chip->max_uA)
+               max_uA = chip->max_uA;
+
+       if (min_uA > chip->max_uA || max_uA < chip->min_uA)
                return -EINVAL;
 
        selector = DIV_ROUND_UP((min_uA - chip->min_uA) * chip->current_level,
index e82e7eaac0f18fd2a50ba3d5506c5620e3e50183..e9c2085f9dfbe0993c6931c573efb52a660f06a0 100644 (file)
@@ -43,33 +43,15 @@ struct anatop_regulator {
        struct regulator_init_data *initdata;
 };
 
-static int anatop_set_voltage(struct regulator_dev *reg, int min_uV,
-                                 int max_uV, unsigned *selector)
+static int anatop_set_voltage_sel(struct regulator_dev *reg, unsigned selector)
 {
        struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
-       u32 val, sel, mask;
-       int uv;
-
-       uv = min_uV;
-       dev_dbg(&reg->dev, "%s: uv %d, min %d, max %d\n", __func__,
-               uv, anatop_reg->min_voltage,
-               anatop_reg->max_voltage);
-
-       if (uv < anatop_reg->min_voltage) {
-               if (max_uV > anatop_reg->min_voltage)
-                       uv = anatop_reg->min_voltage;
-               else
-                       return -EINVAL;
-       }
+       u32 val, mask;
 
        if (!anatop_reg->control_reg)
                return -ENOTSUPP;
 
-       sel = DIV_ROUND_UP(uv - anatop_reg->min_voltage, 25000);
-       if (sel * 25000 + anatop_reg->min_voltage > anatop_reg->max_voltage)
-               return -EINVAL;
-       val = anatop_reg->min_bit_val + sel;
-       *selector = sel;
+       val = anatop_reg->min_bit_val + selector;
        dev_dbg(&reg->dev, "%s: calculated val %d\n", __func__, val);
        mask = ((1 << anatop_reg->vol_bit_width) - 1) <<
                anatop_reg->vol_bit_shift;
@@ -94,21 +76,11 @@ static int anatop_get_voltage_sel(struct regulator_dev *reg)
        return val - anatop_reg->min_bit_val;
 }
 
-static int anatop_list_voltage(struct regulator_dev *reg, unsigned selector)
-{
-       struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg);
-       int uv;
-
-       uv = anatop_reg->min_voltage + selector * 25000;
-       dev_dbg(&reg->dev, "vddio = %d, selector = %u\n", uv, selector);
-
-       return uv;
-}
-
 static struct regulator_ops anatop_rops = {
-       .set_voltage     = anatop_set_voltage,
+       .set_voltage_sel = anatop_set_voltage_sel,
        .get_voltage_sel = anatop_get_voltage_sel,
-       .list_voltage    = anatop_list_voltage,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
 };
 
 static int __devinit anatop_regulator_probe(struct platform_device *pdev)
@@ -176,6 +148,8 @@ static int __devinit anatop_regulator_probe(struct platform_device *pdev)
 
        rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage)
                / 25000 + 1;
+       rdesc->min_uV = sreg->min_voltage;
+       rdesc->uV_step = 25000;
 
        config.dev = &pdev->dev;
        config.init_data = initdata;
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c
new file mode 100644 (file)
index 0000000..c8f95c0
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * arizona-ldo1.c  --  LDO1 supply for Arizona devices
+ *
+ * Copyright 2012 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+#include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/pdata.h>
+#include <linux/mfd/arizona/registers.h>
+
+struct arizona_ldo1 {
+       struct regulator_dev *regulator;
+       struct arizona *arizona;
+
+       struct regulator_consumer_supply supply;
+       struct regulator_init_data init_data;
+};
+
+static struct regulator_ops arizona_ldo1_ops = {
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static const struct regulator_desc arizona_ldo1 = {
+       .name = "LDO1",
+       .supply_name = "LDOVDD",
+       .type = REGULATOR_VOLTAGE,
+       .ops = &arizona_ldo1_ops,
+
+       .vsel_reg = ARIZONA_LDO1_CONTROL_1,
+       .vsel_mask = ARIZONA_LDO1_VSEL_MASK,
+       .min_uV = 900000,
+       .uV_step = 50000,
+       .n_voltages = 7,
+
+       .owner = THIS_MODULE,
+};
+
+static const struct regulator_init_data arizona_ldo1_default = {
+       .constraints = {
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+       },
+       .num_consumer_supplies = 1,
+};
+
+static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
+{
+       struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+       struct regulator_config config = { };
+       struct arizona_ldo1 *ldo1;
+       int ret;
+
+       ldo1 = devm_kzalloc(&pdev->dev, sizeof(*ldo1), GFP_KERNEL);
+       if (ldo1 == NULL) {
+               dev_err(&pdev->dev, "Unable to allocate private data\n");
+               return -ENOMEM;
+       }
+
+       ldo1->arizona = arizona;
+
+       /*
+        * Since the chip usually supplies itself we provide some
+        * default init_data for it.  This will be overridden with
+        * platform data if provided.
+        */
+       ldo1->init_data = arizona_ldo1_default;
+       ldo1->init_data.consumer_supplies = &ldo1->supply;
+       ldo1->supply.supply = "DCVDD";
+       ldo1->supply.dev_name = dev_name(arizona->dev);
+
+       config.dev = arizona->dev;
+       config.driver_data = ldo1;
+       config.regmap = arizona->regmap;
+       config.ena_gpio = arizona->pdata.ldoena;
+
+       if (arizona->pdata.ldo1)
+               config.init_data = arizona->pdata.ldo1;
+       else
+               config.init_data = &ldo1->init_data;
+
+       ldo1->regulator = regulator_register(&arizona_ldo1, &config);
+       if (IS_ERR(ldo1->regulator)) {
+               ret = PTR_ERR(ldo1->regulator);
+               dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
+                       ret);
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, ldo1);
+
+       return 0;
+}
+
+static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
+{
+       struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev);
+
+       regulator_unregister(ldo1->regulator);
+
+       return 0;
+}
+
+static struct platform_driver arizona_ldo1_driver = {
+       .probe = arizona_ldo1_probe,
+       .remove = __devexit_p(arizona_ldo1_remove),
+       .driver         = {
+               .name   = "arizona-ldo1",
+               .owner  = THIS_MODULE,
+       },
+};
+
+module_platform_driver(arizona_ldo1_driver);
+
+/* Module information */
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("Arizona LDO1 driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:arizona-ldo1");
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c
new file mode 100644 (file)
index 0000000..450a069
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * arizona-micsupp.c  --  Microphone supply for Arizona devices
+ *
+ * Copyright 2012 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *  This program is free software; you can redistribute  it and/or modify it
+ *  under  the terms of  the GNU General  Public License as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+
+#include <linux/mfd/arizona/core.h>
+#include <linux/mfd/arizona/pdata.h>
+#include <linux/mfd/arizona/registers.h>
+
+#define ARIZONA_MICSUPP_MAX_SELECTOR 0x1f
+
+struct arizona_micsupp {
+       struct regulator_dev *regulator;
+       struct arizona *arizona;
+
+       struct regulator_consumer_supply supply;
+       struct regulator_init_data init_data;
+};
+
+static int arizona_micsupp_list_voltage(struct regulator_dev *rdev,
+                                       unsigned int selector)
+{
+       if (selector > ARIZONA_MICSUPP_MAX_SELECTOR)
+               return -EINVAL;
+
+       if (selector == ARIZONA_MICSUPP_MAX_SELECTOR)
+               return 3300000;
+       else
+               return (selector * 50000) + 1700000;
+}
+
+static int arizona_micsupp_map_voltage(struct regulator_dev *rdev,
+                                      int min_uV, int max_uV)
+{
+       unsigned int voltage;
+       int selector;
+
+       if (min_uV < 1700000)
+               min_uV = 1700000;
+
+       if (min_uV > 3200000)
+               selector = ARIZONA_MICSUPP_MAX_SELECTOR;
+       else
+               selector = DIV_ROUND_UP(min_uV - 1700000, 50000);
+
+       if (selector < 0)
+               return -EINVAL;
+
+       voltage = arizona_micsupp_list_voltage(rdev, selector);
+       if (voltage < min_uV || voltage > max_uV)
+               return -EINVAL;
+
+       return selector;
+}
+
+static struct regulator_ops arizona_micsupp_ops = {
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+
+       .list_voltage = arizona_micsupp_list_voltage,
+       .map_voltage = arizona_micsupp_map_voltage,
+
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+};
+
+static const struct regulator_desc arizona_micsupp = {
+       .name = "MICVDD",
+       .supply_name = "CPVDD",
+       .type = REGULATOR_VOLTAGE,
+       .n_voltages = ARIZONA_MICSUPP_MAX_SELECTOR + 1,
+       .ops = &arizona_micsupp_ops,
+
+       .vsel_reg = ARIZONA_LDO2_CONTROL_1,
+       .vsel_mask = ARIZONA_LDO2_VSEL_MASK,
+       .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1,
+       .enable_mask = ARIZONA_CPMIC_ENA,
+
+       .owner = THIS_MODULE,
+};
+
+static const struct regulator_init_data arizona_micsupp_default = {
+       .constraints = {
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS |
+                               REGULATOR_CHANGE_VOLTAGE,
+               .min_uV = 1700000,
+               .max_uV = 3300000,
+       },
+
+       .num_consumer_supplies = 1,
+};
+
+static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
+{
+       struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+       struct regulator_config config = { };
+       struct arizona_micsupp *micsupp;
+       int ret;
+
+       micsupp = devm_kzalloc(&pdev->dev, sizeof(*micsupp), GFP_KERNEL);
+       if (micsupp == NULL) {
+               dev_err(&pdev->dev, "Unable to allocate private data\n");
+               return -ENOMEM;
+       }
+
+       micsupp->arizona = arizona;
+
+       /*
+        * Since the chip usually supplies itself we provide some
+        * default init_data for it.  This will be overridden with
+        * platform data if provided.
+        */
+       micsupp->init_data = arizona_micsupp_default;
+       micsupp->init_data.consumer_supplies = &micsupp->supply;
+       micsupp->supply.supply = "MICVDD";
+       micsupp->supply.dev_name = dev_name(arizona->dev);
+
+       config.dev = arizona->dev;
+       config.driver_data = micsupp;
+       config.regmap = arizona->regmap;
+
+       if (arizona->pdata.micvdd)
+               config.init_data = arizona->pdata.micvdd;
+       else
+               config.init_data = &micsupp->init_data;
+
+       /* Default to regulated mode until the API supports bypass */
+       regmap_update_bits(arizona->regmap, ARIZONA_MIC_CHARGE_PUMP_1,
+                          ARIZONA_CPMIC_BYPASS, 0);
+
+       micsupp->regulator = regulator_register(&arizona_micsupp, &config);
+       if (IS_ERR(micsupp->regulator)) {
+               ret = PTR_ERR(micsupp->regulator);
+               dev_err(arizona->dev, "Failed to register mic supply: %d\n",
+                       ret);
+               return ret;
+       }
+
+       platform_set_drvdata(pdev, micsupp);
+
+       return 0;
+}
+
+static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
+{
+       struct arizona_micsupp *micsupp = platform_get_drvdata(pdev);
+
+       regulator_unregister(micsupp->regulator);
+
+       return 0;
+}
+
+static struct platform_driver arizona_micsupp_driver = {
+       .probe = arizona_micsupp_probe,
+       .remove = __devexit_p(arizona_micsupp_remove),
+       .driver         = {
+               .name   = "arizona-micsupp",
+               .owner  = THIS_MODULE,
+       },
+};
+
+module_platform_driver(arizona_micsupp_driver);
+
+/* Module information */
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("Arizona microphone supply driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:arizona-micsupp");
index 8b4b3829d9e719f1acb57ef0d5b158beeefe914d..2e31dffbefe7e4707a93101b86efa85caea02d48 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/mutex.h>
 #include <linux/suspend.h>
 #include <linux/delay.h>
+#include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/regmap.h>
 #include <linux/regulator/of_regulator.h>
@@ -108,28 +109,6 @@ static const char *rdev_get_name(struct regulator_dev *rdev)
                return "";
 }
 
-/* gets the regulator for a given consumer device */
-static struct regulator *get_device_regulator(struct device *dev)
-{
-       struct regulator *regulator = NULL;
-       struct regulator_dev *rdev;
-
-       mutex_lock(&regulator_list_mutex);
-       list_for_each_entry(rdev, &regulator_list, list) {
-               mutex_lock(&rdev->mutex);
-               list_for_each_entry(regulator, &rdev->consumer_list, list) {
-                       if (regulator->dev == dev) {
-                               mutex_unlock(&rdev->mutex);
-                               mutex_unlock(&regulator_list_mutex);
-                               return regulator;
-                       }
-               }
-               mutex_unlock(&rdev->mutex);
-       }
-       mutex_unlock(&regulator_list_mutex);
-       return NULL;
-}
-
 /**
  * of_get_regulator - get a regulator device node based on supply name
  * @dev: Device pointer for the consumer (of regulator) device
@@ -303,18 +282,6 @@ static int regulator_check_drms(struct regulator_dev *rdev)
        return 0;
 }
 
-static ssize_t device_requested_uA_show(struct device *dev,
-                            struct device_attribute *attr, char *buf)
-{
-       struct regulator *regulator;
-
-       regulator = get_device_regulator(dev);
-       if (regulator == NULL)
-               return 0;
-
-       return sprintf(buf, "%d\n", regulator->uA_load);
-}
-
 static ssize_t regulator_uV_show(struct device *dev,
                                struct device_attribute *attr, char *buf)
 {
@@ -427,6 +394,9 @@ static ssize_t regulator_status_show(struct device *dev,
        case REGULATOR_STATUS_STANDBY:
                label = "standby";
                break;
+       case REGULATOR_STATUS_UNDEFINED:
+               label = "undefined";
+               break;
        default:
                return -ERANGE;
        }
@@ -967,6 +937,14 @@ static int set_machine_constraints(struct regulator_dev *rdev,
                }
        }
 
+       if (rdev->constraints->ramp_delay && ops->set_ramp_delay) {
+               ret = ops->set_ramp_delay(rdev, rdev->constraints->ramp_delay);
+               if (ret < 0) {
+                       rdev_err(rdev, "failed to set ramp_delay\n");
+                       goto out;
+               }
+       }
+
        print_constraints(rdev);
        return 0;
 out:
@@ -1097,48 +1075,29 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
        list_add(&regulator->list, &rdev->consumer_list);
 
        if (dev) {
-               /* create a 'requested_microamps_name' sysfs entry */
-               size = scnprintf(buf, REG_STR_SIZE,
-                                "microamps_requested_%s-%s",
-                                dev_name(dev), supply_name);
-               if (size >= REG_STR_SIZE)
-                       goto overflow_err;
-
                regulator->dev = dev;
-               sysfs_attr_init(&regulator->dev_attr.attr);
-               regulator->dev_attr.attr.name = kstrdup(buf, GFP_KERNEL);
-               if (regulator->dev_attr.attr.name == NULL)
-                       goto attr_name_err;
-
-               regulator->dev_attr.attr.mode = 0444;
-               regulator->dev_attr.show = device_requested_uA_show;
-               err = device_create_file(dev, &regulator->dev_attr);
-               if (err < 0) {
-                       rdev_warn(rdev, "could not add regulator_dev requested microamps sysfs entry\n");
-                       goto attr_name_err;
-               }
 
-               /* also add a link to the device sysfs entry */
+               /* Add a link to the device sysfs entry */
                size = scnprintf(buf, REG_STR_SIZE, "%s-%s",
                                 dev->kobj.name, supply_name);
                if (size >= REG_STR_SIZE)
-                       goto attr_err;
+                       goto overflow_err;
 
                regulator->supply_name = kstrdup(buf, GFP_KERNEL);
                if (regulator->supply_name == NULL)
-                       goto attr_err;
+                       goto overflow_err;
 
                err = sysfs_create_link(&rdev->dev.kobj, &dev->kobj,
                                        buf);
                if (err) {
                        rdev_warn(rdev, "could not add device link %s err %d\n",
                                  dev->kobj.name, err);
-                       goto link_name_err;
+                       /* non-fatal */
                }
        } else {
                regulator->supply_name = kstrdup(supply_name, GFP_KERNEL);
                if (regulator->supply_name == NULL)
-                       goto attr_err;
+                       goto overflow_err;
        }
 
        regulator->debugfs = debugfs_create_dir(regulator->supply_name,
@@ -1165,12 +1124,6 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
 
        mutex_unlock(&rdev->mutex);
        return regulator;
-link_name_err:
-       kfree(regulator->supply_name);
-attr_err:
-       device_remove_file(regulator->dev, &regulator->dev_attr);
-attr_name_err:
-       kfree(regulator->dev_attr.attr.name);
 overflow_err:
        list_del(&regulator->list);
        kfree(regulator);
@@ -1181,7 +1134,7 @@ overflow_err:
 static int _regulator_get_enable_time(struct regulator_dev *rdev)
 {
        if (!rdev->desc->ops->enable_time)
-               return 0;
+               return rdev->desc->enable_time;
        return rdev->desc->ops->enable_time(rdev);
 }
 
@@ -1420,11 +1373,8 @@ void regulator_put(struct regulator *regulator)
        debugfs_remove_recursive(regulator->debugfs);
 
        /* remove any sysfs entries */
-       if (regulator->dev) {
+       if (regulator->dev)
                sysfs_remove_link(&rdev->dev.kobj, regulator->supply_name);
-               device_remove_file(regulator->dev, &regulator->dev_attr);
-               kfree(regulator->dev_attr.attr.name);
-       }
        kfree(regulator->supply_name);
        list_del(&regulator->list);
        kfree(regulator);
@@ -1459,19 +1409,61 @@ void devm_regulator_put(struct regulator *regulator)
 {
        int rc;
 
-       rc = devres_destroy(regulator->dev, devm_regulator_release,
+       rc = devres_release(regulator->dev, devm_regulator_release,
                            devm_regulator_match, regulator);
-       if (rc == 0)
-               regulator_put(regulator);
-       else
+       if (rc != 0)
                WARN_ON(rc);
 }
 EXPORT_SYMBOL_GPL(devm_regulator_put);
 
+static int _regulator_do_enable(struct regulator_dev *rdev)
+{
+       int ret, delay;
+
+       /* Query before enabling in case configuration dependent.  */
+       ret = _regulator_get_enable_time(rdev);
+       if (ret >= 0) {
+               delay = ret;
+       } else {
+               rdev_warn(rdev, "enable_time() failed: %d\n", ret);
+               delay = 0;
+       }
+
+       trace_regulator_enable(rdev_get_name(rdev));
+
+       if (rdev->ena_gpio) {
+               gpio_set_value_cansleep(rdev->ena_gpio,
+                                       !rdev->ena_gpio_invert);
+               rdev->ena_gpio_state = 1;
+       } else if (rdev->desc->ops->enable) {
+               ret = rdev->desc->ops->enable(rdev);
+               if (ret < 0)
+                       return ret;
+       } else {
+               return -EINVAL;
+       }
+
+       /* Allow the regulator to ramp; it would be useful to extend
+        * this for bulk operations so that the regulators can ramp
+        * together.  */
+       trace_regulator_enable_delay(rdev_get_name(rdev));
+
+       if (delay >= 1000) {
+               mdelay(delay / 1000);
+               udelay(delay % 1000);
+       } else if (delay) {
+               udelay(delay);
+       }
+
+       trace_regulator_enable_complete(rdev_get_name(rdev));
+
+       return 0;
+}
+
 /* locks held by regulator_enable() */
 static int _regulator_enable(struct regulator_dev *rdev)
 {
-       int ret, delay;
+       int ret;
 
        /* check voltage and requested load before enabling */
        if (rdev->constraints &&
@@ -1485,40 +1477,10 @@ static int _regulator_enable(struct regulator_dev *rdev)
                        if (!_regulator_can_change_status(rdev))
                                return -EPERM;
 
-                       if (!rdev->desc->ops->enable)
-                               return -EINVAL;
-
-                       /* Query before enabling in case configuration
-                        * dependent.  */
-                       ret = _regulator_get_enable_time(rdev);
-                       if (ret >= 0) {
-                               delay = ret;
-                       } else {
-                               rdev_warn(rdev, "enable_time() failed: %d\n",
-                                          ret);
-                               delay = 0;
-                       }
-
-                       trace_regulator_enable(rdev_get_name(rdev));
-
-                       /* Allow the regulator to ramp; it would be useful
-                        * to extend this for bulk operations so that the
-                        * regulators can ramp together.  */
-                       ret = rdev->desc->ops->enable(rdev);
+                       ret = _regulator_do_enable(rdev);
                        if (ret < 0)
                                return ret;
 
-                       trace_regulator_enable_delay(rdev_get_name(rdev));
-
-                       if (delay >= 1000) {
-                               mdelay(delay / 1000);
-                               udelay(delay % 1000);
-                       } else if (delay) {
-                               udelay(delay);
-                       }
-
-                       trace_regulator_enable_complete(rdev_get_name(rdev));
-
                } else if (ret < 0) {
                        rdev_err(rdev, "is_enabled() failed: %d\n", ret);
                        return ret;
@@ -1567,6 +1529,30 @@ int regulator_enable(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(regulator_enable);
 
+static int _regulator_do_disable(struct regulator_dev *rdev)
+{
+       int ret;
+
+       trace_regulator_disable(rdev_get_name(rdev));
+
+       if (rdev->ena_gpio) {
+               gpio_set_value_cansleep(rdev->ena_gpio,
+                                       rdev->ena_gpio_invert);
+               rdev->ena_gpio_state = 0;
+
+       } else if (rdev->desc->ops->disable) {
+               ret = rdev->desc->ops->disable(rdev);
+               if (ret != 0)
+                       return ret;
+       }
+
+       trace_regulator_disable_complete(rdev_get_name(rdev));
+
+       _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
+                            NULL);
+       return 0;
+}
+
 /* locks held by regulator_disable() */
 static int _regulator_disable(struct regulator_dev *rdev)
 {
@@ -1581,20 +1567,12 @@ static int _regulator_disable(struct regulator_dev *rdev)
            (rdev->constraints && !rdev->constraints->always_on)) {
 
                /* we are last user */
-               if (_regulator_can_change_status(rdev) &&
-                   rdev->desc->ops->disable) {
-                       trace_regulator_disable(rdev_get_name(rdev));
-
-                       ret = rdev->desc->ops->disable(rdev);
+               if (_regulator_can_change_status(rdev)) {
+                       ret = _regulator_do_disable(rdev);
                        if (ret < 0) {
                                rdev_err(rdev, "failed to disable\n");
                                return ret;
                        }
-
-                       trace_regulator_disable_complete(rdev_get_name(rdev));
-
-                       _notifier_call_chain(rdev, REGULATOR_EVENT_DISABLE,
-                                            NULL);
                }
 
                rdev->use_count = 0;
@@ -1812,6 +1790,10 @@ EXPORT_SYMBOL_GPL(regulator_disable_regmap);
 
 static int _regulator_is_enabled(struct regulator_dev *rdev)
 {
+       /* A GPIO control always takes precedence */
+       if (rdev->ena_gpio)
+               return rdev->ena_gpio_state;
+
        /* If we don't know then assume that the regulator is always on */
        if (!rdev->desc->ops->is_enabled)
                return 1;
@@ -1882,6 +1864,31 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev,
 }
 EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
 
+/**
+ * regulator_list_voltage_table - List voltages with table based mapping
+ *
+ * @rdev: Regulator device
+ * @selector: Selector to convert into a voltage
+ *
+ * Regulators with table based mapping between voltages and
+ * selectors can set volt_table in the regulator descriptor
+ * and then use this function as their list_voltage() operation.
+ */
+int regulator_list_voltage_table(struct regulator_dev *rdev,
+                                unsigned int selector)
+{
+       if (!rdev->desc->volt_table) {
+               BUG_ON(!rdev->desc->volt_table);
+               return -EINVAL;
+       }
+
+       if (selector >= rdev->desc->n_voltages)
+               return -EINVAL;
+
+       return rdev->desc->volt_table[selector];
+}
+EXPORT_SYMBOL_GPL(regulator_list_voltage_table);
+
 /**
  * regulator_list_voltage - enumerate supported voltages
  * @regulator: regulator source
@@ -1928,8 +1935,18 @@ EXPORT_SYMBOL_GPL(regulator_list_voltage);
 int regulator_is_supported_voltage(struct regulator *regulator,
                                   int min_uV, int max_uV)
 {
+       struct regulator_dev *rdev = regulator->rdev;
        int i, voltages, ret;
 
+       /* If we can't change voltage check the current voltage */
+       if (!(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
+               ret = regulator_get_voltage(regulator);
+               if (ret >= 0)
+                       return (min_uV >= ret && ret <= max_uV);
+               else
+                       return ret;
+       }
+
        ret = regulator_count_voltages(regulator);
        if (ret < 0)
                return ret;
@@ -2045,6 +2062,14 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev,
 {
        int ret, voltage;
 
+       /* Allow uV_step to be 0 for fixed voltage */
+       if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) {
+               if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV)
+                       return 0;
+               else
+                       return -EINVAL;
+       }
+
        if (!rdev->desc->uV_step) {
                BUG_ON(!rdev->desc->uV_step);
                return -EINVAL;
@@ -2071,7 +2096,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
 {
        int ret;
        int delay = 0;
-       int best_val;
+       int best_val = 0;
        unsigned int selector;
        int old_selector = -1;
 
@@ -2084,7 +2109,8 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
         * If we can't obtain the old selector there is not enough
         * info to call set_voltage_time_sel().
         */
-       if (rdev->desc->ops->set_voltage_time_sel &&
+       if (_regulator_is_enabled(rdev) &&
+           rdev->desc->ops->set_voltage_time_sel &&
            rdev->desc->ops->get_voltage_sel) {
                old_selector = rdev->desc->ops->get_voltage_sel(rdev);
                if (old_selector < 0)
@@ -2094,29 +2120,45 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
        if (rdev->desc->ops->set_voltage) {
                ret = rdev->desc->ops->set_voltage(rdev, min_uV, max_uV,
                                                   &selector);
+
+               if (ret >= 0) {
+                       if (rdev->desc->ops->list_voltage)
+                               best_val = rdev->desc->ops->list_voltage(rdev,
+                                                                        selector);
+                       else
+                               best_val = _regulator_get_voltage(rdev);
+               }
+
        } else if (rdev->desc->ops->set_voltage_sel) {
-               if (rdev->desc->ops->map_voltage)
+               if (rdev->desc->ops->map_voltage) {
                        ret = rdev->desc->ops->map_voltage(rdev, min_uV,
                                                           max_uV);
-               else
-                       ret = regulator_map_voltage_iterate(rdev, min_uV,
-                                                           max_uV);
+               } else {
+                       if (rdev->desc->ops->list_voltage ==
+                           regulator_list_voltage_linear)
+                               ret = regulator_map_voltage_linear(rdev,
+                                                               min_uV, max_uV);
+                       else
+                               ret = regulator_map_voltage_iterate(rdev,
+                                                               min_uV, max_uV);
+               }
 
                if (ret >= 0) {
-                       selector = ret;
-                       ret = rdev->desc->ops->set_voltage_sel(rdev, ret);
+                       best_val = rdev->desc->ops->list_voltage(rdev, ret);
+                       if (min_uV <= best_val && max_uV >= best_val) {
+                               selector = ret;
+                               ret = rdev->desc->ops->set_voltage_sel(rdev,
+                                                                      ret);
+                       } else {
+                               ret = -EINVAL;
+                       }
                }
        } else {
                ret = -EINVAL;
        }
 
-       if (rdev->desc->ops->list_voltage)
-               best_val = rdev->desc->ops->list_voltage(rdev, selector);
-       else
-               best_val = -1;
-
        /* Call set_voltage_time_sel if successfully obtained old_selector */
-       if (ret == 0 && old_selector >= 0 &&
+       if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 &&
            rdev->desc->ops->set_voltage_time_sel) {
 
                delay = rdev->desc->ops->set_voltage_time_sel(rdev,
@@ -2126,19 +2168,19 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev,
                                  delay);
                        delay = 0;
                }
-       }
 
-       /* Insert any necessary delays */
-       if (delay >= 1000) {
-               mdelay(delay / 1000);
-               udelay(delay % 1000);
-       } else if (delay) {
-               udelay(delay);
+               /* Insert any necessary delays */
+               if (delay >= 1000) {
+                       mdelay(delay / 1000);
+                       udelay(delay % 1000);
+               } else if (delay) {
+                       udelay(delay);
+               }
        }
 
-       if (ret == 0)
+       if (ret == 0 && best_val >= 0)
                _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
-                                    NULL);
+                                    (void *)best_val);
 
        trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val);
 
@@ -2248,6 +2290,46 @@ int regulator_set_voltage_time(struct regulator *regulator,
 }
 EXPORT_SYMBOL_GPL(regulator_set_voltage_time);
 
+/**
+ *regulator_set_voltage_time_sel - get raise/fall time
+ * @regulator: regulator source
+ * @old_selector: selector for starting voltage
+ * @new_selector: selector for target voltage
+ *
+ * Provided with the starting and target voltage selectors, this function
+ * returns time in microseconds required to rise or fall to this new voltage
+ *
+ * Drivers providing ramp_delay in regulation_constraints can use this as their
+ * set_voltage_time_sel() operation.
+ */
+int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
+                                  unsigned int old_selector,
+                                  unsigned int new_selector)
+{
+       unsigned int ramp_delay = 0;
+       int old_volt, new_volt;
+
+       if (rdev->constraints->ramp_delay)
+               ramp_delay = rdev->constraints->ramp_delay;
+       else if (rdev->desc->ramp_delay)
+               ramp_delay = rdev->desc->ramp_delay;
+
+       if (ramp_delay == 0) {
+               rdev_warn(rdev, "ramp_delay not set\n");
+               return 0;
+       }
+
+       /* sanity check */
+       if (!rdev->desc->ops->list_voltage)
+               return -EINVAL;
+
+       old_volt = rdev->desc->ops->list_voltage(rdev, old_selector);
+       new_volt = rdev->desc->ops->list_voltage(rdev, new_selector);
+
+       return DIV_ROUND_UP(abs(new_volt - old_volt), ramp_delay);
+}
+EXPORT_SYMBOL_GPL(regulator_set_voltage_time_sel);
+
 /**
  * regulator_sync_voltage - re-apply last regulator output voltage
  * @regulator: regulator source
@@ -2628,7 +2710,7 @@ static void _notifier_call_chain(struct regulator_dev *rdev,
                                  unsigned long event, void *data)
 {
        /* call rdev chain first */
-       blocking_notifier_call_chain(&rdev->notifier, event, NULL);
+       blocking_notifier_call_chain(&rdev->notifier, event, data);
 }
 
 /**
@@ -2909,10 +2991,10 @@ int regulator_mode_to_status(unsigned int mode)
                return REGULATOR_STATUS_NORMAL;
        case REGULATOR_MODE_IDLE:
                return REGULATOR_STATUS_IDLE;
-       case REGULATOR_STATUS_STANDBY:
+       case REGULATOR_MODE_STANDBY:
                return REGULATOR_STATUS_STANDBY;
        default:
-               return 0;
+               return REGULATOR_STATUS_UNDEFINED;
        }
 }
 EXPORT_SYMBOL_GPL(regulator_mode_to_status);
@@ -3105,7 +3187,10 @@ regulator_register(const struct regulator_desc *regulator_desc,
        rdev->reg_data = config->driver_data;
        rdev->owner = regulator_desc->owner;
        rdev->desc = regulator_desc;
-       rdev->regmap = config->regmap;
+       if (config->regmap)
+               rdev->regmap = config->regmap;
+       else
+               rdev->regmap = dev_get_regmap(dev, NULL);
        INIT_LIST_HEAD(&rdev->consumer_list);
        INIT_LIST_HEAD(&rdev->list);
        BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier);
@@ -3132,6 +3217,26 @@ regulator_register(const struct regulator_desc *regulator_desc,
 
        dev_set_drvdata(&rdev->dev, rdev);
 
+       if (config->ena_gpio) {
+               ret = gpio_request_one(config->ena_gpio,
+                                      GPIOF_DIR_OUT | config->ena_gpio_flags,
+                                      rdev_get_name(rdev));
+               if (ret != 0) {
+                       rdev_err(rdev, "Failed to request enable GPIO%d: %d\n",
+                                config->ena_gpio, ret);
+                       goto clean;
+               }
+
+               rdev->ena_gpio = config->ena_gpio;
+               rdev->ena_gpio_invert = config->ena_gpio_invert;
+
+               if (config->ena_gpio_flags & GPIOF_OUT_INIT_HIGH)
+                       rdev->ena_gpio_state = 1;
+
+               if (rdev->ena_gpio_invert)
+                       rdev->ena_gpio_state = !rdev->ena_gpio_state;
+       }
+
        /* set regulator constraints */
        if (init_data)
                constraints = &init_data->constraints;
@@ -3200,6 +3305,8 @@ unset_supplies:
 scrub:
        if (rdev->supply)
                regulator_put(rdev->supply);
+       if (rdev->ena_gpio)
+               gpio_free(rdev->ena_gpio);
        kfree(rdev->constraints);
        device_unregister(&rdev->dev);
        /* device core frees rdev */
@@ -3233,6 +3340,8 @@ void regulator_unregister(struct regulator_dev *rdev)
        unset_regulator_supplies(rdev);
        list_del(&rdev->list);
        kfree(rdev->constraints);
+       if (rdev->ena_gpio)
+               gpio_free(rdev->ena_gpio);
        device_unregister(&rdev->dev);
        mutex_unlock(&regulator_list_mutex);
 }
@@ -3472,6 +3581,15 @@ static int __init regulator_init_complete(void)
        struct regulation_constraints *c;
        int enabled, ret;
 
+       /*
+        * Since DT doesn't provide an idiomatic mechanism for
+        * enabling full constraints and since it's much more natural
+        * with DT to provide them just assume that a DT enabled
+        * system has full constraints.
+        */
+       if (of_have_populated_dt())
+               has_full_constraints = true;
+
        mutex_lock(&regulator_list_mutex);
 
        /* If we have a full configuration then disable any regulators
index 1005f5f7e603e8f361718302d070adcfc80a236d..36c5b92fe0af26487cb093234800d534061c41f6 100644 (file)
@@ -107,6 +107,9 @@ static int da903x_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
        struct device *da9034_dev = to_da903x_dev(rdev);
        uint8_t val, mask;
 
+       if (rdev->desc->n_voltages == 1)
+               return -EINVAL;
+
        val = selector << info->vol_shift;
        mask = ((1 << info->vol_nbits) - 1)  << info->vol_shift;
 
@@ -120,6 +123,9 @@ static int da903x_get_voltage_sel(struct regulator_dev *rdev)
        uint8_t val, mask;
        int ret;
 
+       if (rdev->desc->n_voltages == 1)
+               return 0;
+
        ret = da903x_read(da9034_dev, info->vol_reg, &val);
        if (ret)
                return ret;
index 88976d8d44edd1af9d906ca8e2acea259ab46a37..903299cf15cfe8c9716d583fc3c49d76d4ac2d04 100644 (file)
@@ -405,12 +405,12 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev)
                if (!nproot)
                        return -ENODEV;
 
-               for (np = of_get_next_child(nproot, NULL); np;
-                    np = of_get_next_child(nproot, np)) {
+               for_each_child_of_node(nproot, np) {
                        if (!of_node_cmp(np->name,
                                         regulator->info->reg_desc.name)) {
                                config.init_data = of_get_regulator_init_data(
                                        &pdev->dev, np);
+                               config.of_node = np;
                                break;
                        }
                }
index cacd33c9d042fae944b3684811ad1cdc20ef5268..f9d027992aae119b466efa9ba0ac087ce8739074 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/slab.h>
+#include <linux/string.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/fixed.h>
@@ -13,17 +14,20 @@ static void regulator_fixed_release(struct device *dev)
 {
        struct fixed_regulator_data *data = container_of(dev,
                        struct fixed_regulator_data, pdev.dev);
+       kfree(data->cfg.supply_name);
        kfree(data);
 }
 
 /**
- * regulator_register_fixed - register a no-op fixed regulator
+ * regulator_register_fixed_name - register a no-op fixed regulator
  * @id: platform device id
+ * @name: name to be used for the regulator
  * @supplies: consumers for this regulator
  * @num_supplies: number of consumers
+ * @uv: voltage in microvolts
  */
-struct platform_device *regulator_register_fixed(int id,
-               struct regulator_consumer_supply *supplies, int num_supplies)
+struct platform_device *regulator_register_always_on(int id, const char *name,
+       struct regulator_consumer_supply *supplies, int num_supplies, int uv)
 {
        struct fixed_regulator_data *data;
 
@@ -31,8 +35,13 @@ struct platform_device *regulator_register_fixed(int id,
        if (!data)
                return NULL;
 
-       data->cfg.supply_name = "fixed-dummy";
-       data->cfg.microvolts = 0;
+       data->cfg.supply_name = kstrdup(name, GFP_KERNEL);
+       if (!data->cfg.supply_name) {
+               kfree(data);
+               return NULL;
+       }
+
+       data->cfg.microvolts = uv;
        data->cfg.gpio = -EINVAL;
        data->cfg.enabled_at_boot = 1;
        data->cfg.init_data = &data->init_data;
index f09fe7b20e82282e9f68957c1c7b56cad426544e..185468c4d38fcbe691c7842ca9a0f50068ca5e25 100644 (file)
@@ -35,10 +35,6 @@ struct fixed_voltage_data {
        struct regulator_desc desc;
        struct regulator_dev *dev;
        int microvolts;
-       int gpio;
-       unsigned startup_delay;
-       bool enable_high;
-       bool is_enabled;
 };
 
 
@@ -61,11 +57,11 @@ of_get_fixed_voltage_config(struct device *dev)
        config = devm_kzalloc(dev, sizeof(struct fixed_voltage_config),
                                                                 GFP_KERNEL);
        if (!config)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        config->init_data = of_get_regulator_init_data(dev, dev->of_node);
        if (!config->init_data)
-               return NULL;
+               return ERR_PTR(-EINVAL);
 
        init_data = config->init_data;
        init_data->constraints.apply_uV = 0;
@@ -76,13 +72,26 @@ of_get_fixed_voltage_config(struct device *dev)
        } else {
                dev_err(dev,
                         "Fixed regulator specified with variable voltages\n");
-               return NULL;
+               return ERR_PTR(-EINVAL);
        }
 
        if (init_data->constraints.boot_on)
                config->enabled_at_boot = true;
 
        config->gpio = of_get_named_gpio(np, "gpio", 0);
+       /*
+        * of_get_named_gpio() currently returns ENODEV rather than
+        * EPROBE_DEFER. This code attempts to be compatible with both
+        * for now; the ENODEV check can be removed once the API is fixed.
+        * of_get_named_gpio() doesn't differentiate between a missing
+        * property (which would be fine here, since the GPIO is optional)
+        * and some other error. Patches have been posted for both issues.
+        * Once they are check in, we should replace this with:
+        * if (config->gpio < 0 && config->gpio != -ENOENT)
+        */
+       if ((config->gpio == -ENODEV) || (config->gpio == -EPROBE_DEFER))
+               return ERR_PTR(-EPROBE_DEFER);
+
        delay = of_get_property(np, "startup-delay-us", NULL);
        if (delay)
                config->startup_delay = be32_to_cpu(*delay);
@@ -93,41 +102,10 @@ of_get_fixed_voltage_config(struct device *dev)
        if (of_find_property(np, "gpio-open-drain", NULL))
                config->gpio_is_open_drain = true;
 
-       return config;
-}
-
-static int fixed_voltage_is_enabled(struct regulator_dev *dev)
-{
-       struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-       return data->is_enabled;
-}
-
-static int fixed_voltage_enable(struct regulator_dev *dev)
-{
-       struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-       gpio_set_value_cansleep(data->gpio, data->enable_high);
-       data->is_enabled = true;
-
-       return 0;
-}
-
-static int fixed_voltage_disable(struct regulator_dev *dev)
-{
-       struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-       gpio_set_value_cansleep(data->gpio, !data->enable_high);
-       data->is_enabled = false;
-
-       return 0;
-}
+       if (of_find_property(np, "vin-supply", NULL))
+               config->input_supply = "vin";
 
-static int fixed_voltage_enable_time(struct regulator_dev *dev)
-{
-       struct fixed_voltage_data *data = rdev_get_drvdata(dev);
-
-       return data->startup_delay;
+       return config;
 }
 
 static int fixed_voltage_get_voltage(struct regulator_dev *dev)
@@ -151,15 +129,6 @@ static int fixed_voltage_list_voltage(struct regulator_dev *dev,
        return data->microvolts;
 }
 
-static struct regulator_ops fixed_voltage_gpio_ops = {
-       .is_enabled = fixed_voltage_is_enabled,
-       .enable = fixed_voltage_enable,
-       .disable = fixed_voltage_disable,
-       .enable_time = fixed_voltage_enable_time,
-       .get_voltage = fixed_voltage_get_voltage,
-       .list_voltage = fixed_voltage_list_voltage,
-};
-
 static struct regulator_ops fixed_voltage_ops = {
        .get_voltage = fixed_voltage_get_voltage,
        .list_voltage = fixed_voltage_list_voltage,
@@ -172,10 +141,13 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
        struct regulator_config cfg = { };
        int ret;
 
-       if (pdev->dev.of_node)
+       if (pdev->dev.of_node) {
                config = of_get_fixed_voltage_config(&pdev->dev);
-       else
+               if (IS_ERR(config))
+                       return PTR_ERR(config);
+       } else {
                config = pdev->dev.platform_data;
+       }
 
        if (!config)
                return -ENOMEM;
@@ -196,59 +168,44 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
        }
        drvdata->desc.type = REGULATOR_VOLTAGE;
        drvdata->desc.owner = THIS_MODULE;
+       drvdata->desc.ops = &fixed_voltage_ops;
 
-       if (config->microvolts)
-               drvdata->desc.n_voltages = 1;
+       drvdata->desc.enable_time = config->startup_delay;
 
-       drvdata->microvolts = config->microvolts;
-       drvdata->gpio = config->gpio;
-       drvdata->startup_delay = config->startup_delay;
-
-       if (gpio_is_valid(config->gpio)) {
-               int gpio_flag;
-               drvdata->enable_high = config->enable_high;
-
-               /* FIXME: Remove below print warning
-                *
-                * config->gpio must be set to -EINVAL by platform code if
-                * GPIO control is not required. However, early adopters
-                * not requiring GPIO control may forget to initialize
-                * config->gpio to -EINVAL. This will cause GPIO 0 to be used
-                * for GPIO control.
-                *
-                * This warning will be removed once there are a couple of users
-                * for this driver.
-                */
-               if (!config->gpio)
-                       dev_warn(&pdev->dev,
-                               "using GPIO 0 for regulator enable control\n");
-
-               /*
-                * set output direction without changing state
-                * to prevent glitch
-                */
-               drvdata->is_enabled = config->enabled_at_boot;
-               ret = drvdata->is_enabled ?
-                               config->enable_high : !config->enable_high;
-               gpio_flag = ret ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
-
-               if (config->gpio_is_open_drain)
-                       gpio_flag |= GPIOF_OPEN_DRAIN;
-
-               ret = gpio_request_one(config->gpio, gpio_flag,
-                                               config->supply_name);
-               if (ret) {
+       if (config->input_supply) {
+               drvdata->desc.supply_name = kstrdup(config->input_supply,
+                                                       GFP_KERNEL);
+               if (!drvdata->desc.supply_name) {
                        dev_err(&pdev->dev,
-                          "Could not obtain regulator enable GPIO %d: %d\n",
-                                                       config->gpio, ret);
+                               "Failed to allocate input supply\n");
+                       ret = -ENOMEM;
                        goto err_name;
                }
+       }
+
+       if (config->microvolts)
+               drvdata->desc.n_voltages = 1;
 
-               drvdata->desc.ops = &fixed_voltage_gpio_ops;
+       drvdata->microvolts = config->microvolts;
 
+       if (config->gpio >= 0)
+               cfg.ena_gpio = config->gpio;
+       cfg.ena_gpio_invert = !config->enable_high;
+       if (config->enabled_at_boot) {
+               if (config->enable_high) {
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
+               } else {
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
+               }
        } else {
-               drvdata->desc.ops = &fixed_voltage_ops;
+               if (config->enable_high) {
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
+               } else {
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
+               }
        }
+       if (config->gpio_is_open_drain)
+               cfg.ena_gpio_flags |= GPIOF_OPEN_DRAIN;
 
        cfg.dev = &pdev->dev;
        cfg.init_data = config->init_data;
@@ -259,7 +216,7 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
        if (IS_ERR(drvdata->dev)) {
                ret = PTR_ERR(drvdata->dev);
                dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret);
-               goto err_gpio;
+               goto err_input;
        }
 
        platform_set_drvdata(pdev, drvdata);
@@ -269,9 +226,8 @@ static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
 
        return 0;
 
-err_gpio:
-       if (gpio_is_valid(config->gpio))
-               gpio_free(config->gpio);
+err_input:
+       kfree(drvdata->desc.supply_name);
 err_name:
        kfree(drvdata->desc.name);
 err:
@@ -283,8 +239,7 @@ static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
        struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
 
        regulator_unregister(drvdata->dev);
-       if (gpio_is_valid(drvdata->gpio))
-               gpio_free(drvdata->gpio);
+       kfree(drvdata->desc.supply_name);
        kfree(drvdata->desc.name);
 
        return 0;
@@ -296,8 +251,6 @@ static const struct of_device_id fixed_of_match[] __devinitconst = {
        {},
 };
 MODULE_DEVICE_TABLE(of, fixed_of_match);
-#else
-#define fixed_of_match NULL
 #endif
 
 static struct platform_driver regulator_fixed_voltage_driver = {
@@ -306,7 +259,7 @@ static struct platform_driver regulator_fixed_voltage_driver = {
        .driver         = {
                .name           = "reg-fixed-voltage",
                .owner          = THIS_MODULE,
-               .of_match_table = fixed_of_match,
+               .of_match_table = of_match_ptr(fixed_of_match),
        },
 };
 
index 242851a4c1a606d69b41efad88f74dc1060817db..34b67bee9323ce00a49b30bb0cf7d9256660b6f8 100644 (file)
@@ -36,11 +36,6 @@ struct gpio_regulator_data {
        struct regulator_desc desc;
        struct regulator_dev *dev;
 
-       int enable_gpio;
-       bool enable_high;
-       bool is_enabled;
-       unsigned startup_delay;
-
        struct gpio *gpios;
        int nr_gpios;
 
@@ -50,44 +45,6 @@ struct gpio_regulator_data {
        int state;
 };
 
-static int gpio_regulator_is_enabled(struct regulator_dev *dev)
-{
-       struct gpio_regulator_data *data = rdev_get_drvdata(dev);
-
-       return data->is_enabled;
-}
-
-static int gpio_regulator_enable(struct regulator_dev *dev)
-{
-       struct gpio_regulator_data *data = rdev_get_drvdata(dev);
-
-       if (gpio_is_valid(data->enable_gpio)) {
-               gpio_set_value_cansleep(data->enable_gpio, data->enable_high);
-               data->is_enabled = true;
-       }
-
-       return 0;
-}
-
-static int gpio_regulator_disable(struct regulator_dev *dev)
-{
-       struct gpio_regulator_data *data = rdev_get_drvdata(dev);
-
-       if (gpio_is_valid(data->enable_gpio)) {
-               gpio_set_value_cansleep(data->enable_gpio, !data->enable_high);
-               data->is_enabled = false;
-       }
-
-       return 0;
-}
-
-static int gpio_regulator_enable_time(struct regulator_dev *dev)
-{
-       struct gpio_regulator_data *data = rdev_get_drvdata(dev);
-
-       return data->startup_delay;
-}
-
 static int gpio_regulator_get_value(struct regulator_dev *dev)
 {
        struct gpio_regulator_data *data = rdev_get_drvdata(dev);
@@ -153,20 +110,12 @@ static int gpio_regulator_set_current_limit(struct regulator_dev *dev,
 }
 
 static struct regulator_ops gpio_regulator_voltage_ops = {
-       .is_enabled = gpio_regulator_is_enabled,
-       .enable = gpio_regulator_enable,
-       .disable = gpio_regulator_disable,
-       .enable_time = gpio_regulator_enable_time,
        .get_voltage = gpio_regulator_get_value,
        .set_voltage = gpio_regulator_set_voltage,
        .list_voltage = gpio_regulator_list_voltage,
 };
 
 static struct regulator_ops gpio_regulator_current_ops = {
-       .is_enabled = gpio_regulator_is_enabled,
-       .enable = gpio_regulator_enable,
-       .disable = gpio_regulator_disable,
-       .enable_time = gpio_regulator_enable_time,
        .get_current_limit = gpio_regulator_get_value,
        .set_current_limit = gpio_regulator_set_current_limit,
 };
@@ -213,6 +162,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
        drvdata->nr_states = config->nr_states;
 
        drvdata->desc.owner = THIS_MODULE;
+       drvdata->desc.enable_time = config->startup_delay;
 
        /* handle regulator type*/
        switch (config->type) {
@@ -232,52 +182,12 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
                break;
        }
 
-       drvdata->enable_gpio = config->enable_gpio;
-       drvdata->startup_delay = config->startup_delay;
-
-       if (gpio_is_valid(config->enable_gpio)) {
-               drvdata->enable_high = config->enable_high;
-
-               ret = gpio_request(config->enable_gpio, config->supply_name);
-               if (ret) {
-                       dev_err(&pdev->dev,
-                          "Could not obtain regulator enable GPIO %d: %d\n",
-                                               config->enable_gpio, ret);
-                       goto err_memstate;
-               }
-
-               /* set output direction without changing state
-                * to prevent glitch
-                */
-               if (config->enabled_at_boot) {
-                       drvdata->is_enabled = true;
-                       ret = gpio_direction_output(config->enable_gpio,
-                                                   config->enable_high);
-               } else {
-                       drvdata->is_enabled = false;
-                       ret = gpio_direction_output(config->enable_gpio,
-                                                   !config->enable_high);
-               }
-
-               if (ret) {
-                       dev_err(&pdev->dev,
-                          "Could not configure regulator enable GPIO %d direction: %d\n",
-                                               config->enable_gpio, ret);
-                       goto err_enablegpio;
-               }
-       } else {
-               /* Regulator without GPIO control is considered
-                * always enabled
-                */
-               drvdata->is_enabled = true;
-       }
-
        drvdata->nr_gpios = config->nr_gpios;
        ret = gpio_request_array(drvdata->gpios, drvdata->nr_gpios);
        if (ret) {
                dev_err(&pdev->dev,
                   "Could not obtain regulator setting GPIOs: %d\n", ret);
-               goto err_enablegpio;
+               goto err_memstate;
        }
 
        /* build initial state from gpio init data. */
@@ -292,6 +202,21 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
        cfg.init_data = config->init_data;
        cfg.driver_data = drvdata;
 
+       if (config->enable_gpio >= 0)
+               cfg.ena_gpio = config->enable_gpio;
+       cfg.ena_gpio_invert = !config->enable_high;
+       if (config->enabled_at_boot) {
+               if (config->enable_high)
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
+               else
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
+       } else {
+               if (config->enable_high)
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
+               else
+                       cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
+       }
+
        drvdata->dev = regulator_register(&drvdata->desc, &cfg);
        if (IS_ERR(drvdata->dev)) {
                ret = PTR_ERR(drvdata->dev);
@@ -305,9 +230,6 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
 
 err_stategpio:
        gpio_free_array(drvdata->gpios, drvdata->nr_gpios);
-err_enablegpio:
-       if (gpio_is_valid(config->enable_gpio))
-               gpio_free(config->enable_gpio);
 err_memstate:
        kfree(drvdata->states);
 err_memgpio:
@@ -329,9 +251,6 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev)
        kfree(drvdata->states);
        kfree(drvdata->gpios);
 
-       if (gpio_is_valid(drvdata->enable_gpio))
-               gpio_free(drvdata->enable_gpio);
-
        kfree(drvdata->desc.name);
 
        return 0;
index 56d273f2560372371d1b3de53e0141d82bd8cfa6..1d145a07ada940d0308e1197eb4a961a9e988b9a 100644 (file)
@@ -75,19 +75,12 @@ static struct regulator_ops isl_core_ops = {
 
 static int isl6271a_get_fixed_voltage(struct regulator_dev *dev)
 {
-       int id = rdev_get_id(dev);
-       return (id == 1) ? 1100000 : 1300000;
-}
-
-static int isl6271a_list_fixed_voltage(struct regulator_dev *dev, unsigned selector)
-{
-       int id = rdev_get_id(dev);
-       return (id == 1) ? 1100000 : 1300000;
+       return dev->desc->min_uV;
 }
 
 static struct regulator_ops isl_fixed_ops = {
        .get_voltage    = isl6271a_get_fixed_voltage,
-       .list_voltage   = isl6271a_list_fixed_voltage,
+       .list_voltage   = regulator_list_voltage_linear,
 };
 
 static const struct regulator_desc isl_rd[] = {
@@ -107,6 +100,7 @@ static const struct regulator_desc isl_rd[] = {
                .ops            = &isl_fixed_ops,
                .type           = REGULATOR_VOLTAGE,
                .owner          = THIS_MODULE,
+               .min_uV         = 1100000,
        }, {
                .name           = "LDO2",
                .id             = 2,
@@ -114,6 +108,7 @@ static const struct regulator_desc isl_rd[] = {
                .ops            = &isl_fixed_ops,
                .type           = REGULATOR_VOLTAGE,
                .owner          = THIS_MODULE,
+               .min_uV         = 1300000,
        },
 };
 
index 981bea9cb9d7d9c55a2f6e821523c695f35bf83c..7c6e3b8ff484ad03ab60fd25d07f74d80395a65f 100644 (file)
@@ -65,11 +65,11 @@ static const int buck_base_addr[] = {
 #define LP3971_BUCK_TARGET_VOL1_REG(x) (buck_base_addr[x])
 #define LP3971_BUCK_TARGET_VOL2_REG(x) (buck_base_addr[x]+1)
 
-static const int buck_voltage_map[] = {
-          0,  800,  850,  900,  950, 1000, 1050, 1100,
-       1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500,
-       1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800,
-       3000, 3300,
+static const unsigned int buck_voltage_map[] = {
+             0,  800000,  850000,  900000,  950000, 1000000, 1050000, 1100000,
+       1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
+       1550000, 1600000, 1650000, 1700000, 1800000, 1900000, 2500000, 2800000,
+       3000000, 3300000,
 };
 
 #define BUCK_TARGET_VOL_MASK 0x3f
@@ -98,39 +98,19 @@ static const int buck_voltage_map[] = {
 #define LDO_VOL_CONTR_SHIFT(x) ((x & 1) << 2)
 #define LDO_VOL_CONTR_MASK 0x0f
 
-static const int ldo45_voltage_map[] = {
-       1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350,
-       1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300,
+static const unsigned int ldo45_voltage_map[] = {
+       1000000, 1050000, 1100000, 1150000, 1200000, 1250000, 1300000, 1350000,
+       1400000, 1500000, 1800000, 1900000, 2500000, 2800000, 3000000, 3300000,
 };
 
-static const int ldo123_voltage_map[] = {
-       1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500,
-       2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300,
+static const unsigned int ldo123_voltage_map[] = {
+       1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
+       2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000,
 };
 
-static const int *ldo_voltage_map[] = {
-       ldo123_voltage_map, /* LDO1 */
-       ldo123_voltage_map, /* LDO2 */
-       ldo123_voltage_map, /* LDO3 */
-       ldo45_voltage_map, /* LDO4 */
-       ldo45_voltage_map, /* LDO5 */
-};
-
-#define LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[(x - LP3971_LDO1)])
-
 #define LDO_VOL_MIN_IDX 0x00
 #define LDO_VOL_MAX_IDX 0x0f
 
-static int lp3971_ldo_list_voltage(struct regulator_dev *dev, unsigned index)
-{
-       int ldo = rdev_get_id(dev) - LP3971_LDO1;
-
-       if (index > LDO_VOL_MAX_IDX)
-               return -EINVAL;
-
-       return 1000 * LDO_VOL_VALUE_MAP(ldo)[index];
-}
-
 static int lp3971_ldo_is_enabled(struct regulator_dev *dev)
 {
        struct lp3971 *lp3971 = rdev_get_drvdata(dev);
@@ -169,7 +149,7 @@ static int lp3971_ldo_get_voltage(struct regulator_dev *dev)
        reg = lp3971_reg_read(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo));
        val = (reg >> LDO_VOL_CONTR_SHIFT(ldo)) & LDO_VOL_CONTR_MASK;
 
-       return 1000 * LDO_VOL_VALUE_MAP(ldo)[val];
+       return dev->desc->volt_table[val];
 }
 
 static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev,
@@ -184,7 +164,7 @@ static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev,
 }
 
 static struct regulator_ops lp3971_ldo_ops = {
-       .list_voltage = lp3971_ldo_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .is_enabled = lp3971_ldo_is_enabled,
        .enable = lp3971_ldo_enable,
        .disable = lp3971_ldo_disable,
@@ -192,14 +172,6 @@ static struct regulator_ops lp3971_ldo_ops = {
        .set_voltage_sel = lp3971_ldo_set_voltage_sel,
 };
 
-static int lp3971_dcdc_list_voltage(struct regulator_dev *dev, unsigned index)
-{
-       if (index < BUCK_TARGET_VOL_MIN_IDX || index > BUCK_TARGET_VOL_MAX_IDX)
-               return -EINVAL;
-
-       return 1000 * buck_voltage_map[index];
-}
-
 static int lp3971_dcdc_is_enabled(struct regulator_dev *dev)
 {
        struct lp3971 *lp3971 = rdev_get_drvdata(dev);
@@ -240,7 +212,7 @@ static int lp3971_dcdc_get_voltage(struct regulator_dev *dev)
        reg &= BUCK_TARGET_VOL_MASK;
 
        if (reg <= BUCK_TARGET_VOL_MAX_IDX)
-               val = 1000 * buck_voltage_map[reg];
+               val = buck_voltage_map[reg];
        else {
                val = 0;
                dev_warn(&dev->dev, "chip reported incorrect voltage value.\n");
@@ -273,7 +245,7 @@ static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev,
 }
 
 static struct regulator_ops lp3971_dcdc_ops = {
-       .list_voltage = lp3971_dcdc_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .is_enabled = lp3971_dcdc_is_enabled,
        .enable = lp3971_dcdc_enable,
        .disable = lp3971_dcdc_disable,
@@ -287,6 +259,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_LDO1,
                .ops = &lp3971_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo123_voltage_map),
+               .volt_table = ldo123_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -295,6 +268,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_LDO2,
                .ops = &lp3971_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo123_voltage_map),
+               .volt_table = ldo123_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -303,6 +277,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_LDO3,
                .ops = &lp3971_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo123_voltage_map),
+               .volt_table = ldo123_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -311,6 +286,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_LDO4,
                .ops = &lp3971_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo45_voltage_map),
+               .volt_table = ldo45_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -319,6 +295,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_LDO5,
                .ops = &lp3971_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo45_voltage_map),
+               .volt_table = ldo45_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -327,6 +304,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_DCDC1,
                .ops = &lp3971_dcdc_ops,
                .n_voltages = ARRAY_SIZE(buck_voltage_map),
+               .volt_table = buck_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -335,6 +313,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_DCDC2,
                .ops = &lp3971_dcdc_ops,
                .n_voltages = ARRAY_SIZE(buck_voltage_map),
+               .volt_table = buck_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -343,6 +322,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3971_DCDC3,
                .ops = &lp3971_dcdc_ops,
                .n_voltages = ARRAY_SIZE(buck_voltage_map),
+               .volt_table = buck_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
index de073df7d3449a69d0a991c27c95f23f6b0285e3..3cdc755d9b225774aabf25a1101f4aeeae591cec 100644 (file)
@@ -74,54 +74,40 @@ struct lp3972 {
 #define LP3972_OVER2_LDO4_EN   BIT(4)
 #define LP3972_OVER1_S_EN      BIT(2)
 
-static const int ldo1_voltage_map[] = {
-       1700, 1725, 1750, 1775, 1800, 1825, 1850, 1875,
-       1900, 1925, 1950, 1975, 2000,
+static const unsigned int ldo1_voltage_map[] = {
+       1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000,
+       1900000, 1925000, 1950000, 1975000, 2000000,
 };
 
-static const int ldo23_voltage_map[] = {
-       1800, 1900, 2000, 2100, 2200, 2300, 2400, 2500,
-       2600, 2700, 2800, 2900, 3000, 3100, 3200, 3300,
+static const unsigned int ldo23_voltage_map[] = {
+       1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
+       2600000, 2700000, 2800000, 2900000, 3000000, 3100000, 3200000, 3300000,
 };
 
-static const int ldo4_voltage_map[] = {
-       1000, 1050, 1100, 1150, 1200, 1250, 1300, 1350,
-       1400, 1500, 1800, 1900, 2500, 2800, 3000, 3300,
+static const unsigned int ldo4_voltage_map[] = {
+       1000000, 1050000, 1100000, 1150000, 1200000, 1250000, 1300000, 1350000,
+       1400000, 1500000, 1800000, 1900000, 2500000, 2800000, 3000000, 3300000,
 };
 
-static const int ldo5_voltage_map[] = {
-          0,    0,    0,    0,    0,  850,  875,  900,
-        925,  950,  975, 1000, 1025, 1050, 1075, 1100,
-       1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300,
-       1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500,
+static const unsigned int ldo5_voltage_map[] = {
+             0,       0,       0,       0,       0,  850000,  875000,  900000,
+        925000,  950000,  975000, 1000000, 1025000, 1050000, 1075000, 1100000,
+       1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
+       1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
 };
 
-static const int buck1_voltage_map[] = {
-        725,  750,  775,  800,  825,  850,  875,  900,
-        925,  950,  975, 1000, 1025, 1050, 1075, 1100,
-       1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300,
-       1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500,
+static const unsigned int buck1_voltage_map[] = {
+        725000,  750000,  775000,  800000,  825000,  850000,  875000,  900000,
+        925000,  950000,  975000, 1000000, 1025000, 1050000, 1075000, 1100000,
+       1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
+       1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
 };
 
-static const int buck23_voltage_map[] = {
-          0,  800,  850,  900,  950, 1000, 1050, 1100,
-       1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500,
-       1550, 1600, 1650, 1700, 1800, 1900, 2500, 2800,
-       3000, 3300,
-};
-
-static const int *ldo_voltage_map[] = {
-       ldo1_voltage_map,
-       ldo23_voltage_map,
-       ldo23_voltage_map,
-       ldo4_voltage_map,
-       ldo5_voltage_map,
-};
-
-static const int *buck_voltage_map[] = {
-       buck1_voltage_map,
-       buck23_voltage_map,
-       buck23_voltage_map,
+static const unsigned int buck23_voltage_map[] = {
+             0,  800000,  850000,  900000,  950000, 1000000, 1050000, 1100000,
+       1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
+       1550000, 1600000, 1650000, 1700000, 1800000, 1900000, 2500000, 2800000,
+       3000000, 3300000,
 };
 
 static const int ldo_output_enable_mask[] = {
@@ -160,7 +146,6 @@ static const int buck_base_addr[] = {
        LP3972_B3TV_REG,
 };
 
-#define LP3972_LDO_VOL_VALUE_MAP(x) (ldo_voltage_map[x])
 #define LP3972_LDO_OUTPUT_ENABLE_MASK(x) (ldo_output_enable_mask[x])
 #define LP3972_LDO_OUTPUT_ENABLE_REG(x) (ldo_output_enable_addr[x])
 
@@ -177,7 +162,6 @@ static const int buck_base_addr[] = {
 #define LP3972_LDO_VOL_MIN_IDX(x) (((x) == 4) ? 0x05 : 0x00)
 #define LP3972_LDO_VOL_MAX_IDX(x) ((x) ? (((x) == 4) ? 0x1f : 0x0f) : 0x0c)
 
-#define LP3972_BUCK_VOL_VALUE_MAP(x) (buck_voltage_map[x])
 #define LP3972_BUCK_VOL_ENABLE_REG(x) (buck_vol_enable_addr[x])
 #define LP3972_BUCK_VOL1_REG(x) (buck_base_addr[x])
 #define LP3972_BUCK_VOL_MASK 0x1f
@@ -242,17 +226,6 @@ static int lp3972_set_bits(struct lp3972 *lp3972, u8 reg, u16 mask, u16 val)
        return ret;
 }
 
-static int lp3972_ldo_list_voltage(struct regulator_dev *dev, unsigned index)
-{
-       int ldo = rdev_get_id(dev) - LP3972_LDO1;
-
-       if (index < LP3972_LDO_VOL_MIN_IDX(ldo) ||
-           index > LP3972_LDO_VOL_MAX_IDX(ldo))
-               return -EINVAL;
-
-       return 1000 * LP3972_LDO_VOL_VALUE_MAP(ldo)[index];
-}
-
 static int lp3972_ldo_is_enabled(struct regulator_dev *dev)
 {
        struct lp3972 *lp3972 = rdev_get_drvdata(dev);
@@ -294,7 +267,7 @@ static int lp3972_ldo_get_voltage(struct regulator_dev *dev)
        reg = lp3972_reg_read(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo));
        val = (reg >> LP3972_LDO_VOL_CONTR_SHIFT(ldo)) & mask;
 
-       return 1000 * LP3972_LDO_VOL_VALUE_MAP(ldo)[val];
+       return dev->desc->volt_table[val];
 }
 
 static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev,
@@ -337,7 +310,7 @@ static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev,
 }
 
 static struct regulator_ops lp3972_ldo_ops = {
-       .list_voltage = lp3972_ldo_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .is_enabled = lp3972_ldo_is_enabled,
        .enable = lp3972_ldo_enable,
        .disable = lp3972_ldo_disable,
@@ -345,17 +318,6 @@ static struct regulator_ops lp3972_ldo_ops = {
        .set_voltage_sel = lp3972_ldo_set_voltage_sel,
 };
 
-static int lp3972_dcdc_list_voltage(struct regulator_dev *dev, unsigned index)
-{
-       int buck = rdev_get_id(dev) - LP3972_DCDC1;
-
-       if (index < LP3972_BUCK_VOL_MIN_IDX(buck) ||
-           index > LP3972_BUCK_VOL_MAX_IDX(buck))
-               return -EINVAL;
-
-       return 1000 * buck_voltage_map[buck][index];
-}
-
 static int lp3972_dcdc_is_enabled(struct regulator_dev *dev)
 {
        struct lp3972 *lp3972 = rdev_get_drvdata(dev);
@@ -401,7 +363,7 @@ static int lp3972_dcdc_get_voltage(struct regulator_dev *dev)
        reg = lp3972_reg_read(lp3972, LP3972_BUCK_VOL1_REG(buck));
        reg &= LP3972_BUCK_VOL_MASK;
        if (reg <= LP3972_BUCK_VOL_MAX_IDX(buck))
-               val = 1000 * buck_voltage_map[buck][reg];
+               val = dev->desc->volt_table[reg];
        else {
                val = 0;
                dev_warn(&dev->dev, "chip reported incorrect voltage value."
@@ -436,7 +398,7 @@ static int lp3972_dcdc_set_voltage_sel(struct regulator_dev *dev,
 }
 
 static struct regulator_ops lp3972_dcdc_ops = {
-       .list_voltage = lp3972_dcdc_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .is_enabled = lp3972_dcdc_is_enabled,
        .enable = lp3972_dcdc_enable,
        .disable = lp3972_dcdc_disable,
@@ -450,6 +412,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_LDO1,
                .ops = &lp3972_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo1_voltage_map),
+               .volt_table = ldo1_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -458,6 +421,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_LDO2,
                .ops = &lp3972_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo23_voltage_map),
+               .volt_table = ldo23_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -466,6 +430,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_LDO3,
                .ops = &lp3972_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo23_voltage_map),
+               .volt_table = ldo23_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -474,6 +439,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_LDO4,
                .ops = &lp3972_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo4_voltage_map),
+               .volt_table = ldo4_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -482,6 +448,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_LDO5,
                .ops = &lp3972_ldo_ops,
                .n_voltages = ARRAY_SIZE(ldo5_voltage_map),
+               .volt_table = ldo5_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -490,6 +457,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_DCDC1,
                .ops = &lp3972_dcdc_ops,
                .n_voltages = ARRAY_SIZE(buck1_voltage_map),
+               .volt_table = buck1_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -498,6 +466,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_DCDC2,
                .ops = &lp3972_dcdc_ops,
                .n_voltages = ARRAY_SIZE(buck23_voltage_map),
+               .volt_table = buck23_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
@@ -506,6 +475,7 @@ static const struct regulator_desc regulators[] = {
                .id = LP3972_DCDC3,
                .ops = &lp3972_dcdc_ops,
                .n_voltages = ARRAY_SIZE(buck23_voltage_map),
+               .volt_table = buck23_voltage_map,
                .type = REGULATOR_VOLTAGE,
                .owner = THIS_MODULE,
        },
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
new file mode 100644 (file)
index 0000000..212c38e
--- /dev/null
@@ -0,0 +1,943 @@
+/*
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/regulator/lp872x.h>
+#include <linux/regulator/driver.h>
+#include <linux/platform_device.h>
+
+/* Registers : LP8720/8725 shared */
+#define LP872X_GENERAL_CFG             0x00
+#define LP872X_LDO1_VOUT               0x01
+#define LP872X_LDO2_VOUT               0x02
+#define LP872X_LDO3_VOUT               0x03
+#define LP872X_LDO4_VOUT               0x04
+#define LP872X_LDO5_VOUT               0x05
+
+/* Registers : LP8720 */
+#define LP8720_BUCK_VOUT1              0x06
+#define LP8720_BUCK_VOUT2              0x07
+#define LP8720_ENABLE                  0x08
+
+/* Registers : LP8725 */
+#define LP8725_LILO1_VOUT              0x06
+#define LP8725_LILO2_VOUT              0x07
+#define LP8725_BUCK1_VOUT1             0x08
+#define LP8725_BUCK1_VOUT2             0x09
+#define LP8725_BUCK2_VOUT1             0x0A
+#define LP8725_BUCK2_VOUT2             0x0B
+#define LP8725_BUCK_CTRL               0x0C
+#define LP8725_LDO_CTRL                        0x0D
+
+/* Mask/shift : LP8720/LP8725 shared */
+#define LP872X_VOUT_M                  0x1F
+#define LP872X_START_DELAY_M           0xE0
+#define LP872X_START_DELAY_S           5
+#define LP872X_EN_LDO1_M               BIT(0)
+#define LP872X_EN_LDO2_M               BIT(1)
+#define LP872X_EN_LDO3_M               BIT(2)
+#define LP872X_EN_LDO4_M               BIT(3)
+#define LP872X_EN_LDO5_M               BIT(4)
+
+/* Mask/shift : LP8720 */
+#define LP8720_TIMESTEP_S              0               /* Addr 00h */
+#define LP8720_TIMESTEP_M              BIT(0)
+#define LP8720_EXT_DVS_M               BIT(2)
+#define LP8720_BUCK_FPWM_S             5               /* Addr 07h */
+#define LP8720_BUCK_FPWM_M             BIT(5)
+#define LP8720_EN_BUCK_M               BIT(5)          /* Addr 08h */
+#define LP8720_DVS_SEL_M               BIT(7)
+
+/* Mask/shift : LP8725 */
+#define LP8725_TIMESTEP_M              0xC0            /* Addr 00h */
+#define LP8725_TIMESTEP_S              6
+#define LP8725_BUCK1_EN_M              BIT(0)
+#define LP8725_DVS1_M                  BIT(2)
+#define LP8725_DVS2_M                  BIT(3)
+#define LP8725_BUCK2_EN_M              BIT(4)
+#define LP8725_BUCK_CL_M               0xC0            /* Addr 09h, 0Bh */
+#define LP8725_BUCK_CL_S               6
+#define LP8725_BUCK1_FPWM_S            1               /* Addr 0Ch */
+#define LP8725_BUCK1_FPWM_M            BIT(1)
+#define LP8725_BUCK2_FPWM_S            5
+#define LP8725_BUCK2_FPWM_M            BIT(5)
+#define LP8725_EN_LILO1_M              BIT(5)          /* Addr 0Dh */
+#define LP8725_EN_LILO2_M              BIT(6)
+
+/* PWM mode */
+#define LP872X_FORCE_PWM               1
+#define LP872X_AUTO_PWM                        0
+
+#define LP8720_NUM_REGULATORS          6
+#define LP8725_NUM_REGULATORS          9
+#define EXTERN_DVS_USED                        0
+#define MAX_DELAY                      6
+
+/* dump registers in regmap-debugfs */
+#define MAX_REGISTERS                  0x0F
+
+enum lp872x_id {
+       LP8720,
+       LP8725,
+};
+
+struct lp872x {
+       struct regmap *regmap;
+       struct device *dev;
+       enum lp872x_id chipid;
+       struct lp872x_platform_data *pdata;
+       struct regulator_dev **regulators;
+       int num_regulators;
+       enum lp872x_dvs_state dvs_pin;
+       int dvs_gpio;
+};
+
+/* LP8720/LP8725 shared voltage table for LDOs */
+static const unsigned int lp872x_ldo_vtbl[] = {
+       1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000, 1550000,
+       1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000, 2000000,
+       2100000, 2200000, 2300000, 2400000, 2500000, 2600000, 2650000, 2700000,
+       2750000, 2800000, 2850000, 2900000, 2950000, 3000000, 3100000, 3300000,
+};
+
+/* LP8720 LDO4 voltage table */
+static const unsigned int lp8720_ldo4_vtbl[] = {
+        800000,  850000,  900000, 1000000, 1100000, 1200000, 1250000, 1300000,
+       1350000, 1400000, 1450000, 1500000, 1550000, 1600000, 1650000, 1700000,
+       1750000, 1800000, 1850000, 1900000, 2000000, 2100000, 2200000, 2300000,
+       2400000, 2500000, 2600000, 2650000, 2700000, 2750000, 2800000, 2850000,
+};
+
+/* LP8725 LILO(Low Input Low Output) voltage table */
+static const unsigned int lp8725_lilo_vtbl[] = {
+        800000,  850000,  900000,  950000, 1000000, 1050000, 1100000, 1150000,
+       1200000, 1250000, 1300000, 1350000, 1400000, 1500000, 1600000, 1700000,
+       1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
+       2600000, 2700000, 2800000, 2850000, 2900000, 3000000, 3100000, 3300000,
+};
+
+/* LP8720 BUCK voltage table */
+#define EXT_R          0       /* external resistor divider */
+static const unsigned int lp8720_buck_vtbl[] = {
+         EXT_R,  800000,  850000,  900000,  950000, 1000000, 1050000, 1100000,
+       1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
+       1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000,
+       1950000, 2000000, 2050000, 2100000, 2150000, 2200000, 2250000, 2300000,
+};
+
+/* LP8725 BUCK voltage table */
+static const unsigned int lp8725_buck_vtbl[] = {
+        800000,  850000,  900000,  950000, 1000000, 1050000, 1100000, 1150000,
+       1200000, 1250000, 1300000, 1350000, 1400000, 1500000, 1600000, 1700000,
+       1750000, 1800000, 1850000, 1900000, 2000000, 2100000, 2200000, 2300000,
+       2400000, 2500000, 2600000, 2700000, 2800000, 2850000, 2900000, 3000000,
+};
+
+/* LP8725 BUCK current limit */
+static const unsigned int lp8725_buck_uA[] = {
+       460000, 780000, 1050000, 1370000,
+};
+
+static int lp872x_read_byte(struct lp872x *lp, u8 addr, u8 *data)
+{
+       int ret;
+       unsigned int val;
+
+       ret = regmap_read(lp->regmap, addr, &val);
+       if (ret < 0) {
+               dev_err(lp->dev, "failed to read 0x%.2x\n", addr);
+               return ret;
+       }
+
+       *data = (u8)val;
+       return 0;
+}
+
+static inline int lp872x_write_byte(struct lp872x *lp, u8 addr, u8 data)
+{
+       return regmap_write(lp->regmap, addr, data);
+}
+
+static inline int lp872x_update_bits(struct lp872x *lp, u8 addr,
+                               unsigned int mask, u8 data)
+{
+       return regmap_update_bits(lp->regmap, addr, mask, data);
+}
+
+static int _rdev_to_offset(struct regulator_dev *rdev)
+{
+       enum lp872x_regulator_id id = rdev_get_id(rdev);
+
+       switch (id) {
+       case LP8720_ID_LDO1 ... LP8720_ID_BUCK:
+               return id;
+       case LP8725_ID_LDO1 ... LP8725_ID_BUCK2:
+               return id - LP8725_ID_BASE;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int lp872x_get_timestep_usec(struct lp872x *lp)
+{
+       enum lp872x_id chip = lp->chipid;
+       u8 val, mask, shift;
+       int *time_usec, size, ret;
+       int lp8720_time_usec[] = { 25, 50 };
+       int lp8725_time_usec[] = { 32, 64, 128, 256 };
+
+       switch (chip) {
+       case LP8720:
+               mask = LP8720_TIMESTEP_M;
+               shift = LP8720_TIMESTEP_S;
+               time_usec = &lp8720_time_usec[0];
+               size = ARRAY_SIZE(lp8720_time_usec);
+               break;
+       case LP8725:
+               mask = LP8725_TIMESTEP_M;
+               shift = LP8725_TIMESTEP_S;
+               time_usec = &lp8725_time_usec[0];
+               size = ARRAY_SIZE(lp8725_time_usec);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val);
+       if (ret)
+               return -EINVAL;
+
+       val = (val & mask) >> shift;
+       if (val >= size)
+               return -EINVAL;
+
+       return *(time_usec + val);
+}
+
+static int lp872x_regulator_enable_time(struct regulator_dev *rdev)
+{
+       struct lp872x *lp = rdev_get_drvdata(rdev);
+       enum lp872x_regulator_id regulator = rdev_get_id(rdev);
+       int time_step_us = lp872x_get_timestep_usec(lp);
+       int ret, offset;
+       u8 addr, val;
+
+       if (time_step_us < 0)
+               return -EINVAL;
+
+       switch (regulator) {
+       case LP8720_ID_LDO1 ... LP8720_ID_LDO5:
+       case LP8725_ID_LDO1 ... LP8725_ID_LILO2:
+               offset = _rdev_to_offset(rdev);
+               if (offset < 0)
+                       return -EINVAL;
+
+               addr = LP872X_LDO1_VOUT + offset;
+               break;
+       case LP8720_ID_BUCK:
+               addr = LP8720_BUCK_VOUT1;
+               break;
+       case LP8725_ID_BUCK1:
+               addr = LP8725_BUCK1_VOUT1;
+               break;
+       case LP8725_ID_BUCK2:
+               addr = LP8725_BUCK2_VOUT1;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = lp872x_read_byte(lp, addr, &val);
+       if (ret)
+               return ret;
+
+       val = (val & LP872X_START_DELAY_M) >> LP872X_START_DELAY_S;
+
+       return val > MAX_DELAY ? 0 : val * time_step_us;
+}
+
+static void lp872x_set_dvs(struct lp872x *lp, int gpio)
+{
+       enum lp872x_dvs_sel dvs_sel = lp->pdata->dvs->vsel;
+       enum lp872x_dvs_state state;
+
+       state = dvs_sel == SEL_V1 ? DVS_HIGH : DVS_LOW;
+       gpio_set_value(gpio, state);
+       lp->dvs_pin = state;
+}
+
+static u8 lp872x_select_buck_vout_addr(struct lp872x *lp,
+                               enum lp872x_regulator_id buck)
+{
+       u8 val, addr;
+
+       if (lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val))
+               return 0;
+
+       switch (buck) {
+       case LP8720_ID_BUCK:
+               if (val & LP8720_EXT_DVS_M) {
+                       addr = (lp->dvs_pin == DVS_HIGH) ?
+                               LP8720_BUCK_VOUT1 : LP8720_BUCK_VOUT2;
+               } else {
+                       if (lp872x_read_byte(lp, LP8720_ENABLE, &val))
+                               return 0;
+
+                       addr = val & LP8720_DVS_SEL_M ?
+                               LP8720_BUCK_VOUT1 : LP8720_BUCK_VOUT2;
+               }
+               break;
+       case LP8725_ID_BUCK1:
+               if (val & LP8725_DVS1_M)
+                       addr = LP8725_BUCK1_VOUT1;
+               else
+                       addr = (lp->dvs_pin == DVS_HIGH) ?
+                               LP8725_BUCK1_VOUT1 : LP8725_BUCK1_VOUT2;
+               break;
+       case LP8725_ID_BUCK2:
+               addr =  val & LP8725_DVS2_M ?
+                       LP8725_BUCK2_VOUT1 : LP8725_BUCK2_VOUT2;
+               break;
+       default:
+               return 0;
+       }
+
+       return addr;
+}
+
+static bool lp872x_is_valid_buck_addr(u8 addr)
+{
+       switch (addr) {
+       case LP8720_BUCK_VOUT1:
+       case LP8720_BUCK_VOUT2:
+       case LP8725_BUCK1_VOUT1:
+       case LP8725_BUCK1_VOUT2:
+       case LP8725_BUCK2_VOUT1:
+       case LP8725_BUCK2_VOUT2:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static int lp872x_buck_set_voltage_sel(struct regulator_dev *rdev,
+                                       unsigned selector)
+{
+       struct lp872x *lp = rdev_get_drvdata(rdev);
+       enum lp872x_regulator_id buck = rdev_get_id(rdev);
+       u8 addr, mask = LP872X_VOUT_M;
+       struct lp872x_dvs *dvs = lp->pdata->dvs;
+
+       if (dvs && gpio_is_valid(dvs->gpio))
+               lp872x_set_dvs(lp, dvs->gpio);
+
+       addr = lp872x_select_buck_vout_addr(lp, buck);
+       if (!lp872x_is_valid_buck_addr(addr))
+               return -EINVAL;
+
+       return lp872x_update_bits(lp, addr, mask, selector);
+}
+
+static int lp872x_buck_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct lp872x *lp = rdev_get_drvdata(rdev);
+       enum lp872x_regulator_id buck = rdev_get_id(rdev);
+       u8 addr, val;
+       int ret;
+
+       addr = lp872x_select_buck_vout_addr(lp, buck);
+       if (!lp872x_is_valid_buck_addr(addr))
+               return -EINVAL;
+
+       ret = lp872x_read_byte(lp, addr, &val);
+       if (ret)
+               return ret;
+
+       return val & LP872X_VOUT_M;
+}
+
+static int lp8725_buck_set_current_limit(struct regulator_dev *rdev,
+                                       int min_uA, int max_uA)
+{
+       struct lp872x *lp = rdev_get_drvdata(rdev);
+       enum lp872x_regulator_id buck = rdev_get_id(rdev);
+       int i, max = ARRAY_SIZE(lp8725_buck_uA);
+       u8 addr, val;
+
+       switch (buck) {
+       case LP8725_ID_BUCK1:
+               addr = LP8725_BUCK1_VOUT2;
+               break;
+       case LP8725_ID_BUCK2:
+               addr = LP8725_BUCK2_VOUT2;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       for (i = 0 ; i < max ; i++)
+               if (lp8725_buck_uA[i] >= min_uA &&
+                       lp8725_buck_uA[i] <= max_uA)
+                       break;
+
+       if (i == max)
+               return -EINVAL;
+
+       val = i << LP8725_BUCK_CL_S;
+
+       return lp872x_update_bits(lp, addr, LP8725_BUCK_CL_M, val);
+}
+
+static int lp8725_buck_get_current_limit(struct regulator_dev *rdev)
+{
+       struct lp872x *lp = rdev_get_drvdata(rdev);
+       enum lp872x_regulator_id buck = rdev_get_id(rdev);
+       u8 addr, val;
+       int ret;
+
+       switch (buck) {
+       case LP8725_ID_BUCK1:
+               addr = LP8725_BUCK1_VOUT2;
+               break;
+       case LP8725_ID_BUCK2:
+               addr = LP8725_BUCK2_VOUT2;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = lp872x_read_byte(lp, addr, &val);
+       if (ret)
+               return ret;
+
+       val = (val & LP8725_BUCK_CL_M) >> LP8725_BUCK_CL_S;
+
+       return (val < ARRAY_SIZE(lp8725_buck_uA)) ?
+                       lp8725_buck_uA[val] : -EINVAL;
+}
+
+static int lp872x_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+       struct lp872x *lp = rdev_get_drvdata(rdev);
+       enum lp872x_regulator_id buck = rdev_get_id(rdev);
+       u8 addr, mask, shift, val;
+
+       switch (buck) {
+       case LP8720_ID_BUCK:
+               addr = LP8720_BUCK_VOUT2;
+               mask = LP8720_BUCK_FPWM_M;
+               shift = LP8720_BUCK_FPWM_S;
+               break;
+       case LP8725_ID_BUCK1:
+               addr = LP8725_BUCK_CTRL;
+               mask = LP8725_BUCK1_FPWM_M;
+               shift = LP8725_BUCK1_FPWM_S;
+               break;
+       case LP8725_ID_BUCK2:
+               addr = LP8725_BUCK_CTRL;
+               mask = LP8725_BUCK2_FPWM_M;
+               shift = LP8725_BUCK2_FPWM_S;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (mode == REGULATOR_MODE_FAST)
+               val = LP872X_FORCE_PWM << shift;
+       else if (mode == REGULATOR_MODE_NORMAL)
+               val = LP872X_AUTO_PWM << shift;
+       else
+               return -EINVAL;
+
+       return lp872x_update_bits(lp, addr, mask, val);
+}
+
+static unsigned int lp872x_buck_get_mode(struct regulator_dev *rdev)
+{
+       struct lp872x *lp = rdev_get_drvdata(rdev);
+       enum lp872x_regulator_id buck = rdev_get_id(rdev);
+       u8 addr, mask, val;
+       int ret;
+
+       switch (buck) {
+       case LP8720_ID_BUCK:
+               addr = LP8720_BUCK_VOUT2;
+               mask = LP8720_BUCK_FPWM_M;
+               break;
+       case LP8725_ID_BUCK1:
+               addr = LP8725_BUCK_CTRL;
+               mask = LP8725_BUCK1_FPWM_M;
+               break;
+       case LP8725_ID_BUCK2:
+               addr = LP8725_BUCK_CTRL;
+               mask = LP8725_BUCK2_FPWM_M;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = lp872x_read_byte(lp, addr, &val);
+       if (ret)
+               return ret;
+
+       return val & mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
+}
+
+static struct regulator_ops lp872x_ldo_ops = {
+       .list_voltage = regulator_list_voltage_table,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable_time = lp872x_regulator_enable_time,
+};
+
+static struct regulator_ops lp8720_buck_ops = {
+       .list_voltage = regulator_list_voltage_table,
+       .set_voltage_sel = lp872x_buck_set_voltage_sel,
+       .get_voltage_sel = lp872x_buck_get_voltage_sel,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable_time = lp872x_regulator_enable_time,
+       .set_mode = lp872x_buck_set_mode,
+       .get_mode = lp872x_buck_get_mode,
+};
+
+static struct regulator_ops lp8725_buck_ops = {
+       .list_voltage = regulator_list_voltage_table,
+       .set_voltage_sel = lp872x_buck_set_voltage_sel,
+       .get_voltage_sel = lp872x_buck_get_voltage_sel,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable_time = lp872x_regulator_enable_time,
+       .set_mode = lp872x_buck_set_mode,
+       .get_mode = lp872x_buck_get_mode,
+       .set_current_limit = lp8725_buck_set_current_limit,
+       .get_current_limit = lp8725_buck_get_current_limit,
+};
+
+static struct regulator_desc lp8720_regulator_desc[] = {
+       {
+               .name = "ldo1",
+               .id = LP8720_ID_LDO1,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO1_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8720_ENABLE,
+               .enable_mask = LP872X_EN_LDO1_M,
+       },
+       {
+               .name = "ldo2",
+               .id = LP8720_ID_LDO2,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO2_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8720_ENABLE,
+               .enable_mask = LP872X_EN_LDO2_M,
+       },
+       {
+               .name = "ldo3",
+               .id = LP8720_ID_LDO3,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO3_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8720_ENABLE,
+               .enable_mask = LP872X_EN_LDO3_M,
+       },
+       {
+               .name = "ldo4",
+               .id = LP8720_ID_LDO4,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp8720_ldo4_vtbl),
+               .volt_table = lp8720_ldo4_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO4_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8720_ENABLE,
+               .enable_mask = LP872X_EN_LDO4_M,
+       },
+       {
+               .name = "ldo5",
+               .id = LP8720_ID_LDO5,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO5_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8720_ENABLE,
+               .enable_mask = LP872X_EN_LDO5_M,
+       },
+       {
+               .name = "buck",
+               .id = LP8720_ID_BUCK,
+               .ops = &lp8720_buck_ops,
+               .n_voltages = ARRAY_SIZE(lp8720_buck_vtbl),
+               .volt_table = lp8720_buck_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8720_ENABLE,
+               .enable_mask = LP8720_EN_BUCK_M,
+       },
+};
+
+static struct regulator_desc lp8725_regulator_desc[] = {
+       {
+               .name = "ldo1",
+               .id = LP8725_ID_LDO1,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO1_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8725_LDO_CTRL,
+               .enable_mask = LP872X_EN_LDO1_M,
+       },
+       {
+               .name = "ldo2",
+               .id = LP8725_ID_LDO2,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO2_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8725_LDO_CTRL,
+               .enable_mask = LP872X_EN_LDO2_M,
+       },
+       {
+               .name = "ldo3",
+               .id = LP8725_ID_LDO3,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO3_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8725_LDO_CTRL,
+               .enable_mask = LP872X_EN_LDO3_M,
+       },
+       {
+               .name = "ldo4",
+               .id = LP8725_ID_LDO4,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO4_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8725_LDO_CTRL,
+               .enable_mask = LP872X_EN_LDO4_M,
+       },
+       {
+               .name = "ldo5",
+               .id = LP8725_ID_LDO5,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp872x_ldo_vtbl),
+               .volt_table = lp872x_ldo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP872X_LDO5_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8725_LDO_CTRL,
+               .enable_mask = LP872X_EN_LDO5_M,
+       },
+       {
+               .name = "lilo1",
+               .id = LP8725_ID_LILO1,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl),
+               .volt_table = lp8725_lilo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8725_LILO1_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8725_LDO_CTRL,
+               .enable_mask = LP8725_EN_LILO1_M,
+       },
+       {
+               .name = "lilo2",
+               .id = LP8725_ID_LILO2,
+               .ops = &lp872x_ldo_ops,
+               .n_voltages = ARRAY_SIZE(lp8725_lilo_vtbl),
+               .volt_table = lp8725_lilo_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8725_LILO2_VOUT,
+               .vsel_mask = LP872X_VOUT_M,
+               .enable_reg = LP8725_LDO_CTRL,
+               .enable_mask = LP8725_EN_LILO2_M,
+       },
+       {
+               .name = "buck1",
+               .id = LP8725_ID_BUCK1,
+               .ops = &lp8725_buck_ops,
+               .n_voltages = ARRAY_SIZE(lp8725_buck_vtbl),
+               .volt_table = lp8725_buck_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP872X_GENERAL_CFG,
+               .enable_mask = LP8725_BUCK1_EN_M,
+       },
+       {
+               .name = "buck2",
+               .id = LP8725_ID_BUCK2,
+               .ops = &lp8725_buck_ops,
+               .n_voltages = ARRAY_SIZE(lp8725_buck_vtbl),
+               .volt_table = lp8725_buck_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP872X_GENERAL_CFG,
+               .enable_mask = LP8725_BUCK2_EN_M,
+       },
+};
+
+static int lp872x_check_dvs_validity(struct lp872x *lp)
+{
+       struct lp872x_dvs *dvs = lp->pdata->dvs;
+       u8 val = 0;
+       int ret;
+
+       ret = lp872x_read_byte(lp, LP872X_GENERAL_CFG, &val);
+       if (ret)
+               return ret;
+
+       ret = 0;
+       if (lp->chipid == LP8720) {
+               if (val & LP8720_EXT_DVS_M)
+                       ret = dvs ? 0 : -EINVAL;
+       } else {
+               if ((val & LP8725_DVS1_M) == EXTERN_DVS_USED)
+                       ret = dvs ? 0 : -EINVAL;
+       }
+
+       return ret;
+}
+
+static int lp872x_init_dvs(struct lp872x *lp)
+{
+       int ret, gpio;
+       struct lp872x_dvs *dvs = lp->pdata->dvs;
+       enum lp872x_dvs_state pinstate;
+
+       ret = lp872x_check_dvs_validity(lp);
+       if (ret) {
+               dev_warn(lp->dev, "invalid dvs data: %d\n", ret);
+               return ret;
+       }
+
+       gpio = dvs->gpio;
+       if (!gpio_is_valid(gpio)) {
+               dev_err(lp->dev, "invalid gpio: %d\n", gpio);
+               return -EINVAL;
+       }
+
+       pinstate = dvs->init_state;
+       ret = devm_gpio_request_one(lp->dev, gpio, pinstate, "LP872X DVS");
+       if (ret) {
+               dev_err(lp->dev, "gpio request err: %d\n", ret);
+               return ret;
+       }
+
+       lp->dvs_pin = pinstate;
+       lp->dvs_gpio = gpio;
+
+       return 0;
+}
+
+static int lp872x_config(struct lp872x *lp)
+{
+       struct lp872x_platform_data *pdata = lp->pdata;
+       int ret;
+
+       if (!pdata->update_config)
+               return 0;
+
+       ret = lp872x_write_byte(lp, LP872X_GENERAL_CFG, pdata->general_config);
+       if (ret)
+               return ret;
+
+       return lp872x_init_dvs(lp);
+}
+
+static struct regulator_init_data
+*lp872x_find_regulator_init_data(int id, struct lp872x *lp)
+{
+       int i;
+
+       for (i = 0; i < lp->num_regulators; i++) {
+               if (lp->pdata->regulator_data[i].id == id)
+                       return lp->pdata->regulator_data[i].init_data;
+       }
+
+       return NULL;
+}
+
+static int lp872x_regulator_register(struct lp872x *lp)
+{
+       struct regulator_desc *desc;
+       struct regulator_config cfg = { };
+       struct regulator_dev *rdev;
+       int i, ret;
+
+       for (i = 0 ; i < lp->num_regulators ; i++) {
+               desc = (lp->chipid == LP8720) ? &lp8720_regulator_desc[i] :
+                                               &lp8725_regulator_desc[i];
+
+               cfg.dev = lp->dev;
+               cfg.init_data = lp872x_find_regulator_init_data(desc->id, lp);
+               cfg.driver_data = lp;
+               cfg.regmap = lp->regmap;
+
+               rdev = regulator_register(desc, &cfg);
+               if (IS_ERR(rdev)) {
+                       dev_err(lp->dev, "regulator register err");
+                       ret =  PTR_ERR(rdev);
+                       goto err;
+               }
+
+               *(lp->regulators + i) = rdev;
+       }
+
+       return 0;
+err:
+       while (--i >= 0) {
+               rdev = *(lp->regulators + i);
+               regulator_unregister(rdev);
+       }
+       return ret;
+}
+
+static void lp872x_regulator_unregister(struct lp872x *lp)
+{
+       struct regulator_dev *rdev;
+       int i;
+
+       for (i = 0 ; i < lp->num_regulators ; i++) {
+               rdev = *(lp->regulators + i);
+               regulator_unregister(rdev);
+       }
+}
+
+static const struct regmap_config lp872x_regmap_config = {
+       .reg_bits = 8,
+       .val_bits = 8,
+       .max_register = MAX_REGISTERS,
+};
+
+static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
+{
+       struct lp872x *lp;
+       struct lp872x_platform_data *pdata = cl->dev.platform_data;
+       int ret, size, num_regulators;
+       const int lp872x_num_regulators[] = {
+               [LP8720] = LP8720_NUM_REGULATORS,
+               [LP8725] = LP8725_NUM_REGULATORS,
+       };
+
+       if (!pdata) {
+               dev_err(&cl->dev, "no platform data\n");
+               return -EINVAL;
+       }
+
+       lp = devm_kzalloc(&cl->dev, sizeof(struct lp872x), GFP_KERNEL);
+       if (!lp)
+               goto err_mem;
+
+       num_regulators = lp872x_num_regulators[id->driver_data];
+       size = sizeof(struct regulator_dev *) * num_regulators;
+
+       lp->regulators = devm_kzalloc(&cl->dev, size, GFP_KERNEL);
+       if (!lp->regulators)
+               goto err_mem;
+
+       lp->regmap = devm_regmap_init_i2c(cl, &lp872x_regmap_config);
+       if (IS_ERR(lp->regmap)) {
+               ret = PTR_ERR(lp->regmap);
+               dev_err(&cl->dev, "regmap init i2c err: %d\n", ret);
+               goto err_dev;
+       }
+
+       lp->dev = &cl->dev;
+       lp->pdata = pdata;
+       lp->chipid = id->driver_data;
+       lp->num_regulators = num_regulators;
+       i2c_set_clientdata(cl, lp);
+
+       ret = lp872x_config(lp);
+       if (ret)
+               goto err_dev;
+
+       return lp872x_regulator_register(lp);
+
+err_mem:
+       return -ENOMEM;
+err_dev:
+       return ret;
+}
+
+static int __devexit lp872x_remove(struct i2c_client *cl)
+{
+       struct lp872x *lp = i2c_get_clientdata(cl);
+
+       lp872x_regulator_unregister(lp);
+       return 0;
+}
+
+static const struct i2c_device_id lp872x_ids[] = {
+       {"lp8720", LP8720},
+       {"lp8725", LP8725},
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, lp872x_ids);
+
+static struct i2c_driver lp872x_driver = {
+       .driver = {
+               .name = "lp872x",
+               .owner = THIS_MODULE,
+       },
+       .probe = lp872x_probe,
+       .remove = __devexit_p(lp872x_remove),
+       .id_table = lp872x_ids,
+};
+
+module_i2c_driver(lp872x_driver);
+
+MODULE_DESCRIPTION("TI/National Semiconductor LP872x PMU Regulator Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
new file mode 100644 (file)
index 0000000..6356e82
--- /dev/null
@@ -0,0 +1,629 @@
+/*
+ * TI LP8788 MFD - buck regulator driver
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/lp8788.h>
+#include <linux/gpio.h>
+
+/* register address */
+#define LP8788_EN_BUCK                 0x0C
+#define LP8788_BUCK_DVS_SEL            0x1D
+#define LP8788_BUCK1_VOUT0             0x1E
+#define LP8788_BUCK1_VOUT1             0x1F
+#define LP8788_BUCK1_VOUT2             0x20
+#define LP8788_BUCK1_VOUT3             0x21
+#define LP8788_BUCK2_VOUT0             0x22
+#define LP8788_BUCK2_VOUT1             0x23
+#define LP8788_BUCK2_VOUT2             0x24
+#define LP8788_BUCK2_VOUT3             0x25
+#define LP8788_BUCK3_VOUT              0x26
+#define LP8788_BUCK4_VOUT              0x27
+#define LP8788_BUCK1_TIMESTEP          0x28
+#define LP8788_BUCK_PWM                        0x2D
+
+/* mask/shift bits */
+#define LP8788_EN_BUCK1_M              BIT(0)  /* Addr 0Ch */
+#define LP8788_EN_BUCK2_M              BIT(1)
+#define LP8788_EN_BUCK3_M              BIT(2)
+#define LP8788_EN_BUCK4_M              BIT(3)
+#define LP8788_BUCK1_DVS_SEL_M         0x04    /* Addr 1Dh */
+#define LP8788_BUCK1_DVS_M             0x03
+#define LP8788_BUCK1_DVS_S             0
+#define LP8788_BUCK2_DVS_SEL_M         0x40
+#define LP8788_BUCK2_DVS_M             0x30
+#define LP8788_BUCK2_DVS_S             4
+#define LP8788_BUCK1_DVS_I2C           BIT(2)
+#define LP8788_BUCK2_DVS_I2C           BIT(6)
+#define LP8788_BUCK1_DVS_PIN           (0 << 2)
+#define LP8788_BUCK2_DVS_PIN           (0 << 6)
+#define LP8788_VOUT_M                  0x1F    /* Addr 1Eh ~ 27h */
+#define LP8788_STARTUP_TIME_M          0xF8    /* Addr 28h ~ 2Bh */
+#define LP8788_STARTUP_TIME_S          3
+#define LP8788_FPWM_BUCK1_M            BIT(0)  /* Addr 2Dh */
+#define LP8788_FPWM_BUCK1_S            0
+#define LP8788_FPWM_BUCK2_M            BIT(1)
+#define LP8788_FPWM_BUCK2_S            1
+#define LP8788_FPWM_BUCK3_M            BIT(2)
+#define LP8788_FPWM_BUCK3_S            2
+#define LP8788_FPWM_BUCK4_M            BIT(3)
+#define LP8788_FPWM_BUCK4_S            3
+
+#define INVALID_ADDR                   0xFF
+#define LP8788_FORCE_PWM               1
+#define LP8788_AUTO_PWM                        0
+#define PIN_LOW                                0
+#define PIN_HIGH                       1
+#define ENABLE_TIME_USEC               32
+
+enum lp8788_dvs_state {
+       DVS_LOW  = GPIOF_OUT_INIT_LOW,
+       DVS_HIGH = GPIOF_OUT_INIT_HIGH,
+};
+
+enum lp8788_dvs_mode {
+       REGISTER,
+       EXTPIN,
+};
+
+enum lp8788_buck_id {
+       BUCK1,
+       BUCK2,
+       BUCK3,
+       BUCK4,
+};
+
+struct lp8788_pwm_map {
+       u8 mask;
+       u8 shift;
+};
+
+struct lp8788_buck {
+       struct lp8788 *lp;
+       struct regulator_dev *regulator;
+       struct lp8788_pwm_map *pmap;
+       void *dvs;
+};
+
+/* BUCK 1 ~ 4 voltage table */
+static const int lp8788_buck_vtbl[] = {
+        500000,  800000,  850000,  900000,  950000, 1000000, 1050000, 1100000,
+       1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000, 1500000,
+       1550000, 1600000, 1650000, 1700000, 1750000, 1800000, 1850000, 1900000,
+       1950000, 2000000,
+};
+
+/* buck pwm mode selection : used for set/get_mode in regulator ops
+ * @forced pwm : fast mode
+ * @auto pwm   : normal mode
+ */
+static struct lp8788_pwm_map buck_pmap[] = {
+       [BUCK1] = {
+               .mask = LP8788_FPWM_BUCK1_M,
+               .shift = LP8788_FPWM_BUCK1_S,
+       },
+       [BUCK2] = {
+               .mask = LP8788_FPWM_BUCK2_M,
+               .shift = LP8788_FPWM_BUCK2_S,
+       },
+       [BUCK3] = {
+               .mask = LP8788_FPWM_BUCK3_M,
+               .shift = LP8788_FPWM_BUCK3_S,
+       },
+       [BUCK4] = {
+               .mask = LP8788_FPWM_BUCK4_M,
+               .shift = LP8788_FPWM_BUCK4_S,
+       },
+};
+
+static const u8 buck1_vout_addr[] = {
+       LP8788_BUCK1_VOUT0, LP8788_BUCK1_VOUT1,
+       LP8788_BUCK1_VOUT2, LP8788_BUCK1_VOUT3,
+};
+
+static const u8 buck2_vout_addr[] = {
+       LP8788_BUCK2_VOUT0, LP8788_BUCK2_VOUT1,
+       LP8788_BUCK2_VOUT2, LP8788_BUCK2_VOUT3,
+};
+
+static void lp8788_buck1_set_dvs(struct lp8788_buck *buck)
+{
+       struct lp8788_buck1_dvs *dvs = (struct lp8788_buck1_dvs *)buck->dvs;
+       enum lp8788_dvs_state pinstate;
+
+       if (!dvs)
+               return;
+
+       pinstate = dvs->vsel == DVS_SEL_V0 ? DVS_LOW : DVS_HIGH;
+       if (gpio_is_valid(dvs->gpio))
+               gpio_set_value(dvs->gpio, pinstate);
+}
+
+static void lp8788_buck2_set_dvs(struct lp8788_buck *buck)
+{
+       struct lp8788_buck2_dvs *dvs = (struct lp8788_buck2_dvs *)buck->dvs;
+       enum lp8788_dvs_state pin1, pin2;
+
+       if (!dvs)
+               return;
+
+       switch (dvs->vsel) {
+       case DVS_SEL_V0:
+               pin1 = DVS_LOW;
+               pin2 = DVS_LOW;
+               break;
+       case DVS_SEL_V1:
+               pin1 = DVS_HIGH;
+               pin2 = DVS_LOW;
+               break;
+       case DVS_SEL_V2:
+               pin1 = DVS_LOW;
+               pin2 = DVS_HIGH;
+               break;
+       case DVS_SEL_V3:
+               pin1 = DVS_HIGH;
+               pin2 = DVS_HIGH;
+               break;
+       default:
+               return;
+       }
+
+       if (gpio_is_valid(dvs->gpio[0]))
+               gpio_set_value(dvs->gpio[0], pin1);
+
+       if (gpio_is_valid(dvs->gpio[1]))
+               gpio_set_value(dvs->gpio[1], pin2);
+}
+
+static void lp8788_set_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id)
+{
+       switch (id) {
+       case BUCK1:
+               lp8788_buck1_set_dvs(buck);
+               break;
+       case BUCK2:
+               lp8788_buck2_set_dvs(buck);
+               break;
+       default:
+               break;
+       }
+}
+
+static enum lp8788_dvs_mode
+lp8788_get_buck_dvs_ctrl_mode(struct lp8788_buck *buck, enum lp8788_buck_id id)
+{
+       u8 val, mask;
+
+       switch (id) {
+       case BUCK1:
+               mask = LP8788_BUCK1_DVS_SEL_M;
+               break;
+       case BUCK2:
+               mask = LP8788_BUCK2_DVS_SEL_M;
+               break;
+       default:
+               return REGISTER;
+       }
+
+       lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
+
+       return val & mask ? REGISTER : EXTPIN;
+}
+
+static bool lp8788_is_valid_buck_addr(u8 addr)
+{
+       switch (addr) {
+       case LP8788_BUCK1_VOUT0:
+       case LP8788_BUCK1_VOUT1:
+       case LP8788_BUCK1_VOUT2:
+       case LP8788_BUCK1_VOUT3:
+       case LP8788_BUCK2_VOUT0:
+       case LP8788_BUCK2_VOUT1:
+       case LP8788_BUCK2_VOUT2:
+       case LP8788_BUCK2_VOUT3:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static u8 lp8788_select_buck_vout_addr(struct lp8788_buck *buck,
+                                       enum lp8788_buck_id id)
+{
+       enum lp8788_dvs_mode mode = lp8788_get_buck_dvs_ctrl_mode(buck, id);
+       struct lp8788_buck1_dvs *b1_dvs;
+       struct lp8788_buck2_dvs *b2_dvs;
+       u8 val, idx, addr;
+       int pin1, pin2;
+
+       switch (id) {
+       case BUCK1:
+               if (mode == EXTPIN) {
+                       b1_dvs = (struct lp8788_buck1_dvs *)buck->dvs;
+                       if (!b1_dvs)
+                               goto err;
+
+                       idx = gpio_get_value(b1_dvs->gpio) ? 1 : 0;
+               } else {
+                       lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
+                       idx = (val & LP8788_BUCK1_DVS_M) >> LP8788_BUCK1_DVS_S;
+               }
+               addr = buck1_vout_addr[idx];
+               break;
+       case BUCK2:
+               if (mode == EXTPIN) {
+                       b2_dvs = (struct lp8788_buck2_dvs *)buck->dvs;
+                       if (!b2_dvs)
+                               goto err;
+
+                       pin1 = gpio_get_value(b2_dvs->gpio[0]);
+                       pin2 = gpio_get_value(b2_dvs->gpio[1]);
+
+                       if (pin1 == PIN_LOW && pin2 == PIN_LOW)
+                               idx = 0;
+                       else if (pin1 == PIN_LOW && pin2 == PIN_HIGH)
+                               idx = 2;
+                       else if (pin1 == PIN_HIGH && pin2 == PIN_LOW)
+                               idx = 1;
+                       else
+                               idx = 3;
+               } else {
+                       lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val);
+                       idx = (val & LP8788_BUCK2_DVS_M) >> LP8788_BUCK2_DVS_S;
+               }
+               addr = buck2_vout_addr[idx];
+               break;
+       default:
+               goto err;
+       }
+
+       return addr;
+err:
+       return INVALID_ADDR;
+}
+
+static int lp8788_buck12_set_voltage_sel(struct regulator_dev *rdev,
+                                       unsigned selector)
+{
+       struct lp8788_buck *buck = rdev_get_drvdata(rdev);
+       enum lp8788_buck_id id = rdev_get_id(rdev);
+       u8 addr;
+
+       if (buck->dvs)
+               lp8788_set_dvs(buck, id);
+
+       addr = lp8788_select_buck_vout_addr(buck, id);
+       if (!lp8788_is_valid_buck_addr(addr))
+               return -EINVAL;
+
+       return lp8788_update_bits(buck->lp, addr, LP8788_VOUT_M, selector);
+}
+
+static int lp8788_buck12_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct lp8788_buck *buck = rdev_get_drvdata(rdev);
+       enum lp8788_buck_id id = rdev_get_id(rdev);
+       int ret;
+       u8 val, addr;
+
+       addr = lp8788_select_buck_vout_addr(buck, id);
+       if (!lp8788_is_valid_buck_addr(addr))
+               return -EINVAL;
+
+       ret = lp8788_read_byte(buck->lp, addr, &val);
+       if (ret)
+               return ret;
+
+       return val & LP8788_VOUT_M;
+}
+
+static int lp8788_buck_enable_time(struct regulator_dev *rdev)
+{
+       struct lp8788_buck *buck = rdev_get_drvdata(rdev);
+       enum lp8788_buck_id id = rdev_get_id(rdev);
+       u8 val, addr = LP8788_BUCK1_TIMESTEP + id;
+
+       if (lp8788_read_byte(buck->lp, addr, &val))
+               return -EINVAL;
+
+       val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S;
+
+       return ENABLE_TIME_USEC * val;
+}
+
+static int lp8788_buck_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+       struct lp8788_buck *buck = rdev_get_drvdata(rdev);
+       struct lp8788_pwm_map *pmap = buck->pmap;
+       u8 val;
+
+       if (!pmap)
+               return -EINVAL;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               val = LP8788_FORCE_PWM << pmap->shift;
+               break;
+       case REGULATOR_MODE_NORMAL:
+               val = LP8788_AUTO_PWM << pmap->shift;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return lp8788_update_bits(buck->lp, LP8788_BUCK_PWM, pmap->mask, val);
+}
+
+static unsigned int lp8788_buck_get_mode(struct regulator_dev *rdev)
+{
+       struct lp8788_buck *buck = rdev_get_drvdata(rdev);
+       struct lp8788_pwm_map *pmap = buck->pmap;
+       u8 val;
+       int ret;
+
+       if (!pmap)
+               return -EINVAL;
+
+       ret = lp8788_read_byte(buck->lp, LP8788_BUCK_PWM, &val);
+       if (ret)
+               return ret;
+
+       return val & pmap->mask ? REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
+}
+
+static struct regulator_ops lp8788_buck12_ops = {
+       .list_voltage = regulator_list_voltage_table,
+       .set_voltage_sel = lp8788_buck12_set_voltage_sel,
+       .get_voltage_sel = lp8788_buck12_get_voltage_sel,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable_time = lp8788_buck_enable_time,
+       .set_mode = lp8788_buck_set_mode,
+       .get_mode = lp8788_buck_get_mode,
+};
+
+static struct regulator_ops lp8788_buck34_ops = {
+       .list_voltage = regulator_list_voltage_table,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable_time = lp8788_buck_enable_time,
+       .set_mode = lp8788_buck_set_mode,
+       .get_mode = lp8788_buck_get_mode,
+};
+
+static struct regulator_desc lp8788_buck_desc[] = {
+       {
+               .name = "buck1",
+               .id = BUCK1,
+               .ops = &lp8788_buck12_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
+               .volt_table = lp8788_buck_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_BUCK,
+               .enable_mask = LP8788_EN_BUCK1_M,
+       },
+       {
+               .name = "buck2",
+               .id = BUCK2,
+               .ops = &lp8788_buck12_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
+               .volt_table = lp8788_buck_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_BUCK,
+               .enable_mask = LP8788_EN_BUCK2_M,
+       },
+       {
+               .name = "buck3",
+               .id = BUCK3,
+               .ops = &lp8788_buck34_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
+               .volt_table = lp8788_buck_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_BUCK3_VOUT,
+               .vsel_mask = LP8788_VOUT_M,
+               .enable_reg = LP8788_EN_BUCK,
+               .enable_mask = LP8788_EN_BUCK3_M,
+       },
+       {
+               .name = "buck4",
+               .id = BUCK4,
+               .ops = &lp8788_buck34_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_buck_vtbl),
+               .volt_table = lp8788_buck_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_BUCK4_VOUT,
+               .vsel_mask = LP8788_VOUT_M,
+               .enable_reg = LP8788_EN_BUCK,
+               .enable_mask = LP8788_EN_BUCK4_M,
+       },
+};
+
+static int lp8788_set_default_dvs_ctrl_mode(struct lp8788 *lp,
+                                       enum lp8788_buck_id id)
+{
+       u8 mask, val;
+
+       switch (id) {
+       case BUCK1:
+               mask = LP8788_BUCK1_DVS_SEL_M;
+               val  = LP8788_BUCK1_DVS_I2C;
+               break;
+       case BUCK2:
+               mask = LP8788_BUCK2_DVS_SEL_M;
+               val  = LP8788_BUCK2_DVS_I2C;
+               break;
+       default:
+               return 0;
+       }
+
+       return lp8788_update_bits(lp, LP8788_BUCK_DVS_SEL, mask, val);
+}
+
+static int _gpio_request(struct lp8788_buck *buck, int gpio, char *name)
+{
+       struct device *dev = buck->lp->dev;
+
+       if (!gpio_is_valid(gpio)) {
+               dev_err(dev, "invalid gpio: %d\n", gpio);
+               return -EINVAL;
+       }
+
+       return devm_gpio_request_one(dev, gpio, DVS_LOW, name);
+}
+
+static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
+                               enum lp8788_buck_id id)
+{
+       struct lp8788_platform_data *pdata = buck->lp->pdata;
+       char *b1_name = "LP8788_B1_DVS";
+       char *b2_name[] = { "LP8788_B2_DVS1", "LP8788_B2_DVS2" };
+       int i, gpio, ret;
+
+       switch (id) {
+       case BUCK1:
+               gpio = pdata->buck1_dvs->gpio;
+               ret = _gpio_request(buck, gpio, b1_name);
+               if (ret)
+                       return ret;
+
+               buck->dvs = pdata->buck1_dvs;
+               break;
+       case BUCK2:
+               for (i = 0 ; i < LP8788_NUM_BUCK2_DVS ; i++) {
+                       gpio = pdata->buck2_dvs->gpio[i];
+                       ret = _gpio_request(buck, gpio, b2_name[i]);
+                       if (ret)
+                               return ret;
+               }
+               buck->dvs = pdata->buck2_dvs;
+               break;
+       default:
+               break;
+       }
+
+       return 0;
+}
+
+static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id)
+{
+       struct lp8788_platform_data *pdata = buck->lp->pdata;
+       u8 mask[] = { LP8788_BUCK1_DVS_SEL_M, LP8788_BUCK2_DVS_SEL_M };
+       u8 val[]  = { LP8788_BUCK1_DVS_PIN, LP8788_BUCK2_DVS_PIN };
+
+       /* no dvs for buck3, 4 */
+       if (id == BUCK3 || id == BUCK4)
+               return 0;
+
+       /* no dvs platform data, then dvs will be selected by I2C registers */
+       if (!pdata)
+               goto set_default_dvs_mode;
+
+       if ((id == BUCK1 && !pdata->buck1_dvs) ||
+               (id == BUCK2 && !pdata->buck2_dvs))
+               goto set_default_dvs_mode;
+
+       if (lp8788_dvs_gpio_request(buck, id))
+               goto set_default_dvs_mode;
+
+       return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id],
+                               val[id]);
+
+set_default_dvs_mode:
+       return lp8788_set_default_dvs_ctrl_mode(buck->lp, id);
+}
+
+static __devinit int lp8788_buck_probe(struct platform_device *pdev)
+{
+       struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
+       int id = pdev->id;
+       struct lp8788_buck *buck;
+       struct regulator_config cfg = { };
+       struct regulator_dev *rdev;
+       int ret;
+
+       buck = devm_kzalloc(lp->dev, sizeof(struct lp8788_buck), GFP_KERNEL);
+       if (!buck)
+               return -ENOMEM;
+
+       buck->lp = lp;
+       buck->pmap = &buck_pmap[id];
+
+       ret = lp8788_init_dvs(buck, id);
+       if (ret)
+               return ret;
+
+       cfg.dev = lp->dev;
+       cfg.init_data = lp->pdata ? lp->pdata->buck_data[id] : NULL;
+       cfg.driver_data = buck;
+       cfg.regmap = lp->regmap;
+
+       rdev = regulator_register(&lp8788_buck_desc[id], &cfg);
+       if (IS_ERR(rdev)) {
+               ret = PTR_ERR(rdev);
+               dev_err(lp->dev, "BUCK%d regulator register err = %d\n",
+                               id + 1, ret);
+               return ret;
+       }
+
+       buck->regulator = rdev;
+       platform_set_drvdata(pdev, buck);
+
+       return 0;
+}
+
+static int __devexit lp8788_buck_remove(struct platform_device *pdev)
+{
+       struct lp8788_buck *buck = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+       regulator_unregister(buck->regulator);
+
+       return 0;
+}
+
+static struct platform_driver lp8788_buck_driver = {
+       .probe = lp8788_buck_probe,
+       .remove = __devexit_p(lp8788_buck_remove),
+       .driver = {
+               .name = LP8788_DEV_BUCK,
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init lp8788_buck_init(void)
+{
+       return platform_driver_register(&lp8788_buck_driver);
+}
+subsys_initcall(lp8788_buck_init);
+
+static void __exit lp8788_buck_exit(void)
+{
+       platform_driver_unregister(&lp8788_buck_driver);
+}
+module_exit(lp8788_buck_exit);
+
+MODULE_DESCRIPTION("TI LP8788 BUCK Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lp8788-buck");
diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c
new file mode 100644 (file)
index 0000000..d2122e4
--- /dev/null
@@ -0,0 +1,842 @@
+/*
+ * TI LP8788 MFD - ldo regulator driver
+ *
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/gpio.h>
+#include <linux/mfd/lp8788.h>
+
+/* register address */
+#define LP8788_EN_LDO_A                        0x0D    /* DLDO 1 ~ 8 */
+#define LP8788_EN_LDO_B                        0x0E    /* DLDO 9 ~ 12, ALDO 1 ~ 4 */
+#define LP8788_EN_LDO_C                        0x0F    /* ALDO 5 ~ 10 */
+#define LP8788_EN_SEL                  0x10
+#define LP8788_DLDO1_VOUT              0x2E
+#define LP8788_DLDO2_VOUT              0x2F
+#define LP8788_DLDO3_VOUT              0x30
+#define LP8788_DLDO4_VOUT              0x31
+#define LP8788_DLDO5_VOUT              0x32
+#define LP8788_DLDO6_VOUT              0x33
+#define LP8788_DLDO7_VOUT              0x34
+#define LP8788_DLDO8_VOUT              0x35
+#define LP8788_DLDO9_VOUT              0x36
+#define LP8788_DLDO10_VOUT             0x37
+#define LP8788_DLDO11_VOUT             0x38
+#define LP8788_DLDO12_VOUT             0x39
+#define LP8788_ALDO1_VOUT              0x3A
+#define LP8788_ALDO2_VOUT              0x3B
+#define LP8788_ALDO3_VOUT              0x3C
+#define LP8788_ALDO4_VOUT              0x3D
+#define LP8788_ALDO5_VOUT              0x3E
+#define LP8788_ALDO6_VOUT              0x3F
+#define LP8788_ALDO7_VOUT              0x40
+#define LP8788_ALDO8_VOUT              0x41
+#define LP8788_ALDO9_VOUT              0x42
+#define LP8788_ALDO10_VOUT             0x43
+#define LP8788_DLDO1_TIMESTEP          0x44
+
+/* mask/shift bits */
+#define LP8788_EN_DLDO1_M              BIT(0)  /* Addr 0Dh ~ 0Fh */
+#define LP8788_EN_DLDO2_M              BIT(1)
+#define LP8788_EN_DLDO3_M              BIT(2)
+#define LP8788_EN_DLDO4_M              BIT(3)
+#define LP8788_EN_DLDO5_M              BIT(4)
+#define LP8788_EN_DLDO6_M              BIT(5)
+#define LP8788_EN_DLDO7_M              BIT(6)
+#define LP8788_EN_DLDO8_M              BIT(7)
+#define LP8788_EN_DLDO9_M              BIT(0)
+#define LP8788_EN_DLDO10_M             BIT(1)
+#define LP8788_EN_DLDO11_M             BIT(2)
+#define LP8788_EN_DLDO12_M             BIT(3)
+#define LP8788_EN_ALDO1_M              BIT(4)
+#define LP8788_EN_ALDO2_M              BIT(5)
+#define LP8788_EN_ALDO3_M              BIT(6)
+#define LP8788_EN_ALDO4_M              BIT(7)
+#define LP8788_EN_ALDO5_M              BIT(0)
+#define LP8788_EN_ALDO6_M              BIT(1)
+#define LP8788_EN_ALDO7_M              BIT(2)
+#define LP8788_EN_ALDO8_M              BIT(3)
+#define LP8788_EN_ALDO9_M              BIT(4)
+#define LP8788_EN_ALDO10_M             BIT(5)
+#define LP8788_EN_SEL_DLDO911_M                BIT(0)  /* Addr 10h */
+#define LP8788_EN_SEL_DLDO7_M          BIT(1)
+#define LP8788_EN_SEL_ALDO7_M          BIT(2)
+#define LP8788_EN_SEL_ALDO5_M          BIT(3)
+#define LP8788_EN_SEL_ALDO234_M                BIT(4)
+#define LP8788_EN_SEL_ALDO1_M          BIT(5)
+#define LP8788_VOUT_5BIT_M             0x1F    /* Addr 2Eh ~ 43h */
+#define LP8788_VOUT_4BIT_M             0x0F
+#define LP8788_VOUT_3BIT_M             0x07
+#define LP8788_VOUT_1BIT_M             0x01
+#define LP8788_STARTUP_TIME_M          0xF8    /* Addr 44h ~ 59h */
+#define LP8788_STARTUP_TIME_S          3
+
+#define ENABLE_TIME_USEC               32
+#define ENABLE                         GPIOF_OUT_INIT_HIGH
+#define DISABLE                                GPIOF_OUT_INIT_LOW
+
+enum lp8788_enable_mode {
+       REGISTER,
+       EXTPIN,
+};
+
+enum lp8788_ldo_id {
+       DLDO1,
+       DLDO2,
+       DLDO3,
+       DLDO4,
+       DLDO5,
+       DLDO6,
+       DLDO7,
+       DLDO8,
+       DLDO9,
+       DLDO10,
+       DLDO11,
+       DLDO12,
+       ALDO1,
+       ALDO2,
+       ALDO3,
+       ALDO4,
+       ALDO5,
+       ALDO6,
+       ALDO7,
+       ALDO8,
+       ALDO9,
+       ALDO10,
+};
+
+struct lp8788_ldo {
+       struct lp8788 *lp;
+       struct regulator_desc *desc;
+       struct regulator_dev *regulator;
+       struct lp8788_ldo_enable_pin *en_pin;
+};
+
+/* DLDO 1, 2, 3, 9 voltage table */
+const int lp8788_dldo1239_vtbl[] = {
+       1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
+       2600000, 2700000, 2800000, 2900000, 3000000, 2850000, 2850000, 2850000,
+       2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
+       2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
+};
+
+/* DLDO 4 voltage table */
+static const int lp8788_dldo4_vtbl[] = { 1800000, 3000000 };
+
+/* DLDO 5, 7, 8 and ALDO 6 voltage table */
+static const int lp8788_dldo578_aldo6_vtbl[] = {
+       1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
+       2600000, 2700000, 2800000, 2900000, 3000000, 3000000, 3000000, 3000000,
+};
+
+/* DLDO 6 voltage table */
+static const int lp8788_dldo6_vtbl[] = {
+       3000000, 3100000, 3200000, 3300000, 3400000, 3500000, 3600000, 3600000,
+};
+
+/* DLDO 10, 11 voltage table */
+static const int lp8788_dldo1011_vtbl[] = {
+       1100000, 1150000, 1200000, 1250000, 1300000, 1350000, 1400000, 1450000,
+       1500000, 1500000, 1500000, 1500000, 1500000, 1500000, 1500000, 1500000,
+};
+
+/* ALDO 1 voltage table */
+static const int lp8788_aldo1_vtbl[] = { 1800000, 2850000 };
+
+/* ALDO 7 voltage table */
+static const int lp8788_aldo7_vtbl[] = {
+       1200000, 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1800000,
+};
+
+static enum lp8788_ldo_id lp8788_dldo_id[] = {
+       DLDO1,
+       DLDO2,
+       DLDO3,
+       DLDO4,
+       DLDO5,
+       DLDO6,
+       DLDO7,
+       DLDO8,
+       DLDO9,
+       DLDO10,
+       DLDO11,
+       DLDO12,
+};
+
+static enum lp8788_ldo_id lp8788_aldo_id[] = {
+       ALDO1,
+       ALDO2,
+       ALDO3,
+       ALDO4,
+       ALDO5,
+       ALDO6,
+       ALDO7,
+       ALDO8,
+       ALDO9,
+       ALDO10,
+};
+
+/* DLDO 7, 9 and 11, ALDO 1 ~ 5 and 7
+   : can be enabled either by external pin or by i2c register */
+static enum lp8788_enable_mode
+lp8788_get_ldo_enable_mode(struct lp8788_ldo *ldo, enum lp8788_ldo_id id)
+{
+       int ret;
+       u8 val, mask;
+
+       ret = lp8788_read_byte(ldo->lp, LP8788_EN_SEL, &val);
+       if (ret)
+               return ret;
+
+       switch (id) {
+       case DLDO7:
+               mask =  LP8788_EN_SEL_DLDO7_M;
+               break;
+       case DLDO9:
+       case DLDO11:
+               mask =  LP8788_EN_SEL_DLDO911_M;
+               break;
+       case ALDO1:
+               mask =  LP8788_EN_SEL_ALDO1_M;
+               break;
+       case ALDO2 ... ALDO4:
+               mask =  LP8788_EN_SEL_ALDO234_M;
+               break;
+       case ALDO5:
+               mask =  LP8788_EN_SEL_ALDO5_M;
+               break;
+       case ALDO7:
+               mask =  LP8788_EN_SEL_ALDO7_M;
+               break;
+       default:
+               return REGISTER;
+       }
+
+       return val & mask ? EXTPIN : REGISTER;
+}
+
+static int lp8788_ldo_ctrl_by_extern_pin(struct lp8788_ldo *ldo, int pinstate)
+{
+       struct lp8788_ldo_enable_pin *pin = ldo->en_pin;
+
+       if (!pin)
+               return -EINVAL;
+
+       if (gpio_is_valid(pin->gpio))
+               gpio_set_value(pin->gpio, pinstate);
+
+       return 0;
+}
+
+static int lp8788_ldo_is_enabled_by_extern_pin(struct lp8788_ldo *ldo)
+{
+       struct lp8788_ldo_enable_pin *pin = ldo->en_pin;
+
+       if (!pin)
+               return -EINVAL;
+
+       return gpio_get_value(pin->gpio) ? 1 : 0;
+}
+
+static int lp8788_ldo_enable(struct regulator_dev *rdev)
+{
+       struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
+       enum lp8788_ldo_id id = rdev_get_id(rdev);
+       enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id);
+
+       switch (mode) {
+       case EXTPIN:
+               return lp8788_ldo_ctrl_by_extern_pin(ldo, ENABLE);
+       case REGISTER:
+               return regulator_enable_regmap(rdev);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int lp8788_ldo_disable(struct regulator_dev *rdev)
+{
+       struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
+       enum lp8788_ldo_id id = rdev_get_id(rdev);
+       enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id);
+
+       switch (mode) {
+       case EXTPIN:
+               return lp8788_ldo_ctrl_by_extern_pin(ldo, DISABLE);
+       case REGISTER:
+               return regulator_disable_regmap(rdev);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int lp8788_ldo_is_enabled(struct regulator_dev *rdev)
+{
+       struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
+       enum lp8788_ldo_id id = rdev_get_id(rdev);
+       enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id);
+
+       switch (mode) {
+       case EXTPIN:
+               return lp8788_ldo_is_enabled_by_extern_pin(ldo);
+       case REGISTER:
+               return regulator_is_enabled_regmap(rdev);
+       default:
+               return -EINVAL;
+       }
+}
+
+static int lp8788_ldo_enable_time(struct regulator_dev *rdev)
+{
+       struct lp8788_ldo *ldo = rdev_get_drvdata(rdev);
+       enum lp8788_ldo_id id = rdev_get_id(rdev);
+       u8 val, addr = LP8788_DLDO1_TIMESTEP + id;
+
+       if (lp8788_read_byte(ldo->lp, addr, &val))
+               return -EINVAL;
+
+       val = (val & LP8788_STARTUP_TIME_M) >> LP8788_STARTUP_TIME_S;
+
+       return ENABLE_TIME_USEC * val;
+}
+
+static int lp8788_ldo_fixed_get_voltage(struct regulator_dev *rdev)
+{
+       enum lp8788_ldo_id id = rdev_get_id(rdev);
+
+       switch (id) {
+       case ALDO2 ... ALDO5:
+               return 2850000;
+       case DLDO12:
+       case ALDO8 ... ALDO9:
+               return 2500000;
+       case ALDO10:
+               return 1100000;
+       default:
+               return -EINVAL;
+       }
+}
+
+static struct regulator_ops lp8788_ldo_voltage_table_ops = {
+       .list_voltage = regulator_list_voltage_table,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .enable = lp8788_ldo_enable,
+       .disable = lp8788_ldo_disable,
+       .is_enabled = lp8788_ldo_is_enabled,
+       .enable_time = lp8788_ldo_enable_time,
+};
+
+static struct regulator_ops lp8788_ldo_voltage_fixed_ops = {
+       .get_voltage = lp8788_ldo_fixed_get_voltage,
+       .enable = lp8788_ldo_enable,
+       .disable = lp8788_ldo_disable,
+       .is_enabled = lp8788_ldo_is_enabled,
+       .enable_time = lp8788_ldo_enable_time,
+};
+
+static struct regulator_desc lp8788_dldo_desc[] = {
+       {
+               .name = "dldo1",
+               .id = DLDO1,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
+               .volt_table = lp8788_dldo1239_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO1_VOUT,
+               .vsel_mask = LP8788_VOUT_5BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO1_M,
+       },
+       {
+               .name = "dldo2",
+               .id = DLDO2,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
+               .volt_table = lp8788_dldo1239_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO2_VOUT,
+               .vsel_mask = LP8788_VOUT_5BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO2_M,
+       },
+       {
+               .name = "dldo3",
+               .id = DLDO3,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
+               .volt_table = lp8788_dldo1239_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO3_VOUT,
+               .vsel_mask = LP8788_VOUT_5BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO3_M,
+       },
+       {
+               .name = "dldo4",
+               .id = DLDO4,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo4_vtbl),
+               .volt_table = lp8788_dldo4_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO4_VOUT,
+               .vsel_mask = LP8788_VOUT_1BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO4_M,
+       },
+       {
+               .name = "dldo5",
+               .id = DLDO5,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
+               .volt_table = lp8788_dldo578_aldo6_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO5_VOUT,
+               .vsel_mask = LP8788_VOUT_4BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO5_M,
+       },
+       {
+               .name = "dldo6",
+               .id = DLDO6,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo6_vtbl),
+               .volt_table = lp8788_dldo6_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO6_VOUT,
+               .vsel_mask = LP8788_VOUT_3BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO6_M,
+       },
+       {
+               .name = "dldo7",
+               .id = DLDO7,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
+               .volt_table = lp8788_dldo578_aldo6_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO7_VOUT,
+               .vsel_mask = LP8788_VOUT_4BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO7_M,
+       },
+       {
+               .name = "dldo8",
+               .id = DLDO8,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
+               .volt_table = lp8788_dldo578_aldo6_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO8_VOUT,
+               .vsel_mask = LP8788_VOUT_4BIT_M,
+               .enable_reg = LP8788_EN_LDO_A,
+               .enable_mask = LP8788_EN_DLDO8_M,
+       },
+       {
+               .name = "dldo9",
+               .id = DLDO9,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo1239_vtbl),
+               .volt_table = lp8788_dldo1239_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO9_VOUT,
+               .vsel_mask = LP8788_VOUT_5BIT_M,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_DLDO9_M,
+       },
+       {
+               .name = "dldo10",
+               .id = DLDO10,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo1011_vtbl),
+               .volt_table = lp8788_dldo1011_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO10_VOUT,
+               .vsel_mask = LP8788_VOUT_4BIT_M,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_DLDO10_M,
+       },
+       {
+               .name = "dldo11",
+               .id = DLDO11,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo1011_vtbl),
+               .volt_table = lp8788_dldo1011_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_DLDO11_VOUT,
+               .vsel_mask = LP8788_VOUT_4BIT_M,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_DLDO11_M,
+       },
+       {
+               .name = "dldo12",
+               .id = DLDO12,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_DLDO12_M,
+       },
+};
+
+static struct regulator_desc lp8788_aldo_desc[] = {
+       {
+               .name = "aldo1",
+               .id = ALDO1,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_aldo1_vtbl),
+               .volt_table = lp8788_aldo1_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_ALDO1_VOUT,
+               .vsel_mask = LP8788_VOUT_1BIT_M,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_ALDO1_M,
+       },
+       {
+               .name = "aldo2",
+               .id = ALDO2,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_ALDO2_M,
+       },
+       {
+               .name = "aldo3",
+               .id = ALDO3,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_ALDO3_M,
+       },
+       {
+               .name = "aldo4",
+               .id = ALDO4,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_B,
+               .enable_mask = LP8788_EN_ALDO4_M,
+       },
+       {
+               .name = "aldo5",
+               .id = ALDO5,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_C,
+               .enable_mask = LP8788_EN_ALDO5_M,
+       },
+       {
+               .name = "aldo6",
+               .id = ALDO6,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_dldo578_aldo6_vtbl),
+               .volt_table = lp8788_dldo578_aldo6_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_ALDO6_VOUT,
+               .vsel_mask = LP8788_VOUT_4BIT_M,
+               .enable_reg = LP8788_EN_LDO_C,
+               .enable_mask = LP8788_EN_ALDO6_M,
+       },
+       {
+               .name = "aldo7",
+               .id = ALDO7,
+               .ops = &lp8788_ldo_voltage_table_ops,
+               .n_voltages = ARRAY_SIZE(lp8788_aldo7_vtbl),
+               .volt_table = lp8788_aldo7_vtbl,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .vsel_reg = LP8788_ALDO7_VOUT,
+               .vsel_mask = LP8788_VOUT_3BIT_M,
+               .enable_reg = LP8788_EN_LDO_C,
+               .enable_mask = LP8788_EN_ALDO7_M,
+       },
+       {
+               .name = "aldo8",
+               .id = ALDO8,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_C,
+               .enable_mask = LP8788_EN_ALDO8_M,
+       },
+       {
+               .name = "aldo9",
+               .id = ALDO9,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_C,
+               .enable_mask = LP8788_EN_ALDO9_M,
+       },
+       {
+               .name = "aldo10",
+               .id = ALDO10,
+               .ops = &lp8788_ldo_voltage_fixed_ops,
+               .type = REGULATOR_VOLTAGE,
+               .owner = THIS_MODULE,
+               .enable_reg = LP8788_EN_LDO_C,
+               .enable_mask = LP8788_EN_ALDO10_M,
+       },
+};
+
+static int lp8788_gpio_request_ldo_en(struct lp8788_ldo *ldo,
+                               enum lp8788_ext_ldo_en_id id)
+{
+       struct device *dev = ldo->lp->dev;
+       struct lp8788_ldo_enable_pin *pin = ldo->en_pin;
+       int ret, gpio, pinstate;
+       char *name[] = {
+               [EN_ALDO1]   = "LP8788_EN_ALDO1",
+               [EN_ALDO234] = "LP8788_EN_ALDO234",
+               [EN_ALDO5]   = "LP8788_EN_ALDO5",
+               [EN_ALDO7]   = "LP8788_EN_ALDO7",
+               [EN_DLDO7]   = "LP8788_EN_DLDO7",
+               [EN_DLDO911] = "LP8788_EN_DLDO911",
+       };
+
+       gpio = pin->gpio;
+       if (!gpio_is_valid(gpio)) {
+               dev_err(dev, "invalid gpio: %d\n", gpio);
+               return -EINVAL;
+       }
+
+       pinstate = pin->init_state;
+       ret = devm_gpio_request_one(dev, gpio, pinstate, name[id]);
+       if (ret == -EBUSY) {
+               dev_warn(dev, "gpio%d already used\n", gpio);
+               return 0;
+       }
+
+       return ret;
+}
+
+static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo,
+                                       enum lp8788_ldo_id id)
+{
+       int ret;
+       struct lp8788 *lp = ldo->lp;
+       struct lp8788_platform_data *pdata = lp->pdata;
+       enum lp8788_ext_ldo_en_id enable_id;
+       u8 en_mask[] = {
+               [EN_ALDO1]   = LP8788_EN_SEL_ALDO1_M,
+               [EN_ALDO234] = LP8788_EN_SEL_ALDO234_M,
+               [EN_ALDO5]   = LP8788_EN_SEL_ALDO5_M,
+               [EN_ALDO7]   = LP8788_EN_SEL_ALDO7_M,
+               [EN_DLDO7]   = LP8788_EN_SEL_DLDO7_M,
+               [EN_DLDO911] = LP8788_EN_SEL_DLDO911_M,
+       };
+       u8 val[] = {
+               [EN_ALDO1]   = 0 << 5,
+               [EN_ALDO234] = 0 << 4,
+               [EN_ALDO5]   = 0 << 3,
+               [EN_ALDO7]   = 0 << 2,
+               [EN_DLDO7]   = 0 << 1,
+               [EN_DLDO911] = 0 << 0,
+       };
+
+       switch (id) {
+       case DLDO7:
+               enable_id = EN_DLDO7;
+               break;
+       case DLDO9:
+       case DLDO11:
+               enable_id = EN_DLDO911;
+               break;
+       case ALDO1:
+               enable_id = EN_ALDO1;
+               break;
+       case ALDO2 ... ALDO4:
+               enable_id = EN_ALDO234;
+               break;
+       case ALDO5:
+               enable_id = EN_ALDO5;
+               break;
+       case ALDO7:
+               enable_id = EN_ALDO7;
+               break;
+       default:
+               return 0;
+       }
+
+       /* if no platform data for ldo pin, then set default enable mode */
+       if (!pdata || !pdata->ldo_pin || !pdata->ldo_pin[enable_id])
+               goto set_default_ldo_enable_mode;
+
+       ldo->en_pin = pdata->ldo_pin[enable_id];
+
+       ret = lp8788_gpio_request_ldo_en(ldo, enable_id);
+       if (ret)
+               goto set_default_ldo_enable_mode;
+
+       return ret;
+
+set_default_ldo_enable_mode:
+       return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id],
+                               val[enable_id]);
+}
+
+static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
+{
+       struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
+       int id = pdev->id;
+       struct lp8788_ldo *ldo;
+       struct regulator_config cfg = { };
+       struct regulator_dev *rdev;
+       int ret;
+
+       ldo = devm_kzalloc(lp->dev, sizeof(struct lp8788_ldo), GFP_KERNEL);
+       if (!ldo)
+               return -ENOMEM;
+
+       ldo->lp = lp;
+       ret = lp8788_config_ldo_enable_mode(ldo, lp8788_dldo_id[id]);
+       if (ret)
+               return ret;
+
+       cfg.dev = lp->dev;
+       cfg.init_data = lp->pdata ? lp->pdata->dldo_data[id] : NULL;
+       cfg.driver_data = ldo;
+       cfg.regmap = lp->regmap;
+
+       rdev = regulator_register(&lp8788_dldo_desc[id], &cfg);
+       if (IS_ERR(rdev)) {
+               ret = PTR_ERR(rdev);
+               dev_err(lp->dev, "DLDO%d regulator register err = %d\n",
+                               id + 1, ret);
+               return ret;
+       }
+
+       ldo->regulator = rdev;
+       platform_set_drvdata(pdev, ldo);
+
+       return 0;
+}
+
+static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
+{
+       struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+       regulator_unregister(ldo->regulator);
+
+       return 0;
+}
+
+static struct platform_driver lp8788_dldo_driver = {
+       .probe = lp8788_dldo_probe,
+       .remove = __devexit_p(lp8788_dldo_remove),
+       .driver = {
+               .name = LP8788_DEV_DLDO,
+               .owner = THIS_MODULE,
+       },
+};
+
+static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
+{
+       struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
+       int id = pdev->id;
+       struct lp8788_ldo *ldo;
+       struct regulator_config cfg = { };
+       struct regulator_dev *rdev;
+       int ret;
+
+       ldo = devm_kzalloc(lp->dev, sizeof(struct lp8788_ldo), GFP_KERNEL);
+       if (!ldo)
+               return -ENOMEM;
+
+       ldo->lp = lp;
+       ret = lp8788_config_ldo_enable_mode(ldo, lp8788_aldo_id[id]);
+       if (ret)
+               return ret;
+
+       cfg.dev = lp->dev;
+       cfg.init_data = lp->pdata ? lp->pdata->aldo_data[id] : NULL;
+       cfg.driver_data = ldo;
+       cfg.regmap = lp->regmap;
+
+       rdev = regulator_register(&lp8788_aldo_desc[id], &cfg);
+       if (IS_ERR(rdev)) {
+               ret = PTR_ERR(rdev);
+               dev_err(lp->dev, "ALDO%d regulator register err = %d\n",
+                               id + 1, ret);
+               return ret;
+       }
+
+       ldo->regulator = rdev;
+       platform_set_drvdata(pdev, ldo);
+
+       return 0;
+}
+
+static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
+{
+       struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
+
+       platform_set_drvdata(pdev, NULL);
+       regulator_unregister(ldo->regulator);
+
+       return 0;
+}
+
+static struct platform_driver lp8788_aldo_driver = {
+       .probe = lp8788_aldo_probe,
+       .remove = __devexit_p(lp8788_aldo_remove),
+       .driver = {
+               .name = LP8788_DEV_ALDO,
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init lp8788_ldo_init(void)
+{
+       int ret;
+
+       ret = platform_driver_register(&lp8788_dldo_driver);
+       if (ret)
+               return ret;
+
+       return platform_driver_register(&lp8788_aldo_driver);
+}
+subsys_initcall(lp8788_ldo_init);
+
+static void __exit lp8788_ldo_exit(void)
+{
+       platform_driver_unregister(&lp8788_aldo_driver);
+       platform_driver_unregister(&lp8788_dldo_driver);
+}
+module_exit(lp8788_ldo_exit);
+
+MODULE_DESCRIPTION("TI LP8788 LDO Driver");
+MODULE_AUTHOR("Milo Kim");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lp8788-dldo");
+MODULE_ALIAS("platform:lp8788-aldo");
index b9444ee08da9d27af4ec3d9e632e21b75eefa394..f67af3c1b9638636f5bdde781d15b79d516b89e8 100644 (file)
@@ -47,6 +47,14 @@ struct max1586_data {
        struct regulator_dev *rdev[0];
 };
 
+/*
+ * V6 voltage
+ * On I2C bus, sending a "x" byte to the max1586 means :
+ *   set V6 to either 0V, 1.8V, 2.5V, 3V depending on (x & 0x3)
+ * As regulator framework doesn't accept voltages to be 0V, we use 1uV.
+ */
+static int v6_voltages_uv[] = { 1, 1800000, 2500000, 3000000 };
+
 /*
  * V3 voltage
  * On I2C bus, sending a "x" byte to the max1586 means :
@@ -55,113 +63,49 @@ struct max1586_data {
  * R24 and R25=100kOhm as described in the data sheet.
  * The gain is approximately: 1 + R24/R25 + R24/185.5kOhm
  */
-static int max1586_v3_calc_voltage(struct max1586_data *max1586,
-       unsigned selector)
-{
-       unsigned range_uV = max1586->max_uV - max1586->min_uV;
-
-       return max1586->min_uV + (selector * range_uV / MAX1586_V3_MAX_VSEL);
-}
-
-static int max1586_v3_set(struct regulator_dev *rdev, int min_uV, int max_uV,
-                         unsigned *selector)
+static int max1586_v3_set_voltage_sel(struct regulator_dev *rdev,
+                                     unsigned selector)
 {
        struct max1586_data *max1586 = rdev_get_drvdata(rdev);
        struct i2c_client *client = max1586->client;
-       unsigned range_uV = max1586->max_uV - max1586->min_uV;
        u8 v3_prog;
 
-       if (min_uV > max1586->max_uV || max_uV < max1586->min_uV)
-               return -EINVAL;
-       if (min_uV < max1586->min_uV)
-               min_uV = max1586->min_uV;
-
-       *selector = DIV_ROUND_UP((min_uV - max1586->min_uV) *
-                                MAX1586_V3_MAX_VSEL, range_uV);
-       if (max1586_v3_calc_voltage(max1586, *selector) > max_uV)
-               return -EINVAL;
-
        dev_dbg(&client->dev, "changing voltage v3 to %dmv\n",
-               max1586_v3_calc_voltage(max1586, *selector) / 1000);
+               regulator_list_voltage_linear(rdev, selector) / 1000);
 
-       v3_prog = I2C_V3_SELECT | (u8) *selector;
+       v3_prog = I2C_V3_SELECT | (u8) selector;
        return i2c_smbus_write_byte(client, v3_prog);
 }
 
-static int max1586_v3_list(struct regulator_dev *rdev, unsigned selector)
-{
-       struct max1586_data *max1586 = rdev_get_drvdata(rdev);
-
-       if (selector > MAX1586_V3_MAX_VSEL)
-               return -EINVAL;
-       return max1586_v3_calc_voltage(max1586, selector);
-}
-
-/*
- * V6 voltage
- * On I2C bus, sending a "x" byte to the max1586 means :
- *   set V6 to either 0V, 1.8V, 2.5V, 3V depending on (x & 0x3)
- * As regulator framework doesn't accept voltages to be 0V, we use 1uV.
- */
-static int max1586_v6_calc_voltage(unsigned selector)
-{
-       static int voltages_uv[] = { 1, 1800000, 2500000, 3000000 };
-
-       return voltages_uv[selector];
-}
-
-static int max1586_v6_set(struct regulator_dev *rdev, int min_uV, int max_uV,
-                         unsigned int *selector)
+static int max1586_v6_set_voltage_sel(struct regulator_dev *rdev,
+                                     unsigned int selector)
 {
        struct i2c_client *client = rdev_get_drvdata(rdev);
        u8 v6_prog;
 
-       if (min_uV < MAX1586_V6_MIN_UV || min_uV > MAX1586_V6_MAX_UV)
-               return -EINVAL;
-       if (max_uV < MAX1586_V6_MIN_UV || max_uV > MAX1586_V6_MAX_UV)
-               return -EINVAL;
-
-       if (min_uV < 1800000)
-               *selector = 0;
-       else if (min_uV < 2500000)
-               *selector = 1;
-       else if (min_uV < 3000000)
-               *selector = 2;
-       else if (min_uV >= 3000000)
-               *selector = 3;
-
-       if (max1586_v6_calc_voltage(*selector) > max_uV)
-               return -EINVAL;
-
        dev_dbg(&client->dev, "changing voltage v6 to %dmv\n",
-               max1586_v6_calc_voltage(*selector) / 1000);
+               rdev->desc->volt_table[selector] / 1000);
 
-       v6_prog = I2C_V6_SELECT | (u8) *selector;
+       v6_prog = I2C_V6_SELECT | (u8) selector;
        return i2c_smbus_write_byte(client, v6_prog);
 }
 
-static int max1586_v6_list(struct regulator_dev *rdev, unsigned selector)
-{
-       if (selector > MAX1586_V6_MAX_VSEL)
-               return -EINVAL;
-       return max1586_v6_calc_voltage(selector);
-}
-
 /*
  * The Maxim 1586 controls V3 and V6 voltages, but offers no way of reading back
  * the set up value.
  */
 static struct regulator_ops max1586_v3_ops = {
-       .set_voltage = max1586_v3_set,
-       .list_voltage = max1586_v3_list,
+       .set_voltage_sel = max1586_v3_set_voltage_sel,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
 };
 
 static struct regulator_ops max1586_v6_ops = {
-       .set_voltage = max1586_v6_set,
-       .list_voltage = max1586_v6_list,
+       .set_voltage_sel = max1586_v6_set_voltage_sel,
+       .list_voltage = regulator_list_voltage_table,
 };
 
-static const struct regulator_desc max1586_reg[] = {
+static struct regulator_desc max1586_reg[] = {
        {
                .name = "Output_V3",
                .id = MAX1586_V3,
@@ -176,6 +120,7 @@ static const struct regulator_desc max1586_reg[] = {
                .ops = &max1586_v6_ops,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = MAX1586_V6_MAX_VSEL + 1,
+               .volt_table = v6_voltages_uv,
                .owner = THIS_MODULE,
        },
 };
@@ -213,6 +158,13 @@ static int __devinit max1586_pmic_probe(struct i2c_client *client,
                        goto err;
                }
 
+               if (id == MAX1586_V3) {
+                       max1586_reg[id].min_uV = max1586->min_uV;
+                       max1586_reg[id].uV_step =
+                                       (max1586->max_uV - max1586->min_uV) /
+                                       MAX1586_V3_MAX_VSEL;
+               }
+
                config.dev = &client->dev;
                config.init_data = pdata->subdevs[i].platform_data;
                config.driver_data = max1586;
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
new file mode 100644 (file)
index 0000000..c564af6
--- /dev/null
@@ -0,0 +1,389 @@
+/*
+ * max77686.c - Regulator driver for the Maxim 77686
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Chiwoong Byun <woong.byun@smasung.com>
+ * Jonghwa Lee <jonghwa3.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ *
+ * This driver is based on max8997.c
+ */
+
+#include <linux/kernel.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/mfd/max77686.h>
+#include <linux/mfd/max77686-private.h>
+
+#define MAX77686_LDO_MINUV     800000
+#define MAX77686_LDO_UVSTEP    50000
+#define MAX77686_LDO_LOW_MINUV 800000
+#define MAX77686_LDO_LOW_UVSTEP        25000
+#define MAX77686_BUCK_MINUV    750000
+#define MAX77686_BUCK_UVSTEP   50000
+#define MAX77686_RAMP_DELAY    100000                  /* uV/us */
+#define MAX77686_DVS_RAMP_DELAY        27500                   /* uV/us */
+#define MAX77686_DVS_MINUV     600000
+#define MAX77686_DVS_UVSTEP    12500
+
+#define MAX77686_OPMODE_SHIFT  6
+#define MAX77686_OPMODE_BUCK234_SHIFT  4
+#define MAX77686_OPMODE_MASK   0x3
+
+#define MAX77686_VSEL_MASK     0x3F
+#define MAX77686_DVS_VSEL_MASK 0xFF
+
+#define MAX77686_RAMP_RATE_MASK        0xC0
+
+#define MAX77686_REGULATORS    MAX77686_REG_MAX
+#define MAX77686_LDOS          26
+
+enum max77686_ramp_rate {
+       RAMP_RATE_13P75MV,
+       RAMP_RATE_27P5MV,
+       RAMP_RATE_55MV,
+       RAMP_RATE_NO_CTRL,      /* 100mV/us */
+};
+
+struct max77686_data {
+       struct regulator_dev **rdev;
+};
+
+static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay)
+{
+       unsigned int ramp_value = RAMP_RATE_NO_CTRL;
+
+       switch (ramp_delay) {
+       case 1 ... 13750:
+               ramp_value = RAMP_RATE_13P75MV;
+               break;
+       case 13751 ... 27500:
+               ramp_value = RAMP_RATE_27P5MV;
+               break;
+       case 27501 ... 55000:
+               ramp_value = RAMP_RATE_55MV;
+               break;
+       case 55001 ... 100000:
+               break;
+       default:
+               pr_warn("%s: ramp_delay: %d not supported, setting 100000\n",
+                       rdev->desc->name, ramp_delay);
+       }
+
+       return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
+                                 MAX77686_RAMP_RATE_MASK, ramp_value << 6);
+}
+
+static struct regulator_ops max77686_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+};
+
+static struct regulator_ops max77686_buck_dvs_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_ramp_delay         = max77686_set_ramp_delay,
+};
+
+#define regulator_desc_ldo(num)                {                               \
+       .name           = "LDO"#num,                                    \
+       .id             = MAX77686_LDO##num,                            \
+       .ops            = &max77686_ops,                                \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_LDO_MINUV,                           \
+       .uV_step        = MAX77686_LDO_UVSTEP,                          \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_SHIFT,                       \
+}
+#define regulator_desc_ldo_low(num)            {                       \
+       .name           = "LDO"#num,                                    \
+       .id             = MAX77686_LDO##num,                            \
+       .ops            = &max77686_ops,                                \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_LDO_LOW_MINUV,                       \
+       .uV_step        = MAX77686_LDO_LOW_UVSTEP,                      \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_LDO1CTRL1 + num - 1,             \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_SHIFT,                       \
+}
+#define regulator_desc_buck(num)               {                       \
+       .name           = "BUCK"#num,                                   \
+       .id             = MAX77686_BUCK##num,                           \
+       .ops            = &max77686_ops,                                \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_BUCK_MINUV,                          \
+       .uV_step        = MAX77686_BUCK_UVSTEP,                         \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_BUCK5OUT + (num - 5) * 2,        \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_BUCK5CTRL + (num - 5) * 2,       \
+       .enable_mask    = MAX77686_OPMODE_MASK,                         \
+}
+#define regulator_desc_buck1(num)              {                       \
+       .name           = "BUCK"#num,                                   \
+       .id             = MAX77686_BUCK##num,                           \
+       .ops            = &max77686_ops,                                \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_BUCK_MINUV,                          \
+       .uV_step        = MAX77686_BUCK_UVSTEP,                         \
+       .ramp_delay     = MAX77686_RAMP_DELAY,                          \
+       .n_voltages     = MAX77686_VSEL_MASK + 1,                       \
+       .vsel_reg       = MAX77686_REG_BUCK1OUT,                        \
+       .vsel_mask      = MAX77686_VSEL_MASK,                           \
+       .enable_reg     = MAX77686_REG_BUCK1CTRL,                       \
+       .enable_mask    = MAX77686_OPMODE_MASK,                         \
+}
+#define regulator_desc_buck_dvs(num)           {                       \
+       .name           = "BUCK"#num,                                   \
+       .id             = MAX77686_BUCK##num,                           \
+       .ops            = &max77686_buck_dvs_ops,                       \
+       .type           = REGULATOR_VOLTAGE,                            \
+       .owner          = THIS_MODULE,                                  \
+       .min_uV         = MAX77686_DVS_MINUV,                           \
+       .uV_step        = MAX77686_DVS_UVSTEP,                          \
+       .ramp_delay     = MAX77686_DVS_RAMP_DELAY,                      \
+       .n_voltages     = MAX77686_DVS_VSEL_MASK + 1,                   \
+       .vsel_reg       = MAX77686_REG_BUCK2DVS1 + (num - 2) * 10,      \
+       .vsel_mask      = MAX77686_DVS_VSEL_MASK,                       \
+       .enable_reg     = MAX77686_REG_BUCK2CTRL1 + (num - 2) * 10,     \
+       .enable_mask    = MAX77686_OPMODE_MASK                          \
+                       << MAX77686_OPMODE_BUCK234_SHIFT,               \
+}
+
+static struct regulator_desc regulators[] = {
+       regulator_desc_ldo_low(1),
+       regulator_desc_ldo_low(2),
+       regulator_desc_ldo(3),
+       regulator_desc_ldo(4),
+       regulator_desc_ldo(5),
+       regulator_desc_ldo_low(6),
+       regulator_desc_ldo_low(7),
+       regulator_desc_ldo_low(8),
+       regulator_desc_ldo(9),
+       regulator_desc_ldo(10),
+       regulator_desc_ldo(11),
+       regulator_desc_ldo(12),
+       regulator_desc_ldo(13),
+       regulator_desc_ldo(14),
+       regulator_desc_ldo_low(15),
+       regulator_desc_ldo(16),
+       regulator_desc_ldo(17),
+       regulator_desc_ldo(18),
+       regulator_desc_ldo(19),
+       regulator_desc_ldo(20),
+       regulator_desc_ldo(21),
+       regulator_desc_ldo(22),
+       regulator_desc_ldo(23),
+       regulator_desc_ldo(24),
+       regulator_desc_ldo(25),
+       regulator_desc_ldo(26),
+       regulator_desc_buck1(1),
+       regulator_desc_buck_dvs(2),
+       regulator_desc_buck_dvs(3),
+       regulator_desc_buck_dvs(4),
+       regulator_desc_buck(5),
+       regulator_desc_buck(6),
+       regulator_desc_buck(7),
+       regulator_desc_buck(8),
+       regulator_desc_buck(9),
+};
+
+#ifdef CONFIG_OF
+static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
+                                       struct max77686_platform_data *pdata)
+{
+       struct device_node *pmic_np, *regulators_np;
+       struct max77686_regulator_data *rdata;
+       struct of_regulator_match rmatch;
+       unsigned int i;
+
+       pmic_np = iodev->dev->of_node;
+       regulators_np = of_find_node_by_name(pmic_np, "voltage-regulators");
+       if (!regulators_np) {
+               dev_err(iodev->dev, "could not find regulators sub-node\n");
+               return -EINVAL;
+       }
+
+       pdata->num_regulators = ARRAY_SIZE(regulators);
+       rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) *
+                            pdata->num_regulators, GFP_KERNEL);
+       if (!rdata) {
+               dev_err(iodev->dev,
+                       "could not allocate memory for regulator data\n");
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < pdata->num_regulators; i++) {
+               rmatch.name = regulators[i].name;
+               rmatch.init_data = NULL;
+               rmatch.of_node = NULL;
+               of_regulator_match(iodev->dev, regulators_np, &rmatch, 1);
+               rdata[i].initdata = rmatch.init_data;
+       }
+
+       pdata->regulators = rdata;
+
+       return 0;
+}
+#else
+static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
+                                       struct max77686_platform_data *pdata)
+{
+       return 0;
+}
+#endif /* CONFIG_OF */
+
+static __devinit int max77686_pmic_probe(struct platform_device *pdev)
+{
+       struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+       struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
+       struct regulator_dev **rdev;
+       struct max77686_data *max77686;
+       int i,  size;
+       int ret = 0;
+       struct regulator_config config = { };
+
+       dev_dbg(&pdev->dev, "%s\n", __func__);
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "no platform data found for regulator\n");
+               return -ENODEV;
+       }
+
+       if (iodev->dev->of_node) {
+               ret = max77686_pmic_dt_parse_pdata(iodev, pdata);
+               if (ret)
+                       return ret;
+       }
+
+       if (pdata->num_regulators != MAX77686_REGULATORS) {
+               dev_err(&pdev->dev,
+                       "Invalid initial data for regulator's initialiation\n");
+               return -EINVAL;
+       }
+
+       max77686 = devm_kzalloc(&pdev->dev, sizeof(struct max77686_data),
+                               GFP_KERNEL);
+       if (!max77686)
+               return -ENOMEM;
+
+       size = sizeof(struct regulator_dev *) * MAX77686_REGULATORS;
+       max77686->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+       if (!max77686->rdev)
+               return -ENOMEM;
+
+       rdev = max77686->rdev;
+       config.dev = &pdev->dev;
+       config.regmap = iodev->regmap;
+       platform_set_drvdata(pdev, max77686);
+
+       for (i = 0; i < MAX77686_REGULATORS; i++) {
+               config.init_data = pdata->regulators[i].initdata;
+
+               rdev[i] = regulator_register(&regulators[i], &config);
+               if (IS_ERR(rdev[i])) {
+                       ret = PTR_ERR(rdev[i]);
+                       dev_err(&pdev->dev,
+                               "regulator init failed for %d\n", i);
+                               rdev[i] = NULL;
+                               goto err;
+               }
+       }
+
+       return 0;
+err:
+       while (--i >= 0)
+               regulator_unregister(rdev[i]);
+       return ret;
+}
+
+static int __devexit max77686_pmic_remove(struct platform_device *pdev)
+{
+       struct max77686_data *max77686 = platform_get_drvdata(pdev);
+       struct regulator_dev **rdev = max77686->rdev;
+       int i;
+
+       for (i = 0; i < MAX77686_REGULATORS; i++)
+               if (rdev[i])
+                       regulator_unregister(rdev[i]);
+
+       return 0;
+}
+
+static const struct platform_device_id max77686_pmic_id[] = {
+       {"max77686-pmic", 0},
+       { },
+};
+MODULE_DEVICE_TABLE(platform, max77686_pmic_id);
+
+static struct platform_driver max77686_pmic_driver = {
+       .driver = {
+               .name = "max77686-pmic",
+               .owner = THIS_MODULE,
+       },
+       .probe = max77686_pmic_probe,
+       .remove = __devexit_p(max77686_pmic_remove),
+       .id_table = max77686_pmic_id,
+};
+
+static int __init max77686_pmic_init(void)
+{
+       return platform_driver_register(&max77686_pmic_driver);
+}
+subsys_initcall(max77686_pmic_init);
+
+static void __exit max77686_pmic_cleanup(void)
+{
+       platform_driver_unregister(&max77686_pmic_driver);
+}
+module_exit(max77686_pmic_cleanup);
+
+MODULE_DESCRIPTION("MAXIM 77686 Regulator Driver");
+MODULE_AUTHOR("Chiwoong Byun <woong.byun@samsung.com>");
+MODULE_LICENSE("GPL");
index 910c9b26d499f45f50034b417790921649fc4a6f..355ca7bad9d59a9583cdda44ee986ced030ab5fa 100644 (file)
@@ -51,7 +51,6 @@ struct max8952_data {
 
        bool vid0;
        bool vid1;
-       bool en;
 };
 
 static int max8952_read_reg(struct max8952_data *max8952, u8 reg)
@@ -80,38 +79,6 @@ static int max8952_list_voltage(struct regulator_dev *rdev,
        return (max8952->pdata->dvs_mode[selector] * 10 + 770) * 1000;
 }
 
-static int max8952_is_enabled(struct regulator_dev *rdev)
-{
-       struct max8952_data *max8952 = rdev_get_drvdata(rdev);
-       return max8952->en;
-}
-
-static int max8952_enable(struct regulator_dev *rdev)
-{
-       struct max8952_data *max8952 = rdev_get_drvdata(rdev);
-
-       /* If not valid, assume "ALWAYS_HIGH" */
-       if (gpio_is_valid(max8952->pdata->gpio_en))
-               gpio_set_value(max8952->pdata->gpio_en, 1);
-
-       max8952->en = true;
-       return 0;
-}
-
-static int max8952_disable(struct regulator_dev *rdev)
-{
-       struct max8952_data *max8952 = rdev_get_drvdata(rdev);
-
-       /* If not valid, assume "ALWAYS_HIGH" -> not permitted */
-       if (gpio_is_valid(max8952->pdata->gpio_en))
-               gpio_set_value(max8952->pdata->gpio_en, 0);
-       else
-               return -EPERM;
-
-       max8952->en = false;
-       return 0;
-}
-
 static int max8952_get_voltage_sel(struct regulator_dev *rdev)
 {
        struct max8952_data *max8952 = rdev_get_drvdata(rdev);
@@ -146,12 +113,8 @@ static int max8952_set_voltage_sel(struct regulator_dev *rdev,
 
 static struct regulator_ops max8952_ops = {
        .list_voltage           = max8952_list_voltage,
-       .is_enabled             = max8952_is_enabled,
-       .enable                 = max8952_enable,
-       .disable                = max8952_disable,
        .get_voltage_sel        = max8952_get_voltage_sel,
        .set_voltage_sel        = max8952_set_voltage_sel,
-       .set_suspend_disable    = max8952_disable,
 };
 
 static const struct regulator_desc regulator = {
@@ -194,6 +157,10 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
        config.init_data = &pdata->reg_data;
        config.driver_data = max8952;
 
+       config.ena_gpio = pdata->gpio_en;
+       if (pdata->reg_data.constraints.boot_on)
+               config.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
+
        max8952->rdev = regulator_register(&regulator, &config);
 
        if (IS_ERR(max8952->rdev)) {
@@ -202,27 +169,9 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
                return ret;
        }
 
-       max8952->en = !!(pdata->reg_data.constraints.boot_on);
        max8952->vid0 = pdata->default_mode & 0x1;
        max8952->vid1 = (pdata->default_mode >> 1) & 0x1;
 
-       if (gpio_is_valid(pdata->gpio_en)) {
-               if (!gpio_request(pdata->gpio_en, "MAX8952 EN"))
-                       gpio_direction_output(pdata->gpio_en, max8952->en);
-               else
-                       err = 1;
-       } else
-               err = 2;
-
-       if (err) {
-               dev_info(max8952->dev, "EN gpio invalid: assume that EN"
-                               "is always High\n");
-               max8952->en = 1;
-               pdata->gpio_en = -1; /* Mark invalid */
-       }
-
-       err = 0;
-
        if (gpio_is_valid(pdata->gpio_vid0) &&
                        gpio_is_valid(pdata->gpio_vid1)) {
                if (!gpio_request(pdata->gpio_vid0, "MAX8952 VID0"))
@@ -308,7 +257,6 @@ static int __devexit max8952_pmic_remove(struct i2c_client *client)
 
        gpio_free(pdata->gpio_vid0);
        gpio_free(pdata->gpio_vid1);
-       gpio_free(pdata->gpio_en);
        return 0;
 }
 
index 704cd49ef3758c9ac00034238838af634e0c27f1..e39a0c7260dca5b7fe13098dbfd06d98c4b0b3e5 100644 (file)
@@ -1025,7 +1025,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
         */
        if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
                        pdata->buck5_gpiodvs) {
-               bool gpio1set = false, gpio2set = false;
 
                if (!gpio_is_valid(pdata->buck125_gpios[0]) ||
                                !gpio_is_valid(pdata->buck125_gpios[1]) ||
@@ -1035,40 +1034,20 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
                        goto err_out;
                }
 
-               ret = gpio_request(pdata->buck125_gpios[0],
-                               "MAX8997 SET1");
-               if (ret == -EBUSY)
-                       dev_warn(&pdev->dev, "Duplicated gpio request"
-                                       " on SET1\n");
-               else if (ret)
+               ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[0],
+                                       "MAX8997 SET1");
+               if (ret)
                        goto err_out;
-               else
-                       gpio1set = true;
-
-               ret = gpio_request(pdata->buck125_gpios[1],
-                               "MAX8997 SET2");
-               if (ret == -EBUSY)
-                       dev_warn(&pdev->dev, "Duplicated gpio request"
-                                       " on SET2\n");
-               else if (ret) {
-                       if (gpio1set)
-                               gpio_free(pdata->buck125_gpios[0]);
+
+               ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[1],
+                                       "MAX8997 SET2");
+               if (ret)
                        goto err_out;
-               } else
-                       gpio2set = true;
 
-               ret = gpio_request(pdata->buck125_gpios[2],
+               ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[2],
                                "MAX8997 SET3");
-               if (ret == -EBUSY)
-                       dev_warn(&pdev->dev, "Duplicated gpio request"
-                                       " on SET3\n");
-               else if (ret) {
-                       if (gpio1set)
-                               gpio_free(pdata->buck125_gpios[0]);
-                       if (gpio2set)
-                               gpio_free(pdata->buck125_gpios[1]);
+               if (ret)
                        goto err_out;
-               }
 
                gpio_direction_output(pdata->buck125_gpios[0],
                                (max8997->buck125_gpioindex >> 2)
@@ -1079,7 +1058,6 @@ static __devinit int max8997_pmic_probe(struct platform_device *pdev)
                gpio_direction_output(pdata->buck125_gpios[2],
                                (max8997->buck125_gpioindex >> 0)
                                & 0x1); /* SET3 */
-               ret = 0;
        }
 
        /* DVS-GPIO disabled */
index 18bb58b9b96e04836464f86e345310ba1f86227a..5dfa920ff0c8873c91e8c02176af4d722f3c3659 100644 (file)
@@ -111,27 +111,6 @@ static const struct voltage_map_desc *ldo_voltage_map[] = {
        &buck4_voltage_map_desc,        /* BUCK4 */
 };
 
-static int max8998_list_voltage(struct regulator_dev *rdev,
-                               unsigned int selector)
-{
-       const struct voltage_map_desc *desc;
-       int ldo = rdev_get_id(rdev);
-       int val;
-
-       if (ldo >= ARRAY_SIZE(ldo_voltage_map))
-               return -EINVAL;
-
-       desc = ldo_voltage_map[ldo];
-       if (desc == NULL)
-               return -EINVAL;
-
-       val = desc->min + desc->step * selector;
-       if (val > desc->max)
-               return -EINVAL;
-
-       return val * 1000;
-}
-
 static int max8998_get_enable_register(struct regulator_dev *rdev,
                                        int *reg, int *shift)
 {
@@ -297,41 +276,18 @@ static int max8998_get_voltage_sel(struct regulator_dev *rdev)
        return val;
 }
 
-static int max8998_set_voltage_ldo(struct regulator_dev *rdev,
-                                  int min_uV, int max_uV, unsigned *selector)
+static int max8998_set_voltage_ldo_sel(struct regulator_dev *rdev,
+                                      unsigned selector)
 {
        struct max8998_data *max8998 = rdev_get_drvdata(rdev);
        struct i2c_client *i2c = max8998->iodev->i2c;
-       int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
-       const struct voltage_map_desc *desc;
-       int ldo = rdev_get_id(rdev);
-       int reg, shift = 0, mask, ret, i;
-
-       if (ldo >= ARRAY_SIZE(ldo_voltage_map))
-               return -EINVAL;
-
-       desc = ldo_voltage_map[ldo];
-       if (desc == NULL)
-               return -EINVAL;
-
-       if (max_vol < desc->min || min_vol > desc->max)
-               return -EINVAL;
-
-       if (min_vol < desc->min)
-               min_vol = desc->min;
-
-       i = DIV_ROUND_UP(min_vol - desc->min, desc->step);
-
-       if (desc->min + desc->step*i > max_vol)
-               return -EINVAL;
-
-       *selector = i;
+       int reg, shift = 0, mask, ret;
 
        ret = max8998_get_voltage_register(rdev, &reg, &shift, &mask);
        if (ret)
                return ret;
 
-       ret = max8998_update_reg(i2c, reg, i<<shift, mask<<shift);
+       ret = max8998_update_reg(i2c, reg, selector<<shift, mask<<shift);
 
        return ret;
 }
@@ -347,41 +303,18 @@ static inline void buck2_gpio_set(int gpio, int v)
        gpio_set_value(gpio, v & 0x1);
 }
 
-static int max8998_set_voltage_buck(struct regulator_dev *rdev,
-                                   int min_uV, int max_uV, unsigned *selector)
+static int max8998_set_voltage_buck_sel(struct regulator_dev *rdev,
+                                       unsigned selector)
 {
        struct max8998_data *max8998 = rdev_get_drvdata(rdev);
        struct max8998_platform_data *pdata =
                dev_get_platdata(max8998->iodev->dev);
        struct i2c_client *i2c = max8998->iodev->i2c;
-       int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
-       const struct voltage_map_desc *desc;
        int buck = rdev_get_id(rdev);
        int reg, shift = 0, mask, ret;
-       int i, j, previous_sel;
+       int j, previous_sel;
        static u8 buck1_last_val;
 
-       if (buck >= ARRAY_SIZE(ldo_voltage_map))
-               return -EINVAL;
-
-       desc = ldo_voltage_map[buck];
-
-       if (desc == NULL)
-               return -EINVAL;
-
-       if (max_vol < desc->min || min_vol > desc->max)
-               return -EINVAL;
-
-       if (min_vol < desc->min)
-               min_vol = desc->min;
-
-       i = DIV_ROUND_UP(min_vol - desc->min, desc->step);
-
-       if (desc->min + desc->step*i > max_vol)
-               return -EINVAL;
-
-       *selector = i;
-
        ret = max8998_get_voltage_register(rdev, &reg, &shift, &mask);
        if (ret)
                return ret;
@@ -390,19 +323,19 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
 
        /* Check if voltage needs to be changed */
        /* if previous_voltage equal new voltage, return */
-       if (previous_sel == i) {
+       if (previous_sel == selector) {
                dev_dbg(max8998->dev, "No voltage change, old:%d, new:%d\n",
-                       max8998_list_voltage(rdev, previous_sel),
-                       max8998_list_voltage(rdev, i));
+                       regulator_list_voltage_linear(rdev, previous_sel),
+                       regulator_list_voltage_linear(rdev, selector));
                return ret;
        }
 
        switch (buck) {
        case MAX8998_BUCK1:
                dev_dbg(max8998->dev,
-                       "BUCK1, i:%d, buck1_vol1:%d, buck1_vol2:%d\n"
+                       "BUCK1, selector:%d, buck1_vol1:%d, buck1_vol2:%d\n"
                        "buck1_vol3:%d, buck1_vol4:%d\n",
-                       i, max8998->buck1_vol[0], max8998->buck1_vol[1],
+                       selector, max8998->buck1_vol[0], max8998->buck1_vol[1],
                        max8998->buck1_vol[2], max8998->buck1_vol[3]);
 
                if (gpio_is_valid(pdata->buck1_set1) &&
@@ -411,7 +344,7 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
                        /* check if requested voltage */
                        /* value is already defined */
                        for (j = 0; j < ARRAY_SIZE(max8998->buck1_vol); j++) {
-                               if (max8998->buck1_vol[j] == i) {
+                               if (max8998->buck1_vol[j] == selector) {
                                        max8998->buck1_idx = j;
                                        buck1_gpio_set(pdata->buck1_set1,
                                                       pdata->buck1_set2, j);
@@ -426,11 +359,11 @@ static int max8998_set_voltage_buck(struct regulator_dev *rdev,
                        max8998->buck1_idx = (buck1_last_val % 2) + 2;
                        dev_dbg(max8998->dev, "max8998->buck1_idx:%d\n",
                                max8998->buck1_idx);
-                       max8998->buck1_vol[max8998->buck1_idx] = i;
+                       max8998->buck1_vol[max8998->buck1_idx] = selector;
                        ret = max8998_get_voltage_register(rdev, &reg,
                                                           &shift,
                                                           &mask);
-                       ret = max8998_write_reg(i2c, reg, i);
+                       ret = max8998_write_reg(i2c, reg, selector);
                        buck1_gpio_set(pdata->buck1_set1,
                                       pdata->buck1_set2, max8998->buck1_idx);
                        buck1_last_val++;
@@ -440,20 +373,20 @@ buck1_exit:
                                gpio_get_value(pdata->buck1_set2));
                        break;
                } else {
-                       ret = max8998_write_reg(i2c, reg, i);
+                       ret = max8998_write_reg(i2c, reg, selector);
                }
                break;
 
        case MAX8998_BUCK2:
                dev_dbg(max8998->dev,
-                       "BUCK2, i:%d buck2_vol1:%d, buck2_vol2:%d\n"
-                       , i, max8998->buck2_vol[0], max8998->buck2_vol[1]);
+                       "BUCK2, selector:%d buck2_vol1:%d, buck2_vol2:%d\n",
+                       selector, max8998->buck2_vol[0], max8998->buck2_vol[1]);
                if (gpio_is_valid(pdata->buck2_set3)) {
 
                        /* check if requested voltage */
                        /* value is already defined */
                        for (j = 0; j < ARRAY_SIZE(max8998->buck2_vol); j++) {
-                               if (max8998->buck2_vol[j] == i) {
+                               if (max8998->buck2_vol[j] == selector) {
                                        max8998->buck2_idx = j;
                                        buck2_gpio_set(pdata->buck2_set3, j);
                                        goto buck2_exit;
@@ -465,20 +398,21 @@ buck1_exit:
 
                        max8998_get_voltage_register(rdev,
                                        &reg, &shift, &mask);
-                       ret = max8998_write_reg(i2c, reg, i);
-                       max8998->buck2_vol[max8998->buck2_idx] = i;
+                       ret = max8998_write_reg(i2c, reg, selector);
+                       max8998->buck2_vol[max8998->buck2_idx] = selector;
                        buck2_gpio_set(pdata->buck2_set3, max8998->buck2_idx);
 buck2_exit:
                        dev_dbg(max8998->dev, "%s: SET3:%d\n", i2c->name,
                                gpio_get_value(pdata->buck2_set3));
                } else {
-                       ret = max8998_write_reg(i2c, reg, i);
+                       ret = max8998_write_reg(i2c, reg, selector);
                }
                break;
 
        case MAX8998_BUCK3:
        case MAX8998_BUCK4:
-               ret = max8998_update_reg(i2c, reg, i<<shift, mask<<shift);
+               ret = max8998_update_reg(i2c, reg, selector<<shift,
+                                        mask<<shift);
                break;
        }
 
@@ -519,34 +453,30 @@ static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev,
 }
 
 static struct regulator_ops max8998_ldo_ops = {
-       .list_voltage           = max8998_list_voltage,
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = max8998_ldo_is_enabled,
        .enable                 = max8998_ldo_enable,
        .disable                = max8998_ldo_disable,
        .get_voltage_sel        = max8998_get_voltage_sel,
-       .set_voltage            = max8998_set_voltage_ldo,
-       .set_suspend_enable     = max8998_ldo_enable,
-       .set_suspend_disable    = max8998_ldo_disable,
+       .set_voltage_sel        = max8998_set_voltage_ldo_sel,
 };
 
 static struct regulator_ops max8998_buck_ops = {
-       .list_voltage           = max8998_list_voltage,
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
        .is_enabled             = max8998_ldo_is_enabled,
        .enable                 = max8998_ldo_enable,
        .disable                = max8998_ldo_disable,
        .get_voltage_sel        = max8998_get_voltage_sel,
-       .set_voltage            = max8998_set_voltage_buck,
+       .set_voltage_sel        = max8998_set_voltage_buck_sel,
        .set_voltage_time_sel   = max8998_set_voltage_buck_time_sel,
-       .set_suspend_enable     = max8998_ldo_enable,
-       .set_suspend_disable    = max8998_ldo_disable,
 };
 
 static struct regulator_ops max8998_others_ops = {
        .is_enabled             = max8998_ldo_is_enabled,
        .enable                 = max8998_ldo_enable,
        .disable                = max8998_ldo_disable,
-       .set_suspend_enable     = max8998_ldo_enable,
-       .set_suspend_disable    = max8998_ldo_disable,
 };
 
 static struct regulator_desc regulators[] = {
@@ -860,7 +790,10 @@ static __devinit int max8998_pmic_probe(struct platform_device *pdev)
                desc = ldo_voltage_map[id];
                if (desc && regulators[index].ops != &max8998_others_ops) {
                        int count = (desc->max - desc->min) / desc->step + 1;
+
                        regulators[index].n_voltages = count;
+                       regulators[index].min_uV = desc->min * 1000;
+                       regulators[index].uV_step = desc->step * 1000;
                }
 
                config.dev = max8998->dev;
index 7dcdfa283e9368c8bfa492a2104b516dc363d991..4932e3449fe145fc4e27f422df1d1816d7cb99c2 100644 (file)
 
 
 /* Voltage Values */
-static const int mc13783_sw3_val[] = {
+static const unsigned int mc13783_sw3_val[] = {
        5000000, 5000000, 5000000, 5500000,
 };
 
-static const int mc13783_vaudio_val[] = {
+static const unsigned int mc13783_vaudio_val[] = {
        2775000,
 };
 
-static const int mc13783_viohi_val[] = {
+static const unsigned int mc13783_viohi_val[] = {
        2775000,
 };
 
-static const int mc13783_violo_val[] = {
+static const unsigned int mc13783_violo_val[] = {
        1200000, 1300000, 1500000, 1800000,
 };
 
-static const int mc13783_vdig_val[] = {
+static const unsigned int mc13783_vdig_val[] = {
        1200000, 1300000, 1500000, 1800000,
 };
 
-static const int mc13783_vgen_val[] = {
+static const unsigned int mc13783_vgen_val[] = {
        1200000, 1300000, 1500000, 1800000,
        1100000, 2000000, 2775000, 2400000,
 };
 
-static const int mc13783_vrfdig_val[] = {
+static const unsigned int mc13783_vrfdig_val[] = {
        1200000, 1500000, 1800000, 1875000,
 };
 
-static const int mc13783_vrfref_val[] = {
+static const unsigned int mc13783_vrfref_val[] = {
        2475000, 2600000, 2700000, 2775000,
 };
 
-static const int mc13783_vrfcp_val[] = {
+static const unsigned int mc13783_vrfcp_val[] = {
        2700000, 2775000,
 };
 
-static const int mc13783_vsim_val[] = {
+static const unsigned int mc13783_vsim_val[] = {
        1800000, 2900000, 3000000,
 };
 
-static const int mc13783_vesim_val[] = {
+static const unsigned int mc13783_vesim_val[] = {
        1800000, 2900000,
 };
 
-static const int mc13783_vcam_val[] = {
+static const unsigned int mc13783_vcam_val[] = {
        1500000, 1800000, 2500000, 2550000,
        2600000, 2750000, 2800000, 3000000,
 };
 
-static const int mc13783_vrfbg_val[] = {
+static const unsigned int mc13783_vrfbg_val[] = {
        1250000,
 };
 
-static const int mc13783_vvib_val[] = {
+static const unsigned int mc13783_vvib_val[] = {
        1300000, 1800000, 2000000, 3000000,
 };
 
-static const int mc13783_vmmc_val[] = {
+static const unsigned int mc13783_vmmc_val[] = {
        1600000, 1800000, 2000000, 2600000,
        2700000, 2800000, 2900000, 3000000,
 };
 
-static const int mc13783_vrf_val[] = {
+static const unsigned int mc13783_vrf_val[] = {
        1500000, 1875000, 2700000, 2775000,
 };
 
-static const int mc13783_gpo_val[] = {
+static const unsigned int mc13783_gpo_val[] = {
        3100000,
 };
 
-static const int mc13783_pwgtdrv_val[] = {
+static const unsigned int mc13783_pwgtdrv_val[] = {
        5500000,
 };
 
@@ -328,7 +328,7 @@ static struct regulator_ops mc13783_gpo_regulator_ops = {
        .enable = mc13783_gpo_regulator_enable,
        .disable = mc13783_gpo_regulator_disable,
        .is_enabled = mc13783_gpo_regulator_is_enabled,
-       .list_voltage = mc13xxx_regulator_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .set_voltage = mc13xxx_fixed_regulator_set_voltage,
        .get_voltage = mc13xxx_fixed_regulator_get_voltage,
 };
index 970a233dbe46f3aa9e167195bc98f0d60ba9d624..b388b746452e024952cbfc6443adb2ec6bc4751b 100644 (file)
 #define MC13892_USB1                           50
 #define MC13892_USB1_VUSBEN                    (1<<3)
 
-static const int mc13892_vcoincell[] = {
+static const unsigned int mc13892_vcoincell[] = {
        2500000, 2700000, 2800000, 2900000, 3000000, 3100000,
        3200000, 3300000,
 };
 
-static const int mc13892_sw1[] = {
+static const unsigned int mc13892_sw1[] = {
        600000,   625000,  650000,  675000,  700000,  725000,
        750000,   775000,  800000,  825000,  850000,  875000,
        900000,   925000,  950000,  975000, 1000000, 1025000,
@@ -164,7 +164,7 @@ static const int mc13892_sw1[] = {
        1350000, 1375000
 };
 
-static const int mc13892_sw[] = {
+static const unsigned int mc13892_sw[] = {
        600000,   625000,  650000,  675000,  700000,  725000,
        750000,   775000,  800000,  825000,  850000,  875000,
        900000,   925000,  950000,  975000, 1000000, 1025000,
@@ -176,65 +176,65 @@ static const int mc13892_sw[] = {
        1800000, 1825000, 1850000, 1875000
 };
 
-static const int mc13892_swbst[] = {
+static const unsigned int mc13892_swbst[] = {
        5000000,
 };
 
-static const int mc13892_viohi[] = {
+static const unsigned int mc13892_viohi[] = {
        2775000,
 };
 
-static const int mc13892_vpll[] = {
+static const unsigned int mc13892_vpll[] = {
        1050000, 1250000, 1650000, 1800000,
 };
 
-static const int mc13892_vdig[] = {
+static const unsigned int mc13892_vdig[] = {
        1050000, 1250000, 1650000, 1800000,
 };
 
-static const int mc13892_vsd[] = {
+static const unsigned int mc13892_vsd[] = {
        1800000, 2000000, 2600000, 2700000,
        2800000, 2900000, 3000000, 3150000,
 };
 
-static const int mc13892_vusb2[] = {
+static const unsigned int mc13892_vusb2[] = {
        2400000, 2600000, 2700000, 2775000,
 };
 
-static const int mc13892_vvideo[] = {
+static const unsigned int mc13892_vvideo[] = {
        2700000, 2775000, 2500000, 2600000,
 };
 
-static const int mc13892_vaudio[] = {
+static const unsigned int mc13892_vaudio[] = {
        2300000, 2500000, 2775000, 3000000,
 };
 
-static const int mc13892_vcam[] = {
+static const unsigned int mc13892_vcam[] = {
        2500000, 2600000, 2750000, 3000000,
 };
 
-static const int mc13892_vgen1[] = {
+static const unsigned int mc13892_vgen1[] = {
        1200000, 1500000, 2775000, 3150000,
 };
 
-static const int mc13892_vgen2[] = {
+static const unsigned int mc13892_vgen2[] = {
        1200000, 1500000, 1600000, 1800000,
        2700000, 2800000, 3000000, 3150000,
 };
 
-static const int mc13892_vgen3[] = {
+static const unsigned int mc13892_vgen3[] = {
        1800000, 2900000,
 };
 
-static const int mc13892_vusb[] = {
+static const unsigned int mc13892_vusb[] = {
        3300000,
 };
 
-static const int mc13892_gpo[] = {
+static const unsigned int mc13892_gpo[] = {
        2750000,
 };
 
-static const int mc13892_pwgtdrv[] = {
+static const unsigned int mc13892_pwgtdrv[] = {
        5000000,
 };
 
@@ -394,7 +394,7 @@ static struct regulator_ops mc13892_gpo_regulator_ops = {
        .enable = mc13892_gpo_regulator_enable,
        .disable = mc13892_gpo_regulator_disable,
        .is_enabled = mc13892_gpo_regulator_is_enabled,
-       .list_voltage = mc13xxx_regulator_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .set_voltage = mc13xxx_fixed_regulator_set_voltage,
        .get_voltage = mc13xxx_fixed_regulator_get_voltage,
 };
@@ -436,7 +436,7 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev,
        u32 valread;
        int ret;
 
-       value = mc13892_regulators[id].voltages[selector];
+       value = rdev->desc->volt_table[selector];
 
        mc13xxx_lock(priv->mc13xxx);
        ret = mc13xxx_reg_read(priv->mc13xxx,
@@ -469,8 +469,7 @@ err:
 }
 
 static struct regulator_ops mc13892_sw_regulator_ops = {
-       .is_enabled = mc13xxx_sw_regulator_is_enabled,
-       .list_voltage = mc13xxx_regulator_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .set_voltage_sel = mc13892_sw_regulator_set_voltage_sel,
        .get_voltage = mc13892_sw_regulator_get_voltage,
 };
index 4fa9704739bc41bb764ece50e58071783501966a..d6eda28ca5d02dbf4f06498a7787d177304d03f0 100644 (file)
@@ -80,20 +80,6 @@ static int mc13xxx_regulator_is_enabled(struct regulator_dev *rdev)
        return (val & mc13xxx_regulators[id].enable_bit) != 0;
 }
 
-int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev,
-                                               unsigned selector)
-{
-       int id = rdev_get_id(rdev);
-       struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
-       struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
-
-       if (selector >= mc13xxx_regulators[id].desc.n_voltages)
-               return -EINVAL;
-
-       return mc13xxx_regulators[id].voltages[selector];
-}
-EXPORT_SYMBOL_GPL(mc13xxx_regulator_list_voltage);
-
 static int mc13xxx_regulator_set_voltage_sel(struct regulator_dev *rdev,
                                             unsigned selector)
 {
@@ -135,14 +121,14 @@ static int mc13xxx_regulator_get_voltage(struct regulator_dev *rdev)
 
        BUG_ON(val >= mc13xxx_regulators[id].desc.n_voltages);
 
-       return mc13xxx_regulators[id].voltages[val];
+       return rdev->desc->volt_table[val];
 }
 
 struct regulator_ops mc13xxx_regulator_ops = {
        .enable = mc13xxx_regulator_enable,
        .disable = mc13xxx_regulator_disable,
        .is_enabled = mc13xxx_regulator_is_enabled,
-       .list_voltage = mc13xxx_regulator_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .set_voltage_sel = mc13xxx_regulator_set_voltage_sel,
        .get_voltage = mc13xxx_regulator_get_voltage,
 };
@@ -151,15 +137,13 @@ EXPORT_SYMBOL_GPL(mc13xxx_regulator_ops);
 int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, int min_uV,
               int max_uV, unsigned *selector)
 {
-       struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
-       struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
        int id = rdev_get_id(rdev);
 
        dev_dbg(rdev_get_dev(rdev), "%s id: %d min_uV: %d max_uV: %d\n",
                __func__, id, min_uV, max_uV);
 
-       if (min_uV >= mc13xxx_regulators[id].voltages[0] &&
-           max_uV <= mc13xxx_regulators[id].voltages[0])
+       if (min_uV <= rdev->desc->volt_table[0] &&
+           rdev->desc->volt_table[0] <= max_uV)
                return 0;
        else
                return -EINVAL;
@@ -168,13 +152,11 @@ EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_set_voltage);
 
 int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev)
 {
-       struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev);
-       struct mc13xxx_regulator *mc13xxx_regulators = priv->mc13xxx_regulators;
        int id = rdev_get_id(rdev);
 
        dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id);
 
-       return mc13xxx_regulators[id].voltages[0];
+       return rdev->desc->volt_table[0];
 }
 EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_get_voltage);
 
@@ -182,18 +164,12 @@ struct regulator_ops mc13xxx_fixed_regulator_ops = {
        .enable = mc13xxx_regulator_enable,
        .disable = mc13xxx_regulator_disable,
        .is_enabled = mc13xxx_regulator_is_enabled,
-       .list_voltage = mc13xxx_regulator_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .set_voltage = mc13xxx_fixed_regulator_set_voltage,
        .get_voltage = mc13xxx_fixed_regulator_get_voltage,
 };
 EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops);
 
-int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev)
-{
-       return 1;
-}
-EXPORT_SYMBOL_GPL(mc13xxx_sw_regulator_is_enabled);
-
 #ifdef CONFIG_OF
 int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
 {
index 044aba4d28eca99f952207adf15e4b382b2c9f96..eaff5510b6df62cc6096c1e6683a4601cdb50240 100644 (file)
@@ -22,7 +22,6 @@ struct mc13xxx_regulator {
        int vsel_shift;
        int vsel_mask;
        int hi_bit;
-       int const *voltages;
 };
 
 struct mc13xxx_regulator_priv {
@@ -33,10 +32,6 @@ struct mc13xxx_regulator_priv {
        struct regulator_dev *regulators[];
 };
 
-extern int mc13xxx_sw_regulator(struct regulator_dev *rdev);
-extern int mc13xxx_sw_regulator_is_enabled(struct regulator_dev *rdev);
-extern int mc13xxx_regulator_list_voltage(struct regulator_dev *rdev,
-                                               unsigned selector);
 extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev,
                int min_uV, int max_uV, unsigned *selector);
 extern int mc13xxx_fixed_regulator_get_voltage(struct regulator_dev *rdev);
@@ -68,6 +63,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
                .desc = {                                               \
                        .name = #_name,                                 \
                        .n_voltages = ARRAY_SIZE(_voltages),            \
+                       .volt_table =  _voltages,                       \
                        .ops = &_ops,                   \
                        .type = REGULATOR_VOLTAGE,                      \
                        .id = prefix ## _name,          \
@@ -78,7 +74,6 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
                .vsel_reg = prefix ## _vsel_reg,                        \
                .vsel_shift = prefix ## _vsel_reg ## _ ## _name ## VSEL,\
                .vsel_mask = prefix ## _vsel_reg ## _ ## _name ## VSEL_M,\
-               .voltages =  _voltages,                                 \
        }
 
 #define MC13xxx_FIXED_DEFINE(prefix, _name, _reg, _voltages, _ops)     \
@@ -86,6 +81,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
                .desc = {                                               \
                        .name = #_name,                                 \
                        .n_voltages = ARRAY_SIZE(_voltages),            \
+                       .volt_table =  _voltages,                       \
                        .ops = &_ops,           \
                        .type = REGULATOR_VOLTAGE,                      \
                        .id = prefix ## _name,          \
@@ -93,7 +89,6 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
                },                                                      \
                .reg = prefix ## _reg,                          \
                .enable_bit = prefix ## _reg ## _ ## _name ## EN,       \
-               .voltages =  _voltages,                                 \
        }
 
 #define MC13xxx_GPO_DEFINE(prefix, _name, _reg,  _voltages, _ops)      \
@@ -101,6 +96,7 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
                .desc = {                                               \
                        .name = #_name,                                 \
                        .n_voltages = ARRAY_SIZE(_voltages),            \
+                       .volt_table =  _voltages,                       \
                        .ops = &_ops,           \
                        .type = REGULATOR_VOLTAGE,                      \
                        .id = prefix ## _name,          \
@@ -108,7 +104,6 @@ extern struct regulator_ops mc13xxx_fixed_regulator_ops;
                },                                                      \
                .reg = prefix ## _reg,                          \
                .enable_bit = prefix ## _reg ## _ ## _name ## EN,       \
-               .voltages =  _voltages,                                 \
        }
 
 #define MC13xxx_DEFINE_SW(_name, _reg, _vsel_reg, _voltages, ops)      \
index 56593b75168a28e830946201778cd1937f08a724..3e4106f2bda90ccfa6dc7da80380f314bb5189d8 100644 (file)
@@ -20,7 +20,7 @@ static void of_get_regulation_constraints(struct device_node *np,
                                        struct regulator_init_data **init_data)
 {
        const __be32 *min_uV, *max_uV, *uV_offset;
-       const __be32 *min_uA, *max_uA;
+       const __be32 *min_uA, *max_uA, *ramp_delay;
        struct regulation_constraints *constraints = &(*init_data)->constraints;
 
        constraints->name = of_get_property(np, "regulator-name", NULL);
@@ -60,6 +60,10 @@ static void of_get_regulation_constraints(struct device_node *np,
                constraints->always_on = true;
        else /* status change should be possible if not always on. */
                constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS;
+
+       ramp_delay = of_get_property(np, "regulator-ramp-delay", NULL);
+       if (ramp_delay)
+               constraints->ramp_delay = be32_to_cpu(*ramp_delay);
 }
 
 /**
@@ -88,15 +92,17 @@ struct regulator_init_data *of_get_regulator_init_data(struct device *dev,
 EXPORT_SYMBOL_GPL(of_get_regulator_init_data);
 
 /**
- * of_regulator_match - extract regulator init data
+ * of_regulator_match - extract regulator init data when node
+ * property "regulator-compatible" matches with the regulator name.
  * @dev: device requesting the data
  * @node: parent device node of the regulators
  * @matches: match table for the regulators
  * @num_matches: number of entries in match table
  *
  * This function uses a match table specified by the regulator driver and
- * looks up the corresponding init data in the device tree. Note that the
- * match table is modified in place.
+ * looks up the corresponding init data in the device tree  if
+ * regulator-compatible matches. Note that the match table is modified
+ * in place.
  *
  * Returns the number of matches found or a negative error code on failure.
  */
@@ -106,27 +112,40 @@ int of_regulator_match(struct device *dev, struct device_node *node,
 {
        unsigned int count = 0;
        unsigned int i;
+       const char *regulator_comp;
+       struct device_node *child;
 
        if (!dev || !node)
                return -EINVAL;
 
-       for (i = 0; i < num_matches; i++) {
-               struct of_regulator_match *match = &matches[i];
-               struct device_node *child;
-
-               child = of_find_node_by_name(node, match->name);
-               if (!child)
-                       continue;
-
-               match->init_data = of_get_regulator_init_data(dev, child);
-               if (!match->init_data) {
-                       dev_err(dev, "failed to parse DT for regulator %s\n",
+       for_each_child_of_node(node, child) {
+               regulator_comp = of_get_property(child,
+                                       "regulator-compatible", NULL);
+               if (!regulator_comp) {
+                       dev_err(dev, "regulator-compatible is missing for node %s\n",
                                child->name);
-                       return -EINVAL;
+                       continue;
+               }
+               for (i = 0; i < num_matches; i++) {
+                       struct of_regulator_match *match = &matches[i];
+                       if (match->of_node)
+                               continue;
+
+                       if (strcmp(match->name, regulator_comp))
+                               continue;
+
+                       match->init_data =
+                               of_get_regulator_init_data(dev, child);
+                       if (!match->init_data) {
+                               dev_err(dev,
+                                       "failed to parse DT for regulator %s\n",
+                                       child->name);
+                               return -EINVAL;
+                       }
+                       match->of_node = child;
+                       count++;
+                       break;
                }
-
-               match->of_node = child;
-               count++;
        }
 
        return count;
index 795f75a6ac3342537a18600e2d0414b1f011caaf..17d19fbbc490156c8507301808863411a5f3135f 100644 (file)
@@ -257,8 +257,7 @@ static int palmas_set_mode_smps(struct regulator_dev *dev, unsigned int mode)
        unsigned int reg;
 
        palmas_smps_read(pmic->palmas, palmas_regs_info[id].ctrl_addr, &reg);
-       reg &= ~PALMAS_SMPS12_CTRL_STATUS_MASK;
-       reg >>= PALMAS_SMPS12_CTRL_STATUS_SHIFT;
+       reg &= ~PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
 
        switch (mode) {
        case REGULATOR_MODE_NORMAL:
@@ -374,11 +373,22 @@ static int palmas_set_voltage_smps_sel(struct regulator_dev *dev,
 static int palmas_map_voltage_smps(struct regulator_dev *rdev,
                int min_uV, int max_uV)
 {
+       struct palmas_pmic *pmic = rdev_get_drvdata(rdev);
+       int id = rdev_get_id(rdev);
        int ret, voltage;
 
-       ret = ((min_uV - 500000) / 10000) + 1;
-       if (ret < 0)
-               return ret;
+       if (min_uV == 0)
+               return 0;
+
+       if (pmic->range[id]) { /* RANGE is x2 */
+               if (min_uV < 1000000)
+                       min_uV = 1000000;
+               ret = DIV_ROUND_UP(min_uV - 1000000, 20000) + 1;
+       } else {                /* RANGE is x1 */
+               if (min_uV < 500000)
+                       min_uV = 500000;
+               ret = DIV_ROUND_UP(min_uV - 500000, 10000) + 1;
+       }
 
        /* Map back into a voltage to verify we're still in bounds */
        voltage = palmas_list_voltage_smps(rdev, ret);
@@ -400,19 +410,14 @@ static struct regulator_ops palmas_ops_smps = {
        .map_voltage            = palmas_map_voltage_smps,
 };
 
-static int palmas_list_voltage_smps10(struct regulator_dev *dev,
-                                       unsigned selector)
-{
-       return 3750000 + (selector * 1250000);
-}
-
 static struct regulator_ops palmas_ops_smps10 = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
        .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
-       .list_voltage           = palmas_list_voltage_smps10,
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
 };
 
 static int palmas_is_enabled_ldo(struct regulator_dev *dev)
@@ -522,7 +527,15 @@ static int palmas_smps_init(struct palmas *palmas, int id,
        if (ret)
                return ret;
 
-       if (id != PALMAS_REG_SMPS10) {
+       switch (id) {
+       case PALMAS_REG_SMPS10:
+               if (reg_init->mode_sleep) {
+                       reg &= ~PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK;
+                       reg |= reg_init->mode_sleep <<
+                                       PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT;
+               }
+               break;
+       default:
                if (reg_init->warm_reset)
                        reg |= PALMAS_SMPS12_CTRL_WR_S;
 
@@ -534,14 +547,8 @@ static int palmas_smps_init(struct palmas *palmas, int id,
                        reg |= reg_init->mode_sleep <<
                                        PALMAS_SMPS12_CTRL_MODE_SLEEP_SHIFT;
                }
-       } else {
-               if (reg_init->mode_sleep) {
-                       reg &= ~PALMAS_SMPS10_CTRL_MODE_SLEEP_MASK;
-                       reg |= reg_init->mode_sleep <<
-                                       PALMAS_SMPS10_CTRL_MODE_SLEEP_SHIFT;
-               }
-
        }
+
        ret = palmas_smps_write(palmas, addr, reg);
        if (ret)
                return ret;
@@ -665,10 +672,8 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                pmic->desc[id].name = palmas_regs_info[id].name;
                pmic->desc[id].id = id;
 
-               if (id != PALMAS_REG_SMPS10) {
-                       pmic->desc[id].ops = &palmas_ops_smps;
-                       pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
-               } else {
+               switch (id) {
+               case PALMAS_REG_SMPS10:
                        pmic->desc[id].n_voltages = PALMAS_SMPS10_NUM_VOLTAGES;
                        pmic->desc[id].ops = &palmas_ops_smps10;
                        pmic->desc[id].vsel_reg = PALMAS_SMPS10_CTRL;
@@ -677,6 +682,12 @@ static __devinit int palmas_probe(struct platform_device *pdev)
                                        PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
                                                        PALMAS_SMPS10_STATUS);
                        pmic->desc[id].enable_mask = SMPS10_BOOST_EN;
+                       pmic->desc[id].min_uV = 3750000;
+                       pmic->desc[id].uV_step = 1250000;
+                       break;
+               default:
+                       pmic->desc[id].ops = &palmas_ops_smps;
+                       pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
                }
 
                pmic->desc[id].type = REGULATOR_VOLTAGE;
index 8211101121f0c6a07b68184db5bb95bbd53d7e73..68777acc099fb6da2d0d4f1428b11ef1d704f9a3 100644 (file)
 #include <linux/regulator/machine.h>
 #include <linux/mfd/ezx-pcap.h>
 
-static const u16 V1_table[] = {
-       2775, 1275, 1600, 1725, 1825, 1925, 2075, 2275,
+static const unsigned int V1_table[] = {
+       2775000, 1275000, 1600000, 1725000, 1825000, 1925000, 2075000, 2275000,
 };
 
-static const u16 V2_table[] = {
-       2500, 2775,
+static const unsigned int V2_table[] = {
+       2500000, 2775000,
 };
 
-static const u16 V3_table[] = {
-       1075, 1275, 1550, 1725, 1876, 1950, 2075, 2275,
+static const unsigned int V3_table[] = {
+       1075000, 1275000, 1550000, 1725000, 1876000, 1950000, 2075000, 2275000,
 };
 
-static const u16 V4_table[] = {
-       1275, 1550, 1725, 1875, 1950, 2075, 2275, 2775,
+static const unsigned int V4_table[] = {
+       1275000, 1550000, 1725000, 1875000, 1950000, 2075000, 2275000, 2775000,
 };
 
-static const u16 V5_table[] = {
-       1875, 2275, 2475, 2775,
+static const unsigned int V5_table[] = {
+       1875000, 2275000, 2475000, 2775000,
 };
 
-static const u16 V6_table[] = {
-       2475, 2775,
+static const unsigned int V6_table[] = {
+       2475000, 2775000,
 };
 
-static const u16 V7_table[] = {
-       1875, 2775,
+static const unsigned int V7_table[] = {
+       1875000, 2775000,
 };
 
 #define V8_table V4_table
 
-static const u16 V9_table[] = {
-       1575, 1875, 2475, 2775,
+static const unsigned int V9_table[] = {
+       1575000, 1875000, 2475000, 2775000,
 };
 
-static const u16 V10_table[] = {
-       5000,
+static const unsigned int V10_table[] = {
+       5000000,
 };
 
-static const u16 VAUX1_table[] = {
-       1875, 2475, 2775, 3000,
+static const unsigned int VAUX1_table[] = {
+       1875000, 2475000, 2775000, 3000000,
 };
 
 #define VAUX2_table VAUX1_table
 
-static const u16 VAUX3_table[] = {
-       1200, 1200, 1200, 1200, 1400, 1600, 1800, 2000,
-       2200, 2400, 2600, 2800, 3000, 3200, 3400, 3600,
+static const unsigned int VAUX3_table[] = {
+       1200000, 1200000, 1200000, 1200000, 1400000, 1600000, 1800000, 2000000,
+       2200000, 2400000, 2600000, 2800000, 3000000, 3200000, 3400000, 3600000,
 };
 
-static const u16 VAUX4_table[] = {
-       1800, 1800, 3000, 5000,
+static const unsigned int VAUX4_table[] = {
+       1800000, 1800000, 3000000, 5000000,
 };
 
-static const u16 VSIM_table[] = {
-       1875, 3000,
+static const unsigned int VSIM_table[] = {
+       1875000, 3000000,
 };
 
-static const u16 VSIM2_table[] = {
-       1875,
+static const unsigned int VSIM2_table[] = {
+       1875000,
 };
 
-static const u16 VVIB_table[] = {
-       1300, 1800, 2000, 3000,
+static const unsigned int VVIB_table[] = {
+       1300000, 1800000, 2000000, 3000000,
 };
 
-static const u16 SW1_table[] = {
-       900, 950, 1000, 1050, 1100, 1150, 1200, 1250,
-       1300, 1350, 1400, 1450, 1500, 1600, 1875, 2250,
+static const unsigned int SW1_table[] = {
+        900000,  950000, 1000000, 1050000, 1100000, 1150000, 1200000, 1250000,
+       1300000, 1350000, 1400000, 1450000, 1500000, 1600000, 1875000, 2250000,
 };
 
 #define SW2_table SW1_table
 
-static const u16 SW3_table[] = {
-       4000, 4500, 5000, 5500,
+static const unsigned int SW3_table[] = {
+       4000000, 4500000, 5000000, 5500000,
 };
 
 struct pcap_regulator {
@@ -100,8 +100,6 @@ struct pcap_regulator {
        const u8 index;
        const u8 stby;
        const u8 lowpwr;
-       const u8 n_voltages;
-       const u16 *voltage_table;
 };
 
 #define NA 0xff
@@ -113,8 +111,6 @@ struct pcap_regulator {
                .index          = _index,                               \
                .stby           = _stby,                                \
                .lowpwr         = _lowpwr,                              \
-               .n_voltages     = ARRAY_SIZE(_vreg##_table),            \
-               .voltage_table  = _vreg##_table,                        \
        }
 
 static struct pcap_regulator vreg_table[] = {
@@ -157,11 +153,11 @@ static int pcap_regulator_set_voltage_sel(struct regulator_dev *rdev,
        void *pcap = rdev_get_drvdata(rdev);
 
        /* the regulator doesn't support voltage switching */
-       if (vreg->n_voltages == 1)
+       if (rdev->desc->n_voltages == 1)
                return -EINVAL;
 
        return ezx_pcap_set_bits(pcap, vreg->reg,
-                                (vreg->n_voltages - 1) << vreg->index,
+                                (rdev->desc->n_voltages - 1) << vreg->index,
                                 selector << vreg->index);
 }
 
@@ -171,11 +167,11 @@ static int pcap_regulator_get_voltage_sel(struct regulator_dev *rdev)
        void *pcap = rdev_get_drvdata(rdev);
        u32 tmp;
 
-       if (vreg->n_voltages == 1)
+       if (rdev->desc->n_voltages == 1)
                return 0;
 
        ezx_pcap_read(pcap, vreg->reg, &tmp);
-       tmp = ((tmp >> vreg->index) & (vreg->n_voltages - 1));
+       tmp = ((tmp >> vreg->index) & (rdev->desc->n_voltages - 1));
        return tmp;
 }
 
@@ -214,16 +210,8 @@ static int pcap_regulator_is_enabled(struct regulator_dev *rdev)
        return (tmp >> vreg->en) & 1;
 }
 
-static int pcap_regulator_list_voltage(struct regulator_dev *rdev,
-                                                       unsigned int index)
-{
-       struct pcap_regulator *vreg = &vreg_table[rdev_get_id(rdev)];
-
-       return vreg->voltage_table[index] * 1000;
-}
-
 static struct regulator_ops pcap_regulator_ops = {
-       .list_voltage   = pcap_regulator_list_voltage,
+       .list_voltage   = regulator_list_voltage_table,
        .set_voltage_sel = pcap_regulator_set_voltage_sel,
        .get_voltage_sel = pcap_regulator_get_voltage_sel,
        .enable         = pcap_regulator_enable,
@@ -236,6 +224,7 @@ static struct regulator_ops pcap_regulator_ops = {
                .name           = #_vreg,                       \
                .id             = _vreg,                        \
                .n_voltages     = ARRAY_SIZE(_vreg##_table),    \
+               .volt_table     = _vreg##_table,                \
                .ops            = &pcap_regulator_ops,          \
                .type           = REGULATOR_VOLTAGE,            \
                .owner          = THIS_MODULE,                  \
index 3c9d14c0017bba05c5c770dea4478c51b60f533e..092e5cb848a1e3b0e30736bf6fe08823220f77aa 100644 (file)
@@ -100,13 +100,12 @@ static unsigned int ldo_voltage_value(u8 bits)
        return 900 + (bits * 100);
 }
 
-static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
-                                         int min_uV, int max_uV,
-                                         unsigned *selector)
+static int pcf50633_regulator_map_voltage(struct regulator_dev *rdev,
+                                         int min_uV, int max_uV)
 {
        struct pcf50633 *pcf;
        int regulator_id, millivolts;
-       u8 volt_bits, regnr;
+       u8 volt_bits;
 
        pcf = rdev_get_drvdata(rdev);
 
@@ -116,15 +115,11 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
 
        millivolts = min_uV / 1000;
 
-       regnr = rdev->desc->vsel_reg;
-
        switch (regulator_id) {
        case PCF50633_REGULATOR_AUTO:
                volt_bits = auto_voltage_bits(millivolts);
                break;
        case PCF50633_REGULATOR_DOWN1:
-               volt_bits = down_voltage_bits(millivolts);
-               break;
        case PCF50633_REGULATOR_DOWN2:
                volt_bits = down_voltage_bits(millivolts);
                break;
@@ -142,9 +137,7 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev,
                return -EINVAL;
        }
 
-       *selector = volt_bits;
-
-       return pcf50633_reg_write(pcf, regnr, volt_bits);
+       return volt_bits;
 }
 
 static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
@@ -159,8 +152,6 @@ static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
                millivolts = auto_voltage_value(index);
                break;
        case PCF50633_REGULATOR_DOWN1:
-               millivolts = down_voltage_value(index);
-               break;
        case PCF50633_REGULATOR_DOWN2:
                millivolts = down_voltage_value(index);
                break;
@@ -182,9 +173,10 @@ static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev,
 }
 
 static struct regulator_ops pcf50633_regulator_ops = {
-       .set_voltage = pcf50633_regulator_set_voltage,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
        .list_voltage = pcf50633_regulator_list_voltage,
+       .map_voltage = pcf50633_regulator_map_voltage,
        .enable = regulator_enable_regmap,
        .disable = regulator_disable_regmap,
        .is_enabled = regulator_is_enabled_regmap,
index 1d34e64a1307ac3b1e6fd9edb0ad47395aee56ef..8bf4e8c9de9a2a811622ff0e8986a8fea9de2735 100644 (file)
@@ -42,7 +42,6 @@ struct rc5t583_regulator_info {
 
        /* Regulator specific turn-on delay  and voltage settling time*/
        int                     enable_uv_per_us;
-       int                     change_uv_per_us;
 
        /* Used by regulator core */
        struct regulator_desc   desc;
@@ -66,25 +65,6 @@ static int rc5t583_regulator_enable_time(struct regulator_dev *rdev)
        return DIV_ROUND_UP(curr_uV, reg->reg_info->enable_uv_per_us);
 }
 
-static int rc5t583_set_voltage_time_sel(struct regulator_dev *rdev,
-               unsigned int old_selector, unsigned int new_selector)
-{
-       struct rc5t583_regulator *reg = rdev_get_drvdata(rdev);
-       int old_uV, new_uV;
-       old_uV = regulator_list_voltage_linear(rdev, old_selector);
-
-       if (old_uV < 0)
-               return old_uV;
-
-       new_uV = regulator_list_voltage_linear(rdev, new_selector);
-       if (new_uV < 0)
-               return new_uV;
-
-       return DIV_ROUND_UP(abs(old_uV - new_uV),
-                               reg->reg_info->change_uv_per_us);
-}
-
-
 static struct regulator_ops rc5t583_ops = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
@@ -94,7 +74,7 @@ static struct regulator_ops rc5t583_ops = {
        .set_voltage_sel        = regulator_set_voltage_sel_regmap,
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
-       .set_voltage_time_sel   = rc5t583_set_voltage_time_sel,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
 };
 
 #define RC5T583_REG(_id, _en_reg, _en_bit, _disc_reg, _disc_bit, \
@@ -104,7 +84,6 @@ static struct regulator_ops rc5t583_ops = {
        .disc_bit       = _disc_bit,                            \
        .deepsleep_reg  = RC5T583_REG_##_id##DAC_DS,            \
        .enable_uv_per_us = _enable_mv * 1000,                  \
-       .change_uv_per_us = 40 * 1000,                          \
        .deepsleep_id   = RC5T583_DS_##_id,                     \
        .desc = {                                               \
                .name = "rc5t583-regulator-"#_id,               \
@@ -119,6 +98,7 @@ static struct regulator_ops rc5t583_ops = {
                .enable_mask = BIT(_en_bit),                    \
                .min_uV = _min_mv * 1000,                       \
                .uV_step = _step_uV,                            \
+               .ramp_delay = 40 * 1000,                        \
        },                                                      \
 }
 
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
new file mode 100644 (file)
index 0000000..4669dc9
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * s2mps11.c
+ *
+ * Copyright (c) 2012 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 as published by the
+ *  Free Software Foundation;  either version 2 of the  License, or (at your
+ *  option) any later version.
+ *
+ */
+
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/samsung/core.h>
+#include <linux/mfd/samsung/s2mps11.h>
+
+struct s2mps11_info {
+       struct regulator_dev **rdev;
+
+       int ramp_delay2;
+       int ramp_delay34;
+       int ramp_delay5;
+       int ramp_delay16;
+       int ramp_delay7810;
+       int ramp_delay9;
+
+       bool buck6_ramp;
+       bool buck2_ramp;
+       bool buck3_ramp;
+       bool buck4_ramp;
+};
+
+static int get_ramp_delay(int ramp_delay)
+{
+       unsigned char cnt = 0;
+
+       ramp_delay /= 6;
+
+       while (true) {
+               ramp_delay = ramp_delay >> 1;
+               if (ramp_delay == 0)
+                       break;
+               cnt++;
+       }
+       return cnt;
+}
+
+static struct regulator_ops s2mps11_ldo_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+};
+
+static struct regulator_ops s2mps11_buck_ops = {
+       .list_voltage           = regulator_list_voltage_linear,
+       .map_voltage            = regulator_map_voltage_linear,
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+};
+
+#define regulator_desc_ldo1(num)       {               \
+       .name           = "LDO"#num,                    \
+       .id             = S2MPS11_LDO##num,             \
+       .ops            = &s2mps11_ldo_ops,             \
+       .type           = REGULATOR_VOLTAGE,            \
+       .owner          = THIS_MODULE,                  \
+       .min_uV         = S2MPS11_LDO_MIN,              \
+       .uV_step        = S2MPS11_LDO_STEP1,            \
+       .n_voltages     = S2MPS11_LDO_N_VOLTAGES,       \
+       .vsel_reg       = S2MPS11_REG_L1CTRL + num - 1, \
+       .vsel_mask      = S2MPS11_LDO_VSEL_MASK,        \
+       .enable_reg     = S2MPS11_REG_L1CTRL + num - 1, \
+       .enable_mask    = S2MPS11_ENABLE_MASK           \
+}
+#define regulator_desc_ldo2(num)       {               \
+       .name           = "LDO"#num,                    \
+       .id             = S2MPS11_LDO##num,             \
+       .ops            = &s2mps11_ldo_ops,             \
+       .type           = REGULATOR_VOLTAGE,            \
+       .owner          = THIS_MODULE,                  \
+       .min_uV         = S2MPS11_LDO_MIN,              \
+       .uV_step        = S2MPS11_LDO_STEP2,            \
+       .n_voltages     = S2MPS11_LDO_N_VOLTAGES,       \
+       .vsel_reg       = S2MPS11_REG_L1CTRL + num - 1, \
+       .vsel_mask      = S2MPS11_LDO_VSEL_MASK,        \
+       .enable_reg     = S2MPS11_REG_L1CTRL + num - 1, \
+       .enable_mask    = S2MPS11_ENABLE_MASK           \
+}
+
+#define regulator_desc_buck1_4(num)    {                       \
+       .name           = "BUCK"#num,                           \
+       .id             = S2MPS11_BUCK##num,                    \
+       .ops            = &s2mps11_buck_ops,                    \
+       .type           = REGULATOR_VOLTAGE,                    \
+       .owner          = THIS_MODULE,                          \
+       .min_uV         = S2MPS11_BUCK_MIN1,                    \
+       .uV_step        = S2MPS11_BUCK_STEP1,                   \
+       .n_voltages     = S2MPS11_BUCK_N_VOLTAGES,              \
+       .vsel_reg       = S2MPS11_REG_B1CTRL2 + (num - 1) * 2,  \
+       .vsel_mask      = S2MPS11_BUCK_VSEL_MASK,               \
+       .enable_reg     = S2MPS11_REG_B1CTRL1 + (num - 1) * 2,  \
+       .enable_mask    = S2MPS11_ENABLE_MASK                   \
+}
+
+#define regulator_desc_buck5   {                               \
+       .name           = "BUCK5",                              \
+       .id             = S2MPS11_BUCK5,                        \
+       .ops            = &s2mps11_buck_ops,                    \
+       .type           = REGULATOR_VOLTAGE,                    \
+       .owner          = THIS_MODULE,                          \
+       .min_uV         = S2MPS11_BUCK_MIN1,                    \
+       .uV_step        = S2MPS11_BUCK_STEP1,                   \
+       .n_voltages     = S2MPS11_BUCK_N_VOLTAGES,              \
+       .vsel_reg       = S2MPS11_REG_B5CTRL2,                  \
+       .vsel_mask      = S2MPS11_BUCK_VSEL_MASK,               \
+       .enable_reg     = S2MPS11_REG_B5CTRL1,                  \
+       .enable_mask    = S2MPS11_ENABLE_MASK                   \
+}
+
+#define regulator_desc_buck6_8(num)    {                       \
+       .name           = "BUCK"#num,                           \
+       .id             = S2MPS11_BUCK##num,                    \
+       .ops            = &s2mps11_buck_ops,                    \
+       .type           = REGULATOR_VOLTAGE,                    \
+       .owner          = THIS_MODULE,                          \
+       .min_uV         = S2MPS11_BUCK_MIN1,                    \
+       .uV_step        = S2MPS11_BUCK_STEP1,                   \
+       .n_voltages     = S2MPS11_BUCK_N_VOLTAGES,              \
+       .vsel_reg       = S2MPS11_REG_B6CTRL2 + (num - 6) * 2,  \
+       .vsel_mask      = S2MPS11_BUCK_VSEL_MASK,               \
+       .enable_reg     = S2MPS11_REG_B6CTRL1 + (num - 6) * 2,  \
+       .enable_mask    = S2MPS11_ENABLE_MASK                   \
+}
+
+#define regulator_desc_buck9   {                               \
+       .name           = "BUCK9",                              \
+       .id             = S2MPS11_BUCK9,                        \
+       .ops            = &s2mps11_buck_ops,                    \
+       .type           = REGULATOR_VOLTAGE,                    \
+       .owner          = THIS_MODULE,                          \
+       .min_uV         = S2MPS11_BUCK_MIN3,                    \
+       .uV_step        = S2MPS11_BUCK_STEP3,                   \
+       .n_voltages     = S2MPS11_BUCK_N_VOLTAGES,              \
+       .vsel_reg       = S2MPS11_REG_B9CTRL2,                  \
+       .vsel_mask      = S2MPS11_BUCK_VSEL_MASK,               \
+       .enable_reg     = S2MPS11_REG_B9CTRL1,                  \
+       .enable_mask    = S2MPS11_ENABLE_MASK                   \
+}
+
+#define regulator_desc_buck10  {                               \
+       .name           = "BUCK10",                             \
+       .id             = S2MPS11_BUCK10,                       \
+       .ops            = &s2mps11_buck_ops,                    \
+       .type           = REGULATOR_VOLTAGE,                    \
+       .owner          = THIS_MODULE,                          \
+       .min_uV         = S2MPS11_BUCK_MIN2,                    \
+       .uV_step        = S2MPS11_BUCK_STEP2,                   \
+       .n_voltages     = S2MPS11_BUCK_N_VOLTAGES,              \
+       .vsel_reg       = S2MPS11_REG_B9CTRL2,                  \
+       .vsel_mask      = S2MPS11_BUCK_VSEL_MASK,               \
+       .enable_reg     = S2MPS11_REG_B9CTRL1,                  \
+       .enable_mask    = S2MPS11_ENABLE_MASK                   \
+}
+
+static struct regulator_desc regulators[] = {
+       regulator_desc_ldo2(1),
+       regulator_desc_ldo1(2),
+       regulator_desc_ldo1(3),
+       regulator_desc_ldo1(4),
+       regulator_desc_ldo1(5),
+       regulator_desc_ldo2(6),
+       regulator_desc_ldo1(7),
+       regulator_desc_ldo1(8),
+       regulator_desc_ldo1(9),
+       regulator_desc_ldo1(10),
+       regulator_desc_ldo2(11),
+       regulator_desc_ldo1(12),
+       regulator_desc_ldo1(13),
+       regulator_desc_ldo1(14),
+       regulator_desc_ldo1(15),
+       regulator_desc_ldo1(16),
+       regulator_desc_ldo1(17),
+       regulator_desc_ldo1(18),
+       regulator_desc_ldo1(19),
+       regulator_desc_ldo1(20),
+       regulator_desc_ldo1(21),
+       regulator_desc_ldo2(22),
+       regulator_desc_ldo2(23),
+       regulator_desc_ldo1(24),
+       regulator_desc_ldo1(25),
+       regulator_desc_ldo1(26),
+       regulator_desc_ldo2(27),
+       regulator_desc_ldo1(28),
+       regulator_desc_ldo1(29),
+       regulator_desc_ldo1(30),
+       regulator_desc_ldo1(31),
+       regulator_desc_ldo1(32),
+       regulator_desc_ldo1(33),
+       regulator_desc_ldo1(34),
+       regulator_desc_ldo1(35),
+       regulator_desc_ldo1(36),
+       regulator_desc_ldo1(37),
+       regulator_desc_ldo1(38),
+       regulator_desc_buck1_4(1),
+       regulator_desc_buck1_4(2),
+       regulator_desc_buck1_4(3),
+       regulator_desc_buck1_4(4),
+       regulator_desc_buck5,
+       regulator_desc_buck6_8(6),
+       regulator_desc_buck6_8(7),
+       regulator_desc_buck6_8(8),
+       regulator_desc_buck9,
+       regulator_desc_buck10,
+};
+
+static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
+{
+       struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+       struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
+       struct regulator_config config = { };
+       struct regulator_dev **rdev;
+       struct s2mps11_info *s2mps11;
+       int i, ret, size;
+       unsigned char ramp_enable, ramp_reg = 0;
+
+       if (!pdata) {
+               dev_err(pdev->dev.parent, "Platform data not supplied\n");
+               return -ENODEV;
+       }
+
+       s2mps11 = devm_kzalloc(&pdev->dev, sizeof(struct s2mps11_info),
+                               GFP_KERNEL);
+       if (!s2mps11)
+               return -ENOMEM;
+
+       size = sizeof(struct regulator_dev *) * S2MPS11_REGULATOR_MAX;
+       s2mps11->rdev = devm_kzalloc(&pdev->dev, size, GFP_KERNEL);
+       if (!s2mps11->rdev) {
+               return -ENOMEM;
+       }
+
+       rdev = s2mps11->rdev;
+       platform_set_drvdata(pdev, s2mps11);
+
+       s2mps11->ramp_delay2 = pdata->buck2_ramp_delay;
+       s2mps11->ramp_delay34 = pdata->buck34_ramp_delay;
+       s2mps11->ramp_delay5 = pdata->buck5_ramp_delay;
+       s2mps11->ramp_delay16 = pdata->buck16_ramp_delay;
+       s2mps11->ramp_delay7810 = pdata->buck7810_ramp_delay;
+       s2mps11->ramp_delay9 = pdata->buck9_ramp_delay;
+
+       s2mps11->buck6_ramp = pdata->buck6_ramp_enable;
+       s2mps11->buck2_ramp = pdata->buck2_ramp_enable;
+       s2mps11->buck3_ramp = pdata->buck3_ramp_enable;
+       s2mps11->buck4_ramp = pdata->buck4_ramp_enable;
+
+       ramp_enable = (s2mps11->buck2_ramp << 3) | (s2mps11->buck3_ramp << 2) |
+               (s2mps11->buck4_ramp << 1) | s2mps11->buck6_ramp ;
+
+       if (ramp_enable) {
+               if (s2mps11->buck2_ramp)
+                       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay2) >> 6;
+               if (s2mps11->buck3_ramp || s2mps11->buck4_ramp)
+                       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay34) >> 4;
+               sec_reg_write(iodev, S2MPS11_REG_RAMP, ramp_reg | ramp_enable);
+       }
+
+       ramp_reg &= 0x00;
+       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay5) >> 6;
+       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay16) >> 4;
+       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay7810) >> 2;
+       ramp_reg |= get_ramp_delay(s2mps11->ramp_delay9);
+       sec_reg_write(iodev, S2MPS11_REG_RAMP_BUCK, ramp_reg);
+
+       for (i = 0; i < S2MPS11_REGULATOR_MAX; i++) {
+
+               config.dev = &pdev->dev;
+               config.regmap = iodev->regmap;
+               config.init_data = pdata->regulators[i].initdata;
+               config.driver_data = s2mps11;
+
+               rdev[i] = regulator_register(&regulators[i], &config);
+               if (IS_ERR(rdev[i])) {
+                       ret = PTR_ERR(rdev[i]);
+                       dev_err(&pdev->dev, "regulator init failed for %d\n",
+                               i);
+                       rdev[i] = NULL;
+                       goto err;
+               }
+       }
+
+       return 0;
+err:
+       for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
+               if (rdev[i])
+                       regulator_unregister(rdev[i]);
+
+       return ret;
+}
+
+static int __devexit s2mps11_pmic_remove(struct platform_device *pdev)
+{
+       struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
+       struct regulator_dev **rdev = s2mps11->rdev;
+       int i;
+
+       for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
+               if (rdev[i])
+                       regulator_unregister(rdev[i]);
+
+       return 0;
+}
+
+static const struct platform_device_id s2mps11_pmic_id[] = {
+       { "s2mps11-pmic", 0},
+       { },
+};
+MODULE_DEVICE_TABLE(platform, s2mps11_pmic_id);
+
+static struct platform_driver s2mps11_pmic_driver = {
+       .driver = {
+               .name = "s2mps11-pmic",
+               .owner = THIS_MODULE,
+       },
+       .probe = s2mps11_pmic_probe,
+       .remove = __devexit_p(s2mps11_pmic_remove),
+       .id_table = s2mps11_pmic_id,
+};
+
+static int __init s2mps11_pmic_init(void)
+{
+       return platform_driver_register(&s2mps11_pmic_driver);
+}
+subsys_initcall(s2mps11_pmic_init);
+
+static void __exit s2mps11_pmic_exit(void)
+{
+       platform_driver_unregister(&s2mps11_pmic_driver);
+}
+module_exit(s2mps11_pmic_exit);
+
+/* Module information */
+MODULE_AUTHOR("Sangbeom Kim <sbkim73@samsung.com>");
+MODULE_DESCRIPTION("SAMSUNG S2MPS11 Regulator Driver");
+MODULE_LICENSE("GPL");
index 9caadb4821786308aa624e9ef03cd7408dc2083f..102287fa7ecb48df1aae1de76c484b3fe683051d 100644 (file)
@@ -41,6 +41,7 @@ struct s5m8767_info {
        u8 buck3_vol[8];
        u8 buck4_vol[8];
        int buck_gpios[3];
+       int buck_ds[3];
        int buck_gpioindex;
 };
 
@@ -120,27 +121,6 @@ static const struct s5m_voltage_desc *reg_voltage_map[] = {
        [S5M8767_BUCK9] = &buck_voltage_val3,
 };
 
-static int s5m8767_list_voltage(struct regulator_dev *rdev,
-                               unsigned int selector)
-{
-       const struct s5m_voltage_desc *desc;
-       int reg_id = rdev_get_id(rdev);
-       int val;
-
-       if (reg_id >= ARRAY_SIZE(reg_voltage_map) || reg_id < 0)
-               return -EINVAL;
-
-       desc = reg_voltage_map[reg_id];
-       if (desc == NULL)
-               return -EINVAL;
-
-       val = desc->min + desc->step * selector;
-       if (val > desc->max)
-               return -EINVAL;
-
-       return val;
-}
-
 static unsigned int s5m8767_opmode_reg[][4] = {
        /* {OFF, ON, LOWPOWER, SUSPEND} */
        /* LDO1 ... LDO28 */
@@ -283,17 +263,17 @@ static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg)
                reg = S5M8767_REG_BUCK1CTRL2;
                break;
        case S5M8767_BUCK2:
-               reg = S5M8767_REG_BUCK2DVS1;
+               reg = S5M8767_REG_BUCK2DVS2;
                if (s5m8767->buck2_gpiodvs)
                        reg += s5m8767->buck_gpioindex;
                break;
        case S5M8767_BUCK3:
-               reg = S5M8767_REG_BUCK3DVS1;
+               reg = S5M8767_REG_BUCK3DVS2;
                if (s5m8767->buck3_gpiodvs)
                        reg += s5m8767->buck_gpioindex;
                break;
        case S5M8767_BUCK4:
-               reg = S5M8767_REG_BUCK4DVS1;
+               reg = S5M8767_REG_BUCK4DVS2;
                if (s5m8767->buck4_gpiodvs)
                        reg += s5m8767->buck_gpioindex;
                break;
@@ -357,32 +337,34 @@ static int s5m8767_convert_voltage_to_sel(
        return selector;
 }
 
-static inline void s5m8767_set_high(struct s5m8767_info *s5m8767)
+static inline int s5m8767_set_high(struct s5m8767_info *s5m8767)
 {
        int temp_index = s5m8767->buck_gpioindex;
 
        gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
        gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
        gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
+
+       return 0;
 }
 
-static inline void s5m8767_set_low(struct s5m8767_info *s5m8767)
+static inline int s5m8767_set_low(struct s5m8767_info *s5m8767)
 {
        int temp_index = s5m8767->buck_gpioindex;
 
        gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1);
        gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1);
        gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1);
+
+       return 0;
 }
 
-static int s5m8767_set_voltage(struct regulator_dev *rdev,
-                               int min_uV, int max_uV, unsigned *selector)
+static int s5m8767_set_voltage_sel(struct regulator_dev *rdev,
+                                  unsigned selector)
 {
        struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
-       const struct s5m_voltage_desc *desc;
        int reg_id = rdev_get_id(rdev);
-       int sel, reg, mask, ret = 0, old_index, index = 0;
-       u8 val;
+       int reg, mask, ret = 0, old_index, index = 0;
        u8 *buck234_vol = NULL;
 
        switch (reg_id) {
@@ -407,15 +389,9 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev,
                return -EINVAL;
        }
 
-       desc = reg_voltage_map[reg_id];
-
-       sel = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV);
-       if (sel < 0)
-               return sel;
-
        /* buck234_vol != NULL means to control buck234 voltage via DVS GPIO */
        if (buck234_vol) {
-               while (*buck234_vol != sel) {
+               while (*buck234_vol != selector) {
                        buck234_vol++;
                        index++;
                }
@@ -423,22 +399,16 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev,
                s5m8767->buck_gpioindex = index;
 
                if (index > old_index)
-                       s5m8767_set_high(s5m8767);
+                       return s5m8767_set_high(s5m8767);
                else
-                       s5m8767_set_low(s5m8767);
+                       return s5m8767_set_low(s5m8767);
        } else {
                ret = s5m8767_get_voltage_register(rdev, &reg);
                if (ret)
                        return ret;
 
-               s5m_reg_read(s5m8767->iodev, reg, &val);
-               val = (val & ~mask) | sel;
-
-               ret = s5m_reg_write(s5m8767->iodev, reg, val);
+               return s5m_reg_update(s5m8767->iodev, reg, selector, mask);
        }
-
-       *selector = sel;
-       return ret;
 }
 
 static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
@@ -458,15 +428,21 @@ static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev,
 }
 
 static struct regulator_ops s5m8767_ops = {
-       .list_voltage           = s5m8767_list_voltage,
+       .list_voltage           = regulator_list_voltage_linear,
        .is_enabled             = s5m8767_reg_is_enabled,
        .enable                 = s5m8767_reg_enable,
        .disable                = s5m8767_reg_disable,
        .get_voltage_sel        = s5m8767_get_voltage_sel,
-       .set_voltage            = s5m8767_set_voltage,
+       .set_voltage_sel        = s5m8767_set_voltage_sel,
        .set_voltage_time_sel   = s5m8767_set_voltage_time_sel,
 };
 
+static struct regulator_ops s5m8767_buck78_ops = {
+       .is_enabled             = s5m8767_reg_is_enabled,
+       .enable                 = s5m8767_reg_enable,
+       .disable                = s5m8767_reg_disable,
+};
+
 #define s5m8767_regulator_desc(_name) {                \
        .name           = #_name,               \
        .id             = S5M8767_##_name,      \
@@ -475,6 +451,14 @@ static struct regulator_ops s5m8767_ops = {
        .owner          = THIS_MODULE,          \
 }
 
+#define s5m8767_regulator_buck78_desc(_name) { \
+       .name           = #_name,               \
+       .id             = S5M8767_##_name,      \
+       .ops            = &s5m8767_buck78_ops,  \
+       .type           = REGULATOR_VOLTAGE,    \
+       .owner          = THIS_MODULE,          \
+}
+
 static struct regulator_desc regulators[] = {
        s5m8767_regulator_desc(LDO1),
        s5m8767_regulator_desc(LDO2),
@@ -510,8 +494,8 @@ static struct regulator_desc regulators[] = {
        s5m8767_regulator_desc(BUCK4),
        s5m8767_regulator_desc(BUCK5),
        s5m8767_regulator_desc(BUCK6),
-       s5m8767_regulator_desc(BUCK7),
-       s5m8767_regulator_desc(BUCK8),
+       s5m8767_regulator_buck78_desc(BUCK7),
+       s5m8767_regulator_buck78_desc(BUCK8),
        s5m8767_regulator_desc(BUCK9),
 };
 
@@ -522,7 +506,7 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
        struct regulator_config config = { };
        struct regulator_dev **rdev;
        struct s5m8767_info *s5m8767;
-       int i, ret, size;
+       int i, ret, size, buck_init;
 
        if (!pdata) {
                dev_err(pdev->dev.parent, "Platform data not supplied\n");
@@ -573,12 +557,37 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
        s5m8767->buck_gpios[0] = pdata->buck_gpios[0];
        s5m8767->buck_gpios[1] = pdata->buck_gpios[1];
        s5m8767->buck_gpios[2] = pdata->buck_gpios[2];
+       s5m8767->buck_ds[0] = pdata->buck_ds[0];
+       s5m8767->buck_ds[1] = pdata->buck_ds[1];
+       s5m8767->buck_ds[2] = pdata->buck_ds[2];
+
        s5m8767->ramp_delay = pdata->buck_ramp_delay;
        s5m8767->buck2_ramp = pdata->buck2_ramp_enable;
        s5m8767->buck3_ramp = pdata->buck3_ramp_enable;
        s5m8767->buck4_ramp = pdata->buck4_ramp_enable;
        s5m8767->opmode = pdata->opmode;
 
+       buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
+                                               pdata->buck2_init,
+                                               pdata->buck2_init +
+                                               buck_voltage_val2.step);
+
+       s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS2, buck_init);
+
+       buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
+                                               pdata->buck3_init,
+                                               pdata->buck3_init +
+                                               buck_voltage_val2.step);
+
+       s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS2, buck_init);
+
+       buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2,
+                                               pdata->buck4_init,
+                                               pdata->buck4_init +
+                                               buck_voltage_val2.step);
+
+       s5m_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS2, buck_init);
+
        for (i = 0; i < 8; i++) {
                if (s5m8767->buck2_gpiodvs) {
                        s5m8767->buck2_vol[i] =
@@ -608,48 +617,70 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
                }
        }
 
-       if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
-               pdata->buck4_gpiodvs) {
-               if (gpio_is_valid(pdata->buck_gpios[0]) &&
-                       gpio_is_valid(pdata->buck_gpios[1]) &&
-                       gpio_is_valid(pdata->buck_gpios[2])) {
-                       ret = gpio_request(pdata->buck_gpios[0],
-                                               "S5M8767 SET1");
-                       if (ret == -EBUSY)
-                               dev_warn(&pdev->dev, "Duplicated gpio request for SET1\n");
-
-                       ret = gpio_request(pdata->buck_gpios[1],
-                                          "S5M8767 SET2");
-                       if (ret == -EBUSY)
-                               dev_warn(&pdev->dev, "Duplicated gpio request for SET2\n");
-
-                       ret = gpio_request(pdata->buck_gpios[2],
-                                          "S5M8767 SET3");
-                       if (ret == -EBUSY)
-                               dev_warn(&pdev->dev, "Duplicated gpio request for SET3\n");
-                       /* SET1 GPIO */
-                       gpio_direction_output(pdata->buck_gpios[0],
-                                       (s5m8767->buck_gpioindex >> 2) & 0x1);
-                       /* SET2 GPIO */
-                       gpio_direction_output(pdata->buck_gpios[1],
-                                       (s5m8767->buck_gpioindex >> 1) & 0x1);
-                       /* SET3 GPIO */
-                       gpio_direction_output(pdata->buck_gpios[2],
-                                       (s5m8767->buck_gpioindex >> 0) & 0x1);
-                       ret = 0;
-               } else {
-                       dev_err(&pdev->dev, "GPIO NOT VALID\n");
-                       ret = -EINVAL;
+       if (gpio_is_valid(pdata->buck_gpios[0]) &&
+               gpio_is_valid(pdata->buck_gpios[1]) &&
+               gpio_is_valid(pdata->buck_gpios[2])) {
+               ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[0],
+                                       "S5M8767 SET1");
+               if (ret)
                        return ret;
-               }
+
+               ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[1],
+                                       "S5M8767 SET2");
+               if (ret)
+                       return ret;
+
+               ret = devm_gpio_request(&pdev->dev, pdata->buck_gpios[2],
+                                       "S5M8767 SET3");
+               if (ret)
+                       return ret;
+
+               /* SET1 GPIO */
+               gpio_direction_output(pdata->buck_gpios[0],
+                               (s5m8767->buck_gpioindex >> 2) & 0x1);
+               /* SET2 GPIO */
+               gpio_direction_output(pdata->buck_gpios[1],
+                               (s5m8767->buck_gpioindex >> 1) & 0x1);
+               /* SET3 GPIO */
+               gpio_direction_output(pdata->buck_gpios[2],
+                               (s5m8767->buck_gpioindex >> 0) & 0x1);
+       } else {
+               dev_err(&pdev->dev, "GPIO NOT VALID\n");
+               ret = -EINVAL;
+               return ret;
        }
 
-       s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL,
-                       (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
-       s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL,
-                       (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
-       s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL,
-                       (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1), 1 << 1);
+       ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[0], "S5M8767 DS2");
+       if (ret)
+               return ret;
+
+       ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[1], "S5M8767 DS3");
+       if (ret)
+               return ret;
+
+       ret = devm_gpio_request(&pdev->dev, pdata->buck_ds[2], "S5M8767 DS4");
+       if (ret)
+               return ret;
+
+       /* DS2 GPIO */
+       gpio_direction_output(pdata->buck_ds[0], 0x0);
+       /* DS3 GPIO */
+       gpio_direction_output(pdata->buck_ds[1], 0x0);
+       /* DS4 GPIO */
+       gpio_direction_output(pdata->buck_ds[2], 0x0);
+
+       if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
+          pdata->buck4_gpiodvs) {
+               s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL,
+                               (pdata->buck2_gpiodvs) ? (1 << 1) : (0 << 1),
+                               1 << 1);
+               s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL,
+                               (pdata->buck3_gpiodvs) ? (1 << 1) : (0 << 1),
+                               1 << 1);
+               s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL,
+                               (pdata->buck4_gpiodvs) ? (1 << 1) : (0 << 1),
+                               1 << 1);
+       }
 
        /* Initialize GPIO DVS registers */
        for (i = 0; i < 8; i++) {
@@ -668,9 +699,6 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
                                           s5m8767->buck4_vol[i]);
                }
        }
-       s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK2CTRL, 0x78, 0xff);
-       s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK3CTRL, 0x58, 0xff);
-       s5m_reg_update(s5m8767->iodev, S5M8767_REG_BUCK4CTRL, 0x78, 0xff);
 
        if (s5m8767->buck2_ramp)
                s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP, 0x08, 0x08);
@@ -684,9 +712,13 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
        if (s5m8767->buck2_ramp || s5m8767->buck3_ramp
                || s5m8767->buck4_ramp) {
                switch (s5m8767->ramp_delay) {
-               case 15:
+               case 5:
                        s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
-                                       0xc0, 0xf0);
+                                       0x40, 0xf0);
+                       break;
+               case 10:
+                       s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
+                                       0x90, 0xf0);
                        break;
                case 25:
                        s5m_reg_update(s5m8767->iodev, S5M8767_REG_DVSRAMP,
@@ -711,9 +743,12 @@ static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
                int id = pdata->regulators[i].id;
 
                desc = reg_voltage_map[id];
-               if (desc)
+               if (desc) {
                        regulators[id].n_voltages =
                                (desc->max - desc->min) / desc->step + 1;
+                       regulators[id].min_uV = desc->min;
+                       regulators[id].uV_step = desc->step;
+               }
 
                config.dev = s5m8767->dev;
                config.init_data = pdata->regulators[i].initdata;
index d840d8440a91691b0954f5cb84fd134c1118f036..1378409efaec70170b8a3c70eeb09e1402abec33 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps6105x.h>
 
-static const int tps6105x_voltages[] = {
+static const unsigned int tps6105x_voltages[] = {
        4500000,
        5000000,
        5250000,
@@ -105,22 +105,13 @@ static int tps6105x_regulator_set_voltage_sel(struct regulator_dev *rdev,
        return 0;
 }
 
-static int tps6105x_regulator_list_voltage(struct regulator_dev *rdev,
-                                          unsigned selector)
-{
-       if (selector >= ARRAY_SIZE(tps6105x_voltages))
-               return -EINVAL;
-
-       return tps6105x_voltages[selector];
-}
-
 static struct regulator_ops tps6105x_regulator_ops = {
        .enable         = tps6105x_regulator_enable,
        .disable        = tps6105x_regulator_disable,
        .is_enabled     = tps6105x_regulator_is_enabled,
        .get_voltage_sel = tps6105x_regulator_get_voltage_sel,
        .set_voltage_sel = tps6105x_regulator_set_voltage_sel,
-       .list_voltage   = tps6105x_regulator_list_voltage,
+       .list_voltage   = regulator_list_voltage_table,
 };
 
 static const struct regulator_desc tps6105x_regulator_desc = {
@@ -130,6 +121,7 @@ static const struct regulator_desc tps6105x_regulator_desc = {
        .id             = 0,
        .owner          = THIS_MODULE,
        .n_voltages     = ARRAY_SIZE(tps6105x_voltages),
+       .volt_table     = tps6105x_voltages,
 };
 
 /*
index e534269ed44aa2afebcd4cc1c7e509354aa92877..68729a7c8709fbcbc8e88e8cf99924afc2e69f18 100644 (file)
@@ -65,10 +65,8 @@ struct tps62360_chip {
        struct regulator_desc desc;
        struct regulator_dev *rdev;
        struct regmap *regmap;
-       int chip_id;
        int vsel0_gpio;
        int vsel1_gpio;
-       int voltage_base;
        u8 voltage_reg_mask;
        bool en_internal_pulldn;
        bool en_discharge;
@@ -76,7 +74,6 @@ struct tps62360_chip {
        int lru_index[4];
        int curr_vset_vsel[4];
        int curr_vset_id;
-       int change_uv_per_us;
 };
 
 /*
@@ -175,23 +172,6 @@ static int tps62360_dcdc_set_voltage_sel(struct regulator_dev *dev,
        return 0;
 }
 
-static int tps62360_set_voltage_time_sel(struct regulator_dev *rdev,
-               unsigned int old_selector, unsigned int new_selector)
-{
-       struct tps62360_chip *tps = rdev_get_drvdata(rdev);
-       int old_uV, new_uV;
-
-       old_uV = regulator_list_voltage_linear(rdev, old_selector);
-       if (old_uV < 0)
-               return old_uV;
-
-       new_uV = regulator_list_voltage_linear(rdev, new_selector);
-       if (new_uV < 0)
-               return new_uV;
-
-       return DIV_ROUND_UP(abs(old_uV - new_uV), tps->change_uv_per_us);
-}
-
 static int tps62360_set_mode(struct regulator_dev *rdev, unsigned int mode)
 {
        struct tps62360_chip *tps = rdev_get_drvdata(rdev);
@@ -258,7 +238,7 @@ static struct regulator_ops tps62360_dcdc_ops = {
        .set_voltage_sel        = tps62360_dcdc_set_voltage_sel,
        .list_voltage           = regulator_list_voltage_linear,
        .map_voltage            = regulator_map_voltage_linear,
-       .set_voltage_time_sel   = tps62360_set_voltage_time_sel,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
        .set_mode               = tps62360_set_mode,
        .get_mode               = tps62360_get_mode,
 };
@@ -301,7 +281,7 @@ static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
        ramp_ctrl = (ramp_ctrl >> 4) & 0x7;
 
        /* ramp mV/us = 32/(2^ramp_ctrl) */
-       tps->change_uv_per_us = DIV_ROUND_UP(32000, BIT(ramp_ctrl));
+       tps->desc.ramp_delay = DIV_ROUND_UP(32000, BIT(ramp_ctrl));
        return ret;
 }
 
@@ -408,13 +388,13 @@ static int __devinit tps62360_probe(struct i2c_client *client,
        switch (chip_id) {
        case TPS62360:
        case TPS62362:
-               tps->voltage_base = TPS62360_BASE_VOLTAGE;
+               tps->desc.min_uV = TPS62360_BASE_VOLTAGE;
                tps->voltage_reg_mask = 0x3F;
                tps->desc.n_voltages = TPS62360_N_VOLTAGES;
                break;
        case TPS62361:
        case TPS62363:
-               tps->voltage_base = TPS62361_BASE_VOLTAGE;
+               tps->desc.min_uV = TPS62361_BASE_VOLTAGE;
                tps->voltage_reg_mask = 0x7F;
                tps->desc.n_voltages = TPS62361_N_VOLTAGES;
                break;
@@ -427,7 +407,6 @@ static int __devinit tps62360_probe(struct i2c_client *client,
        tps->desc.ops = &tps62360_dcdc_ops;
        tps->desc.type = REGULATOR_VOLTAGE;
        tps->desc.owner = THIS_MODULE;
-       tps->desc.min_uV = tps->voltage_base;
        tps->desc.uV_step = 10000;
 
        tps->regmap = devm_regmap_init_i2c(client, &tps62360_regmap_config);
@@ -449,24 +428,24 @@ static int __devinit tps62360_probe(struct i2c_client *client,
                int gpio_flags;
                gpio_flags = (pdata->vsel0_def_state) ?
                                GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
-               ret = gpio_request_one(tps->vsel0_gpio,
+               ret = devm_gpio_request_one(&client->dev, tps->vsel0_gpio,
                                gpio_flags, "tps62360-vsel0");
                if (ret) {
                        dev_err(&client->dev,
                                "%s(): Could not obtain vsel0 GPIO %d: %d\n",
                                __func__, tps->vsel0_gpio, ret);
-                       goto err_gpio0;
+                       return ret;
                }
 
                gpio_flags = (pdata->vsel1_def_state) ?
                                GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
-               ret = gpio_request_one(tps->vsel1_gpio,
+               ret = devm_gpio_request_one(&client->dev, tps->vsel1_gpio,
                                gpio_flags, "tps62360-vsel1");
                if (ret) {
                        dev_err(&client->dev,
                                "%s(): Could not obtain vsel1 GPIO %d: %d\n",
                                __func__, tps->vsel1_gpio, ret);
-                       goto err_gpio1;
+                       return ret;
                }
                tps->valid_gpios = true;
 
@@ -484,7 +463,7 @@ static int __devinit tps62360_probe(struct i2c_client *client,
        if (ret < 0) {
                dev_err(tps->dev, "%s(): Init failed with err = %d\n",
                                __func__, ret);
-               goto err_init;
+               return ret;
        }
 
        config.dev = &client->dev;
@@ -498,21 +477,11 @@ static int __devinit tps62360_probe(struct i2c_client *client,
                dev_err(tps->dev,
                        "%s(): regulator register failed with err %s\n",
                        __func__, id->name);
-               ret = PTR_ERR(rdev);
-               goto err_init;
+               return PTR_ERR(rdev);
        }
 
        tps->rdev = rdev;
        return 0;
-
-err_init:
-       if (gpio_is_valid(tps->vsel1_gpio))
-               gpio_free(tps->vsel1_gpio);
-err_gpio1:
-       if (gpio_is_valid(tps->vsel0_gpio))
-               gpio_free(tps->vsel0_gpio);
-err_gpio0:
-       return ret;
 }
 
 /**
@@ -525,12 +494,6 @@ static int __devexit tps62360_remove(struct i2c_client *client)
 {
        struct tps62360_chip *tps = i2c_get_clientdata(client);
 
-       if (gpio_is_valid(tps->vsel1_gpio))
-               gpio_free(tps->vsel1_gpio);
-
-       if (gpio_is_valid(tps->vsel0_gpio))
-               gpio_free(tps->vsel0_gpio);
-
        regulator_unregister(tps->rdev);
        return 0;
 }
index 8f1be8586c724a99061092d787273573eda5644e..6998d579d07b424891a79d09e62406a6b7e38d74 100644 (file)
 #define TPS65023_REG_CTRL2_DCDC1       BIT(1)
 #define TPS65023_REG_CTRL2_DCDC3       BIT(0)
 
-/* LDO_CTRL bitfields */
-#define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id)   ((ldo_id)*4)
-#define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id)    (0x07 << ((ldo_id)*4))
-
 /* Number of step-down converters available */
 #define TPS65023_NUM_DCDC              3
 /* Number of LDO voltage regulators  available */
 #define TPS65023_MAX_REG_ID            TPS65023_LDO_2
 
 /* Supported voltage values for regulators */
-static const u16 VCORE_VSEL_table[] = {
-       800, 825, 850, 875,
-       900, 925, 950, 975,
-       1000, 1025, 1050, 1075,
-       1100, 1125, 1150, 1175,
-       1200, 1225, 1250, 1275,
-       1300, 1325, 1350, 1375,
-       1400, 1425, 1450, 1475,
-       1500, 1525, 1550, 1600,
+static const unsigned int VCORE_VSEL_table[] = {
+       800000, 825000, 850000, 875000,
+       900000, 925000, 950000, 975000,
+       1000000, 1025000, 1050000, 1075000,
+       1100000, 1125000, 1150000, 1175000,
+       1200000, 1225000, 1250000, 1275000,
+       1300000, 1325000, 1350000, 1375000,
+       1400000, 1425000, 1450000, 1475000,
+       1500000, 1525000, 1550000, 1600000,
+};
+
+static const unsigned int DCDC_FIXED_3300000_VSEL_table[] = {
+       3300000,
+};
+
+static const unsigned int DCDC_FIXED_1800000_VSEL_table[] = {
+       1800000,
 };
 
 /* Supported voltage values for LDO regulators for tps65020 */
-static const u16 TPS65020_LDO1_VSEL_table[] = {
-       1000, 1050, 1100, 1300,
-       1800, 2500, 3000, 3300,
+static const unsigned int TPS65020_LDO1_VSEL_table[] = {
+       1000000, 1050000, 1100000, 1300000,
+       1800000, 2500000, 3000000, 3300000,
 };
 
-static const u16 TPS65020_LDO2_VSEL_table[] = {
-       1000, 1050, 1100, 1300,
-       1800, 2500, 3000, 3300,
+static const unsigned int TPS65020_LDO2_VSEL_table[] = {
+       1000000, 1050000, 1100000, 1300000,
+       1800000, 2500000, 3000000, 3300000,
 };
 
 /* Supported voltage values for LDO regulators
  * for tps65021 and tps65023 */
-static const u16 TPS65023_LDO1_VSEL_table[] = {
-       1000, 1100, 1300, 1800,
-       2200, 2600, 2800, 3150,
+static const unsigned int TPS65023_LDO1_VSEL_table[] = {
+       1000000, 1100000, 1300000, 1800000,
+       2200000, 2600000, 2800000, 3150000,
 };
 
-static const u16 TPS65023_LDO2_VSEL_table[] = {
-       1050, 1200, 1300, 1800,
-       2500, 2800, 3000, 3300,
+static const unsigned int TPS65023_LDO2_VSEL_table[] = {
+       1050000, 1200000, 1300000, 1800000,
+       2500000, 2800000, 3000000, 3300000,
 };
 
 /* Regulator specific details */
 struct tps_info {
        const char *name;
-       unsigned min_uV;
-       unsigned max_uV;
-       bool fixed;
        u8 table_len;
-       const u16 *table;
+       const unsigned int *table;
 };
 
 /* PMIC details */
@@ -150,7 +151,7 @@ struct tps_driver_data {
        u8 core_regulator;
 };
 
-static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
+static int tps65023_dcdc_get_voltage_sel(struct regulator_dev *dev)
 {
        struct tps_pmic *tps = rdev_get_drvdata(dev);
        int ret;
@@ -164,9 +165,9 @@ static int tps65023_dcdc_get_voltage(struct regulator_dev *dev)
                if (ret != 0)
                        return ret;
                data &= (tps->info[dcdc]->table_len - 1);
-               return tps->info[dcdc]->table[data] * 1000;
+               return data;
        } else
-               return tps->info[dcdc]->min_uV;
+               return 0;
 }
 
 static int tps65023_dcdc_set_voltage_sel(struct regulator_dev *dev,
@@ -193,76 +194,14 @@ out:
        return ret;
 }
 
-static int tps65023_ldo_get_voltage(struct regulator_dev *dev)
-{
-       struct tps_pmic *tps = rdev_get_drvdata(dev);
-       int data, ldo = rdev_get_id(dev);
-       int ret;
-
-       if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
-               return -EINVAL;
-
-       ret = regmap_read(tps->regmap, TPS65023_REG_LDO_CTRL, &data);
-       if (ret != 0)
-               return ret;
-
-       data >>= (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1));
-       data &= (tps->info[ldo]->table_len - 1);
-       return tps->info[ldo]->table[data] * 1000;
-}
-
-static int tps65023_ldo_set_voltage_sel(struct regulator_dev *dev,
-                                       unsigned selector)
-{
-       struct tps_pmic *tps = rdev_get_drvdata(dev);
-       int ldo_index = rdev_get_id(dev) - TPS65023_LDO_1;
-
-       return regmap_update_bits(tps->regmap, TPS65023_REG_LDO_CTRL,
-                       TPS65023_LDO_CTRL_LDOx_MASK(ldo_index),
-                       selector << TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_index));
-}
-
-static int tps65023_dcdc_list_voltage(struct regulator_dev *dev,
-                                       unsigned selector)
-{
-       struct tps_pmic *tps = rdev_get_drvdata(dev);
-       int dcdc = rdev_get_id(dev);
-
-       if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3)
-               return -EINVAL;
-
-       if (dcdc == tps->core_regulator) {
-               if (selector >= tps->info[dcdc]->table_len)
-                       return -EINVAL;
-               else
-                       return tps->info[dcdc]->table[selector] * 1000;
-       } else
-               return tps->info[dcdc]->min_uV;
-}
-
-static int tps65023_ldo_list_voltage(struct regulator_dev *dev,
-                                       unsigned selector)
-{
-       struct tps_pmic *tps = rdev_get_drvdata(dev);
-       int ldo = rdev_get_id(dev);
-
-       if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2)
-               return -EINVAL;
-
-       if (selector >= tps->info[ldo]->table_len)
-               return -EINVAL;
-       else
-               return tps->info[ldo]->table[selector] * 1000;
-}
-
 /* Operations permitted on VDCDCx */
 static struct regulator_ops tps65023_dcdc_ops = {
        .is_enabled = regulator_is_enabled_regmap,
        .enable = regulator_enable_regmap,
        .disable = regulator_disable_regmap,
-       .get_voltage = tps65023_dcdc_get_voltage,
+       .get_voltage_sel = tps65023_dcdc_get_voltage_sel,
        .set_voltage_sel = tps65023_dcdc_set_voltage_sel,
-       .list_voltage = tps65023_dcdc_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
 };
 
 /* Operations permitted on LDOx */
@@ -270,9 +209,9 @@ static struct regulator_ops tps65023_ldo_ops = {
        .is_enabled = regulator_is_enabled_regmap,
        .enable = regulator_enable_regmap,
        .disable = regulator_disable_regmap,
-       .get_voltage = tps65023_ldo_get_voltage,
-       .set_voltage_sel = tps65023_ldo_set_voltage_sel,
-       .list_voltage = tps65023_ldo_list_voltage,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .list_voltage = regulator_list_voltage_table,
 };
 
 static struct regmap_config tps65023_regmap_config = {
@@ -325,19 +264,28 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
                tps->desc[i].name = info->name;
                tps->desc[i].id = i;
                tps->desc[i].n_voltages = info->table_len;
+               tps->desc[i].volt_table = info->table;
                tps->desc[i].ops = (i > TPS65023_DCDC_3 ?
                                        &tps65023_ldo_ops : &tps65023_dcdc_ops);
                tps->desc[i].type = REGULATOR_VOLTAGE;
                tps->desc[i].owner = THIS_MODULE;
 
                tps->desc[i].enable_reg = TPS65023_REG_REG_CTRL;
-               if (i == TPS65023_LDO_1)
+               switch (i) {
+               case TPS65023_LDO_1:
+                       tps->desc[i].vsel_reg = TPS65023_REG_LDO_CTRL;
+                       tps->desc[i].vsel_mask = 0x07;
                        tps->desc[i].enable_mask = 1 << 1;
-               else if (i == TPS65023_LDO_2)
+                       break;
+               case TPS65023_LDO_2:
+                       tps->desc[i].vsel_reg = TPS65023_REG_LDO_CTRL;
+                       tps->desc[i].vsel_mask = 0x70;
                        tps->desc[i].enable_mask = 1 << 2;
-               else /* DCDCx */
+                       break;
+               default: /* DCDCx */
                        tps->desc[i].enable_mask =
                                        1 << (TPS65023_NUM_REGULATOR - i);
+               }
 
                config.dev = &client->dev;
                config.init_data = init_data;
@@ -384,35 +332,26 @@ static int __devexit tps_65023_remove(struct i2c_client *client)
 static const struct tps_info tps65020_regs[] = {
        {
                .name = "VDCDC1",
-               .min_uV = 3300000,
-               .max_uV = 3300000,
-               .fixed  = 1,
+               .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table),
+               .table = DCDC_FIXED_3300000_VSEL_table,
        },
        {
                .name = "VDCDC2",
-               .min_uV =  1800000,
-               .max_uV = 1800000,
-               .fixed = 1,
+               .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table),
+               .table = DCDC_FIXED_1800000_VSEL_table,
        },
        {
                .name = "VDCDC3",
-               .min_uV =  800000,
-               .max_uV = 1600000,
                .table_len = ARRAY_SIZE(VCORE_VSEL_table),
                .table = VCORE_VSEL_table,
        },
-
        {
                .name = "LDO1",
-               .min_uV = 1000000,
-               .max_uV = 3150000,
                .table_len = ARRAY_SIZE(TPS65020_LDO1_VSEL_table),
                .table = TPS65020_LDO1_VSEL_table,
        },
        {
                .name = "LDO2",
-               .min_uV = 1050000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(TPS65020_LDO2_VSEL_table),
                .table = TPS65020_LDO2_VSEL_table,
        },
@@ -421,34 +360,26 @@ static const struct tps_info tps65020_regs[] = {
 static const struct tps_info tps65021_regs[] = {
        {
                .name = "VDCDC1",
-               .min_uV =  3300000,
-               .max_uV = 3300000,
-               .fixed = 1,
+               .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table),
+               .table = DCDC_FIXED_3300000_VSEL_table,
        },
        {
                .name = "VDCDC2",
-               .min_uV =  1800000,
-               .max_uV = 1800000,
-               .fixed = 1,
+               .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table),
+               .table = DCDC_FIXED_1800000_VSEL_table,
        },
        {
                .name = "VDCDC3",
-               .min_uV =  800000,
-               .max_uV = 1600000,
                .table_len = ARRAY_SIZE(VCORE_VSEL_table),
                .table = VCORE_VSEL_table,
        },
        {
                .name = "LDO1",
-               .min_uV = 1000000,
-               .max_uV = 3150000,
                .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
                .table = TPS65023_LDO1_VSEL_table,
        },
        {
                .name = "LDO2",
-               .min_uV = 1050000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
                .table = TPS65023_LDO2_VSEL_table,
        },
@@ -457,34 +388,26 @@ static const struct tps_info tps65021_regs[] = {
 static const struct tps_info tps65023_regs[] = {
        {
                .name = "VDCDC1",
-               .min_uV =  800000,
-               .max_uV = 1600000,
                .table_len = ARRAY_SIZE(VCORE_VSEL_table),
                .table = VCORE_VSEL_table,
        },
        {
                .name = "VDCDC2",
-               .min_uV =  3300000,
-               .max_uV = 3300000,
-               .fixed = 1,
+               .table_len = ARRAY_SIZE(DCDC_FIXED_3300000_VSEL_table),
+               .table = DCDC_FIXED_3300000_VSEL_table,
        },
        {
                .name = "VDCDC3",
-               .min_uV =  1800000,
-               .max_uV = 1800000,
-               .fixed = 1,
+               .table_len = ARRAY_SIZE(DCDC_FIXED_1800000_VSEL_table),
+               .table = DCDC_FIXED_1800000_VSEL_table,
        },
        {
                .name = "LDO1",
-               .min_uV = 1000000,
-               .max_uV = 3150000,
                .table_len = ARRAY_SIZE(TPS65023_LDO1_VSEL_table),
                .table = TPS65023_LDO1_VSEL_table,
        },
        {
                .name = "LDO2",
-               .min_uV = 1050000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(TPS65023_LDO2_VSEL_table),
                .table = TPS65023_LDO2_VSEL_table,
        },
index da38be1016aa544b9aeba85975a058018072c4e7..07d01ccdf308fdf2a6871ce60f6d60f380d4060c 100644 (file)
 /* Number of total regulators available */
 #define TPS6507X_NUM_REGULATOR         (TPS6507X_NUM_DCDC + TPS6507X_NUM_LDO)
 
-/* Supported voltage values for regulators (in milliVolts) */
-static const u16 VDCDCx_VSEL_table[] = {
-       725, 750, 775, 800,
-       825, 850, 875, 900,
-       925, 950, 975, 1000,
-       1025, 1050, 1075, 1100,
-       1125, 1150, 1175, 1200,
-       1225, 1250, 1275, 1300,
-       1325, 1350, 1375, 1400,
-       1425, 1450, 1475, 1500,
-       1550, 1600, 1650, 1700,
-       1750, 1800, 1850, 1900,
-       1950, 2000, 2050, 2100,
-       2150, 2200, 2250, 2300,
-       2350, 2400, 2450, 2500,
-       2550, 2600, 2650, 2700,
-       2750, 2800, 2850, 2900,
-       3000, 3100, 3200, 3300,
+/* Supported voltage values for regulators (in microVolts) */
+static const unsigned int VDCDCx_VSEL_table[] = {
+       725000, 750000, 775000, 800000,
+       825000, 850000, 875000, 900000,
+       925000, 950000, 975000, 1000000,
+       1025000, 1050000, 1075000, 1100000,
+       1125000, 1150000, 1175000, 1200000,
+       1225000, 1250000, 1275000, 1300000,
+       1325000, 1350000, 1375000, 1400000,
+       1425000, 1450000, 1475000, 1500000,
+       1550000, 1600000, 1650000, 1700000,
+       1750000, 1800000, 1850000, 1900000,
+       1950000, 2000000, 2050000, 2100000,
+       2150000, 2200000, 2250000, 2300000,
+       2350000, 2400000, 2450000, 2500000,
+       2550000, 2600000, 2650000, 2700000,
+       2750000, 2800000, 2850000, 2900000,
+       3000000, 3100000, 3200000, 3300000,
 };
 
-static const u16 LDO1_VSEL_table[] = {
-       1000, 1100, 1200, 1250,
-       1300, 1350, 1400, 1500,
-       1600, 1800, 2500, 2750,
-       2800, 3000, 3100, 3300,
+static const unsigned int LDO1_VSEL_table[] = {
+       1000000, 1100000, 1200000, 1250000,
+       1300000, 1350000, 1400000, 1500000,
+       1600000, 1800000, 2500000, 2750000,
+       2800000, 3000000, 3100000, 3300000,
 };
 
-static const u16 LDO2_VSEL_table[] = {
-       725, 750, 775, 800,
-       825, 850, 875, 900,
-       925, 950, 975, 1000,
-       1025, 1050, 1075, 1100,
-       1125, 1150, 1175, 1200,
-       1225, 1250, 1275, 1300,
-       1325, 1350, 1375, 1400,
-       1425, 1450, 1475, 1500,
-       1550, 1600, 1650, 1700,
-       1750, 1800, 1850, 1900,
-       1950, 2000, 2050, 2100,
-       2150, 2200, 2250, 2300,
-       2350, 2400, 2450, 2500,
-       2550, 2600, 2650, 2700,
-       2750, 2800, 2850, 2900,
-       3000, 3100, 3200, 3300,
-};
+/* The voltage mapping table for LDO2 is the same as VDCDCx */
+#define LDO2_VSEL_table VDCDCx_VSEL_table
 
 struct tps_info {
        const char *name;
-       unsigned min_uV;
-       unsigned max_uV;
        u8 table_len;
-       const u16 *table;
+       const unsigned int *table;
 
        /* Does DCDC high or the low register defines output voltage? */
        bool defdcdc_default;
@@ -103,36 +85,26 @@ struct tps_info {
 static struct tps_info tps6507x_pmic_regs[] = {
        {
                .name = "VDCDC1",
-               .min_uV = 725000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
                .table = VDCDCx_VSEL_table,
        },
        {
                .name = "VDCDC2",
-               .min_uV = 725000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
                .table = VDCDCx_VSEL_table,
        },
        {
                .name = "VDCDC3",
-               .min_uV = 725000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(VDCDCx_VSEL_table),
                .table = VDCDCx_VSEL_table,
        },
        {
                .name = "LDO1",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(LDO1_VSEL_table),
                .table = LDO1_VSEL_table,
        },
        {
                .name = "LDO2",
-               .min_uV = 725000,
-               .max_uV = 3300000,
                .table_len = ARRAY_SIZE(LDO2_VSEL_table),
                .table = LDO2_VSEL_table,
        },
@@ -375,28 +347,13 @@ static int tps6507x_pmic_set_voltage_sel(struct regulator_dev *dev,
        return tps6507x_pmic_reg_write(tps, reg, data);
 }
 
-static int tps6507x_pmic_list_voltage(struct regulator_dev *dev,
-                                       unsigned selector)
-{
-       struct tps6507x_pmic *tps = rdev_get_drvdata(dev);
-       int rid = rdev_get_id(dev);
-
-       if (rid < TPS6507X_DCDC_1 || rid > TPS6507X_LDO_2)
-               return -EINVAL;
-
-       if (selector >= tps->info[rid]->table_len)
-               return -EINVAL;
-       else
-               return tps->info[rid]->table[selector] * 1000;
-}
-
 static struct regulator_ops tps6507x_pmic_ops = {
        .is_enabled = tps6507x_pmic_is_enabled,
        .enable = tps6507x_pmic_enable,
        .disable = tps6507x_pmic_disable,
        .get_voltage_sel = tps6507x_pmic_get_voltage_sel,
        .set_voltage_sel = tps6507x_pmic_set_voltage_sel,
-       .list_voltage = tps6507x_pmic_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
 };
 
 static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
@@ -449,6 +406,7 @@ static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
                tps->desc[i].name = info->name;
                tps->desc[i].id = i;
                tps->desc[i].n_voltages = info->table_len;
+               tps->desc[i].volt_table = info->table;
                tps->desc[i].ops = &tps6507x_pmic_ops;
                tps->desc[i].type = REGULATOR_VOLTAGE;
                tps->desc[i].owner = THIS_MODULE;
index 9d371d2cbcae9a5f62e7484260f2879c341905bc..6caa222af77a284f09f1e8a5f634da794dd84838 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/regulator/machine.h>
 #include <linux/mfd/tps65217.h>
 
-#define TPS65217_REGULATOR(_name, _id, _ops, _n)       \
+#define TPS65217_REGULATOR(_name, _id, _ops, _n, _vr, _vm, _em, _t) \
        {                                               \
                .name           = _name,                \
                .id             = _id,                  \
                .n_voltages     = _n,                   \
                .type           = REGULATOR_VOLTAGE,    \
                .owner          = THIS_MODULE,          \
+               .vsel_reg       = _vr,                  \
+               .vsel_mask      = _vm,                  \
+               .enable_reg     = TPS65217_REG_ENABLE,  \
+               .enable_mask    = _em,                  \
+               .volt_table     = _t,                   \
        }                                               \
 
-#define TPS65217_INFO(_nm, _min, _max, _f1, _f2, _t, _n, _em, _vr, _vm)        \
+#define TPS65217_INFO(_nm, _min, _max, _f1, _f2)       \
        {                                               \
                .name           = _nm,                  \
                .min_uV         = _min,                 \
                .max_uV         = _max,                 \
                .vsel_to_uv     = _f1,                  \
                .uv_to_vsel     = _f2,                  \
-               .table          = _t,                   \
-               .table_len      = _n,                   \
-               .enable_mask    = _em,                  \
-               .set_vout_reg   = _vr,                  \
-               .set_vout_mask  = _vm,                  \
        }
 
-static const int LDO1_VSEL_table[] = {
+static const unsigned int LDO1_VSEL_table[] = {
        1000000, 1100000, 1200000, 1250000,
        1300000, 1350000, 1400000, 1500000,
        1600000, 1800000, 2500000, 2750000,
@@ -78,7 +78,7 @@ static int tps65217_vsel_to_uv1(unsigned int vsel)
 
 static int tps65217_uv_to_vsel1(int uV, unsigned int *vsel)
 {
-       if ((uV < 0) && (uV > 3300000))
+       if (uV < 0 || uV > 3300000)
                return -EINVAL;
 
        if (uV <= 1500000)
@@ -112,7 +112,7 @@ static int tps65217_vsel_to_uv2(unsigned int vsel)
 
 static int tps65217_uv_to_vsel2(int uV, unsigned int *vsel)
 {
-       if ((uV < 0) && (uV > 3300000))
+       if (uV < 0 || uV > 3300000)
                return -EINVAL;
 
        if (uV <= 1900000)
@@ -127,46 +127,20 @@ static int tps65217_uv_to_vsel2(int uV, unsigned int *vsel)
 
 static struct tps_info tps65217_pmic_regs[] = {
        TPS65217_INFO("DCDC1", 900000, 1800000, tps65217_vsel_to_uv1,
-                       tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC1_EN,
-                       TPS65217_REG_DEFDCDC1, TPS65217_DEFDCDCX_DCDC_MASK),
+                       tps65217_uv_to_vsel1),
        TPS65217_INFO("DCDC2", 900000, 3300000, tps65217_vsel_to_uv1,
-                       tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC2_EN,
-                       TPS65217_REG_DEFDCDC2, TPS65217_DEFDCDCX_DCDC_MASK),
+                       tps65217_uv_to_vsel1),
        TPS65217_INFO("DCDC3", 900000, 1500000, tps65217_vsel_to_uv1,
-                       tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_DC3_EN,
-                       TPS65217_REG_DEFDCDC3, TPS65217_DEFDCDCX_DCDC_MASK),
-       TPS65217_INFO("LDO1", 1000000, 3300000, NULL, NULL, LDO1_VSEL_table,
-                       16, TPS65217_ENABLE_LDO1_EN, TPS65217_REG_DEFLDO1,
-                       TPS65217_DEFLDO1_LDO1_MASK),
+                       tps65217_uv_to_vsel1),
+       TPS65217_INFO("LDO1", 1000000, 3300000, NULL, NULL),
        TPS65217_INFO("LDO2", 900000, 3300000, tps65217_vsel_to_uv1,
-                       tps65217_uv_to_vsel1, NULL, 64, TPS65217_ENABLE_LDO2_EN,
-                       TPS65217_REG_DEFLDO2, TPS65217_DEFLDO2_LDO2_MASK),
+                       tps65217_uv_to_vsel1),
        TPS65217_INFO("LDO3", 1800000, 3300000, tps65217_vsel_to_uv2,
-                       tps65217_uv_to_vsel2, NULL, 32,
-                       TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN,
-                       TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK),
+                       tps65217_uv_to_vsel2),
        TPS65217_INFO("LDO4", 1800000, 3300000, tps65217_vsel_to_uv2,
-                       tps65217_uv_to_vsel2, NULL, 32,
-                       TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN,
-                       TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK),
+                       tps65217_uv_to_vsel2),
 };
 
-static int tps65217_pmic_is_enabled(struct regulator_dev *dev)
-{
-       int ret;
-       struct tps65217 *tps = rdev_get_drvdata(dev);
-       unsigned int data, rid = rdev_get_id(dev);
-
-       if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
-               return -EINVAL;
-
-       ret = tps65217_reg_read(tps, TPS65217_REG_ENABLE, &data);
-       if (ret)
-               return ret;
-
-       return (data & tps->info[rid]->enable_mask) ? 1 : 0;
-}
-
 static int tps65217_pmic_enable(struct regulator_dev *dev)
 {
        struct tps65217 *tps = rdev_get_drvdata(dev);
@@ -177,9 +151,8 @@ static int tps65217_pmic_enable(struct regulator_dev *dev)
 
        /* Enable the regulator and password protection is level 1 */
        return tps65217_set_bits(tps, TPS65217_REG_ENABLE,
-                               tps->info[rid]->enable_mask,
-                               tps->info[rid]->enable_mask,
-                               TPS65217_PROTECT_L1);
+                                dev->desc->enable_mask, dev->desc->enable_mask,
+                                TPS65217_PROTECT_L1);
 }
 
 static int tps65217_pmic_disable(struct regulator_dev *dev)
@@ -192,25 +165,7 @@ static int tps65217_pmic_disable(struct regulator_dev *dev)
 
        /* Disable the regulator and password protection is level 1 */
        return tps65217_clear_bits(tps, TPS65217_REG_ENABLE,
-                       tps->info[rid]->enable_mask, TPS65217_PROTECT_L1);
-}
-
-static int tps65217_pmic_get_voltage_sel(struct regulator_dev *dev)
-{
-       int ret;
-       struct tps65217 *tps = rdev_get_drvdata(dev);
-       unsigned int selector, rid = rdev_get_id(dev);
-
-       if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
-               return -EINVAL;
-
-       ret = tps65217_reg_read(tps, tps->info[rid]->set_vout_reg, &selector);
-       if (ret)
-               return ret;
-
-       selector &= tps->info[rid]->set_vout_mask;
-
-       return selector;
+                                  dev->desc->enable_mask, TPS65217_PROTECT_L1);
 }
 
 static int tps65217_pmic_set_voltage_sel(struct regulator_dev *dev,
@@ -221,8 +176,7 @@ static int tps65217_pmic_set_voltage_sel(struct regulator_dev *dev,
        unsigned int rid = rdev_get_id(dev);
 
        /* Set the voltage based on vsel value and write protect level is 2 */
-       ret = tps65217_set_bits(tps, tps->info[rid]->set_vout_reg,
-                               tps->info[rid]->set_vout_mask,
+       ret = tps65217_set_bits(tps, dev->desc->vsel_reg, dev->desc->vsel_mask,
                                selector, TPS65217_PROTECT_L2);
 
        /* Set GO bit for DCDCx to initiate voltage transistion */
@@ -252,10 +206,10 @@ static int tps65217_pmic_map_voltage(struct regulator_dev *dev,
        if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
                return -EINVAL;
 
-       if (min_uV < tps->info[rid]->min_uV || min_uV > tps->info[rid]->max_uV)
-               return -EINVAL;
+       if (min_uV < tps->info[rid]->min_uV)
+               min_uV = tps->info[rid]->min_uV;
 
-       if (max_uV < tps->info[rid]->min_uV || max_uV > tps->info[rid]->max_uV)
+       if (max_uV < tps->info[rid]->min_uV || min_uV > tps->info[rid]->max_uV)
                return -EINVAL;
 
        ret = tps->info[rid]->uv_to_vsel(min_uV, &sel);
@@ -274,21 +228,18 @@ static int tps65217_pmic_list_voltage(struct regulator_dev *dev,
        if (rid < TPS65217_DCDC_1 || rid > TPS65217_LDO_4)
                return -EINVAL;
 
-       if (selector >= tps->info[rid]->table_len)
+       if (selector >= dev->desc->n_voltages)
                return -EINVAL;
 
-       if (tps->info[rid]->table)
-               return tps->info[rid]->table[selector];
-
        return tps->info[rid]->vsel_to_uv(selector);
 }
 
 /* Operations permitted on DCDCx, LDO2, LDO3 and LDO4 */
 static struct regulator_ops tps65217_pmic_ops = {
-       .is_enabled             = tps65217_pmic_is_enabled,
+       .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = tps65217_pmic_enable,
        .disable                = tps65217_pmic_disable,
-       .get_voltage_sel        = tps65217_pmic_get_voltage_sel,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = tps65217_pmic_set_voltage_sel,
        .list_voltage           = tps65217_pmic_list_voltage,
        .map_voltage            = tps65217_pmic_map_voltage,
@@ -296,22 +247,38 @@ static struct regulator_ops tps65217_pmic_ops = {
 
 /* Operations permitted on LDO1 */
 static struct regulator_ops tps65217_pmic_ldo1_ops = {
-       .is_enabled             = tps65217_pmic_is_enabled,
+       .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = tps65217_pmic_enable,
        .disable                = tps65217_pmic_disable,
-       .get_voltage_sel        = tps65217_pmic_get_voltage_sel,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
        .set_voltage_sel        = tps65217_pmic_set_voltage_sel,
-       .list_voltage           = tps65217_pmic_list_voltage,
+       .list_voltage           = regulator_list_voltage_table,
 };
 
 static const struct regulator_desc regulators[] = {
-       TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, tps65217_pmic_ops, 64),
-       TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, tps65217_pmic_ops, 64),
-       TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, tps65217_pmic_ops, 64),
-       TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, tps65217_pmic_ldo1_ops, 16),
-       TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, tps65217_pmic_ops, 64),
-       TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, tps65217_pmic_ops, 32),
-       TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, tps65217_pmic_ops, 32),
+       TPS65217_REGULATOR("DCDC1", TPS65217_DCDC_1, tps65217_pmic_ops, 64,
+                          TPS65217_REG_DEFDCDC1, TPS65217_DEFDCDCX_DCDC_MASK,
+                          TPS65217_ENABLE_DC1_EN, NULL),
+       TPS65217_REGULATOR("DCDC2", TPS65217_DCDC_2, tps65217_pmic_ops, 64,
+                          TPS65217_REG_DEFDCDC2, TPS65217_DEFDCDCX_DCDC_MASK,
+                          TPS65217_ENABLE_DC2_EN, NULL),
+       TPS65217_REGULATOR("DCDC3", TPS65217_DCDC_3, tps65217_pmic_ops, 64,
+                          TPS65217_REG_DEFDCDC3, TPS65217_DEFDCDCX_DCDC_MASK,
+                          TPS65217_ENABLE_DC3_EN, NULL),
+       TPS65217_REGULATOR("LDO1", TPS65217_LDO_1, tps65217_pmic_ldo1_ops, 16,
+                          TPS65217_REG_DEFLDO1, TPS65217_DEFLDO1_LDO1_MASK,
+                          TPS65217_ENABLE_LDO1_EN, LDO1_VSEL_table),
+       TPS65217_REGULATOR("LDO2", TPS65217_LDO_2, tps65217_pmic_ops, 64,
+                          TPS65217_REG_DEFLDO2, TPS65217_DEFLDO2_LDO2_MASK,
+                          TPS65217_ENABLE_LDO2_EN, NULL),
+       TPS65217_REGULATOR("LDO3", TPS65217_LDO_3, tps65217_pmic_ops, 32,
+                          TPS65217_REG_DEFLS1, TPS65217_DEFLDO3_LDO3_MASK,
+                          TPS65217_ENABLE_LS1_EN | TPS65217_DEFLDO3_LDO3_EN,
+                          NULL),
+       TPS65217_REGULATOR("LDO4", TPS65217_LDO_4, tps65217_pmic_ops, 32,
+                          TPS65217_REG_DEFLS2, TPS65217_DEFLDO4_LDO4_MASK,
+                          TPS65217_ENABLE_LS2_EN | TPS65217_DEFLDO4_LDO4_EN,
+                          NULL),
 };
 
 static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
@@ -326,6 +293,7 @@ static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
        tps->info[pdev->id] = info;
 
        config.dev = &pdev->dev;
+       config.of_node = pdev->dev.of_node;
        config.init_data = pdev->dev.platform_data;
        config.driver_data = tps;
 
index 1b299aacf22ffa2023652c5a45cf61ac1a1c1416..947ece933d901fa75ef54e286979d12f02dea7ce 100644 (file)
 #define N_SWITCH               2
 #define N_REGULATORS           (N_DCDC + N_LDO + N_SWITCH)
 
-#define FIXED_ILIMSEL          BIT(0)
-#define FIXED_VOLTAGE          BIT(1)
-
 #define CMD_READ(reg)          ((reg) << 6)
 #define CMD_WRITE(reg)         (BIT(5) | (reg) << 6)
 #define STAT_CLK               BIT(3)
@@ -129,12 +126,9 @@ struct field {
 struct supply_info {
        const char      *name;
        int             n_voltages;
-       const int       *voltages;
-       int             fixed_voltage;
+       const unsigned int *voltages;
        int             n_ilimsels;
-       const int       *ilimsels;
-       int             fixed_ilimsel;
-       int             flags;
+       const unsigned int *ilimsels;
        struct field    enable, voltage, ilimsel;
 };
 
@@ -307,7 +301,7 @@ static int write_field(struct tps6524x *hw, const struct field *field,
                                    val << field->shift);
 }
 
-static const int dcdc1_voltages[] = {
+static const unsigned int dcdc1_voltages[] = {
         800000,  825000,  850000,  875000,
         900000,  925000,  950000,  975000,
        1000000, 1025000, 1050000, 1075000,
@@ -318,7 +312,7 @@ static const int dcdc1_voltages[] = {
        1500000, 1525000, 1550000, 1575000,
 };
 
-static const int dcdc2_voltages[] = {
+static const unsigned int dcdc2_voltages[] = {
        1400000, 1450000, 1500000, 1550000,
        1600000, 1650000, 1700000, 1750000,
        1800000, 1850000, 1900000, 1950000,
@@ -329,7 +323,7 @@ static const int dcdc2_voltages[] = {
        2800000, 2850000, 2900000, 2950000,
 };
 
-static const int dcdc3_voltages[] = {
+static const unsigned int dcdc3_voltages[] = {
        2400000, 2450000, 2500000, 2550000, 2600000,
        2650000, 2700000, 2750000, 2800000, 2850000,
        2900000, 2950000, 3000000, 3050000, 3100000,
@@ -337,38 +331,54 @@ static const int dcdc3_voltages[] = {
        3400000, 3450000, 3500000, 3550000, 3600000,
 };
 
-static const int ldo1_voltages[] = {
+static const unsigned int ldo1_voltages[] = {
        4300000, 4350000, 4400000, 4450000,
        4500000, 4550000, 4600000, 4650000,
        4700000, 4750000, 4800000, 4850000,
        4900000, 4950000, 5000000, 5050000,
 };
 
-static const int ldo2_voltages[] = {
+static const unsigned int ldo2_voltages[] = {
        1100000, 1150000, 1200000, 1250000,
        1300000, 1700000, 1750000, 1800000,
        1850000, 1900000, 3150000, 3200000,
        3250000, 3300000, 3350000, 3400000,
 };
 
-static const int ldo_ilimsel[] = {
+static const unsigned int fixed_5000000_voltage[] = {
+       5000000
+};
+
+static const unsigned int ldo_ilimsel[] = {
        400000, 1500000
 };
 
-static const int usb_ilimsel[] = {
+static const unsigned int usb_ilimsel[] = {
        200000, 400000, 800000, 1000000
 };
 
+static const unsigned int fixed_2400000_ilimsel[] = {
+       2400000
+};
+
+static const unsigned int fixed_1200000_ilimsel[] = {
+       1200000
+};
+
+static const unsigned int fixed_400000_ilimsel[] = {
+       400000
+};
+
 #define __MK_FIELD(_reg, _mask, _shift) \
        { .reg = (_reg), .mask = (_mask), .shift = (_shift), }
 
 static const struct supply_info supply_info[N_REGULATORS] = {
        {
                .name           = "DCDC1",
-               .flags          = FIXED_ILIMSEL,
                .n_voltages     = ARRAY_SIZE(dcdc1_voltages),
                .voltages       = dcdc1_voltages,
-               .fixed_ilimsel  = 2400000,
+               .n_ilimsels     = ARRAY_SIZE(fixed_2400000_ilimsel),
+               .ilimsels       = fixed_2400000_ilimsel,
                .enable         = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
                                             DCDCDCDC1_EN_SHIFT),
                .voltage        = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
@@ -376,10 +386,10 @@ static const struct supply_info supply_info[N_REGULATORS] = {
        },
        {
                .name           = "DCDC2",
-               .flags          = FIXED_ILIMSEL,
                .n_voltages     = ARRAY_SIZE(dcdc2_voltages),
                .voltages       = dcdc2_voltages,
-               .fixed_ilimsel  = 1200000,
+               .n_ilimsels     = ARRAY_SIZE(fixed_1200000_ilimsel),
+               .ilimsels       = fixed_1200000_ilimsel,
                .enable         = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
                                             DCDCDCDC2_EN_SHIFT),
                .voltage        = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
@@ -387,10 +397,10 @@ static const struct supply_info supply_info[N_REGULATORS] = {
        },
        {
                .name           = "DCDC3",
-               .flags          = FIXED_ILIMSEL,
                .n_voltages     = ARRAY_SIZE(dcdc3_voltages),
                .voltages       = dcdc3_voltages,
-               .fixed_ilimsel  = 1200000,
+               .n_ilimsels     = ARRAY_SIZE(fixed_1200000_ilimsel),
+               .ilimsels       = fixed_1200000_ilimsel,
                .enable         = __MK_FIELD(REG_DCDC_EN, DCDCDCDC_EN_MASK,
                                        DCDCDCDC3_EN_SHIFT),
                .voltage        = __MK_FIELD(REG_DCDC_SET, DCDC_VDCDC_MASK,
@@ -424,8 +434,8 @@ static const struct supply_info supply_info[N_REGULATORS] = {
        },
        {
                .name           = "USB",
-               .flags          = FIXED_VOLTAGE,
-               .fixed_voltage  = 5000000,
+               .n_voltages     = ARRAY_SIZE(fixed_5000000_voltage),
+               .voltages       = fixed_5000000_voltage,
                .n_ilimsels     = ARRAY_SIZE(usb_ilimsel),
                .ilimsels       = usb_ilimsel,
                .enable         = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
@@ -435,29 +445,15 @@ static const struct supply_info supply_info[N_REGULATORS] = {
        },
        {
                .name           = "LCD",
-               .flags          = FIXED_VOLTAGE | FIXED_ILIMSEL,
-               .fixed_voltage  = 5000000,
-               .fixed_ilimsel  =  400000,
+               .n_voltages     = ARRAY_SIZE(fixed_5000000_voltage),
+               .voltages       = fixed_5000000_voltage,
+               .n_ilimsels     = ARRAY_SIZE(fixed_400000_ilimsel),
+               .ilimsels       = fixed_400000_ilimsel,
                .enable         = __MK_FIELD(REG_BLOCK_EN, BLOCK_MASK,
                                             BLOCK_LCD_SHIFT),
        },
 };
 
-static int list_voltage(struct regulator_dev *rdev, unsigned selector)
-{
-       const struct supply_info *info;
-       struct tps6524x *hw;
-
-       hw      = rdev_get_drvdata(rdev);
-       info    = &supply_info[rdev_get_id(rdev)];
-
-       if (info->flags & FIXED_VOLTAGE)
-               return selector ? -EINVAL : info->fixed_voltage;
-
-       return ((selector < info->n_voltages) ?
-               info->voltages[selector] : -EINVAL);
-}
-
 static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
 {
        const struct supply_info *info;
@@ -466,7 +462,7 @@ static int set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
        hw      = rdev_get_drvdata(rdev);
        info    = &supply_info[rdev_get_id(rdev)];
 
-       if (info->flags & FIXED_VOLTAGE)
+       if (rdev->desc->n_voltages == 1)
                return -EINVAL;
 
        return write_field(hw, &info->voltage, selector);
@@ -481,7 +477,7 @@ static int get_voltage_sel(struct regulator_dev *rdev)
        hw      = rdev_get_drvdata(rdev);
        info    = &supply_info[rdev_get_id(rdev)];
 
-       if (info->flags & FIXED_VOLTAGE)
+       if (rdev->desc->n_voltages == 1)
                return 0;
 
        ret = read_field(hw, &info->voltage);
@@ -503,7 +499,7 @@ static int set_current_limit(struct regulator_dev *rdev, int min_uA,
        hw      = rdev_get_drvdata(rdev);
        info    = &supply_info[rdev_get_id(rdev)];
 
-       if (info->flags & FIXED_ILIMSEL)
+       if (info->n_ilimsels == 1)
                return -EINVAL;
 
        for (i = 0; i < info->n_ilimsels; i++)
@@ -526,8 +522,8 @@ static int get_current_limit(struct regulator_dev *rdev)
        hw      = rdev_get_drvdata(rdev);
        info    = &supply_info[rdev_get_id(rdev)];
 
-       if (info->flags & FIXED_ILIMSEL)
-               return info->fixed_ilimsel;
+       if (info->n_ilimsels == 1)
+               return info->ilimsels[0];
 
        ret = read_field(hw, &info->ilimsel);
        if (ret < 0)
@@ -577,7 +573,7 @@ static struct regulator_ops regulator_ops = {
        .disable                = disable_supply,
        .get_voltage_sel        = get_voltage_sel,
        .set_voltage_sel        = set_voltage_sel,
-       .list_voltage           = list_voltage,
+       .list_voltage           = regulator_list_voltage_table,
        .set_current_limit      = set_current_limit,
        .get_current_limit      = get_current_limit,
 };
@@ -629,13 +625,11 @@ static int __devinit pmic_probe(struct spi_device *spi)
                hw->desc[i].name        = info->name;
                hw->desc[i].id          = i;
                hw->desc[i].n_voltages  = info->n_voltages;
+               hw->desc[i].volt_table  = info->voltages;
                hw->desc[i].ops         = &regulator_ops;
                hw->desc[i].type        = REGULATOR_VOLTAGE;
                hw->desc[i].owner       = THIS_MODULE;
 
-               if (info->flags & FIXED_VOLTAGE)
-                       hw->desc[i].n_voltages = 1;
-
                config.dev = dev;
                config.init_data = init_data;
                config.driver_data = hw;
index c0a214575380020473f593f43beb8c34bbe7fed5..e6da90ab5153dedd64ebd96137776f652af7d152 100644 (file)
@@ -63,8 +63,6 @@ struct tps6586x_regulator {
        int enable_bit[2];
        int enable_reg[2];
 
-       int *voltages;
-
        /* for DVM regulators */
        int go_reg;
        int go_bit;
@@ -72,22 +70,9 @@ struct tps6586x_regulator {
 
 static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev)
 {
-       return rdev_get_dev(rdev)->parent->parent;
+       return rdev_get_dev(rdev)->parent;
 }
 
-static int tps6586x_list_voltage(struct regulator_dev *rdev, unsigned selector)
-{
-       struct tps6586x_regulator *info = rdev_get_drvdata(rdev);
-       int rid = rdev_get_id(rdev);
-
-       /* LDO0 has minimal voltage 1.2V rather than 1.25V */
-       if ((rid == TPS6586X_ID_LDO_0) && (selector == 0))
-               return (info->voltages[0] - 50) * 1000;
-
-       return info->voltages[selector] * 1000;
-}
-
-
 static int tps6586x_set_voltage_sel(struct regulator_dev *rdev,
                                    unsigned selector)
 {
@@ -168,7 +153,7 @@ static int tps6586x_regulator_is_enabled(struct regulator_dev *rdev)
 }
 
 static struct regulator_ops tps6586x_regulator_ops = {
-       .list_voltage = tps6586x_list_voltage,
+       .list_voltage = regulator_list_voltage_table,
        .get_voltage_sel = tps6586x_get_voltage_sel,
        .set_voltage_sel = tps6586x_set_voltage_sel,
 
@@ -177,39 +162,45 @@ static struct regulator_ops tps6586x_regulator_ops = {
        .disable = tps6586x_regulator_disable,
 };
 
-static int tps6586x_ldo_voltages[] = {
-       1250, 1500, 1800, 2500, 2700, 2850, 3100, 3300,
+static const unsigned int tps6586x_ldo0_voltages[] = {
+       1200000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
+};
+
+static const unsigned int tps6586x_ldo4_voltages[] = {
+       1700000, 1725000, 1750000, 1775000, 1800000, 1825000, 1850000, 1875000,
+       1900000, 1925000, 1950000, 1975000, 2000000, 2025000, 2050000, 2075000,
+       2100000, 2125000, 2150000, 2175000, 2200000, 2225000, 2250000, 2275000,
+       2300000, 2325000, 2350000, 2375000, 2400000, 2425000, 2450000, 2475000,
 };
 
-static int tps6586x_ldo4_voltages[] = {
-       1700, 1725, 1750, 1775, 1800, 1825, 1850, 1875,
-       1900, 1925, 1950, 1975, 2000, 2025, 2050, 2075,
-       2100, 2125, 2150, 2175, 2200, 2225, 2250, 2275,
-       2300, 2325, 2350, 2375, 2400, 2425, 2450, 2475,
+static const unsigned int tps6586x_ldo_voltages[] = {
+       1250000, 1500000, 1800000, 2500000, 2700000, 2850000, 3100000, 3300000,
 };
 
-static int tps6586x_sm2_voltages[] = {
-       3000, 3050, 3100, 3150, 3200, 3250, 3300, 3350,
-       3400, 3450, 3500, 3550, 3600, 3650, 3700, 3750,
-       3800, 3850, 3900, 3950, 4000, 4050, 4100, 4150,
-       4200, 4250, 4300, 4350, 4400, 4450, 4500, 4550,
+static const unsigned int tps6586x_sm2_voltages[] = {
+       3000000, 3050000, 3100000, 3150000, 3200000, 3250000, 3300000, 3350000,
+       3400000, 3450000, 3500000, 3550000, 3600000, 3650000, 3700000, 3750000,
+       3800000, 3850000, 3900000, 3950000, 4000000, 4050000, 4100000, 4150000,
+       4200000, 4250000, 4300000, 4350000, 4400000, 4450000, 4500000, 4550000,
 };
 
-static int tps6586x_dvm_voltages[] = {
-        725,  750,  775,  800,  825,  850,  875,  900,
-        925,  950,  975, 1000, 1025, 1050, 1075, 1100,
-       1125, 1150, 1175, 1200, 1225, 1250, 1275, 1300,
-       1325, 1350, 1375, 1400, 1425, 1450, 1475, 1500,
+static const unsigned int tps6586x_dvm_voltages[] = {
+        725000,  750000,  775000,  800000,  825000,  850000,  875000,  900000,
+        925000,  950000,  975000, 1000000, 1025000, 1050000, 1075000, 1100000,
+       1125000, 1150000, 1175000, 1200000, 1225000, 1250000, 1275000, 1300000,
+       1325000, 1350000, 1375000, 1400000, 1425000, 1450000, 1475000, 1500000,
 };
 
-#define TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits,             \
+#define TPS6586X_REGULATOR(_id, _pin_name, vdata, vreg, shift, nbits,  \
                           ereg0, ebit0, ereg1, ebit1)                  \
        .desc   = {                                                     \
+               .supply_name = _pin_name,                               \
                .name   = "REG-" #_id,                                  \
                .ops    = &tps6586x_regulator_ops,                      \
                .type   = REGULATOR_VOLTAGE,                            \
                .id     = TPS6586X_ID_##_id,                            \
                .n_voltages = ARRAY_SIZE(tps6586x_##vdata##_voltages),  \
+               .volt_table = tps6586x_##vdata##_voltages,              \
                .owner  = THIS_MODULE,                                  \
        },                                                              \
        .volt_reg       = TPS6586X_##vreg,                              \
@@ -218,44 +209,45 @@ static int tps6586x_dvm_voltages[] = {
        .enable_reg[0]  = TPS6586X_SUPPLY##ereg0,                       \
        .enable_bit[0]  = (ebit0),                                      \
        .enable_reg[1]  = TPS6586X_SUPPLY##ereg1,                       \
-       .enable_bit[1]  = (ebit1),                                      \
-       .voltages       = tps6586x_##vdata##_voltages,
+       .enable_bit[1]  = (ebit1),
 
 #define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                     \
        .go_reg = TPS6586X_##goreg,                                     \
        .go_bit = (gobit),
 
-#define TPS6586X_LDO(_id, vdata, vreg, shift, nbits,                   \
+#define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits,           \
                     ereg0, ebit0, ereg1, ebit1)                        \
 {                                                                      \
-       TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits,              \
+       TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits,      \
                           ereg0, ebit0, ereg1, ebit1)                  \
 }
 
-#define TPS6586X_DVM(_id, vdata, vreg, shift, nbits,                   \
+#define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits,           \
                     ereg0, ebit0, ereg1, ebit1, goreg, gobit)          \
 {                                                                      \
-       TPS6586X_REGULATOR(_id, vdata, vreg, shift, nbits,              \
+       TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits,      \
                           ereg0, ebit0, ereg1, ebit1)                  \
        TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit)                      \
 }
 
 static struct tps6586x_regulator tps6586x_regulator[] = {
-       TPS6586X_LDO(LDO_0, ldo, SUPPLYV1, 5, 3, ENC, 0, END, 0),
-       TPS6586X_LDO(LDO_3, ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2),
-       TPS6586X_LDO(LDO_5, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
-       TPS6586X_LDO(LDO_6, ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
-       TPS6586X_LDO(LDO_7, ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
-       TPS6586X_LDO(LDO_8, ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
-       TPS6586X_LDO(LDO_9, ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
-       TPS6586X_LDO(LDO_RTC, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
-       TPS6586X_LDO(LDO_1, dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
-       TPS6586X_LDO(SM_2, sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
-
-       TPS6586X_DVM(LDO_2, dvm, LDO2BV1, 0, 5, ENA, 3, ENB, 3, VCC2, 6),
-       TPS6586X_DVM(LDO_4, ldo4, LDO4V1, 0, 5, ENC, 3, END, 3, VCC1, 6),
-       TPS6586X_DVM(SM_0, dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2),
-       TPS6586X_DVM(SM_1, dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0),
+       TPS6586X_LDO(LDO_0, "vinldo01", ldo0, SUPPLYV1, 5, 3, ENC, 0, END, 0),
+       TPS6586X_LDO(LDO_3, "vinldo23", ldo, SUPPLYV4, 0, 3, ENC, 2, END, 2),
+       TPS6586X_LDO(LDO_5, NULL, ldo, SUPPLYV6, 0, 3, ENE, 6, ENE, 6),
+       TPS6586X_LDO(LDO_6, "vinldo678", ldo, SUPPLYV3, 0, 3, ENC, 4, END, 4),
+       TPS6586X_LDO(LDO_7, "vinldo678", ldo, SUPPLYV3, 3, 3, ENC, 5, END, 5),
+       TPS6586X_LDO(LDO_8, "vinldo678", ldo, SUPPLYV2, 5, 3, ENC, 6, END, 6),
+       TPS6586X_LDO(LDO_9, "vinldo9", ldo, SUPPLYV6, 3, 3, ENE, 7, ENE, 7),
+       TPS6586X_LDO(LDO_RTC, NULL, ldo, SUPPLYV4, 3, 3, V4, 7, V4, 7),
+       TPS6586X_LDO(LDO_1, "vinldo01", dvm, SUPPLYV1, 0, 5, ENC, 1, END, 1),
+       TPS6586X_LDO(SM_2, "sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7),
+
+       TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3,
+                                       ENB, 3, VCC2, 6),
+       TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3,
+                                       END, 3, VCC1, 6),
+       TPS6586X_DVM(SM_0, "sm0", dvm, SM0V1, 0, 5, ENA, 1, ENB, 1, VCC1, 2),
+       TPS6586X_DVM(SM_1, "sm1", dvm, SM1V1, 0, 5, ENA, 0, ENB, 0, VCC1, 0),
 };
 
 /*
@@ -362,7 +354,7 @@ static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
        if (err)
                return err;
 
-       config.dev = &pdev->dev;
+       config.dev = pdev->dev.parent;
        config.of_node = pdev->dev.of_node;
        config.init_data = pdev->dev.platform_data;
        config.driver_data = ri;
index 6bf864b4bdf67e8ddd860ed16fe0e7248e65318b..793adda560c3c3364c2053cdb152974fc2a2f02b 100644 (file)
                        TPS65910_SLEEP_CONTROL_EXT_INPUT_EN3 |          \
                        TPS65911_SLEEP_CONTROL_EXT_INPUT_SLEEP)
 
-/* supported VIO voltages in millivolts */
-static const u16 VIO_VSEL_table[] = {
-       1500, 1800, 2500, 3300,
+/* supported VIO voltages in microvolts */
+static const unsigned int VIO_VSEL_table[] = {
+       1500000, 1800000, 2500000, 3300000,
 };
 
 /* VSEL tables for TPS65910 specific LDOs and dcdc's */
 
-/* supported VDD3 voltages in millivolts */
-static const u16 VDD3_VSEL_table[] = {
-       5000,
+/* supported VDD3 voltages in microvolts */
+static const unsigned int VDD3_VSEL_table[] = {
+       5000000,
 };
 
-/* supported VDIG1 voltages in millivolts */
-static const u16 VDIG1_VSEL_table[] = {
-       1200, 1500, 1800, 2700,
+/* supported VDIG1 voltages in microvolts */
+static const unsigned int VDIG1_VSEL_table[] = {
+       1200000, 1500000, 1800000, 2700000,
 };
 
-/* supported VDIG2 voltages in millivolts */
-static const u16 VDIG2_VSEL_table[] = {
-       1000, 1100, 1200, 1800,
+/* supported VDIG2 voltages in microvolts */
+static const unsigned int VDIG2_VSEL_table[] = {
+       1000000, 1100000, 1200000, 1800000,
 };
 
-/* supported VPLL voltages in millivolts */
-static const u16 VPLL_VSEL_table[] = {
-       1000, 1100, 1800, 2500,
+/* supported VPLL voltages in microvolts */
+static const unsigned int VPLL_VSEL_table[] = {
+       1000000, 1100000, 1800000, 2500000,
 };
 
-/* supported VDAC voltages in millivolts */
-static const u16 VDAC_VSEL_table[] = {
-       1800, 2600, 2800, 2850,
+/* supported VDAC voltages in microvolts */
+static const unsigned int VDAC_VSEL_table[] = {
+       1800000, 2600000, 2800000, 2850000,
 };
 
-/* supported VAUX1 voltages in millivolts */
-static const u16 VAUX1_VSEL_table[] = {
-       1800, 2500, 2800, 2850,
+/* supported VAUX1 voltages in microvolts */
+static const unsigned int VAUX1_VSEL_table[] = {
+       1800000, 2500000, 2800000, 2850000,
 };
 
-/* supported VAUX2 voltages in millivolts */
-static const u16 VAUX2_VSEL_table[] = {
-       1800, 2800, 2900, 3300,
+/* supported VAUX2 voltages in microvolts */
+static const unsigned int VAUX2_VSEL_table[] = {
+       1800000, 2800000, 2900000, 3300000,
 };
 
-/* supported VAUX33 voltages in millivolts */
-static const u16 VAUX33_VSEL_table[] = {
-       1800, 2000, 2800, 3300,
+/* supported VAUX33 voltages in microvolts */
+static const unsigned int VAUX33_VSEL_table[] = {
+       1800000, 2000000, 2800000, 3300000,
 };
 
-/* supported VMMC voltages in millivolts */
-static const u16 VMMC_VSEL_table[] = {
-       1800, 2800, 3000, 3300,
+/* supported VMMC voltages in microvolts */
+static const unsigned int VMMC_VSEL_table[] = {
+       1800000, 2800000, 3000000, 3300000,
 };
 
 struct tps_info {
        const char *name;
-       unsigned min_uV;
-       unsigned max_uV;
+       const char *vin_name;
        u8 n_voltages;
-       const u16 *voltage_table;
+       const unsigned int *voltage_table;
        int enable_time_us;
 };
 
 static struct tps_info tps65910_regs[] = {
        {
                .name = "vrtc",
+               .vin_name = "vcc7",
                .enable_time_us = 2200,
        },
        {
                .name = "vio",
-               .min_uV = 1500000,
-               .max_uV = 3300000,
+               .vin_name = "vccio",
                .n_voltages = ARRAY_SIZE(VIO_VSEL_table),
                .voltage_table = VIO_VSEL_table,
                .enable_time_us = 350,
        },
        {
                .name = "vdd1",
-               .min_uV = 600000,
-               .max_uV = 4500000,
+               .vin_name = "vcc1",
                .enable_time_us = 350,
        },
        {
                .name = "vdd2",
-               .min_uV = 600000,
-               .max_uV = 4500000,
+               .vin_name = "vcc2",
                .enable_time_us = 350,
        },
        {
                .name = "vdd3",
-               .min_uV = 5000000,
-               .max_uV = 5000000,
                .n_voltages = ARRAY_SIZE(VDD3_VSEL_table),
                .voltage_table = VDD3_VSEL_table,
                .enable_time_us = 200,
        },
        {
                .name = "vdig1",
-               .min_uV = 1200000,
-               .max_uV = 2700000,
+               .vin_name = "vcc6",
                .n_voltages = ARRAY_SIZE(VDIG1_VSEL_table),
                .voltage_table = VDIG1_VSEL_table,
                .enable_time_us = 100,
        },
        {
                .name = "vdig2",
-               .min_uV = 1000000,
-               .max_uV = 1800000,
+               .vin_name = "vcc6",
                .n_voltages = ARRAY_SIZE(VDIG2_VSEL_table),
                .voltage_table = VDIG2_VSEL_table,
                .enable_time_us = 100,
        },
        {
                .name = "vpll",
-               .min_uV = 1000000,
-               .max_uV = 2500000,
+               .vin_name = "vcc5",
                .n_voltages = ARRAY_SIZE(VPLL_VSEL_table),
                .voltage_table = VPLL_VSEL_table,
                .enable_time_us = 100,
        },
        {
                .name = "vdac",
-               .min_uV = 1800000,
-               .max_uV = 2850000,
+               .vin_name = "vcc5",
                .n_voltages = ARRAY_SIZE(VDAC_VSEL_table),
                .voltage_table = VDAC_VSEL_table,
                .enable_time_us = 100,
        },
        {
                .name = "vaux1",
-               .min_uV = 1800000,
-               .max_uV = 2850000,
+               .vin_name = "vcc4",
                .n_voltages = ARRAY_SIZE(VAUX1_VSEL_table),
                .voltage_table = VAUX1_VSEL_table,
                .enable_time_us = 100,
        },
        {
                .name = "vaux2",
-               .min_uV = 1800000,
-               .max_uV = 3300000,
+               .vin_name = "vcc4",
                .n_voltages = ARRAY_SIZE(VAUX2_VSEL_table),
                .voltage_table = VAUX2_VSEL_table,
                .enable_time_us = 100,
        },
        {
                .name = "vaux33",
-               .min_uV = 1800000,
-               .max_uV = 3300000,
+               .vin_name = "vcc3",
                .n_voltages = ARRAY_SIZE(VAUX33_VSEL_table),
                .voltage_table = VAUX33_VSEL_table,
                .enable_time_us = 100,
        },
        {
                .name = "vmmc",
-               .min_uV = 1800000,
-               .max_uV = 3300000,
+               .vin_name = "vcc3",
                .n_voltages = ARRAY_SIZE(VMMC_VSEL_table),
                .voltage_table = VMMC_VSEL_table,
                .enable_time_us = 100,
@@ -194,91 +181,79 @@ static struct tps_info tps65910_regs[] = {
 static struct tps_info tps65911_regs[] = {
        {
                .name = "vrtc",
+               .vin_name = "vcc7",
                .enable_time_us = 2200,
        },
        {
                .name = "vio",
-               .min_uV = 1500000,
-               .max_uV = 3300000,
+               .vin_name = "vccio",
                .n_voltages = ARRAY_SIZE(VIO_VSEL_table),
                .voltage_table = VIO_VSEL_table,
                .enable_time_us = 350,
        },
        {
                .name = "vdd1",
-               .min_uV = 600000,
-               .max_uV = 4500000,
-               .n_voltages = 73,
+               .vin_name = "vcc1",
+               .n_voltages = 0x4C,
                .enable_time_us = 350,
        },
        {
                .name = "vdd2",
-               .min_uV = 600000,
-               .max_uV = 4500000,
-               .n_voltages = 73,
+               .vin_name = "vcc2",
+               .n_voltages = 0x4C,
                .enable_time_us = 350,
        },
        {
                .name = "vddctrl",
-               .min_uV = 600000,
-               .max_uV = 1400000,
-               .n_voltages = 65,
+               .n_voltages = 0x44,
                .enable_time_us = 900,
        },
        {
                .name = "ldo1",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 47,
+               .vin_name = "vcc6",
+               .n_voltages = 0x33,
                .enable_time_us = 420,
        },
        {
                .name = "ldo2",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 47,
+               .vin_name = "vcc6",
+               .n_voltages = 0x33,
                .enable_time_us = 420,
        },
        {
                .name = "ldo3",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 24,
+               .vin_name = "vcc5",
+               .n_voltages = 0x1A,
                .enable_time_us = 230,
        },
        {
                .name = "ldo4",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 47,
+               .vin_name = "vcc5",
+               .n_voltages = 0x33,
                .enable_time_us = 230,
        },
        {
                .name = "ldo5",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 24,
+               .vin_name = "vcc4",
+               .n_voltages = 0x1A,
                .enable_time_us = 230,
        },
        {
                .name = "ldo6",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 24,
+               .vin_name = "vcc3",
+               .n_voltages = 0x1A,
                .enable_time_us = 230,
        },
        {
                .name = "ldo7",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 24,
+               .vin_name = "vcc3",
+               .n_voltages = 0x1A,
                .enable_time_us = 230,
        },
        {
                .name = "ldo8",
-               .min_uV = 1000000,
-               .max_uV = 3300000,
-               .n_voltages = 24,
+               .vin_name = "vcc3",
+               .n_voltages = 0x1A,
                .enable_time_us = 230,
        },
 };
@@ -321,7 +296,6 @@ struct tps65910_reg {
        struct tps65910 *mfd;
        struct regulator_dev **rdev;
        struct tps_info **info;
-       struct mutex mutex;
        int num_regulators;
        int mode;
        int  (*get_ctrl_reg)(int);
@@ -329,71 +303,6 @@ struct tps65910_reg {
        unsigned int board_ext_control[TPS65910_NUM_REGS];
 };
 
-static inline int tps65910_read(struct tps65910_reg *pmic, u8 reg)
-{
-       unsigned int val;
-       int err;
-
-       err = tps65910_reg_read(pmic->mfd, reg, &val);
-       if (err)
-               return err;
-
-       return val;
-}
-
-static int tps65910_modify_bits(struct tps65910_reg *pmic, u8 reg,
-                                       u8 set_mask, u8 clear_mask)
-{
-       int err, data;
-
-       mutex_lock(&pmic->mutex);
-
-       data = tps65910_read(pmic, reg);
-       if (data < 0) {
-               dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg);
-               err = data;
-               goto out;
-       }
-
-       data &= ~clear_mask;
-       data |= set_mask;
-       err = tps65910_reg_write(pmic->mfd, reg, data);
-       if (err)
-               dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg);
-
-out:
-       mutex_unlock(&pmic->mutex);
-       return err;
-}
-
-static int tps65910_reg_read_locked(struct tps65910_reg *pmic, u8 reg)
-{
-       int data;
-
-       mutex_lock(&pmic->mutex);
-
-       data = tps65910_read(pmic, reg);
-       if (data < 0)
-               dev_err(pmic->mfd->dev, "Read from reg 0x%x failed\n", reg);
-
-       mutex_unlock(&pmic->mutex);
-       return data;
-}
-
-static int tps65910_reg_write_locked(struct tps65910_reg *pmic, u8 reg, u8 val)
-{
-       int err;
-
-       mutex_lock(&pmic->mutex);
-
-       err = tps65910_reg_write(pmic->mfd, reg, val);
-       if (err < 0)
-               dev_err(pmic->mfd->dev, "Write for reg 0x%x failed\n", reg);
-
-       mutex_unlock(&pmic->mutex);
-       return err;
-}
-
 static int tps65910_get_ctrl_register(int id)
 {
        switch (id) {
@@ -462,13 +371,6 @@ static int tps65911_get_ctrl_register(int id)
        }
 }
 
-static int tps65910_enable_time(struct regulator_dev *dev)
-{
-       struct tps65910_reg *pmic = rdev_get_drvdata(dev);
-       int id = rdev_get_id(dev);
-       return pmic->info[id]->enable_time_us;
-}
-
 static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
@@ -481,8 +383,9 @@ static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode)
 
        switch (mode) {
        case REGULATOR_MODE_NORMAL:
-               return tps65910_modify_bits(pmic, reg, LDO_ST_ON_BIT,
-                                                       LDO_ST_MODE_BIT);
+               return tps65910_reg_update_bits(pmic->mfd, reg,
+                                               LDO_ST_MODE_BIT | LDO_ST_ON_BIT,
+                                               LDO_ST_ON_BIT);
        case REGULATOR_MODE_IDLE:
                value = LDO_ST_ON_BIT | LDO_ST_MODE_BIT;
                return tps65910_reg_set_bits(mfd, reg, value);
@@ -496,15 +399,15 @@ static int tps65910_set_mode(struct regulator_dev *dev, unsigned int mode)
 static unsigned int tps65910_get_mode(struct regulator_dev *dev)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
-       int reg, value, id = rdev_get_id(dev);
+       int ret, reg, value, id = rdev_get_id(dev);
 
        reg = pmic->get_ctrl_reg(id);
        if (reg < 0)
                return reg;
 
-       value = tps65910_reg_read_locked(pmic, reg);
-       if (value < 0)
-               return value;
+       ret = tps65910_reg_read(pmic->mfd, reg, &value);
+       if (ret < 0)
+               return ret;
 
        if (!(value & LDO_ST_ON_BIT))
                return REGULATOR_MODE_STANDBY;
@@ -517,33 +420,51 @@ static unsigned int tps65910_get_mode(struct regulator_dev *dev)
 static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
-       int id = rdev_get_id(dev);
+       int ret, id = rdev_get_id(dev);
        int opvsel = 0, srvsel = 0, vselmax = 0, mult = 0, sr = 0;
 
        switch (id) {
        case TPS65910_REG_VDD1:
-               opvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD1_OP);
-               mult = tps65910_reg_read_locked(pmic, TPS65910_VDD1);
+               ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1_OP, &opvsel);
+               if (ret < 0)
+                       return ret;
+               ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1, &mult);
+               if (ret < 0)
+                       return ret;
                mult = (mult & VDD1_VGAIN_SEL_MASK) >> VDD1_VGAIN_SEL_SHIFT;
-               srvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD1_SR);
+               ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD1_SR, &srvsel);
+               if (ret < 0)
+                       return ret;
                sr = opvsel & VDD1_OP_CMD_MASK;
                opvsel &= VDD1_OP_SEL_MASK;
                srvsel &= VDD1_SR_SEL_MASK;
                vselmax = 75;
                break;
        case TPS65910_REG_VDD2:
-               opvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD2_OP);
-               mult = tps65910_reg_read_locked(pmic, TPS65910_VDD2);
+               ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2_OP, &opvsel);
+               if (ret < 0)
+                       return ret;
+               ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2, &mult);
+               if (ret < 0)
+                       return ret;
                mult = (mult & VDD2_VGAIN_SEL_MASK) >> VDD2_VGAIN_SEL_SHIFT;
-               srvsel = tps65910_reg_read_locked(pmic, TPS65910_VDD2_SR);
+               ret = tps65910_reg_read(pmic->mfd, TPS65910_VDD2_SR, &srvsel);
+               if (ret < 0)
+                       return ret;
                sr = opvsel & VDD2_OP_CMD_MASK;
                opvsel &= VDD2_OP_SEL_MASK;
                srvsel &= VDD2_SR_SEL_MASK;
                vselmax = 75;
                break;
        case TPS65911_REG_VDDCTRL:
-               opvsel = tps65910_reg_read_locked(pmic, TPS65911_VDDCTRL_OP);
-               srvsel = tps65910_reg_read_locked(pmic, TPS65911_VDDCTRL_SR);
+               ret = tps65910_reg_read(pmic->mfd, TPS65911_VDDCTRL_OP,
+                                       &opvsel);
+               if (ret < 0)
+                       return ret;
+               ret = tps65910_reg_read(pmic->mfd, TPS65911_VDDCTRL_SR,
+                                       &srvsel);
+               if (ret < 0)
+                       return ret;
                sr = opvsel & VDDCTRL_OP_CMD_MASK;
                opvsel &= VDDCTRL_OP_SEL_MASK;
                srvsel &= VDDCTRL_SR_SEL_MASK;
@@ -577,15 +498,15 @@ static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev)
 static int tps65910_get_voltage_sel(struct regulator_dev *dev)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
-       int reg, value, id = rdev_get_id(dev);
+       int ret, reg, value, id = rdev_get_id(dev);
 
        reg = pmic->get_ctrl_reg(id);
        if (reg < 0)
                return reg;
 
-       value = tps65910_reg_read_locked(pmic, reg);
-       if (value < 0)
-               return value;
+       ret = tps65910_reg_read(pmic->mfd, reg, &value);
+       if (ret < 0)
+               return ret;
 
        switch (id) {
        case TPS65910_REG_VIO:
@@ -609,18 +530,20 @@ static int tps65910_get_voltage_sel(struct regulator_dev *dev)
 
 static int tps65910_get_voltage_vdd3(struct regulator_dev *dev)
 {
-       return 5 * 1000 * 1000;
+       return dev->desc->volt_table[0];
 }
 
 static int tps65911_get_voltage_sel(struct regulator_dev *dev)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
-       int id = rdev_get_id(dev);
-       u8 value, reg;
+       int ret, id = rdev_get_id(dev);
+       unsigned int value, reg;
 
        reg = pmic->get_ctrl_reg(id);
 
-       value = tps65910_reg_read_locked(pmic, reg);
+       ret = tps65910_reg_read(pmic->mfd, reg, &value);
+       if (ret < 0)
+               return ret;
 
        switch (id) {
        case TPS65911_REG_LDO1:
@@ -662,10 +585,10 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev,
                        dcdc_mult--;
                vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;
 
-               tps65910_modify_bits(pmic, TPS65910_VDD1,
-                               (dcdc_mult << VDD1_VGAIN_SEL_SHIFT),
-                                               VDD1_VGAIN_SEL_MASK);
-               tps65910_reg_write_locked(pmic, TPS65910_VDD1_OP, vsel);
+               tps65910_reg_update_bits(pmic->mfd, TPS65910_VDD1,
+                                        VDD1_VGAIN_SEL_MASK,
+                                        dcdc_mult << VDD1_VGAIN_SEL_SHIFT);
+               tps65910_reg_write(pmic->mfd, TPS65910_VDD1_OP, vsel);
                break;
        case TPS65910_REG_VDD2:
                dcdc_mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
@@ -673,14 +596,14 @@ static int tps65910_set_voltage_dcdc_sel(struct regulator_dev *dev,
                        dcdc_mult--;
                vsel = (selector % VDD1_2_NUM_VOLT_FINE) + 3;
 
-               tps65910_modify_bits(pmic, TPS65910_VDD2,
-                               (dcdc_mult << VDD2_VGAIN_SEL_SHIFT),
-                                               VDD1_VGAIN_SEL_MASK);
-               tps65910_reg_write_locked(pmic, TPS65910_VDD2_OP, vsel);
+               tps65910_reg_update_bits(pmic->mfd, TPS65910_VDD2,
+                                        VDD1_VGAIN_SEL_MASK,
+                                        dcdc_mult << VDD2_VGAIN_SEL_SHIFT);
+               tps65910_reg_write(pmic->mfd, TPS65910_VDD2_OP, vsel);
                break;
        case TPS65911_REG_VDDCTRL:
                vsel = selector + 3;
-               tps65910_reg_write_locked(pmic, TPS65911_VDDCTRL_OP, vsel);
+               tps65910_reg_write(pmic->mfd, TPS65911_VDDCTRL_OP, vsel);
        }
 
        return 0;
@@ -706,8 +629,8 @@ static int tps65910_set_voltage_sel(struct regulator_dev *dev,
        case TPS65910_REG_VAUX2:
        case TPS65910_REG_VAUX33:
        case TPS65910_REG_VMMC:
-               return tps65910_modify_bits(pmic, reg,
-                               (selector << LDO_SEL_SHIFT), LDO_SEL_MASK);
+               return tps65910_reg_update_bits(pmic->mfd, reg, LDO_SEL_MASK,
+                                               selector << LDO_SEL_SHIFT);
        }
 
        return -EINVAL;
@@ -727,18 +650,18 @@ static int tps65911_set_voltage_sel(struct regulator_dev *dev,
        case TPS65911_REG_LDO1:
        case TPS65911_REG_LDO2:
        case TPS65911_REG_LDO4:
-               return tps65910_modify_bits(pmic, reg,
-                               (selector << LDO_SEL_SHIFT), LDO1_SEL_MASK);
+               return tps65910_reg_update_bits(pmic->mfd, reg, LDO1_SEL_MASK,
+                                               selector << LDO_SEL_SHIFT);
        case TPS65911_REG_LDO3:
        case TPS65911_REG_LDO5:
        case TPS65911_REG_LDO6:
        case TPS65911_REG_LDO7:
        case TPS65911_REG_LDO8:
-               return tps65910_modify_bits(pmic, reg,
-                               (selector << LDO_SEL_SHIFT), LDO3_SEL_MASK);
+               return tps65910_reg_update_bits(pmic->mfd, reg, LDO3_SEL_MASK,
+                                               selector << LDO_SEL_SHIFT);
        case TPS65910_REG_VIO:
-               return tps65910_modify_bits(pmic, reg,
-                               (selector << LDO_SEL_SHIFT), LDO_SEL_MASK);
+               return tps65910_reg_update_bits(pmic->mfd, reg, LDO_SEL_MASK,
+                                               selector << LDO_SEL_SHIFT);
        }
 
        return -EINVAL;
@@ -768,23 +691,6 @@ static int tps65910_list_voltage_dcdc(struct regulator_dev *dev,
        return  volt * 100 * mult;
 }
 
-static int tps65910_list_voltage(struct regulator_dev *dev,
-                                       unsigned selector)
-{
-       struct tps65910_reg *pmic = rdev_get_drvdata(dev);
-       int id = rdev_get_id(dev), voltage;
-
-       if (id < TPS65910_REG_VIO || id > TPS65910_REG_VMMC)
-               return -EINVAL;
-
-       if (selector >= pmic->info[id]->n_voltages)
-               return -EINVAL;
-       else
-               voltage = pmic->info[id]->voltage_table[selector] * 1000;
-
-       return voltage;
-}
-
 static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector)
 {
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
@@ -816,7 +722,7 @@ static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector)
                step_mv = 100;
                break;
        case TPS65910_REG_VIO:
-               return pmic->info[id]->voltage_table[selector] * 1000;
+               return pmic->info[id]->voltage_table[selector];
        default:
                return -EINVAL;
        }
@@ -824,42 +730,16 @@ static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector)
        return (LDO_MIN_VOLT + selector * step_mv) * 1000;
 }
 
-static int tps65910_set_voltage_dcdc_time_sel(struct regulator_dev *dev,
-               unsigned int old_selector, unsigned int new_selector)
-{
-       int id = rdev_get_id(dev);
-       int old_volt, new_volt;
-
-       old_volt = tps65910_list_voltage_dcdc(dev, old_selector);
-       if (old_volt < 0)
-               return old_volt;
-
-       new_volt = tps65910_list_voltage_dcdc(dev, new_selector);
-       if (new_volt < 0)
-               return new_volt;
-
-       /* VDD1 and VDD2 are 12.5mV/us, VDDCTRL is 100mV/20us */
-       switch (id) {
-       case TPS65910_REG_VDD1:
-       case TPS65910_REG_VDD2:
-               return DIV_ROUND_UP(abs(old_volt - new_volt), 12500);
-       case TPS65911_REG_VDDCTRL:
-               return DIV_ROUND_UP(abs(old_volt - new_volt), 5000);
-       }
-       return -EINVAL;
-}
-
 /* Regulator ops (except VRTC) */
 static struct regulator_ops tps65910_ops_dcdc = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
-       .enable_time            = tps65910_enable_time,
        .set_mode               = tps65910_set_mode,
        .get_mode               = tps65910_get_mode,
        .get_voltage_sel        = tps65910_get_voltage_dcdc_sel,
        .set_voltage_sel        = tps65910_set_voltage_dcdc_sel,
-       .set_voltage_time_sel   = tps65910_set_voltage_dcdc_time_sel,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
        .list_voltage           = tps65910_list_voltage_dcdc,
 };
 
@@ -867,30 +747,27 @@ static struct regulator_ops tps65910_ops_vdd3 = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
-       .enable_time            = tps65910_enable_time,
        .set_mode               = tps65910_set_mode,
        .get_mode               = tps65910_get_mode,
        .get_voltage            = tps65910_get_voltage_vdd3,
-       .list_voltage           = tps65910_list_voltage,
+       .list_voltage           = regulator_list_voltage_table,
 };
 
 static struct regulator_ops tps65910_ops = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
-       .enable_time            = tps65910_enable_time,
        .set_mode               = tps65910_set_mode,
        .get_mode               = tps65910_get_mode,
        .get_voltage_sel        = tps65910_get_voltage_sel,
        .set_voltage_sel        = tps65910_set_voltage_sel,
-       .list_voltage           = tps65910_list_voltage,
+       .list_voltage           = regulator_list_voltage_table,
 };
 
 static struct regulator_ops tps65911_ops = {
        .is_enabled             = regulator_is_enabled_regmap,
        .enable                 = regulator_enable_regmap,
        .disable                = regulator_disable_regmap,
-       .enable_time            = tps65910_enable_time,
        .set_mode               = tps65910_set_mode,
        .get_mode               = tps65910_get_mode,
        .get_voltage_sel        = tps65911_get_voltage_sel,
@@ -996,19 +873,27 @@ static int tps65910_set_ext_sleep_config(struct tps65910_reg *pmic,
                                (tps65910_chip_id(mfd) == TPS65911))) {
                int op_reg_add = pmic->get_ctrl_reg(id) + 1;
                int sr_reg_add = pmic->get_ctrl_reg(id) + 2;
-               int opvsel = tps65910_reg_read_locked(pmic, op_reg_add);
-               int srvsel = tps65910_reg_read_locked(pmic, sr_reg_add);
+               int opvsel, srvsel;
+
+               ret = tps65910_reg_read(pmic->mfd, op_reg_add, &opvsel);
+               if (ret < 0)
+                       return ret;
+               ret = tps65910_reg_read(pmic->mfd, sr_reg_add, &srvsel);
+               if (ret < 0)
+                       return ret;
+
                if (opvsel & VDD1_OP_CMD_MASK) {
                        u8 reg_val = srvsel & VDD1_OP_SEL_MASK;
-                       ret = tps65910_reg_write_locked(pmic, op_reg_add,
-                                                       reg_val);
+
+                       ret = tps65910_reg_write(pmic->mfd, op_reg_add,
+                                                reg_val);
                        if (ret < 0) {
                                dev_err(mfd->dev,
                                        "Error in configuring op register\n");
                                return ret;
                        }
                }
-               ret = tps65910_reg_write_locked(pmic, sr_reg_add, 0);
+               ret = tps65910_reg_write(pmic->mfd, sr_reg_add, 0);
                if (ret < 0) {
                        dev_err(mfd->dev, "Error in settting sr register\n");
                        return ret;
@@ -1126,6 +1011,7 @@ static struct tps65910_board *tps65910_parse_dt_reg_data(
                                "ti,regulator-ext-sleep-control", &prop);
                if (!ret)
                        pmic_plat_data->regulator_ext_sleep_control[idx] = prop;
+
        }
 
        return pmic_plat_data;
@@ -1136,7 +1022,7 @@ static inline struct tps65910_board *tps65910_parse_dt_reg_data(
                        struct of_regulator_match **tps65910_reg_matches)
 {
        *tps65910_reg_matches = NULL;
-       return 0;
+       return NULL;
 }
 #endif
 
@@ -1168,7 +1054,6 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
                return -ENOMEM;
        }
 
-       mutex_init(&pmic->mutex);
        pmic->mfd = tps65910;
        platform_set_drvdata(pdev, pmic);
 
@@ -1229,23 +1114,31 @@ static __devinit int tps65910_probe(struct platform_device *pdev)
                pmic->info[i] = info;
 
                pmic->desc[i].name = info->name;
+               pmic->desc[i].supply_name = info->vin_name;
                pmic->desc[i].id = i;
                pmic->desc[i].n_voltages = info->n_voltages;
+               pmic->desc[i].enable_time = info->enable_time_us;
 
                if (i == TPS65910_REG_VDD1 || i == TPS65910_REG_VDD2) {
                        pmic->desc[i].ops = &tps65910_ops_dcdc;
                        pmic->desc[i].n_voltages = VDD1_2_NUM_VOLT_FINE *
                                                        VDD1_2_NUM_VOLT_COARSE;
+                       pmic->desc[i].ramp_delay = 12500;
                } else if (i == TPS65910_REG_VDD3) {
-                       if (tps65910_chip_id(tps65910) == TPS65910)
+                       if (tps65910_chip_id(tps65910) == TPS65910) {
                                pmic->desc[i].ops = &tps65910_ops_vdd3;
-                       else
+                               pmic->desc[i].volt_table = info->voltage_table;
+                       } else {
                                pmic->desc[i].ops = &tps65910_ops_dcdc;
+                               pmic->desc[i].ramp_delay = 5000;
+                       }
                } else {
-                       if (tps65910_chip_id(tps65910) == TPS65910)
+                       if (tps65910_chip_id(tps65910) == TPS65910) {
                                pmic->desc[i].ops = &tps65910_ops;
-                       else
+                               pmic->desc[i].volt_table = info->voltage_table;
+                       } else {
                                pmic->desc[i].ops = &tps65911_ops;
+                       }
                }
 
                err = tps65910_set_ext_sleep_config(pmic, i,
index c7390711d9547e2762e818ae13cbdb8784fc29f4..242fe90dc56502ad5c5e1cc0ced284561b0e6df9 100644 (file)
@@ -43,9 +43,6 @@ struct twlreg_info {
        u8                      table_len;
        const u16               *table;
 
-       /* regulator specific turn-on delay */
-       u16                     delay;
-
        /* State REMAP default configuration */
        u8                      remap;
 
@@ -223,20 +220,6 @@ static int twl6030reg_enable(struct regulator_dev *rdev)
        return ret;
 }
 
-static int twl4030reg_enable_time(struct regulator_dev *rdev)
-{
-       struct twlreg_info      *info = rdev_get_drvdata(rdev);
-
-       return info->delay;
-}
-
-static int twl6030reg_enable_time(struct regulator_dev *rdev)
-{
-       struct twlreg_info      *info = rdev_get_drvdata(rdev);
-
-       return info->delay;
-}
-
 static int twl4030reg_disable(struct regulator_dev *rdev)
 {
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
@@ -508,7 +491,6 @@ static struct regulator_ops twl4030ldo_ops = {
        .enable         = twl4030reg_enable,
        .disable        = twl4030reg_disable,
        .is_enabled     = twl4030reg_is_enabled,
-       .enable_time    = twl4030reg_enable_time,
 
        .set_mode       = twl4030reg_set_mode,
 
@@ -577,59 +559,53 @@ static struct regulator_ops twl6030coresmps_ops = {
        .get_voltage    = twl6030coresmps_get_voltage,
 };
 
-static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
+static int twl6030ldo_list_voltage(struct regulator_dev *rdev, unsigned sel)
 {
-       struct twlreg_info      *info = rdev_get_drvdata(rdev);
+       struct twlreg_info *info = rdev_get_drvdata(rdev);
 
-       return ((info->min_mV + (index * 100)) * 1000);
+       switch (sel) {
+       case 0:
+               return 0;
+       case 1 ... 24:
+               /* Linear mapping from 00000001 to 00011000:
+                * Absolute voltage value = 1.0 V + 0.1 V Ã— (sel â€“ 00000001)
+                */
+               return (info->min_mV + 100 * (sel - 1)) * 1000;
+       case 25 ... 30:
+               return -EINVAL;
+       case 31:
+               return 2750000;
+       default:
+               return -EINVAL;
+       }
 }
 
 static int
-twl6030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
-                      unsigned *selector)
+twl6030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
 {
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
-       int                     vsel;
-
-       if ((min_uV/1000 < info->min_mV) || (max_uV/1000 > info->max_mV))
-               return -EDOM;
-
-       /*
-        * Use the below formula to calculate vsel
-        * mV = 1000mv + 100mv * (vsel - 1)
-        */
-       vsel = (min_uV/1000 - 1000)/100 + 1;
-       *selector = vsel;
-       return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE, vsel);
 
+       return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE,
+                           selector);
 }
 
-static int twl6030ldo_get_voltage(struct regulator_dev *rdev)
+static int twl6030ldo_get_voltage_sel(struct regulator_dev *rdev)
 {
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
-       int             vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER,
-                                                               VREG_VOLTAGE);
-
-       if (vsel < 0)
-               return vsel;
+       int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE);
 
-       /*
-        * Use the below formula to calculate vsel
-        * mV = 1000mv + 100mv * (vsel - 1)
-        */
-       return (1000 + (100 * (vsel - 1))) * 1000;
+       return vsel;
 }
 
 static struct regulator_ops twl6030ldo_ops = {
        .list_voltage   = twl6030ldo_list_voltage,
 
-       .set_voltage    = twl6030ldo_set_voltage,
-       .get_voltage    = twl6030ldo_get_voltage,
+       .set_voltage_sel = twl6030ldo_set_voltage_sel,
+       .get_voltage_sel = twl6030ldo_get_voltage_sel,
 
        .enable         = twl6030reg_enable,
        .disable        = twl6030reg_disable,
        .is_enabled     = twl6030reg_is_enabled,
-       .enable_time    = twl6030reg_enable_time,
 
        .set_mode       = twl6030reg_set_mode,
 
@@ -663,7 +639,6 @@ static struct regulator_ops twl4030fixed_ops = {
        .enable         = twl4030reg_enable,
        .disable        = twl4030reg_disable,
        .is_enabled     = twl4030reg_is_enabled,
-       .enable_time    = twl4030reg_enable_time,
 
        .set_mode       = twl4030reg_set_mode,
 
@@ -678,7 +653,6 @@ static struct regulator_ops twl6030fixed_ops = {
        .enable         = twl6030reg_enable,
        .disable        = twl6030reg_disable,
        .is_enabled     = twl6030reg_is_enabled,
-       .enable_time    = twl6030reg_enable_time,
 
        .set_mode       = twl6030reg_set_mode,
 
@@ -689,7 +663,6 @@ static struct regulator_ops twl6030_fixed_resource = {
        .enable         = twl6030reg_enable,
        .disable        = twl6030reg_disable,
        .is_enabled     = twl6030reg_is_enabled,
-       .enable_time    = twl6030reg_enable_time,
        .get_status     = twl6030reg_get_status,
 };
 
@@ -886,7 +859,6 @@ static struct regulator_ops twlsmps_ops = {
        .enable                 = twl6030reg_enable,
        .disable                = twl6030reg_disable,
        .is_enabled             = twl6030reg_is_enabled,
-       .enable_time            = twl6030reg_enable_time,
 
        .set_mode               = twl6030reg_set_mode,
 
@@ -909,7 +881,6 @@ static struct twlreg_info TWL4030_INFO_##label = { \
        .id = num, \
        .table_len = ARRAY_SIZE(label##_VSEL_table), \
        .table = label##_VSEL_table, \
-       .delay = turnon_delay, \
        .remap = remap_conf, \
        .desc = { \
                .name = #label, \
@@ -918,6 +889,7 @@ static struct twlreg_info TWL4030_INFO_##label = { \
                .ops = &twl4030ldo_ops, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
+               .enable_time = turnon_delay, \
                }, \
        }
 
@@ -925,7 +897,6 @@ static struct twlreg_info TWL4030_INFO_##label = { \
 static struct twlreg_info TWL4030_INFO_##label = { \
        .base = offset, \
        .id = num, \
-       .delay = turnon_delay, \
        .remap = remap_conf, \
        .desc = { \
                .name = #label, \
@@ -933,6 +904,7 @@ static struct twlreg_info TWL4030_INFO_##label = { \
                .ops = &twl4030smps_ops, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
+               .enable_time = turnon_delay, \
                }, \
        }
 
@@ -955,7 +927,7 @@ static struct twlreg_info TWL6030_INFO_##label = { \
        .desc = { \
                .name = #label, \
                .id = TWL6030_REG_##label, \
-               .n_voltages = (max_mVolts - min_mVolts)/100 + 1, \
+               .n_voltages = 32, \
                .ops = &twl6030ldo_ops, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
@@ -970,7 +942,7 @@ static struct twlreg_info TWL6025_INFO_##label = { \
        .desc = { \
                .name = #label, \
                .id = TWL6025_REG_##label, \
-               .n_voltages = ((max_mVolts - min_mVolts)/100) + 1, \
+               .n_voltages = 32, \
                .ops = &twl6030ldo_ops, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
@@ -983,7 +955,6 @@ static struct twlreg_info TWLFIXED_INFO_##label = { \
        .base = offset, \
        .id = num, \
        .min_mV = mVolts, \
-       .delay = turnon_delay, \
        .remap = remap_conf, \
        .desc = { \
                .name = #label, \
@@ -992,19 +963,20 @@ static struct twlreg_info TWLFIXED_INFO_##label = { \
                .ops = &operations, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
+               .enable_time = turnon_delay, \
                }, \
        }
 
 #define TWL6030_FIXED_RESOURCE(label, offset, turnon_delay) \
 static struct twlreg_info TWLRES_INFO_##label = { \
        .base = offset, \
-       .delay = turnon_delay, \
        .desc = { \
                .name = #label, \
                .id = TWL6030_REG_##label, \
                .ops = &twl6030_fixed_resource, \
                .type = REGULATOR_VOLTAGE, \
                .owner = THIS_MODULE, \
+               .enable_time = turnon_delay, \
                }, \
        }
 
@@ -1109,7 +1081,6 @@ static u8 twl_get_smps_mult(void)
 #define TWL6030_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6030, label)
 #define TWL6025_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWL6025, label)
 #define TWLFIXED_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLFIXED, label)
-#define TWLRES_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLRES, label)
 #define TWLSMPS_OF_MATCH(comp, label) TWL_OF_MATCH(comp, TWLSMPS, label)
 
 static const struct of_device_id twl_of_match[] __devinitconst = {
@@ -1157,7 +1128,6 @@ static const struct of_device_id twl_of_match[] __devinitconst = {
        TWLFIXED_OF_MATCH("ti,twl6030-vusb", VUSB),
        TWLFIXED_OF_MATCH("ti,twl6030-v1v8", V1V8),
        TWLFIXED_OF_MATCH("ti,twl6030-v2v1", V2V1),
-       TWLRES_OF_MATCH("ti,twl6030-clk32kg", CLK32KG),
        TWLSMPS_OF_MATCH("ti,twl6025-smps3", SMPS3),
        TWLSMPS_OF_MATCH("ti,twl6025-smps4", SMPS4),
        TWLSMPS_OF_MATCH("ti,twl6025-vio", VIO),
index 099da11e989fde4e9ed793c3cdee9c6452c58a0f..7413885be01ba5907117c4c95d89df1a4129924b 100644 (file)
@@ -215,8 +215,8 @@ static int wm831x_buckv_list_voltage(struct regulator_dev *rdev,
        return -EINVAL;
 }
 
-static int wm831x_buckv_select_min_voltage(struct regulator_dev *rdev,
-                                          int min_uV, int max_uV)
+static int wm831x_buckv_map_voltage(struct regulator_dev *rdev,
+                                  int min_uV, int max_uV)
 {
        u16 vsel;
 
@@ -251,20 +251,14 @@ static int wm831x_buckv_set_dvs(struct regulator_dev *rdev, int state)
        return 0;
 }
 
-static int wm831x_buckv_set_voltage(struct regulator_dev *rdev,
-                                   int min_uV, int max_uV, unsigned *selector)
+static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev,
+                                       unsigned vsel)
 {
        struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
        struct wm831x *wm831x = dcdc->wm831x;
        int on_reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
        int dvs_reg = dcdc->base + WM831X_DCDC_DVS_CONTROL;
-       int vsel, ret;
-
-       vsel = wm831x_buckv_select_min_voltage(rdev, min_uV, max_uV);
-       if (vsel < 0)
-               return vsel;
-
-       *selector = vsel;
+       int ret;
 
        /* If this value is already set then do a GPIO update if we can */
        if (dcdc->dvs_gpio && dcdc->on_vsel == vsel)
@@ -315,7 +309,7 @@ static int wm831x_buckv_set_suspend_voltage(struct regulator_dev *rdev,
        u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;
        int vsel;
 
-       vsel = wm831x_buckv_select_min_voltage(rdev, uV, uV);
+       vsel = wm831x_buckv_map_voltage(rdev, uV, uV);
        if (vsel < 0)
                return vsel;
 
@@ -373,9 +367,10 @@ static int wm831x_buckv_get_current_limit(struct regulator_dev *rdev)
 }
 
 static struct regulator_ops wm831x_buckv_ops = {
-       .set_voltage = wm831x_buckv_set_voltage,
+       .set_voltage_sel = wm831x_buckv_set_voltage_sel,
        .get_voltage_sel = wm831x_buckv_get_voltage_sel,
        .list_voltage = wm831x_buckv_list_voltage,
+       .map_voltage = wm831x_buckv_map_voltage,
        .set_suspend_voltage = wm831x_buckv_set_suspend_voltage,
        .set_current_limit = wm831x_buckv_set_current_limit,
        .get_current_limit = wm831x_buckv_get_current_limit,
@@ -599,60 +594,25 @@ static struct platform_driver wm831x_buckv_driver = {
  * BUCKP specifics
  */
 
-static int wm831x_buckp_list_voltage(struct regulator_dev *rdev,
-                                     unsigned selector)
-{
-       if (selector <= WM831X_BUCKP_MAX_SELECTOR)
-               return 850000 + (selector * 25000);
-       else
-               return -EINVAL;
-}
-
-static int wm831x_buckp_set_voltage_int(struct regulator_dev *rdev, int reg,
-                                       int min_uV, int max_uV, int *selector)
+static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 {
        struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
        struct wm831x *wm831x = dcdc->wm831x;
-       u16 vsel;
-
-       if (min_uV <= 34000000)
-               vsel = (min_uV - 850000) / 25000;
-       else
-               return -EINVAL;
-
-       if (wm831x_buckp_list_voltage(rdev, vsel) > max_uV)
-               return -EINVAL;
-
-       *selector = vsel;
-
-       return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, vsel);
-}
-
-static int wm831x_buckp_set_voltage(struct regulator_dev *rdev,
-                                   int min_uV, int max_uV,
-                                   unsigned *selector)
-{
-       struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
-       u16 reg = dcdc->base + WM831X_DCDC_ON_CONFIG;
-
-       return wm831x_buckp_set_voltage_int(rdev, reg, min_uV, max_uV,
-                                           selector);
-}
-
-static int wm831x_buckp_set_suspend_voltage(struct regulator_dev *rdev,
-                                           int uV)
-{
-       struct wm831x_dcdc *dcdc = rdev_get_drvdata(rdev);
        u16 reg = dcdc->base + WM831X_DCDC_SLEEP_CONTROL;
-       unsigned selector;
+       int sel;
+
+       sel = regulator_map_voltage_linear(rdev, uV, uV);
+       if (sel < 0)
+               return sel;
 
-       return wm831x_buckp_set_voltage_int(rdev, reg, uV, uV, &selector);
+       return wm831x_set_bits(wm831x, reg, WM831X_DC3_ON_VSEL_MASK, sel);
 }
 
 static struct regulator_ops wm831x_buckp_ops = {
-       .set_voltage = wm831x_buckp_set_voltage,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
-       .list_voltage = wm831x_buckp_list_voltage,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
        .set_suspend_voltage = wm831x_buckp_set_suspend_voltage,
 
        .is_enabled = regulator_is_enabled_regmap,
@@ -715,6 +675,8 @@ static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
        dcdc->desc.vsel_mask = WM831X_DC3_ON_VSEL_MASK;
        dcdc->desc.enable_reg = WM831X_DCDC_ENABLE;
        dcdc->desc.enable_mask = 1 << id;
+       dcdc->desc.min_uV = 850000;
+       dcdc->desc.uV_step = 25000;
 
        config.dev = pdev->dev.parent;
        if (pdata)
index a9a28d8ac18591d4c7126364dbd40197024191f8..5cb70ca1e98d1f1843347fe14d7291d7a041eceb 100644 (file)
@@ -78,13 +78,10 @@ static int wm831x_gp_ldo_list_voltage(struct regulator_dev *rdev,
        return -EINVAL;
 }
 
-static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg,
-                                        int min_uV, int max_uV,
-                                        unsigned *selector)
+static int wm831x_gp_ldo_map_voltage(struct regulator_dev *rdev,
+                                    int min_uV, int max_uV)
 {
-       struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       struct wm831x *wm831x = ldo->wm831x;
-       int vsel, ret;
+       int volt, vsel;
 
        if (min_uV < 900000)
                vsel = 0;
@@ -94,36 +91,25 @@ static int wm831x_gp_ldo_set_voltage_int(struct regulator_dev *rdev, int reg,
                vsel = ((min_uV - 1700000) / 100000)
                        + WM831X_GP_LDO_SELECTOR_LOW + 1;
 
-       ret = wm831x_gp_ldo_list_voltage(rdev, vsel);
-       if (ret < 0)
-               return ret;
-       if (ret < min_uV || ret > max_uV)
+       volt = wm831x_gp_ldo_list_voltage(rdev, vsel);
+       if (volt < min_uV || volt > max_uV)
                return -EINVAL;
 
-       *selector = vsel;
-
-       return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, vsel);
-}
-
-static int wm831x_gp_ldo_set_voltage(struct regulator_dev *rdev,
-                                    int min_uV, int max_uV,
-                                    unsigned *selector)
-{
-       struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       int reg = ldo->base + WM831X_LDO_ON_CONTROL;
-
-       return wm831x_gp_ldo_set_voltage_int(rdev, reg, min_uV, max_uV,
-                                            selector);
+       return vsel;
 }
 
 static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
                                             int uV)
 {
        struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
-       unsigned int selector;
+       struct wm831x *wm831x = ldo->wm831x;
+       int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
 
-       return wm831x_gp_ldo_set_voltage_int(rdev, reg, uV, uV, &selector);
+       sel = wm831x_gp_ldo_map_voltage(rdev, uV, uV);
+       if (sel < 0)
+               return sel;
+
+       return wm831x_set_bits(wm831x, reg, WM831X_LDO1_ON_VSEL_MASK, sel);
 }
 
 static unsigned int wm831x_gp_ldo_get_mode(struct regulator_dev *rdev)
@@ -243,8 +229,9 @@ static unsigned int wm831x_gp_ldo_get_optimum_mode(struct regulator_dev *rdev,
 
 static struct regulator_ops wm831x_gp_ldo_ops = {
        .list_voltage = wm831x_gp_ldo_list_voltage,
+       .map_voltage = wm831x_gp_ldo_map_voltage,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
-       .set_voltage = wm831x_gp_ldo_set_voltage,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage,
        .get_mode = wm831x_gp_ldo_get_mode,
        .set_mode = wm831x_gp_ldo_set_mode,
@@ -384,13 +371,10 @@ static int wm831x_aldo_list_voltage(struct regulator_dev *rdev,
        return -EINVAL;
 }
 
-static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg,
-                                      int min_uV, int max_uV,
-                                      unsigned *selector)
+static int wm831x_aldo_map_voltage(struct regulator_dev *rdev,
+                                  int min_uV, int max_uV)
 {
-       struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       struct wm831x *wm831x = ldo->wm831x;
-       int vsel, ret;
+       int volt, vsel;
 
        if (min_uV < 1000000)
                vsel = 0;
@@ -400,35 +384,26 @@ static int wm831x_aldo_set_voltage_int(struct regulator_dev *rdev, int reg,
                vsel = ((min_uV - 1700000) / 100000)
                        + WM831X_ALDO_SELECTOR_LOW + 1;
 
-       ret = wm831x_aldo_list_voltage(rdev, vsel);
-       if (ret < 0)
-               return ret;
-       if (ret < min_uV || ret > max_uV)
+       volt = wm831x_aldo_list_voltage(rdev, vsel);
+       if (volt < min_uV || volt > max_uV)
                return -EINVAL;
 
-       *selector = vsel;
-
-       return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, vsel);
-}
-
-static int wm831x_aldo_set_voltage(struct regulator_dev *rdev,
-                                  int min_uV, int max_uV, unsigned *selector)
-{
-       struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       int reg = ldo->base + WM831X_LDO_ON_CONTROL;
+       return vsel;
 
-       return wm831x_aldo_set_voltage_int(rdev, reg, min_uV, max_uV,
-                                          selector);
 }
 
 static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
                                             int uV)
 {
        struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       int reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
-       unsigned int selector;
+       struct wm831x *wm831x = ldo->wm831x;
+       int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL;
+
+       sel = wm831x_aldo_map_voltage(rdev, uV, uV);
+       if (sel < 0)
+               return sel;
 
-       return wm831x_aldo_set_voltage_int(rdev, reg, uV, uV, &selector);
+       return wm831x_set_bits(wm831x, reg, WM831X_LDO7_ON_VSEL_MASK, sel);
 }
 
 static unsigned int wm831x_aldo_get_mode(struct regulator_dev *rdev)
@@ -506,8 +481,9 @@ static int wm831x_aldo_get_status(struct regulator_dev *rdev)
 
 static struct regulator_ops wm831x_aldo_ops = {
        .list_voltage = wm831x_aldo_list_voltage,
+       .map_voltage = wm831x_aldo_map_voltage,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
-       .set_voltage = wm831x_aldo_set_voltage,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .set_suspend_voltage = wm831x_aldo_set_suspend_voltage,
        .get_mode = wm831x_aldo_get_mode,
        .set_mode = wm831x_aldo_set_mode,
@@ -628,47 +604,18 @@ static struct platform_driver wm831x_aldo_driver = {
 
 #define WM831X_ALIVE_LDO_MAX_SELECTOR 0xf
 
-static int wm831x_alive_ldo_set_voltage_int(struct regulator_dev *rdev,
-                                           int reg,
-                                           int min_uV, int max_uV,
-                                           unsigned *selector)
-{
-       struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       struct wm831x *wm831x = ldo->wm831x;
-       int vsel, ret;
-
-       vsel = (min_uV - 800000) / 50000;
-
-       ret = regulator_list_voltage_linear(rdev, vsel);
-       if (ret < 0)
-               return ret;
-       if (ret < min_uV || ret > max_uV)
-               return -EINVAL;
-
-       *selector = vsel;
-
-       return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, vsel);
-}
-
-static int wm831x_alive_ldo_set_voltage(struct regulator_dev *rdev,
-                                       int min_uV, int max_uV,
-                                       unsigned *selector)
-{
-       struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       int reg = ldo->base + WM831X_ALIVE_LDO_ON_CONTROL;
-
-       return wm831x_alive_ldo_set_voltage_int(rdev, reg, min_uV, max_uV,
-                                               selector);
-}
-
 static int wm831x_alive_ldo_set_suspend_voltage(struct regulator_dev *rdev,
                                             int uV)
 {
        struct wm831x_ldo *ldo = rdev_get_drvdata(rdev);
-       int reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL;
-       unsigned selector;
+       struct wm831x *wm831x = ldo->wm831x;
+       int sel, reg = ldo->base + WM831X_ALIVE_LDO_SLEEP_CONTROL;
+
+       sel = regulator_map_voltage_linear(rdev, uV, uV);
+       if (sel < 0)
+               return sel;
 
-       return wm831x_alive_ldo_set_voltage_int(rdev, reg, uV, uV, &selector);
+       return wm831x_set_bits(wm831x, reg, WM831X_LDO11_ON_VSEL_MASK, sel);
 }
 
 static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)
@@ -690,8 +637,9 @@ static int wm831x_alive_ldo_get_status(struct regulator_dev *rdev)
 
 static struct regulator_ops wm831x_alive_ldo_ops = {
        .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
-       .set_voltage = wm831x_alive_ldo_set_voltage,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .set_suspend_voltage = wm831x_alive_ldo_set_suspend_voltage,
        .get_status = wm831x_alive_ldo_get_status,
 
@@ -753,6 +701,7 @@ static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
        ldo->desc.enable_mask = 1 << id;
        ldo->desc.min_uV = 800000;
        ldo->desc.uV_step = 50000;
+       ldo->desc.enable_time = 1000;
 
        config.dev = pdev->dev.parent;
        if (pdata)
index 94e550dc70b64a6ef5042a68d2aa8dfef445bec2..7f0fa22ef2aab4e85e71693358737ee099b537e2 100644 (file)
@@ -108,33 +108,6 @@ static int get_isink_val(int min_uA, int max_uA, u16 *setting)
        return -EINVAL;
 }
 
-static inline int wm8350_ldo_val_to_mvolts(unsigned int val)
-{
-       if (val < 16)
-               return (val * 50) + 900;
-       else
-               return ((val - 16) * 100) + 1800;
-
-}
-
-static inline unsigned int wm8350_ldo_mvolts_to_val(int mV)
-{
-       if (mV < 1800)
-               return (mV - 900) / 50;
-       else
-               return ((mV - 1800) / 100) + 16;
-}
-
-static inline int wm8350_dcdc_val_to_mvolts(unsigned int val)
-{
-       return (val * 25) + 850;
-}
-
-static inline unsigned int wm8350_dcdc_mvolts_to_val(int mV)
-{
-       return (mV - 850) / 25;
-}
-
 static int wm8350_isink_set_current(struct regulator_dev *rdev, int min_uA,
        int max_uA)
 {
@@ -359,104 +332,13 @@ int wm8350_isink_set_flash(struct wm8350 *wm8350, int isink, u16 mode,
 }
 EXPORT_SYMBOL_GPL(wm8350_isink_set_flash);
 
-static int wm8350_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV,
-                                  int max_uV, unsigned *selector)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int volt_reg, dcdc = rdev_get_id(rdev), mV,
-               min_mV = min_uV / 1000, max_mV = max_uV / 1000;
-       u16 val;
-
-       if (min_mV < 850 || min_mV > 4025)
-               return -EINVAL;
-       if (max_mV < 850 || max_mV > 4025)
-               return -EINVAL;
-
-       /* step size is 25mV */
-       mV = (min_mV - 826) / 25;
-       if (wm8350_dcdc_val_to_mvolts(mV) > max_mV)
-               return -EINVAL;
-       BUG_ON(wm8350_dcdc_val_to_mvolts(mV) < min_mV);
-
-       switch (dcdc) {
-       case WM8350_DCDC_1:
-               volt_reg = WM8350_DCDC1_CONTROL;
-               break;
-       case WM8350_DCDC_3:
-               volt_reg = WM8350_DCDC3_CONTROL;
-               break;
-       case WM8350_DCDC_4:
-               volt_reg = WM8350_DCDC4_CONTROL;
-               break;
-       case WM8350_DCDC_6:
-               volt_reg = WM8350_DCDC6_CONTROL;
-               break;
-       case WM8350_DCDC_2:
-       case WM8350_DCDC_5:
-       default:
-               return -EINVAL;
-       }
-
-       *selector = mV;
-
-       /* all DCDCs have same mV bits */
-       val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
-       wm8350_reg_write(wm8350, volt_reg, val | mV);
-       return 0;
-}
-
-static int wm8350_dcdc_get_voltage_sel(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int volt_reg, dcdc = rdev_get_id(rdev);
-
-       switch (dcdc) {
-       case WM8350_DCDC_1:
-               volt_reg = WM8350_DCDC1_CONTROL;
-               break;
-       case WM8350_DCDC_3:
-               volt_reg = WM8350_DCDC3_CONTROL;
-               break;
-       case WM8350_DCDC_4:
-               volt_reg = WM8350_DCDC4_CONTROL;
-               break;
-       case WM8350_DCDC_6:
-               volt_reg = WM8350_DCDC6_CONTROL;
-               break;
-       case WM8350_DCDC_2:
-       case WM8350_DCDC_5:
-       default:
-               return -EINVAL;
-       }
-
-       /* all DCDCs have same mV bits */
-       return wm8350_reg_read(wm8350, volt_reg) & WM8350_DC1_VSEL_MASK;
-}
-
-static int wm8350_dcdc_list_voltage(struct regulator_dev *rdev,
-                                   unsigned selector)
-{
-       if (selector > WM8350_DCDC_MAX_VSEL)
-               return -EINVAL;
-       return wm8350_dcdc_val_to_mvolts(selector) * 1000;
-}
-
 static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 {
        struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int volt_reg, mV = uV / 1000, dcdc = rdev_get_id(rdev);
+       int sel, volt_reg, dcdc = rdev_get_id(rdev);
        u16 val;
 
-       dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, mV);
-
-       if (mV && (mV < 850 || mV > 4025)) {
-               dev_err(wm8350->dev,
-                       "DCDC%d suspend voltage %d mV out of range\n",
-                       dcdc, mV);
-               return -EINVAL;
-       }
-       if (mV == 0)
-               mV = 850;
+       dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, dcdc, uV / 1000);
 
        switch (dcdc) {
        case WM8350_DCDC_1:
@@ -477,10 +359,13 @@ static int wm8350_dcdc_set_suspend_voltage(struct regulator_dev *rdev, int uV)
                return -EINVAL;
        }
 
+       sel = regulator_map_voltage_linear(rdev, uV, uV);
+       if (sel < 0)
+               return -EINVAL;
+
        /* all DCDCs have same mV bits */
        val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_DC1_VSEL_MASK;
-       wm8350_reg_write(wm8350, volt_reg,
-                        val | wm8350_dcdc_mvolts_to_val(mV));
+       wm8350_reg_write(wm8350, volt_reg, val | sel);
        return 0;
 }
 
@@ -657,19 +542,49 @@ static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
        return 0;
 }
 
+static int wm8350_ldo_list_voltage(struct regulator_dev *rdev,
+                                   unsigned selector)
+{
+       if (selector > WM8350_LDO1_VSEL_MASK)
+               return -EINVAL;
+
+       if (selector < 16)
+               return (selector * 50000) + 900000;
+       else
+               return ((selector - 16) * 100000) + 1800000;
+}
+
+static int wm8350_ldo_map_voltage(struct regulator_dev *rdev, int min_uV,
+                                 int max_uV)
+{
+       int volt, sel;
+       int min_mV = min_uV / 1000;
+       int max_mV = max_uV / 1000;
+
+       if (min_mV < 900 || min_mV > 3300)
+               return -EINVAL;
+       if (max_mV < 900 || max_mV > 3300)
+               return -EINVAL;
+
+       if (min_mV < 1800) /* step size is 50mV < 1800mV */
+               sel = DIV_ROUND_UP(min_uV - 900, 50);
+       else /* step size is 100mV > 1800mV */
+               sel = DIV_ROUND_UP(min_uV - 1800, 100) + 16;
+
+       volt = wm8350_ldo_list_voltage(rdev, sel);
+       if (volt < min_uV || volt > max_uV)
+               return -EINVAL;
+
+       return sel;
+}
+
 static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
 {
        struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int volt_reg, mV = uV / 1000, ldo = rdev_get_id(rdev);
+       int sel, volt_reg, ldo = rdev_get_id(rdev);
        u16 val;
 
-       dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, mV);
-
-       if (mV < 900 || mV > 3300) {
-               dev_err(wm8350->dev, "LDO%d voltage %d mV out of range\n",
-                       ldo, mV);
-               return -EINVAL;
-       }
+       dev_dbg(wm8350->dev, "%s %d mV %d\n", __func__, ldo, uV / 1000);
 
        switch (ldo) {
        case WM8350_LDO_1:
@@ -688,10 +603,13 @@ static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
                return -EINVAL;
        }
 
+       sel = wm8350_ldo_map_voltage(rdev, uV, uV);
+       if (sel < 0)
+               return -EINVAL;
+
        /* all LDOs have same mV bits */
        val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
-       wm8350_reg_write(wm8350, volt_reg,
-                        val | wm8350_ldo_mvolts_to_val(mV));
+       wm8350_reg_write(wm8350, volt_reg, val | sel);
        return 0;
 }
 
@@ -753,92 +671,6 @@ static int wm8350_ldo_set_suspend_disable(struct regulator_dev *rdev)
        return 0;
 }
 
-static int wm8350_ldo_set_voltage(struct regulator_dev *rdev, int min_uV,
-                                 int max_uV, unsigned *selector)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int volt_reg, ldo = rdev_get_id(rdev), mV, min_mV = min_uV / 1000,
-               max_mV = max_uV / 1000;
-       u16 val;
-
-       if (min_mV < 900 || min_mV > 3300)
-               return -EINVAL;
-       if (max_mV < 900 || max_mV > 3300)
-               return -EINVAL;
-
-       if (min_mV < 1800) {
-               /* step size is 50mV < 1800mV */
-               mV = (min_mV - 851) / 50;
-               if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
-                       return -EINVAL;
-               BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
-       } else {
-               /* step size is 100mV > 1800mV */
-               mV = ((min_mV - 1701) / 100) + 16;
-               if (wm8350_ldo_val_to_mvolts(mV) > max_mV)
-                       return -EINVAL;
-               BUG_ON(wm8350_ldo_val_to_mvolts(mV) < min_mV);
-       }
-
-       switch (ldo) {
-       case WM8350_LDO_1:
-               volt_reg = WM8350_LDO1_CONTROL;
-               break;
-       case WM8350_LDO_2:
-               volt_reg = WM8350_LDO2_CONTROL;
-               break;
-       case WM8350_LDO_3:
-               volt_reg = WM8350_LDO3_CONTROL;
-               break;
-       case WM8350_LDO_4:
-               volt_reg = WM8350_LDO4_CONTROL;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       *selector = mV;
-
-       /* all LDOs have same mV bits */
-       val = wm8350_reg_read(wm8350, volt_reg) & ~WM8350_LDO1_VSEL_MASK;
-       wm8350_reg_write(wm8350, volt_reg, val | mV);
-       return 0;
-}
-
-static int wm8350_ldo_get_voltage_sel(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int volt_reg, ldo = rdev_get_id(rdev);
-
-       switch (ldo) {
-       case WM8350_LDO_1:
-               volt_reg = WM8350_LDO1_CONTROL;
-               break;
-       case WM8350_LDO_2:
-               volt_reg = WM8350_LDO2_CONTROL;
-               break;
-       case WM8350_LDO_3:
-               volt_reg = WM8350_LDO3_CONTROL;
-               break;
-       case WM8350_LDO_4:
-               volt_reg = WM8350_LDO4_CONTROL;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       /* all LDOs have same mV bits */
-       return wm8350_reg_read(wm8350, volt_reg) & WM8350_LDO1_VSEL_MASK;
-}
-
-static int wm8350_ldo_list_voltage(struct regulator_dev *rdev,
-                                   unsigned selector)
-{
-       if (selector > WM8350_LDO1_VSEL_MASK)
-               return -EINVAL;
-       return wm8350_ldo_val_to_mvolts(selector) * 1000;
-}
-
 int wm8350_dcdc_set_slot(struct wm8350 *wm8350, int dcdc, u16 start,
                         u16 stop, u16 fault)
 {
@@ -959,63 +791,6 @@ int wm8350_dcdc25_set_mode(struct wm8350 *wm8350, int dcdc, u16 mode,
 }
 EXPORT_SYMBOL_GPL(wm8350_dcdc25_set_mode);
 
-static int wm8350_dcdc_enable(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int dcdc = rdev_get_id(rdev);
-       u16 shift;
-
-       if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
-               return -EINVAL;
-
-       shift = dcdc - WM8350_DCDC_1;
-       wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
-       return 0;
-}
-
-static int wm8350_dcdc_disable(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int dcdc = rdev_get_id(rdev);
-       u16 shift;
-
-       if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
-               return -EINVAL;
-
-       shift = dcdc - WM8350_DCDC_1;
-       wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
-
-       return 0;
-}
-
-static int wm8350_ldo_enable(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int ldo = rdev_get_id(rdev);
-       u16 shift;
-
-       if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
-               return -EINVAL;
-
-       shift = (ldo - WM8350_LDO_1) + 8;
-       wm8350_set_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
-       return 0;
-}
-
-static int wm8350_ldo_disable(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int ldo = rdev_get_id(rdev);
-       u16 shift;
-
-       if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
-               return -EINVAL;
-
-       shift = (ldo - WM8350_LDO_1) + 8;
-       wm8350_clear_bits(wm8350, WM8350_DCDC_LDO_REQUESTED, 1 << shift);
-       return 0;
-}
-
 static int force_continuous_enable(struct wm8350 *wm8350, int dcdc, int enable)
 {
        int reg = 0, ret;
@@ -1197,42 +972,17 @@ static unsigned int wm8350_dcdc_get_optimum_mode(struct regulator_dev *rdev,
        return mode;
 }
 
-static int wm8350_dcdc_is_enabled(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int dcdc = rdev_get_id(rdev), shift;
-
-       if (dcdc < WM8350_DCDC_1 || dcdc > WM8350_DCDC_6)
-               return -EINVAL;
-
-       shift = dcdc - WM8350_DCDC_1;
-       return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
-           & (1 << shift);
-}
-
-static int wm8350_ldo_is_enabled(struct regulator_dev *rdev)
-{
-       struct wm8350 *wm8350 = rdev_get_drvdata(rdev);
-       int ldo = rdev_get_id(rdev), shift;
-
-       if (ldo < WM8350_LDO_1 || ldo > WM8350_LDO_4)
-               return -EINVAL;
-
-       shift = (ldo - WM8350_LDO_1) + 8;
-       return wm8350_reg_read(wm8350, WM8350_DCDC_LDO_REQUESTED)
-           & (1 << shift);
-}
-
 static struct regulator_ops wm8350_dcdc_ops = {
-       .set_voltage = wm8350_dcdc_set_voltage,
-       .get_voltage_sel = wm8350_dcdc_get_voltage_sel,
-       .list_voltage = wm8350_dcdc_list_voltage,
-       .enable = wm8350_dcdc_enable,
-       .disable = wm8350_dcdc_disable,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
        .get_mode = wm8350_dcdc_get_mode,
        .set_mode = wm8350_dcdc_set_mode,
        .get_optimum_mode = wm8350_dcdc_get_optimum_mode,
-       .is_enabled = wm8350_dcdc_is_enabled,
        .set_suspend_voltage = wm8350_dcdc_set_suspend_voltage,
        .set_suspend_enable = wm8350_dcdc_set_suspend_enable,
        .set_suspend_disable = wm8350_dcdc_set_suspend_disable,
@@ -1240,20 +990,21 @@ static struct regulator_ops wm8350_dcdc_ops = {
 };
 
 static struct regulator_ops wm8350_dcdc2_5_ops = {
-       .enable = wm8350_dcdc_enable,
-       .disable = wm8350_dcdc_disable,
-       .is_enabled = wm8350_dcdc_is_enabled,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
        .set_suspend_enable = wm8350_dcdc25_set_suspend_enable,
        .set_suspend_disable = wm8350_dcdc25_set_suspend_disable,
 };
 
 static struct regulator_ops wm8350_ldo_ops = {
-       .set_voltage = wm8350_ldo_set_voltage,
-       .get_voltage_sel = wm8350_ldo_get_voltage_sel,
+       .map_voltage = wm8350_ldo_map_voltage,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
        .list_voltage = wm8350_ldo_list_voltage,
-       .enable = wm8350_ldo_enable,
-       .disable = wm8350_ldo_disable,
-       .is_enabled = wm8350_ldo_is_enabled,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .is_enabled = regulator_is_enabled_regmap,
        .get_mode = wm8350_ldo_get_mode,
        .set_suspend_voltage = wm8350_ldo_set_suspend_voltage,
        .set_suspend_enable = wm8350_ldo_set_suspend_enable,
@@ -1277,6 +1028,12 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_DC1,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
+               .min_uV = 850000,
+               .uV_step = 25000,
+               .vsel_reg = WM8350_DCDC1_CONTROL,
+               .vsel_mask = WM8350_DC1_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_DC1_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1285,6 +1042,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .ops = &wm8350_dcdc2_5_ops,
                .irq = WM8350_IRQ_UV_DC2,
                .type = REGULATOR_VOLTAGE,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_DC2_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1294,6 +1053,12 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_DC3,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
+               .min_uV = 850000,
+               .uV_step = 25000,
+               .vsel_reg = WM8350_DCDC3_CONTROL,
+               .vsel_mask = WM8350_DC3_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_DC3_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1303,6 +1068,12 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_DC4,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
+               .min_uV = 850000,
+               .uV_step = 25000,
+               .vsel_reg = WM8350_DCDC4_CONTROL,
+               .vsel_mask = WM8350_DC4_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_DC4_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1311,6 +1082,8 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .ops = &wm8350_dcdc2_5_ops,
                .irq = WM8350_IRQ_UV_DC5,
                .type = REGULATOR_VOLTAGE,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_DC5_ENA,
                .owner = THIS_MODULE,
         },
        {
@@ -1320,6 +1093,12 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_DC6,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_DCDC_MAX_VSEL + 1,
+               .min_uV = 850000,
+               .uV_step = 25000,
+               .vsel_reg = WM8350_DCDC6_CONTROL,
+               .vsel_mask = WM8350_DC6_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_DC6_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1329,6 +1108,10 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_LDO1,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_LDO1_VSEL_MASK + 1,
+               .vsel_reg = WM8350_LDO1_CONTROL,
+               .vsel_mask = WM8350_LDO1_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_LDO1_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1338,6 +1121,10 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_LDO2,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_LDO2_VSEL_MASK + 1,
+               .vsel_reg = WM8350_LDO2_CONTROL,
+               .vsel_mask = WM8350_LDO2_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_LDO2_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1347,6 +1134,10 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_LDO3,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_LDO3_VSEL_MASK + 1,
+               .vsel_reg = WM8350_LDO3_CONTROL,
+               .vsel_mask = WM8350_LDO3_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_LDO3_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1356,6 +1147,10 @@ static const struct regulator_desc wm8350_reg[NUM_WM8350_REGULATORS] = {
                .irq = WM8350_IRQ_UV_LDO4,
                .type = REGULATOR_VOLTAGE,
                .n_voltages = WM8350_LDO4_VSEL_MASK + 1,
+               .vsel_reg = WM8350_LDO4_CONTROL,
+               .vsel_mask = WM8350_LDO4_VSEL_MASK,
+               .enable_reg = WM8350_DCDC_LDO_REQUESTED,
+               .enable_mask = WM8350_LDO4_ENA,
                .owner = THIS_MODULE,
        },
        {
@@ -1429,6 +1224,7 @@ static int wm8350_regulator_probe(struct platform_device *pdev)
        config.dev = &pdev->dev;
        config.init_data = pdev->dev.platform_data;
        config.driver_data = dev_get_drvdata(&pdev->dev);
+       config.regmap = wm8350->regmap;
 
        /* register regulator */
        rdev = regulator_register(&wm8350_reg[pdev->id], &config);
index 69a2b7ce5e4a09a3dae1e606aaf3786011dd02b2..9035dd0536118df253769b6e7e5847621ebd9a5e 100644 (file)
@@ -28,34 +28,26 @@ static int wm8400_ldo_list_voltage(struct regulator_dev *dev,
        if (selector < 15)
                return 900000 + (selector * 50000);
        else
-               return 1600000 + ((selector - 14) * 100000);
+               return 1700000 + ((selector - 15) * 100000);
 }
 
 static int wm8400_ldo_map_voltage(struct regulator_dev *dev,
                                  int min_uV, int max_uV)
 {
        u16 val;
+       int volt;
 
        if (min_uV < 900000 || min_uV > 3300000)
                return -EINVAL;
 
-       if (min_uV < 1700000) {
-               /* Steps of 50mV from 900mV;  */
+       if (min_uV < 1700000) /* Steps of 50mV from 900mV;  */
                val = DIV_ROUND_UP(min_uV - 900000, 50000);
+       else /* Steps of 100mV from 1700mV */
+               val = DIV_ROUND_UP(min_uV - 1700000, 100000) + 15;
 
-               if ((val * 50000) + 900000 > max_uV)
-                       return -EINVAL;
-               BUG_ON((val * 50000) + 900000 < min_uV);
-       } else {
-               /* Steps of 100mV from 1700mV */
-               val = DIV_ROUND_UP(min_uV - 1700000, 100000);
-
-               if ((val * 100000) + 1700000 > max_uV)
-                       return -EINVAL;
-               BUG_ON((val * 100000) + 1700000 < min_uV);
-
-               val += 0xf;
-       }
+       volt = wm8400_ldo_list_voltage(dev, val);
+       if (volt < min_uV || volt > max_uV)
+               return -EINVAL;
 
        return val;
 }
@@ -152,6 +144,7 @@ static struct regulator_ops wm8400_dcdc_ops = {
        .enable = regulator_enable_regmap,
        .disable = regulator_disable_regmap,
        .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
        .set_voltage_sel = regulator_set_voltage_sel_regmap,
        .get_mode = wm8400_dcdc_get_mode,
index 9a994316e63c60b748d0afea65ffc123e81fcf09..86bb48db149ed3d2bb1285f9dd4a24fb28a531f2 100644 (file)
@@ -26,8 +26,6 @@
 #include <linux/mfd/wm8994/pdata.h>
 
 struct wm8994_ldo {
-       int enable;
-       bool is_enabled;
        struct regulator_dev *regulator;
        struct wm8994 *wm8994;
 };
@@ -35,64 +33,9 @@ struct wm8994_ldo {
 #define WM8994_LDO1_MAX_SELECTOR 0x7
 #define WM8994_LDO2_MAX_SELECTOR 0x3
 
-static int wm8994_ldo_enable(struct regulator_dev *rdev)
-{
-       struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
-
-       /* If we have no soft control assume that the LDO is always enabled. */
-       if (!ldo->enable)
-               return 0;
-
-       gpio_set_value_cansleep(ldo->enable, 1);
-       ldo->is_enabled = true;
-
-       return 0;
-}
-
-static int wm8994_ldo_disable(struct regulator_dev *rdev)
-{
-       struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
-
-       /* If we have no soft control assume that the LDO is always enabled. */
-       if (!ldo->enable)
-               return -EINVAL;
-
-       gpio_set_value_cansleep(ldo->enable, 0);
-       ldo->is_enabled = false;
-
-       return 0;
-}
-
-static int wm8994_ldo_is_enabled(struct regulator_dev *rdev)
-{
-       struct wm8994_ldo *ldo = rdev_get_drvdata(rdev);
-
-       return ldo->is_enabled;
-}
-
-static int wm8994_ldo_enable_time(struct regulator_dev *rdev)
-{
-       /* 3ms is fairly conservative but this shouldn't be too performance
-        * critical; can be tweaked per-system if required. */
-       return 3000;
-}
-
-static int wm8994_ldo1_list_voltage(struct regulator_dev *rdev,
-                                   unsigned int selector)
-{
-       if (selector > WM8994_LDO1_MAX_SELECTOR)
-               return -EINVAL;
-
-       return (selector * 100000) + 2400000;
-}
-
 static struct regulator_ops wm8994_ldo1_ops = {
-       .enable = wm8994_ldo_enable,
-       .disable = wm8994_ldo_disable,
-       .is_enabled = wm8994_ldo_is_enabled,
-       .enable_time = wm8994_ldo_enable_time,
-
-       .list_voltage = wm8994_ldo1_list_voltage,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
        .set_voltage_sel = regulator_set_voltage_sel_regmap,
 };
@@ -124,11 +67,6 @@ static int wm8994_ldo2_list_voltage(struct regulator_dev *rdev,
 }
 
 static struct regulator_ops wm8994_ldo2_ops = {
-       .enable = wm8994_ldo_enable,
-       .disable = wm8994_ldo_disable,
-       .is_enabled = wm8994_ldo_is_enabled,
-       .enable_time = wm8994_ldo_enable_time,
-
        .list_voltage = wm8994_ldo2_list_voltage,
        .get_voltage_sel = regulator_get_voltage_sel_regmap,
        .set_voltage_sel = regulator_set_voltage_sel_regmap,
@@ -143,6 +81,9 @@ static const struct regulator_desc wm8994_ldo_desc[] = {
                .vsel_reg = WM8994_LDO_1,
                .vsel_mask = WM8994_LDO1_VSEL_MASK,
                .ops = &wm8994_ldo1_ops,
+               .min_uV = 2400000,
+               .uV_step = 100000,
+               .enable_time = 3000,
                .owner = THIS_MODULE,
        },
        {
@@ -153,6 +94,7 @@ static const struct regulator_desc wm8994_ldo_desc[] = {
                .vsel_reg = WM8994_LDO_2,
                .vsel_mask = WM8994_LDO2_VSEL_MASK,
                .ops = &wm8994_ldo2_ops,
+               .enable_time = 3000,
                .owner = THIS_MODULE,
        },
 };
@@ -176,39 +118,26 @@ static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
 
        ldo->wm8994 = wm8994;
 
-       if (pdata->ldo[id].enable && gpio_is_valid(pdata->ldo[id].enable)) {
-               ldo->enable = pdata->ldo[id].enable;
-
-               ret = gpio_request_one(ldo->enable, 0, "WM8994 LDO enable");
-               if (ret < 0) {
-                       dev_err(&pdev->dev, "Failed to get enable GPIO: %d\n",
-                               ret);
-                       goto err;
-               }
-       } else
-               ldo->is_enabled = true;
-
        config.dev = wm8994->dev;
        config.driver_data = ldo;
        config.regmap = wm8994->regmap;
-       if (pdata)
+       if (pdata) {
                config.init_data = pdata->ldo[id].init_data;
+               config.ena_gpio = pdata->ldo[id].enable;
+       }
 
        ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &config);
        if (IS_ERR(ldo->regulator)) {
                ret = PTR_ERR(ldo->regulator);
                dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
                        id + 1, ret);
-               goto err_gpio;
+               goto err;
        }
 
        platform_set_drvdata(pdev, ldo);
 
        return 0;
 
-err_gpio:
-       if (gpio_is_valid(ldo->enable))
-               gpio_free(ldo->enable);
 err:
        return ret;
 }
@@ -220,8 +149,6 @@ static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
        platform_set_drvdata(pdev, NULL);
 
        regulator_unregister(ldo->regulator);
-       if (gpio_is_valid(ldo->enable))
-               gpio_free(ldo->enable);
 
        return 0;
 }
index dc474bc6522de1d44295f67ad3ddb1f7bc33a771..fca9790c7de75550d6e9700be52ee0d019762531 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/interrupt.h>
 #include <linux/ioctl.h>
 #include <linux/completion.h>
+#include <linux/io.h>
 
 #include <asm/uaccess.h>
 
index 4267789ca9959413e90df5ea053154e07481d3ce..132333d754085d6b06a9c096444a95b708e45893 100644 (file)
@@ -568,6 +568,7 @@ static irqreturn_t cmos_interrupt(int irq, void *p)
                hpet_mask_rtc_irq_bit(RTC_AIE);
 
                CMOS_READ(RTC_INTR_FLAGS);
+               pm_wakeup_event(cmos_rtc.dev, 0);
        }
        spin_unlock(&rtc_lock);
 
index 10287865e33012a154100b6b674f541273d132d3..739ef55694f4d30c6d7370ae66c5ad42e996430f 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/rtc.h>
 #include <linux/slab.h>
+#include <linux/of_device.h>
 
 #include <mach/common.h>
 
@@ -265,6 +266,12 @@ static int stmp3xxx_rtc_resume(struct platform_device *dev)
 #define stmp3xxx_rtc_resume    NULL
 #endif
 
+static const struct of_device_id rtc_dt_ids[] = {
+       { .compatible = "fsl,stmp3xxx-rtc", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rtc_dt_ids);
+
 static struct platform_driver stmp3xxx_rtcdrv = {
        .probe          = stmp3xxx_rtc_probe,
        .remove         = stmp3xxx_rtc_remove,
@@ -273,6 +280,7 @@ static struct platform_driver stmp3xxx_rtcdrv = {
        .driver         = {
                .name   = "stmp3xxx-rtc",
                .owner  = THIS_MODULE,
+               .of_match_table = rtc_dt_ids,
        },
 };
 
index f3509120a507f56e3b152e1dee4cb5990ce23d79..15370a2c5ff0b29e5286a9ffb2660beefd045f2e 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * File...........: linux/drivers/s390/block/dasd.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  *                 Horst Hummel <Horst.Hummel@de.ibm.com>
  *                 Carsten Otte <Cotte@de.ibm.com>
@@ -52,7 +51,7 @@ void dasd_int_handler(struct ccw_device *, unsigned long, struct irb *);
 
 MODULE_AUTHOR("Holger Smolinski <Holger.Smolinski@de.ibm.com>");
 MODULE_DESCRIPTION("Linux on S/390 DASD device driver,"
-                  " Copyright 2000 IBM Corporation");
+                  " Copyright IBM Corp. 2000");
 MODULE_SUPPORTED_DEVICE("dasd");
 MODULE_LICENSE("GPL");
 
@@ -82,6 +81,7 @@ static void dasd_profile_exit(struct dasd_profile *);
 static wait_queue_head_t dasd_init_waitq;
 static wait_queue_head_t dasd_flush_wq;
 static wait_queue_head_t generic_waitq;
+static wait_queue_head_t shutdown_waitq;
 
 /*
  * Allocate memory for a new device structure.
@@ -1994,6 +1994,8 @@ static void dasd_device_tasklet(struct dasd_device *device)
        /* Now check if the head of the ccw queue needs to be started. */
        __dasd_device_start_head(device);
        spin_unlock_irq(get_ccwdev_lock(device->cdev));
+       if (waitqueue_active(&shutdown_waitq))
+               wake_up(&shutdown_waitq);
        dasd_put_device(device);
 }
 
@@ -2632,6 +2634,8 @@ static void dasd_block_tasklet(struct dasd_block *block)
        __dasd_block_start_head(block);
        spin_unlock(&block->queue_lock);
        spin_unlock_irq(&block->request_queue_lock);
+       if (waitqueue_active(&shutdown_waitq))
+               wake_up(&shutdown_waitq);
        dasd_put_device(block->base);
 }
 
@@ -3474,6 +3478,32 @@ char *dasd_get_sense(struct irb *irb)
 }
 EXPORT_SYMBOL_GPL(dasd_get_sense);
 
+static inline int _wait_for_empty_queues(struct dasd_device *device)
+{
+       if (device->block)
+               return list_empty(&device->ccw_queue) &&
+                       list_empty(&device->block->ccw_queue);
+       else
+               return list_empty(&device->ccw_queue);
+}
+
+void dasd_generic_shutdown(struct ccw_device *cdev)
+{
+       struct dasd_device *device;
+
+       device = dasd_device_from_cdev(cdev);
+       if (IS_ERR(device))
+               return;
+
+       if (device->block)
+               dasd_schedule_block_bh(device->block);
+
+       dasd_schedule_device_bh(device);
+
+       wait_event(shutdown_waitq, _wait_for_empty_queues(device));
+}
+EXPORT_SYMBOL_GPL(dasd_generic_shutdown);
+
 static int __init dasd_init(void)
 {
        int rc;
@@ -3481,6 +3511,7 @@ static int __init dasd_init(void)
        init_waitqueue_head(&dasd_init_waitq);
        init_waitqueue_head(&dasd_flush_wq);
        init_waitqueue_head(&generic_waitq);
+       init_waitqueue_head(&shutdown_waitq);
 
        /* register 'common' DASD debug area, used for all DBF_XXX calls */
        dasd_debug_area = debug_register("dasd", 1, 1, 8 * sizeof(long));
index 0326571e7ffa61f0a15ee4782897393146132421..f8212d54013a8515188518cd4ee7ea175c9d1d44 100644 (file)
@@ -1,9 +1,8 @@
 /*
- * File...........: linux/drivers/s390/block/dasd_3990_erp.c
  * Author(s)......: Horst  Hummel    <Horst.Hummel@de.ibm.com>
  *                 Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000, 2001
+ * Copyright IBM Corp. 2000, 2001
  *
  */
 
index b3beed5434e43d8064cbf48659a4ff9426ea3c36..157defe5e0693c06c6432ddfbd65d0f6632a6f90 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * PAV alias management for the DASD ECKD discipline
  *
- * Copyright IBM Corporation, 2007
+ * Copyright IBM Corp. 2007
  * Author(s): Stefan Weinhuber <wein@de.ibm.com>
  */
 
index d71511c7850a8560014ceee03c468e4da24c361a..b2b8c18eecedc98f32b708aa000649f35102fa93 100644 (file)
@@ -1,11 +1,10 @@
 /*
- * File...........: linux/drivers/s390/block/dasd_devmap.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  *                 Horst Hummel <Horst.Hummel@de.ibm.com>
  *                 Carsten Otte <Cotte@de.ibm.com>
  *                 Martin Schwidefsky <schwidefsky@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
+ * Copyright IBM Corp. 1999,2001
  *
  * Device mapping and dasd= parameter parsing functions. All devmap
  * functions may not be called from interrupt context. In particular
index 0cea7e98f464bd30d54556675b7a5174ab420b15..9bd5da36f99eb2d3a36642b05508d5578f473846 100644 (file)
@@ -1,10 +1,9 @@
 /*
- * File...........: linux/drivers/s390/block/dasd_diag.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Based on.......: linux/drivers/s390/block/mdisk.c
  * ...............: by Hartmunt Penner <hpenner@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ * Copyright IBM Corp. 1999, 2000
  *
  */
 
index 4f71fbe60c8294df766d783c2ace72c33ef0d50a..a803cc731586cc69191867eaf7eb7d6d55e1b232 100644 (file)
@@ -1,10 +1,9 @@
 /*
- * File...........: linux/drivers/s390/block/dasd_diag.h
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Based on.......: linux/drivers/s390/block/mdisk.h
  * ...............: by Hartmunt Penner <hpenner@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ * Copyright IBM Corp. 1999, 2000
  *
  */
 
index bc2e8a7c265b518e8049bdb1877e0cf57a1b19a2..40a826a7295f7282ec8f05e2dcfd66d8f9601927 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * File...........: linux/drivers/s390/block/dasd_eckd.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  *                 Horst Hummel <Horst.Hummel@de.ibm.com>
  *                 Carsten Otte <Cotte@de.ibm.com>
@@ -4247,6 +4246,7 @@ static struct ccw_driver dasd_eckd_driver = {
        .set_online  = dasd_eckd_set_online,
        .notify      = dasd_generic_notify,
        .path_event  = dasd_generic_path_event,
+       .shutdown    = dasd_generic_shutdown,
        .freeze      = dasd_generic_pm_freeze,
        .thaw        = dasd_generic_restore_device,
        .restore     = dasd_generic_restore_device,
index 4a688a873a77bac88b6e2bbd26619653d1796d7b..2555e494591ff57f6e75202f46ae8b4ea61ee9e8 100644 (file)
@@ -1,9 +1,8 @@
 /*
- * File...........: linux/drivers/s390/block/dasd_eckd.h
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  *                 Horst Hummel <Horst.Hummel@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ * Copyright IBM Corp. 1999, 2000
  *
  */
 
index 16c5208c3dc787c8115941fba4895b305f35760c..ff901b5509c10bca67b67c9f4cc4a133f267b0a0 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Character device driver for extended error reporting.
  *
- *  Copyright (C) 2005 IBM Corporation
+ *  Copyright IBM Corp. 2005
  *  extended error reporting for DASD ECKD devices
  *  Author(s): Stefan Weinhuber <wein@de.ibm.com>
  */
index 0eafe2e421e7dfadccdcb0f087ab80605ccd4d24..d01ef82f8757bab711fd8e33736826362f98faea 100644 (file)
@@ -1,11 +1,10 @@
 /*
- * File...........: linux/drivers/s390/block/dasd.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  *                 Horst Hummel <Horst.Hummel@de.ibm.com>
  *                 Carsten Otte <Cotte@de.ibm.com>
  *                 Martin Schwidefsky <schwidefsky@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
+ * Copyright IBM Corp. 1999, 2001
  *
  */
 
index a62a75358eb94ab7686373e7e166628e1eaf2773..fb7f3bdc66049210753b254c4dc972442c9d224a 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * File...........: linux/drivers/s390/block/dasd_fba.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
  * Copyright IBM Corp. 1999, 2009
index 14c910baa5fe6160192b7c548d8921b829707eda..b5d3db0e5efb0164a05af2043f123539230fb053 100644 (file)
@@ -1,8 +1,7 @@
 /*
- * File...........: linux/drivers/s390/block/dasd_fba.h
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000
+ * Coypright IBM Corp. 1999, 2000
  *
  */
 
index 19a1ff03d65ef25c5320585c04064916827a41bb..f64921756ad610375134b3b59f13bbdb5d9906af 100644 (file)
@@ -1,11 +1,10 @@
 /*
- * File...........: linux/drivers/s390/block/dasd_genhd.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  *                 Horst Hummel <Horst.Hummel@de.ibm.com>
  *                 Carsten Otte <Cotte@de.ibm.com>
  *                 Martin Schwidefsky <schwidefsky@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
+ * Copyright IBM Corp. 1999, 2001
  *
  * gendisk related functions for the dasd driver.
  *
index c05da00583f06c94f5fbb12bb110c7f5a60875c8..7ff93eea673d009a1636e8de79c9336e52e9647a 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * File...........: linux/drivers/s390/block/dasd_int.h
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  *                 Horst Hummel <Horst.Hummel@de.ibm.com>
  *                 Martin Schwidefsky <schwidefsky@de.ibm.com>
@@ -686,6 +685,7 @@ int dasd_generic_set_offline (struct ccw_device *cdev);
 int dasd_generic_notify(struct ccw_device *, int);
 int dasd_generic_last_path_gone(struct dasd_device *);
 int dasd_generic_path_operational(struct dasd_device *);
+void dasd_generic_shutdown(struct ccw_device *);
 
 void dasd_generic_handle_state_change(struct dasd_device *);
 int dasd_generic_pm_freeze(struct ccw_device *);
index 792c69e78fe2ae6474635680dba3c9af436b554e..cceae70279f6407d96f7249f02939de53405ea03 100644 (file)
@@ -1,11 +1,10 @@
 /*
- * File...........: linux/drivers/s390/block/dasd_ioctl.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  *                 Horst Hummel <Horst.Hummel@de.ibm.com>
  *                 Carsten Otte <Cotte@de.ibm.com>
  *                 Martin Schwidefsky <schwidefsky@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2001
+ * Copyright IBM Corp. 1999, 2001
  *
  * i/o controls for the dasd driver.
  */
index e12989fff4ffca7f394124a814a176b82985b941..78ac905a5b7f18c046e121ebc41f1e7f37cc84f6 100644 (file)
@@ -1,11 +1,10 @@
 /*
- * File...........: linux/drivers/s390/block/dasd_proc.c
  * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com>
  *                 Horst Hummel <Horst.Hummel@de.ibm.com>
  *                 Carsten Otte <Cotte@de.ibm.com>
  *                 Martin Schwidefsky <schwidefsky@de.ibm.com>
  * Bugreports.to..: <Linux390@de.ibm.com>
- * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999-2002
+ * Coypright IBM Corp. 1999, 2002
  *
  * /proc interface for the dasd driver.
  *
index 0e9a309b96691d6ec1c2209bb01a6f351a3a04d6..8de2deb176d716daf043e9c80afd1536043eb94b 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  drivers/s390/char/ctrlchar.c
  *  Unified handling of special chars.
  *
- *    Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2001
  *    Author(s): Fritz Elfert <felfert@millenux.com> <elfert@de.ibm.com>
  *
  */
index 935ffa0ea7c6b6dec71bab6ff76f76531a80470b..1a53552f4981dd466a1b38d3b985d84675602e9c 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  drivers/s390/char/ctrlchar.c
  *  Unified handling of special chars.
  *
- *    Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2001
  *    Author(s): Fritz Elfert <felfert@millenux.com> <elfert@de.ibm.com>
  *
  */
index 7ef9cfdc17d8ca983b7d735c0599e8e56ba3e68d..01463b052ae740aa56cd6ea816102a34961ed668 100644 (file)
@@ -1,9 +1,8 @@
 /*
- *  drivers/s390/char/keyboard.c
  *    ebcdic keycode functions for s390 console drivers
  *
  *  S390 version
- *    Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2003
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  */
 
index f682f4e4968041d41237e3b791d1421a544b9095..d0ae2be581910bad288b808fe4e6940c212b4ef8 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  drivers/s390/char/keyboard.h
  *    ebcdic keycode functions for s390 console drivers
  *
- *    Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2003
  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  */
 
index 3c03c1060be6d3cb12c408c7834936f651050def..444d36183a251c38e2c72fda8084ac33f3bd358b 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/char/sclp_config.c
- *
  *    Copyright IBM Corp. 2007
  *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
  */
index 5716487b8c9d378cf0c7b37645abd985d894a687..d70d8c20229c1d3d9a8a4f8a99b8e897591f91f0 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *  drivers/s390/char/sclp_cpi.c
  *    SCLP control programm identification
  *
  *    Copyright IBM Corp. 2001, 2007
index bd1b9c9190514188b9c1469e8f2d2fb23a82c606..2acea809e2accf3f6c6078dd7acec6ed5e3cc256 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *  drivers/s390/char/sclp_cpi_sys.c
  *    SCLP control program identification sysfs interface
  *
  *    Copyright IBM Corp. 2001, 2007
index deef3e6ff49683a8e89a598b6b87b167972d1f2c..65bb6a99c97f550f6d2cdc11f72e09afecfb7dd0 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *  drivers/s390/char/sclp_cpi_sys.h
  *    SCLP control program identification sysfs interface
  *
  *    Copyright IBM Corp. 2007
index ab294d5a534e42386a3056e2fb7e474d781498e2..2553db0fdb5285965df26f1c62d903415c0068fb 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *  drivers/s390/char/sclp_ocf.c
  *    SCLP OCF communication parameters sysfs interface
  *
  *    Copyright IBM Corp. 2011
index 69df137310bc5b5a3081969530d042c77bf095da..475e470d9768ea729adc9ba95feee801f942dda1 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  drivers/s390/char/sclp_quiesce.c
  *     signal quiesce handler
  *
- *  (C) Copyright IBM Corp. 1999,2004
+ *  Copyright IBM Corp. 1999, 2004
  *  Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>
  *             Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
index 50f7115990fffc3954cc99f24bdd06d1caa4fa7a..6a6f76bf6e3dad4fae79fedc125bb39b7678b79a 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Sclp "store data in absolut storage"
  *
- * Copyright IBM Corp. 2003,2007
+ * Copyright IBM Corp. 2003, 2007
  * Author(s): Michael Holzheu
  */
 
index e66a75b3822cbf24f09c0824c87b7f0c81089749..0792c85baafebdefcad5888423ff5b0bc19bee35 100644 (file)
@@ -1,9 +1,8 @@
 /*
- *  drivers/s390/char/sclp_tty.c
  *    SCLP line mode terminal driver.
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Martin Peschke <mpeschke@de.ibm.com>
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
index 4b965b22fecd7a24e375059d8cb0aa5b7f5c5d1b..c8773421c31fc25e8d8dc6e40e54992c818ac16a 100644 (file)
@@ -1,9 +1,8 @@
 /*
- *  drivers/s390/char/sclp_tty.h
  *    interface to the SCLP-read/write driver
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 1999
  *    Author(s): Martin Peschke <mpeschke@de.ibm.com>
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>
  */
index bc6c7cfd36b615cac0565203c8a372dbf6d8c82f..c06be6cc2fc3731182f42e96028372ca4044baf4 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *  drivers/s390/char/tape.h
  *    tape device driver for 3480/3490E/3590 tapes.
  *
  *  S390 and zSeries version
index b28de80b7ca48194c760e309b7e9db53c2045892..6ae929c024ae3bf811ecabe4986301ac6b9a807b 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *  drivers/s390/char/tape_34xx.c
  *    tape device discipline for 3480/3490 tapes.
  *
  *    Copyright IBM Corp. 2001, 2009
index a5c6614b0db259429e034c7817714b3a59c64158..1b0eb49f739c72413c5cdd43835c54141c2464e6 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *  drivers/s390/char/tape_3590.c
  *    tape device discipline for 3590 tapes.
  *
  *    Copyright IBM Corp. 2001, 2009
index 4534055f1376aa3bceb0fdbc7505401fad64877c..36b759e89d22d9aca38c7294a03983648b421a74 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  drivers/s390/char/tape_3590.h
  *    tape device discipline for 3590 tapes.
  *
- *    Copyright IBM Corp. 2001,2006
+ *    Copyright IBM Corp. 2001, 2006
  *    Author(s): Stefan Bader <shbader@de.ibm.com>
  *              Michael Holzheu <holzheu@de.ibm.com>
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>
index 46886a7578c6d850ef2226b6d661eee2628518c7..2d61db3fc62af5c33c3e84b42624c7ce92da231d 100644 (file)
@@ -1,9 +1,8 @@
 /*
- *  drivers/s390/char/tape_char.c
  *    character device frontend for tape device driver
  *
  *  S390 and zSeries version
- *    Copyright IBM Corp. 2001,2006
+ *    Copyright IBM Corp. 2001, 2006
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *              Michael Holzheu <holzheu@de.ibm.com>
  *              Tuan Ngo-Anh <ngoanh@de.ibm.com>
index 55343df61edde6a583328d1a7faa0c2515491670..54b3c79203f5103964e93b80c73e7cc1f13ae9a6 100644 (file)
@@ -1,6 +1,5 @@
 /*
- * (C) Copyright IBM Corp. 2004
- * tape_class.c
+ * Copyright IBM Corp. 2004
  *
  * Tape class device support
  *
@@ -17,7 +16,7 @@
 
 MODULE_AUTHOR("Stefan Bader <shbader@de.ibm.com>");
 MODULE_DESCRIPTION(
-       "(C) Copyright IBM Corp. 2004   All Rights Reserved.\n"
+       "Copyright IBM Corp. 2004   All Rights Reserved.\n"
        "tape_class.c"
 );
 MODULE_LICENSE("GPL");
index ba2092f741d57876bcba1f3cfc3e5237782c83bb..a332c10d50ad4fb701ebcecd6472af002275679d 100644 (file)
@@ -1,6 +1,5 @@
 /*
- * (C) Copyright IBM Corp. 2004   All Rights Reserved.
- * tape_class.h
+ * Copyright IBM Corp. 2004   All Rights Reserved.
  *
  * Tape class device support
  *
index 585618663ba458bb846e8659630a8df778659b6e..f3b5123faf0822e07d9771fb1c922b5fdfe101b8 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *  drivers/s390/char/tape_core.c
  *    basic function of the tape device driver
  *
  *  S390 and zSeries version
index 0ceb37984f7766d3a565a45f3f9b8373ad4b21e7..8733b232a116350c96444414cb7b82ae949b382d 100644 (file)
@@ -1,9 +1,8 @@
 /*
- *  drivers/s390/char/tape.c
  *    tape device driver for S/390 and zSeries tapes.
  *
  *  S390 and zSeries version
- *    Copyright (C) 2001 IBM Corporation
+ *    Copyright IBM Corp. 2001
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *              Michael Holzheu <holzheu@de.ibm.com>
  *              Tuan Ngo-Anh <ngoanh@de.ibm.com>
index e7650170274ac3e3ee12e6f1deca3bdd1e826b95..981a99fd8d4285c2b443f81a320c48f8826871cf 100644 (file)
@@ -1,9 +1,8 @@
 /*
- *  drivers/s390/char/tape_std.c
  *    standard tape device functions for ibm tapes.
  *
  *  S390 and zSeries version
- *    Copyright (C) 2001,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright IBM Corp. 2001, 2002
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *              Michael Holzheu <holzheu@de.ibm.com>
  *              Tuan Ngo-Anh <ngoanh@de.ibm.com>
index 1fc9523593413d7ea1a0ff7e95c49c2817ef82a6..c5816ad9ed7d065880521a089b41d215c5b8fa52 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  drivers/s390/char/tape_std.h
  *    standard tape device functions for ibm tapes.
  *
- *    Copyright (C) IBM Corp. 2001,2006
+ *    Copyright IBM Corp. 2001, 2006
  *    Author(s): Carsten Otte <cotte@de.ibm.com>
  *              Tuan Ngo-Anh <ngoanh@de.ibm.com>
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>
index 10ec690197cbfdd4d9d4fd9652128ec0a4ed6dce..1928f3458d10f197bb15b7a75da7d685b33da4e1 100644 (file)
@@ -1,11 +1,10 @@
 /*
- *  drivers/s390/char/tty3270.c
  *    IBM/3270 Driver - tty functions.
  *
  *  Author(s):
  *    Original 3270 Code for 2.4 written by Richard Hitt (UTS Global)
  *    Rewritten for 2.5 by Martin Schwidefsky <schwidefsky@de.ibm.com>
- *     -- Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *     -- Copyright IBM Corp. 2003
  */
 
 #include <linux/module.h>
index 799da57f0390c4b0ba63404b2df78107c85956ff..11141a8f897414f63c1c0602e4b40bdc9fd5b132 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/char/tty3270.h
- *
  *    Copyright IBM Corp. 2007
  *
  */
index 89c03e6b1c0c633d5b3bb8cd051c83ae7aa8d1e4..0fdedadff7bc845f7700c43b1e830542f7948fcf 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright IBM Corp. 2004,2010
+ * Copyright IBM Corp. 2004, 2010
  * Interface implementation for communication with the z/VM control program
  *
  * Author(s): Christian Borntraeger <borntraeger@de.ibm.com>
index 6a993948e188c3a0219832757fd51922d8dab665..1e29b04183820cda1c576764478a5b42ff4dd1d6 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2004, 2005 IBM Corporation
+ * Copyright IBM Corp. 2004, 2005
  * Interface implementation for communication with the z/VM control program
  * Version 1.0
  * Author(s): Christian Borntraeger <cborntra@de.ibm.com>
index 524d988d89dd4c064cef8839370c692930d12352..c131bc40f96268a7a9163681a579a3a0a843dede 100644 (file)
@@ -1,5 +1,4 @@
 /*
- * drivers/s390/char/vmlogrdr.c
  *     character device driver for reading z/VM system service records
  *
  *
@@ -656,10 +655,19 @@ static ssize_t vmlogrdr_recording_status_show(struct device_driver *driver,
        len = strlen(buf);
        return len;
 }
-
-
 static DRIVER_ATTR(recording_status, 0444, vmlogrdr_recording_status_show,
                   NULL);
+static struct attribute *vmlogrdr_drv_attrs[] = {
+       &driver_attr_recording_status.attr,
+       NULL,
+};
+static struct attribute_group vmlogrdr_drv_attr_group = {
+       .attrs = vmlogrdr_drv_attrs,
+};
+static const struct attribute_group *vmlogrdr_drv_attr_groups[] = {
+       &vmlogrdr_drv_attr_group,
+       NULL,
+};
 
 static struct attribute *vmlogrdr_attrs[] = {
        &dev_attr_autopurge.attr,
@@ -668,6 +676,13 @@ static struct attribute *vmlogrdr_attrs[] = {
        &dev_attr_recording.attr,
        NULL,
 };
+static struct attribute_group vmlogrdr_attr_group = {
+       .attrs = vmlogrdr_attrs,
+};
+static const struct attribute_group *vmlogrdr_attr_groups[] = {
+       &vmlogrdr_attr_group,
+       NULL,
+};
 
 static int vmlogrdr_pm_prepare(struct device *dev)
 {
@@ -692,18 +707,14 @@ static const struct dev_pm_ops vmlogrdr_pm_ops = {
        .prepare = vmlogrdr_pm_prepare,
 };
 
-static struct attribute_group vmlogrdr_attr_group = {
-       .attrs = vmlogrdr_attrs,
-};
-
 static struct class *vmlogrdr_class;
 static struct device_driver vmlogrdr_driver = {
        .name = "vmlogrdr",
        .bus  = &iucv_bus,
        .pm = &vmlogrdr_pm_ops,
+       .groups = vmlogrdr_drv_attr_groups,
 };
 
-
 static int vmlogrdr_register_driver(void)
 {
        int ret;
@@ -717,21 +728,14 @@ static int vmlogrdr_register_driver(void)
        if (ret)
                goto out_iucv;
 
-       ret = driver_create_file(&vmlogrdr_driver,
-                                &driver_attr_recording_status);
-       if (ret)
-               goto out_driver;
-
        vmlogrdr_class = class_create(THIS_MODULE, "vmlogrdr");
        if (IS_ERR(vmlogrdr_class)) {
                ret = PTR_ERR(vmlogrdr_class);
                vmlogrdr_class = NULL;
-               goto out_attr;
+               goto out_driver;
        }
        return 0;
 
-out_attr:
-       driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
 out_driver:
        driver_unregister(&vmlogrdr_driver);
 out_iucv:
@@ -745,7 +749,6 @@ static void vmlogrdr_unregister_driver(void)
 {
        class_destroy(vmlogrdr_class);
        vmlogrdr_class = NULL;
-       driver_remove_file(&vmlogrdr_driver, &driver_attr_recording_status);
        driver_unregister(&vmlogrdr_driver);
        iucv_unregister(&vmlogrdr_iucv_handler, 1);
 }
@@ -762,6 +765,7 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
                dev->bus = &iucv_bus;
                dev->parent = iucv_root;
                dev->driver = &vmlogrdr_driver;
+               dev->groups = vmlogrdr_attr_groups;
                dev_set_drvdata(dev, priv);
                /*
                 * The release function could be called after the
@@ -779,11 +783,6 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
                return ret;
        }
 
-       ret = sysfs_create_group(&dev->kobj, &vmlogrdr_attr_group);
-       if (ret) {
-               device_unregister(dev);
-               return ret;
-       }
        priv->class_device = device_create(vmlogrdr_class, dev,
                                           MKDEV(vmlogrdr_major,
                                                 priv->minor_num),
@@ -791,7 +790,6 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv)
        if (IS_ERR(priv->class_device)) {
                ret = PTR_ERR(priv->class_device);
                priv->class_device=NULL;
-               sysfs_remove_group(&dev->kobj, &vmlogrdr_attr_group);
                device_unregister(dev);
                return ret;
        }
@@ -804,7 +802,6 @@ static int vmlogrdr_unregister_device(struct vmlogrdr_priv_t *priv)
 {
        device_destroy(vmlogrdr_class, MKDEV(vmlogrdr_major, priv->minor_num));
        if (priv->device != NULL) {
-               sysfs_remove_group(&priv->device->kobj, &vmlogrdr_attr_group);
                device_unregister(priv->device);
                priv->device=NULL;
        }
index 2211277a10793201936b3c7253958149972723ec..e9b72311e2549a370f1d213c9a8277e7c233186f 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Watchdog implementation based on z/VM Watchdog Timer API
  *
- * Copyright IBM Corp. 2004,2009
+ * Copyright IBM Corp. 2004, 2009
  *
  * The user space watchdog daemon can use this driver as
  * /dev/vmwatchdog to have z/VM execute the specified CP
index 3303d66b27941c7d1e51e5031f6867c25fbbb8a5..e3b9308b0fe370edf21ec866704dbcb68e08e90a 100644 (file)
@@ -5,7 +5,7 @@
  *
  * For more information please refer to Documentation/s390/zfcpdump.txt
  *
- * Copyright IBM Corp. 2003,2008
+ * Copyright IBM Corp. 2003, 2008
  * Author(s): Michael Holzheu
  */
 
index 65d2e769dfa16123ff0a50593ef0797ff670e8f5..bc10220f684700e2909ed45a8ece94015d1b44ba 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  drivers/s390/cio/airq.c
  *    Support for adapter interruptions
  *
- *    Copyright IBM Corp. 1999,2007
+ *    Copyright IBM Corp. 1999, 2007
  *    Author(s): Ingo Adlung <adlung@de.ibm.com>
  *              Cornelia Huck <cornelia.huck@de.ibm.com>
  *              Arnd Bergmann <arndb@de.ibm.com>
index 08c66035dd19036814b1ff051e917e93165eca85..2d2a966a3b39cdc0cf267b060d1f64285ef4ee84 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  drivers/s390/cio/blacklist.c
  *   S/390 common I/O routines -- blacklisting of specific devices
  *
- *    Copyright (C) 1999-2002 IBM Deutschland Entwicklung GmbH,
- *                           IBM Corporation
+ *    Copyright IBM Corp. 1999, 2002
  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
  *              Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Arnd Bergmann (arndb@de.ibm.com)
index e792436c92701fc684fc830c0656666c5a73c95c..50ad5fdd815dca03e53f62c1c0798738d375f9e0 100644 (file)
@@ -1,7 +1,5 @@
 /*
- *  drivers/s390/cio/chp.c
- *
- *    Copyright IBM Corp. 1999,2010
+ *    Copyright IBM Corp. 1999, 2010
  *    Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Arnd Bergmann (arndb@de.ibm.com)
  *              Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
@@ -362,10 +360,13 @@ static struct attribute *chp_attrs[] = {
        &dev_attr_shared.attr,
        NULL,
 };
-
 static struct attribute_group chp_attr_group = {
        .attrs = chp_attrs,
 };
+static const struct attribute_group *chp_attr_groups[] = {
+       &chp_attr_group,
+       NULL,
+};
 
 static void chp_release(struct device *dev)
 {
@@ -397,6 +398,7 @@ int chp_new(struct chp_id chpid)
        chp->chpid = chpid;
        chp->state = 1;
        chp->dev.parent = &channel_subsystems[chpid.cssid]->device;
+       chp->dev.groups = chp_attr_groups;
        chp->dev.release = chp_release;
        mutex_init(&chp->lock);
 
@@ -426,16 +428,10 @@ int chp_new(struct chp_id chpid)
                put_device(&chp->dev);
                goto out;
        }
-       ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group);
-       if (ret) {
-               device_unregister(&chp->dev);
-               goto out;
-       }
        mutex_lock(&channel_subsystems[chpid.cssid]->mutex);
        if (channel_subsystems[chpid.cssid]->cm_enabled) {
                ret = chp_add_cmg_attr(chp);
                if (ret) {
-                       sysfs_remove_group(&chp->dev.kobj, &chp_attr_group);
                        device_unregister(&chp->dev);
                        mutex_unlock(&channel_subsystems[chpid.cssid]->mutex);
                        goto out;
index 12b4903d6fe373f171b83a8a8a7d9ffc2e9a8b26..e1399dbee83430510ff6266e0bb02957916848cf 100644 (file)
@@ -1,7 +1,5 @@
 /*
- *  drivers/s390/cio/chp.h
- *
- *    Copyright IBM Corp. 2007,2010
+ *    Copyright IBM Corp. 2007, 2010
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
 
index a84631a7391d3ed50c680b939129d159fc25daa3..cfe0c087fe5cc915859265bb59016076e120d84c 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  drivers/s390/cio/chsc.c
  *   S/390 common I/O routines -- channel subsystem call
  *
- *    Copyright IBM Corp. 1999,2010
+ *    Copyright IBM Corp. 1999, 2010
  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
  *              Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Arnd Bergmann (arndb@de.ibm.com)
index a6ddaed8793d3e43896c1758a64aa684b54ee0eb..33d1ef7035936732ec44c32c386be511294fe1f0 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  drivers/s390/cio/cio.c
  *   S/390 common I/O routines -- low level i/o calls
  *
- *    Copyright IBM Corp. 1999,2008
+ *    Copyright IBM Corp. 1999, 2008
  *    Author(s): Ingo Adlung (adlung@de.ibm.com)
  *              Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Arnd Bergmann (arndb@de.ibm.com)
index 204ca728e7fd8c097591f1b81541238a57681814..c9fc61c0a8661702faf5ee10f89a65b4d1b59a83 100644 (file)
@@ -1,9 +1,7 @@
 /*
- * linux/drivers/s390/cio/cmf.c
- *
  * Linux on zSeries Channel Measurement Facility support
  *
- * Copyright 2000,2006 IBM Corporation
+ * Copyright IBM Corp. 2000, 2006
  *
  * Authors: Arnd Bergmann <arndb@de.ibm.com>
  *         Cornelia Huck <cornelia.huck@de.ibm.com>
@@ -1341,7 +1339,7 @@ module_init(init_cmf);
 MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("channel measurement facility base driver\n"
-                  "Copyright 2003 IBM Corporation\n");
+                  "Copyright IBM Corp. 2003\n");
 
 EXPORT_SYMBOL_GPL(enable_cmf);
 EXPORT_SYMBOL_GPL(disable_cmf);
index d0a2dff43fb47eaf95d5097ad42312ddf46e24c1..0f8a25f98b10629de82b87591e3e669175cf4526 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *   Channel report handling code
  *
- *    Copyright IBM Corp. 2000,2009
+ *    Copyright IBM Corp. 2000, 2009
  *    Author(s): Ingo Adlung <adlung@de.ibm.com>,
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>,
  *              Cornelia Huck <cornelia.huck@de.ibm.com>,
index f8f952d520457232f23f92272f7891bb5a03fecf..ed25c8740a9ce4b0bb8e8334a32b72abc08655ae 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  drivers/s390/cio/device.c
  *  bus driver for ccw devices
  *
- *    Copyright IBM Corp. 2002,2008
+ *    Copyright IBM Corp. 2002, 2008
  *    Author(s): Arnd Bergmann (arndb@de.ibm.com)
  *              Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Martin Schwidefsky (schwidefsky@de.ibm.com)
index 1b853513c891ca2f010f8703b110f49c6f65afb3..1bb1d00095afb2c793483c46d2f759c18459f552 100644 (file)
@@ -1,8 +1,7 @@
 /*
- * drivers/s390/cio/device_fsm.c
  * finite state machine for device handling
  *
- *    Copyright IBM Corp. 2002,2008
+ *    Copyright IBM Corp. 2002, 2008
  *    Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
index 78a0b43862c5feb41c0888812c978f686f5f4891..d4fa30541a33bc48f4c318f113ca4e9a5b3d56d3 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  CCW device SENSE ID I/O handling.
  *
- *    Copyright IBM Corp. 2002,2009
+ *    Copyright IBM Corp. 2002, 2009
  *    Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>
  *              Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
index 07a4fd29f0968f5e7bb485761a1b340525a9eeac..368368fe04b27fa29a4506ae87177afa9e8e05a9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  CCW device PGID and path verification I/O handling.
  *
- *    Copyright IBM Corp. 2002,2009
+ *    Copyright IBM Corp. 2002, 2009
  *    Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
  *              Martin Schwidefsky <schwidefsky@de.ibm.com>
  *              Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
index 66d8066ef22a0ccc5dc8ae3911281209dd18fa80..15b56a15db151cf4cfdfbc1e251a57400fb0706c 100644 (file)
@@ -1,8 +1,5 @@
 /*
- * drivers/s390/cio/device_status.c
- *
- *    Copyright (C) 2002 IBM Deutschland Entwicklung GmbH,
- *                      IBM Corporation
+ *    Copyright IBM Corp. 2002
  *    Author(s): Cornelia Huck (cornelia.huck@de.ibm.com)
  *              Martin Schwidefsky (schwidefsky@de.ibm.com)
  *
index 4d10981c7cc102a3ffe1bf8c107cb08d5280d212..e6d5f8c49524d05f78f6548a2937b1747bd7ffe6 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/cio/idset.c
- *
  *    Copyright IBM Corp. 2007
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
index 7543da4529f9f05ded52997b45dbbc34cbaf420d..3d943f03591e1b2180cc6fdd9c92e54c99a0d0e4 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/cio/idset.h
- *
  *    Copyright IBM Corp. 2007
  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
  */
index b962ffbc0803dead8c7efb3e49bd4f5d903bc6a4..5132554d7917f0994f543aea947dcdfdcdcb17d4 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * linux/drivers/s390/cio/qdio.h
- *
- * Copyright 2000,2009 IBM Corp.
+ * Copyright IBM Corp. 2000, 2009
  * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
  *           Jan Glauber <jang@linux.vnet.ibm.com>
  */
index 29021f4e96b6409bc5dffc12b9717871a652bb49..e6e0d31c02acea47a02a8b4a8a7746700de930fb 100644 (file)
@@ -1,7 +1,5 @@
 /*
- *  drivers/s390/cio/qdio_debug.c
- *
- *  Copyright IBM Corp. 2008,2009
+ *  Copyright IBM Corp. 2008, 2009
  *
  *  Author: Jan Glauber (jang@linux.vnet.ibm.com)
  */
index 5d70bd162ae9598cc078fbc5c948b4d38fe28d74..e1f646800ddb7e7cc1ae6a6daa0a03f766ce3a4e 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/cio/qdio_debug.h
- *
  *  Copyright IBM Corp. 2008
  *
  *  Author: Jan Glauber (jang@linux.vnet.ibm.com)
index 7493efafa0d5a69b8ad674ba38bc47d42d097c8b..e06fa03ea1e456bac69ba5f84e634ebbd9f645ce 100644 (file)
@@ -1,9 +1,7 @@
 /*
- * linux/drivers/s390/cio/qdio_main.c
- *
  * Linux for s390 qdio support, buffer handling, qdio API and module support.
  *
- * Copyright 2000,2008 IBM Corp.
+ * Copyright IBM Corp. 2000, 2008
  * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
  *           Jan Glauber <jang@linux.vnet.ibm.com>
  * 2.6 cio integration by Cornelia Huck <cornelia.huck@de.ibm.com>
index ecf12f0aca7b2052c5d8d127bba3a73769a2270e..6c973db149832f13ce9edd9dc38152991054c889 100644 (file)
@@ -1,9 +1,7 @@
 /*
- * driver/s390/cio/qdio_setup.c
- *
  * qdio queue initialization
  *
- * Copyright (C) IBM Corp. 2008
+ * Copyright IBM Corp. 2008
  * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
  */
 #include <linux/kernel.h>
index 011eadea3ee422fabb85ef24caa784401682ff89..2e060088fa87872cb9a9c45edd847e999c54bf6e 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * linux/drivers/s390/cio/thinint_qdio.c
- *
- * Copyright 2000,2009 IBM Corp.
+ * Copyright IBM Corp. 2000, 2009
  * Author(s): Utz Bacher <utz.bacher@de.ibm.com>
  *           Cornelia Huck <cornelia.huck@de.ibm.com>
  *           Jan Glauber <jang@linux.vnet.ibm.com>
index b987d4619586b0d0337db02691a67a2e1a97a043..ae258a4b4e5ea8866333fec3204dba7513fbda5c 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * linux/drivers/s390/crypto/ap_bus.c
- *
- * Copyright (C) 2006 IBM Corporation
+ * Copyright IBM Corp. 2006
  * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
  *           Martin Schwidefsky <schwidefsky@de.ibm.com>
  *           Ralph Wuerthner <rwuerthn@de.ibm.com>
@@ -70,7 +68,7 @@ static int ap_select_domain(void);
  */
 MODULE_AUTHOR("IBM Corporation");
 MODULE_DESCRIPTION("Adjunct Processor Bus driver, "
-                  "Copyright 2006 IBM Corporation");
+                  "Copyright IBM Corp. 2006");
 MODULE_LICENSE("GPL");
 
 /*
@@ -338,6 +336,12 @@ static int ap_queue_enable_interruption(ap_qid_t qid, void *ind)
                        break;
                case AP_RESPONSE_RESET_IN_PROGRESS:
                case AP_RESPONSE_BUSY:
+                       if (i < AP_MAX_RESET - 1) {
+                               udelay(5);
+                               status = ap_queue_interruption_control(qid,
+                                                                      ind);
+                               continue;
+                       }
                        break;
                case AP_RESPONSE_Q_NOT_AVAIL:
                case AP_RESPONSE_DECONFIGURED:
index 726fc65809d84a3d2437327496ded59c5d4e81e9..52d61995af889a5cf3f9b2d9a29a200272ceb3a7 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * linux/drivers/s390/crypto/ap_bus.h
- *
- * Copyright (C) 2006 IBM Corporation
+ * Copyright IBM Corp. 2006
  * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
  *           Martin Schwidefsky <schwidefsky@de.ibm.com>
  *           Ralph Wuerthner <rwuerthn@de.ibm.com>
index 88523208d47daeea4c4519b9637e1bd186e8ccab..2f94132246a1b1f766feecb8bc3c6986d56e9564 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  linux/drivers/s390/crypto/zcrypt_api.c
- *
  *  zcrypt 2.1.0
  *
- *  Copyright (C)  2001, 2006 IBM Corporation
+ *  Copyright IBM Corp. 2001, 2006
  *  Author(s): Robert Burroughs
  *            Eric Rossman (edrossma@us.ibm.com)
  *            Cornelia Huck <cornelia.huck@de.ibm.com>
@@ -47,7 +45,7 @@
  */
 MODULE_AUTHOR("IBM Corporation");
 MODULE_DESCRIPTION("Cryptographic Coprocessor interface, "
-                  "Copyright 2001, 2006 IBM Corporation");
+                  "Copyright IBM Corp. 2001, 2006");
 MODULE_LICENSE("GPL");
 
 static DEFINE_SPINLOCK(zcrypt_device_lock);
index 9688f3985b072ebec20d049e73bfb6d49bfc3a46..7a32c4bc8ef914c9d175c4dd5823b6a07495eb52 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  linux/drivers/s390/crypto/zcrypt_api.h
- *
  *  zcrypt 2.1.0
  *
- *  Copyright (C)  2001, 2006 IBM Corporation
+ *  Copyright IBM Corp. 2001, 2006
  *  Author(s): Robert Burroughs
  *            Eric Rossman (edrossma@us.ibm.com)
  *            Cornelia Huck <cornelia.huck@de.ibm.com>
index ed82f2f59b1717cc19a785cd2489024edac35f56..1f42f103c761d460426b07b8c8021a673bcb1b7e 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  linux/drivers/s390/crypto/zcrypt_cca_key.h
- *
  *  zcrypt 2.1.0
  *
- *  Copyright (C)  2001, 2006 IBM Corporation
+ *  Copyright IBM Corp. 2001, 2006
  *  Author(s): Robert Burroughs
  *            Eric Rossman (edrossma@us.ibm.com)
  *
index 46812440425acca842b3d5837e81481cfd526bfc..744c668f586c56b749ca55ed9c9d40af206f9169 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  linux/drivers/s390/crypto/zcrypt_cex2a.c
- *
  *  zcrypt 2.1.0
  *
- *  Copyright (C)  2001, 2006 IBM Corporation
+ *  Copyright IBM Corp. 2001, 2006
  *  Author(s): Robert Burroughs
  *            Eric Rossman (edrossma@us.ibm.com)
  *
@@ -66,7 +64,7 @@ static struct ap_device_id zcrypt_cex2a_ids[] = {
 MODULE_DEVICE_TABLE(ap, zcrypt_cex2a_ids);
 MODULE_AUTHOR("IBM Corporation");
 MODULE_DESCRIPTION("CEX2A Cryptographic Coprocessor device driver, "
-                  "Copyright 2001, 2006 IBM Corporation");
+                  "Copyright IBM Corp. 2001, 2006");
 MODULE_LICENSE("GPL");
 
 static int zcrypt_cex2a_probe(struct ap_device *ap_dev);
index 0350665810cf53032c9e172210887b5f480b73c2..0dce4b9af184114ecdc13bf3741ab167dfb402d8 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  linux/drivers/s390/crypto/zcrypt_cex2a.h
- *
  *  zcrypt 2.1.0
  *
- *  Copyright (C)  2001, 2006 IBM Corporation
+ *  Copyright IBM Corp. 2001, 2006
  *  Author(s): Robert Burroughs
  *            Eric Rossman (edrossma@us.ibm.com)
  *
index 03ba27f05f9203931a6b381bfd07ba1af3ddefa7..0965e2626d18aa671bc34bfb6a3975923702af1f 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  linux/drivers/s390/crypto/zcrypt_error.h
- *
  *  zcrypt 2.1.0
  *
- *  Copyright (C)  2001, 2006 IBM Corporation
+ *  Copyright IBM Corp. 2001, 2006
  *  Author(s): Robert Burroughs
  *            Eric Rossman (edrossma@us.ibm.com)
  *
index ad7951c21b794dff585eec537bd01c87b395ed23..f2b71d8df01f0c1e42e75bd7b0f9786bbf881cae 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  linux/drivers/s390/crypto/zcrypt_pcica.c
- *
  *  zcrypt 2.1.0
  *
- *  Copyright (C)  2001, 2006 IBM Corporation
+ *  Copyright IBM Corp. 2001, 2006
  *  Author(s): Robert Burroughs
  *            Eric Rossman (edrossma@us.ibm.com)
  *
@@ -56,7 +54,7 @@ static struct ap_device_id zcrypt_pcica_ids[] = {
 MODULE_DEVICE_TABLE(ap, zcrypt_pcica_ids);
 MODULE_AUTHOR("IBM Corporation");
 MODULE_DESCRIPTION("PCICA Cryptographic Coprocessor device driver, "
-                  "Copyright 2001, 2006 IBM Corporation");
+                  "Copyright IBM Corp. 2001, 2006");
 MODULE_LICENSE("GPL");
 
 static int zcrypt_pcica_probe(struct ap_device *ap_dev);
index 3be11187f6df35feda6c095802ddf38ffc6cc8e4..9a59155cad517cff088e9d00708f4694de5b451c 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  linux/drivers/s390/crypto/zcrypt_pcica.h
- *
  *  zcrypt 2.1.0
  *
- *  Copyright (C)  2001, 2006 IBM Corporation
+ *  Copyright IBM Corp. 2001, 2006
  *  Author(s): Robert Burroughs
  *            Eric Rossman (edrossma@us.ibm.com)
  *
index e5dd335fda53b3e46f36faed6d49e717ce5765ee..0d90a4334055efcc22ae73a290c53d83fcee8530 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  linux/drivers/s390/crypto/zcrypt_pcicc.c
- *
  *  zcrypt 2.1.0
  *
- *  Copyright (C)  2001, 2006 IBM Corporation
+ *  Copyright IBM Corp. 2001, 2006
  *  Author(s): Robert Burroughs
  *            Eric Rossman (edrossma@us.ibm.com)
  *
@@ -68,7 +66,7 @@ static struct ap_device_id zcrypt_pcicc_ids[] = {
 MODULE_DEVICE_TABLE(ap, zcrypt_pcicc_ids);
 MODULE_AUTHOR("IBM Corporation");
 MODULE_DESCRIPTION("PCICC Cryptographic Coprocessor device driver, "
-                  "Copyright 2001, 2006 IBM Corporation");
+                  "Copyright IBM Corp. 2001, 2006");
 MODULE_LICENSE("GPL");
 
 static int zcrypt_pcicc_probe(struct ap_device *ap_dev);
index 6d4454846c8f9e4bcc0944f85fc7fcb065999c5d..7fe27e15075b851d01876e88e382902964498e3c 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  linux/drivers/s390/crypto/zcrypt_pcicc.h
- *
  *  zcrypt 2.1.0
  *
- *  Copyright (C)  2001, 2006 IBM Corporation
+ *  Copyright IBM Corp. 2001, 2006
  *  Author(s): Robert Burroughs
  *            Eric Rossman (edrossma@us.ibm.com)
  *
index f7cc43401816d503e33ec3fb75b628c60b9ad400..ccb4f8b60c750f9e7b636c4c5e5f900d523b6321 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  linux/drivers/s390/crypto/zcrypt_pcixcc.c
- *
  *  zcrypt 2.1.0
  *
- *  Copyright (C)  2001, 2006 IBM Corporation
+ *  Copyright IBM Corp. 2001, 2006
  *  Author(s): Robert Burroughs
  *            Eric Rossman (edrossma@us.ibm.com)
  *
@@ -78,7 +76,7 @@ static struct ap_device_id zcrypt_pcixcc_ids[] = {
 MODULE_DEVICE_TABLE(ap, zcrypt_pcixcc_ids);
 MODULE_AUTHOR("IBM Corporation");
 MODULE_DESCRIPTION("PCIXCC Cryptographic Coprocessor device driver, "
-                  "Copyright 2001, 2006 IBM Corporation");
+                  "Copyright IBM Corp. 2001, 2006");
 MODULE_LICENSE("GPL");
 
 static int zcrypt_pcixcc_probe(struct ap_device *ap_dev);
index 8cb7d7a6973b4e19c89f10a0d18fc9bb797f2cf0..c7cdf599e46b1a67230e489ff10bb3dc9a2da776 100644 (file)
@@ -1,9 +1,7 @@
 /*
- *  linux/drivers/s390/crypto/zcrypt_pcixcc.h
- *
  *  zcrypt 2.1.0
  *
- *  Copyright (C)  2001, 2006 IBM Corporation
+ *  Copyright IBM Corp. 2001, 2006
  *  Author(s): Robert Burroughs
  *            Eric Rossman (edrossma@us.ibm.com)
  *
index d74e9ae6dfb3e55407e27bfb5d6d997da1c845f1..b67ee04082677ad46d1495effb234d7a7c1df0d9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * kvm_virtio.c - virtio for kvm on s390
+ * virtio for kvm on s390
  *
  * Copyright IBM Corp. 2008
  *
index 6b1ff90d2f007b9d12cdc29e94ed929a064d1f52..a0a4afe537d079038e02b74e7606b66b0cedcee4 100644 (file)
@@ -1,5 +1,4 @@
 /*
- *  drivers/s390/net/claw.c
  *    ESCON CLAW network driver
  *
  *  Linux for zSeries version
@@ -3380,5 +3379,5 @@ module_exit(claw_cleanup);
 
 MODULE_AUTHOR("Andy Richter <richtera@us.ibm.com>");
 MODULE_DESCRIPTION("Linux for System z CLAW Driver\n" \
-                       "Copyright 2000,2008 IBM Corporation\n");
+                       "Copyright IBM Corp. 2000, 2008\n");
 MODULE_LICENSE("GPL");
index d962fd741a2327cc68c33fea9d36bd4437057104..6514e1cb3f1cf1b21cc7bd2d4422ca48fe2b7d47 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     drivers/s390/net/ctcm_dbug.c
- *
  *     Copyright IBM Corp. 2001, 2007
  *     Authors:        Peter Tiedemann (ptiedem@de.ibm.com)
  *
index 26966d0b9abd1191e3413afa7ca3bcbe42848ddc..47bf0501995e8cfa3834ff18b6e817a45d80e19a 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     drivers/s390/net/ctcm_dbug.h
- *
  *     Copyright IBM Corp. 2001, 2007
  *     Authors:        Peter Tiedemann (ptiedem@de.ibm.com)
  *
index a69766900a17badf80952614a89182a915aba7fa..d4ade9e92fbbd4fa97f9ce1acf4043a7b91b4f65 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * drivers/s390/net/ctcm_fsms.c
- *
  * Copyright IBM Corp. 2001, 2007
  * Authors:    Fritz Elfert (felfert@millenux.com)
  *             Peter Tiedemann (ptiedem@de.ibm.com)
index 046d077fabbb3e02ee7470a5a2f5ef245ac0b9a8..c963d04799c0a21393bc77acc50f87f176358d2b 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * drivers/s390/net/ctcm_fsms.h
- *
  * Copyright IBM Corp. 2001, 2007
  * Authors:    Fritz Elfert (felfert@millenux.com)
  *             Peter Tiedemann (ptiedem@de.ibm.com)
index 3cd25544a27a1ba82fd4549cb49b2320f99d24a9..5227e5734a9d152e45a2b4920a13f92b7354051e 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * drivers/s390/net/ctcm_main.c
- *
  * Copyright IBM Corp. 2001, 2009
  * Author(s):
  *     Original CTC driver(s):
index b9056a55d9950b113d1446422fdec5d955d07c29..477c933685f38f4abdba98a557aca20d43b7b7ef 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     drivers/s390/net/ctcm_main.h
- *
  *     Copyright IBM Corp. 2001, 2007
  *     Authors:        Fritz Elfert (felfert@millenux.com)
  *                     Peter Tiedemann (ptiedem@de.ibm.com)
index ac7975b7a837a9a3db240787d162e57d0fe26e17..05b734a2b5b7ae09f33f2a7307948e232e4f253f 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *     drivers/s390/net/ctcm_mpc.c
- *
  *     Copyright IBM Corp. 2004, 2007
  *     Authors:        Belinda Thompson (belindat@us.ibm.com)
  *                     Andy Richter (richtera@us.ibm.com)
index 1fa07b0c11c010d6de20ceeecd80c030d22cca3c..bd1b1cc54ffa0c7cc8fe1a8ddd5083ad58a57afb 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * drivers/s390/net/ctcm_mpc.h
- *
  * Copyright IBM Corp. 2007
  * Authors:    Peter Tiedemann (ptiedem@de.ibm.com)
  *
index 0c27ae726475cb253dd3dee10ec73ad91873017d..985b5dcbdac8b348dc6394898ad55bcddf9b8aa9 100644 (file)
@@ -1,6 +1,4 @@
 /*
- * drivers/s390/net/ctcm_sysfs.c
- *
  * Copyright IBM Corp. 2007, 2007
  * Authors:    Peter Tiedemann (ptiedem@de.ibm.com)
  *
index 06e8f31ff3dc7854a67c559d694da6cc9df865dc..fa7adad6f9ba07f6e1948d775898866fbfe9d019 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/net/qeth_core.h
- *
  *    Copyright IBM Corp. 2007
  *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
  *              Frank Pavlic <fpavlic@de.ibm.com>,
index e118e1e1e1c12b908b50a3b38f1157c7e1bcd68b..7a8b09612c41ba141c9d17812549d23f5873d6c3 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/net/qeth_core_main.c
- *
  *    Copyright IBM Corp. 2007, 2009
  *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
  *              Frank Pavlic <fpavlic@de.ibm.com>,
index 7fab6544def66b02f9756fe67a6d0a7a529077b5..5cebfddb86bdfbb40b2a0cfa6f212e5d0656cf95 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/net/qeth_core_mpc.c
- *
  *    Copyright IBM Corp. 2007
  *    Author(s): Frank Pavlic <fpavlic@de.ibm.com>,
  *              Thomas Spatzier <tspat@de.ibm.com>,
index a11b30c384236f4444b3c04bf39e3de704348ac7..3690bbf2cb3cf3699abadeb4f2aa0703e11c2ce2 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/net/qeth_core_mpc.h
- *
  *    Copyright IBM Corp. 2007
  *    Author(s): Frank Pavlic <fpavlic@de.ibm.com>,
  *              Thomas Spatzier <tspat@de.ibm.com>,
index f163af575c48c6f34139e03561d6e3938f38f14c..9655dc0ea0ec7187c65de00eb30399bf13ffe1fb 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/net/qeth_core_sys.c
- *
  *    Copyright IBM Corp. 2007
  *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
  *              Frank Pavlic <fpavlic@de.ibm.com>,
index b09355c14ee1c28f2f767f869312fafc2ec80cca..2db409330c217f4d38f9d67bde47ba91fddc98ad 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/net/qeth_l2_main.c
- *
  *    Copyright IBM Corp. 2007, 2009
  *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
  *              Frank Pavlic <fpavlic@de.ibm.com>,
index e367315a63f0e12890447eb0941d4c68aa6cd7d3..29c1c00e3a0f3dcdb826e0e31c33bde2ceb88dcc 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/net/qeth_l3.h
- *
  *    Copyright IBM Corp. 2007
  *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
  *              Frank Pavlic <fpavlic@de.ibm.com>,
index bada7f66c146f18d8c1d89c00b34af2c13989898..0cf706699a043e4d67c52e7dead8a00e7092a4f7 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/net/qeth_l3_main.c
- *
  *    Copyright IBM Corp. 2007, 2009
  *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
  *              Frank Pavlic <fpavlic@de.ibm.com>,
index 4cafedf950ada18f4bb18d1dd3f72ce33611f987..ebc3794862675e591b45395f29cc0f6cf4c5e801 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  drivers/s390/net/qeth_l3_sys.c
- *
  *    Copyright IBM Corp. 2007
  *    Author(s): Utz Bacher <utz.bacher@de.ibm.com>,
  *              Frank Pavlic <fpavlic@de.ibm.com>,
index 149a1151608d4f60ade750da2102f1aa2961bfb6..45bc925928ca724fd6dffbf0870fccb81694b59c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * IUCV special message driver
  *
- * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright IBM Corp. 2003
  * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  */
 
index 08601810966252a1b2815f600724c0c90785fb2b..aff8621de8069b813014a550c468a8bf8d78937b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Module interface and handling of zfcp data structures.
  *
- * Copyright IBM Corporation 2002, 2010
+ * Copyright IBM Corp. 2002, 2010
  */
 
 /*
index 96f13ad88123408b51698023a977e90eb3261d97..e37f04551948907be4be7a6da626b37263b09c1b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Registration and callback for the s390 common I/O layer.
  *
- * Copyright IBM Corporation 2002, 2010
+ * Copyright IBM Corp. 2002, 2010
  */
 
 #define KMSG_COMPONENT "zfcp"
index fab2c2592a9744e400971b73c264fd9f2c3ab7b9..fbd8b4db6025772840ec0af0911f004be0548fe0 100644 (file)
@@ -5,7 +5,7 @@
  * Access Control Lists / Control File Data Channel;
  * handling of response code and states for ports and LUNs.
  *
- * Copyright IBM Corporation 2008, 2010
+ * Copyright IBM Corp. 2008, 2010
  */
 
 #define KMSG_COMPONENT "zfcp"
index a9a816e4aa55f5c2ad8eadfe4302cba48609e421..3c1d22097ad0b66296e730463b01a19775a18977 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Debug traces for zfcp.
  *
- * Copyright IBM Corporation 2002, 2010
+ * Copyright IBM Corp. 2002, 2010
  */
 
 #define KMSG_COMPONENT "zfcp"
index ed5d921e82cd18448a09a16a502724eae4f6ac76..2955e1a3deaf88bcff0140ea3c9e571a8f6e659a 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Global definitions for the zfcp device driver.
  *
- * Copyright IBM Corporation 2002, 2010
+ * Copyright IBM Corp. 2002, 2010
  */
 
 #ifndef ZFCP_DEF_H
index e1b4f800e2260498e30536add0b6bd1c41061a42..92d3df6ac8ba9e6ef37ba3e24b503e6b12217ef2 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Error Recovery Procedures (ERP).
  *
- * Copyright IBM Corporation 2002, 2010
+ * Copyright IBM Corp. 2002, 2010
  */
 
 #define KMSG_COMPONENT "zfcp"
index 2302e1cfb76cb5bec677b849f139494d6028011b..36f422770ff54da358879ab9571e1c3ecd79112b 100644 (file)
@@ -3,7 +3,7 @@
  *
  * External function declarations.
  *
- * Copyright IBM Corporation 2002, 2010
+ * Copyright IBM Corp. 2002, 2010
  */
 
 #ifndef ZFCP_EXT_H
index 297e6b71ce9cf64bb4982159bc00452911dec2fa..88688a80b2c11334bcc99686634bee964858b816 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Fibre Channel related functions for the zfcp device driver.
  *
- * Copyright IBM Corporation 2008, 2010
+ * Copyright IBM Corp. 2008, 2010
  */
 
 #define KMSG_COMPONENT "zfcp"
index 4561f3bf7300e6b74936d7c696960e1082b61f1b..b1d2024ed51367ef4c892a62ed00ecab267ed74b 100644 (file)
@@ -4,7 +4,7 @@
  * Fibre Channel related definitions and inline functions for the zfcp
  * device driver
  *
- * Copyright IBM Corporation 2009
+ * Copyright IBM Corp. 2009
  */
 
 #ifndef ZFCP_FC_H
index e9a787e2e6a59ba46fe7fa70f7b8f719cc95ef04..e1c1efc2c5a0f35158ec402360c78ae87b80c681 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Implementation of FSF commands.
  *
- * Copyright IBM Corporation 2002, 2010
+ * Copyright IBM Corp. 2002, 2010
  */
 
 #define KMSG_COMPONENT "zfcp"
index db8c85382dca7d97735c25af716e9970cc92d23a..5e795b86931b0bf4ab873164680cb23a4b93e52c 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Interface to the FSF support functions.
  *
- * Copyright IBM Corporation 2002, 2010
+ * Copyright IBM Corp. 2002, 2010
  */
 
 #ifndef FSF_H
index e14da5751d32674fa089fe6ffae6ed93da843262..b9fffc8d94a76daaf6b7faadbcd85194cb555094 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Setup and helper functions to access QDIO.
  *
- * Copyright IBM Corporation 2002, 2010
+ * Copyright IBM Corp. 2002, 2010
  */
 
 #define KMSG_COMPONENT "zfcp"
index 8ac7f5342d29d807e815e939b54f68f3c8f38fca..497cd379b0d10b065940e096ee1b60491c48ac44 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Header file for zfcp qdio interface
  *
- * Copyright IBM Corporation 2010
+ * Copyright IBM Corp. 2010
  */
 
 #ifndef ZFCP_QDIO_H
index a72d1b730abab480a6a51154bea08d79ebf5333f..7c2c6194dfca58e1eb2fe6466abf64fd928deb96 100644 (file)
@@ -4,7 +4,7 @@
  * Data structure and helper functions for tracking pending FSF
  * requests.
  *
- * Copyright IBM Corporation 2009
+ * Copyright IBM Corp. 2009
  */
 
 #ifndef ZFCP_REQLIST_H
index b79576b64f451e72352bbc3c92582f23e9a92191..7b31e3f403f9060b2af3955e8f306538206ff486 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Interface to Linux SCSI midlayer.
  *
- * Copyright IBM Corporation 2002, 2010
+ * Copyright IBM Corp. 2002, 2010
  */
 
 #define KMSG_COMPONENT "zfcp"
index cdc4ff78a7baf787e36958b84c208654d97fa9c1..c66af27b230bb99fdde7cd3f28bc45f6eac82ba3 100644 (file)
@@ -3,7 +3,7 @@
  *
  * sysfs attributes.
  *
- * Copyright IBM Corporation 2008, 2010
+ * Copyright IBM Corp. 2008, 2010
  */
 
 #define KMSG_COMPONENT "zfcp"
index 20796ebc33cec3435cb5b2a2de297580e534fb8c..3f2bff0d3aa21fd9996cedc187c441bff167718e 100644 (file)
@@ -4,7 +4,7 @@
  * Tracking of manually configured LUNs and helper functions to
  * register the LUNs with the SCSI midlayer.
  *
- * Copyright IBM Corporation 2010
+ * Copyright IBM Corp. 2010
  */
 
 #include "zfcp_def.h"
index 77759c78cc21167cb93c002f6f951efeb4cab0db..5b30132960c7901e514948c092ab105f43b483a0 100644 (file)
@@ -2643,19 +2643,9 @@ static void qlt_do_work(struct work_struct *work)
        spin_lock_irqsave(&ha->hardware_lock, flags);
        sess = ha->tgt.tgt_ops->find_sess_by_s_id(vha,
            atio->u.isp24.fcp_hdr.s_id);
-       if (sess) {
-               if (unlikely(sess->tearing_down)) {
-                       sess = NULL;
-                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
-                       goto out_term;
-               } else {
-                       /*
-                        * Do the extra kref_get() before dropping
-                        * qla_hw_data->hardware_lock.
-                        */
-                       kref_get(&sess->se_sess->sess_kref);
-               }
-       }
+       /* Do kref_get() before dropping qla_hw_data->hardware_lock. */
+       if (sess)
+               kref_get(&sess->se_sess->sess_kref);
        spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        if (unlikely(!sess)) {
index 9f9ef1644fd97d1fbcb5ba1f978c5080411f9991..170af1571214095fe82db73fa52f520c16a8197b 100644 (file)
@@ -639,7 +639,7 @@ struct qla_tgt_func_tmpl {
 
        int (*handle_cmd)(struct scsi_qla_host *, struct qla_tgt_cmd *,
                        unsigned char *, uint32_t, int, int, int);
-       int (*handle_data)(struct qla_tgt_cmd *);
+       void (*handle_data)(struct qla_tgt_cmd *);
        int (*handle_tmr)(struct qla_tgt_mgmt_cmd *, uint32_t, uint8_t,
                        uint32_t);
        void (*free_cmd)(struct qla_tgt_cmd *);
@@ -813,7 +813,6 @@ struct qla_tgt_sess {
        unsigned int conf_compl_supported:1;
        unsigned int deleted:1;
        unsigned int local:1;
-       unsigned int tearing_down:1;
 
        struct se_session *se_sess;
        struct scsi_qla_host *vha;
index 6e64314dbbb3d33e70782e1506039f9480d1b5c3..4752f65a9272a610a80bb17e25c3ebd736c9894b 100644 (file)
@@ -38,8 +38,6 @@
 #include <linux/string.h>
 #include <linux/configfs.h>
 #include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/ctype.h>
 #include <asm/unaligned.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
@@ -466,8 +464,7 @@ static int tcm_qla2xxx_shutdown_session(struct se_session *se_sess)
        vha = sess->vha;
 
        spin_lock_irqsave(&vha->hw->hardware_lock, flags);
-       sess->tearing_down = 1;
-       target_splice_sess_cmd_list(se_sess);
+       target_sess_cmd_list_set_waiting(se_sess);
        spin_unlock_irqrestore(&vha->hw->hardware_lock, flags);
 
        return 1;
@@ -600,28 +597,15 @@ static int tcm_qla2xxx_handle_cmd(scsi_qla_host_t *vha, struct qla_tgt_cmd *cmd,
                return -EINVAL;
        }
 
-       target_submit_cmd(se_cmd, se_sess, cdb, &cmd->sense_buffer[0],
+       return target_submit_cmd(se_cmd, se_sess, cdb, &cmd->sense_buffer[0],
                                cmd->unpacked_lun, data_length, fcp_task_attr,
                                data_dir, flags);
-       return 0;
 }
 
-static void tcm_qla2xxx_do_rsp(struct work_struct *work)
+static void tcm_qla2xxx_handle_data_work(struct work_struct *work)
 {
        struct qla_tgt_cmd *cmd = container_of(work, struct qla_tgt_cmd, work);
-       /*
-        * Dispatch ->queue_status from workqueue process context
-        */
-       transport_generic_request_failure(&cmd->se_cmd);
-}
 
-/*
- * Called from qla_target.c:qlt_do_ctio_completion()
- */
-static int tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd)
-{
-       struct se_cmd *se_cmd = &cmd->se_cmd;
-       unsigned long flags;
        /*
         * Ensure that the complete FCP WRITE payload has been received.
         * Otherwise return an exception via CHECK_CONDITION status.
@@ -631,24 +615,26 @@ static int tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd)
                 * Check if se_cmd has already been aborted via LUN_RESET, and
                 * waiting upon completion in tcm_qla2xxx_write_pending_status()
                 */
-               spin_lock_irqsave(&se_cmd->t_state_lock, flags);
-               if (se_cmd->transport_state & CMD_T_ABORTED) {
-                       spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
-                       complete(&se_cmd->t_transport_stop_comp);
-                       return 0;
+               if (cmd->se_cmd.transport_state & CMD_T_ABORTED) {
+                       complete(&cmd->se_cmd.t_transport_stop_comp);
+                       return;
                }
-               spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
 
-               se_cmd->scsi_sense_reason = TCM_CHECK_CONDITION_ABORT_CMD;
-               INIT_WORK(&cmd->work, tcm_qla2xxx_do_rsp);
-               queue_work(tcm_qla2xxx_free_wq, &cmd->work);
-               return 0;
+               cmd->se_cmd.scsi_sense_reason = TCM_CHECK_CONDITION_ABORT_CMD;
+               transport_generic_request_failure(&cmd->se_cmd);
+               return;
        }
-       /*
-        * We now tell TCM to queue this WRITE CDB with TRANSPORT_PROCESS_WRITE
-        * status to the backstore processing thread.
-        */
-       return transport_generic_handle_data(&cmd->se_cmd);
+
+       return target_execute_cmd(&cmd->se_cmd);
+}
+
+/*
+ * Called from qla_target.c:qlt_do_ctio_completion()
+ */
+static void tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd)
+{
+       INIT_WORK(&cmd->work, tcm_qla2xxx_handle_data_work);
+       queue_work(tcm_qla2xxx_free_wq, &cmd->work);
 }
 
 /*
@@ -1690,7 +1676,6 @@ static struct target_core_fabric_ops tcm_qla2xxx_ops = {
        .tpg_alloc_fabric_acl           = tcm_qla2xxx_alloc_fabric_acl,
        .tpg_release_fabric_acl         = tcm_qla2xxx_release_fabric_acl,
        .tpg_get_inst_index             = tcm_qla2xxx_tpg_get_inst_index,
-       .new_cmd_map                    = NULL,
        .check_stop_free                = tcm_qla2xxx_check_stop_free,
        .release_cmd                    = tcm_qla2xxx_release_cmd,
        .put_session                    = tcm_qla2xxx_put_session,
index f168a6159961f621631a7af9a78d0099be61cbc3..d860ef7435681adbbd0954d9415d989f592728e5 100644 (file)
@@ -1,5 +1,6 @@
 menu "SuperH / SH-Mobile Driver Options"
 
 source "drivers/sh/intc/Kconfig"
+source "drivers/sh/pfc/Kconfig"
 
 endmenu
index 7139ad2f20864d61c53eeebaec5c3a0f935222c7..e57895b1a425ca7e5b8d14e587204fdd5ef70ef2 100644 (file)
@@ -5,6 +5,7 @@ obj-y   := intc/
 
 obj-$(CONFIG_HAVE_CLK)         += clk/
 obj-$(CONFIG_MAPLE)            += maple/
+obj-$(CONFIG_SH_PFC)           += pfc/
 obj-$(CONFIG_SUPERHYWAY)       += superhyway/
-obj-$(CONFIG_GENERIC_GPIO)     += pfc.o
+
 obj-y                          += pm_runtime.o
index f0d015dd0fef20aa2795b7c4866e00e1e2e478a2..07e9fb4f8041d9d93371fab60aa50e61f23bbabb 100644 (file)
@@ -14,6 +14,8 @@
 #include <linux/io.h>
 #include <linux/sh_clk.h>
 
+#define CPG_CKSTP_BIT  BIT(8)
+
 static unsigned int sh_clk_read(struct clk *clk)
 {
        if (clk->flags & CLK_ENABLE_REG_8BIT)
@@ -66,71 +68,43 @@ int __init sh_clk_mstp_register(struct clk *clks, int nr)
        return ret;
 }
 
-static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
+/*
+ * Div/mult table lookup helpers
+ */
+static inline struct clk_div_table *clk_to_div_table(struct clk *clk)
 {
-       return clk_rate_table_round(clk, clk->freq_table, rate);
+       return clk->priv;
 }
 
-static int sh_clk_div6_divisors[64] = {
-       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
-       17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
-       33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
-       49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
-};
+static inline struct clk_div_mult_table *clk_to_div_mult_table(struct clk *clk)
+{
+       return clk_to_div_table(clk)->div_mult_table;
+}
 
-static struct clk_div_mult_table sh_clk_div6_table = {
-       .divisors = sh_clk_div6_divisors,
-       .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors),
-};
+/*
+ * Common div ops
+ */
+static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate)
+{
+       return clk_rate_table_round(clk, clk->freq_table, rate);
+}
 
-static unsigned long sh_clk_div6_recalc(struct clk *clk)
+static unsigned long sh_clk_div_recalc(struct clk *clk)
 {
-       struct clk_div_mult_table *table = &sh_clk_div6_table;
+       struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
        unsigned int idx;
 
        clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-                            table, NULL);
+                            table, clk->arch_flags ? &clk->arch_flags : NULL);
 
-       idx = sh_clk_read(clk) & 0x003f;
+       idx = (sh_clk_read(clk) >> clk->enable_bit) & clk->div_mask;
 
        return clk->freq_table[idx].frequency;
 }
 
-static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
-{
-       struct clk_div_mult_table *table = &sh_clk_div6_table;
-       u32 value;
-       int ret, i;
-
-       if (!clk->parent_table || !clk->parent_num)
-               return -EINVAL;
-
-       /* Search the parent */
-       for (i = 0; i < clk->parent_num; i++)
-               if (clk->parent_table[i] == parent)
-                       break;
-
-       if (i == clk->parent_num)
-               return -ENODEV;
-
-       ret = clk_reparent(clk, parent);
-       if (ret < 0)
-               return ret;
-
-       value = sh_clk_read(clk) &
-               ~(((1 << clk->src_width) - 1) << clk->src_shift);
-
-       sh_clk_write(value | (i << clk->src_shift), clk);
-
-       /* Rebuild the frequency table */
-       clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-                            table, NULL);
-
-       return 0;
-}
-
-static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
+static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate)
 {
+       struct clk_div_table *dt = clk_to_div_table(clk);
        unsigned long value;
        int idx;
 
@@ -139,51 +113,53 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
                return idx;
 
        value = sh_clk_read(clk);
-       value &= ~0x3f;
-       value |= idx;
+       value &= ~(clk->div_mask << clk->enable_bit);
+       value |= (idx << clk->enable_bit);
        sh_clk_write(value, clk);
+
+       /* XXX: Should use a post-change notifier */
+       if (dt->kick)
+               dt->kick(clk);
+
        return 0;
 }
 
-static int sh_clk_div6_enable(struct clk *clk)
+static int sh_clk_div_enable(struct clk *clk)
 {
-       unsigned long value;
-       int ret;
-
-       ret = sh_clk_div6_set_rate(clk, clk->rate);
-       if (ret == 0) {
-               value = sh_clk_read(clk);
-               value &= ~0x100; /* clear stop bit to enable clock */
-               sh_clk_write(value, clk);
-       }
-       return ret;
+       sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk);
+       return 0;
 }
 
-static void sh_clk_div6_disable(struct clk *clk)
+static void sh_clk_div_disable(struct clk *clk)
 {
-       unsigned long value;
+       unsigned int val;
 
-       value = sh_clk_read(clk);
-       value |= 0x100; /* stop clock */
-       value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
-       sh_clk_write(value, clk);
+       val = sh_clk_read(clk);
+       val |= CPG_CKSTP_BIT;
+
+       /*
+        * div6 clocks require the divisor field to be non-zero or the
+        * above CKSTP toggle silently fails. Ensure that the divisor
+        * array is reset to its initial state on disable.
+        */
+       if (clk->flags & CLK_MASK_DIV_ON_DISABLE)
+               val |= clk->div_mask;
+
+       sh_clk_write(val, clk);
 }
 
-static struct sh_clk_ops sh_clk_div6_clk_ops = {
-       .recalc         = sh_clk_div6_recalc,
+static struct sh_clk_ops sh_clk_div_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+       .set_rate       = sh_clk_div_set_rate,
        .round_rate     = sh_clk_div_round_rate,
-       .set_rate       = sh_clk_div6_set_rate,
-       .enable         = sh_clk_div6_enable,
-       .disable        = sh_clk_div6_disable,
 };
 
-static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
-       .recalc         = sh_clk_div6_recalc,
+static struct sh_clk_ops sh_clk_div_enable_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+       .set_rate       = sh_clk_div_set_rate,
        .round_rate     = sh_clk_div_round_rate,
-       .set_rate       = sh_clk_div6_set_rate,
-       .enable         = sh_clk_div6_enable,
-       .disable        = sh_clk_div6_disable,
-       .set_parent     = sh_clk_div6_set_parent,
+       .enable         = sh_clk_div_enable,
+       .disable        = sh_clk_div_disable,
 };
 
 static int __init sh_clk_init_parent(struct clk *clk)
@@ -218,12 +194,12 @@ static int __init sh_clk_init_parent(struct clk *clk)
        return 0;
 }
 
-static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
-                                          struct sh_clk_ops *ops)
+static int __init sh_clk_div_register_ops(struct clk *clks, int nr,
+                       struct clk_div_table *table, struct sh_clk_ops *ops)
 {
        struct clk *clkp;
        void *freq_table;
-       int nr_divs = sh_clk_div6_table.nr_divisors;
+       int nr_divs = table->div_mult_table->nr_divisors;
        int freq_table_size = sizeof(struct cpufreq_frequency_table);
        int ret = 0;
        int k;
@@ -231,7 +207,7 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
        freq_table_size *= (nr_divs + 1);
        freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
        if (!freq_table) {
-               pr_err("sh_clk_div6_register: unable to alloc memory\n");
+               pr_err("%s: unable to alloc memory\n", __func__);
                return -ENOMEM;
        }
 
@@ -239,47 +215,98 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
                clkp = clks + k;
 
                clkp->ops = ops;
+               clkp->priv = table;
+
                clkp->freq_table = freq_table + (k * freq_table_size);
                clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
-               ret = clk_register(clkp);
-               if (ret < 0)
-                       break;
 
-               ret = sh_clk_init_parent(clkp);
+               ret = clk_register(clkp);
+               if (ret == 0)
+                       ret = sh_clk_init_parent(clkp);
        }
 
        return ret;
 }
 
-int __init sh_clk_div6_register(struct clk *clks, int nr)
-{
-       return sh_clk_div6_register_ops(clks, nr, &sh_clk_div6_clk_ops);
-}
+/*
+ * div6 support
+ */
+static int sh_clk_div6_divisors[64] = {
+       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+       17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
+       33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+       49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64
+};
 
-int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
-{
-       return sh_clk_div6_register_ops(clks, nr,
-                                       &sh_clk_div6_reparent_clk_ops);
-}
+static struct clk_div_mult_table div6_div_mult_table = {
+       .divisors = sh_clk_div6_divisors,
+       .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors),
+};
 
-static unsigned long sh_clk_div4_recalc(struct clk *clk)
+static struct clk_div_table sh_clk_div6_table = {
+       .div_mult_table = &div6_div_mult_table,
+};
+
+static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
 {
-       struct clk_div4_table *d4t = clk->priv;
-       struct clk_div_mult_table *table = d4t->div_mult_table;
-       unsigned int idx;
+       struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
+       u32 value;
+       int ret, i;
 
+       if (!clk->parent_table || !clk->parent_num)
+               return -EINVAL;
+
+       /* Search the parent */
+       for (i = 0; i < clk->parent_num; i++)
+               if (clk->parent_table[i] == parent)
+                       break;
+
+       if (i == clk->parent_num)
+               return -ENODEV;
+
+       ret = clk_reparent(clk, parent);
+       if (ret < 0)
+               return ret;
+
+       value = sh_clk_read(clk) &
+               ~(((1 << clk->src_width) - 1) << clk->src_shift);
+
+       sh_clk_write(value | (i << clk->src_shift), clk);
+
+       /* Rebuild the frequency table */
        clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
-                            table, &clk->arch_flags);
+                            table, NULL);
 
-       idx = (sh_clk_read(clk) >> clk->enable_bit) & 0x000f;
+       return 0;
+}
 
-       return clk->freq_table[idx].frequency;
+static struct sh_clk_ops sh_clk_div6_reparent_clk_ops = {
+       .recalc         = sh_clk_div_recalc,
+       .round_rate     = sh_clk_div_round_rate,
+       .set_rate       = sh_clk_div_set_rate,
+       .enable         = sh_clk_div_enable,
+       .disable        = sh_clk_div_disable,
+       .set_parent     = sh_clk_div6_set_parent,
+};
+
+int __init sh_clk_div6_register(struct clk *clks, int nr)
+{
+       return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table,
+                                      &sh_clk_div_enable_clk_ops);
+}
+
+int __init sh_clk_div6_reparent_register(struct clk *clks, int nr)
+{
+       return sh_clk_div_register_ops(clks, nr, &sh_clk_div6_table,
+                                      &sh_clk_div6_reparent_clk_ops);
 }
 
+/*
+ * div4 support
+ */
 static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
 {
-       struct clk_div4_table *d4t = clk->priv;
-       struct clk_div_mult_table *table = d4t->div_mult_table;
+       struct clk_div_mult_table *table = clk_to_div_mult_table(clk);
        u32 value;
        int ret;
 
@@ -306,107 +333,31 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
        return 0;
 }
 
-static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
-{
-       struct clk_div4_table *d4t = clk->priv;
-       unsigned long value;
-       int idx = clk_rate_table_find(clk, clk->freq_table, rate);
-       if (idx < 0)
-               return idx;
-
-       value = sh_clk_read(clk);
-       value &= ~(0xf << clk->enable_bit);
-       value |= (idx << clk->enable_bit);
-       sh_clk_write(value, clk);
-
-       if (d4t->kick)
-               d4t->kick(clk);
-
-       return 0;
-}
-
-static int sh_clk_div4_enable(struct clk *clk)
-{
-       sh_clk_write(sh_clk_read(clk) & ~(1 << 8), clk);
-       return 0;
-}
-
-static void sh_clk_div4_disable(struct clk *clk)
-{
-       sh_clk_write(sh_clk_read(clk) | (1 << 8), clk);
-}
-
-static struct sh_clk_ops sh_clk_div4_clk_ops = {
-       .recalc         = sh_clk_div4_recalc,
-       .set_rate       = sh_clk_div4_set_rate,
-       .round_rate     = sh_clk_div_round_rate,
-};
-
-static struct sh_clk_ops sh_clk_div4_enable_clk_ops = {
-       .recalc         = sh_clk_div4_recalc,
-       .set_rate       = sh_clk_div4_set_rate,
-       .round_rate     = sh_clk_div_round_rate,
-       .enable         = sh_clk_div4_enable,
-       .disable        = sh_clk_div4_disable,
-};
-
 static struct sh_clk_ops sh_clk_div4_reparent_clk_ops = {
-       .recalc         = sh_clk_div4_recalc,
-       .set_rate       = sh_clk_div4_set_rate,
+       .recalc         = sh_clk_div_recalc,
+       .set_rate       = sh_clk_div_set_rate,
        .round_rate     = sh_clk_div_round_rate,
-       .enable         = sh_clk_div4_enable,
-       .disable        = sh_clk_div4_disable,
+       .enable         = sh_clk_div_enable,
+       .disable        = sh_clk_div_disable,
        .set_parent     = sh_clk_div4_set_parent,
 };
 
-static int __init sh_clk_div4_register_ops(struct clk *clks, int nr,
-                       struct clk_div4_table *table, struct sh_clk_ops *ops)
-{
-       struct clk *clkp;
-       void *freq_table;
-       int nr_divs = table->div_mult_table->nr_divisors;
-       int freq_table_size = sizeof(struct cpufreq_frequency_table);
-       int ret = 0;
-       int k;
-
-       freq_table_size *= (nr_divs + 1);
-       freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL);
-       if (!freq_table) {
-               pr_err("sh_clk_div4_register: unable to alloc memory\n");
-               return -ENOMEM;
-       }
-
-       for (k = 0; !ret && (k < nr); k++) {
-               clkp = clks + k;
-
-               clkp->ops = ops;
-               clkp->priv = table;
-
-               clkp->freq_table = freq_table + (k * freq_table_size);
-               clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
-
-               ret = clk_register(clkp);
-       }
-
-       return ret;
-}
-
 int __init sh_clk_div4_register(struct clk *clks, int nr,
                                struct clk_div4_table *table)
 {
-       return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops);
+       return sh_clk_div_register_ops(clks, nr, table, &sh_clk_div_clk_ops);
 }
 
 int __init sh_clk_div4_enable_register(struct clk *clks, int nr,
                                struct clk_div4_table *table)
 {
-       return sh_clk_div4_register_ops(clks, nr, table,
-                                       &sh_clk_div4_enable_clk_ops);
+       return sh_clk_div_register_ops(clks, nr, table,
+                                      &sh_clk_div_enable_clk_ops);
 }
 
 int __init sh_clk_div4_reparent_register(struct clk *clks, int nr,
                                struct clk_div4_table *table)
 {
-       return sh_clk_div4_register_ops(clks, nr, table,
-                                       &sh_clk_div4_reparent_clk_ops);
+       return sh_clk_div_register_ops(clks, nr, table,
+                                      &sh_clk_div4_reparent_clk_ops);
 }
index bb5df868d77ae8f1a05496c8130cafc0f926d505..44f006d09471cfce4fd204b88e1893928f0a1093 100644 (file)
@@ -1,4 +1,4 @@
-obj-y  := access.o chip.o core.o dynamic.o handle.o virq.o
+obj-y  := access.o chip.o core.o handle.o virq.o
 
 obj-$(CONFIG_INTC_BALANCING)           += balancing.o
 obj-$(CONFIG_INTC_USERIMASK)           += userimask.o
diff --git a/drivers/sh/intc/dynamic.c b/drivers/sh/intc/dynamic.c
deleted file mode 100644 (file)
index 14eb01e..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Dynamic IRQ management
- *
- * Copyright (C) 2010  Paul Mundt
- *
- * Modelled after arch/x86/kernel/apic/io_apic.c
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#define pr_fmt(fmt) "intc: " fmt
-
-#include <linux/irq.h>
-#include <linux/bitmap.h>
-#include <linux/spinlock.h>
-#include <linux/module.h>
-#include "internals.h" /* only for activate_irq() damage.. */
-
-/*
- * The IRQ bitmap provides a global map of bound IRQ vectors for a
- * given platform. Allocation of IRQs are either static through the CPU
- * vector map, or dynamic in the case of board mux vectors or MSI.
- *
- * As this is a central point for all IRQ controllers on the system,
- * each of the available sources are mapped out here. This combined with
- * sparseirq makes it quite trivial to keep the vector map tightly packed
- * when dynamically creating IRQs, as well as tying in to otherwise
- * unused irq_desc positions in the sparse array.
- */
-
-/*
- * Dynamic IRQ allocation and deallocation
- */
-unsigned int create_irq_nr(unsigned int irq_want, int node)
-{
-       int irq = irq_alloc_desc_at(irq_want, node);
-       if (irq < 0)
-               return 0;
-
-       activate_irq(irq);
-       return irq;
-}
-
-int create_irq(void)
-{
-       int irq = irq_alloc_desc(numa_node_id());
-       if (irq >= 0)
-               activate_irq(irq);
-
-       return irq;
-}
-
-void destroy_irq(unsigned int irq)
-{
-       irq_free_desc(irq);
-}
index 93cec21e788bdb7b4024fa5237b9d7a8801c1333..f30ac9354ff248f316fb96a26d534884faa8bf5d 100644 (file)
@@ -219,12 +219,14 @@ restart:
                if (radix_tree_deref_retry(entry))
                        goto restart;
 
-               irq = create_irq();
+               irq = irq_alloc_desc(numa_node_id());
                if (unlikely(irq < 0)) {
                        pr_err("no more free IRQs, bailing..\n");
                        break;
                }
 
+               activate_irq(irq);
+
                pr_info("Setting up a chained VIRQ from %d -> %d\n",
                        irq, entry->pirq);
 
diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c
deleted file mode 100644 (file)
index 522c6c4..0000000
+++ /dev/null
@@ -1,739 +0,0 @@
-/*
- * Pinmuxed GPIO support for SuperH.
- *
- * Copyright (C) 2008 Magnus Damm
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/bitops.h>
-#include <linux/gpio.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-
-static void pfc_iounmap(struct pinmux_info *pip)
-{
-       int k;
-
-       for (k = 0; k < pip->num_resources; k++)
-               if (pip->window[k].virt)
-                       iounmap(pip->window[k].virt);
-
-       kfree(pip->window);
-       pip->window = NULL;
-}
-
-static int pfc_ioremap(struct pinmux_info *pip)
-{
-       struct resource *res;
-       int k;
-
-       if (!pip->num_resources)
-               return 0;
-
-       pip->window = kzalloc(pip->num_resources * sizeof(*pip->window),
-                             GFP_NOWAIT);
-       if (!pip->window)
-               goto err1;
-
-       for (k = 0; k < pip->num_resources; k++) {
-               res = pip->resource + k;
-               WARN_ON(resource_type(res) != IORESOURCE_MEM);
-               pip->window[k].phys = res->start;
-               pip->window[k].size = resource_size(res);
-               pip->window[k].virt = ioremap_nocache(res->start,
-                                                        resource_size(res));
-               if (!pip->window[k].virt)
-                       goto err2;
-       }
-
-       return 0;
-
-err2:
-       pfc_iounmap(pip);
-err1:
-       return -1;
-}
-
-static void __iomem *pfc_phys_to_virt(struct pinmux_info *pip,
-                                     unsigned long address)
-{
-       struct pfc_window *window;
-       int k;
-
-       /* scan through physical windows and convert address */
-       for (k = 0; k < pip->num_resources; k++) {
-               window = pip->window + k;
-
-               if (address < window->phys)
-                       continue;
-
-               if (address >= (window->phys + window->size))
-                       continue;
-
-               return window->virt + (address - window->phys);
-       }
-
-       /* no windows defined, register must be 1:1 mapped virt:phys */
-       return (void __iomem *)address;
-}
-
-static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
-{
-       if (enum_id < r->begin)
-               return 0;
-
-       if (enum_id > r->end)
-               return 0;
-
-       return 1;
-}
-
-static unsigned long gpio_read_raw_reg(void __iomem *mapped_reg,
-                                      unsigned long reg_width)
-{
-       switch (reg_width) {
-       case 8:
-               return ioread8(mapped_reg);
-       case 16:
-               return ioread16(mapped_reg);
-       case 32:
-               return ioread32(mapped_reg);
-       }
-
-       BUG();
-       return 0;
-}
-
-static void gpio_write_raw_reg(void __iomem *mapped_reg,
-                              unsigned long reg_width,
-                              unsigned long data)
-{
-       switch (reg_width) {
-       case 8:
-               iowrite8(data, mapped_reg);
-               return;
-       case 16:
-               iowrite16(data, mapped_reg);
-               return;
-       case 32:
-               iowrite32(data, mapped_reg);
-               return;
-       }
-
-       BUG();
-}
-
-static int gpio_read_bit(struct pinmux_data_reg *dr,
-                        unsigned long in_pos)
-{
-       unsigned long pos;
-
-       pos = dr->reg_width - (in_pos + 1);
-
-       pr_debug("read_bit: addr = %lx, pos = %ld, "
-                "r_width = %ld\n", dr->reg, pos, dr->reg_width);
-
-       return (gpio_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1;
-}
-
-static void gpio_write_bit(struct pinmux_data_reg *dr,
-                          unsigned long in_pos, unsigned long value)
-{
-       unsigned long pos;
-
-       pos = dr->reg_width - (in_pos + 1);
-
-       pr_debug("write_bit addr = %lx, value = %d, pos = %ld, "
-                "r_width = %ld\n",
-                dr->reg, !!value, pos, dr->reg_width);
-
-       if (value)
-               set_bit(pos, &dr->reg_shadow);
-       else
-               clear_bit(pos, &dr->reg_shadow);
-
-       gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
-}
-
-static void config_reg_helper(struct pinmux_info *gpioc,
-                             struct pinmux_cfg_reg *crp,
-                             unsigned long in_pos,
-                             void __iomem **mapped_regp,
-                             unsigned long *maskp,
-                             unsigned long *posp)
-{
-       int k;
-
-       *mapped_regp = pfc_phys_to_virt(gpioc, crp->reg);
-
-       if (crp->field_width) {
-               *maskp = (1 << crp->field_width) - 1;
-               *posp = crp->reg_width - ((in_pos + 1) * crp->field_width);
-       } else {
-               *maskp = (1 << crp->var_field_width[in_pos]) - 1;
-               *posp = crp->reg_width;
-               for (k = 0; k <= in_pos; k++)
-                       *posp -= crp->var_field_width[k];
-       }
-}
-
-static int read_config_reg(struct pinmux_info *gpioc,
-                          struct pinmux_cfg_reg *crp,
-                          unsigned long field)
-{
-       void __iomem *mapped_reg;
-       unsigned long mask, pos;
-
-       config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
-
-       pr_debug("read_reg: addr = %lx, field = %ld, "
-                "r_width = %ld, f_width = %ld\n",
-                crp->reg, field, crp->reg_width, crp->field_width);
-
-       return (gpio_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask;
-}
-
-static void write_config_reg(struct pinmux_info *gpioc,
-                            struct pinmux_cfg_reg *crp,
-                            unsigned long field, unsigned long value)
-{
-       void __iomem *mapped_reg;
-       unsigned long mask, pos, data;
-
-       config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
-
-       pr_debug("write_reg addr = %lx, value = %ld, field = %ld, "
-                "r_width = %ld, f_width = %ld\n",
-                crp->reg, value, field, crp->reg_width, crp->field_width);
-
-       mask = ~(mask << pos);
-       value = value << pos;
-
-       data = gpio_read_raw_reg(mapped_reg, crp->reg_width);
-       data &= mask;
-       data |= value;
-
-       if (gpioc->unlock_reg)
-               gpio_write_raw_reg(pfc_phys_to_virt(gpioc, gpioc->unlock_reg),
-                                  32, ~data);
-
-       gpio_write_raw_reg(mapped_reg, crp->reg_width, data);
-}
-
-static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
-{
-       struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
-       struct pinmux_data_reg *data_reg;
-       int k, n;
-
-       if (!enum_in_range(gpiop->enum_id, &gpioc->data))
-               return -1;
-
-       k = 0;
-       while (1) {
-               data_reg = gpioc->data_regs + k;
-
-               if (!data_reg->reg_width)
-                       break;
-
-               data_reg->mapped_reg = pfc_phys_to_virt(gpioc, data_reg->reg);
-
-               for (n = 0; n < data_reg->reg_width; n++) {
-                       if (data_reg->enum_ids[n] == gpiop->enum_id) {
-                               gpiop->flags &= ~PINMUX_FLAG_DREG;
-                               gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT);
-                               gpiop->flags &= ~PINMUX_FLAG_DBIT;
-                               gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT);
-                               return 0;
-                       }
-               }
-               k++;
-       }
-
-       BUG();
-
-       return -1;
-}
-
-static void setup_data_regs(struct pinmux_info *gpioc)
-{
-       struct pinmux_data_reg *drp;
-       int k;
-
-       for (k = gpioc->first_gpio; k <= gpioc->last_gpio; k++)
-               setup_data_reg(gpioc, k);
-
-       k = 0;
-       while (1) {
-               drp = gpioc->data_regs + k;
-
-               if (!drp->reg_width)
-                       break;
-
-               drp->reg_shadow = gpio_read_raw_reg(drp->mapped_reg,
-                                                   drp->reg_width);
-               k++;
-       }
-}
-
-static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
-                       struct pinmux_data_reg **drp, int *bitp)
-{
-       struct pinmux_gpio *gpiop = &gpioc->gpios[gpio];
-       int k, n;
-
-       if (!enum_in_range(gpiop->enum_id, &gpioc->data))
-               return -1;
-
-       k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT;
-       n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT;
-       *drp = gpioc->data_regs + k;
-       *bitp = n;
-       return 0;
-}
-
-static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
-                         struct pinmux_cfg_reg **crp,
-                         int *fieldp, int *valuep,
-                         unsigned long **cntp)
-{
-       struct pinmux_cfg_reg *config_reg;
-       unsigned long r_width, f_width, curr_width, ncomb;
-       int k, m, n, pos, bit_pos;
-
-       k = 0;
-       while (1) {
-               config_reg = gpioc->cfg_regs + k;
-
-               r_width = config_reg->reg_width;
-               f_width = config_reg->field_width;
-
-               if (!r_width)
-                       break;
-
-               pos = 0;
-               m = 0;
-               for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
-                       if (f_width)
-                               curr_width = f_width;
-                       else
-                               curr_width = config_reg->var_field_width[m];
-
-                       ncomb = 1 << curr_width;
-                       for (n = 0; n < ncomb; n++) {
-                               if (config_reg->enum_ids[pos + n] == enum_id) {
-                                       *crp = config_reg;
-                                       *fieldp = m;
-                                       *valuep = n;
-                                       *cntp = &config_reg->cnt[m];
-                                       return 0;
-                               }
-                       }
-                       pos += ncomb;
-                       m++;
-               }
-               k++;
-       }
-
-       return -1;
-}
-
-static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
-                           int pos, pinmux_enum_t *enum_idp)
-{
-       pinmux_enum_t enum_id = gpioc->gpios[gpio].enum_id;
-       pinmux_enum_t *data = gpioc->gpio_data;
-       int k;
-
-       if (!enum_in_range(enum_id, &gpioc->data)) {
-               if (!enum_in_range(enum_id, &gpioc->mark)) {
-                       pr_err("non data/mark enum_id for gpio %d\n", gpio);
-                       return -1;
-               }
-       }
-
-       if (pos) {
-               *enum_idp = data[pos + 1];
-               return pos + 1;
-       }
-
-       for (k = 0; k < gpioc->gpio_data_size; k++) {
-               if (data[k] == enum_id) {
-                       *enum_idp = data[k + 1];
-                       return k + 1;
-               }
-       }
-
-       pr_err("cannot locate data/mark enum_id for gpio %d\n", gpio);
-       return -1;
-}
-
-enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
-
-static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
-                             int pinmux_type, int cfg_mode)
-{
-       struct pinmux_cfg_reg *cr = NULL;
-       pinmux_enum_t enum_id;
-       struct pinmux_range *range;
-       int in_range, pos, field, value;
-       unsigned long *cntp;
-
-       switch (pinmux_type) {
-
-       case PINMUX_TYPE_FUNCTION:
-               range = NULL;
-               break;
-
-       case PINMUX_TYPE_OUTPUT:
-               range = &gpioc->output;
-               break;
-
-       case PINMUX_TYPE_INPUT:
-               range = &gpioc->input;
-               break;
-
-       case PINMUX_TYPE_INPUT_PULLUP:
-               range = &gpioc->input_pu;
-               break;
-
-       case PINMUX_TYPE_INPUT_PULLDOWN:
-               range = &gpioc->input_pd;
-               break;
-
-       default:
-               goto out_err;
-       }
-
-       pos = 0;
-       enum_id = 0;
-       field = 0;
-       value = 0;
-       while (1) {
-               pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id);
-               if (pos <= 0)
-                       goto out_err;
-
-               if (!enum_id)
-                       break;
-
-               /* first check if this is a function enum */
-               in_range = enum_in_range(enum_id, &gpioc->function);
-               if (!in_range) {
-                       /* not a function enum */
-                       if (range) {
-                               /*
-                                * other range exists, so this pin is
-                                * a regular GPIO pin that now is being
-                                * bound to a specific direction.
-                                *
-                                * for this case we only allow function enums
-                                * and the enums that match the other range.
-                                */
-                               in_range = enum_in_range(enum_id, range);
-
-                               /*
-                                * special case pass through for fixed
-                                * input-only or output-only pins without
-                                * function enum register association.
-                                */
-                               if (in_range && enum_id == range->force)
-                                       continue;
-                       } else {
-                               /*
-                                * no other range exists, so this pin
-                                * must then be of the function type.
-                                *
-                                * allow function type pins to select
-                                * any combination of function/in/out
-                                * in their MARK lists.
-                                */
-                               in_range = 1;
-                       }
-               }
-
-               if (!in_range)
-                       continue;
-
-               if (get_config_reg(gpioc, enum_id, &cr,
-                                  &field, &value, &cntp) != 0)
-                       goto out_err;
-
-               switch (cfg_mode) {
-               case GPIO_CFG_DRYRUN:
-                       if (!*cntp ||
-                           (read_config_reg(gpioc, cr, field) != value))
-                               continue;
-                       break;
-
-               case GPIO_CFG_REQ:
-                       write_config_reg(gpioc, cr, field, value);
-                       *cntp = *cntp + 1;
-                       break;
-
-               case GPIO_CFG_FREE:
-                       *cntp = *cntp - 1;
-                       break;
-               }
-       }
-
-       return 0;
- out_err:
-       return -1;
-}
-
-static DEFINE_SPINLOCK(gpio_lock);
-
-static struct pinmux_info *chip_to_pinmux(struct gpio_chip *chip)
-{
-       return container_of(chip, struct pinmux_info, chip);
-}
-
-static int sh_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-       struct pinmux_info *gpioc = chip_to_pinmux(chip);
-       struct pinmux_data_reg *dummy;
-       unsigned long flags;
-       int i, ret, pinmux_type;
-
-       ret = -EINVAL;
-
-       if (!gpioc)
-               goto err_out;
-
-       spin_lock_irqsave(&gpio_lock, flags);
-
-       if ((gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE) != PINMUX_TYPE_NONE)
-               goto err_unlock;
-
-       /* setup pin function here if no data is associated with pin */
-
-       if (get_data_reg(gpioc, offset, &dummy, &i) != 0)
-               pinmux_type = PINMUX_TYPE_FUNCTION;
-       else
-               pinmux_type = PINMUX_TYPE_GPIO;
-
-       if (pinmux_type == PINMUX_TYPE_FUNCTION) {
-               if (pinmux_config_gpio(gpioc, offset,
-                                      pinmux_type,
-                                      GPIO_CFG_DRYRUN) != 0)
-                       goto err_unlock;
-
-               if (pinmux_config_gpio(gpioc, offset,
-                                      pinmux_type,
-                                      GPIO_CFG_REQ) != 0)
-                       BUG();
-       }
-
-       gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE;
-       gpioc->gpios[offset].flags |= pinmux_type;
-
-       ret = 0;
- err_unlock:
-       spin_unlock_irqrestore(&gpio_lock, flags);
- err_out:
-       return ret;
-}
-
-static void sh_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-       struct pinmux_info *gpioc = chip_to_pinmux(chip);
-       unsigned long flags;
-       int pinmux_type;
-
-       if (!gpioc)
-               return;
-
-       spin_lock_irqsave(&gpio_lock, flags);
-
-       pinmux_type = gpioc->gpios[offset].flags & PINMUX_FLAG_TYPE;
-       pinmux_config_gpio(gpioc, offset, pinmux_type, GPIO_CFG_FREE);
-       gpioc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE;
-       gpioc->gpios[offset].flags |= PINMUX_TYPE_NONE;
-
-       spin_unlock_irqrestore(&gpio_lock, flags);
-}
-
-static int pinmux_direction(struct pinmux_info *gpioc,
-                           unsigned gpio, int new_pinmux_type)
-{
-       int pinmux_type;
-       int ret = -EINVAL;
-
-       if (!gpioc)
-               goto err_out;
-
-       pinmux_type = gpioc->gpios[gpio].flags & PINMUX_FLAG_TYPE;
-
-       switch (pinmux_type) {
-       case PINMUX_TYPE_GPIO:
-               break;
-       case PINMUX_TYPE_OUTPUT:
-       case PINMUX_TYPE_INPUT:
-       case PINMUX_TYPE_INPUT_PULLUP:
-       case PINMUX_TYPE_INPUT_PULLDOWN:
-               pinmux_config_gpio(gpioc, gpio, pinmux_type, GPIO_CFG_FREE);
-               break;
-       default:
-               goto err_out;
-       }
-
-       if (pinmux_config_gpio(gpioc, gpio,
-                              new_pinmux_type,
-                              GPIO_CFG_DRYRUN) != 0)
-               goto err_out;
-
-       if (pinmux_config_gpio(gpioc, gpio,
-                              new_pinmux_type,
-                              GPIO_CFG_REQ) != 0)
-               BUG();
-
-       gpioc->gpios[gpio].flags &= ~PINMUX_FLAG_TYPE;
-       gpioc->gpios[gpio].flags |= new_pinmux_type;
-
-       ret = 0;
- err_out:
-       return ret;
-}
-
-static int sh_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       struct pinmux_info *gpioc = chip_to_pinmux(chip);
-       unsigned long flags;
-       int ret;
-
-       spin_lock_irqsave(&gpio_lock, flags);
-       ret = pinmux_direction(gpioc, offset, PINMUX_TYPE_INPUT);
-       spin_unlock_irqrestore(&gpio_lock, flags);
-
-       return ret;
-}
-
-static void sh_gpio_set_value(struct pinmux_info *gpioc,
-                            unsigned gpio, int value)
-{
-       struct pinmux_data_reg *dr = NULL;
-       int bit = 0;
-
-       if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
-               BUG();
-       else
-               gpio_write_bit(dr, bit, value);
-}
-
-static int sh_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
-                                   int value)
-{
-       struct pinmux_info *gpioc = chip_to_pinmux(chip);
-       unsigned long flags;
-       int ret;
-
-       sh_gpio_set_value(gpioc, offset, value);
-       spin_lock_irqsave(&gpio_lock, flags);
-       ret = pinmux_direction(gpioc, offset, PINMUX_TYPE_OUTPUT);
-       spin_unlock_irqrestore(&gpio_lock, flags);
-
-       return ret;
-}
-
-static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
-{
-       struct pinmux_data_reg *dr = NULL;
-       int bit = 0;
-
-       if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
-               return -EINVAL;
-
-       return gpio_read_bit(dr, bit);
-}
-
-static int sh_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       return sh_gpio_get_value(chip_to_pinmux(chip), offset);
-}
-
-static void sh_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       sh_gpio_set_value(chip_to_pinmux(chip), offset, value);
-}
-
-static int sh_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
-{
-       struct pinmux_info *gpioc = chip_to_pinmux(chip);
-       pinmux_enum_t enum_id;
-       pinmux_enum_t *enum_ids;
-       int i, k, pos;
-
-       pos = 0;
-       enum_id = 0;
-       while (1) {
-               pos = get_gpio_enum_id(gpioc, offset, pos, &enum_id);
-               if (pos <= 0 || !enum_id)
-                       break;
-
-               for (i = 0; i < gpioc->gpio_irq_size; i++) {
-                       enum_ids = gpioc->gpio_irq[i].enum_ids;
-                       for (k = 0; enum_ids[k]; k++) {
-                               if (enum_ids[k] == enum_id)
-                                       return gpioc->gpio_irq[i].irq;
-                       }
-               }
-       }
-
-       return -ENOSYS;
-}
-
-int register_pinmux(struct pinmux_info *pip)
-{
-       struct gpio_chip *chip = &pip->chip;
-       int ret;
-
-       pr_info("%s handling gpio %d -> %d\n",
-               pip->name, pip->first_gpio, pip->last_gpio);
-
-       ret = pfc_ioremap(pip);
-       if (ret < 0)
-               return ret;
-
-       setup_data_regs(pip);
-
-       chip->request = sh_gpio_request;
-       chip->free = sh_gpio_free;
-       chip->direction_input = sh_gpio_direction_input;
-       chip->get = sh_gpio_get;
-       chip->direction_output = sh_gpio_direction_output;
-       chip->set = sh_gpio_set;
-       chip->to_irq = sh_gpio_to_irq;
-
-       WARN_ON(pip->first_gpio != 0); /* needs testing */
-
-       chip->label = pip->name;
-       chip->owner = THIS_MODULE;
-       chip->base = pip->first_gpio;
-       chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1;
-
-       ret = gpiochip_add(chip);
-       if (ret < 0)
-               pfc_iounmap(pip);
-
-       return ret;
-}
-
-int unregister_pinmux(struct pinmux_info *pip)
-{
-       pr_info("%s deregistering\n", pip->name);
-       pfc_iounmap(pip);
-       return gpiochip_remove(&pip->chip);
-}
diff --git a/drivers/sh/pfc/Kconfig b/drivers/sh/pfc/Kconfig
new file mode 100644 (file)
index 0000000..804f9ad
--- /dev/null
@@ -0,0 +1,26 @@
+comment "Pin function controller options"
+
+config SH_PFC
+       # XXX move off the gpio dependency
+       depends on GENERIC_GPIO
+       select GPIO_SH_PFC if ARCH_REQUIRE_GPIOLIB
+       select PINCTRL_SH_PFC
+       def_bool y
+
+#
+# Placeholder for now, rehome to drivers/pinctrl once the PFC APIs
+# have settled.
+#
+config PINCTRL_SH_PFC
+       tristate "SuperH PFC pin controller driver"
+       depends on SH_PFC
+       select PINCTRL
+       select PINMUX
+       select PINCONF
+
+config GPIO_SH_PFC
+       tristate "SuperH PFC GPIO support"
+       depends on SH_PFC && GPIOLIB
+       help
+         This enables support for GPIOs within the SoC's pin function
+         controller.
diff --git a/drivers/sh/pfc/Makefile b/drivers/sh/pfc/Makefile
new file mode 100644 (file)
index 0000000..7916027
--- /dev/null
@@ -0,0 +1,3 @@
+obj-y                          += core.o
+obj-$(CONFIG_PINCTRL_SH_PFC)   += pinctrl.o
+obj-$(CONFIG_GPIO_SH_PFC)      += gpio.o
diff --git a/drivers/sh/pfc/core.c b/drivers/sh/pfc/core.c
new file mode 100644 (file)
index 0000000..6816937
--- /dev/null
@@ -0,0 +1,572 @@
+/*
+ * SuperH Pin Function Controller support.
+ *
+ * Copyright (C) 2008 Magnus Damm
+ * Copyright (C) 2009 - 2012 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#define pr_fmt(fmt) "sh_pfc " KBUILD_MODNAME ": " fmt
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/sh_pfc.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/pinctrl/machine.h>
+
+static struct sh_pfc *sh_pfc __read_mostly;
+
+static inline bool sh_pfc_initialized(void)
+{
+       return !!sh_pfc;
+}
+
+static void pfc_iounmap(struct sh_pfc *pfc)
+{
+       int k;
+
+       for (k = 0; k < pfc->num_resources; k++)
+               if (pfc->window[k].virt)
+                       iounmap(pfc->window[k].virt);
+
+       kfree(pfc->window);
+       pfc->window = NULL;
+}
+
+static int pfc_ioremap(struct sh_pfc *pfc)
+{
+       struct resource *res;
+       int k;
+
+       if (!pfc->num_resources)
+               return 0;
+
+       pfc->window = kzalloc(pfc->num_resources * sizeof(*pfc->window),
+                             GFP_NOWAIT);
+       if (!pfc->window)
+               goto err1;
+
+       for (k = 0; k < pfc->num_resources; k++) {
+               res = pfc->resource + k;
+               WARN_ON(resource_type(res) != IORESOURCE_MEM);
+               pfc->window[k].phys = res->start;
+               pfc->window[k].size = resource_size(res);
+               pfc->window[k].virt = ioremap_nocache(res->start,
+                                                        resource_size(res));
+               if (!pfc->window[k].virt)
+                       goto err2;
+       }
+
+       return 0;
+
+err2:
+       pfc_iounmap(pfc);
+err1:
+       return -1;
+}
+
+static void __iomem *pfc_phys_to_virt(struct sh_pfc *pfc,
+                                     unsigned long address)
+{
+       struct pfc_window *window;
+       int k;
+
+       /* scan through physical windows and convert address */
+       for (k = 0; k < pfc->num_resources; k++) {
+               window = pfc->window + k;
+
+               if (address < window->phys)
+                       continue;
+
+               if (address >= (window->phys + window->size))
+                       continue;
+
+               return window->virt + (address - window->phys);
+       }
+
+       /* no windows defined, register must be 1:1 mapped virt:phys */
+       return (void __iomem *)address;
+}
+
+static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
+{
+       if (enum_id < r->begin)
+               return 0;
+
+       if (enum_id > r->end)
+               return 0;
+
+       return 1;
+}
+
+static unsigned long gpio_read_raw_reg(void __iomem *mapped_reg,
+                                      unsigned long reg_width)
+{
+       switch (reg_width) {
+       case 8:
+               return ioread8(mapped_reg);
+       case 16:
+               return ioread16(mapped_reg);
+       case 32:
+               return ioread32(mapped_reg);
+       }
+
+       BUG();
+       return 0;
+}
+
+static void gpio_write_raw_reg(void __iomem *mapped_reg,
+                              unsigned long reg_width,
+                              unsigned long data)
+{
+       switch (reg_width) {
+       case 8:
+               iowrite8(data, mapped_reg);
+               return;
+       case 16:
+               iowrite16(data, mapped_reg);
+               return;
+       case 32:
+               iowrite32(data, mapped_reg);
+               return;
+       }
+
+       BUG();
+}
+
+int sh_pfc_read_bit(struct pinmux_data_reg *dr, unsigned long in_pos)
+{
+       unsigned long pos;
+
+       pos = dr->reg_width - (in_pos + 1);
+
+       pr_debug("read_bit: addr = %lx, pos = %ld, "
+                "r_width = %ld\n", dr->reg, pos, dr->reg_width);
+
+       return (gpio_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1;
+}
+EXPORT_SYMBOL_GPL(sh_pfc_read_bit);
+
+void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos,
+                     unsigned long value)
+{
+       unsigned long pos;
+
+       pos = dr->reg_width - (in_pos + 1);
+
+       pr_debug("write_bit addr = %lx, value = %d, pos = %ld, "
+                "r_width = %ld\n",
+                dr->reg, !!value, pos, dr->reg_width);
+
+       if (value)
+               set_bit(pos, &dr->reg_shadow);
+       else
+               clear_bit(pos, &dr->reg_shadow);
+
+       gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
+}
+EXPORT_SYMBOL_GPL(sh_pfc_write_bit);
+
+static void config_reg_helper(struct sh_pfc *pfc,
+                             struct pinmux_cfg_reg *crp,
+                             unsigned long in_pos,
+                             void __iomem **mapped_regp,
+                             unsigned long *maskp,
+                             unsigned long *posp)
+{
+       int k;
+
+       *mapped_regp = pfc_phys_to_virt(pfc, crp->reg);
+
+       if (crp->field_width) {
+               *maskp = (1 << crp->field_width) - 1;
+               *posp = crp->reg_width - ((in_pos + 1) * crp->field_width);
+       } else {
+               *maskp = (1 << crp->var_field_width[in_pos]) - 1;
+               *posp = crp->reg_width;
+               for (k = 0; k <= in_pos; k++)
+                       *posp -= crp->var_field_width[k];
+       }
+}
+
+static int read_config_reg(struct sh_pfc *pfc,
+                          struct pinmux_cfg_reg *crp,
+                          unsigned long field)
+{
+       void __iomem *mapped_reg;
+       unsigned long mask, pos;
+
+       config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos);
+
+       pr_debug("read_reg: addr = %lx, field = %ld, "
+                "r_width = %ld, f_width = %ld\n",
+                crp->reg, field, crp->reg_width, crp->field_width);
+
+       return (gpio_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask;
+}
+
+static void write_config_reg(struct sh_pfc *pfc,
+                            struct pinmux_cfg_reg *crp,
+                            unsigned long field, unsigned long value)
+{
+       void __iomem *mapped_reg;
+       unsigned long mask, pos, data;
+
+       config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos);
+
+       pr_debug("write_reg addr = %lx, value = %ld, field = %ld, "
+                "r_width = %ld, f_width = %ld\n",
+                crp->reg, value, field, crp->reg_width, crp->field_width);
+
+       mask = ~(mask << pos);
+       value = value << pos;
+
+       data = gpio_read_raw_reg(mapped_reg, crp->reg_width);
+       data &= mask;
+       data |= value;
+
+       if (pfc->unlock_reg)
+               gpio_write_raw_reg(pfc_phys_to_virt(pfc, pfc->unlock_reg),
+                                  32, ~data);
+
+       gpio_write_raw_reg(mapped_reg, crp->reg_width, data);
+}
+
+static int setup_data_reg(struct sh_pfc *pfc, unsigned gpio)
+{
+       struct pinmux_gpio *gpiop = &pfc->gpios[gpio];
+       struct pinmux_data_reg *data_reg;
+       int k, n;
+
+       if (!enum_in_range(gpiop->enum_id, &pfc->data))
+               return -1;
+
+       k = 0;
+       while (1) {
+               data_reg = pfc->data_regs + k;
+
+               if (!data_reg->reg_width)
+                       break;
+
+               data_reg->mapped_reg = pfc_phys_to_virt(pfc, data_reg->reg);
+
+               for (n = 0; n < data_reg->reg_width; n++) {
+                       if (data_reg->enum_ids[n] == gpiop->enum_id) {
+                               gpiop->flags &= ~PINMUX_FLAG_DREG;
+                               gpiop->flags |= (k << PINMUX_FLAG_DREG_SHIFT);
+                               gpiop->flags &= ~PINMUX_FLAG_DBIT;
+                               gpiop->flags |= (n << PINMUX_FLAG_DBIT_SHIFT);
+                               return 0;
+                       }
+               }
+               k++;
+       }
+
+       BUG();
+
+       return -1;
+}
+
+static void setup_data_regs(struct sh_pfc *pfc)
+{
+       struct pinmux_data_reg *drp;
+       int k;
+
+       for (k = pfc->first_gpio; k <= pfc->last_gpio; k++)
+               setup_data_reg(pfc, k);
+
+       k = 0;
+       while (1) {
+               drp = pfc->data_regs + k;
+
+               if (!drp->reg_width)
+                       break;
+
+               drp->reg_shadow = gpio_read_raw_reg(drp->mapped_reg,
+                                                   drp->reg_width);
+               k++;
+       }
+}
+
+int sh_pfc_get_data_reg(struct sh_pfc *pfc, unsigned gpio,
+                       struct pinmux_data_reg **drp, int *bitp)
+{
+       struct pinmux_gpio *gpiop = &pfc->gpios[gpio];
+       int k, n;
+
+       if (!enum_in_range(gpiop->enum_id, &pfc->data))
+               return -1;
+
+       k = (gpiop->flags & PINMUX_FLAG_DREG) >> PINMUX_FLAG_DREG_SHIFT;
+       n = (gpiop->flags & PINMUX_FLAG_DBIT) >> PINMUX_FLAG_DBIT_SHIFT;
+       *drp = pfc->data_regs + k;
+       *bitp = n;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(sh_pfc_get_data_reg);
+
+static int get_config_reg(struct sh_pfc *pfc, pinmux_enum_t enum_id,
+                         struct pinmux_cfg_reg **crp,
+                         int *fieldp, int *valuep,
+                         unsigned long **cntp)
+{
+       struct pinmux_cfg_reg *config_reg;
+       unsigned long r_width, f_width, curr_width, ncomb;
+       int k, m, n, pos, bit_pos;
+
+       k = 0;
+       while (1) {
+               config_reg = pfc->cfg_regs + k;
+
+               r_width = config_reg->reg_width;
+               f_width = config_reg->field_width;
+
+               if (!r_width)
+                       break;
+
+               pos = 0;
+               m = 0;
+               for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
+                       if (f_width)
+                               curr_width = f_width;
+                       else
+                               curr_width = config_reg->var_field_width[m];
+
+                       ncomb = 1 << curr_width;
+                       for (n = 0; n < ncomb; n++) {
+                               if (config_reg->enum_ids[pos + n] == enum_id) {
+                                       *crp = config_reg;
+                                       *fieldp = m;
+                                       *valuep = n;
+                                       *cntp = &config_reg->cnt[m];
+                                       return 0;
+                               }
+                       }
+                       pos += ncomb;
+                       m++;
+               }
+               k++;
+       }
+
+       return -1;
+}
+
+int sh_pfc_gpio_to_enum(struct sh_pfc *pfc, unsigned gpio, int pos,
+                       pinmux_enum_t *enum_idp)
+{
+       pinmux_enum_t enum_id = pfc->gpios[gpio].enum_id;
+       pinmux_enum_t *data = pfc->gpio_data;
+       int k;
+
+       if (!enum_in_range(enum_id, &pfc->data)) {
+               if (!enum_in_range(enum_id, &pfc->mark)) {
+                       pr_err("non data/mark enum_id for gpio %d\n", gpio);
+                       return -1;
+               }
+       }
+
+       if (pos) {
+               *enum_idp = data[pos + 1];
+               return pos + 1;
+       }
+
+       for (k = 0; k < pfc->gpio_data_size; k++) {
+               if (data[k] == enum_id) {
+                       *enum_idp = data[k + 1];
+                       return k + 1;
+               }
+       }
+
+       pr_err("cannot locate data/mark enum_id for gpio %d\n", gpio);
+       return -1;
+}
+EXPORT_SYMBOL_GPL(sh_pfc_gpio_to_enum);
+
+int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
+                      int cfg_mode)
+{
+       struct pinmux_cfg_reg *cr = NULL;
+       pinmux_enum_t enum_id;
+       struct pinmux_range *range;
+       int in_range, pos, field, value;
+       unsigned long *cntp;
+
+       switch (pinmux_type) {
+
+       case PINMUX_TYPE_FUNCTION:
+               range = NULL;
+               break;
+
+       case PINMUX_TYPE_OUTPUT:
+               range = &pfc->output;
+               break;
+
+       case PINMUX_TYPE_INPUT:
+               range = &pfc->input;
+               break;
+
+       case PINMUX_TYPE_INPUT_PULLUP:
+               range = &pfc->input_pu;
+               break;
+
+       case PINMUX_TYPE_INPUT_PULLDOWN:
+               range = &pfc->input_pd;
+               break;
+
+       default:
+               goto out_err;
+       }
+
+       pos = 0;
+       enum_id = 0;
+       field = 0;
+       value = 0;
+       while (1) {
+               pos = sh_pfc_gpio_to_enum(pfc, gpio, pos, &enum_id);
+               if (pos <= 0)
+                       goto out_err;
+
+               if (!enum_id)
+                       break;
+
+               /* first check if this is a function enum */
+               in_range = enum_in_range(enum_id, &pfc->function);
+               if (!in_range) {
+                       /* not a function enum */
+                       if (range) {
+                               /*
+                                * other range exists, so this pin is
+                                * a regular GPIO pin that now is being
+                                * bound to a specific direction.
+                                *
+                                * for this case we only allow function enums
+                                * and the enums that match the other range.
+                                */
+                               in_range = enum_in_range(enum_id, range);
+
+                               /*
+                                * special case pass through for fixed
+                                * input-only or output-only pins without
+                                * function enum register association.
+                                */
+                               if (in_range && enum_id == range->force)
+                                       continue;
+                       } else {
+                               /*
+                                * no other range exists, so this pin
+                                * must then be of the function type.
+                                *
+                                * allow function type pins to select
+                                * any combination of function/in/out
+                                * in their MARK lists.
+                                */
+                               in_range = 1;
+                       }
+               }
+
+               if (!in_range)
+                       continue;
+
+               if (get_config_reg(pfc, enum_id, &cr,
+                                  &field, &value, &cntp) != 0)
+                       goto out_err;
+
+               switch (cfg_mode) {
+               case GPIO_CFG_DRYRUN:
+                       if (!*cntp ||
+                           (read_config_reg(pfc, cr, field) != value))
+                               continue;
+                       break;
+
+               case GPIO_CFG_REQ:
+                       write_config_reg(pfc, cr, field, value);
+                       *cntp = *cntp + 1;
+                       break;
+
+               case GPIO_CFG_FREE:
+                       *cntp = *cntp - 1;
+                       break;
+               }
+       }
+
+       return 0;
+ out_err:
+       return -1;
+}
+EXPORT_SYMBOL_GPL(sh_pfc_config_gpio);
+
+int register_sh_pfc(struct sh_pfc *pfc)
+{
+       int (*initroutine)(struct sh_pfc *) = NULL;
+       int ret;
+
+       /*
+        * Ensure that the type encoding fits
+        */
+       BUILD_BUG_ON(PINMUX_FLAG_TYPE > ((1 << PINMUX_FLAG_DBIT_SHIFT) - 1));
+
+       if (sh_pfc)
+               return -EBUSY;
+
+       ret = pfc_ioremap(pfc);
+       if (unlikely(ret < 0))
+               return ret;
+
+       spin_lock_init(&pfc->lock);
+
+       pinctrl_provide_dummies();
+       setup_data_regs(pfc);
+
+       sh_pfc = pfc;
+
+       /*
+        * Initialize pinctrl bindings first
+        */
+       initroutine = symbol_request(sh_pfc_register_pinctrl);
+       if (initroutine) {
+               ret = (*initroutine)(pfc);
+               symbol_put_addr(initroutine);
+
+               if (unlikely(ret != 0))
+                       goto err;
+       } else {
+               pr_err("failed to initialize pinctrl bindings\n");
+               goto err;
+       }
+
+       /*
+        * Then the GPIO chip
+        */
+       initroutine = symbol_request(sh_pfc_register_gpiochip);
+       if (initroutine) {
+               ret = (*initroutine)(pfc);
+               symbol_put_addr(initroutine);
+
+               /*
+                * If the GPIO chip fails to come up we still leave the
+                * PFC state as it is, given that there are already
+                * extant users of it that have succeeded by this point.
+                */
+               if (unlikely(ret != 0)) {
+                       pr_notice("failed to init GPIO chip, ignoring...\n");
+                       ret = 0;
+               }
+       }
+
+       pr_info("%s support registered\n", pfc->name);
+
+       return 0;
+
+err:
+       pfc_iounmap(pfc);
+       sh_pfc = NULL;
+
+       return ret;
+}
diff --git a/drivers/sh/pfc/gpio.c b/drivers/sh/pfc/gpio.c
new file mode 100644 (file)
index 0000000..62bca98
--- /dev/null
@@ -0,0 +1,239 @@
+/*
+ * SuperH Pin Function Controller GPIO driver.
+ *
+ * Copyright (C) 2008 Magnus Damm
+ * Copyright (C) 2009 - 2012 Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#define pr_fmt(fmt) "sh_pfc " KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
+
+struct sh_pfc_chip {
+       struct sh_pfc           *pfc;
+       struct gpio_chip        gpio_chip;
+};
+
+static struct sh_pfc_chip *gpio_to_pfc_chip(struct gpio_chip *gc)
+{
+       return container_of(gc, struct sh_pfc_chip, gpio_chip);
+}
+
+static struct sh_pfc *gpio_to_pfc(struct gpio_chip *gc)
+{
+       return gpio_to_pfc_chip(gc)->pfc;
+}
+
+static int sh_gpio_request(struct gpio_chip *gc, unsigned offset)
+{
+       return pinctrl_request_gpio(offset);
+}
+
+static void sh_gpio_free(struct gpio_chip *gc, unsigned offset)
+{
+       pinctrl_free_gpio(offset);
+}
+
+static void sh_gpio_set_value(struct sh_pfc *pfc, unsigned gpio, int value)
+{
+       struct pinmux_data_reg *dr = NULL;
+       int bit = 0;
+
+       if (!pfc || sh_pfc_get_data_reg(pfc, gpio, &dr, &bit) != 0)
+               BUG();
+       else
+               sh_pfc_write_bit(dr, bit, value);
+}
+
+static int sh_gpio_get_value(struct sh_pfc *pfc, unsigned gpio)
+{
+       struct pinmux_data_reg *dr = NULL;
+       int bit = 0;
+
+       if (!pfc || sh_pfc_get_data_reg(pfc, gpio, &dr, &bit) != 0)
+               return -EINVAL;
+
+       return sh_pfc_read_bit(dr, bit);
+}
+
+static int sh_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+       return pinctrl_gpio_direction_input(offset);
+}
+
+static int sh_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
+                                   int value)
+{
+       sh_gpio_set_value(gpio_to_pfc(gc), offset, value);
+
+       return pinctrl_gpio_direction_output(offset);
+}
+
+static int sh_gpio_get(struct gpio_chip *gc, unsigned offset)
+{
+       return sh_gpio_get_value(gpio_to_pfc(gc), offset);
+}
+
+static void sh_gpio_set(struct gpio_chip *gc, unsigned offset, int value)
+{
+       sh_gpio_set_value(gpio_to_pfc(gc), offset, value);
+}
+
+static int sh_gpio_to_irq(struct gpio_chip *gc, unsigned offset)
+{
+       struct sh_pfc *pfc = gpio_to_pfc(gc);
+       pinmux_enum_t enum_id;
+       pinmux_enum_t *enum_ids;
+       int i, k, pos;
+
+       pos = 0;
+       enum_id = 0;
+       while (1) {
+               pos = sh_pfc_gpio_to_enum(pfc, offset, pos, &enum_id);
+               if (pos <= 0 || !enum_id)
+                       break;
+
+               for (i = 0; i < pfc->gpio_irq_size; i++) {
+                       enum_ids = pfc->gpio_irq[i].enum_ids;
+                       for (k = 0; enum_ids[k]; k++) {
+                               if (enum_ids[k] == enum_id)
+                                       return pfc->gpio_irq[i].irq;
+                       }
+               }
+       }
+
+       return -ENOSYS;
+}
+
+static void sh_pfc_gpio_setup(struct sh_pfc_chip *chip)
+{
+       struct sh_pfc *pfc = chip->pfc;
+       struct gpio_chip *gc = &chip->gpio_chip;
+
+       gc->request = sh_gpio_request;
+       gc->free = sh_gpio_free;
+       gc->direction_input = sh_gpio_direction_input;
+       gc->get = sh_gpio_get;
+       gc->direction_output = sh_gpio_direction_output;
+       gc->set = sh_gpio_set;
+       gc->to_irq = sh_gpio_to_irq;
+
+       WARN_ON(pfc->first_gpio != 0); /* needs testing */
+
+       gc->label = pfc->name;
+       gc->owner = THIS_MODULE;
+       gc->base = pfc->first_gpio;
+       gc->ngpio = (pfc->last_gpio - pfc->first_gpio) + 1;
+}
+
+int sh_pfc_register_gpiochip(struct sh_pfc *pfc)
+{
+       struct sh_pfc_chip *chip;
+       int ret;
+
+       chip = kzalloc(sizeof(struct sh_pfc_chip), GFP_KERNEL);
+       if (unlikely(!chip))
+               return -ENOMEM;
+
+       chip->pfc = pfc;
+
+       sh_pfc_gpio_setup(chip);
+
+       ret = gpiochip_add(&chip->gpio_chip);
+       if (unlikely(ret < 0))
+               kfree(chip);
+
+       pr_info("%s handling gpio %d -> %d\n",
+               pfc->name, pfc->first_gpio, pfc->last_gpio);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(sh_pfc_register_gpiochip);
+
+static int sh_pfc_gpio_match(struct gpio_chip *gc, void *data)
+{
+       return !!strstr(gc->label, data);
+}
+
+static int __devinit sh_pfc_gpio_probe(struct platform_device *pdev)
+{
+       struct sh_pfc_chip *chip;
+       struct gpio_chip *gc;
+
+       gc = gpiochip_find("_pfc", sh_pfc_gpio_match);
+       if (unlikely(!gc)) {
+               pr_err("Cant find gpio chip\n");
+               return -ENODEV;
+       }
+
+       chip = gpio_to_pfc_chip(gc);
+       platform_set_drvdata(pdev, chip);
+
+       pr_info("attaching to GPIO chip %s\n", chip->pfc->name);
+
+       return 0;
+}
+
+static int __devexit sh_pfc_gpio_remove(struct platform_device *pdev)
+{
+       struct sh_pfc_chip *chip = platform_get_drvdata(pdev);
+       int ret;
+
+       ret = gpiochip_remove(&chip->gpio_chip);
+       if (unlikely(ret < 0))
+               return ret;
+
+       kfree(chip);
+       return 0;
+}
+
+static struct platform_driver sh_pfc_gpio_driver = {
+       .probe          = sh_pfc_gpio_probe,
+       .remove         = __devexit_p(sh_pfc_gpio_remove),
+       .driver         = {
+               .name   = KBUILD_MODNAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static struct platform_device sh_pfc_gpio_device = {
+       .name           = KBUILD_MODNAME,
+       .id             = -1,
+};
+
+static int __init sh_pfc_gpio_init(void)
+{
+       int rc;
+
+       rc = platform_driver_register(&sh_pfc_gpio_driver);
+       if (likely(!rc)) {
+               rc = platform_device_register(&sh_pfc_gpio_device);
+               if (unlikely(rc))
+                       platform_driver_unregister(&sh_pfc_gpio_driver);
+       }
+
+       return rc;
+}
+
+static void __exit sh_pfc_gpio_exit(void)
+{
+       platform_device_unregister(&sh_pfc_gpio_device);
+       platform_driver_unregister(&sh_pfc_gpio_driver);
+}
+
+module_init(sh_pfc_gpio_init);
+module_exit(sh_pfc_gpio_exit);
+
+MODULE_AUTHOR("Magnus Damm, Paul Mundt");
+MODULE_DESCRIPTION("GPIO driver for SuperH pin function controller");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:pfc-gpio");
diff --git a/drivers/sh/pfc/pinctrl.c b/drivers/sh/pfc/pinctrl.c
new file mode 100644 (file)
index 0000000..0802b6c
--- /dev/null
@@ -0,0 +1,530 @@
+/*
+ * SuperH Pin Function Controller pinmux support.
+ *
+ * Copyright (C) 2012  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+#define DRV_NAME "pinctrl-sh_pfc"
+
+#define pr_fmt(fmt) DRV_NAME " " KBUILD_MODNAME ": " fmt
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/sh_pfc.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf-generic.h>
+
+struct sh_pfc_pinctrl {
+       struct pinctrl_dev *pctl;
+       struct sh_pfc *pfc;
+
+       struct pinmux_gpio **functions;
+       unsigned int nr_functions;
+
+       struct pinctrl_pin_desc *pads;
+       unsigned int nr_pads;
+
+       spinlock_t lock;
+};
+
+static struct sh_pfc_pinctrl *sh_pfc_pmx;
+
+static int sh_pfc_get_groups_count(struct pinctrl_dev *pctldev)
+{
+       struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+       return pmx->nr_pads;
+}
+
+static const char *sh_pfc_get_group_name(struct pinctrl_dev *pctldev,
+                                        unsigned selector)
+{
+       struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+       return pmx->pads[selector].name;
+}
+
+static int sh_pfc_get_group_pins(struct pinctrl_dev *pctldev, unsigned group,
+                                const unsigned **pins, unsigned *num_pins)
+{
+       struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+       *pins = &pmx->pads[group].number;
+       *num_pins = 1;
+
+       return 0;
+}
+
+static void sh_pfc_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
+                               unsigned offset)
+{
+       seq_printf(s, "%s", DRV_NAME);
+}
+
+static struct pinctrl_ops sh_pfc_pinctrl_ops = {
+       .get_groups_count       = sh_pfc_get_groups_count,
+       .get_group_name         = sh_pfc_get_group_name,
+       .get_group_pins         = sh_pfc_get_group_pins,
+       .pin_dbg_show           = sh_pfc_pin_dbg_show,
+};
+
+static int sh_pfc_get_functions_count(struct pinctrl_dev *pctldev)
+{
+       struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+       return pmx->nr_functions;
+}
+
+static const char *sh_pfc_get_function_name(struct pinctrl_dev *pctldev,
+                                           unsigned selector)
+{
+       struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+       return pmx->functions[selector]->name;
+}
+
+static int sh_pfc_get_function_groups(struct pinctrl_dev *pctldev, unsigned func,
+                                     const char * const **groups,
+                                     unsigned * const num_groups)
+{
+       struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+
+       *groups = &pmx->functions[func]->name;
+       *num_groups = 1;
+
+       return 0;
+}
+
+static int sh_pfc_noop_enable(struct pinctrl_dev *pctldev, unsigned func,
+                             unsigned group)
+{
+       return 0;
+}
+
+static void sh_pfc_noop_disable(struct pinctrl_dev *pctldev, unsigned func,
+                               unsigned group)
+{
+}
+
+static inline int sh_pfc_config_function(struct sh_pfc *pfc, unsigned offset)
+{
+       if (sh_pfc_config_gpio(pfc, offset,
+                              PINMUX_TYPE_FUNCTION,
+                              GPIO_CFG_DRYRUN) != 0)
+               return -EINVAL;
+
+       if (sh_pfc_config_gpio(pfc, offset,
+                              PINMUX_TYPE_FUNCTION,
+                              GPIO_CFG_REQ) != 0)
+               return -EINVAL;
+
+       return 0;
+}
+
+static int sh_pfc_reconfig_pin(struct sh_pfc *pfc, unsigned offset,
+                              int new_type)
+{
+       unsigned long flags;
+       int pinmux_type;
+       int ret = -EINVAL;
+
+       spin_lock_irqsave(&pfc->lock, flags);
+
+       pinmux_type = pfc->gpios[offset].flags & PINMUX_FLAG_TYPE;
+
+       /*
+        * See if the present config needs to first be de-configured.
+        */
+       switch (pinmux_type) {
+       case PINMUX_TYPE_GPIO:
+               break;
+       case PINMUX_TYPE_OUTPUT:
+       case PINMUX_TYPE_INPUT:
+       case PINMUX_TYPE_INPUT_PULLUP:
+       case PINMUX_TYPE_INPUT_PULLDOWN:
+               sh_pfc_config_gpio(pfc, offset, pinmux_type, GPIO_CFG_FREE);
+               break;
+       default:
+               goto err;
+       }
+
+       /*
+        * Dry run
+        */
+       if (sh_pfc_config_gpio(pfc, offset, new_type,
+                              GPIO_CFG_DRYRUN) != 0)
+               goto err;
+
+       /*
+        * Request
+        */
+       if (sh_pfc_config_gpio(pfc, offset, new_type,
+                              GPIO_CFG_REQ) != 0)
+               goto err;
+
+       pfc->gpios[offset].flags &= ~PINMUX_FLAG_TYPE;
+       pfc->gpios[offset].flags |= new_type;
+
+       ret = 0;
+
+err:
+       spin_unlock_irqrestore(&pfc->lock, flags);
+
+       return ret;
+}
+
+
+static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev,
+                                     struct pinctrl_gpio_range *range,
+                                     unsigned offset)
+{
+       struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+       struct sh_pfc *pfc = pmx->pfc;
+       unsigned long flags;
+       int ret, pinmux_type;
+
+       spin_lock_irqsave(&pfc->lock, flags);
+
+       pinmux_type = pfc->gpios[offset].flags & PINMUX_FLAG_TYPE;
+
+       switch (pinmux_type) {
+       case PINMUX_TYPE_FUNCTION:
+               pr_notice_once("Use of GPIO API for function requests is "
+                              "deprecated, convert to pinctrl\n");
+               /* handle for now */
+               ret = sh_pfc_config_function(pfc, offset);
+               if (unlikely(ret < 0))
+                       goto err;
+
+               break;
+       case PINMUX_TYPE_GPIO:
+               break;
+       default:
+               pr_err("Unsupported mux type (%d), bailing...\n", pinmux_type);
+               return -ENOTSUPP;
+       }
+
+       ret = 0;
+
+err:
+       spin_unlock_irqrestore(&pfc->lock, flags);
+
+       return ret;
+}
+
+static void sh_pfc_gpio_disable_free(struct pinctrl_dev *pctldev,
+                                    struct pinctrl_gpio_range *range,
+                                    unsigned offset)
+{
+       struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+       struct sh_pfc *pfc = pmx->pfc;
+       unsigned long flags;
+       int pinmux_type;
+
+       spin_lock_irqsave(&pfc->lock, flags);
+
+       pinmux_type = pfc->gpios[offset].flags & PINMUX_FLAG_TYPE;
+
+       sh_pfc_config_gpio(pfc, offset, pinmux_type, GPIO_CFG_FREE);
+
+       spin_unlock_irqrestore(&pfc->lock, flags);
+}
+
+static int sh_pfc_gpio_set_direction(struct pinctrl_dev *pctldev,
+                                    struct pinctrl_gpio_range *range,
+                                    unsigned offset, bool input)
+{
+       struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+       int type = input ? PINMUX_TYPE_INPUT : PINMUX_TYPE_OUTPUT;
+
+       return sh_pfc_reconfig_pin(pmx->pfc, offset, type);
+}
+
+static struct pinmux_ops sh_pfc_pinmux_ops = {
+       .get_functions_count    = sh_pfc_get_functions_count,
+       .get_function_name      = sh_pfc_get_function_name,
+       .get_function_groups    = sh_pfc_get_function_groups,
+       .enable                 = sh_pfc_noop_enable,
+       .disable                = sh_pfc_noop_disable,
+       .gpio_request_enable    = sh_pfc_gpio_request_enable,
+       .gpio_disable_free      = sh_pfc_gpio_disable_free,
+       .gpio_set_direction     = sh_pfc_gpio_set_direction,
+};
+
+static int sh_pfc_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin,
+                             unsigned long *config)
+{
+       struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+       struct sh_pfc *pfc = pmx->pfc;
+
+       *config = pfc->gpios[pin].flags & PINMUX_FLAG_TYPE;
+
+       return 0;
+}
+
+static int sh_pfc_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin,
+                             unsigned long config)
+{
+       struct sh_pfc_pinctrl *pmx = pinctrl_dev_get_drvdata(pctldev);
+       struct sh_pfc *pfc = pmx->pfc;
+
+       /* Validate the new type */
+       if (config >= PINMUX_FLAG_TYPE)
+               return -EINVAL;
+
+       return sh_pfc_reconfig_pin(pmx->pfc, pin, config);
+}
+
+static void sh_pfc_pinconf_dbg_show(struct pinctrl_dev *pctldev,
+                                   struct seq_file *s, unsigned pin)
+{
+       const char *pinmux_type_str[] = {
+               [PINMUX_TYPE_NONE]              = "none",
+               [PINMUX_TYPE_FUNCTION]          = "function",
+               [PINMUX_TYPE_GPIO]              = "gpio",
+               [PINMUX_TYPE_OUTPUT]            = "output",
+               [PINMUX_TYPE_INPUT]             = "input",
+               [PINMUX_TYPE_INPUT_PULLUP]      = "input bias pull up",
+               [PINMUX_TYPE_INPUT_PULLDOWN]    = "input bias pull down",
+       };
+       unsigned long config;
+       int rc;
+
+       rc = sh_pfc_pinconf_get(pctldev, pin, &config);
+       if (unlikely(rc != 0))
+               return;
+
+       seq_printf(s, " %s", pinmux_type_str[config]);
+}
+
+static struct pinconf_ops sh_pfc_pinconf_ops = {
+       .pin_config_get         = sh_pfc_pinconf_get,
+       .pin_config_set         = sh_pfc_pinconf_set,
+       .pin_config_dbg_show    = sh_pfc_pinconf_dbg_show,
+};
+
+static struct pinctrl_gpio_range sh_pfc_gpio_range = {
+       .name           = DRV_NAME,
+       .id             = 0,
+};
+
+static struct pinctrl_desc sh_pfc_pinctrl_desc = {
+       .name           = DRV_NAME,
+       .owner          = THIS_MODULE,
+       .pctlops        = &sh_pfc_pinctrl_ops,
+       .pmxops         = &sh_pfc_pinmux_ops,
+       .confops        = &sh_pfc_pinconf_ops,
+};
+
+int sh_pfc_register_pinctrl(struct sh_pfc *pfc)
+{
+       sh_pfc_pmx = kzalloc(sizeof(struct sh_pfc_pinctrl), GFP_KERNEL);
+       if (unlikely(!sh_pfc_pmx))
+               return -ENOMEM;
+
+       spin_lock_init(&sh_pfc_pmx->lock);
+
+       sh_pfc_pmx->pfc = pfc;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(sh_pfc_register_pinctrl);
+
+static inline void __devinit sh_pfc_map_one_gpio(struct sh_pfc *pfc,
+                                                struct sh_pfc_pinctrl *pmx,
+                                                struct pinmux_gpio *gpio,
+                                                unsigned offset)
+{
+       struct pinmux_data_reg *dummy;
+       unsigned long flags;
+       int bit;
+
+       gpio->flags &= ~PINMUX_FLAG_TYPE;
+
+       if (sh_pfc_get_data_reg(pfc, offset, &dummy, &bit) == 0)
+               gpio->flags |= PINMUX_TYPE_GPIO;
+       else {
+               gpio->flags |= PINMUX_TYPE_FUNCTION;
+
+               spin_lock_irqsave(&pmx->lock, flags);
+               pmx->nr_functions++;
+               spin_unlock_irqrestore(&pmx->lock, flags);
+       }
+}
+
+/* pinmux ranges -> pinctrl pin descs */
+static int __devinit sh_pfc_map_gpios(struct sh_pfc *pfc,
+                                     struct sh_pfc_pinctrl *pmx)
+{
+       unsigned long flags;
+       int i;
+
+       pmx->nr_pads = pfc->last_gpio - pfc->first_gpio + 1;
+
+       pmx->pads = kmalloc(sizeof(struct pinctrl_pin_desc) * pmx->nr_pads,
+                           GFP_KERNEL);
+       if (unlikely(!pmx->pads)) {
+               pmx->nr_pads = 0;
+               return -ENOMEM;
+       }
+
+       spin_lock_irqsave(&pfc->lock, flags);
+
+       /*
+        * We don't necessarily have a 1:1 mapping between pin and linux
+        * GPIO number, as the latter maps to the associated enum_id.
+        * Care needs to be taken to translate back to pin space when
+        * dealing with any pin configurations.
+        */
+       for (i = 0; i < pmx->nr_pads; i++) {
+               struct pinctrl_pin_desc *pin = pmx->pads + i;
+               struct pinmux_gpio *gpio = pfc->gpios + i;
+
+               pin->number = pfc->first_gpio + i;
+               pin->name = gpio->name;
+
+               /* XXX */
+               if (unlikely(!gpio->enum_id))
+                       continue;
+
+               sh_pfc_map_one_gpio(pfc, pmx, gpio, i);
+       }
+
+       spin_unlock_irqrestore(&pfc->lock, flags);
+
+       sh_pfc_pinctrl_desc.pins = pmx->pads;
+       sh_pfc_pinctrl_desc.npins = pmx->nr_pads;
+
+       return 0;
+}
+
+static int __devinit sh_pfc_map_functions(struct sh_pfc *pfc,
+                                         struct sh_pfc_pinctrl *pmx)
+{
+       unsigned long flags;
+       int i, fn;
+
+       pmx->functions = kzalloc(pmx->nr_functions * sizeof(void *),
+                                GFP_KERNEL);
+       if (unlikely(!pmx->functions))
+               return -ENOMEM;
+
+       spin_lock_irqsave(&pmx->lock, flags);
+
+       for (i = fn = 0; i < pmx->nr_pads; i++) {
+               struct pinmux_gpio *gpio = pfc->gpios + i;
+
+               if ((gpio->flags & PINMUX_FLAG_TYPE) == PINMUX_TYPE_FUNCTION)
+                       pmx->functions[fn++] = gpio;
+       }
+
+       spin_unlock_irqrestore(&pmx->lock, flags);
+
+       return 0;
+}
+
+static int __devinit sh_pfc_pinctrl_probe(struct platform_device *pdev)
+{
+       struct sh_pfc *pfc;
+       int ret;
+
+       if (unlikely(!sh_pfc_pmx))
+               return -ENODEV;
+
+       pfc = sh_pfc_pmx->pfc;
+
+       ret = sh_pfc_map_gpios(pfc, sh_pfc_pmx);
+       if (unlikely(ret != 0))
+               return ret;
+
+       ret = sh_pfc_map_functions(pfc, sh_pfc_pmx);
+       if (unlikely(ret != 0))
+               goto free_pads;
+
+       sh_pfc_pmx->pctl = pinctrl_register(&sh_pfc_pinctrl_desc, &pdev->dev,
+                                           sh_pfc_pmx);
+       if (IS_ERR(sh_pfc_pmx->pctl)) {
+               ret = PTR_ERR(sh_pfc_pmx->pctl);
+               goto free_functions;
+       }
+
+       sh_pfc_gpio_range.npins = pfc->last_gpio - pfc->first_gpio + 1;
+       sh_pfc_gpio_range.base = pfc->first_gpio;
+       sh_pfc_gpio_range.pin_base = pfc->first_gpio;
+
+       pinctrl_add_gpio_range(sh_pfc_pmx->pctl, &sh_pfc_gpio_range);
+
+       platform_set_drvdata(pdev, sh_pfc_pmx);
+
+       return 0;
+
+free_functions:
+       kfree(sh_pfc_pmx->functions);
+free_pads:
+       kfree(sh_pfc_pmx->pads);
+       kfree(sh_pfc_pmx);
+
+       return ret;
+}
+
+static int __devexit sh_pfc_pinctrl_remove(struct platform_device *pdev)
+{
+       struct sh_pfc_pinctrl *pmx = platform_get_drvdata(pdev);
+
+       pinctrl_remove_gpio_range(pmx->pctl, &sh_pfc_gpio_range);
+       pinctrl_unregister(pmx->pctl);
+
+       platform_set_drvdata(pdev, NULL);
+
+       kfree(sh_pfc_pmx->functions);
+       kfree(sh_pfc_pmx->pads);
+       kfree(sh_pfc_pmx);
+
+       return 0;
+}
+
+static struct platform_driver sh_pfc_pinctrl_driver = {
+       .probe          = sh_pfc_pinctrl_probe,
+       .remove         = __devexit_p(sh_pfc_pinctrl_remove),
+       .driver         = {
+               .name   = DRV_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static struct platform_device sh_pfc_pinctrl_device = {
+       .name           = DRV_NAME,
+       .id             = -1,
+};
+
+static int __init sh_pfc_pinctrl_init(void)
+{
+       int rc;
+
+       rc = platform_driver_register(&sh_pfc_pinctrl_driver);
+       if (likely(!rc)) {
+               rc = platform_device_register(&sh_pfc_pinctrl_device);
+               if (unlikely(rc))
+                       platform_driver_unregister(&sh_pfc_pinctrl_driver);
+       }
+
+       return rc;
+}
+
+static void __exit sh_pfc_pinctrl_exit(void)
+{
+       platform_driver_unregister(&sh_pfc_pinctrl_driver);
+}
+
+subsys_initcall(sh_pfc_pinctrl_init);
+module_exit(sh_pfc_pinctrl_exit);
index 972a94c58be3be01315af2f40aad90a067d4643d..646a7657fe62fbb545f95fc771b406d0cad6e5f9 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 #include <mach/dma.h>
 #include <plat/s3c64xx-spi.h>
 
+#define MAX_SPI_PORTS          3
+
 /* Registers and bit-fields */
 
 #define S3C64XX_SPI_CH_CFG             0x00
 #define S3C64XX_SPI_SLAVE_AUTO                 (1<<1)
 #define S3C64XX_SPI_SLAVE_SIG_INACT            (1<<0)
 
-#define S3C64XX_SPI_ACT(c) writel(0, (c)->regs + S3C64XX_SPI_SLAVE_SEL)
-
-#define S3C64XX_SPI_DEACT(c) writel(S3C64XX_SPI_SLAVE_SIG_INACT, \
-                                       (c)->regs + S3C64XX_SPI_SLAVE_SEL)
-
 #define S3C64XX_SPI_INT_TRAILING_EN            (1<<6)
 #define S3C64XX_SPI_INT_RX_OVERRUN_EN          (1<<5)
 #define S3C64XX_SPI_INT_RX_UNDERRUN_EN         (1<<4)
 
 #define S3C64XX_SPI_FBCLK_MSK          (3<<0)
 
-#define S3C64XX_SPI_ST_TRLCNTZ(v, i) ((((v) >> (i)->rx_lvl_offset) & \
-                                       (((i)->fifo_lvl_mask + 1))) \
-                                       ? 1 : 0)
-
-#define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & (1 << (i)->tx_st_done)) ? 1 : 0)
-#define TX_FIFO_LVL(v, i) (((v) >> 6) & (i)->fifo_lvl_mask)
-#define RX_FIFO_LVL(v, i) (((v) >> (i)->rx_lvl_offset) & (i)->fifo_lvl_mask)
+#define FIFO_LVL_MASK(i) ((i)->port_conf->fifo_lvl_mask[i->port_id])
+#define S3C64XX_SPI_ST_TX_DONE(v, i) (((v) & \
+                               (1 << (i)->port_conf->tx_st_done)) ? 1 : 0)
+#define TX_FIFO_LVL(v, i) (((v) >> 6) & FIFO_LVL_MASK(i))
+#define RX_FIFO_LVL(v, i) (((v) >> (i)->port_conf->rx_lvl_offset) & \
+                                       FIFO_LVL_MASK(i))
 
 #define S3C64XX_SPI_MAX_TRAILCNT       0x3ff
 #define S3C64XX_SPI_TRAILCNT_OFF       19
@@ -135,6 +134,29 @@ struct s3c64xx_spi_dma_data {
        unsigned                ch;
        enum dma_data_direction direction;
        enum dma_ch     dmach;
+       struct property         *dma_prop;
+};
+
+/**
+ * struct s3c64xx_spi_info - SPI Controller hardware info
+ * @fifo_lvl_mask: Bit-mask for {TX|RX}_FIFO_LVL bits in SPI_STATUS register.
+ * @rx_lvl_offset: Bit offset of RX_FIFO_LVL bits in SPI_STATUS regiter.
+ * @tx_st_done: Bit offset of TX_DONE bit in SPI_STATUS regiter.
+ * @high_speed: True, if the controller supports HIGH_SPEED_EN bit.
+ * @clk_from_cmu: True, if the controller does not include a clock mux and
+ *     prescaler unit.
+ *
+ * The Samsung s3c64xx SPI controller are used on various Samsung SoC's but
+ * differ in some aspects such as the size of the fifo and spi bus clock
+ * setup. Such differences are specified to the driver using this structure
+ * which is provided as driver data to the driver.
+ */
+struct s3c64xx_spi_port_config {
+       int     fifo_lvl_mask[MAX_SPI_PORTS];
+       int     rx_lvl_offset;
+       int     tx_st_done;
+       bool    high_speed;
+       bool    clk_from_cmu;
 };
 
 /**
@@ -175,6 +197,9 @@ struct s3c64xx_spi_driver_data {
        struct s3c64xx_spi_dma_data     rx_dma;
        struct s3c64xx_spi_dma_data     tx_dma;
        struct samsung_dma_ops          *ops;
+       struct s3c64xx_spi_port_config  *port_conf;
+       unsigned int                    port_id;
+       unsigned long                   gpios[4];
 };
 
 static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
@@ -183,7 +208,6 @@ static struct s3c2410_dma_client s3c64xx_spi_dma_client = {
 
 static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
 {
-       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        void __iomem *regs = sdd->regs;
        unsigned long loops;
        u32 val;
@@ -199,7 +223,7 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
        loops = msecs_to_loops(1);
        do {
                val = readl(regs + S3C64XX_SPI_STATUS);
-       } while (TX_FIFO_LVL(val, sci) && loops--);
+       } while (TX_FIFO_LVL(val, sdd) && loops--);
 
        if (loops == 0)
                dev_warn(&sdd->pdev->dev, "Timed out flushing TX FIFO\n");
@@ -208,7 +232,7 @@ static void flush_fifo(struct s3c64xx_spi_driver_data *sdd)
        loops = msecs_to_loops(1);
        do {
                val = readl(regs + S3C64XX_SPI_STATUS);
-               if (RX_FIFO_LVL(val, sci))
+               if (RX_FIFO_LVL(val, sdd))
                        readl(regs + S3C64XX_SPI_RX_DATA);
                else
                        break;
@@ -262,14 +286,24 @@ static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
                                        unsigned len, dma_addr_t buf)
 {
        struct s3c64xx_spi_driver_data *sdd;
-       struct samsung_dma_prep_info info;
+       struct samsung_dma_prep info;
+       struct samsung_dma_config config;
 
-       if (dma->direction == DMA_DEV_TO_MEM)
+       if (dma->direction == DMA_DEV_TO_MEM) {
                sdd = container_of((void *)dma,
                        struct s3c64xx_spi_driver_data, rx_dma);
-       else
+               config.direction = sdd->rx_dma.direction;
+               config.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
+               config.width = sdd->cur_bpw / 8;
+               sdd->ops->config(sdd->rx_dma.ch, &config);
+       } else {
                sdd = container_of((void *)dma,
                        struct s3c64xx_spi_driver_data, tx_dma);
+               config.direction =  sdd->tx_dma.direction;
+               config.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
+               config.width = sdd->cur_bpw / 8;
+               sdd->ops->config(sdd->tx_dma.ch, &config);
+       }
 
        info.cap = DMA_SLAVE;
        info.len = len;
@@ -284,20 +318,17 @@ static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
 
 static int acquire_dma(struct s3c64xx_spi_driver_data *sdd)
 {
-       struct samsung_dma_info info;
+       struct samsung_dma_req req;
 
        sdd->ops = samsung_dma_get_ops();
 
-       info.cap = DMA_SLAVE;
-       info.client = &s3c64xx_spi_dma_client;
-       info.width = sdd->cur_bpw / 8;
+       req.cap = DMA_SLAVE;
+       req.client = &s3c64xx_spi_dma_client;
 
-       info.direction = sdd->rx_dma.direction;
-       info.fifo = sdd->sfr_start + S3C64XX_SPI_RX_DATA;
-       sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &info);
-       info.direction =  sdd->tx_dma.direction;
-       info.fifo = sdd->sfr_start + S3C64XX_SPI_TX_DATA;
-       sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &info);
+       req.dt_dmach_prop = sdd->rx_dma.dma_prop;
+       sdd->rx_dma.ch = sdd->ops->request(sdd->rx_dma.dmach, &req);
+       req.dt_dmach_prop = sdd->tx_dma.dma_prop;
+       sdd->tx_dma.ch = sdd->ops->request(sdd->tx_dma.dmach, &req);
 
        return 1;
 }
@@ -306,7 +337,6 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
                                struct spi_device *spi,
                                struct spi_transfer *xfer, int dma_mode)
 {
-       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        void __iomem *regs = sdd->regs;
        u32 modecfg, chcfg;
 
@@ -356,7 +386,7 @@ static void enable_datapath(struct s3c64xx_spi_driver_data *sdd,
        if (xfer->rx_buf != NULL) {
                sdd->state |= RXBUSY;
 
-               if (sci->high_speed && sdd->cur_speed >= 30000000UL
+               if (sdd->port_conf->high_speed && sdd->cur_speed >= 30000000UL
                                        && !(sdd->cur_mode & SPI_CPHA))
                        chcfg |= S3C64XX_SPI_CH_HS_EN;
 
@@ -383,20 +413,19 @@ static inline void enable_cs(struct s3c64xx_spi_driver_data *sdd,
                if (sdd->tgl_spi != spi) { /* if last mssg on diff device */
                        /* Deselect the last toggled device */
                        cs = sdd->tgl_spi->controller_data;
-                       cs->set_level(cs->line,
-                                       spi->mode & SPI_CS_HIGH ? 0 : 1);
+                       gpio_set_value(cs->line,
+                               spi->mode & SPI_CS_HIGH ? 0 : 1);
                }
                sdd->tgl_spi = NULL;
        }
 
        cs = spi->controller_data;
-       cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0);
+       gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 1 : 0);
 }
 
 static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
                                struct spi_transfer *xfer, int dma_mode)
 {
-       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        void __iomem *regs = sdd->regs;
        unsigned long val;
        int ms;
@@ -413,7 +442,7 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
                val = msecs_to_loops(ms);
                do {
                        status = readl(regs + S3C64XX_SPI_STATUS);
-               } while (RX_FIFO_LVL(status, sci) < xfer->len && --val);
+               } while (RX_FIFO_LVL(status, sdd) < xfer->len && --val);
        }
 
        if (!val)
@@ -432,8 +461,8 @@ static int wait_for_xfer(struct s3c64xx_spi_driver_data *sdd,
                if (xfer->rx_buf == NULL) {
                        val = msecs_to_loops(10);
                        status = readl(regs + S3C64XX_SPI_STATUS);
-                       while ((TX_FIFO_LVL(status, sci)
-                               || !S3C64XX_SPI_ST_TX_DONE(status, sci))
+                       while ((TX_FIFO_LVL(status, sdd)
+                               || !S3C64XX_SPI_ST_TX_DONE(status, sdd))
                                        && --val) {
                                cpu_relax();
                                status = readl(regs + S3C64XX_SPI_STATUS);
@@ -477,17 +506,16 @@ static inline void disable_cs(struct s3c64xx_spi_driver_data *sdd,
        if (sdd->tgl_spi == spi)
                sdd->tgl_spi = NULL;
 
-       cs->set_level(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1);
+       gpio_set_value(cs->line, spi->mode & SPI_CS_HIGH ? 0 : 1);
 }
 
 static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 {
-       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        void __iomem *regs = sdd->regs;
        u32 val;
 
        /* Disable Clock */
-       if (sci->clk_from_cmu) {
+       if (sdd->port_conf->clk_from_cmu) {
                clk_disable(sdd->src_clk);
        } else {
                val = readl(regs + S3C64XX_SPI_CLK_CFG);
@@ -531,7 +559,7 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 
        writel(val, regs + S3C64XX_SPI_MODE_CFG);
 
-       if (sci->clk_from_cmu) {
+       if (sdd->port_conf->clk_from_cmu) {
                /* Configure Clock */
                /* There is half-multiplier before the SPI */
                clk_set_rate(sdd->src_clk, sdd->cur_speed * 2);
@@ -557,7 +585,6 @@ static void s3c64xx_spi_config(struct s3c64xx_spi_driver_data *sdd)
 static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
                                                struct spi_message *msg)
 {
-       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        struct device *dev = &sdd->pdev->dev;
        struct spi_transfer *xfer;
 
@@ -573,7 +600,7 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
        /* Map until end or first fail */
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 
-               if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+               if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1))
                        continue;
 
                if (xfer->tx_buf != NULL) {
@@ -607,7 +634,6 @@ static int s3c64xx_spi_map_mssg(struct s3c64xx_spi_driver_data *sdd,
 static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
                                                struct spi_message *msg)
 {
-       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        struct device *dev = &sdd->pdev->dev;
        struct spi_transfer *xfer;
 
@@ -616,7 +642,7 @@ static void s3c64xx_spi_unmap_mssg(struct s3c64xx_spi_driver_data *sdd,
 
        list_for_each_entry(xfer, &msg->transfers, transfer_list) {
 
-               if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+               if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1))
                        continue;
 
                if (xfer->rx_buf != NULL
@@ -635,7 +661,6 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
                                            struct spi_message *msg)
 {
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
-       struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
        struct spi_device *spi = msg->spi;
        struct s3c64xx_spi_csinfo *cs = spi->controller_data;
        struct spi_transfer *xfer;
@@ -690,7 +715,7 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
                }
 
                /* Polling method for xfers not bigger than FIFO capacity */
-               if (xfer->len <= ((sci->fifo_lvl_mask >> 1) + 1))
+               if (xfer->len <= ((FIFO_LVL_MASK(sdd) >> 1) + 1))
                        use_dma = 0;
                else
                        use_dma = 1;
@@ -707,14 +732,15 @@ static int s3c64xx_spi_transfer_one_message(struct spi_master *master,
                enable_cs(sdd, spi);
 
                /* Start the signals */
-               S3C64XX_SPI_ACT(sdd);
+               writel(0, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
 
                spin_unlock_irqrestore(&sdd->lock, flags);
 
                status = wait_for_xfer(sdd, xfer, use_dma);
 
                /* Quiese the signals */
-               S3C64XX_SPI_DEACT(sdd);
+               writel(S3C64XX_SPI_SLAVE_SIG_INACT,
+                      sdd->regs + S3C64XX_SPI_SLAVE_SEL);
 
                if (status) {
                        dev_err(&spi->dev, "I/O Error: "
@@ -795,6 +821,48 @@ static int s3c64xx_spi_unprepare_transfer(struct spi_master *spi)
        return 0;
 }
 
+static struct s3c64xx_spi_csinfo *s3c64xx_get_slave_ctrldata(
+                               struct s3c64xx_spi_driver_data *sdd,
+                               struct spi_device *spi)
+{
+       struct s3c64xx_spi_csinfo *cs;
+       struct device_node *slave_np, *data_np;
+       u32 fb_delay = 0;
+
+       slave_np = spi->dev.of_node;
+       if (!slave_np) {
+               dev_err(&spi->dev, "device node not found\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       for_each_child_of_node(slave_np, data_np)
+               if (!strcmp(data_np->name, "controller-data"))
+                       break;
+       if (!data_np) {
+               dev_err(&spi->dev, "child node 'controller-data' not found\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       cs = kzalloc(sizeof(*cs), GFP_KERNEL);
+       if (!cs) {
+               dev_err(&spi->dev, "could not allocate memory for controller"
+                                       " data\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       cs->line = of_get_named_gpio(data_np, "cs-gpio", 0);
+       if (!gpio_is_valid(cs->line)) {
+               dev_err(&spi->dev, "chip select gpio is not specified or "
+                                       "invalid\n");
+               kfree(cs);
+               return ERR_PTR(-EINVAL);
+       }
+
+       of_property_read_u32(data_np, "samsung,spi-feedback-delay", &fb_delay);
+       cs->fb_delay = fb_delay;
+       return cs;
+}
+
 /*
  * Here we only check the validity of requested configuration
  * and save the configuration in a local data-structure.
@@ -808,14 +876,31 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
        struct s3c64xx_spi_info *sci;
        struct spi_message *msg;
        unsigned long flags;
-       int err = 0;
+       int err;
 
-       if (cs == NULL || cs->set_level == NULL) {
+       sdd = spi_master_get_devdata(spi->master);
+       if (!cs && spi->dev.of_node) {
+               cs = s3c64xx_get_slave_ctrldata(sdd, spi);
+               spi->controller_data = cs;
+       }
+
+       if (IS_ERR_OR_NULL(cs)) {
                dev_err(&spi->dev, "No CS for SPI(%d)\n", spi->chip_select);
                return -ENODEV;
        }
 
-       sdd = spi_master_get_devdata(spi->master);
+       if (!spi_get_ctldata(spi)) {
+               err = gpio_request_one(cs->line, GPIOF_OUT_INIT_HIGH,
+                                      dev_name(&spi->dev));
+               if (err) {
+                       dev_err(&spi->dev,
+                               "Failed to get /CS gpio [%d]: %d\n",
+                               cs->line, err);
+                       goto err_gpio_req;
+               }
+               spi_set_ctldata(spi, cs);
+       }
+
        sci = sdd->cntrlr_info;
 
        spin_lock_irqsave(&sdd->lock, flags);
@@ -826,7 +911,8 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
                        dev_err(&spi->dev,
                                "setup: attempt while mssg in queue!\n");
                        spin_unlock_irqrestore(&sdd->lock, flags);
-                       return -EBUSY;
+                       err = -EBUSY;
+                       goto err_msgq;
                }
        }
 
@@ -844,7 +930,7 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
        pm_runtime_get_sync(&sdd->pdev->dev);
 
        /* Check if we can provide the requested rate */
-       if (!sci->clk_from_cmu) {
+       if (!sdd->port_conf->clk_from_cmu) {
                u32 psr, speed;
 
                /* Max possible */
@@ -869,22 +955,44 @@ static int s3c64xx_spi_setup(struct spi_device *spi)
                }
 
                speed = clk_get_rate(sdd->src_clk) / 2 / (psr + 1);
-               if (spi->max_speed_hz >= speed)
+               if (spi->max_speed_hz >= speed) {
                        spi->max_speed_hz = speed;
-               else
+               } else {
                        err = -EINVAL;
+                       goto setup_exit;
+               }
        }
 
        pm_runtime_put(&sdd->pdev->dev);
+       disable_cs(sdd, spi);
+       return 0;
 
 setup_exit:
-
        /* setup() returns with device de-selected */
        disable_cs(sdd, spi);
 
+err_msgq:
+       gpio_free(cs->line);
+       spi_set_ctldata(spi, NULL);
+
+err_gpio_req:
+       kfree(cs);
+
        return err;
 }
 
+static void s3c64xx_spi_cleanup(struct spi_device *spi)
+{
+       struct s3c64xx_spi_csinfo *cs = spi_get_ctldata(spi);
+
+       if (cs) {
+               gpio_free(cs->line);
+               if (spi->dev.of_node)
+                       kfree(cs);
+       }
+       spi_set_ctldata(spi, NULL);
+}
+
 static irqreturn_t s3c64xx_spi_irq(int irq, void *data)
 {
        struct s3c64xx_spi_driver_data *sdd = data;
@@ -920,12 +1028,12 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
 
        sdd->cur_speed = 0;
 
-       S3C64XX_SPI_DEACT(sdd);
+       writel(S3C64XX_SPI_SLAVE_SIG_INACT, sdd->regs + S3C64XX_SPI_SLAVE_SEL);
 
        /* Disable Interrupts - we use Polling if not DMA mode */
        writel(0, regs + S3C64XX_SPI_INT_EN);
 
-       if (!sci->clk_from_cmu)
+       if (!sdd->port_conf->clk_from_cmu)
                writel(sci->src_clk_nr << S3C64XX_SPI_CLKSEL_SRCSHFT,
                                regs + S3C64XX_SPI_CLK_CFG);
        writel(0, regs + S3C64XX_SPI_MODE_CFG);
@@ -946,40 +1054,165 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
        flush_fifo(sdd);
 }
 
-static int __init s3c64xx_spi_probe(struct platform_device *pdev)
+static int __devinit s3c64xx_spi_get_dmares(
+                       struct s3c64xx_spi_driver_data *sdd, bool tx)
+{
+       struct platform_device *pdev = sdd->pdev;
+       struct s3c64xx_spi_dma_data *dma_data;
+       struct property *prop;
+       struct resource *res;
+       char prop_name[15], *chan_str;
+
+       if (tx) {
+               dma_data = &sdd->tx_dma;
+               dma_data->direction = DMA_TO_DEVICE;
+               chan_str = "tx";
+       } else {
+               dma_data = &sdd->rx_dma;
+               dma_data->direction = DMA_FROM_DEVICE;
+               chan_str = "rx";
+       }
+
+       if (!sdd->pdev->dev.of_node) {
+               res = platform_get_resource(pdev, IORESOURCE_DMA, tx ? 0 : 1);
+               if (!res) {
+                       dev_err(&pdev->dev, "Unable to get SPI-%s dma "
+                                       "resource\n", chan_str);
+                       return -ENXIO;
+               }
+               dma_data->dmach = res->start;
+               return 0;
+       }
+
+       sprintf(prop_name, "%s-dma-channel", chan_str);
+       prop = of_find_property(pdev->dev.of_node, prop_name, NULL);
+       if (!prop) {
+               dev_err(&pdev->dev, "%s dma channel property not specified\n",
+                                       chan_str);
+               return -ENXIO;
+       }
+
+       dma_data->dmach = DMACH_DT_PROP;
+       dma_data->dma_prop = prop;
+       return 0;
+}
+
+#ifdef CONFIG_OF
+static int s3c64xx_spi_parse_dt_gpio(struct s3c64xx_spi_driver_data *sdd)
+{
+       struct device *dev = &sdd->pdev->dev;
+       int idx, gpio, ret;
+
+       /* find gpios for mosi, miso and clock lines */
+       for (idx = 0; idx < 3; idx++) {
+               gpio = of_get_gpio(dev->of_node, idx);
+               if (!gpio_is_valid(gpio)) {
+                       dev_err(dev, "invalid gpio[%d]: %d\n", idx, gpio);
+                       goto free_gpio;
+               }
+
+               ret = gpio_request(gpio, "spi-bus");
+               if (ret) {
+                       dev_err(dev, "gpio [%d] request failed: %d\n",
+                               gpio, ret);
+                       goto free_gpio;
+               }
+       }
+       return 0;
+
+free_gpio:
+       while (--idx >= 0)
+               gpio_free(sdd->gpios[idx]);
+       return -EINVAL;
+}
+
+static void s3c64xx_spi_dt_gpio_free(struct s3c64xx_spi_driver_data *sdd)
+{
+       unsigned int idx;
+       for (idx = 0; idx < 3; idx++)
+               gpio_free(sdd->gpios[idx]);
+}
+
+static struct __devinit s3c64xx_spi_info * s3c64xx_spi_parse_dt(
+                                               struct device *dev)
 {
-       struct resource *mem_res, *dmatx_res, *dmarx_res;
-       struct s3c64xx_spi_driver_data *sdd;
        struct s3c64xx_spi_info *sci;
-       struct spi_master *master;
-       int ret, irq;
-       char clk_name[16];
+       u32 temp;
 
-       if (pdev->id < 0) {
-               dev_err(&pdev->dev,
-                               "Invalid platform device id-%d\n", pdev->id);
-               return -ENODEV;
+       sci = devm_kzalloc(dev, sizeof(*sci), GFP_KERNEL);
+       if (!sci) {
+               dev_err(dev, "memory allocation for spi_info failed\n");
+               return ERR_PTR(-ENOMEM);
        }
 
-       if (pdev->dev.platform_data == NULL) {
-               dev_err(&pdev->dev, "platform_data missing!\n");
-               return -ENODEV;
+       if (of_property_read_u32(dev->of_node, "samsung,spi-src-clk", &temp)) {
+               dev_warn(dev, "spi bus clock parent not specified, using "
+                               "clock at index 0 as parent\n");
+               sci->src_clk_nr = 0;
+       } else {
+               sci->src_clk_nr = temp;
        }
 
-       sci = pdev->dev.platform_data;
+       if (of_property_read_u32(dev->of_node, "num-cs", &temp)) {
+               dev_warn(dev, "number of chip select lines not specified, "
+                               "assuming 1 chip select line\n");
+               sci->num_cs = 1;
+       } else {
+               sci->num_cs = temp;
+       }
+
+       return sci;
+}
+#else
+static struct s3c64xx_spi_info *s3c64xx_spi_parse_dt(struct device *dev)
+{
+       return dev->platform_data;
+}
+
+static int s3c64xx_spi_parse_dt_gpio(struct s3c64xx_spi_driver_data *sdd)
+{
+       return -EINVAL;
+}
+
+static void s3c64xx_spi_dt_gpio_free(struct s3c64xx_spi_driver_data *sdd)
+{
+}
+#endif
 
-       /* Check for availability of necessary resource */
+static const struct of_device_id s3c64xx_spi_dt_match[];
 
-       dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-       if (dmatx_res == NULL) {
-               dev_err(&pdev->dev, "Unable to get SPI-Tx dma resource\n");
-               return -ENXIO;
+static inline struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config(
+                                               struct platform_device *pdev)
+{
+#ifdef CONFIG_OF
+       if (pdev->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(s3c64xx_spi_dt_match, pdev->dev.of_node);
+               return (struct s3c64xx_spi_port_config *)match->data;
        }
+#endif
+       return (struct s3c64xx_spi_port_config *)
+                        platform_get_device_id(pdev)->driver_data;
+}
 
-       dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
-       if (dmarx_res == NULL) {
-               dev_err(&pdev->dev, "Unable to get SPI-Rx dma resource\n");
-               return -ENXIO;
+static int __init s3c64xx_spi_probe(struct platform_device *pdev)
+{
+       struct resource *mem_res;
+       struct s3c64xx_spi_driver_data *sdd;
+       struct s3c64xx_spi_info *sci = pdev->dev.platform_data;
+       struct spi_master *master;
+       int ret, irq;
+       char clk_name[16];
+
+       if (!sci && pdev->dev.of_node) {
+               sci = s3c64xx_spi_parse_dt(&pdev->dev);
+               if (IS_ERR(sci))
+                       return PTR_ERR(sci);
+       }
+
+       if (!sci) {
+               dev_err(&pdev->dev, "platform_data missing!\n");
+               return -ENODEV;
        }
 
        mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -1004,19 +1237,37 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, master);
 
        sdd = spi_master_get_devdata(master);
+       sdd->port_conf = s3c64xx_spi_get_port_config(pdev);
        sdd->master = master;
        sdd->cntrlr_info = sci;
        sdd->pdev = pdev;
        sdd->sfr_start = mem_res->start;
-       sdd->tx_dma.dmach = dmatx_res->start;
-       sdd->tx_dma.direction = DMA_MEM_TO_DEV;
-       sdd->rx_dma.dmach = dmarx_res->start;
-       sdd->rx_dma.direction = DMA_DEV_TO_MEM;
+       if (pdev->dev.of_node) {
+               ret = of_alias_get_id(pdev->dev.of_node, "spi");
+               if (ret < 0) {
+                       dev_err(&pdev->dev, "failed to get alias id, "
+                                               "errno %d\n", ret);
+                       goto err0;
+               }
+               sdd->port_id = ret;
+       } else {
+               sdd->port_id = pdev->id;
+       }
 
        sdd->cur_bpw = 8;
 
-       master->bus_num = pdev->id;
+       ret = s3c64xx_spi_get_dmares(sdd, true);
+       if (ret)
+               goto err0;
+
+       ret = s3c64xx_spi_get_dmares(sdd, false);
+       if (ret)
+               goto err0;
+
+       master->dev.of_node = pdev->dev.of_node;
+       master->bus_num = sdd->port_id;
        master->setup = s3c64xx_spi_setup;
+       master->cleanup = s3c64xx_spi_cleanup;
        master->prepare_transfer_hardware = s3c64xx_spi_prepare_transfer;
        master->transfer_one_message = s3c64xx_spi_transfer_one_message;
        master->unprepare_transfer_hardware = s3c64xx_spi_unprepare_transfer;
@@ -1025,21 +1276,17 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
        /* the spi->mode bits understood by this driver: */
        master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
-       if (request_mem_region(mem_res->start,
-                       resource_size(mem_res), pdev->name) == NULL) {
-               dev_err(&pdev->dev, "Req mem region failed\n");
-               ret = -ENXIO;
-               goto err0;
-       }
-
-       sdd->regs = ioremap(mem_res->start, resource_size(mem_res));
+       sdd->regs = devm_request_and_ioremap(&pdev->dev, mem_res);
        if (sdd->regs == NULL) {
                dev_err(&pdev->dev, "Unable to remap IO\n");
                ret = -ENXIO;
                goto err1;
        }
 
-       if (sci->cfg_gpio == NULL || sci->cfg_gpio(pdev)) {
+       if (!sci->cfg_gpio && pdev->dev.of_node) {
+               if (s3c64xx_spi_parse_dt_gpio(sdd))
+                       return -EBUSY;
+       } else if (sci->cfg_gpio == NULL || sci->cfg_gpio()) {
                dev_err(&pdev->dev, "Unable to config gpio\n");
                ret = -EBUSY;
                goto err2;
@@ -1075,7 +1322,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
        }
 
        /* Setup Deufult Mode */
-       s3c64xx_spi_hwinit(sdd, pdev->id);
+       s3c64xx_spi_hwinit(sdd, sdd->port_id);
 
        spin_lock_init(&sdd->lock);
        init_completion(&sdd->xfer_completion);
@@ -1100,7 +1347,7 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
 
        dev_dbg(&pdev->dev, "Samsung SoC SPI Driver loaded for Bus SPI-%d "
                                        "with %d Slaves attached\n",
-                                       pdev->id, master->num_chipselect);
+                                       sdd->port_id, master->num_chipselect);
        dev_dbg(&pdev->dev, "\tIOmem=[0x%x-0x%x]\tDMA=[Rx-%d, Tx-%d]\n",
                                        mem_res->end, mem_res->start,
                                        sdd->rx_dma.dmach, sdd->tx_dma.dmach);
@@ -1120,10 +1367,10 @@ err5:
 err4:
        clk_put(sdd->clk);
 err3:
+       if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node)
+               s3c64xx_spi_dt_gpio_free(sdd);
 err2:
-       iounmap((void *) sdd->regs);
 err1:
-       release_mem_region(mem_res->start, resource_size(mem_res));
 err0:
        platform_set_drvdata(pdev, NULL);
        spi_master_put(master);
@@ -1135,7 +1382,6 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
 {
        struct spi_master *master = spi_master_get(platform_get_drvdata(pdev));
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
-       struct resource *mem_res;
 
        pm_runtime_disable(&pdev->dev);
 
@@ -1151,11 +1397,8 @@ static int s3c64xx_spi_remove(struct platform_device *pdev)
        clk_disable(sdd->clk);
        clk_put(sdd->clk);
 
-       iounmap((void *) sdd->regs);
-
-       mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (mem_res != NULL)
-               release_mem_region(mem_res->start, resource_size(mem_res));
+       if (!sdd->cntrlr_info->cfg_gpio && pdev->dev.of_node)
+               s3c64xx_spi_dt_gpio_free(sdd);
 
        platform_set_drvdata(pdev, NULL);
        spi_master_put(master);
@@ -1175,6 +1418,9 @@ static int s3c64xx_spi_suspend(struct device *dev)
        clk_disable(sdd->src_clk);
        clk_disable(sdd->clk);
 
+       if (!sdd->cntrlr_info->cfg_gpio && dev->of_node)
+               s3c64xx_spi_dt_gpio_free(sdd);
+
        sdd->cur_speed = 0; /* Output Clock is stopped */
 
        return 0;
@@ -1182,18 +1428,20 @@ static int s3c64xx_spi_suspend(struct device *dev)
 
 static int s3c64xx_spi_resume(struct device *dev)
 {
-       struct platform_device *pdev = to_platform_device(dev);
        struct spi_master *master = spi_master_get(dev_get_drvdata(dev));
        struct s3c64xx_spi_driver_data *sdd = spi_master_get_devdata(master);
        struct s3c64xx_spi_info *sci = sdd->cntrlr_info;
 
-       sci->cfg_gpio(pdev);
+       if (!sci->cfg_gpio && dev->of_node)
+               s3c64xx_spi_parse_dt_gpio(sdd);
+       else
+               sci->cfg_gpio();
 
        /* Enable the clock */
        clk_enable(sdd->src_clk);
        clk_enable(sdd->clk);
 
-       s3c64xx_spi_hwinit(sdd, pdev->id);
+       s3c64xx_spi_hwinit(sdd, sdd->port_id);
 
        spi_master_resume(master);
 
@@ -1231,13 +1479,89 @@ static const struct dev_pm_ops s3c64xx_spi_pm = {
                           s3c64xx_spi_runtime_resume, NULL)
 };
 
+struct s3c64xx_spi_port_config s3c2443_spi_port_config = {
+       .fifo_lvl_mask  = { 0x7f },
+       .rx_lvl_offset  = 13,
+       .tx_st_done     = 21,
+       .high_speed     = true,
+};
+
+struct s3c64xx_spi_port_config s3c6410_spi_port_config = {
+       .fifo_lvl_mask  = { 0x7f, 0x7F },
+       .rx_lvl_offset  = 13,
+       .tx_st_done     = 21,
+};
+
+struct s3c64xx_spi_port_config s5p64x0_spi_port_config = {
+       .fifo_lvl_mask  = { 0x1ff, 0x7F },
+       .rx_lvl_offset  = 15,
+       .tx_st_done     = 25,
+};
+
+struct s3c64xx_spi_port_config s5pc100_spi_port_config = {
+       .fifo_lvl_mask  = { 0x7f, 0x7F },
+       .rx_lvl_offset  = 13,
+       .tx_st_done     = 21,
+       .high_speed     = true,
+};
+
+struct s3c64xx_spi_port_config s5pv210_spi_port_config = {
+       .fifo_lvl_mask  = { 0x1ff, 0x7F },
+       .rx_lvl_offset  = 15,
+       .tx_st_done     = 25,
+       .high_speed     = true,
+};
+
+struct s3c64xx_spi_port_config exynos4_spi_port_config = {
+       .fifo_lvl_mask  = { 0x1ff, 0x7F, 0x7F },
+       .rx_lvl_offset  = 15,
+       .tx_st_done     = 25,
+       .high_speed     = true,
+       .clk_from_cmu   = true,
+};
+
+static struct platform_device_id s3c64xx_spi_driver_ids[] = {
+       {
+               .name           = "s3c2443-spi",
+               .driver_data    = (kernel_ulong_t)&s3c2443_spi_port_config,
+       }, {
+               .name           = "s3c6410-spi",
+               .driver_data    = (kernel_ulong_t)&s3c6410_spi_port_config,
+       }, {
+               .name           = "s5p64x0-spi",
+               .driver_data    = (kernel_ulong_t)&s5p64x0_spi_port_config,
+       }, {
+               .name           = "s5pc100-spi",
+               .driver_data    = (kernel_ulong_t)&s5pc100_spi_port_config,
+       }, {
+               .name           = "s5pv210-spi",
+               .driver_data    = (kernel_ulong_t)&s5pv210_spi_port_config,
+       }, {
+               .name           = "exynos4210-spi",
+               .driver_data    = (kernel_ulong_t)&exynos4_spi_port_config,
+       },
+       { },
+};
+
+#ifdef CONFIG_OF
+static const struct of_device_id s3c64xx_spi_dt_match[] = {
+       { .compatible = "samsung,exynos4210-spi",
+                       .data = (void *)&exynos4_spi_port_config,
+       },
+       { },
+};
+MODULE_DEVICE_TABLE(of, s3c64xx_spi_dt_match);
+#endif /* CONFIG_OF */
+
 static struct platform_driver s3c64xx_spi_driver = {
        .driver = {
                .name   = "s3c64xx-spi",
                .owner = THIS_MODULE,
                .pm = &s3c64xx_spi_pm,
+               .of_match_table = of_match_ptr(s3c64xx_spi_dt_match),
        },
        .remove = s3c64xx_spi_remove,
+       .id_table = s3c64xx_spi_driver_ids,
 };
 MODULE_ALIAS("platform:s3c64xx-spi");
 
index ae6d78a3e9129a483ecf60ee5919dc4a685b3235..7f99ff3553a65fa1565aae949fd019d10762a452 100644 (file)
@@ -261,7 +261,7 @@ static void spi_tegra_start_transfer(struct spi_device *spi,
                clk_set_rate(tspi->clk, speed);
 
        if (tspi->cur_speed == 0)
-               clk_enable(tspi->clk);
+               clk_prepare_enable(tspi->clk);
 
        tspi->cur_speed = speed;
 
@@ -373,7 +373,7 @@ static void tegra_spi_rx_dma_complete(struct tegra_dma_req *req)
                        spi = m->state;
                        spi_tegra_start_message(spi, m);
                } else {
-                       clk_disable(tspi->clk);
+                       clk_disable_unprepare(tspi->clk);
                        tspi->cur_speed = 0;
                }
        }
index 3c60088871e0b137dbc0632c634fc86b6aabaf4f..9356886f489bcfd7e3939b4f0c7bf042ed0090d3 100644 (file)
@@ -675,7 +675,7 @@ static void tegra_init_i2c_slave(struct nvec_chip *nvec)
 {
        u32 val;
 
-       clk_enable(nvec->i2c_clk);
+       clk_prepare_enable(nvec->i2c_clk);
 
        tegra_periph_reset_assert(nvec->i2c_clk);
        udelay(2);
@@ -695,14 +695,14 @@ static void tegra_init_i2c_slave(struct nvec_chip *nvec)
 
        enable_irq(nvec->irq);
 
-       clk_disable(nvec->i2c_clk);
+       clk_disable_unprepare(nvec->i2c_clk);
 }
 
 static void nvec_disable_i2c_slave(struct nvec_chip *nvec)
 {
        disable_irq(nvec->irq);
        writel(I2C_SL_NEWSL | I2C_SL_NACK, nvec->base + I2C_SL_CNFG);
-       clk_disable(nvec->i2c_clk);
+       clk_disable_unprepare(nvec->i2c_clk);
 }
 
 static void nvec_power_off(void)
@@ -812,7 +812,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev)
 
        tegra_init_i2c_slave(nvec);
 
-       clk_enable(i2c_clk);
+       clk_prepare_enable(i2c_clk);
 
 
        /* enable event reporting */
index f238d574da0c80546700e0d96fffca42a9c20d51..2092a9167d2925e86c19a728ac7ce6131bf795ba 100644 (file)
@@ -25,8 +25,8 @@
 #include <linux/types.h>
 #include <drm/drmP.h>
 #include <drm/drm_crtc_helper.h>
+#include <linux/platform_data/omap_drm.h>
 #include "omap_drm.h"
-#include "omap_priv.h"
 
 #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
 #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt, ##__VA_ARGS__) /* verbose debug */
diff --git a/drivers/staging/omapdrm/omap_priv.h b/drivers/staging/omapdrm/omap_priv.h
deleted file mode 100644 (file)
index ef64414..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * include/drm/omap_priv.h
- *
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob@ti.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __OMAP_PRIV_H__
-#define __OMAP_PRIV_H__
-
-/* Non-userspace facing APIs
- */
-
-/* optional platform data to configure the default configuration of which
- * pipes/overlays/CRTCs are used.. if this is not provided, then instead the
- * first CONFIG_DRM_OMAP_NUM_CRTCS are used, and they are each connected to
- * one manager, with priority given to managers that are connected to
- * detected devices.  Remaining overlays are used as video planes.  This
- * should be a good default behavior for most cases, but yet there still
- * might be times when you wish to do something different.
- */
-struct omap_kms_platform_data {
-       /* overlays to use as CRTCs: */
-       int ovl_cnt;
-       const int *ovl_ids;
-
-       /* overlays to use as video planes: */
-       int pln_cnt;
-       const int *pln_ids;
-
-       int mgr_cnt;
-       const int *mgr_ids;
-
-       int dev_cnt;
-       const char **dev_names;
-};
-
-struct omap_drm_platform_data {
-       struct omap_kms_platform_data *kms_pdata;
-       struct omap_dmm_platform_data *dmm_pdata;
-};
-
-#endif /* __OMAP_DRM_H__ */
index 61648d84fbb6c8eb93c92f7a63a44971cf71415c..9fdcb561422ff844346598d0f3057bf8c3cff439 100644 (file)
@@ -9,7 +9,8 @@ target_core_mod-y               := target_core_configfs.o \
                                   target_core_tmr.o \
                                   target_core_tpg.o \
                                   target_core_transport.o \
-                                  target_core_cdb.o \
+                                  target_core_sbc.o \
+                                  target_core_spc.o \
                                   target_core_ua.o \
                                   target_core_rd.o \
                                   target_core_stat.o
index d57d10cb2e47525406daae44cb22c5c5a8e87937..97c0f78c3c9ca87232fceff82943d293a036d2e1 100644 (file)
@@ -429,19 +429,8 @@ int iscsit_reset_np_thread(
 
 int iscsit_del_np_comm(struct iscsi_np *np)
 {
-       if (!np->np_socket)
-               return 0;
-
-       /*
-        * Some network transports allocate their own struct sock->file,
-        * see  if we need to free any additional allocated resources.
-        */
-       if (np->np_flags & NPF_SCTP_STRUCT_FILE) {
-               kfree(np->np_socket->file);
-               np->np_socket->file = NULL;
-       }
-
-       sock_release(np->np_socket);
+       if (np->np_socket)
+               sock_release(np->np_socket);
        return 0;
 }
 
@@ -1413,8 +1402,10 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
                spin_unlock_bh(&cmd->istate_lock);
 
                iscsit_stop_dataout_timer(cmd);
-               return (!ooo_cmdsn) ? transport_generic_handle_data(
-                                       &cmd->se_cmd) : 0;
+               if (ooo_cmdsn)
+                       return 0;
+               target_execute_cmd(&cmd->se_cmd);
+               return 0;
        } else /* DATAOUT_CANNOT_RECOVER */
                return -1;
 
@@ -2683,7 +2674,7 @@ static int iscsit_send_logout_response(
                 */
                logout_conn = iscsit_get_conn_from_cid_rcfr(sess,
                                cmd->logout_cid);
-               if ((logout_conn)) {
+               if (logout_conn) {
                        iscsit_connection_reinstatement_rcfr(logout_conn);
                        iscsit_dec_conn_usage_count(logout_conn);
                }
@@ -4077,13 +4068,8 @@ int iscsit_close_connection(
        kfree(conn->conn_ops);
        conn->conn_ops = NULL;
 
-       if (conn->sock) {
-               if (conn->conn_flags & CONNFLAG_SCTP_STRUCT_FILE) {
-                       kfree(conn->sock->file);
-                       conn->sock->file = NULL;
-               }
+       if (conn->sock)
                sock_release(conn->sock);
-       }
        conn->thread_set = NULL;
 
        pr_debug("Moving to TARG_CONN_STATE_FREE.\n");
index 69dc8e35c03aa24c2b76ed930e4849a14cbea9ac..a7b25e783b58bedf4bceb927015e4642aafc5c63 100644 (file)
@@ -47,28 +47,6 @@ struct lio_target_configfs_attribute {
        ssize_t (*store)(void *, const char *, size_t);
 };
 
-struct iscsi_portal_group *lio_get_tpg_from_tpg_item(
-       struct config_item *item,
-       struct iscsi_tiqn **tiqn_out)
-{
-       struct se_portal_group *se_tpg = container_of(to_config_group(item),
-                                       struct se_portal_group, tpg_group);
-       struct iscsi_portal_group *tpg = se_tpg->se_tpg_fabric_ptr;
-       int ret;
-
-       if (!tpg) {
-               pr_err("Unable to locate struct iscsi_portal_group "
-                       "pointer\n");
-               return NULL;
-       }
-       ret = iscsit_get_tpg(tpg);
-       if (ret < 0)
-               return NULL;
-
-       *tiqn_out = tpg->tpg_tiqn;
-       return tpg;
-}
-
 /* Start items for lio_target_portal_cit */
 
 static ssize_t lio_target_np_show_sctp(
index 1c70144cdaf176c95ddc8082721dd165c9dbad69..8a908b28d8b2b1455b0cb4c0816131d418912ae8 100644 (file)
@@ -224,7 +224,6 @@ enum iscsi_timer_flags_table {
 /* Used for struct iscsi_np->np_flags */
 enum np_flags_table {
        NPF_IP_NETWORK          = 0x00,
-       NPF_SCTP_STRUCT_FILE    = 0x01 /* Bugfix */
 };
 
 /* Used for struct iscsi_np->np_thread_state */
@@ -481,6 +480,7 @@ struct iscsi_tmr_req {
        bool                    task_reassign:1;
        u32                     ref_cmd_sn;
        u32                     exp_data_sn;
+       struct iscsi_cmd        *ref_cmd;
        struct iscsi_conn_recovery *conn_recovery;
        struct se_tmr_req       *se_tmr_req;
 };
@@ -503,7 +503,6 @@ struct iscsi_conn {
        u16                     local_port;
        int                     net_size;
        u32                     auth_id;
-#define CONNFLAG_SCTP_STRUCT_FILE                      0x01
        u32                     conn_flags;
        /* Used for iscsi_tx_login_rsp() */
        u32                     login_itt;
index ecdd46deeddaf3d6d9aa9ca3acf5ad45274b2c67..3df8a2cef86faab090bcf24dfbc377cc00b32e04 100644 (file)
@@ -965,8 +965,8 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
                if (cmd->immediate_data) {
                        if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
                                spin_unlock_bh(&cmd->istate_lock);
-                               return transport_generic_handle_data(
-                                               &cmd->se_cmd);
+                               target_execute_cmd(&cmd->se_cmd);
+                               return 0;
                        }
                        spin_unlock_bh(&cmd->istate_lock);
 
index a3656c9903a1edffc95a7c0f11f8dee07396c51c..0694d9b1bce6a4e066a7bba1b1ef5f870b4b51d7 100644 (file)
@@ -518,7 +518,7 @@ int iscsi_login_post_auth_non_zero_tsih(
         * initiator and release the new connection.
         */
        conn_ptr = iscsit_get_conn_from_cid_rcfr(sess, cid);
-       if ((conn_ptr)) {
+       if (conn_ptr) {
                pr_err("Connection exists with CID %hu for %s,"
                        " performing connection reinstatement.\n",
                        conn_ptr->cid, sess->sess_ops->InitiatorName);
@@ -539,7 +539,7 @@ int iscsi_login_post_auth_non_zero_tsih(
        if (sess->sess_ops->ErrorRecoveryLevel == 2) {
                cr = iscsit_get_inactive_connection_recovery_entry(
                                sess, cid);
-               if ((cr)) {
+               if (cr) {
                        pr_debug("Performing implicit logout"
                                " for connection recovery on CID: %hu\n",
                                        conn->cid);
@@ -794,22 +794,6 @@ int iscsi_target_setup_login_socket(
                return ret;
        }
        np->np_socket = sock;
-       /*
-        * The SCTP stack needs struct socket->file.
-        */
-       if ((np->np_network_transport == ISCSI_SCTP_TCP) ||
-           (np->np_network_transport == ISCSI_SCTP_UDP)) {
-               if (!sock->file) {
-                       sock->file = kzalloc(sizeof(struct file), GFP_KERNEL);
-                       if (!sock->file) {
-                               pr_err("Unable to allocate struct"
-                                               " file for SCTP\n");
-                               ret = -ENOMEM;
-                               goto fail;
-                       }
-                       np->np_flags |= NPF_SCTP_STRUCT_FILE;
-               }
-       }
        /*
         * Setup the np->np_sockaddr from the passed sockaddr setup
         * in iscsi_target_configfs.c code..
@@ -869,21 +853,15 @@ int iscsi_target_setup_login_socket(
 
 fail:
        np->np_socket = NULL;
-       if (sock) {
-               if (np->np_flags & NPF_SCTP_STRUCT_FILE) {
-                       kfree(sock->file);
-                       sock->file = NULL;
-               }
-
+       if (sock)
                sock_release(sock);
-       }
        return ret;
 }
 
 static int __iscsi_target_login_thread(struct iscsi_np *np)
 {
        u8 buffer[ISCSI_HDR_LEN], iscsi_opcode, zero_tsih = 0;
-       int err, ret = 0, set_sctp_conn_flag, stop;
+       int err, ret = 0, stop;
        struct iscsi_conn *conn = NULL;
        struct iscsi_login *login;
        struct iscsi_portal_group *tpg = NULL;
@@ -894,7 +872,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
        struct sockaddr_in6 sock_in6;
 
        flush_signals(current);
-       set_sctp_conn_flag = 0;
        sock = np->np_socket;
 
        spin_lock_bh(&np->np_thread_lock);
@@ -917,35 +894,12 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
                spin_unlock_bh(&np->np_thread_lock);
                goto out;
        }
-       /*
-        * The SCTP stack needs struct socket->file.
-        */
-       if ((np->np_network_transport == ISCSI_SCTP_TCP) ||
-           (np->np_network_transport == ISCSI_SCTP_UDP)) {
-               if (!new_sock->file) {
-                       new_sock->file = kzalloc(
-                                       sizeof(struct file), GFP_KERNEL);
-                       if (!new_sock->file) {
-                               pr_err("Unable to allocate struct"
-                                               " file for SCTP\n");
-                               sock_release(new_sock);
-                               /* Get another socket */
-                               return 1;
-                       }
-                       set_sctp_conn_flag = 1;
-               }
-       }
-
        iscsi_start_login_thread_timer(np);
 
        conn = kzalloc(sizeof(struct iscsi_conn), GFP_KERNEL);
        if (!conn) {
                pr_err("Could not allocate memory for"
                        " new connection\n");
-               if (set_sctp_conn_flag) {
-                       kfree(new_sock->file);
-                       new_sock->file = NULL;
-               }
                sock_release(new_sock);
                /* Get another socket */
                return 1;
@@ -955,9 +909,6 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
        conn->conn_state = TARG_CONN_STATE_FREE;
        conn->sock = new_sock;
 
-       if (set_sctp_conn_flag)
-               conn->conn_flags |= CONNFLAG_SCTP_STRUCT_FILE;
-
        pr_debug("Moving to TARG_CONN_STATE_XPT_UP.\n");
        conn->conn_state = TARG_CONN_STATE_XPT_UP;
 
@@ -1081,7 +1032,7 @@ static int __iscsi_target_login_thread(struct iscsi_np *np)
                goto new_sess_out;
 
        zero_tsih = (pdu->tsih == 0x0000);
-       if ((zero_tsih)) {
+       if (zero_tsih) {
                /*
                 * This is the leading connection of a new session.
                 * We wait until after authentication to check for
@@ -1205,13 +1156,8 @@ old_sess_out:
                iscsi_release_param_list(conn->param_list);
                conn->param_list = NULL;
        }
-       if (conn->sock) {
-               if (conn->conn_flags & CONNFLAG_SCTP_STRUCT_FILE) {
-                       kfree(conn->sock->file);
-                       conn->sock->file = NULL;
-               }
+       if (conn->sock)
                sock_release(conn->sock);
-       }
        kfree(conn);
 
        if (tpg) {
index ed5241e7f12a1c0ced7f5c4c4c9ce30e1c4fd755..0c4760fabfc0f63f753d921ebb60ba2fe1ad3e18 100644 (file)
@@ -681,7 +681,7 @@ int iscsi_update_param_value(struct iscsi_param *param, char *value)
        param->value = kzalloc(strlen(value) + 1, GFP_KERNEL);
        if (!param->value) {
                pr_err("Unable to allocate memory for value.\n");
-               return -1;
+               return -ENOMEM;
        }
 
        memcpy(param->value, value, strlen(value));
index f4e640b51fd103bc8856b310456567d921dbfc0d..f62fe123d902cd78f0bdbee14337564559ec8ec9 100644 (file)
@@ -19,6 +19,7 @@
  ******************************************************************************/
 
 #include <asm/unaligned.h>
+#include <scsi/scsi_device.h>
 #include <scsi/iscsi_proto.h>
 #include <target/target_core_base.h>
 #include <target/target_core_fabric.h>
@@ -61,7 +62,7 @@ u8 iscsit_tmr_abort_task(
        }
 
        se_tmr->ref_task_tag            = hdr->rtt;
-       se_tmr->ref_cmd                 = &ref_cmd->se_cmd;
+       tmr_req->ref_cmd                = ref_cmd;
        tmr_req->ref_cmd_sn             = hdr->refcmdsn;
        tmr_req->exp_data_sn            = hdr->exp_datasn;
 
@@ -121,7 +122,7 @@ u8 iscsit_tmr_task_reassign(
        struct iscsi_tmr_req *tmr_req = cmd->tmr_req;
        struct se_tmr_req *se_tmr = cmd->se_cmd.se_tmr_req;
        struct iscsi_tm *hdr = (struct iscsi_tm *) buf;
-       int ret;
+       int ret, ref_lun;
 
        pr_debug("Got TASK_REASSIGN TMR ITT: 0x%08x,"
                " RefTaskTag: 0x%08x, ExpDataSN: 0x%08x, CID: %hu\n",
@@ -155,9 +156,16 @@ u8 iscsit_tmr_task_reassign(
                return ISCSI_TMF_RSP_REJECTED;
        }
 
+       ref_lun = scsilun_to_int(&hdr->lun);
+       if (ref_lun != ref_cmd->se_cmd.orig_fe_lun) {
+               pr_err("Unable to perform connection recovery for"
+                       " differing ref_lun: %d ref_cmd orig_fe_lun: %u\n",
+                       ref_lun, ref_cmd->se_cmd.orig_fe_lun);
+               return ISCSI_TMF_RSP_REJECTED;
+       }
+
        se_tmr->ref_task_tag            = hdr->rtt;
-       se_tmr->ref_cmd                 = &ref_cmd->se_cmd;
-       se_tmr->ref_task_lun            = get_unaligned_le64(&hdr->lun);
+       tmr_req->ref_cmd                = ref_cmd;
        tmr_req->ref_cmd_sn             = hdr->refcmdsn;
        tmr_req->exp_data_sn            = hdr->exp_datasn;
        tmr_req->conn_recovery          = cr;
@@ -191,9 +199,7 @@ static int iscsit_task_reassign_complete_nop_out(
        struct iscsi_tmr_req *tmr_req,
        struct iscsi_conn *conn)
 {
-       struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
-       struct se_cmd *se_cmd = se_tmr->ref_cmd;
-       struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+       struct iscsi_cmd *cmd = tmr_req->ref_cmd;
        struct iscsi_conn_recovery *cr;
 
        if (!cmd->cr) {
@@ -251,7 +257,8 @@ static int iscsit_task_reassign_complete_write(
                        pr_debug("WRITE ITT: 0x%08x: t_state: %d"
                                " never sent to transport\n",
                                cmd->init_task_tag, cmd->se_cmd.t_state);
-                       return transport_generic_handle_data(se_cmd);
+                       target_execute_cmd(se_cmd);
+                       return 0;
                }
 
                cmd->i_state = ISTATE_SEND_STATUS;
@@ -360,9 +367,7 @@ static int iscsit_task_reassign_complete_scsi_cmnd(
        struct iscsi_tmr_req *tmr_req,
        struct iscsi_conn *conn)
 {
-       struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
-       struct se_cmd *se_cmd = se_tmr->ref_cmd;
-       struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+       struct iscsi_cmd *cmd = tmr_req->ref_cmd;
        struct iscsi_conn_recovery *cr;
 
        if (!cmd->cr) {
@@ -385,7 +390,7 @@ static int iscsit_task_reassign_complete_scsi_cmnd(
        list_add_tail(&cmd->i_conn_node, &conn->conn_cmd_list);
        spin_unlock_bh(&conn->cmd_lock);
 
-       if (se_cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
+       if (cmd->se_cmd.se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
                cmd->i_state = ISTATE_SEND_STATUS;
                iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
                return 0;
@@ -411,17 +416,14 @@ static int iscsit_task_reassign_complete(
        struct iscsi_tmr_req *tmr_req,
        struct iscsi_conn *conn)
 {
-       struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
-       struct se_cmd *se_cmd;
        struct iscsi_cmd *cmd;
        int ret = 0;
 
-       if (!se_tmr->ref_cmd) {
+       if (!tmr_req->ref_cmd) {
                pr_err("TMR Request is missing a RefCmd struct iscsi_cmd.\n");
                return -1;
        }
-       se_cmd = se_tmr->ref_cmd;
-       cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+       cmd = tmr_req->ref_cmd;
 
        cmd->conn = conn;
 
@@ -547,9 +549,7 @@ int iscsit_task_reassign_prepare_write(
        struct iscsi_tmr_req *tmr_req,
        struct iscsi_conn *conn)
 {
-       struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
-       struct se_cmd *se_cmd = se_tmr->ref_cmd;
-       struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+       struct iscsi_cmd *cmd = tmr_req->ref_cmd;
        struct iscsi_pdu *pdu = NULL;
        struct iscsi_r2t *r2t = NULL, *r2t_tmp;
        int first_incomplete_r2t = 1, i = 0;
@@ -782,14 +782,12 @@ int iscsit_check_task_reassign_expdatasn(
        struct iscsi_tmr_req *tmr_req,
        struct iscsi_conn *conn)
 {
-       struct se_tmr_req *se_tmr = tmr_req->se_tmr_req;
-       struct se_cmd *se_cmd = se_tmr->ref_cmd;
-       struct iscsi_cmd *ref_cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
+       struct iscsi_cmd *ref_cmd = tmr_req->ref_cmd;
 
        if (ref_cmd->iscsi_opcode != ISCSI_OP_SCSI_CMD)
                return 0;
 
-       if (se_cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION)
+       if (ref_cmd->se_cmd.se_cmd_flags & SCF_SENT_CHECK_CONDITION)
                return 0;
 
        if (ref_cmd->data_direction == DMA_NONE)
index 879d8d0fa3feb38e061c911887e50a91a286c30f..a38a3f8ab0d9236598b3bb7f176443c19334e7de 100644 (file)
@@ -303,6 +303,7 @@ int iscsit_tpg_enable_portal_group(struct iscsi_portal_group *tpg)
 {
        struct iscsi_param *param;
        struct iscsi_tiqn *tiqn = tpg->tpg_tiqn;
+       int ret;
 
        spin_lock(&tpg->tpg_state_lock);
        if (tpg->tpg_state == TPG_STATE_ACTIVE) {
@@ -319,19 +320,19 @@ int iscsit_tpg_enable_portal_group(struct iscsi_portal_group *tpg)
        param = iscsi_find_param_from_key(AUTHMETHOD, tpg->param_list);
        if (!param) {
                spin_unlock(&tpg->tpg_state_lock);
-               return -ENOMEM;
+               return -EINVAL;
        }
 
        if (ISCSI_TPG_ATTRIB(tpg)->authentication) {
-               if (!strcmp(param->value, NONE))
-                       if (iscsi_update_param_value(param, CHAP) < 0) {
-                               spin_unlock(&tpg->tpg_state_lock);
-                               return -ENOMEM;
-                       }
-               if (iscsit_ta_authentication(tpg, 1) < 0) {
-                       spin_unlock(&tpg->tpg_state_lock);
-                       return -ENOMEM;
+               if (!strcmp(param->value, NONE)) {
+                       ret = iscsi_update_param_value(param, CHAP);
+                       if (ret)
+                               goto err;
                }
+
+               ret = iscsit_ta_authentication(tpg, 1);
+               if (ret < 0)
+                       goto err;
        }
 
        tpg->tpg_state = TPG_STATE_ACTIVE;
@@ -344,6 +345,10 @@ int iscsit_tpg_enable_portal_group(struct iscsi_portal_group *tpg)
        spin_unlock(&tiqn->tiqn_tpg_lock);
 
        return 0;
+
+err:
+       spin_unlock(&tpg->tpg_state_lock);
+       return ret;
 }
 
 int iscsit_tpg_disable_portal_group(struct iscsi_portal_group *tpg, int force)
@@ -558,7 +563,7 @@ int iscsit_ta_authentication(struct iscsi_portal_group *tpg, u32 authentication)
        if ((authentication != 1) && (authentication != 0)) {
                pr_err("Illegal value for authentication parameter:"
                        " %u, ignoring request.\n", authentication);
-               return -1;
+               return -EINVAL;
        }
 
        memset(buf1, 0, sizeof(buf1));
@@ -593,7 +598,7 @@ int iscsit_ta_authentication(struct iscsi_portal_group *tpg, u32 authentication)
        } else {
                snprintf(buf1, sizeof(buf1), "%s", param->value);
                none = strstr(buf1, NONE);
-               if ((none))
+               if (none)
                        goto out;
                strncat(buf1, ",", strlen(","));
                strncat(buf1, NONE, strlen(NONE));
index 38dfac2b0a1cf1ee91602ab896d4cb271d52195a..5491c632a15ed9073fb1b02efdf6b3ac095c57f8 100644 (file)
@@ -211,12 +211,11 @@ static void tcm_loop_submission_work(struct work_struct *work)
        /*
         * Because some userspace code via scsi-generic do not memset their
         * associated read buffers, go ahead and do that here for type
-        * SCF_SCSI_CONTROL_SG_IO_CDB.  Also note that this is currently
-        * guaranteed to be a single SGL for SCF_SCSI_CONTROL_SG_IO_CDB
-        * by target core in target_setup_cmd_from_cdb() ->
-        * transport_generic_cmd_sequencer().
+        * non-data CDBs.  Also note that this is currently guaranteed to be a
+        * single SGL for this case by target core in
+        * target_setup_cmd_from_cdb() -> transport_generic_cmd_sequencer().
         */
-       if (se_cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB &&
+       if (!(se_cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) &&
            se_cmd->data_direction == DMA_FROM_DEVICE) {
                struct scatterlist *sg = scsi_sglist(sc);
                unsigned char *buf = kmap(sg_page(sg)) + sg->offset;
@@ -779,7 +778,7 @@ static int tcm_loop_write_pending(struct se_cmd *se_cmd)
         * We now tell TCM to add this WRITE CDB directly into the TCM storage
         * object execution queue.
         */
-       transport_generic_process_write(se_cmd);
+       target_execute_cmd(se_cmd);
        return 0;
 }
 
index 7e6136e2ce81dc256babc191fab05953aabf6bfc..39ddba584b30e9d08950bd3143c257da20c80b55 100644 (file)
@@ -1219,28 +1219,14 @@ static void sbp_handle_command(struct sbp_target_request *req)
        ret = sbp_fetch_command(req);
        if (ret) {
                pr_debug("sbp_handle_command: fetch command failed: %d\n", ret);
-               req->status.status |= cpu_to_be32(
-                       STATUS_BLOCK_RESP(STATUS_RESP_TRANSPORT_FAILURE) |
-                       STATUS_BLOCK_DEAD(0) |
-                       STATUS_BLOCK_LEN(1) |
-                       STATUS_BLOCK_SBP_STATUS(SBP_STATUS_UNSPECIFIED_ERROR));
-               sbp_send_status(req);
-               sbp_free_request(req);
-               return;
+               goto err;
        }
 
        ret = sbp_fetch_page_table(req);
        if (ret) {
                pr_debug("sbp_handle_command: fetch page table failed: %d\n",
                        ret);
-               req->status.status |= cpu_to_be32(
-                       STATUS_BLOCK_RESP(STATUS_RESP_TRANSPORT_FAILURE) |
-                       STATUS_BLOCK_DEAD(0) |
-                       STATUS_BLOCK_LEN(1) |
-                       STATUS_BLOCK_SBP_STATUS(SBP_STATUS_UNSPECIFIED_ERROR));
-               sbp_send_status(req);
-               sbp_free_request(req);
-               return;
+               goto err;
        }
 
        unpacked_lun = req->login->lun->unpacked_lun;
@@ -1249,9 +1235,21 @@ static void sbp_handle_command(struct sbp_target_request *req)
        pr_debug("sbp_handle_command ORB:0x%llx unpacked_lun:%d data_len:%d data_dir:%d\n",
                        req->orb_pointer, unpacked_lun, data_length, data_dir);
 
-       target_submit_cmd(&req->se_cmd, sess->se_sess, req->cmd_buf,
-                       req->sense_buf, unpacked_lun, data_length,
-                       MSG_SIMPLE_TAG, data_dir, 0);
+       if (target_submit_cmd(&req->se_cmd, sess->se_sess, req->cmd_buf,
+                             req->sense_buf, unpacked_lun, data_length,
+                             MSG_SIMPLE_TAG, data_dir, 0))
+               goto err;
+
+       return;
+
+err:
+       req->status.status |= cpu_to_be32(
+               STATUS_BLOCK_RESP(STATUS_RESP_TRANSPORT_FAILURE) |
+               STATUS_BLOCK_DEAD(0) |
+               STATUS_BLOCK_LEN(1) |
+               STATUS_BLOCK_SBP_STATUS(SBP_STATUS_UNSPECIFIED_ERROR));
+       sbp_send_status(req);
+       sbp_free_request(req);
 }
 
 /*
@@ -1784,8 +1782,7 @@ static int sbp_write_pending(struct se_cmd *se_cmd)
                return ret;
        }
 
-       transport_generic_process_write(se_cmd);
-
+       target_execute_cmd(se_cmd);
        return 0;
 }
 
diff --git a/drivers/target/target_core_cdb.c b/drivers/target/target_core_cdb.c
deleted file mode 100644 (file)
index 664f6e7..0000000
+++ /dev/null
@@ -1,1130 +0,0 @@
-/*
- * CDB emulation for non-READ/WRITE commands.
- *
- * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc.
- * Copyright (c) 2005, 2006, 2007 SBE, Inc.
- * Copyright (c) 2007-2010 Rising Tide Systems
- * Copyright (c) 2008-2010 Linux-iSCSI.org
- *
- * Nicholas A. Bellinger <nab@kernel.org>
- *
- * 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/module.h>
-#include <asm/unaligned.h>
-#include <scsi/scsi.h>
-
-#include <target/target_core_base.h>
-#include <target/target_core_backend.h>
-#include <target/target_core_fabric.h>
-
-#include "target_core_internal.h"
-#include "target_core_ua.h"
-
-static void
-target_fill_alua_data(struct se_port *port, unsigned char *buf)
-{
-       struct t10_alua_tg_pt_gp *tg_pt_gp;
-       struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
-
-       /*
-        * Set SCCS for MAINTENANCE_IN + REPORT_TARGET_PORT_GROUPS.
-        */
-       buf[5]  = 0x80;
-
-       /*
-        * Set TPGS field for explict and/or implict ALUA access type
-        * and opteration.
-        *
-        * See spc4r17 section 6.4.2 Table 135
-        */
-       if (!port)
-               return;
-       tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
-       if (!tg_pt_gp_mem)
-               return;
-
-       spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
-       tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
-       if (tg_pt_gp)
-               buf[5] |= tg_pt_gp->tg_pt_gp_alua_access_type;
-       spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
-}
-
-static int
-target_emulate_inquiry_std(struct se_cmd *cmd, char *buf)
-{
-       struct se_lun *lun = cmd->se_lun;
-       struct se_device *dev = cmd->se_dev;
-
-       /* Set RMB (removable media) for tape devices */
-       if (dev->transport->get_device_type(dev) == TYPE_TAPE)
-               buf[1] = 0x80;
-
-       buf[2] = dev->transport->get_device_rev(dev);
-
-       /*
-        * NORMACA and HISUP = 0, RESPONSE DATA FORMAT = 2
-        *
-        * SPC4 says:
-        *   A RESPONSE DATA FORMAT field set to 2h indicates that the
-        *   standard INQUIRY data is in the format defined in this
-        *   standard. Response data format values less than 2h are
-        *   obsolete. Response data format values greater than 2h are
-        *   reserved.
-        */
-       buf[3] = 2;
-
-       /*
-        * Enable SCCS and TPGS fields for Emulated ALUA
-        */
-       if (dev->se_sub_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED)
-               target_fill_alua_data(lun->lun_sep, buf);
-
-       buf[7] = 0x2; /* CmdQue=1 */
-
-       snprintf(&buf[8], 8, "LIO-ORG");
-       snprintf(&buf[16], 16, "%s", dev->se_sub_dev->t10_wwn.model);
-       snprintf(&buf[32], 4, "%s", dev->se_sub_dev->t10_wwn.revision);
-       buf[4] = 31; /* Set additional length to 31 */
-
-       return 0;
-}
-
-/* unit serial number */
-static int
-target_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
-{
-       struct se_device *dev = cmd->se_dev;
-       u16 len = 0;
-
-       if (dev->se_sub_dev->su_dev_flags &
-                       SDF_EMULATED_VPD_UNIT_SERIAL) {
-               u32 unit_serial_len;
-
-               unit_serial_len = strlen(dev->se_sub_dev->t10_wwn.unit_serial);
-               unit_serial_len++; /* For NULL Terminator */
-
-               len += sprintf(&buf[4], "%s",
-                       dev->se_sub_dev->t10_wwn.unit_serial);
-               len++; /* Extra Byte for NULL Terminator */
-               buf[3] = len;
-       }
-       return 0;
-}
-
-static void
-target_parse_naa_6h_vendor_specific(struct se_device *dev, unsigned char *buf)
-{
-       unsigned char *p = &dev->se_sub_dev->t10_wwn.unit_serial[0];
-       int cnt;
-       bool next = true;
-
-       /*
-        * Generate up to 36 bits of VENDOR SPECIFIC IDENTIFIER starting on
-        * byte 3 bit 3-0 for NAA IEEE Registered Extended DESIGNATOR field
-        * format, followed by 64 bits of VENDOR SPECIFIC IDENTIFIER EXTENSION
-        * to complete the payload.  These are based from VPD=0x80 PRODUCT SERIAL
-        * NUMBER set via vpd_unit_serial in target_core_configfs.c to ensure
-        * per device uniqeness.
-        */
-       for (cnt = 0; *p && cnt < 13; p++) {
-               int val = hex_to_bin(*p);
-
-               if (val < 0)
-                       continue;
-
-               if (next) {
-                       next = false;
-                       buf[cnt++] |= val;
-               } else {
-                       next = true;
-                       buf[cnt] = val << 4;
-               }
-       }
-}
-
-/*
- * Device identification VPD, for a complete list of
- * DESIGNATOR TYPEs see spc4r17 Table 459.
- */
-static int
-target_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
-{
-       struct se_device *dev = cmd->se_dev;
-       struct se_lun *lun = cmd->se_lun;
-       struct se_port *port = NULL;
-       struct se_portal_group *tpg = NULL;
-       struct t10_alua_lu_gp_member *lu_gp_mem;
-       struct t10_alua_tg_pt_gp *tg_pt_gp;
-       struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
-       unsigned char *prod = &dev->se_sub_dev->t10_wwn.model[0];
-       u32 prod_len;
-       u32 unit_serial_len, off = 0;
-       u16 len = 0, id_len;
-
-       off = 4;
-
-       /*
-        * NAA IEEE Registered Extended Assigned designator format, see
-        * spc4r17 section 7.7.3.6.5
-        *
-        * We depend upon a target_core_mod/ConfigFS provided
-        * /sys/kernel/config/target/core/$HBA/$DEV/wwn/vpd_unit_serial
-        * value in order to return the NAA id.
-        */
-       if (!(dev->se_sub_dev->su_dev_flags & SDF_EMULATED_VPD_UNIT_SERIAL))
-               goto check_t10_vend_desc;
-
-       /* CODE SET == Binary */
-       buf[off++] = 0x1;
-
-       /* Set ASSOCIATION == addressed logical unit: 0)b */
-       buf[off] = 0x00;
-
-       /* Identifier/Designator type == NAA identifier */
-       buf[off++] |= 0x3;
-       off++;
-
-       /* Identifier/Designator length */
-       buf[off++] = 0x10;
-
-       /*
-        * Start NAA IEEE Registered Extended Identifier/Designator
-        */
-       buf[off++] = (0x6 << 4);
-
-       /*
-        * Use OpenFabrics IEEE Company ID: 00 14 05
-        */
-       buf[off++] = 0x01;
-       buf[off++] = 0x40;
-       buf[off] = (0x5 << 4);
-
-       /*
-        * Return ConfigFS Unit Serial Number information for
-        * VENDOR_SPECIFIC_IDENTIFIER and
-        * VENDOR_SPECIFIC_IDENTIFIER_EXTENTION
-        */
-       target_parse_naa_6h_vendor_specific(dev, &buf[off]);
-
-       len = 20;
-       off = (len + 4);
-
-check_t10_vend_desc:
-       /*
-        * T10 Vendor Identifier Page, see spc4r17 section 7.7.3.4
-        */
-       id_len = 8; /* For Vendor field */
-       prod_len = 4; /* For VPD Header */
-       prod_len += 8; /* For Vendor field */
-       prod_len += strlen(prod);
-       prod_len++; /* For : */
-
-       if (dev->se_sub_dev->su_dev_flags &
-                       SDF_EMULATED_VPD_UNIT_SERIAL) {
-               unit_serial_len =
-                       strlen(&dev->se_sub_dev->t10_wwn.unit_serial[0]);
-               unit_serial_len++; /* For NULL Terminator */
-
-               id_len += sprintf(&buf[off+12], "%s:%s", prod,
-                               &dev->se_sub_dev->t10_wwn.unit_serial[0]);
-       }
-       buf[off] = 0x2; /* ASCII */
-       buf[off+1] = 0x1; /* T10 Vendor ID */
-       buf[off+2] = 0x0;
-       memcpy(&buf[off+4], "LIO-ORG", 8);
-       /* Extra Byte for NULL Terminator */
-       id_len++;
-       /* Identifier Length */
-       buf[off+3] = id_len;
-       /* Header size for Designation descriptor */
-       len += (id_len + 4);
-       off += (id_len + 4);
-       /*
-        * struct se_port is only set for INQUIRY VPD=1 through $FABRIC_MOD
-        */
-       port = lun->lun_sep;
-       if (port) {
-               struct t10_alua_lu_gp *lu_gp;
-               u32 padding, scsi_name_len;
-               u16 lu_gp_id = 0;
-               u16 tg_pt_gp_id = 0;
-               u16 tpgt;
-
-               tpg = port->sep_tpg;
-               /*
-                * Relative target port identifer, see spc4r17
-                * section 7.7.3.7
-                *
-                * Get the PROTOCOL IDENTIFIER as defined by spc4r17
-                * section 7.5.1 Table 362
-                */
-               buf[off] =
-                       (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
-               buf[off++] |= 0x1; /* CODE SET == Binary */
-               buf[off] = 0x80; /* Set PIV=1 */
-               /* Set ASSOCIATION == target port: 01b */
-               buf[off] |= 0x10;
-               /* DESIGNATOR TYPE == Relative target port identifer */
-               buf[off++] |= 0x4;
-               off++; /* Skip over Reserved */
-               buf[off++] = 4; /* DESIGNATOR LENGTH */
-               /* Skip over Obsolete field in RTPI payload
-                * in Table 472 */
-               off += 2;
-               buf[off++] = ((port->sep_rtpi >> 8) & 0xff);
-               buf[off++] = (port->sep_rtpi & 0xff);
-               len += 8; /* Header size + Designation descriptor */
-               /*
-                * Target port group identifier, see spc4r17
-                * section 7.7.3.8
-                *
-                * Get the PROTOCOL IDENTIFIER as defined by spc4r17
-                * section 7.5.1 Table 362
-                */
-               if (dev->se_sub_dev->t10_alua.alua_type !=
-                               SPC3_ALUA_EMULATED)
-                       goto check_scsi_name;
-
-               tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
-               if (!tg_pt_gp_mem)
-                       goto check_lu_gp;
-
-               spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
-               tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
-               if (!tg_pt_gp) {
-                       spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
-                       goto check_lu_gp;
-               }
-               tg_pt_gp_id = tg_pt_gp->tg_pt_gp_id;
-               spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
-
-               buf[off] =
-                       (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
-               buf[off++] |= 0x1; /* CODE SET == Binary */
-               buf[off] = 0x80; /* Set PIV=1 */
-               /* Set ASSOCIATION == target port: 01b */
-               buf[off] |= 0x10;
-               /* DESIGNATOR TYPE == Target port group identifier */
-               buf[off++] |= 0x5;
-               off++; /* Skip over Reserved */
-               buf[off++] = 4; /* DESIGNATOR LENGTH */
-               off += 2; /* Skip over Reserved Field */
-               buf[off++] = ((tg_pt_gp_id >> 8) & 0xff);
-               buf[off++] = (tg_pt_gp_id & 0xff);
-               len += 8; /* Header size + Designation descriptor */
-               /*
-                * Logical Unit Group identifier, see spc4r17
-                * section 7.7.3.8
-                */
-check_lu_gp:
-               lu_gp_mem = dev->dev_alua_lu_gp_mem;
-               if (!lu_gp_mem)
-                       goto check_scsi_name;
-
-               spin_lock(&lu_gp_mem->lu_gp_mem_lock);
-               lu_gp = lu_gp_mem->lu_gp;
-               if (!lu_gp) {
-                       spin_unlock(&lu_gp_mem->lu_gp_mem_lock);
-                       goto check_scsi_name;
-               }
-               lu_gp_id = lu_gp->lu_gp_id;
-               spin_unlock(&lu_gp_mem->lu_gp_mem_lock);
-
-               buf[off++] |= 0x1; /* CODE SET == Binary */
-               /* DESIGNATOR TYPE == Logical Unit Group identifier */
-               buf[off++] |= 0x6;
-               off++; /* Skip over Reserved */
-               buf[off++] = 4; /* DESIGNATOR LENGTH */
-               off += 2; /* Skip over Reserved Field */
-               buf[off++] = ((lu_gp_id >> 8) & 0xff);
-               buf[off++] = (lu_gp_id & 0xff);
-               len += 8; /* Header size + Designation descriptor */
-               /*
-                * SCSI name string designator, see spc4r17
-                * section 7.7.3.11
-                *
-                * Get the PROTOCOL IDENTIFIER as defined by spc4r17
-                * section 7.5.1 Table 362
-                */
-check_scsi_name:
-               scsi_name_len = strlen(tpg->se_tpg_tfo->tpg_get_wwn(tpg));
-               /* UTF-8 ",t,0x<16-bit TPGT>" + NULL Terminator */
-               scsi_name_len += 10;
-               /* Check for 4-byte padding */
-               padding = ((-scsi_name_len) & 3);
-               if (padding != 0)
-                       scsi_name_len += padding;
-               /* Header size + Designation descriptor */
-               scsi_name_len += 4;
-
-               buf[off] =
-                       (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
-               buf[off++] |= 0x3; /* CODE SET == UTF-8 */
-               buf[off] = 0x80; /* Set PIV=1 */
-               /* Set ASSOCIATION == target port: 01b */
-               buf[off] |= 0x10;
-               /* DESIGNATOR TYPE == SCSI name string */
-               buf[off++] |= 0x8;
-               off += 2; /* Skip over Reserved and length */
-               /*
-                * SCSI name string identifer containing, $FABRIC_MOD
-                * dependent information.  For LIO-Target and iSCSI
-                * Target Port, this means "<iSCSI name>,t,0x<TPGT> in
-                * UTF-8 encoding.
-                */
-               tpgt = tpg->se_tpg_tfo->tpg_get_tag(tpg);
-               scsi_name_len = sprintf(&buf[off], "%s,t,0x%04x",
-                                       tpg->se_tpg_tfo->tpg_get_wwn(tpg), tpgt);
-               scsi_name_len += 1 /* Include  NULL terminator */;
-               /*
-                * The null-terminated, null-padded (see 4.4.2) SCSI
-                * NAME STRING field contains a UTF-8 format string.
-                * The number of bytes in the SCSI NAME STRING field
-                * (i.e., the value in the DESIGNATOR LENGTH field)
-                * shall be no larger than 256 and shall be a multiple
-                * of four.
-                */
-               if (padding)
-                       scsi_name_len += padding;
-
-               buf[off-1] = scsi_name_len;
-               off += scsi_name_len;
-               /* Header size + Designation descriptor */
-               len += (scsi_name_len + 4);
-       }
-       buf[2] = ((len >> 8) & 0xff);
-       buf[3] = (len & 0xff); /* Page Length for VPD 0x83 */
-       return 0;
-}
-
-/* Extended INQUIRY Data VPD Page */
-static int
-target_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
-{
-       buf[3] = 0x3c;
-       /* Set HEADSUP, ORDSUP, SIMPSUP */
-       buf[5] = 0x07;
-
-       /* If WriteCache emulation is enabled, set V_SUP */
-       if (cmd->se_dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0)
-               buf[6] = 0x01;
-       return 0;
-}
-
-/* Block Limits VPD page */
-static int
-target_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
-{
-       struct se_device *dev = cmd->se_dev;
-       u32 max_sectors;
-       int have_tp = 0;
-
-       /*
-        * Following sbc3r22 section 6.5.3 Block Limits VPD page, when
-        * emulate_tpu=1 or emulate_tpws=1 we will be expect a
-        * different page length for Thin Provisioning.
-        */
-       if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
-               have_tp = 1;
-
-       buf[0] = dev->transport->get_device_type(dev);
-       buf[3] = have_tp ? 0x3c : 0x10;
-
-       /* Set WSNZ to 1 */
-       buf[4] = 0x01;
-
-       /*
-        * Set OPTIMAL TRANSFER LENGTH GRANULARITY
-        */
-       put_unaligned_be16(1, &buf[6]);
-
-       /*
-        * Set MAXIMUM TRANSFER LENGTH
-        */
-       max_sectors = min(dev->se_sub_dev->se_dev_attrib.fabric_max_sectors,
-                         dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
-       put_unaligned_be32(max_sectors, &buf[8]);
-
-       /*
-        * Set OPTIMAL TRANSFER LENGTH
-        */
-       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.optimal_sectors, &buf[12]);
-
-       /*
-        * Exit now if we don't support TP.
-        */
-       if (!have_tp)
-               return 0;
-
-       /*
-        * Set MAXIMUM UNMAP LBA COUNT
-        */
-       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count, &buf[20]);
-
-       /*
-        * Set MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT
-        */
-       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count,
-                          &buf[24]);
-
-       /*
-        * Set OPTIMAL UNMAP GRANULARITY
-        */
-       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.unmap_granularity, &buf[28]);
-
-       /*
-        * UNMAP GRANULARITY ALIGNMENT
-        */
-       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment,
-                          &buf[32]);
-       if (dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment != 0)
-               buf[32] |= 0x80; /* Set the UGAVALID bit */
-
-       return 0;
-}
-
-/* Block Device Characteristics VPD page */
-static int
-target_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf)
-{
-       struct se_device *dev = cmd->se_dev;
-
-       buf[0] = dev->transport->get_device_type(dev);
-       buf[3] = 0x3c;
-       buf[5] = dev->se_sub_dev->se_dev_attrib.is_nonrot ? 1 : 0;
-
-       return 0;
-}
-
-/* Thin Provisioning VPD */
-static int
-target_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
-{
-       struct se_device *dev = cmd->se_dev;
-
-       /*
-        * From sbc3r22 section 6.5.4 Thin Provisioning VPD page:
-        *
-        * The PAGE LENGTH field is defined in SPC-4. If the DP bit is set to
-        * zero, then the page length shall be set to 0004h.  If the DP bit
-        * is set to one, then the page length shall be set to the value
-        * defined in table 162.
-        */
-       buf[0] = dev->transport->get_device_type(dev);
-
-       /*
-        * Set Hardcoded length mentioned above for DP=0
-        */
-       put_unaligned_be16(0x0004, &buf[2]);
-
-       /*
-        * The THRESHOLD EXPONENT field indicates the threshold set size in
-        * LBAs as a power of 2 (i.e., the threshold set size is equal to
-        * 2(threshold exponent)).
-        *
-        * Note that this is currently set to 0x00 as mkp says it will be
-        * changing again.  We can enable this once it has settled in T10
-        * and is actually used by Linux/SCSI ML code.
-        */
-       buf[4] = 0x00;
-
-       /*
-        * A TPU bit set to one indicates that the device server supports
-        * the UNMAP command (see 5.25). A TPU bit set to zero indicates
-        * that the device server does not support the UNMAP command.
-        */
-       if (dev->se_sub_dev->se_dev_attrib.emulate_tpu != 0)
-               buf[5] = 0x80;
-
-       /*
-        * A TPWS bit set to one indicates that the device server supports
-        * the use of the WRITE SAME (16) command (see 5.42) to unmap LBAs.
-        * A TPWS bit set to zero indicates that the device server does not
-        * support the use of the WRITE SAME (16) command to unmap LBAs.
-        */
-       if (dev->se_sub_dev->se_dev_attrib.emulate_tpws != 0)
-               buf[5] |= 0x40;
-
-       return 0;
-}
-
-static int
-target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf);
-
-static struct {
-       uint8_t         page;
-       int             (*emulate)(struct se_cmd *, unsigned char *);
-} evpd_handlers[] = {
-       { .page = 0x00, .emulate = target_emulate_evpd_00 },
-       { .page = 0x80, .emulate = target_emulate_evpd_80 },
-       { .page = 0x83, .emulate = target_emulate_evpd_83 },
-       { .page = 0x86, .emulate = target_emulate_evpd_86 },
-       { .page = 0xb0, .emulate = target_emulate_evpd_b0 },
-       { .page = 0xb1, .emulate = target_emulate_evpd_b1 },
-       { .page = 0xb2, .emulate = target_emulate_evpd_b2 },
-};
-
-/* supported vital product data pages */
-static int
-target_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
-{
-       int p;
-
-       /*
-        * Only report the INQUIRY EVPD=1 pages after a valid NAA
-        * Registered Extended LUN WWN has been set via ConfigFS
-        * during device creation/restart.
-        */
-       if (cmd->se_dev->se_sub_dev->su_dev_flags &
-                       SDF_EMULATED_VPD_UNIT_SERIAL) {
-               buf[3] = ARRAY_SIZE(evpd_handlers);
-               for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p)
-                       buf[p + 4] = evpd_handlers[p].page;
-       }
-
-       return 0;
-}
-
-int target_emulate_inquiry(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg;
-       unsigned char *buf, *map_buf;
-       unsigned char *cdb = cmd->t_task_cdb;
-       int p, ret;
-
-       map_buf = transport_kmap_data_sg(cmd);
-       /*
-        * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we
-        * know we actually allocated a full page.  Otherwise, if the
-        * data buffer is too small, allocate a temporary buffer so we
-        * don't have to worry about overruns in all our INQUIRY
-        * emulation handling.
-        */
-       if (cmd->data_length < SE_INQUIRY_BUF &&
-           (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) {
-               buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL);
-               if (!buf) {
-                       transport_kunmap_data_sg(cmd);
-                       cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
-                       return -ENOMEM;
-               }
-       } else {
-               buf = map_buf;
-       }
-
-       if (dev == tpg->tpg_virt_lun0.lun_se_dev)
-               buf[0] = 0x3f; /* Not connected */
-       else
-               buf[0] = dev->transport->get_device_type(dev);
-
-       if (!(cdb[1] & 0x1)) {
-               if (cdb[2]) {
-                       pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n",
-                              cdb[2]);
-                       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               ret = target_emulate_inquiry_std(cmd, buf);
-               goto out;
-       }
-
-       for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p) {
-               if (cdb[2] == evpd_handlers[p].page) {
-                       buf[1] = cdb[2];
-                       ret = evpd_handlers[p].emulate(cmd, buf);
-                       goto out;
-               }
-       }
-
-       pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]);
-       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-       ret = -EINVAL;
-
-out:
-       if (buf != map_buf) {
-               memcpy(map_buf, buf, cmd->data_length);
-               kfree(buf);
-       }
-       transport_kunmap_data_sg(cmd);
-
-       if (!ret)
-               target_complete_cmd(cmd, GOOD);
-       return ret;
-}
-
-int target_emulate_readcapacity(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       unsigned char *buf;
-       unsigned long long blocks_long = dev->transport->get_blocks(dev);
-       u32 blocks;
-
-       if (blocks_long >= 0x00000000ffffffff)
-               blocks = 0xffffffff;
-       else
-               blocks = (u32)blocks_long;
-
-       buf = transport_kmap_data_sg(cmd);
-
-       buf[0] = (blocks >> 24) & 0xff;
-       buf[1] = (blocks >> 16) & 0xff;
-       buf[2] = (blocks >> 8) & 0xff;
-       buf[3] = blocks & 0xff;
-       buf[4] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff;
-       buf[5] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff;
-       buf[6] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
-       buf[7] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
-
-       transport_kunmap_data_sg(cmd);
-
-       target_complete_cmd(cmd, GOOD);
-       return 0;
-}
-
-int target_emulate_readcapacity_16(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       unsigned char *buf;
-       unsigned long long blocks = dev->transport->get_blocks(dev);
-
-       buf = transport_kmap_data_sg(cmd);
-
-       buf[0] = (blocks >> 56) & 0xff;
-       buf[1] = (blocks >> 48) & 0xff;
-       buf[2] = (blocks >> 40) & 0xff;
-       buf[3] = (blocks >> 32) & 0xff;
-       buf[4] = (blocks >> 24) & 0xff;
-       buf[5] = (blocks >> 16) & 0xff;
-       buf[6] = (blocks >> 8) & 0xff;
-       buf[7] = blocks & 0xff;
-       buf[8] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff;
-       buf[9] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff;
-       buf[10] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
-       buf[11] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
-       /*
-        * Set Thin Provisioning Enable bit following sbc3r22 in section
-        * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled.
-        */
-       if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
-               buf[14] = 0x80;
-
-       transport_kunmap_data_sg(cmd);
-
-       target_complete_cmd(cmd, GOOD);
-       return 0;
-}
-
-static int
-target_modesense_rwrecovery(unsigned char *p)
-{
-       p[0] = 0x01;
-       p[1] = 0x0a;
-
-       return 12;
-}
-
-static int
-target_modesense_control(struct se_device *dev, unsigned char *p)
-{
-       p[0] = 0x0a;
-       p[1] = 0x0a;
-       p[2] = 2;
-       /*
-        * From spc4r23, 7.4.7 Control mode page
-        *
-        * The QUEUE ALGORITHM MODIFIER field (see table 368) specifies
-        * restrictions on the algorithm used for reordering commands
-        * having the SIMPLE task attribute (see SAM-4).
-        *
-        *                    Table 368 -- QUEUE ALGORITHM MODIFIER field
-        *                         Code      Description
-        *                          0h       Restricted reordering
-        *                          1h       Unrestricted reordering allowed
-        *                          2h to 7h    Reserved
-        *                          8h to Fh    Vendor specific
-        *
-        * A value of zero in the QUEUE ALGORITHM MODIFIER field specifies that
-        * the device server shall order the processing sequence of commands
-        * having the SIMPLE task attribute such that data integrity is maintained
-        * for that I_T nexus (i.e., if the transmission of new SCSI transport protocol
-        * requests is halted at any time, the final value of all data observable
-        * on the medium shall be the same as if all the commands had been processed
-        * with the ORDERED task attribute).
-        *
-        * A value of one in the QUEUE ALGORITHM MODIFIER field specifies that the
-        * device server may reorder the processing sequence of commands having the
-        * SIMPLE task attribute in any manner. Any data integrity exposures related to
-        * command sequence order shall be explicitly handled by the application client
-        * through the selection of appropriate ommands and task attributes.
-        */
-       p[3] = (dev->se_sub_dev->se_dev_attrib.emulate_rest_reord == 1) ? 0x00 : 0x10;
-       /*
-        * From spc4r17, section 7.4.6 Control mode Page
-        *
-        * Unit Attention interlocks control (UN_INTLCK_CTRL) to code 00b
-        *
-        * 00b: The logical unit shall clear any unit attention condition
-        * reported in the same I_T_L_Q nexus transaction as a CHECK CONDITION
-        * status and shall not establish a unit attention condition when a com-
-        * mand is completed with BUSY, TASK SET FULL, or RESERVATION CONFLICT
-        * status.
-        *
-        * 10b: The logical unit shall not clear any unit attention condition
-        * reported in the same I_T_L_Q nexus transaction as a CHECK CONDITION
-        * status and shall not establish a unit attention condition when
-        * a command is completed with BUSY, TASK SET FULL, or RESERVATION
-        * CONFLICT status.
-        *
-        * 11b a The logical unit shall not clear any unit attention condition
-        * reported in the same I_T_L_Q nexus transaction as a CHECK CONDITION
-        * status and shall establish a unit attention condition for the
-        * initiator port associated with the I_T nexus on which the BUSY,
-        * TASK SET FULL, or RESERVATION CONFLICT status is being returned.
-        * Depending on the status, the additional sense code shall be set to
-        * PREVIOUS BUSY STATUS, PREVIOUS TASK SET FULL STATUS, or PREVIOUS
-        * RESERVATION CONFLICT STATUS. Until it is cleared by a REQUEST SENSE
-        * command, a unit attention condition shall be established only once
-        * for a BUSY, TASK SET FULL, or RESERVATION CONFLICT status regardless
-        * to the number of commands completed with one of those status codes.
-        */
-       p[4] = (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 2) ? 0x30 :
-              (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00;
-       /*
-        * From spc4r17, section 7.4.6 Control mode Page
-        *
-        * Task Aborted Status (TAS) bit set to zero.
-        *
-        * A task aborted status (TAS) bit set to zero specifies that aborted
-        * tasks shall be terminated by the device server without any response
-        * to the application client. A TAS bit set to one specifies that tasks
-        * aborted by the actions of an I_T nexus other than the I_T nexus on
-        * which the command was received shall be completed with TASK ABORTED
-        * status (see SAM-4).
-        */
-       p[5] = (dev->se_sub_dev->se_dev_attrib.emulate_tas) ? 0x40 : 0x00;
-       p[8] = 0xff;
-       p[9] = 0xff;
-       p[11] = 30;
-
-       return 12;
-}
-
-static int
-target_modesense_caching(struct se_device *dev, unsigned char *p)
-{
-       p[0] = 0x08;
-       p[1] = 0x12;
-       if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0)
-               p[2] = 0x04; /* Write Cache Enable */
-       p[12] = 0x20; /* Disabled Read Ahead */
-
-       return 20;
-}
-
-static void
-target_modesense_write_protect(unsigned char *buf, int type)
-{
-       /*
-        * I believe that the WP bit (bit 7) in the mode header is the same for
-        * all device types..
-        */
-       switch (type) {
-       case TYPE_DISK:
-       case TYPE_TAPE:
-       default:
-               buf[0] |= 0x80; /* WP bit */
-               break;
-       }
-}
-
-static void
-target_modesense_dpofua(unsigned char *buf, int type)
-{
-       switch (type) {
-       case TYPE_DISK:
-               buf[0] |= 0x10; /* DPOFUA bit */
-               break;
-       default:
-               break;
-       }
-}
-
-int target_emulate_modesense(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       char *cdb = cmd->t_task_cdb;
-       unsigned char *rbuf;
-       int type = dev->transport->get_device_type(dev);
-       int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10);
-       int offset = ten ? 8 : 4;
-       int length = 0;
-       unsigned char buf[SE_MODE_PAGE_BUF];
-
-       memset(buf, 0, SE_MODE_PAGE_BUF);
-
-       switch (cdb[2] & 0x3f) {
-       case 0x01:
-               length = target_modesense_rwrecovery(&buf[offset]);
-               break;
-       case 0x08:
-               length = target_modesense_caching(dev, &buf[offset]);
-               break;
-       case 0x0a:
-               length = target_modesense_control(dev, &buf[offset]);
-               break;
-       case 0x3f:
-               length = target_modesense_rwrecovery(&buf[offset]);
-               length += target_modesense_caching(dev, &buf[offset+length]);
-               length += target_modesense_control(dev, &buf[offset+length]);
-               break;
-       default:
-               pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n",
-                      cdb[2] & 0x3f, cdb[3]);
-               cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE;
-               return -EINVAL;
-       }
-       offset += length;
-
-       if (ten) {
-               offset -= 2;
-               buf[0] = (offset >> 8) & 0xff;
-               buf[1] = offset & 0xff;
-
-               if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
-                   (cmd->se_deve &&
-                   (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
-                       target_modesense_write_protect(&buf[3], type);
-
-               if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
-                   (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
-                       target_modesense_dpofua(&buf[3], type);
-
-               if ((offset + 2) > cmd->data_length)
-                       offset = cmd->data_length;
-
-       } else {
-               offset -= 1;
-               buf[0] = offset & 0xff;
-
-               if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
-                   (cmd->se_deve &&
-                   (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
-                       target_modesense_write_protect(&buf[2], type);
-
-               if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
-                   (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
-                       target_modesense_dpofua(&buf[2], type);
-
-               if ((offset + 1) > cmd->data_length)
-                       offset = cmd->data_length;
-       }
-
-       rbuf = transport_kmap_data_sg(cmd);
-       memcpy(rbuf, buf, offset);
-       transport_kunmap_data_sg(cmd);
-
-       target_complete_cmd(cmd, GOOD);
-       return 0;
-}
-
-int target_emulate_request_sense(struct se_cmd *cmd)
-{
-       unsigned char *cdb = cmd->t_task_cdb;
-       unsigned char *buf;
-       u8 ua_asc = 0, ua_ascq = 0;
-       int err = 0;
-
-       if (cdb[1] & 0x01) {
-               pr_err("REQUEST_SENSE description emulation not"
-                       " supported\n");
-               cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-               return -ENOSYS;
-       }
-
-       buf = transport_kmap_data_sg(cmd);
-
-       if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
-               /*
-                * CURRENT ERROR, UNIT ATTENTION
-                */
-               buf[0] = 0x70;
-               buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
-
-               if (cmd->data_length < 18) {
-                       buf[7] = 0x00;
-                       err = -EINVAL;
-                       goto end;
-               }
-               /*
-                * The Additional Sense Code (ASC) from the UNIT ATTENTION
-                */
-               buf[SPC_ASC_KEY_OFFSET] = ua_asc;
-               buf[SPC_ASCQ_KEY_OFFSET] = ua_ascq;
-               buf[7] = 0x0A;
-       } else {
-               /*
-                * CURRENT ERROR, NO SENSE
-                */
-               buf[0] = 0x70;
-               buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE;
-
-               if (cmd->data_length < 18) {
-                       buf[7] = 0x00;
-                       err = -EINVAL;
-                       goto end;
-               }
-               /*
-                * NO ADDITIONAL SENSE INFORMATION
-                */
-               buf[SPC_ASC_KEY_OFFSET] = 0x00;
-               buf[7] = 0x0A;
-       }
-
-end:
-       transport_kunmap_data_sg(cmd);
-       target_complete_cmd(cmd, GOOD);
-       return 0;
-}
-
-/*
- * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support.
- * Note this is not used for TCM/pSCSI passthrough
- */
-int target_emulate_unmap(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       unsigned char *buf, *ptr = NULL;
-       unsigned char *cdb = &cmd->t_task_cdb[0];
-       sector_t lba;
-       unsigned int size = cmd->data_length, range;
-       int ret = 0, offset;
-       unsigned short dl, bd_dl;
-
-       if (!dev->transport->do_discard) {
-               pr_err("UNMAP emulation not supported for: %s\n",
-                               dev->transport->name);
-               cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-               return -ENOSYS;
-       }
-
-       /* First UNMAP block descriptor starts at 8 byte offset */
-       offset = 8;
-       size -= 8;
-       dl = get_unaligned_be16(&cdb[0]);
-       bd_dl = get_unaligned_be16(&cdb[2]);
-
-       buf = transport_kmap_data_sg(cmd);
-
-       ptr = &buf[offset];
-       pr_debug("UNMAP: Sub: %s Using dl: %hu bd_dl: %hu size: %hu"
-               " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr);
-
-       while (size) {
-               lba = get_unaligned_be64(&ptr[0]);
-               range = get_unaligned_be32(&ptr[8]);
-               pr_debug("UNMAP: Using lba: %llu and range: %u\n",
-                                (unsigned long long)lba, range);
-
-               ret = dev->transport->do_discard(dev, lba, range);
-               if (ret < 0) {
-                       pr_err("blkdev_issue_discard() failed: %d\n",
-                                       ret);
-                       goto err;
-               }
-
-               ptr += 16;
-               size -= 16;
-       }
-
-err:
-       transport_kunmap_data_sg(cmd);
-       if (!ret)
-               target_complete_cmd(cmd, GOOD);
-       return ret;
-}
-
-/*
- * Used for TCM/IBLOCK and TCM/FILEIO for block/blk-lib.c level discard support.
- * Note this is not used for TCM/pSCSI passthrough
- */
-int target_emulate_write_same(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       sector_t range;
-       sector_t lba = cmd->t_task_lba;
-       u32 num_blocks;
-       int ret;
-
-       if (!dev->transport->do_discard) {
-               pr_err("WRITE_SAME emulation not supported"
-                               " for: %s\n", dev->transport->name);
-               cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-               return -ENOSYS;
-       }
-
-       if (cmd->t_task_cdb[0] == WRITE_SAME)
-               num_blocks = get_unaligned_be16(&cmd->t_task_cdb[7]);
-       else if (cmd->t_task_cdb[0] == WRITE_SAME_16)
-               num_blocks = get_unaligned_be32(&cmd->t_task_cdb[10]);
-       else /* WRITE_SAME_32 via VARIABLE_LENGTH_CMD */
-               num_blocks = get_unaligned_be32(&cmd->t_task_cdb[28]);
-
-       /*
-        * Use the explicit range when non zero is supplied, otherwise calculate
-        * the remaining range based on ->get_blocks() - starting LBA.
-        */
-       if (num_blocks != 0)
-               range = num_blocks;
-       else
-               range = (dev->transport->get_blocks(dev) - lba) + 1;
-
-       pr_debug("WRITE_SAME UNMAP: LBA: %llu Range: %llu\n",
-                (unsigned long long)lba, (unsigned long long)range);
-
-       ret = dev->transport->do_discard(dev, lba, range);
-       if (ret < 0) {
-               pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n");
-               return ret;
-       }
-
-       target_complete_cmd(cmd, GOOD);
-       return 0;
-}
-
-int target_emulate_synchronize_cache(struct se_cmd *cmd)
-{
-       if (!cmd->se_dev->transport->do_sync_cache) {
-               pr_err("SYNCHRONIZE_CACHE emulation not supported"
-                       " for: %s\n", cmd->se_dev->transport->name);
-               cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-               return -ENOSYS;
-       }
-
-       cmd->se_dev->transport->do_sync_cache(cmd);
-       return 0;
-}
-
-int target_emulate_noop(struct se_cmd *cmd)
-{
-       target_complete_cmd(cmd, GOOD);
-       return 0;
-}
index 5ad972856a8d58ccb25b763a07239a39a12a57ed..cf2c66f3c11690c81ca23e9fd2ce286e76b56e62 100644 (file)
@@ -300,8 +300,8 @@ int core_free_device_list_for_node(
                lun = deve->se_lun;
 
                spin_unlock_irq(&nacl->device_list_lock);
-               core_update_device_list_for_node(lun, NULL, deve->mapped_lun,
-                       TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg, 0);
+               core_disable_device_list_for_node(lun, NULL, deve->mapped_lun,
+                       TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg);
                spin_lock_irq(&nacl->device_list_lock);
        }
        spin_unlock_irq(&nacl->device_list_lock);
@@ -342,72 +342,46 @@ void core_update_device_list_access(
        spin_unlock_irq(&nacl->device_list_lock);
 }
 
-/*      core_update_device_list_for_node():
+/*      core_enable_device_list_for_node():
  *
  *
  */
-int core_update_device_list_for_node(
+int core_enable_device_list_for_node(
        struct se_lun *lun,
        struct se_lun_acl *lun_acl,
        u32 mapped_lun,
        u32 lun_access,
        struct se_node_acl *nacl,
-       struct se_portal_group *tpg,
-       int enable)
+       struct se_portal_group *tpg)
 {
        struct se_port *port = lun->lun_sep;
-       struct se_dev_entry *deve = nacl->device_list[mapped_lun];
-       int trans = 0;
-       /*
-        * If the MappedLUN entry is being disabled, the entry in
-        * port->sep_alua_list must be removed now before clearing the
-        * struct se_dev_entry pointers below as logic in
-        * core_alua_do_transition_tg_pt() depends on these being present.
-        */
-       if (!enable) {
-               /*
-                * deve->se_lun_acl will be NULL for demo-mode created LUNs
-                * that have not been explicitly concerted to MappedLUNs ->
-                * struct se_lun_acl, but we remove deve->alua_port_list from
-                * port->sep_alua_list. This also means that active UAs and
-                * NodeACL context specific PR metadata for demo-mode
-                * MappedLUN *deve will be released below..
-                */
-               spin_lock_bh(&port->sep_alua_lock);
-               list_del(&deve->alua_port_list);
-               spin_unlock_bh(&port->sep_alua_lock);
-       }
+       struct se_dev_entry *deve;
 
        spin_lock_irq(&nacl->device_list_lock);
-       if (enable) {
-               /*
-                * Check if the call is handling demo mode -> explict LUN ACL
-                * transition.  This transition must be for the same struct se_lun
-                * + mapped_lun that was setup in demo mode..
-                */
-               if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
-                       if (deve->se_lun_acl != NULL) {
-                               pr_err("struct se_dev_entry->se_lun_acl"
-                                       " already set for demo mode -> explict"
-                                       " LUN ACL transition\n");
-                               spin_unlock_irq(&nacl->device_list_lock);
-                               return -EINVAL;
-                       }
-                       if (deve->se_lun != lun) {
-                               pr_err("struct se_dev_entry->se_lun does"
-                                       " match passed struct se_lun for demo mode"
-                                       " -> explict LUN ACL transition\n");
-                               spin_unlock_irq(&nacl->device_list_lock);
-                               return -EINVAL;
-                       }
-                       deve->se_lun_acl = lun_acl;
-                       trans = 1;
-               } else {
-                       deve->se_lun = lun;
-                       deve->se_lun_acl = lun_acl;
-                       deve->mapped_lun = mapped_lun;
-                       deve->lun_flags |= TRANSPORT_LUNFLAGS_INITIATOR_ACCESS;
+
+       deve = nacl->device_list[mapped_lun];
+
+       /*
+        * Check if the call is handling demo mode -> explict LUN ACL
+        * transition.  This transition must be for the same struct se_lun
+        * + mapped_lun that was setup in demo mode..
+        */
+       if (deve->lun_flags & TRANSPORT_LUNFLAGS_INITIATOR_ACCESS) {
+               if (deve->se_lun_acl != NULL) {
+                       pr_err("struct se_dev_entry->se_lun_acl"
+                              " already set for demo mode -> explict"
+                              " LUN ACL transition\n");
+                       spin_unlock_irq(&nacl->device_list_lock);
+                       return -EINVAL;
                }
+               if (deve->se_lun != lun) {
+                       pr_err("struct se_dev_entry->se_lun does"
+                              " match passed struct se_lun for demo mode"
+                              " -> explict LUN ACL transition\n");
+                       spin_unlock_irq(&nacl->device_list_lock);
+                       return -EINVAL;
+               }
+               deve->se_lun_acl = lun_acl;
 
                if (lun_access & TRANSPORT_LUNFLAGS_READ_WRITE) {
                        deve->lun_flags &= ~TRANSPORT_LUNFLAGS_READ_ONLY;
@@ -417,27 +391,72 @@ int core_update_device_list_for_node(
                        deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_ONLY;
                }
 
-               if (trans) {
-                       spin_unlock_irq(&nacl->device_list_lock);
-                       return 0;
-               }
-               deve->creation_time = get_jiffies_64();
-               deve->attach_count++;
                spin_unlock_irq(&nacl->device_list_lock);
+               return 0;
+       }
 
-               spin_lock_bh(&port->sep_alua_lock);
-               list_add_tail(&deve->alua_port_list, &port->sep_alua_list);
-               spin_unlock_bh(&port->sep_alua_lock);
+       deve->se_lun = lun;
+       deve->se_lun_acl = lun_acl;
+       deve->mapped_lun = mapped_lun;
+       deve->lun_flags |= TRANSPORT_LUNFLAGS_INITIATOR_ACCESS;
 
-               return 0;
+       if (lun_access & TRANSPORT_LUNFLAGS_READ_WRITE) {
+               deve->lun_flags &= ~TRANSPORT_LUNFLAGS_READ_ONLY;
+               deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_WRITE;
+       } else {
+               deve->lun_flags &= ~TRANSPORT_LUNFLAGS_READ_WRITE;
+               deve->lun_flags |= TRANSPORT_LUNFLAGS_READ_ONLY;
        }
+
+       deve->creation_time = get_jiffies_64();
+       deve->attach_count++;
+       spin_unlock_irq(&nacl->device_list_lock);
+
+       spin_lock_bh(&port->sep_alua_lock);
+       list_add_tail(&deve->alua_port_list, &port->sep_alua_list);
+       spin_unlock_bh(&port->sep_alua_lock);
+
+       return 0;
+}
+
+/*      core_disable_device_list_for_node():
+ *
+ *
+ */
+int core_disable_device_list_for_node(
+       struct se_lun *lun,
+       struct se_lun_acl *lun_acl,
+       u32 mapped_lun,
+       u32 lun_access,
+       struct se_node_acl *nacl,
+       struct se_portal_group *tpg)
+{
+       struct se_port *port = lun->lun_sep;
+       struct se_dev_entry *deve = nacl->device_list[mapped_lun];
+
+       /*
+        * If the MappedLUN entry is being disabled, the entry in
+        * port->sep_alua_list must be removed now before clearing the
+        * struct se_dev_entry pointers below as logic in
+        * core_alua_do_transition_tg_pt() depends on these being present.
+        *
+        * deve->se_lun_acl will be NULL for demo-mode created LUNs
+        * that have not been explicitly converted to MappedLUNs ->
+        * struct se_lun_acl, but we remove deve->alua_port_list from
+        * port->sep_alua_list. This also means that active UAs and
+        * NodeACL context specific PR metadata for demo-mode
+        * MappedLUN *deve will be released below..
+        */
+       spin_lock_bh(&port->sep_alua_lock);
+       list_del(&deve->alua_port_list);
+       spin_unlock_bh(&port->sep_alua_lock);
        /*
         * Wait for any in process SPEC_I_PT=1 or REGISTER_AND_MOVE
         * PR operation to complete.
         */
-       spin_unlock_irq(&nacl->device_list_lock);
        while (atomic_read(&deve->pr_ref_count) != 0)
                cpu_relax();
+
        spin_lock_irq(&nacl->device_list_lock);
        /*
         * Disable struct se_dev_entry LUN ACL mapping
@@ -475,9 +494,9 @@ void core_clear_lun_from_tpg(struct se_lun *lun, struct se_portal_group *tpg)
                                continue;
                        spin_unlock_irq(&nacl->device_list_lock);
 
-                       core_update_device_list_for_node(lun, NULL,
+                       core_disable_device_list_for_node(lun, NULL,
                                deve->mapped_lun, TRANSPORT_LUNFLAGS_NO_ACCESS,
-                               nacl, tpg, 0);
+                               nacl, tpg);
 
                        spin_lock_irq(&nacl->device_list_lock);
                }
@@ -715,7 +734,7 @@ void se_release_device_for_hba(struct se_device *dev)
                se_dev_stop(dev);
 
        if (dev->dev_ptr) {
-               kthread_stop(dev->process_thread);
+               destroy_workqueue(dev->tmr_wq);
                if (dev->transport->free_device)
                        dev->transport->free_device(dev->dev_ptr);
        }
@@ -822,7 +841,7 @@ int se_dev_check_shutdown(struct se_device *dev)
        return ret;
 }
 
-u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
+static u32 se_dev_align_max_sectors(u32 max_sectors, u32 block_size)
 {
        u32 tmp, aligned_max_sectors;
        /*
@@ -1273,7 +1292,6 @@ int se_dev_set_block_size(struct se_device *dev, u32 block_size)
 
 struct se_lun *core_dev_add_lun(
        struct se_portal_group *tpg,
-       struct se_hba *hba,
        struct se_device *dev,
        u32 lun)
 {
@@ -1298,7 +1316,7 @@ struct se_lun *core_dev_add_lun(
        pr_debug("%s_TPG[%u]_LUN[%u] - Activated %s Logical Unit from"
                " CORE HBA: %u\n", tpg->se_tpg_tfo->get_fabric_name(),
                tpg->se_tpg_tfo->tpg_get_tag(tpg), lun_p->unpacked_lun,
-               tpg->se_tpg_tfo->get_fabric_name(), hba->hba_id);
+               tpg->se_tpg_tfo->get_fabric_name(), dev->se_hba->hba_id);
        /*
         * Update LUN maps for dynamically added initiators when
         * generate_node_acl is enabled.
@@ -1470,8 +1488,8 @@ int core_dev_add_initiator_node_lun_acl(
 
        lacl->se_lun = lun;
 
-       if (core_update_device_list_for_node(lun, lacl, lacl->mapped_lun,
-                       lun_access, nacl, tpg, 1) < 0)
+       if (core_enable_device_list_for_node(lun, lacl, lacl->mapped_lun,
+                       lun_access, nacl, tpg) < 0)
                return -EINVAL;
 
        spin_lock(&lun->lun_acl_lock);
@@ -1514,8 +1532,8 @@ int core_dev_del_initiator_node_lun_acl(
        smp_mb__after_atomic_dec();
        spin_unlock(&lun->lun_acl_lock);
 
-       core_update_device_list_for_node(lun, NULL, lacl->mapped_lun,
-               TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg, 0);
+       core_disable_device_list_for_node(lun, NULL, lacl->mapped_lun,
+               TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg);
 
        lacl->se_lun = NULL;
 
index 405cc98eaed6a73b11f5c55d6424e47b1637683e..ea479e54f5fdf3f613cfd2056dc8994b9934c4c0 100644 (file)
@@ -764,8 +764,7 @@ static int target_fabric_port_link(
                goto out;
        }
 
-       lun_p = core_dev_add_lun(se_tpg, dev->se_hba, dev,
-                               lun->unpacked_lun);
+       lun_p = core_dev_add_lun(se_tpg, dev, lun->unpacked_lun);
        if (IS_ERR(lun_p)) {
                pr_err("core_dev_add_lun() failed\n");
                ret = PTR_ERR(lun_p);
index 9f99d0404908fd04fe4a68e30c00b3e015f48879..9e2100551c789f70b033e420d0840b1f2e340f5d 100644 (file)
@@ -331,7 +331,7 @@ static int fd_do_writev(struct se_cmd *cmd, struct scatterlist *sgl,
        return 1;
 }
 
-static void fd_emulate_sync_cache(struct se_cmd *cmd)
+static int fd_execute_sync_cache(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
        struct fd_dev *fd_dev = dev->dev_ptr;
@@ -365,7 +365,7 @@ static void fd_emulate_sync_cache(struct se_cmd *cmd)
                pr_err("FILEIO: vfs_fsync_range() failed: %d\n", ret);
 
        if (immed)
-               return;
+               return 0;
 
        if (ret) {
                cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -373,11 +373,15 @@ static void fd_emulate_sync_cache(struct se_cmd *cmd)
        } else {
                target_complete_cmd(cmd, SAM_STAT_GOOD);
        }
+
+       return 0;
 }
 
-static int fd_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
-               u32 sgl_nents, enum dma_data_direction data_direction)
+static int fd_execute_rw(struct se_cmd *cmd)
 {
+       struct scatterlist *sgl = cmd->t_data_sg;
+       u32 sgl_nents = cmd->t_data_nents;
+       enum dma_data_direction data_direction = cmd->data_direction;
        struct se_device *dev = cmd->se_dev;
        int ret = 0;
 
@@ -550,6 +554,16 @@ static sector_t fd_get_blocks(struct se_device *dev)
        return div_u64(dev_size, dev->se_sub_dev->se_dev_attrib.block_size);
 }
 
+static struct spc_ops fd_spc_ops = {
+       .execute_rw             = fd_execute_rw,
+       .execute_sync_cache     = fd_execute_sync_cache,
+};
+
+static int fd_parse_cdb(struct se_cmd *cmd)
+{
+       return sbc_parse_cdb(cmd, &fd_spc_ops);
+}
+
 static struct se_subsystem_api fileio_template = {
        .name                   = "fileio",
        .owner                  = THIS_MODULE,
@@ -561,8 +575,7 @@ static struct se_subsystem_api fileio_template = {
        .allocate_virtdevice    = fd_allocate_virtdevice,
        .create_virtdevice      = fd_create_virtdevice,
        .free_device            = fd_free_device,
-       .execute_cmd            = fd_execute_cmd,
-       .do_sync_cache          = fd_emulate_sync_cache,
+       .parse_cdb              = fd_parse_cdb,
        .check_configfs_dev_params = fd_check_configfs_dev_params,
        .set_configfs_dev_params = fd_set_configfs_dev_params,
        .show_configfs_dev_params = fd_show_configfs_dev_params,
index fd47950727b4b2ff50edc74ca0c69c23ff35255a..76db75e836ede701c2aed6090a212fdf1a08ad10 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/module.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
+#include <asm/unaligned.h>
 
 #include <target/target_core_base.h>
 #include <target/target_core_backend.h>
@@ -96,6 +97,7 @@ static struct se_device *iblock_create_virtdevice(
        struct request_queue *q;
        struct queue_limits *limits;
        u32 dev_flags = 0;
+       fmode_t mode;
        int ret = -EINVAL;
 
        if (!ib_dev) {
@@ -117,8 +119,11 @@ static struct se_device *iblock_create_virtdevice(
        pr_debug( "IBLOCK: Claiming struct block_device: %s\n",
                        ib_dev->ibd_udev_path);
 
-       bd = blkdev_get_by_path(ib_dev->ibd_udev_path,
-                               FMODE_WRITE|FMODE_READ|FMODE_EXCL, ib_dev);
+       mode = FMODE_READ|FMODE_EXCL;
+       if (!ib_dev->ibd_readonly)
+               mode |= FMODE_WRITE;
+
+       bd = blkdev_get_by_path(ib_dev->ibd_udev_path, mode, ib_dev);
        if (IS_ERR(bd)) {
                ret = PTR_ERR(bd);
                goto failed;
@@ -292,7 +297,7 @@ static void iblock_end_io_flush(struct bio *bio, int err)
  * Implement SYCHRONIZE CACHE.  Note that we can't handle lba ranges and must
  * always flush the whole cache.
  */
-static void iblock_emulate_sync_cache(struct se_cmd *cmd)
+static int iblock_execute_sync_cache(struct se_cmd *cmd)
 {
        struct iblock_dev *ib_dev = cmd->se_dev->dev_ptr;
        int immed = (cmd->t_task_cdb[1] & 0x2);
@@ -311,23 +316,98 @@ static void iblock_emulate_sync_cache(struct se_cmd *cmd)
        if (!immed)
                bio->bi_private = cmd;
        submit_bio(WRITE_FLUSH, bio);
+       return 0;
 }
 
-static int iblock_do_discard(struct se_device *dev, sector_t lba, u32 range)
+static int iblock_execute_unmap(struct se_cmd *cmd)
 {
+       struct se_device *dev = cmd->se_dev;
        struct iblock_dev *ibd = dev->dev_ptr;
-       struct block_device *bd = ibd->ibd_bd;
-       int barrier = 0;
+       unsigned char *buf, *ptr = NULL;
+       sector_t lba;
+       int size = cmd->data_length;
+       u32 range;
+       int ret = 0;
+       int dl, bd_dl;
+
+       buf = transport_kmap_data_sg(cmd);
+
+       dl = get_unaligned_be16(&buf[0]);
+       bd_dl = get_unaligned_be16(&buf[2]);
+
+       size = min(size - 8, bd_dl);
+       if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) {
+               cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
+               ret = -EINVAL;
+               goto err;
+       }
+
+       /* First UNMAP block descriptor starts at 8 byte offset */
+       ptr = &buf[8];
+       pr_debug("UNMAP: Sub: %s Using dl: %u bd_dl: %u size: %u"
+               " ptr: %p\n", dev->transport->name, dl, bd_dl, size, ptr);
+
+       while (size >= 16) {
+               lba = get_unaligned_be64(&ptr[0]);
+               range = get_unaligned_be32(&ptr[8]);
+               pr_debug("UNMAP: Using lba: %llu and range: %u\n",
+                                (unsigned long long)lba, range);
+
+               if (range > dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count) {
+                       cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
+                       ret = -EINVAL;
+                       goto err;
+               }
+
+               if (lba + range > dev->transport->get_blocks(dev) + 1) {
+                       cmd->scsi_sense_reason = TCM_ADDRESS_OUT_OF_RANGE;
+                       ret = -EINVAL;
+                       goto err;
+               }
 
-       return blkdev_issue_discard(bd, lba, range, GFP_KERNEL, barrier);
+               ret = blkdev_issue_discard(ibd->ibd_bd, lba, range,
+                                          GFP_KERNEL, 0);
+               if (ret < 0) {
+                       pr_err("blkdev_issue_discard() failed: %d\n",
+                                       ret);
+                       goto err;
+               }
+
+               ptr += 16;
+               size -= 16;
+       }
+
+err:
+       transport_kunmap_data_sg(cmd);
+       if (!ret)
+               target_complete_cmd(cmd, GOOD);
+       return ret;
+}
+
+static int iblock_execute_write_same(struct se_cmd *cmd)
+{
+       struct iblock_dev *ibd = cmd->se_dev->dev_ptr;
+       int ret;
+
+       ret = blkdev_issue_discard(ibd->ibd_bd, cmd->t_task_lba,
+                                  spc_get_write_same_sectors(cmd), GFP_KERNEL,
+                                  0);
+       if (ret < 0) {
+               pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n");
+               return ret;
+       }
+
+       target_complete_cmd(cmd, GOOD);
+       return 0;
 }
 
 enum {
-       Opt_udev_path, Opt_force, Opt_err
+       Opt_udev_path, Opt_readonly, Opt_force, Opt_err
 };
 
 static match_table_t tokens = {
        {Opt_udev_path, "udev_path=%s"},
+       {Opt_readonly, "readonly=%d"},
        {Opt_force, "force=%d"},
        {Opt_err, NULL}
 };
@@ -340,6 +420,7 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
        char *orig, *ptr, *arg_p, *opts;
        substring_t args[MAX_OPT_ARGS];
        int ret = 0, token;
+       unsigned long tmp_readonly;
 
        opts = kstrdup(page, GFP_KERNEL);
        if (!opts)
@@ -372,6 +453,22 @@ static ssize_t iblock_set_configfs_dev_params(struct se_hba *hba,
                                        ib_dev->ibd_udev_path);
                        ib_dev->ibd_flags |= IBDF_HAS_UDEV_PATH;
                        break;
+               case Opt_readonly:
+                       arg_p = match_strdup(&args[0]);
+                       if (!arg_p) {
+                               ret = -ENOMEM;
+                               break;
+                       }
+                       ret = strict_strtoul(arg_p, 0, &tmp_readonly);
+                       kfree(arg_p);
+                       if (ret < 0) {
+                               pr_err("strict_strtoul() failed for"
+                                               " readonly=\n");
+                               goto out;
+                       }
+                       ib_dev->ibd_readonly = tmp_readonly;
+                       pr_debug("IBLOCK: readonly: %d\n", ib_dev->ibd_readonly);
+                       break;
                case Opt_force:
                        break;
                default:
@@ -411,11 +508,10 @@ static ssize_t iblock_show_configfs_dev_params(
        if (bd)
                bl += sprintf(b + bl, "iBlock device: %s",
                                bdevname(bd, buf));
-       if (ibd->ibd_flags & IBDF_HAS_UDEV_PATH) {
-               bl += sprintf(b + bl, "  UDEV PATH: %s\n",
+       if (ibd->ibd_flags & IBDF_HAS_UDEV_PATH)
+               bl += sprintf(b + bl, "  UDEV PATH: %s",
                                ibd->ibd_udev_path);
-       } else
-               bl += sprintf(b + bl, "\n");
+       bl += sprintf(b + bl, "  readonly: %d\n", ibd->ibd_readonly);
 
        bl += sprintf(b + bl, "        ");
        if (bd) {
@@ -493,9 +589,11 @@ static void iblock_submit_bios(struct bio_list *list, int rw)
        blk_finish_plug(&plug);
 }
 
-static int iblock_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
-               u32 sgl_nents, enum dma_data_direction data_direction)
+static int iblock_execute_rw(struct se_cmd *cmd)
 {
+       struct scatterlist *sgl = cmd->t_data_sg;
+       u32 sgl_nents = cmd->t_data_nents;
+       enum dma_data_direction data_direction = cmd->data_direction;
        struct se_device *dev = cmd->se_dev;
        struct iblock_req *ibr;
        struct bio *bio;
@@ -642,6 +740,18 @@ static void iblock_bio_done(struct bio *bio, int err)
        iblock_complete_cmd(cmd);
 }
 
+static struct spc_ops iblock_spc_ops = {
+       .execute_rw             = iblock_execute_rw,
+       .execute_sync_cache     = iblock_execute_sync_cache,
+       .execute_write_same     = iblock_execute_write_same,
+       .execute_unmap          = iblock_execute_unmap,
+};
+
+static int iblock_parse_cdb(struct se_cmd *cmd)
+{
+       return sbc_parse_cdb(cmd, &iblock_spc_ops);
+}
+
 static struct se_subsystem_api iblock_template = {
        .name                   = "iblock",
        .owner                  = THIS_MODULE,
@@ -653,9 +763,7 @@ static struct se_subsystem_api iblock_template = {
        .allocate_virtdevice    = iblock_allocate_virtdevice,
        .create_virtdevice      = iblock_create_virtdevice,
        .free_device            = iblock_free_device,
-       .execute_cmd            = iblock_execute_cmd,
-       .do_discard             = iblock_do_discard,
-       .do_sync_cache          = iblock_emulate_sync_cache,
+       .parse_cdb              = iblock_parse_cdb,
        .check_configfs_dev_params = iblock_check_configfs_dev_params,
        .set_configfs_dev_params = iblock_set_configfs_dev_params,
        .show_configfs_dev_params = iblock_show_configfs_dev_params,
index 66cf7b9e205edbf799ff77d963bd841f8d87972c..533627ae79ec8b1d49d4d2288e08e645d562a725 100644 (file)
@@ -18,6 +18,7 @@ struct iblock_dev {
        u32     ibd_flags;
        struct bio_set  *ibd_bio_set;
        struct block_device *ibd_bd;
+       bool ibd_readonly;
 } ____cacheline_aligned;
 
 #endif /* TARGET_CORE_IBLOCK_H */
index 165e82429687a49978c368598e20851ec91df0ae..0fd428225d115af6b4b3afbcc3d0beaaade73ebc 100644 (file)
@@ -4,25 +4,16 @@
 /* target_core_alua.c */
 extern struct t10_alua_lu_gp *default_lu_gp;
 
-/* target_core_cdb.c */
-int    target_emulate_inquiry(struct se_cmd *cmd);
-int    target_emulate_readcapacity(struct se_cmd *cmd);
-int    target_emulate_readcapacity_16(struct se_cmd *cmd);
-int    target_emulate_modesense(struct se_cmd *cmd);
-int    target_emulate_request_sense(struct se_cmd *cmd);
-int    target_emulate_unmap(struct se_cmd *cmd);
-int    target_emulate_write_same(struct se_cmd *cmd);
-int    target_emulate_synchronize_cache(struct se_cmd *cmd);
-int    target_emulate_noop(struct se_cmd *cmd);
-
 /* target_core_device.c */
 struct se_dev_entry *core_get_se_deve_from_rtpi(struct se_node_acl *, u16);
 int    core_free_device_list_for_node(struct se_node_acl *,
                struct se_portal_group *);
 void   core_dec_lacl_count(struct se_node_acl *, struct se_cmd *);
 void   core_update_device_list_access(u32, u32, struct se_node_acl *);
-int    core_update_device_list_for_node(struct se_lun *, struct se_lun_acl *,
-               u32, u32, struct se_node_acl *, struct se_portal_group *, int);
+int    core_enable_device_list_for_node(struct se_lun *, struct se_lun_acl *,
+               u32, u32, struct se_node_acl *, struct se_portal_group *);
+int    core_disable_device_list_for_node(struct se_lun *, struct se_lun_acl *,
+               u32, u32, struct se_node_acl *, struct se_portal_group *);
 void   core_clear_lun_from_tpg(struct se_lun *, struct se_portal_group *);
 int    core_dev_export(struct se_device *, struct se_portal_group *,
                struct se_lun *);
@@ -56,8 +47,7 @@ int   se_dev_set_max_sectors(struct se_device *, u32);
 int    se_dev_set_fabric_max_sectors(struct se_device *, u32);
 int    se_dev_set_optimal_sectors(struct se_device *, u32);
 int    se_dev_set_block_size(struct se_device *, u32);
-struct se_lun *core_dev_add_lun(struct se_portal_group *, struct se_hba *,
-               struct se_device *, u32);
+struct se_lun *core_dev_add_lun(struct se_portal_group *, struct se_device *, u32);
 int    core_dev_del_lun(struct se_portal_group *, u32);
 struct se_lun *core_get_lun_from_tpg(struct se_portal_group *, u32);
 struct se_lun_acl *core_dev_init_initiator_node_lun_acl(struct se_portal_group *,
@@ -104,7 +94,6 @@ void release_se_kmem_caches(void);
 u32    scsi_get_new_index(scsi_index_t);
 void   transport_subsystem_check_init(void);
 void   transport_cmd_finish_abort(struct se_cmd *, int);
-void   __target_remove_from_execute_list(struct se_cmd *);
 unsigned char *transport_dump_cmd_direction(struct se_cmd *);
 void   transport_dump_dev_state(struct se_device *, char *, int *);
 void   transport_dump_dev_info(struct se_device *, struct se_lun *,
@@ -116,6 +105,7 @@ int transport_dump_vpd_ident(struct t10_vpd *, unsigned char *, int);
 bool   target_stop_cmd(struct se_cmd *cmd, unsigned long *flags);
 int    transport_clear_lun_from_sessions(struct se_lun *);
 void   transport_send_task_abort(struct se_cmd *);
+int    target_cmd_size_check(struct se_cmd *cmd, unsigned int size);
 
 /* target_core_stat.c */
 void   target_stat_setup_dev_default_groups(struct se_subsystem_dev *);
index a1bcd927a9e60ed6a80903ff737c661c075b675b..1e946502c378886aa90bafc16239d2c34730b9fb 100644 (file)
@@ -507,7 +507,7 @@ static int core_scsi3_pr_seq_non_holder(
         * Check if write exclusive initiator ports *NOT* holding the
         * WRITE_EXCLUSIVE_* reservation.
         */
-       if ((we) && !(registered_nexus)) {
+       if (we && !registered_nexus) {
                if (cmd->data_direction == DMA_TO_DEVICE) {
                        /*
                         * Conflict for write exclusive
@@ -2486,7 +2486,7 @@ static int core_scsi3_pro_reserve(
         */
        spin_lock(&dev->dev_reservation_lock);
        pr_res_holder = dev->dev_pr_res_holder;
-       if ((pr_res_holder)) {
+       if (pr_res_holder) {
                /*
                 * From spc4r17 Section 5.7.9: Reserving:
                 *
@@ -4030,7 +4030,7 @@ static int core_scsi3_pri_read_reservation(struct se_cmd *cmd)
 
        spin_lock(&se_dev->dev_reservation_lock);
        pr_reg = se_dev->dev_pr_res_holder;
-       if ((pr_reg)) {
+       if (pr_reg) {
                /*
                 * Set the hardcoded Additional Length
                 */
index 4ce2cf642fced270ee727e83a81385467b9d9537..6e32ff6f2fa0ce4ead43073d87bedc77d3ffee2c 100644 (file)
 #include <linux/spinlock.h>
 #include <linux/genhd.h>
 #include <linux/cdrom.h>
-#include <linux/file.h>
+#include <linux/ratelimit.h>
 #include <linux/module.h>
+#include <asm/unaligned.h>
+
 #include <scsi/scsi.h>
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_cmnd.h>
 #include <target/target_core_base.h>
 #include <target/target_core_backend.h>
 
+#include "target_core_alua.h"
 #include "target_core_pscsi.h"
 
 #define ISPRINT(a)  ((a >= ' ') && (a <= '~'))
 
 static struct se_subsystem_api pscsi_template;
 
+static int pscsi_execute_cmd(struct se_cmd *cmd);
 static void pscsi_req_done(struct request *, int);
 
 /*     pscsi_attach_hba():
@@ -1019,9 +1023,79 @@ fail:
        return -ENOMEM;
 }
 
-static int pscsi_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
-               u32 sgl_nents, enum dma_data_direction data_direction)
+/*
+ * Clear a lun set in the cdb if the initiator talking to use spoke
+ * and old standards version, as we can't assume the underlying device
+ * won't choke up on it.
+ */
+static inline void pscsi_clear_cdb_lun(unsigned char *cdb)
+{
+       switch (cdb[0]) {
+       case READ_10: /* SBC - RDProtect */
+       case READ_12: /* SBC - RDProtect */
+       case READ_16: /* SBC - RDProtect */
+       case SEND_DIAGNOSTIC: /* SPC - SELF-TEST Code */
+       case VERIFY: /* SBC - VRProtect */
+       case VERIFY_16: /* SBC - VRProtect */
+       case WRITE_VERIFY: /* SBC - VRProtect */
+       case WRITE_VERIFY_12: /* SBC - VRProtect */
+       case MAINTENANCE_IN: /* SPC - Parameter Data Format for SA RTPG */
+               break;
+       default:
+               cdb[1] &= 0x1f; /* clear logical unit number */
+               break;
+       }
+}
+
+static int pscsi_parse_cdb(struct se_cmd *cmd)
+{
+       unsigned char *cdb = cmd->t_task_cdb;
+       unsigned int dummy_size;
+       int ret;
+
+       if (cmd->se_cmd_flags & SCF_BIDI) {
+               cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+               cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
+               return -EINVAL;
+       }
+
+       pscsi_clear_cdb_lun(cdb);
+
+       /*
+        * For REPORT LUNS we always need to emulate the response, for everything
+        * else the default for pSCSI is to pass the command to the underlying
+        * LLD / physical hardware.
+        */
+       switch (cdb[0]) {
+       case REPORT_LUNS:
+               ret = spc_parse_cdb(cmd, &dummy_size);
+               if (ret)
+                       return ret;
+               break;
+       case READ_6:
+       case READ_10:
+       case READ_12:
+       case READ_16:
+       case WRITE_6:
+       case WRITE_10:
+       case WRITE_12:
+       case WRITE_16:
+       case WRITE_VERIFY:
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               /* FALLTHROUGH*/
+       default:
+               cmd->execute_cmd = pscsi_execute_cmd;
+               break;
+       }
+
+       return 0;
+}
+
+static int pscsi_execute_cmd(struct se_cmd *cmd)
 {
+       struct scatterlist *sgl = cmd->t_data_sg;
+       u32 sgl_nents = cmd->t_data_nents;
+       enum dma_data_direction data_direction = cmd->data_direction;
        struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr;
        struct pscsi_plugin_task *pt;
        struct request *req;
@@ -1042,7 +1116,7 @@ static int pscsi_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
        memcpy(pt->pscsi_cdb, cmd->t_task_cdb,
                scsi_command_size(cmd->t_task_cdb));
 
-       if (cmd->se_cmd_flags & SCF_SCSI_NON_DATA_CDB) {
+       if (!sgl) {
                req = blk_get_request(pdv->pdv_sd->request_queue,
                                (data_direction == DMA_TO_DEVICE),
                                GFP_KERNEL);
@@ -1188,7 +1262,7 @@ static struct se_subsystem_api pscsi_template = {
        .create_virtdevice      = pscsi_create_virtdevice,
        .free_device            = pscsi_free_device,
        .transport_complete     = pscsi_transport_complete,
-       .execute_cmd            = pscsi_execute_cmd,
+       .parse_cdb              = pscsi_parse_cdb,
        .check_configfs_dev_params = pscsi_check_configfs_dev_params,
        .set_configfs_dev_params = pscsi_set_configfs_dev_params,
        .show_configfs_dev_params = pscsi_show_configfs_dev_params,
index d0ceb873c0e577bc363971b10605228c804ae5d0..d00bbe33ff8b285f7777eaaf420d802e589169c2 100644 (file)
@@ -284,9 +284,11 @@ static struct rd_dev_sg_table *rd_get_sg_table(struct rd_dev *rd_dev, u32 page)
        return NULL;
 }
 
-static int rd_execute_cmd(struct se_cmd *cmd, struct scatterlist *sgl,
-               u32 sgl_nents, enum dma_data_direction data_direction)
+static int rd_execute_rw(struct se_cmd *cmd)
 {
+       struct scatterlist *sgl = cmd->t_data_sg;
+       u32 sgl_nents = cmd->t_data_nents;
+       enum dma_data_direction data_direction = cmd->data_direction;
        struct se_device *se_dev = cmd->se_dev;
        struct rd_dev *dev = se_dev->dev_ptr;
        struct rd_dev_sg_table *table;
@@ -460,6 +462,15 @@ static sector_t rd_get_blocks(struct se_device *dev)
        return blocks_long;
 }
 
+static struct spc_ops rd_spc_ops = {
+       .execute_rw             = rd_execute_rw,
+};
+
+static int rd_parse_cdb(struct se_cmd *cmd)
+{
+       return sbc_parse_cdb(cmd, &rd_spc_ops);
+}
+
 static struct se_subsystem_api rd_mcp_template = {
        .name                   = "rd_mcp",
        .transport_type         = TRANSPORT_PLUGIN_VHBA_VDEV,
@@ -468,7 +479,7 @@ static struct se_subsystem_api rd_mcp_template = {
        .allocate_virtdevice    = rd_allocate_virtdevice,
        .create_virtdevice      = rd_create_virtdevice,
        .free_device            = rd_free_device,
-       .execute_cmd            = rd_execute_cmd,
+       .parse_cdb              = rd_parse_cdb,
        .check_configfs_dev_params = rd_check_configfs_dev_params,
        .set_configfs_dev_params = rd_set_configfs_dev_params,
        .show_configfs_dev_params = rd_show_configfs_dev_params,
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
new file mode 100644 (file)
index 0000000..a9dd946
--- /dev/null
@@ -0,0 +1,581 @@
+/*
+ * SCSI Block Commands (SBC) parsing and emulation.
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc.
+ * Copyright (c) 2005, 2006, 2007 SBE, Inc.
+ * Copyright (c) 2007-2010 Rising Tide Systems
+ * Copyright (c) 2008-2010 Linux-iSCSI.org
+ *
+ * Nicholas A. Bellinger <nab@kernel.org>
+ *
+ * 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/module.h>
+#include <linux/ratelimit.h>
+#include <asm/unaligned.h>
+#include <scsi/scsi.h>
+
+#include <target/target_core_base.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
+
+#include "target_core_internal.h"
+#include "target_core_ua.h"
+
+
+static int sbc_emulate_readcapacity(struct se_cmd *cmd)
+{
+       struct se_device *dev = cmd->se_dev;
+       unsigned char *buf;
+       unsigned long long blocks_long = dev->transport->get_blocks(dev);
+       u32 blocks;
+
+       if (blocks_long >= 0x00000000ffffffff)
+               blocks = 0xffffffff;
+       else
+               blocks = (u32)blocks_long;
+
+       buf = transport_kmap_data_sg(cmd);
+
+       buf[0] = (blocks >> 24) & 0xff;
+       buf[1] = (blocks >> 16) & 0xff;
+       buf[2] = (blocks >> 8) & 0xff;
+       buf[3] = blocks & 0xff;
+       buf[4] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff;
+       buf[5] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff;
+       buf[6] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
+       buf[7] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
+
+       transport_kunmap_data_sg(cmd);
+
+       target_complete_cmd(cmd, GOOD);
+       return 0;
+}
+
+static int sbc_emulate_readcapacity_16(struct se_cmd *cmd)
+{
+       struct se_device *dev = cmd->se_dev;
+       unsigned char *buf;
+       unsigned long long blocks = dev->transport->get_blocks(dev);
+
+       buf = transport_kmap_data_sg(cmd);
+
+       buf[0] = (blocks >> 56) & 0xff;
+       buf[1] = (blocks >> 48) & 0xff;
+       buf[2] = (blocks >> 40) & 0xff;
+       buf[3] = (blocks >> 32) & 0xff;
+       buf[4] = (blocks >> 24) & 0xff;
+       buf[5] = (blocks >> 16) & 0xff;
+       buf[6] = (blocks >> 8) & 0xff;
+       buf[7] = blocks & 0xff;
+       buf[8] = (dev->se_sub_dev->se_dev_attrib.block_size >> 24) & 0xff;
+       buf[9] = (dev->se_sub_dev->se_dev_attrib.block_size >> 16) & 0xff;
+       buf[10] = (dev->se_sub_dev->se_dev_attrib.block_size >> 8) & 0xff;
+       buf[11] = dev->se_sub_dev->se_dev_attrib.block_size & 0xff;
+       /*
+        * Set Thin Provisioning Enable bit following sbc3r22 in section
+        * READ CAPACITY (16) byte 14 if emulate_tpu or emulate_tpws is enabled.
+        */
+       if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
+               buf[14] = 0x80;
+
+       transport_kunmap_data_sg(cmd);
+
+       target_complete_cmd(cmd, GOOD);
+       return 0;
+}
+
+int spc_get_write_same_sectors(struct se_cmd *cmd)
+{
+       u32 num_blocks;
+
+       if (cmd->t_task_cdb[0] == WRITE_SAME)
+               num_blocks = get_unaligned_be16(&cmd->t_task_cdb[7]);
+       else if (cmd->t_task_cdb[0] == WRITE_SAME_16)
+               num_blocks = get_unaligned_be32(&cmd->t_task_cdb[10]);
+       else /* WRITE_SAME_32 via VARIABLE_LENGTH_CMD */
+               num_blocks = get_unaligned_be32(&cmd->t_task_cdb[28]);
+
+       /*
+        * Use the explicit range when non zero is supplied, otherwise calculate
+        * the remaining range based on ->get_blocks() - starting LBA.
+        */
+       if (num_blocks)
+               return num_blocks;
+
+       return cmd->se_dev->transport->get_blocks(cmd->se_dev) -
+               cmd->t_task_lba + 1;
+}
+EXPORT_SYMBOL(spc_get_write_same_sectors);
+
+static int sbc_emulate_verify(struct se_cmd *cmd)
+{
+       target_complete_cmd(cmd, GOOD);
+       return 0;
+}
+
+static inline u32 sbc_get_size(struct se_cmd *cmd, u32 sectors)
+{
+       return cmd->se_dev->se_sub_dev->se_dev_attrib.block_size * sectors;
+}
+
+static int sbc_check_valid_sectors(struct se_cmd *cmd)
+{
+       struct se_device *dev = cmd->se_dev;
+       unsigned long long end_lba;
+       u32 sectors;
+
+       sectors = cmd->data_length / dev->se_sub_dev->se_dev_attrib.block_size;
+       end_lba = dev->transport->get_blocks(dev) + 1;
+
+       if (cmd->t_task_lba + sectors > end_lba) {
+               pr_err("target: lba %llu, sectors %u exceeds end lba %llu\n",
+                       cmd->t_task_lba, sectors, end_lba);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static inline u32 transport_get_sectors_6(unsigned char *cdb)
+{
+       /*
+        * Use 8-bit sector value.  SBC-3 says:
+        *
+        *   A TRANSFER LENGTH field set to zero specifies that 256
+        *   logical blocks shall be written.  Any other value
+        *   specifies the number of logical blocks that shall be
+        *   written.
+        */
+       return cdb[4] ? : 256;
+}
+
+static inline u32 transport_get_sectors_10(unsigned char *cdb)
+{
+       return (u32)(cdb[7] << 8) + cdb[8];
+}
+
+static inline u32 transport_get_sectors_12(unsigned char *cdb)
+{
+       return (u32)(cdb[6] << 24) + (cdb[7] << 16) + (cdb[8] << 8) + cdb[9];
+}
+
+static inline u32 transport_get_sectors_16(unsigned char *cdb)
+{
+       return (u32)(cdb[10] << 24) + (cdb[11] << 16) +
+                   (cdb[12] << 8) + cdb[13];
+}
+
+/*
+ * Used for VARIABLE_LENGTH_CDB WRITE_32 and READ_32 variants
+ */
+static inline u32 transport_get_sectors_32(unsigned char *cdb)
+{
+       return (u32)(cdb[28] << 24) + (cdb[29] << 16) +
+                   (cdb[30] << 8) + cdb[31];
+
+}
+
+static inline u32 transport_lba_21(unsigned char *cdb)
+{
+       return ((cdb[1] & 0x1f) << 16) | (cdb[2] << 8) | cdb[3];
+}
+
+static inline u32 transport_lba_32(unsigned char *cdb)
+{
+       return (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
+}
+
+static inline unsigned long long transport_lba_64(unsigned char *cdb)
+{
+       unsigned int __v1, __v2;
+
+       __v1 = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
+       __v2 = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
+
+       return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
+}
+
+/*
+ * For VARIABLE_LENGTH_CDB w/ 32 byte extended CDBs
+ */
+static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
+{
+       unsigned int __v1, __v2;
+
+       __v1 = (cdb[12] << 24) | (cdb[13] << 16) | (cdb[14] << 8) | cdb[15];
+       __v2 = (cdb[16] << 24) | (cdb[17] << 16) | (cdb[18] << 8) | cdb[19];
+
+       return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
+}
+
+static int sbc_write_same_supported(struct se_device *dev,
+               unsigned char *flags)
+{
+       if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
+               pr_err("WRITE_SAME PBDATA and LBDATA"
+                       " bits not supported for Block Discard"
+                       " Emulation\n");
+               return -ENOSYS;
+       }
+
+       /*
+        * Currently for the emulated case we only accept
+        * tpws with the UNMAP=1 bit set.
+        */
+       if (!(flags[0] & 0x08)) {
+               pr_err("WRITE_SAME w/o UNMAP bit not"
+                       " supported for Block Discard Emulation\n");
+               return -ENOSYS;
+       }
+
+       return 0;
+}
+
+static void xdreadwrite_callback(struct se_cmd *cmd)
+{
+       unsigned char *buf, *addr;
+       struct scatterlist *sg;
+       unsigned int offset;
+       int i;
+       int count;
+       /*
+        * From sbc3r22.pdf section 5.48 XDWRITEREAD (10) command
+        *
+        * 1) read the specified logical block(s);
+        * 2) transfer logical blocks from the data-out buffer;
+        * 3) XOR the logical blocks transferred from the data-out buffer with
+        *    the logical blocks read, storing the resulting XOR data in a buffer;
+        * 4) if the DISABLE WRITE bit is set to zero, then write the logical
+        *    blocks transferred from the data-out buffer; and
+        * 5) transfer the resulting XOR data to the data-in buffer.
+        */
+       buf = kmalloc(cmd->data_length, GFP_KERNEL);
+       if (!buf) {
+               pr_err("Unable to allocate xor_callback buf\n");
+               return;
+       }
+       /*
+        * Copy the scatterlist WRITE buffer located at cmd->t_data_sg
+        * into the locally allocated *buf
+        */
+       sg_copy_to_buffer(cmd->t_data_sg,
+                         cmd->t_data_nents,
+                         buf,
+                         cmd->data_length);
+
+       /*
+        * Now perform the XOR against the BIDI read memory located at
+        * cmd->t_mem_bidi_list
+        */
+
+       offset = 0;
+       for_each_sg(cmd->t_bidi_data_sg, sg, cmd->t_bidi_data_nents, count) {
+               addr = kmap_atomic(sg_page(sg));
+               if (!addr)
+                       goto out;
+
+               for (i = 0; i < sg->length; i++)
+                       *(addr + sg->offset + i) ^= *(buf + offset + i);
+
+               offset += sg->length;
+               kunmap_atomic(addr);
+       }
+
+out:
+       kfree(buf);
+}
+
+int sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops)
+{
+       struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
+       struct se_device *dev = cmd->se_dev;
+       unsigned char *cdb = cmd->t_task_cdb;
+       unsigned int size;
+       u32 sectors = 0;
+       int ret;
+
+       switch (cdb[0]) {
+       case READ_6:
+               sectors = transport_get_sectors_6(cdb);
+               cmd->t_task_lba = transport_lba_21(cdb);
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case READ_10:
+               sectors = transport_get_sectors_10(cdb);
+               cmd->t_task_lba = transport_lba_32(cdb);
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case READ_12:
+               sectors = transport_get_sectors_12(cdb);
+               cmd->t_task_lba = transport_lba_32(cdb);
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case READ_16:
+               sectors = transport_get_sectors_16(cdb);
+               cmd->t_task_lba = transport_lba_64(cdb);
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case WRITE_6:
+               sectors = transport_get_sectors_6(cdb);
+               cmd->t_task_lba = transport_lba_21(cdb);
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case WRITE_10:
+       case WRITE_VERIFY:
+               sectors = transport_get_sectors_10(cdb);
+               cmd->t_task_lba = transport_lba_32(cdb);
+               if (cdb[1] & 0x8)
+                       cmd->se_cmd_flags |= SCF_FUA;
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case WRITE_12:
+               sectors = transport_get_sectors_12(cdb);
+               cmd->t_task_lba = transport_lba_32(cdb);
+               if (cdb[1] & 0x8)
+                       cmd->se_cmd_flags |= SCF_FUA;
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case WRITE_16:
+               sectors = transport_get_sectors_16(cdb);
+               cmd->t_task_lba = transport_lba_64(cdb);
+               if (cdb[1] & 0x8)
+                       cmd->se_cmd_flags |= SCF_FUA;
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+               cmd->execute_cmd = ops->execute_rw;
+               break;
+       case XDWRITEREAD_10:
+               if ((cmd->data_direction != DMA_TO_DEVICE) ||
+                   !(cmd->se_cmd_flags & SCF_BIDI))
+                       goto out_invalid_cdb_field;
+               sectors = transport_get_sectors_10(cdb);
+
+               cmd->t_task_lba = transport_lba_32(cdb);
+               cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+
+               /*
+                * Setup BIDI XOR callback to be run after I/O completion.
+                */
+               cmd->execute_cmd = ops->execute_rw;
+               cmd->transport_complete_callback = &xdreadwrite_callback;
+               if (cdb[1] & 0x8)
+                       cmd->se_cmd_flags |= SCF_FUA;
+               break;
+       case VARIABLE_LENGTH_CMD:
+       {
+               u16 service_action = get_unaligned_be16(&cdb[8]);
+               switch (service_action) {
+               case XDWRITEREAD_32:
+                       sectors = transport_get_sectors_32(cdb);
+
+                       /*
+                        * Use WRITE_32 and READ_32 opcodes for the emulated
+                        * XDWRITE_READ_32 logic.
+                        */
+                       cmd->t_task_lba = transport_lba_64_ext(cdb);
+                       cmd->se_cmd_flags |= SCF_SCSI_DATA_CDB;
+
+                       /*
+                        * Setup BIDI XOR callback to be run during after I/O
+                        * completion.
+                        */
+                       cmd->execute_cmd = ops->execute_rw;
+                       cmd->transport_complete_callback = &xdreadwrite_callback;
+                       if (cdb[1] & 0x8)
+                               cmd->se_cmd_flags |= SCF_FUA;
+                       break;
+               case WRITE_SAME_32:
+                       if (!ops->execute_write_same)
+                               goto out_unsupported_cdb;
+
+                       sectors = transport_get_sectors_32(cdb);
+                       if (!sectors) {
+                               pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"
+                                      " supported\n");
+                               goto out_invalid_cdb_field;
+                       }
+
+                       size = sbc_get_size(cmd, 1);
+                       cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
+
+                       if (sbc_write_same_supported(dev, &cdb[10]) < 0)
+                               goto out_unsupported_cdb;
+                       cmd->execute_cmd = ops->execute_write_same;
+                       break;
+               default:
+                       pr_err("VARIABLE_LENGTH_CMD service action"
+                               " 0x%04x not supported\n", service_action);
+                       goto out_unsupported_cdb;
+               }
+               break;
+       }
+       case READ_CAPACITY:
+               size = READ_CAP_LEN;
+               cmd->execute_cmd = sbc_emulate_readcapacity;
+               break;
+       case SERVICE_ACTION_IN:
+               switch (cmd->t_task_cdb[1] & 0x1f) {
+               case SAI_READ_CAPACITY_16:
+                       cmd->execute_cmd = sbc_emulate_readcapacity_16;
+                       break;
+               default:
+                       pr_err("Unsupported SA: 0x%02x\n",
+                               cmd->t_task_cdb[1] & 0x1f);
+                       goto out_invalid_cdb_field;
+               }
+               size = (cdb[10] << 24) | (cdb[11] << 16) |
+                      (cdb[12] << 8) | cdb[13];
+               break;
+       case SYNCHRONIZE_CACHE:
+       case SYNCHRONIZE_CACHE_16:
+               if (!ops->execute_sync_cache)
+                       goto out_unsupported_cdb;
+
+               /*
+                * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE
+                */
+               if (cdb[0] == SYNCHRONIZE_CACHE) {
+                       sectors = transport_get_sectors_10(cdb);
+                       cmd->t_task_lba = transport_lba_32(cdb);
+               } else {
+                       sectors = transport_get_sectors_16(cdb);
+                       cmd->t_task_lba = transport_lba_64(cdb);
+               }
+
+               size = sbc_get_size(cmd, sectors);
+
+               /*
+                * Check to ensure that LBA + Range does not exceed past end of
+                * device for IBLOCK and FILEIO ->do_sync_cache() backend calls
+                */
+               if (cmd->t_task_lba || sectors) {
+                       if (sbc_check_valid_sectors(cmd) < 0)
+                               goto out_invalid_cdb_field;
+               }
+               cmd->execute_cmd = ops->execute_sync_cache;
+               break;
+       case UNMAP:
+               if (!ops->execute_unmap)
+                       goto out_unsupported_cdb;
+
+               size = get_unaligned_be16(&cdb[7]);
+               cmd->execute_cmd = ops->execute_unmap;
+               break;
+       case WRITE_SAME_16:
+               if (!ops->execute_write_same)
+                       goto out_unsupported_cdb;
+
+               sectors = transport_get_sectors_16(cdb);
+               if (!sectors) {
+                       pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
+                       goto out_invalid_cdb_field;
+               }
+
+               size = sbc_get_size(cmd, 1);
+               cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
+
+               if (sbc_write_same_supported(dev, &cdb[1]) < 0)
+                       goto out_unsupported_cdb;
+               cmd->execute_cmd = ops->execute_write_same;
+               break;
+       case WRITE_SAME:
+               if (!ops->execute_write_same)
+                       goto out_unsupported_cdb;
+
+               sectors = transport_get_sectors_10(cdb);
+               if (!sectors) {
+                       pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
+                       goto out_invalid_cdb_field;
+               }
+
+               size = sbc_get_size(cmd, 1);
+               cmd->t_task_lba = get_unaligned_be32(&cdb[2]);
+
+               /*
+                * Follow sbcr26 with WRITE_SAME (10) and check for the existence
+                * of byte 1 bit 3 UNMAP instead of original reserved field
+                */
+               if (sbc_write_same_supported(dev, &cdb[1]) < 0)
+                       goto out_unsupported_cdb;
+               cmd->execute_cmd = ops->execute_write_same;
+               break;
+       case VERIFY:
+               size = 0;
+               cmd->execute_cmd = sbc_emulate_verify;
+               break;
+       default:
+               ret = spc_parse_cdb(cmd, &size);
+               if (ret)
+                       return ret;
+       }
+
+       /* reject any command that we don't have a handler for */
+       if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->execute_cmd)
+               goto out_unsupported_cdb;
+
+       if (cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) {
+               unsigned long long end_lba;
+
+               if (sectors > su_dev->se_dev_attrib.fabric_max_sectors) {
+                       printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
+                               " big sectors %u exceeds fabric_max_sectors:"
+                               " %u\n", cdb[0], sectors,
+                               su_dev->se_dev_attrib.fabric_max_sectors);
+                       goto out_invalid_cdb_field;
+               }
+               if (sectors > su_dev->se_dev_attrib.hw_max_sectors) {
+                       printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
+                               " big sectors %u exceeds backend hw_max_sectors:"
+                               " %u\n", cdb[0], sectors,
+                               su_dev->se_dev_attrib.hw_max_sectors);
+                       goto out_invalid_cdb_field;
+               }
+
+               end_lba = dev->transport->get_blocks(dev) + 1;
+               if (cmd->t_task_lba + sectors > end_lba) {
+                       pr_err("cmd exceeds last lba %llu "
+                               "(lba %llu, sectors %u)\n",
+                               end_lba, cmd->t_task_lba, sectors);
+                       goto out_invalid_cdb_field;
+               }
+
+               size = sbc_get_size(cmd, sectors);
+       }
+
+       ret = target_cmd_size_check(cmd, size);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+
+out_unsupported_cdb:
+       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+       cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
+       return -EINVAL;
+out_invalid_cdb_field:
+       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+       return -EINVAL;
+}
+EXPORT_SYMBOL(sbc_parse_cdb);
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
new file mode 100644 (file)
index 0000000..4c861de
--- /dev/null
@@ -0,0 +1,1104 @@
+/*
+ * SCSI Primary Commands (SPC) parsing and emulation.
+ *
+ * Copyright (c) 2002, 2003, 2004, 2005 PyX Technologies, Inc.
+ * Copyright (c) 2005, 2006, 2007 SBE, Inc.
+ * Copyright (c) 2007-2010 Rising Tide Systems
+ * Copyright (c) 2008-2010 Linux-iSCSI.org
+ *
+ * Nicholas A. Bellinger <nab@kernel.org>
+ *
+ * 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/module.h>
+#include <asm/unaligned.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_tcq.h>
+
+#include <target/target_core_base.h>
+#include <target/target_core_backend.h>
+#include <target/target_core_fabric.h>
+
+#include "target_core_internal.h"
+#include "target_core_alua.h"
+#include "target_core_pr.h"
+#include "target_core_ua.h"
+
+
+static void spc_fill_alua_data(struct se_port *port, unsigned char *buf)
+{
+       struct t10_alua_tg_pt_gp *tg_pt_gp;
+       struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
+
+       /*
+        * Set SCCS for MAINTENANCE_IN + REPORT_TARGET_PORT_GROUPS.
+        */
+       buf[5]  = 0x80;
+
+       /*
+        * Set TPGS field for explict and/or implict ALUA access type
+        * and opteration.
+        *
+        * See spc4r17 section 6.4.2 Table 135
+        */
+       if (!port)
+               return;
+       tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
+       if (!tg_pt_gp_mem)
+               return;
+
+       spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
+       tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
+       if (tg_pt_gp)
+               buf[5] |= tg_pt_gp->tg_pt_gp_alua_access_type;
+       spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
+}
+
+static int spc_emulate_inquiry_std(struct se_cmd *cmd, char *buf)
+{
+       struct se_lun *lun = cmd->se_lun;
+       struct se_device *dev = cmd->se_dev;
+
+       /* Set RMB (removable media) for tape devices */
+       if (dev->transport->get_device_type(dev) == TYPE_TAPE)
+               buf[1] = 0x80;
+
+       buf[2] = dev->transport->get_device_rev(dev);
+
+       /*
+        * NORMACA and HISUP = 0, RESPONSE DATA FORMAT = 2
+        *
+        * SPC4 says:
+        *   A RESPONSE DATA FORMAT field set to 2h indicates that the
+        *   standard INQUIRY data is in the format defined in this
+        *   standard. Response data format values less than 2h are
+        *   obsolete. Response data format values greater than 2h are
+        *   reserved.
+        */
+       buf[3] = 2;
+
+       /*
+        * Enable SCCS and TPGS fields for Emulated ALUA
+        */
+       if (dev->se_sub_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED)
+               spc_fill_alua_data(lun->lun_sep, buf);
+
+       buf[7] = 0x2; /* CmdQue=1 */
+
+       snprintf(&buf[8], 8, "LIO-ORG");
+       snprintf(&buf[16], 16, "%s", dev->se_sub_dev->t10_wwn.model);
+       snprintf(&buf[32], 4, "%s", dev->se_sub_dev->t10_wwn.revision);
+       buf[4] = 31; /* Set additional length to 31 */
+
+       return 0;
+}
+
+/* unit serial number */
+static int spc_emulate_evpd_80(struct se_cmd *cmd, unsigned char *buf)
+{
+       struct se_device *dev = cmd->se_dev;
+       u16 len = 0;
+
+       if (dev->se_sub_dev->su_dev_flags &
+                       SDF_EMULATED_VPD_UNIT_SERIAL) {
+               u32 unit_serial_len;
+
+               unit_serial_len = strlen(dev->se_sub_dev->t10_wwn.unit_serial);
+               unit_serial_len++; /* For NULL Terminator */
+
+               len += sprintf(&buf[4], "%s",
+                       dev->se_sub_dev->t10_wwn.unit_serial);
+               len++; /* Extra Byte for NULL Terminator */
+               buf[3] = len;
+       }
+       return 0;
+}
+
+static void spc_parse_naa_6h_vendor_specific(struct se_device *dev,
+               unsigned char *buf)
+{
+       unsigned char *p = &dev->se_sub_dev->t10_wwn.unit_serial[0];
+       int cnt;
+       bool next = true;
+
+       /*
+        * Generate up to 36 bits of VENDOR SPECIFIC IDENTIFIER starting on
+        * byte 3 bit 3-0 for NAA IEEE Registered Extended DESIGNATOR field
+        * format, followed by 64 bits of VENDOR SPECIFIC IDENTIFIER EXTENSION
+        * to complete the payload.  These are based from VPD=0x80 PRODUCT SERIAL
+        * NUMBER set via vpd_unit_serial in target_core_configfs.c to ensure
+        * per device uniqeness.
+        */
+       for (cnt = 0; *p && cnt < 13; p++) {
+               int val = hex_to_bin(*p);
+
+               if (val < 0)
+                       continue;
+
+               if (next) {
+                       next = false;
+                       buf[cnt++] |= val;
+               } else {
+                       next = true;
+                       buf[cnt] = val << 4;
+               }
+       }
+}
+
+/*
+ * Device identification VPD, for a complete list of
+ * DESIGNATOR TYPEs see spc4r17 Table 459.
+ */
+static int spc_emulate_evpd_83(struct se_cmd *cmd, unsigned char *buf)
+{
+       struct se_device *dev = cmd->se_dev;
+       struct se_lun *lun = cmd->se_lun;
+       struct se_port *port = NULL;
+       struct se_portal_group *tpg = NULL;
+       struct t10_alua_lu_gp_member *lu_gp_mem;
+       struct t10_alua_tg_pt_gp *tg_pt_gp;
+       struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem;
+       unsigned char *prod = &dev->se_sub_dev->t10_wwn.model[0];
+       u32 prod_len;
+       u32 unit_serial_len, off = 0;
+       u16 len = 0, id_len;
+
+       off = 4;
+
+       /*
+        * NAA IEEE Registered Extended Assigned designator format, see
+        * spc4r17 section 7.7.3.6.5
+        *
+        * We depend upon a target_core_mod/ConfigFS provided
+        * /sys/kernel/config/target/core/$HBA/$DEV/wwn/vpd_unit_serial
+        * value in order to return the NAA id.
+        */
+       if (!(dev->se_sub_dev->su_dev_flags & SDF_EMULATED_VPD_UNIT_SERIAL))
+               goto check_t10_vend_desc;
+
+       /* CODE SET == Binary */
+       buf[off++] = 0x1;
+
+       /* Set ASSOCIATION == addressed logical unit: 0)b */
+       buf[off] = 0x00;
+
+       /* Identifier/Designator type == NAA identifier */
+       buf[off++] |= 0x3;
+       off++;
+
+       /* Identifier/Designator length */
+       buf[off++] = 0x10;
+
+       /*
+        * Start NAA IEEE Registered Extended Identifier/Designator
+        */
+       buf[off++] = (0x6 << 4);
+
+       /*
+        * Use OpenFabrics IEEE Company ID: 00 14 05
+        */
+       buf[off++] = 0x01;
+       buf[off++] = 0x40;
+       buf[off] = (0x5 << 4);
+
+       /*
+        * Return ConfigFS Unit Serial Number information for
+        * VENDOR_SPECIFIC_IDENTIFIER and
+        * VENDOR_SPECIFIC_IDENTIFIER_EXTENTION
+        */
+       spc_parse_naa_6h_vendor_specific(dev, &buf[off]);
+
+       len = 20;
+       off = (len + 4);
+
+check_t10_vend_desc:
+       /*
+        * T10 Vendor Identifier Page, see spc4r17 section 7.7.3.4
+        */
+       id_len = 8; /* For Vendor field */
+       prod_len = 4; /* For VPD Header */
+       prod_len += 8; /* For Vendor field */
+       prod_len += strlen(prod);
+       prod_len++; /* For : */
+
+       if (dev->se_sub_dev->su_dev_flags &
+                       SDF_EMULATED_VPD_UNIT_SERIAL) {
+               unit_serial_len =
+                       strlen(&dev->se_sub_dev->t10_wwn.unit_serial[0]);
+               unit_serial_len++; /* For NULL Terminator */
+
+               id_len += sprintf(&buf[off+12], "%s:%s", prod,
+                               &dev->se_sub_dev->t10_wwn.unit_serial[0]);
+       }
+       buf[off] = 0x2; /* ASCII */
+       buf[off+1] = 0x1; /* T10 Vendor ID */
+       buf[off+2] = 0x0;
+       memcpy(&buf[off+4], "LIO-ORG", 8);
+       /* Extra Byte for NULL Terminator */
+       id_len++;
+       /* Identifier Length */
+       buf[off+3] = id_len;
+       /* Header size for Designation descriptor */
+       len += (id_len + 4);
+       off += (id_len + 4);
+       /*
+        * struct se_port is only set for INQUIRY VPD=1 through $FABRIC_MOD
+        */
+       port = lun->lun_sep;
+       if (port) {
+               struct t10_alua_lu_gp *lu_gp;
+               u32 padding, scsi_name_len;
+               u16 lu_gp_id = 0;
+               u16 tg_pt_gp_id = 0;
+               u16 tpgt;
+
+               tpg = port->sep_tpg;
+               /*
+                * Relative target port identifer, see spc4r17
+                * section 7.7.3.7
+                *
+                * Get the PROTOCOL IDENTIFIER as defined by spc4r17
+                * section 7.5.1 Table 362
+                */
+               buf[off] =
+                       (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
+               buf[off++] |= 0x1; /* CODE SET == Binary */
+               buf[off] = 0x80; /* Set PIV=1 */
+               /* Set ASSOCIATION == target port: 01b */
+               buf[off] |= 0x10;
+               /* DESIGNATOR TYPE == Relative target port identifer */
+               buf[off++] |= 0x4;
+               off++; /* Skip over Reserved */
+               buf[off++] = 4; /* DESIGNATOR LENGTH */
+               /* Skip over Obsolete field in RTPI payload
+                * in Table 472 */
+               off += 2;
+               buf[off++] = ((port->sep_rtpi >> 8) & 0xff);
+               buf[off++] = (port->sep_rtpi & 0xff);
+               len += 8; /* Header size + Designation descriptor */
+               /*
+                * Target port group identifier, see spc4r17
+                * section 7.7.3.8
+                *
+                * Get the PROTOCOL IDENTIFIER as defined by spc4r17
+                * section 7.5.1 Table 362
+                */
+               if (dev->se_sub_dev->t10_alua.alua_type !=
+                               SPC3_ALUA_EMULATED)
+                       goto check_scsi_name;
+
+               tg_pt_gp_mem = port->sep_alua_tg_pt_gp_mem;
+               if (!tg_pt_gp_mem)
+                       goto check_lu_gp;
+
+               spin_lock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
+               tg_pt_gp = tg_pt_gp_mem->tg_pt_gp;
+               if (!tg_pt_gp) {
+                       spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
+                       goto check_lu_gp;
+               }
+               tg_pt_gp_id = tg_pt_gp->tg_pt_gp_id;
+               spin_unlock(&tg_pt_gp_mem->tg_pt_gp_mem_lock);
+
+               buf[off] =
+                       (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
+               buf[off++] |= 0x1; /* CODE SET == Binary */
+               buf[off] = 0x80; /* Set PIV=1 */
+               /* Set ASSOCIATION == target port: 01b */
+               buf[off] |= 0x10;
+               /* DESIGNATOR TYPE == Target port group identifier */
+               buf[off++] |= 0x5;
+               off++; /* Skip over Reserved */
+               buf[off++] = 4; /* DESIGNATOR LENGTH */
+               off += 2; /* Skip over Reserved Field */
+               buf[off++] = ((tg_pt_gp_id >> 8) & 0xff);
+               buf[off++] = (tg_pt_gp_id & 0xff);
+               len += 8; /* Header size + Designation descriptor */
+               /*
+                * Logical Unit Group identifier, see spc4r17
+                * section 7.7.3.8
+                */
+check_lu_gp:
+               lu_gp_mem = dev->dev_alua_lu_gp_mem;
+               if (!lu_gp_mem)
+                       goto check_scsi_name;
+
+               spin_lock(&lu_gp_mem->lu_gp_mem_lock);
+               lu_gp = lu_gp_mem->lu_gp;
+               if (!lu_gp) {
+                       spin_unlock(&lu_gp_mem->lu_gp_mem_lock);
+                       goto check_scsi_name;
+               }
+               lu_gp_id = lu_gp->lu_gp_id;
+               spin_unlock(&lu_gp_mem->lu_gp_mem_lock);
+
+               buf[off++] |= 0x1; /* CODE SET == Binary */
+               /* DESIGNATOR TYPE == Logical Unit Group identifier */
+               buf[off++] |= 0x6;
+               off++; /* Skip over Reserved */
+               buf[off++] = 4; /* DESIGNATOR LENGTH */
+               off += 2; /* Skip over Reserved Field */
+               buf[off++] = ((lu_gp_id >> 8) & 0xff);
+               buf[off++] = (lu_gp_id & 0xff);
+               len += 8; /* Header size + Designation descriptor */
+               /*
+                * SCSI name string designator, see spc4r17
+                * section 7.7.3.11
+                *
+                * Get the PROTOCOL IDENTIFIER as defined by spc4r17
+                * section 7.5.1 Table 362
+                */
+check_scsi_name:
+               scsi_name_len = strlen(tpg->se_tpg_tfo->tpg_get_wwn(tpg));
+               /* UTF-8 ",t,0x<16-bit TPGT>" + NULL Terminator */
+               scsi_name_len += 10;
+               /* Check for 4-byte padding */
+               padding = ((-scsi_name_len) & 3);
+               if (padding != 0)
+                       scsi_name_len += padding;
+               /* Header size + Designation descriptor */
+               scsi_name_len += 4;
+
+               buf[off] =
+                       (tpg->se_tpg_tfo->get_fabric_proto_ident(tpg) << 4);
+               buf[off++] |= 0x3; /* CODE SET == UTF-8 */
+               buf[off] = 0x80; /* Set PIV=1 */
+               /* Set ASSOCIATION == target port: 01b */
+               buf[off] |= 0x10;
+               /* DESIGNATOR TYPE == SCSI name string */
+               buf[off++] |= 0x8;
+               off += 2; /* Skip over Reserved and length */
+               /*
+                * SCSI name string identifer containing, $FABRIC_MOD
+                * dependent information.  For LIO-Target and iSCSI
+                * Target Port, this means "<iSCSI name>,t,0x<TPGT> in
+                * UTF-8 encoding.
+                */
+               tpgt = tpg->se_tpg_tfo->tpg_get_tag(tpg);
+               scsi_name_len = sprintf(&buf[off], "%s,t,0x%04x",
+                                       tpg->se_tpg_tfo->tpg_get_wwn(tpg), tpgt);
+               scsi_name_len += 1 /* Include  NULL terminator */;
+               /*
+                * The null-terminated, null-padded (see 4.4.2) SCSI
+                * NAME STRING field contains a UTF-8 format string.
+                * The number of bytes in the SCSI NAME STRING field
+                * (i.e., the value in the DESIGNATOR LENGTH field)
+                * shall be no larger than 256 and shall be a multiple
+                * of four.
+                */
+               if (padding)
+                       scsi_name_len += padding;
+
+               buf[off-1] = scsi_name_len;
+               off += scsi_name_len;
+               /* Header size + Designation descriptor */
+               len += (scsi_name_len + 4);
+       }
+       buf[2] = ((len >> 8) & 0xff);
+       buf[3] = (len & 0xff); /* Page Length for VPD 0x83 */
+       return 0;
+}
+
+/* Extended INQUIRY Data VPD Page */
+static int spc_emulate_evpd_86(struct se_cmd *cmd, unsigned char *buf)
+{
+       buf[3] = 0x3c;
+       /* Set HEADSUP, ORDSUP, SIMPSUP */
+       buf[5] = 0x07;
+
+       /* If WriteCache emulation is enabled, set V_SUP */
+       if (cmd->se_dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0)
+               buf[6] = 0x01;
+       return 0;
+}
+
+/* Block Limits VPD page */
+static int spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
+{
+       struct se_device *dev = cmd->se_dev;
+       u32 max_sectors;
+       int have_tp = 0;
+
+       /*
+        * Following spc3r22 section 6.5.3 Block Limits VPD page, when
+        * emulate_tpu=1 or emulate_tpws=1 we will be expect a
+        * different page length for Thin Provisioning.
+        */
+       if (dev->se_sub_dev->se_dev_attrib.emulate_tpu || dev->se_sub_dev->se_dev_attrib.emulate_tpws)
+               have_tp = 1;
+
+       buf[0] = dev->transport->get_device_type(dev);
+       buf[3] = have_tp ? 0x3c : 0x10;
+
+       /* Set WSNZ to 1 */
+       buf[4] = 0x01;
+
+       /*
+        * Set OPTIMAL TRANSFER LENGTH GRANULARITY
+        */
+       put_unaligned_be16(1, &buf[6]);
+
+       /*
+        * Set MAXIMUM TRANSFER LENGTH
+        */
+       max_sectors = min(dev->se_sub_dev->se_dev_attrib.fabric_max_sectors,
+                         dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
+       put_unaligned_be32(max_sectors, &buf[8]);
+
+       /*
+        * Set OPTIMAL TRANSFER LENGTH
+        */
+       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.optimal_sectors, &buf[12]);
+
+       /*
+        * Exit now if we don't support TP.
+        */
+       if (!have_tp)
+               return 0;
+
+       /*
+        * Set MAXIMUM UNMAP LBA COUNT
+        */
+       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_unmap_lba_count, &buf[20]);
+
+       /*
+        * Set MAXIMUM UNMAP BLOCK DESCRIPTOR COUNT
+        */
+       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count,
+                          &buf[24]);
+
+       /*
+        * Set OPTIMAL UNMAP GRANULARITY
+        */
+       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.unmap_granularity, &buf[28]);
+
+       /*
+        * UNMAP GRANULARITY ALIGNMENT
+        */
+       put_unaligned_be32(dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment,
+                          &buf[32]);
+       if (dev->se_sub_dev->se_dev_attrib.unmap_granularity_alignment != 0)
+               buf[32] |= 0x80; /* Set the UGAVALID bit */
+
+       return 0;
+}
+
+/* Block Device Characteristics VPD page */
+static int spc_emulate_evpd_b1(struct se_cmd *cmd, unsigned char *buf)
+{
+       struct se_device *dev = cmd->se_dev;
+
+       buf[0] = dev->transport->get_device_type(dev);
+       buf[3] = 0x3c;
+       buf[5] = dev->se_sub_dev->se_dev_attrib.is_nonrot ? 1 : 0;
+
+       return 0;
+}
+
+/* Thin Provisioning VPD */
+static int spc_emulate_evpd_b2(struct se_cmd *cmd, unsigned char *buf)
+{
+       struct se_device *dev = cmd->se_dev;
+
+       /*
+        * From spc3r22 section 6.5.4 Thin Provisioning VPD page:
+        *
+        * The PAGE LENGTH field is defined in SPC-4. If the DP bit is set to
+        * zero, then the page length shall be set to 0004h.  If the DP bit
+        * is set to one, then the page length shall be set to the value
+        * defined in table 162.
+        */
+       buf[0] = dev->transport->get_device_type(dev);
+
+       /*
+        * Set Hardcoded length mentioned above for DP=0
+        */
+       put_unaligned_be16(0x0004, &buf[2]);
+
+       /*
+        * The THRESHOLD EXPONENT field indicates the threshold set size in
+        * LBAs as a power of 2 (i.e., the threshold set size is equal to
+        * 2(threshold exponent)).
+        *
+        * Note that this is currently set to 0x00 as mkp says it will be
+        * changing again.  We can enable this once it has settled in T10
+        * and is actually used by Linux/SCSI ML code.
+        */
+       buf[4] = 0x00;
+
+       /*
+        * A TPU bit set to one indicates that the device server supports
+        * the UNMAP command (see 5.25). A TPU bit set to zero indicates
+        * that the device server does not support the UNMAP command.
+        */
+       if (dev->se_sub_dev->se_dev_attrib.emulate_tpu != 0)
+               buf[5] = 0x80;
+
+       /*
+        * A TPWS bit set to one indicates that the device server supports
+        * the use of the WRITE SAME (16) command (see 5.42) to unmap LBAs.
+        * A TPWS bit set to zero indicates that the device server does not
+        * support the use of the WRITE SAME (16) command to unmap LBAs.
+        */
+       if (dev->se_sub_dev->se_dev_attrib.emulate_tpws != 0)
+               buf[5] |= 0x40;
+
+       return 0;
+}
+
+static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf);
+
+static struct {
+       uint8_t         page;
+       int             (*emulate)(struct se_cmd *, unsigned char *);
+} evpd_handlers[] = {
+       { .page = 0x00, .emulate = spc_emulate_evpd_00 },
+       { .page = 0x80, .emulate = spc_emulate_evpd_80 },
+       { .page = 0x83, .emulate = spc_emulate_evpd_83 },
+       { .page = 0x86, .emulate = spc_emulate_evpd_86 },
+       { .page = 0xb0, .emulate = spc_emulate_evpd_b0 },
+       { .page = 0xb1, .emulate = spc_emulate_evpd_b1 },
+       { .page = 0xb2, .emulate = spc_emulate_evpd_b2 },
+};
+
+/* supported vital product data pages */
+static int spc_emulate_evpd_00(struct se_cmd *cmd, unsigned char *buf)
+{
+       int p;
+
+       /*
+        * Only report the INQUIRY EVPD=1 pages after a valid NAA
+        * Registered Extended LUN WWN has been set via ConfigFS
+        * during device creation/restart.
+        */
+       if (cmd->se_dev->se_sub_dev->su_dev_flags &
+                       SDF_EMULATED_VPD_UNIT_SERIAL) {
+               buf[3] = ARRAY_SIZE(evpd_handlers);
+               for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p)
+                       buf[p + 4] = evpd_handlers[p].page;
+       }
+
+       return 0;
+}
+
+static int spc_emulate_inquiry(struct se_cmd *cmd)
+{
+       struct se_device *dev = cmd->se_dev;
+       struct se_portal_group *tpg = cmd->se_lun->lun_sep->sep_tpg;
+       unsigned char *buf, *map_buf;
+       unsigned char *cdb = cmd->t_task_cdb;
+       int p, ret;
+
+       map_buf = transport_kmap_data_sg(cmd);
+       /*
+        * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we
+        * know we actually allocated a full page.  Otherwise, if the
+        * data buffer is too small, allocate a temporary buffer so we
+        * don't have to worry about overruns in all our INQUIRY
+        * emulation handling.
+        */
+       if (cmd->data_length < SE_INQUIRY_BUF &&
+           (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) {
+               buf = kzalloc(SE_INQUIRY_BUF, GFP_KERNEL);
+               if (!buf) {
+                       transport_kunmap_data_sg(cmd);
+                       cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+                       return -ENOMEM;
+               }
+       } else {
+               buf = map_buf;
+       }
+
+       if (dev == tpg->tpg_virt_lun0.lun_se_dev)
+               buf[0] = 0x3f; /* Not connected */
+       else
+               buf[0] = dev->transport->get_device_type(dev);
+
+       if (!(cdb[1] & 0x1)) {
+               if (cdb[2]) {
+                       pr_err("INQUIRY with EVPD==0 but PAGE CODE=%02x\n",
+                              cdb[2]);
+                       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+                       ret = -EINVAL;
+                       goto out;
+               }
+
+               ret = spc_emulate_inquiry_std(cmd, buf);
+               goto out;
+       }
+
+       for (p = 0; p < ARRAY_SIZE(evpd_handlers); ++p) {
+               if (cdb[2] == evpd_handlers[p].page) {
+                       buf[1] = cdb[2];
+                       ret = evpd_handlers[p].emulate(cmd, buf);
+                       goto out;
+               }
+       }
+
+       pr_err("Unknown VPD Code: 0x%02x\n", cdb[2]);
+       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+       ret = -EINVAL;
+
+out:
+       if (buf != map_buf) {
+               memcpy(map_buf, buf, cmd->data_length);
+               kfree(buf);
+       }
+       transport_kunmap_data_sg(cmd);
+
+       if (!ret)
+               target_complete_cmd(cmd, GOOD);
+       return ret;
+}
+
+static int spc_modesense_rwrecovery(unsigned char *p)
+{
+       p[0] = 0x01;
+       p[1] = 0x0a;
+
+       return 12;
+}
+
+static int spc_modesense_control(struct se_device *dev, unsigned char *p)
+{
+       p[0] = 0x0a;
+       p[1] = 0x0a;
+       p[2] = 2;
+       /*
+        * From spc4r23, 7.4.7 Control mode page
+        *
+        * The QUEUE ALGORITHM MODIFIER field (see table 368) specifies
+        * restrictions on the algorithm used for reordering commands
+        * having the SIMPLE task attribute (see SAM-4).
+        *
+        *                    Table 368 -- QUEUE ALGORITHM MODIFIER field
+        *                         Code      Description
+        *                          0h       Restricted reordering
+        *                          1h       Unrestricted reordering allowed
+        *                          2h to 7h    Reserved
+        *                          8h to Fh    Vendor specific
+        *
+        * A value of zero in the QUEUE ALGORITHM MODIFIER field specifies that
+        * the device server shall order the processing sequence of commands
+        * having the SIMPLE task attribute such that data integrity is maintained
+        * for that I_T nexus (i.e., if the transmission of new SCSI transport protocol
+        * requests is halted at any time, the final value of all data observable
+        * on the medium shall be the same as if all the commands had been processed
+        * with the ORDERED task attribute).
+        *
+        * A value of one in the QUEUE ALGORITHM MODIFIER field specifies that the
+        * device server may reorder the processing sequence of commands having the
+        * SIMPLE task attribute in any manner. Any data integrity exposures related to
+        * command sequence order shall be explicitly handled by the application client
+        * through the selection of appropriate ommands and task attributes.
+        */
+       p[3] = (dev->se_sub_dev->se_dev_attrib.emulate_rest_reord == 1) ? 0x00 : 0x10;
+       /*
+        * From spc4r17, section 7.4.6 Control mode Page
+        *
+        * Unit Attention interlocks control (UN_INTLCK_CTRL) to code 00b
+        *
+        * 00b: The logical unit shall clear any unit attention condition
+        * reported in the same I_T_L_Q nexus transaction as a CHECK CONDITION
+        * status and shall not establish a unit attention condition when a com-
+        * mand is completed with BUSY, TASK SET FULL, or RESERVATION CONFLICT
+        * status.
+        *
+        * 10b: The logical unit shall not clear any unit attention condition
+        * reported in the same I_T_L_Q nexus transaction as a CHECK CONDITION
+        * status and shall not establish a unit attention condition when
+        * a command is completed with BUSY, TASK SET FULL, or RESERVATION
+        * CONFLICT status.
+        *
+        * 11b a The logical unit shall not clear any unit attention condition
+        * reported in the same I_T_L_Q nexus transaction as a CHECK CONDITION
+        * status and shall establish a unit attention condition for the
+        * initiator port associated with the I_T nexus on which the BUSY,
+        * TASK SET FULL, or RESERVATION CONFLICT status is being returned.
+        * Depending on the status, the additional sense code shall be set to
+        * PREVIOUS BUSY STATUS, PREVIOUS TASK SET FULL STATUS, or PREVIOUS
+        * RESERVATION CONFLICT STATUS. Until it is cleared by a REQUEST SENSE
+        * command, a unit attention condition shall be established only once
+        * for a BUSY, TASK SET FULL, or RESERVATION CONFLICT status regardless
+        * to the number of commands completed with one of those status codes.
+        */
+       p[4] = (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 2) ? 0x30 :
+              (dev->se_sub_dev->se_dev_attrib.emulate_ua_intlck_ctrl == 1) ? 0x20 : 0x00;
+       /*
+        * From spc4r17, section 7.4.6 Control mode Page
+        *
+        * Task Aborted Status (TAS) bit set to zero.
+        *
+        * A task aborted status (TAS) bit set to zero specifies that aborted
+        * tasks shall be terminated by the device server without any response
+        * to the application client. A TAS bit set to one specifies that tasks
+        * aborted by the actions of an I_T nexus other than the I_T nexus on
+        * which the command was received shall be completed with TASK ABORTED
+        * status (see SAM-4).
+        */
+       p[5] = (dev->se_sub_dev->se_dev_attrib.emulate_tas) ? 0x40 : 0x00;
+       p[8] = 0xff;
+       p[9] = 0xff;
+       p[11] = 30;
+
+       return 12;
+}
+
+static int spc_modesense_caching(struct se_device *dev, unsigned char *p)
+{
+       p[0] = 0x08;
+       p[1] = 0x12;
+       if (dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0)
+               p[2] = 0x04; /* Write Cache Enable */
+       p[12] = 0x20; /* Disabled Read Ahead */
+
+       return 20;
+}
+
+static void spc_modesense_write_protect(unsigned char *buf, int type)
+{
+       /*
+        * I believe that the WP bit (bit 7) in the mode header is the same for
+        * all device types..
+        */
+       switch (type) {
+       case TYPE_DISK:
+       case TYPE_TAPE:
+       default:
+               buf[0] |= 0x80; /* WP bit */
+               break;
+       }
+}
+
+static void spc_modesense_dpofua(unsigned char *buf, int type)
+{
+       switch (type) {
+       case TYPE_DISK:
+               buf[0] |= 0x10; /* DPOFUA bit */
+               break;
+       default:
+               break;
+       }
+}
+
+static int spc_emulate_modesense(struct se_cmd *cmd)
+{
+       struct se_device *dev = cmd->se_dev;
+       char *cdb = cmd->t_task_cdb;
+       unsigned char *rbuf;
+       int type = dev->transport->get_device_type(dev);
+       int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10);
+       int offset = ten ? 8 : 4;
+       int length = 0;
+       unsigned char buf[SE_MODE_PAGE_BUF];
+
+       memset(buf, 0, SE_MODE_PAGE_BUF);
+
+       switch (cdb[2] & 0x3f) {
+       case 0x01:
+               length = spc_modesense_rwrecovery(&buf[offset]);
+               break;
+       case 0x08:
+               length = spc_modesense_caching(dev, &buf[offset]);
+               break;
+       case 0x0a:
+               length = spc_modesense_control(dev, &buf[offset]);
+               break;
+       case 0x3f:
+               length = spc_modesense_rwrecovery(&buf[offset]);
+               length += spc_modesense_caching(dev, &buf[offset+length]);
+               length += spc_modesense_control(dev, &buf[offset+length]);
+               break;
+       default:
+               pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n",
+                      cdb[2] & 0x3f, cdb[3]);
+               cmd->scsi_sense_reason = TCM_UNKNOWN_MODE_PAGE;
+               return -EINVAL;
+       }
+       offset += length;
+
+       if (ten) {
+               offset -= 2;
+               buf[0] = (offset >> 8) & 0xff;
+               buf[1] = offset & 0xff;
+
+               if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
+                   (cmd->se_deve &&
+                   (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
+                       spc_modesense_write_protect(&buf[3], type);
+
+               if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
+                   (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
+                       spc_modesense_dpofua(&buf[3], type);
+
+               if ((offset + 2) > cmd->data_length)
+                       offset = cmd->data_length;
+
+       } else {
+               offset -= 1;
+               buf[0] = offset & 0xff;
+
+               if ((cmd->se_lun->lun_access & TRANSPORT_LUNFLAGS_READ_ONLY) ||
+                   (cmd->se_deve &&
+                   (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY)))
+                       spc_modesense_write_protect(&buf[2], type);
+
+               if ((dev->se_sub_dev->se_dev_attrib.emulate_write_cache > 0) &&
+                   (dev->se_sub_dev->se_dev_attrib.emulate_fua_write > 0))
+                       spc_modesense_dpofua(&buf[2], type);
+
+               if ((offset + 1) > cmd->data_length)
+                       offset = cmd->data_length;
+       }
+
+       rbuf = transport_kmap_data_sg(cmd);
+       memcpy(rbuf, buf, offset);
+       transport_kunmap_data_sg(cmd);
+
+       target_complete_cmd(cmd, GOOD);
+       return 0;
+}
+
+static int spc_emulate_request_sense(struct se_cmd *cmd)
+{
+       unsigned char *cdb = cmd->t_task_cdb;
+       unsigned char *buf;
+       u8 ua_asc = 0, ua_ascq = 0;
+       int err = 0;
+
+       if (cdb[1] & 0x01) {
+               pr_err("REQUEST_SENSE description emulation not"
+                       " supported\n");
+               cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+               return -ENOSYS;
+       }
+
+       buf = transport_kmap_data_sg(cmd);
+
+       if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
+               /*
+                * CURRENT ERROR, UNIT ATTENTION
+                */
+               buf[0] = 0x70;
+               buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
+
+               if (cmd->data_length < 18) {
+                       buf[7] = 0x00;
+                       err = -EINVAL;
+                       goto end;
+               }
+               /*
+                * The Additional Sense Code (ASC) from the UNIT ATTENTION
+                */
+               buf[SPC_ASC_KEY_OFFSET] = ua_asc;
+               buf[SPC_ASCQ_KEY_OFFSET] = ua_ascq;
+               buf[7] = 0x0A;
+       } else {
+               /*
+                * CURRENT ERROR, NO SENSE
+                */
+               buf[0] = 0x70;
+               buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE;
+
+               if (cmd->data_length < 18) {
+                       buf[7] = 0x00;
+                       err = -EINVAL;
+                       goto end;
+               }
+               /*
+                * NO ADDITIONAL SENSE INFORMATION
+                */
+               buf[SPC_ASC_KEY_OFFSET] = 0x00;
+               buf[7] = 0x0A;
+       }
+
+end:
+       transport_kunmap_data_sg(cmd);
+       target_complete_cmd(cmd, GOOD);
+       return 0;
+}
+
+static int spc_emulate_testunitready(struct se_cmd *cmd)
+{
+       target_complete_cmd(cmd, GOOD);
+       return 0;
+}
+
+int spc_parse_cdb(struct se_cmd *cmd, unsigned int *size)
+{
+       struct se_device *dev = cmd->se_dev;
+       struct se_subsystem_dev *su_dev = dev->se_sub_dev;
+       unsigned char *cdb = cmd->t_task_cdb;
+
+       switch (cdb[0]) {
+       case MODE_SELECT:
+               *size = cdb[4];
+               break;
+       case MODE_SELECT_10:
+               *size = (cdb[7] << 8) + cdb[8];
+               break;
+       case MODE_SENSE:
+               *size = cdb[4];
+               cmd->execute_cmd = spc_emulate_modesense;
+               break;
+       case MODE_SENSE_10:
+               *size = (cdb[7] << 8) + cdb[8];
+               cmd->execute_cmd = spc_emulate_modesense;
+               break;
+       case LOG_SELECT:
+       case LOG_SENSE:
+               *size = (cdb[7] << 8) + cdb[8];
+               break;
+       case PERSISTENT_RESERVE_IN:
+               if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
+                       cmd->execute_cmd = target_scsi3_emulate_pr_in;
+               *size = (cdb[7] << 8) + cdb[8];
+               break;
+       case PERSISTENT_RESERVE_OUT:
+               if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
+                       cmd->execute_cmd = target_scsi3_emulate_pr_out;
+               *size = (cdb[7] << 8) + cdb[8];
+               break;
+       case RELEASE:
+       case RELEASE_10:
+               if (cdb[0] == RELEASE_10)
+                       *size = (cdb[7] << 8) | cdb[8];
+               else
+                       *size = cmd->data_length;
+
+               if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
+                       cmd->execute_cmd = target_scsi2_reservation_release;
+               break;
+       case RESERVE:
+       case RESERVE_10:
+               /*
+                * The SPC-2 RESERVE does not contain a size in the SCSI CDB.
+                * Assume the passthrough or $FABRIC_MOD will tell us about it.
+                */
+               if (cdb[0] == RESERVE_10)
+                       *size = (cdb[7] << 8) | cdb[8];
+               else
+                       *size = cmd->data_length;
+
+               /*
+                * Setup the legacy emulated handler for SPC-2 and
+                * >= SPC-3 compatible reservation handling (CRH=1)
+                * Otherwise, we assume the underlying SCSI logic is
+                * is running in SPC_PASSTHROUGH, and wants reservations
+                * emulation disabled.
+                */
+               if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
+                       cmd->execute_cmd = target_scsi2_reservation_reserve;
+               break;
+       case REQUEST_SENSE:
+               *size = cdb[4];
+               cmd->execute_cmd = spc_emulate_request_sense;
+               break;
+       case INQUIRY:
+               *size = (cdb[3] << 8) + cdb[4];
+
+               /*
+                * Do implict HEAD_OF_QUEUE processing for INQUIRY.
+                * See spc4r17 section 5.3
+                */
+               if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
+                       cmd->sam_task_attr = MSG_HEAD_TAG;
+               cmd->execute_cmd = spc_emulate_inquiry;
+               break;
+       case SECURITY_PROTOCOL_IN:
+       case SECURITY_PROTOCOL_OUT:
+               *size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
+               break;
+       case EXTENDED_COPY:
+       case READ_ATTRIBUTE:
+       case RECEIVE_COPY_RESULTS:
+       case WRITE_ATTRIBUTE:
+               *size = (cdb[10] << 24) | (cdb[11] << 16) |
+                      (cdb[12] << 8) | cdb[13];
+               break;
+       case RECEIVE_DIAGNOSTIC:
+       case SEND_DIAGNOSTIC:
+               *size = (cdb[3] << 8) | cdb[4];
+               break;
+       case WRITE_BUFFER:
+               *size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
+               break;
+       case REPORT_LUNS:
+               cmd->execute_cmd = target_report_luns;
+               *size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
+               /*
+                * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS
+                * See spc4r17 section 5.3
+                */
+               if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
+                       cmd->sam_task_attr = MSG_HEAD_TAG;
+               break;
+       case TEST_UNIT_READY:
+               cmd->execute_cmd = spc_emulate_testunitready;
+               *size = 0;
+               break;
+       case MAINTENANCE_IN:
+               if (dev->transport->get_device_type(dev) != TYPE_ROM) {
+                       /*
+                        * MAINTENANCE_IN from SCC-2
+                        * Check for emulated MI_REPORT_TARGET_PGS
+                        */
+                       if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS &&
+                           su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
+                               cmd->execute_cmd =
+                                       target_emulate_report_target_port_groups;
+                       }
+                       *size = get_unaligned_be32(&cdb[6]);
+               } else {
+                       /*
+                        * GPCMD_SEND_KEY from multi media commands
+                        */
+                       *size = get_unaligned_be16(&cdb[8]);
+               }
+               break;
+       case MAINTENANCE_OUT:
+               if (dev->transport->get_device_type(dev) != TYPE_ROM) {
+                       /*
+                        * MAINTENANCE_OUT from SCC-2
+                        * Check for emulated MO_SET_TARGET_PGS.
+                        */
+                       if (cdb[1] == MO_SET_TARGET_PGS &&
+                           su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
+                               cmd->execute_cmd =
+                                       target_emulate_set_target_port_groups;
+                       }
+                       *size = get_unaligned_be32(&cdb[6]);
+               } else {
+                       /*
+                        * GPCMD_SEND_KEY from multi media commands
+                        */
+                       *size = get_unaligned_be16(&cdb[8]);
+               }
+               break;
+       default:
+               pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode"
+                       " 0x%02x, sending CHECK_CONDITION.\n",
+                       cmd->se_tfo->get_fabric_name(), cdb[0]);
+               cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+               cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
+               return -EINVAL;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(spc_parse_cdb);
index 84caf1bed9a3392ede0686851f5d90bae80bd83d..1c59a3c23b2c1b37ee8a3c54d62b8c66ea6f9e87 100644 (file)
@@ -295,9 +295,6 @@ static void core_tmr_drain_state_list(
 
                list_move_tail(&cmd->state_list, &drain_task_list);
                cmd->state_active = false;
-
-               if (!list_empty(&cmd->execute_list))
-                       __target_remove_from_execute_list(cmd);
        }
        spin_unlock_irqrestore(&dev->execute_task_lock, flags);
 
@@ -354,57 +351,6 @@ static void core_tmr_drain_state_list(
        }
 }
 
-static void core_tmr_drain_cmd_list(
-       struct se_device *dev,
-       struct se_cmd *prout_cmd,
-       struct se_node_acl *tmr_nacl,
-       int tas,
-       struct list_head *preempt_and_abort_list)
-{
-       LIST_HEAD(drain_cmd_list);
-       struct se_queue_obj *qobj = &dev->dev_queue_obj;
-       struct se_cmd *cmd, *tcmd;
-       unsigned long flags;
-
-       /*
-        * Release all commands remaining in the per-device command queue.
-        *
-        * This follows the same logic as above for the state list.
-        */
-       spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
-       list_for_each_entry_safe(cmd, tcmd, &qobj->qobj_list, se_queue_node) {
-               /*
-                * For PREEMPT_AND_ABORT usage, only process commands
-                * with a matching reservation key.
-                */
-               if (target_check_cdb_and_preempt(preempt_and_abort_list, cmd))
-                       continue;
-               /*
-                * Not aborting PROUT PREEMPT_AND_ABORT CDB..
-                */
-               if (prout_cmd == cmd)
-                       continue;
-
-               cmd->transport_state &= ~CMD_T_QUEUED;
-               atomic_dec(&qobj->queue_cnt);
-               list_move_tail(&cmd->se_queue_node, &drain_cmd_list);
-       }
-       spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
-
-       while (!list_empty(&drain_cmd_list)) {
-               cmd = list_entry(drain_cmd_list.next, struct se_cmd, se_queue_node);
-               list_del_init(&cmd->se_queue_node);
-
-               pr_debug("LUN_RESET: %s from Device Queue: cmd: %p t_state:"
-                       " %d t_fe_count: %d\n", (preempt_and_abort_list) ?
-                       "Preempt" : "", cmd, cmd->t_state,
-                       atomic_read(&cmd->t_fe_count));
-
-               core_tmr_handle_tas_abort(tmr_nacl, cmd, tas,
-                               atomic_read(&cmd->t_fe_count));
-       }
-}
-
 int core_tmr_lun_reset(
         struct se_device *dev,
         struct se_tmr_req *tmr,
@@ -447,8 +393,7 @@ int core_tmr_lun_reset(
        core_tmr_drain_tmr_list(dev, tmr, preempt_and_abort_list);
        core_tmr_drain_state_list(dev, prout_cmd, tmr_nacl, tas,
                                preempt_and_abort_list);
-       core_tmr_drain_cmd_list(dev, prout_cmd, tmr_nacl, tas,
-                               preempt_and_abort_list);
+
        /*
         * Clear any legacy SPC-2 reservation when called during
         * LOGICAL UNIT RESET
index 8bd58e284185bab23b8df5d4a554eeae945c8b04..b8628a5014b9ecb45151e52496845a33be06bfc2 100644 (file)
@@ -77,8 +77,8 @@ static void core_clear_initiator_node_from_tpg(
 
                lun = deve->se_lun;
                spin_unlock_irq(&nacl->device_list_lock);
-               core_update_device_list_for_node(lun, NULL, deve->mapped_lun,
-                       TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg, 0);
+               core_disable_device_list_for_node(lun, NULL, deve->mapped_lun,
+                       TRANSPORT_LUNFLAGS_NO_ACCESS, nacl, tpg);
 
                spin_lock_irq(&nacl->device_list_lock);
        }
@@ -172,8 +172,8 @@ void core_tpg_add_node_to_devs(
                        (lun_access == TRANSPORT_LUNFLAGS_READ_WRITE) ?
                        "READ-WRITE" : "READ-ONLY");
 
-               core_update_device_list_for_node(lun, NULL, lun->unpacked_lun,
-                               lun_access, acl, tpg, 1);
+               core_enable_device_list_for_node(lun, NULL, lun->unpacked_lun,
+                               lun_access, acl, tpg);
                spin_lock(&tpg->tpg_lun_lock);
        }
        spin_unlock(&tpg->tpg_lun_lock);
@@ -306,10 +306,8 @@ struct se_node_acl *core_tpg_check_initiator_node_acl(
         * TPG LUNs if the fabric is not explictly asking for
         * tpg_check_demo_mode_login_only() == 1.
         */
-       if ((tpg->se_tpg_tfo->tpg_check_demo_mode_login_only != NULL) &&
-           (tpg->se_tpg_tfo->tpg_check_demo_mode_login_only(tpg) == 1))
-               do { ; } while (0);
-       else
+       if ((tpg->se_tpg_tfo->tpg_check_demo_mode_login_only == NULL) ||
+           (tpg->se_tpg_tfo->tpg_check_demo_mode_login_only(tpg) != 1))
                core_tpg_add_node_to_devs(acl, tpg);
 
        spin_lock_irq(&tpg->acl_node_lock);
index 634d0f31a28cc59f621ea6122a13777c320339d5..0eaae23d12b576547fa51f25ed8f05579f6ec646 100644 (file)
@@ -66,15 +66,12 @@ struct kmem_cache *t10_alua_lu_gp_mem_cache;
 struct kmem_cache *t10_alua_tg_pt_gp_cache;
 struct kmem_cache *t10_alua_tg_pt_gp_mem_cache;
 
-static int transport_generic_write_pending(struct se_cmd *);
-static int transport_processing_thread(void *param);
-static int __transport_execute_tasks(struct se_device *dev, struct se_cmd *);
 static void transport_complete_task_attr(struct se_cmd *cmd);
 static void transport_handle_queue_full(struct se_cmd *cmd,
                struct se_device *dev);
 static int transport_generic_get_mem(struct se_cmd *cmd);
+static int target_get_sess_cmd(struct se_session *, struct se_cmd *, bool);
 static void transport_put_cmd(struct se_cmd *cmd);
-static void transport_remove_cmd_from_queue(struct se_cmd *cmd);
 static int transport_set_sense_codes(struct se_cmd *cmd, u8 asc, u8 ascq);
 static void target_complete_ok_work(struct work_struct *work);
 
@@ -195,14 +192,6 @@ u32 scsi_get_new_index(scsi_index_t type)
        return new_index;
 }
 
-static void transport_init_queue_obj(struct se_queue_obj *qobj)
-{
-       atomic_set(&qobj->queue_cnt, 0);
-       INIT_LIST_HEAD(&qobj->qobj_list);
-       init_waitqueue_head(&qobj->thread_wq);
-       spin_lock_init(&qobj->cmd_queue_lock);
-}
-
 void transport_subsystem_check_init(void)
 {
        int ret;
@@ -243,7 +232,6 @@ struct se_session *transport_init_session(void)
        INIT_LIST_HEAD(&se_sess->sess_list);
        INIT_LIST_HEAD(&se_sess->sess_acl_list);
        INIT_LIST_HEAD(&se_sess->sess_cmd_list);
-       INIT_LIST_HEAD(&se_sess->sess_wait_list);
        spin_lock_init(&se_sess->sess_cmd_lock);
        kref_init(&se_sess->sess_kref);
 
@@ -468,18 +456,7 @@ static void target_remove_from_state_list(struct se_cmd *cmd)
        spin_unlock_irqrestore(&dev->execute_task_lock, flags);
 }
 
-/*     transport_cmd_check_stop():
- *
- *     'transport_off = 1' determines if CMD_T_ACTIVE should be cleared.
- *     'transport_off = 2' determines if task_dev_state should be removed.
- *
- *     A non-zero u8 t_state sets cmd->t_state.
- *     Returns 1 when command is stopped, else 0.
- */
-static int transport_cmd_check_stop(
-       struct se_cmd *cmd,
-       int transport_off,
-       u8 t_state)
+static int transport_cmd_check_stop(struct se_cmd *cmd, bool remove_from_lists)
 {
        unsigned long flags;
 
@@ -493,13 +470,23 @@ static int transport_cmd_check_stop(
                        __func__, __LINE__, cmd->se_tfo->get_task_tag(cmd));
 
                cmd->transport_state &= ~CMD_T_ACTIVE;
-               if (transport_off == 2)
+               if (remove_from_lists)
                        target_remove_from_state_list(cmd);
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
                complete(&cmd->transport_lun_stop_comp);
                return 1;
        }
+
+       if (remove_from_lists) {
+               target_remove_from_state_list(cmd);
+
+               /*
+                * Clear struct se_cmd->se_lun before the handoff to FE.
+                */
+               cmd->se_lun = NULL;
+       }
+
        /*
         * Determine if frontend context caller is requesting the stopping of
         * this command for frontend exceptions.
@@ -509,58 +496,36 @@ static int transport_cmd_check_stop(
                        __func__, __LINE__,
                        cmd->se_tfo->get_task_tag(cmd));
 
-               if (transport_off == 2)
-                       target_remove_from_state_list(cmd);
-
-               /*
-                * Clear struct se_cmd->se_lun before the transport_off == 2 handoff
-                * to FE.
-                */
-               if (transport_off == 2)
-                       cmd->se_lun = NULL;
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
                complete(&cmd->t_transport_stop_comp);
                return 1;
        }
-       if (transport_off) {
-               cmd->transport_state &= ~CMD_T_ACTIVE;
-               if (transport_off == 2) {
-                       target_remove_from_state_list(cmd);
-                       /*
-                        * Clear struct se_cmd->se_lun before the transport_off == 2
-                        * handoff to fabric module.
-                        */
-                       cmd->se_lun = NULL;
-                       /*
-                        * Some fabric modules like tcm_loop can release
-                        * their internally allocated I/O reference now and
-                        * struct se_cmd now.
-                        *
-                        * Fabric modules are expected to return '1' here if the
-                        * se_cmd being passed is released at this point,
-                        * or zero if not being released.
-                        */
-                       if (cmd->se_tfo->check_stop_free != NULL) {
-                               spin_unlock_irqrestore(
-                                       &cmd->t_state_lock, flags);
-
-                               return cmd->se_tfo->check_stop_free(cmd);
-                       }
+
+       cmd->transport_state &= ~CMD_T_ACTIVE;
+       if (remove_from_lists) {
+               /*
+                * Some fabric modules like tcm_loop can release
+                * their internally allocated I/O reference now and
+                * struct se_cmd now.
+                *
+                * Fabric modules are expected to return '1' here if the
+                * se_cmd being passed is released at this point,
+                * or zero if not being released.
+                */
+               if (cmd->se_tfo->check_stop_free != NULL) {
+                       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+                       return cmd->se_tfo->check_stop_free(cmd);
                }
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+       }
 
-               return 0;
-       } else if (t_state)
-               cmd->t_state = t_state;
        spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
        return 0;
 }
 
 static int transport_cmd_check_stop_to_fabric(struct se_cmd *cmd)
 {
-       return transport_cmd_check_stop(cmd, 2, 0);
+       return transport_cmd_check_stop(cmd, true);
 }
 
 static void transport_lun_remove_cmd(struct se_cmd *cmd)
@@ -591,79 +556,8 @@ void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
 
        if (transport_cmd_check_stop_to_fabric(cmd))
                return;
-       if (remove) {
-               transport_remove_cmd_from_queue(cmd);
+       if (remove)
                transport_put_cmd(cmd);
-       }
-}
-
-static void transport_add_cmd_to_queue(struct se_cmd *cmd, int t_state,
-               bool at_head)
-{
-       struct se_device *dev = cmd->se_dev;
-       struct se_queue_obj *qobj = &dev->dev_queue_obj;
-       unsigned long flags;
-
-       if (t_state) {
-               spin_lock_irqsave(&cmd->t_state_lock, flags);
-               cmd->t_state = t_state;
-               cmd->transport_state |= CMD_T_ACTIVE;
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-       }
-
-       spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
-
-       /* If the cmd is already on the list, remove it before we add it */
-       if (!list_empty(&cmd->se_queue_node))
-               list_del(&cmd->se_queue_node);
-       else
-               atomic_inc(&qobj->queue_cnt);
-
-       if (at_head)
-               list_add(&cmd->se_queue_node, &qobj->qobj_list);
-       else
-               list_add_tail(&cmd->se_queue_node, &qobj->qobj_list);
-       cmd->transport_state |= CMD_T_QUEUED;
-       spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
-
-       wake_up_interruptible(&qobj->thread_wq);
-}
-
-static struct se_cmd *
-transport_get_cmd_from_queue(struct se_queue_obj *qobj)
-{
-       struct se_cmd *cmd;
-       unsigned long flags;
-
-       spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
-       if (list_empty(&qobj->qobj_list)) {
-               spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
-               return NULL;
-       }
-       cmd = list_first_entry(&qobj->qobj_list, struct se_cmd, se_queue_node);
-
-       cmd->transport_state &= ~CMD_T_QUEUED;
-       list_del_init(&cmd->se_queue_node);
-       atomic_dec(&qobj->queue_cnt);
-       spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
-
-       return cmd;
-}
-
-static void transport_remove_cmd_from_queue(struct se_cmd *cmd)
-{
-       struct se_queue_obj *qobj = &cmd->se_dev->dev_queue_obj;
-       unsigned long flags;
-
-       spin_lock_irqsave(&qobj->cmd_queue_lock, flags);
-       if (!(cmd->transport_state & CMD_T_QUEUED)) {
-               spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
-               return;
-       }
-       cmd->transport_state &= ~CMD_T_QUEUED;
-       atomic_dec(&qobj->queue_cnt);
-       list_del_init(&cmd->se_queue_node);
-       spin_unlock_irqrestore(&qobj->cmd_queue_lock, flags);
 }
 
 static void target_complete_failure_work(struct work_struct *work)
@@ -742,68 +636,11 @@ static void target_add_to_state_list(struct se_cmd *cmd)
        spin_unlock_irqrestore(&dev->execute_task_lock, flags);
 }
 
-static void __target_add_to_execute_list(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       bool head_of_queue = false;
-
-       if (!list_empty(&cmd->execute_list))
-               return;
-
-       if (dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED &&
-           cmd->sam_task_attr == MSG_HEAD_TAG)
-               head_of_queue = true;
-
-       if (head_of_queue)
-               list_add(&cmd->execute_list, &dev->execute_list);
-       else
-               list_add_tail(&cmd->execute_list, &dev->execute_list);
-
-       atomic_inc(&dev->execute_tasks);
-
-       if (cmd->state_active)
-               return;
-
-       if (head_of_queue)
-               list_add(&cmd->state_list, &dev->state_list);
-       else
-               list_add_tail(&cmd->state_list, &dev->state_list);
-
-       cmd->state_active = true;
-}
-
-static void target_add_to_execute_list(struct se_cmd *cmd)
-{
-       unsigned long flags;
-       struct se_device *dev = cmd->se_dev;
-
-       spin_lock_irqsave(&dev->execute_task_lock, flags);
-       __target_add_to_execute_list(cmd);
-       spin_unlock_irqrestore(&dev->execute_task_lock, flags);
-}
-
-void __target_remove_from_execute_list(struct se_cmd *cmd)
-{
-       list_del_init(&cmd->execute_list);
-       atomic_dec(&cmd->se_dev->execute_tasks);
-}
-
-static void target_remove_from_execute_list(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       unsigned long flags;
-
-       if (WARN_ON(list_empty(&cmd->execute_list)))
-               return;
-
-       spin_lock_irqsave(&dev->execute_task_lock, flags);
-       __target_remove_from_execute_list(cmd);
-       spin_unlock_irqrestore(&dev->execute_task_lock, flags);
-}
-
 /*
  * Handle QUEUE_FULL / -EAGAIN and -ENOMEM status
  */
+static void transport_write_pending_qf(struct se_cmd *cmd);
+static void transport_complete_qf(struct se_cmd *cmd);
 
 static void target_qf_do_work(struct work_struct *work)
 {
@@ -827,7 +664,10 @@ static void target_qf_do_work(struct work_struct *work)
                        (cmd->t_state == TRANSPORT_COMPLETE_QF_WP) ? "WRITE_PENDING"
                        : "UNKNOWN");
 
-               transport_add_cmd_to_queue(cmd, cmd->t_state, true);
+               if (cmd->t_state == TRANSPORT_COMPLETE_QF_WP)
+                       transport_write_pending_qf(cmd);
+               else if (cmd->t_state == TRANSPORT_COMPLETE_QF_OK)
+                       transport_complete_qf(cmd);
        }
 }
 
@@ -874,8 +714,7 @@ void transport_dump_dev_state(
                break;
        }
 
-       *bl += sprintf(b + *bl, "  Execute/Max Queue Depth: %d/%d",
-               atomic_read(&dev->execute_tasks), dev->queue_depth);
+       *bl += sprintf(b + *bl, "  Max Queue Depth: %d", dev->queue_depth);
        *bl += sprintf(b + *bl, "  SectorSize: %u  HwMaxSectors: %u\n",
                dev->se_sub_dev->se_dev_attrib.block_size,
                dev->se_sub_dev->se_dev_attrib.hw_max_sectors);
@@ -1212,7 +1051,6 @@ struct se_device *transport_add_device_to_core_hba(
                return NULL;
        }
 
-       transport_init_queue_obj(&dev->dev_queue_obj);
        dev->dev_flags          = device_flags;
        dev->dev_status         |= TRANSPORT_DEVICE_DEACTIVATED;
        dev->dev_ptr            = transport_dev;
@@ -1222,7 +1060,6 @@ struct se_device *transport_add_device_to_core_hba(
        INIT_LIST_HEAD(&dev->dev_list);
        INIT_LIST_HEAD(&dev->dev_sep_list);
        INIT_LIST_HEAD(&dev->dev_tmr_list);
-       INIT_LIST_HEAD(&dev->execute_list);
        INIT_LIST_HEAD(&dev->delayed_cmd_list);
        INIT_LIST_HEAD(&dev->state_list);
        INIT_LIST_HEAD(&dev->qf_cmd_list);
@@ -1261,17 +1098,17 @@ struct se_device *transport_add_device_to_core_hba(
         * Setup the Asymmetric Logical Unit Assignment for struct se_device
         */
        if (core_setup_alua(dev, force_pt) < 0)
-               goto out;
+               goto err_dev_list;
 
        /*
         * Startup the struct se_device processing thread
         */
-       dev->process_thread = kthread_run(transport_processing_thread, dev,
-                                         "LIO_%s", dev->transport->name);
-       if (IS_ERR(dev->process_thread)) {
-               pr_err("Unable to create kthread: LIO_%s\n",
+       dev->tmr_wq = alloc_workqueue("tmr-%s", WQ_MEM_RECLAIM | WQ_UNBOUND, 1,
+                                     dev->transport->name);
+       if (!dev->tmr_wq) {
+               pr_err("Unable to create tmr workqueue for %s\n",
                        dev->transport->name);
-               goto out;
+               goto err_dev_list;
        }
        /*
         * Setup work_queue for QUEUE_FULL
@@ -1289,7 +1126,7 @@ struct se_device *transport_add_device_to_core_hba(
                if (!inquiry_prod || !inquiry_rev) {
                        pr_err("All non TCM/pSCSI plugins require"
                                " INQUIRY consts\n");
-                       goto out;
+                       goto err_wq;
                }
 
                strncpy(&dev->se_sub_dev->t10_wwn.vendor[0], "LIO-ORG", 8);
@@ -1299,9 +1136,10 @@ struct se_device *transport_add_device_to_core_hba(
        scsi_dump_inquiry(dev);
 
        return dev;
-out:
-       kthread_stop(dev->process_thread);
 
+err_wq:
+       destroy_workqueue(dev->tmr_wq);
+err_dev_list:
        spin_lock(&hba->device_lock);
        list_del(&dev->dev_list);
        hba->dev_count--;
@@ -1315,35 +1153,54 @@ out:
 }
 EXPORT_SYMBOL(transport_add_device_to_core_hba);
 
-/*     transport_generic_prepare_cdb():
- *
- *     Since the Initiator sees iSCSI devices as LUNs,  the SCSI CDB will
- *     contain the iSCSI LUN in bits 7-5 of byte 1 as per SAM-2.
- *     The point of this is since we are mapping iSCSI LUNs to
- *     SCSI Target IDs having a non-zero LUN in the CDB will throw the
- *     devices and HBAs for a loop.
- */
-static inline void transport_generic_prepare_cdb(
-       unsigned char *cdb)
+int target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
 {
-       switch (cdb[0]) {
-       case READ_10: /* SBC - RDProtect */
-       case READ_12: /* SBC - RDProtect */
-       case READ_16: /* SBC - RDProtect */
-       case SEND_DIAGNOSTIC: /* SPC - SELF-TEST Code */
-       case VERIFY: /* SBC - VRProtect */
-       case VERIFY_16: /* SBC - VRProtect */
-       case WRITE_VERIFY: /* SBC - VRProtect */
-       case WRITE_VERIFY_12: /* SBC - VRProtect */
-       case MAINTENANCE_IN: /* SPC - Parameter Data Format for SA RTPG */
-               break;
-       default:
-               cdb[1] &= 0x1f; /* clear logical unit number */
-               break;
+       struct se_device *dev = cmd->se_dev;
+
+       if (cmd->unknown_data_length) {
+               cmd->data_length = size;
+       } else if (size != cmd->data_length) {
+               pr_warn("TARGET_CORE[%s]: Expected Transfer Length:"
+                       " %u does not match SCSI CDB Length: %u for SAM Opcode:"
+                       " 0x%02x\n", cmd->se_tfo->get_fabric_name(),
+                               cmd->data_length, size, cmd->t_task_cdb[0]);
+
+               cmd->cmd_spdtl = size;
+
+               if (cmd->data_direction == DMA_TO_DEVICE) {
+                       pr_err("Rejecting underflow/overflow"
+                                       " WRITE data\n");
+                       goto out_invalid_cdb_field;
+               }
+               /*
+                * Reject READ_* or WRITE_* with overflow/underflow for
+                * type SCF_SCSI_DATA_CDB.
+                */
+               if (dev->se_sub_dev->se_dev_attrib.block_size != 512)  {
+                       pr_err("Failing OVERFLOW/UNDERFLOW for LBA op"
+                               " CDB on non 512-byte sector setup subsystem"
+                               " plugin: %s\n", dev->transport->name);
+                       /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */
+                       goto out_invalid_cdb_field;
+               }
+
+               if (size > cmd->data_length) {
+                       cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
+                       cmd->residual_count = (size - cmd->data_length);
+               } else {
+                       cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
+                       cmd->residual_count = (cmd->data_length - size);
+               }
+               cmd->data_length = size;
        }
-}
 
-static int transport_generic_cmd_sequencer(struct se_cmd *, unsigned char *);
+       return 0;
+
+out_invalid_cdb_field:
+       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+       return -EINVAL;
+}
 
 /*
  * Used by fabric modules containing a local struct se_cmd within their
@@ -1361,9 +1218,7 @@ void transport_init_se_cmd(
        INIT_LIST_HEAD(&cmd->se_lun_node);
        INIT_LIST_HEAD(&cmd->se_delayed_node);
        INIT_LIST_HEAD(&cmd->se_qf_node);
-       INIT_LIST_HEAD(&cmd->se_queue_node);
        INIT_LIST_HEAD(&cmd->se_cmd_list);
-       INIT_LIST_HEAD(&cmd->execute_list);
        INIT_LIST_HEAD(&cmd->state_list);
        init_completion(&cmd->transport_lun_fe_stop_comp);
        init_completion(&cmd->transport_lun_stop_comp);
@@ -1418,9 +1273,12 @@ int target_setup_cmd_from_cdb(
        struct se_cmd *cmd,
        unsigned char *cdb)
 {
+       struct se_subsystem_dev *su_dev = cmd->se_dev->se_sub_dev;
+       u32 pr_reg_type = 0;
+       u8 alua_ascq = 0;
+       unsigned long flags;
        int ret;
 
-       transport_generic_prepare_cdb(cdb);
        /*
         * Ensure that the received CDB is less than the max (252 + 8) bytes
         * for VARIABLE_LENGTH_CMD
@@ -1457,15 +1315,66 @@ int target_setup_cmd_from_cdb(
         * Copy the original CDB into cmd->
         */
        memcpy(cmd->t_task_cdb, cdb, scsi_command_size(cdb));
+
+       /*
+        * Check for an existing UNIT ATTENTION condition
+        */
+       if (core_scsi3_ua_check(cmd, cdb) < 0) {
+               cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+               cmd->scsi_sense_reason = TCM_CHECK_CONDITION_UNIT_ATTENTION;
+               return -EINVAL;
+       }
+
+       ret = su_dev->t10_alua.alua_state_check(cmd, cdb, &alua_ascq);
+       if (ret != 0) {
+               /*
+                * Set SCSI additional sense code (ASC) to 'LUN Not Accessible';
+                * The ALUA additional sense code qualifier (ASCQ) is determined
+                * by the ALUA primary or secondary access state..
+                */
+               if (ret > 0) {
+                       pr_debug("[%s]: ALUA TG Port not available, "
+                               "SenseKey: NOT_READY, ASC/ASCQ: "
+                               "0x04/0x%02x\n",
+                               cmd->se_tfo->get_fabric_name(), alua_ascq);
+
+                       transport_set_sense_codes(cmd, 0x04, alua_ascq);
+                       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+                       cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY;
+                       return -EINVAL;
+               }
+               cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+               cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+               return -EINVAL;
+       }
+
        /*
-        * Setup the received CDB based on SCSI defined opcodes and
-        * perform unit attention, persistent reservations and ALUA
-        * checks for virtual device backends.  The cmd->t_task_cdb
-        * pointer is expected to be setup before we reach this point.
+        * Check status for SPC-3 Persistent Reservations
         */
-       ret = transport_generic_cmd_sequencer(cmd, cdb);
+       if (su_dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type)) {
+               if (su_dev->t10_pr.pr_ops.t10_seq_non_holder(
+                                       cmd, cdb, pr_reg_type) != 0) {
+                       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+                       cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT;
+                       cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
+                       cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
+                       return -EBUSY;
+               }
+               /*
+                * This means the CDB is allowed for the SCSI Initiator port
+                * when said port is *NOT* holding the legacy SPC-2 or
+                * SPC-3 Persistent Reservation.
+                */
+       }
+
+       ret = cmd->se_dev->transport->parse_cdb(cmd);
        if (ret < 0)
                return ret;
+
+       spin_lock_irqsave(&cmd->t_state_lock, flags);
+       cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE;
+       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+
        /*
         * Check for SAM Task Attribute Emulation
         */
@@ -1503,10 +1412,9 @@ int transport_handle_cdb_direct(
                return -EINVAL;
        }
        /*
-        * Set TRANSPORT_NEW_CMD state and CMD_T_ACTIVE following
-        * transport_generic_handle_cdb*() -> transport_add_cmd_to_queue()
-        * in existing usage to ensure that outstanding descriptors are handled
-        * correctly during shutdown via transport_wait_for_tasks()
+        * Set TRANSPORT_NEW_CMD state and CMD_T_ACTIVE to ensure that
+        * outstanding descriptors are handled correctly during shutdown via
+        * transport_wait_for_tasks()
         *
         * Also, we don't take cmd->t_state_lock here as we only expect
         * this to be called for initial descriptor submission.
@@ -1540,10 +1448,14 @@ EXPORT_SYMBOL(transport_handle_cdb_direct);
  * @data_dir: DMA data direction
  * @flags: flags for command submission from target_sc_flags_tables
  *
+ * Returns non zero to signal active I/O shutdown failure.  All other
+ * setup exceptions will be returned as a SCSI CHECK_CONDITION response,
+ * but still return zero here.
+ *
  * This may only be called from process context, and also currently
  * assumes internal allocation of fabric payload buffer by target-core.
  **/
-void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
+int target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
                unsigned char *cdb, unsigned char *sense, u32 unpacked_lun,
                u32 data_length, int task_attr, int data_dir, int flags)
 {
@@ -1569,7 +1481,9 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
         * for fabrics using TARGET_SCF_ACK_KREF that expect a second
         * kref_put() to happen during fabric packet acknowledgement.
         */
-       target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
+       rc = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
+       if (rc)
+               return rc;
        /*
         * Signal bidirectional data payloads to target-core
         */
@@ -1582,16 +1496,13 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
                transport_send_check_condition_and_sense(se_cmd,
                                se_cmd->scsi_sense_reason, 0);
                target_put_sess_cmd(se_sess, se_cmd);
-               return;
+               return 0;
        }
-       /*
-        * Sanitize CDBs via transport_generic_cmd_sequencer() and
-        * allocate the necessary tasks to complete the received CDB+data
-        */
+
        rc = target_setup_cmd_from_cdb(se_cmd, cdb);
        if (rc != 0) {
                transport_generic_request_failure(se_cmd);
-               return;
+               return 0;
        }
 
        /*
@@ -1600,14 +1511,8 @@ void target_submit_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,
         */
        core_alua_check_nonop_delay(se_cmd);
 
-       /*
-        * Dispatch se_cmd descriptor to se_lun->lun_se_dev backend
-        * for immediate execution of READs, otherwise wait for
-        * transport_generic_handle_data() to be called for WRITEs
-        * when fabric has filled the incoming buffer.
-        */
        transport_handle_cdb_direct(se_cmd);
-       return;
+       return 0;
 }
 EXPORT_SYMBOL(target_submit_cmd);
 
@@ -1662,7 +1567,11 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
                se_cmd->se_tmr_req->ref_task_tag = tag;
 
        /* See target_submit_cmd for commentary */
-       target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
+       ret = target_get_sess_cmd(se_sess, se_cmd, (flags & TARGET_SCF_ACK_KREF));
+       if (ret) {
+               core_tmr_release_req(se_cmd->se_tmr_req);
+               return ret;
+       }
 
        ret = transport_lookup_tmr_lun(se_cmd, unpacked_lun);
        if (ret) {
@@ -1679,67 +1588,6 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
 }
 EXPORT_SYMBOL(target_submit_tmr);
 
-/*
- * Used by fabric module frontends defining a TFO->new_cmd_map() caller
- * to  queue up a newly setup se_cmd w/ TRANSPORT_NEW_CMD_MAP in order to
- * complete setup in TCM process context w/ TFO->new_cmd_map().
- */
-int transport_generic_handle_cdb_map(
-       struct se_cmd *cmd)
-{
-       if (!cmd->se_lun) {
-               dump_stack();
-               pr_err("cmd->se_lun is NULL\n");
-               return -EINVAL;
-       }
-
-       transport_add_cmd_to_queue(cmd, TRANSPORT_NEW_CMD_MAP, false);
-       return 0;
-}
-EXPORT_SYMBOL(transport_generic_handle_cdb_map);
-
-/*     transport_generic_handle_data():
- *
- *
- */
-int transport_generic_handle_data(
-       struct se_cmd *cmd)
-{
-       /*
-        * For the software fabric case, then we assume the nexus is being
-        * failed/shutdown when signals are pending from the kthread context
-        * caller, so we return a failure.  For the HW target mode case running
-        * in interrupt code, the signal_pending() check is skipped.
-        */
-       if (!in_interrupt() && signal_pending(current))
-               return -EPERM;
-       /*
-        * If the received CDB has aleady been ABORTED by the generic
-        * target engine, we now call transport_check_aborted_status()
-        * to queue any delated TASK_ABORTED status for the received CDB to the
-        * fabric module as we are expecting no further incoming DATA OUT
-        * sequences at this point.
-        */
-       if (transport_check_aborted_status(cmd, 1) != 0)
-               return 0;
-
-       transport_add_cmd_to_queue(cmd, TRANSPORT_PROCESS_WRITE, false);
-       return 0;
-}
-EXPORT_SYMBOL(transport_generic_handle_data);
-
-/*     transport_generic_handle_tmr():
- *
- *
- */
-int transport_generic_handle_tmr(
-       struct se_cmd *cmd)
-{
-       transport_add_cmd_to_queue(cmd, TRANSPORT_PROCESS_TMR, false);
-       return 0;
-}
-EXPORT_SYMBOL(transport_generic_handle_tmr);
-
 /*
  * If the cmd is active, request it to be stopped and sleep until it
  * has completed.
@@ -1797,6 +1645,7 @@ void transport_generic_request_failure(struct se_cmd *cmd)
        case TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE:
        case TCM_UNKNOWN_MODE_PAGE:
        case TCM_WRITE_PROTECTED:
+       case TCM_ADDRESS_OUT_OF_RANGE:
        case TCM_CHECK_CONDITION_ABORT_CMD:
        case TCM_CHECK_CONDITION_UNIT_ATTENTION:
        case TCM_CHECK_CONDITION_NOT_READY:
@@ -1832,13 +1681,7 @@ void transport_generic_request_failure(struct se_cmd *cmd)
                cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
                break;
        }
-       /*
-        * If a fabric does not define a cmd->se_tfo->new_cmd_map caller,
-        * make the call to transport_send_check_condition_and_sense()
-        * directly.  Otherwise expect the fabric to make the call to
-        * transport_send_check_condition_and_sense() after handling
-        * possible unsoliticied write data payloads.
-        */
+
        ret = transport_send_check_condition_and_sense(cmd,
                        cmd->scsi_sense_reason, 0);
        if (ret == -EAGAIN || ret == -ENOMEM)
@@ -1856,1193 +1699,204 @@ queue_full:
 }
 EXPORT_SYMBOL(transport_generic_request_failure);
 
-static inline u32 transport_lba_21(unsigned char *cdb)
-{
-       return ((cdb[1] & 0x1f) << 16) | (cdb[2] << 8) | cdb[3];
-}
-
-static inline u32 transport_lba_32(unsigned char *cdb)
-{
-       return (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
-}
-
-static inline unsigned long long transport_lba_64(unsigned char *cdb)
-{
-       unsigned int __v1, __v2;
-
-       __v1 = (cdb[2] << 24) | (cdb[3] << 16) | (cdb[4] << 8) | cdb[5];
-       __v2 = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
-
-       return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
-}
-
-/*
- * For VARIABLE_LENGTH_CDB w/ 32 byte extended CDBs
- */
-static inline unsigned long long transport_lba_64_ext(unsigned char *cdb)
-{
-       unsigned int __v1, __v2;
-
-       __v1 = (cdb[12] << 24) | (cdb[13] << 16) | (cdb[14] << 8) | cdb[15];
-       __v2 = (cdb[16] << 24) | (cdb[17] << 16) | (cdb[18] << 8) | cdb[19];
-
-       return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
-}
-
-static void transport_set_supported_SAM_opcode(struct se_cmd *se_cmd)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&se_cmd->t_state_lock, flags);
-       se_cmd->se_cmd_flags |= SCF_SUPPORTED_SAM_OPCODE;
-       spin_unlock_irqrestore(&se_cmd->t_state_lock, flags);
-}
-
-/*
- * Called from Fabric Module context from transport_execute_tasks()
- *
- * The return of this function determins if the tasks from struct se_cmd
- * get added to the execution queue in transport_execute_tasks(),
- * or are added to the delayed or ordered lists here.
- */
-static inline int transport_execute_task_attr(struct se_cmd *cmd)
+static void __target_execute_cmd(struct se_cmd *cmd)
 {
-       if (cmd->se_dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED)
-               return 1;
-       /*
-        * Check for the existence of HEAD_OF_QUEUE, and if true return 1
-        * to allow the passed struct se_cmd list of tasks to the front of the list.
-        */
-        if (cmd->sam_task_attr == MSG_HEAD_TAG) {
-               pr_debug("Added HEAD_OF_QUEUE for CDB:"
-                       " 0x%02x, se_ordered_id: %u\n",
-                       cmd->t_task_cdb[0],
-                       cmd->se_ordered_id);
-               return 1;
-       } else if (cmd->sam_task_attr == MSG_ORDERED_TAG) {
-               atomic_inc(&cmd->se_dev->dev_ordered_sync);
-               smp_mb__after_atomic_inc();
+       int error = 0;
 
-               pr_debug("Added ORDERED for CDB: 0x%02x to ordered"
-                               " list, se_ordered_id: %u\n",
-                               cmd->t_task_cdb[0],
-                               cmd->se_ordered_id);
-               /*
-                * Add ORDERED command to tail of execution queue if
-                * no other older commands exist that need to be
-                * completed first.
-                */
-               if (!atomic_read(&cmd->se_dev->simple_cmds))
-                       return 1;
-       } else {
-               /*
-                * For SIMPLE and UNTAGGED Task Attribute commands
-                */
-               atomic_inc(&cmd->se_dev->simple_cmds);
-               smp_mb__after_atomic_inc();
-       }
-       /*
-        * Otherwise if one or more outstanding ORDERED task attribute exist,
-        * add the dormant task(s) built for the passed struct se_cmd to the
-        * execution queue and become in Active state for this struct se_device.
-        */
-       if (atomic_read(&cmd->se_dev->dev_ordered_sync) != 0) {
-               /*
-                * Otherwise, add cmd w/ tasks to delayed cmd queue that
-                * will be drained upon completion of HEAD_OF_QUEUE task.
-                */
-               spin_lock(&cmd->se_dev->delayed_cmd_lock);
-               cmd->se_cmd_flags |= SCF_DELAYED_CMD_FROM_SAM_ATTR;
-               list_add_tail(&cmd->se_delayed_node,
-                               &cmd->se_dev->delayed_cmd_list);
-               spin_unlock(&cmd->se_dev->delayed_cmd_lock);
-
-               pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to"
-                       " delayed CMD list, se_ordered_id: %u\n",
-                       cmd->t_task_cdb[0], cmd->sam_task_attr,
-                       cmd->se_ordered_id);
-               /*
-                * Return zero to let transport_execute_tasks() know
-                * not to add the delayed tasks to the execution list.
-                */
-               return 0;
-       }
-       /*
-        * Otherwise, no ORDERED task attributes exist..
-        */
-       return 1;
-}
-
-/*
- * Called from fabric module context in transport_generic_new_cmd() and
- * transport_generic_process_write()
- */
-static void transport_execute_tasks(struct se_cmd *cmd)
-{
-       int add_tasks;
-       struct se_device *se_dev = cmd->se_dev;
-       /*
-        * Call transport_cmd_check_stop() to see if a fabric exception
-        * has occurred that prevents execution.
-        */
-       if (!transport_cmd_check_stop(cmd, 0, TRANSPORT_PROCESSING)) {
-               /*
-                * Check for SAM Task Attribute emulation and HEAD_OF_QUEUE
-                * attribute for the tasks of the received struct se_cmd CDB
-                */
-               add_tasks = transport_execute_task_attr(cmd);
-               if (add_tasks) {
-                       __transport_execute_tasks(se_dev, cmd);
-                       return;
-               }
-       }
-       __transport_execute_tasks(se_dev, NULL);
-}
-
-static int __transport_execute_tasks(struct se_device *dev, struct se_cmd *new_cmd)
-{
-       int error;
-       struct se_cmd *cmd = NULL;
-       unsigned long flags;
-
-check_depth:
-       spin_lock_irq(&dev->execute_task_lock);
-       if (new_cmd != NULL)
-               __target_add_to_execute_list(new_cmd);
-
-       if (list_empty(&dev->execute_list)) {
-               spin_unlock_irq(&dev->execute_task_lock);
-               return 0;
-       }
-       cmd = list_first_entry(&dev->execute_list, struct se_cmd, execute_list);
-       __target_remove_from_execute_list(cmd);
-       spin_unlock_irq(&dev->execute_task_lock);
-
-       spin_lock_irqsave(&cmd->t_state_lock, flags);
-       cmd->transport_state |= CMD_T_BUSY;
-       cmd->transport_state |= CMD_T_SENT;
-
-       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+       spin_lock_irq(&cmd->t_state_lock);
+       cmd->transport_state |= (CMD_T_BUSY|CMD_T_SENT);
+       spin_unlock_irq(&cmd->t_state_lock);
 
        if (cmd->execute_cmd)
                error = cmd->execute_cmd(cmd);
-       else {
-               error = dev->transport->execute_cmd(cmd, cmd->t_data_sg,
-                               cmd->t_data_nents, cmd->data_direction);
-       }
 
-       if (error != 0) {
-               spin_lock_irqsave(&cmd->t_state_lock, flags);
-               cmd->transport_state &= ~CMD_T_BUSY;
-               cmd->transport_state &= ~CMD_T_SENT;
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+       if (error) {
+               spin_lock_irq(&cmd->t_state_lock);
+               cmd->transport_state &= ~(CMD_T_BUSY|CMD_T_SENT);
+               spin_unlock_irq(&cmd->t_state_lock);
 
                transport_generic_request_failure(cmd);
        }
-
-       new_cmd = NULL;
-       goto check_depth;
-
-       return 0;
 }
 
-static inline u32 transport_get_sectors_6(
-       unsigned char *cdb,
-       struct se_cmd *cmd,
-       int *ret)
+void target_execute_cmd(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
 
        /*
-        * Assume TYPE_DISK for non struct se_device objects.
-        * Use 8-bit sector value.
-        */
-       if (!dev)
-               goto type_disk;
-
-       /*
-        * Use 24-bit allocation length for TYPE_TAPE.
-        */
-       if (dev->transport->get_device_type(dev) == TYPE_TAPE)
-               return (u32)(cdb[2] << 16) + (cdb[3] << 8) + cdb[4];
-
-       /*
-        * Everything else assume TYPE_DISK Sector CDB location.
-        * Use 8-bit sector value.  SBC-3 says:
-        *
-        *   A TRANSFER LENGTH field set to zero specifies that 256
-        *   logical blocks shall be written.  Any other value
-        *   specifies the number of logical blocks that shall be
-        *   written.
+        * If the received CDB has aleady been aborted stop processing it here.
         */
-type_disk:
-       return cdb[4] ? : 256;
-}
-
-static inline u32 transport_get_sectors_10(
-       unsigned char *cdb,
-       struct se_cmd *cmd,
-       int *ret)
-{
-       struct se_device *dev = cmd->se_dev;
+       if (transport_check_aborted_status(cmd, 1))
+               return;
 
        /*
-        * Assume TYPE_DISK for non struct se_device objects.
-        * Use 16-bit sector value.
+        * Determine if IOCTL context caller in requesting the stopping of this
+        * command for LUN shutdown purposes.
         */
-       if (!dev)
-               goto type_disk;
+       spin_lock_irq(&cmd->t_state_lock);
+       if (cmd->transport_state & CMD_T_LUN_STOP) {
+               pr_debug("%s:%d CMD_T_LUN_STOP for ITT: 0x%08x\n",
+                       __func__, __LINE__, cmd->se_tfo->get_task_tag(cmd));
 
-       /*
-        * XXX_10 is not defined in SSC, throw an exception
-        */
-       if (dev->transport->get_device_type(dev) == TYPE_TAPE) {
-               *ret = -EINVAL;
-               return 0;
+               cmd->transport_state &= ~CMD_T_ACTIVE;
+               spin_unlock_irq(&cmd->t_state_lock);
+               complete(&cmd->transport_lun_stop_comp);
+               return;
        }
-
-       /*
-        * Everything else assume TYPE_DISK Sector CDB location.
-        * Use 16-bit sector value.
-        */
-type_disk:
-       return (u32)(cdb[7] << 8) + cdb[8];
-}
-
-static inline u32 transport_get_sectors_12(
-       unsigned char *cdb,
-       struct se_cmd *cmd,
-       int *ret)
-{
-       struct se_device *dev = cmd->se_dev;
-
        /*
-        * Assume TYPE_DISK for non struct se_device objects.
-        * Use 32-bit sector value.
+        * Determine if frontend context caller is requesting the stopping of
+        * this command for frontend exceptions.
         */
-       if (!dev)
-               goto type_disk;
+       if (cmd->transport_state & CMD_T_STOP) {
+               pr_debug("%s:%d CMD_T_STOP for ITT: 0x%08x\n",
+                       __func__, __LINE__,
+                       cmd->se_tfo->get_task_tag(cmd));
 
-       /*
-        * XXX_12 is not defined in SSC, throw an exception
-        */
-       if (dev->transport->get_device_type(dev) == TYPE_TAPE) {
-               *ret = -EINVAL;
-               return 0;
+               spin_unlock_irq(&cmd->t_state_lock);
+               complete(&cmd->t_transport_stop_comp);
+               return;
        }
 
-       /*
-        * Everything else assume TYPE_DISK Sector CDB location.
-        * Use 32-bit sector value.
-        */
-type_disk:
-       return (u32)(cdb[6] << 24) + (cdb[7] << 16) + (cdb[8] << 8) + cdb[9];
-}
+       cmd->t_state = TRANSPORT_PROCESSING;
+       spin_unlock_irq(&cmd->t_state_lock);
 
-static inline u32 transport_get_sectors_16(
-       unsigned char *cdb,
-       struct se_cmd *cmd,
-       int *ret)
-{
-       struct se_device *dev = cmd->se_dev;
-
-       /*
-        * Assume TYPE_DISK for non struct se_device objects.
-        * Use 32-bit sector value.
-        */
-       if (!dev)
-               goto type_disk;
+       if (dev->dev_task_attr_type != SAM_TASK_ATTR_EMULATED)
+               goto execute;
 
        /*
-        * Use 24-bit allocation length for TYPE_TAPE.
-        */
-       if (dev->transport->get_device_type(dev) == TYPE_TAPE)
-               return (u32)(cdb[12] << 16) + (cdb[13] << 8) + cdb[14];
-
-type_disk:
-       return (u32)(cdb[10] << 24) + (cdb[11] << 16) +
-                   (cdb[12] << 8) + cdb[13];
-}
-
-/*
- * Used for VARIABLE_LENGTH_CDB WRITE_32 and READ_32 variants
- */
-static inline u32 transport_get_sectors_32(
-       unsigned char *cdb,
-       struct se_cmd *cmd,
-       int *ret)
-{
-       /*
-        * Assume TYPE_DISK for non struct se_device objects.
-        * Use 32-bit sector value.
+        * Check for the existence of HEAD_OF_QUEUE, and if true return 1
+        * to allow the passed struct se_cmd list of tasks to the front of the list.
         */
-       return (u32)(cdb[28] << 24) + (cdb[29] << 16) +
-                   (cdb[30] << 8) + cdb[31];
+       switch (cmd->sam_task_attr) {
+       case MSG_HEAD_TAG:
+               pr_debug("Added HEAD_OF_QUEUE for CDB: 0x%02x, "
+                        "se_ordered_id: %u\n",
+                        cmd->t_task_cdb[0], cmd->se_ordered_id);
+               goto execute;
+       case MSG_ORDERED_TAG:
+               atomic_inc(&dev->dev_ordered_sync);
+               smp_mb__after_atomic_inc();
 
-}
+               pr_debug("Added ORDERED for CDB: 0x%02x to ordered list, "
+                        " se_ordered_id: %u\n",
+                        cmd->t_task_cdb[0], cmd->se_ordered_id);
 
-static inline u32 transport_get_size(
-       u32 sectors,
-       unsigned char *cdb,
-       struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-
-       if (dev->transport->get_device_type(dev) == TYPE_TAPE) {
-               if (cdb[1] & 1) { /* sectors */
-                       return dev->se_sub_dev->se_dev_attrib.block_size * sectors;
-               } else /* bytes */
-                       return sectors;
+               /*
+                * Execute an ORDERED command if no other older commands
+                * exist that need to be completed first.
+                */
+               if (!atomic_read(&dev->simple_cmds))
+                       goto execute;
+               break;
+       default:
+               /*
+                * For SIMPLE and UNTAGGED Task Attribute commands
+                */
+               atomic_inc(&dev->simple_cmds);
+               smp_mb__after_atomic_inc();
+               break;
        }
 
-       pr_debug("Returning block_size: %u, sectors: %u == %u for"
-               " %s object\n", dev->se_sub_dev->se_dev_attrib.block_size,
-               sectors, dev->se_sub_dev->se_dev_attrib.block_size * sectors,
-               dev->transport->name);
-
-       return dev->se_sub_dev->se_dev_attrib.block_size * sectors;
-}
+       if (atomic_read(&dev->dev_ordered_sync) != 0) {
+               spin_lock(&dev->delayed_cmd_lock);
+               list_add_tail(&cmd->se_delayed_node, &dev->delayed_cmd_list);
+               spin_unlock(&dev->delayed_cmd_lock);
 
-static void transport_xor_callback(struct se_cmd *cmd)
-{
-       unsigned char *buf, *addr;
-       struct scatterlist *sg;
-       unsigned int offset;
-       int i;
-       int count;
-       /*
-        * From sbc3r22.pdf section 5.48 XDWRITEREAD (10) command
-        *
-        * 1) read the specified logical block(s);
-        * 2) transfer logical blocks from the data-out buffer;
-        * 3) XOR the logical blocks transferred from the data-out buffer with
-        *    the logical blocks read, storing the resulting XOR data in a buffer;
-        * 4) if the DISABLE WRITE bit is set to zero, then write the logical
-        *    blocks transferred from the data-out buffer; and
-        * 5) transfer the resulting XOR data to the data-in buffer.
-        */
-       buf = kmalloc(cmd->data_length, GFP_KERNEL);
-       if (!buf) {
-               pr_err("Unable to allocate xor_callback buf\n");
+               pr_debug("Added CDB: 0x%02x Task Attr: 0x%02x to"
+                       " delayed CMD list, se_ordered_id: %u\n",
+                       cmd->t_task_cdb[0], cmd->sam_task_attr,
+                       cmd->se_ordered_id);
                return;
        }
-       /*
-        * Copy the scatterlist WRITE buffer located at cmd->t_data_sg
-        * into the locally allocated *buf
-        */
-       sg_copy_to_buffer(cmd->t_data_sg,
-                         cmd->t_data_nents,
-                         buf,
-                         cmd->data_length);
 
+execute:
        /*
-        * Now perform the XOR against the BIDI read memory located at
-        * cmd->t_mem_bidi_list
+        * Otherwise, no ORDERED task attributes exist..
         */
-
-       offset = 0;
-       for_each_sg(cmd->t_bidi_data_sg, sg, cmd->t_bidi_data_nents, count) {
-               addr = kmap_atomic(sg_page(sg));
-               if (!addr)
-                       goto out;
-
-               for (i = 0; i < sg->length; i++)
-                       *(addr + sg->offset + i) ^= *(buf + offset + i);
-
-               offset += sg->length;
-               kunmap_atomic(addr);
-       }
-
-out:
-       kfree(buf);
+       __target_execute_cmd(cmd);
 }
+EXPORT_SYMBOL(target_execute_cmd);
 
 /*
  * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd
  */
 static int transport_get_sense_data(struct se_cmd *cmd)
 {
-       unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL;
-       struct se_device *dev = cmd->se_dev;
-       unsigned long flags;
-       u32 offset = 0;
-
-       WARN_ON(!cmd->se_lun);
-
-       if (!dev)
-               return 0;
-
-       spin_lock_irqsave(&cmd->t_state_lock, flags);
-       if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-               return 0;
-       }
-
-       if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE))
-               goto out;
-
-       if (!dev->transport->get_sense_buffer) {
-               pr_err("dev->transport->get_sense_buffer is NULL\n");
-               goto out;
-       }
-
-       sense_buffer = dev->transport->get_sense_buffer(cmd);
-       if (!sense_buffer) {
-               pr_err("ITT 0x%08x cmd %p: Unable to locate"
-                       " sense buffer for task with sense\n",
-                       cmd->se_tfo->get_task_tag(cmd), cmd);
-               goto out;
-       }
-
-       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
-       offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER);
-
-       memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER);
-
-       /* Automatically padded */
-       cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset;
-
-       pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n",
-               dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status);
-       return 0;
-
-out:
-       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-       return -1;
-}
-
-static inline long long transport_dev_end_lba(struct se_device *dev)
-{
-       return dev->transport->get_blocks(dev) + 1;
-}
-
-static int transport_cmd_get_valid_sectors(struct se_cmd *cmd)
-{
-       struct se_device *dev = cmd->se_dev;
-       u32 sectors;
-
-       if (dev->transport->get_device_type(dev) != TYPE_DISK)
-               return 0;
-
-       sectors = (cmd->data_length / dev->se_sub_dev->se_dev_attrib.block_size);
-
-       if ((cmd->t_task_lba + sectors) > transport_dev_end_lba(dev)) {
-               pr_err("LBA: %llu Sectors: %u exceeds"
-                       " transport_dev_end_lba(): %llu\n",
-                       cmd->t_task_lba, sectors,
-                       transport_dev_end_lba(dev));
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int target_check_write_same_discard(unsigned char *flags, struct se_device *dev)
-{
-       /*
-        * Determine if the received WRITE_SAME is used to for direct
-        * passthrough into Linux/SCSI with struct request via TCM/pSCSI
-        * or we are signaling the use of internal WRITE_SAME + UNMAP=1
-        * emulation for -> Linux/BLOCK disbard with TCM/IBLOCK code.
-        */
-       int passthrough = (dev->transport->transport_type ==
-                               TRANSPORT_PLUGIN_PHBA_PDEV);
-
-       if (!passthrough) {
-               if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
-                       pr_err("WRITE_SAME PBDATA and LBDATA"
-                               " bits not supported for Block Discard"
-                               " Emulation\n");
-                       return -ENOSYS;
-               }
-               /*
-                * Currently for the emulated case we only accept
-                * tpws with the UNMAP=1 bit set.
-                */
-               if (!(flags[0] & 0x08)) {
-                       pr_err("WRITE_SAME w/o UNMAP bit not"
-                               " supported for Block Discard Emulation\n");
-                       return -ENOSYS;
-               }
-       }
-
-       return 0;
-}
-
-/*     transport_generic_cmd_sequencer():
- *
- *     Generic Command Sequencer that should work for most DAS transport
- *     drivers.
- *
- *     Called from target_setup_cmd_from_cdb() in the $FABRIC_MOD
- *     RX Thread.
- *
- *     FIXME: Need to support other SCSI OPCODES where as well.
- */
-static int transport_generic_cmd_sequencer(
-       struct se_cmd *cmd,
-       unsigned char *cdb)
-{
-       struct se_device *dev = cmd->se_dev;
-       struct se_subsystem_dev *su_dev = dev->se_sub_dev;
-       int ret = 0, sector_ret = 0, passthrough;
-       u32 sectors = 0, size = 0, pr_reg_type = 0;
-       u16 service_action;
-       u8 alua_ascq = 0;
-       /*
-        * Check for an existing UNIT ATTENTION condition
-        */
-       if (core_scsi3_ua_check(cmd, cdb) < 0) {
-               cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-               cmd->scsi_sense_reason = TCM_CHECK_CONDITION_UNIT_ATTENTION;
-               return -EINVAL;
-       }
-       /*
-        * Check status of Asymmetric Logical Unit Assignment port
-        */
-       ret = su_dev->t10_alua.alua_state_check(cmd, cdb, &alua_ascq);
-       if (ret != 0) {
-               /*
-                * Set SCSI additional sense code (ASC) to 'LUN Not Accessible';
-                * The ALUA additional sense code qualifier (ASCQ) is determined
-                * by the ALUA primary or secondary access state..
-                */
-               if (ret > 0) {
-                       pr_debug("[%s]: ALUA TG Port not available,"
-                               " SenseKey: NOT_READY, ASC/ASCQ: 0x04/0x%02x\n",
-                               cmd->se_tfo->get_fabric_name(), alua_ascq);
-
-                       transport_set_sense_codes(cmd, 0x04, alua_ascq);
-                       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-                       cmd->scsi_sense_reason = TCM_CHECK_CONDITION_NOT_READY;
-                       return -EINVAL;
-               }
-               goto out_invalid_cdb_field;
-       }
-       /*
-        * Check status for SPC-3 Persistent Reservations
-        */
-       if (su_dev->t10_pr.pr_ops.t10_reservation_check(cmd, &pr_reg_type) != 0) {
-               if (su_dev->t10_pr.pr_ops.t10_seq_non_holder(
-                                       cmd, cdb, pr_reg_type) != 0) {
-                       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-                       cmd->se_cmd_flags |= SCF_SCSI_RESERVATION_CONFLICT;
-                       cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT;
-                       cmd->scsi_sense_reason = TCM_RESERVATION_CONFLICT;
-                       return -EBUSY;
-               }
-               /*
-                * This means the CDB is allowed for the SCSI Initiator port
-                * when said port is *NOT* holding the legacy SPC-2 or
-                * SPC-3 Persistent Reservation.
-                */
-       }
-
-       /*
-        * If we operate in passthrough mode we skip most CDB emulation and
-        * instead hand the commands down to the physical SCSI device.
-        */
-       passthrough =
-               (dev->transport->transport_type == TRANSPORT_PLUGIN_PHBA_PDEV);
-
-       switch (cdb[0]) {
-       case READ_6:
-               sectors = transport_get_sectors_6(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_21(cdb);
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case READ_10:
-               sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_32(cdb);
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case READ_12:
-               sectors = transport_get_sectors_12(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_32(cdb);
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case READ_16:
-               sectors = transport_get_sectors_16(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_64(cdb);
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case WRITE_6:
-               sectors = transport_get_sectors_6(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_21(cdb);
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case WRITE_10:
-       case WRITE_VERIFY:
-               sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_32(cdb);
-               if (cdb[1] & 0x8)
-                       cmd->se_cmd_flags |= SCF_FUA;
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case WRITE_12:
-               sectors = transport_get_sectors_12(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_32(cdb);
-               if (cdb[1] & 0x8)
-                       cmd->se_cmd_flags |= SCF_FUA;
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case WRITE_16:
-               sectors = transport_get_sectors_16(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_64(cdb);
-               if (cdb[1] & 0x8)
-                       cmd->se_cmd_flags |= SCF_FUA;
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-               break;
-       case XDWRITEREAD_10:
-               if ((cmd->data_direction != DMA_TO_DEVICE) ||
-                   !(cmd->se_cmd_flags & SCF_BIDI))
-                       goto out_invalid_cdb_field;
-               sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->t_task_lba = transport_lba_32(cdb);
-               cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-
-               /*
-                * Do now allow BIDI commands for passthrough mode.
-                */
-               if (passthrough)
-                       goto out_unsupported_cdb;
-
-               /*
-                * Setup BIDI XOR callback to be run after I/O completion.
-                */
-               cmd->transport_complete_callback = &transport_xor_callback;
-               if (cdb[1] & 0x8)
-                       cmd->se_cmd_flags |= SCF_FUA;
-               break;
-       case VARIABLE_LENGTH_CMD:
-               service_action = get_unaligned_be16(&cdb[8]);
-               switch (service_action) {
-               case XDWRITEREAD_32:
-                       sectors = transport_get_sectors_32(cdb, cmd, &sector_ret);
-                       if (sector_ret)
-                               goto out_unsupported_cdb;
-                       size = transport_get_size(sectors, cdb, cmd);
-                       /*
-                        * Use WRITE_32 and READ_32 opcodes for the emulated
-                        * XDWRITE_READ_32 logic.
-                        */
-                       cmd->t_task_lba = transport_lba_64_ext(cdb);
-                       cmd->se_cmd_flags |= SCF_SCSI_DATA_SG_IO_CDB;
-
-                       /*
-                        * Do now allow BIDI commands for passthrough mode.
-                        */
-                       if (passthrough)
-                               goto out_unsupported_cdb;
-
-                       /*
-                        * Setup BIDI XOR callback to be run during after I/O
-                        * completion.
-                        */
-                       cmd->transport_complete_callback = &transport_xor_callback;
-                       if (cdb[1] & 0x8)
-                               cmd->se_cmd_flags |= SCF_FUA;
-                       break;
-               case WRITE_SAME_32:
-                       sectors = transport_get_sectors_32(cdb, cmd, &sector_ret);
-                       if (sector_ret)
-                               goto out_unsupported_cdb;
-
-                       if (sectors)
-                               size = transport_get_size(1, cdb, cmd);
-                       else {
-                               pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not"
-                                      " supported\n");
-                               goto out_invalid_cdb_field;
-                       }
-
-                       cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
-                       cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-
-                       if (target_check_write_same_discard(&cdb[10], dev) < 0)
-                               goto out_unsupported_cdb;
-                       if (!passthrough)
-                               cmd->execute_cmd = target_emulate_write_same;
-                       break;
-               default:
-                       pr_err("VARIABLE_LENGTH_CMD service action"
-                               " 0x%04x not supported\n", service_action);
-                       goto out_unsupported_cdb;
-               }
-               break;
-       case MAINTENANCE_IN:
-               if (dev->transport->get_device_type(dev) != TYPE_ROM) {
-                       /* MAINTENANCE_IN from SCC-2 */
-                       /*
-                        * Check for emulated MI_REPORT_TARGET_PGS.
-                        */
-                       if ((cdb[1] & 0x1f) == MI_REPORT_TARGET_PGS &&
-                           su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
-                               cmd->execute_cmd =
-                                       target_emulate_report_target_port_groups;
-                       }
-                       size = (cdb[6] << 24) | (cdb[7] << 16) |
-                              (cdb[8] << 8) | cdb[9];
-               } else {
-                       /* GPCMD_SEND_KEY from multi media commands */
-                       size = (cdb[8] << 8) + cdb[9];
-               }
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case MODE_SELECT:
-               size = cdb[4];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case MODE_SELECT_10:
-               size = (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case MODE_SENSE:
-               size = cdb[4];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_modesense;
-               break;
-       case MODE_SENSE_10:
-               size = (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_modesense;
-               break;
-       case GPCMD_READ_BUFFER_CAPACITY:
-       case GPCMD_SEND_OPC:
-       case LOG_SELECT:
-       case LOG_SENSE:
-               size = (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case READ_BLOCK_LIMITS:
-               size = READ_BLOCK_LEN;
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case GPCMD_GET_CONFIGURATION:
-       case GPCMD_READ_FORMAT_CAPACITIES:
-       case GPCMD_READ_DISC_INFO:
-       case GPCMD_READ_TRACK_RZONE_INFO:
-               size = (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case PERSISTENT_RESERVE_IN:
-               if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
-                       cmd->execute_cmd = target_scsi3_emulate_pr_in;
-               size = (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case PERSISTENT_RESERVE_OUT:
-               if (su_dev->t10_pr.res_type == SPC3_PERSISTENT_RESERVATIONS)
-                       cmd->execute_cmd = target_scsi3_emulate_pr_out;
-               size = (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case GPCMD_MECHANISM_STATUS:
-       case GPCMD_READ_DVD_STRUCTURE:
-               size = (cdb[8] << 8) + cdb[9];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case READ_POSITION:
-               size = READ_POSITION_LEN;
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case MAINTENANCE_OUT:
-               if (dev->transport->get_device_type(dev) != TYPE_ROM) {
-                       /* MAINTENANCE_OUT from SCC-2
-                        *
-                        * Check for emulated MO_SET_TARGET_PGS.
-                        */
-                       if (cdb[1] == MO_SET_TARGET_PGS &&
-                           su_dev->t10_alua.alua_type == SPC3_ALUA_EMULATED) {
-                               cmd->execute_cmd =
-                                       target_emulate_set_target_port_groups;
-                       }
-
-                       size = (cdb[6] << 24) | (cdb[7] << 16) |
-                              (cdb[8] << 8) | cdb[9];
-               } else  {
-                       /* GPCMD_REPORT_KEY from multi media commands */
-                       size = (cdb[8] << 8) + cdb[9];
-               }
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case INQUIRY:
-               size = (cdb[3] << 8) + cdb[4];
-               /*
-                * Do implict HEAD_OF_QUEUE processing for INQUIRY.
-                * See spc4r17 section 5.3
-                */
-               if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
-                       cmd->sam_task_attr = MSG_HEAD_TAG;
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_inquiry;
-               break;
-       case READ_BUFFER:
-               size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case READ_CAPACITY:
-               size = READ_CAP_LEN;
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_readcapacity;
-               break;
-       case READ_MEDIA_SERIAL_NUMBER:
-       case SECURITY_PROTOCOL_IN:
-       case SECURITY_PROTOCOL_OUT:
-               size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case SERVICE_ACTION_IN:
-               switch (cmd->t_task_cdb[1] & 0x1f) {
-               case SAI_READ_CAPACITY_16:
-                       if (!passthrough)
-                               cmd->execute_cmd =
-                                       target_emulate_readcapacity_16;
-                       break;
-               default:
-                       if (passthrough)
-                               break;
-
-                       pr_err("Unsupported SA: 0x%02x\n",
-                               cmd->t_task_cdb[1] & 0x1f);
-                       goto out_invalid_cdb_field;
-               }
-               /*FALLTHROUGH*/
-       case ACCESS_CONTROL_IN:
-       case ACCESS_CONTROL_OUT:
-       case EXTENDED_COPY:
-       case READ_ATTRIBUTE:
-       case RECEIVE_COPY_RESULTS:
-       case WRITE_ATTRIBUTE:
-               size = (cdb[10] << 24) | (cdb[11] << 16) |
-                      (cdb[12] << 8) | cdb[13];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case RECEIVE_DIAGNOSTIC:
-       case SEND_DIAGNOSTIC:
-               size = (cdb[3] << 8) | cdb[4];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-/* #warning FIXME: Figure out correct GPCMD_READ_CD blocksize. */
-#if 0
-       case GPCMD_READ_CD:
-               sectors = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
-               size = (2336 * sectors);
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-#endif
-       case READ_TOC:
-               size = cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case REQUEST_SENSE:
-               size = cdb[4];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_request_sense;
-               break;
-       case READ_ELEMENT_STATUS:
-               size = 65536 * cdb[7] + 256 * cdb[8] + cdb[9];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case WRITE_BUFFER:
-               size = (cdb[6] << 16) + (cdb[7] << 8) + cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case RESERVE:
-       case RESERVE_10:
-               /*
-                * The SPC-2 RESERVE does not contain a size in the SCSI CDB.
-                * Assume the passthrough or $FABRIC_MOD will tell us about it.
-                */
-               if (cdb[0] == RESERVE_10)
-                       size = (cdb[7] << 8) | cdb[8];
-               else
-                       size = cmd->data_length;
-
-               /*
-                * Setup the legacy emulated handler for SPC-2 and
-                * >= SPC-3 compatible reservation handling (CRH=1)
-                * Otherwise, we assume the underlying SCSI logic is
-                * is running in SPC_PASSTHROUGH, and wants reservations
-                * emulation disabled.
-                */
-               if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
-                       cmd->execute_cmd = target_scsi2_reservation_reserve;
-               cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
-               break;
-       case RELEASE:
-       case RELEASE_10:
-               /*
-                * The SPC-2 RELEASE does not contain a size in the SCSI CDB.
-                * Assume the passthrough or $FABRIC_MOD will tell us about it.
-               */
-               if (cdb[0] == RELEASE_10)
-                       size = (cdb[7] << 8) | cdb[8];
-               else
-                       size = cmd->data_length;
-
-               if (su_dev->t10_pr.res_type != SPC_PASSTHROUGH)
-                       cmd->execute_cmd = target_scsi2_reservation_release;
-               cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
-               break;
-       case SYNCHRONIZE_CACHE:
-       case SYNCHRONIZE_CACHE_16:
-               /*
-                * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE
-                */
-               if (cdb[0] == SYNCHRONIZE_CACHE) {
-                       sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
-                       cmd->t_task_lba = transport_lba_32(cdb);
-               } else {
-                       sectors = transport_get_sectors_16(cdb, cmd, &sector_ret);
-                       cmd->t_task_lba = transport_lba_64(cdb);
-               }
-               if (sector_ret)
-                       goto out_unsupported_cdb;
-
-               size = transport_get_size(sectors, cdb, cmd);
-               cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
-
-               if (passthrough)
-                       break;
-
-               /*
-                * Check to ensure that LBA + Range does not exceed past end of
-                * device for IBLOCK and FILEIO ->do_sync_cache() backend calls
-                */
-               if ((cmd->t_task_lba != 0) || (sectors != 0)) {
-                       if (transport_cmd_get_valid_sectors(cmd) < 0)
-                               goto out_invalid_cdb_field;
-               }
-               cmd->execute_cmd = target_emulate_synchronize_cache;
-               break;
-       case UNMAP:
-               size = get_unaligned_be16(&cdb[7]);
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_unmap;
-               break;
-       case WRITE_SAME_16:
-               sectors = transport_get_sectors_16(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
+       unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL;
+       struct se_device *dev = cmd->se_dev;
+       unsigned long flags;
+       u32 offset = 0;
 
-               if (sectors)
-                       size = transport_get_size(1, cdb, cmd);
-               else {
-                       pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
-                       goto out_invalid_cdb_field;
-               }
+       WARN_ON(!cmd->se_lun);
 
-               cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
+       if (!dev)
+               return 0;
 
-               if (target_check_write_same_discard(&cdb[1], dev) < 0)
-                       goto out_unsupported_cdb;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_write_same;
-               break;
-       case WRITE_SAME:
-               sectors = transport_get_sectors_10(cdb, cmd, &sector_ret);
-               if (sector_ret)
-                       goto out_unsupported_cdb;
+       spin_lock_irqsave(&cmd->t_state_lock, flags);
+       if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
+               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+               return 0;
+       }
 
-               if (sectors)
-                       size = transport_get_size(1, cdb, cmd);
-               else {
-                       pr_err("WSNZ=1, WRITE_SAME w/sectors=0 not supported\n");
-                       goto out_invalid_cdb_field;
-               }
+       if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE))
+               goto out;
 
-               cmd->t_task_lba = get_unaligned_be32(&cdb[2]);
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               /*
-                * Follow sbcr26 with WRITE_SAME (10) and check for the existence
-                * of byte 1 bit 3 UNMAP instead of original reserved field
-                */
-               if (target_check_write_same_discard(&cdb[1], dev) < 0)
-                       goto out_unsupported_cdb;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_write_same;
-               break;
-       case ALLOW_MEDIUM_REMOVAL:
-       case ERASE:
-       case REZERO_UNIT:
-       case SEEK_10:
-       case SPACE:
-       case START_STOP:
-       case TEST_UNIT_READY:
-       case VERIFY:
-       case WRITE_FILEMARKS:
-               cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
-               if (!passthrough)
-                       cmd->execute_cmd = target_emulate_noop;
-               break;
-       case GPCMD_CLOSE_TRACK:
-       case INITIALIZE_ELEMENT_STATUS:
-       case GPCMD_LOAD_UNLOAD:
-       case GPCMD_SET_SPEED:
-       case MOVE_MEDIUM:
-               cmd->se_cmd_flags |= SCF_SCSI_NON_DATA_CDB;
-               break;
-       case REPORT_LUNS:
-               cmd->execute_cmd = target_report_luns;
-               size = (cdb[6] << 24) | (cdb[7] << 16) | (cdb[8] << 8) | cdb[9];
-               /*
-                * Do implict HEAD_OF_QUEUE processing for REPORT_LUNS
-                * See spc4r17 section 5.3
-                */
-               if (cmd->se_dev->dev_task_attr_type == SAM_TASK_ATTR_EMULATED)
-                       cmd->sam_task_attr = MSG_HEAD_TAG;
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case GET_EVENT_STATUS_NOTIFICATION:
-               size = (cdb[7] << 8) | cdb[8];
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       case ATA_16:
-               /* Only support ATA passthrough to pSCSI backends.. */
-               if (!passthrough)
-                       goto out_unsupported_cdb;
-
-               /* T_LENGTH */
-               switch (cdb[2] & 0x3) {
-               case 0x0:
-                       sectors = 0;
-                       break;
-               case 0x1:
-                       sectors = (((cdb[1] & 0x1) ? cdb[3] : 0) << 8) | cdb[4];
-                       break;
-               case 0x2:
-                       sectors = (((cdb[1] & 0x1) ? cdb[5] : 0) << 8) | cdb[6];
-                       break;
-               case 0x3:
-                       pr_err("T_LENGTH=0x3 not supported for ATA_16\n");
-                       goto out_invalid_cdb_field;
-               }
+       if (!dev->transport->get_sense_buffer) {
+               pr_err("dev->transport->get_sense_buffer is NULL\n");
+               goto out;
+       }
 
-               /* BYTE_BLOCK */
-               if (cdb[2] & 0x4) {
-                       /* BLOCK T_TYPE: 512 or sector */
-                       size = sectors * ((cdb[2] & 0x10) ?
-                               dev->se_sub_dev->se_dev_attrib.block_size : 512);
-               } else {
-                       /* BYTE */
-                       size = sectors;
-               }
-               cmd->se_cmd_flags |= SCF_SCSI_CONTROL_SG_IO_CDB;
-               break;
-       default:
-               pr_warn("TARGET_CORE[%s]: Unsupported SCSI Opcode"
-                       " 0x%02x, sending CHECK_CONDITION.\n",
-                       cmd->se_tfo->get_fabric_name(), cdb[0]);
-               goto out_unsupported_cdb;
+       sense_buffer = dev->transport->get_sense_buffer(cmd);
+       if (!sense_buffer) {
+               pr_err("ITT 0x%08x cmd %p: Unable to locate"
+                       " sense buffer for task with sense\n",
+                       cmd->se_tfo->get_task_tag(cmd), cmd);
+               goto out;
        }
 
-       if (cmd->unknown_data_length)
-               cmd->data_length = size;
+       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-       if (size != cmd->data_length) {
-               pr_warn("TARGET_CORE[%s]: Expected Transfer Length:"
-                       " %u does not match SCSI CDB Length: %u for SAM Opcode:"
-                       " 0x%02x\n", cmd->se_tfo->get_fabric_name(),
-                               cmd->data_length, size, cdb[0]);
+       offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER);
 
-               cmd->cmd_spdtl = size;
+       memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER);
 
-               if (cmd->data_direction == DMA_TO_DEVICE) {
-                       pr_err("Rejecting underflow/overflow"
-                                       " WRITE data\n");
-                       goto out_invalid_cdb_field;
-               }
-               /*
-                * Reject READ_* or WRITE_* with overflow/underflow for
-                * type SCF_SCSI_DATA_SG_IO_CDB.
-                */
-               if (!ret && (dev->se_sub_dev->se_dev_attrib.block_size != 512))  {
-                       pr_err("Failing OVERFLOW/UNDERFLOW for LBA op"
-                               " CDB on non 512-byte sector setup subsystem"
-                               " plugin: %s\n", dev->transport->name);
-                       /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */
-                       goto out_invalid_cdb_field;
-               }
+       /* Automatically padded */
+       cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset;
 
-               if (size > cmd->data_length) {
-                       cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
-                       cmd->residual_count = (size - cmd->data_length);
-               } else {
-                       cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
-                       cmd->residual_count = (cmd->data_length - size);
-               }
-               cmd->data_length = size;
-       }
+       pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n",
+               dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status);
+       return 0;
 
-       if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
-               if (sectors > su_dev->se_dev_attrib.fabric_max_sectors) {
-                       printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
-                               " big sectors %u exceeds fabric_max_sectors:"
-                               " %u\n", cdb[0], sectors,
-                               su_dev->se_dev_attrib.fabric_max_sectors);
-                       goto out_invalid_cdb_field;
-               }
-               if (sectors > su_dev->se_dev_attrib.hw_max_sectors) {
-                       printk_ratelimited(KERN_ERR "SCSI OP %02xh with too"
-                               " big sectors %u exceeds backend hw_max_sectors:"
-                               " %u\n", cdb[0], sectors,
-                               su_dev->se_dev_attrib.hw_max_sectors);
-                       goto out_invalid_cdb_field;
+out:
+       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
+       return -1;
+}
+
+/*
+ * Process all commands up to the last received ORDERED task attribute which
+ * requires another blocking boundary
+ */
+static void target_restart_delayed_cmds(struct se_device *dev)
+{
+       for (;;) {
+               struct se_cmd *cmd;
+
+               spin_lock(&dev->delayed_cmd_lock);
+               if (list_empty(&dev->delayed_cmd_list)) {
+                       spin_unlock(&dev->delayed_cmd_lock);
+                       break;
                }
-       }
 
-       /* reject any command that we don't have a handler for */
-       if (!(passthrough || cmd->execute_cmd ||
-            (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB)))
-               goto out_unsupported_cdb;
+               cmd = list_entry(dev->delayed_cmd_list.next,
+                                struct se_cmd, se_delayed_node);
+               list_del(&cmd->se_delayed_node);
+               spin_unlock(&dev->delayed_cmd_lock);
 
-       transport_set_supported_SAM_opcode(cmd);
-       return ret;
+               __target_execute_cmd(cmd);
 
-out_unsupported_cdb:
-       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-       cmd->scsi_sense_reason = TCM_UNSUPPORTED_SCSI_OPCODE;
-       return -EINVAL;
-out_invalid_cdb_field:
-       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-       return -EINVAL;
+               if (cmd->sam_task_attr == MSG_ORDERED_TAG)
+                       break;
+       }
 }
 
 /*
@@ -3052,8 +1906,6 @@ out_invalid_cdb_field:
 static void transport_complete_task_attr(struct se_cmd *cmd)
 {
        struct se_device *dev = cmd->se_dev;
-       struct se_cmd *cmd_p, *cmd_tmp;
-       int new_active_tasks = 0;
 
        if (cmd->sam_task_attr == MSG_SIMPLE_TAG) {
                atomic_dec(&dev->simple_cmds);
@@ -3075,38 +1927,8 @@ static void transport_complete_task_attr(struct se_cmd *cmd)
                pr_debug("Incremented dev_cur_ordered_id: %u for ORDERED:"
                        " %u\n", dev->dev_cur_ordered_id, cmd->se_ordered_id);
        }
-       /*
-        * Process all commands up to the last received
-        * ORDERED task attribute which requires another blocking
-        * boundary
-        */
-       spin_lock(&dev->delayed_cmd_lock);
-       list_for_each_entry_safe(cmd_p, cmd_tmp,
-                       &dev->delayed_cmd_list, se_delayed_node) {
 
-               list_del(&cmd_p->se_delayed_node);
-               spin_unlock(&dev->delayed_cmd_lock);
-
-               pr_debug("Calling add_tasks() for"
-                       " cmd_p: 0x%02x Task Attr: 0x%02x"
-                       " Dormant -> Active, se_ordered_id: %u\n",
-                       cmd_p->t_task_cdb[0],
-                       cmd_p->sam_task_attr, cmd_p->se_ordered_id);
-
-               target_add_to_execute_list(cmd_p);
-               new_active_tasks++;
-
-               spin_lock(&dev->delayed_cmd_lock);
-               if (cmd_p->sam_task_attr == MSG_ORDERED_TAG)
-                       break;
-       }
-       spin_unlock(&dev->delayed_cmd_lock);
-       /*
-        * If new tasks have become active, wake up the transport thread
-        * to do the processing of the Active tasks.
-        */
-       if (new_active_tasks != 0)
-               wake_up_interruptible(&dev->dev_queue_obj.thread_wq);
+       target_restart_delayed_cmds(dev);
 }
 
 static void transport_complete_qf(struct se_cmd *cmd)
@@ -3365,31 +2187,27 @@ int transport_generic_map_mem_to_cmd(
        if (!sgl || !sgl_count)
                return 0;
 
-       if ((cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) ||
-           (cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB)) {
-               /*
-                * Reject SCSI data overflow with map_mem_to_cmd() as incoming
-                * scatterlists already have been set to follow what the fabric
-                * passes for the original expected data transfer length.
-                */
-               if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
-                       pr_warn("Rejecting SCSI DATA overflow for fabric using"
-                               " SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n");
-                       cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
-                       cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
-                       return -EINVAL;
-               }
+       /*
+        * Reject SCSI data overflow with map_mem_to_cmd() as incoming
+        * scatterlists already have been set to follow what the fabric
+        * passes for the original expected data transfer length.
+        */
+       if (cmd->se_cmd_flags & SCF_OVERFLOW_BIT) {
+               pr_warn("Rejecting SCSI DATA overflow for fabric using"
+                       " SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC\n");
+               cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
+               cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+               return -EINVAL;
+       }
 
-               cmd->t_data_sg = sgl;
-               cmd->t_data_nents = sgl_count;
+       cmd->t_data_sg = sgl;
+       cmd->t_data_nents = sgl_count;
 
-               if (sgl_bidi && sgl_bidi_count) {
-                       cmd->t_bidi_data_sg = sgl_bidi;
-                       cmd->t_bidi_data_nents = sgl_bidi_count;
-               }
-               cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
+       if (sgl_bidi && sgl_bidi_count) {
+               cmd->t_bidi_data_sg = sgl_bidi;
+               cmd->t_bidi_data_nents = sgl_bidi_count;
        }
-
+       cmd->se_cmd_flags |= SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC;
        return 0;
 }
 EXPORT_SYMBOL(transport_generic_map_mem_to_cmd);
@@ -3461,7 +2279,7 @@ transport_generic_get_mem(struct se_cmd *cmd)
        cmd->t_data_nents = nents;
        sg_init_table(cmd->t_data_sg, nents);
 
-       zero_flag = cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB ? 0 : __GFP_ZERO;
+       zero_flag = cmd->se_cmd_flags & SCF_SCSI_DATA_CDB ? 0 : __GFP_ZERO;
 
        while (length) {
                u32 page_len = min_t(u32, length, PAGE_SIZE);
@@ -3492,7 +2310,6 @@ out:
  */
 int transport_generic_new_cmd(struct se_cmd *cmd)
 {
-       struct se_device *dev = cmd->se_dev;
        int ret = 0;
 
        /*
@@ -3508,8 +2325,7 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
        }
 
        /* Workaround for handling zero-length control CDBs */
-       if ((cmd->se_cmd_flags & SCF_SCSI_CONTROL_SG_IO_CDB) &&
-           !cmd->data_length) {
+       if (!(cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) && !cmd->data_length) {
                spin_lock_irq(&cmd->t_state_lock);
                cmd->t_state = TRANSPORT_COMPLETE;
                cmd->transport_state |= CMD_T_ACTIVE;
@@ -3527,52 +2343,45 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
                return 0;
        }
 
-       if (cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) {
-               struct se_dev_attrib *attr = &dev->se_sub_dev->se_dev_attrib;
-
-               if (transport_cmd_get_valid_sectors(cmd) < 0)
-                       return -EINVAL;
-
-               BUG_ON(cmd->data_length % attr->block_size);
-               BUG_ON(DIV_ROUND_UP(cmd->data_length, attr->block_size) >
-                       attr->hw_max_sectors);
-       }
-
        atomic_inc(&cmd->t_fe_count);
 
        /*
-        * For WRITEs, let the fabric know its buffer is ready.
-        *
-        * The command will be added to the execution queue after its write
-        * data has arrived.
+        * If this command is not a write we can execute it right here,
+        * for write buffers we need to notify the fabric driver first
+        * and let it call back once the write buffers are ready.
         */
-       if (cmd->data_direction == DMA_TO_DEVICE) {
-               target_add_to_state_list(cmd);
-               return transport_generic_write_pending(cmd);
+       target_add_to_state_list(cmd);
+       if (cmd->data_direction != DMA_TO_DEVICE) {
+               target_execute_cmd(cmd);
+               return 0;
        }
-       /*
-        * Everything else but a WRITE, add the command to the execution queue.
-        */
-       transport_execute_tasks(cmd);
-       return 0;
+
+       spin_lock_irq(&cmd->t_state_lock);
+       cmd->t_state = TRANSPORT_WRITE_PENDING;
+       spin_unlock_irq(&cmd->t_state_lock);
+
+       transport_cmd_check_stop(cmd, false);
+
+       ret = cmd->se_tfo->write_pending(cmd);
+       if (ret == -EAGAIN || ret == -ENOMEM)
+               goto queue_full;
+
+       if (ret < 0)
+               return ret;
+       return 1;
 
 out_fail:
        cmd->se_cmd_flags |= SCF_SCSI_CDB_EXCEPTION;
        cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
        return -EINVAL;
+queue_full:
+       pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd);
+       cmd->t_state = TRANSPORT_COMPLETE_QF_WP;
+       transport_handle_queue_full(cmd, cmd->se_dev);
+       return 0;
 }
 EXPORT_SYMBOL(transport_generic_new_cmd);
 
-/*     transport_generic_process_write():
- *
- *
- */
-void transport_generic_process_write(struct se_cmd *cmd)
-{
-       transport_execute_tasks(cmd);
-}
-EXPORT_SYMBOL(transport_generic_process_write);
-
 static void transport_write_pending_qf(struct se_cmd *cmd)
 {
        int ret;
@@ -3585,43 +2394,6 @@ static void transport_write_pending_qf(struct se_cmd *cmd)
        }
 }
 
-static int transport_generic_write_pending(struct se_cmd *cmd)
-{
-       unsigned long flags;
-       int ret;
-
-       spin_lock_irqsave(&cmd->t_state_lock, flags);
-       cmd->t_state = TRANSPORT_WRITE_PENDING;
-       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
-       /*
-        * Clear the se_cmd for WRITE_PENDING status in order to set
-        * CMD_T_ACTIVE so that transport_generic_handle_data can be called
-        * from HW target mode interrupt code.  This is safe to be called
-        * with transport_off=1 before the cmd->se_tfo->write_pending
-        * because the se_cmd->se_lun pointer is not being cleared.
-        */
-       transport_cmd_check_stop(cmd, 1, 0);
-
-       /*
-        * Call the fabric write_pending function here to let the
-        * frontend know that WRITE buffers are ready.
-        */
-       ret = cmd->se_tfo->write_pending(cmd);
-       if (ret == -EAGAIN || ret == -ENOMEM)
-               goto queue_full;
-       else if (ret < 0)
-               return ret;
-
-       return 1;
-
-queue_full:
-       pr_debug("Handling write_pending QUEUE__FULL: se_cmd: %p\n", cmd);
-       cmd->t_state = TRANSPORT_COMPLETE_QF_WP;
-       transport_handle_queue_full(cmd, cmd->se_dev);
-       return 0;
-}
-
 void transport_generic_free_cmd(struct se_cmd *cmd, int wait_for_tasks)
 {
        if (!(cmd->se_cmd_flags & SCF_SE_LUN_CMD)) {
@@ -3648,10 +2420,11 @@ EXPORT_SYMBOL(transport_generic_free_cmd);
  * @se_cmd:    command descriptor to add
  * @ack_kref:  Signal that fabric will perform an ack target_put_sess_cmd()
  */
-void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
-                       bool ack_kref)
+static int target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
+                              bool ack_kref)
 {
        unsigned long flags;
+       int ret = 0;
 
        kref_init(&se_cmd->cmd_kref);
        /*
@@ -3665,11 +2438,17 @@ void target_get_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd,
        }
 
        spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
+       if (se_sess->sess_tearing_down) {
+               ret = -ESHUTDOWN;
+               goto out;
+       }
        list_add_tail(&se_cmd->se_cmd_list, &se_sess->sess_cmd_list);
        se_cmd->check_release = 1;
+
+out:
        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
+       return ret;
 }
-EXPORT_SYMBOL(target_get_sess_cmd);
 
 static void target_release_cmd_kref(struct kref *kref)
 {
@@ -3704,28 +2483,27 @@ int target_put_sess_cmd(struct se_session *se_sess, struct se_cmd *se_cmd)
 }
 EXPORT_SYMBOL(target_put_sess_cmd);
 
-/* target_splice_sess_cmd_list - Split active cmds into sess_wait_list
- * @se_sess:   session to split
+/* target_sess_cmd_list_set_waiting - Flag all commands in
+ *         sess_cmd_list to complete cmd_wait_comp.  Set
+ *         sess_tearing_down so no more commands are queued.
+ * @se_sess:   session to flag
  */
-void target_splice_sess_cmd_list(struct se_session *se_sess)
+void target_sess_cmd_list_set_waiting(struct se_session *se_sess)
 {
        struct se_cmd *se_cmd;
        unsigned long flags;
 
-       WARN_ON(!list_empty(&se_sess->sess_wait_list));
-       INIT_LIST_HEAD(&se_sess->sess_wait_list);
-
        spin_lock_irqsave(&se_sess->sess_cmd_lock, flags);
-       se_sess->sess_tearing_down = 1;
 
-       list_splice_init(&se_sess->sess_cmd_list, &se_sess->sess_wait_list);
+       WARN_ON(se_sess->sess_tearing_down);
+       se_sess->sess_tearing_down = 1;
 
-       list_for_each_entry(se_cmd, &se_sess->sess_wait_list, se_cmd_list)
+       list_for_each_entry(se_cmd, &se_sess->sess_cmd_list, se_cmd_list)
                se_cmd->cmd_wait_set = 1;
 
        spin_unlock_irqrestore(&se_sess->sess_cmd_lock, flags);
 }
-EXPORT_SYMBOL(target_splice_sess_cmd_list);
+EXPORT_SYMBOL(target_sess_cmd_list_set_waiting);
 
 /* target_wait_for_sess_cmds - Wait for outstanding descriptors
  * @se_sess:    session to wait for active I/O
@@ -3739,7 +2517,7 @@ void target_wait_for_sess_cmds(
        bool rc = false;
 
        list_for_each_entry_safe(se_cmd, tmp_cmd,
-                               &se_sess->sess_wait_list, se_cmd_list) {
+                               &se_sess->sess_cmd_list, se_cmd_list) {
                list_del(&se_cmd->se_cmd_list);
 
                pr_debug("Waiting for se_cmd: %p t_state: %d, fabric state:"
@@ -3791,26 +2569,20 @@ static int transport_lun_wait_for_tasks(struct se_cmd *cmd, struct se_lun *lun)
                pr_debug("ConfigFS ITT[0x%08x] - CMD_T_STOP, skipping\n",
                         cmd->se_tfo->get_task_tag(cmd));
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-               transport_cmd_check_stop(cmd, 1, 0);
+               transport_cmd_check_stop(cmd, false);
                return -EPERM;
        }
        cmd->transport_state |= CMD_T_LUN_FE_STOP;
        spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-       wake_up_interruptible(&cmd->se_dev->dev_queue_obj.thread_wq);
-
        // XXX: audit task_flags checks.
        spin_lock_irqsave(&cmd->t_state_lock, flags);
        if ((cmd->transport_state & CMD_T_BUSY) &&
            (cmd->transport_state & CMD_T_SENT)) {
                if (!target_stop_cmd(cmd, &flags))
                        ret++;
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-       } else {
-               spin_unlock_irqrestore(&cmd->t_state_lock,
-                               flags);
-               target_remove_from_execute_list(cmd);
        }
+       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
        pr_debug("ConfigFS: cmd: %p stop tasks ret:"
                        " %d\n", cmd, ret);
@@ -3821,7 +2593,6 @@ static int transport_lun_wait_for_tasks(struct se_cmd *cmd, struct se_lun *lun)
                pr_debug("ConfigFS: ITT[0x%08x] - stopped cmd....\n",
                                cmd->se_tfo->get_task_tag(cmd));
        }
-       transport_remove_cmd_from_queue(cmd);
 
        return 0;
 }
@@ -3840,11 +2611,6 @@ static void __transport_clear_lun_from_sessions(struct se_lun *lun)
                       struct se_cmd, se_lun_node);
                list_del_init(&cmd->se_lun_node);
 
-               /*
-                * This will notify iscsi_target_transport.c:
-                * transport_cmd_check_stop() that a LUN shutdown is in
-                * progress for the iscsi_cmd_t.
-                */
                spin_lock(&cmd->t_state_lock);
                pr_debug("SE_LUN[%d] - Setting cmd->transport"
                        "_lun_stop for  ITT: 0x%08x\n",
@@ -3911,7 +2677,7 @@ check_cond:
 
                        spin_unlock_irqrestore(&cmd->t_state_lock,
                                        cmd_flags);
-                       transport_cmd_check_stop(cmd, 1, 0);
+                       transport_cmd_check_stop(cmd, false);
                        complete(&cmd->transport_lun_fe_stop_comp);
                        spin_lock_irqsave(&lun->lun_cmd_lock, lun_flags);
                        continue;
@@ -3967,10 +2733,7 @@ bool transport_wait_for_tasks(struct se_cmd *cmd)
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
                return false;
        }
-       /*
-        * Only perform a possible wait_for_tasks if SCF_SUPPORTED_SAM_OPCODE
-        * has been set in transport_set_supported_SAM_opcode().
-        */
+
        if (!(cmd->se_cmd_flags & SCF_SUPPORTED_SAM_OPCODE) &&
            !(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) {
                spin_unlock_irqrestore(&cmd->t_state_lock, flags);
@@ -4028,8 +2791,6 @@ bool transport_wait_for_tasks(struct se_cmd *cmd)
 
        spin_unlock_irqrestore(&cmd->t_state_lock, flags);
 
-       wake_up_interruptible(&cmd->se_dev->dev_queue_obj.thread_wq);
-
        wait_for_completion(&cmd->t_transport_stop_comp);
 
        spin_lock_irqsave(&cmd->t_state_lock, flags);
@@ -4212,6 +2973,15 @@ int transport_send_check_condition_and_sense(
                /* WRITE PROTECTED */
                buffer[offset+SPC_ASC_KEY_OFFSET] = 0x27;
                break;
+       case TCM_ADDRESS_OUT_OF_RANGE:
+               /* CURRENT ERROR */
+               buffer[offset] = 0x70;
+               buffer[offset+SPC_ADD_SENSE_LEN_OFFSET] = 10;
+               /* ILLEGAL REQUEST */
+               buffer[offset+SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
+               /* LOGICAL BLOCK ADDRESS OUT OF RANGE */
+               buffer[offset+SPC_ASC_KEY_OFFSET] = 0x21;
+               break;
        case TCM_CHECK_CONDITION_UNIT_ATTENTION:
                /* CURRENT ERROR */
                buffer[offset] = 0x70;
@@ -4312,8 +3082,9 @@ void transport_send_task_abort(struct se_cmd *cmd)
        cmd->se_tfo->queue_status(cmd);
 }
 
-static int transport_generic_do_tmr(struct se_cmd *cmd)
+static void target_tmr_work(struct work_struct *work)
 {
+       struct se_cmd *cmd = container_of(work, struct se_cmd, work);
        struct se_device *dev = cmd->se_dev;
        struct se_tmr_req *tmr = cmd->se_tmr_req;
        int ret;
@@ -4349,80 +3120,13 @@ static int transport_generic_do_tmr(struct se_cmd *cmd)
        cmd->se_tfo->queue_tm_rsp(cmd);
 
        transport_cmd_check_stop_to_fabric(cmd);
-       return 0;
 }
 
-/*     transport_processing_thread():
- *
- *
- */
-static int transport_processing_thread(void *param)
+int transport_generic_handle_tmr(
+       struct se_cmd *cmd)
 {
-       int ret;
-       struct se_cmd *cmd;
-       struct se_device *dev = param;
-
-       while (!kthread_should_stop()) {
-               ret = wait_event_interruptible(dev->dev_queue_obj.thread_wq,
-                               atomic_read(&dev->dev_queue_obj.queue_cnt) ||
-                               kthread_should_stop());
-               if (ret < 0)
-                       goto out;
-
-get_cmd:
-               cmd = transport_get_cmd_from_queue(&dev->dev_queue_obj);
-               if (!cmd)
-                       continue;
-
-               switch (cmd->t_state) {
-               case TRANSPORT_NEW_CMD:
-                       BUG();
-                       break;
-               case TRANSPORT_NEW_CMD_MAP:
-                       if (!cmd->se_tfo->new_cmd_map) {
-                               pr_err("cmd->se_tfo->new_cmd_map is"
-                                       " NULL for TRANSPORT_NEW_CMD_MAP\n");
-                               BUG();
-                       }
-                       ret = cmd->se_tfo->new_cmd_map(cmd);
-                       if (ret < 0) {
-                               transport_generic_request_failure(cmd);
-                               break;
-                       }
-                       ret = transport_generic_new_cmd(cmd);
-                       if (ret < 0) {
-                               transport_generic_request_failure(cmd);
-                               break;
-                       }
-                       break;
-               case TRANSPORT_PROCESS_WRITE:
-                       transport_generic_process_write(cmd);
-                       break;
-               case TRANSPORT_PROCESS_TMR:
-                       transport_generic_do_tmr(cmd);
-                       break;
-               case TRANSPORT_COMPLETE_QF_WP:
-                       transport_write_pending_qf(cmd);
-                       break;
-               case TRANSPORT_COMPLETE_QF_OK:
-                       transport_complete_qf(cmd);
-                       break;
-               default:
-                       pr_err("Unknown t_state: %d  for ITT: 0x%08x "
-                               "i_state: %d on SE LUN: %u\n",
-                               cmd->t_state,
-                               cmd->se_tfo->get_task_tag(cmd),
-                               cmd->se_tfo->get_cmd_state(cmd),
-                               cmd->se_lun->unpacked_lun);
-                       BUG();
-               }
-
-               goto get_cmd;
-       }
-
-out:
-       WARN_ON(!list_empty(&dev->state_list));
-       WARN_ON(!list_empty(&dev->dev_queue_obj.qobj_list));
-       dev->process_thread = NULL;
+       INIT_WORK(&cmd->work, target_tmr_work);
+       queue_work(cmd->se_dev->tmr_wq, &cmd->work);
        return 0;
 }
+EXPORT_SYMBOL(transport_generic_handle_tmr);
index 5b65f33939a84ab6eef4a12cc0fe84b61d64e96c..b9cb5006177e22166732032468bf8d0a733299f8 100644 (file)
@@ -215,7 +215,7 @@ int ft_write_pending(struct se_cmd *se_cmd)
                 */
                if ((ep->xid <= lport->lro_xid) &&
                    (fh->fh_r_ctl == FC_RCTL_DD_DATA_DESC)) {
-                       if ((se_cmd->se_cmd_flags & SCF_SCSI_DATA_SG_IO_CDB) &&
+                       if ((se_cmd->se_cmd_flags & SCF_SCSI_DATA_CDB) &&
                            lport->tt.ddp_target(lport, ep->xid,
                                                 se_cmd->t_data_sg,
                                                 se_cmd->t_data_nents))
@@ -543,9 +543,11 @@ static void ft_send_work(struct work_struct *work)
         * Use a single se_cmd->cmd_kref as we expect to release se_cmd
         * directly from ft_check_stop_free callback in response path.
         */
-       target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb,
-                       &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun),
-                       ntohl(fcp->fc_dl), task_attr, data_dir, 0);
+       if (target_submit_cmd(&cmd->se_cmd, cmd->sess->se_sess, fcp->fc_cdb,
+                             &cmd->ft_sense_buffer[0], scsilun_to_int(&fcp->fc_lun),
+                             ntohl(fcp->fc_dl), task_attr, data_dir, 0))
+               goto err;
+
        pr_debug("r_ctl %x alloc target_submit_cmd\n", fh->fh_r_ctl);
        return;
 
index 071a505f98fc13256fa536f4a39cae111ccd1050..ad36ede1a1eab12b907964ca8c446262d2918528 100644 (file)
@@ -183,6 +183,13 @@ int ft_queue_data_in(struct se_cmd *se_cmd)
        return ft_queue_status(se_cmd);
 }
 
+static void ft_execute_work(struct work_struct *work)
+{
+       struct ft_cmd *cmd = container_of(work, struct ft_cmd, work);
+
+       target_execute_cmd(&cmd->se_cmd);
+}
+
 /*
  * Receive write data frame.
  */
@@ -307,8 +314,10 @@ void ft_recv_write_data(struct ft_cmd *cmd, struct fc_frame *fp)
                cmd->write_data_len += tlen;
        }
 last_frame:
-       if (cmd->write_data_len == se_cmd->data_length)
-               transport_generic_handle_data(se_cmd);
+       if (cmd->write_data_len == se_cmd->data_length) {
+               INIT_WORK(&cmd->work, ft_execute_work);
+               queue_work(cmd->sess->tport->tpg->workqueue, &cmd->work);
+       }
 drop:
        fc_frame_free(fp);
 }
index 4ef747307ecbb51a8ae195191243000e16c51795..d5c689d6217e3a2eb46223fa1ffd01b77e15e0df 100644 (file)
 #define SERIAL_IMX_MAJOR        207
 #define MINOR_START            16
 #define DEV_NAME               "ttymxc"
-#define MAX_INTERNAL_IRQ       MXC_INTERNAL_IRQS
 
 /*
  * This determines how often we check the modem status signals
@@ -741,10 +740,7 @@ static int imx_startup(struct uart_port *port)
 
                /* do not use RTS IRQ on IrDA */
                if (!USE_IRDA(sport)) {
-                       retval = request_irq(sport->rtsirq, imx_rtsint,
-                                    (sport->rtsirq < MAX_INTERNAL_IRQ) ? 0 :
-                                      IRQF_TRIGGER_FALLING |
-                                      IRQF_TRIGGER_RISING,
+                       retval = request_irq(sport->rtsirq, imx_rtsint, 0,
                                        DRIVER_NAME, sport);
                        if (retval)
                                goto error_out3;
index ec56d8397aae4f2caca41058574ec2b3fcd36356..2e341b81ff891b632e5cbee6d2337aba0f10cfe8 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/pinctrl/consumer.h>
+#include <linux/of_device.h>
 
 #include <asm/cacheflush.h>
 
@@ -675,6 +676,30 @@ static struct uart_driver auart_driver = {
 #endif
 };
 
+/*
+ * This function returns 1 if pdev isn't a device instatiated by dt, 0 if it
+ * could successfully get all information from dt or a negative errno.
+ */
+static int serial_mxs_probe_dt(struct mxs_auart_port *s,
+               struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       int ret;
+
+       if (!np)
+               /* no device tree device */
+               return 1;
+
+       ret = of_alias_get_id(np, "serial");
+       if (ret < 0) {
+               dev_err(&pdev->dev, "failed to get alias id: %d\n", ret);
+               return ret;
+       }
+       s->port.line = ret;
+
+       return 0;
+}
+
 static int __devinit mxs_auart_probe(struct platform_device *pdev)
 {
        struct mxs_auart_port *s;
@@ -689,6 +714,12 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
                goto out;
        }
 
+       ret = serial_mxs_probe_dt(s, pdev);
+       if (ret > 0)
+               s->port.line = pdev->id < 0 ? 0 : pdev->id;
+       else if (ret < 0)
+               goto out_free;
+
        pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
        if (IS_ERR(pinctrl)) {
                ret = PTR_ERR(pinctrl);
@@ -711,7 +742,6 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
        s->port.membase = ioremap(r->start, resource_size(r));
        s->port.ops = &mxs_auart_ops;
        s->port.iotype = UPIO_MEM;
-       s->port.line = pdev->id < 0 ? 0 : pdev->id;
        s->port.fifosize = 16;
        s->port.uartclk = clk_get_rate(s->clk);
        s->port.type = PORT_IMX;
@@ -728,7 +758,7 @@ static int __devinit mxs_auart_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, s);
 
-       auart_port[pdev->id] = s;
+       auart_port[s->port.line] = s;
 
        mxs_auart_reset(&s->port);
 
@@ -769,12 +799,19 @@ static int __devexit mxs_auart_remove(struct platform_device *pdev)
        return 0;
 }
 
+static struct of_device_id mxs_auart_dt_ids[] = {
+       { .compatible = "fsl,imx23-auart", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxs_auart_dt_ids);
+
 static struct platform_driver mxs_auart_driver = {
        .probe = mxs_auart_probe,
        .remove = __devexit_p(mxs_auart_remove),
        .driver = {
                .name = "mxs-auart",
                .owner = THIS_MODULE,
+               .of_match_table = mxs_auart_dt_ids,
        },
 };
 
@@ -807,3 +844,4 @@ module_init(mxs_auart_init);
 module_exit(mxs_auart_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Freescale MXS application uart driver");
+MODULE_ALIAS("platform:mxs-auart");
index bddc8fd9a7be3f65bab41b9b6b56c5cea2cd2e4e..271ca161d7ef0c77e87f02e9c10db94034391340 100644 (file)
@@ -185,7 +185,7 @@ config USB_FUSB300
 
 config USB_OMAP
        tristate "OMAP USB Device Controller"
-       depends on ARCH_OMAP
+       depends on ARCH_OMAP1
        select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG
        select USB_OTG_UTILS if ARCH_OMAP
        help
index a460e8c204f42c9bacbac82c55c83bf9896e6672..89cbd2b22ab03b0b378e011b2d8e040429389be0 100644 (file)
@@ -44,7 +44,8 @@
 #include <asm/mach-types.h>
 
 #include <plat/dma.h>
-#include <plat/usb.h>
+
+#include <mach/usb.h>
 
 #include "omap_udc.h"
 
index c46439c8dd7462b2ba39e38f7129a9a1fa10ab41..5444866e13ef72c8ddd7c9a693803c02cd37a61a 100644 (file)
@@ -294,7 +294,7 @@ static int bot_send_write_request(struct usbg_cmd *cmd)
                pr_err("%s(%d)\n", __func__, __LINE__);
 
        wait_for_completion(&cmd->write_complete);
-       transport_generic_process_write(se_cmd);
+       target_execute_cmd(se_cmd);
 cleanup:
        return ret;
 }
@@ -725,7 +725,7 @@ static int uasp_send_write_request(struct usbg_cmd *cmd)
        }
 
        wait_for_completion(&cmd->write_complete);
-       transport_generic_process_write(se_cmd);
+       target_execute_cmd(se_cmd);
 cleanup:
        return ret;
 }
@@ -1065,16 +1065,20 @@ static void usbg_cmd_work(struct work_struct *work)
                                tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,
                                tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
                                cmd->prio_attr, cmd->sense_iu.sense);
-
-               transport_send_check_condition_and_sense(se_cmd,
-                               TCM_UNSUPPORTED_SCSI_OPCODE, 1);
-               usbg_cleanup_cmd(cmd);
-               return;
+               goto out;
        }
 
-       target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
+       if (target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
                        cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun,
-                       0, cmd->prio_attr, dir, TARGET_SCF_UNKNOWN_SIZE);
+                       0, cmd->prio_attr, dir, TARGET_SCF_UNKNOWN_SIZE) < 0)
+               goto out;
+
+       return;
+
+out:
+       transport_send_check_condition_and_sense(se_cmd,
+                       TCM_UNSUPPORTED_SCSI_OPCODE, 1);
+       usbg_cleanup_cmd(cmd);
 }
 
 static int usbg_submit_command(struct f_uas *fu,
@@ -1177,16 +1181,20 @@ static void bot_cmd_work(struct work_struct *work)
                                tv_nexus->tvn_se_sess->se_tpg->se_tpg_tfo,
                                tv_nexus->tvn_se_sess, cmd->data_len, DMA_NONE,
                                cmd->prio_attr, cmd->sense_iu.sense);
-
-               transport_send_check_condition_and_sense(se_cmd,
-                               TCM_UNSUPPORTED_SCSI_OPCODE, 1);
-               usbg_cleanup_cmd(cmd);
-               return;
+               goto out;
        }
 
-       target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
+       if (target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
                        cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun,
-                       cmd->data_len, cmd->prio_attr, dir, 0);
+                       cmd->data_len, cmd->prio_attr, dir, 0) < 0)
+               goto out;
+
+       return;
+
+out:
+       transport_send_check_condition_and_sense(se_cmd,
+                               TCM_UNSUPPORTED_SCSI_OPCODE, 1);
+       usbg_cleanup_cmd(cmd);
 }
 
 static int bot_submit_command(struct f_uas *fu,
@@ -1400,19 +1408,6 @@ static u32 usbg_tpg_get_inst_index(struct se_portal_group *se_tpg)
        return 1;
 }
 
-static int usbg_new_cmd(struct se_cmd *se_cmd)
-{
-       struct usbg_cmd *cmd = container_of(se_cmd, struct usbg_cmd,
-                       se_cmd);
-       int ret;
-
-       ret = target_setup_cmd_from_cdb(se_cmd, cmd->cmd_buf);
-       if (ret)
-               return ret;
-
-       return transport_generic_map_mem_to_cmd(se_cmd, NULL, 0, NULL, 0);
-}
-
 static void usbg_cmd_release(struct kref *ref)
 {
        struct usbg_cmd *cmd = container_of(ref, struct usbg_cmd,
@@ -1902,7 +1897,6 @@ static struct target_core_fabric_ops usbg_ops = {
        .tpg_alloc_fabric_acl           = usbg_alloc_fabric_acl,
        .tpg_release_fabric_acl         = usbg_release_fabric_acl,
        .tpg_get_inst_index             = usbg_tpg_get_inst_index,
-       .new_cmd_map                    = usbg_new_cmd,
        .release_cmd                    = usbg_release_cmd,
        .shutdown_session               = usbg_shutdown_session,
        .close_session                  = usbg_close_session,
index 83e58df29fe3ad32b1a7fc3c27cecc84f4e0a472..dcfaaa91a3fbe0ebf9fba190c223545086b76816 100644 (file)
@@ -308,7 +308,7 @@ config USB_OHCI_HCD
 
 config USB_OHCI_HCD_OMAP1
        bool "OHCI support for OMAP1/2 chips"
-       depends on USB_OHCI_HCD && (ARCH_OMAP1 || ARCH_OMAP2)
+       depends on USB_OHCI_HCD && ARCH_OMAP1
        default y
        ---help---
          Enables support for the OHCI controller on OMAP1/2 chips.
index 800be38c78b47f5d7990243bc71bd8fb14c2bdc6..1d9401e0990a0760716c0407575de6b0908c3b4c 100644 (file)
@@ -1349,6 +1349,11 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ehci_msm_driver
 #endif
 
+#ifdef CONFIG_TILE_USB
+#include "ehci-tilegx.c"
+#define        PLATFORM_DRIVER         ehci_hcd_tilegx_driver
+#endif
+
 #ifdef CONFIG_USB_EHCI_HCD_PMC_MSP
 #include "ehci-pmcmsp.c"
 #define        PLATFORM_DRIVER         ehci_hcd_msp_driver
index 68548236ec4228ceb224d69845daba6345bf9971..ab8a3bf628e3480cc197e3e2c2e1ea32667bb85d 100644 (file)
@@ -46,8 +46,8 @@ static void tegra_ehci_power_up(struct usb_hcd *hcd)
 {
        struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
 
-       clk_enable(tegra->emc_clk);
-       clk_enable(tegra->clk);
+       clk_prepare_enable(tegra->emc_clk);
+       clk_prepare_enable(tegra->clk);
        tegra_usb_phy_power_on(tegra->phy);
        tegra->host_resumed = 1;
 }
@@ -58,8 +58,8 @@ static void tegra_ehci_power_down(struct usb_hcd *hcd)
 
        tegra->host_resumed = 0;
        tegra_usb_phy_power_off(tegra->phy);
-       clk_disable(tegra->clk);
-       clk_disable(tegra->emc_clk);
+       clk_disable_unprepare(tegra->clk);
+       clk_disable_unprepare(tegra->emc_clk);
 }
 
 static int tegra_ehci_internal_port_reset(
@@ -671,7 +671,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
                goto fail_clk;
        }
 
-       err = clk_enable(tegra->clk);
+       err = clk_prepare_enable(tegra->clk);
        if (err)
                goto fail_clken;
 
@@ -682,7 +682,7 @@ static int tegra_ehci_probe(struct platform_device *pdev)
                goto fail_emc_clk;
        }
 
-       clk_enable(tegra->emc_clk);
+       clk_prepare_enable(tegra->emc_clk);
        clk_set_rate(tegra->emc_clk, 400000000);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -782,10 +782,10 @@ fail:
 fail_phy:
        iounmap(hcd->regs);
 fail_io:
-       clk_disable(tegra->emc_clk);
+       clk_disable_unprepare(tegra->emc_clk);
        clk_put(tegra->emc_clk);
 fail_emc_clk:
-       clk_disable(tegra->clk);
+       clk_disable_unprepare(tegra->clk);
 fail_clken:
        clk_put(tegra->clk);
 fail_clk:
@@ -820,10 +820,10 @@ static int tegra_ehci_remove(struct platform_device *pdev)
        tegra_usb_phy_close(tegra->phy);
        iounmap(hcd->regs);
 
-       clk_disable(tegra->clk);
+       clk_disable_unprepare(tegra->clk);
        clk_put(tegra->clk);
 
-       clk_disable(tegra->emc_clk);
+       clk_disable_unprepare(tegra->emc_clk);
        clk_put(tegra->emc_clk);
 
        kfree(tegra);
diff --git a/drivers/usb/host/ehci-tilegx.c b/drivers/usb/host/ehci-tilegx.c
new file mode 100644 (file)
index 0000000..1d215cd
--- /dev/null
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/*
+ * Tilera TILE-Gx USB EHCI host controller driver.
+ */
+
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/usb/tilegx.h>
+#include <linux/usb.h>
+
+#include <asm/homecache.h>
+
+#include <gxio/iorpc_usb_host.h>
+#include <gxio/usb_host.h>
+
+static void tilegx_start_ehc(void)
+{
+}
+
+static void tilegx_stop_ehc(void)
+{
+}
+
+static int tilegx_ehci_setup(struct usb_hcd *hcd)
+{
+       int ret = ehci_init(hcd);
+
+       /*
+        * Some drivers do:
+        *
+        *   struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+        *   ehci->need_io_watchdog = 0;
+        *
+        * here, but since this is a new driver we're going to leave the
+        * watchdog enabled.  Later we may try to turn it off and see
+        * whether we run into any problems.
+        */
+
+       return ret;
+}
+
+static const struct hc_driver ehci_tilegx_hc_driver = {
+       .description            = hcd_name,
+       .product_desc           = "Tile-Gx EHCI",
+       .hcd_priv_size          = sizeof(struct ehci_hcd),
+
+       /*
+        * Generic hardware linkage.
+        */
+       .irq                    = ehci_irq,
+       .flags                  = HCD_MEMORY | HCD_USB2,
+
+       /*
+        * Basic lifecycle operations.
+        */
+       .reset                  = tilegx_ehci_setup,
+       .start                  = ehci_run,
+       .stop                   = ehci_stop,
+       .shutdown               = ehci_shutdown,
+
+       /*
+        * Managing I/O requests and associated device resources.
+        */
+       .urb_enqueue            = ehci_urb_enqueue,
+       .urb_dequeue            = ehci_urb_dequeue,
+       .endpoint_disable       = ehci_endpoint_disable,
+       .endpoint_reset         = ehci_endpoint_reset,
+
+       /*
+        * Scheduling support.
+        */
+       .get_frame_number       = ehci_get_frame,
+
+       /*
+        * Root hub support.
+        */
+       .hub_status_data        = ehci_hub_status_data,
+       .hub_control            = ehci_hub_control,
+       .bus_suspend            = ehci_bus_suspend,
+       .bus_resume             = ehci_bus_resume,
+       .relinquish_port        = ehci_relinquish_port,
+       .port_handed_over       = ehci_port_handed_over,
+
+       .clear_tt_buffer_complete       = ehci_clear_tt_buffer_complete,
+};
+
+static int ehci_hcd_tilegx_drv_probe(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd;
+       struct ehci_hcd *ehci;
+       struct tilegx_usb_platform_data *pdata = pdev->dev.platform_data;
+       pte_t pte = { 0 };
+       int my_cpu = smp_processor_id();
+       int ret;
+
+       if (usb_disabled())
+               return -ENODEV;
+
+       /*
+        * Try to initialize our GXIO context; if we can't, the device
+        * doesn't exist.
+        */
+       if (gxio_usb_host_init(&pdata->usb_ctx, pdata->dev_index, 1) != 0)
+               return -ENXIO;
+
+       hcd = usb_create_hcd(&ehci_tilegx_hc_driver, &pdev->dev,
+                            dev_name(&pdev->dev));
+       if (!hcd)
+               return -ENOMEM;
+
+       /*
+        * We don't use rsrc_start to map in our registers, but seems like
+        * we ought to set it to something, so we use the register VA.
+        */
+       hcd->rsrc_start =
+               (ulong) gxio_usb_host_get_reg_start(&pdata->usb_ctx);
+       hcd->rsrc_len = gxio_usb_host_get_reg_len(&pdata->usb_ctx);
+       hcd->regs = gxio_usb_host_get_reg_start(&pdata->usb_ctx);
+
+       tilegx_start_ehc();
+
+       ehci = hcd_to_ehci(hcd);
+       ehci->caps = hcd->regs;
+       ehci->regs =
+               hcd->regs + HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
+       /* cache this readonly data; minimize chip reads */
+       ehci->hcs_params = readl(&ehci->caps->hcs_params);
+
+       /* Create our IRQs and register them. */
+       pdata->irq = create_irq();
+       if (pdata->irq < 0) {
+               ret = -ENXIO;
+               goto err_no_irq;
+       }
+
+       tile_irq_activate(pdata->irq, TILE_IRQ_PERCPU);
+
+       /* Configure interrupts. */
+       ret = gxio_usb_host_cfg_interrupt(&pdata->usb_ctx,
+                                         cpu_x(my_cpu), cpu_y(my_cpu),
+                                         KERNEL_PL, pdata->irq);
+       if (ret) {
+               ret = -ENXIO;
+               goto err_have_irq;
+       }
+
+       /* Register all of our memory. */
+       pte = pte_set_home(pte, PAGE_HOME_HASH);
+       ret = gxio_usb_host_register_client_memory(&pdata->usb_ctx, pte, 0);
+       if (ret) {
+               ret = -ENXIO;
+               goto err_have_irq;
+       }
+
+       ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED);
+       if (ret == 0) {
+               platform_set_drvdata(pdev, hcd);
+               return ret;
+       }
+
+err_have_irq:
+       destroy_irq(pdata->irq);
+err_no_irq:
+       tilegx_stop_ehc();
+       usb_put_hcd(hcd);
+       gxio_usb_host_destroy(&pdata->usb_ctx);
+       return ret;
+}
+
+static int ehci_hcd_tilegx_drv_remove(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+       struct tilegx_usb_platform_data *pdata = pdev->dev.platform_data;
+
+       usb_remove_hcd(hcd);
+       usb_put_hcd(hcd);
+       tilegx_stop_ehc();
+       gxio_usb_host_destroy(&pdata->usb_ctx);
+       destroy_irq(pdata->irq);
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static void ehci_hcd_tilegx_drv_shutdown(struct platform_device *pdev)
+{
+       usb_hcd_platform_shutdown(pdev);
+       ehci_hcd_tilegx_drv_remove(pdev);
+}
+
+static struct platform_driver ehci_hcd_tilegx_driver = {
+       .probe          = ehci_hcd_tilegx_drv_probe,
+       .remove         = ehci_hcd_tilegx_drv_remove,
+       .shutdown       = ehci_hcd_tilegx_drv_shutdown,
+       .driver = {
+               .name   = "tilegx-ehci",
+               .owner  = THIS_MODULE,
+       }
+};
+
+MODULE_ALIAS("platform:tilegx-ehci");
index e0adf5c0cf556ba2193f373e88080e5163407fa1..2b1e8d84c87387f7f532b1056ec91e6fac3c3b22 100644 (file)
@@ -1100,6 +1100,11 @@ MODULE_LICENSE ("GPL");
 #define PLATFORM_DRIVER                ohci_octeon_driver
 #endif
 
+#ifdef CONFIG_TILE_USB
+#include "ohci-tilegx.c"
+#define PLATFORM_DRIVER                ohci_hcd_tilegx_driver
+#endif
+
 #ifdef CONFIG_USB_CNS3XXX_OHCI
 #include "ohci-cns3xxx.c"
 #define PLATFORM_DRIVER                ohci_hcd_cns3xxx_driver
index 9ce35d0d9d5daad531209e6b651a1fcc714efb18..b02c344e2cc928b652e6af5358474647d81c4ba9 100644 (file)
 #include <linux/clk.h>
 #include <linux/gpio.h>
 
-#include <mach/hardware.h>
 #include <asm/io.h>
 #include <asm/mach-types.h>
 
 #include <plat/mux.h>
-#include <mach/irqs.h>
 #include <plat/fpga.h>
-#include <plat/usb.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/usb.h>
 
 
 /* OMAP-1510 OHCI has its own MMU for DMA */
diff --git a/drivers/usb/host/ohci-tilegx.c b/drivers/usb/host/ohci-tilegx.c
new file mode 100644 (file)
index 0000000..1ae7b28
--- /dev/null
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/*
+ * Tilera TILE-Gx USB OHCI host controller driver.
+ */
+
+#include <linux/irq.h>
+#include <linux/platform_device.h>
+#include <linux/usb/tilegx.h>
+#include <linux/usb.h>
+
+#include <asm/homecache.h>
+
+#include <gxio/iorpc_usb_host.h>
+#include <gxio/usb_host.h>
+
+static void tilegx_start_ohc(void)
+{
+}
+
+static void tilegx_stop_ohc(void)
+{
+}
+
+static int tilegx_ohci_start(struct usb_hcd *hcd)
+{
+       struct ohci_hcd *ohci = hcd_to_ohci(hcd);
+       int ret;
+
+       ret = ohci_init(ohci);
+       if (ret < 0)
+               return ret;
+
+       ret = ohci_run(ohci);
+       if (ret < 0) {
+               dev_err(hcd->self.controller, "can't start %s\n",
+                       hcd->self.bus_name);
+               ohci_stop(hcd);
+               return ret;
+       }
+
+       return 0;
+}
+
+static const struct hc_driver ohci_tilegx_hc_driver = {
+       .description            = hcd_name,
+       .product_desc           = "Tile-Gx OHCI",
+       .hcd_priv_size          = sizeof(struct ohci_hcd),
+
+       /*
+        * Generic hardware linkage.
+        */
+       .irq                    = ohci_irq,
+       .flags                  = HCD_MEMORY | HCD_LOCAL_MEM | HCD_USB11,
+
+       /*
+        * Basic lifecycle operations.
+        */
+       .start                  = tilegx_ohci_start,
+       .stop                   = ohci_stop,
+       .shutdown               = ohci_shutdown,
+
+       /*
+        * Managing I/O requests and associated device resources.
+        */
+       .urb_enqueue            = ohci_urb_enqueue,
+       .urb_dequeue            = ohci_urb_dequeue,
+       .endpoint_disable       = ohci_endpoint_disable,
+
+       /*
+        * Scheduling support.
+        */
+       .get_frame_number       = ohci_get_frame,
+
+       /*
+        * Root hub support.
+        */
+       .hub_status_data        = ohci_hub_status_data,
+       .hub_control            = ohci_hub_control,
+       .start_port_reset       = ohci_start_port_reset,
+};
+
+static int ohci_hcd_tilegx_drv_probe(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd;
+       struct tilegx_usb_platform_data *pdata = pdev->dev.platform_data;
+       pte_t pte = { 0 };
+       int my_cpu = smp_processor_id();
+       int ret;
+
+       if (usb_disabled())
+               return -ENODEV;
+
+       /*
+        * Try to initialize our GXIO context; if we can't, the device
+        * doesn't exist.
+        */
+       if (gxio_usb_host_init(&pdata->usb_ctx, pdata->dev_index, 0) != 0)
+               return -ENXIO;
+
+       hcd = usb_create_hcd(&ohci_tilegx_hc_driver, &pdev->dev,
+                            dev_name(&pdev->dev));
+       if (!hcd)
+               return -ENOMEM;
+
+       /*
+        * We don't use rsrc_start to map in our registers, but seems like
+        * we ought to set it to something, so we use the register VA.
+        */
+       hcd->rsrc_start =
+               (ulong) gxio_usb_host_get_reg_start(&pdata->usb_ctx);
+       hcd->rsrc_len = gxio_usb_host_get_reg_len(&pdata->usb_ctx);
+       hcd->regs = gxio_usb_host_get_reg_start(&pdata->usb_ctx);
+
+       tilegx_start_ohc();
+
+       /* Create our IRQs and register them. */
+       pdata->irq = create_irq();
+       if (pdata->irq < 0) {
+               ret = -ENXIO;
+               goto err_no_irq;
+       }
+
+       tile_irq_activate(pdata->irq, TILE_IRQ_PERCPU);
+
+       /* Configure interrupts. */
+       ret = gxio_usb_host_cfg_interrupt(&pdata->usb_ctx,
+                                         cpu_x(my_cpu), cpu_y(my_cpu),
+                                         KERNEL_PL, pdata->irq);
+       if (ret) {
+               ret = -ENXIO;
+               goto err_have_irq;
+       }
+
+       /* Register all of our memory. */
+       pte = pte_set_home(pte, PAGE_HOME_HASH);
+       ret = gxio_usb_host_register_client_memory(&pdata->usb_ctx, pte, 0);
+       if (ret) {
+               ret = -ENXIO;
+               goto err_have_irq;
+       }
+
+       ohci_hcd_init(hcd_to_ohci(hcd));
+
+       ret = usb_add_hcd(hcd, pdata->irq, IRQF_SHARED);
+       if (ret == 0) {
+               platform_set_drvdata(pdev, hcd);
+               return ret;
+       }
+
+err_have_irq:
+       destroy_irq(pdata->irq);
+err_no_irq:
+       tilegx_stop_ohc();
+       usb_put_hcd(hcd);
+       gxio_usb_host_destroy(&pdata->usb_ctx);
+       return ret;
+}
+
+static int ohci_hcd_tilegx_drv_remove(struct platform_device *pdev)
+{
+       struct usb_hcd *hcd = platform_get_drvdata(pdev);
+       struct tilegx_usb_platform_data* pdata = pdev->dev.platform_data;
+
+       usb_remove_hcd(hcd);
+       usb_put_hcd(hcd);
+       tilegx_stop_ohc();
+       gxio_usb_host_destroy(&pdata->usb_ctx);
+       destroy_irq(pdata->irq);
+       platform_set_drvdata(pdev, NULL);
+
+       return 0;
+}
+
+static void ohci_hcd_tilegx_drv_shutdown(struct platform_device *pdev)
+{
+       usb_hcd_platform_shutdown(pdev);
+       ohci_hcd_tilegx_drv_remove(pdev);
+}
+
+static struct platform_driver ohci_hcd_tilegx_driver = {
+       .probe          = ohci_hcd_tilegx_drv_probe,
+       .remove         = ohci_hcd_tilegx_drv_remove,
+       .shutdown       = ohci_hcd_tilegx_drv_shutdown,
+       .driver = {
+               .name   = "tilegx-ohci",
+               .owner  = THIS_MODULE,
+       }
+};
+
+MODULE_ALIAS("platform:tilegx-ohci");
index 70cf5d7bca48ed25ee08aa6e5fa40dec52b4268a..e0558dfcfafcb21ca413c401990eee9d0c48b0c4 100644 (file)
@@ -36,9 +36,9 @@
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
-#include <plat/usb.h>
 #include <plat/mux.h>
 
+#include <mach/usb.h>
 
 #ifndef        DEBUG
 #undef VERBOSE
index abbe691047bde3ac8cdc05042a27873be649ea71..49619b4415000efc1ef87756d09667017a682244 100644 (file)
 
 #include <linux/module.h>
 #include <linux/kernel.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/pinctrl/consumer.h>
-#include <mach/mxsfb.h>
+#include <linux/mxsfb.h>
 
 #define REG_SET        4
 #define REG_CLR        8
@@ -750,16 +752,43 @@ static void __devexit mxsfb_free_videomem(struct mxsfb_info *host)
        }
 }
 
+static struct platform_device_id mxsfb_devtype[] = {
+       {
+               .name = "imx23-fb",
+               .driver_data = MXSFB_V3,
+       }, {
+               .name = "imx28-fb",
+               .driver_data = MXSFB_V4,
+       }, {
+               /* sentinel */
+       }
+};
+MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
+
+static const struct of_device_id mxsfb_dt_ids[] = {
+       { .compatible = "fsl,imx23-lcdif", .data = &mxsfb_devtype[0], },
+       { .compatible = "fsl,imx28-lcdif", .data = &mxsfb_devtype[1], },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, mxsfb_dt_ids);
+
 static int __devinit mxsfb_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *of_id =
+                       of_match_device(mxsfb_dt_ids, &pdev->dev);
        struct mxsfb_platform_data *pdata = pdev->dev.platform_data;
        struct resource *res;
        struct mxsfb_info *host;
        struct fb_info *fb_info;
        struct fb_modelist *modelist;
        struct pinctrl *pinctrl;
+       int panel_enable;
+       enum of_gpio_flags flags;
        int i, ret;
 
+       if (of_id)
+               pdev->id_entry = of_id->data;
+
        if (!pdata) {
                dev_err(&pdev->dev, "No platformdata. Giving up\n");
                return -ENODEV;
@@ -807,6 +836,22 @@ static int __devinit mxsfb_probe(struct platform_device *pdev)
                goto error_getclock;
        }
 
+       panel_enable = of_get_named_gpio_flags(pdev->dev.of_node,
+                                              "panel-enable-gpios", 0, &flags);
+       if (gpio_is_valid(panel_enable)) {
+               unsigned long f = GPIOF_OUT_INIT_HIGH;
+               if (flags == OF_GPIO_ACTIVE_LOW)
+                       f = GPIOF_OUT_INIT_LOW;
+               ret = devm_gpio_request_one(&pdev->dev, panel_enable,
+                                           f, "panel-enable");
+               if (ret) {
+                       dev_err(&pdev->dev,
+                               "failed to request gpio %d: %d\n",
+                               panel_enable, ret);
+                       goto error_panel_enable;
+               }
+       }
+
        fb_info->pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL);
        if (!fb_info->pseudo_palette) {
                ret = -ENOMEM;
@@ -854,6 +899,7 @@ error_register:
 error_init_fb:
        kfree(fb_info->pseudo_palette);
 error_pseudo_pallette:
+error_panel_enable:
        clk_put(host->clk);
 error_getclock:
 error_getpin:
@@ -901,19 +947,6 @@ static void mxsfb_shutdown(struct platform_device *pdev)
        writel(CTRL_RUN, host->base + LCDC_CTRL + REG_CLR);
 }
 
-static struct platform_device_id mxsfb_devtype[] = {
-       {
-               .name = "imx23-fb",
-               .driver_data = MXSFB_V3,
-       }, {
-               .name = "imx28-fb",
-               .driver_data = MXSFB_V4,
-       }, {
-               /* sentinel */
-       }
-};
-MODULE_DEVICE_TABLE(platform, mxsfb_devtype);
-
 static struct platform_driver mxsfb_driver = {
        .probe = mxsfb_probe,
        .remove = __devexit_p(mxsfb_remove),
@@ -921,6 +954,7 @@ static struct platform_driver mxsfb_driver = {
        .id_table = mxsfb_devtype,
        .driver = {
                   .name = DRIVER_NAME,
+                  .of_match_table = mxsfb_dt_ids,
        },
 };
 
index 979d6eed9a0ff5178657ad5a36a1f203b87814b2..5ceb1cd501955003182fe62b365da7d1b5d282f2 100644 (file)
@@ -60,7 +60,7 @@ config W1_MASTER_GPIO
 
 config HDQ_MASTER_OMAP
        tristate "OMAP HDQ driver"
-       depends on SOC_OMAP2430 || ARCH_OMAP3
+       depends on ARCH_OMAP2PLUS
        help
          Say Y here if you want support for the 1-wire or HDQ Interface
          on an OMAP processor.
index 5ef385bfed18bedb5c7c6c5852af82449c1adc90..291897c881be5c67462ec86d6dafb0b073097a5d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * drivers/w1/masters/omap_hdq.c
  *
- * Copyright (C) 2007 Texas Instruments, Inc.
+ * Copyright (C) 2007,2012 Texas Instruments, Inc.
  *
  * This file is licensed under the terms of the GNU General Public License
  * version 2. This program is licensed "as is" without any warranty of any
@@ -14,9 +14,9 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/err.h>
-#include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/sched.h>
+#include <linux/pm_runtime.h>
 
 #include <asm/irq.h>
 #include <mach/hardware.h>
@@ -61,8 +61,6 @@ struct hdq_data {
        /* lock status update */
        struct  mutex           hdq_mutex;
        int                     hdq_usecount;
-       struct  clk             *hdq_ick;
-       struct  clk             *hdq_fck;
        u8                      hdq_irqstatus;
        /* device lock */
        spinlock_t              hdq_spinlock;
@@ -102,20 +100,20 @@ static struct w1_bus_master omap_w1_master = {
 /* HDQ register I/O routines */
 static inline u8 hdq_reg_in(struct hdq_data *hdq_data, u32 offset)
 {
-       return __raw_readb(hdq_data->hdq_base + offset);
+       return __raw_readl(hdq_data->hdq_base + offset);
 }
 
 static inline void hdq_reg_out(struct hdq_data *hdq_data, u32 offset, u8 val)
 {
-       __raw_writeb(val, hdq_data->hdq_base + offset);
+       __raw_writel(val, hdq_data->hdq_base + offset);
 }
 
 static inline u8 hdq_reg_merge(struct hdq_data *hdq_data, u32 offset,
                        u8 val, u8 mask)
 {
-       u8 new_val = (__raw_readb(hdq_data->hdq_base + offset) & ~mask)
+       u8 new_val = (__raw_readl(hdq_data->hdq_base + offset) & ~mask)
                        | (val & mask);
-       __raw_writeb(new_val, hdq_data->hdq_base + offset);
+       __raw_writel(new_val, hdq_data->hdq_base + offset);
 
        return new_val;
 }
@@ -419,17 +417,8 @@ static int omap_hdq_get(struct hdq_data *hdq_data)
                hdq_data->hdq_usecount++;
                try_module_get(THIS_MODULE);
                if (1 == hdq_data->hdq_usecount) {
-                       if (clk_enable(hdq_data->hdq_ick)) {
-                               dev_dbg(hdq_data->dev, "Can not enable ick\n");
-                               ret = -ENODEV;
-                               goto clk_err;
-                       }
-                       if (clk_enable(hdq_data->hdq_fck)) {
-                               dev_dbg(hdq_data->dev, "Can not enable fck\n");
-                               clk_disable(hdq_data->hdq_ick);
-                               ret = -ENODEV;
-                               goto clk_err;
-                       }
+
+                       pm_runtime_get_sync(hdq_data->dev);
 
                        /* make sure HDQ is out of reset */
                        if (!(hdq_reg_in(hdq_data, OMAP_HDQ_SYSSTATUS) &
@@ -450,9 +439,6 @@ static int omap_hdq_get(struct hdq_data *hdq_data)
                }
        }
 
-clk_err:
-       clk_put(hdq_data->hdq_ick);
-       clk_put(hdq_data->hdq_fck);
 out:
        mutex_unlock(&hdq_data->hdq_mutex);
 rtn:
@@ -475,10 +461,8 @@ static int omap_hdq_put(struct hdq_data *hdq_data)
        } else {
                hdq_data->hdq_usecount--;
                module_put(THIS_MODULE);
-               if (0 == hdq_data->hdq_usecount) {
-                       clk_disable(hdq_data->hdq_ick);
-                       clk_disable(hdq_data->hdq_fck);
-               }
+               if (0 == hdq_data->hdq_usecount)
+                       pm_runtime_put_sync(hdq_data->dev);
        }
        mutex_unlock(&hdq_data->hdq_mutex);
 
@@ -591,35 +575,11 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)
                goto err_ioremap;
        }
 
-       /* get interface & functional clock objects */
-       hdq_data->hdq_ick = clk_get(&pdev->dev, "ick");
-       if (IS_ERR(hdq_data->hdq_ick)) {
-               dev_dbg(&pdev->dev, "Can't get HDQ ick clock object\n");
-               ret = PTR_ERR(hdq_data->hdq_ick);
-               goto err_ick;
-       }
-
-       hdq_data->hdq_fck = clk_get(&pdev->dev, "fck");
-       if (IS_ERR(hdq_data->hdq_fck)) {
-               dev_dbg(&pdev->dev, "Can't get HDQ fck clock object\n");
-               ret = PTR_ERR(hdq_data->hdq_fck);
-               goto err_fck;
-       }
-
        hdq_data->hdq_usecount = 0;
        mutex_init(&hdq_data->hdq_mutex);
 
-       if (clk_enable(hdq_data->hdq_ick)) {
-               dev_dbg(&pdev->dev, "Can not enable ick\n");
-               ret = -ENODEV;
-               goto err_intfclk;
-       }
-
-       if (clk_enable(hdq_data->hdq_fck)) {
-               dev_dbg(&pdev->dev, "Can not enable fck\n");
-               ret = -ENODEV;
-               goto err_fnclk;
-       }
+       pm_runtime_enable(&pdev->dev);
+       pm_runtime_get_sync(&pdev->dev);
 
        rev = hdq_reg_in(hdq_data, OMAP_HDQ_REVISION);
        dev_info(&pdev->dev, "OMAP HDQ Hardware Rev %c.%c. Driver in %s mode\n",
@@ -641,9 +601,7 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)
 
        omap_hdq_break(hdq_data);
 
-       /* don't clock the HDQ until it is needed */
-       clk_disable(hdq_data->hdq_ick);
-       clk_disable(hdq_data->hdq_fck);
+       pm_runtime_put_sync(&pdev->dev);
 
        omap_w1_master.data = hdq_data;
 
@@ -655,20 +613,11 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)
 
        return 0;
 
-err_w1:
 err_irq:
-       clk_disable(hdq_data->hdq_fck);
-
-err_fnclk:
-       clk_disable(hdq_data->hdq_ick);
-
-err_intfclk:
-       clk_put(hdq_data->hdq_fck);
-
-err_fck:
-       clk_put(hdq_data->hdq_ick);
+       pm_runtime_put_sync(&pdev->dev);
+err_w1:
+       pm_runtime_disable(&pdev->dev);
 
-err_ick:
        iounmap(hdq_data->hdq_base);
 
 err_ioremap:
@@ -696,8 +645,7 @@ static int omap_hdq_remove(struct platform_device *pdev)
        mutex_unlock(&hdq_data->hdq_mutex);
 
        /* remove module dependency */
-       clk_put(hdq_data->hdq_ick);
-       clk_put(hdq_data->hdq_fck);
+       pm_runtime_disable(&pdev->dev);
        free_irq(INT_24XX_HDQ_IRQ, hdq_data);
        platform_set_drvdata(pdev, NULL);
        iounmap(hdq_data->hdq_base);
index fe819b76de5685f2cf28a2db9000a117ca8338ce..c450cfcd702f77367395ff875b4a5e73ed7d96bd 100644 (file)
@@ -1115,10 +1115,10 @@ config BOOKE_WDT
 config BOOKE_WDT_DEFAULT_TIMEOUT
        int "PowerPC Book-E Watchdog Timer Default Timeout"
        depends on BOOKE_WDT
-       default 38 if FSL_BOOKE
-       range 0 63 if FSL_BOOKE
-       default 3 if !FSL_BOOKE
-       range 0 3 if !FSL_BOOKE
+       default 38 if PPC_FSL_BOOK3E
+       range 0 63 if PPC_FSL_BOOK3E
+       default 3 if !PPC_FSL_BOOK3E
+       range 0 3 if !PPC_FSL_BOOK3E
        help
          Select the default watchdog timer period to be used by the PowerPC
          Book-E watchdog driver.  A watchdog "event" occurs when the bit
index ce0ab4415eff2cb0fb4c0fc3b9d6deb9ca14e010..3fe82d0e8caae583a2bdd8ac41a30bec5540fa43 100644 (file)
@@ -37,7 +37,7 @@
 u32 booke_wdt_enabled;
 u32 booke_wdt_period = CONFIG_BOOKE_WDT_DEFAULT_TIMEOUT;
 
-#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_PPC_FSL_BOOK3E
 #define WDTP(x)                ((((x)&0x3)<<30)|(((x)&0x3c)<<15))
 #define WDTP_MASK      (WDTP(0x3f))
 #else
@@ -190,7 +190,7 @@ static long booke_wdt_ioctl(struct file *file,
        case WDIOC_SETTIMEOUT:
                if (get_user(tmp, p))
                        return -EFAULT;
-#ifdef CONFIG_FSL_BOOKE
+#ifdef CONFIG_PPC_FSL_BOOK3E
                /* period of 1 gives the largest possible timeout */
                if (tmp > period_to_sec(1))
                        return -EINVAL;
index 8285d65cd2074ff71b954a16e30e39c719808623..02ebfd5f0e6534a5e19536bf5a4115a1e0ed07e4 100644 (file)
@@ -430,6 +430,12 @@ static int omap_wdt_resume(struct platform_device *pdev)
 #define        omap_wdt_resume         NULL
 #endif
 
+static const struct of_device_id omap_wdt_of_match[] = {
+       { .compatible = "ti,omap3-wdt", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, omap_wdt_of_match);
+
 static struct platform_driver omap_wdt_driver = {
        .probe          = omap_wdt_probe,
        .remove         = __devexit_p(omap_wdt_remove),
@@ -439,6 +445,7 @@ static struct platform_driver omap_wdt_driver = {
        .driver         = {
                .owner  = THIS_MODULE,
                .name   = "omap_wdt",
+               .of_match_table = omap_wdt_of_match,
        },
 };
 
index e78956cbd7021c81a50d7bd6e9220ffa9623bb22..34c59f14a1c9d9b4deea3f8fa3a55830813d3498 100644 (file)
@@ -144,7 +144,7 @@ extern void v9fs_session_close(struct v9fs_session_info *v9ses);
 extern void v9fs_session_cancel(struct v9fs_session_info *v9ses);
 extern void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses);
 extern struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
-                       struct nameidata *nameidata);
+                       unsigned int flags);
 extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d);
 extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d);
 extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry,
index d529437ff44269f79cb707592a8e504bf4744cea..64600b5d0522c203ac6e8a4043462fe6e513d4aa 100644 (file)
@@ -100,13 +100,13 @@ static void v9fs_dentry_release(struct dentry *dentry)
        }
 }
 
-static int v9fs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct p9_fid *fid;
        struct inode *inode;
        struct v9fs_inode *v9inode;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        inode = dentry->d_inode;
index 57ccb7537dae3064b6892e4f6af6cff8bcada3a6..cbf9dbb1b2a270f4ebd911f7b1aca3d0107969e3 100644 (file)
@@ -712,88 +712,34 @@ error:
 }
 
 /**
- * v9fs_vfs_create - VFS hook to create files
+ * v9fs_vfs_create - VFS hook to create a regular file
+ *
+ * open(.., O_CREAT) is handled in v9fs_vfs_atomic_open().  This is only called
+ * for mknod(2).
+ *
  * @dir: directory inode that is being created
  * @dentry:  dentry that is being deleted
  * @mode: create permissions
- * @nd: path information
  *
  */
 
 static int
 v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
-       int err;
-       u32 perm;
-       int flags;
-       struct file *filp;
-       struct v9fs_inode *v9inode;
-       struct v9fs_session_info *v9ses;
-       struct p9_fid *fid, *inode_fid;
-
-       err = 0;
-       fid = NULL;
-       v9ses = v9fs_inode2v9ses(dir);
-       perm = unixmode2p9mode(v9ses, mode);
-       if (nd)
-               flags = nd->intent.open.flags;
-       else
-               flags = O_RDWR;
+       struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir);
+       u32 perm = unixmode2p9mode(v9ses, mode);
+       struct p9_fid *fid;
 
-       fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
-                               v9fs_uflags2omode(flags,
-                                               v9fs_proto_dotu(v9ses)));
-       if (IS_ERR(fid)) {
-               err = PTR_ERR(fid);
-               fid = NULL;
-               goto error;
-       }
+       /* P9_OEXCL? */
+       fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_ORDWR);
+       if (IS_ERR(fid))
+               return PTR_ERR(fid);
 
        v9fs_invalidate_inode_attr(dir);
-       /* if we are opening a file, assign the open fid to the file */
-       if (nd) {
-               v9inode = V9FS_I(dentry->d_inode);
-               mutex_lock(&v9inode->v_mutex);
-               if (v9ses->cache && !v9inode->writeback_fid &&
-                   ((flags & O_ACCMODE) != O_RDONLY)) {
-                       /*
-                        * clone a fid and add it to writeback_fid
-                        * we do it during open time instead of
-                        * page dirty time via write_begin/page_mkwrite
-                        * because we want write after unlink usecase
-                        * to work.
-                        */
-                       inode_fid = v9fs_writeback_fid(dentry);
-                       if (IS_ERR(inode_fid)) {
-                               err = PTR_ERR(inode_fid);
-                               mutex_unlock(&v9inode->v_mutex);
-                               goto error;
-                       }
-                       v9inode->writeback_fid = (void *) inode_fid;
-               }
-               mutex_unlock(&v9inode->v_mutex);
-               filp = lookup_instantiate_filp(nd, dentry, generic_file_open);
-               if (IS_ERR(filp)) {
-                       err = PTR_ERR(filp);
-                       goto error;
-               }
-
-               filp->private_data = fid;
-#ifdef CONFIG_9P_FSCACHE
-               if (v9ses->cache)
-                       v9fs_cache_inode_set_cookie(dentry->d_inode, filp);
-#endif
-       } else
-               p9_client_clunk(fid);
+       p9_client_clunk(fid);
 
        return 0;
-
-error:
-       if (fid)
-               p9_client_clunk(fid);
-
-       return err;
 }
 
 /**
@@ -839,7 +785,7 @@ static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
  */
 
 struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
-                                     struct nameidata *nameidata)
+                                     unsigned int flags)
 {
        struct dentry *res;
        struct super_block *sb;
@@ -849,8 +795,8 @@ struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry,
        char *name;
        int result = 0;
 
-       p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p nameidata: %p\n",
-                dir, dentry->d_name.name, dentry, nameidata);
+       p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p flags: %x\n",
+                dir, dentry->d_name.name, dentry, flags);
 
        if (dentry->d_name.len > NAME_MAX)
                return ERR_PTR(-ENAMETOOLONG);
@@ -910,6 +856,86 @@ error:
        return ERR_PTR(result);
 }
 
+static int
+v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry,
+                    struct file *file, unsigned flags, umode_t mode,
+                    int *opened)
+{
+       int err;
+       u32 perm;
+       struct v9fs_inode *v9inode;
+       struct v9fs_session_info *v9ses;
+       struct p9_fid *fid, *inode_fid;
+       struct dentry *res = NULL;
+
+       if (d_unhashed(dentry)) {
+               res = v9fs_vfs_lookup(dir, dentry, 0);
+               if (IS_ERR(res))
+                       return PTR_ERR(res);
+
+               if (res)
+                       dentry = res;
+       }
+
+       /* Only creates */
+       if (!(flags & O_CREAT) || dentry->d_inode)
+               return finish_no_open(file, res);
+
+       err = 0;
+       fid = NULL;
+       v9ses = v9fs_inode2v9ses(dir);
+       perm = unixmode2p9mode(v9ses, mode);
+       fid = v9fs_create(v9ses, dir, dentry, NULL, perm,
+                               v9fs_uflags2omode(flags,
+                                               v9fs_proto_dotu(v9ses)));
+       if (IS_ERR(fid)) {
+               err = PTR_ERR(fid);
+               fid = NULL;
+               goto error;
+       }
+
+       v9fs_invalidate_inode_attr(dir);
+       v9inode = V9FS_I(dentry->d_inode);
+       mutex_lock(&v9inode->v_mutex);
+       if (v9ses->cache && !v9inode->writeback_fid &&
+           ((flags & O_ACCMODE) != O_RDONLY)) {
+               /*
+                * clone a fid and add it to writeback_fid
+                * we do it during open time instead of
+                * page dirty time via write_begin/page_mkwrite
+                * because we want write after unlink usecase
+                * to work.
+                */
+               inode_fid = v9fs_writeback_fid(dentry);
+               if (IS_ERR(inode_fid)) {
+                       err = PTR_ERR(inode_fid);
+                       mutex_unlock(&v9inode->v_mutex);
+                       goto error;
+               }
+               v9inode->writeback_fid = (void *) inode_fid;
+       }
+       mutex_unlock(&v9inode->v_mutex);
+       err = finish_open(file, dentry, generic_file_open, opened);
+       if (err)
+               goto error;
+
+       file->private_data = fid;
+#ifdef CONFIG_9P_FSCACHE
+       if (v9ses->cache)
+               v9fs_cache_inode_set_cookie(dentry->d_inode, file);
+#endif
+
+       *opened |= FILE_CREATED;
+out:
+       dput(res);
+       return err;
+
+error:
+       if (fid)
+               p9_client_clunk(fid);
+       goto out;
+}
+
 /**
  * v9fs_vfs_unlink - VFS unlink hook to delete an inode
  * @i:  inode that is being unlinked
@@ -1488,6 +1514,7 @@ out:
 static const struct inode_operations v9fs_dir_inode_operations_dotu = {
        .create = v9fs_vfs_create,
        .lookup = v9fs_vfs_lookup,
+       .atomic_open = v9fs_vfs_atomic_open,
        .symlink = v9fs_vfs_symlink,
        .link = v9fs_vfs_link,
        .unlink = v9fs_vfs_unlink,
@@ -1502,6 +1529,7 @@ static const struct inode_operations v9fs_dir_inode_operations_dotu = {
 static const struct inode_operations v9fs_dir_inode_operations = {
        .create = v9fs_vfs_create,
        .lookup = v9fs_vfs_lookup,
+       .atomic_open = v9fs_vfs_atomic_open,
        .unlink = v9fs_vfs_unlink,
        .mkdir = v9fs_vfs_mkdir,
        .rmdir = v9fs_vfs_rmdir,
index e3dd2a1e2bfc18e47abae82bce7ee60238527c08..40895546e103e3e9b35e9542e23ac929d74de348 100644 (file)
@@ -230,20 +230,25 @@ int v9fs_open_to_dotl_flags(int flags)
  * @dir: directory inode that is being created
  * @dentry:  dentry that is being deleted
  * @mode: create permissions
- * @nd: path information
  *
  */
 
 static int
 v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
-               struct nameidata *nd)
+               bool excl)
+{
+       return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0);
+}
+
+static int
+v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry,
+                         struct file *file, unsigned flags, umode_t omode,
+                         int *opened)
 {
        int err = 0;
        gid_t gid;
-       int flags;
        umode_t mode;
        char *name = NULL;
-       struct file *filp;
        struct p9_qid qid;
        struct inode *inode;
        struct p9_fid *fid = NULL;
@@ -251,19 +256,23 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
        struct p9_fid *dfid, *ofid, *inode_fid;
        struct v9fs_session_info *v9ses;
        struct posix_acl *pacl = NULL, *dacl = NULL;
+       struct dentry *res = NULL;
 
-       v9ses = v9fs_inode2v9ses(dir);
-       if (nd)
-               flags = nd->intent.open.flags;
-       else {
-               /*
-                * create call without LOOKUP_OPEN is due
-                * to mknod of regular files. So use mknod
-                * operation.
-                */
-               return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0);
+       if (d_unhashed(dentry)) {
+               res = v9fs_vfs_lookup(dir, dentry, 0);
+               if (IS_ERR(res))
+                       return PTR_ERR(res);
+
+               if (res)
+                       dentry = res;
        }
 
+       /* Only creates */
+       if (!(flags & O_CREAT) || dentry->d_inode)
+               return finish_no_open(file, res);
+
+       v9ses = v9fs_inode2v9ses(dir);
+
        name = (char *) dentry->d_name.name;
        p9_debug(P9_DEBUG_VFS, "name:%s flags:0x%x mode:0x%hx\n",
                 name, flags, omode);
@@ -272,7 +281,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
        if (IS_ERR(dfid)) {
                err = PTR_ERR(dfid);
                p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err);
-               return err;
+               goto out;
        }
 
        /* clone a fid to use for creation */
@@ -280,7 +289,7 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
        if (IS_ERR(ofid)) {
                err = PTR_ERR(ofid);
                p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err);
-               return err;
+               goto out;
        }
 
        gid = v9fs_get_fsgid_for_create(dir);
@@ -345,17 +354,18 @@ v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode,
        }
        mutex_unlock(&v9inode->v_mutex);
        /* Since we are opening a file, assign the open fid to the file */
-       filp = lookup_instantiate_filp(nd, dentry, generic_file_open);
-       if (IS_ERR(filp)) {
-               err = PTR_ERR(filp);
+       err = finish_open(file, dentry, generic_file_open, opened);
+       if (err)
                goto err_clunk_old_fid;
-       }
-       filp->private_data = ofid;
+       file->private_data = ofid;
 #ifdef CONFIG_9P_FSCACHE
        if (v9ses->cache)
-               v9fs_cache_inode_set_cookie(inode, filp);
+               v9fs_cache_inode_set_cookie(inode, file);
 #endif
-       return 0;
+       *opened |= FILE_CREATED;
+out:
+       dput(res);
+       return err;
 
 error:
        if (fid)
@@ -364,7 +374,7 @@ err_clunk_old_fid:
        if (ofid)
                p9_client_clunk(ofid);
        v9fs_set_create_acl(NULL, &dacl, &pacl);
-       return err;
+       goto out;
 }
 
 /**
@@ -982,6 +992,7 @@ out:
 
 const struct inode_operations v9fs_dir_inode_operations_dotl = {
        .create = v9fs_vfs_create_dotl,
+       .atomic_open = v9fs_vfs_atomic_open_dotl,
        .lookup = v9fs_vfs_lookup,
        .link = v9fs_vfs_link_dotl,
        .symlink = v9fs_vfs_symlink_dotl,
index 8c92a9ba83306576ef45f4abe217b92954d4c05e..137d50396898e490937349998282a86ab0ed4f4d 100644 (file)
@@ -89,7 +89,7 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses,
        if (v9ses->cache)
                sb->s_bdi->ra_pages = (VM_MAX_READAHEAD * 1024)/PAGE_CACHE_SIZE;
 
-       sb->s_flags = flags | MS_ACTIVE | MS_DIRSYNC | MS_NOATIME;
+       sb->s_flags |= MS_ACTIVE | MS_DIRSYNC | MS_NOATIME;
        if (!v9ses->cache)
                sb->s_flags |= MS_SYNCHRONOUS;
 
@@ -137,7 +137,7 @@ static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags,
                goto close_session;
        }
 
-       sb = sget(fs_type, NULL, v9fs_set_super, v9ses);
+       sb = sget(fs_type, NULL, v9fs_set_super, flags, v9ses);
        if (IS_ERR(sb)) {
                retval = PTR_ERR(sb);
                goto clunk_fid;
index 3d83075aaa2e472dc2de5c0a34f249b3af2be012..b3be2e7c56436f006254d30724463cf8b05d0033 100644 (file)
@@ -266,7 +266,7 @@ const struct dentry_operations adfs_dentry_operations = {
 };
 
 static struct dentry *
-adfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+adfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode = NULL;
        struct object_info obj;
index 06fdcc9382c4d27d2effb1595b7480a402eaf7e9..bdaec92353c2cc0e5e876115ee7a474e45c0ba4b 100644 (file)
@@ -246,7 +246,6 @@ static struct inode *adfs_alloc_inode(struct super_block *sb)
 static void adfs_i_callback(struct rcu_head *head)
 {
        struct inode *inode = container_of(head, struct inode, i_rcu);
-       INIT_LIST_HEAD(&inode->i_dentry);
        kmem_cache_free(adfs_inode_cachep, ADFS_I(inode));
 }
 
index 1fceb320d2f22c16bc1a900cb27597d68977dbbd..6e216419f340de5219a684db6a70f99643784ac5 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/buffer_head.h>
 #include <linux/amigaffs.h>
 #include <linux/mutex.h>
+#include <linux/workqueue.h>
 
 /* AmigaOS allows file names with up to 30 characters length.
  * Names longer than that will be silently truncated. If you
@@ -100,6 +101,10 @@ struct affs_sb_info {
        char *s_prefix;                 /* Prefix for volumes and assigns. */
        char s_volume[32];              /* Volume prefix for absolute symlinks. */
        spinlock_t symlink_lock;        /* protects the previous two */
+       struct super_block *sb;         /* the VFS superblock object */
+       int work_queued;                /* non-zero delayed work is queued */
+       struct delayed_work sb_work;    /* superblock flush delayed work */
+       spinlock_t work_lock;           /* protects sb_work and work_queued */
 };
 
 #define SF_INTL                0x0001          /* International filesystem. */
@@ -120,6 +125,8 @@ static inline struct affs_sb_info *AFFS_SB(struct super_block *sb)
        return sb->s_fs_info;
 }
 
+void affs_mark_sb_dirty(struct super_block *sb);
+
 /* amigaffs.c */
 
 extern int     affs_insert_hash(struct inode *inode, struct buffer_head *bh);
@@ -146,9 +153,9 @@ extern void affs_free_bitmap(struct super_block *sb);
 /* namei.c */
 
 extern int     affs_hash_name(struct super_block *sb, const u8 *name, unsigned int len);
-extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *);
+extern struct dentry *affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int);
 extern int     affs_unlink(struct inode *dir, struct dentry *dentry);
-extern int     affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *);
+extern int     affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool);
 extern int     affs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
 extern int     affs_rmdir(struct inode *dir, struct dentry *dentry);
 extern int     affs_link(struct dentry *olddentry, struct inode *dir,
index 52a6407682e65e1aa0c82805c2d052cc09b20361..eb82ee53ee0be25a3c805c85ac9dd6c4028753b4 100644 (file)
@@ -122,22 +122,16 @@ affs_remove_hash(struct inode *dir, struct buffer_head *rem_bh)
 }
 
 static void
-affs_fix_dcache(struct dentry *dentry, u32 entry_ino)
+affs_fix_dcache(struct inode *inode, u32 entry_ino)
 {
-       struct inode *inode = dentry->d_inode;
-       void *data = dentry->d_fsdata;
-       struct list_head *head, *next;
-
+       struct dentry *dentry;
+       struct hlist_node *p;
        spin_lock(&inode->i_lock);
-       head = &inode->i_dentry;
-       next = head->next;
-       while (next != head) {
-               dentry = list_entry(next, struct dentry, d_alias);
+       hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
                if (entry_ino == (u32)(long)dentry->d_fsdata) {
-                       dentry->d_fsdata = data;
+                       dentry->d_fsdata = (void *)inode->i_ino;
                        break;
                }
-               next = next->next;
        }
        spin_unlock(&inode->i_lock);
 }
@@ -177,7 +171,11 @@ affs_remove_link(struct dentry *dentry)
                }
 
                affs_lock_dir(dir);
-               affs_fix_dcache(dentry, link_ino);
+               /*
+                * if there's a dentry for that block, make it
+                * refer to inode itself.
+                */
+               affs_fix_dcache(inode, link_ino);
                retval = affs_remove_hash(dir, link_bh);
                if (retval) {
                        affs_unlock_dir(dir);
index 3e262711ae06edfc0202e0914bd1627c1ccb643f..6e0be43ef6ef8eef90c57a4560bf671c9d756b7a 100644 (file)
@@ -103,7 +103,7 @@ affs_free_block(struct super_block *sb, u32 block)
        *(__be32 *)bh->b_data = cpu_to_be32(tmp - mask);
 
        mark_buffer_dirty(bh);
-       sb->s_dirt = 1;
+       affs_mark_sb_dirty(sb);
        bm->bm_free++;
 
        mutex_unlock(&sbi->s_bmlock);
@@ -248,7 +248,7 @@ find_bit:
        *(__be32 *)bh->b_data = cpu_to_be32(tmp + mask);
 
        mark_buffer_dirty(bh);
-       sb->s_dirt = 1;
+       affs_mark_sb_dirty(sb);
 
        mutex_unlock(&sbi->s_bmlock);
 
index 47806940aac0a9d003987cbdf4f9a0b0af6c5f47..ff65884a7839974ca472a64097ac996245c96346 100644 (file)
@@ -211,7 +211,7 @@ affs_find_entry(struct inode *dir, struct dentry *dentry)
 }
 
 struct dentry *
-affs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+affs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct super_block *sb = dir->i_sb;
        struct buffer_head *bh;
@@ -255,7 +255,7 @@ affs_unlink(struct inode *dir, struct dentry *dentry)
 }
 
 int
-affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd)
+affs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
 {
        struct super_block *sb = dir->i_sb;
        struct inode    *inode;
index 0782653a05a2d2d9098057572605fa75ef9900f3..c70f1e5fc0247a616d44e60c2681bbf8fc14c747 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/magic.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/writeback.h>
 #include "affs.h"
 
 extern struct timezone sys_tz;
@@ -25,15 +26,17 @@ static int affs_statfs(struct dentry *dentry, struct kstatfs *buf);
 static int affs_remount (struct super_block *sb, int *flags, char *data);
 
 static void
-affs_commit_super(struct super_block *sb, int wait, int clean)
+affs_commit_super(struct super_block *sb, int wait)
 {
        struct affs_sb_info *sbi = AFFS_SB(sb);
        struct buffer_head *bh = sbi->s_root_bh;
        struct affs_root_tail *tail = AFFS_ROOT_TAIL(sb, bh);
 
-       tail->bm_flag = cpu_to_be32(clean);
+       lock_buffer(bh);
        secs_to_datestamp(get_seconds(), &tail->disk_change);
        affs_fix_checksum(sb, bh);
+       unlock_buffer(bh);
+
        mark_buffer_dirty(bh);
        if (wait)
                sync_dirty_buffer(bh);
@@ -45,9 +48,7 @@ affs_put_super(struct super_block *sb)
        struct affs_sb_info *sbi = AFFS_SB(sb);
        pr_debug("AFFS: put_super()\n");
 
-       if (!(sb->s_flags & MS_RDONLY) && sb->s_dirt)
-               affs_commit_super(sb, 1, 1);
-
+       cancel_delayed_work_sync(&sbi->sb_work);
        kfree(sbi->s_prefix);
        affs_free_bitmap(sb);
        affs_brelse(sbi->s_root_bh);
@@ -55,26 +56,43 @@ affs_put_super(struct super_block *sb)
        sb->s_fs_info = NULL;
 }
 
-static void
-affs_write_super(struct super_block *sb)
+static int
+affs_sync_fs(struct super_block *sb, int wait)
 {
-       lock_super(sb);
-       if (!(sb->s_flags & MS_RDONLY))
-               affs_commit_super(sb, 1, 2);
-       sb->s_dirt = 0;
-       unlock_super(sb);
+       affs_commit_super(sb, wait);
+       return 0;
+}
+
+static void flush_superblock(struct work_struct *work)
+{
+       struct affs_sb_info *sbi;
+       struct super_block *sb;
+
+       sbi = container_of(work, struct affs_sb_info, sb_work.work);
+       sb = sbi->sb;
 
-       pr_debug("AFFS: write_super() at %lu, clean=2\n", get_seconds());
+       spin_lock(&sbi->work_lock);
+       sbi->work_queued = 0;
+       spin_unlock(&sbi->work_lock);
+
+       affs_commit_super(sb, 1);
 }
 
-static int
-affs_sync_fs(struct super_block *sb, int wait)
+void affs_mark_sb_dirty(struct super_block *sb)
 {
-       lock_super(sb);
-       affs_commit_super(sb, wait, 2);
-       sb->s_dirt = 0;
-       unlock_super(sb);
-       return 0;
+       struct affs_sb_info *sbi = AFFS_SB(sb);
+       unsigned long delay;
+
+       if (sb->s_flags & MS_RDONLY)
+              return;
+
+       spin_lock(&sbi->work_lock);
+       if (!sbi->work_queued) {
+              delay = msecs_to_jiffies(dirty_writeback_interval * 10);
+              queue_delayed_work(system_long_wq, &sbi->sb_work, delay);
+              sbi->work_queued = 1;
+       }
+       spin_unlock(&sbi->work_lock);
 }
 
 static struct kmem_cache * affs_inode_cachep;
@@ -138,7 +156,6 @@ static const struct super_operations affs_sops = {
        .write_inode    = affs_write_inode,
        .evict_inode    = affs_evict_inode,
        .put_super      = affs_put_super,
-       .write_super    = affs_write_super,
        .sync_fs        = affs_sync_fs,
        .statfs         = affs_statfs,
        .remount_fs     = affs_remount,
@@ -305,8 +322,11 @@ static int affs_fill_super(struct super_block *sb, void *data, int silent)
                return -ENOMEM;
 
        sb->s_fs_info = sbi;
+       sbi->sb = sb;
        mutex_init(&sbi->s_bmlock);
        spin_lock_init(&sbi->symlink_lock);
+       spin_lock_init(&sbi->work_lock);
+       INIT_DELAYED_WORK(&sbi->sb_work, flush_superblock);
 
        if (!parse_options(data,&uid,&gid,&i,&reserved,&root_block,
                                &blocksize,&sbi->s_prefix,
@@ -531,6 +551,7 @@ affs_remount(struct super_block *sb, int *flags, char *data)
                return -EINVAL;
        }
 
+       flush_delayed_work_sync(&sbi->sb_work);
        replace_mount_options(sb, new_opts);
 
        sbi->s_flags = mount_flags;
@@ -549,10 +570,9 @@ affs_remount(struct super_block *sb, int *flags, char *data)
        if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
                return 0;
 
-       if (*flags & MS_RDONLY) {
-               affs_write_super(sb);
+       if (*flags & MS_RDONLY)
                affs_free_bitmap(sb);
-       else
+       else
                res = affs_init_bitmap(sb, flags);
 
        return res;
index e22dc4b4a503e58926b89314aef6889bd26dad82..db477906ba4f441acd9fc100be2668e7894a7c88 100644 (file)
 #include "internal.h"
 
 static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
-                                struct nameidata *nd);
+                                unsigned int flags);
 static int afs_dir_open(struct inode *inode, struct file *file);
 static int afs_readdir(struct file *file, void *dirent, filldir_t filldir);
-static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd);
+static int afs_d_revalidate(struct dentry *dentry, unsigned int flags);
 static int afs_d_delete(const struct dentry *dentry);
 static void afs_d_release(struct dentry *dentry);
 static int afs_lookup_filldir(void *_cookie, const char *name, int nlen,
                                  loff_t fpos, u64 ino, unsigned dtype);
 static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                     struct nameidata *nd);
+                     bool excl);
 static int afs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
 static int afs_rmdir(struct inode *dir, struct dentry *dentry);
 static int afs_unlink(struct inode *dir, struct dentry *dentry);
@@ -516,7 +516,7 @@ out:
  * look up an entry in a directory
  */
 static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,
-                                struct nameidata *nd)
+                                unsigned int flags)
 {
        struct afs_vnode *vnode;
        struct afs_fid fid;
@@ -598,7 +598,7 @@ success:
  * - NOTE! the hit can be a negative hit too, so we can't assume we have an
  *   inode
  */
-static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int afs_d_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct afs_vnode *vnode, *dir;
        struct afs_fid uninitialized_var(fid);
@@ -607,7 +607,7 @@ static int afs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
        void *dir_version;
        int ret;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        vnode = AFS_FS_I(dentry->d_inode);
@@ -949,7 +949,7 @@ error:
  * create a regular file on an AFS filesystem
  */
 static int afs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                     struct nameidata *nd)
+                     bool excl)
 {
        struct afs_file_status status;
        struct afs_callback cb;
index 298cf8919ec79b547db2a80b80a87697c705442f..9682c33d5daf44d66351ca29ebb5c02cb39ca1ae 100644 (file)
@@ -22,7 +22,7 @@
 
 static struct dentry *afs_mntpt_lookup(struct inode *dir,
                                       struct dentry *dentry,
-                                      struct nameidata *nd);
+                                      unsigned int flags);
 static int afs_mntpt_open(struct inode *inode, struct file *file);
 static void afs_mntpt_expiry_timed_out(struct work_struct *work);
 
@@ -104,7 +104,7 @@ out:
  */
 static struct dentry *afs_mntpt_lookup(struct inode *dir,
                                       struct dentry *dentry,
-                                      struct nameidata *nd)
+                                      unsigned int flags)
 {
        _enter("%p,%p{%p{%s},%s}",
               dir,
index f02b31e7e648ff67007990626b8b9f2641f694f3..df8c6047c2a12c41e5cd2935066e9b0397226d9a 100644 (file)
@@ -395,7 +395,7 @@ static struct dentry *afs_mount(struct file_system_type *fs_type,
        as->volume = vol;
 
        /* allocate a deviceless superblock */
-       sb = sget(fs_type, afs_test_super, afs_set_super, as);
+       sb = sget(fs_type, afs_test_super, afs_set_super, flags, as);
        if (IS_ERR(sb)) {
                ret = PTR_ERR(sb);
                afs_put_volume(vol);
@@ -406,7 +406,6 @@ static struct dentry *afs_mount(struct file_system_type *fs_type,
        if (!sb->s_root) {
                /* initial superblock/root creation */
                _debug("create");
-               sb->s_flags = flags;
                ret = afs_fill_super(sb, &params);
                if (ret < 0) {
                        deactivate_locked_super(sb);
index 55c4c76560537f7fe72d6ff5f429eff666b86789..71f613cf4a85a36e08044840f65b36b0c9fc4579 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -56,13 +56,6 @@ static struct kmem_cache     *kioctx_cachep;
 
 static struct workqueue_struct *aio_wq;
 
-/* Used for rare fput completion. */
-static void aio_fput_routine(struct work_struct *);
-static DECLARE_WORK(fput_work, aio_fput_routine);
-
-static DEFINE_SPINLOCK(fput_lock);
-static LIST_HEAD(fput_head);
-
 static void aio_kick_handler(struct work_struct *);
 static void aio_queue_work(struct kioctx *);
 
@@ -479,7 +472,6 @@ static int kiocb_batch_refill(struct kioctx *ctx, struct kiocb_batch *batch)
 {
        unsigned short allocated, to_alloc;
        long avail;
-       bool called_fput = false;
        struct kiocb *req, *n;
        struct aio_ring *ring;
 
@@ -495,28 +487,11 @@ static int kiocb_batch_refill(struct kioctx *ctx, struct kiocb_batch *batch)
        if (allocated == 0)
                goto out;
 
-retry:
        spin_lock_irq(&ctx->ctx_lock);
        ring = kmap_atomic(ctx->ring_info.ring_pages[0]);
 
        avail = aio_ring_avail(&ctx->ring_info, ring) - ctx->reqs_active;
        BUG_ON(avail < 0);
-       if (avail == 0 && !called_fput) {
-               /*
-                * Handle a potential starvation case.  It is possible that
-                * we hold the last reference on a struct file, causing us
-                * to delay the final fput to non-irq context.  In this case,
-                * ctx->reqs_active is artificially high.  Calling the fput
-                * routine here may free up a slot in the event completion
-                * ring, allowing this allocation to succeed.
-                */
-               kunmap_atomic(ring);
-               spin_unlock_irq(&ctx->ctx_lock);
-               aio_fput_routine(NULL);
-               called_fput = true;
-               goto retry;
-       }
-
        if (avail < allocated) {
                /* Trim back the number of requests. */
                list_for_each_entry_safe(req, n, &batch->head, ki_batch) {
@@ -570,36 +545,6 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req)
                wake_up_all(&ctx->wait);
 }
 
-static void aio_fput_routine(struct work_struct *data)
-{
-       spin_lock_irq(&fput_lock);
-       while (likely(!list_empty(&fput_head))) {
-               struct kiocb *req = list_kiocb(fput_head.next);
-               struct kioctx *ctx = req->ki_ctx;
-
-               list_del(&req->ki_list);
-               spin_unlock_irq(&fput_lock);
-
-               /* Complete the fput(s) */
-               if (req->ki_filp != NULL)
-                       fput(req->ki_filp);
-
-               /* Link the iocb into the context's free list */
-               rcu_read_lock();
-               spin_lock_irq(&ctx->ctx_lock);
-               really_put_req(ctx, req);
-               /*
-                * at that point ctx might've been killed, but actual
-                * freeing is RCU'd
-                */
-               spin_unlock_irq(&ctx->ctx_lock);
-               rcu_read_unlock();
-
-               spin_lock_irq(&fput_lock);
-       }
-       spin_unlock_irq(&fput_lock);
-}
-
 /* __aio_put_req
  *     Returns true if this put was the last user of the request.
  */
@@ -618,21 +563,9 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
        req->ki_cancel = NULL;
        req->ki_retry = NULL;
 
-       /*
-        * Try to optimize the aio and eventfd file* puts, by avoiding to
-        * schedule work in case it is not final fput() time. In normal cases,
-        * we would not be holding the last reference to the file*, so
-        * this function will be executed w/out any aio kthread wakeup.
-        */
-       if (unlikely(!fput_atomic(req->ki_filp))) {
-               spin_lock(&fput_lock);
-               list_add(&req->ki_list, &fput_head);
-               spin_unlock(&fput_lock);
-               schedule_work(&fput_work);
-       } else {
-               req->ki_filp = NULL;
-               really_put_req(ctx, req);
-       }
+       fput(req->ki_filp);
+       req->ki_filp = NULL;
+       really_put_req(ctx, req);
        return 1;
 }
 
index 0da90951d2776f827a905337938399ada79e8e69..29e38a1f7f77a15100f1d20b3e51507470273633 100644 (file)
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -171,6 +171,8 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
        struct timespec now;
        unsigned int ia_valid = attr->ia_valid;
 
+       WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex));
+
        if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_TIMES_SET)) {
                if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
                        return -EPERM;
@@ -250,5 +252,4 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
 
        return error;
 }
-
 EXPORT_SYMBOL(notify_change);
index aa9103f8f01bf8d3bad8d0dcbcc8036895226e3f..abf645c1703bab0036dcb76db1acb570590a3cd5 100644 (file)
@@ -257,8 +257,8 @@ static int autofs_dev_ioctl_open_mountpoint(const char *name, dev_t devid)
                 * corresponding to the autofs fs we want to open.
                 */
 
-               filp = dentry_open(path.dentry, path.mnt, O_RDONLY,
-                                  current_cred());
+               filp = dentry_open(&path, O_RDONLY, current_cred());
+               path_put(&path);
                if (IS_ERR(filp)) {
                        err = PTR_ERR(filp);
                        goto out;
index 75e5f1c8e028fc9663eaed4c24ed5958ca8a0a68..e7396cfdb10999b453567231e433451cb6aecc2f 100644 (file)
@@ -32,7 +32,7 @@ static long autofs4_root_ioctl(struct file *,unsigned int,unsigned long);
 static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long);
 #endif
 static int autofs4_dir_open(struct inode *inode, struct file *file);
-static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *);
+static struct dentry *autofs4_lookup(struct inode *,struct dentry *, unsigned int);
 static struct vfsmount *autofs4_d_automount(struct path *);
 static int autofs4_d_manage(struct dentry *, bool);
 static void autofs4_dentry_release(struct dentry *);
@@ -458,7 +458,7 @@ int autofs4_d_manage(struct dentry *dentry, bool rcu_walk)
 }
 
 /* Lookups in the root directory */
-static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *autofs4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct autofs_sb_info *sbi;
        struct autofs_info *ino;
index 1b35d6bd06b06d071f8b24e28ece1aa97d87d1ce..b1342ffb3cf6e595125252ac82d5bd54ebbe9544 100644 (file)
@@ -173,13 +173,13 @@ static const struct file_operations bad_file_ops =
 };
 
 static int bad_inode_create (struct inode *dir, struct dentry *dentry,
-               umode_t mode, struct nameidata *nd)
+               umode_t mode, bool excl)
 {
        return -EIO;
 }
 
 static struct dentry *bad_inode_lookup(struct inode *dir,
-                       struct dentry *dentry, struct nameidata *nd)
+                       struct dentry *dentry, unsigned int flags)
 {
        return ERR_PTR(-EIO);
 }
index e18da23d42b5b163cb3a7f3dd8da9cdf76f9774d..cf7f3c67c8b7848e6e8e55b83c3c76bde007f60a 100644 (file)
@@ -34,7 +34,7 @@ static int befs_readdir(struct file *, void *, filldir_t);
 static int befs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 static int befs_readpage(struct file *file, struct page *page);
 static sector_t befs_bmap(struct address_space *mapping, sector_t block);
-static struct dentry *befs_lookup(struct inode *, struct dentry *, struct nameidata *);
+static struct dentry *befs_lookup(struct inode *, struct dentry *, unsigned int);
 static struct inode *befs_iget(struct super_block *, unsigned long);
 static struct inode *befs_alloc_inode(struct super_block *sb);
 static void befs_destroy_inode(struct inode *inode);
@@ -159,7 +159,7 @@ befs_get_block(struct inode *inode, sector_t block,
 }
 
 static struct dentry *
-befs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+befs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode = NULL;
        struct super_block *sb = dir->i_sb;
index d12c7966db27faba8e118f874335bc25b24f3917..2785ef91191ad07c76bbec51a742e0a43fee8be6 100644 (file)
@@ -85,7 +85,7 @@ const struct file_operations bfs_dir_operations = {
 extern void dump_imap(const char *, struct super_block *);
 
 static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                                               struct nameidata *nd)
+                                               bool excl)
 {
        int err;
        struct inode *inode;
@@ -133,7 +133,7 @@ static int bfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 }
 
 static struct dentry *bfs_lookup(struct inode *dir, struct dentry *dentry,
-                                               struct nameidata *nd)
+                                               unsigned int flags)
 {
        struct inode *inode = NULL;
        struct buffer_head *bh;
index c2bbe1fb132632c14ebb2ea0675ad78500441a52..1e519195d45bd1ab466f8b7ee12505f35a45d271 100644 (file)
@@ -1710,3 +1710,39 @@ int __invalidate_device(struct block_device *bdev, bool kill_dirty)
        return res;
 }
 EXPORT_SYMBOL(__invalidate_device);
+
+void iterate_bdevs(void (*func)(struct block_device *, void *), void *arg)
+{
+       struct inode *inode, *old_inode = NULL;
+
+       spin_lock(&inode_sb_list_lock);
+       list_for_each_entry(inode, &blockdev_superblock->s_inodes, i_sb_list) {
+               struct address_space *mapping = inode->i_mapping;
+
+               spin_lock(&inode->i_lock);
+               if (inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW) ||
+                   mapping->nrpages == 0) {
+                       spin_unlock(&inode->i_lock);
+                       continue;
+               }
+               __iget(inode);
+               spin_unlock(&inode->i_lock);
+               spin_unlock(&inode_sb_list_lock);
+               /*
+                * We hold a reference to 'inode' so it couldn't have been
+                * removed from s_inodes list while we dropped the
+                * inode_sb_list_lock.  We cannot iput the inode now as we can
+                * be holding the last reference and we cannot iput it under
+                * inode_sb_list_lock. So we keep the reference and iput it
+                * later.
+                */
+               iput(old_inode);
+               old_inode = inode;
+
+               func(I_BDEV(inode), arg);
+
+               spin_lock(&inode_sb_list_lock);
+       }
+       spin_unlock(&inode_sb_list_lock);
+       iput(old_inode);
+}
index a7d1921ac76b8ee5d85d563c1ceed80f4a65a2dd..fb8d671d00e6b8c7d8b387d4f158f8ab46d362f1 100644 (file)
@@ -4247,7 +4247,7 @@ static void btrfs_dentry_release(struct dentry *dentry)
 }
 
 static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        struct dentry *ret;
 
@@ -4893,7 +4893,7 @@ out_unlock:
 }
 
 static int btrfs_create(struct inode *dir, struct dentry *dentry,
-                       umode_t mode, struct nameidata *nd)
+                       umode_t mode, bool excl)
 {
        struct btrfs_trans_handle *trans;
        struct btrfs_root *root = BTRFS_I(dir)->root;
@@ -6987,7 +6987,7 @@ void btrfs_destroy_inode(struct inode *inode)
        struct btrfs_ordered_extent *ordered;
        struct btrfs_root *root = BTRFS_I(inode)->root;
 
-       WARN_ON(!list_empty(&inode->i_dentry));
+       WARN_ON(!hlist_empty(&inode->i_dentry));
        WARN_ON(inode->i_data.nrpages);
        WARN_ON(BTRFS_I(inode)->outstanding_extents);
        WARN_ON(BTRFS_I(inode)->reserved_extents);
index 0e92e5763005214b5d55d091d6fcfb94d73f4875..1e9f6c019ad069ea51a5bc7ea475fd0d804dc1ae 100644 (file)
@@ -3268,7 +3268,7 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
        if (fs_info->sb->s_flags & MS_RDONLY)
                return -EROFS;
 
-       ret = mnt_want_write(file->f_path.mnt);
+       ret = mnt_want_write_file(file);
        if (ret)
                return ret;
 
@@ -3338,7 +3338,7 @@ out_bargs:
 out:
        mutex_unlock(&fs_info->balance_mutex);
        mutex_unlock(&fs_info->volume_mutex);
-       mnt_drop_write(file->f_path.mnt);
+       mnt_drop_write_file(file);
        return ret;
 }
 
index e23991574fdf309e6ed95e23985fc5dd0af28e0f..b19d7556772877acac123d6d0ff94080a1cab69b 100644 (file)
@@ -1068,7 +1068,8 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        }
 
        bdev = fs_devices->latest_bdev;
-       s = sget(fs_type, btrfs_test_super, btrfs_set_super, fs_info);
+       s = sget(fs_type, btrfs_test_super, btrfs_set_super, flags | MS_NOSEC,
+                fs_info);
        if (IS_ERR(s)) {
                error = PTR_ERR(s);
                goto error_close_devices;
@@ -1082,7 +1083,6 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
        } else {
                char b[BDEVNAME_SIZE];
 
-               s->s_flags = flags | MS_NOSEC;
                strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
                btrfs_sb(s)->bdev_holder = fs_type;
                error = btrfs_fill_super(s, fs_devices, data,
index 7f0771d3894e7a17bbd01ec1bf9fc8c988918d08..b0b5f7cdfffa98de3e30e0857d64bf954e8b3518 100644 (file)
@@ -567,7 +567,7 @@ lookup_again:
                        if (ret < 0)
                                goto create_error;
                        start = jiffies;
-                       ret = vfs_create(dir->d_inode, next, S_IFREG, NULL);
+                       ret = vfs_create(dir->d_inode, next, S_IFREG, true);
                        cachefiles_hist(cachefiles_create_histogram, start);
                        if (ret < 0)
                                goto create_error;
index 0e3c0924cc3a3f01f648731b1e3baed15a7ce1ad..c0353dfac51f819d3e8cb69644fd50a98fa04224 100644 (file)
@@ -891,6 +891,7 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)
        struct cachefiles_cache *cache;
        mm_segment_t old_fs;
        struct file *file;
+       struct path path;
        loff_t pos, eof;
        size_t len;
        void *data;
@@ -916,10 +917,9 @@ int cachefiles_write_page(struct fscache_storage *op, struct page *page)
 
        /* write the page to the backing filesystem and let it store it in its
         * own time */
-       dget(object->backer);
-       mntget(cache->mnt);
-       file = dentry_open(object->backer, cache->mnt, O_RDWR,
-                          cache->cache_cred);
+       path.mnt = cache->mnt;
+       path.dentry = object->backer;
+       file = dentry_open(&path, O_RDWR, cache->cache_cred);
        if (IS_ERR(file)) {
                ret = PTR_ERR(file);
        } else {
index 3e8094be4604a481999e2921fb0942441c9086a7..00894ff9246c2175b60177bab59b70456733ff01 100644 (file)
@@ -576,7 +576,7 @@ static int is_root_ceph_dentry(struct inode *inode, struct dentry *dentry)
  * the MDS so that it gets our 'caps wanted' value in a single op.
  */
 static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
-                                 struct nameidata *nd)
+                                 unsigned int flags)
 {
        struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
        struct ceph_mds_client *mdsc = fsc->mdsc;
@@ -594,14 +594,6 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
        if (err < 0)
                return ERR_PTR(err);
 
-       /* open (but not create!) intent? */
-       if (nd &&
-           (nd->flags & LOOKUP_OPEN) &&
-           !(nd->intent.open.flags & O_CREAT)) {
-               int mode = nd->intent.open.create_mode & ~current->fs->umask;
-               return ceph_lookup_open(dir, dentry, nd, mode, 1);
-       }
-
        /* can we conclude ENOENT locally? */
        if (dentry->d_inode == NULL) {
                struct ceph_inode_info *ci = ceph_inode(dir);
@@ -642,13 +634,51 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry,
        return dentry;
 }
 
+int ceph_atomic_open(struct inode *dir, struct dentry *dentry,
+                    struct file *file, unsigned flags, umode_t mode,
+                    int *opened)
+{
+       int err;
+       struct dentry *res = NULL;
+
+       if (!(flags & O_CREAT)) {
+               if (dentry->d_name.len > NAME_MAX)
+                       return -ENAMETOOLONG;
+
+               err = ceph_init_dentry(dentry);
+               if (err < 0)
+                       return err;
+
+               return ceph_lookup_open(dir, dentry, file, flags, mode, opened);
+       }
+
+       if (d_unhashed(dentry)) {
+               res = ceph_lookup(dir, dentry, 0);
+               if (IS_ERR(res))
+                       return PTR_ERR(res);
+
+               if (res)
+                       dentry = res;
+       }
+
+       /* We don't deal with positive dentries here */
+       if (dentry->d_inode)
+               return finish_no_open(file, res);
+
+       *opened |= FILE_CREATED;
+       err = ceph_lookup_open(dir, dentry, file, flags, mode, opened);
+       dput(res);
+
+       return err;
+}
+
 /*
  * If we do a create but get no trace back from the MDS, follow up with
  * a lookup (the VFS expects us to link up the provided dentry).
  */
 int ceph_handle_notrace_create(struct inode *dir, struct dentry *dentry)
 {
-       struct dentry *result = ceph_lookup(dir, dentry, NULL);
+       struct dentry *result = ceph_lookup(dir, dentry, 0);
 
        if (result && !IS_ERR(result)) {
                /*
@@ -700,25 +730,9 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry,
 }
 
 static int ceph_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                      struct nameidata *nd)
+                      bool excl)
 {
-       dout("create in dir %p dentry %p name '%.*s'\n",
-            dir, dentry, dentry->d_name.len, dentry->d_name.name);
-
-       if (ceph_snap(dir) != CEPH_NOSNAP)
-               return -EROFS;
-
-       if (nd) {
-               BUG_ON((nd->flags & LOOKUP_OPEN) == 0);
-               dentry = ceph_lookup_open(dir, dentry, nd, mode, 0);
-               /* hrm, what should i do here if we get aliased? */
-               if (IS_ERR(dentry))
-                       return PTR_ERR(dentry);
-               return 0;
-       }
-
-       /* fall back to mknod */
-       return ceph_mknod(dir, dentry, (mode & ~S_IFMT) | S_IFREG, 0);
+       return ceph_mknod(dir, dentry, mode, 0);
 }
 
 static int ceph_symlink(struct inode *dir, struct dentry *dentry,
@@ -1028,12 +1042,12 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry)
 /*
  * Check if cached dentry can be trusted.
  */
-static int ceph_d_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int ceph_d_revalidate(struct dentry *dentry, unsigned int flags)
 {
        int valid = 0;
        struct inode *dir;
 
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        dout("d_revalidate %p '%.*s' inode %p offset %lld\n", dentry,
@@ -1080,7 +1094,7 @@ static void ceph_d_release(struct dentry *dentry)
 }
 
 static int ceph_snapdir_d_revalidate(struct dentry *dentry,
-                                         struct nameidata *nd)
+                                         unsigned int flags)
 {
        /*
         * Eventually, we'll want to revalidate snapped metadata
@@ -1357,6 +1371,7 @@ const struct inode_operations ceph_dir_iops = {
        .rmdir = ceph_unlink,
        .rename = ceph_rename,
        .create = ceph_create,
+       .atomic_open = ceph_atomic_open,
 };
 
 const struct dentry_operations ceph_dentry_ops = {
index 988d4f302e4880281a2b5e04c9f44dd7870202d2..1b81d6c318784813973bc74cccfec02fed0d3dbc 100644 (file)
@@ -213,22 +213,15 @@ out:
  * may_open() fails, the struct *file gets cleaned up (i.e.
  * ceph_release gets called).  So fear not!
  */
-/*
- * flags
- *  path_lookup_open   -> LOOKUP_OPEN
- *  path_lookup_create -> LOOKUP_OPEN|LOOKUP_CREATE
- */
-struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
-                               struct nameidata *nd, int mode,
-                               int locked_dir)
+int ceph_lookup_open(struct inode *dir, struct dentry *dentry,
+                    struct file *file, unsigned flags, umode_t mode,
+                    int *opened)
 {
        struct ceph_fs_client *fsc = ceph_sb_to_client(dir->i_sb);
        struct ceph_mds_client *mdsc = fsc->mdsc;
-       struct file *file;
        struct ceph_mds_request *req;
        struct dentry *ret;
        int err;
-       int flags = nd->intent.open.flags;
 
        dout("ceph_lookup_open dentry %p '%.*s' flags %d mode 0%o\n",
             dentry, dentry->d_name.len, dentry->d_name.name, flags, mode);
@@ -236,7 +229,7 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
        /* do the open */
        req = prepare_open_request(dir->i_sb, flags, mode);
        if (IS_ERR(req))
-               return ERR_CAST(req);
+               return PTR_ERR(req);
        req->r_dentry = dget(dentry);
        req->r_num_caps = 2;
        if (flags & O_CREAT) {
@@ -254,14 +247,17 @@ struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
                err = ceph_handle_notrace_create(dir, dentry);
        if (err)
                goto out;
-       file = lookup_instantiate_filp(nd, req->r_dentry, ceph_open);
-       if (IS_ERR(file))
-               err = PTR_ERR(file);
+       err = finish_open(file, req->r_dentry, ceph_open, opened);
 out:
        ret = ceph_finish_lookup(req, dentry, err);
        ceph_mdsc_put_request(req);
        dout("ceph_lookup_open result=%p\n", ret);
-       return ret;
+
+       if (IS_ERR(ret))
+               return PTR_ERR(ret);
+
+       dput(ret);
+       return err;
 }
 
 int ceph_release(struct inode *inode, struct file *file)
index 1e67dd7305a4e8596a3c5f609ccea2a866e4e31a..7076109f014dae80a85c789c3022b6465f9b70c0 100644 (file)
@@ -871,7 +871,7 @@ static struct dentry *ceph_mount(struct file_system_type *fs_type,
 
        if (ceph_test_opt(fsc->client, NOSHARE))
                compare_super = NULL;
-       sb = sget(fs_type, compare_super, ceph_set_super, fsc);
+       sb = sget(fs_type, compare_super, ceph_set_super, flags, fsc);
        if (IS_ERR(sb)) {
                res = ERR_CAST(sb);
                goto out;
index fc35036d258d7b830c37f5cba078f53c53e7d574..f4d5522cb619eba5f5a27842ea52277e9b3d5563 100644 (file)
@@ -806,9 +806,9 @@ extern int ceph_copy_from_page_vector(struct page **pages,
                                    loff_t off, size_t len);
 extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
 extern int ceph_open(struct inode *inode, struct file *file);
-extern struct dentry *ceph_lookup_open(struct inode *dir, struct dentry *dentry,
-                                      struct nameidata *nd, int mode,
-                                      int locked_dir);
+extern int ceph_lookup_open(struct inode *dir, struct dentry *dentry,
+                            struct file *od, unsigned flags,
+                            umode_t mode, int *opened);
 extern int ceph_release(struct inode *inode, struct file *filp);
 
 /* dir.c */
index 8b6e344eb0ba3a483780f0b32cf0961ec258ca4c..a7610cfedf0a20c7c3d22d149d129d1b15e62bd3 100644 (file)
@@ -257,7 +257,6 @@ cifs_alloc_inode(struct super_block *sb)
 static void cifs_i_callback(struct rcu_head *head)
 {
        struct inode *inode = container_of(head, struct inode, i_rcu);
-       INIT_LIST_HEAD(&inode->i_dentry);
        kmem_cache_free(cifs_inode_cachep, CIFS_I(inode));
 }
 
@@ -638,7 +637,10 @@ cifs_do_mount(struct file_system_type *fs_type,
        mnt_data.cifs_sb = cifs_sb;
        mnt_data.flags = flags;
 
-       sb = sget(fs_type, cifs_match_super, cifs_set_super, &mnt_data);
+       /* BB should we make this contingent on mount parm? */
+       flags |= MS_NODIRATIME | MS_NOATIME;
+
+       sb = sget(fs_type, cifs_match_super, cifs_set_super, flags, &mnt_data);
        if (IS_ERR(sb)) {
                root = ERR_CAST(sb);
                cifs_umount(cifs_sb);
@@ -649,10 +651,6 @@ cifs_do_mount(struct file_system_type *fs_type,
                cFYI(1, "Use existing superblock");
                cifs_umount(cifs_sb);
        } else {
-               sb->s_flags = flags;
-               /* BB should we make this contingent on mount parm? */
-               sb->s_flags |= MS_NODIRATIME | MS_NOATIME;
-
                rc = cifs_read_super(sb);
                if (rc) {
                        root = ERR_PTR(rc);
@@ -778,6 +776,7 @@ struct file_system_type cifs_fs_type = {
 };
 const struct inode_operations cifs_dir_inode_ops = {
        .create = cifs_create,
+       .atomic_open = cifs_atomic_open,
        .lookup = cifs_lookup,
        .getattr = cifs_getattr,
        .unlink = cifs_unlink,
index 65365358c9766dcd2882ab643805565e552f4e25..1c49c5a9b27a6cd5b188425dfdd3fd934687a003 100644 (file)
@@ -45,9 +45,12 @@ extern const struct address_space_operations cifs_addr_ops_smallbuf;
 extern const struct inode_operations cifs_dir_inode_ops;
 extern struct inode *cifs_root_iget(struct super_block *);
 extern int cifs_create(struct inode *, struct dentry *, umode_t,
-                      struct nameidata *);
+                      bool excl);
+extern int cifs_atomic_open(struct inode *, struct dentry *,
+                           struct file *, unsigned, umode_t,
+                           int *);
 extern struct dentry *cifs_lookup(struct inode *, struct dentry *,
-                                 struct nameidata *);
+                                 unsigned int);
 extern int cifs_unlink(struct inode *dir, struct dentry *dentry);
 extern int cifs_hardlink(struct dentry *, struct inode *, struct dentry *);
 extern int cifs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
index ec4e9a2a12f843edf9e8d2f60c8a32f58011ec4d..a180265a10b56b5d4e98c63ff64e298f8146431f 100644 (file)
@@ -133,108 +133,141 @@ cifs_bp_rename_retry:
        return full_path;
 }
 
+/*
+ * Don't allow the separator character in a path component.
+ * The VFS will not allow "/", but "\" is allowed by posix.
+ */
+static int
+check_name(struct dentry *direntry)
+{
+       struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
+       int i;
+
+       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
+               for (i = 0; i < direntry->d_name.len; i++) {
+                       if (direntry->d_name.name[i] == '\\') {
+                               cFYI(1, "Invalid file name");
+                               return -EINVAL;
+                       }
+               }
+       }
+       return 0;
+}
+
+
 /* Inode operations in similar order to how they appear in Linux file fs.h */
 
-int
-cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
-               struct nameidata *nd)
+static int cifs_do_create(struct inode *inode, struct dentry *direntry,
+                         int xid, struct tcon_link *tlink, unsigned oflags,
+                         umode_t mode, __u32 *oplock, __u16 *fileHandle,
+                         int *created)
 {
        int rc = -ENOENT;
-       int xid;
        int create_options = CREATE_NOT_DIR;
-       __u32 oplock = 0;
-       int oflags;
-       /*
-        * BB below access is probably too much for mknod to request
-        *    but we have to do query and setpathinfo so requesting
-        *    less could fail (unless we want to request getatr and setatr
-        *    permissions (only).  At least for POSIX we do not have to
-        *    request so much.
-        */
-       int desiredAccess = GENERIC_READ | GENERIC_WRITE;
-       __u16 fileHandle;
-       struct cifs_sb_info *cifs_sb;
-       struct tcon_link *tlink;
-       struct cifs_tcon *tcon;
+       int desiredAccess;
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+       struct cifs_tcon *tcon = tlink_tcon(tlink);
        char *full_path = NULL;
        FILE_ALL_INFO *buf = NULL;
        struct inode *newinode = NULL;
-       int disposition = FILE_OVERWRITE_IF;
-
-       xid = GetXid();
-
-       cifs_sb = CIFS_SB(inode->i_sb);
-       tlink = cifs_sb_tlink(cifs_sb);
-       if (IS_ERR(tlink)) {
-               FreeXid(xid);
-               return PTR_ERR(tlink);
-       }
-       tcon = tlink_tcon(tlink);
+       int disposition;
 
+       *oplock = 0;
        if (tcon->ses->server->oplocks)
-               oplock = REQ_OPLOCK;
-
-       if (nd)
-               oflags = nd->intent.open.file->f_flags;
-       else
-               oflags = O_RDONLY | O_CREAT;
+               *oplock = REQ_OPLOCK;
 
        full_path = build_path_from_dentry(direntry);
        if (full_path == NULL) {
                rc = -ENOMEM;
-               goto cifs_create_out;
+               goto out;
        }
 
        if (tcon->unix_ext && (tcon->ses->capabilities & CAP_UNIX) &&
+           !tcon->broken_posix_open &&
            (CIFS_UNIX_POSIX_PATH_OPS_CAP &
                        le64_to_cpu(tcon->fsUnixInfo.Capability))) {
                rc = cifs_posix_open(full_path, &newinode,
-                       inode->i_sb, mode, oflags, &oplock, &fileHandle, xid);
-               /* EIO could indicate that (posix open) operation is not
-                  supported, despite what server claimed in capability
-                  negotiation.  EREMOTE indicates DFS junction, which is not
-                  handled in posix open */
-
-               if (rc == 0) {
-                       if (newinode == NULL) /* query inode info */
+                       inode->i_sb, mode, oflags, oplock, fileHandle, xid);
+               switch (rc) {
+               case 0:
+                       if (newinode == NULL) {
+                               /* query inode info */
                                goto cifs_create_get_file_info;
-                       else /* success, no need to query */
-                               goto cifs_create_set_dentry;
-               } else if ((rc != -EIO) && (rc != -EREMOTE) &&
-                        (rc != -EOPNOTSUPP) && (rc != -EINVAL))
-                       goto cifs_create_out;
-               /* else fallthrough to retry, using older open call, this is
-                  case where server does not support this SMB level, and
-                  falsely claims capability (also get here for DFS case
-                  which should be rare for path not covered on files) */
-       }
+                       }
+
+                       if (!S_ISREG(newinode->i_mode)) {
+                               /*
+                                * The server may allow us to open things like
+                                * FIFOs, but the client isn't set up to deal
+                                * with that. If it's not a regular file, just
+                                * close it and proceed as if it were a normal
+                                * lookup.
+                                */
+                               CIFSSMBClose(xid, tcon, *fileHandle);
+                               goto cifs_create_get_file_info;
+                       }
+                       /* success, no need to query */
+                       goto cifs_create_set_dentry;
+
+               case -ENOENT:
+                       goto cifs_create_get_file_info;
+
+               case -EIO:
+               case -EINVAL:
+                       /*
+                        * EIO could indicate that (posix open) operation is not
+                        * supported, despite what server claimed in capability
+                        * negotiation.
+                        *
+                        * POSIX open in samba versions 3.3.1 and earlier could
+                        * incorrectly fail with invalid parameter.
+                        */
+                       tcon->broken_posix_open = true;
+                       break;
+
+               case -EREMOTE:
+               case -EOPNOTSUPP:
+                       /*
+                        * EREMOTE indicates DFS junction, which is not handled
+                        * in posix open.  If either that or op not supported
+                        * returned, follow the normal lookup.
+                        */
+                       break;
 
-       if (nd) {
-               /* if the file is going to stay open, then we
-                  need to set the desired access properly */
-               desiredAccess = 0;
-               if (OPEN_FMODE(oflags) & FMODE_READ)
-                       desiredAccess |= GENERIC_READ; /* is this too little? */
-               if (OPEN_FMODE(oflags) & FMODE_WRITE)
-                       desiredAccess |= GENERIC_WRITE;
-
-               if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
-                       disposition = FILE_CREATE;
-               else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
-                       disposition = FILE_OVERWRITE_IF;
-               else if ((oflags & O_CREAT) == O_CREAT)
-                       disposition = FILE_OPEN_IF;
-               else
-                       cFYI(1, "Create flag not set in create function");
+               default:
+                       goto out;
+               }
+               /*
+                * fallthrough to retry, using older open call, this is case
+                * where server does not support this SMB level, and falsely
+                * claims capability (also get here for DFS case which should be
+                * rare for path not covered on files)
+                */
        }
 
+       desiredAccess = 0;
+       if (OPEN_FMODE(oflags) & FMODE_READ)
+               desiredAccess |= GENERIC_READ; /* is this too little? */
+       if (OPEN_FMODE(oflags) & FMODE_WRITE)
+               desiredAccess |= GENERIC_WRITE;
+
+       disposition = FILE_OVERWRITE_IF;
+       if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
+               disposition = FILE_CREATE;
+       else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
+               disposition = FILE_OVERWRITE_IF;
+       else if ((oflags & O_CREAT) == O_CREAT)
+               disposition = FILE_OPEN_IF;
+       else
+               cFYI(1, "Create flag not set in create function");
+
        /* BB add processing to set equivalent of mode - e.g. via CreateX with
           ACLs */
 
        buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
        if (buf == NULL) {
                rc = -ENOMEM;
-               goto cifs_create_out;
+               goto out;
        }
 
        /*
@@ -250,7 +283,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
        if (tcon->ses->capabilities & CAP_NT_SMBS)
                rc = CIFSSMBOpen(xid, tcon, full_path, disposition,
                         desiredAccess, create_options,
-                        &fileHandle, &oplock, buf, cifs_sb->local_nls,
+                        fileHandle, oplock, buf, cifs_sb->local_nls,
                         cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
        else
                rc = -EIO; /* no NT SMB support fall into legacy open below */
@@ -259,17 +292,17 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
                /* old server, retry the open legacy style */
                rc = SMBLegacyOpen(xid, tcon, full_path, disposition,
                        desiredAccess, create_options,
-                       &fileHandle, &oplock, buf, cifs_sb->local_nls,
+                       fileHandle, oplock, buf, cifs_sb->local_nls,
                        cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
        }
        if (rc) {
                cFYI(1, "cifs_create returned 0x%x", rc);
-               goto cifs_create_out;
+               goto out;
        }
 
        /* If Open reported that we actually created a file
           then we now have to set the mode if possible */
-       if ((tcon->unix_ext) && (oplock & CIFS_CREATE_ACTION)) {
+       if ((tcon->unix_ext) && (*oplock & CIFS_CREATE_ACTION)) {
                struct cifs_unix_set_info_args args = {
                                .mode   = mode,
                                .ctime  = NO_CHANGE_64,
@@ -278,6 +311,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
                                .device = 0,
                };
 
+               *created |= FILE_CREATED;
                if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
                        args.uid = (__u64) current_fsuid();
                        if (inode->i_mode & S_ISGID)
@@ -288,7 +322,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
                        args.uid = NO_CHANGE_64;
                        args.gid = NO_CHANGE_64;
                }
-               CIFSSMBUnixSetFileInfo(xid, tcon, &args, fileHandle,
+               CIFSSMBUnixSetFileInfo(xid, tcon, &args, *fileHandle,
                                        current->tgid);
        } else {
                /* BB implement mode setting via Windows security
@@ -305,11 +339,11 @@ cifs_create_get_file_info:
                                              inode->i_sb, xid);
        else {
                rc = cifs_get_inode_info(&newinode, full_path, buf,
-                                        inode->i_sb, xid, &fileHandle);
+                                        inode->i_sb, xid, fileHandle);
                if (newinode) {
                        if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
                                newinode->i_mode = mode;
-                       if ((oplock & CIFS_CREATE_ACTION) &&
+                       if ((*oplock & CIFS_CREATE_ACTION) &&
                            (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
                                newinode->i_uid = current_fsuid();
                                if (inode->i_mode & S_ISGID)
@@ -321,40 +355,139 @@ cifs_create_get_file_info:
        }
 
 cifs_create_set_dentry:
-       if (rc == 0)
-               d_instantiate(direntry, newinode);
-       else
+       if (rc != 0) {
                cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
+               goto out;
+       }
+       d_drop(direntry);
+       d_add(direntry, newinode);
 
-       if (newinode && nd) {
-               struct cifsFileInfo *pfile_info;
-               struct file *filp;
+       /* ENOENT for create?  How weird... */
+       rc = -ENOENT;
+       if (!newinode) {
+               CIFSSMBClose(xid, tcon, *fileHandle);
+               goto out;
+       }
+       rc = 0;
 
-               filp = lookup_instantiate_filp(nd, direntry, generic_file_open);
-               if (IS_ERR(filp)) {
-                       rc = PTR_ERR(filp);
-                       CIFSSMBClose(xid, tcon, fileHandle);
-                       goto cifs_create_out;
-               }
+out:
+       kfree(buf);
+       kfree(full_path);
+       return rc;
+}
 
-               pfile_info = cifs_new_fileinfo(fileHandle, filp, tlink, oplock);
-               if (pfile_info == NULL) {
-                       fput(filp);
-                       CIFSSMBClose(xid, tcon, fileHandle);
-                       rc = -ENOMEM;
-               }
-       } else {
+int
+cifs_atomic_open(struct inode *inode, struct dentry *direntry,
+                struct file *file, unsigned oflags, umode_t mode,
+                int *opened)
+{
+       int rc;
+       int xid;
+       struct tcon_link *tlink;
+       struct cifs_tcon *tcon;
+       __u16 fileHandle;
+       __u32 oplock;
+       struct file *filp;
+       struct cifsFileInfo *pfile_info;
+
+       /* Posix open is only called (at lookup time) for file create now.  For
+        * opens (rather than creates), because we do not know if it is a file
+        * or directory yet, and current Samba no longer allows us to do posix
+        * open on dirs, we could end up wasting an open call on what turns out
+        * to be a dir. For file opens, we wait to call posix open till
+        * cifs_open.  It could be added to atomic_open in the future but the
+        * performance tradeoff of the extra network request when EISDIR or
+        * EACCES is returned would have to be weighed against the 50% reduction
+        * in network traffic in the other paths.
+        */
+       if (!(oflags & O_CREAT)) {
+               struct dentry *res = cifs_lookup(inode, direntry, 0);
+               if (IS_ERR(res))
+                       return PTR_ERR(res);
+
+               return finish_no_open(file, res);
+       }
+
+       rc = check_name(direntry);
+       if (rc)
+               return rc;
+
+       xid = GetXid();
+
+       cFYI(1, "parent inode = 0x%p name is: %s and dentry = 0x%p",
+            inode, direntry->d_name.name, direntry);
+
+       tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
+       filp = ERR_CAST(tlink);
+       if (IS_ERR(tlink))
+               goto free_xid;
+
+       tcon = tlink_tcon(tlink);
+
+       rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
+                           &oplock, &fileHandle, opened);
+
+       if (rc)
+               goto out;
+
+       rc = finish_open(file, direntry, generic_file_open, opened);
+       if (rc) {
                CIFSSMBClose(xid, tcon, fileHandle);
+               goto out;
        }
 
-cifs_create_out:
-       kfree(buf);
-       kfree(full_path);
+       pfile_info = cifs_new_fileinfo(fileHandle, filp, tlink, oplock);
+       if (pfile_info == NULL) {
+               CIFSSMBClose(xid, tcon, fileHandle);
+               fput(filp);
+               rc = -ENOMEM;
+       }
+
+out:
        cifs_put_tlink(tlink);
+free_xid:
        FreeXid(xid);
        return rc;
 }
 
+int cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode,
+               bool excl)
+{
+       int rc;
+       int xid = GetXid();
+       /*
+        * BB below access is probably too much for mknod to request
+        *    but we have to do query and setpathinfo so requesting
+        *    less could fail (unless we want to request getatr and setatr
+        *    permissions (only).  At least for POSIX we do not have to
+        *    request so much.
+        */
+       unsigned oflags = O_EXCL | O_CREAT | O_RDWR;
+       struct tcon_link *tlink;
+       __u16 fileHandle;
+       __u32 oplock;
+       int created = FILE_CREATED;
+
+       cFYI(1, "cifs_create parent inode = 0x%p name is: %s and dentry = 0x%p",
+            inode, direntry->d_name.name, direntry);
+
+       tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
+       rc = PTR_ERR(tlink);
+       if (IS_ERR(tlink))
+               goto free_xid;
+
+       rc = cifs_do_create(inode, direntry, xid, tlink, oflags, mode,
+                           &oplock, &fileHandle, &created);
+       if (!rc)
+               CIFSSMBClose(xid, tlink_tcon(tlink), fileHandle);
+
+       cifs_put_tlink(tlink);
+free_xid:
+       FreeXid(xid);
+
+       return rc;
+}
+
 int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode,
                dev_t device_number)
 {
@@ -488,20 +621,15 @@ mknod_out:
 
 struct dentry *
 cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
-           struct nameidata *nd)
+           unsigned int flags)
 {
        int xid;
        int rc = 0; /* to get around spurious gcc warning, set to zero here */
-       __u32 oplock;
-       __u16 fileHandle = 0;
-       bool posix_open = false;
        struct cifs_sb_info *cifs_sb;
        struct tcon_link *tlink;
        struct cifs_tcon *pTcon;
-       struct cifsFileInfo *cfile;
        struct inode *newInode = NULL;
        char *full_path = NULL;
-       struct file *filp;
 
        xid = GetXid();
 
@@ -518,31 +646,9 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
        }
        pTcon = tlink_tcon(tlink);
 
-       oplock = pTcon->ses->server->oplocks ? REQ_OPLOCK : 0;
-
-       /*
-        * Don't allow the separator character in a path component.
-        * The VFS will not allow "/", but "\" is allowed by posix.
-        */
-       if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS)) {
-               int i;
-               for (i = 0; i < direntry->d_name.len; i++)
-                       if (direntry->d_name.name[i] == '\\') {
-                               cFYI(1, "Invalid file name");
-                               rc = -EINVAL;
-                               goto lookup_out;
-                       }
-       }
-
-       /*
-        * O_EXCL: optimize away the lookup, but don't hash the dentry. Let
-        * the VFS handle the create.
-        */
-       if (nd && (nd->flags & LOOKUP_EXCL)) {
-               d_instantiate(direntry, NULL);
-               rc = 0;
+       rc = check_name(direntry);
+       if (rc)
                goto lookup_out;
-       }
 
        /* can not grab the rename sem here since it would
        deadlock in the cases (beginning of sys_rename itself)
@@ -560,80 +666,16 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
        }
        cFYI(1, "Full path: %s inode = 0x%p", full_path, direntry->d_inode);
 
-       /* Posix open is only called (at lookup time) for file create now.
-        * For opens (rather than creates), because we do not know if it
-        * is a file or directory yet, and current Samba no longer allows
-        * us to do posix open on dirs, we could end up wasting an open call
-        * on what turns out to be a dir. For file opens, we wait to call posix
-        * open till cifs_open.  It could be added here (lookup) in the future
-        * but the performance tradeoff of the extra network request when EISDIR
-        * or EACCES is returned would have to be weighed against the 50%
-        * reduction in network traffic in the other paths.
-        */
        if (pTcon->unix_ext) {
-               if (nd && !(nd->flags & LOOKUP_DIRECTORY) &&
-                    (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open &&
-                    (nd->intent.open.file->f_flags & O_CREAT)) {
-                       rc = cifs_posix_open(full_path, &newInode,
-                                       parent_dir_inode->i_sb,
-                                       nd->intent.open.create_mode,
-                                       nd->intent.open.file->f_flags, &oplock,
-                                       &fileHandle, xid);
-                       /*
-                        * The check below works around a bug in POSIX
-                        * open in samba versions 3.3.1 and earlier where
-                        * open could incorrectly fail with invalid parameter.
-                        * If either that or op not supported returned, follow
-                        * the normal lookup.
-                        */
-                       switch (rc) {
-                       case 0:
-                               /*
-                                * The server may allow us to open things like
-                                * FIFOs, but the client isn't set up to deal
-                                * with that. If it's not a regular file, just
-                                * close it and proceed as if it were a normal
-                                * lookup.
-                                */
-                               if (newInode && !S_ISREG(newInode->i_mode)) {
-                                       CIFSSMBClose(xid, pTcon, fileHandle);
-                                       break;
-                               }
-                       case -ENOENT:
-                               posix_open = true;
-                       case -EOPNOTSUPP:
-                               break;
-                       default:
-                               pTcon->broken_posix_open = true;
-                       }
-               }
-               if (!posix_open)
-                       rc = cifs_get_inode_info_unix(&newInode, full_path,
-                                               parent_dir_inode->i_sb, xid);
-       } else
+               rc = cifs_get_inode_info_unix(&newInode, full_path,
+                                             parent_dir_inode->i_sb, xid);
+       } else {
                rc = cifs_get_inode_info(&newInode, full_path, NULL,
                                parent_dir_inode->i_sb, xid, NULL);
+       }
 
        if ((rc == 0) && (newInode != NULL)) {
                d_add(direntry, newInode);
-               if (posix_open) {
-                       filp = lookup_instantiate_filp(nd, direntry,
-                                                      generic_file_open);
-                       if (IS_ERR(filp)) {
-                               rc = PTR_ERR(filp);
-                               CIFSSMBClose(xid, pTcon, fileHandle);
-                               goto lookup_out;
-                       }
-
-                       cfile = cifs_new_fileinfo(fileHandle, filp, tlink,
-                                                 oplock);
-                       if (cfile == NULL) {
-                               fput(filp);
-                               CIFSSMBClose(xid, pTcon, fileHandle);
-                               rc = -ENOMEM;
-                               goto lookup_out;
-                       }
-               }
                /* since paths are not looked up by component - the parent
                   directories are presumed to be good here */
                renew_parental_timestamps(direntry);
@@ -658,9 +700,9 @@ lookup_out:
 }
 
 static int
-cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
+cifs_d_revalidate(struct dentry *direntry, unsigned int flags)
 {
-       if (nd && (nd->flags & LOOKUP_RCU))
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        if (direntry->d_inode) {
@@ -689,7 +731,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
         * This may be nfsd (or something), anyway, we can't see the
         * intent of this. So, since this can be for creation, drop it.
         */
-       if (!nd)
+       if (!flags)
                return 0;
 
        /*
@@ -697,7 +739,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
         * case sensitive name which is specified by user if this is
         * for creation.
         */
-       if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
+       if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
                return 0;
 
        if (time_after(jiffies, direntry->d_time + HZ) || !lookupCacheEnabled)
index 745da3d0653e38a0f48db4f0741f3414e44d974e..8e8bb49112ff07abcb3df80ca5d93abd3b04fc82 100644 (file)
@@ -800,7 +800,7 @@ cifs_find_inode(struct inode *inode, void *opaque)
                return 0;
 
        /* if it's not a directory or has no dentries, then flag it */
-       if (S_ISDIR(inode->i_mode) && !list_empty(&inode->i_dentry))
+       if (S_ISDIR(inode->i_mode) && !hlist_empty(&inode->i_dentry))
                fattr->cf_flags |= CIFS_FATTR_INO_COLLISION;
 
        return 1;
@@ -825,9 +825,10 @@ static bool
 inode_has_hashed_dentries(struct inode *inode)
 {
        struct dentry *dentry;
+       struct hlist_node *p;
 
        spin_lock(&inode->i_lock);
-       list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
                if (!d_unhashed(dentry) || IS_ROOT(dentry)) {
                        spin_unlock(&inode->i_lock);
                        return true;
index 6901578761841ae6c0ed950c26de2cf64c9d1389..958ae0e0ff8c0d55d5ef18001154f56e3cb273ce 100644 (file)
@@ -89,17 +89,13 @@ int coda_cache_check(struct inode *inode, int mask)
 /* this won't do any harm: just flag all children */
 static void coda_flag_children(struct dentry *parent, int flag)
 {
-       struct list_head *child;
        struct dentry *de;
 
        spin_lock(&parent->d_lock);
-       list_for_each(child, &parent->d_subdirs)
-       {
-               de = list_entry(child, struct dentry, d_u.d_child);
+       list_for_each_entry(de, &parent->d_subdirs, d_u.d_child) {
                /* don't know what to do with negative dentries */
-               if ( ! de->d_inode ) 
-                       continue;
-               coda_flag_inode(de->d_inode, flag);
+               if (de->d_inode ) 
+                       coda_flag_inode(de->d_inode, flag);
        }
        spin_unlock(&parent->d_lock);
        return; 
index 177515829062d82aed7dcdce9bda390535804614..49fe52d256009729ae9c9ec5cfd1b684255219f3 100644 (file)
@@ -30,8 +30,8 @@
 #include "coda_int.h"
 
 /* dir inode-ops */
-static int coda_create(struct inode *dir, struct dentry *new, umode_t mode, struct nameidata *nd);
-static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, struct nameidata *nd);
+static int coda_create(struct inode *dir, struct dentry *new, umode_t mode, bool excl);
+static struct dentry *coda_lookup(struct inode *dir, struct dentry *target, unsigned int flags);
 static int coda_link(struct dentry *old_dentry, struct inode *dir_inode, 
                     struct dentry *entry);
 static int coda_unlink(struct inode *dir_inode, struct dentry *entry);
@@ -46,7 +46,7 @@ static int coda_rename(struct inode *old_inode, struct dentry *old_dentry,
 static int coda_readdir(struct file *file, void *buf, filldir_t filldir);
 
 /* dentry ops */
-static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd);
+static int coda_dentry_revalidate(struct dentry *de, unsigned int flags);
 static int coda_dentry_delete(const struct dentry *);
 
 /* support routines */
@@ -94,7 +94,7 @@ const struct file_operations coda_dir_operations = {
 
 /* inode operations for directories */
 /* access routines: lookup, readlink, permission */
-static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd)
+static struct dentry *coda_lookup(struct inode *dir, struct dentry *entry, unsigned int flags)
 {
        struct super_block *sb = dir->i_sb;
        const char *name = entry->d_name.name;
@@ -188,7 +188,7 @@ static inline void coda_dir_drop_nlink(struct inode *dir)
 }
 
 /* creation routines: create, mknod, mkdir, link, symlink */
-static int coda_create(struct inode *dir, struct dentry *de, umode_t mode, struct nameidata *nd)
+static int coda_create(struct inode *dir, struct dentry *de, umode_t mode, bool excl)
 {
        int error;
        const char *name=de->d_name.name;
@@ -536,12 +536,12 @@ out:
 }
 
 /* called when a cache lookup succeeds */
-static int coda_dentry_revalidate(struct dentry *de, struct nameidata *nd)
+static int coda_dentry_revalidate(struct dentry *de, unsigned int flags)
 {
        struct inode *inode;
        struct coda_inode_info *cii;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        inode = de->d_inode;
index 7e6c52d8a2074c651b116a39d56a1868d622f9f1..7414ae24a79b4690ed5fb7ed72245d941791a82f 100644 (file)
@@ -442,7 +442,7 @@ static int configfs_attach_attr(struct configfs_dirent * sd, struct dentry * den
 
 static struct dentry * configfs_lookup(struct inode *dir,
                                       struct dentry *dentry,
-                                      struct nameidata *nd)
+                                      unsigned int flags)
 {
        struct configfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
        struct configfs_dirent * sd;
index d013c46402ed118ea9babda0433efd2692a447c7..28cca01ca9c9c2b29b20d16581c430d900101a78 100644 (file)
@@ -417,7 +417,7 @@ static int cramfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
 /*
  * Lookup and fill in the inode data..
  */
-static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry * cramfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        unsigned int offset = 0;
        struct inode *inode = NULL;
index 40469044088def2607d19540ef0cb8dcce78ac91..8086636bf796ab328219d4a898608af1be2fdb2b 100644 (file)
@@ -218,7 +218,7 @@ static void __d_free(struct rcu_head *head)
 {
        struct dentry *dentry = container_of(head, struct dentry, d_u.d_rcu);
 
-       WARN_ON(!list_empty(&dentry->d_alias));
+       WARN_ON(!hlist_unhashed(&dentry->d_alias));
        if (dname_external(dentry))
                kfree(dentry->d_name.name);
        kmem_cache_free(dentry_cache, dentry); 
@@ -267,7 +267,7 @@ static void dentry_iput(struct dentry * dentry)
        struct inode *inode = dentry->d_inode;
        if (inode) {
                dentry->d_inode = NULL;
-               list_del_init(&dentry->d_alias);
+               hlist_del_init(&dentry->d_alias);
                spin_unlock(&dentry->d_lock);
                spin_unlock(&inode->i_lock);
                if (!inode->i_nlink)
@@ -291,7 +291,7 @@ static void dentry_unlink_inode(struct dentry * dentry)
 {
        struct inode *inode = dentry->d_inode;
        dentry->d_inode = NULL;
-       list_del_init(&dentry->d_alias);
+       hlist_del_init(&dentry->d_alias);
        dentry_rcuwalk_barrier(dentry);
        spin_unlock(&dentry->d_lock);
        spin_unlock(&inode->i_lock);
@@ -699,10 +699,11 @@ EXPORT_SYMBOL(dget_parent);
 static struct dentry *__d_find_alias(struct inode *inode, int want_discon)
 {
        struct dentry *alias, *discon_alias;
+       struct hlist_node *p;
 
 again:
        discon_alias = NULL;
-       list_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) {
                spin_lock(&alias->d_lock);
                if (S_ISDIR(inode->i_mode) || !d_unhashed(alias)) {
                        if (IS_ROOT(alias) &&
@@ -737,7 +738,7 @@ struct dentry *d_find_alias(struct inode *inode)
 {
        struct dentry *de = NULL;
 
-       if (!list_empty(&inode->i_dentry)) {
+       if (!hlist_empty(&inode->i_dentry)) {
                spin_lock(&inode->i_lock);
                de = __d_find_alias(inode, 0);
                spin_unlock(&inode->i_lock);
@@ -753,9 +754,10 @@ EXPORT_SYMBOL(d_find_alias);
 void d_prune_aliases(struct inode *inode)
 {
        struct dentry *dentry;
+       struct hlist_node *p;
 restart:
        spin_lock(&inode->i_lock);
-       list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
                spin_lock(&dentry->d_lock);
                if (!dentry->d_count) {
                        __dget_dlock(dentry);
@@ -977,7 +979,7 @@ static void shrink_dcache_for_umount_subtree(struct dentry *dentry)
                        inode = dentry->d_inode;
                        if (inode) {
                                dentry->d_inode = NULL;
-                               list_del_init(&dentry->d_alias);
+                               hlist_del_init(&dentry->d_alias);
                                if (dentry->d_op && dentry->d_op->d_iput)
                                        dentry->d_op->d_iput(dentry, inode);
                                else
@@ -1312,7 +1314,7 @@ struct dentry *__d_alloc(struct super_block *sb, const struct qstr *name)
        INIT_HLIST_BL_NODE(&dentry->d_hash);
        INIT_LIST_HEAD(&dentry->d_lru);
        INIT_LIST_HEAD(&dentry->d_subdirs);
-       INIT_LIST_HEAD(&dentry->d_alias);
+       INIT_HLIST_NODE(&dentry->d_alias);
        INIT_LIST_HEAD(&dentry->d_u.d_child);
        d_set_d_op(dentry, dentry->d_sb->s_d_op);
 
@@ -1400,7 +1402,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
        if (inode) {
                if (unlikely(IS_AUTOMOUNT(inode)))
                        dentry->d_flags |= DCACHE_NEED_AUTOMOUNT;
-               list_add(&dentry->d_alias, &inode->i_dentry);
+               hlist_add_head(&dentry->d_alias, &inode->i_dentry);
        }
        dentry->d_inode = inode;
        dentry_rcuwalk_barrier(dentry);
@@ -1425,7 +1427,7 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
  
 void d_instantiate(struct dentry *entry, struct inode * inode)
 {
-       BUG_ON(!list_empty(&entry->d_alias));
+       BUG_ON(!hlist_unhashed(&entry->d_alias));
        if (inode)
                spin_lock(&inode->i_lock);
        __d_instantiate(entry, inode);
@@ -1458,13 +1460,14 @@ static struct dentry *__d_instantiate_unique(struct dentry *entry,
        int len = entry->d_name.len;
        const char *name = entry->d_name.name;
        unsigned int hash = entry->d_name.hash;
+       struct hlist_node *p;
 
        if (!inode) {
                __d_instantiate(entry, NULL);
                return NULL;
        }
 
-       list_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) {
                /*
                 * Don't need alias->d_lock here, because aliases with
                 * d_parent == entry->d_parent are not subject to name or
@@ -1490,7 +1493,7 @@ struct dentry *d_instantiate_unique(struct dentry *entry, struct inode *inode)
 {
        struct dentry *result;
 
-       BUG_ON(!list_empty(&entry->d_alias));
+       BUG_ON(!hlist_unhashed(&entry->d_alias));
 
        if (inode)
                spin_lock(&inode->i_lock);
@@ -1531,9 +1534,9 @@ static struct dentry * __d_find_any_alias(struct inode *inode)
 {
        struct dentry *alias;
 
-       if (list_empty(&inode->i_dentry))
+       if (hlist_empty(&inode->i_dentry))
                return NULL;
-       alias = list_first_entry(&inode->i_dentry, struct dentry, d_alias);
+       alias = hlist_entry(inode->i_dentry.first, struct dentry, d_alias);
        __dget(alias);
        return alias;
 }
@@ -1607,7 +1610,7 @@ struct dentry *d_obtain_alias(struct inode *inode)
        spin_lock(&tmp->d_lock);
        tmp->d_inode = inode;
        tmp->d_flags |= DCACHE_DISCONNECTED;
-       list_add(&tmp->d_alias, &inode->i_dentry);
+       hlist_add_head(&tmp->d_alias, &inode->i_dentry);
        hlist_bl_lock(&tmp->d_sb->s_anon);
        hlist_bl_add_head(&tmp->d_hash, &tmp->d_sb->s_anon);
        hlist_bl_unlock(&tmp->d_sb->s_anon);
@@ -2384,14 +2387,13 @@ static struct dentry *__d_unalias(struct inode *inode,
                struct dentry *dentry, struct dentry *alias)
 {
        struct mutex *m1 = NULL, *m2 = NULL;
-       struct dentry *ret;
+       struct dentry *ret = ERR_PTR(-EBUSY);
 
        /* If alias and dentry share a parent, then no extra locks required */
        if (alias->d_parent == dentry->d_parent)
                goto out_unalias;
 
        /* See lock_rename() */
-       ret = ERR_PTR(-EBUSY);
        if (!mutex_trylock(&dentry->d_sb->s_vfs_rename_mutex))
                goto out_err;
        m1 = &dentry->d_sb->s_vfs_rename_mutex;
@@ -2399,8 +2401,10 @@ static struct dentry *__d_unalias(struct inode *inode,
                goto out_err;
        m2 = &alias->d_parent->d_inode->i_mutex;
 out_unalias:
-       __d_move(alias, dentry);
-       ret = alias;
+       if (likely(!d_mountpoint(alias))) {
+               __d_move(alias, dentry);
+               ret = alias;
+       }
 out_err:
        spin_unlock(&inode->i_lock);
        if (m2)
@@ -2622,7 +2626,7 @@ global_root:
        if (!slash)
                error = prepend(buffer, buflen, "/", 1);
        if (!error)
-               error = real_mount(vfsmnt)->mnt_ns ? 1 : 2;
+               error = is_mounted(vfsmnt) ? 1 : 2;
        goto out;
 }
 
index b80bc846a15a55d6e8f4fefa2ad2231713616f45..d17c20fd74e6958f171e41e6c74bcf27ab620b56 100644 (file)
@@ -54,13 +54,12 @@ static struct inode *debugfs_get_inode(struct super_block *sb, umode_t mode, dev
                        break;
                case S_IFLNK:
                        inode->i_op = &debugfs_link_operations;
-                       inode->i_fop = fops;
                        inode->i_private = data;
                        break;
                case S_IFDIR:
                        inode->i_op = &simple_dir_inode_operations;
-                       inode->i_fop = fops ? fops : &simple_dir_operations;
-                       inode->i_private = data;
+                       inode->i_fop = &simple_dir_operations;
+                       inode->i_private = NULL;
 
                        /* directory inodes start off with i_nlink == 2
                         * (for "." entry) */
@@ -91,13 +90,12 @@ static int debugfs_mknod(struct inode *dir, struct dentry *dentry,
        return error;
 }
 
-static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode,
-                        void *data, const struct file_operations *fops)
+static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 {
        int res;
 
        mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
-       res = debugfs_mknod(dir, dentry, mode, 0, data, fops);
+       res = debugfs_mknod(dir, dentry, mode, 0, NULL, NULL);
        if (!res) {
                inc_nlink(dir);
                fsnotify_mkdir(dir, dentry);
@@ -106,10 +104,10 @@ static int debugfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode,
 }
 
 static int debugfs_link(struct inode *dir, struct dentry *dentry, umode_t mode,
-                       void *data, const struct file_operations *fops)
+                       void *data)
 {
        mode = (mode & S_IALLUGO) | S_IFLNK;
-       return debugfs_mknod(dir, dentry, mode, 0, data, fops);
+       return debugfs_mknod(dir, dentry, mode, 0, data, NULL);
 }
 
 static int debugfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
@@ -293,13 +291,19 @@ static struct file_system_type debug_fs_type = {
        .kill_sb =      kill_litter_super,
 };
 
-static int debugfs_create_by_name(const char *name, umode_t mode,
-                                 struct dentry *parent,
-                                 struct dentry **dentry,
-                                 void *data,
-                                 const struct file_operations *fops)
+struct dentry *__create_file(const char *name, umode_t mode,
+                                  struct dentry *parent, void *data,
+                                  const struct file_operations *fops)
 {
-       int error = 0;
+       struct dentry *dentry = NULL;
+       int error;
+
+       pr_debug("debugfs: creating file '%s'\n",name);
+
+       error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
+                             &debugfs_mount_count);
+       if (error)
+               goto exit;
 
        /* If the parent is not specified, we create it in the root.
         * We need the root dentry to do this, which is in the super 
@@ -309,30 +313,35 @@ static int debugfs_create_by_name(const char *name, umode_t mode,
        if (!parent)
                parent = debugfs_mount->mnt_root;
 
-       *dentry = NULL;
+       dentry = NULL;
        mutex_lock(&parent->d_inode->i_mutex);
-       *dentry = lookup_one_len(name, parent, strlen(name));
-       if (!IS_ERR(*dentry)) {
+       dentry = lookup_one_len(name, parent, strlen(name));
+       if (!IS_ERR(dentry)) {
                switch (mode & S_IFMT) {
                case S_IFDIR:
-                       error = debugfs_mkdir(parent->d_inode, *dentry, mode,
-                                             data, fops);
+                       error = debugfs_mkdir(parent->d_inode, dentry, mode);
+                                             
                        break;
                case S_IFLNK:
-                       error = debugfs_link(parent->d_inode, *dentry, mode,
-                                            data, fops);
+                       error = debugfs_link(parent->d_inode, dentry, mode,
+                                            data);
                        break;
                default:
-                       error = debugfs_create(parent->d_inode, *dentry, mode,
+                       error = debugfs_create(parent->d_inode, dentry, mode,
                                               data, fops);
                        break;
                }
-               dput(*dentry);
+               dput(dentry);
        } else
-               error = PTR_ERR(*dentry);
+               error = PTR_ERR(dentry);
        mutex_unlock(&parent->d_inode->i_mutex);
 
-       return error;
+       if (error) {
+               dentry = NULL;
+               simple_release_fs(&debugfs_mount, &debugfs_mount_count);
+       }
+exit:
+       return dentry;
 }
 
 /**
@@ -365,25 +374,15 @@ struct dentry *debugfs_create_file(const char *name, umode_t mode,
                                   struct dentry *parent, void *data,
                                   const struct file_operations *fops)
 {
-       struct dentry *dentry = NULL;
-       int error;
-
-       pr_debug("debugfs: creating file '%s'\n",name);
-
-       error = simple_pin_fs(&debug_fs_type, &debugfs_mount,
-                             &debugfs_mount_count);
-       if (error)
-               goto exit;
-
-       error = debugfs_create_by_name(name, mode, parent, &dentry,
-                                      data, fops);
-       if (error) {
-               dentry = NULL;
-               simple_release_fs(&debugfs_mount, &debugfs_mount_count);
-               goto exit;
+       switch (mode & S_IFMT) {
+       case S_IFREG:
+       case 0:
+               break;
+       default:
+               BUG();
        }
-exit:
-       return dentry;
+
+       return __create_file(name, mode, parent, data, fops);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_file);
 
@@ -407,8 +406,7 @@ EXPORT_SYMBOL_GPL(debugfs_create_file);
  */
 struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
 {
-       return debugfs_create_file(name, 
-                                  S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
+       return __create_file(name, S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
                                   parent, NULL, NULL);
 }
 EXPORT_SYMBOL_GPL(debugfs_create_dir);
@@ -446,8 +444,7 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
        if (!link)
                return NULL;
 
-       result = debugfs_create_file(name, S_IFLNK | S_IRWXUGO, parent, link,
-                                    NULL);
+       result = __create_file(name, S_IFLNK | S_IRWXUGO, parent, link, NULL);
        if (!result)
                kfree(link);
        return result;
index 979c1e309c730479fa4642f2c289fa617c94f56b..14afbabe65464e226549894404ec1af9d1a3f747 100644 (file)
@@ -439,15 +439,15 @@ static struct dentry *devpts_mount(struct file_system_type *fs_type,
                return ERR_PTR(error);
 
        if (opts.newinstance)
-               s = sget(fs_type, NULL, set_anon_super, NULL);
+               s = sget(fs_type, NULL, set_anon_super, flags, NULL);
        else
-               s = sget(fs_type, compare_init_pts_sb, set_anon_super, NULL);
+               s = sget(fs_type, compare_init_pts_sb, set_anon_super, flags,
+                        NULL);
 
        if (IS_ERR(s))
                return ERR_CAST(s);
 
        if (!s->s_root) {
-               s->s_flags = flags;
                error = devpts_fill_super(s, data, flags & MS_SILENT ? 1 : 0);
                if (error)
                        goto out_undo_sget;
index 0c85fae37666db4b18fb2bf9ebf692ae04bcbf40..1faf4cb56f3963d0945d8004b8640464b9e3b6fd 100644 (file)
@@ -1258,7 +1258,7 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
         */
        BUG_ON(retval == -EIOCBQUEUED);
        if (dio->is_async && retval == 0 && dio->result &&
-           ((rw & READ) || (dio->result == sdio.size)))
+           ((rw == READ) || (dio->result == sdio.size)))
                retval = -EIOCBQUEUED;
 
        if (retval != -EIOCBQUEUED)
index 534c1d46e69ea6ebb8b860137579d301f9c35840..1b5d9af937dfc4a33015eaa154a8956857381749 100644 (file)
@@ -32,7 +32,7 @@
 /**
  * ecryptfs_d_revalidate - revalidate an ecryptfs dentry
  * @dentry: The ecryptfs dentry
- * @nd: The associated nameidata
+ * @flags: lookup flags
  *
  * Called when the VFS needs to revalidate a dentry. This
  * is called whenever a name lookup finds a dentry in the
  * Returns 1 if valid, 0 otherwise.
  *
  */
-static int ecryptfs_d_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int ecryptfs_d_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct dentry *lower_dentry;
        struct vfsmount *lower_mnt;
-       struct dentry *dentry_save = NULL;
-       struct vfsmount *vfsmount_save = NULL;
        int rc = 1;
 
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        lower_dentry = ecryptfs_dentry_to_lower(dentry);
        lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry);
        if (!lower_dentry->d_op || !lower_dentry->d_op->d_revalidate)
                goto out;
-       if (nd) {
-               dentry_save = nd->path.dentry;
-               vfsmount_save = nd->path.mnt;
-               nd->path.dentry = lower_dentry;
-               nd->path.mnt = lower_mnt;
-       }
-       rc = lower_dentry->d_op->d_revalidate(lower_dentry, nd);
-       if (nd) {
-               nd->path.dentry = dentry_save;
-               nd->path.mnt = vfsmount_save;
-       }
+       rc = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
        if (dentry->d_inode) {
                struct inode *lower_inode =
                        ecryptfs_inode_to_lower(dentry->d_inode);
index 867b64c5d84f9f2892e182baa89c888224b99418..989e034f02bdfa69e2c22994ceef7b06a8b61748 100644 (file)
@@ -550,20 +550,6 @@ extern struct kmem_cache *ecryptfs_key_record_cache;
 extern struct kmem_cache *ecryptfs_key_sig_cache;
 extern struct kmem_cache *ecryptfs_global_auth_tok_cache;
 extern struct kmem_cache *ecryptfs_key_tfm_cache;
-extern struct kmem_cache *ecryptfs_open_req_cache;
-
-struct ecryptfs_open_req {
-#define ECRYPTFS_REQ_PROCESSED 0x00000001
-#define ECRYPTFS_REQ_DROPPED   0x00000002
-#define ECRYPTFS_REQ_ZOMBIE    0x00000004
-       u32 flags;
-       struct file **lower_file;
-       struct dentry *lower_dentry;
-       struct vfsmount *lower_mnt;
-       wait_queue_head_t wait;
-       struct mutex mux;
-       struct list_head kthread_ctl_list;
-};
 
 struct inode *ecryptfs_get_inode(struct inode *lower_inode,
                                 struct super_block *sb);
index a07441a0a8789a9ee1e43f5be0d2b43ec3ee04e8..ffa2be57804dddcd21b89a712cc9107d027b3c3b 100644 (file)
@@ -173,7 +173,7 @@ ecryptfs_do_create(struct inode *directory_inode,
                inode = ERR_CAST(lower_dir_dentry);
                goto out;
        }
-       rc = vfs_create(lower_dir_dentry->d_inode, lower_dentry, mode, NULL);
+       rc = vfs_create(lower_dir_dentry->d_inode, lower_dentry, mode, true);
        if (rc) {
                printk(KERN_ERR "%s: Failure to create dentry in lower fs; "
                       "rc = [%d]\n", __func__, rc);
@@ -240,7 +240,6 @@ out:
  * @dir: The inode of the directory in which to create the file.
  * @dentry: The eCryptfs dentry
  * @mode: The mode of the new file.
- * @nd: nameidata
  *
  * Creates a new file.
  *
@@ -248,7 +247,7 @@ out:
  */
 static int
 ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
-               umode_t mode, struct nameidata *nd)
+               umode_t mode, bool excl)
 {
        struct inode *ecryptfs_inode;
        int rc;
@@ -270,8 +269,8 @@ ecryptfs_create(struct inode *directory_inode, struct dentry *ecryptfs_dentry,
                iput(ecryptfs_inode);
                goto out;
        }
-       d_instantiate(ecryptfs_dentry, ecryptfs_inode);
        unlock_new_inode(ecryptfs_inode);
+       d_instantiate(ecryptfs_dentry, ecryptfs_inode);
 out:
        return rc;
 }
@@ -374,7 +373,7 @@ static int ecryptfs_lookup_interpose(struct dentry *dentry,
  */
 static struct dentry *ecryptfs_lookup(struct inode *ecryptfs_dir_inode,
                                      struct dentry *ecryptfs_dentry,
-                                     struct nameidata *ecryptfs_nd)
+                                     unsigned int flags)
 {
        char *encrypted_and_encoded_name = NULL;
        size_t encrypted_and_encoded_name_size;
index 0dbe58a8b172c1de225b3457600b50d644b1da35..809e67d05ca34fa32eb1363c555db71757d1a6a7 100644 (file)
 #include <linux/mount.h>
 #include "ecryptfs_kernel.h"
 
-struct kmem_cache *ecryptfs_open_req_cache;
+struct ecryptfs_open_req {
+       struct file **lower_file;
+       struct path path;
+       struct completion done;
+       struct list_head kthread_ctl_list;
+};
 
 static struct ecryptfs_kthread_ctl {
 #define ECRYPTFS_KTHREAD_ZOMBIE 0x00000001
@@ -67,18 +72,10 @@ static int ecryptfs_threadfn(void *ignored)
                        req = list_first_entry(&ecryptfs_kthread_ctl.req_list,
                                               struct ecryptfs_open_req,
                                               kthread_ctl_list);
-                       mutex_lock(&req->mux);
                        list_del(&req->kthread_ctl_list);
-                       if (!(req->flags & ECRYPTFS_REQ_ZOMBIE)) {
-                               dget(req->lower_dentry);
-                               mntget(req->lower_mnt);
-                               (*req->lower_file) = dentry_open(
-                                       req->lower_dentry, req->lower_mnt,
-                                       (O_RDWR | O_LARGEFILE), current_cred());
-                               req->flags |= ECRYPTFS_REQ_PROCESSED;
-                       }
-                       wake_up(&req->wait);
-                       mutex_unlock(&req->mux);
+                       *req->lower_file = dentry_open(&req->path,
+                               (O_RDWR | O_LARGEFILE), current_cred());
+                       complete(&req->done);
                }
                mutex_unlock(&ecryptfs_kthread_ctl.mux);
        }
@@ -111,10 +108,9 @@ void ecryptfs_destroy_kthread(void)
        ecryptfs_kthread_ctl.flags |= ECRYPTFS_KTHREAD_ZOMBIE;
        list_for_each_entry(req, &ecryptfs_kthread_ctl.req_list,
                            kthread_ctl_list) {
-               mutex_lock(&req->mux);
-               req->flags |= ECRYPTFS_REQ_ZOMBIE;
-               wake_up(&req->wait);
-               mutex_unlock(&req->mux);
+               list_del(&req->kthread_ctl_list);
+               *req->lower_file = ERR_PTR(-EIO);
+               complete(&req->done);
        }
        mutex_unlock(&ecryptfs_kthread_ctl.mux);
        kthread_stop(ecryptfs_kthread);
@@ -136,34 +132,26 @@ int ecryptfs_privileged_open(struct file **lower_file,
                             struct vfsmount *lower_mnt,
                             const struct cred *cred)
 {
-       struct ecryptfs_open_req *req;
+       struct ecryptfs_open_req req;
        int flags = O_LARGEFILE;
        int rc = 0;
 
+       init_completion(&req.done);
+       req.lower_file = lower_file;
+       req.path.dentry = lower_dentry;
+       req.path.mnt = lower_mnt;
+
        /* Corresponding dput() and mntput() are done when the
         * lower file is fput() when all eCryptfs files for the inode are
         * released. */
-       dget(lower_dentry);
-       mntget(lower_mnt);
        flags |= IS_RDONLY(lower_dentry->d_inode) ? O_RDONLY : O_RDWR;
-       (*lower_file) = dentry_open(lower_dentry, lower_mnt, flags, cred);
+       (*lower_file) = dentry_open(&req.path, flags, cred);
        if (!IS_ERR(*lower_file))
                goto out;
        if ((flags & O_ACCMODE) == O_RDONLY) {
                rc = PTR_ERR((*lower_file));
                goto out;
        }
-       req = kmem_cache_alloc(ecryptfs_open_req_cache, GFP_KERNEL);
-       if (!req) {
-               rc = -ENOMEM;
-               goto out;
-       }
-       mutex_init(&req->mux);
-       req->lower_file = lower_file;
-       req->lower_dentry = lower_dentry;
-       req->lower_mnt = lower_mnt;
-       init_waitqueue_head(&req->wait);
-       req->flags = 0;
        mutex_lock(&ecryptfs_kthread_ctl.mux);
        if (ecryptfs_kthread_ctl.flags & ECRYPTFS_KTHREAD_ZOMBIE) {
                rc = -EIO;
@@ -171,27 +159,14 @@ int ecryptfs_privileged_open(struct file **lower_file,
                printk(KERN_ERR "%s: We are in the middle of shutting down; "
                       "aborting privileged request to open lower file\n",
                        __func__);
-               goto out_free;
+               goto out;
        }
-       list_add_tail(&req->kthread_ctl_list, &ecryptfs_kthread_ctl.req_list);
+       list_add_tail(&req.kthread_ctl_list, &ecryptfs_kthread_ctl.req_list);
        mutex_unlock(&ecryptfs_kthread_ctl.mux);
        wake_up(&ecryptfs_kthread_ctl.wait);
-       wait_event(req->wait, (req->flags != 0));
-       mutex_lock(&req->mux);
-       BUG_ON(req->flags == 0);
-       if (req->flags & ECRYPTFS_REQ_DROPPED
-           || req->flags & ECRYPTFS_REQ_ZOMBIE) {
-               rc = -EIO;
-               printk(KERN_WARNING "%s: Privileged open request dropped\n",
-                      __func__);
-               goto out_unlock;
-       }
-       if (IS_ERR(*req->lower_file))
-               rc = PTR_ERR(*req->lower_file);
-out_unlock:
-       mutex_unlock(&req->mux);
-out_free:
-       kmem_cache_free(ecryptfs_open_req_cache, req);
+       wait_for_completion(&req.done);
+       if (IS_ERR(*lower_file))
+               rc = PTR_ERR(*lower_file);
 out:
        return rc;
 }
index 68954937a071abd9ce4a67b6614880a4073d1554..1c0b3b6b75c6a777948dc80338d5765345d74e95 100644 (file)
@@ -499,13 +499,12 @@ static struct dentry *ecryptfs_mount(struct file_system_type *fs_type, int flags
                goto out;
        }
 
-       s = sget(fs_type, NULL, set_anon_super, NULL);
+       s = sget(fs_type, NULL, set_anon_super, flags, NULL);
        if (IS_ERR(s)) {
                rc = PTR_ERR(s);
                goto out;
        }
 
-       s->s_flags = flags;
        rc = bdi_setup_and_register(&sbi->bdi, "ecryptfs", BDI_CAP_MAP_COPY);
        if (rc)
                goto out1;
@@ -682,11 +681,6 @@ static struct ecryptfs_cache_info {
                .name = "ecryptfs_key_tfm_cache",
                .size = sizeof(struct ecryptfs_key_tfm),
        },
-       {
-               .cache = &ecryptfs_open_req_cache,
-               .name = "ecryptfs_open_req_cache",
-               .size = sizeof(struct ecryptfs_open_req),
-       },
 };
 
 static void ecryptfs_free_kmem_caches(void)
index d8305b582ab00b8537443b5cff2c5f47888c723f..5528926ac7f6d06d68b6e1192bb0517785942195 100644 (file)
@@ -129,7 +129,7 @@ extern struct inode *efs_iget(struct super_block *, unsigned long);
 extern efs_block_t efs_map_block(struct inode *, efs_block_t);
 extern int efs_get_block(struct inode *, sector_t, struct buffer_head *, int);
 
-extern struct dentry *efs_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *efs_lookup(struct inode *, struct dentry *, unsigned int);
 extern struct dentry *efs_fh_to_dentry(struct super_block *sb, struct fid *fid,
                int fh_len, int fh_type);
 extern struct dentry *efs_fh_to_parent(struct super_block *sb, struct fid *fid,
index 832b10ded82f599c27569801bf00ee8f95beff14..96f66d213a19a69fd59b9132f0bd561ce3d1d508 100644 (file)
@@ -58,7 +58,8 @@ static efs_ino_t efs_find_entry(struct inode *inode, const char *name, int len)
        return(0);
 }
 
-struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) {
+struct dentry *efs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
+{
        efs_ino_t inodenum;
        struct inode *inode = NULL;
 
index fc7161d6bf6bb7d816a18314dab290e9b7cffda1..4731fd991efee11b2c05e7c45306134e07b3fe82 100644 (file)
@@ -46,7 +46,7 @@ static inline int exofs_add_nondir(struct dentry *dentry, struct inode *inode)
 }
 
 static struct dentry *exofs_lookup(struct inode *dir, struct dentry *dentry,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        struct inode *inode;
        ino_t ino;
@@ -60,7 +60,7 @@ static struct dentry *exofs_lookup(struct inode *dir, struct dentry *dentry,
 }
 
 static int exofs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                        struct nameidata *nd)
+                        bool excl)
 {
        struct inode *inode = exofs_new_inode(dir, mode);
        int err = PTR_ERR(inode);
index 49cf230554a21d33785d16367d9397ab34a44d91..24a49d47e9354c00f0ebd2da6c92d3520e71332c 100644 (file)
@@ -735,13 +735,7 @@ static int _prepare_for_striping(struct ore_io_state *ios)
 out:
        ios->numdevs = devs_in_group;
        ios->pages_consumed = cur_pg;
-       if (unlikely(ret)) {
-               if (length == ios->length)
-                       return ret;
-               else
-                       ios->length -= length;
-       }
-       return 0;
+       return ret;
 }
 
 int ore_create(struct ore_io_state *ios)
index d222c77cfa1ba0669ca7580c420a1c31da35c86a..5f376d14fdcc3c0d9791fce5f2951d35b54c778b 100644 (file)
@@ -144,26 +144,26 @@ static void _sp2d_reset(struct __stripe_pages_2d *sp2d,
 {
        unsigned data_devs = sp2d->data_devs;
        unsigned group_width = data_devs + sp2d->parity;
-       unsigned p;
+       int p, c;
 
        if (!sp2d->needed)
                return;
 
-       for (p = 0; p < sp2d->pages_in_unit; p++) {
-               struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p];
-
-               if (_1ps->write_count < group_width) {
-                       unsigned c;
+       for (c = data_devs - 1; c >= 0; --c)
+               for (p = sp2d->pages_in_unit - 1; p >= 0; --p) {
+                       struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p];
 
-                       for (c = 0; c < data_devs; c++)
-                               if (_1ps->page_is_read[c]) {
-                                       struct page *page = _1ps->pages[c];
+                       if (_1ps->page_is_read[c]) {
+                               struct page *page = _1ps->pages[c];
 
-                                       r4w->put_page(priv, page);
-                                       _1ps->page_is_read[c] = false;
-                               }
+                               r4w->put_page(priv, page);
+                               _1ps->page_is_read[c] = false;
+                       }
                }
 
+       for (p = 0; p < sp2d->pages_in_unit; p++) {
+               struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p];
+
                memset(_1ps->pages, 0, group_width * sizeof(*_1ps->pages));
                _1ps->write_count = 0;
                _1ps->tx = NULL;
@@ -461,16 +461,12 @@ static void _mark_read4write_pages_uptodate(struct ore_io_state *ios, int ret)
  * ios->sp2d[p][*], xor is calculated the same way. These pages are
  * allocated/freed and don't go through cache
  */
-static int _read_4_write(struct ore_io_state *ios)
+static int _read_4_write_first_stripe(struct ore_io_state *ios)
 {
-       struct ore_io_state *ios_read;
        struct ore_striping_info read_si;
        struct __stripe_pages_2d *sp2d = ios->sp2d;
        u64 offset = ios->si.first_stripe_start;
-       u64 last_stripe_end;
-       unsigned bytes_in_stripe = ios->si.bytes_in_stripe;
-       unsigned i, c, p, min_p = sp2d->pages_in_unit, max_p = -1;
-       int ret;
+       unsigned c, p, min_p = sp2d->pages_in_unit, max_p = -1;
 
        if (offset == ios->offset) /* Go to start collect $200 */
                goto read_last_stripe;
@@ -478,6 +474,9 @@ static int _read_4_write(struct ore_io_state *ios)
        min_p = _sp2d_min_pg(sp2d);
        max_p = _sp2d_max_pg(sp2d);
 
+       ORE_DBGMSG("stripe_start=0x%llx ios->offset=0x%llx min_p=%d max_p=%d\n",
+                  offset, ios->offset, min_p, max_p);
+
        for (c = 0; ; c++) {
                ore_calc_stripe_info(ios->layout, offset, 0, &read_si);
                read_si.obj_offset += min_p * PAGE_SIZE;
@@ -512,6 +511,18 @@ static int _read_4_write(struct ore_io_state *ios)
        }
 
 read_last_stripe:
+       return 0;
+}
+
+static int _read_4_write_last_stripe(struct ore_io_state *ios)
+{
+       struct ore_striping_info read_si;
+       struct __stripe_pages_2d *sp2d = ios->sp2d;
+       u64 offset;
+       u64 last_stripe_end;
+       unsigned bytes_in_stripe = ios->si.bytes_in_stripe;
+       unsigned c, p, min_p = sp2d->pages_in_unit, max_p = -1;
+
        offset = ios->offset + ios->length;
        if (offset % PAGE_SIZE)
                _add_to_r4w_last_page(ios, &offset);
@@ -527,15 +538,15 @@ read_last_stripe:
        c = _dev_order(ios->layout->group_width * ios->layout->mirrors_p1,
                       ios->layout->mirrors_p1, read_si.par_dev, read_si.dev);
 
-       BUG_ON(ios->si.first_stripe_start + bytes_in_stripe != last_stripe_end);
-       /* unaligned IO must be within a single stripe */
-
        if (min_p == sp2d->pages_in_unit) {
                /* Didn't do it yet */
                min_p = _sp2d_min_pg(sp2d);
                max_p = _sp2d_max_pg(sp2d);
        }
 
+       ORE_DBGMSG("offset=0x%llx stripe_end=0x%llx min_p=%d max_p=%d\n",
+                  offset, last_stripe_end, min_p, max_p);
+
        while (offset < last_stripe_end) {
                struct __1_page_stripe *_1ps = &sp2d->_1p_stripes[p];
 
@@ -568,6 +579,15 @@ read_last_stripe:
        }
 
 read_it:
+       return 0;
+}
+
+static int _read_4_write_execute(struct ore_io_state *ios)
+{
+       struct ore_io_state *ios_read;
+       unsigned i;
+       int ret;
+
        ios_read = ios->ios_read_4_write;
        if (!ios_read)
                return 0;
@@ -591,6 +611,8 @@ read_it:
        }
 
        _mark_read4write_pages_uptodate(ios_read, ret);
+       ore_put_io_state(ios_read);
+       ios->ios_read_4_write = NULL; /* Might need a reuse at last stripe */
        return 0;
 }
 
@@ -626,8 +648,11 @@ int _ore_add_parity_unit(struct ore_io_state *ios,
                        /* If first stripe, Read in all read4write pages
                         * (if needed) before we calculate the first parity.
                         */
-                       _read_4_write(ios);
+                       _read_4_write_first_stripe(ios);
                }
+               if (!cur_len) /* If last stripe r4w pages of last stripe */
+                       _read_4_write_last_stripe(ios);
+               _read_4_write_execute(ios);
 
                for (i = 0; i < num_pages; i++) {
                        pages[i] = _raid_page_alloc();
@@ -654,34 +679,14 @@ int _ore_add_parity_unit(struct ore_io_state *ios,
 
 int _ore_post_alloc_raid_stuff(struct ore_io_state *ios)
 {
-       struct ore_layout *layout = ios->layout;
-
        if (ios->parity_pages) {
+               struct ore_layout *layout = ios->layout;
                unsigned pages_in_unit = layout->stripe_unit / PAGE_SIZE;
-               unsigned stripe_size = ios->si.bytes_in_stripe;
-               u64 last_stripe, first_stripe;
 
                if (_sp2d_alloc(pages_in_unit, layout->group_width,
                                layout->parity, &ios->sp2d)) {
                        return -ENOMEM;
                }
-
-               /* Round io down to last full strip */
-               first_stripe = div_u64(ios->offset, stripe_size);
-               last_stripe = div_u64(ios->offset + ios->length, stripe_size);
-
-               /* If an IO spans more then a single stripe it must end at
-                * a stripe boundary. The reminder at the end is pushed into the
-                * next IO.
-                */
-               if (last_stripe != first_stripe) {
-                       ios->length = last_stripe * stripe_size - ios->offset;
-
-                       BUG_ON(!ios->length);
-                       ios->nr_pages = (ios->length + PAGE_SIZE - 1) /
-                                       PAGE_SIZE;
-                       ios->si.length = ios->length; /*make it consistent */
-               }
        }
        return 0;
 }
index b0201ca6e9c6e0b7837917420bb3dfe1dc06b88f..29ab099e3e0818a9d9c85f0449c8df2e4b9b5f70 100644 (file)
 #define dprintk(fmt, args...) do{}while(0)
 
 
-static int get_name(struct vfsmount *mnt, struct dentry *dentry, char *name,
-               struct dentry *child);
+static int get_name(const struct path *path, char *name, struct dentry *child);
 
 
 static int exportfs_get_name(struct vfsmount *mnt, struct dentry *dir,
                char *name, struct dentry *child)
 {
        const struct export_operations *nop = dir->d_sb->s_export_op;
+       struct path path = {.mnt = mnt, .dentry = dir};
 
        if (nop->get_name)
                return nop->get_name(dir, name, child);
        else
-               return get_name(mnt, dir, name, child);
+               return get_name(&path, name, child);
 }
 
 /*
@@ -44,13 +44,14 @@ find_acceptable_alias(struct dentry *result,
 {
        struct dentry *dentry, *toput = NULL;
        struct inode *inode;
+       struct hlist_node *p;
 
        if (acceptable(context, result))
                return result;
 
        inode = result->d_inode;
        spin_lock(&inode->i_lock);
-       list_for_each_entry(dentry, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
                dget(dentry);
                spin_unlock(&inode->i_lock);
                if (toput)
@@ -248,11 +249,10 @@ static int filldir_one(void * __buf, const char * name, int len,
  * calls readdir on the parent until it finds an entry with
  * the same inode number as the child, and returns that.
  */
-static int get_name(struct vfsmount *mnt, struct dentry *dentry,
-               char *name, struct dentry *child)
+static int get_name(const struct path *path, char *name, struct dentry *child)
 {
        const struct cred *cred = current_cred();
-       struct inode *dir = dentry->d_inode;
+       struct inode *dir = path->dentry->d_inode;
        int error;
        struct file *file;
        struct getdents_callback buffer;
@@ -266,7 +266,7 @@ static int get_name(struct vfsmount *mnt, struct dentry *dentry,
        /*
         * Open the directory ...
         */
-       file = dentry_open(dget(dentry), mntget(mnt), O_RDONLY, cred);
+       file = dentry_open(path, O_RDONLY, cred);
        error = PTR_ERR(file);
        if (IS_ERR(file))
                goto out;
index f663a67d7bf0b92503d0ff8561d2886d0e2796e3..73b0d9519836e1181b5b9227bd78ccead322a4d3 100644 (file)
@@ -41,8 +41,8 @@ static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
 {
        int err = ext2_add_link(dentry, inode);
        if (!err) {
-               d_instantiate(dentry, inode);
                unlock_new_inode(inode);
+               d_instantiate(dentry, inode);
                return 0;
        }
        inode_dec_link_count(inode);
@@ -55,7 +55,7 @@ static inline int ext2_add_nondir(struct dentry *dentry, struct inode *inode)
  * Methods themselves.
  */
 
-static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *ext2_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode * inode;
        ino_t ino;
@@ -94,7 +94,7 @@ struct dentry *ext2_get_parent(struct dentry *child)
  * If the create succeeds, we fill in the inode information
  * with d_instantiate(). 
  */
-static int ext2_create (struct inode * dir, struct dentry * dentry, umode_t mode, struct nameidata *nd)
+static int ext2_create (struct inode * dir, struct dentry * dentry, umode_t mode, bool excl)
 {
        struct inode *inode;
 
@@ -242,8 +242,8 @@ static int ext2_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
        if (err)
                goto out_fail;
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
 out:
        return err;
 
index b3621cb7ea31d6959943c7a2ec37e7ae2b362293..5df3d2d8169c25c1af4f45ce77a5f062517049de 100644 (file)
@@ -1184,6 +1184,12 @@ static int ext2_sync_fs(struct super_block *sb, int wait)
        struct ext2_sb_info *sbi = EXT2_SB(sb);
        struct ext2_super_block *es = EXT2_SB(sb)->s_es;
 
+       /*
+        * Write quota structures to quota file, sync_blockdev() will write
+        * them to disk later
+        */
+       dquot_writeback_dquots(sb, -1);
+
        spin_lock(&sbi->s_lock);
        if (es->s_state & cpu_to_le16(EXT2_VALID_FS)) {
                ext2_debug("setting valid to 0\n");
index 92490e9f85ca0fc61a23f8142c0bb197758b1f1f..c8fff930790d4eba76a0810c6e75fd7a85edce85 100644 (file)
@@ -300,10 +300,11 @@ loff_t ext3_dir_llseek(struct file *file, loff_t offset, int origin)
 {
        struct inode *inode = file->f_mapping->host;
        int dx_dir = is_dx_dir(inode);
+       loff_t htree_max = ext3_get_htree_eof(file);
 
        if (likely(dx_dir))
                return generic_file_llseek_size(file, offset, origin,
-                                               ext3_get_htree_eof(file));
+                                               htree_max, htree_max);
        else
                return generic_file_llseek(file, offset, origin);
 }
index eeb63dfc5d20320b0b7876022b342920294e7754..8f4fddac01a679456c8ef867d0a2e33f6592cbee 100644 (file)
@@ -1011,7 +1011,7 @@ errout:
        return NULL;
 }
 
-static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode * inode;
        struct ext3_dir_entry_2 * de;
@@ -1671,8 +1671,8 @@ static int ext3_add_nondir(handle_t *handle,
        int err = ext3_add_entry(handle, dentry, inode);
        if (!err) {
                ext3_mark_inode_dirty(handle, inode);
-               d_instantiate(dentry, inode);
                unlock_new_inode(inode);
+               d_instantiate(dentry, inode);
                return 0;
        }
        drop_nlink(inode);
@@ -1690,7 +1690,7 @@ static int ext3_add_nondir(handle_t *handle,
  * with d_instantiate().
  */
 static int ext3_create (struct inode * dir, struct dentry * dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        handle_t *handle;
        struct inode * inode;
@@ -1836,8 +1836,8 @@ out_clear_inode:
        if (err)
                goto out_clear_inode;
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
 out_stop:
        brelse(dir_block);
        ext3_journal_stop(handle);
index 8c3a44b7c375247f54ac0d0e61be3be99e0b1d6a..4ac304c55c5327703e19ed990c39a67460f1c4ad 100644 (file)
@@ -2526,6 +2526,11 @@ static int ext3_sync_fs(struct super_block *sb, int wait)
        tid_t target;
 
        trace_ext3_sync_fs(sb, wait);
+       /*
+        * Writeback quota in non-journalled quota case - journalled quota has
+        * no dirty dquots
+        */
+       dquot_writeback_dquots(sb, -1);
        if (journal_start_commit(EXT3_SB(sb)->s_journal, &target)) {
                if (wait)
                        log_wait_commit(EXT3_SB(sb)->s_journal, target);
index aa39e600d15954244aead38f7aed30513ce86d65..8e07d2a5a13952836c820c32419f340b148a8ce2 100644 (file)
@@ -324,74 +324,27 @@ static inline loff_t ext4_get_htree_eof(struct file *filp)
 
 
 /*
- * ext4_dir_llseek() based on generic_file_llseek() to handle both
- * non-htree and htree directories, where the "offset" is in terms
- * of the filename hash value instead of the byte offset.
+ * ext4_dir_llseek() calls generic_file_llseek_size to handle htree
+ * directories, where the "offset" is in terms of the filename hash
+ * value instead of the byte offset.
  *
- * NOTE: offsets obtained *before* ext4_set_inode_flag(dir, EXT4_INODE_INDEX)
- *       will be invalid once the directory was converted into a dx directory
+ * Because we may return a 64-bit hash that is well beyond offset limits,
+ * we need to pass the max hash as the maximum allowable offset in
+ * the htree directory case.
+ *
+ * For non-htree, ext4_llseek already chooses the proper max offset.
  */
 loff_t ext4_dir_llseek(struct file *file, loff_t offset, int origin)
 {
        struct inode *inode = file->f_mapping->host;
-       loff_t ret = -EINVAL;
        int dx_dir = is_dx_dir(inode);
+       loff_t htree_max = ext4_get_htree_eof(file);
 
-       mutex_lock(&inode->i_mutex);
-
-       /* NOTE: relative offsets with dx directories might not work
-        *       as expected, as it is difficult to figure out the
-        *       correct offset between dx hashes */
-
-       switch (origin) {
-       case SEEK_END:
-               if (unlikely(offset > 0))
-                       goto out_err; /* not supported for directories */
-
-               /* so only negative offsets are left, does that have a
-                * meaning for directories at all? */
-               if (dx_dir)
-                       offset += ext4_get_htree_eof(file);
-               else
-                       offset += inode->i_size;
-               break;
-       case SEEK_CUR:
-               /*
-                * Here we special-case the lseek(fd, 0, SEEK_CUR)
-                * position-querying operation.  Avoid rewriting the "same"
-                * f_pos value back to the file because a concurrent read(),
-                * write() or lseek() might have altered it
-                */
-               if (offset == 0) {
-                       offset = file->f_pos;
-                       goto out_ok;
-               }
-
-               offset += file->f_pos;
-               break;
-       }
-
-       if (unlikely(offset < 0))
-               goto out_err;
-
-       if (!dx_dir) {
-               if (offset > inode->i_sb->s_maxbytes)
-                       goto out_err;
-       } else if (offset > ext4_get_htree_eof(file))
-               goto out_err;
-
-       /* Special lock needed here? */
-       if (offset != file->f_pos) {
-               file->f_pos = offset;
-               file->f_version = 0;
-       }
-
-out_ok:
-       ret = offset;
-out_err:
-       mutex_unlock(&inode->i_mutex);
-
-       return ret;
+       if (likely(dx_dir))
+               return generic_file_llseek_size(file, offset, origin,
+                                                   htree_max, htree_max);
+       else
+               return ext4_llseek(file, offset, origin);
 }
 
 /*
index 8c7642a00054fd1ddf649e733e4b6efb5a0eb14b..782eecb57e43a33ed5d6485f9490140ae6d88255 100644 (file)
@@ -211,9 +211,9 @@ static int ext4_file_open(struct inode * inode, struct file * filp)
 }
 
 /*
- * ext4_llseek() copied from generic_file_llseek() to handle both
- * block-mapped and extent-mapped maxbytes values. This should
- * otherwise be identical with generic_file_llseek().
+ * ext4_llseek() handles both block-mapped and extent-mapped maxbytes values
+ * by calling generic_file_llseek_size() with the appropriate maxbytes
+ * value for each.
  */
 loff_t ext4_llseek(struct file *file, loff_t offset, int origin)
 {
@@ -225,7 +225,8 @@ loff_t ext4_llseek(struct file *file, loff_t offset, int origin)
        else
                maxbytes = inode->i_sb->s_maxbytes;
 
-       return generic_file_llseek_size(file, offset, origin, maxbytes);
+       return generic_file_llseek_size(file, offset, origin,
+                                       maxbytes, i_size_read(inode));
 }
 
 const struct file_operations ext4_file_operations = {
index bb6c7d8113134ee7796a141065d9ed602650f10e..2a1dcea4f12ef91fd94a154f0d1cad8816af7ed8 100644 (file)
@@ -135,14 +135,7 @@ static int ext4_sync_parent(struct inode *inode)
        inode = igrab(inode);
        while (ext4_test_inode_state(inode, EXT4_STATE_NEWENTRY)) {
                ext4_clear_inode_state(inode, EXT4_STATE_NEWENTRY);
-               dentry = NULL;
-               spin_lock(&inode->i_lock);
-               if (!list_empty(&inode->i_dentry)) {
-                       dentry = list_first_entry(&inode->i_dentry,
-                                                 struct dentry, d_alias);
-                       dget(dentry);
-               }
-               spin_unlock(&inode->i_lock);
+               dentry = d_find_any_alias(inode);
                if (!dentry)
                        break;
                next = igrab(dentry->d_parent->d_inode);
@@ -232,7 +225,7 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
 
        if (!journal) {
                ret = __sync_inode(inode, datasync);
-               if (!ret && !list_empty(&inode->i_dentry))
+               if (!ret && !hlist_empty(&inode->i_dentry))
                        ret = ext4_sync_parent(inode);
                goto out;
        }
index 6ec6f9ee2fec9099c87f523bbf69614eed789050..7f7dad7876035e474b3c9ad7054344f6f6e7d045 100644 (file)
@@ -389,7 +389,7 @@ group_add_out:
                if (err)
                        return err;
 
-               err = mnt_want_write(filp->f_path.mnt);
+               err = mnt_want_write_file(filp);
                if (err)
                        goto resizefs_out;
 
@@ -401,7 +401,7 @@ group_add_out:
                }
                if (err == 0)
                        err = err2;
-               mnt_drop_write(filp->f_path.mnt);
+               mnt_drop_write_file(filp);
 resizefs_out:
                ext4_resize_end(sb);
                return err;
index 5845cd97bf8b094b0fc01082279e8d65ee73f241..d0d3f0e87f997ce589f64321dec35e103c98d2d7 100644 (file)
@@ -1312,7 +1312,7 @@ errout:
        return NULL;
 }
 
-static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode;
        struct ext4_dir_entry_2 *de;
@@ -2072,8 +2072,8 @@ static int ext4_add_nondir(handle_t *handle,
        int err = ext4_add_entry(handle, dentry, inode);
        if (!err) {
                ext4_mark_inode_dirty(handle, inode);
-               d_instantiate(dentry, inode);
                unlock_new_inode(inode);
+               d_instantiate(dentry, inode);
                return 0;
        }
        drop_nlink(inode);
@@ -2091,7 +2091,7 @@ static int ext4_add_nondir(handle_t *handle,
  * with d_instantiate().
  */
 static int ext4_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                      struct nameidata *nd)
+                      bool excl)
 {
        handle_t *handle;
        struct inode *inode;
@@ -2249,8 +2249,8 @@ out_clear_inode:
        err = ext4_mark_inode_dirty(handle, dir);
        if (err)
                goto out_clear_inode;
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
 out_stop:
        brelse(dir_block);
        ext4_journal_stop(handle);
index eb7aa3e4ef05caf136f24e0565a28e6d1e0a1539..d8759401ecae835f696b8f648f4d2ff9883da8c9 100644 (file)
@@ -4325,6 +4325,11 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
 
        trace_ext4_sync_fs(sb, wait);
        flush_workqueue(sbi->dio_unwritten_wq);
+       /*
+        * Writeback quota in non-journalled quota case - journalled quota has
+        * no dirty dquots
+        */
+       dquot_writeback_dquots(sb, -1);
        if (jbd2_journal_start_commit(sbi->s_journal, &target)) {
                if (wait)
                        jbd2_log_wait_commit(sbi->s_journal, target);
index c5938c9084b9796794626d4dc08bd42c0030b283..70d993a9380572bac393a45f3dcb9896db404f9e 100644 (file)
@@ -201,7 +201,7 @@ static const struct dentry_operations msdos_dentry_operations = {
 
 /***** Get inode using directory and name */
 static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        struct super_block *sb = dir->i_sb;
        struct fat_slot_info sinfo;
@@ -265,7 +265,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name,
 
 /***** Create a file */
 static int msdos_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                       struct nameidata *nd)
+                       bool excl)
 {
        struct super_block *sb = dir->i_sb;
        struct inode *inode = NULL;
index 98ae804f5273df49ba857f8853d83ba7503c4255..6cc480652433b66a52c42cbcd3bde3f19e348f30 100644 (file)
@@ -41,9 +41,9 @@ static int vfat_revalidate_shortname(struct dentry *dentry)
        return ret;
 }
 
-static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int vfat_revalidate(struct dentry *dentry, unsigned int flags)
 {
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        /* This is not negative dentry. Always valid. */
@@ -52,9 +52,9 @@ static int vfat_revalidate(struct dentry *dentry, struct nameidata *nd)
        return vfat_revalidate_shortname(dentry);
 }
 
-static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
+static int vfat_revalidate_ci(struct dentry *dentry, unsigned int flags)
 {
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        /*
@@ -74,7 +74,7 @@ static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
         * This may be nfsd (or something), anyway, we can't see the
         * intent of this. So, since this can be for creation, drop it.
         */
-       if (!nd)
+       if (!flags)
                return 0;
 
        /*
@@ -82,7 +82,7 @@ static int vfat_revalidate_ci(struct dentry *dentry, struct nameidata *nd)
         * case sensitive name which is specified by user if this is
         * for creation.
         */
-       if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
+       if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
                return 0;
 
        return vfat_revalidate_shortname(dentry);
@@ -714,7 +714,7 @@ static int vfat_d_anon_disconn(struct dentry *dentry)
 }
 
 static struct dentry *vfat_lookup(struct inode *dir, struct dentry *dentry,
-                                 struct nameidata *nd)
+                                 unsigned int flags)
 {
        struct super_block *sb = dir->i_sb;
        struct fat_slot_info sinfo;
@@ -772,7 +772,7 @@ error:
 }
 
 static int vfat_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                      struct nameidata *nd)
+                      bool excl)
 {
        struct super_block *sb = dir->i_sb;
        struct inode *inode;
index a305d9e2d1b2aac05dcd456bdd23885652272439..b3fc4d67a26b31243474520bfbcddacce3733ded 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/lglock.h>
 #include <linux/percpu_counter.h>
 #include <linux/percpu.h>
+#include <linux/hardirq.h>
+#include <linux/task_work.h>
 #include <linux/ima.h>
 
 #include <linux/atomic.h>
@@ -251,7 +253,6 @@ static void __fput(struct file *file)
        }
        fops_put(file->f_op);
        put_pid(file->f_owner.pid);
-       file_sb_list_del(file);
        if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ)
                i_readcount_dec(inode);
        if (file->f_mode & FMODE_WRITE)
@@ -263,10 +264,77 @@ static void __fput(struct file *file)
        mntput(mnt);
 }
 
+static DEFINE_SPINLOCK(delayed_fput_lock);
+static LIST_HEAD(delayed_fput_list);
+static void delayed_fput(struct work_struct *unused)
+{
+       LIST_HEAD(head);
+       spin_lock_irq(&delayed_fput_lock);
+       list_splice_init(&delayed_fput_list, &head);
+       spin_unlock_irq(&delayed_fput_lock);
+       while (!list_empty(&head)) {
+               struct file *f = list_first_entry(&head, struct file, f_u.fu_list);
+               list_del_init(&f->f_u.fu_list);
+               __fput(f);
+       }
+}
+
+static void ____fput(struct callback_head *work)
+{
+       __fput(container_of(work, struct file, f_u.fu_rcuhead));
+}
+
+/*
+ * If kernel thread really needs to have the final fput() it has done
+ * to complete, call this.  The only user right now is the boot - we
+ * *do* need to make sure our writes to binaries on initramfs has
+ * not left us with opened struct file waiting for __fput() - execve()
+ * won't work without that.  Please, don't add more callers without
+ * very good reasons; in particular, never call that with locks
+ * held and never call that from a thread that might need to do
+ * some work on any kind of umount.
+ */
+void flush_delayed_fput(void)
+{
+       delayed_fput(NULL);
+}
+
+static DECLARE_WORK(delayed_fput_work, delayed_fput);
+
 void fput(struct file *file)
 {
-       if (atomic_long_dec_and_test(&file->f_count))
+       if (atomic_long_dec_and_test(&file->f_count)) {
+               struct task_struct *task = current;
+               file_sb_list_del(file);
+               if (unlikely(in_interrupt() || task->flags & PF_KTHREAD)) {
+                       unsigned long flags;
+                       spin_lock_irqsave(&delayed_fput_lock, flags);
+                       list_add(&file->f_u.fu_list, &delayed_fput_list);
+                       schedule_work(&delayed_fput_work);
+                       spin_unlock_irqrestore(&delayed_fput_lock, flags);
+                       return;
+               }
+               init_task_work(&file->f_u.fu_rcuhead, ____fput);
+               task_work_add(task, &file->f_u.fu_rcuhead, true);
+       }
+}
+
+/*
+ * synchronous analog of fput(); for kernel threads that might be needed
+ * in some umount() (and thus can't use flush_delayed_fput() without
+ * risking deadlocks), need to wait for completion of __fput() and know
+ * for this specific struct file it won't involve anything that would
+ * need them.  Use only if you really need it - at the very least,
+ * don't blindly convert fput() by kernel thread to that.
+ */
+void __fput_sync(struct file *file)
+{
+       if (atomic_long_dec_and_test(&file->f_count)) {
+               struct task_struct *task = current;
+               file_sb_list_del(file);
+               BUG_ON(!(task->flags & PF_KTHREAD));
                __fput(file);
+       }
 }
 
 EXPORT_SYMBOL(fput);
@@ -483,10 +551,8 @@ void mark_files_ro(struct super_block *sb)
 {
        struct file *f;
 
-retry:
        lg_global_lock(&files_lglock);
        do_file_list_for_each_entry(sb, f) {
-               struct vfsmount *mnt;
                if (!S_ISREG(f->f_path.dentry->d_inode->i_mode))
                       continue;
                if (!file_count(f))
@@ -499,12 +565,7 @@ retry:
                if (file_check_writeable(f) != 0)
                        continue;
                file_release_write(f);
-               mnt = mntget(f->f_path.mnt);
-               /* This can sleep, so we can't hold the spinlock. */
-               lg_global_unlock(&files_lglock);
-               mnt_drop_write(mnt);
-               mntput(mnt);
-               goto retry;
+               mnt_drop_write_file(f);
        } while_file_list_for_each_entry;
        lg_global_unlock(&files_lglock);
 }
index 3360f1e678ad1c0eef52994f4b44342854ef621e..bd447e88f208d2671ed5d13a054ad39cffc51e7b 100644 (file)
@@ -48,7 +48,7 @@
 #define VXFS_BLOCK_PER_PAGE(sbp)  ((PAGE_CACHE_SIZE / (sbp)->s_blocksize))
 
 
-static struct dentry * vxfs_lookup(struct inode *, struct dentry *, struct nameidata *);
+static struct dentry * vxfs_lookup(struct inode *, struct dentry *, unsigned int);
 static int             vxfs_readdir(struct file *, void *, filldir_t);
 
 const struct inode_operations vxfs_dir_inode_ops = {
@@ -203,7 +203,7 @@ vxfs_inode_by_name(struct inode *dip, struct dentry *dp)
  *   in the return pointer.
  */
 static struct dentry *
-vxfs_lookup(struct inode *dip, struct dentry *dp, struct nameidata *nd)
+vxfs_lookup(struct inode *dip, struct dentry *dp, unsigned int flags)
 {
        struct inode            *ip = NULL;
        ino_t                   ino;
index 41a3ccff18d87bdfc3f65148e2f39f8067f3a8ce..8f660dd6137a1105ba648e1a1412ffc5900c1233 100644 (file)
@@ -1315,6 +1315,8 @@ void writeback_inodes_sb_nr(struct super_block *sb,
                .reason                 = reason,
        };
 
+       if (sb->s_bdi == &noop_backing_dev_info)
+               return;
        WARN_ON(!rwsem_is_locked(&sb->s_umount));
        bdi_queue_work(sb->s_bdi, &work);
        wait_for_completion(&done);
@@ -1398,6 +1400,9 @@ void sync_inodes_sb(struct super_block *sb)
                .reason         = WB_REASON_SYNC,
        };
 
+       /* Nothing to do? */
+       if (sb->s_bdi == &noop_backing_dev_info)
+               return;
        WARN_ON(!rwsem_is_locked(&sb->s_umount));
 
        bdi_queue_work(sb->s_bdi, &work);
index e159e682ad4c68b16b82ef7eeafa889c05877580..5df4775fea03638f14d1408cfe16408e8a0ed6d7 100644 (file)
@@ -6,18 +6,6 @@
 #include <linux/fs_struct.h>
 #include "internal.h"
 
-static inline void path_get_longterm(struct path *path)
-{
-       path_get(path);
-       mnt_make_longterm(path->mnt);
-}
-
-static inline void path_put_longterm(struct path *path)
-{
-       mnt_make_shortterm(path->mnt);
-       path_put(path);
-}
-
 /*
  * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
  * It can block.
@@ -26,7 +14,7 @@ void set_fs_root(struct fs_struct *fs, struct path *path)
 {
        struct path old_root;
 
-       path_get_longterm(path);
+       path_get(path);
        spin_lock(&fs->lock);
        write_seqcount_begin(&fs->seq);
        old_root = fs->root;
@@ -34,7 +22,7 @@ void set_fs_root(struct fs_struct *fs, struct path *path)
        write_seqcount_end(&fs->seq);
        spin_unlock(&fs->lock);
        if (old_root.dentry)
-               path_put_longterm(&old_root);
+               path_put(&old_root);
 }
 
 /*
@@ -45,7 +33,7 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path)
 {
        struct path old_pwd;
 
-       path_get_longterm(path);
+       path_get(path);
        spin_lock(&fs->lock);
        write_seqcount_begin(&fs->seq);
        old_pwd = fs->pwd;
@@ -54,7 +42,7 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path)
        spin_unlock(&fs->lock);
 
        if (old_pwd.dentry)
-               path_put_longterm(&old_pwd);
+               path_put(&old_pwd);
 }
 
 static inline int replace_path(struct path *p, const struct path *old, const struct path *new)
@@ -84,7 +72,7 @@ void chroot_fs_refs(struct path *old_root, struct path *new_root)
                        write_seqcount_end(&fs->seq);
                        while (hits--) {
                                count++;
-                               path_get_longterm(new_root);
+                               path_get(new_root);
                        }
                        spin_unlock(&fs->lock);
                }
@@ -92,13 +80,13 @@ void chroot_fs_refs(struct path *old_root, struct path *new_root)
        } while_each_thread(g, p);
        read_unlock(&tasklist_lock);
        while (count--)
-               path_put_longterm(old_root);
+               path_put(old_root);
 }
 
 void free_fs_struct(struct fs_struct *fs)
 {
-       path_put_longterm(&fs->root);
-       path_put_longterm(&fs->pwd);
+       path_put(&fs->root);
+       path_put(&fs->pwd);
        kmem_cache_free(fs_cachep, fs);
 }
 
@@ -132,9 +120,9 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old)
 
                spin_lock(&old->lock);
                fs->root = old->root;
-               path_get_longterm(&fs->root);
+               path_get(&fs->root);
                fs->pwd = old->pwd;
-               path_get_longterm(&fs->pwd);
+               path_get(&fs->pwd);
                spin_unlock(&old->lock);
        }
        return fs;
index 334e0b18a014c72bf78583f76a6c3b02f9058181..8964cf3999b2bb561ec71d93914170529f72977a 100644 (file)
@@ -154,7 +154,7 @@ u64 fuse_get_attr_version(struct fuse_conn *fc)
  * the lookup once more.  If the lookup results in the same inode,
  * then refresh the attributes, timeouts and mark the dentry valid.
  */
-static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
+static int fuse_dentry_revalidate(struct dentry *entry, unsigned int flags)
 {
        struct inode *inode;
 
@@ -174,7 +174,7 @@ static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
                if (!inode)
                        return 0;
 
-               if (nd && (nd->flags & LOOKUP_RCU))
+               if (flags & LOOKUP_RCU)
                        return -ECHILD;
 
                fc = get_fuse_conn(inode);
@@ -249,7 +249,7 @@ static struct dentry *fuse_d_add_directory(struct dentry *entry,
                /* This tries to shrink the subtree below alias */
                fuse_invalidate_entry(alias);
                dput(alias);
-               if (!list_empty(&inode->i_dentry))
+               if (!hlist_empty(&inode->i_dentry))
                        return ERR_PTR(-EBUSY);
        } else {
                dput(alias);
@@ -316,7 +316,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, struct qstr *name,
 }
 
 static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
-                                 struct nameidata *nd)
+                                 unsigned int flags)
 {
        int err;
        struct fuse_entry_out outarg;
@@ -370,7 +370,8 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
  * 'mknod' + 'open' requests.
  */
 static int fuse_create_open(struct inode *dir, struct dentry *entry,
-                           umode_t mode, struct nameidata *nd)
+                           struct file *file, unsigned flags,
+                           umode_t mode, int *opened)
 {
        int err;
        struct inode *inode;
@@ -381,15 +382,11 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
        struct fuse_open_out outopen;
        struct fuse_entry_out outentry;
        struct fuse_file *ff;
-       struct file *file;
-       int flags = nd->intent.open.flags;
-
-       if (fc->no_create)
-               return -ENOSYS;
 
        forget = fuse_alloc_forget();
+       err = -ENOMEM;
        if (!forget)
-               return -ENOMEM;
+               goto out_err;
 
        req = fuse_get_req(fc);
        err = PTR_ERR(req);
@@ -428,11 +425,8 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
        req->out.args[1].value = &outopen;
        fuse_request_send(fc, req);
        err = req->out.h.error;
-       if (err) {
-               if (err == -ENOSYS)
-                       fc->no_create = 1;
+       if (err)
                goto out_free_ff;
-       }
 
        err = -EIO;
        if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
@@ -448,28 +442,74 @@ static int fuse_create_open(struct inode *dir, struct dentry *entry,
                flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
                fuse_sync_release(ff, flags);
                fuse_queue_forget(fc, forget, outentry.nodeid, 1);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto out_err;
        }
        kfree(forget);
        d_instantiate(entry, inode);
        fuse_change_entry_timeout(entry, &outentry);
        fuse_invalidate_attr(dir);
-       file = lookup_instantiate_filp(nd, entry, generic_file_open);
-       if (IS_ERR(file)) {
+       err = finish_open(file, entry, generic_file_open, opened);
+       if (err) {
                fuse_sync_release(ff, flags);
-               return PTR_ERR(file);
+       } else {
+               file->private_data = fuse_file_get(ff);
+               fuse_finish_open(inode, file);
        }
-       file->private_data = fuse_file_get(ff);
-       fuse_finish_open(inode, file);
-       return 0;
+       return err;
 
- out_free_ff:
+out_free_ff:
        fuse_file_free(ff);
- out_put_request:
+out_put_request:
        fuse_put_request(fc, req);
- out_put_forget_req:
+out_put_forget_req:
        kfree(forget);
+out_err:
+       return err;
+}
+
+static int fuse_mknod(struct inode *, struct dentry *, umode_t, dev_t);
+static int fuse_atomic_open(struct inode *dir, struct dentry *entry,
+                           struct file *file, unsigned flags,
+                           umode_t mode, int *opened)
+{
+       int err;
+       struct fuse_conn *fc = get_fuse_conn(dir);
+       struct dentry *res = NULL;
+
+       if (d_unhashed(entry)) {
+               res = fuse_lookup(dir, entry, 0);
+               if (IS_ERR(res))
+                       return PTR_ERR(res);
+
+               if (res)
+                       entry = res;
+       }
+
+       if (!(flags & O_CREAT) || entry->d_inode)
+               goto no_open;
+
+       /* Only creates */
+       *opened |= FILE_CREATED;
+
+       if (fc->no_create)
+               goto mknod;
+
+       err = fuse_create_open(dir, entry, file, flags, mode, opened);
+       if (err == -ENOSYS) {
+               fc->no_create = 1;
+               goto mknod;
+       }
+out_dput:
+       dput(res);
        return err;
+
+mknod:
+       err = fuse_mknod(dir, entry, mode, 0);
+       if (err)
+               goto out_dput;
+no_open:
+       return finish_no_open(file, res);
 }
 
 /*
@@ -571,14 +611,8 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, umode_t mode,
 }
 
 static int fuse_create(struct inode *dir, struct dentry *entry, umode_t mode,
-                      struct nameidata *nd)
+                      bool excl)
 {
-       if (nd) {
-               int err = fuse_create_open(dir, entry, mode, nd);
-               if (err != -ENOSYS)
-                       return err;
-               /* Fall back on mknod */
-       }
        return fuse_mknod(dir, entry, mode, 0);
 }
 
@@ -1646,6 +1680,7 @@ static const struct inode_operations fuse_dir_inode_operations = {
        .link           = fuse_link,
        .setattr        = fuse_setattr,
        .create         = fuse_create,
+       .atomic_open    = fuse_atomic_open,
        .mknod          = fuse_mknod,
        .permission     = fuse_permission,
        .getattr        = fuse_getattr,
index 0da8da2c991d30a906f954ce021f5373092298f9..4fddb3c22d258ca6da35b4e743ec80fc20ee2e08 100644 (file)
@@ -25,7 +25,7 @@
 /**
  * gfs2_drevalidate - Check directory lookup consistency
  * @dentry: the mapping to check
- * @nd:
+ * @flags: lookup flags
  *
  * Check to make sure the lookup necessary to arrive at this inode from its
  * parent is still good.
@@ -33,7 +33,7 @@
  * Returns: 1 if the dentry is ok, 0 if it isn't
  */
 
-static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
+static int gfs2_drevalidate(struct dentry *dentry, unsigned int flags)
 {
        struct dentry *parent;
        struct gfs2_sbd *sdp;
@@ -44,7 +44,7 @@ static int gfs2_drevalidate(struct dentry *dentry, struct nameidata *nd)
        int error;
        int had_lock = 0;
 
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        parent = dget_parent(dentry);
index a9ba2444e077ac145f23c25161038a0f8ac2f468..867674785fcf04909ae03cd5d6f95752fcaeee6d 100644 (file)
@@ -755,11 +755,8 @@ fail:
  */
 
 static int gfs2_create(struct inode *dir, struct dentry *dentry,
-                      umode_t mode, struct nameidata *nd)
+                      umode_t mode, bool excl)
 {
-       int excl = 0;
-       if (nd && (nd->flags & LOOKUP_EXCL))
-               excl = 1;
        return gfs2_create_inode(dir, dentry, S_IFREG | mode, 0, NULL, 0, excl);
 }
 
@@ -775,7 +772,7 @@ static int gfs2_create(struct inode *dir, struct dentry *dentry,
  */
 
 static struct dentry *gfs2_lookup(struct inode *dir, struct dentry *dentry,
-                                 struct nameidata *nd)
+                                 unsigned int flags)
 {
        struct inode *inode = gfs2_lookupi(dir, &dentry->d_name, 0);
        if (inode && !IS_ERR(inode)) {
index b8c250fc4922e8dd501a0c12c1481f7d1a32e0d8..6c906078f657024c6f17c663b413a97de643e8b0 100644 (file)
@@ -1286,7 +1286,7 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,
                error = -EBUSY;
                goto error_bdev;
        }
-       s = sget(fs_type, test_gfs2_super, set_gfs2_super, bdev);
+       s = sget(fs_type, test_gfs2_super, set_gfs2_super, flags, bdev);
        mutex_unlock(&bdev->bd_fsfreeze_mutex);
        error = PTR_ERR(s);
        if (IS_ERR(s))
@@ -1316,7 +1316,6 @@ static struct dentry *gfs2_mount(struct file_system_type *fs_type, int flags,
        } else {
                char b[BDEVNAME_SIZE];
 
-               s->s_flags = flags;
                s->s_mode = mode;
                strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
                sb_set_blocksize(s, block_size(bdev));
@@ -1360,7 +1359,7 @@ static struct dentry *gfs2_mount_meta(struct file_system_type *fs_type,
                       dev_name, error);
                return ERR_PTR(error);
        }
-       s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super,
+       s = sget(&gfs2_fs_type, test_gfs2_super, set_meta_super, flags,
                 path.dentry->d_inode->i_sb->s_bdev);
        path_put(&path);
        if (IS_ERR(s)) {
index b97178e7d397d3e767694622779ace8716c4d6f3..27b5cc7d688166d4e9a74525d6e1ad00133fe94f 100644 (file)
@@ -1108,7 +1108,7 @@ void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
        }
 }
 
-int gfs2_quota_sync(struct super_block *sb, int type, int wait)
+int gfs2_quota_sync(struct super_block *sb, int type)
 {
        struct gfs2_sbd *sdp = sb->s_fs_info;
        struct gfs2_quota_data **qda;
@@ -1154,7 +1154,7 @@ int gfs2_quota_sync(struct super_block *sb, int type, int wait)
 
 static int gfs2_quota_sync_timeo(struct super_block *sb, int type)
 {
-       return gfs2_quota_sync(sb, type, 0);
+       return gfs2_quota_sync(sb, type);
 }
 
 int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id)
index 90bf1c302a983df6c74191f5c2341b8cf5c70f69..f25d98b87904aa7ab315c8668b90b556c67dcf90 100644 (file)
@@ -26,7 +26,7 @@ extern int gfs2_quota_check(struct gfs2_inode *ip, u32 uid, u32 gid);
 extern void gfs2_quota_change(struct gfs2_inode *ip, s64 change,
                              u32 uid, u32 gid);
 
-extern int gfs2_quota_sync(struct super_block *sb, int type, int wait);
+extern int gfs2_quota_sync(struct super_block *sb, int type);
 extern int gfs2_quota_refresh(struct gfs2_sbd *sdp, int user, u32 id);
 
 extern int gfs2_quota_init(struct gfs2_sbd *sdp);
index 713e621c240b9e6989ea50b7fa0a0c4f3b5f111d..f3d6bbfb32c5308e9893fe6c689bf1935af2bc50 100644 (file)
@@ -838,7 +838,7 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp)
        int error;
 
        flush_workqueue(gfs2_delete_workqueue);
-       gfs2_quota_sync(sdp->sd_vfs, 0, 1);
+       gfs2_quota_sync(sdp->sd_vfs, 0);
        gfs2_statfs_sync(sdp->sd_vfs, 0);
 
        error = gfs2_glock_nq_init(sdp->sd_trans_gl, LM_ST_SHARED, GL_NOCACHE,
@@ -952,6 +952,8 @@ restart:
 static int gfs2_sync_fs(struct super_block *sb, int wait)
 {
        struct gfs2_sbd *sdp = sb->s_fs_info;
+
+       gfs2_quota_sync(sb, -1);
        if (wait && sdp)
                gfs2_log_flush(sdp, NULL);
        return 0;
index 9c2592b1d5ff74ab0e5c2f800b0d0e4508119021..73ecc34c434280ec0c7343ca0f801ea08c784f6e 100644 (file)
@@ -168,7 +168,7 @@ static ssize_t quota_sync_store(struct gfs2_sbd *sdp, const char *buf,
        if (simple_strtol(buf, NULL, 0) != 1)
                return -EINVAL;
 
-       gfs2_quota_sync(sdp->sd_vfs, 0, 1);
+       gfs2_quota_sync(sdp->sd_vfs, 0);
        return len;
 }
 
index 62fc14ea4b7387549d2f7017345070864a0d182d..422dde2ec0a1ecc99f5d129136e044e5ee0a1f1b 100644 (file)
@@ -18,7 +18,7 @@
  * hfs_lookup()
  */
 static struct dentry *hfs_lookup(struct inode *dir, struct dentry *dentry,
-                                struct nameidata *nd)
+                                unsigned int flags)
 {
        hfs_cat_rec rec;
        struct hfs_find_data fd;
@@ -187,7 +187,7 @@ static int hfs_dir_release(struct inode *inode, struct file *file)
  * the directory and the name (and its length) of the new file.
  */
 static int hfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                     struct nameidata *nd)
+                     bool excl)
 {
        struct inode *inode;
        int res;
index 2c16316d291794a875b5afc36908829cfe1f5ce5..a67955a0c36f621e8ca935c50f769a4b5023a1e4 100644 (file)
@@ -432,7 +432,7 @@ out:
                if (inode->i_ino < HFS_FIRSTUSER_CNID)
                        set_bit(HFS_FLG_ALT_MDB_DIRTY, &HFS_SB(sb)->flags);
                set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
-               sb->s_dirt = 1;
+               hfs_mark_mdb_dirty(sb);
        }
        return res;
 
index 1bf967c6bfdc6cb1b129887135f47608652b6311..8275175acf6eaaf8606b940d6f05c96d7ae08a5c 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/mutex.h>
 #include <linux/buffer_head.h>
 #include <linux/fs.h>
+#include <linux/workqueue.h>
 
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
@@ -137,16 +138,15 @@ struct hfs_sb_info {
        gid_t s_gid;                            /* The gid of all files */
 
        int session, part;
-
        struct nls_table *nls_io, *nls_disk;
-
        struct mutex bitmap_lock;
-
        unsigned long flags;
-
        u16 blockoffset;
-
        int fs_div;
+       struct super_block *sb;
+       int work_queued;                /* non-zero delayed work is queued */
+       struct delayed_work mdb_work;   /* MDB flush delayed work */
+       spinlock_t work_lock;           /* protects mdb_work and work_queued */
 };
 
 #define HFS_FLG_BITMAP_DIRTY   0
@@ -226,6 +226,9 @@ extern int hfs_compare_dentry(const struct dentry *parent,
 extern void hfs_asc2mac(struct super_block *, struct hfs_name *, struct qstr *);
 extern int hfs_mac2asc(struct super_block *, char *, const struct hfs_name *);
 
+/* super.c */
+extern void hfs_mark_mdb_dirty(struct super_block *sb);
+
 extern struct timezone sys_tz;
 
 /*
@@ -253,7 +256,7 @@ static inline const char *hfs_mdb_name(struct super_block *sb)
 static inline void hfs_bitmap_dirty(struct super_block *sb)
 {
        set_bit(HFS_FLG_BITMAP_DIRTY, &HFS_SB(sb)->flags);
-       sb->s_dirt = 1;
+       hfs_mark_mdb_dirty(sb);
 }
 
 #define sb_bread512(sb, sec, data) ({                  \
index 761ec06354b4719df8731e098caaca14bbcf8127..ee1bc55677f1486c6f27a2549d8f6ce60c1581de 100644 (file)
@@ -220,7 +220,7 @@ struct inode *hfs_new_inode(struct inode *dir, struct qstr *name, umode_t mode)
        insert_inode_hash(inode);
        mark_inode_dirty(inode);
        set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
-       sb->s_dirt = 1;
+       hfs_mark_mdb_dirty(sb);
 
        return inode;
 }
@@ -235,7 +235,7 @@ void hfs_delete_inode(struct inode *inode)
                if (HFS_I(inode)->cat_key.ParID == cpu_to_be32(HFS_ROOT_CNID))
                        HFS_SB(sb)->root_dirs--;
                set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
-               sb->s_dirt = 1;
+               hfs_mark_mdb_dirty(sb);
                return;
        }
        HFS_SB(sb)->file_count--;
@@ -248,7 +248,7 @@ void hfs_delete_inode(struct inode *inode)
                }
        }
        set_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags);
-       sb->s_dirt = 1;
+       hfs_mark_mdb_dirty(sb);
 }
 
 void hfs_inode_read_fork(struct inode *inode, struct hfs_extent *ext,
@@ -489,7 +489,7 @@ out:
 }
 
 static struct dentry *hfs_file_lookup(struct inode *dir, struct dentry *dentry,
-                                     struct nameidata *nd)
+                                     unsigned int flags)
 {
        struct inode *inode = NULL;
        hfs_cat_rec rec;
@@ -644,13 +644,7 @@ static int hfs_file_fsync(struct file *filp, loff_t start, loff_t end,
 
        /* sync the superblock to buffers */
        sb = inode->i_sb;
-       if (sb->s_dirt) {
-               lock_super(sb);
-               sb->s_dirt = 0;
-               if (!(sb->s_flags & MS_RDONLY))
-                       hfs_mdb_commit(sb);
-               unlock_super(sb);
-       }
+       flush_delayed_work_sync(&HFS_SB(sb)->mdb_work);
        /* .. finally sync the buffers to disk */
        err = sync_blockdev(sb->s_bdev);
        if (!ret)
index 1563d5ce57643e23ac08e3a7db02e0b336603c60..5fd51a5833ffb91facba871b74589bf8b9a6c087 100644 (file)
@@ -260,6 +260,10 @@ void hfs_mdb_commit(struct super_block *sb)
 {
        struct hfs_mdb *mdb = HFS_SB(sb)->mdb;
 
+       if (sb->s_flags & MS_RDONLY)
+               return;
+
+       lock_buffer(HFS_SB(sb)->mdb_bh);
        if (test_and_clear_bit(HFS_FLG_MDB_DIRTY, &HFS_SB(sb)->flags)) {
                /* These parameters may have been modified, so write them back */
                mdb->drLsMod = hfs_mtime();
@@ -283,9 +287,13 @@ void hfs_mdb_commit(struct super_block *sb)
                                     &mdb->drXTFlSize, NULL);
                hfs_inode_write_fork(HFS_SB(sb)->cat_tree->inode, mdb->drCTExtRec,
                                     &mdb->drCTFlSize, NULL);
+
+               lock_buffer(HFS_SB(sb)->alt_mdb_bh);
                memcpy(HFS_SB(sb)->alt_mdb, HFS_SB(sb)->mdb, HFS_SECTOR_SIZE);
                HFS_SB(sb)->alt_mdb->drAtrb |= cpu_to_be16(HFS_SB_ATTRIB_UNMNT);
                HFS_SB(sb)->alt_mdb->drAtrb &= cpu_to_be16(~HFS_SB_ATTRIB_INCNSTNT);
+               unlock_buffer(HFS_SB(sb)->alt_mdb_bh);
+
                mark_buffer_dirty(HFS_SB(sb)->alt_mdb_bh);
                sync_dirty_buffer(HFS_SB(sb)->alt_mdb_bh);
        }
@@ -308,7 +316,11 @@ void hfs_mdb_commit(struct super_block *sb)
                                break;
                        }
                        len = min((int)sb->s_blocksize - off, size);
+
+                       lock_buffer(bh);
                        memcpy(bh->b_data + off, ptr, len);
+                       unlock_buffer(bh);
+
                        mark_buffer_dirty(bh);
                        brelse(bh);
                        block++;
@@ -317,6 +329,7 @@ void hfs_mdb_commit(struct super_block *sb)
                        size -= len;
                }
        }
+       unlock_buffer(HFS_SB(sb)->mdb_bh);
 }
 
 void hfs_mdb_close(struct super_block *sb)
index 7b4c537d6e136b42fba064de39b0c57703b5fec3..4eb873e0c07b137c0225f30b20fdf78bfb0c0006 100644 (file)
@@ -29,43 +29,9 @@ static struct kmem_cache *hfs_inode_cachep;
 
 MODULE_LICENSE("GPL");
 
-/*
- * hfs_write_super()
- *
- * Description:
- *   This function is called by the VFS only. When the filesystem
- *   is mounted r/w it updates the MDB on disk.
- * Input Variable(s):
- *   struct super_block *sb: Pointer to the hfs superblock
- * Output Variable(s):
- *   NONE
- * Returns:
- *   void
- * Preconditions:
- *   'sb' points to a "valid" (struct super_block).
- * Postconditions:
- *   The MDB is marked 'unsuccessfully unmounted' by clearing bit 8 of drAtrb
- *   (hfs_put_super() must set this flag!). Some MDB fields are updated
- *   and the MDB buffer is written to disk by calling hfs_mdb_commit().
- */
-static void hfs_write_super(struct super_block *sb)
-{
-       lock_super(sb);
-       sb->s_dirt = 0;
-
-       /* sync everything to the buffers */
-       if (!(sb->s_flags & MS_RDONLY))
-               hfs_mdb_commit(sb);
-       unlock_super(sb);
-}
-
 static int hfs_sync_fs(struct super_block *sb, int wait)
 {
-       lock_super(sb);
        hfs_mdb_commit(sb);
-       sb->s_dirt = 0;
-       unlock_super(sb);
-
        return 0;
 }
 
@@ -78,13 +44,44 @@ static int hfs_sync_fs(struct super_block *sb, int wait)
  */
 static void hfs_put_super(struct super_block *sb)
 {
-       if (sb->s_dirt)
-               hfs_write_super(sb);
+       cancel_delayed_work_sync(&HFS_SB(sb)->mdb_work);
        hfs_mdb_close(sb);
        /* release the MDB's resources */
        hfs_mdb_put(sb);
 }
 
+static void flush_mdb(struct work_struct *work)
+{
+       struct hfs_sb_info *sbi;
+       struct super_block *sb;
+
+       sbi = container_of(work, struct hfs_sb_info, mdb_work.work);
+       sb = sbi->sb;
+
+       spin_lock(&sbi->work_lock);
+       sbi->work_queued = 0;
+       spin_unlock(&sbi->work_lock);
+
+       hfs_mdb_commit(sb);
+}
+
+void hfs_mark_mdb_dirty(struct super_block *sb)
+{
+       struct hfs_sb_info *sbi = HFS_SB(sb);
+       unsigned long delay;
+
+       if (sb->s_flags & MS_RDONLY)
+               return;
+
+       spin_lock(&sbi->work_lock);
+       if (!sbi->work_queued) {
+               delay = msecs_to_jiffies(dirty_writeback_interval * 10);
+               queue_delayed_work(system_long_wq, &sbi->mdb_work, delay);
+               sbi->work_queued = 1;
+       }
+       spin_unlock(&sbi->work_lock);
+}
+
 /*
  * hfs_statfs()
  *
@@ -184,7 +181,6 @@ static const struct super_operations hfs_super_operations = {
        .write_inode    = hfs_write_inode,
        .evict_inode    = hfs_evict_inode,
        .put_super      = hfs_put_super,
-       .write_super    = hfs_write_super,
        .sync_fs        = hfs_sync_fs,
        .statfs         = hfs_statfs,
        .remount_fs     = hfs_remount,
@@ -387,7 +383,10 @@ static int hfs_fill_super(struct super_block *sb, void *data, int silent)
        if (!sbi)
                return -ENOMEM;
 
+       sbi->sb = sb;
        sb->s_fs_info = sbi;
+       spin_lock_init(&sbi->work_lock);
+       INIT_DELAYED_WORK(&sbi->mdb_work, flush_mdb);
 
        res = -EINVAL;
        if (!parse_options((char *)data, sbi)) {
index 19cf291eb91f6325126121393ca2354204fb6c5f..91b91fd3a9013a08cc7d12d5e3934b09931b1a1e 100644 (file)
 
 /* dentry case-handling: just lowercase everything */
 
-static int hfs_revalidate_dentry(struct dentry *dentry, struct nameidata *nd)
+static int hfs_revalidate_dentry(struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode;
        int diff;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        inode = dentry->d_inode;
index 1cad80c789cb42e5ebada89cc294c9e07fde0d22..4cfbe2edd29692bfdb609c38c20b6d888349967f 100644 (file)
@@ -153,7 +153,7 @@ done:
        kunmap(page);
        *max = offset + (curr - pptr) * 32 + i - start;
        sbi->free_blocks -= *max;
-       sb->s_dirt = 1;
+       hfsplus_mark_mdb_dirty(sb);
        dprint(DBG_BITMAP, "-> %u,%u\n", start, *max);
 out:
        mutex_unlock(&sbi->alloc_mutex);
@@ -228,7 +228,7 @@ out:
        set_page_dirty(page);
        kunmap(page);
        sbi->free_blocks += len;
-       sb->s_dirt = 1;
+       hfsplus_mark_mdb_dirty(sb);
        mutex_unlock(&sbi->alloc_mutex);
 
        return 0;
index 26b53fb09f684404b2c488057f13c08ec8b2c0e2..6b9f921ef2fa178d75ed2e24d0e7a2a424fbf4d2 100644 (file)
@@ -25,7 +25,7 @@ static inline void hfsplus_instantiate(struct dentry *dentry,
 
 /* Find the entry inside dir named dentry->d_name */
 static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry,
-                                    struct nameidata *nd)
+                                    unsigned int flags)
 {
        struct inode *inode = NULL;
        struct hfs_find_data fd;
@@ -316,7 +316,7 @@ static int hfsplus_link(struct dentry *src_dentry, struct inode *dst_dir,
        inode->i_ctime = CURRENT_TIME_SEC;
        mark_inode_dirty(inode);
        sbi->file_count++;
-       dst_dir->i_sb->s_dirt = 1;
+       hfsplus_mark_mdb_dirty(dst_dir->i_sb);
 out:
        mutex_unlock(&sbi->vh_mutex);
        return res;
@@ -465,7 +465,7 @@ out:
 }
 
 static int hfsplus_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                         struct nameidata *nd)
+                         bool excl)
 {
        return hfsplus_mknod(dir, dentry, mode, 0);
 }
index 4e75ac646fea3ac10643a657ae5276c7ee9d19c8..558dbb463a4e835632437a5bc427900c304a262f 100644 (file)
@@ -153,8 +153,11 @@ struct hfsplus_sb_info {
        gid_t gid;
 
        int part, session;
-
        unsigned long flags;
+
+       int work_queued;               /* non-zero delayed work is queued */
+       struct delayed_work sync_work; /* FS sync delayed work */
+       spinlock_t work_lock;          /* protects sync_work and work_queued */
 };
 
 #define HFSPLUS_SB_WRITEBACKUP 0
@@ -428,7 +431,7 @@ int hfsplus_show_options(struct seq_file *, struct dentry *);
 
 /* super.c */
 struct inode *hfsplus_iget(struct super_block *, unsigned long);
-int hfsplus_sync_fs(struct super_block *sb, int wait);
+void hfsplus_mark_mdb_dirty(struct super_block *sb);
 
 /* tables.c */
 extern u16 hfsplus_case_fold_table[];
index 82b69ee4dacce835559fa631c54115c11ba0f44e..3d8b4a675ba0d84a0b33d190b337eb1cc84a8fae 100644 (file)
@@ -168,7 +168,7 @@ const struct dentry_operations hfsplus_dentry_operations = {
 };
 
 static struct dentry *hfsplus_file_lookup(struct inode *dir,
-               struct dentry *dentry, struct nameidata *nd)
+               struct dentry *dentry, unsigned int flags)
 {
        struct hfs_find_data fd;
        struct super_block *sb = dir->i_sb;
@@ -431,7 +431,7 @@ struct inode *hfsplus_new_inode(struct super_block *sb, umode_t mode)
                sbi->file_count++;
        insert_inode_hash(inode);
        mark_inode_dirty(inode);
-       sb->s_dirt = 1;
+       hfsplus_mark_mdb_dirty(sb);
 
        return inode;
 }
@@ -442,7 +442,7 @@ void hfsplus_delete_inode(struct inode *inode)
 
        if (S_ISDIR(inode->i_mode)) {
                HFSPLUS_SB(sb)->folder_count--;
-               sb->s_dirt = 1;
+               hfsplus_mark_mdb_dirty(sb);
                return;
        }
        HFSPLUS_SB(sb)->file_count--;
@@ -455,7 +455,7 @@ void hfsplus_delete_inode(struct inode *inode)
                inode->i_size = 0;
                hfsplus_file_truncate(inode);
        }
-       sb->s_dirt = 1;
+       hfsplus_mark_mdb_dirty(sb);
 }
 
 void hfsplus_inode_read_fork(struct inode *inode, struct hfsplus_fork_raw *fork)
index a9bca4b8768be786346ec1c832ed73e2c3699df3..47333209801378c5cbd5baef0c948c1767a4fa2a 100644 (file)
@@ -124,7 +124,7 @@ static int hfsplus_system_write_inode(struct inode *inode)
 
        if (fork->total_size != cpu_to_be64(inode->i_size)) {
                set_bit(HFSPLUS_SB_WRITEBACKUP, &sbi->flags);
-               inode->i_sb->s_dirt = 1;
+               hfsplus_mark_mdb_dirty(inode->i_sb);
        }
        hfsplus_inode_write_fork(inode, fork);
        if (tree)
@@ -161,7 +161,7 @@ static void hfsplus_evict_inode(struct inode *inode)
        }
 }
 
-int hfsplus_sync_fs(struct super_block *sb, int wait)
+static int hfsplus_sync_fs(struct super_block *sb, int wait)
 {
        struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
        struct hfsplus_vh *vhdr = sbi->s_vhdr;
@@ -171,9 +171,7 @@ int hfsplus_sync_fs(struct super_block *sb, int wait)
        if (!wait)
                return 0;
 
-       dprint(DBG_SUPER, "hfsplus_write_super\n");
-
-       sb->s_dirt = 0;
+       dprint(DBG_SUPER, "hfsplus_sync_fs\n");
 
        /*
         * Explicitly write out the special metadata inodes.
@@ -226,12 +224,34 @@ out:
        return error;
 }
 
-static void hfsplus_write_super(struct super_block *sb)
+static void delayed_sync_fs(struct work_struct *work)
 {
-       if (!(sb->s_flags & MS_RDONLY))
-               hfsplus_sync_fs(sb, 1);
-       else
-               sb->s_dirt = 0;
+       struct hfsplus_sb_info *sbi;
+
+       sbi = container_of(work, struct hfsplus_sb_info, sync_work.work);
+
+       spin_lock(&sbi->work_lock);
+       sbi->work_queued = 0;
+       spin_unlock(&sbi->work_lock);
+
+       hfsplus_sync_fs(sbi->alloc_file->i_sb, 1);
+}
+
+void hfsplus_mark_mdb_dirty(struct super_block *sb)
+{
+       struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
+       unsigned long delay;
+
+       if (sb->s_flags & MS_RDONLY)
+               return;
+
+       spin_lock(&sbi->work_lock);
+       if (!sbi->work_queued) {
+               delay = msecs_to_jiffies(dirty_writeback_interval * 10);
+               queue_delayed_work(system_long_wq, &sbi->sync_work, delay);
+               sbi->work_queued = 1;
+       }
+       spin_unlock(&sbi->work_lock);
 }
 
 static void hfsplus_put_super(struct super_block *sb)
@@ -240,8 +260,7 @@ static void hfsplus_put_super(struct super_block *sb)
 
        dprint(DBG_SUPER, "hfsplus_put_super\n");
 
-       if (!sb->s_fs_info)
-               return;
+       cancel_delayed_work_sync(&sbi->sync_work);
 
        if (!(sb->s_flags & MS_RDONLY) && sbi->s_vhdr) {
                struct hfsplus_vh *vhdr = sbi->s_vhdr;
@@ -328,7 +347,6 @@ static const struct super_operations hfsplus_sops = {
        .write_inode    = hfsplus_write_inode,
        .evict_inode    = hfsplus_evict_inode,
        .put_super      = hfsplus_put_super,
-       .write_super    = hfsplus_write_super,
        .sync_fs        = hfsplus_sync_fs,
        .statfs         = hfsplus_statfs,
        .remount_fs     = hfsplus_remount,
@@ -355,6 +373,8 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_fs_info = sbi;
        mutex_init(&sbi->alloc_mutex);
        mutex_init(&sbi->vh_mutex);
+       spin_lock_init(&sbi->work_lock);
+       INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs);
        hfsplus_fill_defaults(sbi);
 
        err = -EINVAL;
index 2afa5bbccf9baf9cc4389d88940cb21516bf8bb8..124146543aa76ec87187955cf237f6a04e441ad4 100644 (file)
@@ -553,7 +553,7 @@ static int read_name(struct inode *ino, char *name)
 }
 
 int hostfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                 struct nameidata *nd)
+                 bool excl)
 {
        struct inode *inode;
        char *name;
@@ -595,7 +595,7 @@ int hostfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
 }
 
 struct dentry *hostfs_lookup(struct inode *ino, struct dentry *dentry,
-                            struct nameidata *nd)
+                            unsigned int flags)
 {
        struct inode *inode;
        char *name;
index b8472f803f4e54ea5039b85ac36cfdf33a48925b..78e12b2e0ea2c487dd09b89794e5e3bdb666152b 100644 (file)
@@ -189,7 +189,7 @@ out:
  *           to tell read_inode to read fnode or not.
  */
 
-struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+struct dentry *hpfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
index c07ef1f1ced60a0cf295772a218575d9c78e58d1..ac1ead194db5ebf2ea8d5f1ef2102033615d08a9 100644 (file)
@@ -220,7 +220,7 @@ extern const struct dentry_operations hpfs_dentry_operations;
 
 /* dir.c */
 
-struct dentry *hpfs_lookup(struct inode *, struct dentry *, struct nameidata *);
+struct dentry *hpfs_lookup(struct inode *, struct dentry *, unsigned int);
 extern const struct file_operations hpfs_dir_ops;
 
 /* dnode.c */
index 9083ef8af58c162f7fd207f7ef37263b1f35de4f..bc9082482f6841c21a0bb520d4333fae14efcb9a 100644 (file)
@@ -115,7 +115,7 @@ bail:
        return err;
 }
 
-static int hpfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd)
+static int hpfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
 {
        const unsigned char *name = dentry->d_name.name;
        unsigned len = dentry->d_name.len;
index d4f93b52cec512723447fb1390a9c9b6cca8b45f..c1dffe47fde212b75daa69a0860255ee39b29285 100644 (file)
@@ -138,7 +138,7 @@ static int file_removed(struct dentry *dentry, const char *file)
 }
 
 static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        struct dentry *proc_dentry, *parent;
        struct qstr *name = &dentry->d_name;
@@ -420,8 +420,7 @@ static int hppfs_open(struct inode *inode, struct file *file)
 {
        const struct cred *cred = file->f_cred;
        struct hppfs_private *data;
-       struct vfsmount *proc_mnt;
-       struct dentry *proc_dentry;
+       struct path path;
        char *host_file;
        int err, fd, type, filter;
 
@@ -434,12 +433,11 @@ static int hppfs_open(struct inode *inode, struct file *file)
        if (host_file == NULL)
                goto out_free2;
 
-       proc_dentry = HPPFS_I(inode)->proc_dentry;
-       proc_mnt = inode->i_sb->s_fs_info;
+       path.mnt = inode->i_sb->s_fs_info;
+       path.dentry = HPPFS_I(inode)->proc_dentry;
 
        /* XXX This isn't closed anywhere */
-       data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
-                                     file_mode(file->f_mode), cred);
+       data->proc_file = dentry_open(&path, file_mode(file->f_mode), cred);
        err = PTR_ERR(data->proc_file);
        if (IS_ERR(data->proc_file))
                goto out_free1;
@@ -484,8 +482,7 @@ static int hppfs_dir_open(struct inode *inode, struct file *file)
 {
        const struct cred *cred = file->f_cred;
        struct hppfs_private *data;
-       struct vfsmount *proc_mnt;
-       struct dentry *proc_dentry;
+       struct path path;
        int err;
 
        err = -ENOMEM;
@@ -493,10 +490,9 @@ static int hppfs_dir_open(struct inode *inode, struct file *file)
        if (data == NULL)
                goto out;
 
-       proc_dentry = HPPFS_I(inode)->proc_dentry;
-       proc_mnt = inode->i_sb->s_fs_info;
-       data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt),
-                                     file_mode(file->f_mode), cred);
+       path.mnt = inode->i_sb->s_fs_info;
+       path.dentry = HPPFS_I(inode)->proc_dentry;
+       data->proc_file = dentry_open(&path, file_mode(file->f_mode), cred);
        err = PTR_ERR(data->proc_file);
        if (IS_ERR(data->proc_file))
                goto out_free;
index cc9281b6c62893a94cedcb36128dcae427861fcd..e13e9bdb0bf57f2cdfe03fc1ad013826e1668d41 100644 (file)
@@ -565,7 +565,7 @@ static int hugetlbfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mod
        return retval;
 }
 
-static int hugetlbfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd)
+static int hugetlbfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
 {
        return hugetlbfs_mknod(dir, dentry, mode | S_IFREG, 0);
 }
index c99163b1b31036ef68974c0c5dbc192f8f73f4da..775cbabd4fa5f3fe3840277a4f0aac4456f02396 100644 (file)
@@ -182,7 +182,7 @@ int inode_init_always(struct super_block *sb, struct inode *inode)
        }
        inode->i_private = NULL;
        inode->i_mapping = mapping;
-       INIT_LIST_HEAD(&inode->i_dentry);       /* buggered by rcu freeing */
+       INIT_HLIST_HEAD(&inode->i_dentry);      /* buggered by rcu freeing */
 #ifdef CONFIG_FS_POSIX_ACL
        inode->i_acl = inode->i_default_acl = ACL_NOT_CACHED;
 #endif
index 18bc216ea09d95ecff126ef96987ff786b5cbcb1..a6fd56c68b1164928d380fdc787a988107c15a55 100644 (file)
@@ -41,6 +41,11 @@ static inline int __sync_blockdev(struct block_device *bdev, int wait)
  */
 extern void __init chrdev_init(void);
 
+/*
+ * namei.c
+ */
+extern int __inode_permission(struct inode *, int);
+
 /*
  * namespace.c
  */
@@ -50,8 +55,6 @@ extern int copy_mount_string(const void __user *, char **);
 extern struct vfsmount *lookup_mnt(struct path *);
 extern int finish_automount(struct vfsmount *, struct path *);
 
-extern void mnt_make_longterm(struct vfsmount *);
-extern void mnt_make_shortterm(struct vfsmount *);
 extern int sb_prepare_remount_readonly(struct super_block *);
 
 extern void __init mnt_init(void);
@@ -84,9 +87,6 @@ extern struct super_block *user_get_super(dev_t);
 /*
  * open.c
  */
-struct nameidata;
-extern struct file *nameidata_to_filp(struct nameidata *);
-extern void release_open_intent(struct nameidata *);
 struct open_flags {
        int open_flag;
        umode_t mode;
index 0e73f63d92745d244a7007b3d1b367784d467c58..3620ad1ea9bcfc31cf2814ad98df9896cbd8bba9 100644 (file)
@@ -114,7 +114,7 @@ extern int isofs_name_translate(struct iso_directory_record *, char *, struct in
 int get_joliet_filename(struct iso_directory_record *, unsigned char *, struct inode *);
 int get_acorn_filename(struct iso_directory_record *, char *, struct inode *);
 
-extern struct dentry *isofs_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *isofs_lookup(struct inode *, struct dentry *, unsigned int flags);
 extern struct buffer_head *isofs_bread(struct inode *, sector_t);
 extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long);
 
index 1e2946f2a69e5ac6dd17924f124459b318439eb8..c167028844ed539fca2b25931ccfb51a8d32d962 100644 (file)
@@ -163,7 +163,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry,
        return 0;
 }
 
-struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        int found;
        unsigned long uninitialized_var(block);
index b56018896d5e398b3f5bce94776db8dd0cf9de37..ad7774d3209575b0bf47d010dad56043412d2ac8 100644 (file)
@@ -25,9 +25,9 @@
 static int jffs2_readdir (struct file *, void *, filldir_t);
 
 static int jffs2_create (struct inode *,struct dentry *,umode_t,
-                        struct nameidata *);
+                        bool);
 static struct dentry *jffs2_lookup (struct inode *,struct dentry *,
-                                   struct nameidata *);
+                                   unsigned int);
 static int jffs2_link (struct dentry *,struct inode *,struct dentry *);
 static int jffs2_unlink (struct inode *,struct dentry *);
 static int jffs2_symlink (struct inode *,struct dentry *,const char *);
@@ -74,7 +74,7 @@ const struct inode_operations jffs2_dir_inode_operations =
    nice and simple
 */
 static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        struct jffs2_inode_info *dir_f;
        struct jffs2_full_dirent *fd = NULL, *fd_list;
@@ -175,7 +175,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
 
 static int jffs2_create(struct inode *dir_i, struct dentry *dentry,
-                       umode_t mode, struct nameidata *nd)
+                       umode_t mode, bool excl)
 {
        struct jffs2_raw_inode *ri;
        struct jffs2_inode_info *f, *dir_f;
@@ -226,8 +226,8 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry,
                  __func__, inode->i_ino, inode->i_mode, inode->i_nlink,
                  f->inocache->pino_nlink, inode->i_mapping->nrpages);
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        return 0;
 
  fail:
@@ -446,8 +446,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char
        mutex_unlock(&dir_f->sem);
        jffs2_complete_reservation(c);
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        return 0;
 
  fail:
@@ -591,8 +591,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, umode_t mode
        mutex_unlock(&dir_f->sem);
        jffs2_complete_reservation(c);
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        return 0;
 
  fail:
@@ -766,8 +766,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, umode_t mode
        mutex_unlock(&dir_f->sem);
        jffs2_complete_reservation(c);
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        return 0;
 
  fail:
index 07c91ca6017db03d404362e5e763fdbf90fdc2ef..3b91a7ad60862008f50c67526b7854f938aadc19 100644 (file)
@@ -73,7 +73,7 @@ static inline void free_ea_wmap(struct inode *inode)
  *
  */
 static int jfs_create(struct inode *dip, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        int rc = 0;
        tid_t tid;              /* transaction id */
@@ -176,8 +176,8 @@ static int jfs_create(struct inode *dip, struct dentry *dentry, umode_t mode,
                unlock_new_inode(ip);
                iput(ip);
        } else {
-               d_instantiate(dentry, ip);
                unlock_new_inode(ip);
+               d_instantiate(dentry, ip);
        }
 
       out2:
@@ -309,8 +309,8 @@ static int jfs_mkdir(struct inode *dip, struct dentry *dentry, umode_t mode)
                unlock_new_inode(ip);
                iput(ip);
        } else {
-               d_instantiate(dentry, ip);
                unlock_new_inode(ip);
+               d_instantiate(dentry, ip);
        }
 
       out2:
@@ -1043,8 +1043,8 @@ static int jfs_symlink(struct inode *dip, struct dentry *dentry,
                unlock_new_inode(ip);
                iput(ip);
        } else {
-               d_instantiate(dentry, ip);
                unlock_new_inode(ip);
+               d_instantiate(dentry, ip);
        }
 
       out2:
@@ -1424,8 +1424,8 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
                unlock_new_inode(ip);
                iput(ip);
        } else {
-               d_instantiate(dentry, ip);
                unlock_new_inode(ip);
+               d_instantiate(dentry, ip);
        }
 
       out1:
@@ -1436,7 +1436,7 @@ static int jfs_mknod(struct inode *dir, struct dentry *dentry,
        return rc;
 }
 
-static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *jfs_lookup(struct inode *dip, struct dentry *dentry, unsigned int flags)
 {
        struct btstack btstack;
        ino_t inum;
@@ -1570,7 +1570,7 @@ out:
        return result;
 }
 
-static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int jfs_ci_revalidate(struct dentry *dentry, unsigned int flags)
 {
        /*
         * This is not negative dentry. Always valid.
@@ -1589,7 +1589,7 @@ static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd)
         * This may be nfsd (or something), anyway, we can't see the
         * intent of this. So, since this can be for creation, drop it.
         */
-       if (!nd)
+       if (!flags)
                return 0;
 
        /*
@@ -1597,7 +1597,7 @@ static int jfs_ci_revalidate(struct dentry *dentry, struct nameidata *nd)
         * case sensitive name which is specified by user if this is
         * for creation.
         */
-       if (nd->flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
+       if (flags & (LOOKUP_CREATE | LOOKUP_RENAME_TARGET))
                return 0;
        return 1;
 }
index 4a82950f412f8c274007f574e91b9ee59766061a..c55c7452d2857c1f0f59042f5b6ffd1de9eba8b6 100644 (file)
@@ -601,6 +601,11 @@ static int jfs_sync_fs(struct super_block *sb, int wait)
 
        /* log == NULL indicates read-only mount */
        if (log) {
+               /*
+                * Write quota structures to quota file, sync_blockdev() will
+                * write them to disk later
+                */
+               dquot_writeback_dquots(sb, -1);
                jfs_flush_journal(log, wait);
                jfs_syncpt(log, 0);
        }
index f86ec27a4230a6cd23f6d020c53217cd30a060f1..a74cb1725ac694adf25be38ad2266afc0f382059 100644 (file)
@@ -53,7 +53,7 @@ static int simple_delete_dentry(const struct dentry *dentry)
  * Lookup the data. This is trivial - if the dentry didn't already
  * exist, we know it is negative.  Set d_op to delete negative dentries.
  */
-struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+struct dentry *simple_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        static const struct dentry_operations simple_dentry_operations = {
                .d_delete = simple_delete_dentry,
@@ -222,15 +222,15 @@ struct dentry *mount_pseudo(struct file_system_type *fs_type, char *name,
        const struct super_operations *ops,
        const struct dentry_operations *dops, unsigned long magic)
 {
-       struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
+       struct super_block *s;
        struct dentry *dentry;
        struct inode *root;
        struct qstr d_name = QSTR_INIT(name, strlen(name));
 
+       s = sget(fs_type, NULL, set_anon_super, MS_NOUSER, NULL);
        if (IS_ERR(s))
                return ERR_CAST(s);
 
-       s->s_flags = MS_NOUSER;
        s->s_maxbytes = MAX_LFS_FILESIZE;
        s->s_blocksize = PAGE_SIZE;
        s->s_blocksize_bits = PAGE_SHIFT;
index fce6238d52c1bf742307325a588d545e169508e4..82c353304f9eeccab27b01b86379441df323deeb 100644 (file)
@@ -308,7 +308,7 @@ static int flock_make_lock(struct file *filp, struct file_lock **lock,
        return 0;
 }
 
-static int assign_type(struct file_lock *fl, int type)
+static int assign_type(struct file_lock *fl, long type)
 {
        switch (type) {
        case F_RDLCK:
@@ -445,7 +445,7 @@ static const struct lock_manager_operations lease_manager_ops = {
 /*
  * Initialize a lease, use the default lock manager operations
  */
-static int lease_init(struct file *filp, int type, struct file_lock *fl)
+static int lease_init(struct file *filp, long type, struct file_lock *fl)
  {
        if (assign_type(fl, type) != 0)
                return -EINVAL;
@@ -463,7 +463,7 @@ static int lease_init(struct file *filp, int type, struct file_lock *fl)
 }
 
 /* Allocate a file_lock initialised to this type of lease */
-static struct file_lock *lease_alloc(struct file *filp, int type)
+static struct file_lock *lease_alloc(struct file *filp, long type)
 {
        struct file_lock *fl = locks_alloc_lock();
        int error = -ENOMEM;
index bea5d1b9954ba771b76829acc2e1d6a92162310a..26e4a941532fb62dc18338a08bd313d9ccb4445b 100644 (file)
@@ -349,7 +349,7 @@ static void logfs_set_name(struct logfs_disk_dentry *dd, struct qstr *name)
 }
 
 static struct dentry *logfs_lookup(struct inode *dir, struct dentry *dentry,
-               struct nameidata *nd)
+               unsigned int flags)
 {
        struct page *page;
        struct logfs_disk_dentry *dd;
@@ -502,7 +502,7 @@ static int logfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 }
 
 static int logfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        struct inode *inode;
 
index 97bca623d893a8345323739add9a4178da72ec9a..345c24b8a6f86965b39d7dd017fb294908ddd8d0 100644 (file)
@@ -519,7 +519,7 @@ static struct dentry *logfs_get_sb_device(struct logfs_super *super,
        log_super("LogFS: Start mount %x\n", mount_count++);
 
        err = -EINVAL;
-       sb = sget(type, logfs_sb_test, logfs_sb_set, super);
+       sb = sget(type, logfs_sb_test, logfs_sb_set, flags | MS_NOATIME, super);
        if (IS_ERR(sb)) {
                super->s_devops->put_device(super);
                kfree(super);
@@ -542,7 +542,6 @@ static struct dentry *logfs_get_sb_device(struct logfs_super *super,
        sb->s_maxbytes  = (1ull << 43) - 1;
        sb->s_max_links = LOGFS_LINK_MAX;
        sb->s_op        = &logfs_super_operations;
-       sb->s_flags     = flags | MS_NOATIME;
 
        err = logfs_read_sb(sb, sb->s_flags & MS_RDONLY);
        if (err)
index 2d0ee17863051d4c31e747f451e4565d657cc6d9..0db73d9dd66845d289f6f1a58e1960ecc1ee3e74 100644 (file)
@@ -18,7 +18,7 @@ static int add_nondir(struct dentry *dentry, struct inode *inode)
        return err;
 }
 
-static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *minix_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode * inode = NULL;
        ino_t ino;
@@ -55,7 +55,7 @@ static int minix_mknod(struct inode * dir, struct dentry *dentry, umode_t mode,
 }
 
 static int minix_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        return minix_mknod(dir, dentry, mode, 0);
 }
index 4ef36d93e5a241822e10c21f93dc72d7137d32ec..4f291f9de641ea2aca94f609daa7e865ae71fd58 100644 (file)
@@ -22,7 +22,6 @@ struct mount {
        struct vfsmount mnt;
 #ifdef CONFIG_SMP
        struct mnt_pcp __percpu *mnt_pcp;
-       atomic_t mnt_longterm;          /* how many of the refs are longterm */
 #else
        int mnt_count;
        int mnt_writers;
@@ -49,6 +48,8 @@ struct mount {
        int mnt_ghosts;
 };
 
+#define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */
+
 static inline struct mount *real_mount(struct vfsmount *mnt)
 {
        return container_of(mnt, struct mount, mnt);
@@ -59,6 +60,12 @@ static inline int mnt_has_parent(struct mount *mnt)
        return mnt != mnt->mnt_parent;
 }
 
+static inline int is_mounted(struct vfsmount *mnt)
+{
+       /* neither detached nor internal? */
+       return !IS_ERR_OR_NULL(real_mount(mnt));
+}
+
 extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
 
 static inline void get_mnt_ns(struct mnt_namespace *ns)
@@ -67,10 +74,12 @@ static inline void get_mnt_ns(struct mnt_namespace *ns)
 }
 
 struct proc_mounts {
-       struct seq_file m; /* must be the first element */
+       struct seq_file m;
        struct mnt_namespace *ns;
        struct path root;
        int (*show)(struct seq_file *, struct vfsmount *);
 };
 
+#define proc_mounts(p) (container_of((p), struct proc_mounts, m))
+
 extern const struct seq_operations mounts_op;
index 7d694194024ac4d2459e7cc3d60014bdff64e3ba..2ccc35c4dc24d95e2a5c1bf5528528fa6f22827d 100644 (file)
@@ -315,31 +315,22 @@ static inline int do_inode_permission(struct inode *inode, int mask)
 }
 
 /**
- * inode_permission  -  check for access rights to a given inode
- * @inode:     inode to check permission on
- * @mask:      right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC, ...)
+ * __inode_permission - Check for access rights to a given inode
+ * @inode: Inode to check permission on
+ * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
  *
- * Used to check for read/write/execute permissions on an inode.
- * We use "fsuid" for this, letting us set arbitrary permissions
- * for filesystem access without changing the "normal" uids which
- * are used for other things.
+ * Check for read/write/execute permissions on an inode.
  *
  * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask.
+ *
+ * This does not check for a read-only file system.  You probably want
+ * inode_permission().
  */
-int inode_permission(struct inode *inode, int mask)
+int __inode_permission(struct inode *inode, int mask)
 {
        int retval;
 
        if (unlikely(mask & MAY_WRITE)) {
-               umode_t mode = inode->i_mode;
-
-               /*
-                * Nobody gets write access to a read-only fs.
-                */
-               if (IS_RDONLY(inode) &&
-                   (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
-                       return -EROFS;
-
                /*
                 * Nobody gets write access to an immutable file.
                 */
@@ -358,6 +349,47 @@ int inode_permission(struct inode *inode, int mask)
        return security_inode_permission(inode, mask);
 }
 
+/**
+ * sb_permission - Check superblock-level permissions
+ * @sb: Superblock of inode to check permission on
+ * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
+ *
+ * Separate out file-system wide checks from inode-specific permission checks.
+ */
+static int sb_permission(struct super_block *sb, struct inode *inode, int mask)
+{
+       if (unlikely(mask & MAY_WRITE)) {
+               umode_t mode = inode->i_mode;
+
+               /* Nobody gets write access to a read-only fs. */
+               if ((sb->s_flags & MS_RDONLY) &&
+                   (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))
+                       return -EROFS;
+       }
+       return 0;
+}
+
+/**
+ * inode_permission - Check for access rights to a given inode
+ * @inode: Inode to check permission on
+ * @mask: Right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
+ *
+ * Check for read/write/execute permissions on an inode.  We use fs[ug]id for
+ * this, letting us set arbitrary permissions for filesystem access without
+ * changing the "normal" UIDs which are used for other things.
+ *
+ * When checking for MAY_APPEND, MAY_WRITE must also be set in @mask.
+ */
+int inode_permission(struct inode *inode, int mask)
+{
+       int retval;
+
+       retval = sb_permission(inode->i_sb, inode, mask);
+       if (retval)
+               return retval;
+       return __inode_permission(inode, mask);
+}
+
 /**
  * path_get - get a reference to a path
  * @path: path to get the reference to
@@ -395,6 +427,18 @@ EXPORT_SYMBOL(path_put);
  * to restart the path walk from the beginning in ref-walk mode.
  */
 
+static inline void lock_rcu_walk(void)
+{
+       br_read_lock(&vfsmount_lock);
+       rcu_read_lock();
+}
+
+static inline void unlock_rcu_walk(void)
+{
+       rcu_read_unlock();
+       br_read_unlock(&vfsmount_lock);
+}
+
 /**
  * unlazy_walk - try to switch to ref-walk mode.
  * @nd: nameidata pathwalk data
@@ -448,8 +492,7 @@ static int unlazy_walk(struct nameidata *nd, struct dentry *dentry)
        }
        mntget(nd->path.mnt);
 
-       rcu_read_unlock();
-       br_read_unlock(&vfsmount_lock);
+       unlock_rcu_walk();
        nd->flags &= ~LOOKUP_RCU;
        return 0;
 
@@ -463,25 +506,9 @@ err_root:
        return -ECHILD;
 }
 
-/**
- * release_open_intent - free up open intent resources
- * @nd: pointer to nameidata
- */
-void release_open_intent(struct nameidata *nd)
+static inline int d_revalidate(struct dentry *dentry, unsigned int flags)
 {
-       struct file *file = nd->intent.open.file;
-
-       if (file && !IS_ERR(file)) {
-               if (file->f_path.dentry == NULL)
-                       put_filp(file);
-               else
-                       fput(file);
-       }
-}
-
-static inline int d_revalidate(struct dentry *dentry, struct nameidata *nd)
-{
-       return dentry->d_op->d_revalidate(dentry, nd);
+       return dentry->d_op->d_revalidate(dentry, flags);
 }
 
 /**
@@ -506,15 +533,13 @@ static int complete_walk(struct nameidata *nd)
                spin_lock(&dentry->d_lock);
                if (unlikely(!__d_rcu_to_refcount(dentry, nd->seq))) {
                        spin_unlock(&dentry->d_lock);
-                       rcu_read_unlock();
-                       br_read_unlock(&vfsmount_lock);
+                       unlock_rcu_walk();
                        return -ECHILD;
                }
                BUG_ON(nd->inode != dentry->d_inode);
                spin_unlock(&dentry->d_lock);
                mntget(nd->path.mnt);
-               rcu_read_unlock();
-               br_read_unlock(&vfsmount_lock);
+               unlock_rcu_walk();
        }
 
        if (likely(!(nd->flags & LOOKUP_JUMPED)))
@@ -527,7 +552,7 @@ static int complete_walk(struct nameidata *nd)
                return 0;
 
        /* Note: we do not d_invalidate() */
-       status = d_revalidate(dentry, nd);
+       status = d_revalidate(dentry, nd->flags);
        if (status > 0)
                return 0;
 
@@ -602,10 +627,25 @@ static inline void path_to_nameidata(const struct path *path,
        nd->path.dentry = path->dentry;
 }
 
+/*
+ * Helper to directly jump to a known parsed path from ->follow_link,
+ * caller must have taken a reference to path beforehand.
+ */
+void nd_jump_link(struct nameidata *nd, struct path *path)
+{
+       path_put(&nd->path);
+
+       nd->path = *path;
+       nd->inode = nd->path.dentry->d_inode;
+       nd->flags |= LOOKUP_JUMPED;
+
+       BUG_ON(nd->inode->i_op->follow_link);
+}
+
 static inline void put_link(struct nameidata *nd, struct path *link, void *cookie)
 {
        struct inode *inode = link->dentry->d_inode;
-       if (!IS_ERR(cookie) && inode->i_op->put_link)
+       if (inode->i_op->put_link)
                inode->i_op->put_link(link->dentry, nd, cookie);
        path_put(link);
 }
@@ -613,19 +653,19 @@ static inline void put_link(struct nameidata *nd, struct path *link, void *cooki
 static __always_inline int
 follow_link(struct path *link, struct nameidata *nd, void **p)
 {
-       int error;
        struct dentry *dentry = link->dentry;
+       int error;
+       char *s;
 
        BUG_ON(nd->flags & LOOKUP_RCU);
 
        if (link->mnt == nd->path.mnt)
                mntget(link->mnt);
 
-       if (unlikely(current->total_link_count >= 40)) {
-               *p = ERR_PTR(-ELOOP); /* no ->put_link(), please */
-               path_put(&nd->path);
-               return -ELOOP;
-       }
+       error = -ELOOP;
+       if (unlikely(current->total_link_count >= 40))
+               goto out_put_nd_path;
+
        cond_resched();
        current->total_link_count++;
 
@@ -633,30 +673,28 @@ follow_link(struct path *link, struct nameidata *nd, void **p)
        nd_set_link(nd, NULL);
 
        error = security_inode_follow_link(link->dentry, nd);
-       if (error) {
-               *p = ERR_PTR(error); /* no ->put_link(), please */
-               path_put(&nd->path);
-               return error;
-       }
+       if (error)
+               goto out_put_nd_path;
 
        nd->last_type = LAST_BIND;
        *p = dentry->d_inode->i_op->follow_link(dentry, nd);
        error = PTR_ERR(*p);
-       if (!IS_ERR(*p)) {
-               char *s = nd_get_link(nd);
-               error = 0;
-               if (s)
-                       error = __vfs_follow_link(nd, s);
-               else if (nd->last_type == LAST_BIND) {
-                       nd->flags |= LOOKUP_JUMPED;
-                       nd->inode = nd->path.dentry->d_inode;
-                       if (nd->inode->i_op->follow_link) {
-                               /* stepped on a _really_ weird one */
-                               path_put(&nd->path);
-                               error = -ELOOP;
-                       }
-               }
+       if (IS_ERR(*p))
+               goto out_put_nd_path;
+
+       error = 0;
+       s = nd_get_link(nd);
+       if (s) {
+               error = __vfs_follow_link(nd, s);
+               if (unlikely(error))
+                       put_link(nd, link, *p);
        }
+
+       return error;
+
+out_put_nd_path:
+       path_put(&nd->path);
+       path_put(link);
        return error;
 }
 
@@ -675,6 +713,16 @@ static int follow_up_rcu(struct path *path)
        return 1;
 }
 
+/*
+ * follow_up - Find the mountpoint of path's vfsmount
+ *
+ * Given a path, find the mountpoint of its source file system.
+ * Replace @path with the path of the mountpoint in the parent mount.
+ * Up is towards /.
+ *
+ * Return 1 if we went up a level and 0 if we were already at the
+ * root.
+ */
 int follow_up(struct path *path)
 {
        struct mount *mnt = real_mount(path->mnt);
@@ -683,7 +731,7 @@ int follow_up(struct path *path)
 
        br_read_lock(&vfsmount_lock);
        parent = mnt->mnt_parent;
-       if (&parent->mnt == path->mnt) {
+       if (parent == mnt) {
                br_read_unlock(&vfsmount_lock);
                return 0;
        }
@@ -946,8 +994,7 @@ failed:
        nd->flags &= ~LOOKUP_RCU;
        if (!(nd->flags & LOOKUP_ROOT))
                nd->root.mnt = NULL;
-       rcu_read_unlock();
-       br_read_unlock(&vfsmount_lock);
+       unlock_rcu_walk();
        return -ECHILD;
 }
 
@@ -1048,7 +1095,7 @@ static void follow_dotdot(struct nameidata *nd)
  * dir->d_inode->i_mutex must be held
  */
 static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir,
-                                   struct nameidata *nd, bool *need_lookup)
+                                   unsigned int flags, bool *need_lookup)
 {
        struct dentry *dentry;
        int error;
@@ -1059,7 +1106,7 @@ static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir,
                if (d_need_lookup(dentry)) {
                        *need_lookup = true;
                } else if (dentry->d_flags & DCACHE_OP_REVALIDATE) {
-                       error = d_revalidate(dentry, nd);
+                       error = d_revalidate(dentry, flags);
                        if (unlikely(error <= 0)) {
                                if (error < 0) {
                                        dput(dentry);
@@ -1089,7 +1136,7 @@ static struct dentry *lookup_dcache(struct qstr *name, struct dentry *dir,
  * dir->d_inode->i_mutex must be held
  */
 static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry,
-                                 struct nameidata *nd)
+                                 unsigned int flags)
 {
        struct dentry *old;
 
@@ -1099,7 +1146,7 @@ static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry,
                return ERR_PTR(-ENOENT);
        }
 
-       old = dir->i_op->lookup(dir, dentry, nd);
+       old = dir->i_op->lookup(dir, dentry, flags);
        if (unlikely(old)) {
                dput(dentry);
                dentry = old;
@@ -1108,16 +1155,16 @@ static struct dentry *lookup_real(struct inode *dir, struct dentry *dentry,
 }
 
 static struct dentry *__lookup_hash(struct qstr *name,
-               struct dentry *base, struct nameidata *nd)
+               struct dentry *base, unsigned int flags)
 {
        bool need_lookup;
        struct dentry *dentry;
 
-       dentry = lookup_dcache(name, base, nd, &need_lookup);
+       dentry = lookup_dcache(name, base, flags, &need_lookup);
        if (!need_lookup)
                return dentry;
 
-       return lookup_real(base->d_inode, dentry, nd);
+       return lookup_real(base->d_inode, dentry, flags);
 }
 
 /*
@@ -1167,7 +1214,7 @@ static int lookup_fast(struct nameidata *nd, struct qstr *name,
                if (unlikely(d_need_lookup(dentry)))
                        goto unlazy;
                if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE)) {
-                       status = d_revalidate(dentry, nd);
+                       status = d_revalidate(dentry, nd->flags);
                        if (unlikely(status <= 0)) {
                                if (status != -ECHILD)
                                        need_reval = 0;
@@ -1197,7 +1244,7 @@ unlazy:
        }
 
        if (unlikely(dentry->d_flags & DCACHE_OP_REVALIDATE) && need_reval)
-               status = d_revalidate(dentry, nd);
+               status = d_revalidate(dentry, nd->flags);
        if (unlikely(status <= 0)) {
                if (status < 0) {
                        dput(dentry);
@@ -1236,7 +1283,7 @@ static int lookup_slow(struct nameidata *nd, struct qstr *name,
        BUG_ON(nd->inode != parent->d_inode);
 
        mutex_lock(&parent->d_inode->i_mutex);
-       dentry = __lookup_hash(name, parent, nd);
+       dentry = __lookup_hash(name, parent, nd->flags);
        mutex_unlock(&parent->d_inode->i_mutex);
        if (IS_ERR(dentry))
                return PTR_ERR(dentry);
@@ -1284,8 +1331,7 @@ static void terminate_walk(struct nameidata *nd)
                nd->flags &= ~LOOKUP_RCU;
                if (!(nd->flags & LOOKUP_ROOT))
                        nd->root.mnt = NULL;
-               rcu_read_unlock();
-               br_read_unlock(&vfsmount_lock);
+               unlock_rcu_walk();
        }
 }
 
@@ -1383,9 +1429,10 @@ static inline int nested_symlink(struct path *path, struct nameidata *nd)
                void *cookie;
 
                res = follow_link(&link, nd, &cookie);
-               if (!res)
-                       res = walk_component(nd, path, &nd->last,
-                                            nd->last_type, LOOKUP_FOLLOW);
+               if (res)
+                       break;
+               res = walk_component(nd, path, &nd->last,
+                                    nd->last_type, LOOKUP_FOLLOW);
                put_link(nd, &link, cookie);
        } while (res > 0);
 
@@ -1651,8 +1698,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
                nd->path = nd->root;
                nd->inode = inode;
                if (flags & LOOKUP_RCU) {
-                       br_read_lock(&vfsmount_lock);
-                       rcu_read_lock();
+                       lock_rcu_walk();
                        nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
                } else {
                        path_get(&nd->path);
@@ -1664,8 +1710,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
 
        if (*name=='/') {
                if (flags & LOOKUP_RCU) {
-                       br_read_lock(&vfsmount_lock);
-                       rcu_read_lock();
+                       lock_rcu_walk();
                        set_root_rcu(nd);
                } else {
                        set_root(nd);
@@ -1677,8 +1722,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
                        struct fs_struct *fs = current->fs;
                        unsigned seq;
 
-                       br_read_lock(&vfsmount_lock);
-                       rcu_read_lock();
+                       lock_rcu_walk();
 
                        do {
                                seq = read_seqcount_begin(&fs->seq);
@@ -1713,8 +1757,7 @@ static int path_init(int dfd, const char *name, unsigned int flags,
                        if (fput_needed)
                                *fp = file;
                        nd->seq = __read_seqcount_begin(&nd->path.dentry->d_seq);
-                       br_read_lock(&vfsmount_lock);
-                       rcu_read_lock();
+                       lock_rcu_walk();
                } else {
                        path_get(&file->f_path);
                        fput_light(file, fput_needed);
@@ -1777,8 +1820,9 @@ static int path_lookupat(int dfd, const char *name,
                        struct path link = path;
                        nd->flags |= LOOKUP_PARENT;
                        err = follow_link(&link, nd, &cookie);
-                       if (!err)
-                               err = lookup_last(nd, &path);
+                       if (err)
+                               break;
+                       err = lookup_last(nd, &path);
                        put_link(nd, &link, cookie);
                }
        }
@@ -1821,9 +1865,27 @@ static int do_path_lookup(int dfd, const char *name,
        return retval;
 }
 
-int kern_path_parent(const char *name, struct nameidata *nd)
+/* does lookup, returns the object with parent locked */
+struct dentry *kern_path_locked(const char *name, struct path *path)
 {
-       return do_path_lookup(AT_FDCWD, name, LOOKUP_PARENT, nd);
+       struct nameidata nd;
+       struct dentry *d;
+       int err = do_path_lookup(AT_FDCWD, name, LOOKUP_PARENT, &nd);
+       if (err)
+               return ERR_PTR(err);
+       if (nd.last_type != LAST_NORM) {
+               path_put(&nd.path);
+               return ERR_PTR(-EINVAL);
+       }
+       mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
+       d = __lookup_hash(&nd.last, nd.path.dentry, 0);
+       if (IS_ERR(d)) {
+               mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
+               path_put(&nd.path);
+               return d;
+       }
+       *path = nd.path;
+       return d;
 }
 
 int kern_path(const char *name, unsigned int flags, struct path *path)
@@ -1866,7 +1928,7 @@ int vfs_path_lookup(struct dentry *dentry, struct vfsmount *mnt,
  */
 static struct dentry *lookup_hash(struct nameidata *nd)
 {
-       return __lookup_hash(&nd->last, nd->path.dentry, nd);
+       return __lookup_hash(&nd->last, nd->path.dentry, nd->flags);
 }
 
 /**
@@ -1913,7 +1975,7 @@ struct dentry *lookup_one_len(const char *name, struct dentry *base, int len)
        if (err)
                return ERR_PTR(err);
 
-       return __lookup_hash(&this, base, NULL);
+       return __lookup_hash(&this, base, 0);
 }
 
 int user_path_at_empty(int dfd, const char __user *name, unsigned flags,
@@ -2086,10 +2148,9 @@ void unlock_rename(struct dentry *p1, struct dentry *p2)
 }
 
 int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool want_excl)
 {
        int error = may_create(dir, dentry);
-
        if (error)
                return error;
 
@@ -2100,7 +2161,7 @@ int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
        error = security_inode_create(dir, dentry, mode);
        if (error)
                return error;
-       error = dir->i_op->create(dir, dentry, mode, nd);
+       error = dir->i_op->create(dir, dentry, mode, want_excl);
        if (!error)
                fsnotify_create(dir, dentry);
        return error;
@@ -2187,21 +2248,275 @@ static inline int open_to_namei_flags(int flag)
        return flag;
 }
 
+static int may_o_create(struct path *dir, struct dentry *dentry, umode_t mode)
+{
+       int error = security_path_mknod(dir, dentry, mode, 0);
+       if (error)
+               return error;
+
+       error = inode_permission(dir->dentry->d_inode, MAY_WRITE | MAY_EXEC);
+       if (error)
+               return error;
+
+       return security_inode_create(dir->dentry->d_inode, dentry, mode);
+}
+
 /*
- * Handle the last step of open()
+ * Attempt to atomically look up, create and open a file from a negative
+ * dentry.
+ *
+ * Returns 0 if successful.  The file will have been created and attached to
+ * @file by the filesystem calling finish_open().
+ *
+ * Returns 1 if the file was looked up only or didn't need creating.  The
+ * caller will need to perform the open themselves.  @path will have been
+ * updated to point to the new dentry.  This may be negative.
+ *
+ * Returns an error code otherwise.
+ */
+static int atomic_open(struct nameidata *nd, struct dentry *dentry,
+                       struct path *path, struct file *file,
+                       const struct open_flags *op,
+                       bool *want_write, bool need_lookup,
+                       int *opened)
+{
+       struct inode *dir =  nd->path.dentry->d_inode;
+       unsigned open_flag = open_to_namei_flags(op->open_flag);
+       umode_t mode;
+       int error;
+       int acc_mode;
+       int create_error = 0;
+       struct dentry *const DENTRY_NOT_SET = (void *) -1UL;
+
+       BUG_ON(dentry->d_inode);
+
+       /* Don't create child dentry for a dead directory. */
+       if (unlikely(IS_DEADDIR(dir))) {
+               error = -ENOENT;
+               goto out;
+       }
+
+       mode = op->mode & S_IALLUGO;
+       if ((open_flag & O_CREAT) && !IS_POSIXACL(dir))
+               mode &= ~current_umask();
+
+       if (open_flag & O_EXCL) {
+               open_flag &= ~O_TRUNC;
+               *opened |= FILE_CREATED;
+       }
+
+       /*
+        * Checking write permission is tricky, bacuse we don't know if we are
+        * going to actually need it: O_CREAT opens should work as long as the
+        * file exists.  But checking existence breaks atomicity.  The trick is
+        * to check access and if not granted clear O_CREAT from the flags.
+        *
+        * Another problem is returing the "right" error value (e.g. for an
+        * O_EXCL open we want to return EEXIST not EROFS).
+        */
+       if ((open_flag & (O_CREAT | O_TRUNC)) ||
+           (open_flag & O_ACCMODE) != O_RDONLY) {
+               error = mnt_want_write(nd->path.mnt);
+               if (!error) {
+                       *want_write = true;
+               } else if (!(open_flag & O_CREAT)) {
+                       /*
+                        * No O_CREATE -> atomicity not a requirement -> fall
+                        * back to lookup + open
+                        */
+                       goto no_open;
+               } else if (open_flag & (O_EXCL | O_TRUNC)) {
+                       /* Fall back and fail with the right error */
+                       create_error = error;
+                       goto no_open;
+               } else {
+                       /* No side effects, safe to clear O_CREAT */
+                       create_error = error;
+                       open_flag &= ~O_CREAT;
+               }
+       }
+
+       if (open_flag & O_CREAT) {
+               error = may_o_create(&nd->path, dentry, op->mode);
+               if (error) {
+                       create_error = error;
+                       if (open_flag & O_EXCL)
+                               goto no_open;
+                       open_flag &= ~O_CREAT;
+               }
+       }
+
+       if (nd->flags & LOOKUP_DIRECTORY)
+               open_flag |= O_DIRECTORY;
+
+       file->f_path.dentry = DENTRY_NOT_SET;
+       file->f_path.mnt = nd->path.mnt;
+       error = dir->i_op->atomic_open(dir, dentry, file, open_flag, mode,
+                                     opened);
+       if (error < 0) {
+               if (create_error && error == -ENOENT)
+                       error = create_error;
+               goto out;
+       }
+
+       acc_mode = op->acc_mode;
+       if (*opened & FILE_CREATED) {
+               fsnotify_create(dir, dentry);
+               acc_mode = MAY_OPEN;
+       }
+
+       if (error) {    /* returned 1, that is */
+               if (WARN_ON(file->f_path.dentry == DENTRY_NOT_SET)) {
+                       error = -EIO;
+                       goto out;
+               }
+               if (file->f_path.dentry) {
+                       dput(dentry);
+                       dentry = file->f_path.dentry;
+               }
+               goto looked_up;
+       }
+
+       /*
+        * We didn't have the inode before the open, so check open permission
+        * here.
+        */
+       error = may_open(&file->f_path, acc_mode, open_flag);
+       if (error)
+               fput(file);
+
+out:
+       dput(dentry);
+       return error;
+
+no_open:
+       if (need_lookup) {
+               dentry = lookup_real(dir, dentry, nd->flags);
+               if (IS_ERR(dentry))
+                       return PTR_ERR(dentry);
+
+               if (create_error) {
+                       int open_flag = op->open_flag;
+
+                       error = create_error;
+                       if ((open_flag & O_EXCL)) {
+                               if (!dentry->d_inode)
+                                       goto out;
+                       } else if (!dentry->d_inode) {
+                               goto out;
+                       } else if ((open_flag & O_TRUNC) &&
+                                  S_ISREG(dentry->d_inode->i_mode)) {
+                               goto out;
+                       }
+                       /* will fail later, go on to get the right error */
+               }
+       }
+looked_up:
+       path->dentry = dentry;
+       path->mnt = nd->path.mnt;
+       return 1;
+}
+
+/*
+ * Look up and maybe create and open the last component.
+ *
+ * Must be called with i_mutex held on parent.
+ *
+ * Returns 0 if the file was successfully atomically created (if necessary) and
+ * opened.  In this case the file will be returned attached to @file.
+ *
+ * Returns 1 if the file was not completely opened at this time, though lookups
+ * and creations will have been performed and the dentry returned in @path will
+ * be positive upon return if O_CREAT was specified.  If O_CREAT wasn't
+ * specified then a negative dentry may be returned.
+ *
+ * An error code is returned otherwise.
+ *
+ * FILE_CREATE will be set in @*opened if the dentry was created and will be
+ * cleared otherwise prior to returning.
  */
-static struct file *do_last(struct nameidata *nd, struct path *path,
-                           const struct open_flags *op, const char *pathname)
+static int lookup_open(struct nameidata *nd, struct path *path,
+                       struct file *file,
+                       const struct open_flags *op,
+                       bool *want_write, int *opened)
 {
        struct dentry *dir = nd->path.dentry;
+       struct inode *dir_inode = dir->d_inode;
        struct dentry *dentry;
+       int error;
+       bool need_lookup;
+
+       *opened &= ~FILE_CREATED;
+       dentry = lookup_dcache(&nd->last, dir, nd->flags, &need_lookup);
+       if (IS_ERR(dentry))
+               return PTR_ERR(dentry);
+
+       /* Cached positive dentry: will open in f_op->open */
+       if (!need_lookup && dentry->d_inode)
+               goto out_no_open;
+
+       if ((nd->flags & LOOKUP_OPEN) && dir_inode->i_op->atomic_open) {
+               return atomic_open(nd, dentry, path, file, op, want_write,
+                                  need_lookup, opened);
+       }
+
+       if (need_lookup) {
+               BUG_ON(dentry->d_inode);
+
+               dentry = lookup_real(dir_inode, dentry, nd->flags);
+               if (IS_ERR(dentry))
+                       return PTR_ERR(dentry);
+       }
+
+       /* Negative dentry, just create the file */
+       if (!dentry->d_inode && (op->open_flag & O_CREAT)) {
+               umode_t mode = op->mode;
+               if (!IS_POSIXACL(dir->d_inode))
+                       mode &= ~current_umask();
+               /*
+                * This write is needed to ensure that a
+                * rw->ro transition does not occur between
+                * the time when the file is created and when
+                * a permanent write count is taken through
+                * the 'struct file' in finish_open().
+                */
+               error = mnt_want_write(nd->path.mnt);
+               if (error)
+                       goto out_dput;
+               *want_write = true;
+               *opened |= FILE_CREATED;
+               error = security_path_mknod(&nd->path, dentry, mode, 0);
+               if (error)
+                       goto out_dput;
+               error = vfs_create(dir->d_inode, dentry, mode,
+                                  nd->flags & LOOKUP_EXCL);
+               if (error)
+                       goto out_dput;
+       }
+out_no_open:
+       path->dentry = dentry;
+       path->mnt = nd->path.mnt;
+       return 1;
+
+out_dput:
+       dput(dentry);
+       return error;
+}
+
+/*
+ * Handle the last step of open()
+ */
+static int do_last(struct nameidata *nd, struct path *path,
+                  struct file *file, const struct open_flags *op,
+                  int *opened, const char *pathname)
+{
+       struct dentry *dir = nd->path.dentry;
        int open_flag = op->open_flag;
-       int will_truncate = open_flag & O_TRUNC;
-       int want_write = 0;
+       bool will_truncate = (open_flag & O_TRUNC) != 0;
+       bool want_write = false;
        int acc_mode = op->acc_mode;
-       struct file *filp;
        struct inode *inode;
-       int symlink_ok = 0;
+       bool symlink_ok = false;
        struct path save_parent = { .dentry = NULL, .mnt = NULL };
        bool retried = false;
        int error;
@@ -2214,112 +2529,99 @@ static struct file *do_last(struct nameidata *nd, struct path *path,
        case LAST_DOT:
                error = handle_dots(nd, nd->last_type);
                if (error)
-                       return ERR_PTR(error);
+                       return error;
                /* fallthrough */
        case LAST_ROOT:
                error = complete_walk(nd);
                if (error)
-                       return ERR_PTR(error);
+                       return error;
                audit_inode(pathname, nd->path.dentry);
                if (open_flag & O_CREAT) {
                        error = -EISDIR;
-                       goto exit;
+                       goto out;
                }
-               goto ok;
+               goto finish_open;
        case LAST_BIND:
                error = complete_walk(nd);
                if (error)
-                       return ERR_PTR(error);
+                       return error;
                audit_inode(pathname, dir);
-               goto ok;
+               goto finish_open;
        }
 
        if (!(open_flag & O_CREAT)) {
                if (nd->last.name[nd->last.len])
                        nd->flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
                if (open_flag & O_PATH && !(nd->flags & LOOKUP_FOLLOW))
-                       symlink_ok = 1;
+                       symlink_ok = true;
                /* we _can_ be in RCU mode here */
                error = lookup_fast(nd, &nd->last, path, &inode);
-               if (unlikely(error)) {
-                       if (error < 0)
-                               goto exit;
+               if (likely(!error))
+                       goto finish_lookup;
 
-                       error = lookup_slow(nd, &nd->last, path);
-                       if (error < 0)
-                               goto exit;
+               if (error < 0)
+                       goto out;
 
-                       inode = path->dentry->d_inode;
-               }
-               goto finish_lookup;
-       }
-
-       /* create side of things */
-       /*
-        * This will *only* deal with leaving RCU mode - LOOKUP_JUMPED has been
-        * cleared when we got to the last component we are about to look up
-        */
-       error = complete_walk(nd);
-       if (error)
-               return ERR_PTR(error);
+               BUG_ON(nd->inode != dir->d_inode);
+       } else {
+               /* create side of things */
+               /*
+                * This will *only* deal with leaving RCU mode - LOOKUP_JUMPED
+                * has been cleared when we got to the last component we are
+                * about to look up
+                */
+               error = complete_walk(nd);
+               if (error)
+                       return error;
 
-       audit_inode(pathname, dir);
-       error = -EISDIR;
-       /* trailing slashes? */
-       if (nd->last.name[nd->last.len])
-               goto exit;
+               audit_inode(pathname, dir);
+               error = -EISDIR;
+               /* trailing slashes? */
+               if (nd->last.name[nd->last.len])
+                       goto out;
+       }
 
 retry_lookup:
        mutex_lock(&dir->d_inode->i_mutex);
+       error = lookup_open(nd, path, file, op, &want_write, opened);
+       mutex_unlock(&dir->d_inode->i_mutex);
 
-       dentry = lookup_hash(nd);
-       error = PTR_ERR(dentry);
-       if (IS_ERR(dentry)) {
-               mutex_unlock(&dir->d_inode->i_mutex);
-               goto exit;
-       }
+       if (error <= 0) {
+               if (error)
+                       goto out;
 
-       path->dentry = dentry;
-       path->mnt = nd->path.mnt;
+               if ((*opened & FILE_CREATED) ||
+                   !S_ISREG(file->f_path.dentry->d_inode->i_mode))
+                       will_truncate = false;
 
-       /* Negative dentry, just create the file */
-       if (!dentry->d_inode) {
-               umode_t mode = op->mode;
-               if (!IS_POSIXACL(dir->d_inode))
-                       mode &= ~current_umask();
-               /*
-                * This write is needed to ensure that a
-                * rw->ro transition does not occur between
-                * the time when the file is created and when
-                * a permanent write count is taken through
-                * the 'struct file' in nameidata_to_filp().
-                */
-               error = mnt_want_write(nd->path.mnt);
-               if (error)
-                       goto exit_mutex_unlock;
-               want_write = 1;
+               audit_inode(pathname, file->f_path.dentry);
+               goto opened;
+       }
+
+       if (*opened & FILE_CREATED) {
                /* Don't check for write permission, don't truncate */
                open_flag &= ~O_TRUNC;
-               will_truncate = 0;
+               will_truncate = false;
                acc_mode = MAY_OPEN;
-               error = security_path_mknod(&nd->path, dentry, mode, 0);
-               if (error)
-                       goto exit_mutex_unlock;
-               error = vfs_create(dir->d_inode, dentry, mode, nd);
-               if (error)
-                       goto exit_mutex_unlock;
-               mutex_unlock(&dir->d_inode->i_mutex);
-               dput(nd->path.dentry);
-               nd->path.dentry = dentry;
-               goto common;
+               path_to_nameidata(path, nd);
+               goto finish_open_created;
        }
 
        /*
         * It already exists.
         */
-       mutex_unlock(&dir->d_inode->i_mutex);
        audit_inode(pathname, path->dentry);
 
+       /*
+        * If atomic_open() acquired write access it is dropped now due to
+        * possible mount and symlink following (this might be optimized away if
+        * necessary...)
+        */
+       if (want_write) {
+               mnt_drop_write(nd->path.mnt);
+               want_write = false;
+       }
+
        error = -EEXIST;
        if (open_flag & O_EXCL)
                goto exit_dput;
@@ -2338,18 +2640,18 @@ finish_lookup:
        error = -ENOENT;
        if (!inode) {
                path_to_nameidata(path, nd);
-               goto exit;
+               goto out;
        }
 
        if (should_follow_link(inode, !symlink_ok)) {
                if (nd->flags & LOOKUP_RCU) {
                        if (unlikely(unlazy_walk(nd, path->dentry))) {
                                error = -ECHILD;
-                               goto exit;
+                               goto out;
                        }
                }
                BUG_ON(inode != path->dentry->d_inode);
-               return NULL;
+               return 1;
        }
 
        if ((nd->flags & LOOKUP_RCU) || nd->path.mnt != path->mnt) {
@@ -2365,119 +2667,122 @@ finish_lookup:
        error = complete_walk(nd);
        if (error) {
                path_put(&save_parent);
-               return ERR_PTR(error);
+               return error;
        }
        error = -EISDIR;
        if ((open_flag & O_CREAT) && S_ISDIR(nd->inode->i_mode))
-               goto exit;
+               goto out;
        error = -ENOTDIR;
        if ((nd->flags & LOOKUP_DIRECTORY) && !nd->inode->i_op->lookup)
-               goto exit;
+               goto out;
        audit_inode(pathname, nd->path.dentry);
-ok:
+finish_open:
        if (!S_ISREG(nd->inode->i_mode))
-               will_truncate = 0;
+               will_truncate = false;
 
        if (will_truncate) {
                error = mnt_want_write(nd->path.mnt);
                if (error)
-                       goto exit;
-               want_write = 1;
+                       goto out;
+               want_write = true;
        }
-common:
+finish_open_created:
        error = may_open(&nd->path, acc_mode, open_flag);
        if (error)
-               goto exit;
-       filp = nameidata_to_filp(nd);
-       if (filp == ERR_PTR(-EOPENSTALE) && save_parent.dentry && !retried) {
-               BUG_ON(save_parent.dentry != dir);
-               path_put(&nd->path);
-               nd->path = save_parent;
-               nd->inode = dir->d_inode;
-               save_parent.mnt = NULL;
-               save_parent.dentry = NULL;
-               if (want_write) {
-                       mnt_drop_write(nd->path.mnt);
-                       want_write = 0;
-               }
-               retried = true;
-               goto retry_lookup;
-       }
-       if (!IS_ERR(filp)) {
-               error = ima_file_check(filp, op->acc_mode);
-               if (error) {
-                       fput(filp);
-                       filp = ERR_PTR(error);
-               }
+               goto out;
+       file->f_path.mnt = nd->path.mnt;
+       error = finish_open(file, nd->path.dentry, NULL, opened);
+       if (error) {
+               if (error == -EOPENSTALE)
+                       goto stale_open;
+               goto out;
        }
-       if (!IS_ERR(filp)) {
-               if (will_truncate) {
-                       error = handle_truncate(filp);
-                       if (error) {
-                               fput(filp);
-                               filp = ERR_PTR(error);
-                       }
-               }
+opened:
+       error = open_check_o_direct(file);
+       if (error)
+               goto exit_fput;
+       error = ima_file_check(file, op->acc_mode);
+       if (error)
+               goto exit_fput;
+
+       if (will_truncate) {
+               error = handle_truncate(file);
+               if (error)
+                       goto exit_fput;
        }
 out:
        if (want_write)
                mnt_drop_write(nd->path.mnt);
        path_put(&save_parent);
        terminate_walk(nd);
-       return filp;
+       return error;
 
-exit_mutex_unlock:
-       mutex_unlock(&dir->d_inode->i_mutex);
 exit_dput:
        path_put_conditional(path, nd);
-exit:
-       filp = ERR_PTR(error);
        goto out;
+exit_fput:
+       fput(file);
+       goto out;
+
+stale_open:
+       /* If no saved parent or already retried then can't retry */
+       if (!save_parent.dentry || retried)
+               goto out;
+
+       BUG_ON(save_parent.dentry != dir);
+       path_put(&nd->path);
+       nd->path = save_parent;
+       nd->inode = dir->d_inode;
+       save_parent.mnt = NULL;
+       save_parent.dentry = NULL;
+       if (want_write) {
+               mnt_drop_write(nd->path.mnt);
+               want_write = false;
+       }
+       retried = true;
+       goto retry_lookup;
 }
 
 static struct file *path_openat(int dfd, const char *pathname,
                struct nameidata *nd, const struct open_flags *op, int flags)
 {
        struct file *base = NULL;
-       struct file *filp;
+       struct file *file;
        struct path path;
+       int opened = 0;
        int error;
 
-       filp = get_empty_filp();
-       if (!filp)
+       file = get_empty_filp();
+       if (!file)
                return ERR_PTR(-ENFILE);
 
-       filp->f_flags = op->open_flag;
-       nd->intent.open.file = filp;
-       nd->intent.open.flags = open_to_namei_flags(op->open_flag);
-       nd->intent.open.create_mode = op->mode;
+       file->f_flags = op->open_flag;
 
        error = path_init(dfd, pathname, flags | LOOKUP_PARENT, nd, &base);
        if (unlikely(error))
-               goto out_filp;
+               goto out;
 
        current->total_link_count = 0;
        error = link_path_walk(pathname, nd);
        if (unlikely(error))
-               goto out_filp;
+               goto out;
 
-       filp = do_last(nd, &path, op, pathname);
-       while (unlikely(!filp)) { /* trailing symlink */
+       error = do_last(nd, &path, file, op, &opened, pathname);
+       while (unlikely(error > 0)) { /* trailing symlink */
                struct path link = path;
                void *cookie;
                if (!(nd->flags & LOOKUP_FOLLOW)) {
                        path_put_conditional(&path, nd);
                        path_put(&nd->path);
-                       filp = ERR_PTR(-ELOOP);
+                       error = -ELOOP;
                        break;
                }
                nd->flags |= LOOKUP_PARENT;
                nd->flags &= ~(LOOKUP_OPEN|LOOKUP_CREATE|LOOKUP_EXCL);
                error = follow_link(&link, nd, &cookie);
                if (unlikely(error))
-                       filp = ERR_PTR(error);
-               else
-                       filp = do_last(nd, &path, op, pathname);
+                       break;
+               error = do_last(nd, &path, file, op, &opened, pathname);
                put_link(nd, &link, cookie);
        }
 out:
@@ -2485,18 +2790,20 @@ out:
                path_put(&nd->root);
        if (base)
                fput(base);
-       release_open_intent(nd);
-       if (filp == ERR_PTR(-EOPENSTALE)) {
-               if (flags & LOOKUP_RCU)
-                       filp = ERR_PTR(-ECHILD);
-               else
-                       filp = ERR_PTR(-ESTALE);
+       if (!(opened & FILE_OPENED)) {
+               BUG_ON(!error);
+               put_filp(file);
        }
-       return filp;
-
-out_filp:
-       filp = ERR_PTR(error);
-       goto out;
+       if (unlikely(error)) {
+               if (error == -EOPENSTALE) {
+                       if (flags & LOOKUP_RCU)
+                               error = -ECHILD;
+                       else
+                               error = -ESTALE;
+               }
+               file = ERR_PTR(error);
+       }
+       return file;
 }
 
 struct file *do_filp_open(int dfd, const char *pathname,
@@ -2551,7 +2858,6 @@ struct dentry *kern_path_create(int dfd, const char *pathname, struct path *path
                goto out;
        nd.flags &= ~LOOKUP_PARENT;
        nd.flags |= LOOKUP_CREATE | LOOKUP_EXCL;
-       nd.intent.open.flags = O_EXCL;
 
        /*
         * Do the final lookup.
@@ -2670,7 +2976,7 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const char __user *, filename, umode_t, mode,
                goto out_drop_write;
        switch (mode & S_IFMT) {
                case 0: case S_IFREG:
-                       error = vfs_create(path.dentry->d_inode,dentry,mode,NULL);
+                       error = vfs_create(path.dentry->d_inode,dentry,mode,true);
                        break;
                case S_IFCHR: case S_IFBLK:
                        error = vfs_mknod(path.dentry->d_inode,dentry,mode,
index 1e4a5fe3d7b7f789d66839f37b1f917c1fa3e2ba..c53d3381b0d0043d91e2f7c47e4cafbdaaaf13d6 100644 (file)
@@ -515,8 +515,20 @@ struct mount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry,
 }
 
 /*
- * lookup_mnt increments the ref count before returning
- * the vfsmount struct.
+ * lookup_mnt - Return the first child mount mounted at path
+ *
+ * "First" means first mounted chronologically.  If you create the
+ * following mounts:
+ *
+ * mount /dev/sda1 /mnt
+ * mount /dev/sda2 /mnt
+ * mount /dev/sda3 /mnt
+ *
+ * Then lookup_mnt() on the base /mnt dentry in the root mount will
+ * return successively the root dentry and vfsmount of /dev/sda1, then
+ * /dev/sda2, then /dev/sda3, then NULL.
+ *
+ * lookup_mnt takes a reference to the found vfsmount.
  */
 struct vfsmount *lookup_mnt(struct path *path)
 {
@@ -621,21 +633,6 @@ static void attach_mnt(struct mount *mnt, struct path *path)
        list_add_tail(&mnt->mnt_child, &real_mount(path->mnt)->mnt_mounts);
 }
 
-static inline void __mnt_make_longterm(struct mount *mnt)
-{
-#ifdef CONFIG_SMP
-       atomic_inc(&mnt->mnt_longterm);
-#endif
-}
-
-/* needs vfsmount lock for write */
-static inline void __mnt_make_shortterm(struct mount *mnt)
-{
-#ifdef CONFIG_SMP
-       atomic_dec(&mnt->mnt_longterm);
-#endif
-}
-
 /*
  * vfsmount lock must be held for write
  */
@@ -649,10 +646,8 @@ static void commit_tree(struct mount *mnt)
        BUG_ON(parent == mnt);
 
        list_add_tail(&head, &mnt->mnt_list);
-       list_for_each_entry(m, &head, mnt_list) {
+       list_for_each_entry(m, &head, mnt_list)
                m->mnt_ns = n;
-               __mnt_make_longterm(m);
-       }
 
        list_splice(&head, n->list.prev);
 
@@ -725,56 +720,60 @@ static struct mount *clone_mnt(struct mount *old, struct dentry *root,
                                        int flag)
 {
        struct super_block *sb = old->mnt.mnt_sb;
-       struct mount *mnt = alloc_vfsmnt(old->mnt_devname);
+       struct mount *mnt;
+       int err;
 
-       if (mnt) {
-               if (flag & (CL_SLAVE | CL_PRIVATE))
-                       mnt->mnt_group_id = 0; /* not a peer of original */
-               else
-                       mnt->mnt_group_id = old->mnt_group_id;
-
-               if ((flag & CL_MAKE_SHARED) && !mnt->mnt_group_id) {
-                       int err = mnt_alloc_group_id(mnt);
-                       if (err)
-                               goto out_free;
-               }
+       mnt = alloc_vfsmnt(old->mnt_devname);
+       if (!mnt)
+               return ERR_PTR(-ENOMEM);
 
-               mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~MNT_WRITE_HOLD;
-               atomic_inc(&sb->s_active);
-               mnt->mnt.mnt_sb = sb;
-               mnt->mnt.mnt_root = dget(root);
-               mnt->mnt_mountpoint = mnt->mnt.mnt_root;
-               mnt->mnt_parent = mnt;
-               br_write_lock(&vfsmount_lock);
-               list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
-               br_write_unlock(&vfsmount_lock);
+       if (flag & (CL_SLAVE | CL_PRIVATE))
+               mnt->mnt_group_id = 0; /* not a peer of original */
+       else
+               mnt->mnt_group_id = old->mnt_group_id;
 
-               if (flag & CL_SLAVE) {
-                       list_add(&mnt->mnt_slave, &old->mnt_slave_list);
-                       mnt->mnt_master = old;
-                       CLEAR_MNT_SHARED(mnt);
-               } else if (!(flag & CL_PRIVATE)) {
-                       if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old))
-                               list_add(&mnt->mnt_share, &old->mnt_share);
-                       if (IS_MNT_SLAVE(old))
-                               list_add(&mnt->mnt_slave, &old->mnt_slave);
-                       mnt->mnt_master = old->mnt_master;
-               }
-               if (flag & CL_MAKE_SHARED)
-                       set_mnt_shared(mnt);
-
-               /* stick the duplicate mount on the same expiry list
-                * as the original if that was on one */
-               if (flag & CL_EXPIRE) {
-                       if (!list_empty(&old->mnt_expire))
-                               list_add(&mnt->mnt_expire, &old->mnt_expire);
-               }
+       if ((flag & CL_MAKE_SHARED) && !mnt->mnt_group_id) {
+               err = mnt_alloc_group_id(mnt);
+               if (err)
+                       goto out_free;
        }
+
+       mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~MNT_WRITE_HOLD;
+       atomic_inc(&sb->s_active);
+       mnt->mnt.mnt_sb = sb;
+       mnt->mnt.mnt_root = dget(root);
+       mnt->mnt_mountpoint = mnt->mnt.mnt_root;
+       mnt->mnt_parent = mnt;
+       br_write_lock(&vfsmount_lock);
+       list_add_tail(&mnt->mnt_instance, &sb->s_mounts);
+       br_write_unlock(&vfsmount_lock);
+
+       if (flag & CL_SLAVE) {
+               list_add(&mnt->mnt_slave, &old->mnt_slave_list);
+               mnt->mnt_master = old;
+               CLEAR_MNT_SHARED(mnt);
+       } else if (!(flag & CL_PRIVATE)) {
+               if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old))
+                       list_add(&mnt->mnt_share, &old->mnt_share);
+               if (IS_MNT_SLAVE(old))
+                       list_add(&mnt->mnt_slave, &old->mnt_slave);
+               mnt->mnt_master = old->mnt_master;
+       }
+       if (flag & CL_MAKE_SHARED)
+               set_mnt_shared(mnt);
+
+       /* stick the duplicate mount on the same expiry list
+        * as the original if that was on one */
+       if (flag & CL_EXPIRE) {
+               if (!list_empty(&old->mnt_expire))
+                       list_add(&mnt->mnt_expire, &old->mnt_expire);
+       }
+
        return mnt;
 
  out_free:
        free_vfsmnt(mnt);
-       return NULL;
+       return ERR_PTR(err);
 }
 
 static inline void mntfree(struct mount *mnt)
@@ -804,7 +803,8 @@ static void mntput_no_expire(struct mount *mnt)
 put_again:
 #ifdef CONFIG_SMP
        br_read_lock(&vfsmount_lock);
-       if (likely(atomic_read(&mnt->mnt_longterm))) {
+       if (likely(mnt->mnt_ns)) {
+               /* shouldn't be the last one */
                mnt_add_count(mnt, -1);
                br_read_unlock(&vfsmount_lock);
                return;
@@ -939,7 +939,7 @@ EXPORT_SYMBOL(replace_mount_options);
 /* iterator; we want it to have access to namespace_sem, thus here... */
 static void *m_start(struct seq_file *m, loff_t *pos)
 {
-       struct proc_mounts *p = container_of(m, struct proc_mounts, m);
+       struct proc_mounts *p = proc_mounts(m);
 
        down_read(&namespace_sem);
        return seq_list_start(&p->ns->list, *pos);
@@ -947,7 +947,7 @@ static void *m_start(struct seq_file *m, loff_t *pos)
 
 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
 {
-       struct proc_mounts *p = container_of(m, struct proc_mounts, m);
+       struct proc_mounts *p = proc_mounts(m);
 
        return seq_list_next(v, &p->ns->list, pos);
 }
@@ -959,7 +959,7 @@ static void m_stop(struct seq_file *m, void *v)
 
 static int m_show(struct seq_file *m, void *v)
 {
-       struct proc_mounts *p = container_of(m, struct proc_mounts, m);
+       struct proc_mounts *p = proc_mounts(m);
        struct mount *r = list_entry(v, struct mount, mnt_list);
        return p->show(m, &r->mnt);
 }
@@ -1074,8 +1074,6 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill)
                list_del_init(&p->mnt_expire);
                list_del_init(&p->mnt_list);
                __touch_mnt_namespace(p->mnt_ns);
-               if (p->mnt_ns)
-                       __mnt_make_shortterm(p);
                p->mnt_ns = NULL;
                list_del_init(&p->mnt_child);
                if (mnt_has_parent(p)) {
@@ -1260,11 +1258,12 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
        struct path path;
 
        if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt))
-               return NULL;
+               return ERR_PTR(-EINVAL);
 
        res = q = clone_mnt(mnt, dentry, flag);
-       if (!q)
-               goto Enomem;
+       if (IS_ERR(q))
+               return q;
+
        q->mnt_mountpoint = mnt->mnt_mountpoint;
 
        p = mnt;
@@ -1286,8 +1285,8 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
                        path.mnt = &q->mnt;
                        path.dentry = p->mnt_mountpoint;
                        q = clone_mnt(p, p->mnt.mnt_root, flag);
-                       if (!q)
-                               goto Enomem;
+                       if (IS_ERR(q))
+                               goto out;
                        br_write_lock(&vfsmount_lock);
                        list_add_tail(&q->mnt_list, &res->mnt_list);
                        attach_mnt(q, &path);
@@ -1295,7 +1294,7 @@ struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
                }
        }
        return res;
-Enomem:
+out:
        if (res) {
                LIST_HEAD(umount_list);
                br_write_lock(&vfsmount_lock);
@@ -1303,9 +1302,11 @@ Enomem:
                br_write_unlock(&vfsmount_lock);
                release_mounts(&umount_list);
        }
-       return NULL;
+       return q;
 }
 
+/* Caller should check returned pointer for errors */
+
 struct vfsmount *collect_mounts(struct path *path)
 {
        struct mount *tree;
@@ -1313,7 +1314,9 @@ struct vfsmount *collect_mounts(struct path *path)
        tree = copy_tree(real_mount(path->mnt), path->dentry,
                         CL_COPY_ALL | CL_PRIVATE);
        up_write(&namespace_sem);
-       return tree ? &tree->mnt : NULL;
+       if (IS_ERR(tree))
+               return NULL;
+       return &tree->mnt;
 }
 
 void drop_collected_mounts(struct vfsmount *mnt)
@@ -1608,14 +1611,15 @@ static int do_loopback(struct path *path, char *old_name,
        if (!check_mnt(real_mount(path->mnt)) || !check_mnt(old))
                goto out2;
 
-       err = -ENOMEM;
        if (recurse)
                mnt = copy_tree(old, old_path.dentry, 0);
        else
                mnt = clone_mnt(old, old_path.dentry, 0);
 
-       if (!mnt)
-               goto out2;
+       if (IS_ERR(mnt)) {
+               err = PTR_ERR(mnt);
+               goto out;
+       }
 
        err = graft_tree(mnt, path);
        if (err) {
@@ -2209,23 +2213,6 @@ static struct mnt_namespace *alloc_mnt_ns(void)
        return new_ns;
 }
 
-void mnt_make_longterm(struct vfsmount *mnt)
-{
-       __mnt_make_longterm(real_mount(mnt));
-}
-
-void mnt_make_shortterm(struct vfsmount *m)
-{
-#ifdef CONFIG_SMP
-       struct mount *mnt = real_mount(m);
-       if (atomic_add_unless(&mnt->mnt_longterm, -1, 1))
-               return;
-       br_write_lock(&vfsmount_lock);
-       atomic_dec(&mnt->mnt_longterm);
-       br_write_unlock(&vfsmount_lock);
-#endif
-}
-
 /*
  * Allocate a new namespace structure and populate it with contents
  * copied from the namespace of the passed in task structure.
@@ -2246,10 +2233,10 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
        down_write(&namespace_sem);
        /* First pass: copy the tree topology */
        new = copy_tree(old, old->mnt.mnt_root, CL_COPY_ALL | CL_EXPIRE);
-       if (!new) {
+       if (IS_ERR(new)) {
                up_write(&namespace_sem);
                kfree(new_ns);
-               return ERR_PTR(-ENOMEM);
+               return ERR_CAST(new);
        }
        new_ns->root = new;
        br_write_lock(&vfsmount_lock);
@@ -2265,18 +2252,13 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
        q = new;
        while (p) {
                q->mnt_ns = new_ns;
-               __mnt_make_longterm(q);
                if (fs) {
                        if (&p->mnt == fs->root.mnt) {
                                fs->root.mnt = mntget(&q->mnt);
-                               __mnt_make_longterm(q);
-                               mnt_make_shortterm(&p->mnt);
                                rootmnt = &p->mnt;
                        }
                        if (&p->mnt == fs->pwd.mnt) {
                                fs->pwd.mnt = mntget(&q->mnt);
-                               __mnt_make_longterm(q);
-                               mnt_make_shortterm(&p->mnt);
                                pwdmnt = &p->mnt;
                        }
                }
@@ -2320,7 +2302,6 @@ static struct mnt_namespace *create_mnt_ns(struct vfsmount *m)
        if (!IS_ERR(new_ns)) {
                struct mount *mnt = real_mount(m);
                mnt->mnt_ns = new_ns;
-               __mnt_make_longterm(mnt);
                new_ns->root = mnt;
                list_add(&new_ns->list, &mnt->mnt_list);
        } else {
@@ -2615,7 +2596,7 @@ struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
                 * it is a longterm mount, don't release mnt until
                 * we unmount before file sys is unregistered
                */
-               mnt_make_longterm(mnt);
+               real_mount(mnt)->mnt_ns = MNT_NS_INTERNAL;
        }
        return mnt;
 }
@@ -2625,7 +2606,9 @@ void kern_unmount(struct vfsmount *mnt)
 {
        /* release long term mount so mount point can be released */
        if (!IS_ERR_OR_NULL(mnt)) {
-               mnt_make_shortterm(mnt);
+               br_write_lock(&vfsmount_lock);
+               real_mount(mnt)->mnt_ns = NULL;
+               br_write_unlock(&vfsmount_lock);
                mntput(mnt);
        }
 }
index aeed93a6bde0c972796b92972ec5cea58126dc75..4117e7b377bbf731a5345ef8b640ad5aa6607837 100644 (file)
@@ -30,8 +30,8 @@ static void ncp_do_readdir(struct file *, void *, filldir_t,
 
 static int ncp_readdir(struct file *, void *, filldir_t);
 
-static int ncp_create(struct inode *, struct dentry *, umode_t, struct nameidata *);
-static struct dentry *ncp_lookup(struct inode *, struct dentry *, struct nameidata *);
+static int ncp_create(struct inode *, struct dentry *, umode_t, bool);
+static struct dentry *ncp_lookup(struct inode *, struct dentry *, unsigned int);
 static int ncp_unlink(struct inode *, struct dentry *);
 static int ncp_mkdir(struct inode *, struct dentry *, umode_t);
 static int ncp_rmdir(struct inode *, struct dentry *);
@@ -72,7 +72,7 @@ const struct inode_operations ncp_dir_inode_operations =
 /*
  * Dentry operations routines
  */
-static int ncp_lookup_validate(struct dentry *, struct nameidata *);
+static int ncp_lookup_validate(struct dentry *, unsigned int);
 static int ncp_hash_dentry(const struct dentry *, const struct inode *,
                struct qstr *);
 static int ncp_compare_dentry(const struct dentry *, const struct inode *,
@@ -290,7 +290,7 @@ leave_me:;
 
 
 static int
-ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
+ncp_lookup_validate(struct dentry *dentry, unsigned int flags)
 {
        struct ncp_server *server;
        struct dentry *parent;
@@ -302,7 +302,7 @@ ncp_lookup_validate(struct dentry *dentry, struct nameidata *nd)
        if (dentry == dentry->d_sb->s_root)
                return 1;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        parent = dget_parent(dentry);
@@ -836,7 +836,7 @@ out:
        return result;
 }
 
-static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *ncp_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct ncp_server *server = NCP_SERVER(dir);
        struct inode *inode = NULL;
@@ -980,7 +980,7 @@ out:
 }
 
 static int ncp_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        return ncp_create_new(dir, dentry, mode, 0, 0);
 }
index f430057ff3b397c2fe1f523bf5fcea4135276f8c..a6b1c7fb8232c0a3152f79175e2047421c896859 100644 (file)
@@ -46,8 +46,8 @@
 static int nfs_opendir(struct inode *, struct file *);
 static int nfs_closedir(struct inode *, struct file *);
 static int nfs_readdir(struct file *, void *, filldir_t);
-static struct dentry *nfs_lookup(struct inode *, struct dentry *, struct nameidata *);
-static int nfs_create(struct inode *, struct dentry *, umode_t, struct nameidata *);
+static struct dentry *nfs_lookup(struct inode *, struct dentry *, unsigned int);
+static int nfs_create(struct inode *, struct dentry *, umode_t, bool);
 static int nfs_mkdir(struct inode *, struct dentry *, umode_t);
 static int nfs_rmdir(struct inode *, struct dentry *);
 static int nfs_unlink(struct inode *, struct dentry *);
@@ -111,11 +111,13 @@ const struct inode_operations nfs3_dir_inode_operations = {
 
 #ifdef CONFIG_NFS_V4
 
-static struct dentry *nfs_atomic_lookup(struct inode *, struct dentry *, struct nameidata *);
-static int nfs_open_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd);
+static int nfs_atomic_open(struct inode *, struct dentry *,
+                          struct file *, unsigned, umode_t,
+                          int *);
 const struct inode_operations nfs4_dir_inode_operations = {
-       .create         = nfs_open_create,
-       .lookup         = nfs_atomic_lookup,
+       .create         = nfs_create,
+       .lookup         = nfs_lookup,
+       .atomic_open    = nfs_atomic_open,
        .link           = nfs_link,
        .unlink         = nfs_unlink,
        .symlink        = nfs_symlink,
@@ -1028,28 +1030,15 @@ static int nfs_check_verifier(struct inode *dir, struct dentry *dentry)
        return 1;
 }
 
-/*
- * Return the intent data that applies to this particular path component
- *
- * Note that the current set of intents only apply to the very last
- * component of the path and none of them is set before that last
- * component.
- */
-static inline unsigned int nfs_lookup_check_intent(struct nameidata *nd,
-                                               unsigned int mask)
-{
-       return nd->flags & mask;
-}
-
 /*
  * Use intent information to check whether or not we're going to do
  * an O_EXCL create using this path component.
  */
-static int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
+static int nfs_is_exclusive_create(struct inode *dir, unsigned int flags)
 {
        if (NFS_PROTO(dir)->version == 2)
                return 0;
-       return nd && nfs_lookup_check_intent(nd, LOOKUP_EXCL);
+       return flags & LOOKUP_EXCL;
 }
 
 /*
@@ -1061,25 +1050,20 @@ static int nfs_is_exclusive_create(struct inode *dir, struct nameidata *nd)
  *
  */
 static inline
-int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd)
+int nfs_lookup_verify_inode(struct inode *inode, unsigned int flags)
 {
        struct nfs_server *server = NFS_SERVER(inode);
 
        if (IS_AUTOMOUNT(inode))
                return 0;
-       if (nd != NULL) {
-               /* VFS wants an on-the-wire revalidation */
-               if (nd->flags & LOOKUP_REVAL)
-                       goto out_force;
-               /* This is an open(2) */
-               if (nfs_lookup_check_intent(nd, LOOKUP_OPEN) != 0 &&
-                               !(server->flags & NFS_MOUNT_NOCTO) &&
-                               (S_ISREG(inode->i_mode) ||
-                                S_ISDIR(inode->i_mode)))
-                       goto out_force;
-               return 0;
-       }
-       return nfs_revalidate_inode(server, inode);
+       /* VFS wants an on-the-wire revalidation */
+       if (flags & LOOKUP_REVAL)
+               goto out_force;
+       /* This is an open(2) */
+       if ((flags & LOOKUP_OPEN) && !(server->flags & NFS_MOUNT_NOCTO) &&
+           (S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
+               goto out_force;
+       return 0;
 out_force:
        return __nfs_revalidate_inode(server, inode);
 }
@@ -1093,10 +1077,10 @@ out_force:
  */
 static inline
 int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
-                      struct nameidata *nd)
+                      unsigned int flags)
 {
        /* Don't revalidate a negative dentry if we're creating a new file */
-       if (nd != NULL && nfs_lookup_check_intent(nd, LOOKUP_CREATE) != 0)
+       if (flags & LOOKUP_CREATE)
                return 0;
        if (NFS_SERVER(dir)->flags & NFS_MOUNT_LOOKUP_CACHE_NONEG)
                return 1;
@@ -1114,7 +1098,7 @@ int nfs_neg_need_reval(struct inode *dir, struct dentry *dentry,
  * If the parent directory is seen to have changed, we throw out the
  * cached dentry and do a new lookup.
  */
-static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct inode *dir;
        struct inode *inode;
@@ -1123,7 +1107,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
        struct nfs_fattr *fattr = NULL;
        int error;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        parent = dget_parent(dentry);
@@ -1132,7 +1116,7 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
        inode = dentry->d_inode;
 
        if (!inode) {
-               if (nfs_neg_need_reval(dir, dentry, nd))
+               if (nfs_neg_need_reval(dir, dentry, flags))
                        goto out_bad;
                goto out_valid_noent;
        }
@@ -1148,8 +1132,8 @@ static int nfs_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
                goto out_set_verifier;
 
        /* Force a full look up iff the parent directory has changed */
-       if (!nfs_is_exclusive_create(dir, nd) && nfs_check_verifier(dir, dentry)) {
-               if (nfs_lookup_verify_inode(inode, nd))
+       if (!nfs_is_exclusive_create(dir, flags) && nfs_check_verifier(dir, dentry)) {
+               if (nfs_lookup_verify_inode(inode, flags))
                        goto out_zap_parent;
                goto out_valid;
        }
@@ -1286,7 +1270,7 @@ const struct dentry_operations nfs_dentry_operations = {
        .d_release      = nfs_d_release,
 };
 
-static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
 {
        struct dentry *res;
        struct dentry *parent;
@@ -1307,7 +1291,7 @@ static struct dentry *nfs_lookup(struct inode *dir, struct dentry * dentry, stru
         * If we're doing an exclusive create, optimize away the lookup
         * but don't hash the dentry.
         */
-       if (nfs_is_exclusive_create(dir, nd)) {
+       if (nfs_is_exclusive_create(dir, flags)) {
                d_instantiate(dentry, NULL);
                res = NULL;
                goto out;
@@ -1354,7 +1338,7 @@ out:
 }
 
 #ifdef CONFIG_NFS_V4
-static int nfs4_lookup_revalidate(struct dentry *, struct nameidata *);
+static int nfs4_lookup_revalidate(struct dentry *, unsigned int);
 
 const struct dentry_operations nfs4_dentry_operations = {
        .d_revalidate   = nfs4_lookup_revalidate,
@@ -1364,24 +1348,6 @@ const struct dentry_operations nfs4_dentry_operations = {
        .d_release      = nfs_d_release,
 };
 
-/*
- * Use intent information to determine whether we need to substitute
- * the NFSv4-style stateful OPEN for the LOOKUP call
- */
-static int is_atomic_open(struct nameidata *nd)
-{
-       if (nd == NULL || nfs_lookup_check_intent(nd, LOOKUP_OPEN) == 0)
-               return 0;
-       /* NFS does not (yet) have a stateful open for directories */
-       if (nd->flags & LOOKUP_DIRECTORY)
-               return 0;
-       /* Are we trying to write to a read only partition? */
-       if (__mnt_is_readonly(nd->path.mnt) &&
-           (nd->intent.open.flags & (O_CREAT|O_TRUNC|O_ACCMODE)))
-               return 0;
-       return 1;
-}
-
 static fmode_t flags_to_mode(int flags)
 {
        fmode_t res = (__force fmode_t)flags & FMODE_EXEC;
@@ -1403,136 +1369,143 @@ static int do_open(struct inode *inode, struct file *filp)
        return 0;
 }
 
-static int nfs_intent_set_file(struct nameidata *nd, struct nfs_open_context *ctx)
+static int nfs_finish_open(struct nfs_open_context *ctx,
+                          struct dentry *dentry,
+                          struct file *file, unsigned open_flags,
+                          int *opened)
 {
-       struct file *filp;
-       int ret = 0;
+       int err;
+
+       if (ctx->dentry != dentry) {
+               dput(ctx->dentry);
+               ctx->dentry = dget(dentry);
+       }
 
        /* If the open_intent is for execute, we have an extra check to make */
        if (ctx->mode & FMODE_EXEC) {
-               ret = nfs_may_open(ctx->dentry->d_inode,
-                               ctx->cred,
-                               nd->intent.open.flags);
-               if (ret < 0)
+               err = nfs_may_open(dentry->d_inode, ctx->cred, open_flags);
+               if (err < 0)
                        goto out;
        }
-       filp = lookup_instantiate_filp(nd, ctx->dentry, do_open);
-       if (IS_ERR(filp))
-               ret = PTR_ERR(filp);
-       else
-               nfs_file_set_open_context(filp, ctx);
+
+       err = finish_open(file, dentry, do_open, opened);
+       if (err)
+               goto out;
+       nfs_file_set_open_context(file, ctx);
+
 out:
        put_nfs_open_context(ctx);
-       return ret;
+       return err;
 }
 
-static struct dentry *nfs_atomic_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static int nfs_atomic_open(struct inode *dir, struct dentry *dentry,
+                           struct file *file, unsigned open_flags,
+                           umode_t mode, int *opened)
 {
        struct nfs_open_context *ctx;
-       struct iattr attr;
-       struct dentry *res = NULL;
+       struct dentry *res;
+       struct iattr attr = { .ia_valid = ATTR_OPEN };
        struct inode *inode;
-       int open_flags;
        int err;
 
-       dfprintk(VFS, "NFS: atomic_lookup(%s/%ld), %s\n",
+       /* Expect a negative dentry */
+       BUG_ON(dentry->d_inode);
+
+       dfprintk(VFS, "NFS: atomic_open(%s/%ld), %s\n",
                        dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
 
-       /* Check that we are indeed trying to open this file */
-       if (!is_atomic_open(nd))
+       /* NFS only supports OPEN on regular files */
+       if ((open_flags & O_DIRECTORY)) {
+               if (!d_unhashed(dentry)) {
+                       /*
+                        * Hashed negative dentry with O_DIRECTORY: dentry was
+                        * revalidated and is fine, no need to perform lookup
+                        * again
+                        */
+                       return -ENOENT;
+               }
                goto no_open;
-
-       if (dentry->d_name.len > NFS_SERVER(dir)->namelen) {
-               res = ERR_PTR(-ENAMETOOLONG);
-               goto out;
-       }
-
-       /* Let vfs_create() deal with O_EXCL. Instantiate, but don't hash
-        * the dentry. */
-       if (nd->flags & LOOKUP_EXCL) {
-               d_instantiate(dentry, NULL);
-               goto out;
        }
 
-       open_flags = nd->intent.open.flags;
-       attr.ia_valid = ATTR_OPEN;
-
-       ctx = create_nfs_open_context(dentry, open_flags);
-       res = ERR_CAST(ctx);
-       if (IS_ERR(ctx))
-               goto out;
+       if (dentry->d_name.len > NFS_SERVER(dir)->namelen)
+               return -ENAMETOOLONG;
 
-       if (nd->flags & LOOKUP_CREATE) {
-               attr.ia_mode = nd->intent.open.create_mode;
+       if (open_flags & O_CREAT) {
                attr.ia_valid |= ATTR_MODE;
-               attr.ia_mode &= ~current_umask();
-       } else
-               open_flags &= ~(O_EXCL | O_CREAT);
-
+               attr.ia_mode = mode & ~current_umask();
+       }
        if (open_flags & O_TRUNC) {
                attr.ia_valid |= ATTR_SIZE;
                attr.ia_size = 0;
        }
 
-       /* Open the file on the server */
+       ctx = create_nfs_open_context(dentry, open_flags);
+       err = PTR_ERR(ctx);
+       if (IS_ERR(ctx))
+               goto out;
+
        nfs_block_sillyrename(dentry->d_parent);
        inode = NFS_PROTO(dir)->open_context(dir, ctx, open_flags, &attr);
+       d_drop(dentry);
        if (IS_ERR(inode)) {
                nfs_unblock_sillyrename(dentry->d_parent);
                put_nfs_open_context(ctx);
-               switch (PTR_ERR(inode)) {
-                       /* Make a negative dentry */
-                       case -ENOENT:
-                               d_add(dentry, NULL);
-                               res = NULL;
-                               goto out;
-                       /* This turned out not to be a regular file */
-                       case -EISDIR:
-                       case -ENOTDIR:
+               err = PTR_ERR(inode);
+               switch (err) {
+               case -ENOENT:
+                       d_add(dentry, NULL);
+                       break;
+               case -EISDIR:
+               case -ENOTDIR:
+                       goto no_open;
+               case -ELOOP:
+                       if (!(open_flags & O_NOFOLLOW))
                                goto no_open;
-                       case -ELOOP:
-                               if (!(nd->intent.open.flags & O_NOFOLLOW))
-                                       goto no_open;
+                       break;
                        /* case -EINVAL: */
-                       default:
-                               res = ERR_CAST(inode);
-                               goto out;
+               default:
+                       break;
                }
+               goto out;
        }
        res = d_add_unique(dentry, inode);
-       nfs_unblock_sillyrename(dentry->d_parent);
-       if (res != NULL) {
-               dput(ctx->dentry);
-               ctx->dentry = dget(res);
+       if (res != NULL)
                dentry = res;
-       }
-       err = nfs_intent_set_file(nd, ctx);
-       if (err < 0) {
-               if (res != NULL)
-                       dput(res);
-               return ERR_PTR(err);
-       }
-out:
+
+       nfs_unblock_sillyrename(dentry->d_parent);
        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-       return res;
+
+       err = nfs_finish_open(ctx, dentry, file, open_flags, opened);
+
+       dput(res);
+out:
+       return err;
+
 no_open:
-       return nfs_lookup(dir, dentry, nd);
+       res = nfs_lookup(dir, dentry, 0);
+       err = PTR_ERR(res);
+       if (IS_ERR(res))
+               goto out;
+
+       return finish_no_open(file, res);
 }
 
-static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int nfs4_lookup_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct dentry *parent = NULL;
        struct inode *inode;
        struct inode *dir;
-       int openflags, ret = 0;
+       int ret = 0;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
-       inode = dentry->d_inode;
-       if (!is_atomic_open(nd) || d_mountpoint(dentry))
+       if (!(flags & LOOKUP_OPEN) || (flags & LOOKUP_DIRECTORY))
+               goto no_open;
+       if (d_mountpoint(dentry))
                goto no_open;
 
+       inode = dentry->d_inode;
        parent = dget_parent(dentry);
        dir = parent->d_inode;
 
@@ -1540,7 +1513,7 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
         * optimize away revalidation of negative dentries.
         */
        if (inode == NULL) {
-               if (!nfs_neg_need_reval(dir, dentry, nd))
+               if (!nfs_neg_need_reval(dir, dentry, flags))
                        ret = 1;
                goto out;
        }
@@ -1548,9 +1521,8 @@ static int nfs4_lookup_revalidate(struct dentry *dentry, struct nameidata *nd)
        /* NFS only supports OPEN on regular files */
        if (!S_ISREG(inode->i_mode))
                goto no_open_dput;
-       openflags = nd->intent.open.flags;
        /* We cannot do exclusive creation on a positive dentry */
-       if ((openflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL))
+       if (flags & LOOKUP_EXCL)
                goto no_open_dput;
 
        /* Let f_op->open() actually open (and revalidate) the file */
@@ -1563,48 +1535,7 @@ out:
 no_open_dput:
        dput(parent);
 no_open:
-       return nfs_lookup_revalidate(dentry, nd);
-}
-
-static int nfs_open_create(struct inode *dir, struct dentry *dentry,
-               umode_t mode, struct nameidata *nd)
-{
-       struct nfs_open_context *ctx = NULL;
-       struct iattr attr;
-       int error;
-       int open_flags = O_CREAT|O_EXCL;
-
-       dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
-                       dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
-
-       attr.ia_mode = mode;
-       attr.ia_valid = ATTR_MODE;
-
-       if (nd)
-               open_flags = nd->intent.open.flags;
-
-       ctx = create_nfs_open_context(dentry, open_flags);
-       error = PTR_ERR(ctx);
-       if (IS_ERR(ctx))
-               goto out_err_drop;
-
-       error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, ctx);
-       if (error != 0)
-               goto out_put_ctx;
-       if (nd) {
-               error = nfs_intent_set_file(nd, ctx);
-               if (error < 0)
-                       goto out_err;
-       } else {
-               put_nfs_open_context(ctx);
-       }
-       return 0;
-out_put_ctx:
-       put_nfs_open_context(ctx);
-out_err_drop:
-       d_drop(dentry);
-out_err:
-       return error;
+       return nfs_lookup_revalidate(dentry, flags);
 }
 
 #endif /* CONFIG_NFSV4 */
@@ -1658,11 +1589,11 @@ out_error:
  * reply path made it appear to have failed.
  */
 static int nfs_create(struct inode *dir, struct dentry *dentry,
-               umode_t mode, struct nameidata *nd)
+               umode_t mode, bool excl)
 {
        struct iattr attr;
+       int open_flags = excl ? O_CREAT | O_EXCL : O_CREAT;
        int error;
-       int open_flags = O_CREAT|O_EXCL;
 
        dfprintk(VFS, "NFS: create(%s/%ld), %s\n",
                        dir->i_sb->s_id, dir->i_ino, dentry->d_name.name);
@@ -1670,10 +1601,7 @@ static int nfs_create(struct inode *dir, struct dentry *dentry,
        attr.ia_mode = mode;
        attr.ia_valid = ATTR_MODE;
 
-       if (nd)
-               open_flags = nd->intent.open.flags;
-
-       error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags, NULL);
+       error = NFS_PROTO(dir)->create(dir, dentry, &attr, open_flags);
        if (error != 0)
                goto out_err;
        return 0;
index 8abfb19bd3aa3b739611ce1f97025d643539b09c..a67990f90bd7d28bdea3310514e4a88275eadc14 100644 (file)
@@ -62,7 +62,7 @@ static int nfs_superblock_set_dummy_root(struct super_block *sb, struct inode *i
                 */
                spin_lock(&sb->s_root->d_inode->i_lock);
                spin_lock(&sb->s_root->d_lock);
-               list_del_init(&sb->s_root->d_alias);
+               hlist_del_init(&sb->s_root->d_alias);
                spin_unlock(&sb->s_root->d_lock);
                spin_unlock(&sb->s_root->d_inode->i_lock);
        }
index 2292a0fd2bffd3b042b43e9dc4b607acbd0eb6ad..3187e24e8f78f41ffa3f78b55ccf42ff29d167f0 100644 (file)
@@ -314,7 +314,7 @@ static void nfs3_free_createdata(struct nfs3_createdata *data)
  */
 static int
 nfs3_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                int flags, struct nfs_open_context *ctx)
+                int flags)
 {
        struct nfs3_createdata *data;
        umode_t mode = sattr->ia_mode;
index 15fc7e4664ed53206074df177efd74e30dd13521..c157b2089b475c22c046a15f293236f7725a4ee7 100644 (file)
@@ -2806,37 +2806,22 @@ static int nfs4_proc_readlink(struct inode *inode, struct page *page,
 }
 
 /*
- * Got race?
- * We will need to arrange for the VFS layer to provide an atomic open.
- * Until then, this create/open method is prone to inefficiency and race
- * conditions due to the lookup, create, and open VFS calls from sys_open()
- * placed on the wire.
- *
- * Given the above sorry state of affairs, I'm simply sending an OPEN.
- * The file will be opened again in the subsequent VFS open call
- * (nfs4_proc_file_open).
- *
- * The open for read will just hang around to be used by any process that
- * opens the file O_RDONLY. This will all be resolved with the VFS changes.
+ * This is just for mknod.  open(O_CREAT) will always do ->open_context().
  */
-
 static int
 nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-                 int flags, struct nfs_open_context *ctx)
+                int flags)
 {
-       struct dentry *de = dentry;
+       struct nfs_open_context *ctx;
        struct nfs4_state *state;
-       struct rpc_cred *cred = NULL;
-       fmode_t fmode = 0;
        int status = 0;
 
-       if (ctx != NULL) {
-               cred = ctx->cred;
-               de = ctx->dentry;
-               fmode = ctx->mode;
-       }
+       ctx = alloc_nfs_open_context(dentry, FMODE_READ);
+       if (IS_ERR(ctx))
+               return PTR_ERR(ctx);
+
        sattr->ia_mode &= ~current_umask();
-       state = nfs4_do_open(dir, de, fmode, flags, sattr, cred, NULL);
+       state = nfs4_do_open(dir, dentry, ctx->mode, flags, sattr, ctx->cred, NULL);
        d_drop(dentry);
        if (IS_ERR(state)) {
                status = PTR_ERR(state);
@@ -2844,11 +2829,9 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
        }
        d_add(dentry, igrab(state->inode));
        nfs_set_verifier(dentry, nfs_save_change_attribute(dir));
-       if (ctx != NULL)
-               ctx->state = state;
-       else
-               nfs4_close_sync(state, fmode);
+       ctx->state = state;
 out:
+       put_nfs_open_context(ctx);
        return status;
 }
 
index b47277baebab92930bee6c1fbac445fd8978a6b9..f50d3e8d6f2230a42cdc656b61004dcf62182dd2 100644 (file)
@@ -454,7 +454,10 @@ int objio_read_pagelist(struct nfs_read_data *rdata)
        objios->ios->done = _read_done;
        dprintk("%s: offset=0x%llx length=0x%x\n", __func__,
                rdata->args.offset, rdata->args.count);
-       return ore_read(objios->ios);
+       ret = ore_read(objios->ios);
+       if (unlikely(ret))
+               objio_free_result(&objios->oir);
+       return ret;
 }
 
 /*
@@ -486,8 +489,16 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
        struct nfs_write_data *wdata = objios->oir.rpcdata;
        struct address_space *mapping = wdata->header->inode->i_mapping;
        pgoff_t index = offset / PAGE_SIZE;
-       struct page *page = find_get_page(mapping, index);
+       struct page *page;
+       loff_t i_size = i_size_read(wdata->header->inode);
+
+       if (offset >= i_size) {
+               *uptodate = true;
+               dprintk("%s: g_zero_page index=0x%lx\n", __func__, index);
+               return ZERO_PAGE(0);
+       }
 
+       page = find_get_page(mapping, index);
        if (!page) {
                page = find_or_create_page(mapping, index, GFP_NOFS);
                if (unlikely(!page)) {
@@ -507,8 +518,10 @@ static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
 
 static void __r4w_put_page(void *priv, struct page *page)
 {
-       dprintk("%s: index=0x%lx\n", __func__, page->index);
-       page_cache_release(page);
+       dprintk("%s: index=0x%lx\n", __func__,
+               (page == ZERO_PAGE(0)) ? -1UL : page->index);
+       if (ZERO_PAGE(0) != page)
+               page_cache_release(page);
        return;
 }
 
@@ -539,8 +552,10 @@ int objio_write_pagelist(struct nfs_write_data *wdata, int how)
        dprintk("%s: offset=0x%llx length=0x%x\n", __func__,
                wdata->args.offset, wdata->args.count);
        ret = ore_write(objios->ios);
-       if (unlikely(ret))
+       if (unlikely(ret)) {
+               objio_free_result(&objios->oir);
                return ret;
+       }
 
        if (objios->sync)
                _write_done(objios->ios, objios);
index 617c7419a08ef5d0b107292bb626b84b99916b2d..4433806e116f9a4b26f605c4ef986a1633eb3efd 100644 (file)
@@ -259,7 +259,7 @@ static void nfs_free_createdata(const struct nfs_createdata *data)
 
 static int
 nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
-               int flags, struct nfs_open_context *ctx)
+               int flags)
 {
        struct nfs_createdata *data;
        struct rpc_message msg = {
index 06228192f64efb52e8466afd2334bc04952d50a4..8b2a2977b720729f2a63a4d7bb8e5e4b7de5522e 100644 (file)
@@ -2419,7 +2419,7 @@ static struct dentry *nfs_fs_mount_common(struct file_system_type *fs_type,
                sb_mntdata.mntflags |= MS_SYNCHRONOUS;
 
        /* Get a superblock - note that we may end up sharing one that already exists */
-       s = sget(fs_type, compare_super, nfs_set_super, &sb_mntdata);
+       s = sget(fs_type, compare_super, nfs_set_super, flags, &sb_mntdata);
        if (IS_ERR(s)) {
                mntroot = ERR_CAST(s);
                goto out_err_nosb;
index c8bd9c3be7f747410622fd1172b2c7243886f838..4700a0a929d72baeb0c86024a1c5051e6d19cab5 100644 (file)
@@ -745,7 +745,7 @@ __be32
 nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
                        int may_flags, struct file **filp)
 {
-       struct dentry   *dentry;
+       struct path     path;
        struct inode    *inode;
        int             flags = O_RDONLY|O_LARGEFILE;
        __be32          err;
@@ -762,8 +762,9 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
        if (err)
                goto out;
 
-       dentry = fhp->fh_dentry;
-       inode = dentry->d_inode;
+       path.mnt = fhp->fh_export->ex_path.mnt;
+       path.dentry = fhp->fh_dentry;
+       inode = path.dentry->d_inode;
 
        /* Disallow write access to files with the append-only bit set
         * or any access when mandatory locking enabled
@@ -792,8 +793,7 @@ nfsd_open(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type,
                else
                        flags = O_WRONLY|O_LARGEFILE;
        }
-       *filp = dentry_open(dget(dentry), mntget(fhp->fh_export->ex_path.mnt),
-                           flags, current_cred());
+       *filp = dentry_open(&path, flags, current_cred());
        if (IS_ERR(*filp))
                host_err = PTR_ERR(*filp);
        else {
@@ -1329,7 +1329,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
        err = 0;
        switch (type) {
        case S_IFREG:
-               host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
+               host_err = vfs_create(dirp, dchild, iap->ia_mode, true);
                if (!host_err)
                        nfsd_check_ignore_resizing(iap);
                break;
@@ -1492,7 +1492,7 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp,
                goto out;
        }
 
-       host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL);
+       host_err = vfs_create(dirp, dchild, iap->ia_mode, true);
        if (host_err < 0) {
                fh_drop_write(fhp);
                goto out_nfserr;
index b72847988b78d96d99b7571d17fea769e463c6b0..1d0c0b84c5a319e61e24f04f3d643f9284b6cee6 100644 (file)
@@ -63,7 +63,7 @@ static inline int nilfs_add_nondir(struct dentry *dentry, struct inode *inode)
  */
 
 static struct dentry *
-nilfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+nilfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode;
        ino_t ino;
@@ -85,7 +85,7 @@ nilfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
  * with d_instantiate().
  */
 static int nilfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                       struct nameidata *nd)
+                       bool excl)
 {
        struct inode *inode;
        struct nilfs_transaction_info ti;
index 1099a76cee5962838841a9719a0758e4defcb2d3..d57c42f974ea3ccb78dfccccc34cbbedf9603004 100644 (file)
@@ -1288,7 +1288,8 @@ nilfs_mount(struct file_system_type *fs_type, int flags,
                err = -EBUSY;
                goto failed;
        }
-       s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, sd.bdev);
+       s = sget(fs_type, nilfs_test_bdev_super, nilfs_set_bdev_super, flags,
+                sd.bdev);
        mutex_unlock(&sd.bdev->bd_fsfreeze_mutex);
        if (IS_ERR(s)) {
                err = PTR_ERR(s);
@@ -1301,7 +1302,6 @@ nilfs_mount(struct file_system_type *fs_type, int flags,
                s_new = true;
 
                /* New superblock instance created */
-               s->s_flags = flags;
                s->s_mode = mode;
                strlcpy(s->s_id, bdevname(sd.bdev, b), sizeof(s->s_id));
                sb_set_blocksize(s, block_size(sd.bdev));
index 3568c8a8b1387aea2845d6998b2b7e6d1dc6dcb2..d43803669739df471e8e832ced4377f6f75ab015 100644 (file)
@@ -61,8 +61,6 @@ static struct fsnotify_event *get_one_event(struct fsnotify_group *group,
 static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)
 {
        int client_fd;
-       struct dentry *dentry;
-       struct vfsmount *mnt;
        struct file *new_file;
 
        pr_debug("%s: group=%p event=%p\n", __func__, group, event);
@@ -81,12 +79,10 @@ static int create_fd(struct fsnotify_group *group, struct fsnotify_event *event)
         * we need a new file handle for the userspace program so it can read even if it was
         * originally opened O_WRONLY.
         */
-       dentry = dget(event->path.dentry);
-       mnt = mntget(event->path.mnt);
        /* it's possible this event was an overflow event.  in that case dentry and mnt
         * are NULL;  That's fine, just don't call dentry open */
-       if (dentry && mnt)
-               new_file = dentry_open(dentry, mnt,
+       if (event->path.dentry && event->path.mnt)
+               new_file = dentry_open(&event->path,
                                       group->fanotify_data.f_flags | FMODE_NONOTIFY,
                                       current_cred());
        else
index b39c5c161adb64bff0d33faa64f41d8f4a9942cd..6baadb5a84307d176cd87ad99f399992ddff9519 100644 (file)
@@ -52,6 +52,7 @@ void __fsnotify_vfsmount_delete(struct vfsmount *mnt)
 void __fsnotify_update_child_dentry_flags(struct inode *inode)
 {
        struct dentry *alias;
+       struct hlist_node *p;
        int watched;
 
        if (!S_ISDIR(inode->i_mode))
@@ -63,7 +64,7 @@ void __fsnotify_update_child_dentry_flags(struct inode *inode)
        spin_lock(&inode->i_lock);
        /* run all of the dentries associated with this inode.  Since this is a
         * directory, there damn well better only be one item on this list */
-       list_for_each_entry(alias, &inode->i_dentry, d_alias) {
+       hlist_for_each_entry(alias, p, &inode->i_dentry, d_alias) {
                struct dentry *child;
 
                /* run all of the children of the original inode and fix their
index 358273e59aded3d416dea0f1e67627731d9d0d8f..436f36037e094577592576e71054a2cf350a29bb 100644 (file)
  * Locking: Caller must hold i_mutex on the directory.
  */
 static struct dentry *ntfs_lookup(struct inode *dir_ino, struct dentry *dent,
-               struct nameidata *nd)
+               unsigned int flags)
 {
        ntfs_volume *vol = NTFS_SB(dir_ino->i_sb);
        struct inode *dent_inode;
index e5ba348183321d133ab7f75c715b305dbed28a07..8db4b58b2e4b2e92a5e6fe42c7c71c657866c125 100644 (file)
@@ -49,14 +49,13 @@ void ocfs2_dentry_attach_gen(struct dentry *dentry)
 }
 
 
-static int ocfs2_dentry_revalidate(struct dentry *dentry,
-                                  struct nameidata *nd)
+static int ocfs2_dentry_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode;
        int ret = 0;    /* if all else fails, just return false */
        struct ocfs2_super *osb;
 
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        inode = dentry->d_inode;
@@ -170,13 +169,11 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode,
                                      u64 parent_blkno,
                                      int skip_unhashed)
 {
-       struct list_head *p;
-       struct dentry *dentry = NULL;
+       struct hlist_node *p;
+       struct dentry *dentry;
 
        spin_lock(&inode->i_lock);
-       list_for_each(p, &inode->i_dentry) {
-               dentry = list_entry(p, struct dentry, d_alias);
-
+       hlist_for_each_entry(dentry, p, &inode->i_dentry, d_alias) {
                spin_lock(&dentry->d_lock);
                if (ocfs2_match_dentry(dentry, parent_blkno, skip_unhashed)) {
                        trace_ocfs2_find_local_alias(dentry->d_name.len,
@@ -184,16 +181,13 @@ struct dentry *ocfs2_find_local_alias(struct inode *inode,
 
                        dget_dlock(dentry);
                        spin_unlock(&dentry->d_lock);
-                       break;
+                       spin_unlock(&inode->i_lock);
+                       return dentry;
                }
                spin_unlock(&dentry->d_lock);
-
-               dentry = NULL;
        }
-
        spin_unlock(&inode->i_lock);
-
-       return dentry;
+       return NULL;
 }
 
 DEFINE_SPINLOCK(dentry_attach_lock);
index e31d6ae013abba789b8d72591e8a460f6a8c7afc..83b6f98e0665433bda36a2f1d4f34a1ce7bec4cd 100644 (file)
@@ -526,7 +526,7 @@ bail:
 static int dlmfs_create(struct inode *dir,
                        struct dentry *dentry,
                        umode_t mode,
-                       struct nameidata *nd)
+                       bool excl)
 {
        int status = 0;
        struct inode *inode;
index 9f39c640cddf2076b951295dde5ef68217b26452..f1fd0741162b63baeaed44d6f4118a23df7c3c32 100644 (file)
@@ -98,7 +98,7 @@ static int ocfs2_create_symlink_data(struct ocfs2_super *osb,
 #define OCFS2_ORPHAN_NAMELEN ((int)(2 * sizeof(u64)))
 
 static struct dentry *ocfs2_lookup(struct inode *dir, struct dentry *dentry,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        int status;
        u64 blkno;
@@ -618,7 +618,7 @@ static int ocfs2_mkdir(struct inode *dir,
 static int ocfs2_create(struct inode *dir,
                        struct dentry *dentry,
                        umode_t mode,
-                       struct nameidata *nd)
+                       bool excl)
 {
        int ret;
 
index f00576ec320f26384a021d8cecab6fbcde93dd6a..fb5b3ff79dc6c232161fd89e35d4a23079a62a74 100644 (file)
@@ -285,13 +285,13 @@ static int omfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 }
 
 static int omfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        return omfs_add_node(dir, dentry, mode | S_IFREG);
 }
 
 static struct dentry *omfs_lookup(struct inode *dir, struct dentry *dentry,
-                                 struct nameidata *nd)
+                                 unsigned int flags)
 {
        struct buffer_head *bh;
        struct inode *inode = NULL;
index 1540632d8387fe98a51d0193201346acb18ae70e..1e914b397e129f311875eb15d0c7679ace93aa3e 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -537,25 +537,6 @@ static int chown_common(struct path *path, uid_t user, gid_t group)
        return error;
 }
 
-SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
-{
-       struct path path;
-       int error;
-
-       error = user_path(filename, &path);
-       if (error)
-               goto out;
-       error = mnt_want_write(path.mnt);
-       if (error)
-               goto out_release;
-       error = chown_common(&path, user, group);
-       mnt_drop_write(path.mnt);
-out_release:
-       path_put(&path);
-out:
-       return error;
-}
-
 SYSCALL_DEFINE5(fchownat, int, dfd, const char __user *, filename, uid_t, user,
                gid_t, group, int, flag)
 {
@@ -583,23 +564,15 @@ out:
        return error;
 }
 
-SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group)
+SYSCALL_DEFINE3(chown, const char __user *, filename, uid_t, user, gid_t, group)
 {
-       struct path path;
-       int error;
+       return sys_fchownat(AT_FDCWD, filename, user, group, 0);
+}
 
-       error = user_lpath(filename, &path);
-       if (error)
-               goto out;
-       error = mnt_want_write(path.mnt);
-       if (error)
-               goto out_release;
-       error = chown_common(&path, user, group);
-       mnt_drop_write(path.mnt);
-out_release:
-       path_put(&path);
-out:
-       return error;
+SYSCALL_DEFINE3(lchown, const char __user *, filename, uid_t, user, gid_t, group)
+{
+       return sys_fchownat(AT_FDCWD, filename, user, group,
+                           AT_SYMLINK_NOFOLLOW);
 }
 
 SYSCALL_DEFINE3(fchown, unsigned int, fd, uid_t, user, gid_t, group)
@@ -667,10 +640,9 @@ int open_check_o_direct(struct file *f)
        return 0;
 }
 
-static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt,
-                                  struct file *f,
-                                  int (*open)(struct inode *, struct file *),
-                                  const struct cred *cred)
+static int do_dentry_open(struct file *f,
+                         int (*open)(struct inode *, struct file *),
+                         const struct cred *cred)
 {
        static const struct file_operations empty_fops = {};
        struct inode *inode;
@@ -682,9 +654,9 @@ static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt,
        if (unlikely(f->f_flags & O_PATH))
                f->f_mode = FMODE_PATH;
 
-       inode = dentry->d_inode;
+       inode = f->f_path.dentry->d_inode;
        if (f->f_mode & FMODE_WRITE) {
-               error = __get_file_write_access(inode, mnt);
+               error = __get_file_write_access(inode, f->f_path.mnt);
                if (error)
                        goto cleanup_file;
                if (!special_file(inode->i_mode))
@@ -692,14 +664,12 @@ static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt,
        }
 
        f->f_mapping = inode->i_mapping;
-       f->f_path.dentry = dentry;
-       f->f_path.mnt = mnt;
        f->f_pos = 0;
        file_sb_list_add(f, inode->i_sb);
 
        if (unlikely(f->f_mode & FMODE_PATH)) {
                f->f_op = &empty_fops;
-               return f;
+               return 0;
        }
 
        f->f_op = fops_get(inode->i_fop);
@@ -726,10 +696,11 @@ static struct file *do_dentry_open(struct dentry *dentry, struct vfsmount *mnt,
 
        file_ra_state_init(&f->f_ra, f->f_mapping->host->i_mapping);
 
-       return f;
+       return 0;
 
 cleanup_all:
        fops_put(f->f_op);
+       file_sb_list_del(f);
        if (f->f_mode & FMODE_WRITE) {
                put_write_access(inode);
                if (!special_file(inode->i_mode)) {
@@ -740,124 +711,62 @@ cleanup_all:
                         * here, so just reset the state.
                         */
                        file_reset_write(f);
-                       mnt_drop_write(mnt);
+                       mnt_drop_write(f->f_path.mnt);
                }
        }
-       file_sb_list_del(f);
-       f->f_path.dentry = NULL;
-       f->f_path.mnt = NULL;
 cleanup_file:
-       dput(dentry);
-       mntput(mnt);
-       return ERR_PTR(error);
-}
-
-static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
-                               struct file *f,
-                               int (*open)(struct inode *, struct file *),
-                               const struct cred *cred)
-{
-       struct file *res = do_dentry_open(dentry, mnt, f, open, cred);
-       if (!IS_ERR(res)) {
-               int error = open_check_o_direct(f);
-               if (error) {
-                       fput(res);
-                       res = ERR_PTR(error);
-               }
-       } else {
-               put_filp(f);
-       }
-       return res;
+       path_put(&f->f_path);
+       f->f_path.mnt = NULL;
+       f->f_path.dentry = NULL;
+       return error;
 }
 
 /**
- * lookup_instantiate_filp - instantiates the open intent filp
- * @nd: pointer to nameidata
+ * finish_open - finish opening a file
+ * @od: opaque open data
  * @dentry: pointer to dentry
  * @open: open callback
  *
- * Helper for filesystems that want to use lookup open intents and pass back
- * a fully instantiated struct file to the caller.
- * This function is meant to be called from within a filesystem's
- * lookup method.
- * Beware of calling it for non-regular files! Those ->open methods might block
- * (e.g. in fifo_open), leaving you with parent locked (and in case of fifo,
- * leading to a deadlock, as nobody can open that fifo anymore, because
- * another process to open fifo will block on locked parent when doing lookup).
- * Note that in case of error, nd->intent.open.file is destroyed, but the
- * path information remains valid.
+ * This can be used to finish opening a file passed to i_op->atomic_open().
+ *
  * If the open callback is set to NULL, then the standard f_op->open()
  * filesystem callback is substituted.
  */
-struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
-               int (*open)(struct inode *, struct file *))
+int finish_open(struct file *file, struct dentry *dentry,
+               int (*open)(struct inode *, struct file *),
+               int *opened)
 {
-       const struct cred *cred = current_cred();
+       int error;
+       BUG_ON(*opened & FILE_OPENED); /* once it's opened, it's opened */
 
-       if (IS_ERR(nd->intent.open.file))
-               goto out;
-       if (IS_ERR(dentry))
-               goto out_err;
-       nd->intent.open.file = __dentry_open(dget(dentry), mntget(nd->path.mnt),
-                                            nd->intent.open.file,
-                                            open, cred);
-out:
-       return nd->intent.open.file;
-out_err:
-       release_open_intent(nd);
-       nd->intent.open.file = ERR_CAST(dentry);
-       goto out;
+       mntget(file->f_path.mnt);
+       file->f_path.dentry = dget(dentry);
+
+       error = do_dentry_open(file, open, current_cred());
+       if (!error)
+               *opened |= FILE_OPENED;
+
+       return error;
 }
-EXPORT_SYMBOL_GPL(lookup_instantiate_filp);
+EXPORT_SYMBOL(finish_open);
 
 /**
- * nameidata_to_filp - convert a nameidata to an open filp.
- * @nd: pointer to nameidata
- * @flags: open flags
+ * finish_no_open - finish ->atomic_open() without opening the file
+ *
+ * @od: opaque open data
+ * @dentry: dentry or NULL (as returned from ->lookup())
  *
- * Note that this function destroys the original nameidata
+ * This can be used to set the result of a successful lookup in ->atomic_open().
+ * The filesystem's atomic_open() method shall return NULL after calling this.
  */
-struct file *nameidata_to_filp(struct nameidata *nd)
+int finish_no_open(struct file *file, struct dentry *dentry)
 {
-       const struct cred *cred = current_cred();
-       struct file *filp;
-
-       /* Pick up the filp from the open intent */
-       filp = nd->intent.open.file;
-
-       /* Has the filesystem initialised the file for us? */
-       if (filp->f_path.dentry != NULL) {
-               nd->intent.open.file = NULL;
-       } else {
-               struct file *res;
-
-               path_get(&nd->path);
-               res = do_dentry_open(nd->path.dentry, nd->path.mnt,
-                                    filp, NULL, cred);
-               if (!IS_ERR(res)) {
-                       int error;
-
-                       nd->intent.open.file = NULL;
-                       BUG_ON(res != filp);
-
-                       error = open_check_o_direct(filp);
-                       if (error) {
-                               fput(filp);
-                               filp = ERR_PTR(error);
-                       }
-               } else {
-                       /* Allow nd->intent.open.file to be recycled */
-                       filp = res;
-               }
-       }
-       return filp;
+       file->f_path.dentry = dentry;
+       return 1;
 }
+EXPORT_SYMBOL(finish_no_open);
 
-/*
- * dentry_open() will have done dput(dentry) and mntput(mnt) if it returns an
- * error.
- */
-struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
+struct file *dentry_open(const struct path *path, int flags,
                         const struct cred *cred)
 {
        int error;
@@ -866,18 +775,28 @@ struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags,
        validate_creds(cred);
 
        /* We must always pass in a valid mount pointer. */
-       BUG_ON(!mnt);
+       BUG_ON(!path->mnt);
 
        error = -ENFILE;
        f = get_empty_filp();
-       if (f == NULL) {
-               dput(dentry);
-               mntput(mnt);
+       if (f == NULL)
                return ERR_PTR(error);
-       }
 
        f->f_flags = flags;
-       return __dentry_open(dentry, mnt, f, NULL, cred);
+       f->f_path = *path;
+       path_get(&f->f_path);
+       error = do_dentry_open(f, NULL, cred);
+       if (!error) {
+               error = open_check_o_direct(f);
+               if (error) {
+                       fput(f);
+                       f = ERR_PTR(error);
+               }
+       } else { 
+               put_filp(f);
+               f = ERR_PTR(error);
+       }
+       return f;
 }
 EXPORT_SYMBOL(dentry_open);
 
index bc49c975d501bad147ee9ac64fdafc5579de6d01..4a3477949bca6da23a13161708e0ee7168fdb654 100644 (file)
@@ -170,13 +170,13 @@ static const struct file_operations openprom_operations = {
        .llseek         = generic_file_llseek,
 };
 
-static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, struct nameidata *);
+static struct dentry *openpromfs_lookup(struct inode *, struct dentry *, unsigned int);
 
 static const struct inode_operations openprom_inode_operations = {
        .lookup         = openpromfs_lookup,
 };
 
-static struct dentry *openpromfs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *openpromfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        struct op_inode_info *ent_oi, *oi = OP_I(dir);
        struct device_node *dp, *child;
index bed378db075813350362c39f423d1b4335240bfa..3e000a51ac0d09556d184d26422a91d0bc4c0ff9 100644 (file)
@@ -237,8 +237,9 @@ int propagate_mnt(struct mount *dest_mnt, struct dentry *dest_dentry,
 
                source =  get_source(m, prev_dest_mnt, prev_src_mnt, &type);
 
-               if (!(child = copy_tree(source, source->mnt.mnt_root, type))) {
-                       ret = -ENOMEM;
+               child = copy_tree(source, source->mnt.mnt_root, type);
+               if (IS_ERR(child)) {
+                       ret = PTR_ERR(child);
                        list_splice(tree_list, tmp_list.prev);
                        goto out;
                }
index 437195f204e14e908bdda87ace0e8b0ce81efb21..2772208338f811c6b5d5bc067c490fe8725ba3cb 100644 (file)
@@ -1427,16 +1427,19 @@ static int proc_exe_link(struct dentry *dentry, struct path *exe_path)
 static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
 {
        struct inode *inode = dentry->d_inode;
+       struct path path;
        int error = -EACCES;
 
-       /* We don't need a base pointer in the /proc filesystem */
-       path_put(&nd->path);
-
        /* Are we allowed to snoop on the tasks file descriptors? */
        if (!proc_fd_access_allowed(inode))
                goto out;
 
-       error = PROC_I(inode)->op.proc_get_link(dentry, &nd->path);
+       error = PROC_I(inode)->op.proc_get_link(dentry, &path);
+       if (error)
+               goto out;
+
+       nd_jump_link(nd, &path);
+       return NULL;
 out:
        return ERR_PTR(error);
 }
@@ -1601,13 +1604,13 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
  * made this apply to all per process world readable and executable
  * directories.
  */
-int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
+int pid_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode;
        struct task_struct *task;
        const struct cred *cred;
 
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        inode = dentry->d_inode;
@@ -1781,7 +1784,7 @@ static int proc_fd_link(struct dentry *dentry, struct path *path)
        return proc_fd_info(dentry->d_inode, path, NULL);
 }
 
-static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int tid_fd_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct inode *inode;
        struct task_struct *task;
@@ -1789,7 +1792,7 @@ static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
        struct files_struct *files;
        const struct cred *cred;
 
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        inode = dentry->d_inode;
@@ -1868,7 +1871,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
        d_set_d_op(dentry, &tid_fd_dentry_operations);
        d_add(dentry, inode);
        /* Close the race of the process dying before we return the dentry */
-       if (tid_fd_revalidate(dentry, NULL))
+       if (tid_fd_revalidate(dentry, 0))
                error = NULL;
 
  out:
@@ -1956,7 +1959,7 @@ out_no_task:
 }
 
 static struct dentry *proc_lookupfd(struct inode *dir, struct dentry *dentry,
-                                   struct nameidata *nd)
+                                   unsigned int flags)
 {
        return proc_lookupfd_common(dir, dentry, proc_fd_instantiate);
 }
@@ -2003,7 +2006,7 @@ static int dname_to_vma_addr(struct dentry *dentry,
        return 0;
 }
 
-static int map_files_d_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int map_files_d_revalidate(struct dentry *dentry, unsigned int flags)
 {
        unsigned long vm_start, vm_end;
        bool exact_vma_exists = false;
@@ -2013,7 +2016,7 @@ static int map_files_d_revalidate(struct dentry *dentry, struct nameidata *nd)
        struct inode *inode;
        int status = 0;
 
-       if (nd && nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        if (!capable(CAP_SYS_ADMIN)) {
@@ -2145,7 +2148,7 @@ proc_map_files_instantiate(struct inode *dir, struct dentry *dentry,
 }
 
 static struct dentry *proc_map_files_lookup(struct inode *dir,
-               struct dentry *dentry, struct nameidata *nd)
+               struct dentry *dentry, unsigned int flags)
 {
        unsigned long vm_start, vm_end;
        struct vm_area_struct *vma;
@@ -2371,7 +2374,7 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
        d_set_d_op(dentry, &tid_fd_dentry_operations);
        d_add(dentry, inode);
        /* Close the race of the process dying before we return the dentry */
-       if (tid_fd_revalidate(dentry, NULL))
+       if (tid_fd_revalidate(dentry, 0))
                error = NULL;
 
  out:
@@ -2380,7 +2383,7 @@ static struct dentry *proc_fdinfo_instantiate(struct inode *dir,
 
 static struct dentry *proc_lookupfdinfo(struct inode *dir,
                                        struct dentry *dentry,
-                                       struct nameidata *nd)
+                                       unsigned int flags)
 {
        return proc_lookupfd_common(dir, dentry, proc_fdinfo_instantiate);
 }
@@ -2430,7 +2433,7 @@ static struct dentry *proc_pident_instantiate(struct inode *dir,
        d_set_d_op(dentry, &pid_dentry_operations);
        d_add(dentry, inode);
        /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, NULL))
+       if (pid_revalidate(dentry, 0))
                error = NULL;
 out:
        return error;
@@ -2630,7 +2633,7 @@ static const struct file_operations proc_attr_dir_operations = {
 };
 
 static struct dentry *proc_attr_dir_lookup(struct inode *dir,
-                               struct dentry *dentry, struct nameidata *nd)
+                               struct dentry *dentry, unsigned int flags)
 {
        return proc_pident_lookup(dir, dentry,
                                  attr_dir_stuff, ARRAY_SIZE(attr_dir_stuff));
@@ -3114,7 +3117,8 @@ static const struct file_operations proc_tgid_base_operations = {
        .llseek         = default_llseek,
 };
 
-static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
+static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
+{
        return proc_pident_lookup(dir, dentry,
                                  tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff));
 }
@@ -3237,13 +3241,13 @@ static struct dentry *proc_pid_instantiate(struct inode *dir,
 
        d_add(dentry, inode);
        /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, NULL))
+       if (pid_revalidate(dentry, 0))
                error = NULL;
 out:
        return error;
 }
 
-struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
+struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
 {
        struct dentry *result;
        struct task_struct *task;
@@ -3470,7 +3474,8 @@ static int proc_tid_base_readdir(struct file * filp,
                                   tid_base_stuff,ARRAY_SIZE(tid_base_stuff));
 }
 
-static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
+static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
+{
        return proc_pident_lookup(dir, dentry,
                                  tid_base_stuff, ARRAY_SIZE(tid_base_stuff));
 }
@@ -3508,13 +3513,13 @@ static struct dentry *proc_task_instantiate(struct inode *dir,
 
        d_add(dentry, inode);
        /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, NULL))
+       if (pid_revalidate(dentry, 0))
                error = NULL;
 out:
        return error;
 }
 
-static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, unsigned int flags)
 {
        struct dentry *result = ERR_PTR(-ENOENT);
        struct task_struct *task;
index 2edf34f2eb61136972e12e79714e36e4197e4ad8..b3647fe6a60870e55f36710497fd9dff583963ee 100644 (file)
@@ -446,7 +446,7 @@ out_unlock:
 }
 
 struct dentry *proc_lookup(struct inode *dir, struct dentry *dentry,
-               struct nameidata *nd)
+               unsigned int flags)
 {
        return proc_lookup_de(PDE(dir), dir, dentry);
 }
index eca4aca5b6e227c11bb13c100deac3861b747a44..e1167a1c9126ee5f6a91971fec50ff3eaa79cce4 100644 (file)
@@ -106,7 +106,7 @@ void pde_users_dec(struct proc_dir_entry *pde);
 
 extern spinlock_t proc_subdir_lock;
 
-struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *);
+struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, unsigned int);
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir);
 unsigned long task_vsize(struct mm_struct *);
 unsigned long task_statm(struct mm_struct *,
@@ -132,7 +132,7 @@ int proc_remount(struct super_block *sb, int *flags, char *data);
  * of the /proc/<pid> subdirectories.
  */
 int proc_readdir(struct file *, void *, filldir_t);
-struct dentry *proc_lookup(struct inode *, struct dentry *, struct nameidata *);
+struct dentry *proc_lookup(struct inode *, struct dentry *, unsigned int);
 
 
 
@@ -142,7 +142,7 @@ typedef struct dentry *instantiate_t(struct inode *, struct dentry *,
 int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
        const char *name, int len,
        instantiate_t instantiate, struct task_struct *task, const void *ptr);
-int pid_revalidate(struct dentry *dentry, struct nameidata *nd);
+int pid_revalidate(struct dentry *dentry, unsigned int flags);
 struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task);
 extern const struct dentry_operations pid_dentry_operations;
 int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
index 0d9e23a39e495f0d6dd0a69d0f84aaa05faef9b5..b178ed733c3698a0ad2fcf49def0727b9fc135f6 100644 (file)
@@ -56,7 +56,7 @@ static struct dentry *proc_ns_instantiate(struct inode *dir,
        d_set_d_op(dentry, &pid_dentry_operations);
        d_add(dentry, inode);
        /* Close the race of the process dying before we return the dentry */
-       if (pid_revalidate(dentry, NULL))
+       if (pid_revalidate(dentry, 0))
                error = NULL;
 out:
        return error;
@@ -140,7 +140,7 @@ const struct file_operations proc_ns_dir_operations = {
 };
 
 static struct dentry *proc_ns_dir_lookup(struct inode *dir,
-                               struct dentry *dentry, struct nameidata *nd)
+                               struct dentry *dentry, unsigned int flags)
 {
        struct dentry *error;
        struct task_struct *task = get_proc_task(dir);
index 927cbd115e532857936a0ddc4d51de14149a37b7..df7dd08d439121253bb180e26ad4d7e982775adf 100644 (file)
@@ -101,6 +101,11 @@ void proc_device_tree_update_prop(struct proc_dir_entry *pde,
 {
        struct proc_dir_entry *ent;
 
+       if (!oldprop) {
+               proc_device_tree_add_prop(pde, newprop);
+               return;
+       }
+
        for (ent = pde->subdir; ent != NULL; ent = ent->next)
                if (ent->data == oldprop)
                        break;
index 06e1cc17caf6a8315c142397dad8ff1ff3d9ec75..fe72cd073dea8080becd6018ae89c76a4b83fe9f 100644 (file)
@@ -119,7 +119,7 @@ static struct net *get_proc_task_net(struct inode *dir)
 }
 
 static struct dentry *proc_tgid_net_lookup(struct inode *dir,
-               struct dentry *dentry, struct nameidata *nd)
+               struct dentry *dentry, unsigned int flags)
 {
        struct dentry *de;
        struct net *net;
index 3476bca8f7af93392539e28b14aeaf9b40c457a0..dfafeb2b05a0e2ddc5481b2b2a4f445ec8086a0e 100644 (file)
@@ -433,7 +433,7 @@ static struct ctl_table_header *grab_header(struct inode *inode)
 }
 
 static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
-                                       struct nameidata *nd)
+                                       unsigned int flags)
 {
        struct ctl_table_header *head = grab_header(dir);
        struct ctl_table_header *h = NULL;
@@ -794,9 +794,9 @@ static const struct inode_operations proc_sys_dir_operations = {
        .getattr        = proc_sys_getattr,
 };
 
-static int proc_sys_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int proc_sys_revalidate(struct dentry *dentry, unsigned int flags)
 {
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
        return !PROC_I(dentry->d_inode)->sysctl->unregistering;
 }
index 7c30fce037c0e9cbf6d848aeb7cc1f8c25a13e83..9a2d9fd7cadd2acde77a4e00615f9bbafefc8d96 100644 (file)
@@ -111,7 +111,7 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
                options = data;
        }
 
-       sb = sget(fs_type, proc_test_super, proc_set_super, ns);
+       sb = sget(fs_type, proc_test_super, proc_set_super, flags, ns);
        if (IS_ERR(sb))
                return ERR_CAST(sb);
 
@@ -121,7 +121,6 @@ static struct dentry *proc_mount(struct file_system_type *fs_type,
        }
 
        if (!sb->s_root) {
-               sb->s_flags = flags;
                err = proc_fill_super(sb);
                if (err) {
                        deactivate_locked_super(sb);
@@ -200,13 +199,12 @@ static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct
        return 0;
 }
 
-static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags)
 {
-       if (!proc_lookup(dir, dentry, nd)) {
+       if (!proc_lookup(dir, dentry, flags))
                return NULL;
-       }
        
-       return proc_pid_lookup(dir, dentry, nd);
+       return proc_pid_lookup(dir, dentry, flags);
 }
 
 static int proc_root_readdir(struct file * filp,
index 5e289a7cbad17d8547458f1d8b2526f2e85e5cb9..5fe34c355e85e9bb7175cbfb2367e5c49928837a 100644 (file)
@@ -17,7 +17,7 @@
 
 static unsigned mounts_poll(struct file *file, poll_table *wait)
 {
-       struct proc_mounts *p = file->private_data;
+       struct proc_mounts *p = proc_mounts(file->private_data);
        struct mnt_namespace *ns = p->ns;
        unsigned res = POLLIN | POLLRDNORM;
 
@@ -121,7 +121,7 @@ out:
 
 static int show_mountinfo(struct seq_file *m, struct vfsmount *mnt)
 {
-       struct proc_mounts *p = m->private;
+       struct proc_mounts *p = proc_mounts(m);
        struct mount *r = real_mount(mnt);
        struct super_block *sb = mnt->mnt_sb;
        struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt };
@@ -268,7 +268,6 @@ static int mounts_open_common(struct inode *inode, struct file *file,
        if (ret)
                goto err_free;
 
-       p->m.private = p;
        p->ns = ns;
        p->root = root;
        p->m.poll_event = ns->event;
@@ -288,7 +287,7 @@ static int mounts_open_common(struct inode *inode, struct file *file,
 
 static int mounts_release(struct inode *inode, struct file *file)
 {
-       struct proc_mounts *p = file->private_data;
+       struct proc_mounts *p = proc_mounts(file->private_data);
        path_put(&p->root);
        put_mnt_ns(p->ns);
        return seq_release(inode, file);
index a512c0b30e8e72a853a5c7711217b2c56778a62f..d024505ba007549239f055f723c6fe13d8d23828 100644 (file)
@@ -95,7 +95,7 @@ static struct buffer_head *qnx4_find_entry(int len, struct inode *dir,
        return NULL;
 }
 
-struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+struct dentry * qnx4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        int ino;
        struct qnx4_inode_entry *de;
index 244d4620189b3daf49708ad9d08b861e7106dd6d..34e2d329c97e057f330d83f835fd111f931607be 100644 (file)
@@ -23,7 +23,7 @@ struct qnx4_inode_info {
 };
 
 extern struct inode *qnx4_iget(struct super_block *, unsigned long);
-extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd);
+extern struct dentry *qnx4_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags);
 extern unsigned long qnx4_count_free_blocks(struct super_block *sb);
 extern unsigned long qnx4_block_map(struct inode *inode, long iblock);
 
index e44012dc56458a9e379695a5ee36fe44a7f768fc..2049c814bda475a7e02e9e4411d54cc74f304660 100644 (file)
@@ -622,7 +622,6 @@ static struct inode *qnx6_alloc_inode(struct super_block *sb)
 static void qnx6_i_callback(struct rcu_head *head)
 {
        struct inode *inode = container_of(head, struct inode, i_rcu);
-       INIT_LIST_HEAD(&inode->i_dentry);
        kmem_cache_free(qnx6_inode_cachep, QNX6_I(inode));
 }
 
index 8a97289e04ad18204537535f90e1ab85eae9ac2f..0561326a94f5d48551d68be18dccbb8ffe59fd38 100644 (file)
@@ -13,7 +13,7 @@
 #include "qnx6.h"
 
 struct dentry *qnx6_lookup(struct inode *dir, struct dentry *dentry,
-                               struct nameidata *nd)
+                               unsigned int flags)
 {
        unsigned ino;
        struct page *page;
index 6c5e02a0b6a8d9df7e0244493c3ba5c828457ec3..b00fcc960d374f28154b3efa9c7d9f8a4e5e7c88 100644 (file)
@@ -45,7 +45,7 @@ struct qnx6_inode_info {
 
 extern struct inode *qnx6_iget(struct super_block *sb, unsigned ino);
 extern struct dentry *qnx6_lookup(struct inode *dir, struct dentry *dentry,
-                                       struct nameidata *nd);
+                                       unsigned int flags);
 
 #ifdef CONFIG_QNX6FS_DEBUG
 extern void qnx6_superblock_debug(struct qnx6_super_block *,
index 10cbe841cb7ecca3a823da92621ec3e614a2be09..d679fc48ef27bcb6e62ac10fb9de1ba2677d7fdd 100644 (file)
@@ -595,12 +595,14 @@ out:
 }
 EXPORT_SYMBOL(dquot_scan_active);
 
-int dquot_quota_sync(struct super_block *sb, int type, int wait)
+/* Write all dquot structures to quota files */
+int dquot_writeback_dquots(struct super_block *sb, int type)
 {
        struct list_head *dirty;
        struct dquot *dquot;
        struct quota_info *dqopt = sb_dqopt(sb);
        int cnt;
+       int err, ret = 0;
 
        mutex_lock(&dqopt->dqonoff_mutex);
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
@@ -624,7 +626,9 @@ int dquot_quota_sync(struct super_block *sb, int type, int wait)
                        atomic_inc(&dquot->dq_count);
                        spin_unlock(&dq_list_lock);
                        dqstats_inc(DQST_LOOKUPS);
-                       sb->dq_op->write_dquot(dquot);
+                       err = sb->dq_op->write_dquot(dquot);
+                       if (!ret && err)
+                               err = ret;
                        dqput(dquot);
                        spin_lock(&dq_list_lock);
                }
@@ -638,7 +642,21 @@ int dquot_quota_sync(struct super_block *sb, int type, int wait)
        dqstats_inc(DQST_SYNCS);
        mutex_unlock(&dqopt->dqonoff_mutex);
 
-       if (!wait || (dqopt->flags & DQUOT_QUOTA_SYS_FILE))
+       return ret;
+}
+EXPORT_SYMBOL(dquot_writeback_dquots);
+
+/* Write all dquot structures to disk and make them visible from userspace */
+int dquot_quota_sync(struct super_block *sb, int type)
+{
+       struct quota_info *dqopt = sb_dqopt(sb);
+       int cnt;
+       int ret;
+
+       ret = dquot_writeback_dquots(sb, type);
+       if (ret)
+               return ret;
+       if (dqopt->flags & DQUOT_QUOTA_SYS_FILE)
                return 0;
 
        /* This is not very clever (and fast) but currently I don't know about
index 9a391204ca278e4186300215ef521183af70eb68..c659f92298d3623eed8da9eb9d53c064dd917141 100644 (file)
@@ -47,7 +47,7 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
 static void quota_sync_one(struct super_block *sb, void *arg)
 {
        if (sb->s_qcop && sb->s_qcop->quota_sync)
-               sb->s_qcop->quota_sync(sb, *(int *)arg, 1);
+               sb->s_qcop->quota_sync(sb, *(int *)arg);
 }
 
 static int quota_sync_all(int type)
@@ -270,7 +270,7 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id,
        case Q_SYNC:
                if (!sb->s_qcop->quota_sync)
                        return -ENOSYS;
-               return sb->s_qcop->quota_sync(sb, type, 1);
+               return sb->s_qcop->quota_sync(sb, type);
        case Q_XQUOTAON:
        case Q_XQUOTAOFF:
        case Q_XQUOTARM:
index a1fdabe21dec4e93a42bc101d6a32b480cc89c23..eab8c09d3801ca00db98687c49f22b58a633ccc8 100644 (file)
@@ -114,7 +114,7 @@ static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, umode_t mode)
        return retval;
 }
 
-static int ramfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd)
+static int ramfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, bool excl)
 {
        return ramfs_mknod(dir, dentry, mode | S_IFREG, 0);
 }
index c20614f86c01ed88ed36a65e9dfafdabfd3ba4d3..1adfb691e4f152444d8b7a080c1159057bbed9ad 100644 (file)
@@ -55,10 +55,11 @@ static loff_t lseek_execute(struct file *file, struct inode *inode,
  * @file:      file structure to seek on
  * @offset:    file offset to seek to
  * @origin:    type of seek
- * @size:      max size of file system
+ * @size:      max size of this file in file system
+ * @eof:       offset used for SEEK_END position
  *
  * This is a variant of generic_file_llseek that allows passing in a custom
- * file size.
+ * maximum file size and a custom EOF position, for e.g. hashed directories
  *
  * Synchronization:
  * SEEK_SET and SEEK_END are unsynchronized (but atomic on 64bit platforms)
@@ -67,13 +68,13 @@ static loff_t lseek_execute(struct file *file, struct inode *inode,
  */
 loff_t
 generic_file_llseek_size(struct file *file, loff_t offset, int origin,
-               loff_t maxsize)
+               loff_t maxsize, loff_t eof)
 {
        struct inode *inode = file->f_mapping->host;
 
        switch (origin) {
        case SEEK_END:
-               offset += i_size_read(inode);
+               offset += eof;
                break;
        case SEEK_CUR:
                /*
@@ -99,7 +100,7 @@ generic_file_llseek_size(struct file *file, loff_t offset, int origin,
                 * In the generic case the entire file is data, so as long as
                 * offset isn't at the end of the file then the offset is data.
                 */
-               if (offset >= i_size_read(inode))
+               if (offset >= eof)
                        return -ENXIO;
                break;
        case SEEK_HOLE:
@@ -107,9 +108,9 @@ generic_file_llseek_size(struct file *file, loff_t offset, int origin,
                 * There is a virtual hole at the end of the file, so as long as
                 * offset isn't i_size or larger, return i_size.
                 */
-               if (offset >= i_size_read(inode))
+               if (offset >= eof)
                        return -ENXIO;
-               offset = i_size_read(inode);
+               offset = eof;
                break;
        }
 
@@ -132,7 +133,8 @@ loff_t generic_file_llseek(struct file *file, loff_t offset, int origin)
        struct inode *inode = file->f_mapping->host;
 
        return generic_file_llseek_size(file, offset, origin,
-                                       inode->i_sb->s_maxbytes);
+                                       inode->i_sb->s_maxbytes,
+                                       i_size_read(inode));
 }
 EXPORT_SYMBOL(generic_file_llseek);
 
index 84e8a69cee9d3882d5b7552c6cfdbc3459baf8e5..8567fb847601ceac1e8a7a6b6048061d4797352d 100644 (file)
@@ -322,7 +322,7 @@ static int reiserfs_find_entry(struct inode *dir, const char *name, int namelen,
 }
 
 static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry,
-                                     struct nameidata *nd)
+                                     unsigned int flags)
 {
        int retval;
        int lock_depth;
@@ -573,7 +573,7 @@ static int new_inode_init(struct inode *inode, struct inode *dir, umode_t mode)
 }
 
 static int reiserfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                          struct nameidata *nd)
+                          bool excl)
 {
        int retval;
        struct inode *inode;
@@ -634,8 +634,8 @@ static int reiserfs_create(struct inode *dir, struct dentry *dentry, umode_t mod
        reiserfs_update_inode_transaction(inode);
        reiserfs_update_inode_transaction(dir);
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        retval = journal_end(&th, dir->i_sb, jbegin_count);
 
       out_failed:
@@ -712,8 +712,8 @@ static int reiserfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode
                goto out_failed;
        }
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        retval = journal_end(&th, dir->i_sb, jbegin_count);
 
       out_failed:
@@ -800,8 +800,8 @@ static int reiserfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode
        // the above add_entry did not update dir's stat data
        reiserfs_update_sd(&th, dir);
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        retval = journal_end(&th, dir->i_sb, jbegin_count);
 out_failed:
        reiserfs_write_unlock_once(dir->i_sb, lock_depth);
@@ -1096,8 +1096,8 @@ static int reiserfs_symlink(struct inode *parent_dir,
                goto out_failed;
        }
 
-       d_instantiate(dentry, inode);
        unlock_new_inode(inode);
+       d_instantiate(dentry, inode);
        retval = journal_end(&th, parent_dir->i_sb, jbegin_count);
       out_failed:
        reiserfs_write_unlock(parent_dir->i_sb);
index 2c1ade692cc840efbb50be597877fde71cb4780c..e60e87035bb3eac8ed3047b392dd5a71b13ee0c3 100644 (file)
@@ -403,7 +403,7 @@ static void *r_start(struct seq_file *m, loff_t * pos)
        if (l)
                return NULL;
 
-       if (IS_ERR(sget(&reiserfs_fs_type, test_sb, set_sb, s)))
+       if (IS_ERR(sget(&reiserfs_fs_type, test_sb, set_sb, 0, s)))
                return NULL;
 
        up_write(&s->s_umount);
index 651ce767b55d8241e283b3001d7fc9e6d803b317..7a37dabf5a968b7c8977c2028665f58554987912 100644 (file)
@@ -68,6 +68,11 @@ static int reiserfs_sync_fs(struct super_block *s, int wait)
 {
        struct reiserfs_transaction_handle th;
 
+       /*
+        * Writeback quota in non-journalled quota case - journalled quota has
+        * no dirty dquots
+        */
+       dquot_writeback_dquots(s, -1);
        reiserfs_write_lock(s);
        if (!journal_begin(&th, s, 1))
                if (!journal_end_sync(&th, s, 1))
index 46fc1c20a6b1c65ccd72a8f18106283b01197916..d319963aeb1171e755018f966a3e1bff776cacf3 100644 (file)
@@ -62,7 +62,7 @@
 static int xattr_create(struct inode *dir, struct dentry *dentry, int mode)
 {
        BUG_ON(!mutex_is_locked(&dir->i_mutex));
-       return dir->i_op->create(dir, dentry, mode, NULL);
+       return dir->i_op->create(dir, dentry, mode, true);
 }
 #endif
 
@@ -942,7 +942,7 @@ int reiserfs_permission(struct inode *inode, int mask)
        return generic_permission(inode, mask);
 }
 
-static int xattr_hide_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int xattr_hide_revalidate(struct dentry *dentry, unsigned int flags)
 {
        return -EPERM;
 }
index e64f6b5f7ae57f72d636a4b7f3f5a2c2e3839202..77c5f21739837753efdfed09e806e32d1376a219 100644 (file)
@@ -210,7 +210,7 @@ out:
  * look up an entry in a directory
  */
 static struct dentry *romfs_lookup(struct inode *dir, struct dentry *dentry,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        unsigned long offset, maxoff;
        struct inode *inode;
index abcc58f3c15266dd24b9533b4b1103d3514a0c3e..7834a517f7f422cfb9bc35f997e8c69e4e91e52d 100644 (file)
@@ -134,7 +134,7 @@ out:
 
 
 static struct dentry *squashfs_lookup(struct inode *dir, struct dentry *dentry,
-                                struct nameidata *nd)
+                                unsigned int flags)
 {
        const unsigned char *name = dentry->d_name.name;
        int len = dentry->d_name.len;
index cf001775617f5781ac4f43f5695ad7802c6b4524..c743fb3be4b8a45d8d99f9b757bfc44bbb949683 100644 (file)
@@ -105,11 +105,12 @@ static int prune_super(struct shrinker *shrink, struct shrink_control *sc)
 /**
  *     alloc_super     -       create new superblock
  *     @type:  filesystem type superblock should belong to
+ *     @flags: the mount flags
  *
  *     Allocates and initializes a new &struct super_block.  alloc_super()
  *     returns a pointer new superblock or %NULL if allocation had failed.
  */
-static struct super_block *alloc_super(struct file_system_type *type)
+static struct super_block *alloc_super(struct file_system_type *type, int flags)
 {
        struct super_block *s = kzalloc(sizeof(struct super_block),  GFP_USER);
        static const struct super_operations default_op;
@@ -136,6 +137,7 @@ static struct super_block *alloc_super(struct file_system_type *type)
 #else
                INIT_LIST_HEAD(&s->s_files);
 #endif
+               s->s_flags = flags;
                s->s_bdi = &default_backing_dev_info;
                INIT_HLIST_NODE(&s->s_instances);
                INIT_HLIST_BL_HEAD(&s->s_anon);
@@ -415,11 +417,13 @@ EXPORT_SYMBOL(generic_shutdown_super);
  *     @type:  filesystem type superblock should belong to
  *     @test:  comparison callback
  *     @set:   setup callback
+ *     @flags: mount flags
  *     @data:  argument to each of them
  */
 struct super_block *sget(struct file_system_type *type,
                        int (*test)(struct super_block *,void *),
                        int (*set)(struct super_block *,void *),
+                       int flags,
                        void *data)
 {
        struct super_block *s = NULL;
@@ -450,7 +454,7 @@ retry:
        }
        if (!s) {
                spin_unlock(&sb_lock);
-               s = alloc_super(type);
+               s = alloc_super(type, flags);
                if (!s)
                        return ERR_PTR(-ENOMEM);
                goto retry;
@@ -925,13 +929,12 @@ struct dentry *mount_ns(struct file_system_type *fs_type, int flags,
 {
        struct super_block *sb;
 
-       sb = sget(fs_type, ns_test_super, ns_set_super, data);
+       sb = sget(fs_type, ns_test_super, ns_set_super, flags, data);
        if (IS_ERR(sb))
                return ERR_CAST(sb);
 
        if (!sb->s_root) {
                int err;
-               sb->s_flags = flags;
                err = fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
                if (err) {
                        deactivate_locked_super(sb);
@@ -992,7 +995,8 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
                error = -EBUSY;
                goto error_bdev;
        }
-       s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
+       s = sget(fs_type, test_bdev_super, set_bdev_super, flags | MS_NOSEC,
+                bdev);
        mutex_unlock(&bdev->bd_fsfreeze_mutex);
        if (IS_ERR(s))
                goto error_s;
@@ -1017,7 +1021,6 @@ struct dentry *mount_bdev(struct file_system_type *fs_type,
        } else {
                char b[BDEVNAME_SIZE];
 
-               s->s_flags = flags | MS_NOSEC;
                s->s_mode = mode;
                strlcpy(s->s_id, bdevname(bdev, b), sizeof(s->s_id));
                sb_set_blocksize(s, block_size(bdev));
@@ -1062,13 +1065,11 @@ struct dentry *mount_nodev(struct file_system_type *fs_type,
        int (*fill_super)(struct super_block *, void *, int))
 {
        int error;
-       struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
+       struct super_block *s = sget(fs_type, NULL, set_anon_super, flags, NULL);
 
        if (IS_ERR(s))
                return ERR_CAST(s);
 
-       s->s_flags = flags;
-
        error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
        if (error) {
                deactivate_locked_super(s);
@@ -1091,11 +1092,10 @@ struct dentry *mount_single(struct file_system_type *fs_type,
        struct super_block *s;
        int error;
 
-       s = sget(fs_type, compare_single, set_anon_super, NULL);
+       s = sget(fs_type, compare_single, set_anon_super, flags, NULL);
        if (IS_ERR(s))
                return ERR_CAST(s);
        if (!s->s_root) {
-               s->s_flags = flags;
                error = fill_super(s, data, flags & MS_SILENT ? 1 : 0);
                if (error) {
                        deactivate_locked_super(s);
index 11e3d1c449018dcf9a95c352746f46d6522c4cb2..eb8722dc556f5b567c40438919c6ef1ddeef084d 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
  */
 static int __sync_filesystem(struct super_block *sb, int wait)
 {
-       /*
-        * This should be safe, as we require bdi backing to actually
-        * write out data in the first place
-        */
-       if (sb->s_bdi == &noop_backing_dev_info)
-               return 0;
-
-       if (sb->s_qcop && sb->s_qcop->quota_sync)
-               sb->s_qcop->quota_sync(sb, -1, wait);
-
        if (wait)
                sync_inodes_sb(sb);
        else
@@ -77,29 +67,48 @@ int sync_filesystem(struct super_block *sb)
 }
 EXPORT_SYMBOL_GPL(sync_filesystem);
 
-static void sync_one_sb(struct super_block *sb, void *arg)
+static void sync_inodes_one_sb(struct super_block *sb, void *arg)
 {
        if (!(sb->s_flags & MS_RDONLY))
-               __sync_filesystem(sb, *(int *)arg);
+               sync_inodes_sb(sb);
 }
-/*
- * Sync all the data for all the filesystems (called by sys_sync() and
- * emergency sync)
- */
-static void sync_filesystems(int wait)
+
+static void sync_fs_one_sb(struct super_block *sb, void *arg)
 {
-       iterate_supers(sync_one_sb, &wait);
+       if (!(sb->s_flags & MS_RDONLY) && sb->s_op->sync_fs)
+               sb->s_op->sync_fs(sb, *(int *)arg);
+}
+
+static void fdatawrite_one_bdev(struct block_device *bdev, void *arg)
+{
+       filemap_fdatawrite(bdev->bd_inode->i_mapping);
+}
+
+static void fdatawait_one_bdev(struct block_device *bdev, void *arg)
+{
+       filemap_fdatawait(bdev->bd_inode->i_mapping);
 }
 
 /*
- * sync everything.  Start out by waking pdflush, because that writes back
- * all queues in parallel.
+ * Sync everything. We start by waking flusher threads so that most of
+ * writeback runs on all devices in parallel. Then we sync all inodes reliably
+ * which effectively also waits for all flusher threads to finish doing
+ * writeback. At this point all data is on disk so metadata should be stable
+ * and we tell filesystems to sync their metadata via ->sync_fs() calls.
+ * Finally, we writeout all block devices because some filesystems (e.g. ext2)
+ * just write metadata (such as inodes or bitmaps) to block device page cache
+ * and do not sync it on their own in ->sync_fs().
  */
 SYSCALL_DEFINE0(sync)
 {
+       int nowait = 0, wait = 1;
+
        wakeup_flusher_threads(0, WB_REASON_SYNC);
-       sync_filesystems(0);
-       sync_filesystems(1);
+       iterate_supers(sync_inodes_one_sb, NULL);
+       iterate_supers(sync_fs_one_sb, &nowait);
+       iterate_supers(sync_fs_one_sb, &wait);
+       iterate_bdevs(fdatawrite_one_bdev, NULL);
+       iterate_bdevs(fdatawait_one_bdev, NULL);
        if (unlikely(laptop_mode))
                laptop_sync_completion();
        return 0;
@@ -107,12 +116,18 @@ SYSCALL_DEFINE0(sync)
 
 static void do_sync_work(struct work_struct *work)
 {
+       int nowait = 0;
+
        /*
         * Sync twice to reduce the possibility we skipped some inodes / pages
         * because they were temporarily locked
         */
-       sync_filesystems(0);
-       sync_filesystems(0);
+       iterate_supers(sync_inodes_one_sb, &nowait);
+       iterate_supers(sync_fs_one_sb, &nowait);
+       iterate_bdevs(fdatawrite_one_bdev, NULL);
+       iterate_supers(sync_inodes_one_sb, &nowait);
+       iterate_supers(sync_fs_one_sb, &nowait);
+       iterate_bdevs(fdatawrite_one_bdev, NULL);
        printk("Emergency Sync complete\n");
        kfree(work);
 }
index e6bb9b2a4cbef3df52450d349a87a316844d6c8a..a5cf784f9cc2abec93c2a5272345838e20fb62ad 100644 (file)
@@ -300,15 +300,15 @@ void release_sysfs_dirent(struct sysfs_dirent * sd)
 static int sysfs_dentry_delete(const struct dentry *dentry)
 {
        struct sysfs_dirent *sd = dentry->d_fsdata;
-       return !!(sd->s_flags & SYSFS_FLAG_REMOVED);
+       return !(sd && !(sd->s_flags & SYSFS_FLAG_REMOVED));
 }
 
-static int sysfs_dentry_revalidate(struct dentry *dentry, struct nameidata *nd)
+static int sysfs_dentry_revalidate(struct dentry *dentry, unsigned int flags)
 {
        struct sysfs_dirent *sd;
        int is_dir;
 
-       if (nd->flags & LOOKUP_RCU)
+       if (flags & LOOKUP_RCU)
                return -ECHILD;
 
        sd = dentry->d_fsdata;
@@ -355,18 +355,15 @@ out_bad:
        return 0;
 }
 
-static void sysfs_dentry_iput(struct dentry *dentry, struct inode *inode)
+static void sysfs_dentry_release(struct dentry *dentry)
 {
-       struct sysfs_dirent * sd = dentry->d_fsdata;
-
-       sysfs_put(sd);
-       iput(inode);
+       sysfs_put(dentry->d_fsdata);
 }
 
-static const struct dentry_operations sysfs_dentry_ops = {
+const struct dentry_operations sysfs_dentry_ops = {
        .d_revalidate   = sysfs_dentry_revalidate,
        .d_delete       = sysfs_dentry_delete,
-       .d_iput         = sysfs_dentry_iput,
+       .d_release      = sysfs_dentry_release,
 };
 
 struct sysfs_dirent *sysfs_new_dirent(const char *name, umode_t mode, int type)
@@ -764,7 +761,7 @@ int sysfs_create_dir(struct kobject * kobj)
 }
 
 static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
-                               struct nameidata *nd)
+                               unsigned int flags)
 {
        struct dentry *ret = NULL;
        struct dentry *parent = dentry->d_parent;
@@ -786,6 +783,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
                ret = ERR_PTR(-ENOENT);
                goto out_unlock;
        }
+       dentry->d_fsdata = sysfs_get(sd);
 
        /* attach dentry and inode */
        inode = sysfs_get_inode(dir->i_sb, sd);
@@ -795,16 +793,7 @@ static struct dentry * sysfs_lookup(struct inode *dir, struct dentry *dentry,
        }
 
        /* instantiate and hash dentry */
-       ret = d_find_alias(inode);
-       if (!ret) {
-               d_set_d_op(dentry, &sysfs_dentry_ops);
-               dentry->d_fsdata = sysfs_get(sd);
-               d_add(dentry, inode);
-       } else {
-               d_move(ret, dentry);
-               iput(inode);
-       }
-
+       ret = d_materialise_unique(dentry, inode);
  out_unlock:
        mutex_unlock(&sysfs_mutex);
        return ret;
index 52c3bdb66a849b98df33cefccff5b6cc0a7ded8c..71eb7e2539274a5cacd1fe61ba0bca46db8381b4 100644 (file)
@@ -68,6 +68,7 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent)
        }
        root->d_fsdata = &sysfs_root;
        sb->s_root = root;
+       sb->s_d_op = &sysfs_dentry_ops;
        return 0;
 }
 
@@ -117,13 +118,12 @@ static struct dentry *sysfs_mount(struct file_system_type *fs_type,
        for (type = KOBJ_NS_TYPE_NONE; type < KOBJ_NS_TYPES; type++)
                info->ns[type] = kobj_ns_grab_current(type);
 
-       sb = sget(fs_type, sysfs_test_super, sysfs_set_super, info);
+       sb = sget(fs_type, sysfs_test_super, sysfs_set_super, flags, info);
        if (IS_ERR(sb) || sb->s_fs_info != info)
                free_sysfs_super_info(info);
        if (IS_ERR(sb))
                return ERR_CAST(sb);
        if (!sb->s_root) {
-               sb->s_flags = flags;
                error = sysfs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
                if (error) {
                        deactivate_locked_super(sb);
index 661a9639570b973dcce69ac3abc4bdbe84cb6991..d73c0932bbd6f688b811784236fc1a78ffce3c37 100644 (file)
@@ -157,6 +157,7 @@ extern struct kmem_cache *sysfs_dir_cachep;
  */
 extern struct mutex sysfs_mutex;
 extern spinlock_t sysfs_assoc_lock;
+extern const struct dentry_operations sysfs_dentry_ops;
 
 extern const struct file_operations sysfs_dir_operations;
 extern const struct inode_operations sysfs_dir_inode_operations;
index 08d0b2568cd35e060a9e6b8ffda87d7d6569cbdb..80e1e2b18df17f3537050cd7557955a1c1cd6b49 100644 (file)
@@ -43,7 +43,6 @@ static int sysv_sync_fs(struct super_block *sb, int wait)
         * then attach current time stamp.
         * But if the filesystem was marked clean, keep it clean.
         */
-       sb->s_dirt = 0;
        old_time = fs32_to_cpu(sbi, *sbi->s_sb_time);
        if (sbi->s_type == FSTYPE_SYSV4) {
                if (*sbi->s_sb_state == cpu_to_fs32(sbi, 0x7c269d38 - old_time))
@@ -57,23 +56,12 @@ static int sysv_sync_fs(struct super_block *sb, int wait)
        return 0;
 }
 
-static void sysv_write_super(struct super_block *sb)
-{
-       if (!(sb->s_flags & MS_RDONLY))
-               sysv_sync_fs(sb, 1);
-       else
-               sb->s_dirt = 0;
-}
-
 static int sysv_remount(struct super_block *sb, int *flags, char *data)
 {
        struct sysv_sb_info *sbi = SYSV_SB(sb);
-       lock_super(sb);
+
        if (sbi->s_forced_ro)
                *flags |= MS_RDONLY;
-       if (*flags & MS_RDONLY)
-               sysv_write_super(sb);
-       unlock_super(sb);
        return 0;
 }
 
@@ -81,9 +69,6 @@ static void sysv_put_super(struct super_block *sb)
 {
        struct sysv_sb_info *sbi = SYSV_SB(sb);
 
-       if (sb->s_dirt)
-               sysv_write_super(sb);
-
        if (!(sb->s_flags & MS_RDONLY)) {
                /* XXX ext2 also updates the state here */
                mark_buffer_dirty(sbi->s_bh1);
@@ -357,7 +342,6 @@ const struct super_operations sysv_sops = {
        .write_inode    = sysv_write_inode,
        .evict_inode    = sysv_evict_inode,
        .put_super      = sysv_put_super,
-       .write_super    = sysv_write_super,
        .sync_fs        = sysv_sync_fs,
        .remount_fs     = sysv_remount,
        .statfs         = sysv_statfs,
index d7466e2936148103f20c5a6dbec5fba33e4fb2f3..1c0d5f264767df5ebc7bf0dc77a0267b097a4052 100644 (file)
@@ -43,7 +43,7 @@ const struct dentry_operations sysv_dentry_operations = {
        .d_hash         = sysv_hash,
 };
 
-static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *sysv_lookup(struct inode * dir, struct dentry * dentry, unsigned int flags)
 {
        struct inode * inode = NULL;
        ino_t ino;
@@ -80,7 +80,7 @@ static int sysv_mknod(struct inode * dir, struct dentry * dentry, umode_t mode,
        return err;
 }
 
-static int sysv_create(struct inode * dir, struct dentry * dentry, umode_t mode, struct nameidata *nd)
+static int sysv_create(struct inode * dir, struct dentry * dentry, umode_t mode, bool excl)
 {
        return sysv_mknod(dir, dentry, mode, 0);
 }
index 11b07672f6c5586752b0448810226fdee81b049c..0bc35fdc58e2981fc455fc043c43f00deb10a0d8 100644 (file)
@@ -117,7 +117,6 @@ static inline void dirty_sb(struct super_block *sb)
        mark_buffer_dirty(sbi->s_bh1);
        if (sbi->s_bh1 != sbi->s_bh2)
                mark_buffer_dirty(sbi->s_bh2);
-       sb->s_dirt = 1;
 }
 
 
index 92df3b08153901350a433f8b95c95cd493479aad..bb3167257aabfed6d16452eed551e577c95b706d 100644 (file)
@@ -2802,6 +2802,8 @@ static ssize_t dfs_file_read(struct file *file, char __user *u, size_t count,
                val = d->chk_fs;
        else if (dent == d->dfs_tst_rcvry)
                val = d->tst_rcvry;
+       else if (dent == d->dfs_ro_error)
+               val = c->ro_error;
        else
                return -EINVAL;
 
@@ -2885,6 +2887,8 @@ static ssize_t dfs_file_write(struct file *file, const char __user *u,
                d->chk_fs = val;
        else if (dent == d->dfs_tst_rcvry)
                d->tst_rcvry = val;
+       else if (dent == d->dfs_ro_error)
+               c->ro_error = !!val;
        else
                return -EINVAL;
 
@@ -2996,6 +3000,13 @@ int dbg_debugfs_init_fs(struct ubifs_info *c)
                goto out_remove;
        d->dfs_tst_rcvry = dent;
 
+       fname = "ro_error";
+       dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+                                  &dfs_fops);
+       if (IS_ERR_OR_NULL(dent))
+               goto out_remove;
+       d->dfs_ro_error = dent;
+
        return 0;
 
 out_remove:
index 486a8e024fb65b15f1a20173877c5b1e361c7bae..8b8cc4e945f4014bd8e0a77d1d9bde0197f0fa76 100644 (file)
@@ -79,6 +79,10 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c,
  * @dfs_chk_lprops: debugfs knob to enable UBIFS LEP properties extra checks
  * @dfs_chk_fs: debugfs knob to enable UBIFS contents extra checks
  * @dfs_tst_rcvry: debugfs knob to enable UBIFS recovery testing
+ * @dfs_ro_error: debugfs knob to switch UBIFS to R/O mode (different to
+ *                re-mounting to R/O mode because it does not flush any buffers
+ *                and UBIFS just starts returning -EROFS on all write
+ *               operations)
  */
 struct ubifs_debug_info {
        struct ubifs_zbranch old_zroot;
@@ -122,6 +126,7 @@ struct ubifs_debug_info {
        struct dentry *dfs_chk_lprops;
        struct dentry *dfs_chk_fs;
        struct dentry *dfs_tst_rcvry;
+       struct dentry *dfs_ro_error;
 };
 
 /**
index a6d42efc76d227d62289f852982160442d7e5cea..c95681cf1b71cfe7c99f70d5d88eb2f54c7804c0 100644 (file)
@@ -184,7 +184,7 @@ static int dbg_check_name(const struct ubifs_info *c,
 }
 
 static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
-                                  struct nameidata *nd)
+                                  unsigned int flags)
 {
        int err;
        union ubifs_key key;
@@ -246,7 +246,7 @@ out:
 }
 
 static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                       struct nameidata *nd)
+                       bool excl)
 {
        struct inode *inode;
        struct ubifs_info *c = dir->i_sb->s_fs_info;
@@ -969,7 +969,7 @@ static int ubifs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct ubifs_budget_req ino_req = { .dirtied_ino = 1,
                        .dirtied_ino_d = ALIGN(old_inode_ui->data_len, 8) };
        struct timespec time;
-       unsigned int saved_nlink;
+       unsigned int uninitialized_var(saved_nlink);
 
        /*
         * Budget request settings: deletion direntry, new direntry, removing
index b02734db187c2d1b2b79696c6a133482376c860b..cebf17ea045824a052e024a0e0e954c0b5a0c9e9 100644 (file)
@@ -176,7 +176,7 @@ int ubifs_orphan_start_commit(struct ubifs_info *c)
                *last = orphan;
                last = &orphan->cnext;
        }
-       *last = orphan->cnext;
+       *last = NULL;
        c->cmt_orphans = c->new_orphans;
        c->new_orphans = 0;
        dbg_cmt("%d orphans to commit", c->cmt_orphans);
@@ -382,7 +382,7 @@ static int consolidate(struct ubifs_info *c)
                        last = &orphan->cnext;
                        cnt += 1;
                }
-               *last = orphan->cnext;
+               *last = NULL;
                ubifs_assert(cnt == c->tot_orphans - c->new_orphans);
                c->cmt_orphans = cnt;
                c->ohead_lnum = c->orph_first;
index 3a2da7e476e5c8e7b346a8c3aaca9a1454659ca8..eba46d4a76192c017846c4389addf2ebdcc2a78e 100644 (file)
@@ -1007,7 +1007,7 @@ out:
  */
 int ubifs_replay_journal(struct ubifs_info *c)
 {
-       int err, i, lnum, offs, free;
+       int err, lnum, free;
 
        BUILD_BUG_ON(UBIFS_TRUN_KEY > 5);
 
@@ -1025,25 +1025,17 @@ int ubifs_replay_journal(struct ubifs_info *c)
        dbg_mnt("start replaying the journal");
        c->replaying = 1;
        lnum = c->ltail_lnum = c->lhead_lnum;
-       offs = c->lhead_offs;
 
-       for (i = 0; i < c->log_lebs; i++, lnum++) {
-               if (lnum >= UBIFS_LOG_LNUM + c->log_lebs) {
-                       /*
-                        * The log is logically circular, we reached the last
-                        * LEB, switch to the first one.
-                        */
-                       lnum = UBIFS_LOG_LNUM;
-                       offs = 0;
-               }
-               err = replay_log_leb(c, lnum, offs, c->sbuf);
+       lnum = UBIFS_LOG_LNUM;
+       do {
+               err = replay_log_leb(c, lnum, 0, c->sbuf);
                if (err == 1)
                        /* We hit the end of the log */
                        break;
                if (err)
                        goto out;
-               offs = 0;
-       }
+               lnum = ubifs_next_log_lnum(c, lnum);
+       } while (lnum != UBIFS_LOG_LNUM);
 
        err = replay_buds(c);
        if (err)
index ef3d1ba6d992b8ffb9ab0d57e633a22d586758d2..15e2fc5aa60bd4790a86c828aaea6995b17e1737 100644 (file)
@@ -718,8 +718,12 @@ static int fixup_free_space(struct ubifs_info *c)
                lnum = ubifs_next_log_lnum(c, lnum);
        }
 
-       /* Fixup the current log head */
-       err = fixup_leb(c, c->lhead_lnum, c->lhead_offs);
+       /*
+        * Fixup the log head which contains the only a CS node at the
+        * beginning.
+        */
+       err = fixup_leb(c, c->lhead_lnum,
+                       ALIGN(UBIFS_CS_NODE_SZ, c->min_io_size));
        if (err)
                goto out;
 
index 5862dd9d278402fe140ad9096fd8eacb7c1f1909..1c766c39c03819b4d088f19f0215c63a89f2b539 100644 (file)
@@ -2136,7 +2136,7 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
 
        dbg_gen("opened ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
 
-       sb = sget(fs_type, sb_test, sb_set, c);
+       sb = sget(fs_type, sb_test, sb_set, flags, c);
        if (IS_ERR(sb)) {
                err = PTR_ERR(sb);
                kfree(c);
@@ -2153,7 +2153,6 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
                        goto out_deact;
                }
        } else {
-               sb->s_flags = flags;
                err = ubifs_fill_super(sb, data, flags & MS_SILENT ? 1 : 0);
                if (err)
                        goto out_deact;
index 18024178ac4c040a3f23181ff2dc1a5cc48f2dc8..544b2799a9114c4620844bec32b9921881da97b9 100644 (file)
@@ -251,7 +251,7 @@ out_ok:
 }
 
 static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
-                                struct nameidata *nd)
+                                unsigned int flags)
 {
        struct inode *inode = NULL;
        struct fileIdentDesc cfi;
@@ -551,7 +551,7 @@ static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
 }
 
 static int udf_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-                     struct nameidata *nd)
+                     bool excl)
 {
        struct udf_fileident_bh fibh;
        struct inode *inode;
index 42694e11c23de46b25f1177888b97ec2aac1cf32..1b3e410bf334b206eea15615d52b1ab16656de88 100644 (file)
@@ -116,7 +116,7 @@ void ufs_free_fragments(struct inode *inode, u64 fragment, unsigned count)
        ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
        if (sb->s_flags & MS_SYNCHRONOUS)
                ubh_sync_block(UCPI_UBH(ucpi));
-       sb->s_dirt = 1;
+       ufs_mark_sb_dirty(sb);
        
        unlock_super (sb);
        UFSD("EXIT\n");
@@ -214,7 +214,7 @@ do_more:
                goto do_more;
        }
 
-       sb->s_dirt = 1;
+       ufs_mark_sb_dirty(sb);
        unlock_super (sb);
        UFSD("EXIT\n");
        return;
@@ -557,7 +557,7 @@ static u64 ufs_add_fragments(struct inode *inode, u64 fragment,
        ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
        if (sb->s_flags & MS_SYNCHRONOUS)
                ubh_sync_block(UCPI_UBH(ucpi));
-       sb->s_dirt = 1;
+       ufs_mark_sb_dirty(sb);
 
        UFSD("EXIT, fragment %llu\n", (unsigned long long)fragment);
        
@@ -677,7 +677,7 @@ succed:
        ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
        if (sb->s_flags & MS_SYNCHRONOUS)
                ubh_sync_block(UCPI_UBH(ucpi));
-       sb->s_dirt = 1;
+       ufs_mark_sb_dirty(sb);
 
        result += cgno * uspi->s_fpg;
        UFSD("EXIT3, result %llu\n", (unsigned long long)result);
index 4ec5c1085a87ca56549491f52cec362e50a303d1..e84cbe21b9867d1f50ebe9d4c0fc3c7e1d05e7d0 100644 (file)
@@ -116,7 +116,7 @@ void ufs_free_inode (struct inode * inode)
        if (sb->s_flags & MS_SYNCHRONOUS)
                ubh_sync_block(UCPI_UBH(ucpi));
        
-       sb->s_dirt = 1;
+       ufs_mark_sb_dirty(sb);
        unlock_super (sb);
        UFSD("EXIT\n");
 }
@@ -288,7 +288,7 @@ cg_found:
        ubh_mark_buffer_dirty (UCPI_UBH(ucpi));
        if (sb->s_flags & MS_SYNCHRONOUS)
                ubh_sync_block(UCPI_UBH(ucpi));
-       sb->s_dirt = 1;
+       ufs_mark_sb_dirty(sb);
 
        inode->i_ino = cg * uspi->s_ipg + bit;
        inode_init_owner(inode, dir, mode);
index a2281cadefa120c444d3022843d7504019037c04..90d74b8f8eba8dacd536c74ac161cceddc241196 100644 (file)
@@ -46,7 +46,7 @@ static inline int ufs_add_nondir(struct dentry *dentry, struct inode *inode)
        return err;
 }
 
-static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, unsigned int flags)
 {
        struct inode * inode = NULL;
        ino_t ino;
@@ -71,7 +71,7 @@ static struct dentry *ufs_lookup(struct inode * dir, struct dentry *dentry, stru
  * with d_instantiate(). 
  */
 static int ufs_create (struct inode * dir, struct dentry * dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        struct inode *inode;
        int err;
index 302f340d0071280adaef9366b98280b18e5dd32a..444927e5706b773380d9050213a8179b3d611fd9 100644 (file)
@@ -302,7 +302,7 @@ void ufs_error (struct super_block * sb, const char * function,
        if (!(sb->s_flags & MS_RDONLY)) {
                usb1->fs_clean = UFS_FSBAD;
                ubh_mark_buffer_dirty(USPI_UBH(uspi));
-               sb->s_dirt = 1;
+               ufs_mark_sb_dirty(sb);
                sb->s_flags |= MS_RDONLY;
        }
        va_start (args, fmt);
@@ -334,7 +334,7 @@ void ufs_panic (struct super_block * sb, const char * function,
        if (!(sb->s_flags & MS_RDONLY)) {
                usb1->fs_clean = UFS_FSBAD;
                ubh_mark_buffer_dirty(USPI_UBH(uspi));
-               sb->s_dirt = 1;
+               ufs_mark_sb_dirty(sb);
        }
        va_start (args, fmt);
        vsnprintf (error_buf, sizeof(error_buf), fmt, args);
@@ -691,6 +691,83 @@ static void ufs_put_super_internal(struct super_block *sb)
        UFSD("EXIT\n");
 }
 
+static int ufs_sync_fs(struct super_block *sb, int wait)
+{
+       struct ufs_sb_private_info * uspi;
+       struct ufs_super_block_first * usb1;
+       struct ufs_super_block_third * usb3;
+       unsigned flags;
+
+       lock_ufs(sb);
+       lock_super(sb);
+
+       UFSD("ENTER\n");
+
+       flags = UFS_SB(sb)->s_flags;
+       uspi = UFS_SB(sb)->s_uspi;
+       usb1 = ubh_get_usb_first(uspi);
+       usb3 = ubh_get_usb_third(uspi);
+
+       usb1->fs_time = cpu_to_fs32(sb, get_seconds());
+       if ((flags & UFS_ST_MASK) == UFS_ST_SUN  ||
+           (flags & UFS_ST_MASK) == UFS_ST_SUNOS ||
+           (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
+               ufs_set_fs_state(sb, usb1, usb3,
+                               UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
+       ufs_put_cstotal(sb);
+
+       UFSD("EXIT\n");
+       unlock_super(sb);
+       unlock_ufs(sb);
+
+       return 0;
+}
+
+static void delayed_sync_fs(struct work_struct *work)
+{
+       struct ufs_sb_info *sbi;
+
+       sbi = container_of(work, struct ufs_sb_info, sync_work.work);
+
+       spin_lock(&sbi->work_lock);
+       sbi->work_queued = 0;
+       spin_unlock(&sbi->work_lock);
+
+       ufs_sync_fs(sbi->sb, 1);
+}
+
+void ufs_mark_sb_dirty(struct super_block *sb)
+{
+       struct ufs_sb_info *sbi = UFS_SB(sb);
+       unsigned long delay;
+
+       spin_lock(&sbi->work_lock);
+       if (!sbi->work_queued) {
+               delay = msecs_to_jiffies(dirty_writeback_interval * 10);
+               queue_delayed_work(system_long_wq, &sbi->sync_work, delay);
+               sbi->work_queued = 1;
+       }
+       spin_unlock(&sbi->work_lock);
+}
+
+static void ufs_put_super(struct super_block *sb)
+{
+       struct ufs_sb_info * sbi = UFS_SB(sb);
+
+       UFSD("ENTER\n");
+
+       if (!(sb->s_flags & MS_RDONLY))
+               ufs_put_super_internal(sb);
+       cancel_delayed_work_sync(&sbi->sync_work);
+
+       ubh_brelse_uspi (sbi->s_uspi);
+       kfree (sbi->s_uspi);
+       kfree (sbi);
+       sb->s_fs_info = NULL;
+       UFSD("EXIT\n");
+       return;
+}
+
 static int ufs_fill_super(struct super_block *sb, void *data, int silent)
 {
        struct ufs_sb_info * sbi;
@@ -716,6 +793,7 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
        if (!sbi)
                goto failed_nomem;
        sb->s_fs_info = sbi;
+       sbi->sb = sb;
 
        UFSD("flag %u\n", (int)(sb->s_flags & MS_RDONLY));
        
@@ -727,6 +805,8 @@ static int ufs_fill_super(struct super_block *sb, void *data, int silent)
        }
 #endif
        mutex_init(&sbi->mutex);
+       spin_lock_init(&sbi->work_lock);
+       INIT_DELAYED_WORK(&sbi->sync_work, delayed_sync_fs);
        /*
         * Set default mount options
         * Parse mount options
@@ -1191,68 +1271,6 @@ failed_nomem:
        return -ENOMEM;
 }
 
-static int ufs_sync_fs(struct super_block *sb, int wait)
-{
-       struct ufs_sb_private_info * uspi;
-       struct ufs_super_block_first * usb1;
-       struct ufs_super_block_third * usb3;
-       unsigned flags;
-
-       lock_ufs(sb);
-       lock_super(sb);
-
-       UFSD("ENTER\n");
-
-       flags = UFS_SB(sb)->s_flags;
-       uspi = UFS_SB(sb)->s_uspi;
-       usb1 = ubh_get_usb_first(uspi);
-       usb3 = ubh_get_usb_third(uspi);
-
-       usb1->fs_time = cpu_to_fs32(sb, get_seconds());
-       if ((flags & UFS_ST_MASK) == UFS_ST_SUN  ||
-           (flags & UFS_ST_MASK) == UFS_ST_SUNOS ||
-           (flags & UFS_ST_MASK) == UFS_ST_SUNx86)
-               ufs_set_fs_state(sb, usb1, usb3,
-                               UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
-       ufs_put_cstotal(sb);
-       sb->s_dirt = 0;
-
-       UFSD("EXIT\n");
-       unlock_super(sb);
-       unlock_ufs(sb);
-
-       return 0;
-}
-
-static void ufs_write_super(struct super_block *sb)
-{
-       if (!(sb->s_flags & MS_RDONLY))
-               ufs_sync_fs(sb, 1);
-       else
-               sb->s_dirt = 0;
-}
-
-static void ufs_put_super(struct super_block *sb)
-{
-       struct ufs_sb_info * sbi = UFS_SB(sb);
-               
-       UFSD("ENTER\n");
-
-       if (sb->s_dirt)
-               ufs_write_super(sb);
-
-       if (!(sb->s_flags & MS_RDONLY))
-               ufs_put_super_internal(sb);
-       
-       ubh_brelse_uspi (sbi->s_uspi);
-       kfree (sbi->s_uspi);
-       kfree (sbi);
-       sb->s_fs_info = NULL;
-       UFSD("EXIT\n");
-       return;
-}
-
-
 static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
 {
        struct ufs_sb_private_info * uspi;
@@ -1308,7 +1326,6 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data)
                        ufs_set_fs_state(sb, usb1, usb3,
                                UFS_FSOK - fs32_to_cpu(sb, usb1->fs_time));
                ubh_mark_buffer_dirty (USPI_UBH(uspi));
-               sb->s_dirt = 0;
                sb->s_flags |= MS_RDONLY;
        } else {
        /*
@@ -1458,7 +1475,6 @@ static const struct super_operations ufs_super_ops = {
        .write_inode    = ufs_write_inode,
        .evict_inode    = ufs_evict_inode,
        .put_super      = ufs_put_super,
-       .write_super    = ufs_write_super,
        .sync_fs        = ufs_sync_fs,
        .statfs         = ufs_statfs,
        .remount_fs     = ufs_remount,
index 528750b7e701ab781018a7af83c83fff8de79277..343e6fc571e5b3976b6132d43dccb03b538d9380 100644 (file)
@@ -20,6 +20,10 @@ struct ufs_sb_info {
        unsigned s_mount_opt;
        struct mutex mutex;
        struct task_struct *mutex_owner;
+       struct super_block *sb;
+       int work_queued; /* non-zero if the delayed work is queued */
+       struct delayed_work sync_work; /* FS sync delayed work */
+       spinlock_t work_lock; /* protects sync_work and work_queued */
 };
 
 struct ufs_inode_info {
@@ -123,6 +127,7 @@ extern __printf(3, 4)
 void ufs_error(struct super_block *, const char *, const char *, ...);
 extern __printf(3, 4)
 void ufs_panic(struct super_block *, const char *, const char *, ...);
+void ufs_mark_sb_dirty(struct super_block *sb);
 
 /* symlink.c */
 extern const struct inode_operations ufs_fast_symlink_inode_operations;
index 8aba544f9fad80b2a79ca581d6360340cf5e2314..0cbd5d340b6705b9c6e22ff0a60a49891c302860 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/kernel.h>
 #include <linux/stat.h>
 #include <linux/fs.h>
+#include <linux/workqueue.h>
 
 #include <asm/div64.h>
 typedef __u64 __bitwise __fs64;
index 3a05a41b5d76b8bfbbc6399d287f78b56e06ccc4..1f1535d25a9bb726b96742fa82c59dec74183f51 100644 (file)
@@ -208,6 +208,7 @@ xfs_open_by_handle(
        struct inode            *inode;
        struct dentry           *dentry;
        fmode_t                 fmode;
+       struct path             path;
 
        if (!capable(CAP_SYS_ADMIN))
                return -XFS_ERROR(EPERM);
@@ -252,8 +253,10 @@ xfs_open_by_handle(
                goto out_dput;
        }
 
-       filp = dentry_open(dentry, mntget(parfilp->f_path.mnt),
-                          hreq->oflags, cred);
+       path.mnt = parfilp->f_path.mnt;
+       path.dentry = dentry;
+       filp = dentry_open(&path, hreq->oflags, cred);
+       dput(dentry);
        if (IS_ERR(filp)) {
                put_unused_fd(fd);
                return PTR_ERR(filp);
index 1a25fd80279882bae3c0a11176ec61b35ac830db..9c4340f5c3e0ff92bb84505155c3ba4f9a4bac54 100644 (file)
@@ -179,7 +179,7 @@ xfs_vn_create(
        struct inode    *dir,
        struct dentry   *dentry,
        umode_t         mode,
-       struct nameidata *nd)
+       bool            flags)
 {
        return xfs_vn_mknod(dir, dentry, mode, 0);
 }
@@ -197,7 +197,7 @@ STATIC struct dentry *
 xfs_vn_lookup(
        struct inode    *dir,
        struct dentry   *dentry,
-       struct nameidata *nd)
+       unsigned int flags)
 {
        struct xfs_inode *cip;
        struct xfs_name name;
@@ -222,7 +222,7 @@ STATIC struct dentry *
 xfs_vn_ci_lookup(
        struct inode    *dir,
        struct dentry   *dentry,
-       struct nameidata *nd)
+       unsigned int flags)
 {
        struct xfs_inode *ip;
        struct xfs_name xname;
index 9e6e1c6eb60a94885f1e9c08038cc8e081f86547..18fd41033e03a97be6f3e070082d1aca5323330f 100644 (file)
@@ -117,9 +117,6 @@ struct acpi_device;
 typedef int (*acpi_op_add) (struct acpi_device * device);
 typedef int (*acpi_op_remove) (struct acpi_device * device, int type);
 typedef int (*acpi_op_start) (struct acpi_device * device);
-typedef int (*acpi_op_suspend) (struct acpi_device * device,
-                               pm_message_t state);
-typedef int (*acpi_op_resume) (struct acpi_device * device);
 typedef int (*acpi_op_bind) (struct acpi_device * device);
 typedef int (*acpi_op_unbind) (struct acpi_device * device);
 typedef void (*acpi_op_notify) (struct acpi_device * device, u32 event);
@@ -133,8 +130,6 @@ struct acpi_device_ops {
        acpi_op_add add;
        acpi_op_remove remove;
        acpi_op_start start;
-       acpi_op_suspend suspend;
-       acpi_op_resume resume;
        acpi_op_bind bind;
        acpi_op_unbind unbind;
        acpi_op_notify notify;
index 9d650476d5dcf8eb346c8520db639efbb9907964..64ec644808bcb82951f38eaa682cb536e605d7bf 100644 (file)
@@ -59,10 +59,7 @@ struct acpi_processor_cx {
        u8 entry_method;
        u8 index;
        u32 latency;
-       u32 latency_ticks;
        u32 power;
-       u32 usage;
-       u64 time;
        u8 bm_sts_skip;
        char desc[ACPI_CX_DESC_LEN];
 };
@@ -334,8 +331,8 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr);
 int acpi_processor_hotplug(struct acpi_processor *pr);
 int acpi_processor_power_exit(struct acpi_processor *pr,
                              struct acpi_device *device);
-int acpi_processor_suspend(struct acpi_device * device, pm_message_t state);
-int acpi_processor_resume(struct acpi_device * device);
+int acpi_processor_suspend(struct device *dev);
+int acpi_processor_resume(struct device *dev);
 extern struct cpuidle_driver acpi_idle_driver;
 
 /* in processor_thermal.c */
index 2521a95fa6d98597d1fafe4d4cff23ce9dc0f069..44c87e731e9d4c5fff13cbf851694cd41356fb04 100644 (file)
@@ -163,16 +163,8 @@ struct ceph_connection {
 
        /* connection negotiation temps */
        char in_banner[CEPH_BANNER_MAX_LEN];
-       union {
-               struct {  /* outgoing connection */
-                       struct ceph_msg_connect out_connect;
-                       struct ceph_msg_connect_reply in_reply;
-               };
-               struct {  /* incoming */
-                       struct ceph_msg_connect in_connect;
-                       struct ceph_msg_connect_reply out_reply;
-               };
-       };
+       struct ceph_msg_connect out_connect;
+       struct ceph_msg_connect_reply in_reply;
        struct ceph_entity_addr actual_peer_addr;
 
        /* message out temps */
index 6c26a3da0e03173b29ce1535c9833537f85a6786..89dcd30ac8ea81144fe5e44d00e0c473e01331f8 100644 (file)
@@ -34,6 +34,7 @@ struct cpuidle_driver;
 struct cpuidle_state_usage {
        void            *driver_data;
 
+       unsigned long long      disable;
        unsigned long long      usage;
        unsigned long long      time; /* in US */
 };
@@ -46,7 +47,7 @@ struct cpuidle_state {
        unsigned int    exit_latency; /* in US */
        int             power_usage; /* in mW */
        unsigned int    target_residency; /* in US */
-       unsigned int    disable;
+       bool            disabled; /* disabled on all CPUs */
 
        int (*enter)    (struct cpuidle_device *dev,
                        struct cpuidle_driver *drv,
@@ -136,13 +137,17 @@ struct cpuidle_driver {
 extern void disable_cpuidle(void);
 extern int cpuidle_idle_call(void);
 extern int cpuidle_register_driver(struct cpuidle_driver *drv);
-struct cpuidle_driver *cpuidle_get_driver(void);
+extern struct cpuidle_driver *cpuidle_get_driver(void);
+extern struct cpuidle_driver *cpuidle_driver_ref(void);
+extern void cpuidle_driver_unref(void);
 extern void cpuidle_unregister_driver(struct cpuidle_driver *drv);
 extern int cpuidle_register_device(struct cpuidle_device *dev);
 extern void cpuidle_unregister_device(struct cpuidle_device *dev);
 
 extern void cpuidle_pause_and_lock(void);
 extern void cpuidle_resume_and_unlock(void);
+extern void cpuidle_pause(void);
+extern void cpuidle_resume(void);
 extern int cpuidle_enable_device(struct cpuidle_device *dev);
 extern void cpuidle_disable_device(struct cpuidle_device *dev);
 extern int cpuidle_wrap_enter(struct cpuidle_device *dev,
@@ -157,6 +162,8 @@ static inline int cpuidle_idle_call(void) { return -ENODEV; }
 static inline int cpuidle_register_driver(struct cpuidle_driver *drv)
 {return -ENODEV; }
 static inline struct cpuidle_driver *cpuidle_get_driver(void) {return NULL; }
+static inline struct cpuidle_driver *cpuidle_driver_ref(void) {return NULL; }
+static inline void cpuidle_driver_unref(void) {}
 static inline void cpuidle_unregister_driver(struct cpuidle_driver *drv) { }
 static inline int cpuidle_register_device(struct cpuidle_device *dev)
 {return -ENODEV; }
@@ -164,6 +171,8 @@ static inline void cpuidle_unregister_device(struct cpuidle_device *dev) { }
 
 static inline void cpuidle_pause_and_lock(void) { }
 static inline void cpuidle_resume_and_unlock(void) { }
+static inline void cpuidle_pause(void) { }
+static inline void cpuidle_resume(void) { }
 static inline int cpuidle_enable_device(struct cpuidle_device *dev)
 {return -ENODEV; }
 static inline void cpuidle_disable_device(struct cpuidle_device *dev) { }
@@ -202,14 +211,7 @@ struct cpuidle_governor {
 extern int cpuidle_register_governor(struct cpuidle_governor *gov);
 extern void cpuidle_unregister_governor(struct cpuidle_governor *gov);
 
-#ifdef CONFIG_INTEL_IDLE
-extern int intel_idle_cpu_init(int cpu);
 #else
-static inline int intel_idle_cpu_init(int cpu) { return -1; }
-#endif
-
-#else
-static inline int intel_idle_cpu_init(int cpu) { return -1; }
 
 static inline int cpuidle_register_governor(struct cpuidle_governor *gov)
 {return 0;}
index 094789ff3e9f4e958ab35a90aa001d05997a0fa2..caa34e50537e895a7a4b5149148f03157e253129 100644 (file)
@@ -128,7 +128,7 @@ struct dentry {
                struct rcu_head d_rcu;
        } d_u;
        struct list_head d_subdirs;     /* our children */
-       struct list_head d_alias;       /* inode alias list */
+       struct hlist_node d_alias;      /* inode alias list */
 };
 
 /*
@@ -144,7 +144,7 @@ enum dentry_d_lock_class
 };
 
 struct dentry_operations {
-       int (*d_revalidate)(struct dentry *, struct nameidata *);
+       int (*d_revalidate)(struct dentry *, unsigned int);
        int (*d_hash)(const struct dentry *, const struct inode *,
                        struct qstr *);
        int (*d_compare)(const struct dentry *, const struct inode *,
index 07261d52a6dfabee77c5ffbc34953a6faec1fdce..1148575fd134e1b02e02acaa2d8892f4e6e91237 100644 (file)
@@ -53,4 +53,5 @@ void dw_apb_clocksource_start(struct dw_apb_clocksource *dw_cs);
 cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs);
 void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs);
 
+extern struct sys_timer dw_apb_timer;
 #endif /* __DW_APB_TIMER_H__ */
index 58bf158c53d91aca4f7c60a22f0109851aa53b21..a22408bac0d005bca76c99e30a5d88b83e294561 100644 (file)
@@ -39,4 +39,7 @@ extern void put_unused_fd(unsigned int fd);
 
 extern void fd_install(unsigned int fd, struct file *file);
 
+extern void flush_delayed_fput(void);
+extern void __fput_sync(struct file *);
+
 #endif /* __LINUX_FILE_H */
index 17fd887c798f3fff64aaf27bf82a81a2d237ee31..8fabb037a48db40e8a490fc74c15ce907ad9059a 100644 (file)
@@ -826,7 +826,7 @@ struct inode {
        struct list_head        i_lru;          /* inode LRU list */
        struct list_head        i_sb_list;
        union {
-               struct list_head        i_dentry;
+               struct hlist_head       i_dentry;
                struct rcu_head         i_rcu;
        };
        u64                     i_version;
@@ -1571,7 +1571,7 @@ extern void unlock_super(struct super_block *);
 /*
  * VFS helper functions..
  */
-extern int vfs_create(struct inode *, struct dentry *, umode_t, struct nameidata *);
+extern int vfs_create(struct inode *, struct dentry *, umode_t, bool);
 extern int vfs_mkdir(struct inode *, struct dentry *, umode_t);
 extern int vfs_mknod(struct inode *, struct dentry *, umode_t, dev_t);
 extern int vfs_symlink(struct inode *, struct dentry *, const char *);
@@ -1666,7 +1666,7 @@ struct file_operations {
 };
 
 struct inode_operations {
-       struct dentry * (*lookup) (struct inode *,struct dentry *, struct nameidata *);
+       struct dentry * (*lookup) (struct inode *,struct dentry *, unsigned int);
        void * (*follow_link) (struct dentry *, struct nameidata *);
        int (*permission) (struct inode *, int);
        struct posix_acl * (*get_acl)(struct inode *, int);
@@ -1674,7 +1674,7 @@ struct inode_operations {
        int (*readlink) (struct dentry *, char __user *,int);
        void (*put_link) (struct dentry *, struct nameidata *, void *);
 
-       int (*create) (struct inode *,struct dentry *,umode_t,struct nameidata *);
+       int (*create) (struct inode *,struct dentry *, umode_t, bool);
        int (*link) (struct dentry *,struct inode *,struct dentry *);
        int (*unlink) (struct inode *,struct dentry *);
        int (*symlink) (struct inode *,struct dentry *,const char *);
@@ -1693,6 +1693,9 @@ struct inode_operations {
        int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start,
                      u64 len);
        int (*update_time)(struct inode *, struct timespec *, int);
+       int (*atomic_open)(struct inode *, struct dentry *,
+                          struct file *, unsigned open_flag,
+                          umode_t create_mode, int *opened);
 } ____cacheline_aligned;
 
 struct seq_file;
@@ -1911,7 +1914,7 @@ void free_anon_bdev(dev_t);
 struct super_block *sget(struct file_system_type *type,
                        int (*test)(struct super_block *,void *),
                        int (*set)(struct super_block *,void *),
-                       void *data);
+                       int flags, void *data);
 extern struct dentry *mount_pseudo(struct file_system_type *, char *,
        const struct super_operations *ops,
        const struct dentry_operations *dops,
@@ -2057,10 +2060,17 @@ extern long do_sys_open(int dfd, const char __user *filename, int flags,
 extern struct file *filp_open(const char *, int, umode_t);
 extern struct file *file_open_root(struct dentry *, struct vfsmount *,
                                   const char *, int);
-extern struct file * dentry_open(struct dentry *, struct vfsmount *, int,
-                                const struct cred *);
+extern struct file * dentry_open(const struct path *, int, const struct cred *);
 extern int filp_close(struct file *, fl_owner_t id);
 extern char * getname(const char __user *);
+enum {
+       FILE_CREATED = 1,
+       FILE_OPENED = 2
+};
+extern int finish_open(struct file *file, struct dentry *dentry,
+                       int (*open)(struct inode *, struct file *),
+                       int *opened);
+extern int finish_no_open(struct file *file, struct dentry *dentry);
 
 /* fs/ioctl.c */
 
@@ -2091,6 +2101,7 @@ extern sector_t blkdev_max_block(struct block_device *bdev);
 extern void bd_forget(struct inode *inode);
 extern void bdput(struct block_device *);
 extern void invalidate_bdev(struct block_device *);
+extern void iterate_bdevs(void (*)(struct block_device *, void *), void *);
 extern int sync_blockdev(struct block_device *bdev);
 extern void kill_bdev(struct block_device *);
 extern struct super_block *freeze_bdev(struct block_device *);
@@ -2112,6 +2123,10 @@ static inline int thaw_bdev(struct block_device *bdev, struct super_block *sb)
 {
        return 0;
 }
+
+static inline void iterate_bdevs(void (*f)(struct block_device *, void *), void *arg)
+{
+}
 #endif
 extern int sync_filesystem(struct super_block *);
 extern const struct file_operations def_blk_fops;
@@ -2438,7 +2453,7 @@ extern loff_t noop_llseek(struct file *file, loff_t offset, int origin);
 extern loff_t no_llseek(struct file *file, loff_t offset, int origin);
 extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin);
 extern loff_t generic_file_llseek_size(struct file *file, loff_t offset,
-               int origin, loff_t maxsize);
+               int origin, loff_t maxsize, loff_t eof);
 extern int generic_file_open(struct inode * inode, struct file * filp);
 extern int nonseekable_open(struct inode * inode, struct file * filp);
 
@@ -2560,7 +2575,7 @@ extern int simple_write_end(struct file *file, struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned copied,
                        struct page *page, void *fsdata);
 
-extern struct dentry *simple_lookup(struct inode *, struct dentry *, struct nameidata *);
+extern struct dentry *simple_lookup(struct inode *, struct dentry *, unsigned int flags);
 extern ssize_t generic_read_dir(struct file *, char __user *, size_t, loff_t *);
 extern const struct file_operations simple_dir_operations;
 extern const struct inode_operations simple_dir_inode_operations;
index 176a939d15474cf73baff4b1d0020c2e1212d19b..af961d6f7ab14edc6b3a0c8ec813124fba5415da 100644 (file)
@@ -65,7 +65,7 @@ struct trace_iterator {
        void                    *private;
        int                     cpu_file;
        struct mutex            mutex;
-       struct ring_buffer_iter *buffer_iter[NR_CPUS];
+       struct ring_buffer_iter **buffer_iter;
        unsigned long           iter_flags;
 
        /* trace_seq for __print_flags() and __print_symbolic() etc. */
@@ -207,6 +207,9 @@ struct ftrace_event_call {
         *   bit 1:             enabled
         *   bit 2:             filter_active
         *   bit 3:             enabled cmd record
+        *   bit 4:             allow trace by non root (cap any)
+        *   bit 5:             failed to apply filter
+        *   bit 6:             ftrace internal event (do not enable)
         *
         * Changes to flags must hold the event_mutex.
         *
index 3993477103a5673e65f69a751ba302d5c03b0a0e..555382660bc40e00eb4876eae585f3f9a5e6eea6 100644 (file)
@@ -683,7 +683,6 @@ struct twl4030_audio_data {
 };
 
 struct twl4030_platform_data {
-       unsigned                                irq_base, irq_end;
        struct twl4030_clock_init_data          *clock;
        struct twl4030_bci_platform_data        *bci;
        struct twl4030_gpio_platform_data       *gpio;
index 9e65eff6af3bdc5dd6e865296233c8f9a1cd2a10..8a74761869908ea56a3e840f2f0fa9a98df20de5 100644 (file)
@@ -168,8 +168,8 @@ extern struct cred init_cred;
        .children       = LIST_HEAD_INIT(tsk.children),                 \
        .sibling        = LIST_HEAD_INIT(tsk.sibling),                  \
        .group_leader   = &tsk,                                         \
-       RCU_INIT_POINTER(.real_cred, &init_cred),                       \
-       RCU_INIT_POINTER(.cred, &init_cred),                            \
+       RCU_POINTER_INITIALIZER(real_cred, &init_cred),                 \
+       RCU_POINTER_INITIALIZER(cred, &init_cred),                      \
        .comm           = INIT_TASK_COMM,                               \
        .thread         = INIT_THREAD,                                  \
        .fs             = &init_fs,                                     \
index e6ca56de99364fb435a7bf2932a1cf5e37e3146b..78e2ada50cd5a95c7b7527777a870428afa5352c 100644 (file)
@@ -308,6 +308,8 @@ enum {
 
 struct intel_iommu {
        void __iomem    *reg; /* Pointer to hardware regs, virtual addr */
+       u64             reg_phys; /* physical address of hw register set */
+       u64             reg_size; /* size of hw register set */
        u64             cap;
        u64             ecap;
        u32             gcmd; /* Holds TE, EAFL. Don't need SRTP, SFL, WBF */
index 7fd2d2138bf3de8130e5660922a32fe81a47f22b..069e4075f8720331f99696e34a563d4ac1b76e35 100644 (file)
@@ -67,4 +67,13 @@ int check_signature(const volatile void __iomem *io_addr,
                        const unsigned char *signature, int length);
 void devm_ioremap_release(struct device *dev, void *res);
 
+/*
+ * Some systems do not have legacy ISA devices.
+ * /dev/port is not a valid interface on these systems.
+ * So for those archs, <asm/io.h> should define the following symbol.
+ */
+#ifndef arch_has_dev_port
+#define arch_has_dev_port()     (1)
+#endif
+
 #endif /* _LINUX_IO_H */
index a5261e3d2e3c26f3cf645af875e4093d5adcaa77..553fb66da130a3a9b3700958c5cce22a6b5cda73 100644 (file)
@@ -150,9 +150,7 @@ struct irq_data {
        void                    *handler_data;
        void                    *chip_data;
        struct msi_desc         *msi_desc;
-#ifdef CONFIG_SMP
        cpumask_var_t           affinity;
-#endif
 };
 
 /*
index c513a40510f534f3136b015f8fafa2d597b18099..0976fc46d1e0143b1a167cde02e2026e54ba8db2 100644 (file)
@@ -42,8 +42,7 @@
  * allowed.
  *
  * Not initializing the key (static data is initialized to 0s anyway) is the
- * same as using STATIC_KEY_INIT_FALSE and static_key_false() is
- * equivalent with static_branch().
+ * same as using STATIC_KEY_INIT_FALSE.
  *
 */
 
@@ -107,12 +106,6 @@ static __always_inline bool static_key_true(struct static_key *key)
        return !static_key_false(key);
 }
 
-/* Deprecated. Please use 'static_key_false() instead. */
-static __always_inline bool static_branch(struct static_key *key)
-{
-       return arch_static_branch(key);
-}
-
 extern struct jump_entry __start___jump_table[];
 extern struct jump_entry __stop___jump_table[];
 
@@ -166,14 +159,6 @@ static __always_inline bool static_key_true(struct static_key *key)
        return false;
 }
 
-/* Deprecated. Please use 'static_key_false() instead. */
-static __always_inline bool static_branch(struct static_key *key)
-{
-       if (unlikely(atomic_read(&key->enabled)) > 0)
-               return true;
-       return false;
-}
-
 static inline void static_key_slow_inc(struct static_key *key)
 {
        atomic_inc(&key->enabled);
index e07f5e0c5df4400eb34ac0d89150003e512381b0..604382143bcfccd6772260ed56e16589800af83c 100644 (file)
@@ -377,7 +377,6 @@ extern enum system_states {
        SYSTEM_HALT,
        SYSTEM_POWER_OFF,
        SYSTEM_RESTART,
-       SYSTEM_SUSPEND_DISK,
 } system_state;
 
 #define TAINT_PROPRIETARY_MODULE       0
index 4cd22ed627efd79205860b0efa6dde15a07897ed..cef3b315ba7c2e0786e78940cc476c8e12bc89ce 100644 (file)
@@ -303,7 +303,9 @@ static inline bool key_is_instantiated(const struct key *key)
                                   rwsem_is_locked(&((struct key *)(KEY))->sem)))
 
 #define rcu_assign_keypointer(KEY, PAYLOAD)                            \
-       (rcu_assign_pointer((KEY)->payload.rcudata, PAYLOAD))
+do {                                                                   \
+       rcu_assign_pointer((KEY)->payload.rcudata, (PAYLOAD));          \
+} while (0)
 
 #ifdef CONFIG_SYSCTL
 extern ctl_table key_sysctls[];
index d6bd50110ec2f80956ada720336052b0e1d685f7..2e7a1e032c71a91e6a9dff98a0b637d621932a25 100644 (file)
@@ -55,12 +55,17 @@ struct kmsg_dumper {
 #ifdef CONFIG_PRINTK
 void kmsg_dump(enum kmsg_dump_reason reason);
 
+bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog,
+                              char *line, size_t size, size_t *len);
+
 bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
                        char *line, size_t size, size_t *len);
 
 bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
                          char *buf, size_t size, size_t *len);
 
+void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper);
+
 void kmsg_dump_rewind(struct kmsg_dumper *dumper);
 
 int kmsg_dump_register(struct kmsg_dumper *dumper);
@@ -71,6 +76,13 @@ static inline void kmsg_dump(enum kmsg_dump_reason reason)
 {
 }
 
+static inline bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper,
+                                            bool syslog, const char *line,
+                                            size_t size, size_t *len)
+{
+       return false;
+}
+
 static inline bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
                                const char *line, size_t size, size_t *len)
 {
@@ -83,6 +95,10 @@ static inline bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog,
        return false;
 }
 
+static inline void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper)
+{
+}
+
 static inline void kmsg_dump_rewind(struct kmsg_dumper *dumper)
 {
 }
index 21603b42f22fb150f73a5be185e6c1d615de6329..0b2e0ed309f51038583a23f168383ab6e6a6f72c 100644 (file)
@@ -347,6 +347,7 @@ struct s5m_platform_data {
        bool                            buck_voltage_lock;
 
        int                             buck_gpios[3];
+       int                             buck_ds[3];
        int                             buck2_voltage[8];
        bool                            buck2_gpiodvs;
        int                             buck3_voltage[8];
@@ -369,6 +370,10 @@ struct s5m_platform_data {
        bool                            buck2_ramp_enable;
        bool                            buck3_ramp_enable;
        bool                            buck4_ramp_enable;
+
+       int                             buck2_init;
+       int                             buck3_init;
+       int                             buck4_init;
 };
 
 #endif /*  __LINUX_MFD_S5M_CORE_H */
index f5171dbf8850c5c036e2e431ade03382bbe21983..d83af39815abca0e17f8282b92791289fec15007 100644 (file)
@@ -101,6 +101,7 @@ struct tmio_mmc_host;
 struct tmio_mmc_data {
        unsigned int                    hclk;
        unsigned long                   capabilities;
+       unsigned long                   capabilities2;
        unsigned long                   flags;
        u32                             ocr_mask;       /* available voltages */
        struct tmio_mmc_dma             *dma;
@@ -110,6 +111,9 @@ struct tmio_mmc_data {
        void (*set_clk_div)(struct platform_device *host, int state);
        int (*get_cd)(struct platform_device *host);
        int (*write16_hook)(struct tmio_mmc_host *host, int addr);
+       /* clock management callbacks */
+       int (*clk_enable)(struct platform_device *pdev, unsigned int *f);
+       void (*clk_disable)(struct platform_device *pdev);
 };
 
 /*
index e030ef9a64eede0ca1bc8ca529a6788624c6017c..12c06870829af2add4caed14a9ea57f069b7479f 100644 (file)
@@ -217,7 +217,8 @@ enum tps65217_regulator_id {
  * Board data may be used to initialize regulator.
  */
 struct tps65217_board {
-       struct regulator_init_data *tps65217_init_data;
+       struct regulator_init_data *tps65217_init_data[TPS65217_NUM_REGULATOR];
+       struct device_node *of_node[TPS65217_NUM_REGULATOR];
 };
 
 /**
@@ -227,11 +228,6 @@ struct tps65217_board {
  * @max_uV:            minimum micro volts
  * @vsel_to_uv:                Function pointer to get voltage from selector
  * @uv_to_vsel:                Function pointer to get selector from voltage
- * @table:             Table for non-uniform voltage step-size
- * @table_len:         Length of the voltage table
- * @enable_mask:       Regulator enable mask bits
- * @set_vout_reg:      Regulator output voltage set register
- * @set_vout_mask:     Regulator output voltage set mask
  *
  * This data is used to check the regualtor voltage limits while setting.
  */
@@ -241,11 +237,6 @@ struct tps_info {
        int max_uV;
        int (*vsel_to_uv)(unsigned int vsel);
        int (*uv_to_vsel)(int uV, unsigned int *vsel);
-       const int *table;
-       unsigned int table_len;
-       unsigned int enable_mask;
-       unsigned int set_vout_reg;
-       unsigned int set_vout_mask;
 };
 
 /**
index dd8dc0a6c46243141ea59e325cde465fb993bce5..6c4c478e21a4f79d33577db36faba4e9f37f3cd3 100644 (file)
@@ -880,4 +880,10 @@ static inline int tps65910_reg_clear_bits(struct tps65910 *tps65910, u8 reg,
        return regmap_update_bits(tps65910->regmap, reg, mask, 0);
 }
 
+static inline int tps65910_reg_update_bits(struct tps65910 *tps65910, u8 reg,
+                                          u8 mask, u8 val)
+{
+       return regmap_update_bits(tps65910->regmap, reg, mask, val);
+}
+
 #endif /*  __LINUX_MFD_TPS65910_H */
index b36d08ce5c578dcd18e224828217ded481de54ee..f9f279cf5b1bd558520aa23757cb53e0928a18a3 100644 (file)
@@ -1591,6 +1591,7 @@ void vmemmap_populate_print_last(void);
 enum mf_flags {
        MF_COUNT_INCREASED = 1 << 0,
        MF_ACTION_REQUIRED = 1 << 1,
+       MF_MUST_KILL = 1 << 2,
 };
 extern int memory_failure(unsigned long pfn, int trapno, int flags);
 extern void memory_failure_queue(unsigned long pfn, int trapno, int flags);
index d76513b5b2631b1daf7b9aa4c4b03f1d52d83d32..111aca5e97f3d1801ace7ed7c009af4165a3869a 100644 (file)
@@ -149,6 +149,7 @@ struct sd_switch_caps {
 #define SD_SET_CURRENT_LIMIT_400       1
 #define SD_SET_CURRENT_LIMIT_600       2
 #define SD_SET_CURRENT_LIMIT_800       3
+#define SD_SET_CURRENT_NO_CHANGE       (-1)
 
 #define SD_MAX_CURRENT_200     (1 << SD_SET_CURRENT_LIMIT_200)
 #define SD_MAX_CURRENT_400     (1 << SD_SET_CURRENT_LIMIT_400)
diff --git a/include/linux/mmc/cd-gpio.h b/include/linux/mmc/cd-gpio.h
deleted file mode 100644 (file)
index cefaba0..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * Generic GPIO card-detect helper header
- *
- * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef MMC_CD_GPIO_H
-#define MMC_CD_GPIO_H
-
-struct mmc_host;
-int mmc_cd_gpio_request(struct mmc_host *host, unsigned int gpio);
-void mmc_cd_gpio_free(struct mmc_host *host);
-
-#endif
index 0707d228d7f11d675743aa8d58b5b5c05274295f..f578a71d82a6b71bd1c9203b53e77713c4543065 100644 (file)
@@ -11,6 +11,7 @@
 #define LINUX_MMC_HOST_H
 
 #include <linux/leds.h>
+#include <linux/mutex.h>
 #include <linux/sched.h>
 #include <linux/device.h>
 #include <linux/fault-inject.h>
@@ -150,11 +151,31 @@ struct mmc_async_req {
        int (*err_check) (struct mmc_card *, struct mmc_async_req *);
 };
 
-struct mmc_hotplug {
-       unsigned int irq;
+/**
+ * struct mmc_slot - MMC slot functions
+ *
+ * @cd_irq:            MMC/SD-card slot hotplug detection IRQ or -EINVAL
+ * @lock:              protect the @handler_priv pointer
+ * @handler_priv:      MMC/SD-card slot context
+ *
+ * Some MMC/SD host controllers implement slot-functions like card and
+ * write-protect detection natively. However, a large number of controllers
+ * leave these functions to the CPU. This struct provides a hook to attach
+ * such slot-function drivers.
+ */
+struct mmc_slot {
+       int cd_irq;
+       struct mutex lock;
        void *handler_priv;
 };
 
+struct regulator;
+
+struct mmc_supply {
+       struct regulator *vmmc;         /* Card power supply */
+       struct regulator *vqmmc;        /* Optional Vccq supply */
+};
+
 struct mmc_host {
        struct device           *parent;
        struct device           class_dev;
@@ -168,6 +189,9 @@ struct mmc_host {
        u32                     ocr_avail_sd;   /* SD-specific OCR */
        u32                     ocr_avail_mmc;  /* MMC-specific OCR */
        struct notifier_block   pm_notify;
+       u32                     max_current_330;
+       u32                     max_current_300;
+       u32                     max_current_180;
 
 #define MMC_VDD_165_195                0x00000080      /* VDD voltage 1.65 - 1.95 */
 #define MMC_VDD_20_21          0x00000100      /* VDD voltage 2.0 ~ 2.1 */
@@ -211,16 +235,9 @@ struct mmc_host {
 #define MMC_CAP_UHS_SDR50      (1 << 17)       /* Host supports UHS SDR50 mode */
 #define MMC_CAP_UHS_SDR104     (1 << 18)       /* Host supports UHS SDR104 mode */
 #define MMC_CAP_UHS_DDR50      (1 << 19)       /* Host supports UHS DDR50 mode */
-#define MMC_CAP_SET_XPC_330    (1 << 20)       /* Host supports >150mA current at 3.3V */
-#define MMC_CAP_SET_XPC_300    (1 << 21)       /* Host supports >150mA current at 3.0V */
-#define MMC_CAP_SET_XPC_180    (1 << 22)       /* Host supports >150mA current at 1.8V */
 #define MMC_CAP_DRIVER_TYPE_A  (1 << 23)       /* Host supports Driver Type A */
 #define MMC_CAP_DRIVER_TYPE_C  (1 << 24)       /* Host supports Driver Type C */
 #define MMC_CAP_DRIVER_TYPE_D  (1 << 25)       /* Host supports Driver Type D */
-#define MMC_CAP_MAX_CURRENT_200        (1 << 26)       /* Host max current limit is 200mA */
-#define MMC_CAP_MAX_CURRENT_400        (1 << 27)       /* Host max current limit is 400mA */
-#define MMC_CAP_MAX_CURRENT_600        (1 << 28)       /* Host max current limit is 600mA */
-#define MMC_CAP_MAX_CURRENT_800        (1 << 29)       /* Host max current limit is 800mA */
 #define MMC_CAP_CMD23          (1 << 30)       /* CMD23 supported. */
 #define MMC_CAP_HW_RESET       (1 << 31)       /* Hardware reset */
 
@@ -238,6 +255,8 @@ struct mmc_host {
 #define MMC_CAP2_BROKEN_VOLTAGE        (1 << 7)        /* Use the broken voltage */
 #define MMC_CAP2_DETECT_ON_ERR (1 << 8)        /* On I/O err check card removal */
 #define MMC_CAP2_HC_ERASE_SZ   (1 << 9)        /* High-capacity erase size */
+#define MMC_CAP2_CD_ACTIVE_HIGH        (1 << 10)       /* Card-detect signal active high */
+#define MMC_CAP2_RO_ACTIVE_HIGH        (1 << 11)       /* Write-protect signal active high */
 
        mmc_pm_flag_t           pm_caps;        /* supported pm features */
        unsigned int        power_notify_type;
@@ -290,7 +309,7 @@ struct mmc_host {
 
        struct delayed_work     detect;
        int                     detect_change;  /* card detect flag */
-       struct mmc_hotplug      hotplug;
+       struct mmc_slot         slot;
 
        const struct mmc_bus_ops *bus_ops;      /* current bus driver */
        unsigned int            bus_refs;       /* reference counter */
@@ -309,6 +328,7 @@ struct mmc_host {
 #ifdef CONFIG_REGULATOR
        bool                    regulator_enabled; /* regulator state */
 #endif
+       struct mmc_supply       supply;
 
        struct dentry           *debugfs_root;
 
@@ -357,13 +377,12 @@ static inline void mmc_signal_sdio_irq(struct mmc_host *host)
        wake_up_process(host->sdio_irq_thread);
 }
 
-struct regulator;
-
 #ifdef CONFIG_REGULATOR
 int mmc_regulator_get_ocrmask(struct regulator *supply);
 int mmc_regulator_set_ocr(struct mmc_host *mmc,
                        struct regulator *supply,
                        unsigned short vdd_bit);
+int mmc_regulator_get_supply(struct mmc_host *mmc);
 #else
 static inline int mmc_regulator_get_ocrmask(struct regulator *supply)
 {
@@ -376,6 +395,11 @@ static inline int mmc_regulator_set_ocr(struct mmc_host *mmc,
 {
        return 0;
 }
+
+static inline int mmc_regulator_get_supply(struct mmc_host *mmc)
+{
+       return 0;
+}
 #endif
 
 int mmc_card_awake(struct mmc_host *host);
index e9051e1cb1ce38434d0443cfee5c7c74e43a1967..ac83b105bedd66d2fb051ead198d11297ab650c3 100644 (file)
@@ -122,6 +122,7 @@ struct sdhci_host {
 #define SDHCI_PV_ENABLED       (1<<8)  /* Preset value enabled */
 #define SDHCI_SDIO_IRQ_ENABLED (1<<9)  /* SDIO irq enabled */
 #define SDHCI_HS200_NEEDS_TUNING (1<<10)       /* HS200 needs tuning */
+#define SDHCI_USING_RETUNING_TIMER (1<<11)     /* Host is using a retuning timer for the card */
 
        unsigned int version;   /* SDHCI spec. version */
 
@@ -155,7 +156,8 @@ struct sdhci_host {
 
        struct timer_list timer;        /* Timer for timeouts */
 
-       unsigned int caps;      /* Alternative capabilities */
+       unsigned int caps;      /* Alternative CAPABILITY_0 */
+       unsigned int caps1;     /* Alternative CAPABILITY_1 */
 
        unsigned int            ocr_avail_sdio; /* OCR bit masks */
        unsigned int            ocr_avail_sd;
index 05f0e3db1c12b6681a820ff48519b0abe03b983b..c2f73cbb4d5cb14912a01efa59983b21e5ff081a 100644 (file)
@@ -44,6 +44,8 @@ struct sh_mmcif_plat_data {
        struct sh_mmcif_dma     *dma;           /* Deprecated. Instead */
        unsigned int            slave_id_tx;    /* use embedded slave_id_[tr]x */
        unsigned int            slave_id_rx;
+       bool                    use_cd_gpio : 1;
+       unsigned int            cd_gpio;
        u8                      sup_pclk;       /* 1 :SH7757, 0: SH7724/SH7372 */
        unsigned long           caps;
        u32                     ocr;
index e94e620aeddc01a49b4f6073f54400ff343e66e2..b65679ffa880a3fae58ae49fa574aedeb9dfd333 100644 (file)
@@ -23,6 +23,7 @@ struct sh_mobile_sdhi_info {
        int dma_slave_rx;
        unsigned long tmio_flags;
        unsigned long tmio_caps;
+       unsigned long tmio_caps2;
        u32 tmio_ocr_mask;      /* available MMC voltages */
        unsigned int cd_gpio;
        struct tmio_mmc_data *pdata;
diff --git a/include/linux/mmc/slot-gpio.h b/include/linux/mmc/slot-gpio.h
new file mode 100644 (file)
index 0000000..7d88d27
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Generic GPIO card-detect helper header
+ *
+ * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef MMC_SLOT_GPIO_H
+#define MMC_SLOT_GPIO_H
+
+struct mmc_host;
+
+int mmc_gpio_get_ro(struct mmc_host *host);
+int mmc_gpio_request_ro(struct mmc_host *host, unsigned int gpio);
+void mmc_gpio_free_ro(struct mmc_host *host);
+
+int mmc_gpio_get_cd(struct mmc_host *host);
+int mmc_gpio_request_cd(struct mmc_host *host, unsigned int gpio);
+void mmc_gpio_free_cd(struct mmc_host *host);
+
+#endif
diff --git a/include/linux/mxsfb.h b/include/linux/mxsfb.h
new file mode 100644 (file)
index 0000000..f14943d
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+#ifndef __LINUX_MXSFB_H
+#define __LINUX_MXSFB_H
+
+#include <linux/fb.h>
+
+#define STMLCDIF_8BIT 1        /** pixel data bus to the display is of 8 bit width */
+#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
+#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 */
+
+struct mxsfb_platform_data {
+       struct fb_videomode *mode_list;
+       unsigned mode_count;
+
+       unsigned default_bpp;
+
+       unsigned dotclk_delay;  /* refer manual HW_LCDIF_VDCTRL4 register */
+       unsigned ld_intf_width; /* refer STMLCDIF_* macros */
+
+       unsigned fb_size;       /* Size of the video memory. If zero a
+                                * default will be used
+                                */
+       unsigned long fb_phys;  /* physical address for the video memory. If
+                                * zero the framebuffer memory will be dynamically
+                                * allocated. If specified,fb_size must also be specified.
+                                * fb_phys must be unused by Linux.
+                                */
+};
+
+#endif /* __LINUX_MXSFB_H */
index ffc02135c483c2c6363eed8dc0a4b15b2def6656..d2ef8b34b96722078c5ab7a3914579d5b50a8ca6 100644 (file)
@@ -7,12 +7,6 @@
 
 struct vfsmount;
 
-struct open_intent {
-       int     flags;
-       int     create_mode;
-       struct file *file;
-};
-
 enum { MAX_NESTED_LINKS = 8 };
 
 struct nameidata {
@@ -25,11 +19,6 @@ struct nameidata {
        int             last_type;
        unsigned        depth;
        char *saved_names[MAX_NESTED_LINKS + 1];
-
-       /* Intent data */
-       union {
-               struct open_intent open;
-       } intent;
 };
 
 /*
@@ -78,13 +67,10 @@ extern int kern_path(const char *, unsigned, struct path *);
 
 extern struct dentry *kern_path_create(int, const char *, struct path *, int);
 extern struct dentry *user_path_create(int, const char __user *, struct path *, int);
-extern int kern_path_parent(const char *, struct nameidata *);
+extern struct dentry *kern_path_locked(const char *, struct path *);
 extern int vfs_path_lookup(struct dentry *, struct vfsmount *,
                           const char *, unsigned int, struct path *);
 
-extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry *dentry,
-               int (*open)(struct inode *, struct file *));
-
 extern struct dentry *lookup_one_len(const char *, struct dentry *, int);
 
 extern int follow_down_one(struct path *);
@@ -94,6 +80,8 @@ extern int follow_up(struct path *);
 extern struct dentry *lock_rename(struct dentry *, struct dentry *);
 extern void unlock_rename(struct dentry *, struct dentry *);
 
+extern void nd_jump_link(struct nameidata *nd, struct path *path);
+
 static inline void nd_set_link(struct nameidata *nd, char *path)
 {
        nd->saved_names[nd->depth] = path;
index 8aadd90b808a67b466ceb66cbc0de0b57883e96b..d3b7c18b18f4e068997789bda6cc25be52720f8a 100644 (file)
@@ -1374,7 +1374,7 @@ struct nfs_rpc_ops {
        int     (*readlink)(struct inode *, struct page *, unsigned int,
                            unsigned int);
        int     (*create)  (struct inode *, struct dentry *,
-                           struct iattr *, int, struct nfs_open_context *);
+                           struct iattr *, int);
        int     (*remove)  (struct inode *, struct qstr *);
        void    (*unlink_setup)  (struct rpc_message *, struct inode *dir);
        void    (*unlink_rpc_prepare) (struct rpc_task *, struct nfs_unlinkdata *);
index 2ec1083af7ffba234db74acdd0e42d25d861b8c1..b27c87191df23f4283fbcaa383c8b6641853c354 100644 (file)
@@ -260,8 +260,7 @@ extern int of_machine_is_compatible(const char *compat);
 extern int prom_add_property(struct device_node* np, struct property* prop);
 extern int prom_remove_property(struct device_node *np, struct property *prop);
 extern int prom_update_property(struct device_node *np,
-                               struct property *newprop,
-                               struct property *oldprop);
+                               struct property *newprop);
 
 #if defined(CONFIG_OF_DYNAMIC)
 /* For updating the device tree at runtime */
index ab741b0d007402daf8feee824e0aae91751bafe6..fc35260773489d55724f87d3493f5d5b23ab1f57 100644 (file)
 #define PCI_DEVICE_ID_AMD_11H_NB_DRAM  0x1302
 #define PCI_DEVICE_ID_AMD_11H_NB_MISC  0x1303
 #define PCI_DEVICE_ID_AMD_11H_NB_LINK  0x1304
+#define PCI_DEVICE_ID_AMD_15H_M10H_F3  0x1403
 #define PCI_DEVICE_ID_AMD_15H_NB_F0    0x1600
 #define PCI_DEVICE_ID_AMD_15H_NB_F1    0x1601
 #define PCI_DEVICE_ID_AMD_15H_NB_F2    0x1602
 #define PCI_DEVICE_ID_INTEL_IOAT_SNB7  0x3c27
 #define PCI_DEVICE_ID_INTEL_IOAT_SNB8  0x3c2e
 #define PCI_DEVICE_ID_INTEL_IOAT_SNB9  0x3c2f
+#define PCI_DEVICE_ID_INTEL_UNC_HA     0x3c46
+#define PCI_DEVICE_ID_INTEL_UNC_IMC0   0x3cb0
+#define PCI_DEVICE_ID_INTEL_UNC_IMC1   0x3cb1
+#define PCI_DEVICE_ID_INTEL_UNC_IMC2   0x3cb4
+#define PCI_DEVICE_ID_INTEL_UNC_IMC3   0x3cb5
+#define PCI_DEVICE_ID_INTEL_UNC_QPI0   0x3c41
+#define PCI_DEVICE_ID_INTEL_UNC_QPI1   0x3c42
+#define PCI_DEVICE_ID_INTEL_UNC_R2PCIE 0x3c43
+#define PCI_DEVICE_ID_INTEL_UNC_R3QPI0 0x3c44
+#define PCI_DEVICE_ID_INTEL_UNC_R3QPI1 0x3c45
+#define PCI_DEVICE_ID_INTEL_JAKETOWN_UBOX      0x3ce0
 #define PCI_DEVICE_ID_INTEL_IOAT_SNB   0x402f
 #define PCI_DEVICE_ID_INTEL_5100_16    0x65f0
 #define PCI_DEVICE_ID_INTEL_5100_21    0x65f5
index 45db49f64bb492ddf34d2b451fffa810ea45b965..76c5c8b724a77253e3ca635c90e53ed6230b3c5f 100644 (file)
@@ -677,6 +677,7 @@ struct hw_perf_event {
                        u64             last_tag;
                        unsigned long   config_base;
                        unsigned long   event_base;
+                       int             event_base_rdpmc;
                        int             idx;
                        int             last_cpu;
 
@@ -1106,6 +1107,8 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr,
                                struct task_struct *task,
                                perf_overflow_handler_t callback,
                                void *context);
+extern void perf_pmu_migrate_context(struct pmu *pmu,
+                               int src_cpu, int dst_cpu);
 extern u64 perf_event_read_value(struct perf_event *event,
                                 u64 *enabled, u64 *running);
 
diff --git a/include/linux/platform_data/clk-nomadik.h b/include/linux/platform_data/clk-nomadik.h
new file mode 100644 (file)
index 0000000..5713c87
--- /dev/null
@@ -0,0 +1,2 @@
+/* Minimal platform data header */
+void nomadik_clk_init(void);
diff --git a/include/linux/platform_data/omap_drm.h b/include/linux/platform_data/omap_drm.h
new file mode 100644 (file)
index 0000000..3da73bd
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * DRM/KMS platform data for TI OMAP platforms
+ *
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <rob.clark@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __PLATFORM_DATA_OMAP_DRM_H__
+#define __PLATFORM_DATA_OMAP_DRM_H__
+
+/*
+ * Optional platform data to configure the default configuration of which
+ * pipes/overlays/CRTCs are used.. if this is not provided, then instead the
+ * first CONFIG_DRM_OMAP_NUM_CRTCS are used, and they are each connected to
+ * one manager, with priority given to managers that are connected to
+ * detected devices.  Remaining overlays are used as video planes.  This
+ * should be a good default behavior for most cases, but yet there still
+ * might be times when you wish to do something different.
+ */
+struct omap_kms_platform_data {
+       /* overlays to use as CRTCs: */
+       int ovl_cnt;
+       const int *ovl_ids;
+
+       /* overlays to use as video planes: */
+       int pln_cnt;
+       const int *pln_ids;
+
+       int mgr_cnt;
+       const int *mgr_ids;
+
+       int dev_cnt;
+       const char **dev_names;
+};
+
+struct omap_drm_platform_data {
+       struct omap_kms_platform_data *kms_pdata;
+};
+
+#endif /* __PLATFORM_DATA_OMAP_DRM_H__ */
index 30f794eb382654f9017b868b4245986b4e621a31..a7d6172922d405c950c701bf4a7d2d21bb4e0c77 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/notifier.h>
+#include <linux/cpuidle.h>
 
 enum gpd_status {
        GPD_STATE_ACTIVE = 0,   /* PM domain is active */
@@ -45,6 +46,11 @@ struct gpd_dev_ops {
        bool (*active_wakeup)(struct device *dev);
 };
 
+struct gpd_cpu_data {
+       unsigned int saved_exit_latency;
+       struct cpuidle_state *idle_state;
+};
+
 struct generic_pm_domain {
        struct dev_pm_domain domain;    /* PM domain operations */
        struct list_head gpd_list_node; /* Node in the global PM domains list */
@@ -75,6 +81,7 @@ struct generic_pm_domain {
        bool max_off_time_changed;
        bool cached_power_down_ok;
        struct device_node *of_node; /* Node in device tree */
+       struct gpd_cpu_data *cpu_data;
 };
 
 static inline struct generic_pm_domain *pd_to_genpd(struct dev_pm_domain *pd)
@@ -105,6 +112,7 @@ struct generic_pm_domain_data {
        struct gpd_timing_data td;
        struct notifier_block nb;
        struct mutex lock;
+       unsigned int refcount;
        bool need_restore;
        bool always_on;
 };
@@ -155,6 +163,8 @@ extern int pm_genpd_add_callbacks(struct device *dev,
                                  struct gpd_dev_ops *ops,
                                  struct gpd_timing_data *td);
 extern int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td);
+extern int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int state);
+extern int genpd_detach_cpuidle(struct generic_pm_domain *genpd);
 extern void pm_genpd_init(struct generic_pm_domain *genpd,
                          struct dev_power_governor *gov, bool is_off);
 
@@ -211,6 +221,14 @@ static inline int __pm_genpd_remove_callbacks(struct device *dev, bool clear_td)
 {
        return -ENOSYS;
 }
+static inline int genpd_attach_cpuidle(struct generic_pm_domain *genpd, int st)
+{
+       return -ENOSYS;
+}
+static inline int genpd_detach_cpuidle(struct generic_pm_domain *genpd)
+{
+       return -ENOSYS;
+}
 static inline void pm_genpd_init(struct generic_pm_domain *genpd,
                                 struct dev_power_governor *gov, bool is_off)
 {
index 233149cb19f4ae8af9ad35b7f6d2d5ab5929e288..9924ea1f22e07306f39607e08df8b36244832ab9 100644 (file)
@@ -66,7 +66,7 @@ enum pm_qos_req_action {
 
 static inline int dev_pm_qos_request_active(struct dev_pm_qos_request *req)
 {
-       return req->dev != 0;
+       return req->dev != NULL;
 }
 
 int pm_qos_update_target(struct pm_qos_constraints *c, struct plist_node *node,
diff --git a/include/linux/power/smartreflex.h b/include/linux/power/smartreflex.h
new file mode 100644 (file)
index 0000000..3101e62
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+ * OMAP Smartreflex Defines and Routines
+ *
+ * Author: Thara Gopinath      <thara@ti.com>
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <x0080970@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __POWER_SMARTREFLEX_H
+#define __POWER_SMARTREFLEX_H
+
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <plat/voltage.h>
+
+/*
+ * Different Smartreflex IPs version. The v1 is the 65nm version used in
+ * OMAP3430. The v2 is the update for the 45nm version of the IP
+ * used in OMAP3630 and OMAP4430
+ */
+#define SR_TYPE_V1     1
+#define SR_TYPE_V2     2
+
+/* SMART REFLEX REG ADDRESS OFFSET */
+#define SRCONFIG               0x00
+#define SRSTATUS               0x04
+#define SENVAL                 0x08
+#define SENMIN                 0x0C
+#define SENMAX                 0x10
+#define SENAVG                 0x14
+#define AVGWEIGHT              0x18
+#define NVALUERECIPROCAL       0x1c
+#define SENERROR_V1            0x20
+#define ERRCONFIG_V1           0x24
+#define IRQ_EOI                        0x20
+#define IRQSTATUS_RAW          0x24
+#define IRQSTATUS              0x28
+#define IRQENABLE_SET          0x2C
+#define IRQENABLE_CLR          0x30
+#define SENERROR_V2            0x34
+#define ERRCONFIG_V2           0x38
+
+/* Bit/Shift Positions */
+
+/* SRCONFIG */
+#define SRCONFIG_ACCUMDATA_SHIFT       22
+#define SRCONFIG_SRCLKLENGTH_SHIFT     12
+#define SRCONFIG_SENNENABLE_V1_SHIFT   5
+#define SRCONFIG_SENPENABLE_V1_SHIFT   3
+#define SRCONFIG_SENNENABLE_V2_SHIFT   1
+#define SRCONFIG_SENPENABLE_V2_SHIFT   0
+#define SRCONFIG_CLKCTRL_SHIFT         0
+
+#define SRCONFIG_ACCUMDATA_MASK                (0x3ff << 22)
+
+#define SRCONFIG_SRENABLE              BIT(11)
+#define SRCONFIG_SENENABLE             BIT(10)
+#define SRCONFIG_ERRGEN_EN             BIT(9)
+#define SRCONFIG_MINMAXAVG_EN          BIT(8)
+#define SRCONFIG_DELAYCTRL             BIT(2)
+
+/* AVGWEIGHT */
+#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT  2
+#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT  0
+
+/* NVALUERECIPROCAL */
+#define NVALUERECIPROCAL_SENPGAIN_SHIFT        20
+#define NVALUERECIPROCAL_SENNGAIN_SHIFT        16
+#define NVALUERECIPROCAL_RNSENP_SHIFT  8
+#define NVALUERECIPROCAL_RNSENN_SHIFT  0
+
+/* ERRCONFIG */
+#define ERRCONFIG_ERRWEIGHT_SHIFT      16
+#define ERRCONFIG_ERRMAXLIMIT_SHIFT    8
+#define ERRCONFIG_ERRMINLIMIT_SHIFT    0
+
+#define SR_ERRWEIGHT_MASK              (0x07 << 16)
+#define SR_ERRMAXLIMIT_MASK            (0xff << 8)
+#define SR_ERRMINLIMIT_MASK            (0xff << 0)
+
+#define ERRCONFIG_VPBOUNDINTEN_V1      BIT(31)
+#define ERRCONFIG_VPBOUNDINTST_V1      BIT(30)
+#define        ERRCONFIG_MCUACCUMINTEN         BIT(29)
+#define ERRCONFIG_MCUACCUMINTST                BIT(28)
+#define        ERRCONFIG_MCUVALIDINTEN         BIT(27)
+#define ERRCONFIG_MCUVALIDINTST                BIT(26)
+#define ERRCONFIG_MCUBOUNDINTEN                BIT(25)
+#define        ERRCONFIG_MCUBOUNDINTST         BIT(24)
+#define        ERRCONFIG_MCUDISACKINTEN        BIT(23)
+#define ERRCONFIG_VPBOUNDINTST_V2      BIT(23)
+#define ERRCONFIG_MCUDISACKINTST       BIT(22)
+#define ERRCONFIG_VPBOUNDINTEN_V2      BIT(22)
+
+#define ERRCONFIG_STATUS_V1_MASK       (ERRCONFIG_VPBOUNDINTST_V1 | \
+                                       ERRCONFIG_MCUACCUMINTST | \
+                                       ERRCONFIG_MCUVALIDINTST | \
+                                       ERRCONFIG_MCUBOUNDINTST | \
+                                       ERRCONFIG_MCUDISACKINTST)
+/* IRQSTATUS */
+#define IRQSTATUS_MCUACCUMINT          BIT(3)
+#define IRQSTATUS_MCVALIDINT           BIT(2)
+#define IRQSTATUS_MCBOUNDSINT          BIT(1)
+#define IRQSTATUS_MCUDISABLEACKINT     BIT(0)
+
+/* IRQENABLE_SET and IRQENABLE_CLEAR */
+#define IRQENABLE_MCUACCUMINT          BIT(3)
+#define IRQENABLE_MCUVALIDINT          BIT(2)
+#define IRQENABLE_MCUBOUNDSINT         BIT(1)
+#define IRQENABLE_MCUDISABLEACKINT     BIT(0)
+
+/* Common Bit values */
+
+#define SRCLKLENGTH_12MHZ_SYSCLK       0x3c
+#define SRCLKLENGTH_13MHZ_SYSCLK       0x41
+#define SRCLKLENGTH_19MHZ_SYSCLK       0x60
+#define SRCLKLENGTH_26MHZ_SYSCLK       0x82
+#define SRCLKLENGTH_38MHZ_SYSCLK       0xC0
+
+/*
+ * 3430 specific values. Maybe these should be passed from board file or
+ * pmic structures.
+ */
+#define OMAP3430_SR_ACCUMDATA          0x1f4
+
+#define OMAP3430_SR1_SENPAVGWEIGHT     0x03
+#define OMAP3430_SR1_SENNAVGWEIGHT     0x03
+
+#define OMAP3430_SR2_SENPAVGWEIGHT     0x01
+#define OMAP3430_SR2_SENNAVGWEIGHT     0x01
+
+#define OMAP3430_SR_ERRWEIGHT          0x04
+#define OMAP3430_SR_ERRMAXLIMIT                0x02
+
+struct omap_sr {
+       char                            *name;
+       struct list_head                node;
+       struct platform_device          *pdev;
+       struct omap_sr_nvalue_table     *nvalue_table;
+       struct voltagedomain            *voltdm;
+       struct dentry                   *dbg_dir;
+       unsigned int                    irq;
+       int                             srid;
+       int                             ip_type;
+       int                             nvalue_count;
+       bool                            autocomp_active;
+       u32                             clk_length;
+       u32                             err_weight;
+       u32                             err_minlimit;
+       u32                             err_maxlimit;
+       u32                             accum_data;
+       u32                             senn_avgweight;
+       u32                             senp_avgweight;
+       u32                             senp_mod;
+       u32                             senn_mod;
+       void __iomem                    *base;
+};
+
+/**
+ * test_cond_timeout - busy-loop, testing a condition
+ * @cond: condition to test until it evaluates to true
+ * @timeout: maximum number of microseconds in the timeout
+ * @index: loop index (integer)
+ *
+ * Loop waiting for @cond to become true or until at least @timeout
+ * microseconds have passed.  To use, define some integer @index in the
+ * calling code.  After running, if @index == @timeout, then the loop has
+ * timed out.
+ *
+ * Copied from omap_test_timeout */
+#define sr_test_cond_timeout(cond, timeout, index)             \
+({                                                             \
+       for (index = 0; index < timeout; index++) {             \
+               if (cond)                                       \
+                       break;                                  \
+               udelay(1);                                      \
+       }                                                       \
+})
+
+/**
+ * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
+ *                             pmic specific info to smartreflex driver
+ *
+ * @sr_pmic_init:      API to initialize smartreflex on the PMIC side.
+ */
+struct omap_sr_pmic_data {
+       void (*sr_pmic_init) (void);
+};
+
+/**
+ * struct omap_smartreflex_dev_attr - Smartreflex Device attribute.
+ *
+ * @sensor_voltdm_name:       Name of voltdomain of SR instance
+ */
+struct omap_smartreflex_dev_attr {
+       const char      *sensor_voltdm_name;
+};
+
+#ifdef CONFIG_POWER_AVS_OMAP
+/*
+ * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
+ * The smartreflex class driver should pass the class type.
+ * Should be used to populate the class_type field of the
+ * omap_smartreflex_class_data structure.
+ */
+#define SR_CLASS1      0x1
+#define SR_CLASS2      0x2
+#define SR_CLASS3      0x3
+
+/**
+ * struct omap_sr_class_data - Smartreflex class driver info
+ *
+ * @enable:            API to enable a particular class smaartreflex.
+ * @disable:           API to disable a particular class smartreflex.
+ * @configure:         API to configure a particular class smartreflex.
+ * @notify:            API to notify the class driver about an event in SR.
+ *                     Not needed for class3.
+ * @notify_flags:      specify the events to be notified to the class driver
+ * @class_type:                specify which smartreflex class.
+ *                     Can be used by the SR driver to take any class
+ *                     based decisions.
+ */
+struct omap_sr_class_data {
+       int (*enable)(struct omap_sr *sr);
+       int (*disable)(struct omap_sr *sr, int is_volt_reset);
+       int (*configure)(struct omap_sr *sr);
+       int (*notify)(struct omap_sr *sr, u32 status);
+       u8 notify_flags;
+       u8 class_type;
+};
+
+/**
+ * struct omap_sr_nvalue_table - Smartreflex n-target value info
+ *
+ * @efuse_offs:          The offset of the efuse where n-target values are stored.
+ * @nvalue:      The n-target value.
+ * @errminlimit:  The value of the ERRMINLIMIT bitfield for this n-target
+ * @volt_nominal: microvolts DC that the VDD is initially programmed to
+ */
+struct omap_sr_nvalue_table {
+       u32 efuse_offs;
+       u32 nvalue;
+       u32 errminlimit;
+       unsigned long volt_nominal;
+};
+
+/**
+ * struct omap_sr_data - Smartreflex platform data.
+ *
+ * @name:              instance name
+ * @ip_type:           Smartreflex IP type.
+ * @senp_mod:          SENPENABLE value for the sr
+ * @senn_mod:          SENNENABLE value for sr
+ * @nvalue_count:      Number of distinct nvalues in the nvalue table
+ * @enable_on_init:    whether this sr module needs to enabled at
+ *                     boot up or not.
+ * @nvalue_table:      table containing the  efuse offsets and nvalues
+ *                     corresponding to them.
+ * @voltdm:            Pointer to the voltage domain associated with the SR
+ */
+struct omap_sr_data {
+       const char                      *name;
+       int                             ip_type;
+       u32                             senp_mod;
+       u32                             senn_mod;
+       int                             nvalue_count;
+       bool                            enable_on_init;
+       struct omap_sr_nvalue_table     *nvalue_table;
+       struct voltagedomain            *voltdm;
+};
+
+/* Smartreflex module enable/disable interface */
+void omap_sr_enable(struct voltagedomain *voltdm);
+void omap_sr_disable(struct voltagedomain *voltdm);
+void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
+
+/* API to register the pmic specific data with the smartreflex driver. */
+void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
+
+/* Smartreflex driver hooks to be called from Smartreflex class driver */
+int sr_enable(struct voltagedomain *voltdm, unsigned long volt);
+void sr_disable(struct voltagedomain *voltdm);
+int sr_configure_errgen(struct voltagedomain *voltdm);
+int sr_disable_errgen(struct voltagedomain *voltdm);
+int sr_configure_minmax(struct voltagedomain *voltdm);
+
+/* API to register the smartreflex class driver with the smartreflex driver */
+int sr_register_class(struct omap_sr_class_data *class_data);
+#else
+static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
+static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
+static inline void omap_sr_disable_reset_volt(
+               struct voltagedomain *voltdm) {}
+static inline void omap_sr_register_pmic(
+               struct omap_sr_pmic_data *pmic_data) {}
+#endif
+#endif
index c09fa042b5ea077bb748507fd41e464891bbb7b3..524ede8a160a2d85e426f277131fc803558ec748 100644 (file)
@@ -333,7 +333,7 @@ struct quotactl_ops {
        int (*quota_on)(struct super_block *, int, int, struct path *);
        int (*quota_on_meta)(struct super_block *, int, int);
        int (*quota_off)(struct super_block *, int);
-       int (*quota_sync)(struct super_block *, int, int);
+       int (*quota_sync)(struct super_block *, int);
        int (*get_info)(struct super_block *, int, struct if_dqinfo *);
        int (*set_info)(struct super_block *, int, struct if_dqinfo *);
        int (*get_dqblk)(struct super_block *, int, qid_t, struct fs_disk_quota *);
index 17b977304a09f8208dad924dc475676bd4a6f5f9..ec6b65feaabac1fef7222dd1ad1bc2d286136983 100644 (file)
@@ -83,7 +83,8 @@ int dquot_quota_on(struct super_block *sb, int type, int format_id,
 int dquot_quota_on_mount(struct super_block *sb, char *qf_name,
        int format_id, int type);
 int dquot_quota_off(struct super_block *sb, int type);
-int dquot_quota_sync(struct super_block *sb, int type, int wait);
+int dquot_writeback_dquots(struct super_block *sb, int type);
+int dquot_quota_sync(struct super_block *sb, int type);
 int dquot_get_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
 int dquot_set_dqinfo(struct super_block *sb, int type, struct if_dqinfo *ii);
 int dquot_get_dqblk(struct super_block *sb, int type, qid_t id,
@@ -255,6 +256,11 @@ static inline int dquot_resume(struct super_block *sb, int type)
 
 #define dquot_file_open                generic_file_open
 
+static inline int dquot_writeback_dquots(struct super_block *sb, int type)
+{
+       return 0;
+}
+
 #endif /* CONFIG_QUOTA */
 
 static inline int dquot_alloc_space_nodirty(struct inode *inode, qsize_t nr)
index 9cac722b169c9a1f5dbcae489d7b4c43a4fbe1a2..115ead2b51553d78a523c4e62db3cb4b84866cd0 100644 (file)
@@ -147,6 +147,7 @@ extern void synchronize_sched(void);
 
 extern void __rcu_read_lock(void);
 extern void __rcu_read_unlock(void);
+extern void rcu_read_unlock_special(struct task_struct *t);
 void synchronize_rcu(void);
 
 /*
@@ -255,6 +256,10 @@ static inline void destroy_rcu_head_on_stack(struct rcu_head *head)
 }
 #endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */
 
+#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SMP)
+extern int rcu_is_cpu_idle(void);
+#endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SMP) */
+
 #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU)
 bool rcu_lockdep_current_cpu_online(void);
 #else /* #if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PROVE_RCU) */
@@ -266,15 +271,6 @@ static inline bool rcu_lockdep_current_cpu_online(void)
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 
-#ifdef CONFIG_PROVE_RCU
-extern int rcu_is_cpu_idle(void);
-#else /* !CONFIG_PROVE_RCU */
-static inline int rcu_is_cpu_idle(void)
-{
-       return 0;
-}
-#endif /* else !CONFIG_PROVE_RCU */
-
 static inline void rcu_lock_acquire(struct lockdep_map *map)
 {
        lock_acquire(map, 0, 0, 2, 1, NULL, _THIS_IP_);
@@ -431,8 +427,7 @@ extern int rcu_my_thread_group_empty(void);
 static inline void rcu_preempt_sleep_check(void)
 {
        rcu_lockdep_assert(!lock_is_held(&rcu_lock_map),
-                          "Illegal context switch in RCU read-side "
-                          "critical section");
+                          "Illegal context switch in RCU read-side critical section");
 }
 #else /* #ifdef CONFIG_PROVE_RCU */
 static inline void rcu_preempt_sleep_check(void)
@@ -513,10 +508,10 @@ static inline void rcu_preempt_sleep_check(void)
                (_________p1); \
        })
 #define __rcu_assign_pointer(p, v, space) \
-       ({ \
+       do { \
                smp_wmb(); \
                (p) = (typeof(*v) __force space *)(v); \
-       })
+       } while (0)
 
 
 /**
@@ -851,7 +846,7 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
  *
  * Assigns the specified value to the specified RCU-protected
  * pointer, ensuring that any concurrent RCU readers will see
- * any prior initialization.  Returns the value assigned.
+ * any prior initialization.
  *
  * Inserts memory barriers on architectures that require them
  * (which is most of them), and also prevents the compiler from
@@ -903,25 +898,17 @@ static inline notrace void rcu_read_unlock_sched_notrace(void)
  * the reader-accessible portions of the linked structure.
  */
 #define RCU_INIT_POINTER(p, v) \
-               p = (typeof(*v) __force __rcu *)(v)
-
-static __always_inline bool __is_kfree_rcu_offset(unsigned long offset)
-{
-       return offset < 4096;
-}
-
-static __always_inline
-void __kfree_rcu(struct rcu_head *head, unsigned long offset)
-{
-       typedef void (*rcu_callback)(struct rcu_head *);
-
-       BUILD_BUG_ON(!__builtin_constant_p(offset));
-
-       /* See the kfree_rcu() header comment. */
-       BUILD_BUG_ON(!__is_kfree_rcu_offset(offset));
+       do { \
+               p = (typeof(*v) __force __rcu *)(v); \
+       } while (0)
 
-       kfree_call_rcu(head, (rcu_callback)offset);
-}
+/**
+ * RCU_POINTER_INITIALIZER() - statically initialize an RCU protected pointer
+ *
+ * GCC-style initialization for an RCU-protected pointer in a structure field.
+ */
+#define RCU_POINTER_INITIALIZER(p, v) \
+               .p = (typeof(*v) __force __rcu *)(v)
 
 /*
  * Does the specified offset indicate that the corresponding rcu_head
@@ -935,7 +922,7 @@ void __kfree_rcu(struct rcu_head *head, unsigned long offset)
 #define __kfree_rcu(head, offset) \
        do { \
                BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); \
-               call_rcu(head, (void (*)(struct rcu_head *))(unsigned long)(offset)); \
+               kfree_call_rcu(head, (void (*)(struct rcu_head *))(unsigned long)(offset)); \
        } while (0)
 
 /**
index 56af22ec9aba3e85aa32e035897b90b1b12cc67d..7f7e00df3adf9991ce844a280c4c5c03a9d7bcb6 100644 (file)
  */
 
 #include <linux/list.h>
+#include <linux/rbtree.h>
 
 struct module;
 struct device;
 struct i2c_client;
 struct spi_device;
 struct regmap;
+struct regmap_range_cfg;
 
 /* An enum of all the supported cache types */
 enum regcache_type {
@@ -43,6 +45,14 @@ struct reg_default {
 
 #ifdef CONFIG_REGMAP
 
+enum regmap_endian {
+       /* Unspecified -> 0 -> Backwards compatible default */
+       REGMAP_ENDIAN_DEFAULT = 0,
+       REGMAP_ENDIAN_BIG,
+       REGMAP_ENDIAN_LITTLE,
+       REGMAP_ENDIAN_NATIVE,
+};
+
 /**
  * Configuration for the register map of a device.
  *
@@ -84,6 +94,15 @@ struct reg_default {
  * @reg_defaults_raw: Power on reset values for registers (for use with
  *                    register cache support).
  * @num_reg_defaults_raw: Number of elements in reg_defaults_raw.
+ * @reg_format_endian: Endianness for formatted register addresses. If this is
+ *                     DEFAULT, the @reg_format_endian_default value from the
+ *                     regmap bus is used.
+ * @val_format_endian: Endianness for formatted register values. If this is
+ *                     DEFAULT, the @reg_format_endian_default value from the
+ *                     regmap bus is used.
+ *
+ * @ranges: Array of configuration entries for virtual address ranges.
+ * @num_ranges: Number of range configuration entries.
  */
 struct regmap_config {
        const char *name;
@@ -109,6 +128,43 @@ struct regmap_config {
        u8 write_flag_mask;
 
        bool use_single_rw;
+
+       enum regmap_endian reg_format_endian;
+       enum regmap_endian val_format_endian;
+
+       const struct regmap_range_cfg *ranges;
+       unsigned int n_ranges;
+};
+
+/**
+ * Configuration for indirectly accessed or paged registers.
+ * Registers, mapped to this virtual range, are accessed in two steps:
+ *     1. page selector register update;
+ *     2. access through data window registers.
+ *
+ * @range_min: Address of the lowest register address in virtual range.
+ * @range_max: Address of the highest register in virtual range.
+ *
+ * @page_sel_reg: Register with selector field.
+ * @page_sel_mask: Bit shift for selector value.
+ * @page_sel_shift: Bit mask for selector value.
+ *
+ * @window_start: Address of first (lowest) register in data window.
+ * @window_len: Number of registers in data window.
+ */
+struct regmap_range_cfg {
+       /* Registers of virtual address range */
+       unsigned int range_min;
+       unsigned int range_max;
+
+       /* Page selector for indirect addressing */
+       unsigned int selector_reg;
+       unsigned int selector_mask;
+       int selector_shift;
+
+       /* Data window (per each page) */
+       unsigned int window_start;
+       unsigned int window_len;
 };
 
 typedef int (*regmap_hw_write)(void *context, const void *data,
@@ -133,6 +189,12 @@ typedef void (*regmap_hw_free_context)(void *context);
  *         data.
  * @read_flag_mask: Mask to be set in the top byte of the register when doing
  *                  a read.
+ * @reg_format_endian_default: Default endianness for formatted register
+ *     addresses. Used when the regmap_config specifies DEFAULT. If this is
+ *     DEFAULT, BIG is assumed.
+ * @val_format_endian_default: Default endianness for formatted register
+ *     values. Used when the regmap_config specifies DEFAULT. If this is
+ *     DEFAULT, BIG is assumed.
  */
 struct regmap_bus {
        bool fast_io;
@@ -141,6 +203,8 @@ struct regmap_bus {
        regmap_hw_read read;
        regmap_hw_free_context free_context;
        u8 read_flag_mask;
+       enum regmap_endian reg_format_endian_default;
+       enum regmap_endian val_format_endian_default;
 };
 
 struct regmap *regmap_init(struct device *dev,
@@ -219,6 +283,7 @@ struct regmap_irq {
  * @status_base: Base status register address.
  * @mask_base:   Base mask register address.
  * @ack_base:    Base ack address.  If zero then the chip is clear on read.
+ * @wake_base:   Base address for wake enables.  If zero unsupported.
  * @irq_reg_stride:  Stride to use for chips where registers are not contiguous.
  *
  * @num_regs:    Number of registers in each control bank.
@@ -232,6 +297,7 @@ struct regmap_irq_chip {
        unsigned int status_base;
        unsigned int mask_base;
        unsigned int ack_base;
+       unsigned int wake_base;
        unsigned int irq_reg_stride;
 
        int num_regs;
@@ -243,7 +309,7 @@ struct regmap_irq_chip {
 struct regmap_irq_chip_data;
 
 int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
-                       int irq_base, struct regmap_irq_chip *chip,
+                       int irq_base, const struct regmap_irq_chip *chip,
                        struct regmap_irq_chip_data **data);
 void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *data);
 int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data);
@@ -361,7 +427,6 @@ static inline int regmap_register_patch(struct regmap *map,
 static inline struct regmap *dev_get_regmap(struct device *dev,
                                            const char *name)
 {
-       WARN_ONCE(1, "regmap API is disabled");
        return NULL;
 }
 
index 4ed1b30ac5fc9ff04cf2a50b1b4ba91e1718e2b7..da339fd8c7559de74ad46dd3536f4b95981c89d8 100644 (file)
@@ -290,6 +290,12 @@ static inline int regulator_set_voltage(struct regulator *regulator,
 }
 
 static inline int regulator_get_voltage(struct regulator *regulator)
+{
+       return -EINVAL;
+}
+
+static inline int regulator_is_supported_voltage(struct regulator *regulator,
+                                  int min_uV, int max_uV)
 {
        return 0;
 }
index b0432cc2b16958809bdd66a8ce6d0c65d7b4a881..bac4c871f3bd1930b481c214e932cec9666e05b6 100644 (file)
@@ -32,6 +32,8 @@ enum regulator_status {
        REGULATOR_STATUS_NORMAL,
        REGULATOR_STATUS_IDLE,
        REGULATOR_STATUS_STANDBY,
+       /* in case that any other status doesn't apply */
+       REGULATOR_STATUS_UNDEFINED,
 };
 
 /**
@@ -67,6 +69,8 @@ enum regulator_status {
  *
  * @enable_time: Time taken for the regulator voltage output voltage to
  *               stabilise after being enabled, in microseconds.
+ * @set_ramp_delay: Set the ramp delay for the regulator. The driver should
+ *             select ramp delay equal to or less than(closest) ramp_delay.
  * @set_voltage_time_sel: Time taken for the regulator voltage output voltage
  *               to stabilise after being set to a new value, in microseconds.
  *               The function provides the from and to voltage selector, the
@@ -113,6 +117,7 @@ struct regulator_ops {
 
        /* Time taken to enable or set voltage on the regulator */
        int (*enable_time) (struct regulator_dev *);
+       int (*set_ramp_delay) (struct regulator_dev *, int ramp_delay);
        int (*set_voltage_time_sel) (struct regulator_dev *,
                                     unsigned int old_selector,
                                     unsigned int new_selector);
@@ -170,11 +175,15 @@ enum regulator_type {
  *
  * @min_uV: Voltage given by the lowest selector (if linear mapping)
  * @uV_step: Voltage increase with each selector (if linear mapping)
+ * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
+ * @volt_table: Voltage mapping table (if table based mapping)
  *
  * @vsel_reg: Register for selector when using regulator_regmap_X_voltage_
  * @vsel_mask: Mask for register bitfield used for selector
  * @enable_reg: Register for control when using regmap enable/disable ops
  * @enable_mask: Mask for control when using regmap enable/disable ops
+ *
+ * @enable_time: Time taken for initial enable of regulator (in uS).
  */
 struct regulator_desc {
        const char *name;
@@ -188,11 +197,16 @@ struct regulator_desc {
 
        unsigned int min_uV;
        unsigned int uV_step;
+       unsigned int ramp_delay;
+
+       const unsigned int *volt_table;
 
        unsigned int vsel_reg;
        unsigned int vsel_mask;
        unsigned int enable_reg;
        unsigned int enable_mask;
+
+       unsigned int enable_time;
 };
 
 /**
@@ -208,6 +222,9 @@ struct regulator_desc {
  * @of_node: OpenFirmware node to parse for device tree bindings (may be
  *           NULL).
  * @regmap: regmap to use for core regmap helpers
+ * @ena_gpio: GPIO controlling regulator enable.
+ * @ena_gpio_invert: Sense for GPIO enable control.
+ * @ena_gpio_flags: Flags to use when calling gpio_request_one()
  */
 struct regulator_config {
        struct device *dev;
@@ -215,6 +232,10 @@ struct regulator_config {
        void *driver_data;
        struct device_node *of_node;
        struct regmap *regmap;
+
+       int ena_gpio;
+       unsigned int ena_gpio_invert:1;
+       unsigned int ena_gpio_flags;
 };
 
 /*
@@ -253,6 +274,10 @@ struct regulator_dev {
        void *reg_data;         /* regulator_dev data */
 
        struct dentry *debugfs;
+
+       int ena_gpio;
+       unsigned int ena_gpio_invert:1;
+       unsigned int ena_gpio_state:1;
 };
 
 struct regulator_dev *
@@ -271,6 +296,8 @@ int regulator_mode_to_status(unsigned int);
 
 int regulator_list_voltage_linear(struct regulator_dev *rdev,
                                  unsigned int selector);
+int regulator_list_voltage_table(struct regulator_dev *rdev,
+                                 unsigned int selector);
 int regulator_map_voltage_linear(struct regulator_dev *rdev,
                                  int min_uV, int max_uV);
 int regulator_map_voltage_iterate(struct regulator_dev *rdev,
@@ -280,6 +307,9 @@ int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel);
 int regulator_is_enabled_regmap(struct regulator_dev *rdev);
 int regulator_enable_regmap(struct regulator_dev *rdev);
 int regulator_disable_regmap(struct regulator_dev *rdev);
+int regulator_set_voltage_time_sel(struct regulator_dev *rdev,
+                                  unsigned int old_selector,
+                                  unsigned int new_selector);
 
 void *regulator_get_init_drvdata(struct regulator_init_data *reg_init_data);
 
index f83f7440b4885656f171f904e8a1a150141cef36..48918be649d499b55bfaf762b23d9d7ae0df201e 100644 (file)
@@ -22,6 +22,7 @@ struct regulator_init_data;
 /**
  * struct fixed_voltage_config - fixed_voltage_config structure
  * @supply_name:       Name of the regulator supply
+ * @input_supply:      Name of the input regulator supply
  * @microvolts:                Output voltage of regulator
  * @gpio:              GPIO to use for enable control
  *                     set to -EINVAL if not used
@@ -46,6 +47,7 @@ struct regulator_init_data;
  */
 struct fixed_voltage_config {
        const char *supply_name;
+       const char *input_supply;
        int microvolts;
        int gpio;
        unsigned startup_delay;
@@ -58,14 +60,17 @@ struct fixed_voltage_config {
 struct regulator_consumer_supply;
 
 #if IS_ENABLED(CONFIG_REGULATOR)
-struct platform_device *regulator_register_fixed(int id,
-               struct regulator_consumer_supply *supplies, int num_supplies);
+struct platform_device *regulator_register_always_on(int id, const char *name,
+               struct regulator_consumer_supply *supplies, int num_supplies, int uv);
 #else
-static inline struct platform_device *regulator_register_fixed(int id,
-               struct regulator_consumer_supply *supplies, int num_supplies)
+static inline struct platform_device *regulator_register_always_on(int id, const char *name,
+               struct regulator_consumer_supply *supplies, int num_supplies, int uv)
 {
        return NULL;
 }
 #endif
 
+#define regulator_register_fixed(id, s, ns) regulator_register_always_on(id, \
+                                               "fixed-dummy", s, ns, 0)
+
 #endif
diff --git a/include/linux/regulator/lp872x.h b/include/linux/regulator/lp872x.h
new file mode 100644 (file)
index 0000000..132e05c
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2012 Texas Instruments
+ *
+ * Author: Milo(Woogyom) Kim <milo.kim@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef __LP872X_REGULATOR_H__
+#define __LP872X_REGULATOR_H__
+
+#include <linux/regulator/machine.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#define LP872X_MAX_REGULATORS          9
+
+enum lp872x_regulator_id {
+       LP8720_ID_BASE,
+       LP8720_ID_LDO1 = LP8720_ID_BASE,
+       LP8720_ID_LDO2,
+       LP8720_ID_LDO3,
+       LP8720_ID_LDO4,
+       LP8720_ID_LDO5,
+       LP8720_ID_BUCK,
+
+       LP8725_ID_BASE,
+       LP8725_ID_LDO1 = LP8725_ID_BASE,
+       LP8725_ID_LDO2,
+       LP8725_ID_LDO3,
+       LP8725_ID_LDO4,
+       LP8725_ID_LDO5,
+       LP8725_ID_LILO1,
+       LP8725_ID_LILO2,
+       LP8725_ID_BUCK1,
+       LP8725_ID_BUCK2,
+
+       LP872X_ID_MAX,
+};
+
+enum lp872x_dvs_state {
+       DVS_LOW  = GPIOF_OUT_INIT_LOW,
+       DVS_HIGH = GPIOF_OUT_INIT_HIGH,
+};
+
+enum lp872x_dvs_sel {
+       SEL_V1,
+       SEL_V2,
+};
+
+/**
+ * lp872x_dvs
+ * @gpio       : gpio pin number for dvs control
+ * @vsel       : dvs selector for buck v1 or buck v2 register
+ * @init_state : initial dvs pin state
+ */
+struct lp872x_dvs {
+       int gpio;
+       enum lp872x_dvs_sel vsel;
+       enum lp872x_dvs_state init_state;
+};
+
+/**
+ * lp872x_regdata
+ * @id        : regulator id
+ * @init_data : init data for each regulator
+ */
+struct lp872x_regulator_data {
+       enum lp872x_regulator_id id;
+       struct regulator_init_data *init_data;
+};
+
+/**
+ * lp872x_platform_data
+ * @general_config    : the value of LP872X_GENERAL_CFG register
+ * @update_config     : if LP872X_GENERAL_CFG register is updated, set true
+ * @regulator_data    : platform regulator id and init data
+ * @dvs               : dvs data for buck voltage control
+ */
+struct lp872x_platform_data {
+       u8 general_config;
+       bool update_config;
+       struct lp872x_regulator_data regulator_data[LP872X_MAX_REGULATORS];
+       struct lp872x_dvs *dvs;
+};
+
+#endif
index b02108446be756cc1c216271e21ac3cbf7a132d8..40dd0a394cfa95c1f470e0c2bbc6ee334005bef9 100644 (file)
@@ -92,6 +92,7 @@ struct regulator_state {
  *                 mode.
  * @initial_state: Suspend state to set by default.
  * @initial_mode: Mode to set at startup.
+ * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
  */
 struct regulation_constraints {
 
@@ -125,6 +126,8 @@ struct regulation_constraints {
        /* mode to set on startup */
        unsigned int initial_mode;
 
+       unsigned int ramp_delay;
+
        /* constraint flags */
        unsigned always_on:1;   /* regulator never off when system is on */
        unsigned boot_on:1;     /* bootloader/firmware enabled regulator */
index 4a1f493e0feff18485fc7ccff11da4e7eb12dde7..1a2ebd39b8006b9021faf9b51ca18a0504dee85b 100644 (file)
@@ -1405,7 +1405,7 @@ struct task_struct {
        int (*notifier)(void *priv);
        void *notifier_data;
        sigset_t *notifier_mask;
-       struct hlist_head task_works;
+       struct callback_head *task_works;
 
        struct audit_context *audit_context;
 #ifdef CONFIG_AUDITSYSCALL
@@ -1546,7 +1546,6 @@ struct task_struct {
        unsigned long timer_slack_ns;
        unsigned long default_timer_slack_ns;
 
-       struct list_head        *scm_work_list;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
        /* Index of current stored address in ret_stack */
        int curr_ret_stack;
@@ -1581,7 +1580,6 @@ struct task_struct {
 #endif
 #ifdef CONFIG_UPROBES
        struct uprobe_task *utask;
-       int uprobe_srcu_id;
 #endif
 };
 
index c513b73cd7cb8499a7ac61edb3789e7e24a8bfab..50910913b2687928bf59b4053b92beb21e569918 100644 (file)
@@ -18,7 +18,6 @@ struct clk_mapping {
        struct kref             ref;
 };
 
-
 struct sh_clk_ops {
 #ifdef CONFIG_SH_CLK_CPG_LEGACY
        void (*init)(struct clk *clk);
@@ -31,6 +30,10 @@ struct sh_clk_ops {
        long (*round_rate)(struct clk *clk, unsigned long rate);
 };
 
+#define SH_CLK_DIV_MSK(div)    ((1 << (div)) - 1)
+#define SH_CLK_DIV4_MSK                SH_CLK_DIV_MSK(4)
+#define SH_CLK_DIV6_MSK                SH_CLK_DIV_MSK(6)
+
 struct clk {
        struct list_head        node;
        struct clk              *parent;
@@ -52,6 +55,7 @@ struct clk {
        unsigned int            enable_bit;
        void __iomem            *mapped_reg;
 
+       unsigned int            div_mask;
        unsigned long           arch_flags;
        void                    *priv;
        struct clk_mapping      *mapping;
@@ -65,6 +69,8 @@ struct clk {
 #define CLK_ENABLE_REG_16BIT   BIT(2)
 #define CLK_ENABLE_REG_8BIT    BIT(3)
 
+#define CLK_MASK_DIV_ON_DISABLE        BIT(4)
+
 #define CLK_ENABLE_REG_MASK    (CLK_ENABLE_REG_32BIT | \
                                 CLK_ENABLE_REG_16BIT | \
                                 CLK_ENABLE_REG_8BIT)
@@ -146,14 +152,17 @@ static inline int __deprecated sh_clk_mstp32_register(struct clk *clks, int nr)
        .enable_reg = (void __iomem *)_reg,                     \
        .enable_bit = _shift,                                   \
        .arch_flags = _div_bitmap,                              \
+       .div_mask = SH_CLK_DIV4_MSK,                            \
        .flags = _flags,                                        \
 }
 
-struct clk_div4_table {
+struct clk_div_table {
        struct clk_div_mult_table *div_mult_table;
        void (*kick)(struct clk *clk);
 };
 
+#define clk_div4_table clk_div_table
+
 int sh_clk_div4_register(struct clk *clks, int nr,
                         struct clk_div4_table *table);
 int sh_clk_div4_enable_register(struct clk *clks, int nr,
@@ -165,7 +174,9 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
                        _num_parents, _src_shift, _src_width)   \
 {                                                              \
        .enable_reg = (void __iomem *)_reg,                     \
-       .flags = _flags,                                        \
+       .enable_bit = 0, /* unused */                           \
+       .flags = _flags | CLK_MASK_DIV_ON_DISABLE,              \
+       .div_mask = SH_CLK_DIV6_MSK,                            \
        .parent_table = _parents,                               \
        .parent_num = _num_parents,                             \
        .src_shift = _src_shift,                                \
@@ -176,7 +187,9 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
 {                                                              \
        .parent         = _parent,                              \
        .enable_reg     = (void __iomem *)_reg,                 \
-       .flags          = _flags,                               \
+       .enable_bit     = 0,    /* unused */                    \
+       .div_mask       = SH_CLK_DIV6_MSK,                      \
+       .flags          = _flags | CLK_MASK_DIV_ON_DISABLE,     \
 }
 
 int sh_clk_div6_register(struct clk *clks, int nr);
index 5c15aed9c4b2430adebf1b5ca0b9325bcbd22acd..c19a0925829a2bd136e6823a4cc750e2367bbb78 100644 (file)
 #ifndef __SH_PFC_H
 #define __SH_PFC_H
 
+#include <linux/stringify.h>
 #include <asm-generic/gpio.h>
 
 typedef unsigned short pinmux_enum_t;
 typedef unsigned short pinmux_flag_t;
 
-#define PINMUX_TYPE_NONE            0
-#define PINMUX_TYPE_FUNCTION        1
-#define PINMUX_TYPE_GPIO            2
-#define PINMUX_TYPE_OUTPUT          3
-#define PINMUX_TYPE_INPUT           4
-#define PINMUX_TYPE_INPUT_PULLUP    5
-#define PINMUX_TYPE_INPUT_PULLDOWN  6
+enum {
+       PINMUX_TYPE_NONE,
 
-#define PINMUX_FLAG_TYPE            (0x7)
-#define PINMUX_FLAG_WANT_PULLUP     (1 << 3)
-#define PINMUX_FLAG_WANT_PULLDOWN   (1 << 4)
+       PINMUX_TYPE_FUNCTION,
+       PINMUX_TYPE_GPIO,
+       PINMUX_TYPE_OUTPUT,
+       PINMUX_TYPE_INPUT,
+       PINMUX_TYPE_INPUT_PULLUP,
+       PINMUX_TYPE_INPUT_PULLDOWN,
+
+       PINMUX_FLAG_TYPE,       /* must be last */
+};
 
 #define PINMUX_FLAG_DBIT_SHIFT      5
 #define PINMUX_FLAG_DBIT            (0x1f << PINMUX_FLAG_DBIT_SHIFT)
@@ -36,9 +38,12 @@ typedef unsigned short pinmux_flag_t;
 struct pinmux_gpio {
        pinmux_enum_t enum_id;
        pinmux_flag_t flags;
+       const char *name;
 };
 
-#define PINMUX_GPIO(gpio, data_or_mark) [gpio] = { data_or_mark }
+#define PINMUX_GPIO(gpio, data_or_mark) \
+       [gpio] = { .name = __stringify(gpio), .enum_id = data_or_mark, .flags = PINMUX_TYPE_NONE }
+
 #define PINMUX_DATA(data_or_mark, ids...) data_or_mark, ids, 0
 
 struct pinmux_cfg_reg {
@@ -89,7 +94,7 @@ struct pfc_window {
        unsigned long size;
 };
 
-struct pinmux_info {
+struct sh_pfc {
        char *name;
        pinmux_enum_t reserved_id;
        struct pinmux_range data;
@@ -112,17 +117,45 @@ struct pinmux_info {
        struct pinmux_irq *gpio_irq;
        unsigned int gpio_irq_size;
 
+       spinlock_t lock;
+
        struct resource *resource;
        unsigned int num_resources;
        struct pfc_window *window;
 
        unsigned long unlock_reg;
-
-       struct gpio_chip chip;
 };
 
-int register_pinmux(struct pinmux_info *pip);
-int unregister_pinmux(struct pinmux_info *pip);
+/* XXX compat for now */
+#define pinmux_info sh_pfc
+
+/* drivers/sh/pfc/gpio.c */
+int sh_pfc_register_gpiochip(struct sh_pfc *pfc);
+
+/* drivers/sh/pfc/pinctrl.c */
+int sh_pfc_register_pinctrl(struct sh_pfc *pfc);
+
+/* drivers/sh/pfc/core.c */
+int register_sh_pfc(struct sh_pfc *pfc);
+
+int sh_pfc_read_bit(struct pinmux_data_reg *dr, unsigned long in_pos);
+void sh_pfc_write_bit(struct pinmux_data_reg *dr, unsigned long in_pos,
+                     unsigned long value);
+int sh_pfc_get_data_reg(struct sh_pfc *pfc, unsigned gpio,
+                       struct pinmux_data_reg **drp, int *bitp);
+int sh_pfc_gpio_to_enum(struct sh_pfc *pfc, unsigned gpio, int pos,
+                       pinmux_enum_t *enum_idp);
+int sh_pfc_config_gpio(struct sh_pfc *pfc, unsigned gpio, int pinmux_type,
+                      int cfg_mode);
+
+/* xxx */
+static inline int register_pinmux(struct pinmux_info *pip)
+{
+       struct sh_pfc *pfc = pip;
+       return register_sh_pfc(pfc);
+}
+
+enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
 
 /* helper macro for port */
 #define PORT_1(fn, pfx, sfx) fn(pfx, sfx)
index 717fb746c9a822ce1098870b17b706c184cfdeb7..dd6f06be3c9feb18ddc0a3752aaa43797c38fd08 100644 (file)
@@ -90,10 +90,6 @@ void kick_all_cpus_sync(void);
 void __init call_function_init(void);
 void generic_smp_call_function_single_interrupt(void);
 void generic_smp_call_function_interrupt(void);
-void ipi_call_lock(void);
-void ipi_call_unlock(void);
-void ipi_call_lock_irq(void);
-void ipi_call_unlock_irq(void);
 #else
 static inline void call_function_init(void) { }
 #endif
@@ -181,7 +177,6 @@ static inline int up_smp_call_function(smp_call_func_t func, void *info)
        } while (0)
 
 static inline void smp_send_reschedule(int cpu) { }
-#define num_booting_cpus()                     1
 #define smp_prepare_boot_cpu()                 do {} while (0)
 #define smp_call_function_many(mask, func, info, wait) \
                        (up_smp_call_function(func, info))
index cd83059fb592c7464fc2e812d92e315fe7c77381..0c808d7fa579ec81d2da272caa0cc6630c9635a2 100644 (file)
@@ -408,6 +408,12 @@ static inline void unlock_system_sleep(void) {}
 
 #endif /* !CONFIG_PM_SLEEP */
 
+#ifdef CONFIG_PM_SLEEP_DEBUG
+extern bool pm_print_times_enabled;
+#else
+#define pm_print_times_enabled (false)
+#endif
+
 #ifdef CONFIG_PM_AUTOSLEEP
 
 /* kernel/power/autosleep.c */
index 294d5d5e90b1fe410da2330f0bd0dfce132a021d..fb46b03b18522752538bfae6e192804e9629fc2a 100644 (file)
@@ -4,29 +4,21 @@
 #include <linux/list.h>
 #include <linux/sched.h>
 
-struct task_work;
-typedef void (*task_work_func_t)(struct task_work *);
-
-struct task_work {
-       struct hlist_node hlist;
-       task_work_func_t func;
-       void *data;
-};
+typedef void (*task_work_func_t)(struct callback_head *);
 
 static inline void
-init_task_work(struct task_work *twork, task_work_func_t func, void *data)
+init_task_work(struct callback_head *twork, task_work_func_t func)
 {
        twork->func = func;
-       twork->data = data;
 }
 
-int task_work_add(struct task_struct *task, struct task_work *twork, bool);
-struct task_work *task_work_cancel(struct task_struct *, task_work_func_t);
+int task_work_add(struct task_struct *task, struct callback_head *twork, bool);
+struct callback_head *task_work_cancel(struct task_struct *, task_work_func_t);
 void task_work_run(void);
 
 static inline void exit_task_work(struct task_struct *task)
 {
-       if (unlikely(!hlist_empty(&task->task_works)))
+       if (unlikely(task->task_works))
                task_work_run();
 }
 
index ab8be90b5cc957c9fad62cab8c86796a0645d77a..f37fceb69b73d294e9b045293f6bbbf71b72388d 100644 (file)
@@ -31,10 +31,10 @@ enum tick_nohz_mode {
  * struct tick_sched - sched tick emulation and no idle tick control/stats
  * @sched_timer:       hrtimer to schedule the periodic tick in high
  *                     resolution mode
- * @idle_tick:         Store the last idle tick expiry time when the tick
- *                     timer is modified for idle sleeps. This is necessary
+ * @last_tick:         Store the last tick expiry time when the tick
+ *                     timer is modified for nohz sleeps. This is necessary
  *                     to resume the tick timer operation in the timeline
- *                     when the CPU returns from idle
+ *                     when the CPU returns from nohz sleep.
  * @tick_stopped:      Indicator that the idle tick has been stopped
  * @idle_jiffies:      jiffies at the entry to idle for idle time accounting
  * @idle_calls:                Total number of idle calls
@@ -51,7 +51,7 @@ struct tick_sched {
        struct hrtimer                  sched_timer;
        unsigned long                   check_clocks;
        enum tick_nohz_mode             nohz_mode;
-       ktime_t                         idle_tick;
+       ktime_t                         last_tick;
        int                             inidle;
        int                             tick_stopped;
        unsigned long                   idle_jiffies;
diff --git a/include/linux/time-armada-370-xp.h b/include/linux/time-armada-370-xp.h
new file mode 100644 (file)
index 0000000..dfdfdc0
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Marvell Armada 370/XP SoC timer handling.
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Lior Amsalem <alior@marvell.com>
+ * Gregory CLEMENT <gregory.clement@free-electrons.com>
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
+ *
+ */
+#ifndef __TIME_ARMADA_370_XPPRCMU_H
+#define __TIME_ARMADA_370_XPPRCMU_H
+
+#include <linux/init.h>
+
+void __init armada_370_xp_timer_init(void);
+
+#endif
index 6a4d82bedb03d4f6e9742069c40324c0441265f0..1e98b553042598e0d1d6a41337bec8194ee54a63 100644 (file)
@@ -192,7 +192,7 @@ static inline void tracehook_notify_resume(struct pt_regs *regs)
         * hlist_add_head(task->task_works);
         */
        smp_mb__after_clear_bit();
-       if (unlikely(!hlist_empty(&current->task_works)))
+       if (unlikely(current->task_works))
                task_work_run();
 }
 
index bd96ecd0e05c731c7b55306b693fec2f81cc3d06..802de56c41e8660bd87defec22fdbd6c4d1eb857 100644 (file)
@@ -153,7 +153,7 @@ static inline void tracepoint_synchronize_unregister(void)
        }                                                               \
        static inline void trace_##name##_rcuidle(proto)                \
        {                                                               \
-               if (static_branch(&__tracepoint_##name.key))            \
+               if (static_key_false(&__tracepoint_##name.key))         \
                        __DO_TRACE(&__tracepoint_##name,                \
                                TP_PROTO(data_proto),                   \
                                TP_ARGS(data_args),                     \
index 9c1bd539ea70e780e0e926b54bfc9320d3ec34a4..bf0dd7524b2a81cb660723c08ce76857991df54e 100644 (file)
@@ -246,14 +246,15 @@ struct ustat {
 };
 
 /**
- * struct rcu_head - callback structure for use with RCU
+ * struct callback_head - callback structure for use with RCU and task_work
  * @next: next update requests in a list
  * @func: actual update function to call after the grace period.
  */
-struct rcu_head {
-       struct rcu_head *next;
-       void (*func)(struct rcu_head *head);
+struct callback_head {
+       struct callback_head *next;
+       void (*func)(struct callback_head *head);
 };
+#define rcu_head callback_head
 
 #endif /* __KERNEL__ */
 #endif /*  __ASSEMBLY__ */
diff --git a/include/linux/usb/tilegx.h b/include/linux/usb/tilegx.h
new file mode 100644 (file)
index 0000000..2d65e34
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2012 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   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, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ *
+ * Structure to contain platform-specific data related to Tile-Gx USB
+ * controllers.
+ */
+
+#ifndef _LINUX_USB_TILEGX_H
+#define _LINUX_USB_TILEGX_H
+
+#include <gxio/usb_host.h>
+
+struct tilegx_usb_platform_data {
+       /* GXIO device index. */
+       int dev_index;
+
+       /* GXIO device context. */
+       gxio_usb_host_context_t usb_ctx;
+
+       /* Device IRQ. */
+       unsigned int irq;
+};
+
+#endif /* _LINUX_USB_TILEGX_H */
index d456f4c71a323b18b4bcbf24ca59a5bc96b8243a..079d7887dac13697d0dfc5d0cc6ce256800151d0 100644 (file)
@@ -13,7 +13,6 @@
 #define SCM_MAX_FD     253
 
 struct scm_fp_list {
-       struct list_head        list;
        short                   count;
        short                   max;
        struct file             *fp[SCM_MAX_FD];
index 2d7db85e93ae8a7fa8406a1bde8ebc91afa99ff2..f1405d335a968d093aadafee06ab4be105970f88 100644 (file)
@@ -24,10 +24,8 @@ struct se_subsystem_api {
                                struct se_subsystem_dev *, void *);
        void (*free_device)(void *);
        int (*transport_complete)(struct se_cmd *cmd, struct scatterlist *);
-       int (*execute_cmd)(struct se_cmd *, struct scatterlist *, u32,
-                       enum dma_data_direction);
-       int (*do_discard)(struct se_device *, sector_t, u32);
-       void (*do_sync_cache)(struct se_cmd *);
+
+       int (*parse_cdb)(struct se_cmd *cmd);
        ssize_t (*check_configfs_dev_params)(struct se_hba *,
                        struct se_subsystem_dev *);
        ssize_t (*set_configfs_dev_params)(struct se_hba *,
@@ -40,6 +38,13 @@ struct se_subsystem_api {
        unsigned char *(*get_sense_buffer)(struct se_cmd *);
 };
 
+struct spc_ops {
+       int (*execute_rw)(struct se_cmd *cmd);
+       int (*execute_sync_cache)(struct se_cmd *cmd);
+       int (*execute_write_same)(struct se_cmd *cmd);
+       int (*execute_unmap)(struct se_cmd *cmd);
+};
+
 int    transport_subsystem_register(struct se_subsystem_api *);
 void   transport_subsystem_release(struct se_subsystem_api *);
 
@@ -49,6 +54,10 @@ struct se_device *transport_add_device_to_core_hba(struct se_hba *,
 
 void   target_complete_cmd(struct se_cmd *, u8);
 
+int    sbc_parse_cdb(struct se_cmd *cmd, struct spc_ops *ops);
+int    spc_parse_cdb(struct se_cmd *cmd, unsigned int *size);
+int    spc_get_write_same_sectors(struct se_cmd *cmd);
+
 void   transport_set_vpd_proto_id(struct t10_vpd *, unsigned char *);
 int    transport_set_vpd_assoc(struct t10_vpd *, unsigned char *);
 int    transport_set_vpd_ident_type(struct t10_vpd *, unsigned char *);
index dc35d8660aa68ba44f43a684f136e548bc54424f..128ce46fa48a799fa9b3b332a07d2babfee01925 100644 (file)
@@ -145,12 +145,9 @@ enum transport_state_table {
        TRANSPORT_NO_STATE      = 0,
        TRANSPORT_NEW_CMD       = 1,
        TRANSPORT_WRITE_PENDING = 3,
-       TRANSPORT_PROCESS_WRITE = 4,
        TRANSPORT_PROCESSING    = 5,
        TRANSPORT_COMPLETE      = 6,
-       TRANSPORT_PROCESS_TMR   = 9,
        TRANSPORT_ISTATE_PROCESSING = 11,
-       TRANSPORT_NEW_CMD_MAP   = 16,
        TRANSPORT_COMPLETE_QF_WP = 18,
        TRANSPORT_COMPLETE_QF_OK = 19,
 };
@@ -160,25 +157,20 @@ enum se_cmd_flags_table {
        SCF_SUPPORTED_SAM_OPCODE        = 0x00000001,
        SCF_TRANSPORT_TASK_SENSE        = 0x00000002,
        SCF_EMULATED_TASK_SENSE         = 0x00000004,
-       SCF_SCSI_DATA_SG_IO_CDB         = 0x00000008,
-       SCF_SCSI_CONTROL_SG_IO_CDB      = 0x00000010,
-       SCF_SCSI_NON_DATA_CDB           = 0x00000020,
-       SCF_SCSI_TMR_CDB                = 0x00000040,
-       SCF_SCSI_CDB_EXCEPTION          = 0x00000080,
-       SCF_SCSI_RESERVATION_CONFLICT   = 0x00000100,
-       SCF_FUA                         = 0x00000200,
-       SCF_SE_LUN_CMD                  = 0x00000800,
-       SCF_SE_ALLOW_EOO                = 0x00001000,
-       SCF_BIDI                        = 0x00002000,
-       SCF_SENT_CHECK_CONDITION        = 0x00004000,
-       SCF_OVERFLOW_BIT                = 0x00008000,
-       SCF_UNDERFLOW_BIT               = 0x00010000,
-       SCF_SENT_DELAYED_TAS            = 0x00020000,
-       SCF_ALUA_NON_OPTIMIZED          = 0x00040000,
-       SCF_DELAYED_CMD_FROM_SAM_ATTR   = 0x00080000,
-       SCF_UNUSED                      = 0x00100000,
-       SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00200000,
-       SCF_ACK_KREF                    = 0x00400000,
+       SCF_SCSI_DATA_CDB               = 0x00000008,
+       SCF_SCSI_TMR_CDB                = 0x00000010,
+       SCF_SCSI_CDB_EXCEPTION          = 0x00000020,
+       SCF_SCSI_RESERVATION_CONFLICT   = 0x00000040,
+       SCF_FUA                         = 0x00000080,
+       SCF_SE_LUN_CMD                  = 0x00000100,
+       SCF_BIDI                        = 0x00000400,
+       SCF_SENT_CHECK_CONDITION        = 0x00000800,
+       SCF_OVERFLOW_BIT                = 0x00001000,
+       SCF_UNDERFLOW_BIT               = 0x00002000,
+       SCF_SENT_DELAYED_TAS            = 0x00004000,
+       SCF_ALUA_NON_OPTIMIZED          = 0x00008000,
+       SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x00020000,
+       SCF_ACK_KREF                    = 0x00040000,
 };
 
 /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */
@@ -220,6 +212,7 @@ enum tcm_sense_reason_table {
        TCM_CHECK_CONDITION_UNIT_ATTENTION      = 0x0e,
        TCM_CHECK_CONDITION_NOT_READY           = 0x0f,
        TCM_RESERVATION_CONFLICT                = 0x10,
+       TCM_ADDRESS_OUT_OF_RANGE                = 0x11,
 };
 
 enum target_sc_flags_table {
@@ -471,13 +464,6 @@ struct t10_reservation {
        struct t10_reservation_ops pr_ops;
 };
 
-struct se_queue_obj {
-       atomic_t                queue_cnt;
-       spinlock_t              cmd_queue_lock;
-       struct list_head        qobj_list;
-       wait_queue_head_t       thread_wq;
-};
-
 struct se_tmr_req {
        /* Task Management function to be performed */
        u8                      function;
@@ -486,11 +472,8 @@ struct se_tmr_req {
        int                     call_transport;
        /* Reference to ITT that Task Mgmt should be performed */
        u32                     ref_task_tag;
-       /* 64-bit encoded SAM LUN from $FABRIC_MOD TMR header */
-       u64                     ref_task_lun;
        void                    *fabric_tmr_ptr;
        struct se_cmd           *task_cmd;
-       struct se_cmd           *ref_cmd;
        struct se_device        *tmr_dev;
        struct se_lun           *tmr_lun;
        struct list_head        tmr_list;
@@ -537,7 +520,6 @@ struct se_cmd {
        /* Only used for internal passthrough and legacy TCM fabric modules */
        struct se_session       *se_sess;
        struct se_tmr_req       *se_tmr_req;
-       struct list_head        se_queue_node;
        struct list_head        se_cmd_list;
        struct completion       cmd_wait_comp;
        struct kref             cmd_kref;
@@ -575,7 +557,6 @@ struct se_cmd {
        struct scatterlist      *t_bidi_data_sg;
        unsigned int            t_bidi_data_nents;
 
-       struct list_head        execute_list;
        struct list_head        state_list;
        bool                    state_active;
 
@@ -633,7 +614,6 @@ struct se_session {
        struct list_head        sess_list;
        struct list_head        sess_acl_list;
        struct list_head        sess_cmd_list;
-       struct list_head        sess_wait_list;
        spinlock_t              sess_cmd_lock;
        struct kref             sess_kref;
 };
@@ -780,13 +760,11 @@ struct se_device {
        /* Active commands on this virtual SE device */
        atomic_t                simple_cmds;
        atomic_t                dev_ordered_id;
-       atomic_t                execute_tasks;
        atomic_t                dev_ordered_sync;
        atomic_t                dev_qf_count;
        struct se_obj           dev_obj;
        struct se_obj           dev_access_obj;
        struct se_obj           dev_export_obj;
-       struct se_queue_obj     dev_queue_obj;
        spinlock_t              delayed_cmd_lock;
        spinlock_t              execute_task_lock;
        spinlock_t              dev_reservation_lock;
@@ -802,11 +780,9 @@ struct se_device {
        struct t10_pr_registration *dev_pr_res_holder;
        struct list_head        dev_sep_list;
        struct list_head        dev_tmr_list;
-       /* Pointer to descriptor for processing thread */
-       struct task_struct      *process_thread;
+       struct workqueue_struct *tmr_wq;
        struct work_struct      qf_work_queue;
        struct list_head        delayed_cmd_list;
-       struct list_head        execute_list;
        struct list_head        state_list;
        struct list_head        qf_cmd_list;
        /* Pointer to associated SE HBA */
index c78a23333c4fb801c72e86a55b05fd7e7bf66f67..69fb3cfd02d7f2acc0d656b458287d4d89666f82 100644 (file)
@@ -32,12 +32,6 @@ struct target_core_fabric_ops {
        void (*tpg_release_fabric_acl)(struct se_portal_group *,
                                        struct se_node_acl *);
        u32 (*tpg_get_inst_index)(struct se_portal_group *);
-       /*
-        * Optional function pointer for TCM to perform command map
-        * from TCM processing thread context, for those struct se_cmd
-        * initially allocated in interrupt context.
-        */
-       int (*new_cmd_map)(struct se_cmd *);
        /*
         * Optional to release struct se_cmd and fabric dependent allocated
         * I/O descriptor in transport_cmd_check_stop().
@@ -108,20 +102,18 @@ void      transport_init_se_cmd(struct se_cmd *, struct target_core_fabric_ops *,
                struct se_session *, u32, int, int, unsigned char *);
 int    transport_lookup_cmd_lun(struct se_cmd *, u32);
 int    target_setup_cmd_from_cdb(struct se_cmd *, unsigned char *);
-void   target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,
+int    target_submit_cmd(struct se_cmd *, struct se_session *, unsigned char *,
                unsigned char *, u32, u32, int, int, int);
 int    target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,
                unsigned char *sense, u32 unpacked_lun,
                void *fabric_tmr_ptr, unsigned char tm_type,
                gfp_t, unsigned int, int);
 int    transport_handle_cdb_direct(struct se_cmd *);
-int    transport_generic_handle_cdb_map(struct se_cmd *);
-int    transport_generic_handle_data(struct se_cmd *);
 int    transport_generic_map_mem_to_cmd(struct se_cmd *cmd,
                struct scatterlist *, u32, struct scatterlist *, u32);
 int    transport_generic_new_cmd(struct se_cmd *);
 
-void   transport_generic_process_write(struct se_cmd *);
+void   target_execute_cmd(struct se_cmd *cmd);
 
 void   transport_generic_free_cmd(struct se_cmd *, int);
 
@@ -129,9 +121,8 @@ bool        transport_wait_for_tasks(struct se_cmd *);
 int    transport_check_aborted_status(struct se_cmd *, int);
 int    transport_send_check_condition_and_sense(struct se_cmd *, u8, int);
 
-void   target_get_sess_cmd(struct se_session *, struct se_cmd *, bool);
 int    target_put_sess_cmd(struct se_session *, struct se_cmd *);
-void   target_splice_sess_cmd_list(struct se_session *);
+void   target_sess_cmd_list_set_waiting(struct se_session *);
 void   target_wait_for_sess_cmds(struct se_session *, int);
 
 int    core_alua_check_nonop_delay(struct se_cmd *);
index d274734b2aa42fee56d7ce7ab2b7898d39521e7e..5bde94d8585b77c71e957926ed9ca7b5b85bcc5c 100644 (file)
@@ -541,6 +541,50 @@ TRACE_EVENT(rcu_torture_read,
                  __entry->rcutorturename, __entry->rhp)
 );
 
+/*
+ * Tracepoint for _rcu_barrier() execution.  The string "s" describes
+ * the _rcu_barrier phase:
+ *     "Begin": rcu_barrier_callback() started.
+ *     "Check": rcu_barrier_callback() checking for piggybacking.
+ *     "EarlyExit": rcu_barrier_callback() piggybacked, thus early exit.
+ *     "Inc1": rcu_barrier_callback() piggyback check counter incremented.
+ *     "Offline": rcu_barrier_callback() found offline CPU
+ *     "OnlineQ": rcu_barrier_callback() found online CPU with callbacks.
+ *     "OnlineNQ": rcu_barrier_callback() found online CPU, no callbacks.
+ *     "IRQ": An rcu_barrier_callback() callback posted on remote CPU.
+ *     "CB": An rcu_barrier_callback() invoked a callback, not the last.
+ *     "LastCB": An rcu_barrier_callback() invoked the last callback.
+ *     "Inc2": rcu_barrier_callback() piggyback check counter incremented.
+ * The "cpu" argument is the CPU or -1 if meaningless, the "cnt" argument
+ * is the count of remaining callbacks, and "done" is the piggybacking count.
+ */
+TRACE_EVENT(rcu_barrier,
+
+       TP_PROTO(char *rcuname, char *s, int cpu, int cnt, unsigned long done),
+
+       TP_ARGS(rcuname, s, cpu, cnt, done),
+
+       TP_STRUCT__entry(
+               __field(char *, rcuname)
+               __field(char *, s)
+               __field(int, cpu)
+               __field(int, cnt)
+               __field(unsigned long, done)
+       ),
+
+       TP_fast_assign(
+               __entry->rcuname = rcuname;
+               __entry->s = s;
+               __entry->cpu = cpu;
+               __entry->cnt = cnt;
+               __entry->done = done;
+       ),
+
+       TP_printk("%s %s cpu %d remaining %d # %lu",
+                 __entry->rcuname, __entry->s, __entry->cpu, __entry->cnt,
+                 __entry->done)
+);
+
 #else /* #ifdef CONFIG_RCU_TRACE */
 
 #define trace_rcu_grace_period(rcuname, gpnum, gpevent) do { } while (0)
@@ -564,6 +608,7 @@ TRACE_EVENT(rcu_torture_read,
 #define trace_rcu_batch_end(rcuname, callbacks_invoked, cb, nr, iit, risk) \
        do { } while (0)
 #define trace_rcu_torture_read(rcutorturename, rhp) do { } while (0)
+#define trace_rcu_barrier(name, s, cpu, cnt, done) do { } while (0)
 
 #endif /* #else #ifdef CONFIG_RCU_TRACE */
 
index 769724944fc60ccbbb2fcab4d03a6fe832fe679e..c6bc2faaf2611533b1b2a72e6d3e191fa6033616 100644 (file)
@@ -571,6 +571,7 @@ static inline void ftrace_test_probe_##call(void)                   \
 
 #undef __print_flags
 #undef __print_symbolic
+#undef __print_hex
 #undef __get_dynamic_array
 #undef __get_str
 
index b5cc0a7c4708f167925aa1f974eb356f99de1ebc..3f151f6c6da79cd2e28d55ba513aed39b2593923 100644 (file)
@@ -68,6 +68,7 @@
 #include <linux/shmem_fs.h>
 #include <linux/slab.h>
 #include <linux/perf_event.h>
+#include <linux/file.h>
 
 #include <asm/io.h>
 #include <asm/bugs.h>
@@ -804,8 +805,8 @@ static noinline int init_post(void)
        system_state = SYSTEM_RUNNING;
        numa_default_policy();
 
-
        current->signal->flags |= SIGNAL_UNKILLABLE;
+       flush_delayed_fput();
 
        if (ramdisk_execute_command) {
                run_init_process(ramdisk_execute_command);
index 8ce57691e7b60994d9cc97620b7550c603df5391..f8e54f5b90804ea58309da551fcd40dd8cf12333 100644 (file)
@@ -413,7 +413,7 @@ static void mqueue_evict_inode(struct inode *inode)
 }
 
 static int mqueue_create(struct inode *dir, struct dentry *dentry,
-                               umode_t mode, struct nameidata *nd)
+                               umode_t mode, bool excl)
 {
        struct inode *inode;
        struct mq_attr *attr = dentry->d_fsdata;
@@ -721,8 +721,8 @@ static int mq_attr_ok(struct ipc_namespace *ipc_ns, struct mq_attr *attr)
 /*
  * Invoked when creating a new queue via sys_mq_open
  */
-static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,
-                       struct dentry *dentry, int oflag, umode_t mode,
+static struct file *do_create(struct ipc_namespace *ipc_ns, struct inode *dir,
+                       struct path *path, int oflag, umode_t mode,
                        struct mq_attr *attr)
 {
        const struct cred *cred = current_cred();
@@ -732,9 +732,9 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,
        if (attr) {
                ret = mq_attr_ok(ipc_ns, attr);
                if (ret)
-                       goto out;
+                       return ERR_PTR(ret);
                /* store for use during create */
-               dentry->d_fsdata = attr;
+               path->dentry->d_fsdata = attr;
        } else {
                struct mq_attr def_attr;
 
@@ -744,71 +744,51 @@ static struct file *do_create(struct ipc_namespace *ipc_ns, struct dentry *dir,
                                          ipc_ns->mq_msgsize_default);
                ret = mq_attr_ok(ipc_ns, &def_attr);
                if (ret)
-                       goto out;
+                       return ERR_PTR(ret);
        }
 
        mode &= ~current_umask();
-       ret = mnt_want_write(ipc_ns->mq_mnt);
+       ret = mnt_want_write(path->mnt);
        if (ret)
-               goto out;
-       ret = vfs_create(dir->d_inode, dentry, mode, NULL);
-       dentry->d_fsdata = NULL;
-       if (ret)
-               goto out_drop_write;
-
-       result = dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred);
+               return ERR_PTR(ret);
+       ret = vfs_create(dir, path->dentry, mode, true);
+       path->dentry->d_fsdata = NULL;
+       if (!ret)
+               result = dentry_open(path, oflag, cred);
+       else
+               result = ERR_PTR(ret);
        /*
         * dentry_open() took a persistent mnt_want_write(),
         * so we can now drop this one.
         */
-       mnt_drop_write(ipc_ns->mq_mnt);
+       mnt_drop_write(path->mnt);
        return result;
-
-out_drop_write:
-       mnt_drop_write(ipc_ns->mq_mnt);
-out:
-       dput(dentry);
-       mntput(ipc_ns->mq_mnt);
-       return ERR_PTR(ret);
 }
 
 /* Opens existing queue */
-static struct file *do_open(struct ipc_namespace *ipc_ns,
-                               struct dentry *dentry, int oflag)
+static struct file *do_open(struct path *path, int oflag)
 {
-       int ret;
-       const struct cred *cred = current_cred();
-
        static const int oflag2acc[O_ACCMODE] = { MAY_READ, MAY_WRITE,
                                                  MAY_READ | MAY_WRITE };
-
-       if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY)) {
-               ret = -EINVAL;
-               goto err;
-       }
-
-       if (inode_permission(dentry->d_inode, oflag2acc[oflag & O_ACCMODE])) {
-               ret = -EACCES;
-               goto err;
-       }
-
-       return dentry_open(dentry, ipc_ns->mq_mnt, oflag, cred);
-
-err:
-       dput(dentry);
-       mntput(ipc_ns->mq_mnt);
-       return ERR_PTR(ret);
+       int acc;
+       if ((oflag & O_ACCMODE) == (O_RDWR | O_WRONLY))
+               return ERR_PTR(-EINVAL);
+       acc = oflag2acc[oflag & O_ACCMODE];
+       if (inode_permission(path->dentry->d_inode, acc))
+               return ERR_PTR(-EACCES);
+       return dentry_open(path, oflag, current_cred());
 }
 
 SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
                struct mq_attr __user *, u_attr)
 {
-       struct dentry *dentry;
+       struct path path;
        struct file *filp;
        char *name;
        struct mq_attr attr;
        int fd, error;
        struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
+       struct dentry *root = ipc_ns->mq_mnt->mnt_root;
 
        if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr)))
                return -EFAULT;
@@ -822,52 +802,49 @@ SYSCALL_DEFINE4(mq_open, const char __user *, u_name, int, oflag, umode_t, mode,
        if (fd < 0)
                goto out_putname;
 
-       mutex_lock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex);
-       dentry = lookup_one_len(name, ipc_ns->mq_mnt->mnt_root, strlen(name));
-       if (IS_ERR(dentry)) {
-               error = PTR_ERR(dentry);
+       error = 0;
+       mutex_lock(&root->d_inode->i_mutex);
+       path.dentry = lookup_one_len(name, root, strlen(name));
+       if (IS_ERR(path.dentry)) {
+               error = PTR_ERR(path.dentry);
                goto out_putfd;
        }
-       mntget(ipc_ns->mq_mnt);
+       path.mnt = mntget(ipc_ns->mq_mnt);
 
        if (oflag & O_CREAT) {
-               if (dentry->d_inode) {  /* entry already exists */
-                       audit_inode(name, dentry);
+               if (path.dentry->d_inode) {     /* entry already exists */
+                       audit_inode(name, path.dentry);
                        if (oflag & O_EXCL) {
                                error = -EEXIST;
                                goto out;
                        }
-                       filp = do_open(ipc_ns, dentry, oflag);
+                       filp = do_open(&path, oflag);
                } else {
-                       filp = do_create(ipc_ns, ipc_ns->mq_mnt->mnt_root,
-                                               dentry, oflag, mode,
+                       filp = do_create(ipc_ns, root->d_inode,
+                                               &path, oflag, mode,
                                                u_attr ? &attr : NULL);
                }
        } else {
-               if (!dentry->d_inode) {
+               if (!path.dentry->d_inode) {
                        error = -ENOENT;
                        goto out;
                }
-               audit_inode(name, dentry);
-               filp = do_open(ipc_ns, dentry, oflag);
+               audit_inode(name, path.dentry);
+               filp = do_open(&path, oflag);
        }
 
-       if (IS_ERR(filp)) {
+       if (!IS_ERR(filp))
+               fd_install(fd, filp);
+       else
                error = PTR_ERR(filp);
-               goto out_putfd;
-       }
-
-       fd_install(fd, filp);
-       goto out_upsem;
-
 out:
-       dput(dentry);
-       mntput(ipc_ns->mq_mnt);
+       path_put(&path);
 out_putfd:
-       put_unused_fd(fd);
-       fd = error;
-out_upsem:
-       mutex_unlock(&ipc_ns->mq_mnt->mnt_root->d_inode->i_mutex);
+       if (error) {
+               put_unused_fd(fd);
+               fd = error;
+       }
+       mutex_unlock(&root->d_inode->i_mutex);
 out_putname:
        putname(name);
        return fd;
index 5bf0790497e7779cf1001f6cb30c214de812ccd5..3a5ca582ba1ebe2373803bfbf1887357d05b523e 100644 (file)
@@ -595,7 +595,7 @@ void audit_trim_trees(void)
 
                root_mnt = collect_mounts(&path);
                path_put(&path);
-               if (!root_mnt)
+               if (IS_ERR(root_mnt))
                        goto skip_it;
 
                spin_lock(&hash_lock);
@@ -669,8 +669,8 @@ int audit_add_tree_rule(struct audit_krule *rule)
                goto Err;
        mnt = collect_mounts(&path);
        path_put(&path);
-       if (!mnt) {
-               err = -ENOMEM;
+       if (IS_ERR(mnt)) {
+               err = PTR_ERR(mnt);
                goto Err;
        }
 
@@ -719,8 +719,8 @@ int audit_tag_tree(char *old, char *new)
                return err;
        tagged = collect_mounts(&path2);
        path_put(&path2);
-       if (!tagged)
-               return -ENOMEM;
+       if (IS_ERR(tagged))
+               return PTR_ERR(tagged);
 
        err = kern_path(old, 0, &path1);
        if (err) {
index e683869365d9bdaf60abcb44e37da05506ab5672..3823281401b57e423f9a4ba9255b5904920e7e1d 100644 (file)
@@ -355,34 +355,15 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
 /* Get path information necessary for adding watches. */
 static int audit_get_nd(struct audit_watch *watch, struct path *parent)
 {
-       struct nameidata nd;
-       struct dentry *d;
-       int err;
-
-       err = kern_path_parent(watch->path, &nd);
-       if (err)
-               return err;
-
-       if (nd.last_type != LAST_NORM) {
-               path_put(&nd.path);
-               return -EINVAL;
-       }
-
-       mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
-       d = lookup_one_len(nd.last.name, nd.path.dentry, nd.last.len);
-       if (IS_ERR(d)) {
-               mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-               path_put(&nd.path);
+       struct dentry *d = kern_path_locked(watch->path, parent);
+       if (IS_ERR(d))
                return PTR_ERR(d);
-       }
+       mutex_unlock(&parent->dentry->d_inode->i_mutex);
        if (d->d_inode) {
                /* update watch filter fields */
                watch->dev = d->d_inode->i_sb->s_dev;
                watch->ino = d->d_inode->i_ino;
        }
-       mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
-
-       *parent = nd.path;
        dput(d);
        return 0;
 }
index b303dfc7dce0703299c3e8840e91d101497495ec..af2b5641fc8b094617aa812ac203ff49272ab979 100644 (file)
@@ -822,7 +822,7 @@ EXPORT_SYMBOL_GPL(cgroup_unlock);
  */
 
 static int cgroup_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode);
-static struct dentry *cgroup_lookup(struct inode *, struct dentry *, struct nameidata *);
+static struct dentry *cgroup_lookup(struct inode *, struct dentry *, unsigned int);
 static int cgroup_rmdir(struct inode *unused_dir, struct dentry *dentry);
 static int cgroup_populate_dir(struct cgroup *cgrp);
 static const struct inode_operations cgroup_dir_inode_operations;
@@ -1587,7 +1587,7 @@ static struct dentry *cgroup_mount(struct file_system_type *fs_type,
        opts.new_root = new_root;
 
        /* Locate an existing or new sb for this hierarchy */
-       sb = sget(fs_type, cgroup_test_super, cgroup_set_super, &opts);
+       sb = sget(fs_type, cgroup_test_super, cgroup_set_super, 0, &opts);
        if (IS_ERR(sb)) {
                ret = PTR_ERR(sb);
                cgroup_drop_root(opts.new_root);
@@ -2570,7 +2570,7 @@ static const struct inode_operations cgroup_dir_inode_operations = {
        .rename = cgroup_rename,
 };
 
-static struct dentry *cgroup_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
+static struct dentry *cgroup_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
 {
        if (dentry->d_name.len > NAME_MAX)
                return ERR_PTR(-ENAMETOOLONG);
index 67b847dfa2bb64b58d30db51460f22243142ee2d..1f91413edb87d0c9b77efc4e84c9b2f9729e9b8c 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/ctype.h>
 #include <linux/string.h>
 #include <linux/kernel.h>
+#include <linux/kmsg_dump.h>
 #include <linux/reboot.h>
 #include <linux/sched.h>
 #include <linux/sysrq.h>
@@ -2040,8 +2041,15 @@ static int kdb_env(int argc, const char **argv)
  */
 static int kdb_dmesg(int argc, const char **argv)
 {
-       char *syslog_data[4], *start, *end, c = '\0', *p;
-       int diag, logging, logsize, lines = 0, adjust = 0, n;
+       int diag;
+       int logging;
+       int lines = 0;
+       int adjust = 0;
+       int n = 0;
+       int skip = 0;
+       struct kmsg_dumper dumper = { .active = 1 };
+       size_t len;
+       char buf[201];
 
        if (argc > 2)
                return KDB_ARGCOUNT;
@@ -2064,22 +2072,10 @@ static int kdb_dmesg(int argc, const char **argv)
                kdb_set(2, setargs);
        }
 
-       /* syslog_data[0,1] physical start, end+1.  syslog_data[2,3]
-        * logical start, end+1. */
-       kdb_syslog_data(syslog_data);
-       if (syslog_data[2] == syslog_data[3])
-               return 0;
-       logsize = syslog_data[1] - syslog_data[0];
-       start = syslog_data[2];
-       end = syslog_data[3];
-#define KDB_WRAP(p) (((p - syslog_data[0]) % logsize) + syslog_data[0])
-       for (n = 0, p = start; p < end; ++p) {
-               c = *KDB_WRAP(p);
-               if (c == '\n')
-                       ++n;
-       }
-       if (c != '\n')
-               ++n;
+       kmsg_dump_rewind_nolock(&dumper);
+       while (kmsg_dump_get_line_nolock(&dumper, 1, NULL, 0, NULL))
+               n++;
+
        if (lines < 0) {
                if (adjust >= n)
                        kdb_printf("buffer only contains %d lines, nothing "
@@ -2087,21 +2083,11 @@ static int kdb_dmesg(int argc, const char **argv)
                else if (adjust - lines >= n)
                        kdb_printf("buffer only contains %d lines, last %d "
                                   "lines printed\n", n, n - adjust);
-               if (adjust) {
-                       for (; start < end && adjust; ++start) {
-                               if (*KDB_WRAP(start) == '\n')
-                                       --adjust;
-                       }
-                       if (start < end)
-                               ++start;
-               }
-               for (p = start; p < end && lines; ++p) {
-                       if (*KDB_WRAP(p) == '\n')
-                               ++lines;
-               }
-               end = p;
+               skip = adjust;
+               lines = abs(lines);
        } else if (lines > 0) {
-               int skip = n - (adjust + lines);
+               skip = n - lines - adjust;
+               lines = abs(lines);
                if (adjust >= n) {
                        kdb_printf("buffer only contains %d lines, "
                                   "nothing printed\n", n);
@@ -2112,35 +2098,24 @@ static int kdb_dmesg(int argc, const char **argv)
                        kdb_printf("buffer only contains %d lines, first "
                                   "%d lines printed\n", n, lines);
                }
-               for (; start < end && skip; ++start) {
-                       if (*KDB_WRAP(start) == '\n')
-                               --skip;
-               }
-               for (p = start; p < end && lines; ++p) {
-                       if (*KDB_WRAP(p) == '\n')
-                               --lines;
-               }
-               end = p;
+       } else {
+               lines = n;
        }
-       /* Do a line at a time (max 200 chars) to reduce protocol overhead */
-       c = '\n';
-       while (start != end) {
-               char buf[201];
-               p = buf;
-               if (KDB_FLAG(CMD_INTERRUPT))
-                       return 0;
-               while (start < end && (c = *KDB_WRAP(start)) &&
-                      (p - buf) < sizeof(buf)-1) {
-                       ++start;
-                       *p++ = c;
-                       if (c == '\n')
-                               break;
+
+       if (skip >= n || skip < 0)
+               return 0;
+
+       kmsg_dump_rewind_nolock(&dumper);
+       while (kmsg_dump_get_line_nolock(&dumper, 1, buf, sizeof(buf), &len)) {
+               if (skip) {
+                       skip--;
+                       continue;
                }
-               *p = '\0';
-               kdb_printf("%s", buf);
+               if (!lines--)
+                       break;
+
+               kdb_printf("%.*s\n", (int)len - 1, buf);
        }
-       if (c != '\n')
-               kdb_printf("\n");
 
        return 0;
 }
index 47c4e56e513ba72ec485afdaa2ad0e30bac6e30f..392ec6a25844c48f1242a649c0c58a1d22c0c783 100644 (file)
@@ -205,7 +205,6 @@ extern char kdb_grep_string[];
 extern int kdb_grep_leading;
 extern int kdb_grep_trailing;
 extern char *kdb_cmds[];
-extern void kdb_syslog_data(char *syslog_data[]);
 extern unsigned long kdb_task_state_string(const char *);
 extern char kdb_task_state_char (const struct task_struct *);
 extern unsigned long kdb_task_state(const struct task_struct *p,
index d7d71d6ec97278cf60fa5b13e79a80bff27b6af2..f1cf0edeb39afa1a3f6543a2f383ac8c4828127b 100644 (file)
@@ -1645,6 +1645,8 @@ perf_install_in_context(struct perf_event_context *ctx,
        lockdep_assert_held(&ctx->mutex);
 
        event->ctx = ctx;
+       if (event->cpu != -1)
+               event->cpu = cpu;
 
        if (!task) {
                /*
@@ -6252,6 +6254,8 @@ SYSCALL_DEFINE5(perf_event_open,
                }
        }
 
+       get_online_cpus();
+
        event = perf_event_alloc(&attr, cpu, task, group_leader, NULL,
                                 NULL, NULL);
        if (IS_ERR(event)) {
@@ -6304,7 +6308,7 @@ SYSCALL_DEFINE5(perf_event_open,
        /*
         * Get the target context (task or percpu):
         */
-       ctx = find_get_context(pmu, task, cpu);
+       ctx = find_get_context(pmu, task, event->cpu);
        if (IS_ERR(ctx)) {
                err = PTR_ERR(ctx);
                goto err_alloc;
@@ -6377,20 +6381,23 @@ SYSCALL_DEFINE5(perf_event_open,
        mutex_lock(&ctx->mutex);
 
        if (move_group) {
-               perf_install_in_context(ctx, group_leader, cpu);
+               synchronize_rcu();
+               perf_install_in_context(ctx, group_leader, event->cpu);
                get_ctx(ctx);
                list_for_each_entry(sibling, &group_leader->sibling_list,
                                    group_entry) {
-                       perf_install_in_context(ctx, sibling, cpu);
+                       perf_install_in_context(ctx, sibling, event->cpu);
                        get_ctx(ctx);
                }
        }
 
-       perf_install_in_context(ctx, event, cpu);
+       perf_install_in_context(ctx, event, event->cpu);
        ++ctx->generation;
        perf_unpin_context(ctx);
        mutex_unlock(&ctx->mutex);
 
+       put_online_cpus();
+
        event->owner = current;
 
        mutex_lock(&current->perf_event_mutex);
@@ -6419,6 +6426,7 @@ err_context:
 err_alloc:
        free_event(event);
 err_task:
+       put_online_cpus();
        if (task)
                put_task_struct(task);
 err_group_fd:
@@ -6479,6 +6487,39 @@ err:
 }
 EXPORT_SYMBOL_GPL(perf_event_create_kernel_counter);
 
+void perf_pmu_migrate_context(struct pmu *pmu, int src_cpu, int dst_cpu)
+{
+       struct perf_event_context *src_ctx;
+       struct perf_event_context *dst_ctx;
+       struct perf_event *event, *tmp;
+       LIST_HEAD(events);
+
+       src_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, src_cpu)->ctx;
+       dst_ctx = &per_cpu_ptr(pmu->pmu_cpu_context, dst_cpu)->ctx;
+
+       mutex_lock(&src_ctx->mutex);
+       list_for_each_entry_safe(event, tmp, &src_ctx->event_list,
+                                event_entry) {
+               perf_remove_from_context(event);
+               put_ctx(src_ctx);
+               list_add(&event->event_entry, &events);
+       }
+       mutex_unlock(&src_ctx->mutex);
+
+       synchronize_rcu();
+
+       mutex_lock(&dst_ctx->mutex);
+       list_for_each_entry_safe(event, tmp, &events, event_entry) {
+               list_del(&event->event_entry);
+               if (event->state >= PERF_EVENT_STATE_OFF)
+                       event->state = PERF_EVENT_STATE_INACTIVE;
+               perf_install_in_context(dst_ctx, event, dst_cpu);
+               get_ctx(dst_ctx);
+       }
+       mutex_unlock(&dst_ctx->mutex);
+}
+EXPORT_SYMBOL_GPL(perf_pmu_migrate_context);
+
 static void sync_child_event(struct perf_event *child_event,
                               struct task_struct *child)
 {
index 985be4d80fe8188da34ee47be809faf7b0801ee9..f93532748bca38340f0f2d196b54324a03590480 100644 (file)
 #define UINSNS_PER_PAGE                        (PAGE_SIZE/UPROBE_XOL_SLOT_BYTES)
 #define MAX_UPROBE_XOL_SLOTS           UINSNS_PER_PAGE
 
-static struct srcu_struct uprobes_srcu;
 static struct rb_root uprobes_tree = RB_ROOT;
 
 static DEFINE_SPINLOCK(uprobes_treelock);      /* serialize rbtree access */
 
 #define UPROBES_HASH_SZ        13
 
+/*
+ * We need separate register/unregister and mmap/munmap lock hashes because
+ * of mmap_sem nesting.
+ *
+ * uprobe_register() needs to install probes on (potentially) all processes
+ * and thus needs to acquire multiple mmap_sems (consequtively, not
+ * concurrently), whereas uprobe_mmap() is called while holding mmap_sem
+ * for the particular process doing the mmap.
+ *
+ * uprobe_register()->register_for_each_vma() needs to drop/acquire mmap_sem
+ * because of lock order against i_mmap_mutex. This means there's a hole in
+ * the register vma iteration where a mmap() can happen.
+ *
+ * Thus uprobe_register() can race with uprobe_mmap() and we can try and
+ * install a probe where one is already installed.
+ */
+
 /* serialize (un)register */
 static struct mutex uprobes_mutex[UPROBES_HASH_SZ];
 
@@ -61,17 +77,6 @@ static struct mutex uprobes_mmap_mutex[UPROBES_HASH_SZ];
  */
 static atomic_t uprobe_events = ATOMIC_INIT(0);
 
-/*
- * Maintain a temporary per vma info that can be used to search if a vma
- * has already been handled. This structure is introduced since extending
- * vm_area_struct wasnt recommended.
- */
-struct vma_info {
-       struct list_head        probe_list;
-       struct mm_struct        *mm;
-       loff_t                  vaddr;
-};
-
 struct uprobe {
        struct rb_node          rb_node;        /* node in the rb tree */
        atomic_t                ref;
@@ -100,7 +105,8 @@ static bool valid_vma(struct vm_area_struct *vma, bool is_register)
        if (!is_register)
                return true;
 
-       if ((vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)) == (VM_READ|VM_EXEC))
+       if ((vma->vm_flags & (VM_HUGETLB|VM_READ|VM_WRITE|VM_EXEC|VM_SHARED))
+                               == (VM_READ|VM_EXEC))
                return true;
 
        return false;
@@ -129,33 +135,17 @@ static loff_t vma_address(struct vm_area_struct *vma, loff_t offset)
 static int __replace_page(struct vm_area_struct *vma, struct page *page, struct page *kpage)
 {
        struct mm_struct *mm = vma->vm_mm;
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *ptep;
-       spinlock_t *ptl;
        unsigned long addr;
-       int err = -EFAULT;
+       spinlock_t *ptl;
+       pte_t *ptep;
 
        addr = page_address_in_vma(page, vma);
        if (addr == -EFAULT)
-               goto out;
-
-       pgd = pgd_offset(mm, addr);
-       if (!pgd_present(*pgd))
-               goto out;
-
-       pud = pud_offset(pgd, addr);
-       if (!pud_present(*pud))
-               goto out;
-
-       pmd = pmd_offset(pud, addr);
-       if (!pmd_present(*pmd))
-               goto out;
+               return -EFAULT;
 
-       ptep = pte_offset_map_lock(mm, pmd, addr, &ptl);
+       ptep = page_check_address(page, mm, addr, &ptl, 0);
        if (!ptep)
-               goto out;
+               return -EAGAIN;
 
        get_page(kpage);
        page_add_new_anon_rmap(kpage, vma, addr);
@@ -174,10 +164,8 @@ static int __replace_page(struct vm_area_struct *vma, struct page *page, struct
                try_to_free_swap(page);
        put_page(page);
        pte_unmap_unlock(ptep, ptl);
-       err = 0;
 
-out:
-       return err;
+       return 0;
 }
 
 /**
@@ -222,9 +210,8 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
        void *vaddr_old, *vaddr_new;
        struct vm_area_struct *vma;
        struct uprobe *uprobe;
-       loff_t addr;
        int ret;
-
+retry:
        /* Read the page with vaddr into memory */
        ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &old_page, &vma);
        if (ret <= 0)
@@ -246,10 +233,6 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
        if (mapping != vma->vm_file->f_mapping)
                goto put_out;
 
-       addr = vma_address(vma, uprobe->offset);
-       if (vaddr != (unsigned long)addr)
-               goto put_out;
-
        ret = -ENOMEM;
        new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, vaddr);
        if (!new_page)
@@ -267,11 +250,7 @@ static int write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
        vaddr_new = kmap_atomic(new_page);
 
        memcpy(vaddr_new, vaddr_old, PAGE_SIZE);
-
-       /* poke the new insn in, ASSUMES we don't cross page boundary */
-       vaddr &= ~PAGE_MASK;
-       BUG_ON(vaddr + UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
-       memcpy(vaddr_new + vaddr, &opcode, UPROBE_SWBP_INSN_SIZE);
+       memcpy(vaddr_new + (vaddr & ~PAGE_MASK), &opcode, UPROBE_SWBP_INSN_SIZE);
 
        kunmap_atomic(vaddr_new);
        kunmap_atomic(vaddr_old);
@@ -291,6 +270,8 @@ unlock_out:
 put_out:
        put_page(old_page);
 
+       if (unlikely(ret == -EAGAIN))
+               goto retry;
        return ret;
 }
 
@@ -312,7 +293,7 @@ static int read_opcode(struct mm_struct *mm, unsigned long vaddr, uprobe_opcode_
        void *vaddr_new;
        int ret;
 
-       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 0, &page, NULL);
+       ret = get_user_pages(NULL, mm, vaddr, 1, 0, 1, &page, NULL);
        if (ret <= 0)
                return ret;
 
@@ -333,10 +314,20 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
        uprobe_opcode_t opcode;
        int result;
 
+       if (current->mm == mm) {
+               pagefault_disable();
+               result = __copy_from_user_inatomic(&opcode, (void __user*)vaddr,
+                                                               sizeof(opcode));
+               pagefault_enable();
+
+               if (likely(result == 0))
+                       goto out;
+       }
+
        result = read_opcode(mm, vaddr, &opcode);
        if (result)
                return result;
-
+out:
        if (is_swbp_insn(&opcode))
                return 1;
 
@@ -355,7 +346,9 @@ static int is_swbp_at_addr(struct mm_struct *mm, unsigned long vaddr)
 int __weak set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm, unsigned long vaddr)
 {
        int result;
-
+       /*
+        * See the comment near uprobes_hash().
+        */
        result = is_swbp_at_addr(mm, vaddr);
        if (result == 1)
                return -EEXIST;
@@ -520,7 +513,6 @@ static struct uprobe *alloc_uprobe(struct inode *inode, loff_t offset)
        uprobe->inode = igrab(inode);
        uprobe->offset = offset;
        init_rwsem(&uprobe->consumer_rwsem);
-       INIT_LIST_HEAD(&uprobe->pending_list);
 
        /* add to uprobes_tree, sorted on inode:offset */
        cur_uprobe = insert_uprobe(uprobe);
@@ -588,20 +580,22 @@ static bool consumer_del(struct uprobe *uprobe, struct uprobe_consumer *uc)
 }
 
 static int
-__copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *insn,
-                       unsigned long nbytes, unsigned long offset)
+__copy_insn(struct address_space *mapping, struct file *filp, char *insn,
+                       unsigned long nbytes, loff_t offset)
 {
-       struct file *filp = vma->vm_file;
        struct page *page;
        void *vaddr;
-       unsigned long off1;
-       unsigned long idx;
+       unsigned long off;
+       pgoff_t idx;
 
        if (!filp)
                return -EINVAL;
 
-       idx = (unsigned long)(offset >> PAGE_CACHE_SHIFT);
-       off1 = offset &= ~PAGE_MASK;
+       if (!mapping->a_ops->readpage)
+               return -EIO;
+
+       idx = offset >> PAGE_CACHE_SHIFT;
+       off = offset & ~PAGE_MASK;
 
        /*
         * Ensure that the page that has the original instruction is
@@ -612,22 +606,20 @@ __copy_insn(struct address_space *mapping, struct vm_area_struct *vma, char *ins
                return PTR_ERR(page);
 
        vaddr = kmap_atomic(page);
-       memcpy(insn, vaddr + off1, nbytes);
+       memcpy(insn, vaddr + off, nbytes);
        kunmap_atomic(vaddr);
        page_cache_release(page);
 
        return 0;
 }
 
-static int
-copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr)
+static int copy_insn(struct uprobe *uprobe, struct file *filp)
 {
        struct address_space *mapping;
        unsigned long nbytes;
        int bytes;
 
-       addr &= ~PAGE_MASK;
-       nbytes = PAGE_SIZE - addr;
+       nbytes = PAGE_SIZE - (uprobe->offset & ~PAGE_MASK);
        mapping = uprobe->inode->i_mapping;
 
        /* Instruction at end of binary; copy only available bytes */
@@ -638,13 +630,13 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr)
 
        /* Instruction at the page-boundary; copy bytes in second page */
        if (nbytes < bytes) {
-               if (__copy_insn(mapping, vma, uprobe->arch.insn + nbytes,
-                               bytes - nbytes, uprobe->offset + nbytes))
-                       return -ENOMEM;
-
+               int err = __copy_insn(mapping, filp, uprobe->arch.insn + nbytes,
+                               bytes - nbytes, uprobe->offset + nbytes);
+               if (err)
+                       return err;
                bytes = nbytes;
        }
-       return __copy_insn(mapping, vma, uprobe->arch.insn, bytes, uprobe->offset);
+       return __copy_insn(mapping, filp, uprobe->arch.insn, bytes, uprobe->offset);
 }
 
 /*
@@ -672,9 +664,8 @@ copy_insn(struct uprobe *uprobe, struct vm_area_struct *vma, unsigned long addr)
  */
 static int
 install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
-                       struct vm_area_struct *vma, loff_t vaddr)
+                       struct vm_area_struct *vma, unsigned long vaddr)
 {
-       unsigned long addr;
        int ret;
 
        /*
@@ -687,20 +678,22 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
        if (!uprobe->consumers)
                return -EEXIST;
 
-       addr = (unsigned long)vaddr;
-
        if (!(uprobe->flags & UPROBE_COPY_INSN)) {
-               ret = copy_insn(uprobe, vma, addr);
+               ret = copy_insn(uprobe, vma->vm_file);
                if (ret)
                        return ret;
 
                if (is_swbp_insn((uprobe_opcode_t *)uprobe->arch.insn))
-                       return -EEXIST;
+                       return -ENOTSUPP;
 
-               ret = arch_uprobe_analyze_insn(&uprobe->arch, mm);
+               ret = arch_uprobe_analyze_insn(&uprobe->arch, mm, vaddr);
                if (ret)
                        return ret;
 
+               /* write_opcode() assumes we don't cross page boundary */
+               BUG_ON((uprobe->offset & ~PAGE_MASK) +
+                               UPROBE_SWBP_INSN_SIZE > PAGE_SIZE);
+
                uprobe->flags |= UPROBE_COPY_INSN;
        }
 
@@ -713,7 +706,7 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
         * Hence increment before and decrement on failure.
         */
        atomic_inc(&mm->uprobes_state.count);
-       ret = set_swbp(&uprobe->arch, mm, addr);
+       ret = set_swbp(&uprobe->arch, mm, vaddr);
        if (ret)
                atomic_dec(&mm->uprobes_state.count);
 
@@ -721,27 +714,21 @@ install_breakpoint(struct uprobe *uprobe, struct mm_struct *mm,
 }
 
 static void
-remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, loff_t vaddr)
+remove_breakpoint(struct uprobe *uprobe, struct mm_struct *mm, unsigned long vaddr)
 {
-       if (!set_orig_insn(&uprobe->arch, mm, (unsigned long)vaddr, true))
+       if (!set_orig_insn(&uprobe->arch, mm, vaddr, true))
                atomic_dec(&mm->uprobes_state.count);
 }
 
 /*
- * There could be threads that have hit the breakpoint and are entering the
- * notifier code and trying to acquire the uprobes_treelock. The thread
- * calling delete_uprobe() that is removing the uprobe from the rb_tree can
- * race with these threads and might acquire the uprobes_treelock compared
- * to some of the breakpoint hit threads. In such a case, the breakpoint
- * hit threads will not find the uprobe. The current unregistering thread
- * waits till all other threads have hit a breakpoint, to acquire the
- * uprobes_treelock before the uprobe is removed from the rbtree.
+ * There could be threads that have already hit the breakpoint. They
+ * will recheck the current insn and restart if find_uprobe() fails.
+ * See find_active_uprobe().
  */
 static void delete_uprobe(struct uprobe *uprobe)
 {
        unsigned long flags;
 
-       synchronize_srcu(&uprobes_srcu);
        spin_lock_irqsave(&uprobes_treelock, flags);
        rb_erase(&uprobe->rb_node, &uprobes_tree);
        spin_unlock_irqrestore(&uprobes_treelock, flags);
@@ -750,139 +737,135 @@ static void delete_uprobe(struct uprobe *uprobe)
        atomic_dec(&uprobe_events);
 }
 
-static struct vma_info *
-__find_next_vma_info(struct address_space *mapping, struct list_head *head,
-                       struct vma_info *vi, loff_t offset, bool is_register)
+struct map_info {
+       struct map_info *next;
+       struct mm_struct *mm;
+       unsigned long vaddr;
+};
+
+static inline struct map_info *free_map_info(struct map_info *info)
+{
+       struct map_info *next = info->next;
+       kfree(info);
+       return next;
+}
+
+static struct map_info *
+build_map_info(struct address_space *mapping, loff_t offset, bool is_register)
 {
+       unsigned long pgoff = offset >> PAGE_SHIFT;
        struct prio_tree_iter iter;
        struct vm_area_struct *vma;
-       struct vma_info *tmpvi;
-       unsigned long pgoff;
-       int existing_vma;
-       loff_t vaddr;
-
-       pgoff = offset >> PAGE_SHIFT;
+       struct map_info *curr = NULL;
+       struct map_info *prev = NULL;
+       struct map_info *info;
+       int more = 0;
 
+ again:
+       mutex_lock(&mapping->i_mmap_mutex);
        vma_prio_tree_foreach(vma, &iter, &mapping->i_mmap, pgoff, pgoff) {
                if (!valid_vma(vma, is_register))
                        continue;
 
-               existing_vma = 0;
-               vaddr = vma_address(vma, offset);
-
-               list_for_each_entry(tmpvi, head, probe_list) {
-                       if (tmpvi->mm == vma->vm_mm && tmpvi->vaddr == vaddr) {
-                               existing_vma = 1;
-                               break;
-                       }
+               if (!prev && !more) {
+                       /*
+                        * Needs GFP_NOWAIT to avoid i_mmap_mutex recursion through
+                        * reclaim. This is optimistic, no harm done if it fails.
+                        */
+                       prev = kmalloc(sizeof(struct map_info),
+                                       GFP_NOWAIT | __GFP_NOMEMALLOC | __GFP_NOWARN);
+                       if (prev)
+                               prev->next = NULL;
                }
-
-               /*
-                * Another vma needs a probe to be installed. However skip
-                * installing the probe if the vma is about to be unlinked.
-                */
-               if (!existing_vma && atomic_inc_not_zero(&vma->vm_mm->mm_users)) {
-                       vi->mm = vma->vm_mm;
-                       vi->vaddr = vaddr;
-                       list_add(&vi->probe_list, head);
-
-                       return vi;
+               if (!prev) {
+                       more++;
+                       continue;
                }
-       }
 
-       return NULL;
-}
-
-/*
- * Iterate in the rmap prio tree  and find a vma where a probe has not
- * yet been inserted.
- */
-static struct vma_info *
-find_next_vma_info(struct address_space *mapping, struct list_head *head,
-               loff_t offset, bool is_register)
-{
-       struct vma_info *vi, *retvi;
+               if (!atomic_inc_not_zero(&vma->vm_mm->mm_users))
+                       continue;
 
-       vi = kzalloc(sizeof(struct vma_info), GFP_KERNEL);
-       if (!vi)
-               return ERR_PTR(-ENOMEM);
+               info = prev;
+               prev = prev->next;
+               info->next = curr;
+               curr = info;
 
-       mutex_lock(&mapping->i_mmap_mutex);
-       retvi = __find_next_vma_info(mapping, head, vi, offset, is_register);
+               info->mm = vma->vm_mm;
+               info->vaddr = vma_address(vma, offset);
+       }
        mutex_unlock(&mapping->i_mmap_mutex);
 
-       if (!retvi)
-               kfree(vi);
+       if (!more)
+               goto out;
+
+       prev = curr;
+       while (curr) {
+               mmput(curr->mm);
+               curr = curr->next;
+       }
 
-       return retvi;
+       do {
+               info = kmalloc(sizeof(struct map_info), GFP_KERNEL);
+               if (!info) {
+                       curr = ERR_PTR(-ENOMEM);
+                       goto out;
+               }
+               info->next = prev;
+               prev = info;
+       } while (--more);
+
+       goto again;
+ out:
+       while (prev)
+               prev = free_map_info(prev);
+       return curr;
 }
 
 static int register_for_each_vma(struct uprobe *uprobe, bool is_register)
 {
-       struct list_head try_list;
-       struct vm_area_struct *vma;
-       struct address_space *mapping;
-       struct vma_info *vi, *tmpvi;
-       struct mm_struct *mm;
-       loff_t vaddr;
-       int ret;
+       struct map_info *info;
+       int err = 0;
 
-       mapping = uprobe->inode->i_mapping;
-       INIT_LIST_HEAD(&try_list);
+       info = build_map_info(uprobe->inode->i_mapping,
+                                       uprobe->offset, is_register);
+       if (IS_ERR(info))
+               return PTR_ERR(info);
 
-       ret = 0;
+       while (info) {
+               struct mm_struct *mm = info->mm;
+               struct vm_area_struct *vma;
 
-       for (;;) {
-               vi = find_next_vma_info(mapping, &try_list, uprobe->offset, is_register);
-               if (!vi)
-                       break;
+               if (err)
+                       goto free;
 
-               if (IS_ERR(vi)) {
-                       ret = PTR_ERR(vi);
-                       break;
-               }
+               down_write(&mm->mmap_sem);
+               vma = find_vma(mm, (unsigned long)info->vaddr);
+               if (!vma || !valid_vma(vma, is_register))
+                       goto unlock;
 
-               mm = vi->mm;
-               down_read(&mm->mmap_sem);
-               vma = find_vma(mm, (unsigned long)vi->vaddr);
-               if (!vma || !valid_vma(vma, is_register)) {
-                       list_del(&vi->probe_list);
-                       kfree(vi);
-                       up_read(&mm->mmap_sem);
-                       mmput(mm);
-                       continue;
-               }
-               vaddr = vma_address(vma, uprobe->offset);
                if (vma->vm_file->f_mapping->host != uprobe->inode ||
-                                               vaddr != vi->vaddr) {
-                       list_del(&vi->probe_list);
-                       kfree(vi);
-                       up_read(&mm->mmap_sem);
-                       mmput(mm);
-                       continue;
-               }
-
-               if (is_register)
-                       ret = install_breakpoint(uprobe, mm, vma, vi->vaddr);
-               else
-                       remove_breakpoint(uprobe, mm, vi->vaddr);
+                   vma_address(vma, uprobe->offset) != info->vaddr)
+                       goto unlock;
 
-               up_read(&mm->mmap_sem);
-               mmput(mm);
                if (is_register) {
-                       if (ret && ret == -EEXIST)
-                               ret = 0;
-                       if (ret)
-                               break;
+                       err = install_breakpoint(uprobe, mm, vma, info->vaddr);
+                       /*
+                        * We can race against uprobe_mmap(), see the
+                        * comment near uprobe_hash().
+                        */
+                       if (err == -EEXIST)
+                               err = 0;
+               } else {
+                       remove_breakpoint(uprobe, mm, info->vaddr);
                }
+ unlock:
+               up_write(&mm->mmap_sem);
+ free:
+               mmput(mm);
+               info = free_map_info(info);
        }
 
-       list_for_each_entry_safe(vi, tmpvi, &try_list, probe_list) {
-               list_del(&vi->probe_list);
-               kfree(vi);
-       }
-
-       return ret;
+       return err;
 }
 
 static int __uprobe_register(struct uprobe *uprobe)
@@ -1048,7 +1031,7 @@ static void build_probe_list(struct inode *inode, struct list_head *head)
 int uprobe_mmap(struct vm_area_struct *vma)
 {
        struct list_head tmp_list;
-       struct uprobe *uprobe, *u;
+       struct uprobe *uprobe;
        struct inode *inode;
        int ret, count;
 
@@ -1066,12 +1049,9 @@ int uprobe_mmap(struct vm_area_struct *vma)
        ret = 0;
        count = 0;
 
-       list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) {
-               loff_t vaddr;
-
-               list_del(&uprobe->pending_list);
+       list_for_each_entry(uprobe, &tmp_list, pending_list) {
                if (!ret) {
-                       vaddr = vma_address(vma, uprobe->offset);
+                       loff_t vaddr = vma_address(vma, uprobe->offset);
 
                        if (vaddr < vma->vm_start || vaddr >= vma->vm_end) {
                                put_uprobe(uprobe);
@@ -1079,8 +1059,10 @@ int uprobe_mmap(struct vm_area_struct *vma)
                        }
 
                        ret = install_breakpoint(uprobe, vma->vm_mm, vma, vaddr);
-
-                       /* Ignore double add: */
+                       /*
+                        * We can race against uprobe_register(), see the
+                        * comment near uprobe_hash().
+                        */
                        if (ret == -EEXIST) {
                                ret = 0;
 
@@ -1115,7 +1097,7 @@ int uprobe_mmap(struct vm_area_struct *vma)
 void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned long end)
 {
        struct list_head tmp_list;
-       struct uprobe *uprobe, *u;
+       struct uprobe *uprobe;
        struct inode *inode;
 
        if (!atomic_read(&uprobe_events) || !valid_vma(vma, false))
@@ -1132,11 +1114,8 @@ void uprobe_munmap(struct vm_area_struct *vma, unsigned long start, unsigned lon
        mutex_lock(uprobes_mmap_hash(inode));
        build_probe_list(inode, &tmp_list);
 
-       list_for_each_entry_safe(uprobe, u, &tmp_list, pending_list) {
-               loff_t vaddr;
-
-               list_del(&uprobe->pending_list);
-               vaddr = vma_address(vma, uprobe->offset);
+       list_for_each_entry(uprobe, &tmp_list, pending_list) {
+               loff_t vaddr = vma_address(vma, uprobe->offset);
 
                if (vaddr >= start && vaddr < end) {
                        /*
@@ -1378,9 +1357,6 @@ void uprobe_free_utask(struct task_struct *t)
 {
        struct uprobe_task *utask = t->utask;
 
-       if (t->uprobe_srcu_id != -1)
-               srcu_read_unlock_raw(&uprobes_srcu, t->uprobe_srcu_id);
-
        if (!utask)
                return;
 
@@ -1398,7 +1374,6 @@ void uprobe_free_utask(struct task_struct *t)
 void uprobe_copy_process(struct task_struct *t)
 {
        t->utask = NULL;
-       t->uprobe_srcu_id = -1;
 }
 
 /*
@@ -1417,7 +1392,6 @@ static struct uprobe_task *add_utask(void)
        if (unlikely(!utask))
                return NULL;
 
-       utask->active_uprobe = NULL;
        current->utask = utask;
        return utask;
 }
@@ -1479,41 +1453,64 @@ static bool can_skip_sstep(struct uprobe *uprobe, struct pt_regs *regs)
        return false;
 }
 
+static struct uprobe *find_active_uprobe(unsigned long bp_vaddr, int *is_swbp)
+{
+       struct mm_struct *mm = current->mm;
+       struct uprobe *uprobe = NULL;
+       struct vm_area_struct *vma;
+
+       down_read(&mm->mmap_sem);
+       vma = find_vma(mm, bp_vaddr);
+       if (vma && vma->vm_start <= bp_vaddr) {
+               if (valid_vma(vma, false)) {
+                       struct inode *inode;
+                       loff_t offset;
+
+                       inode = vma->vm_file->f_mapping->host;
+                       offset = bp_vaddr - vma->vm_start;
+                       offset += (vma->vm_pgoff << PAGE_SHIFT);
+                       uprobe = find_uprobe(inode, offset);
+               }
+
+               if (!uprobe)
+                       *is_swbp = is_swbp_at_addr(mm, bp_vaddr);
+       } else {
+               *is_swbp = -EFAULT;
+       }
+       up_read(&mm->mmap_sem);
+
+       return uprobe;
+}
+
 /*
  * Run handler and ask thread to singlestep.
  * Ensure all non-fatal signals cannot interrupt thread while it singlesteps.
  */
 static void handle_swbp(struct pt_regs *regs)
 {
-       struct vm_area_struct *vma;
        struct uprobe_task *utask;
        struct uprobe *uprobe;
-       struct mm_struct *mm;
        unsigned long bp_vaddr;
+       int uninitialized_var(is_swbp);
 
-       uprobe = NULL;
        bp_vaddr = uprobe_get_swbp_addr(regs);
-       mm = current->mm;
-       down_read(&mm->mmap_sem);
-       vma = find_vma(mm, bp_vaddr);
-
-       if (vma && vma->vm_start <= bp_vaddr && valid_vma(vma, false)) {
-               struct inode *inode;
-               loff_t offset;
-
-               inode = vma->vm_file->f_mapping->host;
-               offset = bp_vaddr - vma->vm_start;
-               offset += (vma->vm_pgoff << PAGE_SHIFT);
-               uprobe = find_uprobe(inode, offset);
-       }
-
-       srcu_read_unlock_raw(&uprobes_srcu, current->uprobe_srcu_id);
-       current->uprobe_srcu_id = -1;
-       up_read(&mm->mmap_sem);
+       uprobe = find_active_uprobe(bp_vaddr, &is_swbp);
 
        if (!uprobe) {
-               /* No matching uprobe; signal SIGTRAP. */
-               send_sig(SIGTRAP, current, 0);
+               if (is_swbp > 0) {
+                       /* No matching uprobe; signal SIGTRAP. */
+                       send_sig(SIGTRAP, current, 0);
+               } else {
+                       /*
+                        * Either we raced with uprobe_unregister() or we can't
+                        * access this memory. The latter is only possible if
+                        * another thread plays with our ->mm. In both cases
+                        * we can simply restart. If this vma was unmapped we
+                        * can pretend this insn was not executed yet and get
+                        * the (correct) SIGSEGV after restart.
+                        */
+                       instruction_pointer_set(regs, bp_vaddr);
+               }
                return;
        }
 
@@ -1620,7 +1617,6 @@ int uprobe_pre_sstep_notifier(struct pt_regs *regs)
                utask->state = UTASK_BP_HIT;
 
        set_thread_flag(TIF_UPROBE);
-       current->uprobe_srcu_id = srcu_read_lock_raw(&uprobes_srcu);
 
        return 1;
 }
@@ -1655,7 +1651,6 @@ static int __init init_uprobes(void)
                mutex_init(&uprobes_mutex[i]);
                mutex_init(&uprobes_mmap_mutex[i]);
        }
-       init_srcu_struct(&uprobes_srcu);
 
        return register_die_notifier(&uprobe_exception_nb);
 }
index 2f59cc334516a9b9e831bb54aa0375c999ae69b2..d17f6c4ddfa9755f4318413805f9b64417b34d47 100644 (file)
@@ -953,14 +953,11 @@ void do_exit(long code)
        exit_signals(tsk);  /* sets PF_EXITING */
        /*
         * tsk->flags are checked in the futex code to protect against
-        * an exiting task cleaning up the robust pi futexes, and in
-        * task_work_add() to avoid the race with exit_task_work().
+        * an exiting task cleaning up the robust pi futexes.
         */
        smp_mb();
        raw_spin_unlock_wait(&tsk->pi_lock);
 
-       exit_task_work(tsk);
-
        if (unlikely(in_atomic()))
                printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
                                current->comm, task_pid_nr(current),
@@ -995,6 +992,7 @@ void do_exit(long code)
        exit_shm(tsk);
        exit_files(tsk);
        exit_fs(tsk);
+       exit_task_work(tsk);
        check_stack_usage();
        exit_thread();
 
index f00e319d8376289f0273fc1d301f4c1ebb132c86..ff1cad3b7bdc5eda7d525c165c6aaa4cfe659aec 100644 (file)
@@ -1420,7 +1420,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
         */
        p->group_leader = p;
        INIT_LIST_HEAD(&p->thread_group);
-       INIT_HLIST_HEAD(&p->task_works);
+       p->task_works = NULL;
 
        /* Now that the task is set up, run cgroup callbacks if
         * necessary. We need to run them before the task is visible
index 8c548232ba39daf0f7320d64f19d85775000201a..814c9ef6bba14d7e212d082c659fe83f0f361ce8 100644 (file)
@@ -781,7 +781,7 @@ static void wake_threads_waitq(struct irq_desc *desc)
                wake_up(&desc->wait_for_threads);
 }
 
-static void irq_thread_dtor(struct task_work *unused)
+static void irq_thread_dtor(struct callback_head *unused)
 {
        struct task_struct *tsk = current;
        struct irq_desc *desc;
@@ -813,7 +813,7 @@ static void irq_thread_dtor(struct task_work *unused)
  */
 static int irq_thread(void *data)
 {
-       struct task_work on_exit_work;
+       struct callback_head on_exit_work;
        static const struct sched_param param = {
                .sched_priority = MAX_USER_RT_PRIO/2,
        };
@@ -830,7 +830,7 @@ static int irq_thread(void *data)
 
        sched_setscheduler(current, SCHED_FIFO, &param);
 
-       init_task_work(&on_exit_work, irq_thread_dtor, NULL);
+       init_task_work(&on_exit_work, irq_thread_dtor);
        task_work_add(current, &on_exit_work, false);
 
        while (!irq_wait_for_interrupt(action)) {
index 8f9b4eb974e0bd27e435462433a581a9b42e63b8..a70518c9d82f42c57eb400208ce95dd4dd2aafaa 100644 (file)
@@ -175,7 +175,7 @@ config PM_TEST_SUSPEND
        You probably want to have your system's RTC driver statically
        linked, ensuring that it's available when this test runs.
 
-config CAN_PM_TRACE
+config PM_SLEEP_DEBUG
        def_bool y
        depends on PM_DEBUG && PM_SLEEP
 
@@ -196,7 +196,7 @@ config PM_TRACE
 
 config PM_TRACE_RTC
        bool "Suspend/resume event tracing"
-       depends on CAN_PM_TRACE
+       depends on PM_SLEEP_DEBUG
        depends on X86
        select PM_TRACE
        ---help---
index 238025f5472e42d745752f0c29d3534ab7b66285..b26f5f1e773e6b6aa3420ee1fb60c9b8fc6025cc 100644 (file)
@@ -5,6 +5,7 @@
  * Copyright (c) 2003 Open Source Development Lab
  * Copyright (c) 2004 Pavel Machek <pavel@ucw.cz>
  * Copyright (c) 2009 Rafael J. Wysocki, Novell Inc.
+ * Copyright (C) 2012 Bojan Smojver <bojan@rexursive.com>
  *
  * This file is released under the GPLv2.
  */
@@ -45,6 +46,9 @@ enum {
        HIBERNATION_PLATFORM,
        HIBERNATION_SHUTDOWN,
        HIBERNATION_REBOOT,
+#ifdef CONFIG_SUSPEND
+       HIBERNATION_SUSPEND,
+#endif
        /* keep last */
        __HIBERNATION_AFTER_LAST
 };
@@ -353,6 +357,7 @@ int hibernation_snapshot(int platform_mode)
        }
 
        suspend_console();
+       ftrace_stop();
        pm_restrict_gfp_mask();
 
        error = dpm_suspend(PMSG_FREEZE);
@@ -378,6 +383,7 @@ int hibernation_snapshot(int platform_mode)
        if (error || !in_suspend)
                pm_restore_gfp_mask();
 
+       ftrace_start();
        resume_console();
        dpm_complete(msg);
 
@@ -480,6 +486,7 @@ int hibernation_restore(int platform_mode)
 
        pm_prepare_console();
        suspend_console();
+       ftrace_stop();
        pm_restrict_gfp_mask();
        error = dpm_suspend_start(PMSG_QUIESCE);
        if (!error) {
@@ -487,6 +494,7 @@ int hibernation_restore(int platform_mode)
                dpm_resume_end(PMSG_RECOVER);
        }
        pm_restore_gfp_mask();
+       ftrace_start();
        resume_console();
        pm_restore_console();
        return error;
@@ -513,6 +521,7 @@ int hibernation_platform_enter(void)
 
        entering_platform_hibernation = true;
        suspend_console();
+       ftrace_stop();
        error = dpm_suspend_start(PMSG_HIBERNATE);
        if (error) {
                if (hibernation_ops->recover)
@@ -556,6 +565,7 @@ int hibernation_platform_enter(void)
  Resume_devices:
        entering_platform_hibernation = false;
        dpm_resume_end(PMSG_RESTORE);
+       ftrace_start();
        resume_console();
 
  Close:
@@ -573,6 +583,10 @@ int hibernation_platform_enter(void)
  */
 static void power_down(void)
 {
+#ifdef CONFIG_SUSPEND
+       int error;
+#endif
+
        switch (hibernation_mode) {
        case HIBERNATION_REBOOT:
                kernel_restart(NULL);
@@ -582,6 +596,25 @@ static void power_down(void)
        case HIBERNATION_SHUTDOWN:
                kernel_power_off();
                break;
+#ifdef CONFIG_SUSPEND
+       case HIBERNATION_SUSPEND:
+               error = suspend_devices_and_enter(PM_SUSPEND_MEM);
+               if (error) {
+                       if (hibernation_ops)
+                               hibernation_mode = HIBERNATION_PLATFORM;
+                       else
+                               hibernation_mode = HIBERNATION_SHUTDOWN;
+                       power_down();
+               }
+               /*
+                * Restore swap signature.
+                */
+               error = swsusp_unmark();
+               if (error)
+                       printk(KERN_ERR "PM: Swap will be unusable! "
+                                       "Try swapon -a.\n");
+               return;
+#endif
        }
        kernel_halt();
        /*
@@ -819,6 +852,9 @@ static const char * const hibernation_modes[] = {
        [HIBERNATION_PLATFORM]  = "platform",
        [HIBERNATION_SHUTDOWN]  = "shutdown",
        [HIBERNATION_REBOOT]    = "reboot",
+#ifdef CONFIG_SUSPEND
+       [HIBERNATION_SUSPEND]   = "suspend",
+#endif
 };
 
 /*
@@ -859,6 +895,9 @@ static ssize_t disk_show(struct kobject *kobj, struct kobj_attribute *attr,
                switch (i) {
                case HIBERNATION_SHUTDOWN:
                case HIBERNATION_REBOOT:
+#ifdef CONFIG_SUSPEND
+               case HIBERNATION_SUSPEND:
+#endif
                        break;
                case HIBERNATION_PLATFORM:
                        if (hibernation_ops)
@@ -899,6 +938,9 @@ static ssize_t disk_store(struct kobject *kobj, struct kobj_attribute *attr,
                switch (mode) {
                case HIBERNATION_SHUTDOWN:
                case HIBERNATION_REBOOT:
+#ifdef CONFIG_SUSPEND
+               case HIBERNATION_SUSPEND:
+#endif
                        hibernation_mode = mode;
                        break;
                case HIBERNATION_PLATFORM:
index 428f8a034e9684c50a72f41faf71785822456bd5..f458238109ccd32d195c39b02f1d0cc6efdc09c0 100644 (file)
@@ -235,6 +235,47 @@ late_initcall(pm_debugfs_init);
 
 #endif /* CONFIG_PM_SLEEP */
 
+#ifdef CONFIG_PM_SLEEP_DEBUG
+/*
+ * pm_print_times: print time taken by devices to suspend and resume.
+ *
+ * show() returns whether printing of suspend and resume times is enabled.
+ * store() accepts 0 or 1.  0 disables printing and 1 enables it.
+ */
+bool pm_print_times_enabled;
+
+static ssize_t pm_print_times_show(struct kobject *kobj,
+                                  struct kobj_attribute *attr, char *buf)
+{
+       return sprintf(buf, "%d\n", pm_print_times_enabled);
+}
+
+static ssize_t pm_print_times_store(struct kobject *kobj,
+                                   struct kobj_attribute *attr,
+                                   const char *buf, size_t n)
+{
+       unsigned long val;
+
+       if (kstrtoul(buf, 10, &val))
+               return -EINVAL;
+
+       if (val > 1)
+               return -EINVAL;
+
+       pm_print_times_enabled = !!val;
+       return n;
+}
+
+power_attr(pm_print_times);
+
+static inline void pm_print_times_init(void)
+{
+       pm_print_times_enabled = !!initcall_debug;
+}
+#else /* !CONFIG_PP_SLEEP_DEBUG */
+static inline void pm_print_times_init(void) {}
+#endif /* CONFIG_PM_SLEEP_DEBUG */
+
 struct kobject *power_kobj;
 
 /**
@@ -531,6 +572,9 @@ static struct attribute * g[] = {
 #ifdef CONFIG_PM_DEBUG
        &pm_test_attr.attr,
 #endif
+#ifdef CONFIG_PM_SLEEP_DEBUG
+       &pm_print_times_attr.attr,
+#endif
 #endif
        NULL,
 };
@@ -566,6 +610,7 @@ static int __init pm_init(void)
        error = sysfs_create_group(power_kobj, &attr_group);
        if (error)
                return error;
+       pm_print_times_init();
        return pm_autosleep_init();
 }
 
index b0bd4beaebfe7caa84c4c3b4ded37d3e47acacd6..7d4b7ffb3c1d4371f19e81fe83c67ea88ac83759 100644 (file)
@@ -156,6 +156,9 @@ extern void swsusp_free(void);
 extern int swsusp_read(unsigned int *flags_p);
 extern int swsusp_write(unsigned int flags);
 extern void swsusp_close(fmode_t);
+#ifdef CONFIG_SUSPEND
+extern int swsusp_unmark(void);
+#endif
 
 /* kernel/power/block_io.c */
 extern struct block_device *hib_resume_bdev;
index 396d262b8fd01381a99de04d2d310be787b37565..c8b7446b27dfc21add10f610e1692a2f3acee7ed 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/export.h>
 #include <linux/suspend.h>
 #include <linux/syscore_ops.h>
+#include <linux/ftrace.h>
 #include <trace/events/power.h>
 
 #include "power.h"
@@ -212,6 +213,7 @@ int suspend_devices_and_enter(suspend_state_t state)
                        goto Close;
        }
        suspend_console();
+       ftrace_stop();
        suspend_test_start();
        error = dpm_suspend_start(PMSG_SUSPEND);
        if (error) {
@@ -231,6 +233,7 @@ int suspend_devices_and_enter(suspend_state_t state)
        suspend_test_start();
        dpm_resume_end(PMSG_RESUME);
        suspend_test_finish("resume devices");
+       ftrace_start();
        resume_console();
  Close:
        if (suspend_ops->end)
index 11e22c068e8b25ab8c6ba1127be955d2d4d33e39..3c9d764eb0d8af7e2db7ec99888061a5a573b7ed 100644 (file)
@@ -448,9 +448,9 @@ static int save_image(struct swap_map_handle *handle,
        struct timeval start;
        struct timeval stop;
 
-       printk(KERN_INFO "PM: Saving image data pages (%u pages) ...     ",
+       printk(KERN_INFO "PM: Saving image data pages (%u pages)...\n",
                nr_to_write);
-       m = nr_to_write / 100;
+       m = nr_to_write / 10;
        if (!m)
                m = 1;
        nr_pages = 0;
@@ -464,7 +464,8 @@ static int save_image(struct swap_map_handle *handle,
                if (ret)
                        break;
                if (!(nr_pages % m))
-                       printk(KERN_CONT "\b\b\b\b%3d%%", nr_pages / m);
+                       printk(KERN_INFO "PM: Image saving progress: %3d%%\n",
+                              nr_pages / m * 10);
                nr_pages++;
        }
        err2 = hib_wait_on_bio_chain(&bio);
@@ -472,9 +473,7 @@ static int save_image(struct swap_map_handle *handle,
        if (!ret)
                ret = err2;
        if (!ret)
-               printk(KERN_CONT "\b\b\b\bdone\n");
-       else
-               printk(KERN_CONT "\n");
+               printk(KERN_INFO "PM: Image saving done.\n");
        swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
        return ret;
 }
@@ -668,9 +667,9 @@ static int save_image_lzo(struct swap_map_handle *handle,
 
        printk(KERN_INFO
                "PM: Using %u thread(s) for compression.\n"
-               "PM: Compressing and saving image data (%u pages) ...     ",
+               "PM: Compressing and saving image data (%u pages)...\n",
                nr_threads, nr_to_write);
-       m = nr_to_write / 100;
+       m = nr_to_write / 10;
        if (!m)
                m = 1;
        nr_pages = 0;
@@ -690,8 +689,10 @@ static int save_image_lzo(struct swap_map_handle *handle,
                                       data_of(*snapshot), PAGE_SIZE);
 
                                if (!(nr_pages % m))
-                                       printk(KERN_CONT "\b\b\b\b%3d%%",
-                                              nr_pages / m);
+                                       printk(KERN_INFO
+                                              "PM: Image saving progress: "
+                                              "%3d%%\n",
+                                              nr_pages / m * 10);
                                nr_pages++;
                        }
                        if (!off)
@@ -761,11 +762,8 @@ out_finish:
        do_gettimeofday(&stop);
        if (!ret)
                ret = err2;
-       if (!ret) {
-               printk(KERN_CONT "\b\b\b\bdone\n");
-       } else {
-               printk(KERN_CONT "\n");
-       }
+       if (!ret)
+               printk(KERN_INFO "PM: Image saving done.\n");
        swsusp_show_speed(&start, &stop, nr_to_write, "Wrote");
 out_clean:
        if (crc) {
@@ -973,9 +971,9 @@ static int load_image(struct swap_map_handle *handle,
        int err2;
        unsigned nr_pages;
 
-       printk(KERN_INFO "PM: Loading image data pages (%u pages) ...     ",
+       printk(KERN_INFO "PM: Loading image data pages (%u pages)...\n",
                nr_to_read);
-       m = nr_to_read / 100;
+       m = nr_to_read / 10;
        if (!m)
                m = 1;
        nr_pages = 0;
@@ -993,7 +991,8 @@ static int load_image(struct swap_map_handle *handle,
                if (ret)
                        break;
                if (!(nr_pages % m))
-                       printk("\b\b\b\b%3d%%", nr_pages / m);
+                       printk(KERN_INFO "PM: Image loading progress: %3d%%\n",
+                              nr_pages / m * 10);
                nr_pages++;
        }
        err2 = hib_wait_on_bio_chain(&bio);
@@ -1001,12 +1000,11 @@ static int load_image(struct swap_map_handle *handle,
        if (!ret)
                ret = err2;
        if (!ret) {
-               printk("\b\b\b\bdone\n");
+               printk(KERN_INFO "PM: Image loading done.\n");
                snapshot_write_finalize(snapshot);
                if (!snapshot_image_loaded(snapshot))
                        ret = -ENODATA;
-       } else
-               printk("\n");
+       }
        swsusp_show_speed(&start, &stop, nr_to_read, "Read");
        return ret;
 }
@@ -1185,9 +1183,9 @@ static int load_image_lzo(struct swap_map_handle *handle,
 
        printk(KERN_INFO
                "PM: Using %u thread(s) for decompression.\n"
-               "PM: Loading and decompressing image data (%u pages) ...     ",
+               "PM: Loading and decompressing image data (%u pages)...\n",
                nr_threads, nr_to_read);
-       m = nr_to_read / 100;
+       m = nr_to_read / 10;
        if (!m)
                m = 1;
        nr_pages = 0;
@@ -1319,7 +1317,10 @@ static int load_image_lzo(struct swap_map_handle *handle,
                                       data[thr].unc + off, PAGE_SIZE);
 
                                if (!(nr_pages % m))
-                                       printk("\b\b\b\b%3d%%", nr_pages / m);
+                                       printk(KERN_INFO
+                                              "PM: Image loading progress: "
+                                              "%3d%%\n",
+                                              nr_pages / m * 10);
                                nr_pages++;
 
                                ret = snapshot_write_next(snapshot);
@@ -1344,7 +1345,7 @@ out_finish:
        }
        do_gettimeofday(&stop);
        if (!ret) {
-               printk("\b\b\b\bdone\n");
+               printk(KERN_INFO "PM: Image loading done.\n");
                snapshot_write_finalize(snapshot);
                if (!snapshot_image_loaded(snapshot))
                        ret = -ENODATA;
@@ -1357,8 +1358,7 @@ out_finish:
                                }
                        }
                }
-       } else
-               printk("\n");
+       }
        swsusp_show_speed(&start, &stop, nr_to_read, "Read");
 out_clean:
        for (i = 0; i < ring_size; i++)
@@ -1472,6 +1472,34 @@ void swsusp_close(fmode_t mode)
        blkdev_put(hib_resume_bdev, mode);
 }
 
+/**
+ *      swsusp_unmark - Unmark swsusp signature in the resume device
+ */
+
+#ifdef CONFIG_SUSPEND
+int swsusp_unmark(void)
+{
+       int error;
+
+       hib_bio_read_page(swsusp_resume_block, swsusp_header, NULL);
+       if (!memcmp(HIBERNATE_SIG,swsusp_header->sig, 10)) {
+               memcpy(swsusp_header->sig,swsusp_header->orig_sig, 10);
+               error = hib_bio_write_page(swsusp_resume_block,
+                                       swsusp_header, NULL);
+       } else {
+               printk(KERN_ERR "PM: Cannot find swsusp signature!\n");
+               error = -ENODEV;
+       }
+
+       /*
+        * We just returned from suspend, we don't need the image any more.
+        */
+       free_all_swap_pages(root_swap);
+
+       return error;
+}
+#endif
+
 static int swsusp_header_init(void)
 {
        swsusp_header = (struct swsusp_header*) __get_free_page(GFP_KERNEL);
index c8fba3380076afd8db340855340e5886b8497dc6..8f50de394d22b30090d1cf62cd3fd3069d451d57 100644 (file)
@@ -9,6 +9,7 @@
  * manipulate wakelocks on Android.
  */
 
+#include <linux/capability.h>
 #include <linux/ctype.h>
 #include <linux/device.h>
 #include <linux/err.h>
@@ -188,6 +189,9 @@ int pm_wake_lock(const char *buf)
        size_t len;
        int ret = 0;
 
+       if (!capable(CAP_BLOCK_SUSPEND))
+               return -EPERM;
+
        while (*str && !isspace(*str))
                str++;
 
@@ -231,6 +235,9 @@ int pm_wake_unlock(const char *buf)
        size_t len;
        int ret = 0;
 
+       if (!capable(CAP_BLOCK_SUSPEND))
+               return -EPERM;
+
        len = strlen(buf);
        if (!len)
                return -EINVAL;
index 177fa49357a5d346f1296ca431d4a674c7659508..ac4bc9e79465ed6cf416d9694f8ddc463e2e77ab 100644 (file)
@@ -1192,21 +1192,6 @@ SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)
        return do_syslog(type, buf, len, SYSLOG_FROM_CALL);
 }
 
-#ifdef CONFIG_KGDB_KDB
-/* kdb dmesg command needs access to the syslog buffer.  do_syslog()
- * uses locks so it cannot be used during debugging.  Just tell kdb
- * where the start and end of the physical and logical logs are.  This
- * is equivalent to do_syslog(3).
- */
-void kdb_syslog_data(char *syslog_data[4])
-{
-       syslog_data[0] = log_buf;
-       syslog_data[1] = log_buf + log_buf_len;
-       syslog_data[2] = log_buf + log_first_idx;
-       syslog_data[3] = log_buf + log_next_idx;
-}
-#endif /* CONFIG_KGDB_KDB */
-
 static bool __read_mostly ignore_loglevel;
 
 static int __init ignore_loglevel_setup(char *str)
@@ -2525,7 +2510,7 @@ void kmsg_dump(enum kmsg_dump_reason reason)
 }
 
 /**
- * kmsg_dump_get_line - retrieve one kmsg log line
+ * kmsg_dump_get_line_nolock - retrieve one kmsg log line (unlocked version)
  * @dumper: registered kmsg dumper
  * @syslog: include the "<4>" prefixes
  * @line: buffer to copy the line to
@@ -2540,11 +2525,12 @@ void kmsg_dump(enum kmsg_dump_reason reason)
  *
  * A return value of FALSE indicates that there are no more records to
  * read.
+ *
+ * The function is similar to kmsg_dump_get_line(), but grabs no locks.
  */
-bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
-                       char *line, size_t size, size_t *len)
+bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog,
+                              char *line, size_t size, size_t *len)
 {
-       unsigned long flags;
        struct log *msg;
        size_t l = 0;
        bool ret = false;
@@ -2552,7 +2538,6 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
        if (!dumper->active)
                goto out;
 
-       raw_spin_lock_irqsave(&logbuf_lock, flags);
        if (dumper->cur_seq < log_first_seq) {
                /* messages are gone, move to first available one */
                dumper->cur_seq = log_first_seq;
@@ -2560,10 +2545,8 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
        }
 
        /* last entry */
-       if (dumper->cur_seq >= log_next_seq) {
-               raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+       if (dumper->cur_seq >= log_next_seq)
                goto out;
-       }
 
        msg = log_from_idx(dumper->cur_idx);
        l = msg_print_text(msg, 0, syslog, line, size);
@@ -2571,12 +2554,41 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
        dumper->cur_idx = log_next(dumper->cur_idx);
        dumper->cur_seq++;
        ret = true;
-       raw_spin_unlock_irqrestore(&logbuf_lock, flags);
 out:
        if (len)
                *len = l;
        return ret;
 }
+
+/**
+ * kmsg_dump_get_line - retrieve one kmsg log line
+ * @dumper: registered kmsg dumper
+ * @syslog: include the "<4>" prefixes
+ * @line: buffer to copy the line to
+ * @size: maximum size of the buffer
+ * @len: length of line placed into buffer
+ *
+ * Start at the beginning of the kmsg buffer, with the oldest kmsg
+ * record, and copy one record into the provided buffer.
+ *
+ * Consecutive calls will return the next available record moving
+ * towards the end of the buffer with the youngest messages.
+ *
+ * A return value of FALSE indicates that there are no more records to
+ * read.
+ */
+bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
+                       char *line, size_t size, size_t *len)
+{
+       unsigned long flags;
+       bool ret;
+
+       raw_spin_lock_irqsave(&logbuf_lock, flags);
+       ret = kmsg_dump_get_line_nolock(dumper, syslog, line, size, len);
+       raw_spin_unlock_irqrestore(&logbuf_lock, flags);
+
+       return ret;
+}
 EXPORT_SYMBOL_GPL(kmsg_dump_get_line);
 
 /**
@@ -2678,6 +2690,24 @@ out:
 }
 EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
 
+/**
+ * kmsg_dump_rewind_nolock - reset the interator (unlocked version)
+ * @dumper: registered kmsg dumper
+ *
+ * Reset the dumper's iterator so that kmsg_dump_get_line() and
+ * kmsg_dump_get_buffer() can be called again and used multiple
+ * times within the same dumper.dump() callback.
+ *
+ * The function is similar to kmsg_dump_rewind(), but grabs no locks.
+ */
+void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper)
+{
+       dumper->cur_seq = clear_seq;
+       dumper->cur_idx = clear_idx;
+       dumper->next_seq = log_next_seq;
+       dumper->next_idx = log_next_idx;
+}
+
 /**
  * kmsg_dump_rewind - reset the interator
  * @dumper: registered kmsg dumper
@@ -2691,10 +2721,7 @@ void kmsg_dump_rewind(struct kmsg_dumper *dumper)
        unsigned long flags;
 
        raw_spin_lock_irqsave(&logbuf_lock, flags);
-       dumper->cur_seq = clear_seq;
-       dumper->cur_idx = clear_idx;
-       dumper->next_seq = log_next_seq;
-       dumper->next_idx = log_next_idx;
+       kmsg_dump_rewind_nolock(dumper);
        raw_spin_unlock_irqrestore(&logbuf_lock, flags);
 }
 EXPORT_SYMBOL_GPL(kmsg_dump_rewind);
index 95cba41ce1e9a10568bf17a403b637b57a822d62..4e6a61b15e86fe0e27fc30d80775de4f4c8c47e6 100644 (file)
 
 #ifdef CONFIG_PREEMPT_RCU
 
+/*
+ * Preemptible RCU implementation for rcu_read_lock().
+ * Just increment ->rcu_read_lock_nesting, shared state will be updated
+ * if we block.
+ */
+void __rcu_read_lock(void)
+{
+       current->rcu_read_lock_nesting++;
+       barrier();  /* critical section after entry code. */
+}
+EXPORT_SYMBOL_GPL(__rcu_read_lock);
+
+/*
+ * Preemptible RCU implementation for rcu_read_unlock().
+ * Decrement ->rcu_read_lock_nesting.  If the result is zero (outermost
+ * rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then
+ * invoke rcu_read_unlock_special() to clean up after a context switch
+ * in an RCU read-side critical section and other special cases.
+ */
+void __rcu_read_unlock(void)
+{
+       struct task_struct *t = current;
+
+       if (t->rcu_read_lock_nesting != 1) {
+               --t->rcu_read_lock_nesting;
+       } else {
+               barrier();  /* critical section before exit code. */
+               t->rcu_read_lock_nesting = INT_MIN;
+               barrier();  /* assign before ->rcu_read_unlock_special load */
+               if (unlikely(ACCESS_ONCE(t->rcu_read_unlock_special)))
+                       rcu_read_unlock_special(t);
+               barrier();  /* ->rcu_read_unlock_special load before assign */
+               t->rcu_read_lock_nesting = 0;
+       }
+#ifdef CONFIG_PROVE_LOCKING
+       {
+               int rrln = ACCESS_ONCE(t->rcu_read_lock_nesting);
+
+               WARN_ON_ONCE(rrln < 0 && rrln > INT_MIN / 2);
+       }
+#endif /* #ifdef CONFIG_PROVE_LOCKING */
+}
+EXPORT_SYMBOL_GPL(__rcu_read_unlock);
+
 /*
  * Check for a task exiting while in a preemptible-RCU read-side
  * critical section, clean up if so.  No need to issue warnings,
index 37a5444204d2895193b8ffafbe8b7552c0f83acc..547b1fe5b052c4000a3747c58c3852aa618ae184 100644 (file)
@@ -172,7 +172,7 @@ void rcu_irq_enter(void)
        local_irq_restore(flags);
 }
 
-#ifdef CONFIG_PROVE_RCU
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
 
 /*
  * Test whether RCU thinks that the current CPU is idle.
@@ -183,7 +183,7 @@ int rcu_is_cpu_idle(void)
 }
 EXPORT_SYMBOL(rcu_is_cpu_idle);
 
-#endif /* #ifdef CONFIG_PROVE_RCU */
+#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
 /*
  * Test whether the current CPU was interrupted from idle.  Nested
index fc31a2d651005dd6a912bd3487795975e33740e3..918fd1e8509c9d5589d9ff75d0f63bca0b27cc32 100644 (file)
@@ -132,7 +132,6 @@ static struct rcu_preempt_ctrlblk rcu_preempt_ctrlblk = {
        RCU_TRACE(.rcb.name = "rcu_preempt")
 };
 
-static void rcu_read_unlock_special(struct task_struct *t);
 static int rcu_preempted_readers_exp(void);
 static void rcu_report_exp_done(void);
 
@@ -351,8 +350,9 @@ static int rcu_initiate_boost(void)
                        rcu_preempt_ctrlblk.boost_tasks =
                                rcu_preempt_ctrlblk.gp_tasks;
                invoke_rcu_callbacks();
-       } else
+       } else {
                RCU_TRACE(rcu_initiate_boost_trace());
+       }
        return 1;
 }
 
@@ -526,24 +526,12 @@ void rcu_preempt_note_context_switch(void)
        local_irq_restore(flags);
 }
 
-/*
- * Tiny-preemptible RCU implementation for rcu_read_lock().
- * Just increment ->rcu_read_lock_nesting, shared state will be updated
- * if we block.
- */
-void __rcu_read_lock(void)
-{
-       current->rcu_read_lock_nesting++;
-       barrier();  /* needed if we ever invoke rcu_read_lock in rcutiny.c */
-}
-EXPORT_SYMBOL_GPL(__rcu_read_lock);
-
 /*
  * Handle special cases during rcu_read_unlock(), such as needing to
  * notify RCU core processing or task having blocked during the RCU
  * read-side critical section.
  */
-static noinline void rcu_read_unlock_special(struct task_struct *t)
+void rcu_read_unlock_special(struct task_struct *t)
 {
        int empty;
        int empty_exp;
@@ -626,38 +614,6 @@ static noinline void rcu_read_unlock_special(struct task_struct *t)
        local_irq_restore(flags);
 }
 
-/*
- * Tiny-preemptible RCU implementation for rcu_read_unlock().
- * Decrement ->rcu_read_lock_nesting.  If the result is zero (outermost
- * rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then
- * invoke rcu_read_unlock_special() to clean up after a context switch
- * in an RCU read-side critical section and other special cases.
- */
-void __rcu_read_unlock(void)
-{
-       struct task_struct *t = current;
-
-       barrier();  /* needed if we ever invoke rcu_read_unlock in rcutiny.c */
-       if (t->rcu_read_lock_nesting != 1)
-               --t->rcu_read_lock_nesting;
-       else {
-               t->rcu_read_lock_nesting = INT_MIN;
-               barrier();  /* assign before ->rcu_read_unlock_special load */
-               if (unlikely(ACCESS_ONCE(t->rcu_read_unlock_special)))
-                       rcu_read_unlock_special(t);
-               barrier();  /* ->rcu_read_unlock_special load before assign */
-               t->rcu_read_lock_nesting = 0;
-       }
-#ifdef CONFIG_PROVE_LOCKING
-       {
-               int rrln = ACCESS_ONCE(t->rcu_read_lock_nesting);
-
-               WARN_ON_ONCE(rrln < 0 && rrln > INT_MIN / 2);
-       }
-#endif /* #ifdef CONFIG_PROVE_LOCKING */
-}
-EXPORT_SYMBOL_GPL(__rcu_read_unlock);
-
 /*
  * Check for a quiescent state from the current CPU.  When a task blocks,
  * the task is recorded in the rcu_preempt_ctrlblk structure, which is
@@ -823,9 +779,9 @@ void synchronize_rcu_expedited(void)
                rpcp->exp_tasks = NULL;
 
        /* Wait for tail of ->blkd_tasks list to drain. */
-       if (!rcu_preempted_readers_exp())
+       if (!rcu_preempted_readers_exp()) {
                local_irq_restore(flags);
-       else {
+       else {
                rcu_initiate_boost();
                local_irq_restore(flags);
                wait_event(sync_rcu_preempt_exp_wq,
@@ -846,8 +802,6 @@ EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
  */
 int rcu_preempt_needs_cpu(void)
 {
-       if (!rcu_preempt_running_reader())
-               rcu_preempt_cpu_qs();
        return rcu_preempt_ctrlblk.rcb.rcucblist != NULL;
 }
 
index e66b34ab7555f9153a8c5955678d73fc87b6d777..25b15033c61f88ff7d76854fd16401779d9d9f62 100644 (file)
@@ -49,8 +49,7 @@
 #include <asm/byteorder.h>
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and "
-             "Josh Triplett <josh@freedesktop.org>");
+MODULE_AUTHOR("Paul E. McKenney <paulmck@us.ibm.com> and Josh Triplett <josh@freedesktop.org>");
 
 static int nreaders = -1;      /* # reader threads, defaults to 2*ncpus */
 static int nfakewriters = 4;   /* # fake writer threads */
@@ -206,6 +205,7 @@ static unsigned long boost_starttime;       /* jiffies of next boost test start. */
 DEFINE_MUTEX(boost_mutex);             /* protect setting boost_starttime */
                                        /*  and boost task create/destroy. */
 static atomic_t barrier_cbs_count;     /* Barrier callbacks registered. */
+static bool barrier_phase;             /* Test phase. */
 static atomic_t barrier_cbs_invoked;   /* Barrier callbacks invoked. */
 static wait_queue_head_t *barrier_cbs_wq; /* Coordinate barrier testing. */
 static DECLARE_WAIT_QUEUE_HEAD(barrier_wq);
@@ -407,8 +407,9 @@ rcu_torture_cb(struct rcu_head *p)
        if (++rp->rtort_pipe_count >= RCU_TORTURE_PIPE_LEN) {
                rp->rtort_mbtest = 0;
                rcu_torture_free(rp);
-       } else
+       } else {
                cur_ops->deferred_free(rp);
+       }
 }
 
 static int rcu_no_completed(void)
@@ -635,6 +636,17 @@ static void srcu_torture_synchronize(void)
        synchronize_srcu(&srcu_ctl);
 }
 
+static void srcu_torture_call(struct rcu_head *head,
+                             void (*func)(struct rcu_head *head))
+{
+       call_srcu(&srcu_ctl, head, func);
+}
+
+static void srcu_torture_barrier(void)
+{
+       srcu_barrier(&srcu_ctl);
+}
+
 static int srcu_torture_stats(char *page)
 {
        int cnt = 0;
@@ -661,8 +673,8 @@ static struct rcu_torture_ops srcu_ops = {
        .completed      = srcu_torture_completed,
        .deferred_free  = srcu_torture_deferred_free,
        .sync           = srcu_torture_synchronize,
-       .call           = NULL,
-       .cb_barrier     = NULL,
+       .call           = srcu_torture_call,
+       .cb_barrier     = srcu_torture_barrier,
        .stats          = srcu_torture_stats,
        .name           = "srcu"
 };
@@ -1013,7 +1025,11 @@ rcu_torture_fakewriter(void *arg)
        do {
                schedule_timeout_uninterruptible(1 + rcu_random(&rand)%10);
                udelay(rcu_random(&rand) & 0x3ff);
-               cur_ops->sync();
+               if (cur_ops->cb_barrier != NULL &&
+                   rcu_random(&rand) % (nfakewriters * 8) == 0)
+                       cur_ops->cb_barrier();
+               else
+                       cur_ops->sync();
                rcu_stutter_wait("rcu_torture_fakewriter");
        } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
 
@@ -1183,27 +1199,27 @@ rcu_torture_printk(char *page)
        }
        cnt += sprintf(&page[cnt], "%s%s ", torture_type, TORTURE_FLAG);
        cnt += sprintf(&page[cnt],
-                      "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d "
-                      "rtmbe: %d rtbke: %ld rtbre: %ld "
-                      "rtbf: %ld rtb: %ld nt: %ld "
-                      "onoff: %ld/%ld:%ld/%ld "
-                      "barrier: %ld/%ld:%ld",
+                      "rtc: %p ver: %lu tfle: %d rta: %d rtaf: %d rtf: %d ",
                       rcu_torture_current,
                       rcu_torture_current_version,
                       list_empty(&rcu_torture_freelist),
                       atomic_read(&n_rcu_torture_alloc),
                       atomic_read(&n_rcu_torture_alloc_fail),
-                      atomic_read(&n_rcu_torture_free),
+                      atomic_read(&n_rcu_torture_free));
+       cnt += sprintf(&page[cnt], "rtmbe: %d rtbke: %ld rtbre: %ld ",
                       atomic_read(&n_rcu_torture_mberror),
                       n_rcu_torture_boost_ktrerror,
-                      n_rcu_torture_boost_rterror,
+                      n_rcu_torture_boost_rterror);
+       cnt += sprintf(&page[cnt], "rtbf: %ld rtb: %ld nt: %ld ",
                       n_rcu_torture_boost_failure,
                       n_rcu_torture_boosts,
-                      n_rcu_torture_timers,
+                      n_rcu_torture_timers);
+       cnt += sprintf(&page[cnt], "onoff: %ld/%ld:%ld/%ld ",
                       n_online_successes,
                       n_online_attempts,
                       n_offline_successes,
-                      n_offline_attempts,
+                      n_offline_attempts);
+       cnt += sprintf(&page[cnt], "barrier: %ld/%ld:%ld",
                       n_barrier_successes,
                       n_barrier_attempts,
                       n_rcu_torture_barrier_error);
@@ -1445,8 +1461,7 @@ rcu_torture_shutdown(void *arg)
                delta = shutdown_time - jiffies_snap;
                if (verbose)
                        printk(KERN_ALERT "%s" TORTURE_FLAG
-                              "rcu_torture_shutdown task: %lu "
-                              "jiffies remaining\n",
+                              "rcu_torture_shutdown task: %lu jiffies remaining\n",
                               torture_type, delta);
                schedule_timeout_interruptible(delta);
                jiffies_snap = ACCESS_ONCE(jiffies);
@@ -1498,8 +1513,7 @@ rcu_torture_onoff(void *arg)
                        if (cpu_down(cpu) == 0) {
                                if (verbose)
                                        printk(KERN_ALERT "%s" TORTURE_FLAG
-                                              "rcu_torture_onoff task: "
-                                              "offlined %d\n",
+                                              "rcu_torture_onoff task: offlined %d\n",
                                               torture_type, cpu);
                                n_offline_successes++;
                        }
@@ -1512,8 +1526,7 @@ rcu_torture_onoff(void *arg)
                        if (cpu_up(cpu) == 0) {
                                if (verbose)
                                        printk(KERN_ALERT "%s" TORTURE_FLAG
-                                              "rcu_torture_onoff task: "
-                                              "onlined %d\n",
+                                              "rcu_torture_onoff task: onlined %d\n",
                                               torture_type, cpu);
                                n_online_successes++;
                        }
@@ -1631,6 +1644,7 @@ void rcu_torture_barrier_cbf(struct rcu_head *rcu)
 static int rcu_torture_barrier_cbs(void *arg)
 {
        long myid = (long)arg;
+       bool lastphase = 0;
        struct rcu_head rcu;
 
        init_rcu_head_on_stack(&rcu);
@@ -1638,9 +1652,11 @@ static int rcu_torture_barrier_cbs(void *arg)
        set_user_nice(current, 19);
        do {
                wait_event(barrier_cbs_wq[myid],
-                          atomic_read(&barrier_cbs_count) == n_barrier_cbs ||
+                          barrier_phase != lastphase ||
                           kthread_should_stop() ||
                           fullstop != FULLSTOP_DONTSTOP);
+               lastphase = barrier_phase;
+               smp_mb(); /* ensure barrier_phase load before ->call(). */
                if (kthread_should_stop() || fullstop != FULLSTOP_DONTSTOP)
                        break;
                cur_ops->call(&rcu, rcu_torture_barrier_cbf);
@@ -1665,7 +1681,8 @@ static int rcu_torture_barrier(void *arg)
        do {
                atomic_set(&barrier_cbs_invoked, 0);
                atomic_set(&barrier_cbs_count, n_barrier_cbs);
-               /* wake_up() path contains the required barriers. */
+               smp_mb(); /* Ensure barrier_phase after prior assignments. */
+               barrier_phase = !barrier_phase;
                for (i = 0; i < n_barrier_cbs; i++)
                        wake_up(&barrier_cbs_wq[i]);
                wait_event(barrier_wq,
@@ -1684,7 +1701,7 @@ static int rcu_torture_barrier(void *arg)
                schedule_timeout_interruptible(HZ / 10);
        } while (!kthread_should_stop() && fullstop == FULLSTOP_DONTSTOP);
        VERBOSE_PRINTK_STRING("rcu_torture_barrier task stopping");
-       rcutorture_shutdown_absorb("rcu_torture_barrier_cbs");
+       rcutorture_shutdown_absorb("rcu_torture_barrier");
        while (!kthread_should_stop())
                schedule_timeout_interruptible(1);
        return 0;
@@ -1908,8 +1925,8 @@ rcu_torture_init(void)
        static struct rcu_torture_ops *torture_ops[] =
                { &rcu_ops, &rcu_sync_ops, &rcu_expedited_ops,
                  &rcu_bh_ops, &rcu_bh_sync_ops, &rcu_bh_expedited_ops,
-                 &srcu_ops, &srcu_sync_ops, &srcu_raw_ops,
-                 &srcu_raw_sync_ops, &srcu_expedited_ops,
+                 &srcu_ops, &srcu_sync_ops, &srcu_expedited_ops,
+                 &srcu_raw_ops, &srcu_raw_sync_ops,
                  &sched_ops, &sched_sync_ops, &sched_expedited_ops, };
 
        mutex_lock(&fullstop_mutex);
@@ -1931,8 +1948,7 @@ rcu_torture_init(void)
                return -EINVAL;
        }
        if (cur_ops->fqs == NULL && fqs_duration != 0) {
-               printk(KERN_ALERT "rcu-torture: ->fqs NULL and non-zero "
-                                 "fqs_duration, fqs disabled.\n");
+               printk(KERN_ALERT "rcu-torture: ->fqs NULL and non-zero fqs_duration, fqs disabled.\n");
                fqs_duration = 0;
        }
        if (cur_ops->init)
index 4b97bba7396e6194db4bf5b644ef8b5a1997c974..f280e542e3e9f531df83b03d1e1fce6cf8ebaaa2 100644 (file)
 
 /* Data structures. */
 
-static struct lock_class_key rcu_node_class[NUM_RCU_LVLS];
-
-#define RCU_STATE_INITIALIZER(structname) { \
-       .level = { &structname##_state.node[0] }, \
-       .levelcnt = { \
-               NUM_RCU_LVL_0,  /* root of hierarchy. */ \
-               NUM_RCU_LVL_1, \
-               NUM_RCU_LVL_2, \
-               NUM_RCU_LVL_3, \
-               NUM_RCU_LVL_4, /* == MAX_RCU_LVLS */ \
-       }, \
+static struct lock_class_key rcu_node_class[RCU_NUM_LVLS];
+
+#define RCU_STATE_INITIALIZER(sname, cr) { \
+       .level = { &sname##_state.node[0] }, \
+       .call = cr, \
        .fqs_state = RCU_GP_IDLE, \
        .gpnum = -300, \
        .completed = -300, \
-       .onofflock = __RAW_SPIN_LOCK_UNLOCKED(&structname##_state.onofflock), \
-       .orphan_nxttail = &structname##_state.orphan_nxtlist, \
-       .orphan_donetail = &structname##_state.orphan_donelist, \
-       .fqslock = __RAW_SPIN_LOCK_UNLOCKED(&structname##_state.fqslock), \
-       .n_force_qs = 0, \
-       .n_force_qs_ngp = 0, \
-       .name = #structname, \
+       .onofflock = __RAW_SPIN_LOCK_UNLOCKED(&sname##_state.onofflock), \
+       .orphan_nxttail = &sname##_state.orphan_nxtlist, \
+       .orphan_donetail = &sname##_state.orphan_donelist, \
+       .barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \
+       .fqslock = __RAW_SPIN_LOCK_UNLOCKED(&sname##_state.fqslock), \
+       .name = #sname, \
 }
 
-struct rcu_state rcu_sched_state = RCU_STATE_INITIALIZER(rcu_sched);
+struct rcu_state rcu_sched_state =
+       RCU_STATE_INITIALIZER(rcu_sched, call_rcu_sched);
 DEFINE_PER_CPU(struct rcu_data, rcu_sched_data);
 
-struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh);
+struct rcu_state rcu_bh_state = RCU_STATE_INITIALIZER(rcu_bh, call_rcu_bh);
 DEFINE_PER_CPU(struct rcu_data, rcu_bh_data);
 
 static struct rcu_state *rcu_state;
+LIST_HEAD(rcu_struct_flavors);
+
+/* Increase (but not decrease) the CONFIG_RCU_FANOUT_LEAF at boot time. */
+static int rcu_fanout_leaf = CONFIG_RCU_FANOUT_LEAF;
+module_param(rcu_fanout_leaf, int, 0);
+int rcu_num_lvls __read_mostly = RCU_NUM_LVLS;
+static int num_rcu_lvl[] = {  /* Number of rcu_nodes at specified level. */
+       NUM_RCU_LVL_0,
+       NUM_RCU_LVL_1,
+       NUM_RCU_LVL_2,
+       NUM_RCU_LVL_3,
+       NUM_RCU_LVL_4,
+};
+int rcu_num_nodes __read_mostly = NUM_RCU_NODES; /* Total # rcu_nodes in use. */
 
 /*
  * The rcu_scheduler_active variable transitions from zero to one just
@@ -147,13 +155,6 @@ static void invoke_rcu_callbacks(struct rcu_state *rsp, struct rcu_data *rdp);
 unsigned long rcutorture_testseq;
 unsigned long rcutorture_vernum;
 
-/* State information for rcu_barrier() and friends. */
-
-static DEFINE_PER_CPU(struct rcu_head, rcu_barrier_head) = {NULL};
-static atomic_t rcu_barrier_cpu_count;
-static DEFINE_MUTEX(rcu_barrier_mutex);
-static struct completion rcu_barrier_completion;
-
 /*
  * Return true if an RCU grace period is in progress.  The ACCESS_ONCE()s
  * permit this function to be invoked without holding the root rcu_node
@@ -358,7 +359,7 @@ static void rcu_idle_enter_common(struct rcu_dynticks *rdtp, long long oldval)
                struct task_struct *idle = idle_task(smp_processor_id());
 
                trace_rcu_dyntick("Error on entry: not idle task", oldval, 0);
-               ftrace_dump(DUMP_ALL);
+               ftrace_dump(DUMP_ORIG);
                WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s",
                          current->pid, current->comm,
                          idle->pid, idle->comm); /* must be idle task! */
@@ -468,7 +469,7 @@ static void rcu_idle_exit_common(struct rcu_dynticks *rdtp, long long oldval)
 
                trace_rcu_dyntick("Error on exit: not idle task",
                                  oldval, rdtp->dynticks_nesting);
-               ftrace_dump(DUMP_ALL);
+               ftrace_dump(DUMP_ORIG);
                WARN_ONCE(1, "Current pid: %d comm: %s / Idle pid: %d comm: %s",
                          current->pid, current->comm,
                          idle->pid, idle->comm); /* must be idle task! */
@@ -585,8 +586,6 @@ void rcu_nmi_exit(void)
        WARN_ON_ONCE(atomic_read(&rdtp->dynticks) & 0x1);
 }
 
-#ifdef CONFIG_PROVE_RCU
-
 /**
  * rcu_is_cpu_idle - see if RCU thinks that the current CPU is idle
  *
@@ -604,7 +603,7 @@ int rcu_is_cpu_idle(void)
 }
 EXPORT_SYMBOL(rcu_is_cpu_idle);
 
-#ifdef CONFIG_HOTPLUG_CPU
+#if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU)
 
 /*
  * Is the current CPU online?  Disable preemption to avoid false positives
@@ -645,9 +644,7 @@ bool rcu_lockdep_current_cpu_online(void)
 }
 EXPORT_SYMBOL_GPL(rcu_lockdep_current_cpu_online);
 
-#endif /* #ifdef CONFIG_HOTPLUG_CPU */
-
-#endif /* #ifdef CONFIG_PROVE_RCU */
+#endif /* #if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU) */
 
 /**
  * rcu_is_cpu_rrupt_from_idle - see if idle or immediately interrupted from idle
@@ -733,7 +730,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
        int cpu;
        long delta;
        unsigned long flags;
-       int ndetected;
+       int ndetected = 0;
        struct rcu_node *rnp = rcu_get_root(rsp);
 
        /* Only let one CPU complain about others per time interval. */
@@ -774,7 +771,7 @@ static void print_other_cpu_stall(struct rcu_state *rsp)
         */
        rnp = rcu_get_root(rsp);
        raw_spin_lock_irqsave(&rnp->lock, flags);
-       ndetected = rcu_print_task_stall(rnp);
+       ndetected += rcu_print_task_stall(rnp);
        raw_spin_unlock_irqrestore(&rnp->lock, flags);
 
        print_cpu_stall_info_end();
@@ -860,9 +857,10 @@ static int rcu_panic(struct notifier_block *this, unsigned long ev, void *ptr)
  */
 void rcu_cpu_stall_reset(void)
 {
-       rcu_sched_state.jiffies_stall = jiffies + ULONG_MAX / 2;
-       rcu_bh_state.jiffies_stall = jiffies + ULONG_MAX / 2;
-       rcu_preempt_stall_reset();
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp)
+               rsp->jiffies_stall = jiffies + ULONG_MAX / 2;
 }
 
 static struct notifier_block rcu_panic_block = {
@@ -894,8 +892,9 @@ static void __note_new_gpnum(struct rcu_state *rsp, struct rcu_node *rnp, struct
                if (rnp->qsmask & rdp->grpmask) {
                        rdp->qs_pending = 1;
                        rdp->passed_quiesce = 0;
-               } else
+               } else {
                        rdp->qs_pending = 0;
+               }
                zero_cpu_stall_ticks(rdp);
        }
 }
@@ -936,6 +935,18 @@ check_for_new_grace_period(struct rcu_state *rsp, struct rcu_data *rdp)
        return ret;
 }
 
+/*
+ * Initialize the specified rcu_data structure's callback list to empty.
+ */
+static void init_callback_list(struct rcu_data *rdp)
+{
+       int i;
+
+       rdp->nxtlist = NULL;
+       for (i = 0; i < RCU_NEXT_SIZE; i++)
+               rdp->nxttail[i] = &rdp->nxtlist;
+}
+
 /*
  * Advance this CPU's callbacks, but only if the current grace period
  * has ended.  This may be called only from the CPU to whom the rdp
@@ -1328,8 +1339,6 @@ static void
 rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
                          struct rcu_node *rnp, struct rcu_data *rdp)
 {
-       int i;
-
        /*
         * Orphan the callbacks.  First adjust the counts.  This is safe
         * because ->onofflock excludes _rcu_barrier()'s adoption of
@@ -1340,7 +1349,7 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
                rsp->qlen += rdp->qlen;
                rdp->n_cbs_orphaned += rdp->qlen;
                rdp->qlen_lazy = 0;
-               rdp->qlen = 0;
+               ACCESS_ONCE(rdp->qlen) = 0;
        }
 
        /*
@@ -1369,9 +1378,7 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
        }
 
        /* Finally, initialize the rcu_data structure's list to empty.  */
-       rdp->nxtlist = NULL;
-       for (i = 0; i < RCU_NEXT_SIZE; i++)
-               rdp->nxttail[i] = &rdp->nxtlist;
+       init_callback_list(rdp);
 }
 
 /*
@@ -1505,6 +1512,9 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
        if (need_report & RCU_OFL_TASKS_EXP_GP)
                rcu_report_exp_rnp(rsp, rnp, true);
+       WARN_ONCE(rdp->qlen != 0 || rdp->nxtlist != NULL,
+                 "rcu_cleanup_dead_cpu: Callbacks on offline CPU %d: qlen=%lu, nxtlist=%p\n",
+                 cpu, rdp->qlen, rdp->nxtlist);
 }
 
 #else /* #ifdef CONFIG_HOTPLUG_CPU */
@@ -1592,7 +1602,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
        }
        smp_mb(); /* List handling before counting for rcu_barrier(). */
        rdp->qlen_lazy -= count_lazy;
-       rdp->qlen -= count;
+       ACCESS_ONCE(rdp->qlen) -= count;
        rdp->n_cbs_invoked += count;
 
        /* Reinstate batch limit if we have worked down the excess. */
@@ -1605,6 +1615,7 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
                rdp->n_force_qs_snap = rsp->n_force_qs;
        } else if (rdp->qlen < rdp->qlen_last_fqs_check - qhimark)
                rdp->qlen_last_fqs_check = rdp->qlen;
+       WARN_ON_ONCE((rdp->nxtlist == NULL) != (rdp->qlen == 0));
 
        local_irq_restore(flags);
 
@@ -1745,8 +1756,6 @@ static void force_quiescent_state(struct rcu_state *rsp, int relaxed)
                break; /* grace period idle or initializing, ignore. */
 
        case RCU_SAVE_DYNTICK:
-               if (RCU_SIGNAL_INIT != RCU_SAVE_DYNTICK)
-                       break; /* So gcc recognizes the dead code. */
 
                raw_spin_unlock(&rnp->lock);  /* irqs remain disabled */
 
@@ -1788,9 +1797,10 @@ unlock_fqs_ret:
  * whom the rdp belongs.
  */
 static void
-__rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp)
+__rcu_process_callbacks(struct rcu_state *rsp)
 {
        unsigned long flags;
+       struct rcu_data *rdp = __this_cpu_ptr(rsp->rda);
 
        WARN_ON_ONCE(rdp->beenonline == 0);
 
@@ -1826,11 +1836,11 @@ __rcu_process_callbacks(struct rcu_state *rsp, struct rcu_data *rdp)
  */
 static void rcu_process_callbacks(struct softirq_action *unused)
 {
+       struct rcu_state *rsp;
+
        trace_rcu_utilization("Start RCU core");
-       __rcu_process_callbacks(&rcu_sched_state,
-                               &__get_cpu_var(rcu_sched_data));
-       __rcu_process_callbacks(&rcu_bh_state, &__get_cpu_var(rcu_bh_data));
-       rcu_preempt_process_callbacks();
+       for_each_rcu_flavor(rsp)
+               __rcu_process_callbacks(rsp);
        trace_rcu_utilization("End RCU core");
 }
 
@@ -1857,6 +1867,56 @@ static void invoke_rcu_core(void)
        raise_softirq(RCU_SOFTIRQ);
 }
 
+/*
+ * Handle any core-RCU processing required by a call_rcu() invocation.
+ */
+static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp,
+                           struct rcu_head *head, unsigned long flags)
+{
+       /*
+        * If called from an extended quiescent state, invoke the RCU
+        * core in order to force a re-evaluation of RCU's idleness.
+        */
+       if (rcu_is_cpu_idle() && cpu_online(smp_processor_id()))
+               invoke_rcu_core();
+
+       /* If interrupts were disabled or CPU offline, don't invoke RCU core. */
+       if (irqs_disabled_flags(flags) || cpu_is_offline(smp_processor_id()))
+               return;
+
+       /*
+        * Force the grace period if too many callbacks or too long waiting.
+        * Enforce hysteresis, and don't invoke force_quiescent_state()
+        * if some other CPU has recently done so.  Also, don't bother
+        * invoking force_quiescent_state() if the newly enqueued callback
+        * is the only one waiting for a grace period to complete.
+        */
+       if (unlikely(rdp->qlen > rdp->qlen_last_fqs_check + qhimark)) {
+
+               /* Are we ignoring a completed grace period? */
+               rcu_process_gp_end(rsp, rdp);
+               check_for_new_grace_period(rsp, rdp);
+
+               /* Start a new grace period if one not already started. */
+               if (!rcu_gp_in_progress(rsp)) {
+                       unsigned long nestflag;
+                       struct rcu_node *rnp_root = rcu_get_root(rsp);
+
+                       raw_spin_lock_irqsave(&rnp_root->lock, nestflag);
+                       rcu_start_gp(rsp, nestflag);  /* rlses rnp_root->lock */
+               } else {
+                       /* Give the grace period a kick. */
+                       rdp->blimit = LONG_MAX;
+                       if (rsp->n_force_qs == rdp->n_force_qs_snap &&
+                           *rdp->nxttail[RCU_DONE_TAIL] != head)
+                               force_quiescent_state(rsp, 0);
+                       rdp->n_force_qs_snap = rsp->n_force_qs;
+                       rdp->qlen_last_fqs_check = rdp->qlen;
+               }
+       } else if (ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs), jiffies))
+               force_quiescent_state(rsp, 1);
+}
+
 static void
 __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
           struct rcu_state *rsp, bool lazy)
@@ -1881,7 +1941,7 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
        rdp = this_cpu_ptr(rsp->rda);
 
        /* Add the callback to our list. */
-       rdp->qlen++;
+       ACCESS_ONCE(rdp->qlen)++;
        if (lazy)
                rdp->qlen_lazy++;
        else
@@ -1896,43 +1956,8 @@ __call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu),
        else
                trace_rcu_callback(rsp->name, head, rdp->qlen_lazy, rdp->qlen);
 
-       /* If interrupts were disabled, don't dive into RCU core. */
-       if (irqs_disabled_flags(flags)) {
-               local_irq_restore(flags);
-               return;
-       }
-
-       /*
-        * Force the grace period if too many callbacks or too long waiting.
-        * Enforce hysteresis, and don't invoke force_quiescent_state()
-        * if some other CPU has recently done so.  Also, don't bother
-        * invoking force_quiescent_state() if the newly enqueued callback
-        * is the only one waiting for a grace period to complete.
-        */
-       if (unlikely(rdp->qlen > rdp->qlen_last_fqs_check + qhimark)) {
-
-               /* Are we ignoring a completed grace period? */
-               rcu_process_gp_end(rsp, rdp);
-               check_for_new_grace_period(rsp, rdp);
-
-               /* Start a new grace period if one not already started. */
-               if (!rcu_gp_in_progress(rsp)) {
-                       unsigned long nestflag;
-                       struct rcu_node *rnp_root = rcu_get_root(rsp);
-
-                       raw_spin_lock_irqsave(&rnp_root->lock, nestflag);
-                       rcu_start_gp(rsp, nestflag);  /* rlses rnp_root->lock */
-               } else {
-                       /* Give the grace period a kick. */
-                       rdp->blimit = LONG_MAX;
-                       if (rsp->n_force_qs == rdp->n_force_qs_snap &&
-                           *rdp->nxttail[RCU_DONE_TAIL] != head)
-                               force_quiescent_state(rsp, 0);
-                       rdp->n_force_qs_snap = rsp->n_force_qs;
-                       rdp->qlen_last_fqs_check = rdp->qlen;
-               }
-       } else if (ULONG_CMP_LT(ACCESS_ONCE(rsp->jiffies_force_qs), jiffies))
-               force_quiescent_state(rsp, 1);
+       /* Go handle any RCU core processing required. */
+       __call_rcu_core(rsp, rdp, head, flags);
        local_irq_restore(flags);
 }
 
@@ -1962,28 +1987,16 @@ EXPORT_SYMBOL_GPL(call_rcu_bh);
  * occasionally incorrectly indicate that there are multiple CPUs online
  * when there was in fact only one the whole time, as this just adds
  * some overhead: RCU still operates correctly.
- *
- * Of course, sampling num_online_cpus() with preemption enabled can
- * give erroneous results if there are concurrent CPU-hotplug operations.
- * For example, given a demonic sequence of preemptions in num_online_cpus()
- * and CPU-hotplug operations, there could be two or more CPUs online at
- * all times, but num_online_cpus() might well return one (or even zero).
- *
- * However, all such demonic sequences require at least one CPU-offline
- * operation.  Furthermore, rcu_blocking_is_gp() giving the wrong answer
- * is only a problem if there is an RCU read-side critical section executing
- * throughout.  But RCU-sched and RCU-bh read-side critical sections
- * disable either preemption or bh, which prevents a CPU from going offline.
- * Therefore, the only way that rcu_blocking_is_gp() can incorrectly return
- * that there is only one CPU when in fact there was more than one throughout
- * is when there were no RCU readers in the system.  If there are no
- * RCU readers, the grace period by definition can be of zero length,
- * regardless of the number of online CPUs.
  */
 static inline int rcu_blocking_is_gp(void)
 {
+       int ret;
+
        might_sleep();  /* Check for RCU read-side critical section. */
-       return num_online_cpus() <= 1;
+       preempt_disable();
+       ret = num_online_cpus() <= 1;
+       preempt_enable();
+       return ret;
 }
 
 /**
@@ -2118,9 +2131,9 @@ void synchronize_sched_expedited(void)
                put_online_cpus();
 
                /* No joy, try again later.  Or just synchronize_sched(). */
-               if (trycount++ < 10)
+               if (trycount++ < 10) {
                        udelay(trycount * num_online_cpus());
-               else {
+               else {
                        synchronize_sched();
                        return;
                }
@@ -2241,9 +2254,12 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
  */
 static int rcu_pending(int cpu)
 {
-       return __rcu_pending(&rcu_sched_state, &per_cpu(rcu_sched_data, cpu)) ||
-              __rcu_pending(&rcu_bh_state, &per_cpu(rcu_bh_data, cpu)) ||
-              rcu_preempt_pending(cpu);
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp)
+               if (__rcu_pending(rsp, per_cpu_ptr(rsp->rda, cpu)))
+                       return 1;
+       return 0;
 }
 
 /*
@@ -2253,20 +2269,41 @@ static int rcu_pending(int cpu)
  */
 static int rcu_cpu_has_callbacks(int cpu)
 {
+       struct rcu_state *rsp;
+
        /* RCU callbacks either ready or pending? */
-       return per_cpu(rcu_sched_data, cpu).nxtlist ||
-              per_cpu(rcu_bh_data, cpu).nxtlist ||
-              rcu_preempt_cpu_has_callbacks(cpu);
+       for_each_rcu_flavor(rsp)
+               if (per_cpu_ptr(rsp->rda, cpu)->nxtlist)
+                       return 1;
+       return 0;
+}
+
+/*
+ * Helper function for _rcu_barrier() tracing.  If tracing is disabled,
+ * the compiler is expected to optimize this away.
+ */
+static void _rcu_barrier_trace(struct rcu_state *rsp, char *s,
+                              int cpu, unsigned long done)
+{
+       trace_rcu_barrier(rsp->name, s, cpu,
+                         atomic_read(&rsp->barrier_cpu_count), done);
 }
 
 /*
  * RCU callback function for _rcu_barrier().  If we are last, wake
  * up the task executing _rcu_barrier().
  */
-static void rcu_barrier_callback(struct rcu_head *notused)
+static void rcu_barrier_callback(struct rcu_head *rhp)
 {
-       if (atomic_dec_and_test(&rcu_barrier_cpu_count))
-               complete(&rcu_barrier_completion);
+       struct rcu_data *rdp = container_of(rhp, struct rcu_data, barrier_head);
+       struct rcu_state *rsp = rdp->rsp;
+
+       if (atomic_dec_and_test(&rsp->barrier_cpu_count)) {
+               _rcu_barrier_trace(rsp, "LastCB", -1, rsp->n_barrier_done);
+               complete(&rsp->barrier_completion);
+       } else {
+               _rcu_barrier_trace(rsp, "CB", -1, rsp->n_barrier_done);
+       }
 }
 
 /*
@@ -2274,35 +2311,63 @@ static void rcu_barrier_callback(struct rcu_head *notused)
  */
 static void rcu_barrier_func(void *type)
 {
-       int cpu = smp_processor_id();
-       struct rcu_head *head = &per_cpu(rcu_barrier_head, cpu);
-       void (*call_rcu_func)(struct rcu_head *head,
-                             void (*func)(struct rcu_head *head));
+       struct rcu_state *rsp = type;
+       struct rcu_data *rdp = __this_cpu_ptr(rsp->rda);
 
-       atomic_inc(&rcu_barrier_cpu_count);
-       call_rcu_func = type;
-       call_rcu_func(head, rcu_barrier_callback);
+       _rcu_barrier_trace(rsp, "IRQ", -1, rsp->n_barrier_done);
+       atomic_inc(&rsp->barrier_cpu_count);
+       rsp->call(&rdp->barrier_head, rcu_barrier_callback);
 }
 
 /*
  * Orchestrate the specified type of RCU barrier, waiting for all
  * RCU callbacks of the specified type to complete.
  */
-static void _rcu_barrier(struct rcu_state *rsp,
-                        void (*call_rcu_func)(struct rcu_head *head,
-                                              void (*func)(struct rcu_head *head)))
+static void _rcu_barrier(struct rcu_state *rsp)
 {
        int cpu;
        unsigned long flags;
        struct rcu_data *rdp;
-       struct rcu_head rh;
+       struct rcu_data rd;
+       unsigned long snap = ACCESS_ONCE(rsp->n_barrier_done);
+       unsigned long snap_done;
 
-       init_rcu_head_on_stack(&rh);
+       init_rcu_head_on_stack(&rd.barrier_head);
+       _rcu_barrier_trace(rsp, "Begin", -1, snap);
 
        /* Take mutex to serialize concurrent rcu_barrier() requests. */
-       mutex_lock(&rcu_barrier_mutex);
+       mutex_lock(&rsp->barrier_mutex);
+
+       /*
+        * Ensure that all prior references, including to ->n_barrier_done,
+        * are ordered before the _rcu_barrier() machinery.
+        */
+       smp_mb();  /* See above block comment. */
+
+       /*
+        * Recheck ->n_barrier_done to see if others did our work for us.
+        * This means checking ->n_barrier_done for an even-to-odd-to-even
+        * transition.  The "if" expression below therefore rounds the old
+        * value up to the next even number and adds two before comparing.
+        */
+       snap_done = ACCESS_ONCE(rsp->n_barrier_done);
+       _rcu_barrier_trace(rsp, "Check", -1, snap_done);
+       if (ULONG_CMP_GE(snap_done, ((snap + 1) & ~0x1) + 2)) {
+               _rcu_barrier_trace(rsp, "EarlyExit", -1, snap_done);
+               smp_mb(); /* caller's subsequent code after above check. */
+               mutex_unlock(&rsp->barrier_mutex);
+               return;
+       }
 
-       smp_mb();  /* Prevent any prior operations from leaking in. */
+       /*
+        * Increment ->n_barrier_done to avoid duplicate work.  Use
+        * ACCESS_ONCE() to prevent the compiler from speculating
+        * the increment to precede the early-exit check.
+        */
+       ACCESS_ONCE(rsp->n_barrier_done)++;
+       WARN_ON_ONCE((rsp->n_barrier_done & 0x1) != 1);
+       _rcu_barrier_trace(rsp, "Inc1", -1, rsp->n_barrier_done);
+       smp_mb(); /* Order ->n_barrier_done increment with below mechanism. */
 
        /*
         * Initialize the count to one rather than to zero in order to
@@ -2321,8 +2386,8 @@ static void _rcu_barrier(struct rcu_state *rsp,
         * 6.   Both rcu_barrier_callback() callbacks are invoked, awakening
         *      us -- but before CPU 1's orphaned callbacks are invoked!!!
         */
-       init_completion(&rcu_barrier_completion);
-       atomic_set(&rcu_barrier_cpu_count, 1);
+       init_completion(&rsp->barrier_completion);
+       atomic_set(&rsp->barrier_cpu_count, 1);
        raw_spin_lock_irqsave(&rsp->onofflock, flags);
        rsp->rcu_barrier_in_progress = current;
        raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
@@ -2338,14 +2403,19 @@ static void _rcu_barrier(struct rcu_state *rsp,
                preempt_disable();
                rdp = per_cpu_ptr(rsp->rda, cpu);
                if (cpu_is_offline(cpu)) {
+                       _rcu_barrier_trace(rsp, "Offline", cpu,
+                                          rsp->n_barrier_done);
                        preempt_enable();
                        while (cpu_is_offline(cpu) && ACCESS_ONCE(rdp->qlen))
                                schedule_timeout_interruptible(1);
                } else if (ACCESS_ONCE(rdp->qlen)) {
-                       smp_call_function_single(cpu, rcu_barrier_func,
-                                                (void *)call_rcu_func, 1);
+                       _rcu_barrier_trace(rsp, "OnlineQ", cpu,
+                                          rsp->n_barrier_done);
+                       smp_call_function_single(cpu, rcu_barrier_func, rsp, 1);
                        preempt_enable();
                } else {
+                       _rcu_barrier_trace(rsp, "OnlineNQ", cpu,
+                                          rsp->n_barrier_done);
                        preempt_enable();
                }
        }
@@ -2362,24 +2432,32 @@ static void _rcu_barrier(struct rcu_state *rsp,
        rcu_adopt_orphan_cbs(rsp);
        rsp->rcu_barrier_in_progress = NULL;
        raw_spin_unlock_irqrestore(&rsp->onofflock, flags);
-       atomic_inc(&rcu_barrier_cpu_count);
+       atomic_inc(&rsp->barrier_cpu_count);
        smp_mb__after_atomic_inc(); /* Ensure atomic_inc() before callback. */
-       call_rcu_func(&rh, rcu_barrier_callback);
+       rd.rsp = rsp;
+       rsp->call(&rd.barrier_head, rcu_barrier_callback);
 
        /*
         * Now that we have an rcu_barrier_callback() callback on each
         * CPU, and thus each counted, remove the initial count.
         */
-       if (atomic_dec_and_test(&rcu_barrier_cpu_count))
-               complete(&rcu_barrier_completion);
+       if (atomic_dec_and_test(&rsp->barrier_cpu_count))
+               complete(&rsp->barrier_completion);
+
+       /* Increment ->n_barrier_done to prevent duplicate work. */
+       smp_mb(); /* Keep increment after above mechanism. */
+       ACCESS_ONCE(rsp->n_barrier_done)++;
+       WARN_ON_ONCE((rsp->n_barrier_done & 0x1) != 0);
+       _rcu_barrier_trace(rsp, "Inc2", -1, rsp->n_barrier_done);
+       smp_mb(); /* Keep increment before caller's subsequent code. */
 
        /* Wait for all rcu_barrier_callback() callbacks to be invoked. */
-       wait_for_completion(&rcu_barrier_completion);
+       wait_for_completion(&rsp->barrier_completion);
 
        /* Other rcu_barrier() invocations can now safely proceed. */
-       mutex_unlock(&rcu_barrier_mutex);
+       mutex_unlock(&rsp->barrier_mutex);
 
-       destroy_rcu_head_on_stack(&rh);
+       destroy_rcu_head_on_stack(&rd.barrier_head);
 }
 
 /**
@@ -2387,7 +2465,7 @@ static void _rcu_barrier(struct rcu_state *rsp,
  */
 void rcu_barrier_bh(void)
 {
-       _rcu_barrier(&rcu_bh_state, call_rcu_bh);
+       _rcu_barrier(&rcu_bh_state);
 }
 EXPORT_SYMBOL_GPL(rcu_barrier_bh);
 
@@ -2396,7 +2474,7 @@ EXPORT_SYMBOL_GPL(rcu_barrier_bh);
  */
 void rcu_barrier_sched(void)
 {
-       _rcu_barrier(&rcu_sched_state, call_rcu_sched);
+       _rcu_barrier(&rcu_sched_state);
 }
 EXPORT_SYMBOL_GPL(rcu_barrier_sched);
 
@@ -2407,18 +2485,15 @@ static void __init
 rcu_boot_init_percpu_data(int cpu, struct rcu_state *rsp)
 {
        unsigned long flags;
-       int i;
        struct rcu_data *rdp = per_cpu_ptr(rsp->rda, cpu);
        struct rcu_node *rnp = rcu_get_root(rsp);
 
        /* Set up local state, ensuring consistent view of global state. */
        raw_spin_lock_irqsave(&rnp->lock, flags);
        rdp->grpmask = 1UL << (cpu - rdp->mynode->grplo);
-       rdp->nxtlist = NULL;
-       for (i = 0; i < RCU_NEXT_SIZE; i++)
-               rdp->nxttail[i] = &rdp->nxtlist;
+       init_callback_list(rdp);
        rdp->qlen_lazy = 0;
-       rdp->qlen = 0;
+       ACCESS_ONCE(rdp->qlen) = 0;
        rdp->dynticks = &per_cpu(rcu_dynticks, cpu);
        WARN_ON_ONCE(rdp->dynticks->dynticks_nesting != DYNTICK_TASK_EXIT_IDLE);
        WARN_ON_ONCE(atomic_read(&rdp->dynticks->dynticks) != 1);
@@ -2492,9 +2567,11 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp, int preemptible)
 
 static void __cpuinit rcu_prepare_cpu(int cpu)
 {
-       rcu_init_percpu_data(cpu, &rcu_sched_state, 0);
-       rcu_init_percpu_data(cpu, &rcu_bh_state, 0);
-       rcu_preempt_init_percpu_data(cpu);
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp)
+               rcu_init_percpu_data(cpu, rsp,
+                                    strcmp(rsp->name, "rcu_preempt") == 0);
 }
 
 /*
@@ -2506,6 +2583,7 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
        long cpu = (long)hcpu;
        struct rcu_data *rdp = per_cpu_ptr(rcu_state->rda, cpu);
        struct rcu_node *rnp = rdp->mynode;
+       struct rcu_state *rsp;
 
        trace_rcu_utilization("Start CPU hotplug");
        switch (action) {
@@ -2530,18 +2608,16 @@ static int __cpuinit rcu_cpu_notify(struct notifier_block *self,
                 * touch any data without introducing corruption. We send the
                 * dying CPU's callbacks to an arbitrarily chosen online CPU.
                 */
-               rcu_cleanup_dying_cpu(&rcu_bh_state);
-               rcu_cleanup_dying_cpu(&rcu_sched_state);
-               rcu_preempt_cleanup_dying_cpu();
+               for_each_rcu_flavor(rsp)
+                       rcu_cleanup_dying_cpu(rsp);
                rcu_cleanup_after_idle(cpu);
                break;
        case CPU_DEAD:
        case CPU_DEAD_FROZEN:
        case CPU_UP_CANCELED:
        case CPU_UP_CANCELED_FROZEN:
-               rcu_cleanup_dead_cpu(cpu, &rcu_bh_state);
-               rcu_cleanup_dead_cpu(cpu, &rcu_sched_state);
-               rcu_preempt_cleanup_dead_cpu(cpu);
+               for_each_rcu_flavor(rsp)
+                       rcu_cleanup_dead_cpu(cpu, rsp);
                break;
        default:
                break;
@@ -2574,9 +2650,9 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp)
 {
        int i;
 
-       for (i = NUM_RCU_LVLS - 1; i > 0; i--)
+       for (i = rcu_num_lvls - 1; i > 0; i--)
                rsp->levelspread[i] = CONFIG_RCU_FANOUT;
-       rsp->levelspread[0] = CONFIG_RCU_FANOUT_LEAF;
+       rsp->levelspread[0] = rcu_fanout_leaf;
 }
 #else /* #ifdef CONFIG_RCU_FANOUT_EXACT */
 static void __init rcu_init_levelspread(struct rcu_state *rsp)
@@ -2586,7 +2662,7 @@ static void __init rcu_init_levelspread(struct rcu_state *rsp)
        int i;
 
        cprv = NR_CPUS;
-       for (i = NUM_RCU_LVLS - 1; i >= 0; i--) {
+       for (i = rcu_num_lvls - 1; i >= 0; i--) {
                ccur = rsp->levelcnt[i];
                rsp->levelspread[i] = (cprv + ccur - 1) / ccur;
                cprv = ccur;
@@ -2613,13 +2689,15 @@ static void __init rcu_init_one(struct rcu_state *rsp,
 
        /* Initialize the level-tracking arrays. */
 
-       for (i = 1; i < NUM_RCU_LVLS; i++)
+       for (i = 0; i < rcu_num_lvls; i++)
+               rsp->levelcnt[i] = num_rcu_lvl[i];
+       for (i = 1; i < rcu_num_lvls; i++)
                rsp->level[i] = rsp->level[i - 1] + rsp->levelcnt[i - 1];
        rcu_init_levelspread(rsp);
 
        /* Initialize the elements themselves, starting from the leaves. */
 
-       for (i = NUM_RCU_LVLS - 1; i >= 0; i--) {
+       for (i = rcu_num_lvls - 1; i >= 0; i--) {
                cpustride *= rsp->levelspread[i];
                rnp = rsp->level[i];
                for (j = 0; j < rsp->levelcnt[i]; j++, rnp++) {
@@ -2649,13 +2727,74 @@ static void __init rcu_init_one(struct rcu_state *rsp,
        }
 
        rsp->rda = rda;
-       rnp = rsp->level[NUM_RCU_LVLS - 1];
+       rnp = rsp->level[rcu_num_lvls - 1];
        for_each_possible_cpu(i) {
                while (i > rnp->grphi)
                        rnp++;
                per_cpu_ptr(rsp->rda, i)->mynode = rnp;
                rcu_boot_init_percpu_data(i, rsp);
        }
+       list_add(&rsp->flavors, &rcu_struct_flavors);
+}
+
+/*
+ * Compute the rcu_node tree geometry from kernel parameters.  This cannot
+ * replace the definitions in rcutree.h because those are needed to size
+ * the ->node array in the rcu_state structure.
+ */
+static void __init rcu_init_geometry(void)
+{
+       int i;
+       int j;
+       int n = nr_cpu_ids;
+       int rcu_capacity[MAX_RCU_LVLS + 1];
+
+       /* If the compile-time values are accurate, just leave. */
+       if (rcu_fanout_leaf == CONFIG_RCU_FANOUT_LEAF)
+               return;
+
+       /*
+        * Compute number of nodes that can be handled an rcu_node tree
+        * with the given number of levels.  Setting rcu_capacity[0] makes
+        * some of the arithmetic easier.
+        */
+       rcu_capacity[0] = 1;
+       rcu_capacity[1] = rcu_fanout_leaf;
+       for (i = 2; i <= MAX_RCU_LVLS; i++)
+               rcu_capacity[i] = rcu_capacity[i - 1] * CONFIG_RCU_FANOUT;
+
+       /*
+        * The boot-time rcu_fanout_leaf parameter is only permitted
+        * to increase the leaf-level fanout, not decrease it.  Of course,
+        * the leaf-level fanout cannot exceed the number of bits in
+        * the rcu_node masks.  Finally, the tree must be able to accommodate
+        * the configured number of CPUs.  Complain and fall back to the
+        * compile-time values if these limits are exceeded.
+        */
+       if (rcu_fanout_leaf < CONFIG_RCU_FANOUT_LEAF ||
+           rcu_fanout_leaf > sizeof(unsigned long) * 8 ||
+           n > rcu_capacity[MAX_RCU_LVLS]) {
+               WARN_ON(1);
+               return;
+       }
+
+       /* Calculate the number of rcu_nodes at each level of the tree. */
+       for (i = 1; i <= MAX_RCU_LVLS; i++)
+               if (n <= rcu_capacity[i]) {
+                       for (j = 0; j <= i; j++)
+                               num_rcu_lvl[j] =
+                                       DIV_ROUND_UP(n, rcu_capacity[i - j]);
+                       rcu_num_lvls = i;
+                       for (j = i + 1; j <= MAX_RCU_LVLS; j++)
+                               num_rcu_lvl[j] = 0;
+                       break;
+               }
+
+       /* Calculate the total number of rcu_node structures. */
+       rcu_num_nodes = 0;
+       for (i = 0; i <= MAX_RCU_LVLS; i++)
+               rcu_num_nodes += num_rcu_lvl[i];
+       rcu_num_nodes -= n;
 }
 
 void __init rcu_init(void)
@@ -2663,6 +2802,7 @@ void __init rcu_init(void)
        int cpu;
 
        rcu_bootup_announce();
+       rcu_init_geometry();
        rcu_init_one(&rcu_sched_state, &rcu_sched_data);
        rcu_init_one(&rcu_bh_state, &rcu_bh_data);
        __rcu_init_preempt();
index 19b61ac1079f825702a7f17ae7d8dec88756c141..4d29169f212468bdc6f8dd17311ecf8bdd6850a8 100644 (file)
 #define RCU_FANOUT_4         (RCU_FANOUT_3 * CONFIG_RCU_FANOUT)
 
 #if NR_CPUS <= RCU_FANOUT_1
-#  define NUM_RCU_LVLS       1
+#  define RCU_NUM_LVLS       1
 #  define NUM_RCU_LVL_0              1
 #  define NUM_RCU_LVL_1              (NR_CPUS)
 #  define NUM_RCU_LVL_2              0
 #  define NUM_RCU_LVL_3              0
 #  define NUM_RCU_LVL_4              0
 #elif NR_CPUS <= RCU_FANOUT_2
-#  define NUM_RCU_LVLS       2
+#  define RCU_NUM_LVLS       2
 #  define NUM_RCU_LVL_0              1
 #  define NUM_RCU_LVL_1              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
 #  define NUM_RCU_LVL_2              (NR_CPUS)
 #  define NUM_RCU_LVL_3              0
 #  define NUM_RCU_LVL_4              0
 #elif NR_CPUS <= RCU_FANOUT_3
-#  define NUM_RCU_LVLS       3
+#  define RCU_NUM_LVLS       3
 #  define NUM_RCU_LVL_0              1
 #  define NUM_RCU_LVL_1              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
 #  define NUM_RCU_LVL_2              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
 #  define NUM_RCU_LVL_3              (NR_CPUS)
 #  define NUM_RCU_LVL_4              0
 #elif NR_CPUS <= RCU_FANOUT_4
-#  define NUM_RCU_LVLS       4
+#  define RCU_NUM_LVLS       4
 #  define NUM_RCU_LVL_0              1
 #  define NUM_RCU_LVL_1              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_3)
 #  define NUM_RCU_LVL_2              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
@@ -76,6 +76,9 @@
 #define RCU_SUM (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3 + NUM_RCU_LVL_4)
 #define NUM_RCU_NODES (RCU_SUM - NR_CPUS)
 
+extern int rcu_num_lvls;
+extern int rcu_num_nodes;
+
 /*
  * Dynticks per-CPU state.
  */
@@ -97,6 +100,7 @@ struct rcu_dynticks {
                                    /* # times non-lazy CBs posted to CPU. */
        unsigned long nonlazy_posted_snap;
                                    /* idle-period nonlazy_posted snapshot. */
+       int tick_nohz_enabled_snap; /* Previously seen value from sysfs. */
 #endif /* #ifdef CONFIG_RCU_FAST_NO_HZ */
 };
 
@@ -206,7 +210,7 @@ struct rcu_node {
  */
 #define rcu_for_each_node_breadth_first(rsp, rnp) \
        for ((rnp) = &(rsp)->node[0]; \
-            (rnp) < &(rsp)->node[NUM_RCU_NODES]; (rnp)++)
+            (rnp) < &(rsp)->node[rcu_num_nodes]; (rnp)++)
 
 /*
  * Do a breadth-first scan of the non-leaf rcu_node structures for the
@@ -215,7 +219,7 @@ struct rcu_node {
  */
 #define rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) \
        for ((rnp) = &(rsp)->node[0]; \
-            (rnp) < (rsp)->level[NUM_RCU_LVLS - 1]; (rnp)++)
+            (rnp) < (rsp)->level[rcu_num_lvls - 1]; (rnp)++)
 
 /*
  * Scan the leaves of the rcu_node hierarchy for the specified rcu_state
@@ -224,8 +228,8 @@ struct rcu_node {
  * It is still a leaf node, even if it is also the root node.
  */
 #define rcu_for_each_leaf_node(rsp, rnp) \
-       for ((rnp) = (rsp)->level[NUM_RCU_LVLS - 1]; \
-            (rnp) < &(rsp)->node[NUM_RCU_NODES]; (rnp)++)
+       for ((rnp) = (rsp)->level[rcu_num_lvls - 1]; \
+            (rnp) < &(rsp)->node[rcu_num_nodes]; (rnp)++)
 
 /* Index values for nxttail array in struct rcu_data. */
 #define RCU_DONE_TAIL          0       /* Also RCU_WAIT head. */
@@ -311,6 +315,9 @@ struct rcu_data {
        unsigned long n_rp_need_fqs;
        unsigned long n_rp_need_nothing;
 
+       /* 6) _rcu_barrier() callback. */
+       struct rcu_head barrier_head;
+
        int cpu;
        struct rcu_state *rsp;
 };
@@ -357,10 +364,12 @@ do {                                                                      \
  */
 struct rcu_state {
        struct rcu_node node[NUM_RCU_NODES];    /* Hierarchy. */
-       struct rcu_node *level[NUM_RCU_LVLS];   /* Hierarchy levels. */
+       struct rcu_node *level[RCU_NUM_LVLS];   /* Hierarchy levels. */
        u32 levelcnt[MAX_RCU_LVLS + 1];         /* # nodes in each level. */
-       u8 levelspread[NUM_RCU_LVLS];           /* kids/node in each level. */
+       u8 levelspread[RCU_NUM_LVLS];           /* kids/node in each level. */
        struct rcu_data __percpu *rda;          /* pointer of percu rcu_data. */
+       void (*call)(struct rcu_head *head,     /* call_rcu() flavor. */
+                    void (*func)(struct rcu_head *head));
 
        /* The following fields are guarded by the root rcu_node's lock. */
 
@@ -392,6 +401,11 @@ struct rcu_state {
        struct task_struct *rcu_barrier_in_progress;
                                                /* Task doing rcu_barrier(), */
                                                /*  or NULL if no barrier. */
+       struct mutex barrier_mutex;             /* Guards barrier fields. */
+       atomic_t barrier_cpu_count;             /* # CPUs waiting on. */
+       struct completion barrier_completion;   /* Wake at barrier end. */
+       unsigned long n_barrier_done;           /* ++ at start and end of */
+                                               /*  _rcu_barrier(). */
        raw_spinlock_t fqslock;                 /* Only one task forcing */
                                                /*  quiescent states. */
        unsigned long jiffies_force_qs;         /* Time at which to invoke */
@@ -409,8 +423,13 @@ struct rcu_state {
        unsigned long gp_max;                   /* Maximum GP duration in */
                                                /*  jiffies. */
        char *name;                             /* Name of structure. */
+       struct list_head flavors;               /* List of RCU flavors. */
 };
 
+extern struct list_head rcu_struct_flavors;
+#define for_each_rcu_flavor(rsp) \
+       list_for_each_entry((rsp), &rcu_struct_flavors, flavors)
+
 /* Return values for rcu_preempt_offline_tasks(). */
 
 #define RCU_OFL_TASKS_NORM_GP  0x1             /* Tasks blocking normal */
@@ -453,25 +472,18 @@ static void rcu_stop_cpu_kthread(int cpu);
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 static void rcu_print_detail_task_stall(struct rcu_state *rsp);
 static int rcu_print_task_stall(struct rcu_node *rnp);
-static void rcu_preempt_stall_reset(void);
 static void rcu_preempt_check_blocked_tasks(struct rcu_node *rnp);
 #ifdef CONFIG_HOTPLUG_CPU
 static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
                                     struct rcu_node *rnp,
                                     struct rcu_data *rdp);
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
-static void rcu_preempt_cleanup_dead_cpu(int cpu);
 static void rcu_preempt_check_callbacks(int cpu);
-static void rcu_preempt_process_callbacks(void);
 void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *rcu));
 #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_TREE_PREEMPT_RCU)
 static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp,
                               bool wake);
 #endif /* #if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_TREE_PREEMPT_RCU) */
-static int rcu_preempt_pending(int cpu);
-static int rcu_preempt_cpu_has_callbacks(int cpu);
-static void __cpuinit rcu_preempt_init_percpu_data(int cpu);
-static void rcu_preempt_cleanup_dying_cpu(void);
 static void __init __rcu_init_preempt(void);
 static void rcu_initiate_boost(struct rcu_node *rnp, unsigned long flags);
 static void rcu_preempt_boost_start_gp(struct rcu_node *rnp);
index 3e4899459f3d9d7177ee67d41b8ea1121ddb9540..7f3244c0df014a7673831159ae1dbc25ceff55c8 100644 (file)
@@ -68,17 +68,21 @@ static void __init rcu_bootup_announce_oddness(void)
        printk(KERN_INFO "\tAdditional per-CPU info printed with stalls.\n");
 #endif
 #if NUM_RCU_LVL_4 != 0
-       printk(KERN_INFO "\tExperimental four-level hierarchy is enabled.\n");
+       printk(KERN_INFO "\tFour-level hierarchy is enabled.\n");
 #endif
+       if (rcu_fanout_leaf != CONFIG_RCU_FANOUT_LEAF)
+               printk(KERN_INFO "\tExperimental boot-time adjustment of leaf fanout to %d.\n", rcu_fanout_leaf);
+       if (nr_cpu_ids != NR_CPUS)
+               printk(KERN_INFO "\tRCU restricting CPUs from NR_CPUS=%d to nr_cpu_ids=%d.\n", NR_CPUS, nr_cpu_ids);
 }
 
 #ifdef CONFIG_TREE_PREEMPT_RCU
 
-struct rcu_state rcu_preempt_state = RCU_STATE_INITIALIZER(rcu_preempt);
+struct rcu_state rcu_preempt_state =
+       RCU_STATE_INITIALIZER(rcu_preempt, call_rcu);
 DEFINE_PER_CPU(struct rcu_data, rcu_preempt_data);
 static struct rcu_state *rcu_state = &rcu_preempt_state;
 
-static void rcu_read_unlock_special(struct task_struct *t);
 static int rcu_preempted_readers_exp(struct rcu_node *rnp);
 
 /*
@@ -232,18 +236,6 @@ static void rcu_preempt_note_context_switch(int cpu)
        local_irq_restore(flags);
 }
 
-/*
- * Tree-preemptible RCU implementation for rcu_read_lock().
- * Just increment ->rcu_read_lock_nesting, shared state will be updated
- * if we block.
- */
-void __rcu_read_lock(void)
-{
-       current->rcu_read_lock_nesting++;
-       barrier();  /* needed if we ever invoke rcu_read_lock in rcutree.c */
-}
-EXPORT_SYMBOL_GPL(__rcu_read_lock);
-
 /*
  * Check for preempted RCU readers blocking the current grace period
  * for the specified rcu_node structure.  If the caller needs a reliable
@@ -310,7 +302,7 @@ static struct list_head *rcu_next_node_entry(struct task_struct *t,
  * notify RCU core processing or task having blocked during the RCU
  * read-side critical section.
  */
-static noinline void rcu_read_unlock_special(struct task_struct *t)
+void rcu_read_unlock_special(struct task_struct *t)
 {
        int empty;
        int empty_exp;
@@ -398,8 +390,9 @@ static noinline void rcu_read_unlock_special(struct task_struct *t)
                                                         rnp->grphi,
                                                         !!rnp->gp_tasks);
                        rcu_report_unblock_qs_rnp(rnp, flags);
-               } else
+               } else {
                        raw_spin_unlock_irqrestore(&rnp->lock, flags);
+               }
 
 #ifdef CONFIG_RCU_BOOST
                /* Unboost if we were boosted. */
@@ -418,38 +411,6 @@ static noinline void rcu_read_unlock_special(struct task_struct *t)
        }
 }
 
-/*
- * Tree-preemptible RCU implementation for rcu_read_unlock().
- * Decrement ->rcu_read_lock_nesting.  If the result is zero (outermost
- * rcu_read_unlock()) and ->rcu_read_unlock_special is non-zero, then
- * invoke rcu_read_unlock_special() to clean up after a context switch
- * in an RCU read-side critical section and other special cases.
- */
-void __rcu_read_unlock(void)
-{
-       struct task_struct *t = current;
-
-       if (t->rcu_read_lock_nesting != 1)
-               --t->rcu_read_lock_nesting;
-       else {
-               barrier();  /* critical section before exit code. */
-               t->rcu_read_lock_nesting = INT_MIN;
-               barrier();  /* assign before ->rcu_read_unlock_special load */
-               if (unlikely(ACCESS_ONCE(t->rcu_read_unlock_special)))
-                       rcu_read_unlock_special(t);
-               barrier();  /* ->rcu_read_unlock_special load before assign */
-               t->rcu_read_lock_nesting = 0;
-       }
-#ifdef CONFIG_PROVE_LOCKING
-       {
-               int rrln = ACCESS_ONCE(t->rcu_read_lock_nesting);
-
-               WARN_ON_ONCE(rrln < 0 && rrln > INT_MIN / 2);
-       }
-#endif /* #ifdef CONFIG_PROVE_LOCKING */
-}
-EXPORT_SYMBOL_GPL(__rcu_read_unlock);
-
 #ifdef CONFIG_RCU_CPU_STALL_VERBOSE
 
 /*
@@ -539,16 +500,6 @@ static int rcu_print_task_stall(struct rcu_node *rnp)
        return ndetected;
 }
 
-/*
- * Suppress preemptible RCU's CPU stall warnings by pushing the
- * time of the next stall-warning message comfortably far into the
- * future.
- */
-static void rcu_preempt_stall_reset(void)
-{
-       rcu_preempt_state.jiffies_stall = jiffies + ULONG_MAX / 2;
-}
-
 /*
  * Check that the list of blocked tasks for the newly completed grace
  * period is in fact empty.  It is a serious bug to complete a grace
@@ -649,14 +600,6 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
 
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 
-/*
- * Do CPU-offline processing for preemptible RCU.
- */
-static void rcu_preempt_cleanup_dead_cpu(int cpu)
-{
-       rcu_cleanup_dead_cpu(cpu, &rcu_preempt_state);
-}
-
 /*
  * Check for a quiescent state from the current CPU.  When a task blocks,
  * the task is recorded in the corresponding CPU's rcu_node structure,
@@ -677,15 +620,6 @@ static void rcu_preempt_check_callbacks(int cpu)
                t->rcu_read_unlock_special |= RCU_READ_UNLOCK_NEED_QS;
 }
 
-/*
- * Process callbacks for preemptible RCU.
- */
-static void rcu_preempt_process_callbacks(void)
-{
-       __rcu_process_callbacks(&rcu_preempt_state,
-                               &__get_cpu_var(rcu_preempt_data));
-}
-
 #ifdef CONFIG_RCU_BOOST
 
 static void rcu_preempt_do_callbacks(void)
@@ -824,9 +758,9 @@ sync_rcu_preempt_exp_init(struct rcu_state *rsp, struct rcu_node *rnp)
        int must_wait = 0;
 
        raw_spin_lock_irqsave(&rnp->lock, flags);
-       if (list_empty(&rnp->blkd_tasks))
+       if (list_empty(&rnp->blkd_tasks)) {
                raw_spin_unlock_irqrestore(&rnp->lock, flags);
-       else {
+       else {
                rnp->exp_tasks = rnp->blkd_tasks.next;
                rcu_initiate_boost(rnp, flags);  /* releases rnp->lock */
                must_wait = 1;
@@ -870,9 +804,9 @@ void synchronize_rcu_expedited(void)
         * expedited grace period for us, just leave.
         */
        while (!mutex_trylock(&sync_rcu_preempt_exp_mutex)) {
-               if (trycount++ < 10)
+               if (trycount++ < 10) {
                        udelay(trycount * num_online_cpus());
-               else {
+               else {
                        synchronize_rcu();
                        return;
                }
@@ -917,50 +851,15 @@ mb_ret:
 }
 EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
 
-/*
- * Check to see if there is any immediate preemptible-RCU-related work
- * to be done.
- */
-static int rcu_preempt_pending(int cpu)
-{
-       return __rcu_pending(&rcu_preempt_state,
-                            &per_cpu(rcu_preempt_data, cpu));
-}
-
-/*
- * Does preemptible RCU have callbacks on this CPU?
- */
-static int rcu_preempt_cpu_has_callbacks(int cpu)
-{
-       return !!per_cpu(rcu_preempt_data, cpu).nxtlist;
-}
-
 /**
  * rcu_barrier - Wait until all in-flight call_rcu() callbacks complete.
  */
 void rcu_barrier(void)
 {
-       _rcu_barrier(&rcu_preempt_state, call_rcu);
+       _rcu_barrier(&rcu_preempt_state);
 }
 EXPORT_SYMBOL_GPL(rcu_barrier);
 
-/*
- * Initialize preemptible RCU's per-CPU data.
- */
-static void __cpuinit rcu_preempt_init_percpu_data(int cpu)
-{
-       rcu_init_percpu_data(cpu, &rcu_preempt_state, 1);
-}
-
-/*
- * Move preemptible RCU's callbacks from dying CPU to other online CPU
- * and record a quiescent state.
- */
-static void rcu_preempt_cleanup_dying_cpu(void)
-{
-       rcu_cleanup_dying_cpu(&rcu_preempt_state);
-}
-
 /*
  * Initialize preemptible RCU's state structures.
  */
@@ -1045,14 +944,6 @@ static int rcu_print_task_stall(struct rcu_node *rnp)
        return 0;
 }
 
-/*
- * Because preemptible RCU does not exist, there is no need to suppress
- * its CPU stall warnings.
- */
-static void rcu_preempt_stall_reset(void)
-{
-}
-
 /*
  * Because there is no preemptible RCU, there can be no readers blocked,
  * so there is no need to check for blocked tasks.  So check only for
@@ -1080,14 +971,6 @@ static int rcu_preempt_offline_tasks(struct rcu_state *rsp,
 
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 
-/*
- * Because preemptible RCU does not exist, it never needs CPU-offline
- * processing.
- */
-static void rcu_preempt_cleanup_dead_cpu(int cpu)
-{
-}
-
 /*
  * Because preemptible RCU does not exist, it never has any callbacks
  * to check.
@@ -1096,14 +979,6 @@ static void rcu_preempt_check_callbacks(int cpu)
 {
 }
 
-/*
- * Because preemptible RCU does not exist, it never has any callbacks
- * to process.
- */
-static void rcu_preempt_process_callbacks(void)
-{
-}
-
 /*
  * Queue an RCU callback for lazy invocation after a grace period.
  * This will likely be later named something like "call_rcu_lazy()",
@@ -1144,22 +1019,6 @@ static void rcu_report_exp_rnp(struct rcu_state *rsp, struct rcu_node *rnp,
 
 #endif /* #ifdef CONFIG_HOTPLUG_CPU */
 
-/*
- * Because preemptible RCU does not exist, it never has any work to do.
- */
-static int rcu_preempt_pending(int cpu)
-{
-       return 0;
-}
-
-/*
- * Because preemptible RCU does not exist, it never has callbacks
- */
-static int rcu_preempt_cpu_has_callbacks(int cpu)
-{
-       return 0;
-}
-
 /*
  * Because preemptible RCU does not exist, rcu_barrier() is just
  * another name for rcu_barrier_sched().
@@ -1170,21 +1029,6 @@ void rcu_barrier(void)
 }
 EXPORT_SYMBOL_GPL(rcu_barrier);
 
-/*
- * Because preemptible RCU does not exist, there is no per-CPU
- * data to initialize.
- */
-static void __cpuinit rcu_preempt_init_percpu_data(int cpu)
-{
-}
-
-/*
- * Because there is no preemptible RCU, there is no cleanup to do.
- */
-static void rcu_preempt_cleanup_dying_cpu(void)
-{
-}
-
 /*
  * Because preemptible RCU does not exist, it need not be initialized.
  */
@@ -1968,9 +1812,11 @@ static void rcu_idle_count_callbacks_posted(void)
  */
 #define RCU_IDLE_FLUSHES 5             /* Number of dyntick-idle tries. */
 #define RCU_IDLE_OPT_FLUSHES 3         /* Optional dyntick-idle tries. */
-#define RCU_IDLE_GP_DELAY 6            /* Roughly one grace period. */
+#define RCU_IDLE_GP_DELAY 4            /* Roughly one grace period. */
 #define RCU_IDLE_LAZY_GP_DELAY (6 * HZ)        /* Roughly six seconds. */
 
+extern int tick_nohz_enabled;
+
 /*
  * Does the specified flavor of RCU have non-lazy callbacks pending on
  * the specified CPU?  Both RCU flavor and CPU are specified by the
@@ -2047,10 +1893,13 @@ int rcu_needs_cpu(int cpu, unsigned long *delta_jiffies)
                return 1;
        }
        /* Set up for the possibility that RCU will post a timer. */
-       if (rcu_cpu_has_nonlazy_callbacks(cpu))
-               *delta_jiffies = RCU_IDLE_GP_DELAY;
-       else
-               *delta_jiffies = RCU_IDLE_LAZY_GP_DELAY;
+       if (rcu_cpu_has_nonlazy_callbacks(cpu)) {
+               *delta_jiffies = round_up(RCU_IDLE_GP_DELAY + jiffies,
+                                         RCU_IDLE_GP_DELAY) - jiffies;
+       } else {
+               *delta_jiffies = jiffies + RCU_IDLE_LAZY_GP_DELAY;
+               *delta_jiffies = round_jiffies(*delta_jiffies) - jiffies;
+       }
        return 0;
 }
 
@@ -2109,6 +1958,7 @@ static void rcu_cleanup_after_idle(int cpu)
 
        del_timer(&rdtp->idle_gp_timer);
        trace_rcu_prep_idle("Cleanup after idle");
+       rdtp->tick_nohz_enabled_snap = ACCESS_ONCE(tick_nohz_enabled);
 }
 
 /*
@@ -2134,6 +1984,18 @@ static void rcu_prepare_for_idle(int cpu)
 {
        struct timer_list *tp;
        struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
+       int tne;
+
+       /* Handle nohz enablement switches conservatively. */
+       tne = ACCESS_ONCE(tick_nohz_enabled);
+       if (tne != rdtp->tick_nohz_enabled_snap) {
+               if (rcu_cpu_has_callbacks(cpu))
+                       invoke_rcu_core(); /* force nohz to see update. */
+               rdtp->tick_nohz_enabled_snap = tne;
+               return;
+       }
+       if (!tne)
+               return;
 
        /*
         * If this is an idle re-entry, for example, due to use of
@@ -2187,10 +2049,11 @@ static void rcu_prepare_for_idle(int cpu)
                if (rcu_cpu_has_nonlazy_callbacks(cpu)) {
                        trace_rcu_prep_idle("Dyntick with callbacks");
                        rdtp->idle_gp_timer_expires =
-                                          jiffies + RCU_IDLE_GP_DELAY;
+                               round_up(jiffies + RCU_IDLE_GP_DELAY,
+                                        RCU_IDLE_GP_DELAY);
                } else {
                        rdtp->idle_gp_timer_expires =
-                                          jiffies + RCU_IDLE_LAZY_GP_DELAY;
+                               round_jiffies(jiffies + RCU_IDLE_LAZY_GP_DELAY);
                        trace_rcu_prep_idle("Dyntick with lazy callbacks");
                }
                tp = &rdtp->idle_gp_timer;
@@ -2231,8 +2094,9 @@ static void rcu_prepare_for_idle(int cpu)
        if (rcu_cpu_has_callbacks(cpu)) {
                trace_rcu_prep_idle("More callbacks");
                invoke_rcu_core();
-       } else
+       } else {
                trace_rcu_prep_idle("Callbacks drained");
+       }
 }
 
 /*
@@ -2269,6 +2133,7 @@ static void print_cpu_stall_fast_no_hz(char *cp, int cpu)
 
 static void print_cpu_stall_fast_no_hz(char *cp, int cpu)
 {
+       *cp = '\0';
 }
 
 #endif /* #else #ifdef CONFIG_RCU_FAST_NO_HZ */
index d4bc16ddd1d4aa09efb52cbee140f1f0b45afc36..abffb486e94ed7ea581b54861f253ca8567bddda 100644 (file)
 #define RCU_TREE_NONCORE
 #include "rcutree.h"
 
+static int show_rcubarrier(struct seq_file *m, void *unused)
+{
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp)
+               seq_printf(m, "%s: %c bcc: %d nbd: %lu\n",
+                          rsp->name, rsp->rcu_barrier_in_progress ? 'B' : '.',
+                          atomic_read(&rsp->barrier_cpu_count),
+                          rsp->n_barrier_done);
+       return 0;
+}
+
+static int rcubarrier_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, show_rcubarrier, NULL);
+}
+
+static const struct file_operations rcubarrier_fops = {
+       .owner = THIS_MODULE,
+       .open = rcubarrier_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
 #ifdef CONFIG_RCU_BOOST
 
 static char convert_kthread_status(unsigned int kthread_status)
@@ -95,24 +120,16 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
                   rdp->n_cbs_invoked, rdp->n_cbs_orphaned, rdp->n_cbs_adopted);
 }
 
-#define PRINT_RCU_DATA(name, func, m) \
-       do { \
-               int _p_r_d_i; \
-               \
-               for_each_possible_cpu(_p_r_d_i) \
-                       func(m, &per_cpu(name, _p_r_d_i)); \
-       } while (0)
-
 static int show_rcudata(struct seq_file *m, void *unused)
 {
-#ifdef CONFIG_TREE_PREEMPT_RCU
-       seq_puts(m, "rcu_preempt:\n");
-       PRINT_RCU_DATA(rcu_preempt_data, print_one_rcu_data, m);
-#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-       seq_puts(m, "rcu_sched:\n");
-       PRINT_RCU_DATA(rcu_sched_data, print_one_rcu_data, m);
-       seq_puts(m, "rcu_bh:\n");
-       PRINT_RCU_DATA(rcu_bh_data, print_one_rcu_data, m);
+       int cpu;
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp) {
+               seq_printf(m, "%s:\n", rsp->name);
+               for_each_possible_cpu(cpu)
+                       print_one_rcu_data(m, per_cpu_ptr(rsp->rda, cpu));
+       }
        return 0;
 }
 
@@ -166,6 +183,9 @@ static void print_one_rcu_data_csv(struct seq_file *m, struct rcu_data *rdp)
 
 static int show_rcudata_csv(struct seq_file *m, void *unused)
 {
+       int cpu;
+       struct rcu_state *rsp;
+
        seq_puts(m, "\"CPU\",\"Online?\",\"c\",\"g\",\"pq\",\"pgp\",\"pq\",");
        seq_puts(m, "\"dt\",\"dt nesting\",\"dt NMI nesting\",\"df\",");
        seq_puts(m, "\"of\",\"qll\",\"ql\",\"qs\"");
@@ -173,14 +193,11 @@ static int show_rcudata_csv(struct seq_file *m, void *unused)
        seq_puts(m, "\"kt\",\"ktl\"");
 #endif /* #ifdef CONFIG_RCU_BOOST */
        seq_puts(m, ",\"b\",\"ci\",\"co\",\"ca\"\n");
-#ifdef CONFIG_TREE_PREEMPT_RCU
-       seq_puts(m, "\"rcu_preempt:\"\n");
-       PRINT_RCU_DATA(rcu_preempt_data, print_one_rcu_data_csv, m);
-#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-       seq_puts(m, "\"rcu_sched:\"\n");
-       PRINT_RCU_DATA(rcu_sched_data, print_one_rcu_data_csv, m);
-       seq_puts(m, "\"rcu_bh:\"\n");
-       PRINT_RCU_DATA(rcu_bh_data, print_one_rcu_data_csv, m);
+       for_each_rcu_flavor(rsp) {
+               seq_printf(m, "\"%s:\"\n", rsp->name);
+               for_each_possible_cpu(cpu)
+                       print_one_rcu_data_csv(m, per_cpu_ptr(rsp->rda, cpu));
+       }
        return 0;
 }
 
@@ -201,8 +218,7 @@ static const struct file_operations rcudata_csv_fops = {
 
 static void print_one_rcu_node_boost(struct seq_file *m, struct rcu_node *rnp)
 {
-       seq_printf(m,  "%d:%d tasks=%c%c%c%c kt=%c ntb=%lu neb=%lu nnb=%lu "
-                  "j=%04x bt=%04x\n",
+       seq_printf(m, "%d:%d tasks=%c%c%c%c kt=%c ntb=%lu neb=%lu nnb=%lu ",
                   rnp->grplo, rnp->grphi,
                   "T."[list_empty(&rnp->blkd_tasks)],
                   "N."[!rnp->gp_tasks],
@@ -210,11 +226,11 @@ static void print_one_rcu_node_boost(struct seq_file *m, struct rcu_node *rnp)
                   "B."[!rnp->boost_tasks],
                   convert_kthread_status(rnp->boost_kthread_status),
                   rnp->n_tasks_boosted, rnp->n_exp_boosts,
-                  rnp->n_normal_boosts,
+                  rnp->n_normal_boosts);
+       seq_printf(m, "j=%04x bt=%04x\n",
                   (int)(jiffies & 0xffff),
                   (int)(rnp->boost_time & 0xffff));
-       seq_printf(m, "%s: nt=%lu egt=%lu bt=%lu nb=%lu ny=%lu nos=%lu\n",
-                  "     balk",
+       seq_printf(m, "    balk: nt=%lu egt=%lu bt=%lu nb=%lu ny=%lu nos=%lu\n",
                   rnp->n_balk_blkd_tasks,
                   rnp->n_balk_exp_gp_tasks,
                   rnp->n_balk_boost_tasks,
@@ -270,15 +286,15 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
        struct rcu_node *rnp;
 
        gpnum = rsp->gpnum;
-       seq_printf(m, "c=%lu g=%lu s=%d jfq=%ld j=%x "
-                     "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n",
-                  rsp->completed, gpnum, rsp->fqs_state,
+       seq_printf(m, "%s: c=%lu g=%lu s=%d jfq=%ld j=%x ",
+                  rsp->name, rsp->completed, gpnum, rsp->fqs_state,
                   (long)(rsp->jiffies_force_qs - jiffies),
-                  (int)(jiffies & 0xffff),
+                  (int)(jiffies & 0xffff));
+       seq_printf(m, "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n",
                   rsp->n_force_qs, rsp->n_force_qs_ngp,
                   rsp->n_force_qs - rsp->n_force_qs_ngp,
                   rsp->n_force_qs_lh, rsp->qlen_lazy, rsp->qlen);
-       for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < NUM_RCU_NODES; rnp++) {
+       for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < rcu_num_nodes; rnp++) {
                if (rnp->level != level) {
                        seq_puts(m, "\n");
                        level = rnp->level;
@@ -295,14 +311,10 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
 
 static int show_rcuhier(struct seq_file *m, void *unused)
 {
-#ifdef CONFIG_TREE_PREEMPT_RCU
-       seq_puts(m, "rcu_preempt:\n");
-       print_one_rcu_state(m, &rcu_preempt_state);
-#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-       seq_puts(m, "rcu_sched:\n");
-       print_one_rcu_state(m, &rcu_sched_state);
-       seq_puts(m, "rcu_bh:\n");
-       print_one_rcu_state(m, &rcu_bh_state);
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp)
+               print_one_rcu_state(m, rsp);
        return 0;
 }
 
@@ -343,11 +355,10 @@ static void show_one_rcugp(struct seq_file *m, struct rcu_state *rsp)
 
 static int show_rcugp(struct seq_file *m, void *unused)
 {
-#ifdef CONFIG_TREE_PREEMPT_RCU
-       show_one_rcugp(m, &rcu_preempt_state);
-#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-       show_one_rcugp(m, &rcu_sched_state);
-       show_one_rcugp(m, &rcu_bh_state);
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp)
+               show_one_rcugp(m, rsp);
        return 0;
 }
 
@@ -366,44 +377,36 @@ static const struct file_operations rcugp_fops = {
 
 static void print_one_rcu_pending(struct seq_file *m, struct rcu_data *rdp)
 {
-       seq_printf(m, "%3d%cnp=%ld "
-                  "qsp=%ld rpq=%ld cbr=%ld cng=%ld "
-                  "gpc=%ld gps=%ld nf=%ld nn=%ld\n",
+       seq_printf(m, "%3d%cnp=%ld ",
                   rdp->cpu,
                   cpu_is_offline(rdp->cpu) ? '!' : ' ',
-                  rdp->n_rcu_pending,
+                  rdp->n_rcu_pending);
+       seq_printf(m, "qsp=%ld rpq=%ld cbr=%ld cng=%ld ",
                   rdp->n_rp_qs_pending,
                   rdp->n_rp_report_qs,
                   rdp->n_rp_cb_ready,
-                  rdp->n_rp_cpu_needs_gp,
+                  rdp->n_rp_cpu_needs_gp);
+       seq_printf(m, "gpc=%ld gps=%ld nf=%ld nn=%ld\n",
                   rdp->n_rp_gp_completed,
                   rdp->n_rp_gp_started,
                   rdp->n_rp_need_fqs,
                   rdp->n_rp_need_nothing);
 }
 
-static void print_rcu_pendings(struct seq_file *m, struct rcu_state *rsp)
+static int show_rcu_pending(struct seq_file *m, void *unused)
 {
        int cpu;
        struct rcu_data *rdp;
-
-       for_each_possible_cpu(cpu) {
-               rdp = per_cpu_ptr(rsp->rda, cpu);
-               if (rdp->beenonline)
-                       print_one_rcu_pending(m, rdp);
+       struct rcu_state *rsp;
+
+       for_each_rcu_flavor(rsp) {
+               seq_printf(m, "%s:\n", rsp->name);
+               for_each_possible_cpu(cpu) {
+                       rdp = per_cpu_ptr(rsp->rda, cpu);
+                       if (rdp->beenonline)
+                               print_one_rcu_pending(m, rdp);
+               }
        }
-}
-
-static int show_rcu_pending(struct seq_file *m, void *unused)
-{
-#ifdef CONFIG_TREE_PREEMPT_RCU
-       seq_puts(m, "rcu_preempt:\n");
-       print_rcu_pendings(m, &rcu_preempt_state);
-#endif /* #ifdef CONFIG_TREE_PREEMPT_RCU */
-       seq_puts(m, "rcu_sched:\n");
-       print_rcu_pendings(m, &rcu_sched_state);
-       seq_puts(m, "rcu_bh:\n");
-       print_rcu_pendings(m, &rcu_bh_state);
        return 0;
 }
 
@@ -453,6 +456,11 @@ static int __init rcutree_trace_init(void)
        if (!rcudir)
                goto free_out;
 
+       retval = debugfs_create_file("rcubarrier", 0444, rcudir,
+                                               NULL, &rcubarrier_fops);
+       if (!retval)
+               goto free_out;
+
        retval = debugfs_create_file("rcudata", 0444, rcudir,
                                                NULL, &rcudata_fops);
        if (!retval)
index 677102789cf22d4847936782f6c6f67085421927..be4f856d52f81bab8184544b5dd6dd9b823bc21b 100644 (file)
@@ -1971,6 +1971,13 @@ static void ptrace_do_notify(int signr, int exit_code, int why)
 void ptrace_notify(int exit_code)
 {
        BUG_ON((exit_code & (0x7f | ~0xffff)) != SIGTRAP);
+       if (unlikely(current->task_works)) {
+               if (test_and_clear_ti_thread_flag(current_thread_info(),
+                                                  TIF_NOTIFY_RESUME)) {
+                       smp_mb__after_clear_bit();
+                       task_work_run();
+               }
+       }
 
        spin_lock_irq(&current->sighand->siglock);
        ptrace_do_notify(SIGTRAP, exit_code, CLD_TRAPPED);
@@ -2191,6 +2198,14 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka,
        struct signal_struct *signal = current->signal;
        int signr;
 
+       if (unlikely(current->task_works)) {
+               if (test_and_clear_ti_thread_flag(current_thread_info(),
+                                                  TIF_NOTIFY_RESUME)) {
+                       smp_mb__after_clear_bit();
+                       task_work_run();
+               }
+       }
+
        if (unlikely(uprobe_deny_signal()))
                return 0;
 
index d0ae5b24875e0f73659d79ae6cd3f9ee11d5ab41..29dd40a9f2f403ab86f39c96ddb505851b1d36c2 100644 (file)
@@ -581,26 +581,6 @@ int smp_call_function(smp_call_func_t func, void *info, int wait)
        return 0;
 }
 EXPORT_SYMBOL(smp_call_function);
-
-void ipi_call_lock(void)
-{
-       raw_spin_lock(&call_function.lock);
-}
-
-void ipi_call_unlock(void)
-{
-       raw_spin_unlock(&call_function.lock);
-}
-
-void ipi_call_lock_irq(void)
-{
-       raw_spin_lock_irq(&call_function.lock);
-}
-
-void ipi_call_unlock_irq(void)
-{
-       raw_spin_unlock_irq(&call_function.lock);
-}
 #endif /* USE_GENERIC_SMP_HELPERS */
 
 /* Setup configured maximum number of CPUs to activate */
index 80c0acfb847211af69e9356677f45f8ea1c4c240..6ef9433e1c7001ff0d00799379de7e71ef1a0113 100644 (file)
@@ -3,8 +3,6 @@
 
 struct task_struct;
 
-int smpboot_prepare(unsigned int cpu);
-
 #ifdef CONFIG_GENERIC_SMP_IDLE_THREAD
 struct task_struct *idle_thread_get(unsigned int cpu);
 void idle_thread_set_boot_cpu(void);
index 82d1c794066d450d6c08c6de4452a9cbd344ef63..91d4e1742a0c4ec1cd8805b6663f5a95b5d42b3b 100644 (file)
@@ -3,82 +3,78 @@
 #include <linux/tracehook.h>
 
 int
-task_work_add(struct task_struct *task, struct task_work *twork, bool notify)
+task_work_add(struct task_struct *task, struct callback_head *twork, bool notify)
 {
+       struct callback_head *last, *first;
        unsigned long flags;
-       int err = -ESRCH;
 
-#ifndef TIF_NOTIFY_RESUME
-       if (notify)
-               return -ENOTSUPP;
-#endif
        /*
-        * We must not insert the new work if the task has already passed
-        * exit_task_work(). We rely on do_exit()->raw_spin_unlock_wait()
-        * and check PF_EXITING under pi_lock.
+        * Not inserting the new work if the task has already passed
+        * exit_task_work() is the responisbility of callers.
         */
        raw_spin_lock_irqsave(&task->pi_lock, flags);
-       if (likely(!(task->flags & PF_EXITING))) {
-               hlist_add_head(&twork->hlist, &task->task_works);
-               err = 0;
-       }
+       last = task->task_works;
+       first = last ? last->next : twork;
+       twork->next = first;
+       if (last)
+               last->next = twork;
+       task->task_works = twork;
        raw_spin_unlock_irqrestore(&task->pi_lock, flags);
 
        /* test_and_set_bit() implies mb(), see tracehook_notify_resume(). */
-       if (likely(!err) && notify)
+       if (notify)
                set_notify_resume(task);
-       return err;
+       return 0;
 }
 
-struct task_work *
+struct callback_head *
 task_work_cancel(struct task_struct *task, task_work_func_t func)
 {
        unsigned long flags;
-       struct task_work *twork;
-       struct hlist_node *pos;
+       struct callback_head *last, *res = NULL;
 
        raw_spin_lock_irqsave(&task->pi_lock, flags);
-       hlist_for_each_entry(twork, pos, &task->task_works, hlist) {
-               if (twork->func == func) {
-                       hlist_del(&twork->hlist);
-                       goto found;
+       last = task->task_works;
+       if (last) {
+               struct callback_head *q = last, *p = q->next;
+               while (1) {
+                       if (p->func == func) {
+                               q->next = p->next;
+                               if (p == last)
+                                       task->task_works = q == p ? NULL : q;
+                               res = p;
+                               break;
+                       }
+                       if (p == last)
+                               break;
+                       q = p;
+                       p = q->next;
                }
        }
-       twork = NULL;
- found:
        raw_spin_unlock_irqrestore(&task->pi_lock, flags);
-
-       return twork;
+       return res;
 }
 
 void task_work_run(void)
 {
        struct task_struct *task = current;
-       struct hlist_head task_works;
-       struct hlist_node *pos;
+       struct callback_head *p, *q;
 
-       raw_spin_lock_irq(&task->pi_lock);
-       hlist_move_list(&task->task_works, &task_works);
-       raw_spin_unlock_irq(&task->pi_lock);
+       while (1) {
+               raw_spin_lock_irq(&task->pi_lock);
+               p = task->task_works;
+               task->task_works = NULL;
+               raw_spin_unlock_irq(&task->pi_lock);
 
-       if (unlikely(hlist_empty(&task_works)))
-               return;
-       /*
-        * We use hlist to save the space in task_struct, but we want fifo.
-        * Find the last entry, the list should be short, then process them
-        * in reverse order.
-        */
-       for (pos = task_works.first; pos->next; pos = pos->next)
-               ;
+               if (unlikely(!p))
+                       return;
 
-       for (;;) {
-               struct hlist_node **pprev = pos->pprev;
-               struct task_work *twork = container_of(pos, struct task_work,
-                                                       hlist);
-               twork->func(twork);
-
-               if (pprev == &task_works.first)
-                       break;
-               pos = container_of(pprev, struct hlist_node, next);
+               q = p->next; /* head */
+               p->next = NULL; /* cut it */
+               while (q) {
+                       p = q->next;
+                       q->func(q);
+                       q = p;
+               }
        }
 }
index 4a08472c3ca71399edc34ffafa9f5394f25597e7..024540f97f74c3e94205826f33d3968ea765f626 100644 (file)
@@ -105,7 +105,7 @@ static ktime_t tick_init_jiffy_update(void)
 /*
  * NO HZ enabled ?
  */
-static int tick_nohz_enabled __read_mostly  = 1;
+int tick_nohz_enabled __read_mostly  = 1;
 
 /*
  * Enable / Disable tickless mode
@@ -271,50 +271,15 @@ u64 get_cpu_iowait_time_us(int cpu, u64 *last_update_time)
 }
 EXPORT_SYMBOL_GPL(get_cpu_iowait_time_us);
 
-static void tick_nohz_stop_sched_tick(struct tick_sched *ts)
+static ktime_t tick_nohz_stop_sched_tick(struct tick_sched *ts,
+                                        ktime_t now, int cpu)
 {
        unsigned long seq, last_jiffies, next_jiffies, delta_jiffies;
+       ktime_t last_update, expires, ret = { .tv64 = 0 };
        unsigned long rcu_delta_jiffies;
-       ktime_t last_update, expires, now;
        struct clock_event_device *dev = __get_cpu_var(tick_cpu_device).evtdev;
        u64 time_delta;
-       int cpu;
-
-       cpu = smp_processor_id();
-       ts = &per_cpu(tick_cpu_sched, cpu);
-
-       now = tick_nohz_start_idle(cpu, ts);
-
-       /*
-        * If this cpu is offline and it is the one which updates
-        * jiffies, then give up the assignment and let it be taken by
-        * the cpu which runs the tick timer next. If we don't drop
-        * this here the jiffies might be stale and do_timer() never
-        * invoked.
-        */
-       if (unlikely(!cpu_online(cpu))) {
-               if (cpu == tick_do_timer_cpu)
-                       tick_do_timer_cpu = TICK_DO_TIMER_NONE;
-       }
-
-       if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
-               return;
 
-       if (need_resched())
-               return;
-
-       if (unlikely(local_softirq_pending() && cpu_online(cpu))) {
-               static int ratelimit;
-
-               if (ratelimit < 10) {
-                       printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
-                              (unsigned int) local_softirq_pending());
-                       ratelimit++;
-               }
-               return;
-       }
-
-       ts->idle_calls++;
        /* Read jiffies and the time when jiffies were updated last */
        do {
                seq = read_seqbegin(&xtime_lock);
@@ -397,6 +362,8 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts)
                if (ts->tick_stopped && ktime_equal(expires, dev->next_event))
                        goto out;
 
+               ret = expires;
+
                /*
                 * nohz_stop_sched_tick can be called several times before
                 * the nohz_restart_sched_tick is called. This happens when
@@ -408,16 +375,10 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts)
                        select_nohz_load_balancer(1);
                        calc_load_enter_idle();
 
-                       ts->idle_tick = hrtimer_get_expires(&ts->sched_timer);
+                       ts->last_tick = hrtimer_get_expires(&ts->sched_timer);
                        ts->tick_stopped = 1;
-                       ts->idle_jiffies = last_jiffies;
                }
 
-               ts->idle_sleeps++;
-
-               /* Mark expires */
-               ts->idle_expires = expires;
-
                /*
                 * If the expiration time == KTIME_MAX, then
                 * in this case we simply stop the tick timer.
@@ -448,6 +409,65 @@ out:
        ts->next_jiffies = next_jiffies;
        ts->last_jiffies = last_jiffies;
        ts->sleep_length = ktime_sub(dev->next_event, now);
+
+       return ret;
+}
+
+static bool can_stop_idle_tick(int cpu, struct tick_sched *ts)
+{
+       /*
+        * If this cpu is offline and it is the one which updates
+        * jiffies, then give up the assignment and let it be taken by
+        * the cpu which runs the tick timer next. If we don't drop
+        * this here the jiffies might be stale and do_timer() never
+        * invoked.
+        */
+       if (unlikely(!cpu_online(cpu))) {
+               if (cpu == tick_do_timer_cpu)
+                       tick_do_timer_cpu = TICK_DO_TIMER_NONE;
+       }
+
+       if (unlikely(ts->nohz_mode == NOHZ_MODE_INACTIVE))
+               return false;
+
+       if (need_resched())
+               return false;
+
+       if (unlikely(local_softirq_pending() && cpu_online(cpu))) {
+               static int ratelimit;
+
+               if (ratelimit < 10) {
+                       printk(KERN_ERR "NOHZ: local_softirq_pending %02x\n",
+                              (unsigned int) local_softirq_pending());
+                       ratelimit++;
+               }
+               return false;
+       }
+
+       return true;
+}
+
+static void __tick_nohz_idle_enter(struct tick_sched *ts)
+{
+       ktime_t now, expires;
+       int cpu = smp_processor_id();
+
+       now = tick_nohz_start_idle(cpu, ts);
+
+       if (can_stop_idle_tick(cpu, ts)) {
+               int was_stopped = ts->tick_stopped;
+
+               ts->idle_calls++;
+
+               expires = tick_nohz_stop_sched_tick(ts, now, cpu);
+               if (expires.tv64 > 0LL) {
+                       ts->idle_sleeps++;
+                       ts->idle_expires = expires;
+               }
+
+               if (!was_stopped && ts->tick_stopped)
+                       ts->idle_jiffies = ts->last_jiffies;
+       }
 }
 
 /**
@@ -485,7 +505,7 @@ void tick_nohz_idle_enter(void)
         * update of the idle time accounting in tick_nohz_start_idle().
         */
        ts->inidle = 1;
-       tick_nohz_stop_sched_tick(ts);
+       __tick_nohz_idle_enter(ts);
 
        local_irq_enable();
 }
@@ -505,7 +525,7 @@ void tick_nohz_irq_exit(void)
        if (!ts->inidle)
                return;
 
-       tick_nohz_stop_sched_tick(ts);
+       __tick_nohz_idle_enter(ts);
 }
 
 /**
@@ -523,7 +543,7 @@ ktime_t tick_nohz_get_sleep_length(void)
 static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
 {
        hrtimer_cancel(&ts->sched_timer);
-       hrtimer_set_expires(&ts->sched_timer, ts->idle_tick);
+       hrtimer_set_expires(&ts->sched_timer, ts->last_tick);
 
        while (1) {
                /* Forward the time to expire in the future */
@@ -546,6 +566,41 @@ static void tick_nohz_restart(struct tick_sched *ts, ktime_t now)
        }
 }
 
+static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
+{
+       /* Update jiffies first */
+       select_nohz_load_balancer(0);
+       tick_do_update_jiffies64(now);
+       update_cpu_load_nohz();
+
+       touch_softlockup_watchdog();
+       /*
+        * Cancel the scheduled timer and restore the tick
+        */
+       ts->tick_stopped  = 0;
+       ts->idle_exittime = now;
+
+       tick_nohz_restart(ts, now);
+}
+
+static void tick_nohz_account_idle_ticks(struct tick_sched *ts)
+{
+#ifndef CONFIG_VIRT_CPU_ACCOUNTING
+       unsigned long ticks;
+       /*
+        * We stopped the tick in idle. Update process times would miss the
+        * time we slept as update_process_times does only a 1 tick
+        * accounting. Enforce that this is accounted to idle !
+        */
+       ticks = jiffies - ts->idle_jiffies;
+       /*
+        * We might be one off. Do not randomly account a huge number of ticks!
+        */
+       if (ticks && ticks < LONG_MAX)
+               account_idle_ticks(ticks);
+#endif
+}
+
 /**
  * tick_nohz_idle_exit - restart the idle tick from the idle task
  *
@@ -557,9 +612,6 @@ void tick_nohz_idle_exit(void)
 {
        int cpu = smp_processor_id();
        struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu);
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
-       unsigned long ticks;
-#endif
        ktime_t now;
 
        local_irq_disable();
@@ -574,40 +626,11 @@ void tick_nohz_idle_exit(void)
        if (ts->idle_active)
                tick_nohz_stop_idle(cpu, now);
 
-       if (!ts->tick_stopped) {
-               local_irq_enable();
-               return;
+       if (ts->tick_stopped) {
+               tick_nohz_restart_sched_tick(ts, now);
+               tick_nohz_account_idle_ticks(ts);
        }
 
-       /* Update jiffies first */
-       select_nohz_load_balancer(0);
-       tick_do_update_jiffies64(now);
-       update_cpu_load_nohz();
-
-#ifndef CONFIG_VIRT_CPU_ACCOUNTING
-       /*
-        * We stopped the tick in idle. Update process times would miss the
-        * time we slept as update_process_times does only a 1 tick
-        * accounting. Enforce that this is accounted to idle !
-        */
-       ticks = jiffies - ts->idle_jiffies;
-       /*
-        * We might be one off. Do not randomly account a huge number of ticks!
-        */
-       if (ticks && ticks < LONG_MAX)
-               account_idle_ticks(ticks);
-#endif
-
-       calc_load_exit_idle();
-       touch_softlockup_watchdog();
-       /*
-        * Cancel the scheduled timer and restore the tick
-        */
-       ts->tick_stopped  = 0;
-       ts->idle_exittime = now;
-
-       tick_nohz_restart(ts, now);
-
        local_irq_enable();
 }
 
@@ -811,7 +834,8 @@ static enum hrtimer_restart tick_sched_timer(struct hrtimer *timer)
                 */
                if (ts->tick_stopped) {
                        touch_softlockup_watchdog();
-                       ts->idle_jiffies++;
+                       if (idle_cpu(cpu))
+                               ts->idle_jiffies++;
                }
                update_process_times(user_mode(regs));
                profile_tick(CPU_PROFILING);
index 3447cfaf11e7d61b11d30bc063967e47d85e59d4..f045cc50832d0fc8aee045755d3ba60d655f2647 100644 (file)
 /* Structure holding internal timekeeping values. */
 struct timekeeper {
        /* Current clocksource used for timekeeping. */
-       struct clocksource *clock;
+       struct clocksource      *clock;
        /* NTP adjusted clock multiplier */
-       u32     mult;
+       u32                     mult;
        /* The shift value of the current clocksource. */
-       int     shift;
-
+       u32                     shift;
        /* Number of clock cycles in one NTP interval. */
-       cycle_t cycle_interval;
+       cycle_t                 cycle_interval;
        /* Number of clock shifted nano seconds in one NTP interval. */
-       u64     xtime_interval;
+       u64                     xtime_interval;
        /* shifted nano seconds left over when rounding cycle_interval */
-       s64     xtime_remainder;
+       s64                     xtime_remainder;
        /* Raw nano seconds accumulated per NTP interval. */
-       u32     raw_interval;
+       u32                     raw_interval;
+
+       /* Current CLOCK_REALTIME time in seconds */
+       u64                     xtime_sec;
+       /* Clock shifted nano seconds */
+       u64                     xtime_nsec;
 
-       /* Clock shifted nano seconds remainder not stored in xtime.tv_nsec. */
-       u64     xtime_nsec;
        /* Difference between accumulated time and NTP time in ntp
         * shifted nano seconds. */
-       s64     ntp_error;
+       s64                     ntp_error;
        /* Shift conversion between clock shifted nano seconds and
         * ntp shifted nano seconds. */
-       int     ntp_error_shift;
+       u32                     ntp_error_shift;
 
-       /* The current time */
-       struct timespec xtime;
        /*
         * wall_to_monotonic is what we need to add to xtime (or xtime corrected
         * for sub jiffie times) to get to monotonic time.  Monotonic is pegged
@@ -64,20 +64,17 @@ struct timekeeper {
         * - wall_to_monotonic is no longer the boot time, getboottime must be
         * used instead.
         */
-       struct timespec wall_to_monotonic;
+       struct timespec         wall_to_monotonic;
        /* time spent in suspend */
-       struct timespec total_sleep_time;
+       struct timespec         total_sleep_time;
        /* The raw monotonic time for the CLOCK_MONOTONIC_RAW posix clock. */
-       struct timespec raw_time;
-
+       struct timespec         raw_time;
        /* Offset clock monotonic -> clock realtime */
-       ktime_t offs_real;
-
+       ktime_t                 offs_real;
        /* Offset clock monotonic -> clock boottime */
-       ktime_t offs_boot;
-
+       ktime_t                 offs_boot;
        /* Seqlock for all timekeeper values */
-       seqlock_t lock;
+       seqlock_t               lock;
 };
 
 static struct timekeeper timekeeper;
@@ -88,11 +85,37 @@ static struct timekeeper timekeeper;
  */
 __cacheline_aligned_in_smp DEFINE_SEQLOCK(xtime_lock);
 
-
 /* flag for if timekeeping is suspended */
 int __read_mostly timekeeping_suspended;
 
+static inline void tk_normalize_xtime(struct timekeeper *tk)
+{
+       while (tk->xtime_nsec >= ((u64)NSEC_PER_SEC << tk->shift)) {
+               tk->xtime_nsec -= (u64)NSEC_PER_SEC << tk->shift;
+               tk->xtime_sec++;
+       }
+}
 
+static struct timespec tk_xtime(struct timekeeper *tk)
+{
+       struct timespec ts;
+
+       ts.tv_sec = tk->xtime_sec;
+       ts.tv_nsec = (long)(tk->xtime_nsec >> tk->shift);
+       return ts;
+}
+
+static void tk_set_xtime(struct timekeeper *tk, const struct timespec *ts)
+{
+       tk->xtime_sec = ts->tv_sec;
+       tk->xtime_nsec = ts->tv_nsec << tk->shift;
+}
+
+static void tk_xtime_add(struct timekeeper *tk, const struct timespec *ts)
+{
+       tk->xtime_sec += ts->tv_sec;
+       tk->xtime_nsec += ts->tv_nsec << tk->shift;
+}
 
 /**
  * timekeeper_setup_internals - Set up internals to use clocksource clock.
@@ -104,12 +127,14 @@ int __read_mostly timekeeping_suspended;
  *
  * Unless you're the timekeeping code, you should not be using this!
  */
-static void timekeeper_setup_internals(struct clocksource *clock)
+static void tk_setup_internals(struct timekeeper *tk, struct clocksource *clock)
 {
        cycle_t interval;
        u64 tmp, ntpinterval;
+       struct clocksource *old_clock;
 
-       timekeeper.clock = clock;
+       old_clock = tk->clock;
+       tk->clock = clock;
        clock->cycle_last = clock->read(clock);
 
        /* Do the ns -> cycle conversion first, using original mult */
@@ -122,80 +147,96 @@ static void timekeeper_setup_internals(struct clocksource *clock)
                tmp = 1;
 
        interval = (cycle_t) tmp;
-       timekeeper.cycle_interval = interval;
+       tk->cycle_interval = interval;
 
        /* Go back from cycles -> shifted ns */
-       timekeeper.xtime_interval = (u64) interval * clock->mult;
-       timekeeper.xtime_remainder = ntpinterval - timekeeper.xtime_interval;
-       timekeeper.raw_interval =
+       tk->xtime_interval = (u64) interval * clock->mult;
+       tk->xtime_remainder = ntpinterval - tk->xtime_interval;
+       tk->raw_interval =
                ((u64) interval * clock->mult) >> clock->shift;
 
-       timekeeper.xtime_nsec = 0;
-       timekeeper.shift = clock->shift;
+        /* if changing clocks, convert xtime_nsec shift units */
+       if (old_clock) {
+               int shift_change = clock->shift - old_clock->shift;
+               if (shift_change < 0)
+                       tk->xtime_nsec >>= -shift_change;
+               else
+                       tk->xtime_nsec <<= shift_change;
+       }
+       tk->shift = clock->shift;
 
-       timekeeper.ntp_error = 0;
-       timekeeper.ntp_error_shift = NTP_SCALE_SHIFT - clock->shift;
+       tk->ntp_error = 0;
+       tk->ntp_error_shift = NTP_SCALE_SHIFT - clock->shift;
 
        /*
         * The timekeeper keeps its own mult values for the currently
         * active clocksource. These value will be adjusted via NTP
         * to counteract clock drifting.
         */
-       timekeeper.mult = clock->mult;
+       tk->mult = clock->mult;
 }
 
 /* Timekeeper helper functions. */
-static inline s64 timekeeping_get_ns(void)
+static inline s64 timekeeping_get_ns(struct timekeeper *tk)
 {
        cycle_t cycle_now, cycle_delta;
        struct clocksource *clock;
+       s64 nsec;
 
        /* read clocksource: */
-       clock = timekeeper.clock;
+       clock = tk->clock;
        cycle_now = clock->read(clock);
 
        /* calculate the delta since the last update_wall_time: */
        cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
 
-       /* return delta convert to nanoseconds using ntp adjusted mult. */
-       return clocksource_cyc2ns(cycle_delta, timekeeper.mult,
-                                 timekeeper.shift);
+       nsec = cycle_delta * tk->mult + tk->xtime_nsec;
+       nsec >>= tk->shift;
+
+       /* If arch requires, add in gettimeoffset() */
+       return nsec + arch_gettimeoffset();
 }
 
-static inline s64 timekeeping_get_ns_raw(void)
+static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
 {
        cycle_t cycle_now, cycle_delta;
        struct clocksource *clock;
+       s64 nsec;
 
        /* read clocksource: */
-       clock = timekeeper.clock;
+       clock = tk->clock;
        cycle_now = clock->read(clock);
 
        /* calculate the delta since the last update_wall_time: */
        cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
 
-       /* return delta convert to nanoseconds. */
-       return clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
+       /* convert delta to nanoseconds. */
+       nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
+
+       /* If arch requires, add in gettimeoffset() */
+       return nsec + arch_gettimeoffset();
 }
 
-static void update_rt_offset(void)
+static void update_rt_offset(struct timekeeper *tk)
 {
-       struct timespec tmp, *wtm = &timekeeper.wall_to_monotonic;
+       struct timespec tmp, *wtm = &tk->wall_to_monotonic;
 
        set_normalized_timespec(&tmp, -wtm->tv_sec, -wtm->tv_nsec);
-       timekeeper.offs_real = timespec_to_ktime(tmp);
+       tk->offs_real = timespec_to_ktime(tmp);
 }
 
 /* must hold write on timekeeper.lock */
-static void timekeeping_update(bool clearntp)
+static void timekeeping_update(struct timekeeper *tk, bool clearntp)
 {
+       struct timespec xt;
+
        if (clearntp) {
-               timekeeper.ntp_error = 0;
+               tk->ntp_error = 0;
                ntp_clear();
        }
-       update_rt_offset();
-       update_vsyscall(&timekeeper.xtime, &timekeeper.wall_to_monotonic,
-                        timekeeper.clock, timekeeper.mult);
+       update_rt_offset(tk);
+       xt = tk_xtime(tk);
+       update_vsyscall(&xt, &tk->wall_to_monotonic, tk->clock, tk->mult);
 }
 
 
@@ -206,27 +247,26 @@ static void timekeeping_update(bool clearntp)
  * update_wall_time(). This is useful before significant clock changes,
  * as it avoids having to deal with this time offset explicitly.
  */
-static void timekeeping_forward_now(void)
+static void timekeeping_forward_now(struct timekeeper *tk)
 {
        cycle_t cycle_now, cycle_delta;
        struct clocksource *clock;
        s64 nsec;
 
-       clock = timekeeper.clock;
+       clock = tk->clock;
        cycle_now = clock->read(clock);
        cycle_delta = (cycle_now - clock->cycle_last) & clock->mask;
        clock->cycle_last = cycle_now;
 
-       nsec = clocksource_cyc2ns(cycle_delta, timekeeper.mult,
-                                 timekeeper.shift);
+       tk->xtime_nsec += cycle_delta * tk->mult;
 
        /* If arch requires, add in gettimeoffset() */
-       nsec += arch_gettimeoffset();
+       tk->xtime_nsec += arch_gettimeoffset() << tk->shift;
 
-       timespec_add_ns(&timekeeper.xtime, nsec);
+       tk_normalize_xtime(tk);
 
        nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
-       timespec_add_ns(&timekeeper.raw_time, nsec);
+       timespec_add_ns(&tk->raw_time, nsec);
 }
 
 /**
@@ -238,18 +278,15 @@ static void timekeeping_forward_now(void)
 void getnstimeofday(struct timespec *ts)
 {
        unsigned long seq;
-       s64 nsecs;
+       s64 nsecs = 0;
 
        WARN_ON(timekeeping_suspended);
 
        do {
                seq = read_seqbegin(&timekeeper.lock);
 
-               *ts = timekeeper.xtime;
-               nsecs = timekeeping_get_ns();
-
-               /* If arch requires, add in gettimeoffset() */
-               nsecs += arch_gettimeoffset();
+               ts->tv_sec = timekeeper.xtime_sec;
+               ts->tv_nsec = timekeeping_get_ns(&timekeeper);
 
        } while (read_seqretry(&timekeeper.lock, seq));
 
@@ -266,13 +303,10 @@ ktime_t ktime_get(void)
 
        do {
                seq = read_seqbegin(&timekeeper.lock);
-               secs = timekeeper.xtime.tv_sec +
+               secs = timekeeper.xtime_sec +
                                timekeeper.wall_to_monotonic.tv_sec;
-               nsecs = timekeeper.xtime.tv_nsec +
+               nsecs = timekeeping_get_ns(&timekeeper) +
                                timekeeper.wall_to_monotonic.tv_nsec;
-               nsecs += timekeeping_get_ns();
-               /* If arch requires, add in gettimeoffset() */
-               nsecs += arch_gettimeoffset();
 
        } while (read_seqretry(&timekeeper.lock, seq));
        /*
@@ -295,22 +329,19 @@ void ktime_get_ts(struct timespec *ts)
 {
        struct timespec tomono;
        unsigned int seq;
-       s64 nsecs;
 
        WARN_ON(timekeeping_suspended);
 
        do {
                seq = read_seqbegin(&timekeeper.lock);
-               *ts = timekeeper.xtime;
+               ts->tv_sec = timekeeper.xtime_sec;
+               ts->tv_nsec = timekeeping_get_ns(&timekeeper);
                tomono = timekeeper.wall_to_monotonic;
-               nsecs = timekeeping_get_ns();
-               /* If arch requires, add in gettimeoffset() */
-               nsecs += arch_gettimeoffset();
 
        } while (read_seqretry(&timekeeper.lock, seq));
 
        set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec,
-                               ts->tv_nsec + tomono.tv_nsec + nsecs);
+                               ts->tv_nsec + tomono.tv_nsec);
 }
 EXPORT_SYMBOL_GPL(ktime_get_ts);
 
@@ -333,20 +364,14 @@ void getnstime_raw_and_real(struct timespec *ts_raw, struct timespec *ts_real)
        WARN_ON_ONCE(timekeeping_suspended);
 
        do {
-               u32 arch_offset;
-
                seq = read_seqbegin(&timekeeper.lock);
 
                *ts_raw = timekeeper.raw_time;
-               *ts_real = timekeeper.xtime;
-
-               nsecs_raw = timekeeping_get_ns_raw();
-               nsecs_real = timekeeping_get_ns();
+               ts_real->tv_sec = timekeeper.xtime_sec;
+               ts_real->tv_nsec = 0;
 
-               /* If arch requires, add in gettimeoffset() */
-               arch_offset = arch_gettimeoffset();
-               nsecs_raw += arch_offset;
-               nsecs_real += arch_offset;
+               nsecs_raw = timekeeping_get_ns_raw(&timekeeper);
+               nsecs_real = timekeeping_get_ns(&timekeeper);
 
        } while (read_seqretry(&timekeeper.lock, seq));
 
@@ -381,7 +406,7 @@ EXPORT_SYMBOL(do_gettimeofday);
  */
 int do_settimeofday(const struct timespec *tv)
 {
-       struct timespec ts_delta;
+       struct timespec ts_delta, xt;
        unsigned long flags;
 
        if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
@@ -389,15 +414,18 @@ int do_settimeofday(const struct timespec *tv)
 
        write_seqlock_irqsave(&timekeeper.lock, flags);
 
-       timekeeping_forward_now();
+       timekeeping_forward_now(&timekeeper);
+
+       xt = tk_xtime(&timekeeper);
+       ts_delta.tv_sec = tv->tv_sec - xt.tv_sec;
+       ts_delta.tv_nsec = tv->tv_nsec - xt.tv_nsec;
 
-       ts_delta.tv_sec = tv->tv_sec - timekeeper.xtime.tv_sec;
-       ts_delta.tv_nsec = tv->tv_nsec - timekeeper.xtime.tv_nsec;
        timekeeper.wall_to_monotonic =
                        timespec_sub(timekeeper.wall_to_monotonic, ts_delta);
 
-       timekeeper.xtime = *tv;
-       timekeeping_update(true);
+       tk_set_xtime(&timekeeper, tv);
+
+       timekeeping_update(&timekeeper, true);
 
        write_sequnlock_irqrestore(&timekeeper.lock, flags);
 
@@ -424,13 +452,14 @@ int timekeeping_inject_offset(struct timespec *ts)
 
        write_seqlock_irqsave(&timekeeper.lock, flags);
 
-       timekeeping_forward_now();
+       timekeeping_forward_now(&timekeeper);
+
 
-       timekeeper.xtime = timespec_add(timekeeper.xtime, *ts);
+       tk_xtime_add(&timekeeper, ts);
        timekeeper.wall_to_monotonic =
                                timespec_sub(timekeeper.wall_to_monotonic, *ts);
 
-       timekeeping_update(true);
+       timekeeping_update(&timekeeper, true);
 
        write_sequnlock_irqrestore(&timekeeper.lock, flags);
 
@@ -455,14 +484,14 @@ static int change_clocksource(void *data)
 
        write_seqlock_irqsave(&timekeeper.lock, flags);
 
-       timekeeping_forward_now();
+       timekeeping_forward_now(&timekeeper);
        if (!new->enable || new->enable(new) == 0) {
                old = timekeeper.clock;
-               timekeeper_setup_internals(new);
+               tk_setup_internals(&timekeeper, new);
                if (old->disable)
                        old->disable(old);
        }
-       timekeeping_update(true);
+       timekeeping_update(&timekeeper, true);
 
        write_sequnlock_irqrestore(&timekeeper.lock, flags);
 
@@ -512,7 +541,7 @@ void getrawmonotonic(struct timespec *ts)
 
        do {
                seq = read_seqbegin(&timekeeper.lock);
-               nsecs = timekeeping_get_ns_raw();
+               nsecs = timekeeping_get_ns_raw(&timekeeper);
                *ts = timekeeper.raw_time;
 
        } while (read_seqretry(&timekeeper.lock, seq));
@@ -547,6 +576,7 @@ u64 timekeeping_max_deferment(void)
 {
        unsigned long seq;
        u64 ret;
+
        do {
                seq = read_seqbegin(&timekeeper.lock);
 
@@ -607,19 +637,17 @@ void __init timekeeping_init(void)
        clock = clocksource_default_clock();
        if (clock->enable)
                clock->enable(clock);
-       timekeeper_setup_internals(clock);
+       tk_setup_internals(&timekeeper, clock);
 
-       timekeeper.xtime.tv_sec = now.tv_sec;
-       timekeeper.xtime.tv_nsec = now.tv_nsec;
+       tk_set_xtime(&timekeeper, &now);
        timekeeper.raw_time.tv_sec = 0;
        timekeeper.raw_time.tv_nsec = 0;
-       if (boot.tv_sec == 0 && boot.tv_nsec == 0) {
-               boot.tv_sec = timekeeper.xtime.tv_sec;
-               boot.tv_nsec = timekeeper.xtime.tv_nsec;
-       }
+       if (boot.tv_sec == 0 && boot.tv_nsec == 0)
+               boot = tk_xtime(&timekeeper);
+
        set_normalized_timespec(&timekeeper.wall_to_monotonic,
                                -boot.tv_sec, -boot.tv_nsec);
-       update_rt_offset();
+       update_rt_offset(&timekeeper);
        timekeeper.total_sleep_time.tv_sec = 0;
        timekeeper.total_sleep_time.tv_nsec = 0;
        write_sequnlock_irqrestore(&timekeeper.lock, flags);
@@ -641,7 +669,8 @@ static void update_sleep_time(struct timespec t)
  * Takes a timespec offset measuring a suspend interval and properly
  * adds the sleep offset to the timekeeping variables.
  */
-static void __timekeeping_inject_sleeptime(struct timespec *delta)
+static void __timekeeping_inject_sleeptime(struct timekeeper *tk,
+                                                       struct timespec *delta)
 {
        if (!timespec_valid(delta)) {
                printk(KERN_WARNING "__timekeeping_inject_sleeptime: Invalid "
@@ -649,10 +678,9 @@ static void __timekeeping_inject_sleeptime(struct timespec *delta)
                return;
        }
 
-       timekeeper.xtime = timespec_add(timekeeper.xtime, *delta);
-       timekeeper.wall_to_monotonic =
-                       timespec_sub(timekeeper.wall_to_monotonic, *delta);
-       update_sleep_time(timespec_add(timekeeper.total_sleep_time, *delta));
+       tk_xtime_add(tk, delta);
+       tk->wall_to_monotonic = timespec_sub(tk->wall_to_monotonic, *delta);
+       update_sleep_time(timespec_add(tk->total_sleep_time, *delta));
 }
 
 
@@ -678,11 +706,11 @@ void timekeeping_inject_sleeptime(struct timespec *delta)
 
        write_seqlock_irqsave(&timekeeper.lock, flags);
 
-       timekeeping_forward_now();
+       timekeeping_forward_now(&timekeeper);
 
-       __timekeeping_inject_sleeptime(delta);
+       __timekeeping_inject_sleeptime(&timekeeper, delta);
 
-       timekeeping_update(true);
+       timekeeping_update(&timekeeper, true);
 
        write_sequnlock_irqrestore(&timekeeper.lock, flags);
 
@@ -711,13 +739,13 @@ static void timekeeping_resume(void)
 
        if (timespec_compare(&ts, &timekeeping_suspend_time) > 0) {
                ts = timespec_sub(ts, timekeeping_suspend_time);
-               __timekeeping_inject_sleeptime(&ts);
+               __timekeeping_inject_sleeptime(&timekeeper, &ts);
        }
        /* re-base the last cycle value */
        timekeeper.clock->cycle_last = timekeeper.clock->read(timekeeper.clock);
        timekeeper.ntp_error = 0;
        timekeeping_suspended = 0;
-       timekeeping_update(false);
+       timekeeping_update(&timekeeper, false);
        write_sequnlock_irqrestore(&timekeeper.lock, flags);
 
        touch_softlockup_watchdog();
@@ -737,7 +765,7 @@ static int timekeeping_suspend(void)
        read_persistent_clock(&timekeeping_suspend_time);
 
        write_seqlock_irqsave(&timekeeper.lock, flags);
-       timekeeping_forward_now();
+       timekeeping_forward_now(&timekeeper);
        timekeeping_suspended = 1;
 
        /*
@@ -746,7 +774,7 @@ static int timekeeping_suspend(void)
         * try to compensate so the difference in system time
         * and persistent_clock time stays close to constant.
         */
-       delta = timespec_sub(timekeeper.xtime, timekeeping_suspend_time);
+       delta = timespec_sub(tk_xtime(&timekeeper), timekeeping_suspend_time);
        delta_delta = timespec_sub(delta, old_delta);
        if (abs(delta_delta.tv_sec)  >= 2) {
                /*
@@ -785,7 +813,8 @@ device_initcall(timekeeping_init_ops);
  * If the error is already larger, we look ahead even further
  * to compensate for late or lost adjustments.
  */
-static __always_inline int timekeeping_bigadjust(s64 error, s64 *interval,
+static __always_inline int timekeeping_bigadjust(struct timekeeper *tk,
+                                                s64 error, s64 *interval,
                                                 s64 *offset)
 {
        s64 tick_error, i;
@@ -801,7 +830,7 @@ static __always_inline int timekeeping_bigadjust(s64 error, s64 *interval,
         * here.  This is tuned so that an error of about 1 msec is adjusted
         * within about 1 sec (or 2^20 nsec in 2^SHIFT_HZ ticks).
         */
-       error2 = timekeeper.ntp_error >> (NTP_SCALE_SHIFT + 22 - 2 * SHIFT_HZ);
+       error2 = tk->ntp_error >> (NTP_SCALE_SHIFT + 22 - 2 * SHIFT_HZ);
        error2 = abs(error2);
        for (look_ahead = 0; error2 > 0; look_ahead++)
                error2 >>= 2;
@@ -810,8 +839,8 @@ static __always_inline int timekeeping_bigadjust(s64 error, s64 *interval,
         * Now calculate the error in (1 << look_ahead) ticks, but first
         * remove the single look ahead already included in the error.
         */
-       tick_error = ntp_tick_length() >> (timekeeper.ntp_error_shift + 1);
-       tick_error -= timekeeper.xtime_interval >> 1;
+       tick_error = ntp_tick_length() >> (tk->ntp_error_shift + 1);
+       tick_error -= tk->xtime_interval >> 1;
        error = ((error - tick_error) >> look_ahead) + tick_error;
 
        /* Finally calculate the adjustment shift value.  */
@@ -836,9 +865,9 @@ static __always_inline int timekeeping_bigadjust(s64 error, s64 *interval,
  * this is optimized for the most common adjustments of -1,0,1,
  * for other values we can do a bit more work.
  */
-static void timekeeping_adjust(s64 offset)
+static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
 {
-       s64 error, interval = timekeeper.cycle_interval;
+       s64 error, interval = tk->cycle_interval;
        int adj;
 
        /*
@@ -854,7 +883,7 @@ static void timekeeping_adjust(s64 offset)
         *
         * Note: It does not "save" on aggravation when reading the code.
         */
-       error = timekeeper.ntp_error >> (timekeeper.ntp_error_shift - 1);
+       error = tk->ntp_error >> (tk->ntp_error_shift - 1);
        if (error > interval) {
                /*
                 * We now divide error by 4(via shift), which checks if
@@ -876,7 +905,8 @@ static void timekeeping_adjust(s64 offset)
                if (likely(error <= interval))
                        adj = 1;
                else
-                       adj = timekeeping_bigadjust(error, &interval, &offset);
+                       adj = timekeeping_bigadjust(tk, error, &interval,
+                                                       &offset);
        } else if (error < -interval) {
                /* See comment above, this is just switched for the negative */
                error >>= 2;
@@ -885,18 +915,17 @@ static void timekeeping_adjust(s64 offset)
                        interval = -interval;
                        offset = -offset;
                } else
-                       adj = timekeeping_bigadjust(error, &interval, &offset);
-       } else /* No adjustment needed */
+                       adj = timekeeping_bigadjust(tk, error, &interval,
+                                                       &offset);
+       } else
                return;
 
-       if (unlikely(timekeeper.clock->maxadj &&
-                       (timekeeper.mult + adj >
-                       timekeeper.clock->mult + timekeeper.clock->maxadj))) {
+       if (unlikely(tk->clock->maxadj &&
+               (tk->mult + adj > tk->clock->mult + tk->clock->maxadj))) {
                printk_once(KERN_WARNING
                        "Adjusting %s more than 11%% (%ld vs %ld)\n",
-                       timekeeper.clock->name, (long)timekeeper.mult + adj,
-                       (long)timekeeper.clock->mult +
-                               timekeeper.clock->maxadj);
+                       tk->clock->name, (long)tk->mult + adj,
+                       (long)tk->clock->mult + tk->clock->maxadj);
        }
        /*
         * So the following can be confusing.
@@ -947,11 +976,60 @@ static void timekeeping_adjust(s64 offset)
         *
         * XXX - TODO: Doc ntp_error calculation.
         */
-       timekeeper.mult += adj;
-       timekeeper.xtime_interval += interval;
-       timekeeper.xtime_nsec -= offset;
-       timekeeper.ntp_error -= (interval - offset) <<
-                               timekeeper.ntp_error_shift;
+       tk->mult += adj;
+       tk->xtime_interval += interval;
+       tk->xtime_nsec -= offset;
+       tk->ntp_error -= (interval - offset) << tk->ntp_error_shift;
+
+       /*
+        * It may be possible that when we entered this function, xtime_nsec
+        * was very small.  Further, if we're slightly speeding the clocksource
+        * in the code above, its possible the required corrective factor to
+        * xtime_nsec could cause it to underflow.
+        *
+        * Now, since we already accumulated the second, cannot simply roll
+        * the accumulated second back, since the NTP subsystem has been
+        * notified via second_overflow. So instead we push xtime_nsec forward
+        * by the amount we underflowed, and add that amount into the error.
+        *
+        * We'll correct this error next time through this function, when
+        * xtime_nsec is not as small.
+        */
+       if (unlikely((s64)tk->xtime_nsec < 0)) {
+               s64 neg = -(s64)tk->xtime_nsec;
+               tk->xtime_nsec = 0;
+               tk->ntp_error += neg << tk->ntp_error_shift;
+       }
+
+}
+
+
+/**
+ * accumulate_nsecs_to_secs - Accumulates nsecs into secs
+ *
+ * Helper function that accumulates a the nsecs greater then a second
+ * from the xtime_nsec field to the xtime_secs field.
+ * It also calls into the NTP code to handle leapsecond processing.
+ *
+ */
+static inline void accumulate_nsecs_to_secs(struct timekeeper *tk)
+{
+       u64 nsecps = (u64)NSEC_PER_SEC << tk->shift;
+
+       while (tk->xtime_nsec >= nsecps) {
+               int leap;
+
+               tk->xtime_nsec -= nsecps;
+               tk->xtime_sec++;
+
+               /* Figure out if its a leap sec and apply if needed */
+               leap = second_overflow(tk->xtime_sec);
+               tk->xtime_sec += leap;
+               tk->wall_to_monotonic.tv_sec -= leap;
+               if (leap)
+                       clock_was_set_delayed();
+
+       }
 }
 
 
@@ -964,46 +1042,36 @@ static void timekeeping_adjust(s64 offset)
  *
  * Returns the unconsumed cycles.
  */
-static cycle_t logarithmic_accumulation(cycle_t offset, int shift)
+static cycle_t logarithmic_accumulation(struct timekeeper *tk, cycle_t offset,
+                                               u32 shift)
 {
-       u64 nsecps = (u64)NSEC_PER_SEC << timekeeper.shift;
        u64 raw_nsecs;
 
-       /* If the offset is smaller than a shifted interval, do nothing */
-       if (offset < timekeeper.cycle_interval<<shift)
+       /* If the offset is smaller then a shifted interval, do nothing */
+       if (offset < tk->cycle_interval<<shift)
                return offset;
 
        /* Accumulate one shifted interval */
-       offset -= timekeeper.cycle_interval << shift;
-       timekeeper.clock->cycle_last += timekeeper.cycle_interval << shift;
+       offset -= tk->cycle_interval << shift;
+       tk->clock->cycle_last += tk->cycle_interval << shift;
 
-       timekeeper.xtime_nsec += timekeeper.xtime_interval << shift;
-       while (timekeeper.xtime_nsec >= nsecps) {
-               int leap;
-               timekeeper.xtime_nsec -= nsecps;
-               timekeeper.xtime.tv_sec++;
-               leap = second_overflow(timekeeper.xtime.tv_sec);
-               timekeeper.xtime.tv_sec += leap;
-               timekeeper.wall_to_monotonic.tv_sec -= leap;
-               if (leap)
-                       clock_was_set_delayed();
-       }
+       tk->xtime_nsec += tk->xtime_interval << shift;
+       accumulate_nsecs_to_secs(tk);
 
        /* Accumulate raw time */
-       raw_nsecs = timekeeper.raw_interval << shift;
-       raw_nsecs += timekeeper.raw_time.tv_nsec;
+       raw_nsecs = tk->raw_interval << shift;
+       raw_nsecs += tk->raw_time.tv_nsec;
        if (raw_nsecs >= NSEC_PER_SEC) {
                u64 raw_secs = raw_nsecs;
                raw_nsecs = do_div(raw_secs, NSEC_PER_SEC);
-               timekeeper.raw_time.tv_sec += raw_secs;
+               tk->raw_time.tv_sec += raw_secs;
        }
-       timekeeper.raw_time.tv_nsec = raw_nsecs;
+       tk->raw_time.tv_nsec = raw_nsecs;
 
        /* Accumulate error between NTP and clock interval */
-       timekeeper.ntp_error += ntp_tick_length() << shift;
-       timekeeper.ntp_error -=
-           (timekeeper.xtime_interval + timekeeper.xtime_remainder) <<
-                               (timekeeper.ntp_error_shift + shift);
+       tk->ntp_error += ntp_tick_length() << shift;
+       tk->ntp_error -= (tk->xtime_interval + tk->xtime_remainder) <<
+                                               (tk->ntp_error_shift + shift);
 
        return offset;
 }
@@ -1019,6 +1087,7 @@ static void update_wall_time(void)
        cycle_t offset;
        int shift = 0, maxshift;
        unsigned long flags;
+       s64 remainder;
 
        write_seqlock_irqsave(&timekeeper.lock, flags);
 
@@ -1033,8 +1102,6 @@ static void update_wall_time(void)
 #else
        offset = (clock->read(clock) - clock->cycle_last) & clock->mask;
 #endif
-       timekeeper.xtime_nsec = (s64)timekeeper.xtime.tv_nsec <<
-                                               timekeeper.shift;
 
        /*
         * With NO_HZ we may have to accumulate many cycle_intervals
@@ -1050,64 +1117,36 @@ static void update_wall_time(void)
        maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1;
        shift = min(shift, maxshift);
        while (offset >= timekeeper.cycle_interval) {
-               offset = logarithmic_accumulation(offset, shift);
+               offset = logarithmic_accumulation(&timekeeper, offset, shift);
                if(offset < timekeeper.cycle_interval<<shift)
                        shift--;
        }
 
        /* correct the clock when NTP error is too big */
-       timekeeping_adjust(offset);
-
-       /*
-        * Since in the loop above, we accumulate any amount of time
-        * in xtime_nsec over a second into xtime.tv_sec, its possible for
-        * xtime_nsec to be fairly small after the loop. Further, if we're
-        * slightly speeding the clocksource up in timekeeping_adjust(),
-        * its possible the required corrective factor to xtime_nsec could
-        * cause it to underflow.
-        *
-        * Now, we cannot simply roll the accumulated second back, since
-        * the NTP subsystem has been notified via second_overflow. So
-        * instead we push xtime_nsec forward by the amount we underflowed,
-        * and add that amount into the error.
-        *
-        * We'll correct this error next time through this function, when
-        * xtime_nsec is not as small.
-        */
-       if (unlikely((s64)timekeeper.xtime_nsec < 0)) {
-               s64 neg = -(s64)timekeeper.xtime_nsec;
-               timekeeper.xtime_nsec = 0;
-               timekeeper.ntp_error += neg << timekeeper.ntp_error_shift;
-       }
+       timekeeping_adjust(&timekeeper, offset);
 
 
        /*
-        * Store full nanoseconds into xtime after rounding it up and
-        * add the remainder to the error difference.
-        */
-       timekeeper.xtime.tv_nsec = ((s64)timekeeper.xtime_nsec >>
-                                               timekeeper.shift) + 1;
-       timekeeper.xtime_nsec -= (s64)timekeeper.xtime.tv_nsec <<
-                                               timekeeper.shift;
-       timekeeper.ntp_error += timekeeper.xtime_nsec <<
-                               timekeeper.ntp_error_shift;
+       * Store only full nanoseconds into xtime_nsec after rounding
+       * it up and add the remainder to the error difference.
+       * XXX - This is necessary to avoid small 1ns inconsistnecies caused
+       * by truncating the remainder in vsyscalls. However, it causes
+       * additional work to be done in timekeeping_adjust(). Once
+       * the vsyscall implementations are converted to use xtime_nsec
+       * (shifted nanoseconds), this can be killed.
+       */
+       remainder = timekeeper.xtime_nsec & ((1 << timekeeper.shift) - 1);
+       timekeeper.xtime_nsec -= remainder;
+       timekeeper.xtime_nsec += 1 << timekeeper.shift;
+       timekeeper.ntp_error += remainder << timekeeper.ntp_error_shift;
 
        /*
         * Finally, make sure that after the rounding
-        * xtime.tv_nsec isn't larger than NSEC_PER_SEC
+        * xtime_nsec isn't larger than NSEC_PER_SEC
         */
-       if (unlikely(timekeeper.xtime.tv_nsec >= NSEC_PER_SEC)) {
-               int leap;
-               timekeeper.xtime.tv_nsec -= NSEC_PER_SEC;
-               timekeeper.xtime.tv_sec++;
-               leap = second_overflow(timekeeper.xtime.tv_sec);
-               timekeeper.xtime.tv_sec += leap;
-               timekeeper.wall_to_monotonic.tv_sec -= leap;
-               if (leap)
-                       clock_was_set_delayed();
-       }
+       accumulate_nsecs_to_secs(&timekeeper);
 
-       timekeeping_update(false);
+       timekeeping_update(&timekeeper, false);
 
 out:
        write_sequnlock_irqrestore(&timekeeper.lock, flags);
@@ -1152,21 +1191,20 @@ void get_monotonic_boottime(struct timespec *ts)
 {
        struct timespec tomono, sleep;
        unsigned int seq;
-       s64 nsecs;
 
        WARN_ON(timekeeping_suspended);
 
        do {
                seq = read_seqbegin(&timekeeper.lock);
-               *ts = timekeeper.xtime;
+               ts->tv_sec = timekeeper.xtime_sec;
+               ts->tv_nsec = timekeeping_get_ns(&timekeeper);
                tomono = timekeeper.wall_to_monotonic;
                sleep = timekeeper.total_sleep_time;
-               nsecs = timekeeping_get_ns();
 
        } while (read_seqretry(&timekeeper.lock, seq));
 
        set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec + sleep.tv_sec,
-                       ts->tv_nsec + tomono.tv_nsec + sleep.tv_nsec + nsecs);
+                       ts->tv_nsec + tomono.tv_nsec + sleep.tv_nsec);
 }
 EXPORT_SYMBOL_GPL(get_monotonic_boottime);
 
@@ -1199,13 +1237,13 @@ EXPORT_SYMBOL_GPL(monotonic_to_bootbased);
 
 unsigned long get_seconds(void)
 {
-       return timekeeper.xtime.tv_sec;
+       return timekeeper.xtime_sec;
 }
 EXPORT_SYMBOL(get_seconds);
 
 struct timespec __current_kernel_time(void)
 {
-       return timekeeper.xtime;
+       return tk_xtime(&timekeeper);
 }
 
 struct timespec current_kernel_time(void)
@@ -1216,7 +1254,7 @@ struct timespec current_kernel_time(void)
        do {
                seq = read_seqbegin(&timekeeper.lock);
 
-               now = timekeeper.xtime;
+               now = tk_xtime(&timekeeper);
        } while (read_seqretry(&timekeeper.lock, seq));
 
        return now;
@@ -1231,7 +1269,7 @@ struct timespec get_monotonic_coarse(void)
        do {
                seq = read_seqbegin(&timekeeper.lock);
 
-               now = timekeeper.xtime;
+               now = tk_xtime(&timekeeper);
                mono = timekeeper.wall_to_monotonic;
        } while (read_seqretry(&timekeeper.lock, seq));
 
@@ -1266,7 +1304,7 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,
 
        do {
                seq = read_seqbegin(&timekeeper.lock);
-               *xtim = timekeeper.xtime;
+               *xtim = tk_xtime(&timekeeper);
                *wtom = timekeeper.wall_to_monotonic;
                *sleep = timekeeper.total_sleep_time;
        } while (read_seqretry(&timekeeper.lock, seq));
@@ -1290,11 +1328,8 @@ ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot)
        do {
                seq = read_seqbegin(&timekeeper.lock);
 
-               secs = timekeeper.xtime.tv_sec;
-               nsecs = timekeeper.xtime.tv_nsec;
-               nsecs += timekeeping_get_ns();
-               /* If arch requires, add in gettimeoffset() */
-               nsecs += arch_gettimeoffset();
+               secs = timekeeper.xtime_sec;
+               nsecs = timekeeping_get_ns(&timekeeper);
 
                *offs_real = timekeeper.offs_real;
                *offs_boot = timekeeper.offs_boot;
index 3258455549f421d3b65e0d085929541f672b29b0..af5a7e9f164b53b3bedbc32ac0b516c7091760db 100644 (file)
@@ -167,7 +167,7 @@ static void print_cpu(struct seq_file *m, int cpu, u64 now)
        {
                struct tick_sched *ts = tick_get_tick_sched(cpu);
                P(nohz_mode);
-               P_ns(idle_tick);
+               P_ns(last_tick);
                P(tick_stopped);
                P(idle_jiffies);
                P(idle_calls);
@@ -259,7 +259,7 @@ static int timer_list_show(struct seq_file *m, void *v)
        u64 now = ktime_to_ns(ktime_get());
        int cpu;
 
-       SEQ_printf(m, "Timer List Version: v0.6\n");
+       SEQ_printf(m, "Timer List Version: v0.7\n");
        SEQ_printf(m, "HRTIMER_MAX_CLOCK_BASES: %d\n", HRTIMER_MAX_CLOCK_BASES);
        SEQ_printf(m, "now at %Ld nsecs\n", (unsigned long long)now);
 
index 6ec7e7e0db435d722cecd601090ca4a8b3dc994a..a61c09374ebab1fdba0bdd370b56cf70018de62d 100644 (file)
@@ -77,6 +77,7 @@ struct tvec_base {
        struct timer_list *running_timer;
        unsigned long timer_jiffies;
        unsigned long next_timer;
+       unsigned long active_timers;
        struct tvec_root tv1;
        struct tvec tv2;
        struct tvec tv3;
@@ -330,7 +331,8 @@ void set_timer_slack(struct timer_list *timer, int slack_hz)
 }
 EXPORT_SYMBOL_GPL(set_timer_slack);
 
-static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
+static void
+__internal_add_timer(struct tvec_base *base, struct timer_list *timer)
 {
        unsigned long expires = timer->expires;
        unsigned long idx = expires - base->timer_jiffies;
@@ -372,6 +374,19 @@ static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
        list_add_tail(&timer->entry, vec);
 }
 
+static void internal_add_timer(struct tvec_base *base, struct timer_list *timer)
+{
+       __internal_add_timer(base, timer);
+       /*
+        * Update base->active_timers and base->next_timer
+        */
+       if (!tbase_get_deferrable(timer->base)) {
+               if (time_before(timer->expires, base->next_timer))
+                       base->next_timer = timer->expires;
+               base->active_timers++;
+       }
+}
+
 #ifdef CONFIG_TIMER_STATS
 void __timer_stats_timer_set_start_info(struct timer_list *timer, void *addr)
 {
@@ -654,8 +669,7 @@ void init_timer_deferrable_key(struct timer_list *timer,
 }
 EXPORT_SYMBOL(init_timer_deferrable_key);
 
-static inline void detach_timer(struct timer_list *timer,
-                               int clear_pending)
+static inline void detach_timer(struct timer_list *timer, bool clear_pending)
 {
        struct list_head *entry = &timer->entry;
 
@@ -667,6 +681,29 @@ static inline void detach_timer(struct timer_list *timer,
        entry->prev = LIST_POISON2;
 }
 
+static inline void
+detach_expired_timer(struct timer_list *timer, struct tvec_base *base)
+{
+       detach_timer(timer, true);
+       if (!tbase_get_deferrable(timer->base))
+               timer->base->active_timers--;
+}
+
+static int detach_if_pending(struct timer_list *timer, struct tvec_base *base,
+                            bool clear_pending)
+{
+       if (!timer_pending(timer))
+               return 0;
+
+       detach_timer(timer, clear_pending);
+       if (!tbase_get_deferrable(timer->base)) {
+               timer->base->active_timers--;
+               if (timer->expires == base->next_timer)
+                       base->next_timer = base->timer_jiffies;
+       }
+       return 1;
+}
+
 /*
  * We are using hashed locking: holding per_cpu(tvec_bases).lock
  * means that all timers which are tied to this base via timer->base are
@@ -712,16 +749,9 @@ __mod_timer(struct timer_list *timer, unsigned long expires,
 
        base = lock_timer_base(timer, &flags);
 
-       if (timer_pending(timer)) {
-               detach_timer(timer, 0);
-               if (timer->expires == base->next_timer &&
-                   !tbase_get_deferrable(timer->base))
-                       base->next_timer = base->timer_jiffies;
-               ret = 1;
-       } else {
-               if (pending_only)
-                       goto out_unlock;
-       }
+       ret = detach_if_pending(timer, base, false);
+       if (!ret && pending_only)
+               goto out_unlock;
 
        debug_activate(timer, expires);
 
@@ -752,9 +782,6 @@ __mod_timer(struct timer_list *timer, unsigned long expires,
        }
 
        timer->expires = expires;
-       if (time_before(timer->expires, base->next_timer) &&
-           !tbase_get_deferrable(timer->base))
-               base->next_timer = timer->expires;
        internal_add_timer(base, timer);
 
 out_unlock:
@@ -920,9 +947,6 @@ void add_timer_on(struct timer_list *timer, int cpu)
        spin_lock_irqsave(&base->lock, flags);
        timer_set_base(timer, base);
        debug_activate(timer, timer->expires);
-       if (time_before(timer->expires, base->next_timer) &&
-           !tbase_get_deferrable(timer->base))
-               base->next_timer = timer->expires;
        internal_add_timer(base, timer);
        /*
         * Check whether the other CPU is idle and needs to be
@@ -959,13 +983,7 @@ int del_timer(struct timer_list *timer)
        timer_stats_timer_clear_start_info(timer);
        if (timer_pending(timer)) {
                base = lock_timer_base(timer, &flags);
-               if (timer_pending(timer)) {
-                       detach_timer(timer, 1);
-                       if (timer->expires == base->next_timer &&
-                           !tbase_get_deferrable(timer->base))
-                               base->next_timer = base->timer_jiffies;
-                       ret = 1;
-               }
+               ret = detach_if_pending(timer, base, true);
                spin_unlock_irqrestore(&base->lock, flags);
        }
 
@@ -990,19 +1008,10 @@ int try_to_del_timer_sync(struct timer_list *timer)
 
        base = lock_timer_base(timer, &flags);
 
-       if (base->running_timer == timer)
-               goto out;
-
-       timer_stats_timer_clear_start_info(timer);
-       ret = 0;
-       if (timer_pending(timer)) {
-               detach_timer(timer, 1);
-               if (timer->expires == base->next_timer &&
-                   !tbase_get_deferrable(timer->base))
-                       base->next_timer = base->timer_jiffies;
-               ret = 1;
+       if (base->running_timer != timer) {
+               timer_stats_timer_clear_start_info(timer);
+               ret = detach_if_pending(timer, base, true);
        }
-out:
        spin_unlock_irqrestore(&base->lock, flags);
 
        return ret;
@@ -1089,7 +1098,8 @@ static int cascade(struct tvec_base *base, struct tvec *tv, int index)
         */
        list_for_each_entry_safe(timer, tmp, &tv_list, entry) {
                BUG_ON(tbase_get_base(timer->base) != base);
-               internal_add_timer(base, timer);
+               /* No accounting, while moving them */
+               __internal_add_timer(base, timer);
        }
 
        return index;
@@ -1178,7 +1188,7 @@ static inline void __run_timers(struct tvec_base *base)
                        timer_stats_account_timer(timer);
 
                        base->running_timer = timer;
-                       detach_timer(timer, 1);
+                       detach_expired_timer(timer, base);
 
                        spin_unlock_irq(&base->lock);
                        call_timer_fn(timer, fn, data);
@@ -1316,18 +1326,21 @@ static unsigned long cmp_next_hrtimer_event(unsigned long now,
 unsigned long get_next_timer_interrupt(unsigned long now)
 {
        struct tvec_base *base = __this_cpu_read(tvec_bases);
-       unsigned long expires;
+       unsigned long expires = now + NEXT_TIMER_MAX_DELTA;
 
        /*
         * Pretend that there is no timer pending if the cpu is offline.
         * Possible pending timers will be migrated later to an active cpu.
         */
        if (cpu_is_offline(smp_processor_id()))
-               return now + NEXT_TIMER_MAX_DELTA;
+               return expires;
+
        spin_lock(&base->lock);
-       if (time_before_eq(base->next_timer, base->timer_jiffies))
-               base->next_timer = __next_timer_interrupt(base);
-       expires = base->next_timer;
+       if (base->active_timers) {
+               if (time_before_eq(base->next_timer, base->timer_jiffies))
+                       base->next_timer = __next_timer_interrupt(base);
+               expires = base->next_timer;
+       }
        spin_unlock(&base->lock);
 
        if (time_before_eq(expires, now))
@@ -1704,6 +1717,7 @@ static int __cpuinit init_timers_cpu(int cpu)
 
        base->timer_jiffies = jiffies;
        base->next_timer = base->timer_jiffies;
+       base->active_timers = 0;
        return 0;
 }
 
@@ -1714,11 +1728,9 @@ static void migrate_timer_list(struct tvec_base *new_base, struct list_head *hea
 
        while (!list_empty(head)) {
                timer = list_first_entry(head, struct timer_list, entry);
-               detach_timer(timer, 0);
+               /* We ignore the accounting on the dying cpu */
+               detach_timer(timer, false);
                timer_set_base(timer, new_base);
-               if (time_before(timer->expires, new_base->next_timer) &&
-                   !tbase_get_deferrable(timer->base))
-                       new_base->next_timer = timer->expires;
                internal_add_timer(new_base, timer);
        }
 }
index a008663d86c8e740c64c1cc26977a7a199917b9b..b4f20fba09fcc77dc571bdf718bfd04adfb29897 100644 (file)
@@ -312,7 +312,7 @@ static int remove_ftrace_list_ops(struct ftrace_ops **list,
 
 static int __register_ftrace_function(struct ftrace_ops *ops)
 {
-       if (ftrace_disabled)
+       if (unlikely(ftrace_disabled))
                return -ENODEV;
 
        if (FTRACE_WARN_ON(ops == &global_ops))
@@ -4299,16 +4299,12 @@ int register_ftrace_function(struct ftrace_ops *ops)
 
        mutex_lock(&ftrace_lock);
 
-       if (unlikely(ftrace_disabled))
-               goto out_unlock;
-
        ret = __register_ftrace_function(ops);
        if (!ret)
                ret = ftrace_startup(ops, 0);
 
-
- out_unlock:
        mutex_unlock(&ftrace_lock);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(register_ftrace_function);
index f765465bffe47968752e272308d7fb5b63093a65..49491fa7daa2d35546a6e5ba46d73103594c384e 100644 (file)
@@ -3239,6 +3239,10 @@ rb_get_reader_page(struct ring_buffer_per_cpu *cpu_buffer)
        if (cpu_buffer->commit_page == cpu_buffer->reader_page)
                goto out;
 
+       /* Don't bother swapping if the ring buffer is empty */
+       if (rb_num_of_entries(cpu_buffer) == 0)
+               goto out;
+
        /*
         * Reset the reader page to size zero.
         */
index a7fa0702be1cd5b269ed6f15e9624f4b02968b11..a120f98c4112c15b5d6febf78674c00ec459e18d 100644 (file)
@@ -830,6 +830,8 @@ int register_tracer(struct tracer *type)
                current_trace = saved_tracer;
                if (ret) {
                        printk(KERN_CONT "FAILED!\n");
+                       /* Add the warning after printing 'FAILED' */
+                       WARN_ON(1);
                        goto out;
                }
                /* Only reset on passing, to avoid touching corrupted buffers */
@@ -1708,9 +1710,11 @@ EXPORT_SYMBOL_GPL(trace_vprintk);
 
 static void trace_iterator_increment(struct trace_iterator *iter)
 {
+       struct ring_buffer_iter *buf_iter = trace_buffer_iter(iter, iter->cpu);
+
        iter->idx++;
-       if (iter->buffer_iter[iter->cpu])
-               ring_buffer_read(iter->buffer_iter[iter->cpu], NULL);
+       if (buf_iter)
+               ring_buffer_read(buf_iter, NULL);
 }
 
 static struct trace_entry *
@@ -1718,7 +1722,7 @@ peek_next_entry(struct trace_iterator *iter, int cpu, u64 *ts,
                unsigned long *lost_events)
 {
        struct ring_buffer_event *event;
-       struct ring_buffer_iter *buf_iter = iter->buffer_iter[cpu];
+       struct ring_buffer_iter *buf_iter = trace_buffer_iter(iter, cpu);
 
        if (buf_iter)
                event = ring_buffer_iter_peek(buf_iter, ts);
@@ -1856,10 +1860,10 @@ void tracing_iter_reset(struct trace_iterator *iter, int cpu)
 
        tr->data[cpu]->skipped_entries = 0;
 
-       if (!iter->buffer_iter[cpu])
+       buf_iter = trace_buffer_iter(iter, cpu);
+       if (!buf_iter)
                return;
 
-       buf_iter = iter->buffer_iter[cpu];
        ring_buffer_iter_reset(buf_iter);
 
        /*
@@ -2205,13 +2209,15 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter)
 
 int trace_empty(struct trace_iterator *iter)
 {
+       struct ring_buffer_iter *buf_iter;
        int cpu;
 
        /* If we are looking at one CPU buffer, only check that one */
        if (iter->cpu_file != TRACE_PIPE_ALL_CPU) {
                cpu = iter->cpu_file;
-               if (iter->buffer_iter[cpu]) {
-                       if (!ring_buffer_iter_empty(iter->buffer_iter[cpu]))
+               buf_iter = trace_buffer_iter(iter, cpu);
+               if (buf_iter) {
+                       if (!ring_buffer_iter_empty(buf_iter))
                                return 0;
                } else {
                        if (!ring_buffer_empty_cpu(iter->tr->buffer, cpu))
@@ -2221,8 +2227,9 @@ int trace_empty(struct trace_iterator *iter)
        }
 
        for_each_tracing_cpu(cpu) {
-               if (iter->buffer_iter[cpu]) {
-                       if (!ring_buffer_iter_empty(iter->buffer_iter[cpu]))
+               buf_iter = trace_buffer_iter(iter, cpu);
+               if (buf_iter) {
+                       if (!ring_buffer_iter_empty(buf_iter))
                                return 0;
                } else {
                        if (!ring_buffer_empty_cpu(iter->tr->buffer, cpu))
@@ -2381,6 +2388,11 @@ __tracing_open(struct inode *inode, struct file *file)
        if (!iter)
                return ERR_PTR(-ENOMEM);
 
+       iter->buffer_iter = kzalloc(sizeof(*iter->buffer_iter) * num_possible_cpus(),
+                                   GFP_KERNEL);
+       if (!iter->buffer_iter)
+               goto release;
+
        /*
         * We make a copy of the current tracer to avoid concurrent
         * changes on it while we are reading.
@@ -2441,6 +2453,8 @@ __tracing_open(struct inode *inode, struct file *file)
  fail:
        mutex_unlock(&trace_types_lock);
        kfree(iter->trace);
+       kfree(iter->buffer_iter);
+release:
        seq_release_private(inode, file);
        return ERR_PTR(-ENOMEM);
 }
@@ -2481,6 +2495,7 @@ static int tracing_release(struct inode *inode, struct file *file)
        mutex_destroy(&iter->mutex);
        free_cpumask_var(iter->started);
        kfree(iter->trace);
+       kfree(iter->buffer_iter);
        seq_release_private(inode, file);
        return 0;
 }
index 5aec220d2de0de314b4d292eaaeba43c60f34a1a..55e1f7f0db126edf4bbcbe07245a9558b1030bec 100644 (file)
@@ -317,6 +317,14 @@ struct tracer {
 
 #define TRACE_PIPE_ALL_CPU     -1
 
+static inline struct ring_buffer_iter *
+trace_buffer_iter(struct trace_iterator *iter, int cpu)
+{
+       if (iter->buffer_iter && iter->buffer_iter[cpu])
+               return iter->buffer_iter[cpu];
+       return NULL;
+}
+
 int tracer_init(struct tracer *t, struct trace_array *tr);
 int tracing_is_enabled(void);
 void trace_wake_up(void);
index a7d2a4c653d8d893f51652c8cd599bf780359f45..ce27c8ba8d318ffa6337f231e12a680f6deb7720 100644 (file)
@@ -538,7 +538,7 @@ get_return_for_leaf(struct trace_iterator *iter,
                next = &data->ret;
        } else {
 
-               ring_iter = iter->buffer_iter[iter->cpu];
+               ring_iter = trace_buffer_iter(iter, iter->cpu);
 
                /* First peek to compare current entry and the next one */
                if (ring_iter)
index df611a0e76c55b0d47febf4312874e839114bb13..123b189c732c4142965252d80e9d49745127fe39 100644 (file)
@@ -1325,4 +1325,4 @@ __init static int init_events(void)
 
        return 0;
 }
-device_initcall(init_events);
+early_initcall(init_events);
index a9e15403434ef9adcec951800048752b8cbb1275..8269d56dcdaa38a2af895777bfb1a2d873df5f84 100644 (file)
@@ -378,14 +378,6 @@ config MPILIB
          It is used to implement RSA digital signature verification,
          which is used by IMA/EVM digital signature extension.
 
-config MPILIB_EXTRA
-       bool
-       depends on MPILIB
-       help
-         Additional sources of multiprecision maths library from GnuPG.
-         This code is unnecessary for RSA digital signature verification,
-         but can be compiled if needed.
-
 config SIGNATURE
        tristate
        depends on KEYS && CRYPTO
index ff5bdee4716d5206c7f16f4ce67e911f668c97e7..4a186508bf8b98de56872d254cc405f3a47c0cb2 100644 (file)
@@ -714,7 +714,7 @@ config STACKTRACE
 
 config DEBUG_STACK_USAGE
        bool "Stack utilization instrumentation"
-       depends on DEBUG_KERNEL
+       depends on DEBUG_KERNEL && !IA64 && !PARISC
        help
          Enables the display of the minimum amount of free stack which each
          task has ever had available in the sysrq-T and sysrq-P debug output.
index 23a5e031cd8bc43605655da59bce57eadb3304b8..c24c2f7e296fa15e5431ef7dc4a31f8551e37c15 100644 (file)
@@ -87,12 +87,10 @@ void __list_add_rcu(struct list_head *new,
                    struct list_head *prev, struct list_head *next)
 {
        WARN(next->prev != prev,
-               "list_add_rcu corruption. next->prev should be "
-               "prev (%p), but was %p. (next=%p).\n",
+               "list_add_rcu corruption. next->prev should be prev (%p), but was %p. (next=%p).\n",
                prev, next->prev, next);
        WARN(prev->next != next,
-               "list_add_rcu corruption. prev->next should be "
-               "next (%p), but was %p. (prev=%p).\n",
+               "list_add_rcu corruption. prev->next should be next (%p), but was %p. (prev=%p).\n",
                next, prev->next, prev);
        new->next = next;
        new->prev = prev;
index 567d52e74d774860a19c5b87ad6e1709d0d87fc9..45ca90a8639c5284bbe56d76c19ab743abf8c1fa 100644 (file)
@@ -19,14 +19,3 @@ mpi-y = \
        mpih-mul.o                      \
        mpi-pow.o                       \
        mpiutil.o
-
-mpi-$(CONFIG_MPILIB_EXTRA) += \
-       mpi-add.o                       \
-       mpi-div.o                       \
-       mpi-cmp.o                       \
-       mpi-gcd.o                       \
-       mpi-inline.o                    \
-       mpi-inv.o                       \
-       mpi-mpow.o                      \
-       mpi-mul.o                       \
-       mpi-scan.o
diff --git a/lib/mpi/generic_mpi-asm-defs.h b/lib/mpi/generic_mpi-asm-defs.h
deleted file mode 100644 (file)
index 047d1f5..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-/* This file defines some basic constants for the MPI machinery.  We
- * need to define the types on a per-CPU basis, so it is done with
- * this file here.  */
-#define BYTES_PER_MPI_LIMB  (SIZEOF_UNSIGNED_LONG)
diff --git a/lib/mpi/mpi-add.c b/lib/mpi/mpi-add.c
deleted file mode 100644 (file)
index f56b9ba..0000000
+++ /dev/null
@@ -1,234 +0,0 @@
-/* mpi-add.c  -  MPI functions
- *     Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
- *     Copyright (C) 1994, 1996 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG 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.
- *
- * GnuPG 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
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- *      The GNU MP Library itself is published under the LGPL;
- *      however I decided to publish this code under the plain GPL.
- */
-
-#include "mpi-internal.h"
-
-/****************
- * Add the unsigned integer V to the mpi-integer U and store the
- * result in W. U and V may be the same.
- */
-int mpi_add_ui(MPI w, const MPI u, unsigned long v)
-{
-       mpi_ptr_t wp, up;
-       mpi_size_t usize, wsize;
-       int usign, wsign;
-
-       usize = u->nlimbs;
-       usign = u->sign;
-       wsign = 0;
-
-       /* If not space for W (and possible carry), increase space.  */
-       wsize = usize + 1;
-       if (w->alloced < wsize)
-               if (mpi_resize(w, wsize) < 0)
-                       return -ENOMEM;
-
-       /* These must be after realloc (U may be the same as W).  */
-       up = u->d;
-       wp = w->d;
-
-       if (!usize) {           /* simple */
-               wp[0] = v;
-               wsize = v ? 1 : 0;
-       } else if (!usign) {    /* mpi is not negative */
-               mpi_limb_t cy;
-               cy = mpihelp_add_1(wp, up, usize, v);
-               wp[usize] = cy;
-               wsize = usize + cy;
-       } else {                /* The signs are different.  Need exact comparison to determine
-                                * which operand to subtract from which.  */
-               if (usize == 1 && up[0] < v) {
-                       wp[0] = v - up[0];
-                       wsize = 1;
-               } else {
-                       mpihelp_sub_1(wp, up, usize, v);
-                       /* Size can decrease with at most one limb. */
-                       wsize = usize - (wp[usize - 1] == 0);
-                       wsign = 1;
-               }
-       }
-
-       w->nlimbs = wsize;
-       w->sign = wsign;
-       return 0;
-}
-
-int mpi_add(MPI w, MPI u, MPI v)
-{
-       mpi_ptr_t wp, up, vp;
-       mpi_size_t usize, vsize, wsize;
-       int usign, vsign, wsign;
-
-       if (u->nlimbs < v->nlimbs) {    /* Swap U and V. */
-               usize = v->nlimbs;
-               usign = v->sign;
-               vsize = u->nlimbs;
-               vsign = u->sign;
-               wsize = usize + 1;
-               if (RESIZE_IF_NEEDED(w, wsize) < 0)
-                       return -ENOMEM;
-               /* These must be after realloc (u or v may be the same as w).  */
-               up = v->d;
-               vp = u->d;
-       } else {
-               usize = u->nlimbs;
-               usign = u->sign;
-               vsize = v->nlimbs;
-               vsign = v->sign;
-               wsize = usize + 1;
-               if (RESIZE_IF_NEEDED(w, wsize) < 0)
-                       return -ENOMEM;
-               /* These must be after realloc (u or v may be the same as w).  */
-               up = u->d;
-               vp = v->d;
-       }
-       wp = w->d;
-       wsign = 0;
-
-       if (!vsize) {           /* simple */
-               MPN_COPY(wp, up, usize);
-               wsize = usize;
-               wsign = usign;
-       } else if (usign != vsign) {    /* different sign */
-               /* This test is right since USIZE >= VSIZE */
-               if (usize != vsize) {
-                       mpihelp_sub(wp, up, usize, vp, vsize);
-                       wsize = usize;
-                       MPN_NORMALIZE(wp, wsize);
-                       wsign = usign;
-               } else if (mpihelp_cmp(up, vp, usize) < 0) {
-                       mpihelp_sub_n(wp, vp, up, usize);
-                       wsize = usize;
-                       MPN_NORMALIZE(wp, wsize);
-                       if (!usign)
-                               wsign = 1;
-               } else {
-                       mpihelp_sub_n(wp, up, vp, usize);
-                       wsize = usize;
-                       MPN_NORMALIZE(wp, wsize);
-                       if (usign)
-                               wsign = 1;
-               }
-       } else {                /* U and V have same sign. Add them. */
-               mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
-               wp[usize] = cy;
-               wsize = usize + cy;
-               if (usign)
-                       wsign = 1;
-       }
-
-       w->nlimbs = wsize;
-       w->sign = wsign;
-       return 0;
-}
-
-/****************
- * Subtract the unsigned integer V from the mpi-integer U and store the
- * result in W.
- */
-int mpi_sub_ui(MPI w, MPI u, unsigned long v)
-{
-       mpi_ptr_t wp, up;
-       mpi_size_t usize, wsize;
-       int usign, wsign;
-
-       usize = u->nlimbs;
-       usign = u->sign;
-       wsign = 0;
-
-       /* If not space for W (and possible carry), increase space.  */
-       wsize = usize + 1;
-       if (w->alloced < wsize)
-               if (mpi_resize(w, wsize) < 0)
-                       return -ENOMEM;
-
-       /* These must be after realloc (U may be the same as W).  */
-       up = u->d;
-       wp = w->d;
-
-       if (!usize) {           /* simple */
-               wp[0] = v;
-               wsize = v ? 1 : 0;
-               wsign = 1;
-       } else if (usign) {     /* mpi and v are negative */
-               mpi_limb_t cy;
-               cy = mpihelp_add_1(wp, up, usize, v);
-               wp[usize] = cy;
-               wsize = usize + cy;
-       } else {                /* The signs are different.  Need exact comparison to determine
-                                * which operand to subtract from which.  */
-               if (usize == 1 && up[0] < v) {
-                       wp[0] = v - up[0];
-                       wsize = 1;
-                       wsign = 1;
-               } else {
-                       mpihelp_sub_1(wp, up, usize, v);
-                       /* Size can decrease with at most one limb. */
-                       wsize = usize - (wp[usize - 1] == 0);
-               }
-       }
-
-       w->nlimbs = wsize;
-       w->sign = wsign;
-       return 0;
-}
-
-int mpi_sub(MPI w, MPI u, MPI v)
-{
-       int rc;
-
-       if (w == v) {
-               MPI vv;
-               if (mpi_copy(&vv, v) < 0)
-                       return -ENOMEM;
-               vv->sign = !vv->sign;
-               rc = mpi_add(w, u, vv);
-               mpi_free(vv);
-       } else {
-               /* fixme: this is not thread-save (we temp. modify v) */
-               v->sign = !v->sign;
-               rc = mpi_add(w, u, v);
-               v->sign = !v->sign;
-       }
-       return rc;
-}
-
-int mpi_addm(MPI w, MPI u, MPI v, MPI m)
-{
-       if (mpi_add(w, u, v) < 0 || mpi_fdiv_r(w, w, m) < 0)
-               return -ENOMEM;
-       return 0;
-}
-
-int mpi_subm(MPI w, MPI u, MPI v, MPI m)
-{
-       if (mpi_sub(w, u, v) < 0 || mpi_fdiv_r(w, w, m) < 0)
-               return -ENOMEM;
-       return 0;
-}
index 0c505361da197a9a46c8b2665af7b5520ad11974..568724804f291a8581444baa7f18b4e71447bca4 100644 (file)
@@ -54,165 +54,3 @@ unsigned mpi_get_nbits(MPI a)
        return n;
 }
 EXPORT_SYMBOL_GPL(mpi_get_nbits);
-
-/****************
- * Test whether bit N is set.
- */
-int mpi_test_bit(MPI a, unsigned n)
-{
-       unsigned limbno, bitno;
-       mpi_limb_t limb;
-
-       limbno = n / BITS_PER_MPI_LIMB;
-       bitno = n % BITS_PER_MPI_LIMB;
-
-       if (limbno >= a->nlimbs)
-               return 0;       /* too far left: this is a 0 */
-       limb = a->d[limbno];
-       return (limb & (A_LIMB_1 << bitno)) ? 1 : 0;
-}
-
-/****************
- * Set bit N of A.
- */
-int mpi_set_bit(MPI a, unsigned n)
-{
-       unsigned limbno, bitno;
-
-       limbno = n / BITS_PER_MPI_LIMB;
-       bitno = n % BITS_PER_MPI_LIMB;
-
-       if (limbno >= a->nlimbs) {      /* resize */
-               if (a->alloced >= limbno)
-                       if (mpi_resize(a, limbno + 1) < 0)
-                               return -ENOMEM;
-               a->nlimbs = limbno + 1;
-       }
-       a->d[limbno] |= (A_LIMB_1 << bitno);
-       return 0;
-}
-
-/****************
- * Set bit N of A. and clear all bits above
- */
-int mpi_set_highbit(MPI a, unsigned n)
-{
-       unsigned limbno, bitno;
-
-       limbno = n / BITS_PER_MPI_LIMB;
-       bitno = n % BITS_PER_MPI_LIMB;
-
-       if (limbno >= a->nlimbs) {      /* resize */
-               if (a->alloced >= limbno)
-                       if (mpi_resize(a, limbno + 1) < 0)
-                               return -ENOMEM;
-               a->nlimbs = limbno + 1;
-       }
-       a->d[limbno] |= (A_LIMB_1 << bitno);
-       for (bitno++; bitno < BITS_PER_MPI_LIMB; bitno++)
-               a->d[limbno] &= ~(A_LIMB_1 << bitno);
-       a->nlimbs = limbno + 1;
-       return 0;
-}
-
-/****************
- * clear bit N of A and all bits above
- */
-void mpi_clear_highbit(MPI a, unsigned n)
-{
-       unsigned limbno, bitno;
-
-       limbno = n / BITS_PER_MPI_LIMB;
-       bitno = n % BITS_PER_MPI_LIMB;
-
-       if (limbno >= a->nlimbs)
-               return;         /* not allocated, so need to clear bits :-) */
-
-       for (; bitno < BITS_PER_MPI_LIMB; bitno++)
-               a->d[limbno] &= ~(A_LIMB_1 << bitno);
-       a->nlimbs = limbno + 1;
-}
-
-/****************
- * Clear bit N of A.
- */
-void mpi_clear_bit(MPI a, unsigned n)
-{
-       unsigned limbno, bitno;
-
-       limbno = n / BITS_PER_MPI_LIMB;
-       bitno = n % BITS_PER_MPI_LIMB;
-
-       if (limbno >= a->nlimbs)
-               return;         /* don't need to clear this bit, it's to far to left */
-       a->d[limbno] &= ~(A_LIMB_1 << bitno);
-}
-
-/****************
- * Shift A by N bits to the right
- * FIXME: should use alloc_limb if X and A are same.
- */
-int mpi_rshift(MPI x, MPI a, unsigned n)
-{
-       mpi_ptr_t xp;
-       mpi_size_t xsize;
-
-       xsize = a->nlimbs;
-       x->sign = a->sign;
-       if (RESIZE_IF_NEEDED(x, (size_t) xsize) < 0)
-               return -ENOMEM;
-       xp = x->d;
-
-       if (xsize) {
-               mpihelp_rshift(xp, a->d, xsize, n);
-               MPN_NORMALIZE(xp, xsize);
-       }
-       x->nlimbs = xsize;
-       return 0;
-}
-
-/****************
- * Shift A by COUNT limbs to the left
- * This is used only within the MPI library
- */
-int mpi_lshift_limbs(MPI a, unsigned int count)
-{
-       const int n = a->nlimbs;
-       mpi_ptr_t ap;
-       int i;
-
-       if (!count || !n)
-               return 0;
-
-       if (RESIZE_IF_NEEDED(a, n + count) < 0)
-               return -ENOMEM;
-
-       ap = a->d;
-       for (i = n - 1; i >= 0; i--)
-               ap[i + count] = ap[i];
-       for (i = 0; i < count; i++)
-               ap[i] = 0;
-       a->nlimbs += count;
-       return 0;
-}
-
-/****************
- * Shift A by COUNT limbs to the right
- * This is used only within the MPI library
- */
-void mpi_rshift_limbs(MPI a, unsigned int count)
-{
-       mpi_ptr_t ap = a->d;
-       mpi_size_t n = a->nlimbs;
-       unsigned int i;
-
-       if (count >= n) {
-               a->nlimbs = 0;
-               return;
-       }
-
-       for (i = 0; i < n - count; i++)
-               ap[i] = ap[i + count];
-       ap[i] = 0;
-       a->nlimbs -= count;
-}
diff --git a/lib/mpi/mpi-cmp.c b/lib/mpi/mpi-cmp.c
deleted file mode 100644 (file)
index 914bc42..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* mpi-cmp.c  -  MPI functions
- * Copyright (C) 1998, 1999 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG 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.
- *
- * GnuPG 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 "mpi-internal.h"
-
-int mpi_cmp_ui(MPI u, unsigned long v)
-{
-       mpi_limb_t limb = v;
-
-       mpi_normalize(u);
-       if (!u->nlimbs && !limb)
-               return 0;
-       if (u->sign)
-               return -1;
-       if (u->nlimbs > 1)
-               return 1;
-
-       if (u->d[0] == limb)
-               return 0;
-       else if (u->d[0] > limb)
-               return 1;
-       else
-               return -1;
-}
-
-int mpi_cmp(MPI u, MPI v)
-{
-       mpi_size_t usize, vsize;
-       int cmp;
-
-       mpi_normalize(u);
-       mpi_normalize(v);
-       usize = u->nlimbs;
-       vsize = v->nlimbs;
-       if (!u->sign && v->sign)
-               return 1;
-       if (u->sign && !v->sign)
-               return -1;
-       if (usize != vsize && !u->sign && !v->sign)
-               return usize - vsize;
-       if (usize != vsize && u->sign && v->sign)
-               return vsize + usize;
-       if (!usize)
-               return 0;
-       cmp = mpihelp_cmp(u->d, v->d, usize);
-       if (!cmp)
-               return 0;
-       if ((cmp < 0 ? 1 : 0) == (u->sign ? 1 : 0))
-               return 1;
-       return -1;
-}
diff --git a/lib/mpi/mpi-div.c b/lib/mpi/mpi-div.c
deleted file mode 100644 (file)
index f68cbbb..0000000
+++ /dev/null
@@ -1,338 +0,0 @@
-/* mpi-div.c  -  MPI functions
- *     Copyright (C) 1994, 1996 Free Software Foundation, Inc.
- *     Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG 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.
- *
- * GnuPG 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
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- *      The GNU MP Library itself is published under the LGPL;
- *      however I decided to publish this code under the plain GPL.
- */
-
-#include <linux/string.h>
-#include "mpi-internal.h"
-#include "longlong.h"
-
-int mpi_fdiv_r(MPI rem, MPI dividend, MPI divisor)
-{
-       int rc = -ENOMEM;
-       int divisor_sign = divisor->sign;
-       MPI temp_divisor = NULL;
-
-       /* We need the original value of the divisor after the remainder has been
-        * preliminary calculated.      We have to copy it to temporary space if it's
-        * the same variable as REM.  */
-       if (rem == divisor) {
-               if (mpi_copy(&temp_divisor, divisor) < 0)
-                       goto nomem;
-               divisor = temp_divisor;
-       }
-
-       if (mpi_tdiv_qr(NULL, rem, dividend, divisor) < 0)
-               goto nomem;
-       if (((divisor_sign ? 1 : 0) ^ (dividend->sign ? 1 : 0)) && rem->nlimbs)
-               if (mpi_add(rem, rem, divisor) < 0)
-                       goto nomem;
-
-       rc = 0;
-
-nomem:
-       if (temp_divisor)
-               mpi_free(temp_divisor);
-       return rc;
-}
-
-/****************
- * Division rounding the quotient towards -infinity.
- * The remainder gets the same sign as the denominator.
- * rem is optional
- */
-
-ulong mpi_fdiv_r_ui(MPI rem, MPI dividend, ulong divisor)
-{
-       mpi_limb_t rlimb;
-
-       rlimb = mpihelp_mod_1(dividend->d, dividend->nlimbs, divisor);
-       if (rlimb && dividend->sign)
-               rlimb = divisor - rlimb;
-
-       if (rem) {
-               rem->d[0] = rlimb;
-               rem->nlimbs = rlimb ? 1 : 0;
-       }
-       return rlimb;
-}
-
-int mpi_fdiv_q(MPI quot, MPI dividend, MPI divisor)
-{
-       MPI tmp = mpi_alloc(mpi_get_nlimbs(quot));
-       if (!tmp)
-               return -ENOMEM;
-       mpi_fdiv_qr(quot, tmp, dividend, divisor);
-       mpi_free(tmp);
-       return 0;
-}
-
-int mpi_fdiv_qr(MPI quot, MPI rem, MPI dividend, MPI divisor)
-{
-       int divisor_sign = divisor->sign;
-       MPI temp_divisor = NULL;
-
-       if (quot == divisor || rem == divisor) {
-               if (mpi_copy(&temp_divisor, divisor) < 0)
-                       return -ENOMEM;
-               divisor = temp_divisor;
-       }
-
-       if (mpi_tdiv_qr(quot, rem, dividend, divisor) < 0)
-               goto nomem;
-
-       if ((divisor_sign ^ dividend->sign) && rem->nlimbs) {
-               if (mpi_sub_ui(quot, quot, 1) < 0)
-                       goto nomem;
-               if (mpi_add(rem, rem, divisor) < 0)
-                       goto nomem;
-       }
-
-       if (temp_divisor)
-               mpi_free(temp_divisor);
-
-       return 0;
-
-nomem:
-       mpi_free(temp_divisor);
-       return -ENOMEM;
-}
-
-/* If den == quot, den needs temporary storage.
- * If den == rem, den needs temporary storage.
- * If num == quot, num needs temporary storage.
- * If den has temporary storage, it can be normalized while being copied,
- *   i.e no extra storage should be allocated.
- */
-
-int mpi_tdiv_r(MPI rem, MPI num, MPI den)
-{
-       return mpi_tdiv_qr(NULL, rem, num, den);
-}
-
-int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den)
-{
-       int rc = -ENOMEM;
-       mpi_ptr_t np, dp;
-       mpi_ptr_t qp, rp;
-       mpi_size_t nsize = num->nlimbs;
-       mpi_size_t dsize = den->nlimbs;
-       mpi_size_t qsize, rsize;
-       mpi_size_t sign_remainder = num->sign;
-       mpi_size_t sign_quotient = num->sign ^ den->sign;
-       unsigned normalization_steps;
-       mpi_limb_t q_limb;
-       mpi_ptr_t marker[5];
-       int markidx = 0;
-
-       if (!dsize)
-               return -EINVAL;
-
-       memset(marker, 0, sizeof(marker));
-
-       /* Ensure space is enough for quotient and remainder.
-        * We need space for an extra limb in the remainder, because it's
-        * up-shifted (normalized) below.  */
-       rsize = nsize + 1;
-       if (mpi_resize(rem, rsize) < 0)
-               goto nomem;
-
-       qsize = rsize - dsize;  /* qsize cannot be bigger than this.  */
-       if (qsize <= 0) {
-               if (num != rem) {
-                       rem->nlimbs = num->nlimbs;
-                       rem->sign = num->sign;
-                       MPN_COPY(rem->d, num->d, nsize);
-               }
-               if (quot) {
-                       /* This needs to follow the assignment to rem, in case the
-                        * numerator and quotient are the same.  */
-                       quot->nlimbs = 0;
-                       quot->sign = 0;
-               }
-               return 0;
-       }
-
-       if (quot)
-               if (mpi_resize(quot, qsize) < 0)
-                       goto nomem;
-
-       /* Read pointers here, when reallocation is finished.  */
-       np = num->d;
-       dp = den->d;
-       rp = rem->d;
-
-       /* Optimize division by a single-limb divisor.  */
-       if (dsize == 1) {
-               mpi_limb_t rlimb;
-               if (quot) {
-                       qp = quot->d;
-                       rlimb = mpihelp_divmod_1(qp, np, nsize, dp[0]);
-                       qsize -= qp[qsize - 1] == 0;
-                       quot->nlimbs = qsize;
-                       quot->sign = sign_quotient;
-               } else
-                       rlimb = mpihelp_mod_1(np, nsize, dp[0]);
-               rp[0] = rlimb;
-               rsize = rlimb != 0 ? 1 : 0;
-               rem->nlimbs = rsize;
-               rem->sign = sign_remainder;
-               return 0;
-       }
-
-       if (quot) {
-               qp = quot->d;
-               /* Make sure QP and NP point to different objects.  Otherwise the
-                * numerator would be gradually overwritten by the quotient limbs.  */
-               if (qp == np) { /* Copy NP object to temporary space.  */
-                       np = marker[markidx++] = mpi_alloc_limb_space(nsize);
-                       if (!np)
-                               goto nomem;
-                       MPN_COPY(np, qp, nsize);
-               }
-       } else                  /* Put quotient at top of remainder. */
-               qp = rp + dsize;
-
-       count_leading_zeros(normalization_steps, dp[dsize - 1]);
-
-       /* Normalize the denominator, i.e. make its most significant bit set by
-        * shifting it NORMALIZATION_STEPS bits to the left.  Also shift the
-        * numerator the same number of steps (to keep the quotient the same!).
-        */
-       if (normalization_steps) {
-               mpi_ptr_t tp;
-               mpi_limb_t nlimb;
-
-               /* Shift up the denominator setting the most significant bit of
-                * the most significant word.  Use temporary storage not to clobber
-                * the original contents of the denominator.  */
-               tp = marker[markidx++] = mpi_alloc_limb_space(dsize);
-               if (!tp)
-                       goto nomem;
-               mpihelp_lshift(tp, dp, dsize, normalization_steps);
-               dp = tp;
-
-               /* Shift up the numerator, possibly introducing a new most
-                * significant word.  Move the shifted numerator in the remainder
-                * meanwhile.  */
-               nlimb = mpihelp_lshift(rp, np, nsize, normalization_steps);
-               if (nlimb) {
-                       rp[nsize] = nlimb;
-                       rsize = nsize + 1;
-               } else
-                       rsize = nsize;
-       } else {
-               /* The denominator is already normalized, as required.  Copy it to
-                * temporary space if it overlaps with the quotient or remainder.  */
-               if (dp == rp || (quot && (dp == qp))) {
-                       mpi_ptr_t tp;
-
-                       tp = marker[markidx++] = mpi_alloc_limb_space(dsize);
-                       if (!tp)
-                               goto nomem;
-                       MPN_COPY(tp, dp, dsize);
-                       dp = tp;
-               }
-
-               /* Move the numerator to the remainder.  */
-               if (rp != np)
-                       MPN_COPY(rp, np, nsize);
-
-               rsize = nsize;
-       }
-
-       q_limb = mpihelp_divrem(qp, 0, rp, rsize, dp, dsize);
-
-       if (quot) {
-               qsize = rsize - dsize;
-               if (q_limb) {
-                       qp[qsize] = q_limb;
-                       qsize += 1;
-               }
-
-               quot->nlimbs = qsize;
-               quot->sign = sign_quotient;
-       }
-
-       rsize = dsize;
-       MPN_NORMALIZE(rp, rsize);
-
-       if (normalization_steps && rsize) {
-               mpihelp_rshift(rp, rp, rsize, normalization_steps);
-               rsize -= rp[rsize - 1] == 0 ? 1 : 0;
-       }
-
-       rem->nlimbs = rsize;
-       rem->sign = sign_remainder;
-
-       rc = 0;
-nomem:
-       while (markidx)
-               mpi_free_limb_space(marker[--markidx]);
-       return rc;
-}
-
-int mpi_tdiv_q_2exp(MPI w, MPI u, unsigned count)
-{
-       mpi_size_t usize, wsize;
-       mpi_size_t limb_cnt;
-
-       usize = u->nlimbs;
-       limb_cnt = count / BITS_PER_MPI_LIMB;
-       wsize = usize - limb_cnt;
-       if (limb_cnt >= usize)
-               w->nlimbs = 0;
-       else {
-               mpi_ptr_t wp;
-               mpi_ptr_t up;
-
-               if (RESIZE_IF_NEEDED(w, wsize) < 0)
-                       return -ENOMEM;
-               wp = w->d;
-               up = u->d;
-
-               count %= BITS_PER_MPI_LIMB;
-               if (count) {
-                       mpihelp_rshift(wp, up + limb_cnt, wsize, count);
-                       wsize -= !wp[wsize - 1];
-               } else {
-                       MPN_COPY_INCR(wp, up + limb_cnt, wsize);
-               }
-
-               w->nlimbs = wsize;
-       }
-       return 0;
-}
-
-/****************
- * Check whether dividend is divisible by divisor
- * (note: divisor must fit into a limb)
- */
-int mpi_divisible_ui(MPI dividend, ulong divisor)
-{
-       return !mpihelp_mod_1(dividend->d, dividend->nlimbs, divisor);
-}
diff --git a/lib/mpi/mpi-gcd.c b/lib/mpi/mpi-gcd.c
deleted file mode 100644 (file)
index 13c48ae..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/* mpi-gcd.c  -  MPI functions
- * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG 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.
- *
- * GnuPG 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 "mpi-internal.h"
-
-/****************
- * Find the greatest common divisor G of A and B.
- * Return: true if this 1, false in all other cases
- */
-int mpi_gcd(MPI g, const MPI xa, const MPI xb)
-{
-       MPI a = NULL, b = NULL;
-
-       if (mpi_copy(&a, xa) < 0)
-               goto nomem;
-
-       if (mpi_copy(&b, xb) < 0)
-               goto nomem;
-
-       /* TAOCP Vol II, 4.5.2, Algorithm A */
-       a->sign = 0;
-       b->sign = 0;
-       while (mpi_cmp_ui(b, 0)) {
-               if (mpi_fdiv_r(g, a, b) < 0)    /* g used as temorary variable */
-                       goto nomem;
-               if (mpi_set(a, b) < 0)
-                       goto nomem;
-               if (mpi_set(b, g) < 0)
-                       goto nomem;
-       }
-       if (mpi_set(g, a) < 0)
-               goto nomem;
-
-       mpi_free(a);
-       mpi_free(b);
-       return !mpi_cmp_ui(g, 1);
-
-nomem:
-       mpi_free(a);
-       mpi_free(b);
-       return -ENOMEM;
-}
diff --git a/lib/mpi/mpi-inline.c b/lib/mpi/mpi-inline.c
deleted file mode 100644 (file)
index 654f68a..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/* mpi-inline.c
- * Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG 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.
- *
- * GnuPG 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
- */
-
-/* put the inline functions as real functions into the lib */
-#define G10_MPI_INLINE_DECL
-
-#include "mpi-internal.h"
-
-/* always include the header becuase it is only
- * included by mpi-internal if __GCC__ is defined but we
- * need it here in all cases and the above definition of
- * of the macro allows us to do so
- */
-#include "mpi-inline.h"
diff --git a/lib/mpi/mpi-inv.c b/lib/mpi/mpi-inv.c
deleted file mode 100644 (file)
index 0951f98..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-/* mpi-inv.c  -  MPI functions
- * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG 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.
- *
- * GnuPG 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 "mpi-internal.h"
-
-/****************
- * Calculate the multiplicative inverse X of A mod N
- * That is: Find the solution x for
- *             1 = (a*x) mod n
- */
-int mpi_invm(MPI x, const MPI a, const MPI n)
-{
-       /* Extended Euclid's algorithm (See TAOPC Vol II, 4.5.2, Alg X)
-        * modified according to Michael Penk's solution for Exercice 35
-        * with further enhancement */
-       MPI u = NULL, v = NULL;
-       MPI u1 = NULL, u2 = NULL, u3 = NULL;
-       MPI v1 = NULL, v2 = NULL, v3 = NULL;
-       MPI t1 = NULL, t2 = NULL, t3 = NULL;
-       unsigned k;
-       int sign;
-       int odd = 0;
-       int rc = -ENOMEM;
-
-       if (mpi_copy(&u, a) < 0)
-               goto cleanup;
-       if (mpi_copy(&v, n) < 0)
-               goto cleanup;
-
-       for (k = 0; !mpi_test_bit(u, 0) && !mpi_test_bit(v, 0); k++) {
-               if (mpi_rshift(u, u, 1) < 0)
-                       goto cleanup;
-               if (mpi_rshift(v, v, 1) < 0)
-                       goto cleanup;
-       }
-       odd = mpi_test_bit(v, 0);
-
-       u1 = mpi_alloc_set_ui(1);
-       if (!u1)
-               goto cleanup;
-       if (!odd) {
-               u2 = mpi_alloc_set_ui(0);
-               if (!u2)
-                       goto cleanup;
-       }
-       if (mpi_copy(&u3, u) < 0)
-               goto cleanup;
-       if (mpi_copy(&v1, v) < 0)
-               goto cleanup;
-       if (!odd) {
-               v2 = mpi_alloc(mpi_get_nlimbs(u));
-               if (!v2)
-                       goto cleanup;
-               if (mpi_sub(v2, u1, u) < 0)
-                       goto cleanup;   /* U is used as const 1 */
-       }
-       if (mpi_copy(&v3, v) < 0)
-               goto cleanup;
-       if (mpi_test_bit(u, 0)) {       /* u is odd */
-               t1 = mpi_alloc_set_ui(0);
-               if (!t1)
-                       goto cleanup;
-               if (!odd) {
-                       t2 = mpi_alloc_set_ui(1);
-                       if (!t2)
-                               goto cleanup;
-                       t2->sign = 1;
-               }
-               if (mpi_copy(&t3, v) < 0)
-                       goto cleanup;
-               t3->sign = !t3->sign;
-               goto Y4;
-       } else {
-               t1 = mpi_alloc_set_ui(1);
-               if (!t1)
-                       goto cleanup;
-               if (!odd) {
-                       t2 = mpi_alloc_set_ui(0);
-                       if (!t2)
-                               goto cleanup;
-               }
-               if (mpi_copy(&t3, u) < 0)
-                       goto cleanup;
-       }
-       do {
-               do {
-                       if (!odd) {
-                               if (mpi_test_bit(t1, 0) || mpi_test_bit(t2, 0)) {       /* one is odd */
-                                       if (mpi_add(t1, t1, v) < 0)
-                                               goto cleanup;
-                                       if (mpi_sub(t2, t2, u) < 0)
-                                               goto cleanup;
-                               }
-                               if (mpi_rshift(t1, t1, 1) < 0)
-                                       goto cleanup;
-                               if (mpi_rshift(t2, t2, 1) < 0)
-                                       goto cleanup;
-                               if (mpi_rshift(t3, t3, 1) < 0)
-                                       goto cleanup;
-                       } else {
-                               if (mpi_test_bit(t1, 0))
-                                       if (mpi_add(t1, t1, v) < 0)
-                                               goto cleanup;
-                               if (mpi_rshift(t1, t1, 1) < 0)
-                                       goto cleanup;
-                               if (mpi_rshift(t3, t3, 1) < 0)
-                                       goto cleanup;
-                       }
-Y4:
-                       ;
-               } while (!mpi_test_bit(t3, 0)); /* while t3 is even */
-
-               if (!t3->sign) {
-                       if (mpi_set(u1, t1) < 0)
-                               goto cleanup;
-                       if (!odd)
-                               if (mpi_set(u2, t2) < 0)
-                                       goto cleanup;
-                       if (mpi_set(u3, t3) < 0)
-                               goto cleanup;
-               } else {
-                       if (mpi_sub(v1, v, t1) < 0)
-                               goto cleanup;
-                       sign = u->sign;
-                       u->sign = !u->sign;
-                       if (!odd)
-                               if (mpi_sub(v2, u, t2) < 0)
-                                       goto cleanup;
-                       u->sign = sign;
-                       sign = t3->sign;
-                       t3->sign = !t3->sign;
-                       if (mpi_set(v3, t3) < 0)
-                               goto cleanup;
-                       t3->sign = sign;
-               }
-               if (mpi_sub(t1, u1, v1) < 0)
-                       goto cleanup;
-               if (!odd)
-                       if (mpi_sub(t2, u2, v2) < 0)
-                               goto cleanup;
-               if (mpi_sub(t3, u3, v3) < 0)
-                       goto cleanup;
-               if (t1->sign) {
-                       if (mpi_add(t1, t1, v) < 0)
-                               goto cleanup;
-                       if (!odd)
-                               if (mpi_sub(t2, t2, u) < 0)
-                                       goto cleanup;
-               }
-       } while (mpi_cmp_ui(t3, 0));    /* while t3 != 0 */
-       /* mpi_lshift( u3, k ); */
-       rc = mpi_set(x, u1);
-
-cleanup:
-       mpi_free(u1);
-       mpi_free(v1);
-       mpi_free(t1);
-       if (!odd) {
-               mpi_free(u2);
-               mpi_free(v2);
-               mpi_free(t2);
-       }
-       mpi_free(u3);
-       mpi_free(v3);
-       mpi_free(t3);
-
-       mpi_free(u);
-       mpi_free(v);
-       return rc;
-}
diff --git a/lib/mpi/mpi-mpow.c b/lib/mpi/mpi-mpow.c
deleted file mode 100644 (file)
index 7328d0d..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/* mpi-mpow.c  -  MPI functions
- * Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG 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.
- *
- * GnuPG 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 "mpi-internal.h"
-#include "longlong.h"
-
-static int build_index(const MPI *exparray, int k, int i, int t)
-{
-       int j, bitno;
-       int index = 0;
-
-       bitno = t - i;
-       for (j = k - 1; j >= 0; j--) {
-               index <<= 1;
-               if (mpi_test_bit(exparray[j], bitno))
-                       index |= 1;
-       }
-       return index;
-}
-
-/****************
- * RES = (BASE[0] ^ EXP[0]) *  (BASE[1] ^ EXP[1]) * ... * mod M
- */
-int mpi_mulpowm(MPI res, MPI *basearray, MPI *exparray, MPI m)
-{
-       int rc = -ENOMEM;
-       int k;                  /* number of elements */
-       int t;                  /* bit size of largest exponent */
-       int i, j, idx;
-       MPI *G = NULL;          /* table with precomputed values of size 2^k */
-       MPI tmp = NULL;
-
-       for (k = 0; basearray[k]; k++)
-               ;
-       if (!k) {
-               pr_emerg("mpi_mulpowm: assert(k) failed\n");
-               BUG();
-       }
-       for (t = 0, i = 0; (tmp = exparray[i]); i++) {
-               j = mpi_get_nbits(tmp);
-               if (j > t)
-                       t = j;
-       }
-       if (i != k) {
-               pr_emerg("mpi_mulpowm: assert(i==k) failed\n");
-               BUG();
-       }
-       if (!t) {
-               pr_emerg("mpi_mulpowm: assert(t) failed\n");
-               BUG();
-       }
-       if (k >= 10) {
-               pr_emerg("mpi_mulpowm: assert(k<10) failed\n");
-               BUG();
-       }
-
-       G = kzalloc((1 << k) * sizeof *G, GFP_KERNEL);
-       if (!G)
-               goto err_out;
-
-       /* and calculate */
-       tmp = mpi_alloc(mpi_get_nlimbs(m) + 1);
-       if (!tmp)
-               goto nomem;
-       if (mpi_set_ui(res, 1) < 0)
-               goto nomem;
-       for (i = 1; i <= t; i++) {
-               if (mpi_mulm(tmp, res, res, m) < 0)
-                       goto nomem;
-               idx = build_index(exparray, k, i, t);
-               if (!(idx >= 0 && idx < (1 << k))) {
-                       pr_emerg("mpi_mulpowm: assert(idx >= 0 && idx < (1<<k)) failed\n");
-                       BUG();
-               }
-               if (!G[idx]) {
-                       if (!idx) {
-                               G[0] = mpi_alloc_set_ui(1);
-                               if (!G[0])
-                                       goto nomem;
-                       } else {
-                               for (j = 0; j < k; j++) {
-                                       if ((idx & (1 << j))) {
-                                               if (!G[idx]) {
-                                                       if (mpi_copy
-                                                           (&G[idx],
-                                                            basearray[j]) < 0)
-                                                               goto nomem;
-                                               } else {
-                                                       if (mpi_mulm
-                                                           (G[idx], G[idx],
-                                                            basearray[j],
-                                                            m) < 0)
-                                                               goto nomem;
-                                               }
-                                       }
-                               }
-                               if (!G[idx]) {
-                                       G[idx] = mpi_alloc(0);
-                                       if (!G[idx])
-                                               goto nomem;
-                               }
-                       }
-               }
-               if (mpi_mulm(res, tmp, G[idx], m) < 0)
-                       goto nomem;
-       }
-
-       rc = 0;
-nomem:
-       /* cleanup */
-       mpi_free(tmp);
-       for (i = 0; i < (1 << k); i++)
-               mpi_free(G[i]);
-       kfree(G);
-err_out:
-       return rc;
-}
diff --git a/lib/mpi/mpi-mul.c b/lib/mpi/mpi-mul.c
deleted file mode 100644 (file)
index 1f3219e..0000000
+++ /dev/null
@@ -1,194 +0,0 @@
-/* mpi-mul.c  -  MPI functions
- *     Copyright (C) 1994, 1996 Free Software Foundation, Inc.
- *     Copyright (C) 1998, 2001 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG 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.
- *
- * GnuPG 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
- *
- * Note: This code is heavily based on the GNU MP Library.
- *      Actually it's the same code with only minor changes in the
- *      way the data is stored; this is to support the abstraction
- *      of an optional secure memory allocation which may be used
- *      to avoid revealing of sensitive data due to paging etc.
- *      The GNU MP Library itself is published under the LGPL;
- *      however I decided to publish this code under the plain GPL.
- */
-
-#include "mpi-internal.h"
-
-int mpi_mul_ui(MPI prod, MPI mult, unsigned long small_mult)
-{
-       mpi_size_t size, prod_size;
-       mpi_ptr_t prod_ptr;
-       mpi_limb_t cy;
-       int sign;
-
-       size = mult->nlimbs;
-       sign = mult->sign;
-
-       if (!size || !small_mult) {
-               prod->nlimbs = 0;
-               prod->sign = 0;
-               return 0;
-       }
-
-       prod_size = size + 1;
-       if (prod->alloced < prod_size)
-               if (mpi_resize(prod, prod_size) < 0)
-                       return -ENOMEM;
-       prod_ptr = prod->d;
-
-       cy = mpihelp_mul_1(prod_ptr, mult->d, size, (mpi_limb_t) small_mult);
-       if (cy)
-               prod_ptr[size++] = cy;
-       prod->nlimbs = size;
-       prod->sign = sign;
-       return 0;
-}
-
-int mpi_mul_2exp(MPI w, MPI u, unsigned long cnt)
-{
-       mpi_size_t usize, wsize, limb_cnt;
-       mpi_ptr_t wp;
-       mpi_limb_t wlimb;
-       int usign, wsign;
-
-       usize = u->nlimbs;
-       usign = u->sign;
-
-       if (!usize) {
-               w->nlimbs = 0;
-               w->sign = 0;
-               return 0;
-       }
-
-       limb_cnt = cnt / BITS_PER_MPI_LIMB;
-       wsize = usize + limb_cnt + 1;
-       if (w->alloced < wsize)
-               if (mpi_resize(w, wsize) < 0)
-                       return -ENOMEM;
-       wp = w->d;
-       wsize = usize + limb_cnt;
-       wsign = usign;
-
-       cnt %= BITS_PER_MPI_LIMB;
-       if (cnt) {
-               wlimb = mpihelp_lshift(wp + limb_cnt, u->d, usize, cnt);
-               if (wlimb) {
-                       wp[wsize] = wlimb;
-                       wsize++;
-               }
-       } else {
-               MPN_COPY_DECR(wp + limb_cnt, u->d, usize);
-       }
-
-       /* Zero all whole limbs at low end.  Do it here and not before calling
-        * mpn_lshift, not to lose for U == W.  */
-       MPN_ZERO(wp, limb_cnt);
-
-       w->nlimbs = wsize;
-       w->sign = wsign;
-       return 0;
-}
-
-int mpi_mul(MPI w, MPI u, MPI v)
-{
-       int rc = -ENOMEM;
-       mpi_size_t usize, vsize, wsize;
-       mpi_ptr_t up, vp, wp;
-       mpi_limb_t cy;
-       int usign, vsign, sign_product;
-       int assign_wp = 0;
-       mpi_ptr_t tmp_limb = NULL;
-
-       if (u->nlimbs < v->nlimbs) {    /* Swap U and V. */
-               usize = v->nlimbs;
-               usign = v->sign;
-               up = v->d;
-               vsize = u->nlimbs;
-               vsign = u->sign;
-               vp = u->d;
-       } else {
-               usize = u->nlimbs;
-               usign = u->sign;
-               up = u->d;
-               vsize = v->nlimbs;
-               vsign = v->sign;
-               vp = v->d;
-       }
-       sign_product = usign ^ vsign;
-       wp = w->d;
-
-       /* Ensure W has space enough to store the result.  */
-       wsize = usize + vsize;
-       if (w->alloced < (size_t) wsize) {
-               if (wp == up || wp == vp) {
-                       wp = mpi_alloc_limb_space(wsize);
-                       if (!wp)
-                               goto nomem;
-                       assign_wp = 1;
-               } else {
-                       if (mpi_resize(w, wsize) < 0)
-                               goto nomem;
-                       wp = w->d;
-               }
-       } else {                /* Make U and V not overlap with W.      */
-               if (wp == up) {
-                       /* W and U are identical.  Allocate temporary space for U.      */
-                       up = tmp_limb = mpi_alloc_limb_space(usize);
-                       if (!up)
-                               goto nomem;
-                       /* Is V identical too?  Keep it identical with U.  */
-                       if (wp == vp)
-                               vp = up;
-                       /* Copy to the temporary space.  */
-                       MPN_COPY(up, wp, usize);
-               } else if (wp == vp) {
-                       /* W and V are identical.  Allocate temporary space for V.      */
-                       vp = tmp_limb = mpi_alloc_limb_space(vsize);
-                       if (!vp)
-                               goto nomem;
-                       /* Copy to the temporary space.  */
-                       MPN_COPY(vp, wp, vsize);
-               }
-       }
-
-       if (!vsize)
-               wsize = 0;
-       else {
-               if (mpihelp_mul(wp, up, usize, vp, vsize, &cy) < 0)
-                       goto nomem;
-               wsize -= cy ? 0 : 1;
-       }
-
-       if (assign_wp)
-               mpi_assign_limb_space(w, wp, wsize);
-
-       w->nlimbs = wsize;
-       w->sign = sign_product;
-       rc = 0;
-nomem:
-       if (tmp_limb)
-               mpi_free_limb_space(tmp_limb);
-       return rc;
-}
-
-int mpi_mulm(MPI w, MPI u, MPI v, MPI m)
-{
-       if (mpi_mul(w, u, v) < 0)
-               return -ENOMEM;
-       return mpi_fdiv_r(w, w, m);
-}
diff --git a/lib/mpi/mpi-scan.c b/lib/mpi/mpi-scan.c
deleted file mode 100644 (file)
index b2da5ad..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/* mpi-scan.c  -  MPI functions
- * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG 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.
- *
- * GnuPG 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 "mpi-internal.h"
-#include "longlong.h"
-
-/****************
- * Scan through an mpi and return byte for byte. a -1 is returned to indicate
- * the end of the mpi. Scanning is done from the lsb to the msb, returned
- * values are in the range of 0 .. 255.
- *
- * FIXME: This code is VERY ugly!
- */
-int mpi_getbyte(const MPI a, unsigned idx)
-{
-       int i, j;
-       unsigned n;
-       mpi_ptr_t ap;
-       mpi_limb_t limb;
-
-       ap = a->d;
-       for (n = 0, i = 0; i < a->nlimbs; i++) {
-               limb = ap[i];
-               for (j = 0; j < BYTES_PER_MPI_LIMB; j++, n++)
-                       if (n == idx)
-                               return (limb >> j * 8) & 0xff;
-       }
-       return -1;
-}
-
-/****************
- * Put a value at position IDX into A. idx counts from lsb to msb
- */
-void mpi_putbyte(MPI a, unsigned idx, int xc)
-{
-       int i, j;
-       unsigned n;
-       mpi_ptr_t ap;
-       mpi_limb_t limb, c;
-
-       c = xc & 0xff;
-       ap = a->d;
-       for (n = 0, i = 0; i < a->alloced; i++) {
-               limb = ap[i];
-               for (j = 0; j < BYTES_PER_MPI_LIMB; j++, n++)
-                       if (n == idx) {
-#if BYTES_PER_MPI_LIMB == 4
-                               if (j == 0)
-                                       limb = (limb & 0xffffff00) | c;
-                               else if (j == 1)
-                                       limb = (limb & 0xffff00ff) | (c << 8);
-                               else if (j == 2)
-                                       limb = (limb & 0xff00ffff) | (c << 16);
-                               else
-                                       limb = (limb & 0x00ffffff) | (c << 24);
-#elif BYTES_PER_MPI_LIMB == 8
-                               if (j == 0)
-                                       limb = (limb & 0xffffffffffffff00) | c;
-                               else if (j == 1)
-                                       limb =
-                                           (limb & 0xffffffffffff00ff) | (c <<
-                                                                          8);
-                               else if (j == 2)
-                                       limb =
-                                           (limb & 0xffffffffff00ffff) | (c <<
-                                                                          16);
-                               else if (j == 3)
-                                       limb =
-                                           (limb & 0xffffffff00ffffff) | (c <<
-                                                                          24);
-                               else if (j == 4)
-                                       limb =
-                                           (limb & 0xffffff00ffffffff) | (c <<
-                                                                          32);
-                               else if (j == 5)
-                                       limb =
-                                           (limb & 0xffff00ffffffffff) | (c <<
-                                                                          40);
-                               else if (j == 6)
-                                       limb =
-                                           (limb & 0xff00ffffffffffff) | (c <<
-                                                                          48);
-                               else
-                                       limb =
-                                           (limb & 0x00ffffffffffffff) | (c <<
-                                                                          56);
-#else
-#error please enhance this function, its ugly - i know.
-#endif
-                               if (a->nlimbs <= i)
-                                       a->nlimbs = i + 1;
-                               ap[i] = limb;
-                               return;
-                       }
-       }
-       log_bug("index out of range\n");
-}
-
-/****************
- * Count the number of zerobits at the low end of A
- */
-unsigned mpi_trailing_zeros(const MPI a)
-{
-       unsigned n, count = 0;
-
-       for (n = 0; n < a->nlimbs; n++) {
-               if (a->d[n]) {
-                       unsigned nn;
-                       mpi_limb_t alimb = a->d[n];
-
-                       count_trailing_zeros(nn, alimb);
-                       count += nn;
-                       break;
-               }
-               count += BITS_PER_MPI_LIMB;
-       }
-       return count;
-
-}
index f26b41fcb48c694c06fdcea18b55bdfd3788fb6d..f0fa659958002ca824d47144e6ecba3fdcdc7e38 100644 (file)
@@ -73,81 +73,6 @@ leave:
 }
 EXPORT_SYMBOL_GPL(mpi_read_from_buffer);
 
-/****************
- * Make an mpi from a character string.
- */
-int mpi_fromstr(MPI val, const char *str)
-{
-       int hexmode = 0, sign = 0, prepend_zero = 0, i, j, c, c1, c2;
-       unsigned nbits, nbytes, nlimbs;
-       mpi_limb_t a;
-
-       if (*str == '-') {
-               sign = 1;
-               str++;
-       }
-       if (*str == '0' && str[1] == 'x')
-               hexmode = 1;
-       else
-               return -EINVAL; /* other bases are not yet supported */
-       str += 2;
-
-       nbits = strlen(str) * 4;
-       if (nbits % 8)
-               prepend_zero = 1;
-       nbytes = (nbits + 7) / 8;
-       nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
-       if (val->alloced < nlimbs)
-               if (!mpi_resize(val, nlimbs))
-                       return -ENOMEM;
-       i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
-       i %= BYTES_PER_MPI_LIMB;
-       j = val->nlimbs = nlimbs;
-       val->sign = sign;
-       for (; j > 0; j--) {
-               a = 0;
-               for (; i < BYTES_PER_MPI_LIMB; i++) {
-                       if (prepend_zero) {
-                               c1 = '0';
-                               prepend_zero = 0;
-                       } else
-                               c1 = *str++;
-                       assert(c1);
-                       c2 = *str++;
-                       assert(c2);
-                       if (c1 >= '0' && c1 <= '9')
-                               c = c1 - '0';
-                       else if (c1 >= 'a' && c1 <= 'f')
-                               c = c1 - 'a' + 10;
-                       else if (c1 >= 'A' && c1 <= 'F')
-                               c = c1 - 'A' + 10;
-                       else {
-                               mpi_clear(val);
-                               return 1;
-                       }
-                       c <<= 4;
-                       if (c2 >= '0' && c2 <= '9')
-                               c |= c2 - '0';
-                       else if (c2 >= 'a' && c2 <= 'f')
-                               c |= c2 - 'a' + 10;
-                       else if (c2 >= 'A' && c2 <= 'F')
-                               c |= c2 - 'A' + 10;
-                       else {
-                               mpi_clear(val);
-                               return 1;
-                       }
-                       a <<= 8;
-                       a |= c;
-               }
-               i = 0;
-
-               val->d[j - 1] = a;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(mpi_fromstr);
-
 /****************
  * Return an allocated buffer with the MPI (msb first).
  * NBYTES receives the length of this buffer. Caller must free the
index cde1aaec18da9d179853724b3928c5be8a4508d6..c57d1d46295e39bb75c57ccd489dad15c97ed40c 100644 (file)
 #define UDIV_TIME UMUL_TIME
 #endif
 
-/* FIXME: We should be using invert_limb (or invert_normalized_limb)
- * here (not udiv_qrnnd).
- */
-
-mpi_limb_t
-mpihelp_mod_1(mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
-             mpi_limb_t divisor_limb)
-{
-       mpi_size_t i;
-       mpi_limb_t n1, n0, r;
-       int dummy;
-
-       /* Botch: Should this be handled at all?  Rely on callers?  */
-       if (!dividend_size)
-               return 0;
-
-       /* If multiplication is much faster than division, and the
-        * dividend is large, pre-invert the divisor, and use
-        * only multiplications in the inner loop.
-        *
-        * This test should be read:
-        *   Does it ever help to use udiv_qrnnd_preinv?
-        *     && Does what we save compensate for the inversion overhead?
-        */
-       if (UDIV_TIME > (2 * UMUL_TIME + 6)
-           && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME) {
-               int normalization_steps;
-
-               count_leading_zeros(normalization_steps, divisor_limb);
-               if (normalization_steps) {
-                       mpi_limb_t divisor_limb_inverted;
-
-                       divisor_limb <<= normalization_steps;
-
-                       /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB.  The
-                        * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
-                        * most significant bit (with weight 2**N) implicit.
-                        *
-                        * Special case for DIVISOR_LIMB == 100...000.
-                        */
-                       if (!(divisor_limb << 1))
-                               divisor_limb_inverted = ~(mpi_limb_t) 0;
-                       else
-                               udiv_qrnnd(divisor_limb_inverted, dummy,
-                                          -divisor_limb, 0, divisor_limb);
-
-                       n1 = dividend_ptr[dividend_size - 1];
-                       r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps);
-
-                       /* Possible optimization:
-                        * if (r == 0
-                        * && divisor_limb > ((n1 << normalization_steps)
-                        *                 | (dividend_ptr[dividend_size - 2] >> ...)))
-                        * ...one division less...
-                        */
-                       for (i = dividend_size - 2; i >= 0; i--) {
-                               n0 = dividend_ptr[i];
-                               UDIV_QRNND_PREINV(dummy, r, r,
-                                                 ((n1 << normalization_steps)
-                                                  | (n0 >>
-                                                     (BITS_PER_MPI_LIMB -
-                                                      normalization_steps))),
-                                                 divisor_limb,
-                                                 divisor_limb_inverted);
-                               n1 = n0;
-                       }
-                       UDIV_QRNND_PREINV(dummy, r, r,
-                                         n1 << normalization_steps,
-                                         divisor_limb, divisor_limb_inverted);
-                       return r >> normalization_steps;
-               } else {
-                       mpi_limb_t divisor_limb_inverted;
-
-                       /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB.  The
-                        * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
-                        * most significant bit (with weight 2**N) implicit.
-                        *
-                        * Special case for DIVISOR_LIMB == 100...000.
-                        */
-                       if (!(divisor_limb << 1))
-                               divisor_limb_inverted = ~(mpi_limb_t) 0;
-                       else
-                               udiv_qrnnd(divisor_limb_inverted, dummy,
-                                          -divisor_limb, 0, divisor_limb);
-
-                       i = dividend_size - 1;
-                       r = dividend_ptr[i];
-
-                       if (r >= divisor_limb)
-                               r = 0;
-                       else
-                               i--;
-
-                       for (; i >= 0; i--) {
-                               n0 = dividend_ptr[i];
-                               UDIV_QRNND_PREINV(dummy, r, r,
-                                                 n0, divisor_limb,
-                                                 divisor_limb_inverted);
-                       }
-                       return r;
-               }
-       } else {
-               if (UDIV_NEEDS_NORMALIZATION) {
-                       int normalization_steps;
-
-                       count_leading_zeros(normalization_steps, divisor_limb);
-                       if (normalization_steps) {
-                               divisor_limb <<= normalization_steps;
-
-                               n1 = dividend_ptr[dividend_size - 1];
-                               r = n1 >> (BITS_PER_MPI_LIMB -
-                                          normalization_steps);
-
-                               /* Possible optimization:
-                                * if (r == 0
-                                * && divisor_limb > ((n1 << normalization_steps)
-                                *                 | (dividend_ptr[dividend_size - 2] >> ...)))
-                                * ...one division less...
-                                */
-                               for (i = dividend_size - 2; i >= 0; i--) {
-                                       n0 = dividend_ptr[i];
-                                       udiv_qrnnd(dummy, r, r,
-                                                  ((n1 << normalization_steps)
-                                                   | (n0 >>
-                                                      (BITS_PER_MPI_LIMB -
-                                                       normalization_steps))),
-                                                  divisor_limb);
-                                       n1 = n0;
-                               }
-                               udiv_qrnnd(dummy, r, r,
-                                          n1 << normalization_steps,
-                                          divisor_limb);
-                               return r >> normalization_steps;
-                       }
-               }
-               /* No normalization needed, either because udiv_qrnnd doesn't require
-                * it, or because DIVISOR_LIMB is already normalized.  */
-               i = dividend_size - 1;
-               r = dividend_ptr[i];
-
-               if (r >= divisor_limb)
-                       r = 0;
-               else
-                       i--;
-
-               for (; i >= 0; i--) {
-                       n0 = dividend_ptr[i];
-                       udiv_qrnnd(dummy, r, r, n0, divisor_limb);
-               }
-               return r;
-       }
-}
-
 /* Divide num (NP/NSIZE) by den (DP/DSIZE) and write
  * the NSIZE-DSIZE least significant quotient limbs at QP
  * and the DSIZE long remainder at NP. If QEXTRA_LIMBS is
@@ -387,159 +234,3 @@ q_test:
 
        return most_significant_q_limb;
 }
-
-/****************
- * Divide (DIVIDEND_PTR,,DIVIDEND_SIZE) by DIVISOR_LIMB.
- * Write DIVIDEND_SIZE limbs of quotient at QUOT_PTR.
- * Return the single-limb remainder.
- * There are no constraints on the value of the divisor.
- *
- * QUOT_PTR and DIVIDEND_PTR might point to the same limb.
- */
-
-mpi_limb_t
-mpihelp_divmod_1(mpi_ptr_t quot_ptr,
-                mpi_ptr_t dividend_ptr, mpi_size_t dividend_size,
-                mpi_limb_t divisor_limb)
-{
-       mpi_size_t i;
-       mpi_limb_t n1, n0, r;
-       int dummy;
-
-       if (!dividend_size)
-               return 0;
-
-       /* If multiplication is much faster than division, and the
-        * dividend is large, pre-invert the divisor, and use
-        * only multiplications in the inner loop.
-        *
-        * This test should be read:
-        * Does it ever help to use udiv_qrnnd_preinv?
-        * && Does what we save compensate for the inversion overhead?
-        */
-       if (UDIV_TIME > (2 * UMUL_TIME + 6)
-           && (UDIV_TIME - (2 * UMUL_TIME + 6)) * dividend_size > UDIV_TIME) {
-               int normalization_steps;
-
-               count_leading_zeros(normalization_steps, divisor_limb);
-               if (normalization_steps) {
-                       mpi_limb_t divisor_limb_inverted;
-
-                       divisor_limb <<= normalization_steps;
-
-                       /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB.  The
-                        * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
-                        * most significant bit (with weight 2**N) implicit.
-                        */
-                       /* Special case for DIVISOR_LIMB == 100...000.  */
-                       if (!(divisor_limb << 1))
-                               divisor_limb_inverted = ~(mpi_limb_t) 0;
-                       else
-                               udiv_qrnnd(divisor_limb_inverted, dummy,
-                                          -divisor_limb, 0, divisor_limb);
-
-                       n1 = dividend_ptr[dividend_size - 1];
-                       r = n1 >> (BITS_PER_MPI_LIMB - normalization_steps);
-
-                       /* Possible optimization:
-                        * if (r == 0
-                        * && divisor_limb > ((n1 << normalization_steps)
-                        *                 | (dividend_ptr[dividend_size - 2] >> ...)))
-                        * ...one division less...
-                        */
-                       for (i = dividend_size - 2; i >= 0; i--) {
-                               n0 = dividend_ptr[i];
-                               UDIV_QRNND_PREINV(quot_ptr[i + 1], r, r,
-                                                 ((n1 << normalization_steps)
-                                                  | (n0 >>
-                                                     (BITS_PER_MPI_LIMB -
-                                                      normalization_steps))),
-                                                 divisor_limb,
-                                                 divisor_limb_inverted);
-                               n1 = n0;
-                       }
-                       UDIV_QRNND_PREINV(quot_ptr[0], r, r,
-                                         n1 << normalization_steps,
-                                         divisor_limb, divisor_limb_inverted);
-                       return r >> normalization_steps;
-               } else {
-                       mpi_limb_t divisor_limb_inverted;
-
-                       /* Compute (2**2N - 2**N * DIVISOR_LIMB) / DIVISOR_LIMB.  The
-                        * result is a (N+1)-bit approximation to 1/DIVISOR_LIMB, with the
-                        * most significant bit (with weight 2**N) implicit.
-                        */
-                       /* Special case for DIVISOR_LIMB == 100...000.  */
-                       if (!(divisor_limb << 1))
-                               divisor_limb_inverted = ~(mpi_limb_t) 0;
-                       else
-                               udiv_qrnnd(divisor_limb_inverted, dummy,
-                                          -divisor_limb, 0, divisor_limb);
-
-                       i = dividend_size - 1;
-                       r = dividend_ptr[i];
-
-                       if (r >= divisor_limb)
-                               r = 0;
-                       else
-                               quot_ptr[i--] = 0;
-
-                       for (; i >= 0; i--) {
-                               n0 = dividend_ptr[i];
-                               UDIV_QRNND_PREINV(quot_ptr[i], r, r,
-                                                 n0, divisor_limb,
-                                                 divisor_limb_inverted);
-                       }
-                       return r;
-               }
-       } else {
-               if (UDIV_NEEDS_NORMALIZATION) {
-                       int normalization_steps;
-
-                       count_leading_zeros(normalization_steps, divisor_limb);
-                       if (normalization_steps) {
-                               divisor_limb <<= normalization_steps;
-
-                               n1 = dividend_ptr[dividend_size - 1];
-                               r = n1 >> (BITS_PER_MPI_LIMB -
-                                          normalization_steps);
-
-                               /* Possible optimization:
-                                * if (r == 0
-                                * && divisor_limb > ((n1 << normalization_steps)
-                                *                 | (dividend_ptr[dividend_size - 2] >> ...)))
-                                * ...one division less...
-                                */
-                               for (i = dividend_size - 2; i >= 0; i--) {
-                                       n0 = dividend_ptr[i];
-                                       udiv_qrnnd(quot_ptr[i + 1], r, r,
-                                                  ((n1 << normalization_steps)
-                                                   | (n0 >>
-                                                      (BITS_PER_MPI_LIMB -
-                                                       normalization_steps))),
-                                                  divisor_limb);
-                                       n1 = n0;
-                               }
-                               udiv_qrnnd(quot_ptr[0], r, r,
-                                          n1 << normalization_steps,
-                                          divisor_limb);
-                               return r >> normalization_steps;
-                       }
-               }
-               /* No normalization needed, either because udiv_qrnnd doesn't require
-                * it, or because DIVISOR_LIMB is already normalized.  */
-               i = dividend_size - 1;
-               r = dividend_ptr[i];
-
-               if (r >= divisor_limb)
-                       r = 0;
-               else
-                       quot_ptr[i--] = 0;
-
-               for (; i >= 0; i--) {
-                       n0 = dividend_ptr[i];
-                       udiv_qrnnd(quot_ptr[i], r, r, n0, divisor_limb);
-               }
-               return r;
-       }
-}
index c69c5eef233bd27cd2bc1f3c31d04bed089a08a0..7c841719fdfb73647e6b20834da7a27a38b128e1 100644 (file)
@@ -330,36 +330,6 @@ mpih_sqr_n(mpi_ptr_t prodp, mpi_ptr_t up, mpi_size_t size, mpi_ptr_t tspace)
        }
 }
 
-/* This should be made into an inline function in gmp.h.  */
-int mpihelp_mul_n(mpi_ptr_t prodp, mpi_ptr_t up, mpi_ptr_t vp, mpi_size_t size)
-{
-       if (up == vp) {
-               if (size < KARATSUBA_THRESHOLD)
-                       mpih_sqr_n_basecase(prodp, up, size);
-               else {
-                       mpi_ptr_t tspace;
-                       tspace = mpi_alloc_limb_space(2 * size);
-                       if (!tspace)
-                               return -ENOMEM;
-                       mpih_sqr_n(prodp, up, size, tspace);
-                       mpi_free_limb_space(tspace);
-               }
-       } else {
-               if (size < KARATSUBA_THRESHOLD)
-                       mul_n_basecase(prodp, up, vp, size);
-               else {
-                       mpi_ptr_t tspace;
-                       tspace = mpi_alloc_limb_space(2 * size);
-                       if (!tspace)
-                               return -ENOMEM;
-                       mul_n(prodp, up, vp, size, tspace);
-                       mpi_free_limb_space(tspace);
-               }
-       }
-
-       return 0;
-}
-
 int
 mpihelp_mul_karatsuba_case(mpi_ptr_t prodp,
                           mpi_ptr_t up, mpi_size_t usize,
index 26e4ed31e256f793d4bdc21ea81f7f6a8ca4bf71..657979f71bef0a0b3331eb804c0921d1f7afe6a8 100644 (file)
@@ -106,13 +106,6 @@ int mpi_resize(MPI a, unsigned nlimbs)
        return 0;
 }
 
-void mpi_clear(MPI a)
-{
-       a->nlimbs = 0;
-       a->nbits = 0;
-       a->flags = 0;
-}
-
 void mpi_free(MPI a)
 {
        if (!a)
@@ -128,84 +121,3 @@ void mpi_free(MPI a)
        kfree(a);
 }
 EXPORT_SYMBOL_GPL(mpi_free);
-
-/****************
- * Note: This copy function should not interpret the MPI
- *      but copy it transparently.
- */
-int mpi_copy(MPI *copied, const MPI a)
-{
-       size_t i;
-       MPI b;
-
-       *copied = NULL;
-
-       if (a) {
-               b = mpi_alloc(a->nlimbs);
-               if (!b)
-                       return -ENOMEM;
-
-               b->nlimbs = a->nlimbs;
-               b->sign = a->sign;
-               b->flags = a->flags;
-               b->nbits = a->nbits;
-
-               for (i = 0; i < b->nlimbs; i++)
-                       b->d[i] = a->d[i];
-
-               *copied = b;
-       }
-
-       return 0;
-}
-
-int mpi_set(MPI w, const MPI u)
-{
-       mpi_ptr_t wp, up;
-       mpi_size_t usize = u->nlimbs;
-       int usign = u->sign;
-
-       if (RESIZE_IF_NEEDED(w, (size_t) usize) < 0)
-               return -ENOMEM;
-
-       wp = w->d;
-       up = u->d;
-       MPN_COPY(wp, up, usize);
-       w->nlimbs = usize;
-       w->nbits = u->nbits;
-       w->flags = u->flags;
-       w->sign = usign;
-       return 0;
-}
-
-int mpi_set_ui(MPI w, unsigned long u)
-{
-       if (RESIZE_IF_NEEDED(w, 1) < 0)
-               return -ENOMEM;
-       w->d[0] = u;
-       w->nlimbs = u ? 1 : 0;
-       w->sign = 0;
-       w->nbits = 0;
-       w->flags = 0;
-       return 0;
-}
-
-MPI mpi_alloc_set_ui(unsigned long u)
-{
-       MPI w = mpi_alloc(1);
-       if (!w)
-               return w;
-       w->d[0] = u;
-       w->nlimbs = u ? 1 : 0;
-       w->sign = 0;
-       return w;
-}
-
-void mpi_swap(MPI a, MPI b)
-{
-       struct gcry_mpi tmp;
-
-       tmp = *a;
-       *a = *b;
-       *b = tmp;
-}
index d1be02ca18898df63e705504395463b733639ddb..0420867755615d4f78be0272caf87e8d5b0fb112 100644 (file)
 
 static mempool_t *page_pool, *isa_page_pool;
 
-#ifdef CONFIG_HIGHMEM
+#if defined(CONFIG_HIGHMEM) || defined(CONFIG_NEED_BOUNCE_POOL)
 static __init int init_emergency_pool(void)
 {
-#ifndef CONFIG_MEMORY_HOTPLUG
+#if defined(CONFIG_HIGHMEM) && !defined(CONFIG_MEMORY_HOTPLUG)
        if (max_pfn <= max_low_pfn)
                return 0;
 #endif
 
        page_pool = mempool_create_page_pool(POOL_SIZE, 0);
        BUG_ON(!page_pool);
-       printk("highmem bounce pool size: %d pages\n", POOL_SIZE);
+       printk("bounce pool size: %d pages\n", POOL_SIZE);
 
        return 0;
 }
 
 __initcall(init_emergency_pool);
+#endif
 
+#ifdef CONFIG_HIGHMEM
 /*
  * highmem version, map in to vec
  */
index ab1e7145e2909c8e1a02359fb1e148118c42e1b2..de4ce70584508edfa95eec5827271511052af102 100644 (file)
@@ -345,14 +345,14 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,
  * Also when FAIL is set do a force kill because something went
  * wrong earlier.
  */
-static void kill_procs(struct list_head *to_kill, int doit, int trapno,
+static void kill_procs(struct list_head *to_kill, int forcekill, int trapno,
                          int fail, struct page *page, unsigned long pfn,
                          int flags)
 {
        struct to_kill *tk, *next;
 
        list_for_each_entry_safe (tk, next, to_kill, nd) {
-               if (doit) {
+               if (forcekill) {
                        /*
                         * In case something went wrong with munmapping
                         * make sure the process doesn't catch the
@@ -858,7 +858,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
        struct address_space *mapping;
        LIST_HEAD(tokill);
        int ret;
-       int kill = 1;
+       int kill = 1, forcekill;
        struct page *hpage = compound_head(p);
        struct page *ppage;
 
@@ -888,7 +888,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
         * be called inside page lock (it's recommended but not enforced).
         */
        mapping = page_mapping(hpage);
-       if (!PageDirty(hpage) && mapping &&
+       if (!(flags & MF_MUST_KILL) && !PageDirty(hpage) && mapping &&
            mapping_cap_writeback_dirty(mapping)) {
                if (page_mkclean(hpage)) {
                        SetPageDirty(hpage);
@@ -965,12 +965,14 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
         * Now that the dirty bit has been propagated to the
         * struct page and all unmaps done we can decide if
         * killing is needed or not.  Only kill when the page
-        * was dirty, otherwise the tokill list is merely
+        * was dirty or the process is not restartable,
+        * otherwise the tokill list is merely
         * freed.  When there was a problem unmapping earlier
         * use a more force-full uncatchable kill to prevent
         * any accesses to the poisoned memory.
         */
-       kill_procs(&tokill, !!PageDirty(ppage), trapno,
+       forcekill = PageDirty(ppage) || (flags & MF_MUST_KILL);
+       kill_procs(&tokill, forcekill, trapno,
                      ret != SWAP_SUCCESS, p, pfn, flags);
 
        return ret;
index bd106361be4bf2d080e67f11252198c710745278..c15b998e5a860f9d3c375ad31ce9d5f34fbb5ea0 100644 (file)
@@ -1877,7 +1877,7 @@ static int shmem_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode)
 }
 
 static int shmem_create(struct inode *dir, struct dentry *dentry, umode_t mode,
-               struct nameidata *nd)
+               bool excl)
 {
        return shmem_mknod(dir, dentry, mode | S_IFREG, 0);
 }
index b332c3d76059ea5c1fe1de82d17fac4884b714a2..10255e81be79d84c5428504c2a79be3180626f79 100644 (file)
@@ -1423,7 +1423,7 @@ static int process_connect(struct ceph_connection *con)
                 * dropped messages.
                 */
                dout("process_connect got RESET peer seq %u\n",
-                    le32_to_cpu(con->in_connect.connect_seq));
+                    le32_to_cpu(con->in_reply.connect_seq));
                pr_err("%s%lld %s connection reset\n",
                       ENTITY_NAME(con->peer_name),
                       ceph_pr_addr(&con->peer_addr.in_addr));
@@ -1450,10 +1450,10 @@ static int process_connect(struct ceph_connection *con)
                 * If we sent a smaller connect_seq than the peer has, try
                 * again with a larger value.
                 */
-               dout("process_connect got RETRY my seq = %u, peer_seq = %u\n",
+               dout("process_connect got RETRY_SESSION my seq %u, peer %u\n",
                     le32_to_cpu(con->out_connect.connect_seq),
-                    le32_to_cpu(con->in_connect.connect_seq));
-               con->connect_seq = le32_to_cpu(con->in_connect.connect_seq);
+                    le32_to_cpu(con->in_reply.connect_seq));
+               con->connect_seq = le32_to_cpu(con->in_reply.connect_seq);
                ceph_con_out_kvec_reset(con);
                ret = prepare_write_connect(con);
                if (ret < 0)
@@ -1468,9 +1468,9 @@ static int process_connect(struct ceph_connection *con)
                 */
                dout("process_connect got RETRY_GLOBAL my %u peer_gseq %u\n",
                     con->peer_global_seq,
-                    le32_to_cpu(con->in_connect.global_seq));
+                    le32_to_cpu(con->in_reply.global_seq));
                get_global_seq(con->msgr,
-                              le32_to_cpu(con->in_connect.global_seq));
+                              le32_to_cpu(con->in_reply.global_seq));
                ceph_con_out_kvec_reset(con);
                ret = prepare_write_connect(con);
                if (ret < 0)
index 611c5efd4cb0b71abeb9b3d965acbf490673e644..8f6ccfd68ef4fb6625652f0b34f7f3fdb4b4a91e 100644 (file)
@@ -109,25 +109,9 @@ void __scm_destroy(struct scm_cookie *scm)
 
        if (fpl) {
                scm->fp = NULL;
-               if (current->scm_work_list) {
-                       list_add_tail(&fpl->list, current->scm_work_list);
-               } else {
-                       LIST_HEAD(work_list);
-
-                       current->scm_work_list = &work_list;
-
-                       list_add(&fpl->list, &work_list);
-                       while (!list_empty(&work_list)) {
-                               fpl = list_first_entry(&work_list, struct scm_fp_list, list);
-
-                               list_del(&fpl->list);
-                               for (i=fpl->count-1; i>=0; i--)
-                                       fput(fpl->fp[i]);
-                               kfree(fpl);
-                       }
-
-                       current->scm_work_list = NULL;
-               }
+               for (i=fpl->count-1; i>=0; i--)
+                       fput(fpl->fp[i]);
+               kfree(fpl);
        }
 }
 EXPORT_SYMBOL(__scm_destroy);
diff --git a/samples/seccomp/.gitignore b/samples/seccomp/.gitignore
new file mode 100644 (file)
index 0000000..78fb781
--- /dev/null
@@ -0,0 +1,3 @@
+bpf-direct
+bpf-fancy
+dropper
index 35664fe6daa16ef6d7660abe317864ffb22d5cce..b9c1219924f197b7195650ea99cc0c28b79aaa56 100644 (file)
@@ -38,8 +38,9 @@ config IMA_MEASURE_PCR_IDX
          measurement list.  If unsure, use the default 10.
 
 config IMA_AUDIT
-       bool
+       bool "Enables auditing support"
        depends on IMA
+       depends on AUDIT
        default y
        help
          This option adds a kernel parameter 'ima_audit', which
index 5690c021de8fbc2b069d622634a33841a0498bff..5f740f6971e1f59c6d3e7bfb6254d6350f3f55fa 100644 (file)
@@ -6,4 +6,5 @@
 obj-$(CONFIG_IMA) += ima.o
 
 ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
-        ima_policy.o ima_audit.o
+        ima_policy.o
+ima-$(CONFIG_IMA_AUDIT) += ima_audit.o
index 3ccf7acac6df88c01e80a509d6a129f88953acd1..e7c99fd0d2236e7d3a923733bdf7e622f8cd993a 100644 (file)
@@ -61,10 +61,19 @@ struct ima_queue_entry {
 };
 extern struct list_head ima_measurements;      /* list of all measurements */
 
+#ifdef CONFIG_IMA_AUDIT
 /* declarations */
 void integrity_audit_msg(int audit_msgno, struct inode *inode,
                         const unsigned char *fname, const char *op,
                         const char *cause, int result, int info);
+#else
+static inline void integrity_audit_msg(int audit_msgno, struct inode *inode,
+                                      const unsigned char *fname,
+                                      const char *op, const char *cause,
+                                      int result, int info)
+{
+}
+#endif
 
 /* Internal IMA function definitions */
 int ima_init(void);
index 88a2788b981d96ab543ac982c8935b09e56b26e3..032ff03ad9078bc956faa6c6e6d6759b6e2a0420 100644 (file)
@@ -175,7 +175,9 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
        }
        memset(&entry->template, 0, sizeof(entry->template));
        memcpy(entry->template.digest, iint->digest, IMA_DIGEST_SIZE);
-       strncpy(entry->template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
+       strcpy(entry->template.file_name,
+              (strlen(filename) > IMA_EVENT_NAME_LEN_MAX) ?
+              file->f_dentry->d_name.name : filename);
 
        result = ima_store_template(entry, violation, inode);
        if (!result || result == -EEXIST)
index 21e96bf188dfcc12ff3b05226f3c7d83521dbc2b..7a57f6769e9cffd276e5e33e64efa7f388561cd4 100644 (file)
@@ -17,8 +17,6 @@
 
 static int ima_audit;
 
-#ifdef CONFIG_IMA_AUDIT
-
 /* ima_audit_setup - enable informational auditing messages */
 static int __init ima_audit_setup(char *str)
 {
@@ -29,7 +27,6 @@ static int __init ima_audit_setup(char *str)
        return 1;
 }
 __setup("ima_audit=", ima_audit_setup);
-#endif
 
 void integrity_audit_msg(int audit_msgno, struct inode *inode,
                         const unsigned char *fname, const char *op,
index e1aa2b482dd2c5ae064a024656baa3f524c3a4aa..38477c9c3415cd9af47ec402e9694056a9ca3c22 100644 (file)
@@ -367,20 +367,11 @@ int __init ima_fs_init(void)
 
        return 0;
 out:
-       securityfs_remove(runtime_measurements_count);
-       securityfs_remove(ascii_runtime_measurements);
-       securityfs_remove(binary_runtime_measurements);
-       securityfs_remove(ima_dir);
-       securityfs_remove(ima_policy);
-       return -1;
-}
-
-void __exit ima_fs_cleanup(void)
-{
        securityfs_remove(violations);
        securityfs_remove(runtime_measurements_count);
        securityfs_remove(ascii_runtime_measurements);
        securityfs_remove(binary_runtime_measurements);
        securityfs_remove(ima_dir);
        securityfs_remove(ima_policy);
+       return -1;
 }
index 17f1f060306ff3c2aca7c1364b36536d30c0c302..b5dfd534f13dad49b958748687800ccc02df3353 100644 (file)
@@ -90,8 +90,3 @@ int __init ima_init(void)
 
        return ima_fs_init();
 }
-
-void __exit ima_cleanup(void)
-{
-       ima_fs_cleanup();
-}
index b17be79b9cf24b8f2319ea2d54875b0a048dcfdf..be8294915cf7f65524a21ab2dd3101ecb0a6edd9 100644 (file)
@@ -54,6 +54,7 @@ static void ima_rdwr_violation_check(struct file *file)
        fmode_t mode = file->f_mode;
        int rc;
        bool send_tomtou = false, send_writers = false;
+       unsigned char *pathname = NULL, *pathbuf = NULL;
 
        if (!S_ISREG(inode->i_mode) || !ima_initialized)
                return;
@@ -75,12 +76,27 @@ static void ima_rdwr_violation_check(struct file *file)
 out:
        mutex_unlock(&inode->i_mutex);
 
+       if (!send_tomtou && !send_writers)
+               return;
+
+       /* We will allow 11 spaces for ' (deleted)' to be appended */
+       pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL);
+       if (pathbuf) {
+               pathname = d_path(&file->f_path, pathbuf, PATH_MAX + 11);
+               if (IS_ERR(pathname))
+                       pathname = NULL;
+               else if (strlen(pathname) > IMA_EVENT_NAME_LEN_MAX)
+                       pathname = NULL;
+       }
        if (send_tomtou)
-               ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
-                                 "ToMToU");
+               ima_add_violation(inode,
+                                 !pathname ? dentry->d_name.name : pathname,
+                                 "invalid_pcr", "ToMToU");
        if (send_writers)
-               ima_add_violation(inode, dentry->d_name.name, "invalid_pcr",
-                                 "open_writers");
+               ima_add_violation(inode,
+                                 !pathname ? dentry->d_name.name : pathname,
+                                 "invalid_pcr", "open_writers");
+       kfree(pathbuf);
 }
 
 static void ima_check_last_writer(struct integrity_iint_cache *iint,
@@ -123,6 +139,7 @@ static int process_measurement(struct file *file, const unsigned char *filename,
 {
        struct inode *inode = file->f_dentry->d_inode;
        struct integrity_iint_cache *iint;
+       unsigned char *pathname = NULL, *pathbuf = NULL;
        int rc = 0;
 
        if (!ima_initialized || !S_ISREG(inode->i_mode))
@@ -147,8 +164,21 @@ retry:
                goto out;
 
        rc = ima_collect_measurement(iint, file);
-       if (!rc)
-               ima_store_measurement(iint, file, filename);
+       if (rc != 0)
+               goto out;
+
+       if (function != BPRM_CHECK) {
+               /* We will allow 11 spaces for ' (deleted)' to be appended */
+               pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL);
+               if (pathbuf) {
+                       pathname =
+                           d_path(&file->f_path, pathbuf, PATH_MAX + 11);
+                       if (IS_ERR(pathname))
+                               pathname = NULL;
+               }
+       }
+       ima_store_measurement(iint, file, !pathname ? filename : pathname);
+       kfree(pathbuf);
 out:
        mutex_unlock(&iint->mutex);
        return rc;
@@ -228,15 +258,11 @@ static int __init init_ima(void)
        int error;
 
        error = ima_init();
-       ima_initialized = 1;
+       if (!error)
+               ima_initialized = 1;
        return error;
 }
 
-static void __exit cleanup_ima(void)
-{
-       ima_cleanup();
-}
-
 late_initcall(init_ima);       /* Start IMA after the TPM is available */
 
 MODULE_DESCRIPTION("Integrity Measurement Architecture");
index d8edff209bf3b2bfc4373fa15ef17d25b30b86ed..1a9583008aaef1bf1fe6868f921408ac83d06a63 100644 (file)
@@ -63,6 +63,8 @@ static struct ima_measure_rule_entry default_rules[] = {
        {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
        {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
        {.action = DONT_MEASURE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_MEASURE,.fsmagic = DEVPTS_SUPER_MAGIC,.flags = IMA_FSMAGIC},
+       {.action = DONT_MEASURE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC},
        {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
        {.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
        {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC,
index c92d42b021aa47c62dea181c6b90129d80ff7e53..1c261763f4799180432f2162a096579007243203 100644 (file)
@@ -24,7 +24,7 @@
  *
  * If successful, 0 will be returned.
  */
-long compat_keyctl_instantiate_key_iov(
+static long compat_keyctl_instantiate_key_iov(
        key_serial_t id,
        const struct compat_iovec __user *_payload_iov,
        unsigned ioc,
@@ -33,7 +33,7 @@ long compat_keyctl_instantiate_key_iov(
        struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
        long ret;
 
-       if (_payload_iov == 0 || ioc == 0)
+       if (!_payload_iov || !ioc)
                goto no_payload;
 
        ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc,
index 3dcbf86b0d31b9c7c9c889c80dacf34f9b33adc6..22ff05269e3d5a35ec00750816e662f9709209db 100644 (file)
@@ -149,7 +149,7 @@ extern key_ref_t lookup_user_key(key_serial_t id, unsigned long flags,
 #define KEY_LOOKUP_FOR_UNLINK  0x04
 
 extern long join_session_keyring(const char *name);
-extern void key_change_session_keyring(struct task_work *twork);
+extern void key_change_session_keyring(struct callback_head *twork);
 
 extern struct work_struct key_gc_work;
 extern unsigned key_gc_delay;
@@ -242,7 +242,7 @@ extern long keyctl_instantiate_key_iov(key_serial_t,
 extern long keyctl_invalidate_key(key_serial_t);
 
 extern long keyctl_instantiate_key_common(key_serial_t,
-                                         const struct iovec __user *,
+                                         const struct iovec *,
                                          unsigned, size_t, key_serial_t);
 
 /*
index 0f5b3f0272995dc7057f1306c346468174d3e464..3364fbf46807bb384e61a761f2f6f2fab9ebb888 100644 (file)
@@ -1106,7 +1106,7 @@ long keyctl_instantiate_key_iov(key_serial_t id,
        struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
        long ret;
 
-       if (_payload_iov == 0 || ioc == 0)
+       if (!_payload_iov || !ioc)
                goto no_payload;
 
        ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc,
@@ -1456,7 +1456,7 @@ long keyctl_session_to_parent(void)
 {
        struct task_struct *me, *parent;
        const struct cred *mycred, *pcred;
-       struct task_work *newwork, *oldwork;
+       struct callback_head *newwork, *oldwork;
        key_ref_t keyring_r;
        struct cred *cred;
        int ret;
@@ -1466,19 +1466,17 @@ long keyctl_session_to_parent(void)
                return PTR_ERR(keyring_r);
 
        ret = -ENOMEM;
-       newwork = kmalloc(sizeof(struct task_work), GFP_KERNEL);
-       if (!newwork)
-               goto error_keyring;
 
        /* our parent is going to need a new cred struct, a new tgcred struct
         * and new security data, so we allocate them here to prevent ENOMEM in
         * our parent */
        cred = cred_alloc_blank();
        if (!cred)
-               goto error_newwork;
+               goto error_keyring;
+       newwork = &cred->rcu;
 
        cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r);
-       init_task_work(newwork, key_change_session_keyring, cred);
+       init_task_work(newwork, key_change_session_keyring);
 
        me = current;
        rcu_read_lock();
@@ -1488,6 +1486,7 @@ long keyctl_session_to_parent(void)
        oldwork = NULL;
        parent = me->real_parent;
 
+       task_lock(parent);
        /* the parent mustn't be init and mustn't be a kernel thread */
        if (parent->pid <= 1 || !parent->mm)
                goto unlock;
@@ -1531,20 +1530,15 @@ long keyctl_session_to_parent(void)
        if (!ret)
                newwork = NULL;
 unlock:
+       task_unlock(parent);
        write_unlock_irq(&tasklist_lock);
        rcu_read_unlock();
-       if (oldwork) {
-               put_cred(oldwork->data);
-               kfree(oldwork);
-       }
-       if (newwork) {
-               put_cred(newwork->data);
-               kfree(newwork);
-       }
+       if (oldwork)
+               put_cred(container_of(oldwork, struct cred, rcu));
+       if (newwork)
+               put_cred(cred);
        return ret;
 
-error_newwork:
-       kfree(newwork);
 error_keyring:
        key_ref_put(keyring_r);
        return ret;
index 7445875f681807559aaa9a071ff1d0eea41bc93c..81e7852d281d51d4faa2600b15b16ab290defa11 100644 (file)
@@ -751,6 +751,7 @@ static void keyring_unlink_rcu_disposal(struct rcu_head *rcu)
 int __key_link_begin(struct key *keyring, const struct key_type *type,
                     const char *description, unsigned long *_prealloc)
        __acquires(&keyring->sem)
+       __acquires(&keyring_serialise_link_sem)
 {
        struct keyring_list *klist, *nklist;
        unsigned long prealloc;
@@ -960,6 +961,7 @@ void __key_link(struct key *keyring, struct key *key,
 void __key_link_end(struct key *keyring, struct key_type *type,
                    unsigned long prealloc)
        __releases(&keyring->sem)
+       __releases(&keyring_serialise_link_sem)
 {
        BUG_ON(type == NULL);
        BUG_ON(type->name == NULL);
index 4ad54eea1ea45554d5d931497671fdb32a33660b..54339cfd6734d46927e8e9228019891e7130c272 100644 (file)
@@ -834,12 +834,11 @@ error:
  * Replace a process's session keyring on behalf of one of its children when
  * the target  process is about to resume userspace execution.
  */
-void key_change_session_keyring(struct task_work *twork)
+void key_change_session_keyring(struct callback_head *twork)
 {
        const struct cred *old = current_cred();
-       struct cred *new = twork->data;
+       struct cred *new = container_of(twork, struct cred, rcu);
 
-       kfree(twork);
        if (unlikely(current->flags & PF_EXITING)) {
                put_cred(new);
                return;
index 13ae6b0bdd655a63b913e4a430f2c2f7c2157c9a..689fe2d2216569aea465076ff7d219c9a8ea9216 100644 (file)
@@ -2157,8 +2157,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
                                                get_file(devnull);
                                        } else {
                                                devnull = dentry_open(
-                                                       dget(selinux_null),
-                                                       mntget(selinuxfs_mount),
+                                                       &selinux_null,
                                                        O_RDWR, cred);
                                                if (IS_ERR(devnull)) {
                                                        devnull = NULL;
index dde2005407aa5343dd92fe0e91e4b1a0d68ee33d..6d3885165d143a27fb218e785aa4a13ac7937045 100644 (file)
@@ -221,7 +221,7 @@ extern void selinux_status_update_policyload(int seqno);
 extern void selinux_complete_init(void);
 extern int selinux_disable(void);
 extern void exit_sel_fs(void);
-extern struct dentry *selinux_null;
+extern struct path selinux_null;
 extern struct vfsmount *selinuxfs_mount;
 extern void selnl_notify_setenforce(int val);
 extern void selnl_notify_policyload(u32 seqno);
index 3ad2902512888282e299b64434a7790d9788e060..298e695d6822577e80e5a03a3b5b77d78fe9ebc8 100644 (file)
@@ -1297,7 +1297,7 @@ out:
 
 #define NULL_FILE_NAME "null"
 
-struct dentry *selinux_null;
+struct path selinux_null;
 
 static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf,
                                            size_t count, loff_t *ppos)
@@ -1838,7 +1838,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
 
        init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3));
        d_add(dentry, inode);
-       selinux_null = dentry;
+       selinux_null.dentry = dentry;
 
        dentry = sel_make_dir(sb->s_root, "avc", &sel_last_ino);
        if (IS_ERR(dentry)) {
@@ -1912,7 +1912,7 @@ static int __init init_sel_fs(void)
                return err;
        }
 
-       selinuxfs_mount = kern_mount(&sel_fs_type);
+       selinux_null.mnt = selinuxfs_mount = kern_mount(&sel_fs_type);
        if (IS_ERR(selinuxfs_mount)) {
                printk(KERN_ERR "selinuxfs:  could not mount!\n");
                err = PTR_ERR(selinuxfs_mount);
index cc361b8f3d1345f7347c0ff7a968f916908be800..99b36124f7121ebfa3061a528543d49b2bacb6e3 100644 (file)
@@ -43,7 +43,6 @@ struct superblock_smack {
        char            *smk_hat;
        char            *smk_default;
        int             smk_initialized;
-       spinlock_t      smk_sblock;     /* for initialization */
 };
 
 struct socket_smack {
@@ -283,6 +282,19 @@ static inline char *smk_of_current(void)
        return smk_of_task(current_security());
 }
 
+/*
+ * Is the task privileged and allowed to be privileged
+ * by the onlycap rule.
+ */
+static inline int smack_privileged(int cap)
+{
+       if (!capable(cap))
+               return 0;
+       if (smack_onlycap == NULL || smack_onlycap == smk_of_current())
+               return 1;
+       return 0;
+}
+
 /*
  * logging functions
  */
index 9f3705e927128b74c299e24afb4146b51881f6bf..db14689a21e02ad60bc8cd1ab5e5dc97f8419188 100644 (file)
@@ -220,14 +220,9 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
        }
 
        /*
-        * Return if a specific label has been designated as the
-        * only one that gets privilege and current does not
-        * have that label.
+        * Allow for priviliged to override policy.
         */
-       if (smack_onlycap != NULL && smack_onlycap != sp)
-               goto out_audit;
-
-       if (capable(CAP_MAC_OVERRIDE))
+       if (rc != 0 && smack_privileged(CAP_MAC_OVERRIDE))
                rc = 0;
 
 out_audit:
index ee0bb5735f35c98d6edfa7bb4c9590ef2a234cc4..8221514cc997303f5d5d8844198c233fe79b64ac 100644 (file)
@@ -217,7 +217,7 @@ static int smack_syslog(int typefrom_file)
        int rc = 0;
        char *sp = smk_of_current();
 
-       if (capable(CAP_MAC_OVERRIDE))
+       if (smack_privileged(CAP_MAC_OVERRIDE))
                return 0;
 
         if (sp != smack_known_floor.smk_known)
@@ -251,7 +251,6 @@ static int smack_sb_alloc_security(struct super_block *sb)
        sbsp->smk_floor = smack_known_floor.smk_known;
        sbsp->smk_hat = smack_known_hat.smk_known;
        sbsp->smk_initialized = 0;
-       spin_lock_init(&sbsp->smk_sblock);
 
        sb->s_security = sbsp;
 
@@ -332,13 +331,10 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
        char *commap;
        char *nsp;
 
-       spin_lock(&sp->smk_sblock);
-       if (sp->smk_initialized != 0) {
-               spin_unlock(&sp->smk_sblock);
+       if (sp->smk_initialized != 0)
                return 0;
-       }
+
        sp->smk_initialized = 1;
-       spin_unlock(&sp->smk_sblock);
 
        for (op = data; op != NULL; op = commap) {
                commap = strchr(op, ',');
@@ -825,7 +821,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
            strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
            strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
            strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
-               if (!capable(CAP_MAC_ADMIN))
+               if (!smack_privileged(CAP_MAC_ADMIN))
                        rc = -EPERM;
                /*
                 * check label validity here so import wont fail on
@@ -835,7 +831,7 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
                    smk_import(value, size) == NULL)
                        rc = -EINVAL;
        } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
-               if (!capable(CAP_MAC_ADMIN))
+               if (!smack_privileged(CAP_MAC_ADMIN))
                        rc = -EPERM;
                if (size != TRANS_TRUE_SIZE ||
                    strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
@@ -931,7 +927,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
            strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
            strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 ||
            strcmp(name, XATTR_NAME_SMACKMMAP)) {
-               if (!capable(CAP_MAC_ADMIN))
+               if (!smack_privileged(CAP_MAC_ADMIN))
                        rc = -EPERM;
        } else
                rc = cap_inode_removexattr(dentry, name);
@@ -1720,7 +1716,8 @@ static int smack_task_wait(struct task_struct *p)
         * state into account in the decision as well as
         * the smack value.
         */
-       if (capable(CAP_MAC_OVERRIDE) || has_capability(p, CAP_MAC_OVERRIDE))
+       if (smack_privileged(CAP_MAC_OVERRIDE) ||
+           has_capability(p, CAP_MAC_OVERRIDE))
                rc = 0;
        /* we log only if we didn't get overriden */
  out_log:
@@ -2721,7 +2718,7 @@ static int smack_setprocattr(struct task_struct *p, char *name,
        if (p != current)
                return -EPERM;
 
-       if (!capable(CAP_MAC_ADMIN))
+       if (!smack_privileged(CAP_MAC_ADMIN))
                return -EPERM;
 
        if (value == NULL || size == 0 || size >= SMK_LONGLABEL)
@@ -2784,7 +2781,7 @@ static int smack_unix_stream_connect(struct sock *sock,
        smk_ad_setfield_u_net_sk(&ad, other);
 #endif
 
-       if (!capable(CAP_MAC_OVERRIDE))
+       if (!smack_privileged(CAP_MAC_OVERRIDE))
                rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
 
        /*
@@ -2820,7 +2817,7 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
        smk_ad_setfield_u_net_sk(&ad, other->sk);
 #endif
 
-       if (!capable(CAP_MAC_OVERRIDE))
+       if (!smack_privileged(CAP_MAC_OVERRIDE))
                rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad);
 
        return rc;
index 1810c9a4ed48b84e2c317a5940e799546379d1f8..d31e6d957c21a47733ca1d73e8a43ef7d3fae22c 100644 (file)
@@ -215,28 +215,27 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
  * @access: access string
  * @rule: Smack rule
  * @import: if non-zero, import labels
+ * @len: label length limit
  *
  * Returns 0 on success, -1 on failure
  */
 static int smk_fill_rule(const char *subject, const char *object,
                                const char *access, struct smack_rule *rule,
-                               int import)
+                               int import, int len)
 {
-       int rc = -1;
-       int done;
        const char *cp;
        struct smack_known *skp;
 
        if (import) {
-               rule->smk_subject = smk_import(subject, 0);
+               rule->smk_subject = smk_import(subject, len);
                if (rule->smk_subject == NULL)
                        return -1;
 
-               rule->smk_object = smk_import(object, 0);
+               rule->smk_object = smk_import(object, len);
                if (rule->smk_object == NULL)
                        return -1;
        } else {
-               cp = smk_parse_smack(subject, 0);
+               cp = smk_parse_smack(subject, len);
                if (cp == NULL)
                        return -1;
                skp = smk_find_entry(cp);
@@ -245,7 +244,7 @@ static int smk_fill_rule(const char *subject, const char *object,
                        return -1;
                rule->smk_subject = skp->smk_known;
 
-               cp = smk_parse_smack(object, 0);
+               cp = smk_parse_smack(object, len);
                if (cp == NULL)
                        return -1;
                skp = smk_find_entry(cp);
@@ -257,7 +256,7 @@ static int smk_fill_rule(const char *subject, const char *object,
 
        rule->smk_access = 0;
 
-       for (cp = access, done = 0; *cp && !done; cp++) {
+       for (cp = access; *cp != '\0'; cp++) {
                switch (*cp) {
                case '-':
                        break;
@@ -282,13 +281,11 @@ static int smk_fill_rule(const char *subject, const char *object,
                        rule->smk_access |= MAY_TRANSMUTE;
                        break;
                default:
-                       done = 1;
-                       break;
+                       return 0;
                }
        }
-       rc = 0;
 
-       return rc;
+       return 0;
 }
 
 /**
@@ -304,7 +301,8 @@ static int smk_parse_rule(const char *data, struct smack_rule *rule, int import)
        int rc;
 
        rc = smk_fill_rule(data, data + SMK_LABELLEN,
-                          data + SMK_LABELLEN + SMK_LABELLEN, rule, import);
+                          data + SMK_LABELLEN + SMK_LABELLEN, rule, import,
+                          SMK_LABELLEN);
        return rc;
 }
 
@@ -340,7 +338,7 @@ static int smk_parse_long_rule(const char *data, struct smack_rule *rule,
                goto free_out_o;
 
        if (sscanf(data, "%s %s %s", subject, object, access) == 3)
-               rc = smk_fill_rule(subject, object, access, rule, import);
+               rc = smk_fill_rule(subject, object, access, rule, import, 0);
 
        kfree(access);
 free_out_o:
@@ -520,6 +518,9 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
        if (strlen(srp->smk_subject) >= max || strlen(srp->smk_object) >= max)
                return;
 
+       if (srp->smk_access == 0)
+               return;
+
        seq_printf(s, "%s %s", srp->smk_subject, srp->smk_object);
 
        seq_putc(s, ' ');
@@ -534,8 +535,6 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
                seq_putc(s, 'a');
        if (srp->smk_access & MAY_TRANSMUTE)
                seq_putc(s, 't');
-       if (srp->smk_access == 0)
-               seq_putc(s, '-');
 
        seq_putc(s, '\n');
 }
@@ -595,13 +594,12 @@ static int smk_open_load(struct inode *inode, struct file *file)
 static ssize_t smk_write_load(struct file *file, const char __user *buf,
                              size_t count, loff_t *ppos)
 {
-
        /*
         * Must have privilege.
         * No partial writes.
         * Enough data must be present.
         */
-       if (!capable(CAP_MAC_ADMIN))
+       if (!smack_privileged(CAP_MAC_ADMIN))
                return -EPERM;
 
        return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
@@ -787,7 +785,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
         * No partial writes.
         * Enough data must be present.
         */
-       if (!capable(CAP_MAC_ADMIN))
+       if (!smack_privileged(CAP_MAC_ADMIN))
                return -EPERM;
        if (*ppos != 0)
                return -EINVAL;
@@ -1090,7 +1088,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
         * "<addr/mask, as a.b.c.d/e><space><label>"
         * "<addr, as a.b.c.d><space><label>"
         */
-       if (!capable(CAP_MAC_ADMIN))
+       if (!smack_privileged(CAP_MAC_ADMIN))
                return -EPERM;
        if (*ppos != 0)
                return -EINVAL;
@@ -1267,7 +1265,7 @@ static ssize_t smk_write_doi(struct file *file, const char __user *buf,
        char temp[80];
        int i;
 
-       if (!capable(CAP_MAC_ADMIN))
+       if (!smack_privileged(CAP_MAC_ADMIN))
                return -EPERM;
 
        if (count >= sizeof(temp) || count == 0)
@@ -1334,7 +1332,7 @@ static ssize_t smk_write_direct(struct file *file, const char __user *buf,
        char temp[80];
        int i;
 
-       if (!capable(CAP_MAC_ADMIN))
+       if (!smack_privileged(CAP_MAC_ADMIN))
                return -EPERM;
 
        if (count >= sizeof(temp) || count == 0)
@@ -1412,7 +1410,7 @@ static ssize_t smk_write_mapped(struct file *file, const char __user *buf,
        char temp[80];
        int i;
 
-       if (!capable(CAP_MAC_ADMIN))
+       if (!smack_privileged(CAP_MAC_ADMIN))
                return -EPERM;
 
        if (count >= sizeof(temp) || count == 0)
@@ -1503,7 +1501,7 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
        char *data;
        int rc = count;
 
-       if (!capable(CAP_MAC_ADMIN))
+       if (!smack_privileged(CAP_MAC_ADMIN))
                return -EPERM;
 
        data = kzalloc(count + 1, GFP_KERNEL);
@@ -1586,7 +1584,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
        char *sp = smk_of_task(current->cred->security);
        int rc = count;
 
-       if (!capable(CAP_MAC_ADMIN))
+       if (!smack_privileged(CAP_MAC_ADMIN))
                return -EPERM;
 
        /*
@@ -1664,7 +1662,7 @@ static ssize_t smk_write_logging(struct file *file, const char __user *buf,
        char temp[32];
        int i;
 
-       if (!capable(CAP_MAC_ADMIN))
+       if (!smack_privileged(CAP_MAC_ADMIN))
                return -EPERM;
 
        if (count >= sizeof(temp) || count == 0)
@@ -1885,7 +1883,7 @@ static ssize_t smk_write_load2(struct file *file, const char __user *buf,
        /*
         * Must have privilege.
         */
-       if (!capable(CAP_MAC_ADMIN))
+       if (!smack_privileged(CAP_MAC_ADMIN))
                return -EPERM;
 
        return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
@@ -2051,7 +2049,6 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
        }
 
        root_inode = sb->s_root->d_inode;
-       root_inode->i_security = new_inode_smack(smack_known_floor.smk_known);
 
        return 0;
 }
index 270790d384e20f06a38f369cf5aa9c980aac4ed6..4cedc6950d72ffb79c329612fd91dc0fed465668 100644 (file)
@@ -997,45 +997,10 @@ static void onyx_exit_codec(struct aoa_codec *codec)
        onyx->codec.soundbus_dev->detach_codec(onyx->codec.soundbus_dev, onyx);
 }
 
-static int onyx_create(struct i2c_adapter *adapter,
-                      struct device_node *node,
-                      int addr)
-{
-       struct i2c_board_info info;
-       struct i2c_client *client;
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       strlcpy(info.type, "aoa_codec_onyx", I2C_NAME_SIZE);
-       info.addr = addr;
-       info.platform_data = node;
-       client = i2c_new_device(adapter, &info);
-       if (!client)
-               return -ENODEV;
-
-       /*
-        * We know the driver is already loaded, so the device should be
-        * already bound. If not it means binding failed, which suggests
-        * the device doesn't really exist and should be deleted.
-        * Ideally this would be replaced by better checks _before_
-        * instantiating the device.
-        */
-       if (!client->driver) {
-               i2c_unregister_device(client);
-               return -ENODEV;
-       }
-
-       /*
-        * Let i2c-core delete that device on driver removal.
-        * This is safe because i2c-core holds the core_lock mutex for us.
-        */
-       list_add_tail(&client->detected, &client->driver->clients);
-       return 0;
-}
-
 static int onyx_i2c_probe(struct i2c_client *client,
                          const struct i2c_device_id *id)
 {
-       struct device_node *node = client->dev.platform_data;
+       struct device_node *node = client->dev.of_node;
        struct onyx *onyx;
        u8 dummy;
 
@@ -1071,40 +1036,6 @@ static int onyx_i2c_probe(struct i2c_client *client,
        return -ENODEV;
 }
 
-static int onyx_i2c_attach(struct i2c_adapter *adapter)
-{
-       struct device_node *busnode, *dev = NULL;
-       struct pmac_i2c_bus *bus;
-
-       bus = pmac_i2c_adapter_to_bus(adapter);
-       if (bus == NULL)
-               return -ENODEV;
-       busnode = pmac_i2c_get_bus_node(bus);
-
-       while ((dev = of_get_next_child(busnode, dev)) != NULL) {
-               if (of_device_is_compatible(dev, "pcm3052")) {
-                       const u32 *addr;
-                       printk(KERN_DEBUG PFX "found pcm3052\n");
-                       addr = of_get_property(dev, "reg", NULL);
-                       if (!addr)
-                               return -ENODEV;
-                       return onyx_create(adapter, dev, (*addr)>>1);
-               }
-       }
-
-       /* if that didn't work, try desperate mode for older
-        * machines that have stuff missing from the device tree */
-
-       if (!of_device_is_compatible(busnode, "k2-i2c"))
-               return -ENODEV;
-
-       printk(KERN_DEBUG PFX "found k2-i2c, checking if onyx chip is on it\n");
-       /* probe both possible addresses for the onyx chip */
-       if (onyx_create(adapter, NULL, 0x46) == 0)
-               return 0;
-       return onyx_create(adapter, NULL, 0x47);
-}
-
 static int onyx_i2c_remove(struct i2c_client *client)
 {
        struct onyx *onyx = i2c_get_clientdata(client);
@@ -1117,16 +1048,16 @@ static int onyx_i2c_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id onyx_i2c_id[] = {
-       { "aoa_codec_onyx", 0 },
+       { "MAC,pcm3052", 0 },
        { }
 };
+MODULE_DEVICE_TABLE(i2c,onyx_i2c_id);
 
 static struct i2c_driver onyx_driver = {
        .driver = {
                .name = "aoa_codec_onyx",
                .owner = THIS_MODULE,
        },
-       .attach_adapter = onyx_i2c_attach,
        .probe = onyx_i2c_probe,
        .remove = onyx_i2c_remove,
        .id_table = onyx_i2c_id,
index 8e63d1f35ce1228cc1f6abb76cb39e1d421ea43a..c491ae0f749ca42578c8fd8faf4f4b43f0fcaf55 100644 (file)
@@ -883,43 +883,10 @@ static void tas_exit_codec(struct aoa_codec *codec)
 }
 
 
-static int tas_create(struct i2c_adapter *adapter,
-                      struct device_node *node,
-                      int addr)
-{
-       struct i2c_board_info info;
-       struct i2c_client *client;
-
-       memset(&info, 0, sizeof(struct i2c_board_info));
-       strlcpy(info.type, "aoa_codec_tas", I2C_NAME_SIZE);
-       info.addr = addr;
-       info.platform_data = node;
-
-       client = i2c_new_device(adapter, &info);
-       if (!client)
-               return -ENODEV;
-       /*
-        * We know the driver is already loaded, so the device should be
-        * already bound. If not it means binding failed, and then there
-        * is no point in keeping the device instantiated.
-        */
-       if (!client->driver) {
-               i2c_unregister_device(client);
-               return -ENODEV;
-       }
-
-       /*
-        * Let i2c-core delete that device on driver removal.
-        * This is safe because i2c-core holds the core_lock mutex for us.
-        */
-       list_add_tail(&client->detected, &client->driver->clients);
-       return 0;
-}
-
 static int tas_i2c_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
-       struct device_node *node = client->dev.platform_data;
+       struct device_node *node = client->dev.of_node;
        struct tas *tas;
 
        tas = kzalloc(sizeof(struct tas), GFP_KERNEL);
@@ -953,47 +920,6 @@ static int tas_i2c_probe(struct i2c_client *client,
        return -EINVAL;
 }
 
-static int tas_i2c_attach(struct i2c_adapter *adapter)
-{
-       struct device_node *busnode, *dev = NULL;
-       struct pmac_i2c_bus *bus;
-
-       bus = pmac_i2c_adapter_to_bus(adapter);
-       if (bus == NULL)
-               return -ENODEV;
-       busnode = pmac_i2c_get_bus_node(bus);
-
-       while ((dev = of_get_next_child(busnode, dev)) != NULL) {
-               if (of_device_is_compatible(dev, "tas3004")) {
-                       const u32 *addr;
-                       printk(KERN_DEBUG PFX "found tas3004\n");
-                       addr = of_get_property(dev, "reg", NULL);
-                       if (!addr)
-                               continue;
-                       return tas_create(adapter, dev, ((*addr) >> 1) & 0x7f);
-               }
-               /* older machines have no 'codec' node with a 'compatible'
-                * property that says 'tas3004', they just have a 'deq'
-                * node without any such property... */
-               if (strcmp(dev->name, "deq") == 0) {
-                       const u32 *_addr;
-                       u32 addr;
-                       printk(KERN_DEBUG PFX "found 'deq' node\n");
-                       _addr = of_get_property(dev, "i2c-address", NULL);
-                       if (!_addr)
-                               continue;
-                       addr = ((*_addr) >> 1) & 0x7f;
-                       /* now, if the address doesn't match any of the two
-                        * that a tas3004 can have, we cannot handle this.
-                        * I doubt it ever happens but hey. */
-                       if (addr != 0x34 && addr != 0x35)
-                               continue;
-                       return tas_create(adapter, dev, addr);
-               }
-       }
-       return -ENODEV;
-}
-
 static int tas_i2c_remove(struct i2c_client *client)
 {
        struct tas *tas = i2c_get_clientdata(client);
@@ -1011,16 +937,16 @@ static int tas_i2c_remove(struct i2c_client *client)
 }
 
 static const struct i2c_device_id tas_i2c_id[] = {
-       { "aoa_codec_tas", 0 },
+       { "MAC,tas3004", 0 },
        { }
 };
+MODULE_DEVICE_TABLE(i2c,tas_i2c_id);
 
 static struct i2c_driver tas_driver = {
        .driver = {
                .name = "aoa_codec_tas",
                .owner = THIS_MODULE,
        },
-       .attach_adapter = tas_i2c_attach,
        .probe = tas_i2c_probe,
        .remove = tas_i2c_remove,
        .id_table = tas_i2c_id,
index 456b7d723d6660176acbfb82436cf2f938985bab..ee27ba3933bd272399f6199b8614f68ef2ab07fe 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <asm/fiq.h>
 
+#include <mach/irqs.h>
 #include <mach/ssi.h>
 
 #include "imx-ssi.h"
index ddc6cde14e2a588763531d94f22b0dab2b1d9a49..f3ebc38c10fe7633ea5ec260562b64bfdb7e402f 100644 (file)
@@ -74,7 +74,7 @@ static void dma_enqueue(struct snd_pcm_substream *substream)
        struct runtime_data *prtd = substream->runtime->private_data;
        dma_addr_t pos = prtd->dma_pos;
        unsigned int limit;
-       struct samsung_dma_prep_info dma_info;
+       struct samsung_dma_prep dma_info;
 
        pr_debug("Entered %s\n", __func__);
 
@@ -146,7 +146,8 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
        unsigned long totbytes = params_buffer_bytes(params);
        struct s3c_dma_params *dma =
                snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-       struct samsung_dma_info dma_info;
+       struct samsung_dma_req req;
+       struct samsung_dma_config config;
 
        pr_debug("Entered %s\n", __func__);
 
@@ -166,16 +167,17 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
 
                prtd->params->ops = samsung_dma_get_ops();
 
-               dma_info.cap = (samsung_dma_has_circular() ?
+               req.cap = (samsung_dma_has_circular() ?
                        DMA_CYCLIC : DMA_SLAVE);
-               dma_info.client = prtd->params->client;
-               dma_info.direction =
+               req.client = prtd->params->client;
+               config.direction =
                        (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
                        ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
-               dma_info.width = prtd->params->dma_size;
-               dma_info.fifo = prtd->params->dma_addr;
+               config.width = prtd->params->dma_size;
+               config.fifo = prtd->params->dma_addr;
                prtd->params->ch = prtd->params->ops->request(
-                               prtd->params->channel, &dma_info);
+                               prtd->params->channel, &req);
+               prtd->params->ops->config(prtd->params->ch, &config);
        }
 
        snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
index c1c8e955f4d31b2a79be704d7dda736bd1e24010..76dc230f2bb05e42e430535be777200fd457e537 100644 (file)
@@ -58,17 +58,9 @@ config SND_SOC_TEGRA_WM8753
          Say Y or M here if you want to add support for SoC audio on Tegra
          boards using the WM8753 codec, such as Whistler.
 
-config MACH_HAS_SND_SOC_TEGRA_WM8903
-       bool
-       help
-         Machines that use the SND_SOC_TEGRA_WM8903 driver should select
-         this config option, in order to allow the user to enable
-         SND_SOC_TEGRA_WM8903.
-
 config SND_SOC_TEGRA_WM8903
        tristate "SoC Audio support for Tegra boards using a WM8903 codec"
        depends on SND_SOC_TEGRA && I2C
-       depends on MACH_HAS_SND_SOC_TEGRA_WM8903
        select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
        select SND_SOC_TEGRA30_I2S if ARCH_TEGRA_3x_SOC
        select SND_SOC_WM8903
@@ -79,7 +71,7 @@ config SND_SOC_TEGRA_WM8903
 
 config SND_SOC_TEGRA_TRIMSLICE
        tristate "SoC Audio support for TrimSlice board"
-       depends on SND_SOC_TEGRA && MACH_TRIMSLICE && I2C
+       depends on SND_SOC_TEGRA && I2C
        select SND_SOC_TEGRA20_I2S if ARCH_TEGRA_2x_SOC
        select SND_SOC_TLV320AIC23
        help
index 0c7af63d444b4ba42f8305a8d12392668718e624..1647dbfe74b5f7dd324331ae5d92e8dc4e5b1740 100644 (file)
@@ -62,7 +62,7 @@ static int tegra20_i2s_runtime_suspend(struct device *dev)
 {
        struct tegra20_i2s *i2s = dev_get_drvdata(dev);
 
-       clk_disable(i2s->clk_i2s);
+       clk_disable_unprepare(i2s->clk_i2s);
 
        return 0;
 }
@@ -72,7 +72,7 @@ static int tegra20_i2s_runtime_resume(struct device *dev)
        struct tegra20_i2s *i2s = dev_get_drvdata(dev);
        int ret;
 
-       ret = clk_enable(i2s->clk_i2s);
+       ret = clk_prepare_enable(i2s->clk_i2s);
        if (ret) {
                dev_err(dev, "clk_enable failed: %d\n", ret);
                return ret;
index f9b57418bd088c42f83f7e4bfde699dd7407298d..2262e4fdec2af6f2fc85edb65c3f1cf180643a2c 100644 (file)
@@ -54,7 +54,7 @@ static int tegra20_spdif_runtime_suspend(struct device *dev)
 {
        struct tegra20_spdif *spdif = dev_get_drvdata(dev);
 
-       clk_disable(spdif->clk_spdif_out);
+       clk_disable_unprepare(spdif->clk_spdif_out);
 
        return 0;
 }
@@ -64,7 +64,7 @@ static int tegra20_spdif_runtime_resume(struct device *dev)
        struct tegra20_spdif *spdif = dev_get_drvdata(dev);
        int ret;
 
-       ret = clk_enable(spdif->clk_spdif_out);
+       ret = clk_prepare_enable(spdif->clk_spdif_out);
        if (ret) {
                dev_err(dev, "clk_enable failed: %d\n", ret);
                return ret;
index f43edb364a185de5cb2f3c43aa16850a32c2236e..bf5610122c763b85ec91f7132f6eb00de92a2b06 100644 (file)
@@ -56,8 +56,8 @@ static int tegra30_ahub_runtime_suspend(struct device *dev)
        regcache_cache_only(ahub->regmap_apbif, true);
        regcache_cache_only(ahub->regmap_ahub, true);
 
-       clk_disable(ahub->clk_apbif);
-       clk_disable(ahub->clk_d_audio);
+       clk_disable_unprepare(ahub->clk_apbif);
+       clk_disable_unprepare(ahub->clk_d_audio);
 
        return 0;
 }
@@ -77,12 +77,12 @@ static int tegra30_ahub_runtime_resume(struct device *dev)
 {
        int ret;
 
-       ret = clk_enable(ahub->clk_d_audio);
+       ret = clk_prepare_enable(ahub->clk_d_audio);
        if (ret) {
                dev_err(dev, "clk_enable d_audio failed: %d\n", ret);
                return ret;
        }
-       ret = clk_enable(ahub->clk_apbif);
+       ret = clk_prepare_enable(ahub->clk_apbif);
        if (ret) {
                dev_err(dev, "clk_enable apbif failed: %d\n", ret);
                clk_disable(ahub->clk_d_audio);
index 8596032985dc790e7ca07fc637fd11c36f210cf8..d308faaae148e36fcf83ae8beab5f4abce9ff08d 100644 (file)
@@ -62,7 +62,7 @@ static int tegra30_i2s_runtime_suspend(struct device *dev)
 
        regcache_cache_only(i2s->regmap, true);
 
-       clk_disable(i2s->clk_i2s);
+       clk_disable_unprepare(i2s->clk_i2s);
 
        return 0;
 }
@@ -72,7 +72,7 @@ static int tegra30_i2s_runtime_resume(struct device *dev)
        struct tegra30_i2s *i2s = dev_get_drvdata(dev);
        int ret;
 
-       ret = clk_enable(i2s->clk_i2s);
+       ret = clk_prepare_enable(i2s->clk_i2s);
        if (ret) {
                dev_err(dev, "clk_enable failed: %d\n", ret);
                return ret;
index 9515ce58ea022a11f059edd9f7163ca1b95a1a04..6872c77a1196e948de6827c88581120ec19064f3 100644 (file)
@@ -69,9 +69,9 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
        data->set_baseclock = 0;
        data->set_mclk = 0;
 
-       clk_disable(data->clk_cdev1);
-       clk_disable(data->clk_pll_a_out0);
-       clk_disable(data->clk_pll_a);
+       clk_disable_unprepare(data->clk_cdev1);
+       clk_disable_unprepare(data->clk_pll_a_out0);
+       clk_disable_unprepare(data->clk_pll_a);
 
        err = clk_set_rate(data->clk_pll_a, new_baseclock);
        if (err) {
@@ -87,19 +87,19 @@ int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
 
        /* Don't set cdev1/extern1 rate; it's locked to pll_a_out0 */
 
-       err = clk_enable(data->clk_pll_a);
+       err = clk_prepare_enable(data->clk_pll_a);
        if (err) {
                dev_err(data->dev, "Can't enable pll_a: %d\n", err);
                return err;
        }
 
-       err = clk_enable(data->clk_pll_a_out0);
+       err = clk_prepare_enable(data->clk_pll_a_out0);
        if (err) {
                dev_err(data->dev, "Can't enable pll_a_out0: %d\n", err);
                return err;
        }
 
-       err = clk_enable(data->clk_cdev1);
+       err = clk_prepare_enable(data->clk_cdev1);
        if (err) {
                dev_err(data->dev, "Can't enable cdev1: %d\n", err);
                return err;
index 3d69aa9ff51e8ff336cae400860a4b544dc82fe3..46c2f6b7b123c388d056ae6c324cdde76edef182 100644 (file)
@@ -250,8 +250,12 @@ endef
 all_objs := $(sort $(ALL_OBJS))
 all_deps := $(all_objs:%.o=.%.d)
 
+# let .d file also depends on the source and header files
 define check_deps
-               $(CC) -M $(CFLAGS) $< > $@;
+               @set -e; $(RM) $@; \
+               $(CC) -M $(CFLAGS) $< > $@.$$$$; \
+               sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+               $(RM) $@.$$$$
 endef
 
 $(gui_deps): ks_version.h
@@ -270,11 +274,13 @@ endif
 
 tags:  force
        $(RM) tags
-       find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px
+       find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
+       --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/'
 
 TAGS:  force
        $(RM) TAGS
-       find . -name '*.[ch]' | xargs etags
+       find . -name '*.[ch]' | xargs etags \
+       --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/'
 
 define do_install
        $(print_install)                                \
@@ -290,7 +296,7 @@ install_lib: all_cmd install_plugins install_python
 install: install_lib
 
 clean:
-       $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES).*.d
+       $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d
        $(RM) tags TAGS
 
 endif # skip-makefile
index 554828219c33cceaf0c5b9d3f57bd69d4a7a109f..5f34aa371b5660c503cfca05e9e0731aba013ea7 100644 (file)
@@ -467,8 +467,10 @@ int pevent_register_function(struct pevent *pevent, char *func,
                item->mod = NULL;
        item->addr = addr;
 
-       pevent->funclist = item;
+       if (!item->func || (mod && !item->mod))
+               die("malloc func");
 
+       pevent->funclist = item;
        pevent->func_count++;
 
        return 0;
@@ -511,12 +513,12 @@ struct printk_list {
 
 static int printk_cmp(const void *a, const void *b)
 {
-       const struct func_map *fa = a;
-       const struct func_map *fb = b;
+       const struct printk_map *pa = a;
+       const struct printk_map *pb = b;
 
-       if (fa->addr < fb->addr)
+       if (pa->addr < pb->addr)
                return -1;
-       if (fa->addr > fb->addr)
+       if (pa->addr > pb->addr)
                return 1;
 
        return 0;
@@ -583,10 +585,13 @@ int pevent_register_print_string(struct pevent *pevent, char *fmt,
        item = malloc_or_die(sizeof(*item));
 
        item->next = pevent->printklist;
-       pevent->printklist = item;
        item->printk = strdup(fmt);
        item->addr = addr;
 
+       if (!item->printk)
+               die("malloc fmt");
+
+       pevent->printklist = item;
        pevent->printk_count++;
 
        return 0;
@@ -616,7 +621,9 @@ static struct event_format *alloc_event(void)
 {
        struct event_format *event;
 
-       event = malloc_or_die(sizeof(*event));
+       event = malloc(sizeof(*event));
+       if (!event)
+               return NULL;
        memset(event, 0, sizeof(*event));
 
        return event;
@@ -626,12 +633,8 @@ static void add_event(struct pevent *pevent, struct event_format *event)
 {
        int i;
 
-       if (!pevent->events)
-               pevent->events = malloc_or_die(sizeof(event));
-       else
-               pevent->events =
-                       realloc(pevent->events, sizeof(event) *
-                               (pevent->nr_events + 1));
+       pevent->events = realloc(pevent->events, sizeof(event) *
+                                (pevent->nr_events + 1));
        if (!pevent->events)
                die("Can not allocate events");
 
@@ -697,6 +700,10 @@ static void free_arg(struct print_arg *arg)
                free_arg(arg->symbol.field);
                free_flag_sym(arg->symbol.symbols);
                break;
+       case PRINT_HEX:
+               free_arg(arg->hex.field);
+               free_arg(arg->hex.size);
+               break;
        case PRINT_TYPE:
                free(arg->typecast.type);
                free_arg(arg->typecast.item);
@@ -775,6 +782,25 @@ int pevent_peek_char(void)
        return __peek_char();
 }
 
+static int extend_token(char **tok, char *buf, int size)
+{
+       char *newtok = realloc(*tok, size);
+
+       if (!newtok) {
+               free(*tok);
+               *tok = NULL;
+               return -1;
+       }
+
+       if (!*tok)
+               strcpy(newtok, buf);
+       else
+               strcat(newtok, buf);
+       *tok = newtok;
+
+       return 0;
+}
+
 static enum event_type force_token(const char *str, char **tok);
 
 static enum event_type __read_token(char **tok)
@@ -859,17 +885,10 @@ static enum event_type __read_token(char **tok)
                do {
                        if (i == (BUFSIZ - 1)) {
                                buf[i] = 0;
-                               if (*tok) {
-                                       *tok = realloc(*tok, tok_size + BUFSIZ);
-                                       if (!*tok)
-                                               return EVENT_NONE;
-                                       strcat(*tok, buf);
-                               } else
-                                       *tok = strdup(buf);
+                               tok_size += BUFSIZ;
 
-                               if (!*tok)
+                               if (extend_token(tok, buf, tok_size) < 0)
                                        return EVENT_NONE;
-                               tok_size += BUFSIZ;
                                i = 0;
                        }
                        last_ch = ch;
@@ -908,17 +927,10 @@ static enum event_type __read_token(char **tok)
        while (get_type(__peek_char()) == type) {
                if (i == (BUFSIZ - 1)) {
                        buf[i] = 0;
-                       if (*tok) {
-                               *tok = realloc(*tok, tok_size + BUFSIZ);
-                               if (!*tok)
-                                       return EVENT_NONE;
-                               strcat(*tok, buf);
-                       } else
-                               *tok = strdup(buf);
+                       tok_size += BUFSIZ;
 
-                       if (!*tok)
+                       if (extend_token(tok, buf, tok_size) < 0)
                                return EVENT_NONE;
-                       tok_size += BUFSIZ;
                        i = 0;
                }
                ch = __read_char();
@@ -927,14 +939,7 @@ static enum event_type __read_token(char **tok)
 
  out:
        buf[i] = 0;
-       if (*tok) {
-               *tok = realloc(*tok, tok_size + i);
-               if (!*tok)
-                       return EVENT_NONE;
-               strcat(*tok, buf);
-       } else
-               *tok = strdup(buf);
-       if (!*tok)
+       if (extend_token(tok, buf, tok_size + i + 1) < 0)
                return EVENT_NONE;
 
        if (type == EVENT_ITEM) {
@@ -1255,9 +1260,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f
                                        field->flags |= FIELD_IS_POINTER;
 
                                if (field->type) {
-                                       field->type = realloc(field->type,
-                                                             strlen(field->type) +
-                                                             strlen(last_token) + 2);
+                                       char *new_type;
+                                       new_type = realloc(field->type,
+                                                          strlen(field->type) +
+                                                          strlen(last_token) + 2);
+                                       if (!new_type) {
+                                               free(last_token);
+                                               goto fail;
+                                       }
+                                       field->type = new_type;
                                        strcat(field->type, " ");
                                        strcat(field->type, last_token);
                                        free(last_token);
@@ -1282,6 +1293,7 @@ static int event_read_fields(struct event_format *event, struct format_field **f
                if (strcmp(token, "[") == 0) {
                        enum event_type last_type = type;
                        char *brackets = token;
+                       char *new_brackets;
                        int len;
 
                        field->flags |= FIELD_IS_ARRAY;
@@ -1301,9 +1313,14 @@ static int event_read_fields(struct event_format *event, struct format_field **f
                                        len = 1;
                                last_type = type;
 
-                               brackets = realloc(brackets,
-                                                  strlen(brackets) +
-                                                  strlen(token) + len);
+                               new_brackets = realloc(brackets,
+                                                      strlen(brackets) +
+                                                      strlen(token) + len);
+                               if (!new_brackets) {
+                                       free(brackets);
+                                       goto fail;
+                               }
+                               brackets = new_brackets;
                                if (len == 2)
                                        strcat(brackets, " ");
                                strcat(brackets, token);
@@ -1319,7 +1336,12 @@ static int event_read_fields(struct event_format *event, struct format_field **f
 
                        free_token(token);
 
-                       brackets = realloc(brackets, strlen(brackets) + 2);
+                       new_brackets = realloc(brackets, strlen(brackets) + 2);
+                       if (!new_brackets) {
+                               free(brackets);
+                               goto fail;
+                       }
+                       brackets = new_brackets;
                        strcat(brackets, "]");
 
                        /* add brackets to type */
@@ -1330,10 +1352,16 @@ static int event_read_fields(struct event_format *event, struct format_field **f
                         * the format: type [] item;
                         */
                        if (type == EVENT_ITEM) {
-                               field->type = realloc(field->type,
-                                                     strlen(field->type) +
-                                                     strlen(field->name) +
-                                                     strlen(brackets) + 2);
+                               char *new_type;
+                               new_type = realloc(field->type,
+                                                  strlen(field->type) +
+                                                  strlen(field->name) +
+                                                  strlen(brackets) + 2);
+                               if (!new_type) {
+                                       free(brackets);
+                                       goto fail;
+                               }
+                               field->type = new_type;
                                strcat(field->type, " ");
                                strcat(field->type, field->name);
                                free_token(field->name);
@@ -1341,9 +1369,15 @@ static int event_read_fields(struct event_format *event, struct format_field **f
                                field->name = token;
                                type = read_token(&token);
                        } else {
-                               field->type = realloc(field->type,
-                                                     strlen(field->type) +
-                                                     strlen(brackets) + 1);
+                               char *new_type;
+                               new_type = realloc(field->type,
+                                                  strlen(field->type) +
+                                                  strlen(brackets) + 1);
+                               if (!new_type) {
+                                       free(brackets);
+                                       goto fail;
+                               }
+                               field->type = new_type;
                                strcat(field->type, brackets);
                        }
                        free(brackets);
@@ -1726,10 +1760,16 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok)
                /* could just be a type pointer */
                if ((strcmp(arg->op.op, "*") == 0) &&
                    type == EVENT_DELIM && (strcmp(token, ")") == 0)) {
+                       char *new_atom;
+
                        if (left->type != PRINT_ATOM)
                                die("bad pointer type");
-                       left->atom.atom = realloc(left->atom.atom,
+                       new_atom = realloc(left->atom.atom,
                                            strlen(left->atom.atom) + 3);
+                       if (!new_atom)
+                               goto out_free;
+
+                       left->atom.atom = new_atom;
                        strcat(left->atom.atom, " *");
                        free(arg->op.op);
                        *arg = *left;
@@ -2146,6 +2186,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
                if (value == NULL)
                        goto out_free;
                field->value = strdup(value);
+               if (field->value == NULL)
+                       goto out_free;
 
                free_arg(arg);
                arg = alloc_arg();
@@ -2159,6 +2201,8 @@ process_fields(struct event_format *event, struct print_flag_sym **list, char **
                if (value == NULL)
                        goto out_free;
                field->str = strdup(value);
+               if (field->str == NULL)
+                       goto out_free;
                free_arg(arg);
                arg = NULL;
 
@@ -2259,6 +2303,45 @@ process_symbols(struct event_format *event, struct print_arg *arg, char **tok)
        return EVENT_ERROR;
 }
 
+static enum event_type
+process_hex(struct event_format *event, struct print_arg *arg, char **tok)
+{
+       struct print_arg *field;
+       enum event_type type;
+       char *token;
+
+       memset(arg, 0, sizeof(*arg));
+       arg->type = PRINT_HEX;
+
+       field = alloc_arg();
+       type = process_arg(event, field, &token);
+
+       if (test_type_token(type, token, EVENT_DELIM, ","))
+               goto out_free;
+
+       arg->hex.field = field;
+
+       free_token(token);
+
+       field = alloc_arg();
+       type = process_arg(event, field, &token);
+
+       if (test_type_token(type, token, EVENT_DELIM, ")"))
+               goto out_free;
+
+       arg->hex.size = field;
+
+       free_token(token);
+       type = read_token_item(tok);
+       return type;
+
+ out_free:
+       free_arg(field);
+       free_token(token);
+       *tok = NULL;
+       return EVENT_ERROR;
+}
+
 static enum event_type
 process_dynamic_array(struct event_format *event, struct print_arg *arg, char **tok)
 {
@@ -2488,6 +2571,10 @@ process_function(struct event_format *event, struct print_arg *arg,
                is_symbolic_field = 1;
                return process_symbols(event, arg, tok);
        }
+       if (strcmp(token, "__print_hex") == 0) {
+               free_token(token);
+               return process_hex(event, arg, tok);
+       }
        if (strcmp(token, "__get_str") == 0) {
                free_token(token);
                return process_str(event, arg, tok);
@@ -2541,7 +2628,16 @@ process_arg_token(struct event_format *event, struct print_arg *arg,
                }
                /* atoms can be more than one token long */
                while (type == EVENT_ITEM) {
-                       atom = realloc(atom, strlen(atom) + strlen(token) + 2);
+                       char *new_atom;
+                       new_atom = realloc(atom,
+                                          strlen(atom) + strlen(token) + 2);
+                       if (!new_atom) {
+                               free(atom);
+                               *tok = NULL;
+                               free_token(token);
+                               return EVENT_ERROR;
+                       }
+                       atom = new_atom;
                        strcat(atom, " ");
                        strcat(atom, token);
                        free_token(token);
@@ -2835,7 +2931,7 @@ static int get_common_info(struct pevent *pevent,
        event = pevent->events[0];
        field = pevent_find_common_field(event, type);
        if (!field)
-               die("field '%s' not found", type);
+               return -1;
 
        *offset = field->offset;
        *size = field->size;
@@ -2886,15 +2982,16 @@ static int parse_common_flags(struct pevent *pevent, void *data)
 
 static int parse_common_lock_depth(struct pevent *pevent, void *data)
 {
-       int ret;
-
-       ret = __parse_common(pevent, data,
-                            &pevent->ld_size, &pevent->ld_offset,
-                            "common_lock_depth");
-       if (ret < 0)
-               return -1;
+       return __parse_common(pevent, data,
+                             &pevent->ld_size, &pevent->ld_offset,
+                             "common_lock_depth");
+}
 
-       return ret;
+static int parse_common_migrate_disable(struct pevent *pevent, void *data)
+{
+       return __parse_common(pevent, data,
+                             &pevent->ld_size, &pevent->ld_offset,
+                             "common_migrate_disable");
 }
 
 static int events_id_cmp(const void *a, const void *b);
@@ -2995,6 +3092,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
                break;
        case PRINT_FLAGS:
        case PRINT_SYMBOL:
+       case PRINT_HEX:
                break;
        case PRINT_TYPE:
                val = eval_num_arg(data, size, event, arg->typecast.item);
@@ -3214,11 +3312,13 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
 {
        struct pevent *pevent = event->pevent;
        struct print_flag_sym *flag;
+       struct format_field *field;
        unsigned long long val, fval;
        unsigned long addr;
        char *str;
+       unsigned char *hex;
        int print;
-       int len;
+       int i, len;
 
        switch (arg->type) {
        case PRINT_NULL:
@@ -3228,27 +3328,29 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                print_str_to_seq(s, format, len_arg, arg->atom.atom);
                return;
        case PRINT_FIELD:
-               if (!arg->field.field) {
-                       arg->field.field = pevent_find_any_field(event, arg->field.name);
-                       if (!arg->field.field)
+               field = arg->field.field;
+               if (!field) {
+                       field = pevent_find_any_field(event, arg->field.name);
+                       if (!field)
                                die("field %s not found", arg->field.name);
+                       arg->field.field = field;
                }
                /* Zero sized fields, mean the rest of the data */
-               len = arg->field.field->size ? : size - arg->field.field->offset;
+               len = field->size ? : size - field->offset;
 
                /*
                 * Some events pass in pointers. If this is not an array
                 * and the size is the same as long_size, assume that it
                 * is a pointer.
                 */
-               if (!(arg->field.field->flags & FIELD_IS_ARRAY) &&
-                   arg->field.field->size == pevent->long_size) {
-                       addr = *(unsigned long *)(data + arg->field.field->offset);
+               if (!(field->flags & FIELD_IS_ARRAY) &&
+                   field->size == pevent->long_size) {
+                       addr = *(unsigned long *)(data + field->offset);
                        trace_seq_printf(s, "%lx", addr);
                        break;
                }
                str = malloc_or_die(len + 1);
-               memcpy(str, data + arg->field.field->offset, len);
+               memcpy(str, data + field->offset, len);
                str[len] = 0;
                print_str_to_seq(s, format, len_arg, str);
                free(str);
@@ -3281,6 +3383,23 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                        }
                }
                break;
+       case PRINT_HEX:
+               field = arg->hex.field->field.field;
+               if (!field) {
+                       str = arg->hex.field->field.name;
+                       field = pevent_find_any_field(event, str);
+                       if (!field)
+                               die("field %s not found", str);
+                       arg->hex.field->field.field = field;
+               }
+               hex = data + field->offset;
+               len = eval_num_arg(data, size, event, arg->hex.size);
+               for (i = 0; i < len; i++) {
+                       if (i)
+                               trace_seq_putc(s, ' ');
+                       trace_seq_printf(s, "%02x", hex[i]);
+               }
+               break;
 
        case PRINT_TYPE:
                break;
@@ -3299,7 +3418,7 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
                break;
        }
        case PRINT_BSTRING:
-               trace_seq_printf(s, format, arg->string.string);
+               print_str_to_seq(s, format, len_arg, arg->string.string);
                break;
        case PRINT_OP:
                /*
@@ -3363,6 +3482,10 @@ process_defined_func(struct trace_seq *s, void *data, int size,
                        string = malloc_or_die(sizeof(*string));
                        string->next = strings;
                        string->str = strdup(str.buffer);
+                       if (!string->str)
+                               die("malloc str");
+
+                       args[i] = (unsigned long long)string->str;
                        strings = string;
                        trace_seq_destroy(&str);
                        break;
@@ -3400,6 +3523,7 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
        unsigned long long ip, val;
        char *ptr;
        void *bptr;
+       int vsize;
 
        field = pevent->bprint_buf_field;
        ip_field = pevent->bprint_ip_field;
@@ -3448,6 +3572,8 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
                                goto process_again;
                        case '0' ... '9':
                                goto process_again;
+                       case '.':
+                               goto process_again;
                        case 'p':
                                ls = 1;
                                /* fall through */
@@ -3455,23 +3581,30 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
                        case 'u':
                        case 'x':
                        case 'i':
-                               /* the pointers are always 4 bytes aligned */
-                               bptr = (void *)(((unsigned long)bptr + 3) &
-                                               ~3);
                                switch (ls) {
                                case 0:
-                                       ls = 4;
+                                       vsize = 4;
                                        break;
                                case 1:
-                                       ls = pevent->long_size;
+                                       vsize = pevent->long_size;
                                        break;
                                case 2:
-                                       ls = 8;
+                                       vsize = 8;
+                                       break;
                                default:
+                                       vsize = ls; /* ? */
                                        break;
                                }
-                               val = pevent_read_number(pevent, bptr, ls);
-                               bptr += ls;
+                       /* fall through */
+                       case '*':
+                               if (*ptr == '*')
+                                       vsize = 4;
+
+                               /* the pointers are always 4 bytes aligned */
+                               bptr = (void *)(((unsigned long)bptr + 3) &
+                                               ~3);
+                               val = pevent_read_number(pevent, bptr, vsize);
+                               bptr += vsize;
                                arg = alloc_arg();
                                arg->next = NULL;
                                arg->type = PRINT_ATOM;
@@ -3479,12 +3612,21 @@ static struct print_arg *make_bprint_args(char *fmt, void *data, int size, struc
                                sprintf(arg->atom.atom, "%lld", val);
                                *next = arg;
                                next = &arg->next;
+                               /*
+                                * The '*' case means that an arg is used as the length.
+                                * We need to continue to figure out for what.
+                                */
+                               if (*ptr == '*')
+                                       goto process_again;
+
                                break;
                        case 's':
                                arg = alloc_arg();
                                arg->next = NULL;
                                arg->type = PRINT_BSTRING;
                                arg->string.string = strdup(bptr);
+                               if (!arg->string.string)
+                                       break;
                                bptr += strlen(bptr) + 1;
                                *next = arg;
                                next = &arg->next;
@@ -3589,6 +3731,16 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,
        trace_seq_printf(s, fmt, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
 }
 
+static int is_printable_array(char *p, unsigned int len)
+{
+       unsigned int i;
+
+       for (i = 0; i < len && p[i]; i++)
+               if (!isprint(p[i]))
+                   return 0;
+       return 1;
+}
+
 static void print_event_fields(struct trace_seq *s, void *data, int size,
                               struct event_format *event)
 {
@@ -3608,7 +3760,8 @@ static void print_event_fields(struct trace_seq *s, void *data, int size,
                                len = offset >> 16;
                                offset &= 0xffff;
                        }
-                       if (field->flags & FIELD_IS_STRING) {
+                       if (field->flags & FIELD_IS_STRING &&
+                           is_printable_array(data + offset, len)) {
                                trace_seq_printf(s, "%s", (char *)data + offset);
                        } else {
                                trace_seq_puts(s, "ARRAY[");
@@ -3619,6 +3772,7 @@ static void print_event_fields(struct trace_seq *s, void *data, int size,
                                                         *((unsigned char *)data + offset + i));
                                }
                                trace_seq_putc(s, ']');
+                               field->flags &= ~FIELD_IS_STRING;
                        }
                } else {
                        val = pevent_read_number(event->pevent, data + field->offset,
@@ -3758,6 +3912,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
                                } else if (*(ptr+1) == 'M' || *(ptr+1) == 'm') {
                                        print_mac_arg(s, *(ptr+1), data, size, event, arg);
                                        ptr++;
+                                       arg = arg->next;
                                        break;
                                }
 
@@ -3794,14 +3949,15 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
                                                break;
                                        }
                                }
-                               if (pevent->long_size == 8 && ls) {
+                               if (pevent->long_size == 8 && ls &&
+                                   sizeof(long) != 8) {
                                        char *p;
 
                                        ls = 2;
                                        /* make %l into %ll */
                                        p = strchr(format, 'l');
                                        if (p)
-                                               memmove(p, p+1, strlen(p)+1);
+                                               memmove(p+1, p, strlen(p)+1);
                                        else if (strcmp(format, "%p") == 0)
                                                strcpy(format, "0x%llx");
                                }
@@ -3878,8 +4034,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event
  * pevent_data_lat_fmt - parse the data for the latency format
  * @pevent: a handle to the pevent
  * @s: the trace_seq to write to
- * @data: the raw data to read from
- * @size: currently unused.
+ * @record: the record to read from
  *
  * This parses out the Latency format (interrupts disabled,
  * need rescheduling, in hard/soft interrupt, preempt count
@@ -3889,10 +4044,13 @@ void pevent_data_lat_fmt(struct pevent *pevent,
                         struct trace_seq *s, struct pevent_record *record)
 {
        static int check_lock_depth = 1;
+       static int check_migrate_disable = 1;
        static int lock_depth_exists;
+       static int migrate_disable_exists;
        unsigned int lat_flags;
        unsigned int pc;
        int lock_depth;
+       int migrate_disable;
        int hardirq;
        int softirq;
        void *data = record->data;
@@ -3900,18 +4058,26 @@ void pevent_data_lat_fmt(struct pevent *pevent,
        lat_flags = parse_common_flags(pevent, data);
        pc = parse_common_pc(pevent, data);
        /* lock_depth may not always exist */
-       if (check_lock_depth) {
-               struct format_field *field;
-               struct event_format *event;
-
-               check_lock_depth = 0;
-               event = pevent->events[0];
-               field = pevent_find_common_field(event, "common_lock_depth");
-               if (field)
-                       lock_depth_exists = 1;
-       }
        if (lock_depth_exists)
                lock_depth = parse_common_lock_depth(pevent, data);
+       else if (check_lock_depth) {
+               lock_depth = parse_common_lock_depth(pevent, data);
+               if (lock_depth < 0)
+                       check_lock_depth = 0;
+               else
+                       lock_depth_exists = 1;
+       }
+
+       /* migrate_disable may not always exist */
+       if (migrate_disable_exists)
+               migrate_disable = parse_common_migrate_disable(pevent, data);
+       else if (check_migrate_disable) {
+               migrate_disable = parse_common_migrate_disable(pevent, data);
+               if (migrate_disable < 0)
+                       check_migrate_disable = 0;
+               else
+                       migrate_disable_exists = 1;
+       }
 
        hardirq = lat_flags & TRACE_FLAG_HARDIRQ;
        softirq = lat_flags & TRACE_FLAG_SOFTIRQ;
@@ -3930,6 +4096,13 @@ void pevent_data_lat_fmt(struct pevent *pevent,
        else
                trace_seq_putc(s, '.');
 
+       if (migrate_disable_exists) {
+               if (migrate_disable < 0)
+                       trace_seq_putc(s, '.');
+               else
+                       trace_seq_printf(s, "%d", migrate_disable);
+       }
+
        if (lock_depth_exists) {
                if (lock_depth < 0)
                        trace_seq_putc(s, '.');
@@ -3996,10 +4169,7 @@ const char *pevent_data_comm_from_pid(struct pevent *pevent, int pid)
  * pevent_data_comm_from_pid - parse the data into the print format
  * @s: the trace_seq to write to
  * @event: the handle to the event
- * @cpu: the cpu the event was recorded on
- * @data: the raw data
- * @size: the size of the raw data
- * @nsecs: the timestamp of the event
+ * @record: the record to read from
  *
  * This parses the raw @data using the given @event information and
  * writes the print format into the trace_seq.
@@ -4279,6 +4449,13 @@ static void print_args(struct print_arg *args)
                trace_seq_destroy(&s);
                printf(")");
                break;
+       case PRINT_HEX:
+               printf("__print_hex(");
+               print_args(args->hex.field);
+               printf(", ");
+               print_args(args->hex.size);
+               printf(")");
+               break;
        case PRINT_STRING:
        case PRINT_BSTRING:
                printf("__get_str(%s)", args->string.string);
@@ -4541,6 +4718,8 @@ int pevent_parse_event(struct pevent *pevent,
                die("failed to read event id");
 
        event->system = strdup(sys);
+       if (!event->system)
+               die("failed to allocate system");
 
        /* Add pevent to event so that it can be referenced */
        event->pevent = pevent;
@@ -4582,6 +4761,11 @@ int pevent_parse_event(struct pevent *pevent,
                        list = &arg->next;
                        arg->type = PRINT_FIELD;
                        arg->field.name = strdup(field->name);
+                       if (!arg->field.name) {
+                               do_warning("failed to allocate field name");
+                               event->flags |= EVENT_FL_FAILED;
+                               return -1;
+                       }
                        arg->field.field = field;
                }
                return 0;
@@ -4753,7 +4937,7 @@ int pevent_get_any_field_val(struct trace_seq *s, struct event_format *event,
  * @record: The record with the field name.
  * @err: print default error if failed.
  *
- * Returns: 0 on success, -1 field not fould, or 1 if buffer is full.
+ * Returns: 0 on success, -1 field not found, or 1 if buffer is full.
  */
 int pevent_print_num_field(struct trace_seq *s, const char *fmt,
                           struct event_format *event, const char *name,
@@ -4795,11 +4979,12 @@ static void free_func_handle(struct pevent_function_handler *func)
  * pevent_register_print_function - register a helper function
  * @pevent: the handle to the pevent
  * @func: the function to process the helper function
+ * @ret_type: the return type of the helper function
  * @name: the name of the helper function
  * @parameters: A list of enum pevent_func_arg_type
  *
  * Some events may have helper functions in the print format arguments.
- * This allows a plugin to dynmically create a way to process one
+ * This allows a plugin to dynamically create a way to process one
  * of these functions.
  *
  * The @parameters is a variable list of pevent_func_arg_type enums that
@@ -4870,12 +5055,13 @@ int pevent_register_print_function(struct pevent *pevent,
 }
 
 /**
- * pevent_register_event_handle - register a way to parse an event
+ * pevent_register_event_handler - register a way to parse an event
  * @pevent: the handle to the pevent
  * @id: the id of the event to register
  * @sys_name: the system name the event belongs to
  * @event_name: the name of the event
  * @func: the function to call to parse the event information
+ * @context: the data to be passed to @func
  *
  * This function allows a developer to override the parsing of
  * a given event. If for some reason the default print format
@@ -4925,6 +5111,11 @@ int pevent_register_event_handler(struct pevent *pevent,
        if (sys_name)
                handle->sys_name = strdup(sys_name);
 
+       if ((event_name && !handle->event_name) ||
+           (sys_name && !handle->sys_name)) {
+               die("Failed to allocate event/sys name");
+       }
+
        handle->func = func;
        handle->next = pevent->handlers;
        pevent->handlers = handle;
index ac997bc7b59252e5fc0fb2cc9b1e9ef12bd15419..5772ad8cb38646fbd5a6375b528ad710ff217b3f 100644 (file)
@@ -226,6 +226,11 @@ struct print_arg_symbol {
        struct print_flag_sym   *symbols;
 };
 
+struct print_arg_hex {
+       struct print_arg        *field;
+       struct print_arg        *size;
+};
+
 struct print_arg_dynarray {
        struct format_field     *field;
        struct print_arg        *index;
@@ -253,6 +258,7 @@ enum print_arg_type {
        PRINT_FIELD,
        PRINT_FLAGS,
        PRINT_SYMBOL,
+       PRINT_HEX,
        PRINT_TYPE,
        PRINT_STRING,
        PRINT_BSTRING,
@@ -270,6 +276,7 @@ struct print_arg {
                struct print_arg_typecast       typecast;
                struct print_arg_flags          flags;
                struct print_arg_symbol         symbol;
+               struct print_arg_hex            hex;
                struct print_arg_func           func;
                struct print_arg_string         string;
                struct print_arg_op             op;
index dfcfe2c131de6e3d8ea6c26cbf452c2834fd90d7..ad17855528f9adaa82cb37b0e6a8fe7ede2ed755 100644 (file)
@@ -96,7 +96,7 @@ static enum event_type read_token(char **tok)
            (strcmp(token, "=") == 0 || strcmp(token, "!") == 0) &&
            pevent_peek_char() == '~') {
                /* append it */
-               *tok = malloc(3);
+               *tok = malloc_or_die(3);
                sprintf(*tok, "%c%c", *token, '~');
                free_token(token);
                /* Now remove the '~' from the buffer */
@@ -148,17 +148,11 @@ add_filter_type(struct event_filter *filter, int id)
        if (filter_type)
                return filter_type;
 
-       if (!filter->filters)
-               filter->event_filters =
-                       malloc_or_die(sizeof(*filter->event_filters));
-       else {
-               filter->event_filters =
-                       realloc(filter->event_filters,
-                               sizeof(*filter->event_filters) *
-                               (filter->filters + 1));
-               if (!filter->event_filters)
-                       die("Could not allocate filter");
-       }
+       filter->event_filters = realloc(filter->event_filters,
+                                       sizeof(*filter->event_filters) *
+                                       (filter->filters + 1));
+       if (!filter->event_filters)
+               die("Could not allocate filter");
 
        for (i = 0; i < filter->filters; i++) {
                if (filter->event_filters[i].event_id > id)
@@ -1480,7 +1474,7 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
 {
        struct filter_type *filter_type;
        int count = 0;
-       int *ids;
+       int *ids = NULL;
        int i;
 
        if (!filter->filters)
@@ -1504,10 +1498,8 @@ void pevent_filter_clear_trivial(struct event_filter *filter,
                default:
                        break;
                }
-               if (count)
-                       ids = realloc(ids, sizeof(*ids) * (count + 1));
-               else
-                       ids = malloc(sizeof(*ids));
+
+               ids = realloc(ids, sizeof(*ids) * (count + 1));
                if (!ids)
                        die("Can't allocate ids");
                ids[count++] = filter_type->event_id;
@@ -1710,18 +1702,43 @@ static int test_num(struct event_format *event,
 
 static const char *get_field_str(struct filter_arg *arg, struct pevent_record *record)
 {
-       const char *val = record->data + arg->str.field->offset;
+       struct event_format *event;
+       struct pevent *pevent;
+       unsigned long long addr;
+       const char *val = NULL;
+       char hex[64];
 
-       /*
-        * We need to copy the data since we can't be sure the field
-        * is null terminated.
-        */
-       if (*(val + arg->str.field->size - 1)) {
-               /* copy it */
-               memcpy(arg->str.buffer, val, arg->str.field->size);
-               /* the buffer is already NULL terminated */
-               val = arg->str.buffer;
+       /* If the field is not a string convert it */
+       if (arg->str.field->flags & FIELD_IS_STRING) {
+               val = record->data + arg->str.field->offset;
+
+               /*
+                * We need to copy the data since we can't be sure the field
+                * is null terminated.
+                */
+               if (*(val + arg->str.field->size - 1)) {
+                       /* copy it */
+                       memcpy(arg->str.buffer, val, arg->str.field->size);
+                       /* the buffer is already NULL terminated */
+                       val = arg->str.buffer;
+               }
+
+       } else {
+               event = arg->str.field->event;
+               pevent = event->pevent;
+               addr = get_value(event, arg->str.field, record);
+
+               if (arg->str.field->flags & (FIELD_IS_POINTER | FIELD_IS_LONG))
+                       /* convert to a kernel symbol */
+                       val = pevent_find_function(pevent, addr);
+
+               if (val == NULL) {
+                       /* just use the hex of the string name */
+                       snprintf(hex, 64, "0x%llx", addr);
+                       val = hex;
+               }
        }
+
        return val;
 }
 
@@ -2001,11 +2018,13 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
        char *lstr;
        char *rstr;
        char *op;
-       char *str;
+       char *str = NULL;
        int len;
 
        lstr = arg_to_str(filter, arg->exp.left);
        rstr = arg_to_str(filter, arg->exp.right);
+       if (!lstr || !rstr)
+               goto out;
 
        switch (arg->exp.type) {
        case FILTER_EXP_ADD:
@@ -2045,6 +2064,7 @@ static char *exp_to_str(struct event_filter *filter, struct filter_arg *arg)
        len = strlen(op) + strlen(lstr) + strlen(rstr) + 4;
        str = malloc_or_die(len);
        snprintf(str, len, "%s %s %s", lstr, op, rstr);
+out:
        free(lstr);
        free(rstr);
 
@@ -2061,6 +2081,8 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
 
        lstr = arg_to_str(filter, arg->num.left);
        rstr = arg_to_str(filter, arg->num.right);
+       if (!lstr || !rstr)
+               goto out;
 
        switch (arg->num.type) {
        case FILTER_CMP_EQ:
@@ -2097,6 +2119,7 @@ static char *num_to_str(struct event_filter *filter, struct filter_arg *arg)
                break;
        }
 
+out:
        free(lstr);
        free(rstr);
        return str;
@@ -2247,7 +2270,12 @@ int pevent_filter_compare(struct event_filter *filter1, struct event_filter *fil
                /* The best way to compare complex filters is with strings */
                str1 = arg_to_str(filter1, filter_type1->filter);
                str2 = arg_to_str(filter2, filter_type2->filter);
-               result = strcmp(str1, str2) != 0;
+               if (str1 && str2)
+                       result = strcmp(str1, str2) != 0;
+               else
+                       /* bail out if allocation fails */
+                       result = 1;
+
                free(str1);
                free(str2);
                if (result)
index a3dbadb26ef596d29f6e2e9c3a5326bff4dfdad7..7065cd6fbdfc576a28d588f778354d15771a2ad1 100644 (file)
@@ -12,7 +12,7 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-This 'perf bench' command is general framework for benchmark suites.
+This 'perf bench' command is general framework for benchmark suites.
 
 COMMON OPTIONS
 --------------
@@ -45,14 +45,20 @@ SUBSYSTEM
 'sched'::
        Scheduler and IPC mechanisms.
 
+'mem'::
+       Memory access performance.
+
+'all'::
+       All benchmark subsystems.
+
 SUITES FOR 'sched'
 ~~~~~~~~~~~~~~~~~~
 *messaging*::
 Suite for evaluating performance of scheduler and IPC mechanisms.
 Based on hackbench by Rusty Russell.
 
-Options of *pipe*
-^^^^^^^^^^^^^^^^^
+Options of *messaging*
+^^^^^^^^^^^^^^^^^^^^^^
 -p::
 --pipe::
 Use pipe() instead of socketpair()
@@ -115,6 +121,72 @@ Example of *pipe*
                 59004 ops/sec
 ---------------------
 
+SUITES FOR 'mem'
+~~~~~~~~~~~~~~~~
+*memcpy*::
+Suite for evaluating performance of simple memory copy in various ways.
+
+Options of *memcpy*
+^^^^^^^^^^^^^^^^^^^
+-l::
+--length::
+Specify length of memory to copy (default: 1MB).
+Available units are B, KB, MB, GB and TB (case insensitive).
+
+-r::
+--routine::
+Specify routine to copy (default: default).
+Available routines are depend on the architecture.
+On x86-64, x86-64-unrolled, x86-64-movsq and x86-64-movsb are supported.
+
+-i::
+--iterations::
+Repeat memcpy invocation this number of times.
+
+-c::
+--cycle::
+Use perf's cpu-cycles event instead of gettimeofday syscall.
+
+-o::
+--only-prefault::
+Show only the result with page faults before memcpy.
+
+-n::
+--no-prefault::
+Show only the result without page faults before memcpy.
+
+*memset*::
+Suite for evaluating performance of simple memory set in various ways.
+
+Options of *memset*
+^^^^^^^^^^^^^^^^^^^
+-l::
+--length::
+Specify length of memory to set (default: 1MB).
+Available units are B, KB, MB, GB and TB (case insensitive).
+
+-r::
+--routine::
+Specify routine to set (default: default).
+Available routines are depend on the architecture.
+On x86-64, x86-64-unrolled, x86-64-stosq and x86-64-stosb are supported.
+
+-i::
+--iterations::
+Repeat memset invocation this number of times.
+
+-c::
+--cycle::
+Use perf's cpu-cycles event instead of gettimeofday syscall.
+
+-o::
+--only-prefault::
+Show only the result with page faults before memset.
+
+-n::
+--no-prefault::
+Show only the result without page faults before memset.
+
 SEE ALSO
 --------
 linkperf:perf[1]
index 2d89f02719b5f6ce52e502414c031a2d7610ca9a..495210a612c4d218170f696dcf5d93323f22a571 100644 (file)
@@ -57,7 +57,7 @@ OPTIONS
 
 -s::
 --sort=::
-       Sort by key(s): pid, comm, dso, symbol, parent.
+       Sort by key(s): pid, comm, dso, symbol, parent, srcline.
 
 -p::
 --parent=<regex>::
index 4a5680cb242ebe656c266c19bcf81bc64bbc623c..5b80d84d6b4a3e7e430499d0381c11a8856f316d 100644 (file)
@@ -112,7 +112,7 @@ Default is to monitor all CPUS.
 
 -s::
 --sort::
-       Sort by key(s): pid, comm, dso, symbol, parent
+       Sort by key(s): pid, comm, dso, symbol, parent, srcline.
 
 -n::
 --show-nr-samples::
index 0eee64cfe9a0f48ced0ee2397068979763355cd4..75d74e5db8d552372aa0b7c19861c76458784f5e 100644 (file)
@@ -155,7 +155,7 @@ endif
 
 ### --- END CONFIGURATION SECTION ---
 
-BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)/util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
+BASIC_CFLAGS = -Iutil/include -Iarch/$(ARCH)/include -I$(OUTPUT)util -I$(TRACE_EVENT_DIR) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
 BASIC_LDFLAGS =
 
 # Guard against environment variables
@@ -503,6 +503,7 @@ else
                LIB_OBJS += $(OUTPUT)ui/progress.o
                LIB_OBJS += $(OUTPUT)ui/util.o
                LIB_OBJS += $(OUTPUT)ui/tui/setup.o
+               LIB_OBJS += $(OUTPUT)ui/tui/util.o
                LIB_H += ui/browser.h
                LIB_H += ui/browsers/map.h
                LIB_H += ui/helpline.h
@@ -522,13 +523,18 @@ else
                msg := $(warning GTK2 not found, disables GTK2 support. Please install gtk2-devel or libgtk2.0-dev);
                BASIC_CFLAGS += -DNO_GTK2_SUPPORT
        else
+               ifeq ($(call try-cc,$(SOURCE_GTK2_INFOBAR),$(FLAGS_GTK2)),y)
+                       BASIC_CFLAGS += -DHAVE_GTK_INFO_BAR
+               endif
                BASIC_CFLAGS += $(shell pkg-config --cflags gtk+-2.0)
                EXTLIBS += $(shell pkg-config --libs gtk+-2.0)
                LIB_OBJS += $(OUTPUT)ui/gtk/browser.o
                LIB_OBJS += $(OUTPUT)ui/gtk/setup.o
+               LIB_OBJS += $(OUTPUT)ui/gtk/util.o
                # Make sure that it'd be included only once.
                ifneq ($(findstring -DNO_NEWT_SUPPORT,$(BASIC_CFLAGS)),)
                        LIB_OBJS += $(OUTPUT)ui/setup.o
+                       LIB_OBJS += $(OUTPUT)ui/util.o
                endif
        endif
 endif
index 71557225bf92aeb708100acfa3f5027948de3831..02dad5d3359b0f23abe24169a126b2dc3bacfd99 100644 (file)
 static const char      *length_str     = "1MB";
 static const char      *routine        = "default";
 static int             iterations      = 1;
-static bool            use_clock;
-static int             clock_fd;
+static bool            use_cycle;
+static int             cycle_fd;
 static bool            only_prefault;
 static bool            no_prefault;
 
 static const struct option options[] = {
        OPT_STRING('l', "length", &length_str, "1MB",
                    "Specify length of memory to copy. "
-                   "available unit: B, MB, GB (upper and lower)"),
+                   "Available units: B, KB, MB, GB and TB (upper and lower)"),
        OPT_STRING('r', "routine", &routine, "default",
                    "Specify routine to copy"),
        OPT_INTEGER('i', "iterations", &iterations,
                    "repeat memcpy() invocation this number of times"),
-       OPT_BOOLEAN('c', "clock", &use_clock,
-                   "Use CPU clock for measuring"),
+       OPT_BOOLEAN('c', "cycle", &use_cycle,
+                   "Use cycles event instead of gettimeofday() for measuring"),
        OPT_BOOLEAN('o', "only-prefault", &only_prefault,
                    "Show only the result with page faults before memcpy()"),
        OPT_BOOLEAN('n', "no-prefault", &no_prefault,
@@ -76,27 +76,27 @@ static const char * const bench_mem_memcpy_usage[] = {
        NULL
 };
 
-static struct perf_event_attr clock_attr = {
+static struct perf_event_attr cycle_attr = {
        .type           = PERF_TYPE_HARDWARE,
        .config         = PERF_COUNT_HW_CPU_CYCLES
 };
 
-static void init_clock(void)
+static void init_cycle(void)
 {
-       clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0);
+       cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
 
-       if (clock_fd < 0 && errno == ENOSYS)
+       if (cycle_fd < 0 && errno == ENOSYS)
                die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
        else
-               BUG_ON(clock_fd < 0);
+               BUG_ON(cycle_fd < 0);
 }
 
-static u64 get_clock(void)
+static u64 get_cycle(void)
 {
        int ret;
        u64 clk;
 
-       ret = read(clock_fd, &clk, sizeof(u64));
+       ret = read(cycle_fd, &clk, sizeof(u64));
        BUG_ON(ret != sizeof(u64));
 
        return clk;
@@ -119,9 +119,9 @@ static void alloc_mem(void **dst, void **src, size_t length)
                die("memory allocation failed - maybe length is too large?\n");
 }
 
-static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
+static u64 do_memcpy_cycle(memcpy_t fn, size_t len, bool prefault)
 {
-       u64 clock_start = 0ULL, clock_end = 0ULL;
+       u64 cycle_start = 0ULL, cycle_end = 0ULL;
        void *src = NULL, *dst = NULL;
        int i;
 
@@ -130,14 +130,14 @@ static u64 do_memcpy_clock(memcpy_t fn, size_t len, bool prefault)
        if (prefault)
                fn(dst, src, len);
 
-       clock_start = get_clock();
+       cycle_start = get_cycle();
        for (i = 0; i < iterations; ++i)
                fn(dst, src, len);
-       clock_end = get_clock();
+       cycle_end = get_cycle();
 
        free(src);
        free(dst);
-       return clock_end - clock_start;
+       return cycle_end - cycle_start;
 }
 
 static double do_memcpy_gettimeofday(memcpy_t fn, size_t len, bool prefault)
@@ -182,17 +182,17 @@ int bench_mem_memcpy(int argc, const char **argv,
        int i;
        size_t len;
        double result_bps[2];
-       u64 result_clock[2];
+       u64 result_cycle[2];
 
        argc = parse_options(argc, argv, options,
                             bench_mem_memcpy_usage, 0);
 
-       if (use_clock)
-               init_clock();
+       if (use_cycle)
+               init_cycle();
 
        len = (size_t)perf_atoll((char *)length_str);
 
-       result_clock[0] = result_clock[1] = 0ULL;
+       result_cycle[0] = result_cycle[1] = 0ULL;
        result_bps[0] = result_bps[1] = 0.0;
 
        if ((s64)len <= 0) {
@@ -223,11 +223,11 @@ int bench_mem_memcpy(int argc, const char **argv,
 
        if (!only_prefault && !no_prefault) {
                /* show both of results */
-               if (use_clock) {
-                       result_clock[0] =
-                               do_memcpy_clock(routines[i].fn, len, false);
-                       result_clock[1] =
-                               do_memcpy_clock(routines[i].fn, len, true);
+               if (use_cycle) {
+                       result_cycle[0] =
+                               do_memcpy_cycle(routines[i].fn, len, false);
+                       result_cycle[1] =
+                               do_memcpy_cycle(routines[i].fn, len, true);
                } else {
                        result_bps[0] =
                                do_memcpy_gettimeofday(routines[i].fn,
@@ -237,9 +237,9 @@ int bench_mem_memcpy(int argc, const char **argv,
                                                len, true);
                }
        } else {
-               if (use_clock) {
-                       result_clock[pf] =
-                               do_memcpy_clock(routines[i].fn,
+               if (use_cycle) {
+                       result_cycle[pf] =
+                               do_memcpy_cycle(routines[i].fn,
                                                len, only_prefault);
                } else {
                        result_bps[pf] =
@@ -251,12 +251,12 @@ int bench_mem_memcpy(int argc, const char **argv,
        switch (bench_format) {
        case BENCH_FORMAT_DEFAULT:
                if (!only_prefault && !no_prefault) {
-                       if (use_clock) {
-                               printf(" %14lf Clock/Byte\n",
-                                       (double)result_clock[0]
+                       if (use_cycle) {
+                               printf(" %14lf Cycle/Byte\n",
+                                       (double)result_cycle[0]
                                        / (double)len);
-                               printf(" %14lf Clock/Byte (with prefault)\n",
-                                       (double)result_clock[1]
+                               printf(" %14lf Cycle/Byte (with prefault)\n",
+                                       (double)result_cycle[1]
                                        / (double)len);
                        } else {
                                print_bps(result_bps[0]);
@@ -265,9 +265,9 @@ int bench_mem_memcpy(int argc, const char **argv,
                                printf(" (with prefault)\n");
                        }
                } else {
-                       if (use_clock) {
-                               printf(" %14lf Clock/Byte",
-                                       (double)result_clock[pf]
+                       if (use_cycle) {
+                               printf(" %14lf Cycle/Byte",
+                                       (double)result_cycle[pf]
                                        / (double)len);
                        } else
                                print_bps(result_bps[pf]);
@@ -277,17 +277,17 @@ int bench_mem_memcpy(int argc, const char **argv,
                break;
        case BENCH_FORMAT_SIMPLE:
                if (!only_prefault && !no_prefault) {
-                       if (use_clock) {
+                       if (use_cycle) {
                                printf("%lf %lf\n",
-                                       (double)result_clock[0] / (double)len,
-                                       (double)result_clock[1] / (double)len);
+                                       (double)result_cycle[0] / (double)len,
+                                       (double)result_cycle[1] / (double)len);
                        } else {
                                printf("%lf %lf\n",
                                        result_bps[0], result_bps[1]);
                        }
                } else {
-                       if (use_clock) {
-                               printf("%lf\n", (double)result_clock[pf]
+                       if (use_cycle) {
+                               printf("%lf\n", (double)result_cycle[pf]
                                        / (double)len);
                        } else
                                printf("%lf\n", result_bps[pf]);
index e9079185bd72d32e48dfee280ead72c96c7d9ef3..350cc9557265197a03e35abb3fd49dc39dde64ac 100644 (file)
 static const char      *length_str     = "1MB";
 static const char      *routine        = "default";
 static int             iterations      = 1;
-static bool            use_clock;
-static int             clock_fd;
+static bool            use_cycle;
+static int             cycle_fd;
 static bool            only_prefault;
 static bool            no_prefault;
 
 static const struct option options[] = {
        OPT_STRING('l', "length", &length_str, "1MB",
-                   "Specify length of memory to copy. "
-                   "available unit: B, MB, GB (upper and lower)"),
+                   "Specify length of memory to set. "
+                   "Available units: B, KB, MB, GB and TB (upper and lower)"),
        OPT_STRING('r', "routine", &routine, "default",
-                   "Specify routine to copy"),
+                   "Specify routine to set"),
        OPT_INTEGER('i', "iterations", &iterations,
                    "repeat memset() invocation this number of times"),
-       OPT_BOOLEAN('c', "clock", &use_clock,
-                   "Use CPU clock for measuring"),
+       OPT_BOOLEAN('c', "cycle", &use_cycle,
+                   "Use cycles event instead of gettimeofday() for measuring"),
        OPT_BOOLEAN('o', "only-prefault", &only_prefault,
                    "Show only the result with page faults before memset()"),
        OPT_BOOLEAN('n', "no-prefault", &no_prefault,
@@ -76,27 +76,27 @@ static const char * const bench_mem_memset_usage[] = {
        NULL
 };
 
-static struct perf_event_attr clock_attr = {
+static struct perf_event_attr cycle_attr = {
        .type           = PERF_TYPE_HARDWARE,
        .config         = PERF_COUNT_HW_CPU_CYCLES
 };
 
-static void init_clock(void)
+static void init_cycle(void)
 {
-       clock_fd = sys_perf_event_open(&clock_attr, getpid(), -1, -1, 0);
+       cycle_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, 0);
 
-       if (clock_fd < 0 && errno == ENOSYS)
+       if (cycle_fd < 0 && errno == ENOSYS)
                die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
        else
-               BUG_ON(clock_fd < 0);
+               BUG_ON(cycle_fd < 0);
 }
 
-static u64 get_clock(void)
+static u64 get_cycle(void)
 {
        int ret;
        u64 clk;
 
-       ret = read(clock_fd, &clk, sizeof(u64));
+       ret = read(cycle_fd, &clk, sizeof(u64));
        BUG_ON(ret != sizeof(u64));
 
        return clk;
@@ -115,9 +115,9 @@ static void alloc_mem(void **dst, size_t length)
                die("memory allocation failed - maybe length is too large?\n");
 }
 
-static u64 do_memset_clock(memset_t fn, size_t len, bool prefault)
+static u64 do_memset_cycle(memset_t fn, size_t len, bool prefault)
 {
-       u64 clock_start = 0ULL, clock_end = 0ULL;
+       u64 cycle_start = 0ULL, cycle_end = 0ULL;
        void *dst = NULL;
        int i;
 
@@ -126,13 +126,13 @@ static u64 do_memset_clock(memset_t fn, size_t len, bool prefault)
        if (prefault)
                fn(dst, -1, len);
 
-       clock_start = get_clock();
+       cycle_start = get_cycle();
        for (i = 0; i < iterations; ++i)
                fn(dst, i, len);
-       clock_end = get_clock();
+       cycle_end = get_cycle();
 
        free(dst);
-       return clock_end - clock_start;
+       return cycle_end - cycle_start;
 }
 
 static double do_memset_gettimeofday(memset_t fn, size_t len, bool prefault)
@@ -176,17 +176,17 @@ int bench_mem_memset(int argc, const char **argv,
        int i;
        size_t len;
        double result_bps[2];
-       u64 result_clock[2];
+       u64 result_cycle[2];
 
        argc = parse_options(argc, argv, options,
                             bench_mem_memset_usage, 0);
 
-       if (use_clock)
-               init_clock();
+       if (use_cycle)
+               init_cycle();
 
        len = (size_t)perf_atoll((char *)length_str);
 
-       result_clock[0] = result_clock[1] = 0ULL;
+       result_cycle[0] = result_cycle[1] = 0ULL;
        result_bps[0] = result_bps[1] = 0.0;
 
        if ((s64)len <= 0) {
@@ -217,11 +217,11 @@ int bench_mem_memset(int argc, const char **argv,
 
        if (!only_prefault && !no_prefault) {
                /* show both of results */
-               if (use_clock) {
-                       result_clock[0] =
-                               do_memset_clock(routines[i].fn, len, false);
-                       result_clock[1] =
-                               do_memset_clock(routines[i].fn, len, true);
+               if (use_cycle) {
+                       result_cycle[0] =
+                               do_memset_cycle(routines[i].fn, len, false);
+                       result_cycle[1] =
+                               do_memset_cycle(routines[i].fn, len, true);
                } else {
                        result_bps[0] =
                                do_memset_gettimeofday(routines[i].fn,
@@ -231,9 +231,9 @@ int bench_mem_memset(int argc, const char **argv,
                                                len, true);
                }
        } else {
-               if (use_clock) {
-                       result_clock[pf] =
-                               do_memset_clock(routines[i].fn,
+               if (use_cycle) {
+                       result_cycle[pf] =
+                               do_memset_cycle(routines[i].fn,
                                                len, only_prefault);
                } else {
                        result_bps[pf] =
@@ -245,12 +245,12 @@ int bench_mem_memset(int argc, const char **argv,
        switch (bench_format) {
        case BENCH_FORMAT_DEFAULT:
                if (!only_prefault && !no_prefault) {
-                       if (use_clock) {
-                               printf(" %14lf Clock/Byte\n",
-                                       (double)result_clock[0]
+                       if (use_cycle) {
+                               printf(" %14lf Cycle/Byte\n",
+                                       (double)result_cycle[0]
                                        / (double)len);
-                               printf(" %14lf Clock/Byte (with prefault)\n ",
-                                       (double)result_clock[1]
+                               printf(" %14lf Cycle/Byte (with prefault)\n ",
+                                       (double)result_cycle[1]
                                        / (double)len);
                        } else {
                                print_bps(result_bps[0]);
@@ -259,9 +259,9 @@ int bench_mem_memset(int argc, const char **argv,
                                printf(" (with prefault)\n");
                        }
                } else {
-                       if (use_clock) {
-                               printf(" %14lf Clock/Byte",
-                                       (double)result_clock[pf]
+                       if (use_cycle) {
+                               printf(" %14lf Cycle/Byte",
+                                       (double)result_cycle[pf]
                                        / (double)len);
                        } else
                                print_bps(result_bps[pf]);
@@ -271,17 +271,17 @@ int bench_mem_memset(int argc, const char **argv,
                break;
        case BENCH_FORMAT_SIMPLE:
                if (!only_prefault && !no_prefault) {
-                       if (use_clock) {
+                       if (use_cycle) {
                                printf("%lf %lf\n",
-                                       (double)result_clock[0] / (double)len,
-                                       (double)result_clock[1] / (double)len);
+                                       (double)result_cycle[0] / (double)len,
+                                       (double)result_cycle[1] / (double)len);
                        } else {
                                printf("%lf %lf\n",
                                        result_bps[0], result_bps[1]);
                        }
                } else {
-                       if (use_clock) {
-                               printf("%lf\n", (double)result_clock[pf]
+                       if (use_cycle) {
+                               printf("%lf\n", (double)result_cycle[pf]
                                        / (double)len);
                        } else
                                printf("%lf\n", result_bps[pf]);
index b0e74ab2d7a2990d8d1fce67b95a555d53a70ee3..1f3100216448da9d0d794847a0c0f0b315bd59fb 100644 (file)
@@ -33,7 +33,7 @@ struct bench_suite {
 };
                                                \
 /* sentinel: easy for help */
-#define suite_all { "all", "test all suite (pseudo suite)", NULL }
+#define suite_all { "all", "Test all benchmark suites", NULL }
 
 static struct bench_suite sched_suites[] = {
        { "messaging",
@@ -75,7 +75,7 @@ static struct bench_subsys subsystems[] = {
          "memory access performance",
          mem_suites },
        { "all",                /* sentinel: easy for help */
-         "test all subsystem (pseudo subsystem)",
+         "all benchmark subsystem",
          NULL },
        { NULL,
          NULL,
index acd78dc283411692f9e7e48b78085d9b5da63471..0dd5a058f766e2e2b2ad7196af78bf3d7a81d563 100644 (file)
@@ -60,7 +60,7 @@ static int __cmd_evlist(const char *input_name, struct perf_attr_details *detail
        list_for_each_entry(pos, &session->evlist->entries, node) {
                bool first = true;
 
-               printf("%s", event_name(pos));
+               printf("%s", perf_evsel__name(pos));
 
                if (details->verbose || details->freq) {
                        comma_printf(&first, " sample_freq=%" PRIu64,
index 547af48deb4f99081221f566f48dc023ab6b0e76..ce35015f2dc6423901f7d42b223754b4b67117e3 100644 (file)
@@ -57,6 +57,11 @@ static unsigned long nr_allocs, nr_cross_allocs;
 
 #define PATH_SYS_NODE  "/sys/devices/system/node"
 
+struct perf_kmem {
+       struct perf_tool    tool;
+       struct perf_session *session;
+};
+
 static void init_cpunode_map(void)
 {
        FILE *fp;
@@ -278,14 +283,16 @@ static void process_free_event(void *data,
        s_alloc->alloc_cpu = -1;
 }
 
-static void process_raw_event(union perf_event *raw_event __used, void *data,
+static void process_raw_event(struct perf_tool *tool,
+                             union perf_event *raw_event __used, void *data,
                              int cpu, u64 timestamp, struct thread *thread)
 {
+       struct perf_kmem *kmem = container_of(tool, struct perf_kmem, tool);
        struct event_format *event;
        int type;
 
-       type = trace_parse_common_type(data);
-       event = trace_find_event(type);
+       type = trace_parse_common_type(kmem->session->pevent, data);
+       event = pevent_find_event(kmem->session->pevent, type);
 
        if (!strcmp(event->name, "kmalloc") ||
            !strcmp(event->name, "kmem_cache_alloc")) {
@@ -306,7 +313,7 @@ static void process_raw_event(union perf_event *raw_event __used, void *data,
        }
 }
 
-static int process_sample_event(struct perf_tool *tool __used,
+static int process_sample_event(struct perf_tool *tool,
                                union perf_event *event,
                                struct perf_sample *sample,
                                struct perf_evsel *evsel __used,
@@ -322,16 +329,18 @@ static int process_sample_event(struct perf_tool *tool __used,
 
        dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
 
-       process_raw_event(event, sample->raw_data, sample->cpu,
+       process_raw_event(tool, event, sample->raw_data, sample->cpu,
                          sample->time, thread);
 
        return 0;
 }
 
-static struct perf_tool perf_kmem = {
-       .sample                 = process_sample_event,
-       .comm                   = perf_event__process_comm,
-       .ordered_samples        = true,
+static struct perf_kmem perf_kmem = {
+       .tool = {
+               .sample                 = process_sample_event,
+               .comm                   = perf_event__process_comm,
+               .ordered_samples        = true,
+       },
 };
 
 static double fragmentation(unsigned long n_req, unsigned long n_alloc)
@@ -486,11 +495,15 @@ static void sort_result(void)
 static int __cmd_kmem(void)
 {
        int err = -EINVAL;
-       struct perf_session *session = perf_session__new(input_name, O_RDONLY,
-                                                        0, false, &perf_kmem);
+       struct perf_session *session;
+
+       session = perf_session__new(input_name, O_RDONLY, 0, false,
+                                   &perf_kmem.tool);
        if (session == NULL)
                return -ENOMEM;
 
+       perf_kmem.session = session;
+
        if (perf_session__create_kernel_maps(session) < 0)
                goto out_delete;
 
@@ -498,7 +511,7 @@ static int __cmd_kmem(void)
                goto out_delete;
 
        setup_pager();
-       err = perf_session__process_events(session, &perf_kmem);
+       err = perf_session__process_events(session, &perf_kmem.tool);
        if (err != 0)
                goto out_delete;
        sort_result();
index fd53319de20d68f906536787c48523769e565aba..b3c4285488688ba19b6073bd6c743a84e4e0e8b1 100644 (file)
@@ -724,8 +724,8 @@ process_raw_event(void *data, int cpu, u64 timestamp, struct thread *thread)
        struct event_format *event;
        int type;
 
-       type = trace_parse_common_type(data);
-       event = trace_find_event(type);
+       type = trace_parse_common_type(session->pevent, data);
+       event = pevent_find_event(session->pevent, type);
 
        if (!strcmp(event->name, "lock_acquire"))
                process_lock_acquire_event(data, event, cpu, timestamp, thread);
index f95840d04e4c7a224821e395600df2bbdc7e4323..f5a6452931e6dabaa4f3b4593ab91f30aa7d586b 100644 (file)
@@ -265,7 +265,7 @@ try_again:
 
                        if (err == ENOENT) {
                                ui__error("The %s event is not supported.\n",
-                                           event_name(pos));
+                                         perf_evsel__name(pos));
                                exit(EXIT_FAILURE);
                        }
 
@@ -916,7 +916,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __used)
                usage_with_options(record_usage, record_options);
 
        list_for_each_entry(pos, &evsel_list->entries, node) {
-               if (perf_header__push_event(pos->attr.config, event_name(pos)))
+               if (perf_header__push_event(pos->attr.config, perf_evsel__name(pos)))
                        goto out_free_fd;
        }
 
index 25249f76329daf851f925240f8c295c0c3fc5bdc..69b1c1185159174f070425d15c17afc8d5325f50 100644 (file)
@@ -69,7 +69,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool,
 
        if ((sort__has_parent || symbol_conf.use_callchain)
            && sample->callchain) {
-               err = machine__resolve_callchain(machine, evsel, al->thread,
+               err = machine__resolve_callchain(machine, al->thread,
                                                 sample->callchain, &parent);
                if (err)
                        return err;
@@ -140,7 +140,7 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel,
        struct hist_entry *he;
 
        if ((sort__has_parent || symbol_conf.use_callchain) && sample->callchain) {
-               err = machine__resolve_callchain(machine, evsel, al->thread,
+               err = machine__resolve_callchain(machine, al->thread,
                                                 sample->callchain, &parent);
                if (err)
                        return err;
@@ -230,7 +230,7 @@ static int process_read_event(struct perf_tool *tool,
        struct perf_report *rep = container_of(tool, struct perf_report, tool);
 
        if (rep->show_threads) {
-               const char *name = evsel ? event_name(evsel) : "unknown";
+               const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
                perf_read_values_add_value(&rep->show_threads_values,
                                           event->read.pid, event->read.tid,
                                           event->read.id,
@@ -239,17 +239,18 @@ static int process_read_event(struct perf_tool *tool,
        }
 
        dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
-                   evsel ? event_name(evsel) : "FAIL",
+                   evsel ? perf_evsel__name(evsel) : "FAIL",
                    event->read.value);
 
        return 0;
 }
 
+/* For pipe mode, sample_type is not currently set */
 static int perf_report__setup_sample_type(struct perf_report *rep)
 {
        struct perf_session *self = rep->session;
 
-       if (!(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
+       if (!self->fd_pipe && !(self->sample_type & PERF_SAMPLE_CALLCHAIN)) {
                if (sort__has_parent) {
                        ui__error("Selected --sort parent, but no "
                                    "callchain data. Did you call "
@@ -272,7 +273,8 @@ static int perf_report__setup_sample_type(struct perf_report *rep)
        }
 
        if (sort__branch_mode == 1) {
-               if (!(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) {
+               if (!self->fd_pipe &&
+                   !(self->sample_type & PERF_SAMPLE_BRANCH_STACK)) {
                        ui__error("Selected -b but no branch data. "
                                  "Did you call perf record without -b?\n");
                        return -1;
@@ -314,7 +316,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
 
        list_for_each_entry(pos, &evlist->entries, node) {
                struct hists *hists = &pos->hists;
-               const char *evname = event_name(pos);
+               const char *evname = perf_evsel__name(pos);
 
                hists__fprintf_nr_sample_events(hists, evname, stdout);
                hists__fprintf(hists, NULL, false, true, 0, 0, stdout);
index b125e07eb39937e314b314943ad4061ba467a98c..7a9ad2b1ee7601de26ed2d97ff91fae39a46f185 100644 (file)
@@ -43,6 +43,11 @@ static u64                   sleep_measurement_overhead;
 
 static unsigned long           nr_tasks;
 
+struct perf_sched {
+       struct perf_tool    tool;
+       struct perf_session *session;
+};
+
 struct sched_atom;
 
 struct task_desc {
@@ -1597,11 +1602,13 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
                                                 struct perf_evsel *evsel,
                                                 struct machine *machine)
 {
+       struct perf_sched *sched = container_of(tool, struct perf_sched, tool);
+       struct pevent *pevent = sched->session->pevent;
        struct thread *thread = machine__findnew_thread(machine, sample->pid);
 
        if (thread == NULL) {
                pr_debug("problem processing %s event, skipping it.\n",
-                        evsel->name);
+                        perf_evsel__name(evsel));
                return -1;
        }
 
@@ -1612,7 +1619,8 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
                tracepoint_handler f = evsel->handler.func;
 
                if (evsel->handler.data == NULL)
-                       evsel->handler.data = trace_find_event(evsel->attr.config);
+                       evsel->handler.data = pevent_find_event(pevent,
+                                                         evsel->attr.config);
 
                f(tool, evsel->handler.data, sample, machine, thread);
        }
@@ -1620,12 +1628,14 @@ static int perf_sched__process_tracepoint_sample(struct perf_tool *tool,
        return 0;
 }
 
-static struct perf_tool perf_sched = {
-       .sample                 = perf_sched__process_tracepoint_sample,
-       .comm                   = perf_event__process_comm,
-       .lost                   = perf_event__process_lost,
-       .fork                   = perf_event__process_task,
-       .ordered_samples        = true,
+static struct perf_sched perf_sched = {
+       .tool = {
+               .sample          = perf_sched__process_tracepoint_sample,
+               .comm            = perf_event__process_comm,
+               .lost            = perf_event__process_lost,
+               .fork            = perf_event__process_task,
+               .ordered_samples = true,
+       },
 };
 
 static void read_events(bool destroy, struct perf_session **psession)
@@ -1640,16 +1650,20 @@ static void read_events(bool destroy, struct perf_session **psession)
                { "sched:sched_process_exit", process_sched_exit_event, },
                { "sched:sched_migrate_task", process_sched_migrate_task_event, },
        };
-       struct perf_session *session = perf_session__new(input_name, O_RDONLY,
-                                                        0, false, &perf_sched);
+       struct perf_session *session;
+
+       session = perf_session__new(input_name, O_RDONLY, 0, false,
+                                   &perf_sched.tool);
        if (session == NULL)
                die("No Memory");
 
-       err = perf_evlist__set_tracepoints_handlers_array(session->evlist, handlers);
+       perf_sched.session = session;
+
+       err = perf_session__set_tracepoints_handlers(session, handlers);
        assert(err == 0);
 
        if (perf_session__has_traces(session, "record -R")) {
-               err = perf_session__process_events(session, &perf_sched);
+               err = perf_session__process_events(session, &perf_sched.tool);
                if (err)
                        die("Failed to process events, error %d", err);
 
index 8e395a538eb92b212ee20ac9e475c7ab70f2f191..1e60ab70b2b14789b17a2a7199f5a8d175709242 100644 (file)
@@ -28,6 +28,11 @@ static bool                  system_wide;
 static const char              *cpu_list;
 static DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
 
+struct perf_script {
+       struct perf_tool    tool;
+       struct perf_session *session;
+};
+
 enum perf_output_field {
        PERF_OUTPUT_COMM            = 1U << 0,
        PERF_OUTPUT_TID             = 1U << 1,
@@ -137,10 +142,11 @@ static const char *output_field2str(enum perf_output_field field)
 
 #define PRINT_FIELD(x)  (output[attr->type].fields & PERF_OUTPUT_##x)
 
-static int perf_event_attr__check_stype(struct perf_event_attr *attr,
-                                 u64 sample_type, const char *sample_msg,
-                                 enum perf_output_field field)
+static int perf_evsel__check_stype(struct perf_evsel *evsel,
+                                  u64 sample_type, const char *sample_msg,
+                                  enum perf_output_field field)
 {
+       struct perf_event_attr *attr = &evsel->attr;
        int type = attr->type;
        const char *evname;
 
@@ -148,7 +154,7 @@ static int perf_event_attr__check_stype(struct perf_event_attr *attr,
                return 0;
 
        if (output[type].user_set) {
-               evname = __event_name(attr->type, attr->config);
+               evname = perf_evsel__name(evsel);
                pr_err("Samples for '%s' event do not have %s attribute set. "
                       "Cannot print '%s' field.\n",
                       evname, sample_msg, output_field2str(field));
@@ -157,7 +163,7 @@ static int perf_event_attr__check_stype(struct perf_event_attr *attr,
 
        /* user did not ask for it explicitly so remove from the default list */
        output[type].fields &= ~field;
-       evname = __event_name(attr->type, attr->config);
+       evname = perf_evsel__name(evsel);
        pr_debug("Samples for '%s' event do not have %s attribute set. "
                 "Skipping '%s' field.\n",
                 evname, sample_msg, output_field2str(field));
@@ -175,8 +181,8 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
                return -EINVAL;
 
        if (PRINT_FIELD(IP)) {
-               if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP",
-                                          PERF_OUTPUT_IP))
+               if (perf_evsel__check_stype(evsel, PERF_SAMPLE_IP, "IP",
+                                           PERF_OUTPUT_IP))
                        return -EINVAL;
 
                if (!no_callchain &&
@@ -185,8 +191,8 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
        }
 
        if (PRINT_FIELD(ADDR) &&
-               perf_event_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR",
-                                      PERF_OUTPUT_ADDR))
+               perf_evsel__check_stype(evsel, PERF_SAMPLE_ADDR, "ADDR",
+                                       PERF_OUTPUT_ADDR))
                return -EINVAL;
 
        if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
@@ -208,18 +214,18 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
        }
 
        if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
-               perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID",
-                                      PERF_OUTPUT_TID|PERF_OUTPUT_PID))
+               perf_evsel__check_stype(evsel, PERF_SAMPLE_TID, "TID",
+                                       PERF_OUTPUT_TID|PERF_OUTPUT_PID))
                return -EINVAL;
 
        if (PRINT_FIELD(TIME) &&
-               perf_event_attr__check_stype(attr, PERF_SAMPLE_TIME, "TIME",
-                                      PERF_OUTPUT_TIME))
+               perf_evsel__check_stype(evsel, PERF_SAMPLE_TIME, "TIME",
+                                       PERF_OUTPUT_TIME))
                return -EINVAL;
 
        if (PRINT_FIELD(CPU) &&
-               perf_event_attr__check_stype(attr, PERF_SAMPLE_CPU, "CPU",
-                                      PERF_OUTPUT_CPU))
+               perf_evsel__check_stype(evsel, PERF_SAMPLE_CPU, "CPU",
+                                       PERF_OUTPUT_CPU))
                return -EINVAL;
 
        return 0;
@@ -256,11 +262,13 @@ static int perf_session__check_output_opt(struct perf_session *session)
        return 0;
 }
 
-static void print_sample_start(struct perf_sample *sample,
+static void print_sample_start(struct pevent *pevent,
+                              struct perf_sample *sample,
                               struct thread *thread,
-                              struct perf_event_attr *attr)
+                              struct perf_evsel *evsel)
 {
        int type;
+       struct perf_event_attr *attr = &evsel->attr;
        struct event_format *event;
        const char *evname = NULL;
        unsigned long secs;
@@ -300,12 +308,18 @@ static void print_sample_start(struct perf_sample *sample,
 
        if (PRINT_FIELD(EVNAME)) {
                if (attr->type == PERF_TYPE_TRACEPOINT) {
-                       type = trace_parse_common_type(sample->raw_data);
-                       event = trace_find_event(type);
+                       /*
+                        * XXX Do we really need this here?
+                        * perf_evlist__set_tracepoint_names should have done
+                        * this already
+                        */
+                       type = trace_parse_common_type(pevent,
+                                                      sample->raw_data);
+                       event = pevent_find_event(pevent, type);
                        if (event)
                                evname = event->name;
                } else
-                       evname = __event_name(attr->type, attr->config);
+                       evname = perf_evsel__name(evsel);
 
                printf("%s: ", evname ? evname : "[unknown]");
        }
@@ -387,7 +401,7 @@ static void print_sample_bts(union perf_event *event,
                        printf(" ");
                else
                        printf("\n");
-               perf_event__print_ip(event, sample, machine, evsel,
+               perf_event__print_ip(event, sample, machine,
                                     PRINT_FIELD(SYM), PRINT_FIELD(DSO),
                                     PRINT_FIELD(SYMOFFSET));
        }
@@ -402,6 +416,7 @@ static void print_sample_bts(union perf_event *event,
 }
 
 static void process_event(union perf_event *event __unused,
+                         struct pevent *pevent,
                          struct perf_sample *sample,
                          struct perf_evsel *evsel,
                          struct machine *machine,
@@ -412,7 +427,7 @@ static void process_event(union perf_event *event __unused,
        if (output[attr->type].fields == 0)
                return;
 
-       print_sample_start(sample, thread, attr);
+       print_sample_start(pevent, sample, thread, evsel);
 
        if (is_bts_event(attr)) {
                print_sample_bts(event, sample, evsel, machine, thread);
@@ -420,7 +435,7 @@ static void process_event(union perf_event *event __unused,
        }
 
        if (PRINT_FIELD(TRACE))
-               print_trace_event(sample->cpu, sample->raw_data,
+               print_trace_event(pevent, sample->cpu, sample->raw_data,
                                  sample->raw_size);
 
        if (PRINT_FIELD(ADDR))
@@ -431,7 +446,7 @@ static void process_event(union perf_event *event __unused,
                        printf(" ");
                else
                        printf("\n");
-               perf_event__print_ip(event, sample, machine, evsel,
+               perf_event__print_ip(event, sample, machine,
                                     PRINT_FIELD(SYM), PRINT_FIELD(DSO),
                                     PRINT_FIELD(SYMOFFSET));
        }
@@ -451,7 +466,8 @@ static int default_stop_script(void)
        return 0;
 }
 
-static int default_generate_script(const char *outfile __unused)
+static int default_generate_script(struct pevent *pevent __unused,
+                                  const char *outfile __unused)
 {
        return 0;
 }
@@ -489,6 +505,7 @@ static int process_sample_event(struct perf_tool *tool __used,
                                struct machine *machine)
 {
        struct addr_location al;
+       struct perf_script *scr = container_of(tool, struct perf_script, tool);
        struct thread *thread = machine__findnew_thread(machine, event->ip.tid);
 
        if (thread == NULL) {
@@ -520,24 +537,27 @@ static int process_sample_event(struct perf_tool *tool __used,
        if (cpu_list && !test_bit(sample->cpu, cpu_bitmap))
                return 0;
 
-       scripting_ops->process_event(event, sample, evsel, machine, thread);
+       scripting_ops->process_event(event, scr->session->pevent,
+                                    sample, evsel, machine, thread);
 
        evsel->hists.stats.total_period += sample->period;
        return 0;
 }
 
-static struct perf_tool perf_script = {
-       .sample          = process_sample_event,
-       .mmap            = perf_event__process_mmap,
-       .comm            = perf_event__process_comm,
-       .exit            = perf_event__process_task,
-       .fork            = perf_event__process_task,
-       .attr            = perf_event__process_attr,
-       .event_type      = perf_event__process_event_type,
-       .tracing_data    = perf_event__process_tracing_data,
-       .build_id        = perf_event__process_build_id,
-       .ordered_samples = true,
-       .ordering_requires_timestamps = true,
+static struct perf_script perf_script = {
+       .tool = {
+               .sample          = process_sample_event,
+               .mmap            = perf_event__process_mmap,
+               .comm            = perf_event__process_comm,
+               .exit            = perf_event__process_task,
+               .fork            = perf_event__process_task,
+               .attr            = perf_event__process_attr,
+               .event_type      = perf_event__process_event_type,
+               .tracing_data    = perf_event__process_tracing_data,
+               .build_id        = perf_event__process_build_id,
+               .ordered_samples = true,
+               .ordering_requires_timestamps = true,
+       },
 };
 
 extern volatile int session_done;
@@ -553,7 +573,7 @@ static int __cmd_script(struct perf_session *session)
 
        signal(SIGINT, sig_handler);
 
-       ret = perf_session__process_events(session, &perf_script);
+       ret = perf_session__process_events(session, &perf_script.tool);
 
        if (debug_mode)
                pr_err("Misordered timestamps: %" PRIu64 "\n", nr_unordered);
@@ -1335,10 +1355,13 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
        if (!script_name)
                setup_pager();
 
-       session = perf_session__new(input_name, O_RDONLY, 0, false, &perf_script);
+       session = perf_session__new(input_name, O_RDONLY, 0, false,
+                                   &perf_script.tool);
        if (session == NULL)
                return -ENOMEM;
 
+       perf_script.session = session;
+
        if (cpu_list) {
                if (perf_session__cpu_bitmap(session, cpu_list, cpu_bitmap))
                        return -1;
@@ -1384,7 +1407,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __used)
                        return -1;
                }
 
-               err = scripting_ops->generate_script("perf-script");
+               err = scripting_ops->generate_script(session->pevent,
+                                                    "perf-script");
                goto out;
        }
 
index 07b5c7703dd10677e12a5b6e36c8603f18fd0f7e..861f0aec77aeacf099653d87ca9c6df9b6f2787c 100644 (file)
@@ -391,7 +391,7 @@ static int read_counter_aggr(struct perf_evsel *counter)
 
        if (verbose) {
                fprintf(output, "%s: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
-                       event_name(counter), count[0], count[1], count[2]);
+                       perf_evsel__name(counter), count[0], count[1], count[2]);
        }
 
        /*
@@ -496,7 +496,7 @@ static int run_perf_stat(int argc __used, const char **argv)
                            errno == ENXIO) {
                                if (verbose)
                                        ui__warning("%s event is not supported by the kernel.\n",
-                                                   event_name(counter));
+                                                   perf_evsel__name(counter));
                                counter->supported = false;
                                continue;
                        }
@@ -594,7 +594,7 @@ static void nsec_printout(int cpu, struct perf_evsel *evsel, double avg)
                        csv_output ? 0 : -4,
                        evsel_list->cpus->map[cpu], csv_sep);
 
-       fprintf(output, fmt, cpustr, msecs, csv_sep, event_name(evsel));
+       fprintf(output, fmt, cpustr, msecs, csv_sep, perf_evsel__name(evsel));
 
        if (evsel->cgrp)
                fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -792,7 +792,7 @@ static void abs_printout(int cpu, struct perf_evsel *evsel, double avg)
        else
                cpu = 0;
 
-       fprintf(output, fmt, cpustr, avg, csv_sep, event_name(evsel));
+       fprintf(output, fmt, cpustr, avg, csv_sep, perf_evsel__name(evsel));
 
        if (evsel->cgrp)
                fprintf(output, "%s%s", csv_sep, evsel->cgrp->name);
@@ -908,7 +908,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
                        counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
                        csv_sep,
                        csv_output ? 0 : -24,
-                       event_name(counter));
+                       perf_evsel__name(counter));
 
                if (counter->cgrp)
                        fprintf(output, "%s%s", csv_sep, counter->cgrp->name);
@@ -961,7 +961,7 @@ static void print_counter(struct perf_evsel *counter)
                                counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
                                csv_sep,
                                csv_output ? 0 : -24,
-                               event_name(counter));
+                               perf_evsel__name(counter));
 
                        if (counter->cgrp)
                                fprintf(output, "%s%s",
index 5a8727c0875772c9c37c3fc381b1812161c3b983..5ce30305462b1775fbfc80f9569e29328d25edd3 100644 (file)
@@ -583,7 +583,7 @@ static int test__basic_mmap(void)
                if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
                        pr_debug("expected %d %s events, got %d\n",
                                 expected_nr_events[evsel->idx],
-                                event_name(evsel), nr_events[evsel->idx]);
+                                perf_evsel__name(evsel), nr_events[evsel->idx]);
                        goto out_munmap;
                }
        }
index 6bb0277b7dfecdbf63e727592995480a409f16f5..e3cab5f088f8def4264a0ec65dba4f85b0b0f954 100644 (file)
@@ -245,7 +245,7 @@ static void perf_top__show_details(struct perf_top *top)
        if (notes->src == NULL)
                goto out_unlock;
 
-       printf("Showing %s for %s\n", event_name(top->sym_evsel), symbol->name);
+       printf("Showing %s for %s\n", perf_evsel__name(top->sym_evsel), symbol->name);
        printf("  Events  Pcnt (>=%d%%)\n", top->sym_pcnt_filter);
 
        more = symbol__annotate_printf(symbol, he->ms.map, top->sym_evsel->idx,
@@ -408,7 +408,7 @@ static void perf_top__print_mapped_keys(struct perf_top *top)
        fprintf(stdout, "\t[e]     display entries (lines).           \t(%d)\n", top->print_entries);
 
        if (top->evlist->nr_entries > 1)
-               fprintf(stdout, "\t[E]     active event counter.              \t(%s)\n", event_name(top->sym_evsel));
+               fprintf(stdout, "\t[E]     active event counter.              \t(%s)\n", perf_evsel__name(top->sym_evsel));
 
        fprintf(stdout, "\t[f]     profile display filter (count).    \t(%d)\n", top->count_filter);
 
@@ -503,13 +503,13 @@ static void perf_top__handle_keypress(struct perf_top *top, int c)
                                fprintf(stderr, "\nAvailable events:");
 
                                list_for_each_entry(top->sym_evsel, &top->evlist->entries, node)
-                                       fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, event_name(top->sym_evsel));
+                                       fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel));
 
                                prompt_integer(&counter, "Enter details event counter");
 
                                if (counter >= top->evlist->nr_entries) {
                                        top->sym_evsel = list_entry(top->evlist->entries.next, struct perf_evsel, node);
-                                       fprintf(stderr, "Sorry, no such event, using %s.\n", event_name(top->sym_evsel));
+                                       fprintf(stderr, "Sorry, no such event, using %s.\n", perf_evsel__name(top->sym_evsel));
                                        sleep(1);
                                        break;
                                }
@@ -774,7 +774,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
 
                if ((sort__has_parent || symbol_conf.use_callchain) &&
                    sample->callchain) {
-                       err = machine__resolve_callchain(machine, evsel, al.thread,
+                       err = machine__resolve_callchain(machine, al.thread,
                                                         sample->callchain, &parent);
                        if (err)
                                return;
@@ -960,7 +960,7 @@ try_again:
 
                        if (err == ENOENT) {
                                ui__error("The %s event is not supported.\n",
-                                           event_name(counter));
+                                         perf_evsel__name(counter));
                                goto out_err;
                        } else if (err == EMFILE) {
                                ui__error("Too many events are opened.\n"
index d9084e03ce56676628736c5814e27badbe2ef730..6c18785a6417986dabe47f775b0fd07067447012 100644 (file)
@@ -78,6 +78,19 @@ int main(int argc, char *argv[])
         return 0;
 }
 endef
+
+define SOURCE_GTK2_INFOBAR
+#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"
+#include <gtk/gtk.h>
+#pragma GCC diagnostic error \"-Wstrict-prototypes\"
+
+int main(void)
+{
+       gtk_info_bar_new();
+
+       return 0;
+}
+endef
 endif
 
 ifndef NO_LIBPERL
index 34b1c46eaf42c63d36ed5c36cbaceea38c2347a9..67a2703e666a360c1fd71a8af6ea150174ebeb70 100644 (file)
@@ -814,7 +814,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
 {
        struct disasm_line *pos, *n;
        struct annotation *notes;
-       const size_t size = symbol__size(sym);
+       size_t size;
        struct map_symbol ms = {
                .map = map,
                .sym = sym,
@@ -834,6 +834,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
        if (sym == NULL)
                return -1;
 
+       size = symbol__size(sym);
+
        if (map->dso->annotate_warned)
                return -1;
 
index 53f6697d014e788396b474c6be957893b8fd09ca..482f0517b61e20f61a18933133717ce53fc0e1c1 100644 (file)
@@ -23,6 +23,7 @@ struct hist_browser {
        struct hists        *hists;
        struct hist_entry   *he_selection;
        struct map_symbol   *selection;
+       int                  print_seq;
        bool                 has_symbols;
 };
 
@@ -800,6 +801,196 @@ do_offset:
        }
 }
 
+static int hist_browser__fprintf_callchain_node_rb_tree(struct hist_browser *browser,
+                                                       struct callchain_node *chain_node,
+                                                       u64 total, int level,
+                                                       FILE *fp)
+{
+       struct rb_node *node;
+       int offset = level * LEVEL_OFFSET_STEP;
+       u64 new_total, remaining;
+       int printed = 0;
+
+       if (callchain_param.mode == CHAIN_GRAPH_REL)
+               new_total = chain_node->children_hit;
+       else
+               new_total = total;
+
+       remaining = new_total;
+       node = rb_first(&chain_node->rb_root);
+       while (node) {
+               struct callchain_node *child = rb_entry(node, struct callchain_node, rb_node);
+               struct rb_node *next = rb_next(node);
+               u64 cumul = callchain_cumul_hits(child);
+               struct callchain_list *chain;
+               char folded_sign = ' ';
+               int first = true;
+               int extra_offset = 0;
+
+               remaining -= cumul;
+
+               list_for_each_entry(chain, &child->val, list) {
+                       char ipstr[BITS_PER_LONG / 4 + 1], *alloc_str;
+                       const char *str;
+                       bool was_first = first;
+
+                       if (first)
+                               first = false;
+                       else
+                               extra_offset = LEVEL_OFFSET_STEP;
+
+                       folded_sign = callchain_list__folded(chain);
+
+                       alloc_str = NULL;
+                       str = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
+                       if (was_first) {
+                               double percent = cumul * 100.0 / new_total;
+
+                               if (asprintf(&alloc_str, "%2.2f%% %s", percent, str) < 0)
+                                       str = "Not enough memory!";
+                               else
+                                       str = alloc_str;
+                       }
+
+                       printed += fprintf(fp, "%*s%c %s\n", offset + extra_offset, " ", folded_sign, str);
+                       free(alloc_str);
+                       if (folded_sign == '+')
+                               break;
+               }
+
+               if (folded_sign == '-') {
+                       const int new_level = level + (extra_offset ? 2 : 1);
+                       printed += hist_browser__fprintf_callchain_node_rb_tree(browser, child, new_total,
+                                                                               new_level, fp);
+               }
+
+               node = next;
+       }
+
+       return printed;
+}
+
+static int hist_browser__fprintf_callchain_node(struct hist_browser *browser,
+                                               struct callchain_node *node,
+                                               int level, FILE *fp)
+{
+       struct callchain_list *chain;
+       int offset = level * LEVEL_OFFSET_STEP;
+       char folded_sign = ' ';
+       int printed = 0;
+
+       list_for_each_entry(chain, &node->val, list) {
+               char ipstr[BITS_PER_LONG / 4 + 1], *s;
+
+               folded_sign = callchain_list__folded(chain);
+               s = callchain_list__sym_name(chain, ipstr, sizeof(ipstr));
+               printed += fprintf(fp, "%*s%c %s\n", offset, " ", folded_sign, s);
+       }
+
+       if (folded_sign == '-')
+               printed += hist_browser__fprintf_callchain_node_rb_tree(browser, node,
+                                                                       browser->hists->stats.total_period,
+                                                                       level + 1,  fp);
+       return printed;
+}
+
+static int hist_browser__fprintf_callchain(struct hist_browser *browser,
+                                          struct rb_root *chain, int level, FILE *fp)
+{
+       struct rb_node *nd;
+       int printed = 0;
+
+       for (nd = rb_first(chain); nd; nd = rb_next(nd)) {
+               struct callchain_node *node = rb_entry(nd, struct callchain_node, rb_node);
+
+               printed += hist_browser__fprintf_callchain_node(browser, node, level, fp);
+       }
+
+       return printed;
+}
+
+static int hist_browser__fprintf_entry(struct hist_browser *browser,
+                                      struct hist_entry *he, FILE *fp)
+{
+       char s[8192];
+       double percent;
+       int printed = 0;
+       char folded_sign = ' ';
+
+       if (symbol_conf.use_callchain)
+               folded_sign = hist_entry__folded(he);
+
+       hist_entry__snprintf(he, s, sizeof(s), browser->hists);
+       percent = (he->period * 100.0) / browser->hists->stats.total_period;
+
+       if (symbol_conf.use_callchain)
+               printed += fprintf(fp, "%c ", folded_sign);
+
+       printed += fprintf(fp, " %5.2f%%", percent);
+
+       if (symbol_conf.show_nr_samples)
+               printed += fprintf(fp, " %11u", he->nr_events);
+
+       if (symbol_conf.show_total_period)
+               printed += fprintf(fp, " %12" PRIu64, he->period);
+
+       printed += fprintf(fp, "%s\n", rtrim(s));
+
+       if (folded_sign == '-')
+               printed += hist_browser__fprintf_callchain(browser, &he->sorted_chain, 1, fp);
+
+       return printed;
+}
+
+static int hist_browser__fprintf(struct hist_browser *browser, FILE *fp)
+{
+       struct rb_node *nd = hists__filter_entries(rb_first(browser->b.entries));
+       int printed = 0;
+
+       while (nd) {
+               struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node);
+
+               printed += hist_browser__fprintf_entry(browser, h, fp);
+               nd = hists__filter_entries(rb_next(nd));
+       }
+
+       return printed;
+}
+
+static int hist_browser__dump(struct hist_browser *browser)
+{
+       char filename[64];
+       FILE *fp;
+
+       while (1) {
+               scnprintf(filename, sizeof(filename), "perf.hist.%d", browser->print_seq);
+               if (access(filename, F_OK))
+                       break;
+               /*
+                * XXX: Just an arbitrary lazy upper limit
+                */
+               if (++browser->print_seq == 8192) {
+                       ui_helpline__fpush("Too many perf.hist.N files, nothing written!");
+                       return -1;
+               }
+       }
+
+       fp = fopen(filename, "w");
+       if (fp == NULL) {
+               char bf[64];
+               strerror_r(errno, bf, sizeof(bf));
+               ui_helpline__fpush("Couldn't write to %s: %s", filename, bf);
+               return -1;
+       }
+
+       ++browser->print_seq;
+       hist_browser__fprintf(browser, fp);
+       fclose(fp);
+       ui_helpline__fpush("%s written!", filename);
+
+       return 0;
+}
+
 static struct hist_browser *hist_browser__new(struct hists *hists)
 {
        struct hist_browser *browser = zalloc(sizeof(*browser));
@@ -937,6 +1128,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                            browser->selection->map->dso->annotate_warned)
                                continue;
                        goto do_annotate;
+               case 'P':
+                       hist_browser__dump(browser);
+                       continue;
                case 'd':
                        goto zoom_dso;
                case 't':
@@ -969,6 +1163,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
                                        "E             Expand all callchains\n"
                                        "d             Zoom into current DSO\n"
                                        "t             Zoom into current Thread\n"
+                                       "P             Print histograms to perf.hist.N\n"
                                        "/             Filter symbol by name");
                        continue;
                case K_ENTER:
@@ -1172,7 +1367,7 @@ static void perf_evsel_menu__write(struct ui_browser *browser,
        struct perf_evsel *evsel = list_entry(entry, struct perf_evsel, node);
        bool current_entry = ui_browser__is_current_entry(browser, row);
        unsigned long nr_events = evsel->hists.stats.nr_events[PERF_RECORD_SAMPLE];
-       const char *ev_name = event_name(evsel);
+       const char *ev_name = perf_evsel__name(evsel);
        char bf[256], unit;
        const char *warn = " ";
        size_t printed;
@@ -1240,7 +1435,7 @@ browse_hists:
                         */
                        if (timer)
                                timer(arg);
-                       ev_name = event_name(pos);
+                       ev_name = perf_evsel__name(pos);
                        key = perf_evsel__hists_browse(pos, nr_events, help,
                                                       ev_name, true, timer,
                                                       arg, delay_secs);
@@ -1309,17 +1504,11 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
        ui_helpline__push("Press ESC to exit");
 
        list_for_each_entry(pos, &evlist->entries, node) {
-               const char *ev_name = event_name(pos);
+               const char *ev_name = perf_evsel__name(pos);
                size_t line_len = strlen(ev_name) + 7;
 
                if (menu.b.width < line_len)
                        menu.b.width = line_len;
-               /*
-                * Cache the evsel name, tracepoints have a _high_ cost per
-                * event_name() call.
-                */
-               if (pos->name == NULL)
-                       pos->name = strdup(ev_name);
        }
 
        return perf_evsel_menu__run(&menu, evlist->nr_entries, help, timer,
@@ -1330,11 +1519,10 @@ int perf_evlist__tui_browse_hists(struct perf_evlist *evlist, const char *help,
                                  void(*timer)(void *arg), void *arg,
                                  int delay_secs)
 {
-
        if (evlist->nr_entries == 1) {
                struct perf_evsel *first = list_entry(evlist->entries.next,
                                                      struct perf_evsel, node);
-               const char *ev_name = event_name(first);
+               const char *ev_name = perf_evsel__name(first);
                return perf_evsel__hists_browse(first, evlist->nr_entries, help,
                                                ev_name, false, timer, arg,
                                                delay_secs);
index 0656c381a89cae7dcfd92302ea2c021ca75b517c..ec12e0b4ded6567d1c673049cf39cea0f93891f0 100644 (file)
@@ -11,8 +11,8 @@
 
 static void perf_gtk__signal(int sig)
 {
+       perf_gtk__exit(false);
        psignal(sig, "perf");
-       gtk_main_quit();
 }
 
 static void perf_gtk__resize_window(GtkWidget *window)
@@ -122,13 +122,59 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists)
        gtk_container_add(GTK_CONTAINER(window), view);
 }
 
+#ifdef HAVE_GTK_INFO_BAR
+static GtkWidget *perf_gtk__setup_info_bar(void)
+{
+       GtkWidget *info_bar;
+       GtkWidget *label;
+       GtkWidget *content_area;
+
+       info_bar = gtk_info_bar_new();
+       gtk_widget_set_no_show_all(info_bar, TRUE);
+
+       label = gtk_label_new("");
+       gtk_widget_show(label);
+
+       content_area = gtk_info_bar_get_content_area(GTK_INFO_BAR(info_bar));
+       gtk_container_add(GTK_CONTAINER(content_area), label);
+
+       gtk_info_bar_add_button(GTK_INFO_BAR(info_bar), GTK_STOCK_OK,
+                               GTK_RESPONSE_OK);
+       g_signal_connect(info_bar, "response",
+                        G_CALLBACK(gtk_widget_hide), NULL);
+
+       pgctx->info_bar = info_bar;
+       pgctx->message_label = label;
+
+       return info_bar;
+}
+#endif
+
+static GtkWidget *perf_gtk__setup_statusbar(void)
+{
+       GtkWidget *stbar;
+       unsigned ctxid;
+
+       stbar = gtk_statusbar_new();
+
+       ctxid = gtk_statusbar_get_context_id(GTK_STATUSBAR(stbar),
+                                            "perf report");
+       pgctx->statbar = stbar;
+       pgctx->statbar_ctx_id = ctxid;
+
+       return stbar;
+}
+
 int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
                                  const char *help __used,
                                  void (*timer) (void *arg)__used,
                                  void *arg __used, int delay_secs __used)
 {
        struct perf_evsel *pos;
+       GtkWidget *vbox;
        GtkWidget *notebook;
+       GtkWidget *info_bar;
+       GtkWidget *statbar;
        GtkWidget *window;
 
        signal(SIGSEGV, perf_gtk__signal);
@@ -143,11 +189,17 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
 
        g_signal_connect(window, "delete_event", gtk_main_quit, NULL);
 
+       pgctx = perf_gtk__activate_context(window);
+       if (!pgctx)
+               return -1;
+
+       vbox = gtk_vbox_new(FALSE, 0);
+
        notebook = gtk_notebook_new();
 
        list_for_each_entry(pos, &evlist->entries, node) {
                struct hists *hists = &pos->hists;
-               const char *evname = event_name(pos);
+               const char *evname = perf_evsel__name(pos);
                GtkWidget *scrolled_window;
                GtkWidget *tab_label;
 
@@ -164,7 +216,16 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
                gtk_notebook_append_page(GTK_NOTEBOOK(notebook), scrolled_window, tab_label);
        }
 
-       gtk_container_add(GTK_CONTAINER(window), notebook);
+       gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0);
+
+       info_bar = perf_gtk__setup_info_bar();
+       if (info_bar)
+               gtk_box_pack_start(GTK_BOX(vbox), info_bar, FALSE, FALSE, 0);
+
+       statbar = perf_gtk__setup_statusbar();
+       gtk_box_pack_start(GTK_BOX(vbox), statbar, FALSE, FALSE, 0);
+
+       gtk_container_add(GTK_CONTAINER(window), vbox);
 
        gtk_widget_show_all(window);
 
@@ -174,5 +235,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
 
        gtk_main();
 
+       perf_gtk__deactivate_context(&pgctx);
+
        return 0;
 }
index 75177ee04032d06a3862acf4befd82b0b67516d3..a4d0f2b4a2dcf4c4b6bfb9b21a52aabc4b9376ca 100644 (file)
@@ -1,8 +1,39 @@
 #ifndef _PERF_GTK_H_
 #define _PERF_GTK_H_ 1
 
+#include <stdbool.h>
+
 #pragma GCC diagnostic ignored "-Wstrict-prototypes"
 #include <gtk/gtk.h>
 #pragma GCC diagnostic error "-Wstrict-prototypes"
 
+
+struct perf_gtk_context {
+       GtkWidget *main_window;
+
+#ifdef HAVE_GTK_INFO_BAR
+       GtkWidget *info_bar;
+       GtkWidget *message_label;
+#endif
+       GtkWidget *statbar;
+       guint statbar_ctx_id;
+};
+
+extern struct perf_gtk_context *pgctx;
+
+static inline bool perf_gtk__is_active_context(struct perf_gtk_context *ctx)
+{
+       return ctx && ctx->main_window;
+}
+
+struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window);
+int perf_gtk__deactivate_context(struct perf_gtk_context **ctx);
+
+#ifndef HAVE_GTK_INFO_BAR
+static inline GtkWidget *perf_gtk__setup_info_bar(void)
+{
+       return NULL;
+}
+#endif
+
 #endif /* _PERF_GTK_H_ */
index 8295299577660b24b99405a22965316f04f96e98..92879ce61e2fc0059f6827c38b9ff8eaf114adba 100644 (file)
@@ -1,12 +1,17 @@
 #include "gtk.h"
 #include "../../util/cache.h"
+#include "../../util/debug.h"
+
+extern struct perf_error_ops perf_gtk_eops;
 
 int perf_gtk__init(void)
 {
+       perf_error__register(&perf_gtk_eops);
        return gtk_init_check(NULL, NULL) ? 0 : -1;
 }
 
 void perf_gtk__exit(bool wait_for_ok __used)
 {
+       perf_error__unregister(&perf_gtk_eops);
        gtk_main_quit();
 }
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
new file mode 100644 (file)
index 0000000..0ead373
--- /dev/null
@@ -0,0 +1,129 @@
+#include "../util.h"
+#include "../../util/debug.h"
+#include "gtk.h"
+
+#include <string.h>
+
+
+struct perf_gtk_context *pgctx;
+
+struct perf_gtk_context *perf_gtk__activate_context(GtkWidget *window)
+{
+       struct perf_gtk_context *ctx;
+
+       ctx = malloc(sizeof(*pgctx));
+       if (ctx)
+               ctx->main_window = window;
+
+       return ctx;
+}
+
+int perf_gtk__deactivate_context(struct perf_gtk_context **ctx)
+{
+       if (!perf_gtk__is_active_context(*ctx))
+               return -1;
+
+       free(*ctx);
+       *ctx = NULL;
+       return 0;
+}
+
+static int perf_gtk__error(const char *format, va_list args)
+{
+       char *msg;
+       GtkWidget *dialog;
+
+       if (!perf_gtk__is_active_context(pgctx) ||
+           vasprintf(&msg, format, args) < 0) {
+               fprintf(stderr, "Error:\n");
+               vfprintf(stderr, format, args);
+               fprintf(stderr, "\n");
+               return -1;
+       }
+
+       dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(pgctx->main_window),
+                                       GTK_DIALOG_DESTROY_WITH_PARENT,
+                                       GTK_MESSAGE_ERROR,
+                                       GTK_BUTTONS_CLOSE,
+                                       "<b>Error</b>\n\n%s", msg);
+       gtk_dialog_run(GTK_DIALOG(dialog));
+
+       gtk_widget_destroy(dialog);
+       free(msg);
+       return 0;
+}
+
+#ifdef HAVE_GTK_INFO_BAR
+static int perf_gtk__warning_info_bar(const char *format, va_list args)
+{
+       char *msg;
+
+       if (!perf_gtk__is_active_context(pgctx) ||
+           vasprintf(&msg, format, args) < 0) {
+               fprintf(stderr, "Warning:\n");
+               vfprintf(stderr, format, args);
+               fprintf(stderr, "\n");
+               return -1;
+       }
+
+       gtk_label_set_text(GTK_LABEL(pgctx->message_label), msg);
+       gtk_info_bar_set_message_type(GTK_INFO_BAR(pgctx->info_bar),
+                                     GTK_MESSAGE_WARNING);
+       gtk_widget_show(pgctx->info_bar);
+
+       free(msg);
+       return 0;
+}
+#else
+static int perf_gtk__warning_statusbar(const char *format, va_list args)
+{
+       char *msg, *p;
+
+       if (!perf_gtk__is_active_context(pgctx) ||
+           vasprintf(&msg, format, args) < 0) {
+               fprintf(stderr, "Warning:\n");
+               vfprintf(stderr, format, args);
+               fprintf(stderr, "\n");
+               return -1;
+       }
+
+       gtk_statusbar_pop(GTK_STATUSBAR(pgctx->statbar),
+                         pgctx->statbar_ctx_id);
+
+       /* Only first line can be displayed */
+       p = strchr(msg, '\n');
+       if (p)
+               *p = '\0';
+
+       gtk_statusbar_push(GTK_STATUSBAR(pgctx->statbar),
+                          pgctx->statbar_ctx_id, msg);
+
+       free(msg);
+       return 0;
+}
+#endif
+
+struct perf_error_ops perf_gtk_eops = {
+       .error          = perf_gtk__error,
+#ifdef HAVE_GTK_INFO_BAR
+       .warning        = perf_gtk__warning_info_bar,
+#else
+       .warning        = perf_gtk__warning_statusbar,
+#endif
+};
+
+/*
+ * FIXME: Functions below should be implemented properly.
+ *        For now, just add stubs for NO_NEWT=1 build.
+ */
+#ifdef NO_NEWT_SUPPORT
+int ui_helpline__show_help(const char *format __used, va_list ap __used)
+{
+       return 0;
+}
+
+void ui_progress__update(u64 curr __used, u64 total __used,
+                        const char *title __used)
+{
+}
+#endif
index d33e943ac434608067fe54fb734cda5a02d1d991..e813c1d173463564a496bdd3917f3079089a3101 100644 (file)
@@ -15,6 +15,8 @@ pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
 
 static volatile int ui__need_resize;
 
+extern struct perf_error_ops perf_tui_eops;
+
 void ui__refresh_dimensions(bool force)
 {
        if (force || ui__need_resize) {
@@ -122,6 +124,8 @@ int ui__init(void)
        signal(SIGINT, ui__signal);
        signal(SIGQUIT, ui__signal);
        signal(SIGTERM, ui__signal);
+
+       perf_error__register(&perf_tui_eops);
 out:
        return err;
 }
@@ -137,4 +141,6 @@ void ui__exit(bool wait_for_ok)
        SLsmg_refresh();
        SLsmg_reset_smg();
        SLang_reset_tty();
+
+       perf_error__unregister(&perf_tui_eops);
 }
diff --git a/tools/perf/ui/tui/util.c b/tools/perf/ui/tui/util.c
new file mode 100644 (file)
index 0000000..092902e
--- /dev/null
@@ -0,0 +1,243 @@
+#include "../../util/util.h"
+#include <signal.h>
+#include <stdbool.h>
+#include <string.h>
+#include <sys/ttydefaults.h>
+
+#include "../../util/cache.h"
+#include "../../util/debug.h"
+#include "../browser.h"
+#include "../keysyms.h"
+#include "../helpline.h"
+#include "../ui.h"
+#include "../util.h"
+#include "../libslang.h"
+
+static void ui_browser__argv_write(struct ui_browser *browser,
+                                  void *entry, int row)
+{
+       char **arg = entry;
+       bool current_entry = ui_browser__is_current_entry(browser, row);
+
+       ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
+                                                      HE_COLORSET_NORMAL);
+       slsmg_write_nstring(*arg, browser->width);
+}
+
+static int popup_menu__run(struct ui_browser *menu)
+{
+       int key;
+
+       if (ui_browser__show(menu, " ", "ESC: exit, ENTER|->: Select option") < 0)
+               return -1;
+
+       while (1) {
+               key = ui_browser__run(menu, 0);
+
+               switch (key) {
+               case K_RIGHT:
+               case K_ENTER:
+                       key = menu->index;
+                       break;
+               case K_LEFT:
+               case K_ESC:
+               case 'q':
+               case CTRL('c'):
+                       key = -1;
+                       break;
+               default:
+                       continue;
+               }
+
+               break;
+       }
+
+       ui_browser__hide(menu);
+       return key;
+}
+
+int ui__popup_menu(int argc, char * const argv[])
+{
+       struct ui_browser menu = {
+               .entries    = (void *)argv,
+               .refresh    = ui_browser__argv_refresh,
+               .seek       = ui_browser__argv_seek,
+               .write      = ui_browser__argv_write,
+               .nr_entries = argc,
+       };
+
+       return popup_menu__run(&menu);
+}
+
+int ui_browser__input_window(const char *title, const char *text, char *input,
+                            const char *exit_msg, int delay_secs)
+{
+       int x, y, len, key;
+       int max_len = 60, nr_lines = 0;
+       static char buf[50];
+       const char *t;
+
+       t = text;
+       while (1) {
+               const char *sep = strchr(t, '\n');
+
+               if (sep == NULL)
+                       sep = strchr(t, '\0');
+               len = sep - t;
+               if (max_len < len)
+                       max_len = len;
+               ++nr_lines;
+               if (*sep == '\0')
+                       break;
+               t = sep + 1;
+       }
+
+       max_len += 2;
+       nr_lines += 8;
+       y = SLtt_Screen_Rows / 2 - nr_lines / 2;
+       x = SLtt_Screen_Cols / 2 - max_len / 2;
+
+       SLsmg_set_color(0);
+       SLsmg_draw_box(y, x++, nr_lines, max_len);
+       if (title) {
+               SLsmg_gotorc(y, x + 1);
+               SLsmg_write_string((char *)title);
+       }
+       SLsmg_gotorc(++y, x);
+       nr_lines -= 7;
+       max_len -= 2;
+       SLsmg_write_wrapped_string((unsigned char *)text, y, x,
+                                  nr_lines, max_len, 1);
+       y += nr_lines;
+       len = 5;
+       while (len--) {
+               SLsmg_gotorc(y + len - 1, x);
+               SLsmg_write_nstring((char *)" ", max_len);
+       }
+       SLsmg_draw_box(y++, x + 1, 3, max_len - 2);
+
+       SLsmg_gotorc(y + 3, x);
+       SLsmg_write_nstring((char *)exit_msg, max_len);
+       SLsmg_refresh();
+
+       x += 2;
+       len = 0;
+       key = ui__getch(delay_secs);
+       while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
+               if (key == K_BKSPC) {
+                       if (len == 0)
+                               goto next_key;
+                       SLsmg_gotorc(y, x + --len);
+                       SLsmg_write_char(' ');
+               } else {
+                       buf[len] = key;
+                       SLsmg_gotorc(y, x + len++);
+                       SLsmg_write_char(key);
+               }
+               SLsmg_refresh();
+
+               /* XXX more graceful overflow handling needed */
+               if (len == sizeof(buf) - 1) {
+                       ui_helpline__push("maximum size of symbol name reached!");
+                       key = K_ENTER;
+                       break;
+               }
+next_key:
+               key = ui__getch(delay_secs);
+       }
+
+       buf[len] = '\0';
+       strncpy(input, buf, len+1);
+       return key;
+}
+
+int ui__question_window(const char *title, const char *text,
+                       const char *exit_msg, int delay_secs)
+{
+       int x, y;
+       int max_len = 0, nr_lines = 0;
+       const char *t;
+
+       t = text;
+       while (1) {
+               const char *sep = strchr(t, '\n');
+               int len;
+
+               if (sep == NULL)
+                       sep = strchr(t, '\0');
+               len = sep - t;
+               if (max_len < len)
+                       max_len = len;
+               ++nr_lines;
+               if (*sep == '\0')
+                       break;
+               t = sep + 1;
+       }
+
+       max_len += 2;
+       nr_lines += 4;
+       y = SLtt_Screen_Rows / 2 - nr_lines / 2,
+       x = SLtt_Screen_Cols / 2 - max_len / 2;
+
+       SLsmg_set_color(0);
+       SLsmg_draw_box(y, x++, nr_lines, max_len);
+       if (title) {
+               SLsmg_gotorc(y, x + 1);
+               SLsmg_write_string((char *)title);
+       }
+       SLsmg_gotorc(++y, x);
+       nr_lines -= 2;
+       max_len -= 2;
+       SLsmg_write_wrapped_string((unsigned char *)text, y, x,
+                                  nr_lines, max_len, 1);
+       SLsmg_gotorc(y + nr_lines - 2, x);
+       SLsmg_write_nstring((char *)" ", max_len);
+       SLsmg_gotorc(y + nr_lines - 1, x);
+       SLsmg_write_nstring((char *)exit_msg, max_len);
+       SLsmg_refresh();
+       return ui__getch(delay_secs);
+}
+
+int ui__help_window(const char *text)
+{
+       return ui__question_window("Help", text, "Press any key...", 0);
+}
+
+int ui__dialog_yesno(const char *msg)
+{
+       return ui__question_window(NULL, msg, "Enter: Yes, ESC: No", 0);
+}
+
+static int __ui__warning(const char *title, const char *format, va_list args)
+{
+       char *s;
+
+       if (vasprintf(&s, format, args) > 0) {
+               int key;
+
+               pthread_mutex_lock(&ui__lock);
+               key = ui__question_window(title, s, "Press any key...", 0);
+               pthread_mutex_unlock(&ui__lock);
+               free(s);
+               return key;
+       }
+
+       fprintf(stderr, "%s\n", title);
+       vfprintf(stderr, format, args);
+       return K_ESC;
+}
+
+static int perf_tui__error(const char *format, va_list args)
+{
+       return __ui__warning("Error:", format, args);
+}
+
+static int perf_tui__warning(const char *format, va_list args)
+{
+       return __ui__warning("Warning:", format, args);
+}
+
+struct perf_error_ops perf_tui_eops = {
+       .error          = perf_tui__error,
+       .warning        = perf_tui__warning,
+};
index ad4374a16bb08b88c008ca6e79fcf4a5b15903b5..4f989774c8c674c535990dcf82ae2ba47d5971e3 100644 (file)
-#include "../util.h"
-#include <signal.h>
-#include <stdbool.h>
-#include <string.h>
-#include <sys/ttydefaults.h>
-
-#include "../cache.h"
-#include "../debug.h"
-#include "browser.h"
-#include "keysyms.h"
-#include "helpline.h"
-#include "ui.h"
 #include "util.h"
-#include "libslang.h"
-
-static void ui_browser__argv_write(struct ui_browser *browser,
-                                  void *entry, int row)
-{
-       char **arg = entry;
-       bool current_entry = ui_browser__is_current_entry(browser, row);
-
-       ui_browser__set_color(browser, current_entry ? HE_COLORSET_SELECTED :
-                                                      HE_COLORSET_NORMAL);
-       slsmg_write_nstring(*arg, browser->width);
-}
-
-static int popup_menu__run(struct ui_browser *menu)
-{
-       int key;
-
-       if (ui_browser__show(menu, " ", "ESC: exit, ENTER|->: Select option") < 0)
-               return -1;
+#include "../debug.h"
 
-       while (1) {
-               key = ui_browser__run(menu, 0);
-
-               switch (key) {
-               case K_RIGHT:
-               case K_ENTER:
-                       key = menu->index;
-                       break;
-               case K_LEFT:
-               case K_ESC:
-               case 'q':
-               case CTRL('c'):
-                       key = -1;
-                       break;
-               default:
-                       continue;
-               }
-
-               break;
-       }
-
-       ui_browser__hide(menu);
-       return key;
-}
 
-int ui__popup_menu(int argc, char * const argv[])
+/*
+ * Default error logging functions
+ */
+static int perf_stdio__error(const char *format, va_list args)
 {
-       struct ui_browser menu = {
-               .entries    = (void *)argv,
-               .refresh    = ui_browser__argv_refresh,
-               .seek       = ui_browser__argv_seek,
-               .write      = ui_browser__argv_write,
-               .nr_entries = argc,
-       };
-
-       return popup_menu__run(&menu);
+       fprintf(stderr, "Error:\n");
+       vfprintf(stderr, format, args);
+       return 0;
 }
 
-int ui_browser__input_window(const char *title, const char *text, char *input,
-                            const char *exit_msg, int delay_secs)
+static int perf_stdio__warning(const char *format, va_list args)
 {
-       int x, y, len, key;
-       int max_len = 60, nr_lines = 0;
-       static char buf[50];
-       const char *t;
-
-       t = text;
-       while (1) {
-               const char *sep = strchr(t, '\n');
-
-               if (sep == NULL)
-                       sep = strchr(t, '\0');
-               len = sep - t;
-               if (max_len < len)
-                       max_len = len;
-               ++nr_lines;
-               if (*sep == '\0')
-                       break;
-               t = sep + 1;
-       }
-
-       max_len += 2;
-       nr_lines += 8;
-       y = SLtt_Screen_Rows / 2 - nr_lines / 2;
-       x = SLtt_Screen_Cols / 2 - max_len / 2;
-
-       SLsmg_set_color(0);
-       SLsmg_draw_box(y, x++, nr_lines, max_len);
-       if (title) {
-               SLsmg_gotorc(y, x + 1);
-               SLsmg_write_string((char *)title);
-       }
-       SLsmg_gotorc(++y, x);
-       nr_lines -= 7;
-       max_len -= 2;
-       SLsmg_write_wrapped_string((unsigned char *)text, y, x,
-                                  nr_lines, max_len, 1);
-       y += nr_lines;
-       len = 5;
-       while (len--) {
-               SLsmg_gotorc(y + len - 1, x);
-               SLsmg_write_nstring((char *)" ", max_len);
-       }
-       SLsmg_draw_box(y++, x + 1, 3, max_len - 2);
-
-       SLsmg_gotorc(y + 3, x);
-       SLsmg_write_nstring((char *)exit_msg, max_len);
-       SLsmg_refresh();
-
-       x += 2;
-       len = 0;
-       key = ui__getch(delay_secs);
-       while (key != K_TIMER && key != K_ENTER && key != K_ESC) {
-               if (key == K_BKSPC) {
-                       if (len == 0)
-                               goto next_key;
-                       SLsmg_gotorc(y, x + --len);
-                       SLsmg_write_char(' ');
-               } else {
-                       buf[len] = key;
-                       SLsmg_gotorc(y, x + len++);
-                       SLsmg_write_char(key);
-               }
-               SLsmg_refresh();
-
-               /* XXX more graceful overflow handling needed */
-               if (len == sizeof(buf) - 1) {
-                       ui_helpline__push("maximum size of symbol name reached!");
-                       key = K_ENTER;
-                       break;
-               }
-next_key:
-               key = ui__getch(delay_secs);
-       }
-
-       buf[len] = '\0';
-       strncpy(input, buf, len+1);
-       return key;
+       fprintf(stderr, "Warning:\n");
+       vfprintf(stderr, format, args);
+       return 0;
 }
 
-int ui__question_window(const char *title, const char *text,
-                       const char *exit_msg, int delay_secs)
+static struct perf_error_ops default_eops =
 {
-       int x, y;
-       int max_len = 0, nr_lines = 0;
-       const char *t;
-
-       t = text;
-       while (1) {
-               const char *sep = strchr(t, '\n');
-               int len;
-
-               if (sep == NULL)
-                       sep = strchr(t, '\0');
-               len = sep - t;
-               if (max_len < len)
-                       max_len = len;
-               ++nr_lines;
-               if (*sep == '\0')
-                       break;
-               t = sep + 1;
-       }
-
-       max_len += 2;
-       nr_lines += 4;
-       y = SLtt_Screen_Rows / 2 - nr_lines / 2,
-       x = SLtt_Screen_Cols / 2 - max_len / 2;
-
-       SLsmg_set_color(0);
-       SLsmg_draw_box(y, x++, nr_lines, max_len);
-       if (title) {
-               SLsmg_gotorc(y, x + 1);
-               SLsmg_write_string((char *)title);
-       }
-       SLsmg_gotorc(++y, x);
-       nr_lines -= 2;
-       max_len -= 2;
-       SLsmg_write_wrapped_string((unsigned char *)text, y, x,
-                                  nr_lines, max_len, 1);
-       SLsmg_gotorc(y + nr_lines - 2, x);
-       SLsmg_write_nstring((char *)" ", max_len);
-       SLsmg_gotorc(y + nr_lines - 1, x);
-       SLsmg_write_nstring((char *)exit_msg, max_len);
-       SLsmg_refresh();
-       return ui__getch(delay_secs);
-}
+       .error          = perf_stdio__error,
+       .warning        = perf_stdio__warning,
+};
 
-int ui__help_window(const char *text)
-{
-       return ui__question_window("Help", text, "Press any key...", 0);
-}
+static struct perf_error_ops *perf_eops = &default_eops;
 
-int ui__dialog_yesno(const char *msg)
-{
-       return ui__question_window(NULL, msg, "Enter: Yes, ESC: No", 0);
-}
 
-int __ui__warning(const char *title, const char *format, va_list args)
+int ui__error(const char *format, ...)
 {
-       char *s;
-
-       if (use_browser > 0 && vasprintf(&s, format, args) > 0) {
-               int key;
+       int ret;
+       va_list args;
 
-               pthread_mutex_lock(&ui__lock);
-               key = ui__question_window(title, s, "Press any key...", 0);
-               pthread_mutex_unlock(&ui__lock);
-               free(s);
-               return key;
-       }
+       va_start(args, format);
+       ret = perf_eops->error(format, args);
+       va_end(args);
 
-       fprintf(stderr, "%s:\n", title);
-       vfprintf(stderr, format, args);
-       return K_ESC;
+       return ret;
 }
 
 int ui__warning(const char *format, ...)
 {
-       int key;
+       int ret;
        va_list args;
 
        va_start(args, format);
-       key = __ui__warning("Warning", format, args);
+       ret = perf_eops->warning(format, args);
        va_end(args);
-       return key;
+
+       return ret;
 }
 
-int ui__error(const char *format, ...)
+
+/**
+ * perf_error__register - Register error logging functions
+ * @eops: The pointer to error logging function struct
+ *
+ * Register UI-specific error logging functions. Before calling this,
+ * other logging functions should be unregistered, if any.
+ */
+int perf_error__register(struct perf_error_ops *eops)
 {
-       int key;
-       va_list args;
+       if (perf_eops != &default_eops)
+               return -1;
 
-       va_start(args, format);
-       key = __ui__warning("Error", format, args);
-       va_end(args);
-       return key;
+       perf_eops = eops;
+       return 0;
+}
+
+/**
+ * perf_error__unregister - Unregister error logging functions
+ * @eops: The pointer to error logging function struct
+ *
+ * Unregister already registered error logging functions.
+ */
+int perf_error__unregister(struct perf_error_ops *eops)
+{
+       if (perf_eops != eops)
+               return -1;
+
+       perf_eops = &default_eops;
+       return 0;
 }
index 2d1738bd71c8adc639e7e53919f2cf988ea07ec3..361f08c52d37cba6acf8056cba96f297ceb25515 100644 (file)
@@ -9,6 +9,13 @@ int ui__help_window(const char *text);
 int ui__dialog_yesno(const char *msg);
 int ui__question_window(const char *title, const char *text,
                        const char *exit_msg, int delay_secs);
-int __ui__warning(const char *title, const char *format, va_list args);
+
+struct perf_error_ops {
+       int (*error)(const char *format, va_list args);
+       int (*warning)(const char *format, va_list args);
+};
+
+int perf_error__register(struct perf_error_ops *eops);
+int perf_error__unregister(struct perf_error_ops *eops);
 
 #endif /* _PERF_UI_UTIL_H_ */
index efb1fce259a4f2ea9ae202a9111976daf497bb53..4dfe0bb3c3225455e4f0ff3b1cb74a386352db3c 100644 (file)
@@ -47,7 +47,7 @@ int dump_printf(const char *fmt, ...)
        return ret;
 }
 
-#ifdef NO_NEWT_SUPPORT
+#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
 int ui__warning(const char *format, ...)
 {
        va_list args;
index 6bebe7f0a20c6cb6b12cac9d041203d3221f2b1a..015c91dbc096310554ba6f7bcec51c16d7cabfac 100644 (file)
@@ -12,8 +12,9 @@ int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
 void trace_event(union perf_event *event);
 
 struct ui_progress;
+struct perf_error_ops;
 
-#ifdef NO_NEWT_SUPPORT
+#if defined(NO_NEWT_SUPPORT) && defined(NO_GTK2_SUPPORT)
 static inline int ui_helpline__show_help(const char *format __used, va_list ap __used)
 {
        return 0;
@@ -23,12 +24,28 @@ static inline void ui_progress__update(u64 curr __used, u64 total __used,
                                       const char *title __used) {}
 
 #define ui__error(format, arg...) ui__warning(format, ##arg)
-#else
+
+static inline int
+perf_error__register(struct perf_error_ops *eops __used)
+{
+       return 0;
+}
+
+static inline int
+perf_error__unregister(struct perf_error_ops *eops __used)
+{
+       return 0;
+}
+
+#else /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
+
 extern char ui_helpline__last_msg[];
 int ui_helpline__show_help(const char *format, va_list ap);
 #include "../ui/progress.h"
 int ui__error(const char *format, ...) __attribute__((format(printf, 1, 2)));
-#endif
+#include "../ui/util.h"
+
+#endif /* NO_NEWT_SUPPORT && NO_GTK2_SUPPORT */
 
 int ui__warning(const char *format, ...) __attribute__((format(printf, 1, 2)));
 int ui__error_paranoid(void);
index 7400fb3fc50c91910a51eb3dc6a679ca6e4a05de..f74e9560350eb3dccfe7cc47c6a13e6256f91bb4 100644 (file)
@@ -224,8 +224,8 @@ out_free_attrs:
        return err;
 }
 
-static struct perf_evsel *
-       perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
+struct perf_evsel *
+perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
 {
        struct perf_evsel *evsel;
 
index 989bee9624c23c66e002b7a245c89c7114f3b219..40d4d3cdced0e081ec41863abe6ab46c562a3e3a 100644 (file)
@@ -73,6 +73,9 @@ int perf_evlist__set_tracepoints_handlers(struct perf_evlist *evlist,
 #define perf_evlist__set_tracepoints_handlers_array(evlist, array) \
        perf_evlist__set_tracepoints_handlers(evlist, array, ARRAY_SIZE(array))
 
+struct perf_evsel *
+perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id);
+
 void perf_evlist__id_add(struct perf_evlist *evlist, struct perf_evsel *evsel,
                         int cpu, int thread, u64 id);
 
index 9f6cebd798eed5ee44ea4510305b93b4f2e3fd6b..e81771364867bd2b5d7bf52e38e9ae0984316a0a 100644 (file)
@@ -15,7 +15,7 @@
 #include "cpumap.h"
 #include "thread_map.h"
 #include "target.h"
-#include "../../include/linux/perf_event.h"
+#include "../../../include/linux/hw_breakpoint.h"
 
 #define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
 #define GROUP_FD(group_fd, cpu) (*(int *)xyarray__entry(group_fd, cpu, 0))
@@ -78,7 +78,7 @@ static const char *perf_evsel__hw_names[PERF_COUNT_HW_MAX] = {
        "ref-cycles",
 };
 
-const char *__perf_evsel__hw_name(u64 config)
+static const char *__perf_evsel__hw_name(u64 config)
 {
        if (config < PERF_COUNT_HW_MAX && perf_evsel__hw_names[config])
                return perf_evsel__hw_names[config];
@@ -86,16 +86,15 @@ const char *__perf_evsel__hw_name(u64 config)
        return "unknown-hardware";
 }
 
-static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
+static int perf_evsel__add_modifiers(struct perf_evsel *evsel, char *bf, size_t size)
 {
-       int colon = 0;
+       int colon = 0, r = 0;
        struct perf_event_attr *attr = &evsel->attr;
-       int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(attr->config));
        bool exclude_guest_default = false;
 
 #define MOD_PRINT(context, mod)        do {                                    \
                if (!attr->exclude_##context) {                         \
-                       if (!colon) colon = r++;                        \
+                       if (!colon) colon = ++r;                        \
                        r += scnprintf(bf + r, size - r, "%c", mod);    \
                } } while(0)
 
@@ -108,7 +107,7 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
 
        if (attr->precise_ip) {
                if (!colon)
-                       colon = r++;
+                       colon = ++r;
                r += scnprintf(bf + r, size - r, "%.*s", attr->precise_ip, "ppp");
                exclude_guest_default = true;
        }
@@ -119,39 +118,211 @@ static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
        }
 #undef MOD_PRINT
        if (colon)
-               bf[colon] = ':';
+               bf[colon - 1] = ':';
        return r;
 }
 
-int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size)
+static int perf_evsel__hw_name(struct perf_evsel *evsel, char *bf, size_t size)
+{
+       int r = scnprintf(bf, size, "%s", __perf_evsel__hw_name(evsel->attr.config));
+       return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
+}
+
+static const char *perf_evsel__sw_names[PERF_COUNT_SW_MAX] = {
+       "cpu-clock",
+       "task-clock",
+       "page-faults",
+       "context-switches",
+       "CPU-migrations",
+       "minor-faults",
+       "major-faults",
+       "alignment-faults",
+       "emulation-faults",
+};
+
+static const char *__perf_evsel__sw_name(u64 config)
 {
-       int ret;
+       if (config < PERF_COUNT_SW_MAX && perf_evsel__sw_names[config])
+               return perf_evsel__sw_names[config];
+       return "unknown-software";
+}
+
+static int perf_evsel__sw_name(struct perf_evsel *evsel, char *bf, size_t size)
+{
+       int r = scnprintf(bf, size, "%s", __perf_evsel__sw_name(evsel->attr.config));
+       return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
+}
+
+static int __perf_evsel__bp_name(char *bf, size_t size, u64 addr, u64 type)
+{
+       int r;
+
+       r = scnprintf(bf, size, "mem:0x%" PRIx64 ":", addr);
+
+       if (type & HW_BREAKPOINT_R)
+               r += scnprintf(bf + r, size - r, "r");
+
+       if (type & HW_BREAKPOINT_W)
+               r += scnprintf(bf + r, size - r, "w");
+
+       if (type & HW_BREAKPOINT_X)
+               r += scnprintf(bf + r, size - r, "x");
+
+       return r;
+}
+
+static int perf_evsel__bp_name(struct perf_evsel *evsel, char *bf, size_t size)
+{
+       struct perf_event_attr *attr = &evsel->attr;
+       int r = __perf_evsel__bp_name(bf, size, attr->bp_addr, attr->bp_type);
+       return r + perf_evsel__add_modifiers(evsel, bf + r, size - r);
+}
+
+const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
+                               [PERF_EVSEL__MAX_ALIASES] = {
+ { "L1-dcache",        "l1-d",         "l1d",          "L1-data",              },
+ { "L1-icache",        "l1-i",         "l1i",          "L1-instruction",       },
+ { "LLC",      "L2",                                                   },
+ { "dTLB",     "d-tlb",        "Data-TLB",                             },
+ { "iTLB",     "i-tlb",        "Instruction-TLB",                      },
+ { "branch",   "branches",     "bpu",          "btb",          "bpc",  },
+ { "node",                                                             },
+};
+
+const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
+                                  [PERF_EVSEL__MAX_ALIASES] = {
+ { "load",     "loads",        "read",                                 },
+ { "store",    "stores",       "write",                                },
+ { "prefetch", "prefetches",   "speculative-read", "speculative-load", },
+};
+
+const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
+                                      [PERF_EVSEL__MAX_ALIASES] = {
+ { "refs",     "Reference",    "ops",          "access",               },
+ { "misses",   "miss",                                                 },
+};
+
+#define C(x)           PERF_COUNT_HW_CACHE_##x
+#define CACHE_READ     (1 << C(OP_READ))
+#define CACHE_WRITE    (1 << C(OP_WRITE))
+#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
+#define COP(x)         (1 << x)
+
+/*
+ * cache operartion stat
+ * L1I : Read and prefetch only
+ * ITLB and BPU : Read-only
+ */
+static unsigned long perf_evsel__hw_cache_stat[C(MAX)] = {
+ [C(L1D)]      = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
+ [C(L1I)]      = (CACHE_READ | CACHE_PREFETCH),
+ [C(LL)]       = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
+ [C(DTLB)]     = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
+ [C(ITLB)]     = (CACHE_READ),
+ [C(BPU)]      = (CACHE_READ),
+ [C(NODE)]     = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
+};
+
+bool perf_evsel__is_cache_op_valid(u8 type, u8 op)
+{
+       if (perf_evsel__hw_cache_stat[type] & COP(op))
+               return true;    /* valid */
+       else
+               return false;   /* invalid */
+}
+
+int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
+                                           char *bf, size_t size)
+{
+       if (result) {
+               return scnprintf(bf, size, "%s-%s-%s", perf_evsel__hw_cache[type][0],
+                                perf_evsel__hw_cache_op[op][0],
+                                perf_evsel__hw_cache_result[result][0]);
+       }
+
+       return scnprintf(bf, size, "%s-%s", perf_evsel__hw_cache[type][0],
+                        perf_evsel__hw_cache_op[op][1]);
+}
+
+static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size)
+{
+       u8 op, result, type = (config >>  0) & 0xff;
+       const char *err = "unknown-ext-hardware-cache-type";
+
+       if (type > PERF_COUNT_HW_CACHE_MAX)
+               goto out_err;
+
+       op = (config >>  8) & 0xff;
+       err = "unknown-ext-hardware-cache-op";
+       if (op > PERF_COUNT_HW_CACHE_OP_MAX)
+               goto out_err;
+
+       result = (config >> 16) & 0xff;
+       err = "unknown-ext-hardware-cache-result";
+       if (result > PERF_COUNT_HW_CACHE_RESULT_MAX)
+               goto out_err;
+
+       err = "invalid-cache";
+       if (!perf_evsel__is_cache_op_valid(type, op))
+               goto out_err;
+
+       return __perf_evsel__hw_cache_type_op_res_name(type, op, result, bf, size);
+out_err:
+       return scnprintf(bf, size, "%s", err);
+}
+
+static int perf_evsel__hw_cache_name(struct perf_evsel *evsel, char *bf, size_t size)
+{
+       int ret = __perf_evsel__hw_cache_name(evsel->attr.config, bf, size);
+       return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
+}
+
+static int perf_evsel__raw_name(struct perf_evsel *evsel, char *bf, size_t size)
+{
+       int ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
+       return ret + perf_evsel__add_modifiers(evsel, bf + ret, size - ret);
+}
+
+const char *perf_evsel__name(struct perf_evsel *evsel)
+{
+       char bf[128];
+
+       if (evsel->name)
+               return evsel->name;
 
        switch (evsel->attr.type) {
        case PERF_TYPE_RAW:
-               ret = scnprintf(bf, size, "raw 0x%" PRIx64, evsel->attr.config);
+               perf_evsel__raw_name(evsel, bf, sizeof(bf));
                break;
 
        case PERF_TYPE_HARDWARE:
-               ret = perf_evsel__hw_name(evsel, bf, size);
+               perf_evsel__hw_name(evsel, bf, sizeof(bf));
+               break;
+
+       case PERF_TYPE_HW_CACHE:
+               perf_evsel__hw_cache_name(evsel, bf, sizeof(bf));
+               break;
+
+       case PERF_TYPE_SOFTWARE:
+               perf_evsel__sw_name(evsel, bf, sizeof(bf));
                break;
+
+       case PERF_TYPE_TRACEPOINT:
+               scnprintf(bf, sizeof(bf), "%s", "unknown tracepoint");
+               break;
+
+       case PERF_TYPE_BREAKPOINT:
+               perf_evsel__bp_name(evsel, bf, sizeof(bf));
+               break;
+
        default:
-               /*
-                * FIXME
-                *
-                * This is the minimal perf_evsel__name so that we can
-                * reconstruct event names taking into account event modifiers.
-                *
-                * The old event_name uses it now for raw anr hw events, so that
-                * we don't drag all the parsing stuff into the python binding.
-                *
-                * On the next devel cycle the rest of the event naming will be
-                * brought here.
-                */
-               return 0;
-       }
-
-       return ret;
+               scnprintf(bf, sizeof(bf), "%s", "unknown attr type");
+               break;
+       }
+
+       evsel->name = strdup(bf);
+
+       return evsel->name ?: "unknown";
 }
 
 void perf_evsel__config(struct perf_evsel *evsel, struct perf_record_opts *opts,
index 4ba8b564e6f47f039652ebac739d9d899d5881f5..67cc5033d19234e28071523f51ecf7c7186822b1 100644 (file)
@@ -83,8 +83,19 @@ void perf_evsel__config(struct perf_evsel *evsel,
                        struct perf_record_opts *opts,
                        struct perf_evsel *first);
 
-const char* __perf_evsel__hw_name(u64 config);
-int perf_evsel__name(struct perf_evsel *evsel, char *bf, size_t size);
+bool perf_evsel__is_cache_op_valid(u8 type, u8 op);
+
+#define PERF_EVSEL__MAX_ALIASES 8
+
+extern const char *perf_evsel__hw_cache[PERF_COUNT_HW_CACHE_MAX]
+                                      [PERF_EVSEL__MAX_ALIASES];
+extern const char *perf_evsel__hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX]
+                                         [PERF_EVSEL__MAX_ALIASES];
+const char *perf_evsel__hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
+                                      [PERF_EVSEL__MAX_ALIASES];
+int __perf_evsel__hw_cache_type_op_res_name(u8 type, u8 op, u8 result,
+                                           char *bf, size_t size);
+const char *perf_evsel__name(struct perf_evsel *evsel);
 
 int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
 int perf_evsel__alloc_id(struct perf_evsel *evsel, int ncpus, int nthreads);
index e909d43cf5422333e4d47d2b412c1f3fa0b636af..5a47aba46759274f7f542e533bae4a62749d565a 100644 (file)
@@ -641,7 +641,7 @@ static int write_event_desc(int fd, struct perf_header *h __used,
                /*
                 * write event string as passed on cmdline
                 */
-               ret = do_write_string(fd, event_name(attr));
+               ret = do_write_string(fd, perf_evsel__name(attr));
                if (ret < 0)
                        return ret;
                /*
@@ -1474,15 +1474,15 @@ out:
 
 static int process_tracing_data(struct perf_file_section *section __unused,
                              struct perf_header *ph __unused,
-                             int feat __unused, int fd)
+                             int feat __unused, int fd, void *data)
 {
-       trace_report(fd, false);
+       trace_report(fd, data, false);
        return 0;
 }
 
 static int process_build_id(struct perf_file_section *section,
                            struct perf_header *ph,
-                           int feat __unused, int fd)
+                           int feat __unused, int fd, void *data __used)
 {
        if (perf_header__read_build_ids(ph, fd, section->offset, section->size))
                pr_debug("Failed to read buildids, continuing...\n");
@@ -1493,7 +1493,7 @@ struct feature_ops {
        int (*write)(int fd, struct perf_header *h, struct perf_evlist *evlist);
        void (*print)(struct perf_header *h, int fd, FILE *fp);
        int (*process)(struct perf_file_section *section,
-                      struct perf_header *h, int feat, int fd);
+                      struct perf_header *h, int feat, int fd, void *data);
        const char *name;
        bool full_only;
 };
@@ -1988,7 +1988,7 @@ int perf_file_header__read(struct perf_file_header *header,
 
 static int perf_file_section__process(struct perf_file_section *section,
                                      struct perf_header *ph,
-                                     int feat, int fd, void *data __used)
+                                     int feat, int fd, void *data)
 {
        if (lseek(fd, section->offset, SEEK_SET) == (off_t)-1) {
                pr_debug("Failed to lseek to %" PRIu64 " offset for feature "
@@ -2004,7 +2004,7 @@ static int perf_file_section__process(struct perf_file_section *section,
        if (!feat_ops[feat].process)
                return 0;
 
-       return feat_ops[feat].process(section, ph, feat, fd);
+       return feat_ops[feat].process(section, ph, feat, fd, data);
 }
 
 static int perf_file_header__read_pipe(struct perf_pipe_file_header *header,
@@ -2093,9 +2093,11 @@ static int read_attr(int fd, struct perf_header *ph,
        return ret <= 0 ? -1 : 0;
 }
 
-static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel)
+static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel,
+                                          struct pevent *pevent)
 {
-       struct event_format *event = trace_find_event(evsel->attr.config);
+       struct event_format *event = pevent_find_event(pevent,
+                                                      evsel->attr.config);
        char bf[128];
 
        if (event == NULL)
@@ -2109,13 +2111,14 @@ static int perf_evsel__set_tracepoint_name(struct perf_evsel *evsel)
        return 0;
 }
 
-static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist)
+static int perf_evlist__set_tracepoint_names(struct perf_evlist *evlist,
+                                            struct pevent *pevent)
 {
        struct perf_evsel *pos;
 
        list_for_each_entry(pos, &evlist->entries, node) {
                if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
-                   perf_evsel__set_tracepoint_name(pos))
+                   perf_evsel__set_tracepoint_name(pos, pevent))
                        return -1;
        }
 
@@ -2198,12 +2201,12 @@ int perf_session__read_header(struct perf_session *session, int fd)
                event_count =  f_header.event_types.size / sizeof(struct perf_trace_event_type);
        }
 
-       perf_header__process_sections(header, fd, NULL,
+       perf_header__process_sections(header, fd, &session->pevent,
                                      perf_file_section__process);
 
        lseek(fd, header->data_offset, SEEK_SET);
 
-       if (perf_evlist__set_tracepoint_names(session->evlist))
+       if (perf_evlist__set_tracepoint_names(session->evlist, session->pevent))
                goto out_delete_evlist;
 
        header->frozen = 1;
@@ -2419,8 +2422,8 @@ int perf_event__process_tracing_data(union perf_event *event,
        lseek(session->fd, offset + sizeof(struct tracing_data_event),
              SEEK_SET);
 
-       size_read = trace_report(session->fd, session->repipe);
-
+       size_read = trace_report(session->fd, &session->pevent,
+                                session->repipe);
        padding = ALIGN(size_read, sizeof(u64)) - size_read;
 
        if (read(session->fd, buf, padding) < 0)
index 34bb556d62191a1300b295011be6210f9633fcf7..0b096c27a419bb46969e75fe8590f65dbde149be 100644 (file)
@@ -47,6 +47,7 @@ enum hist_column {
        HISTC_SYMBOL_TO,
        HISTC_DSO_FROM,
        HISTC_DSO_TO,
+       HISTC_SRCLINE,
        HISTC_NR_COLS, /* Last entry */
 };
 
index 1eb804fd3fbff078baa9e70f57d850676607c1b9..b6842c1d02a8dfd6ed22da698e8e3cf65ff9a50c 100644 (file)
@@ -108,4 +108,14 @@ int eprintf(int level,
 #define pr_debug3(fmt, ...) pr_debugN(3, pr_fmt(fmt), ##__VA_ARGS__)
 #define pr_debug4(fmt, ...) pr_debugN(4, pr_fmt(fmt), ##__VA_ARGS__)
 
+/*
+ * This looks more complex than it should be. But we need to
+ * get the type for the ~ right in round_down (it needs to be
+ * as wide as the result!), and we want to evaluate the macro
+ * arguments just once each.
+ */
+#define __round_mask(x, y) ((__typeof__(x))((y)-1))
+#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
+#define round_down(x, y) ((x) & ~__round_mask(x, y))
+
 #endif
index 81371bad4ef0e43e1121b5b8c4367fe4d6b212d8..c14c665d9a259c8c5c9aed791a32f2096eff6bb0 100644 (file)
@@ -157,7 +157,7 @@ void machine__exit(struct machine *self);
 void machine__delete(struct machine *self);
 
 int machine__resolve_callchain(struct machine *machine,
-                              struct perf_evsel *evsel, struct thread *thread,
+                              struct thread *thread,
                               struct ip_callchain *chain,
                               struct symbol **parent);
 int maps__set_kallsyms_ref_reloc_sym(struct map **maps, const char *symbol_name,
index 76b98e2a587d7c8a52a1264d88aad3bdb6839831..1b997d2b89ce2638f63c01aee63c2b7884028427 100644 (file)
@@ -181,6 +181,22 @@ static int test__checkevent_breakpoint_w(struct perf_evlist *evlist)
        return 0;
 }
 
+static int test__checkevent_breakpoint_rw(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel = list_entry(evlist->entries.next,
+                                             struct perf_evsel, node);
+
+       TEST_ASSERT_VAL("wrong number of entries", 1 == evlist->nr_entries);
+       TEST_ASSERT_VAL("wrong type",
+                       PERF_TYPE_BREAKPOINT == evsel->attr.type);
+       TEST_ASSERT_VAL("wrong config", 0 == evsel->attr.config);
+       TEST_ASSERT_VAL("wrong bp_type",
+               (HW_BREAKPOINT_R|HW_BREAKPOINT_W) == evsel->attr.bp_type);
+       TEST_ASSERT_VAL("wrong bp_len",
+                       HW_BREAKPOINT_LEN_4 == evsel->attr.bp_len);
+       return 0;
+}
+
 static int test__checkevent_tracepoint_modifier(struct perf_evlist *evlist)
 {
        struct perf_evsel *evsel = list_entry(evlist->entries.next,
@@ -309,6 +325,8 @@ static int test__checkevent_breakpoint_modifier(struct perf_evlist *evlist)
        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong name",
+                       !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:u"));
 
        return test__checkevent_breakpoint(evlist);
 }
@@ -322,6 +340,8 @@ static int test__checkevent_breakpoint_x_modifier(struct perf_evlist *evlist)
        TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
        TEST_ASSERT_VAL("wrong precise_ip", !evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong name",
+                       !strcmp(perf_evsel__name(evsel), "mem:0x0:x:k"));
 
        return test__checkevent_breakpoint_x(evlist);
 }
@@ -335,6 +355,8 @@ static int test__checkevent_breakpoint_r_modifier(struct perf_evlist *evlist)
        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", !evsel->attr.exclude_hv);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong name",
+                       !strcmp(perf_evsel__name(evsel), "mem:0x0:r:hp"));
 
        return test__checkevent_breakpoint_r(evlist);
 }
@@ -348,10 +370,27 @@ static int test__checkevent_breakpoint_w_modifier(struct perf_evlist *evlist)
        TEST_ASSERT_VAL("wrong exclude_kernel", evsel->attr.exclude_kernel);
        TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
        TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong name",
+                       !strcmp(perf_evsel__name(evsel), "mem:0x0:w:up"));
 
        return test__checkevent_breakpoint_w(evlist);
 }
 
+static int test__checkevent_breakpoint_rw_modifier(struct perf_evlist *evlist)
+{
+       struct perf_evsel *evsel = list_entry(evlist->entries.next,
+                                             struct perf_evsel, node);
+
+       TEST_ASSERT_VAL("wrong exclude_user", evsel->attr.exclude_user);
+       TEST_ASSERT_VAL("wrong exclude_kernel", !evsel->attr.exclude_kernel);
+       TEST_ASSERT_VAL("wrong exclude_hv", evsel->attr.exclude_hv);
+       TEST_ASSERT_VAL("wrong precise_ip", evsel->attr.precise_ip);
+       TEST_ASSERT_VAL("wrong name",
+                       !strcmp(perf_evsel__name(evsel), "mem:0x0:rw:kp"));
+
+       return test__checkevent_breakpoint_rw(evlist);
+}
+
 static int test__checkevent_pmu(struct perf_evlist *evlist)
 {
 
@@ -413,19 +452,63 @@ static int test__checkevent_pmu_name(struct perf_evlist *evlist)
 {
        struct perf_evsel *evsel;
 
-       /* cpu/config=1,name=krava1/u */
+       /* cpu/config=1,name=krava/u */
        evsel = list_entry(evlist->entries.next, struct perf_evsel, node);
        TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
        TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
        TEST_ASSERT_VAL("wrong config",  1 == evsel->attr.config);
-       TEST_ASSERT_VAL("wrong name", !strcmp(evsel->name, "krava"));
+       TEST_ASSERT_VAL("wrong name", !strcmp(perf_evsel__name(evsel), "krava"));
 
-       /* cpu/config=2/" */
+       /* cpu/config=2/u" */
        evsel = list_entry(evsel->node.next, struct perf_evsel, node);
        TEST_ASSERT_VAL("wrong number of entries", 2 == evlist->nr_entries);
        TEST_ASSERT_VAL("wrong type", PERF_TYPE_RAW == evsel->attr.type);
        TEST_ASSERT_VAL("wrong config",  2 == evsel->attr.config);
-       TEST_ASSERT_VAL("wrong name", !strcmp(evsel->name, "raw 0x2"));
+       TEST_ASSERT_VAL("wrong name",
+                       !strcmp(perf_evsel__name(evsel), "raw 0x2:u"));
+
+       return 0;
+}
+
+static int test__checkterms_simple(struct list_head *terms)
+{
+       struct parse_events__term *term;
+
+       /* config=10 */
+       term = list_entry(terms->next, struct parse_events__term, list);
+       TEST_ASSERT_VAL("wrong type term",
+                       term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG);
+       TEST_ASSERT_VAL("wrong type val",
+                       term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
+       TEST_ASSERT_VAL("wrong val", term->val.num == 10);
+       TEST_ASSERT_VAL("wrong config", !term->config);
+
+       /* config1 */
+       term = list_entry(term->list.next, struct parse_events__term, list);
+       TEST_ASSERT_VAL("wrong type term",
+                       term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG1);
+       TEST_ASSERT_VAL("wrong type val",
+                       term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
+       TEST_ASSERT_VAL("wrong val", term->val.num == 1);
+       TEST_ASSERT_VAL("wrong config", !term->config);
+
+       /* config2=3 */
+       term = list_entry(term->list.next, struct parse_events__term, list);
+       TEST_ASSERT_VAL("wrong type term",
+                       term->type_term == PARSE_EVENTS__TERM_TYPE_CONFIG2);
+       TEST_ASSERT_VAL("wrong type val",
+                       term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
+       TEST_ASSERT_VAL("wrong val", term->val.num == 3);
+       TEST_ASSERT_VAL("wrong config", !term->config);
+
+       /* umask=1*/
+       term = list_entry(term->list.next, struct parse_events__term, list);
+       TEST_ASSERT_VAL("wrong type term",
+                       term->type_term == PARSE_EVENTS__TERM_TYPE_USER);
+       TEST_ASSERT_VAL("wrong type val",
+                       term->type_val == PARSE_EVENTS__TERM_TYPE_NUM);
+       TEST_ASSERT_VAL("wrong val", term->val.num == 1);
+       TEST_ASSERT_VAL("wrong config", !strcmp(term->config, "umask"));
 
        return 0;
 }
@@ -541,10 +624,16 @@ static struct test__event_st test__events[] = {
                .name  = "instructions:H",
                .check = test__checkevent_exclude_guest_modifier,
        },
+       [26] = {
+               .name  = "mem:0:rw",
+               .check = test__checkevent_breakpoint_rw,
+       },
+       [27] = {
+               .name  = "mem:0:rw:kp",
+               .check = test__checkevent_breakpoint_rw_modifier,
+       },
 };
 
-#define TEST__EVENTS_CNT (sizeof(test__events) / sizeof(struct test__event_st))
-
 static struct test__event_st test__events_pmu[] = {
        [0] = {
                .name  = "cpu/config=10,config1,config2=3,period=1000/u",
@@ -556,10 +645,23 @@ static struct test__event_st test__events_pmu[] = {
        },
 };
 
-#define TEST__EVENTS_PMU_CNT (sizeof(test__events_pmu) / \
-                             sizeof(struct test__event_st))
+struct test__term {
+       const char *str;
+       __u32 type;
+       int (*check)(struct list_head *terms);
+};
+
+static struct test__term test__terms[] = {
+       [0] = {
+               .str   = "config=10,config1,config2=3,umask=1",
+               .check = test__checkterms_simple,
+       },
+};
+
+#define TEST__TERMS_CNT (sizeof(test__terms) / \
+                        sizeof(struct test__term))
 
-static int test(struct test__event_st *e)
+static int test_event(struct test__event_st *e)
 {
        struct perf_evlist *evlist;
        int ret;
@@ -590,7 +692,48 @@ static int test_events(struct test__event_st *events, unsigned cnt)
                struct test__event_st *e = &events[i];
 
                pr_debug("running test %d '%s'\n", i, e->name);
-               ret = test(e);
+               ret = test_event(e);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+}
+
+static int test_term(struct test__term *t)
+{
+       struct list_head *terms;
+       int ret;
+
+       terms = malloc(sizeof(*terms));
+       if (!terms)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(terms);
+
+       ret = parse_events_terms(terms, t->str);
+       if (ret) {
+               pr_debug("failed to parse terms '%s', err %d\n",
+                        t->str , ret);
+               return ret;
+       }
+
+       ret = t->check(terms);
+       parse_events__free_terms(terms);
+
+       return ret;
+}
+
+static int test_terms(struct test__term *terms, unsigned cnt)
+{
+       int ret = 0;
+       unsigned i;
+
+       for (i = 0; i < cnt; i++) {
+               struct test__term *t = &terms[i];
+
+               pr_debug("running test %d '%s'\n", i, t->str);
+               ret = test_term(t);
                if (ret)
                        break;
        }
@@ -617,9 +760,17 @@ int parse_events__test(void)
 {
        int ret;
 
-       ret = test_events(test__events, TEST__EVENTS_CNT);
-       if (!ret && test_pmu())
-               ret = test_events(test__events_pmu, TEST__EVENTS_PMU_CNT);
+#define TEST_EVENTS(tests)                             \
+do {                                                   \
+       ret = test_events(tests, ARRAY_SIZE(tests));    \
+       if (ret)                                        \
+               return ret;                             \
+} while (0)
 
-       return ret;
+       TEST_EVENTS(test__events);
+
+       if (test_pmu())
+               TEST_EVENTS(test__events_pmu);
+
+       return test_terms(test__terms, ARRAY_SIZE(test__terms));
 }
index 05dbc8b3c767217ceb3204c7be46f5aedbb205c4..1aa721d7c10f33d84bbd63f8761ed67f18fbe86c 100644 (file)
 #include "cache.h"
 #include "header.h"
 #include "debugfs.h"
+#include "parse-events-bison.h"
+#define YY_EXTRA_TYPE int
 #include "parse-events-flex.h"
 #include "pmu.h"
 
 #define MAX_NAME_LEN 100
 
 struct event_symbol {
-       u8              type;
-       u64             config;
        const char      *symbol;
        const char      *alias;
 };
@@ -26,32 +26,88 @@ struct event_symbol {
 #ifdef PARSER_DEBUG
 extern int parse_events_debug;
 #endif
-int parse_events_parse(struct list_head *list, int *idx);
-
-#define CHW(x) .type = PERF_TYPE_HARDWARE, .config = PERF_COUNT_HW_##x
-#define CSW(x) .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_##x
-
-static struct event_symbol event_symbols[] = {
-  { CHW(CPU_CYCLES),                   "cpu-cycles",                   "cycles"                },
-  { CHW(STALLED_CYCLES_FRONTEND),      "stalled-cycles-frontend",      "idle-cycles-frontend"  },
-  { CHW(STALLED_CYCLES_BACKEND),       "stalled-cycles-backend",       "idle-cycles-backend"   },
-  { CHW(INSTRUCTIONS),                 "instructions",                 ""                      },
-  { CHW(CACHE_REFERENCES),             "cache-references",             ""                      },
-  { CHW(CACHE_MISSES),                 "cache-misses",                 ""                      },
-  { CHW(BRANCH_INSTRUCTIONS),          "branch-instructions",          "branches"              },
-  { CHW(BRANCH_MISSES),                        "branch-misses",                ""                      },
-  { CHW(BUS_CYCLES),                   "bus-cycles",                   ""                      },
-  { CHW(REF_CPU_CYCLES),               "ref-cycles",                   ""                      },
-
-  { CSW(CPU_CLOCK),                    "cpu-clock",                    ""                      },
-  { CSW(TASK_CLOCK),                   "task-clock",                   ""                      },
-  { CSW(PAGE_FAULTS),                  "page-faults",                  "faults"                },
-  { CSW(PAGE_FAULTS_MIN),              "minor-faults",                 ""                      },
-  { CSW(PAGE_FAULTS_MAJ),              "major-faults",                 ""                      },
-  { CSW(CONTEXT_SWITCHES),             "context-switches",             "cs"                    },
-  { CSW(CPU_MIGRATIONS),               "cpu-migrations",               "migrations"            },
-  { CSW(ALIGNMENT_FAULTS),             "alignment-faults",             ""                      },
-  { CSW(EMULATION_FAULTS),             "emulation-faults",             ""                      },
+int parse_events_parse(void *data, void *scanner);
+
+static struct event_symbol event_symbols_hw[PERF_COUNT_HW_MAX] = {
+       [PERF_COUNT_HW_CPU_CYCLES] = {
+               .symbol = "cpu-cycles",
+               .alias  = "cycles",
+       },
+       [PERF_COUNT_HW_INSTRUCTIONS] = {
+               .symbol = "instructions",
+               .alias  = "",
+       },
+       [PERF_COUNT_HW_CACHE_REFERENCES] = {
+               .symbol = "cache-references",
+               .alias  = "",
+       },
+       [PERF_COUNT_HW_CACHE_MISSES] = {
+               .symbol = "cache-misses",
+               .alias  = "",
+       },
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = {
+               .symbol = "branch-instructions",
+               .alias  = "branches",
+       },
+       [PERF_COUNT_HW_BRANCH_MISSES] = {
+               .symbol = "branch-misses",
+               .alias  = "",
+       },
+       [PERF_COUNT_HW_BUS_CYCLES] = {
+               .symbol = "bus-cycles",
+               .alias  = "",
+       },
+       [PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = {
+               .symbol = "stalled-cycles-frontend",
+               .alias  = "idle-cycles-frontend",
+       },
+       [PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = {
+               .symbol = "stalled-cycles-backend",
+               .alias  = "idle-cycles-backend",
+       },
+       [PERF_COUNT_HW_REF_CPU_CYCLES] = {
+               .symbol = "ref-cycles",
+               .alias  = "",
+       },
+};
+
+static struct event_symbol event_symbols_sw[PERF_COUNT_SW_MAX] = {
+       [PERF_COUNT_SW_CPU_CLOCK] = {
+               .symbol = "cpu-clock",
+               .alias  = "",
+       },
+       [PERF_COUNT_SW_TASK_CLOCK] = {
+               .symbol = "task-clock",
+               .alias  = "",
+       },
+       [PERF_COUNT_SW_PAGE_FAULTS] = {
+               .symbol = "page-faults",
+               .alias  = "faults",
+       },
+       [PERF_COUNT_SW_CONTEXT_SWITCHES] = {
+               .symbol = "context-switches",
+               .alias  = "cs",
+       },
+       [PERF_COUNT_SW_CPU_MIGRATIONS] = {
+               .symbol = "cpu-migrations",
+               .alias  = "migrations",
+       },
+       [PERF_COUNT_SW_PAGE_FAULTS_MIN] = {
+               .symbol = "minor-faults",
+               .alias  = "",
+       },
+       [PERF_COUNT_SW_PAGE_FAULTS_MAJ] = {
+               .symbol = "major-faults",
+               .alias  = "",
+       },
+       [PERF_COUNT_SW_ALIGNMENT_FAULTS] = {
+               .symbol = "alignment-faults",
+               .alias  = "",
+       },
+       [PERF_COUNT_SW_EMULATION_FAULTS] = {
+               .symbol = "emulation-faults",
+               .alias  = "",
+       },
 };
 
 #define __PERF_EVENT_FIELD(config, name) \
@@ -62,63 +118,6 @@ static struct event_symbol event_symbols[] = {
 #define PERF_EVENT_TYPE(config)                __PERF_EVENT_FIELD(config, TYPE)
 #define PERF_EVENT_ID(config)          __PERF_EVENT_FIELD(config, EVENT)
 
-static const char *sw_event_names[PERF_COUNT_SW_MAX] = {
-       "cpu-clock",
-       "task-clock",
-       "page-faults",
-       "context-switches",
-       "CPU-migrations",
-       "minor-faults",
-       "major-faults",
-       "alignment-faults",
-       "emulation-faults",
-};
-
-#define MAX_ALIASES 8
-
-static const char *hw_cache[PERF_COUNT_HW_CACHE_MAX][MAX_ALIASES] = {
- { "L1-dcache",        "l1-d",         "l1d",          "L1-data",              },
- { "L1-icache",        "l1-i",         "l1i",          "L1-instruction",       },
- { "LLC",      "L2",                                                   },
- { "dTLB",     "d-tlb",        "Data-TLB",                             },
- { "iTLB",     "i-tlb",        "Instruction-TLB",                      },
- { "branch",   "branches",     "bpu",          "btb",          "bpc",  },
- { "node",                                                             },
-};
-
-static const char *hw_cache_op[PERF_COUNT_HW_CACHE_OP_MAX][MAX_ALIASES] = {
- { "load",     "loads",        "read",                                 },
- { "store",    "stores",       "write",                                },
- { "prefetch", "prefetches",   "speculative-read", "speculative-load", },
-};
-
-static const char *hw_cache_result[PERF_COUNT_HW_CACHE_RESULT_MAX]
-                                 [MAX_ALIASES] = {
- { "refs",     "Reference",    "ops",          "access",               },
- { "misses",   "miss",                                                 },
-};
-
-#define C(x)           PERF_COUNT_HW_CACHE_##x
-#define CACHE_READ     (1 << C(OP_READ))
-#define CACHE_WRITE    (1 << C(OP_WRITE))
-#define CACHE_PREFETCH (1 << C(OP_PREFETCH))
-#define COP(x)         (1 << x)
-
-/*
- * cache operartion stat
- * L1I : Read and prefetch only
- * ITLB and BPU : Read-only
- */
-static unsigned long hw_cache_stat[C(MAX)] = {
- [C(L1D)]      = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
- [C(L1I)]      = (CACHE_READ | CACHE_PREFETCH),
- [C(LL)]       = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
- [C(DTLB)]     = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
- [C(ITLB)]     = (CACHE_READ),
- [C(BPU)]      = (CACHE_READ),
- [C(NODE)]     = (CACHE_READ | CACHE_WRITE | CACHE_PREFETCH),
-};
-
 #define for_each_subsystem(sys_dir, sys_dirent, sys_next)             \
        while (!readdir_r(sys_dir, &sys_dirent, &sys_next) && sys_next)        \
        if (sys_dirent.d_type == DT_DIR &&                                     \
@@ -218,48 +217,6 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config)
        return NULL;
 }
 
-#define TP_PATH_LEN (MAX_EVENT_LENGTH * 2 + 1)
-static const char *tracepoint_id_to_name(u64 config)
-{
-       static char buf[TP_PATH_LEN];
-       struct tracepoint_path *path;
-
-       path = tracepoint_id_to_path(config);
-       if (path) {
-               snprintf(buf, TP_PATH_LEN, "%s:%s", path->system, path->name);
-               free(path->name);
-               free(path->system);
-               free(path);
-       } else
-               snprintf(buf, TP_PATH_LEN, "%s:%s", "unknown", "unknown");
-
-       return buf;
-}
-
-static int is_cache_op_valid(u8 cache_type, u8 cache_op)
-{
-       if (hw_cache_stat[cache_type] & COP(cache_op))
-               return 1;       /* valid */
-       else
-               return 0;       /* invalid */
-}
-
-static char *event_cache_name(u8 cache_type, u8 cache_op, u8 cache_result)
-{
-       static char name[50];
-
-       if (cache_result) {
-               sprintf(name, "%s-%s-%s", hw_cache[cache_type][0],
-                       hw_cache_op[cache_op][0],
-                       hw_cache_result[cache_result][0]);
-       } else {
-               sprintf(name, "%s-%s", hw_cache[cache_type][0],
-                       hw_cache_op[cache_op][1]);
-       }
-
-       return name;
-}
-
 const char *event_type(int type)
 {
        switch (type) {
@@ -282,76 +239,6 @@ const char *event_type(int type)
        return "unknown";
 }
 
-const char *event_name(struct perf_evsel *evsel)
-{
-       u64 config = evsel->attr.config;
-       int type = evsel->attr.type;
-
-       if (type == PERF_TYPE_RAW || type == PERF_TYPE_HARDWARE) {
-               /*
-                * XXX minimal fix, see comment on perf_evsen__name, this static buffer
-                * will go away together with event_name in the next devel cycle.
-                */
-               static char bf[128];
-               perf_evsel__name(evsel, bf, sizeof(bf));
-               return bf;
-       }
-
-       if (evsel->name)
-               return evsel->name;
-
-       return __event_name(type, config);
-}
-
-const char *__event_name(int type, u64 config)
-{
-       static char buf[32];
-
-       if (type == PERF_TYPE_RAW) {
-               sprintf(buf, "raw 0x%" PRIx64, config);
-               return buf;
-       }
-
-       switch (type) {
-       case PERF_TYPE_HARDWARE:
-               return __perf_evsel__hw_name(config);
-
-       case PERF_TYPE_HW_CACHE: {
-               u8 cache_type, cache_op, cache_result;
-
-               cache_type   = (config >>  0) & 0xff;
-               if (cache_type > PERF_COUNT_HW_CACHE_MAX)
-                       return "unknown-ext-hardware-cache-type";
-
-               cache_op     = (config >>  8) & 0xff;
-               if (cache_op > PERF_COUNT_HW_CACHE_OP_MAX)
-                       return "unknown-ext-hardware-cache-op";
-
-               cache_result = (config >> 16) & 0xff;
-               if (cache_result > PERF_COUNT_HW_CACHE_RESULT_MAX)
-                       return "unknown-ext-hardware-cache-result";
-
-               if (!is_cache_op_valid(cache_type, cache_op))
-                       return "invalid-cache";
-
-               return event_cache_name(cache_type, cache_op, cache_result);
-       }
-
-       case PERF_TYPE_SOFTWARE:
-               if (config < PERF_COUNT_SW_MAX && sw_event_names[config])
-                       return sw_event_names[config];
-               return "unknown-software";
-
-       case PERF_TYPE_TRACEPOINT:
-               return tracepoint_id_to_name(config);
-
-       default:
-               break;
-       }
-
-       return "unknown";
-}
-
 static int add_event(struct list_head **_list, int *idx,
                     struct perf_event_attr *attr, char *name)
 {
@@ -373,19 +260,20 @@ static int add_event(struct list_head **_list, int *idx,
                return -ENOMEM;
        }
 
-       evsel->name = strdup(name);
+       if (name)
+               evsel->name = strdup(name);
        list_add_tail(&evsel->node, list);
        *_list = list;
        return 0;
 }
 
-static int parse_aliases(char *str, const char *names[][MAX_ALIASES], int size)
+static int parse_aliases(char *str, const char *names[][PERF_EVSEL__MAX_ALIASES], int size)
 {
        int i, j;
        int n, longest = -1;
 
        for (i = 0; i < size; i++) {
-               for (j = 0; j < MAX_ALIASES && names[i][j]; j++) {
+               for (j = 0; j < PERF_EVSEL__MAX_ALIASES && names[i][j]; j++) {
                        n = strlen(names[i][j]);
                        if (n > longest && !strncasecmp(str, names[i][j], n))
                                longest = n;
@@ -410,7 +298,7 @@ int parse_events_add_cache(struct list_head **list, int *idx,
         * No fallback - if we cannot get a clear cache type
         * then bail out:
         */
-       cache_type = parse_aliases(type, hw_cache,
+       cache_type = parse_aliases(type, perf_evsel__hw_cache,
                                   PERF_COUNT_HW_CACHE_MAX);
        if (cache_type == -1)
                return -EINVAL;
@@ -423,18 +311,18 @@ int parse_events_add_cache(struct list_head **list, int *idx,
                snprintf(name + n, MAX_NAME_LEN - n, "-%s\n", str);
 
                if (cache_op == -1) {
-                       cache_op = parse_aliases(str, hw_cache_op,
+                       cache_op = parse_aliases(str, perf_evsel__hw_cache_op,
                                                 PERF_COUNT_HW_CACHE_OP_MAX);
                        if (cache_op >= 0) {
-                               if (!is_cache_op_valid(cache_type, cache_op))
+                               if (!perf_evsel__is_cache_op_valid(cache_type, cache_op))
                                        return -EINVAL;
                                continue;
                        }
                }
 
                if (cache_result == -1) {
-                       cache_result = parse_aliases(str, hw_cache_result,
-                                               PERF_COUNT_HW_CACHE_RESULT_MAX);
+                       cache_result = parse_aliases(str, perf_evsel__hw_cache_result,
+                                                    PERF_COUNT_HW_CACHE_RESULT_MAX);
                        if (cache_result >= 0)
                                continue;
                }
@@ -549,21 +437,31 @@ parse_breakpoint_type(const char *type, struct perf_event_attr *attr)
                if (!type || !type[i])
                        break;
 
+#define CHECK_SET_TYPE(bit)            \
+do {                                   \
+       if (attr->bp_type & bit)        \
+               return -EINVAL;         \
+       else                            \
+               attr->bp_type |= bit;   \
+} while (0)
+
                switch (type[i]) {
                case 'r':
-                       attr->bp_type |= HW_BREAKPOINT_R;
+                       CHECK_SET_TYPE(HW_BREAKPOINT_R);
                        break;
                case 'w':
-                       attr->bp_type |= HW_BREAKPOINT_W;
+                       CHECK_SET_TYPE(HW_BREAKPOINT_W);
                        break;
                case 'x':
-                       attr->bp_type |= HW_BREAKPOINT_X;
+                       CHECK_SET_TYPE(HW_BREAKPOINT_X);
                        break;
                default:
                        return -EINVAL;
                }
        }
 
+#undef CHECK_SET_TYPE
+
        if (!attr->bp_type) /* Default */
                attr->bp_type = HW_BREAKPOINT_R | HW_BREAKPOINT_W;
 
@@ -574,7 +472,6 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
                                void *ptr, char *type)
 {
        struct perf_event_attr attr;
-       char name[MAX_NAME_LEN];
 
        memset(&attr, 0, sizeof(attr));
        attr.bp_addr = (unsigned long) ptr;
@@ -593,8 +490,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
 
        attr.type = PERF_TYPE_BREAKPOINT;
 
-       snprintf(name, MAX_NAME_LEN, "mem:%p:%s", ptr, type ? type : "rw");
-       return add_event(list, idx, &attr, name);
+       return add_event(list, idx, &attr, NULL);
 }
 
 static int config_term(struct perf_event_attr *attr,
@@ -666,8 +562,7 @@ int parse_events_add_numeric(struct list_head **list, int *idx,
            config_attr(&attr, head_config, 1))
                return -EINVAL;
 
-       return add_event(list, idx, &attr,
-                        (char *) __event_name(type, config));
+       return add_event(list, idx, &attr, NULL);
 }
 
 static int parse_events__is_name_term(struct parse_events__term *term)
@@ -675,8 +570,7 @@ static int parse_events__is_name_term(struct parse_events__term *term)
        return term->type_term == PARSE_EVENTS__TERM_TYPE_NAME;
 }
 
-static char *pmu_event_name(struct perf_event_attr *attr,
-                           struct list_head *head_terms)
+static char *pmu_event_name(struct list_head *head_terms)
 {
        struct parse_events__term *term;
 
@@ -684,7 +578,7 @@ static char *pmu_event_name(struct perf_event_attr *attr,
                if (parse_events__is_name_term(term))
                        return term->val.str;
 
-       return (char *) __event_name(PERF_TYPE_RAW, attr->config);
+       return NULL;
 }
 
 int parse_events_add_pmu(struct list_head **list, int *idx,
@@ -699,6 +593,9 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
 
        memset(&attr, 0, sizeof(attr));
 
+       if (perf_pmu__check_alias(pmu, head_config))
+               return -EINVAL;
+
        /*
         * Configure hardcoded terms first, no need to check
         * return value when called with fail == 0 ;)
@@ -709,7 +606,7 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
                return -EINVAL;
 
        return add_event(list, idx, &attr,
-                        pmu_event_name(&attr, head_config));
+                        pmu_event_name(head_config));
 }
 
 void parse_events_update_lists(struct list_head *list_event,
@@ -787,27 +684,62 @@ int parse_events_modifier(struct list_head *list, char *str)
        return 0;
 }
 
-int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
+static int parse_events__scanner(const char *str, void *data, int start_token)
 {
-       LIST_HEAD(list);
-       LIST_HEAD(list_tmp);
        YY_BUFFER_STATE buffer;
-       int ret, idx = evlist->nr_entries;
+       void *scanner;
+       int ret;
+
+       ret = parse_events_lex_init_extra(start_token, &scanner);
+       if (ret)
+               return ret;
 
-       buffer = parse_events__scan_string(str);
+       buffer = parse_events__scan_string(str, scanner);
 
 #ifdef PARSER_DEBUG
        parse_events_debug = 1;
 #endif
-       ret = parse_events_parse(&list, &idx);
+       ret = parse_events_parse(data, scanner);
 
-       parse_events__flush_buffer(buffer);
-       parse_events__delete_buffer(buffer);
-       parse_events_lex_destroy();
+       parse_events__flush_buffer(buffer, scanner);
+       parse_events__delete_buffer(buffer, scanner);
+       parse_events_lex_destroy(scanner);
+       return ret;
+}
+
+/*
+ * parse event config string, return a list of event terms.
+ */
+int parse_events_terms(struct list_head *terms, const char *str)
+{
+       struct parse_events_data__terms data = {
+               .terms = NULL,
+       };
+       int ret;
 
+       ret = parse_events__scanner(str, &data, PE_START_TERMS);
        if (!ret) {
-               int entries = idx - evlist->nr_entries;
-               perf_evlist__splice_list_tail(evlist, &list, entries);
+               list_splice(data.terms, terms);
+               free(data.terms);
+               return 0;
+       }
+
+       parse_events__free_terms(data.terms);
+       return ret;
+}
+
+int parse_events(struct perf_evlist *evlist, const char *str, int unset __used)
+{
+       struct parse_events_data__events data = {
+               .list = LIST_HEAD_INIT(data.list),
+               .idx  = evlist->nr_entries,
+       };
+       int ret;
+
+       ret = parse_events__scanner(str, &data, PE_START_EVENTS);
+       if (!ret) {
+               int entries = data.idx - evlist->nr_entries;
+               perf_evlist__splice_list_tail(evlist, &data.list, entries);
                return 0;
        }
 
@@ -946,16 +878,13 @@ int is_valid_tracepoint(const char *event_string)
        return 0;
 }
 
-void print_events_type(u8 type)
+static void __print_events_type(u8 type, struct event_symbol *syms,
+                               unsigned max)
 {
-       struct event_symbol *syms = event_symbols;
-       unsigned int i;
        char name[64];
+       unsigned i;
 
-       for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
-               if (type != syms->type)
-                       continue;
-
+       for (i = 0; i < max ; i++, syms++) {
                if (strlen(syms->alias))
                        snprintf(name, sizeof(name),  "%s OR %s",
                                 syms->symbol, syms->alias);
@@ -967,19 +896,28 @@ void print_events_type(u8 type)
        }
 }
 
+void print_events_type(u8 type)
+{
+       if (type == PERF_TYPE_SOFTWARE)
+               __print_events_type(type, event_symbols_sw, PERF_COUNT_SW_MAX);
+       else
+               __print_events_type(type, event_symbols_hw, PERF_COUNT_HW_MAX);
+}
+
 int print_hwcache_events(const char *event_glob)
 {
        unsigned int type, op, i, printed = 0;
+       char name[64];
 
        for (type = 0; type < PERF_COUNT_HW_CACHE_MAX; type++) {
                for (op = 0; op < PERF_COUNT_HW_CACHE_OP_MAX; op++) {
                        /* skip invalid cache type */
-                       if (!is_cache_op_valid(type, op))
+                       if (!perf_evsel__is_cache_op_valid(type, op))
                                continue;
 
                        for (i = 0; i < PERF_COUNT_HW_CACHE_RESULT_MAX; i++) {
-                               char *name = event_cache_name(type, op, i);
-
+                               __perf_evsel__hw_cache_type_op_res_name(type, op, i,
+                                                                       name, sizeof(name));
                                if (event_glob != NULL && !strglobmatch(name, event_glob))
                                        continue;
 
@@ -993,26 +931,13 @@ int print_hwcache_events(const char *event_glob)
        return printed;
 }
 
-/*
- * Print the help text for the event symbols:
- */
-void print_events(const char *event_glob)
+static void print_symbol_events(const char *event_glob, unsigned type,
+                               struct event_symbol *syms, unsigned max)
 {
-       unsigned int i, type, prev_type = -1, printed = 0, ntypes_printed = 0;
-       struct event_symbol *syms = event_symbols;
+       unsigned i, printed = 0;
        char name[MAX_NAME_LEN];
 
-       printf("\n");
-       printf("List of pre-defined events (to be used in -e):\n");
-
-       for (i = 0; i < ARRAY_SIZE(event_symbols); i++, syms++) {
-               type = syms->type;
-
-               if (type != prev_type && printed) {
-                       printf("\n");
-                       printed = 0;
-                       ntypes_printed++;
-               }
+       for (i = 0; i < max; i++, syms++) {
 
                if (event_glob != NULL && 
                    !(strglobmatch(syms->symbol, event_glob) ||
@@ -1023,17 +948,31 @@ void print_events(const char *event_glob)
                        snprintf(name, MAX_NAME_LEN, "%s OR %s", syms->symbol, syms->alias);
                else
                        strncpy(name, syms->symbol, MAX_NAME_LEN);
-               printf("  %-50s [%s]\n", name,
-                       event_type_descriptors[type]);
 
-               prev_type = type;
-               ++printed;
+               printf("  %-50s [%s]\n", name, event_type_descriptors[type]);
+
+               printed++;
        }
 
-       if (ntypes_printed) {
-               printed = 0;
+       if (printed)
                printf("\n");
-       }
+}
+
+/*
+ * Print the help text for the event symbols:
+ */
+void print_events(const char *event_glob)
+{
+
+       printf("\n");
+       printf("List of pre-defined events (to be used in -e):\n");
+
+       print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
+                           event_symbols_hw, PERF_COUNT_HW_MAX);
+
+       print_symbol_events(event_glob, PERF_TYPE_SOFTWARE,
+                           event_symbols_sw, PERF_COUNT_SW_MAX);
+
        print_hwcache_events(event_glob);
 
        if (event_glob != NULL)
@@ -1106,6 +1045,13 @@ int parse_events__term_str(struct parse_events__term **term,
                        config, str, 0);
 }
 
+int parse_events__term_clone(struct parse_events__term **new,
+                            struct parse_events__term *term)
+{
+       return new_term(new, term->type_val, term->type_term, term->config,
+                       term->val.str, term->val.num);
+}
+
 void parse_events__free_terms(struct list_head *terms)
 {
        struct parse_events__term *term, *h;
index 8cac57ab4ee6b396549a4ee857486effedb9343b..ee9c218a193c8d8c8b20f893da976d262931e172 100644 (file)
@@ -26,13 +26,12 @@ extern struct tracepoint_path *tracepoint_id_to_path(u64 config);
 extern bool have_tracepoints(struct list_head *evlist);
 
 const char *event_type(int type);
-const char *event_name(struct perf_evsel *event);
-extern const char *__event_name(int type, u64 config);
 
 extern int parse_events_option(const struct option *opt, const char *str,
                               int unset);
 extern int parse_events(struct perf_evlist *evlist, const char *str,
                        int unset);
+extern int parse_events_terms(struct list_head *terms, const char *str);
 extern int parse_filter(const struct option *opt, const char *str, int unset);
 
 #define EVENTS_HELP_MAX (128*1024)
@@ -63,11 +62,22 @@ struct parse_events__term {
        struct list_head list;
 };
 
+struct parse_events_data__events {
+       struct list_head list;
+       int idx;
+};
+
+struct parse_events_data__terms {
+       struct list_head *terms;
+};
+
 int parse_events__is_hardcoded_term(struct parse_events__term *term);
 int parse_events__term_num(struct parse_events__term **_term,
                           int type_term, char *config, long num);
 int parse_events__term_str(struct parse_events__term **_term,
                           int type_term, char *config, char *str);
+int parse_events__term_clone(struct parse_events__term **new,
+                            struct parse_events__term *term);
 void parse_events__free_terms(struct list_head *terms);
 int parse_events_modifier(struct list_head *list, char *str);
 int parse_events_add_tracepoint(struct list_head **list, int *idx,
@@ -83,8 +93,7 @@ int parse_events_add_pmu(struct list_head **list, int *idx,
                         char *pmu , struct list_head *head_config);
 void parse_events_update_lists(struct list_head *list_event,
                               struct list_head *list_all);
-void parse_events_error(struct list_head *list_all,
-                       int *idx, char const *msg);
+void parse_events_error(void *data, void *scanner, char const *msg);
 int parse_events__test(void);
 
 void print_events(const char *event_glob);
index 618a8e7883995bbee72f4b90c6d5e55a012f05f1..384ca74c6b22d442ad74b23d70dd3598a4e7208a 100644 (file)
@@ -1,4 +1,6 @@
 
+%option reentrant
+%option bison-bridge
 %option prefix="parse_events_"
 %option stack
 
@@ -8,7 +10,10 @@
 #include "parse-events-bison.h"
 #include "parse-events.h"
 
-static int __value(char *str, int base, int token)
+char *parse_events_get_text(yyscan_t yyscanner);
+YYSTYPE *parse_events_get_lval(yyscan_t yyscanner);
+
+static int __value(YYSTYPE *yylval, char *str, int base, int token)
 {
        long num;
 
@@ -17,35 +22,48 @@ static int __value(char *str, int base, int token)
        if (errno)
                return PE_ERROR;
 
-       parse_events_lval.num = num;
+       yylval->num = num;
        return token;
 }
 
-static int value(int base)
+static int value(yyscan_t scanner, int base)
 {
-       return __value(parse_events_text, base, PE_VALUE);
+       YYSTYPE *yylval = parse_events_get_lval(scanner);
+       char *text = parse_events_get_text(scanner);
+
+       return __value(yylval, text, base, PE_VALUE);
 }
 
-static int raw(void)
+static int raw(yyscan_t scanner)
 {
-       return __value(parse_events_text + 1, 16, PE_RAW);
+       YYSTYPE *yylval = parse_events_get_lval(scanner);
+       char *text = parse_events_get_text(scanner);
+
+       return __value(yylval, text + 1, 16, PE_RAW);
 }
 
-static int str(int token)
+static int str(yyscan_t scanner, int token)
 {
-       parse_events_lval.str = strdup(parse_events_text);
+       YYSTYPE *yylval = parse_events_get_lval(scanner);
+       char *text = parse_events_get_text(scanner);
+
+       yylval->str = strdup(text);
        return token;
 }
 
-static int sym(int type, int config)
+static int sym(yyscan_t scanner, int type, int config)
 {
-       parse_events_lval.num = (type << 16) + config;
-       return PE_VALUE_SYM;
+       YYSTYPE *yylval = parse_events_get_lval(scanner);
+
+       yylval->num = (type << 16) + config;
+       return type == PERF_TYPE_HARDWARE ? PE_VALUE_SYM_HW : PE_VALUE_SYM_SW;
 }
 
-static int term(int type)
+static int term(yyscan_t scanner, int type)
 {
-       parse_events_lval.num = type;
+       YYSTYPE *yylval = parse_events_get_lval(scanner);
+
+       yylval->num = type;
        return PE_TERM;
 }
 
@@ -58,28 +76,41 @@ num_hex             0x[a-fA-F0-9]+
 num_raw_hex    [a-fA-F0-9]+
 name           [a-zA-Z_*?][a-zA-Z0-9_*?]*
 modifier_event [ukhpGH]{1,8}
-modifier_bp    [rwx]
+modifier_bp    [rwx]{1,3}
 
 %%
-cpu-cycles|cycles                              { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
-stalled-cycles-frontend|idle-cycles-frontend   { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
-stalled-cycles-backend|idle-cycles-backend     { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
-instructions                                   { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
-cache-references                               { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
-cache-misses                                   { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
-branch-instructions|branches                   { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
-branch-misses                                  { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
-bus-cycles                                     { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
-ref-cycles                                     { return sym(PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
-cpu-clock                                      { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
-task-clock                                     { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
-page-faults|faults                             { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
-minor-faults                                   { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
-major-faults                                   { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
-context-switches|cs                            { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
-cpu-migrations|migrations                      { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
-alignment-faults                               { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
-emulation-faults                               { return sym(PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
+
+%{
+       {
+               int start_token;
+
+               start_token = (int) parse_events_get_extra(yyscanner);
+               if (start_token) {
+                       parse_events_set_extra(NULL, yyscanner);
+                       return start_token;
+               }
+         }
+%}
+
+cpu-cycles|cycles                              { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CPU_CYCLES); }
+stalled-cycles-frontend|idle-cycles-frontend   { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_FRONTEND); }
+stalled-cycles-backend|idle-cycles-backend     { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_STALLED_CYCLES_BACKEND); }
+instructions                                   { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_INSTRUCTIONS); }
+cache-references                               { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_REFERENCES); }
+cache-misses                                   { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_CACHE_MISSES); }
+branch-instructions|branches                   { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_INSTRUCTIONS); }
+branch-misses                                  { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BRANCH_MISSES); }
+bus-cycles                                     { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_BUS_CYCLES); }
+ref-cycles                                     { return sym(yyscanner, PERF_TYPE_HARDWARE, PERF_COUNT_HW_REF_CPU_CYCLES); }
+cpu-clock                                      { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_CLOCK); }
+task-clock                                     { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_TASK_CLOCK); }
+page-faults|faults                             { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS); }
+minor-faults                                   { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MIN); }
+major-faults                                   { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_PAGE_FAULTS_MAJ); }
+context-switches|cs                            { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CONTEXT_SWITCHES); }
+cpu-migrations|migrations                      { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_CPU_MIGRATIONS); }
+alignment-faults                               { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_ALIGNMENT_FAULTS); }
+emulation-faults                               { return sym(yyscanner, PERF_TYPE_SOFTWARE, PERF_COUNT_SW_EMULATION_FAULTS); }
 
 L1-dcache|l1-d|l1d|L1-data             |
 L1-icache|l1-i|l1i|L1-instruction      |
@@ -87,14 +118,14 @@ LLC|L2                                     |
 dTLB|d-tlb|Data-TLB                    |
 iTLB|i-tlb|Instruction-TLB             |
 branch|branches|bpu|btb|bpc            |
-node                                   { return str(PE_NAME_CACHE_TYPE); }
+node                                   { return str(yyscanner, PE_NAME_CACHE_TYPE); }
 
 load|loads|read                                |
 store|stores|write                     |
 prefetch|prefetches                    |
 speculative-read|speculative-load      |
 refs|Reference|ops|access              |
-misses|miss                            { return str(PE_NAME_CACHE_OP_RESULT); }
+misses|miss                            { return str(yyscanner, PE_NAME_CACHE_OP_RESULT); }
 
        /*
         * These are event config hardcoded term names to be specified
@@ -102,38 +133,39 @@ misses|miss                               { return str(PE_NAME_CACHE_OP_RESULT); }
         * so we can put them here directly. In case the we have a conflict
         * in future, this needs to go into '//' condition block.
         */
-config                 { return term(PARSE_EVENTS__TERM_TYPE_CONFIG); }
-config1                        { return term(PARSE_EVENTS__TERM_TYPE_CONFIG1); }
-config2                        { return term(PARSE_EVENTS__TERM_TYPE_CONFIG2); }
-name                   { return term(PARSE_EVENTS__TERM_TYPE_NAME); }
-period                 { return term(PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
-branch_type            { return term(PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
+config                 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
+config1                        { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
+config2                        { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
+name                   { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NAME); }
+period                 { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD); }
+branch_type            { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE); }
 
 mem:                   { BEGIN(mem); return PE_PREFIX_MEM; }
-r{num_raw_hex}         { return raw(); }
-{num_dec}              { return value(10); }
-{num_hex}              { return value(16); }
+r{num_raw_hex}         { return raw(yyscanner); }
+{num_dec}              { return value(yyscanner, 10); }
+{num_hex}              { return value(yyscanner, 16); }
 
-{modifier_event}       { return str(PE_MODIFIER_EVENT); }
-{name}                 { return str(PE_NAME); }
+{modifier_event}       { return str(yyscanner, PE_MODIFIER_EVENT); }
+{name}                 { return str(yyscanner, PE_NAME); }
 "/"                    { return '/'; }
 -                      { return '-'; }
 ,                      { return ','; }
 :                      { return ':'; }
 =                      { return '='; }
+\n                     { }
 
 <mem>{
-{modifier_bp}          { return str(PE_MODIFIER_BP); }
+{modifier_bp}          { return str(yyscanner, PE_MODIFIER_BP); }
 :                      { return ':'; }
-{num_dec}              { return value(10); }
-{num_hex}              { return value(16); }
+{num_dec}              { return value(yyscanner, 10); }
+{num_hex}              { return value(yyscanner, 16); }
        /*
         * We need to separate 'mem:' scanner part, in order to get specific
         * modifier bits parsed out. Otherwise we would need to handle PE_NAME
         * and we'd need to parse it manually. During the escape from <mem>
         * state we need to put the escaping char back, so we dont miss it.
         */
-.                      { unput(*parse_events_text); BEGIN(INITIAL); }
+.                      { unput(*yytext); BEGIN(INITIAL); }
        /*
         * We destroy the scanner after reaching EOF,
         * but anyway just to be sure get back to INIT state.
@@ -143,7 +175,7 @@ r{num_raw_hex}              { return raw(); }
 
 %%
 
-int parse_events_wrap(void)
+int parse_events_wrap(void *scanner __used)
 {
        return 1;
 }
index 362cc59332ae78e0774fed92e3f20a2f751fa211..2bc5fbff2b5d2b101ac4b65cb9623c5d7ff24326 100644 (file)
@@ -1,7 +1,8 @@
-
+%pure-parser
 %name-prefix "parse_events_"
-%parse-param {struct list_head *list_all}
-%parse-param {int *idx}
+%parse-param {void *_data}
+%parse-param {void *scanner}
+%lex-param {void* scanner}
 
 %{
 
@@ -12,8 +13,9 @@
 #include "types.h"
 #include "util.h"
 #include "parse-events.h"
+#include "parse-events-bison.h"
 
-extern int parse_events_lex (void);
+extern int parse_events_lex (YYSTYPE* lvalp, void* scanner);
 
 #define ABORT_ON(val) \
 do { \
@@ -23,14 +25,16 @@ do { \
 
 %}
 
-%token PE_VALUE PE_VALUE_SYM PE_RAW PE_TERM
+%token PE_START_EVENTS PE_START_TERMS
+%token PE_VALUE PE_VALUE_SYM_HW PE_VALUE_SYM_SW PE_RAW PE_TERM
 %token PE_NAME
 %token PE_MODIFIER_EVENT PE_MODIFIER_BP
 %token PE_NAME_CACHE_TYPE PE_NAME_CACHE_OP_RESULT
 %token PE_PREFIX_MEM PE_PREFIX_RAW
 %token PE_ERROR
 %type <num> PE_VALUE
-%type <num> PE_VALUE_SYM
+%type <num> PE_VALUE_SYM_HW
+%type <num> PE_VALUE_SYM_SW
 %type <num> PE_RAW
 %type <num> PE_TERM
 %type <str> PE_NAME
@@ -38,6 +42,7 @@ do { \
 %type <str> PE_NAME_CACHE_OP_RESULT
 %type <str> PE_MODIFIER_EVENT
 %type <str> PE_MODIFIER_BP
+%type <num> value_sym
 %type <head> event_config
 %type <term> event_term
 %type <head> event_pmu
@@ -58,24 +63,33 @@ do { \
 }
 %%
 
+start:
+PE_START_EVENTS events
+|
+PE_START_TERMS  terms
+
 events:
 events ',' event | event
 
 event:
 event_def PE_MODIFIER_EVENT
 {
+       struct parse_events_data__events *data = _data;
+
        /*
         * Apply modifier on all events added by single event definition
         * (there could be more events added for multiple tracepoint
         * definitions via '*?'.
         */
        ABORT_ON(parse_events_modifier($1, $2));
-       parse_events_update_lists($1, list_all);
+       parse_events_update_lists($1, &data->list);
 }
 |
 event_def
 {
-       parse_events_update_lists($1, list_all);
+       struct parse_events_data__events *data = _data;
+
+       parse_events_update_lists($1, &data->list);
 }
 
 event_def: event_pmu |
@@ -89,104 +103,131 @@ event_def: event_pmu |
 event_pmu:
 PE_NAME '/' event_config '/'
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_pmu(&list, idx, $1, $3));
+       ABORT_ON(parse_events_add_pmu(&list, &data->idx, $1, $3));
        parse_events__free_terms($3);
        $$ = list;
 }
 
+value_sym:
+PE_VALUE_SYM_HW
+|
+PE_VALUE_SYM_SW
+
 event_legacy_symbol:
-PE_VALUE_SYM '/' event_config '/'
+value_sym '/' event_config '/'
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
        int type = $1 >> 16;
        int config = $1 & 255;
 
-       ABORT_ON(parse_events_add_numeric(&list, idx, type, config, $3));
+       ABORT_ON(parse_events_add_numeric(&list, &data->idx,
+                                         type, config, $3));
        parse_events__free_terms($3);
        $$ = list;
 }
 |
-PE_VALUE_SYM sep_slash_dc
+value_sym sep_slash_dc
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
        int type = $1 >> 16;
        int config = $1 & 255;
 
-       ABORT_ON(parse_events_add_numeric(&list, idx, type, config, NULL));
+       ABORT_ON(parse_events_add_numeric(&list, &data->idx,
+                                         type, config, NULL));
        $$ = list;
 }
 
 event_legacy_cache:
 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT '-' PE_NAME_CACHE_OP_RESULT
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, $5));
+       ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, $5));
        $$ = list;
 }
 |
 PE_NAME_CACHE_TYPE '-' PE_NAME_CACHE_OP_RESULT
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_cache(&list, idx, $1, $3, NULL));
+       ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, $3, NULL));
        $$ = list;
 }
 |
 PE_NAME_CACHE_TYPE
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_cache(&list, idx, $1, NULL, NULL));
+       ABORT_ON(parse_events_add_cache(&list, &data->idx, $1, NULL, NULL));
        $$ = list;
 }
 
 event_legacy_mem:
 PE_PREFIX_MEM PE_VALUE ':' PE_MODIFIER_BP sep_dc
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, $4));
+       ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
+                                            (void *) $2, $4));
        $$ = list;
 }
 |
 PE_PREFIX_MEM PE_VALUE sep_dc
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_breakpoint(&list, idx, (void *) $2, NULL));
+       ABORT_ON(parse_events_add_breakpoint(&list, &data->idx,
+                                            (void *) $2, NULL));
        $$ = list;
 }
 
 event_legacy_tracepoint:
 PE_NAME ':' PE_NAME
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_tracepoint(&list, idx, $1, $3));
+       ABORT_ON(parse_events_add_tracepoint(&list, &data->idx, $1, $3));
        $$ = list;
 }
 
 event_legacy_numeric:
 PE_VALUE ':' PE_VALUE
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_numeric(&list, idx, $1, $3, NULL));
+       ABORT_ON(parse_events_add_numeric(&list, &data->idx, $1, $3, NULL));
        $$ = list;
 }
 
 event_legacy_raw:
 PE_RAW
 {
+       struct parse_events_data__events *data = _data;
        struct list_head *list = NULL;
 
-       ABORT_ON(parse_events_add_numeric(&list, idx, PERF_TYPE_RAW, $1, NULL));
+       ABORT_ON(parse_events_add_numeric(&list, &data->idx,
+                                         PERF_TYPE_RAW, $1, NULL));
        $$ = list;
 }
 
+terms: event_config
+{
+       struct parse_events_data__terms *data = _data;
+       data->terms = $1;
+}
+
 event_config:
 event_config ',' event_term
 {
@@ -267,8 +308,7 @@ sep_slash_dc: '/' | ':' |
 
 %%
 
-void parse_events_error(struct list_head *list_all __used,
-                       int *idx __used,
+void parse_events_error(void *data __used, void *scanner __used,
                        char const *msg __used)
 {
 }
index a119a5371699bd1c89575ce02de0d47655548e52..67715a42cd6dc377e0056dff9590404734199d14 100644 (file)
@@ -72,7 +72,7 @@ static int pmu_format(char *name, struct list_head *format)
                 "%s/bus/event_source/devices/%s/format", sysfs, name);
 
        if (stat(path, &st) < 0)
-               return -1;
+               return 0;       /* no error if format does not exist */
 
        if (pmu_format_parse(path, format))
                return -1;
@@ -80,6 +80,114 @@ static int pmu_format(char *name, struct list_head *format)
        return 0;
 }
 
+static int perf_pmu__new_alias(struct list_head *list, char *name, FILE *file)
+{
+       struct perf_pmu__alias *alias;
+       char buf[256];
+       int ret;
+
+       ret = fread(buf, 1, sizeof(buf), file);
+       if (ret == 0)
+               return -EINVAL;
+       buf[ret] = 0;
+
+       alias = malloc(sizeof(*alias));
+       if (!alias)
+               return -ENOMEM;
+
+       INIT_LIST_HEAD(&alias->terms);
+       ret = parse_events_terms(&alias->terms, buf);
+       if (ret) {
+               free(alias);
+               return ret;
+       }
+
+       alias->name = strdup(name);
+       list_add_tail(&alias->list, list);
+       return 0;
+}
+
+/*
+ * Process all the sysfs attributes located under the directory
+ * specified in 'dir' parameter.
+ */
+static int pmu_aliases_parse(char *dir, struct list_head *head)
+{
+       struct dirent *evt_ent;
+       DIR *event_dir;
+       int ret = 0;
+
+       event_dir = opendir(dir);
+       if (!event_dir)
+               return -EINVAL;
+
+       while (!ret && (evt_ent = readdir(event_dir))) {
+               char path[PATH_MAX];
+               char *name = evt_ent->d_name;
+               FILE *file;
+
+               if (!strcmp(name, ".") || !strcmp(name, ".."))
+                       continue;
+
+               snprintf(path, PATH_MAX, "%s/%s", dir, name);
+
+               ret = -EINVAL;
+               file = fopen(path, "r");
+               if (!file)
+                       break;
+               ret = perf_pmu__new_alias(head, name, file);
+               fclose(file);
+       }
+
+       closedir(event_dir);
+       return ret;
+}
+
+/*
+ * Reading the pmu event aliases definition, which should be located at:
+ * /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
+ */
+static int pmu_aliases(char *name, struct list_head *head)
+{
+       struct stat st;
+       char path[PATH_MAX];
+       const char *sysfs;
+
+       sysfs = sysfs_find_mountpoint();
+       if (!sysfs)
+               return -1;
+
+       snprintf(path, PATH_MAX,
+                "%s/bus/event_source/devices/%s/events", sysfs, name);
+
+       if (stat(path, &st) < 0)
+               return -1;
+
+       if (pmu_aliases_parse(path, head))
+               return -1;
+
+       return 0;
+}
+
+static int pmu_alias_terms(struct perf_pmu__alias *alias,
+                          struct list_head *terms)
+{
+       struct parse_events__term *term, *clone;
+       LIST_HEAD(list);
+       int ret;
+
+       list_for_each_entry(term, &alias->terms, list) {
+               ret = parse_events__term_clone(&clone, term);
+               if (ret) {
+                       parse_events__free_terms(&list);
+                       return ret;
+               }
+               list_add_tail(&clone->list, &list);
+       }
+       list_splice(&list, terms);
+       return 0;
+}
+
 /*
  * Reading/parsing the default pmu type value, which should be
  * located at:
@@ -118,6 +226,7 @@ static struct perf_pmu *pmu_lookup(char *name)
 {
        struct perf_pmu *pmu;
        LIST_HEAD(format);
+       LIST_HEAD(aliases);
        __u32 type;
 
        /*
@@ -135,10 +244,15 @@ static struct perf_pmu *pmu_lookup(char *name)
        if (!pmu)
                return NULL;
 
+       pmu_aliases(name, &aliases);
+
        INIT_LIST_HEAD(&pmu->format);
+       INIT_LIST_HEAD(&pmu->aliases);
        list_splice(&format, &pmu->format);
+       list_splice(&aliases, &pmu->aliases);
        pmu->name = strdup(name);
        pmu->type = type;
+       list_add_tail(&pmu->list, &pmus);
        return pmu;
 }
 
@@ -279,6 +393,59 @@ int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
        return pmu_config(&pmu->format, attr, head_terms);
 }
 
+static struct perf_pmu__alias *pmu_find_alias(struct perf_pmu *pmu,
+                                             struct parse_events__term *term)
+{
+       struct perf_pmu__alias *alias;
+       char *name;
+
+       if (parse_events__is_hardcoded_term(term))
+               return NULL;
+
+       if (term->type_val == PARSE_EVENTS__TERM_TYPE_NUM) {
+               if (term->val.num != 1)
+                       return NULL;
+               if (pmu_find_format(&pmu->format, term->config))
+                       return NULL;
+               name = term->config;
+       } else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
+               if (strcasecmp(term->config, "event"))
+                       return NULL;
+               name = term->val.str;
+       } else {
+               return NULL;
+       }
+
+       list_for_each_entry(alias, &pmu->aliases, list) {
+               if (!strcasecmp(alias->name, name))
+                       return alias;
+       }
+       return NULL;
+}
+
+/*
+ * Find alias in the terms list and replace it with the terms
+ * defined for the alias
+ */
+int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms)
+{
+       struct parse_events__term *term, *h;
+       struct perf_pmu__alias *alias;
+       int ret;
+
+       list_for_each_entry_safe(term, h, head_terms, list) {
+               alias = pmu_find_alias(pmu, term);
+               if (!alias)
+                       continue;
+               ret = pmu_alias_terms(alias, &term->list);
+               if (ret)
+                       return ret;
+               list_del(&term->list);
+               free(term);
+       }
+       return 0;
+}
+
 int perf_pmu__new_format(struct list_head *list, char *name,
                         int config, unsigned long *bits)
 {
index 68c0db965e1f52574375859e821daacce9387a3a..535f2c5258ab05a8110727704c98791c850dc588 100644 (file)
@@ -19,17 +19,26 @@ struct perf_pmu__format {
        struct list_head list;
 };
 
+struct perf_pmu__alias {
+       char *name;
+       struct list_head terms;
+       struct list_head list;
+};
+
 struct perf_pmu {
        char *name;
        __u32 type;
        struct list_head format;
+       struct list_head aliases;
        struct list_head list;
 };
 
 struct perf_pmu *perf_pmu__find(char *name);
 int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
                     struct list_head *head_terms);
-
+int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms);
+struct list_head *perf_pmu__alias(struct perf_pmu *pmu,
+                               struct list_head *head_terms);
 int perf_pmu_wrap(void);
 void perf_pmu_error(struct list_head *list, char *name, char const *msg);
 
index 4c1b3d72a1d2d24093733018674024e42723a548..02dfa19a467fcde82abfb0e0802a26a5579c9890 100644 (file)
@@ -209,6 +209,10 @@ static void define_event_symbols(struct event_format *event,
                define_symbolic_values(args->symbol.symbols, ev_name,
                                       cur_field_name);
                break;
+       case PRINT_HEX:
+               define_event_symbols(event, ev_name, args->hex.field);
+               define_event_symbols(event, ev_name, args->hex.size);
+               break;
        case PRINT_BSTRING:
        case PRINT_DYNAMIC_ARRAY:
        case PRINT_STRING:
@@ -233,7 +237,8 @@ static void define_event_symbols(struct event_format *event,
                define_event_symbols(event, ev_name, args->next);
 }
 
-static inline struct event_format *find_cache_event(int type)
+static inline
+struct event_format *find_cache_event(struct pevent *pevent, int type)
 {
        static char ev_name[256];
        struct event_format *event;
@@ -241,7 +246,7 @@ static inline struct event_format *find_cache_event(int type)
        if (events[type])
                return events[type];
 
-       events[type] = event = trace_find_event(type);
+       events[type] = event = pevent_find_event(pevent, type);
        if (!event)
                return NULL;
 
@@ -252,7 +257,8 @@ static inline struct event_format *find_cache_event(int type)
        return event;
 }
 
-static void perl_process_tracepoint(union perf_event *pevent __unused,
+static void perl_process_tracepoint(union perf_event *perf_event __unused,
+                                   struct pevent *pevent,
                                    struct perf_sample *sample,
                                    struct perf_evsel *evsel,
                                    struct machine *machine __unused,
@@ -275,13 +281,13 @@ static void perl_process_tracepoint(union perf_event *pevent __unused,
        if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
                return;
 
-       type = trace_parse_common_type(data);
+       type = trace_parse_common_type(pevent, data);
 
-       event = find_cache_event(type);
+       event = find_cache_event(pevent, type);
        if (!event)
                die("ug! no event found for type %d", type);
 
-       pid = trace_parse_common_pid(data);
+       pid = trace_parse_common_pid(pevent, data);
 
        sprintf(handler, "%s::%s", event->system, event->name);
 
@@ -314,7 +320,8 @@ static void perl_process_tracepoint(union perf_event *pevent __unused,
                                offset = field->offset;
                        XPUSHs(sv_2mortal(newSVpv((char *)data + offset, 0)));
                } else { /* FIELD_IS_NUMERIC */
-                       val = read_size(data + field->offset, field->size);
+                       val = read_size(pevent, data + field->offset,
+                                       field->size);
                        if (field->flags & FIELD_IS_SIGNED) {
                                XPUSHs(sv_2mortal(newSViv(val)));
                        } else {
@@ -368,14 +375,15 @@ static void perl_process_event_generic(union perf_event *pevent __unused,
        LEAVE;
 }
 
-static void perl_process_event(union perf_event *pevent,
+static void perl_process_event(union perf_event *event,
+                              struct pevent *pevent,
                               struct perf_sample *sample,
                               struct perf_evsel *evsel,
                               struct machine *machine,
                               struct thread *thread)
 {
-       perl_process_tracepoint(pevent, sample, evsel, machine, thread);
-       perl_process_event_generic(pevent, sample, evsel, machine, thread);
+       perl_process_tracepoint(event, pevent, sample, evsel, machine, thread);
+       perl_process_event_generic(event, sample, evsel, machine, thread);
 }
 
 static void run_start_sub(void)
@@ -448,7 +456,7 @@ static int perl_stop_script(void)
        return 0;
 }
 
-static int perl_generate_script(const char *outfile)
+static int perl_generate_script(struct pevent *pevent, const char *outfile)
 {
        struct event_format *event = NULL;
        struct format_field *f;
@@ -495,7 +503,7 @@ static int perl_generate_script(const char *outfile)
        fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n");
        fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n\n");
 
-       while ((event = trace_find_next_event(event))) {
+       while ((event = trace_find_next_event(pevent, event))) {
                fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
                fprintf(ofp, "\tmy (");
 
index acb9795286c4bd077531fcf65f14cc8d0699a198..ce4d1b0c38626d800defaf373b231ae9171f3904 100644 (file)
@@ -166,6 +166,10 @@ static void define_event_symbols(struct event_format *event,
                define_values(PRINT_SYMBOL, args->symbol.symbols, ev_name,
                              cur_field_name);
                break;
+       case PRINT_HEX:
+               define_event_symbols(event, ev_name, args->hex.field);
+               define_event_symbols(event, ev_name, args->hex.size);
+               break;
        case PRINT_STRING:
                break;
        case PRINT_TYPE:
@@ -190,7 +194,8 @@ static void define_event_symbols(struct event_format *event,
                define_event_symbols(event, ev_name, args->next);
 }
 
-static inline struct event_format *find_cache_event(int type)
+static inline
+struct event_format *find_cache_event(struct pevent *pevent, int type)
 {
        static char ev_name[256];
        struct event_format *event;
@@ -198,7 +203,7 @@ static inline struct event_format *find_cache_event(int type)
        if (events[type])
                return events[type];
 
-       events[type] = event = trace_find_event(type);
+       events[type] = event = pevent_find_event(pevent, type);
        if (!event)
                return NULL;
 
@@ -209,7 +214,8 @@ static inline struct event_format *find_cache_event(int type)
        return event;
 }
 
-static void python_process_event(union perf_event *pevent __unused,
+static void python_process_event(union perf_event *perf_event __unused,
+                                struct pevent *pevent,
                                 struct perf_sample *sample,
                                 struct perf_evsel *evsel __unused,
                                 struct machine *machine __unused,
@@ -233,13 +239,13 @@ static void python_process_event(union perf_event *pevent __unused,
        if (!t)
                Py_FatalError("couldn't create Python tuple");
 
-       type = trace_parse_common_type(data);
+       type = trace_parse_common_type(pevent, data);
 
-       event = find_cache_event(type);
+       event = find_cache_event(pevent, type);
        if (!event)
                die("ug! no event found for type %d", type);
 
-       pid = trace_parse_common_pid(data);
+       pid = trace_parse_common_pid(pevent, data);
 
        sprintf(handler_name, "%s__%s", event->system, event->name);
 
@@ -284,7 +290,8 @@ static void python_process_event(union perf_event *pevent __unused,
                                offset = field->offset;
                        obj = PyString_FromString((char *)data + offset);
                } else { /* FIELD_IS_NUMERIC */
-                       val = read_size(data + field->offset, field->size);
+                       val = read_size(pevent, data + field->offset,
+                                       field->size);
                        if (field->flags & FIELD_IS_SIGNED) {
                                if ((long long)val >= LONG_MIN &&
                                    (long long)val <= LONG_MAX)
@@ -438,7 +445,7 @@ out:
        return err;
 }
 
-static int python_generate_script(const char *outfile)
+static int python_generate_script(struct pevent *pevent, const char *outfile)
 {
        struct event_format *event = NULL;
        struct format_field *f;
@@ -487,7 +494,7 @@ static int python_generate_script(const char *outfile)
        fprintf(ofp, "def trace_end():\n");
        fprintf(ofp, "\tprint \"in trace_end\"\n\n");
 
-       while ((event = trace_find_next_event(event))) {
+       while ((event = trace_find_next_event(pevent, event))) {
                fprintf(ofp, "def %s__%s(", event->system, event->name);
                fprintf(ofp, "event_name, ");
                fprintf(ofp, "context, ");
index 56142d0fb8d79bfdc1bd21cd7ac24f0ded4627bf..8e485592ca200c1712d1c959296230f9dce50d33 100644 (file)
@@ -14,6 +14,7 @@
 #include "sort.h"
 #include "util.h"
 #include "cpumap.h"
+#include "event-parse.h"
 
 static int perf_session__open(struct perf_session *self, bool force)
 {
@@ -289,7 +290,6 @@ struct branch_info *machine__resolve_bstack(struct machine *self,
 }
 
 int machine__resolve_callchain(struct machine *self,
-                              struct perf_evsel *evsel __used,
                               struct thread *thread,
                               struct ip_callchain *chain,
                               struct symbol **parent)
@@ -1449,7 +1449,7 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp)
        ret += hists__fprintf_nr_events(&session->hists, fp);
 
        list_for_each_entry(pos, &session->evlist->entries, node) {
-               ret += fprintf(fp, "%s stats:\n", event_name(pos));
+               ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
                ret += hists__fprintf_nr_events(&pos->hists, fp);
        }
 
@@ -1490,8 +1490,8 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
 }
 
 void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
-                         struct machine *machine, struct perf_evsel *evsel,
-                         int print_sym, int print_dso, int print_symoffset)
+                         struct machine *machine, int print_sym,
+                         int print_dso, int print_symoffset)
 {
        struct addr_location al;
        struct callchain_cursor_node *node;
@@ -1505,7 +1505,7 @@ void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
 
        if (symbol_conf.use_callchain && sample->callchain) {
 
-               if (machine__resolve_callchain(machine, evsel, al.thread,
+               if (machine__resolve_callchain(machine, al.thread,
                                                sample->callchain, NULL) != 0) {
                        if (verbose)
                                error("Failed to resolve callchain. Skipping\n");
@@ -1611,3 +1611,58 @@ void perf_session__fprintf_info(struct perf_session *session, FILE *fp,
        perf_header__fprintf_info(session, fp, full);
        fprintf(fp, "# ========\n#\n");
 }
+
+
+int __perf_session__set_tracepoints_handlers(struct perf_session *session,
+                                            const struct perf_evsel_str_handler *assocs,
+                                            size_t nr_assocs)
+{
+       struct perf_evlist *evlist = session->evlist;
+       struct event_format *format;
+       struct perf_evsel *evsel;
+       char *tracepoint, *name;
+       size_t i;
+       int err;
+
+       for (i = 0; i < nr_assocs; i++) {
+               err = -ENOMEM;
+               tracepoint = strdup(assocs[i].name);
+               if (tracepoint == NULL)
+                       goto out;
+
+               err = -ENOENT;
+               name = strchr(tracepoint, ':');
+               if (name == NULL)
+                       goto out_free;
+
+               *name++ = '\0';
+               format = pevent_find_event_by_name(session->pevent,
+                                                  tracepoint, name);
+               if (format == NULL) {
+                       /*
+                        * Adding a handler for an event not in the session,
+                        * just ignore it.
+                        */
+                       goto next;
+               }
+
+               evsel = perf_evlist__find_tracepoint_by_id(evlist, format->id);
+               if (evsel == NULL)
+                       goto next;
+
+               err = -EEXIST;
+               if (evsel->handler.func != NULL)
+                       goto out_free;
+               evsel->handler.func = assocs[i].handler;
+next:
+               free(tracepoint);
+       }
+
+       err = 0;
+out:
+       return err;
+
+out_free:
+       free(tracepoint);
+       goto out;
+}
index 0c702e3f0a364272a9d979b04786403c4e079bbe..7c435bde6eb0ea1f913e1dadfca3da0c23432302 100644 (file)
@@ -33,6 +33,7 @@ struct perf_session {
        struct machine          host_machine;
        struct rb_root          machines;
        struct perf_evlist      *evlist;
+       struct pevent           *pevent;
        /*
         * FIXME: Need to split this up further, we need global
         *        stats + per event stats. 'perf diff' also needs
@@ -151,11 +152,20 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
                                            unsigned int type);
 
 void perf_event__print_ip(union perf_event *event, struct perf_sample *sample,
-                         struct machine *machine, struct perf_evsel *evsel,
-                         int print_sym, int print_dso, int print_symoffset);
+                         struct machine *machine, int print_sym,
+                         int print_dso, int print_symoffset);
 
 int perf_session__cpu_bitmap(struct perf_session *session,
                             const char *cpu_list, unsigned long *cpu_bitmap);
 
 void perf_session__fprintf_info(struct perf_session *s, FILE *fp, bool full);
+
+struct perf_evsel_str_handler;
+
+int __perf_session__set_tracepoints_handlers(struct perf_session *session,
+                                            const struct perf_evsel_str_handler *assocs,
+                                            size_t nr_assocs);
+
+#define perf_session__set_tracepoints_handlers(session, array) \
+       __perf_session__set_tracepoints_handlers(session, array, ARRAY_SIZE(array))
 #endif /* __PERF_SESSION_H */
index a27237430c5f1a8b9fd24458609cc405eff9ac73..0f5a0a496bc491e545d3bf30e8820163fbba61c6 100644 (file)
@@ -241,6 +241,54 @@ struct sort_entry sort_sym = {
        .se_width_idx   = HISTC_SYMBOL,
 };
 
+/* --sort srcline */
+
+static int64_t
+sort__srcline_cmp(struct hist_entry *left, struct hist_entry *right)
+{
+       return (int64_t)(right->ip - left->ip);
+}
+
+static int hist_entry__srcline_snprintf(struct hist_entry *self, char *bf,
+                                  size_t size, unsigned int width __used)
+{
+       FILE *fp;
+       char cmd[PATH_MAX + 2], *path = self->srcline, *nl;
+       size_t line_len;
+
+       if (path != NULL)
+               goto out_path;
+
+       snprintf(cmd, sizeof(cmd), "addr2line -e %s %016" PRIx64,
+                self->ms.map->dso->long_name, self->ip);
+       fp = popen(cmd, "r");
+       if (!fp)
+               goto out_ip;
+
+       if (getline(&path, &line_len, fp) < 0 || !line_len)
+               goto out_ip;
+       fclose(fp);
+       self->srcline = strdup(path);
+       if (self->srcline == NULL)
+               goto out_ip;
+
+       nl = strchr(self->srcline, '\n');
+       if (nl != NULL)
+               *nl = '\0';
+       path = self->srcline;
+out_path:
+       return repsep_snprintf(bf, size, "%s", path);
+out_ip:
+       return repsep_snprintf(bf, size, "%-#*llx", BITS_PER_LONG / 4, self->ip);
+}
+
+struct sort_entry sort_srcline = {
+       .se_header      = "Source:Line",
+       .se_cmp         = sort__srcline_cmp,
+       .se_snprintf    = hist_entry__srcline_snprintf,
+       .se_width_idx   = HISTC_SRCLINE,
+};
+
 /* --sort parent */
 
 static int64_t
@@ -439,6 +487,7 @@ static struct sort_dimension sort_dimensions[] = {
        DIM(SORT_PARENT, "parent", sort_parent),
        DIM(SORT_CPU, "cpu", sort_cpu),
        DIM(SORT_MISPREDICT, "mispredict", sort_mispredict),
+       DIM(SORT_SRCLINE, "srcline", sort_srcline),
 };
 
 int sort_dimension__add(const char *tok)
index 472aa5a63a58f571fccd884f1e7f16f08b3b5ec7..e724b26acd5135e609aca16212edaf7ec56a9da4 100644 (file)
@@ -71,6 +71,7 @@ struct hist_entry {
        char                    level;
        bool                    used;
        u8                      filtered;
+       char                    *srcline;
        struct symbol           *parent;
        union {
                unsigned long     position;
@@ -93,6 +94,7 @@ enum sort_type {
        SORT_SYM_FROM,
        SORT_SYM_TO,
        SORT_MISPREDICT,
+       SORT_SRCLINE,
 };
 
 /*
index d5836382ff2cad7d00fd156d1296f99f8433f698..199bc4d8905d4ff75d31a60471673fac68470aec 100644 (file)
@@ -313,3 +313,25 @@ int strtailcmp(const char *s1, const char *s2)
        return 0;
 }
 
+/**
+ * rtrim - Removes trailing whitespace from @s.
+ * @s: The string to be stripped.
+ *
+ * Note that the first trailing whitespace is replaced with a %NUL-terminator
+ * in the given string @s. Returns @s.
+ */
+char *rtrim(char *s)
+{
+       size_t size = strlen(s);
+       char *end;
+
+       if (!size)
+               return s;
+
+       end = s + size - 1;
+       while (end >= s && isspace(*end))
+               end--;
+       *(end + 1) = '\0';
+
+       return s;
+}
index 3e2e5ea0f03f692c41f62e8aeb1f5d3382c86ce1..50958bbeb26aa0c0d19f92deb830649cd43d5100 100644 (file)
@@ -1478,14 +1478,31 @@ static int elf_read_build_id(Elf *elf, void *bf, size_t size)
                goto out;
        }
 
-       sec = elf_section_by_name(elf, &ehdr, &shdr,
-                                 ".note.gnu.build-id", NULL);
-       if (sec == NULL) {
+       /*
+        * Check following sections for notes:
+        *   '.note.gnu.build-id'
+        *   '.notes'
+        *   '.note' (VDSO specific)
+        */
+       do {
+               sec = elf_section_by_name(elf, &ehdr, &shdr,
+                                         ".note.gnu.build-id", NULL);
+               if (sec)
+                       break;
+
                sec = elf_section_by_name(elf, &ehdr, &shdr,
                                          ".notes", NULL);
-               if (sec == NULL)
-                       goto out;
-       }
+               if (sec)
+                       break;
+
+               sec = elf_section_by_name(elf, &ehdr, &shdr,
+                                         ".note", NULL);
+               if (sec)
+                       break;
+
+               return err;
+
+       } while (0);
 
        data = elf_getdata(sec, NULL);
        if (data == NULL)
@@ -1590,11 +1607,62 @@ out:
        return err;
 }
 
+static int filename__read_debuglink(const char *filename,
+                                   char *debuglink, size_t size)
+{
+       int fd, err = -1;
+       Elf *elf;
+       GElf_Ehdr ehdr;
+       GElf_Shdr shdr;
+       Elf_Data *data;
+       Elf_Scn *sec;
+       Elf_Kind ek;
+
+       fd = open(filename, O_RDONLY);
+       if (fd < 0)
+               goto out;
+
+       elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
+       if (elf == NULL) {
+               pr_debug2("%s: cannot read %s ELF file.\n", __func__, filename);
+               goto out_close;
+       }
+
+       ek = elf_kind(elf);
+       if (ek != ELF_K_ELF)
+               goto out_close;
+
+       if (gelf_getehdr(elf, &ehdr) == NULL) {
+               pr_err("%s: cannot get elf header.\n", __func__);
+               goto out_close;
+       }
+
+       sec = elf_section_by_name(elf, &ehdr, &shdr,
+                                 ".gnu_debuglink", NULL);
+       if (sec == NULL)
+               goto out_close;
+
+       data = elf_getdata(sec, NULL);
+       if (data == NULL)
+               goto out_close;
+
+       /* the start of this section is a zero-terminated string */
+       strncpy(debuglink, data->d_buf, size);
+
+       elf_end(elf);
+
+out_close:
+       close(fd);
+out:
+       return err;
+}
+
 char dso__symtab_origin(const struct dso *dso)
 {
        static const char origin[] = {
                [SYMTAB__KALLSYMS]            = 'k',
                [SYMTAB__JAVA_JIT]            = 'j',
+               [SYMTAB__DEBUGLINK]           = 'l',
                [SYMTAB__BUILD_ID_CACHE]      = 'B',
                [SYMTAB__FEDORA_DEBUGINFO]    = 'f',
                [SYMTAB__UBUNTU_DEBUGINFO]    = 'u',
@@ -1662,10 +1730,22 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
         */
        want_symtab = 1;
 restart:
-       for (dso->symtab_type = SYMTAB__BUILD_ID_CACHE;
+       for (dso->symtab_type = SYMTAB__DEBUGLINK;
             dso->symtab_type != SYMTAB__NOT_FOUND;
             dso->symtab_type++) {
                switch (dso->symtab_type) {
+               case SYMTAB__DEBUGLINK: {
+                       char *debuglink;
+                       strncpy(name, dso->long_name, size);
+                       debuglink = name + dso->long_name_len;
+                       while (debuglink != name && *debuglink != '/')
+                               debuglink--;
+                       if (*debuglink == '/')
+                               debuglink++;
+                       filename__read_debuglink(dso->long_name, debuglink,
+                                                size - (debuglink - name));
+                       }
+                       break;
                case SYMTAB__BUILD_ID_CACHE:
                        /* skip the locally configured cache if a symfs is given */
                        if (symbol_conf.symfs[0] ||
index af0752b1aca1a9097b1eb552da416683bf3394c7..a884b99017f085c0dceb47e7b766dab8527dc7df 100644 (file)
@@ -257,6 +257,7 @@ enum symtab_type {
        SYMTAB__KALLSYMS = 0,
        SYMTAB__GUEST_KALLSYMS,
        SYMTAB__JAVA_JIT,
+       SYMTAB__DEBUGLINK,
        SYMTAB__BUILD_ID_CACHE,
        SYMTAB__FEDORA_DEBUGINFO,
        SYMTAB__UBUNTU_DEBUGINFO,
index abe0e8e9506820ac4d5e5b9f2b08c89ffde49b73..7eeebcee291c4c70a8e0bc0dc0371d107080a1d9 100644 (file)
@@ -65,7 +65,7 @@ size_t perf_top__header_snprintf(struct perf_top *top, char *bf, size_t size)
                                top->freq ? "Hz" : "");
        }
 
-       ret += SNPRINTF(bf + ret, size - ret, "%s", event_name(top->sym_evsel));
+       ret += SNPRINTF(bf + ret, size - ret, "%s", perf_evsel__name(top->sym_evsel));
 
        ret += SNPRINTF(bf + ret, size - ret, "], ");
 
index 5dd3b5ec8411191c41d76d19345496b3923f9a6f..0715c843c2e73ad6fc61832854cb33571732a73f 100644 (file)
@@ -32,29 +32,25 @@ int header_page_size_size;
 int header_page_ts_size;
 int header_page_data_offset;
 
-struct pevent *perf_pevent;
-static struct pevent *pevent;
-
 bool latency_format;
 
-int read_trace_init(int file_bigendian, int host_bigendian)
+struct pevent *read_trace_init(int file_bigendian, int host_bigendian)
 {
-       if (pevent)
-               return 0;
-
-       perf_pevent = pevent_alloc();
-       pevent = perf_pevent;
+       struct pevent *pevent = pevent_alloc();
 
-       pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
-       pevent_set_file_bigendian(pevent, file_bigendian);
-       pevent_set_host_bigendian(pevent, host_bigendian);
+       if (pevent != NULL) {
+               pevent_set_flag(pevent, PEVENT_NSEC_OUTPUT);
+               pevent_set_file_bigendian(pevent, file_bigendian);
+               pevent_set_host_bigendian(pevent, host_bigendian);
+       }
 
-       return 0;
+       return pevent;
 }
 
 static int get_common_field(struct scripting_context *context,
                            int *offset, int *size, const char *type)
 {
+       struct pevent *pevent = context->pevent;
        struct event_format *event;
        struct format_field *field;
 
@@ -150,7 +146,7 @@ void *raw_field_ptr(struct event_format *event, const char *name, void *data)
        return data + field->offset;
 }
 
-int trace_parse_common_type(void *data)
+int trace_parse_common_type(struct pevent *pevent, void *data)
 {
        struct pevent_record record;
 
@@ -158,7 +154,7 @@ int trace_parse_common_type(void *data)
        return pevent_data_type(pevent, &record);
 }
 
-int trace_parse_common_pid(void *data)
+int trace_parse_common_pid(struct pevent *pevent, void *data)
 {
        struct pevent_record record;
 
@@ -166,27 +162,21 @@ int trace_parse_common_pid(void *data)
        return pevent_data_pid(pevent, &record);
 }
 
-unsigned long long read_size(void *ptr, int size)
+unsigned long long read_size(struct pevent *pevent, void *ptr, int size)
 {
        return pevent_read_number(pevent, ptr, size);
 }
 
-struct event_format *trace_find_event(int type)
-{
-       return pevent_find_event(pevent, type);
-}
-
-
-void print_trace_event(int cpu, void *data, int size)
+void print_trace_event(struct pevent *pevent, int cpu, void *data, int size)
 {
        struct event_format *event;
        struct pevent_record record;
        struct trace_seq s;
        int type;
 
-       type = trace_parse_common_type(data);
+       type = trace_parse_common_type(pevent, data);
 
-       event = trace_find_event(type);
+       event = pevent_find_event(pevent, type);
        if (!event) {
                warning("ug! no event found for type %d", type);
                return;
@@ -202,8 +192,8 @@ void print_trace_event(int cpu, void *data, int size)
        trace_seq_do_printf(&s);
 }
 
-void print_event(int cpu, void *data, int size, unsigned long long nsecs,
-                 char *comm)
+void print_event(struct pevent *pevent, int cpu, void *data, int size,
+                unsigned long long nsecs, char *comm)
 {
        struct pevent_record record;
        struct trace_seq s;
@@ -226,7 +216,8 @@ void print_event(int cpu, void *data, int size, unsigned long long nsecs,
        printf("\n");
 }
 
-void parse_proc_kallsyms(char *file, unsigned int size __unused)
+void parse_proc_kallsyms(struct pevent *pevent,
+                        char *file, unsigned int size __unused)
 {
        unsigned long long addr;
        char *func;
@@ -257,7 +248,8 @@ void parse_proc_kallsyms(char *file, unsigned int size __unused)
        }
 }
 
-void parse_ftrace_printk(char *file, unsigned int size __unused)
+void parse_ftrace_printk(struct pevent *pevent,
+                        char *file, unsigned int size __unused)
 {
        unsigned long long addr;
        char *printk;
@@ -281,17 +273,19 @@ void parse_ftrace_printk(char *file, unsigned int size __unused)
        }
 }
 
-int parse_ftrace_file(char *buf, unsigned long size)
+int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size)
 {
        return pevent_parse_event(pevent, buf, size, "ftrace");
 }
 
-int parse_event_file(char *buf, unsigned long size, char *sys)
+int parse_event_file(struct pevent *pevent,
+                    char *buf, unsigned long size, char *sys)
 {
        return pevent_parse_event(pevent, buf, size, sys);
 }
 
-struct event_format *trace_find_next_event(struct event_format *event)
+struct event_format *trace_find_next_event(struct pevent *pevent,
+                                          struct event_format *event)
 {
        static int idx;
 
index f097e0dd6c5cb4986aa1e5cd1a1cb61cdca55cdf..719ed74a85652541d19e1f7dc15d26e2348a31fc 100644 (file)
@@ -114,20 +114,20 @@ static void skip(int size)
        };
 }
 
-static unsigned int read4(void)
+static unsigned int read4(struct pevent *pevent)
 {
        unsigned int data;
 
        read_or_die(&data, 4);
-       return __data2host4(perf_pevent, data);
+       return __data2host4(pevent, data);
 }
 
-static unsigned long long read8(void)
+static unsigned long long read8(struct pevent *pevent)
 {
        unsigned long long data;
 
        read_or_die(&data, 8);
-       return __data2host8(perf_pevent, data);
+       return __data2host8(pevent, data);
 }
 
 static char *read_string(void)
@@ -168,12 +168,12 @@ static char *read_string(void)
        return str;
 }
 
-static void read_proc_kallsyms(void)
+static void read_proc_kallsyms(struct pevent *pevent)
 {
        unsigned int size;
        char *buf;
 
-       size = read4();
+       size = read4(pevent);
        if (!size)
                return;
 
@@ -181,29 +181,29 @@ static void read_proc_kallsyms(void)
        read_or_die(buf, size);
        buf[size] = '\0';
 
-       parse_proc_kallsyms(buf, size);
+       parse_proc_kallsyms(pevent, buf, size);
 
        free(buf);
 }
 
-static void read_ftrace_printk(void)
+static void read_ftrace_printk(struct pevent *pevent)
 {
        unsigned int size;
        char *buf;
 
-       size = read4();
+       size = read4(pevent);
        if (!size)
                return;
 
        buf = malloc_or_die(size);
        read_or_die(buf, size);
 
-       parse_ftrace_printk(buf, size);
+       parse_ftrace_printk(pevent, buf, size);
 
        free(buf);
 }
 
-static void read_header_files(void)
+static void read_header_files(struct pevent *pevent)
 {
        unsigned long long size;
        char *header_event;
@@ -214,7 +214,7 @@ static void read_header_files(void)
        if (memcmp(buf, "header_page", 12) != 0)
                die("did not read header page");
 
-       size = read8();
+       size = read8(pevent);
        skip(size);
 
        /*
@@ -227,47 +227,48 @@ static void read_header_files(void)
        if (memcmp(buf, "header_event", 13) != 0)
                die("did not read header event");
 
-       size = read8();
+       size = read8(pevent);
        header_event = malloc_or_die(size);
        read_or_die(header_event, size);
        free(header_event);
 }
 
-static void read_ftrace_file(unsigned long long size)
+static void read_ftrace_file(struct pevent *pevent, unsigned long long size)
 {
        char *buf;
 
        buf = malloc_or_die(size);
        read_or_die(buf, size);
-       parse_ftrace_file(buf, size);
+       parse_ftrace_file(pevent, buf, size);
        free(buf);
 }
 
-static void read_event_file(char *sys, unsigned long long size)
+static void read_event_file(struct pevent *pevent, char *sys,
+                           unsigned long long size)
 {
        char *buf;
 
        buf = malloc_or_die(size);
        read_or_die(buf, size);
-       parse_event_file(buf, size, sys);
+       parse_event_file(pevent, buf, size, sys);
        free(buf);
 }
 
-static void read_ftrace_files(void)
+static void read_ftrace_files(struct pevent *pevent)
 {
        unsigned long long size;
        int count;
        int i;
 
-       count = read4();
+       count = read4(pevent);
 
        for (i = 0; i < count; i++) {
-               size = read8();
-               read_ftrace_file(size);
+               size = read8(pevent);
+               read_ftrace_file(pevent, size);
        }
 }
 
-static void read_event_files(void)
+static void read_event_files(struct pevent *pevent)
 {
        unsigned long long size;
        char *sys;
@@ -275,15 +276,15 @@ static void read_event_files(void)
        int count;
        int i,x;
 
-       systems = read4();
+       systems = read4(pevent);
 
        for (i = 0; i < systems; i++) {
                sys = read_string();
 
-               count = read4();
+               count = read4(pevent);
                for (x=0; x < count; x++) {
-                       size = read8();
-                       read_event_file(sys, size);
+                       size = read8(pevent);
+                       read_event_file(pevent, sys, size);
                }
        }
 }
@@ -377,7 +378,7 @@ static int calc_index(void *ptr, int cpu)
        return (unsigned long)ptr - (unsigned long)cpu_data[cpu].page;
 }
 
-struct pevent_record *trace_peek_data(int cpu)
+struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu)
 {
        struct pevent_record *data;
        void *page = cpu_data[cpu].page;
@@ -399,15 +400,15 @@ struct pevent_record *trace_peek_data(int cpu)
                /* FIXME: handle header page */
                if (header_page_ts_size != 8)
                        die("expected a long long type for timestamp");
-               cpu_data[cpu].timestamp = data2host8(perf_pevent, ptr);
+               cpu_data[cpu].timestamp = data2host8(pevent, ptr);
                ptr += 8;
                switch (header_page_size_size) {
                case 4:
-                       cpu_data[cpu].page_size = data2host4(perf_pevent, ptr);
+                       cpu_data[cpu].page_size = data2host4(pevent, ptr);
                        ptr += 4;
                        break;
                case 8:
-                       cpu_data[cpu].page_size = data2host8(perf_pevent, ptr);
+                       cpu_data[cpu].page_size = data2host8(pevent, ptr);
                        ptr += 8;
                        break;
                default:
@@ -421,10 +422,10 @@ read_again:
 
        if (idx >= cpu_data[cpu].page_size) {
                get_next_page(cpu);
-               return trace_peek_data(cpu);
+               return trace_peek_data(pevent, cpu);
        }
 
-       type_len_ts = data2host4(perf_pevent, ptr);
+       type_len_ts = data2host4(pevent, ptr);
        ptr += 4;
 
        type_len = type_len4host(type_len_ts);
@@ -434,14 +435,14 @@ read_again:
        case RINGBUF_TYPE_PADDING:
                if (!delta)
                        die("error, hit unexpected end of page");
-               length = data2host4(perf_pevent, ptr);
+               length = data2host4(pevent, ptr);
                ptr += 4;
                length *= 4;
                ptr += length;
                goto read_again;
 
        case RINGBUF_TYPE_TIME_EXTEND:
-               extend = data2host4(perf_pevent, ptr);
+               extend = data2host4(pevent, ptr);
                ptr += 4;
                extend <<= TS_SHIFT;
                extend += delta;
@@ -452,7 +453,7 @@ read_again:
                ptr += 12;
                break;
        case 0:
-               length = data2host4(perf_pevent, ptr);
+               length = data2host4(pevent, ptr);
                ptr += 4;
                die("here! length=%d", length);
                break;
@@ -477,17 +478,17 @@ read_again:
        return data;
 }
 
-struct pevent_record *trace_read_data(int cpu)
+struct pevent_record *trace_read_data(struct pevent *pevent, int cpu)
 {
        struct pevent_record *data;
 
-       data = trace_peek_data(cpu);
+       data = trace_peek_data(pevent, cpu);
        cpu_data[cpu].next = NULL;
 
        return data;
 }
 
-ssize_t trace_report(int fd, bool __repipe)
+ssize_t trace_report(int fd, struct pevent **ppevent, bool __repipe)
 {
        char buf[BUFSIZ];
        char test[] = { 23, 8, 68 };
@@ -519,30 +520,32 @@ ssize_t trace_report(int fd, bool __repipe)
        file_bigendian = buf[0];
        host_bigendian = bigendian();
 
-       read_trace_init(file_bigendian, host_bigendian);
+       *ppevent = read_trace_init(file_bigendian, host_bigendian);
+       if (*ppevent == NULL)
+               die("read_trace_init failed");
 
        read_or_die(buf, 1);
        long_size = buf[0];
 
-       page_size = read4();
+       page_size = read4(*ppevent);
 
-       read_header_files();
+       read_header_files(*ppevent);
 
-       read_ftrace_files();
-       read_event_files();
-       read_proc_kallsyms();
-       read_ftrace_printk();
+       read_ftrace_files(*ppevent);
+       read_event_files(*ppevent);
+       read_proc_kallsyms(*ppevent);
+       read_ftrace_printk(*ppevent);
 
        size = calc_data_size - 1;
        calc_data_size = 0;
        repipe = false;
 
        if (show_funcs) {
-               pevent_print_funcs(perf_pevent);
+               pevent_print_funcs(*ppevent);
                return size;
        }
        if (show_printk) {
-               pevent_print_printk(perf_pevent);
+               pevent_print_printk(*ppevent);
                return size;
        }
 
index 18ae6c1831d3896263c5a7c3ff58f264bcefbfa5..474aa7a7df43e178717c7808c2ee279c4d026fb2 100644 (file)
@@ -36,6 +36,7 @@ static int stop_script_unsupported(void)
 }
 
 static void process_event_unsupported(union perf_event *event __unused,
+                                     struct pevent *pevent __unused,
                                      struct perf_sample *sample __unused,
                                      struct perf_evsel *evsel __unused,
                                      struct machine *machine __unused,
@@ -61,7 +62,8 @@ static int python_start_script_unsupported(const char *script __unused,
        return -1;
 }
 
-static int python_generate_script_unsupported(const char *outfile __unused)
+static int python_generate_script_unsupported(struct pevent *pevent __unused,
+                                             const char *outfile __unused)
 {
        print_python_unsupported_msg();
 
@@ -122,7 +124,8 @@ static int perl_start_script_unsupported(const char *script __unused,
        return -1;
 }
 
-static int perl_generate_script_unsupported(const char *outfile __unused)
+static int perl_generate_script_unsupported(struct pevent *pevent __unused,
+                                           const char *outfile __unused)
 {
        print_perl_unsupported_msg();
 
index 639852ac1117109849adc8386c66efbf0ccba24f..8fef1d6687b73250a24e682b4c41a9fb29384421 100644 (file)
@@ -8,6 +8,7 @@
 struct machine;
 struct perf_sample;
 union perf_event;
+struct perf_tool;
 struct thread;
 
 extern int header_page_size_size;
@@ -29,35 +30,36 @@ enum {
 
 int bigendian(void);
 
-int read_trace_init(int file_bigendian, int host_bigendian);
-void print_trace_event(int cpu, void *data, int size);
+struct pevent *read_trace_init(int file_bigendian, int host_bigendian);
+void print_trace_event(struct pevent *pevent, int cpu, void *data, int size);
 
-void print_event(int cpu, void *data, int size, unsigned long long nsecs,
-                 char *comm);
+void print_event(struct pevent *pevent, int cpu, void *data, int size,
+                unsigned long long nsecs, char *comm);
 
-int parse_ftrace_file(char *buf, unsigned long size);
-int parse_event_file(char *buf, unsigned long size, char *sys);
+int parse_ftrace_file(struct pevent *pevent, char *buf, unsigned long size);
+int parse_event_file(struct pevent *pevent,
+                    char *buf, unsigned long size, char *sys);
 
-struct pevent_record *trace_peek_data(int cpu);
-struct event_format *trace_find_event(int type);
+struct pevent_record *trace_peek_data(struct pevent *pevent, int cpu);
 
 unsigned long long
 raw_field_value(struct event_format *event, const char *name, void *data);
 void *raw_field_ptr(struct event_format *event, const char *name, void *data);
 
-void parse_proc_kallsyms(char *file, unsigned int size __unused);
-void parse_ftrace_printk(char *file, unsigned int size __unused);
+void parse_proc_kallsyms(struct pevent *pevent, char *file, unsigned int size);
+void parse_ftrace_printk(struct pevent *pevent, char *file, unsigned int size);
 
-ssize_t trace_report(int fd, bool repipe);
+ssize_t trace_report(int fd, struct pevent **pevent, bool repipe);
 
-int trace_parse_common_type(void *data);
-int trace_parse_common_pid(void *data);
+int trace_parse_common_type(struct pevent *pevent, void *data);
+int trace_parse_common_pid(struct pevent *pevent, void *data);
 
-struct event_format *trace_find_next_event(struct event_format *event);
-unsigned long long read_size(void *ptr, int size);
+struct event_format *trace_find_next_event(struct pevent *pevent,
+                                          struct event_format *event);
+unsigned long long read_size(struct pevent *pevent, void *ptr, int size);
 unsigned long long eval_flag(const char *flag);
 
-struct pevent_record *trace_read_data(int cpu);
+struct pevent_record *trace_read_data(struct pevent *pevent, int cpu);
 int read_tracing_data(int fd, struct list_head *pattrs);
 
 struct tracing_data {
@@ -77,11 +79,12 @@ struct scripting_ops {
        int (*start_script) (const char *script, int argc, const char **argv);
        int (*stop_script) (void);
        void (*process_event) (union perf_event *event,
+                              struct pevent *pevent,
                               struct perf_sample *sample,
                               struct perf_evsel *evsel,
                               struct machine *machine,
                               struct thread *thread);
-       int (*generate_script) (const char *outfile);
+       int (*generate_script) (struct pevent *pevent, const char *outfile);
 };
 
 int script_spec_register(const char *spec, struct scripting_ops *ops);
@@ -90,6 +93,7 @@ void setup_perl_scripting(void);
 void setup_python_scripting(void);
 
 struct scripting_context {
+       struct pevent *pevent;
        void *event_data;
 };
 
index 2daaedb83d8425c5e87077f05f2712d865b49368..b13c7331eaf8cbf89a8a1b6626238e44ab84d657 100644 (file)
@@ -264,4 +264,6 @@ bool is_power_of_2(unsigned long n)
 
 size_t hex_width(u64 v);
 
+char *rtrim(char *s);
+
 #endif